diff --git a/assets/resources/game/skill/buff/buff.prefab b/assets/resources/game/skill/buff/buff.prefab index 4bd250b9..f9e5f3ed 100644 --- a/assets/resources/game/skill/buff/buff.prefab +++ b/assets/resources/game/skill/buff/buff.prefab @@ -99,8 +99,8 @@ }, "_lscale": { "__type__": "cc.Vec3", - "x": 0.2, - "y": 0.2, + "x": 0.5, + "y": 0.5, "z": 1 }, "_mobility": 0, diff --git a/assets/script/game/hero/SCastSystem.ts b/assets/script/game/hero/SCastSystem.ts index 4bdda3af..7f558840 100644 --- a/assets/script/game/hero/SCastSystem.ts +++ b/assets/script/game/hero/SCastSystem.ts @@ -1,5 +1,5 @@ import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS"; -import { Vec3 } from "cc"; +import { Vec3, Prefab, instantiate, tween, Node } from "cc"; import { HeroAttrsComp } from "./HeroAttrsComp"; import { HeroViewComp } from "./HeroViewComp"; import { DTType, RType, SkillConfig, SkillKind, SkillSet, SkillUpList, TGroup } from "../common/config/SkillSet"; @@ -113,7 +113,7 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate if (isFriendly) { const friendlyTargets = this.resolveFriendlyTargets(targetEids, FacSet.HERO); if (friendlyTargets.length === 0) continue; - this.applyFriendlySkillEffects(s_uuid, cardLv, config, null as any, mockAttrs, friendlyTargets, null); + this.applyFriendlySkillEffects(s_uuid, cardLv, config, null as any, mockAttrs, friendlyTargets, spawnPos); } else { const enemyTargetPos = this.resolveRepeatCastTargetPos(new Vec3(spawnPos.x + 300, spawnPos.y, spawnPos.z), i); this.createSkillEntityForCard(s_uuid, cardLv, mockAttrs, spawnPos, enemyTargetPos, i); @@ -384,37 +384,114 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate const applyTargets = kind === SkillKind.Heal ? this.pickHealTargetsByMostMissingHp(targets, sHit) : this.pickRandomFriendlyTargets(targets, sHit); + for (const target of applyTargets) { - if (!target.ent) continue; - const model = target.ent.get(HeroAttrsComp); - if (!model || model.is_dead) continue; - if (kind === SkillKind.Heal && sAp !== 0) { - const addHp = Math.floor(sAp*_cAttrsComp.ap/100);//技能的ap是百分值 需要/100 - model.add_hp(addHp); - target.health(addHp); - } else if (kind === SkillKind.Shield && sAp !== 0) { - const addShield = Math.max(0, Math.floor(sAp)); - model.add_shield(addShield); - } - if (!config.buffs || config.buffs.length === 0) continue; - for (const buffConf of config.buffs) { - if (!buffConf) continue; - const sBuffAp=buffConf.value+sUp.buff_ap - const sBuffHp=buffConf.value+sUp.buff_hp - switch (buffConf.buff){ - case Attrs.ap: - model.add_ap(sBuffAp) - //加工动画 - break - case Attrs.hp_max: - model.add_hp_max(sBuffHp) - //加最大生命值动画 - break - } + const startPos = _heroView?.node?.position || _targetPos; + if (startPos) { + this.playFriendlyCastEffect(startPos, target, () => { + this.applyActualFriendlyEffect(target, kind, sAp, _cAttrsComp, config, sUp); + }); + } else { + this.applyActualFriendlyEffect(target, kind, sAp, _cAttrsComp, config, sUp); } } } + private playFriendlyCastEffect(startPos: Vec3, target: HeroViewComp, callback: Function) { + if (!target.node || !target.node.isValid) { + callback(); + return; + } + + const prefabPath = "game/skill/buff/buff"; + const prefab = oops.res.get(prefabPath, Prefab); + if (!prefab) { + oops.res.load(prefabPath, Prefab, (err, res) => { + if (err) { + callback(); + return; + } + this.doPlayFriendlyCastEffect(startPos.clone(), target, res as Prefab, callback); + }); + } else { + this.doPlayFriendlyCastEffect(startPos.clone(), target, prefab as Prefab, callback); + } + } + + private doPlayFriendlyCastEffect(startPos: Vec3, target: HeroViewComp, prefab: Prefab, callback: Function) { + if (!target.node || !target.node.isValid) { + callback(); + return; + } + const scene = smc.map?.MapView?.scene; + const parent = scene?.entityLayer?.node?.getChildByName("SKILL") || target.node.parent; + if (!parent) { + callback(); + return; + } + + const node = instantiate(prefab); + node.parent = parent; + node.setPosition(startPos); + + const targetPos = target.node.position.clone(); + targetPos.y += 50; + + const midX = (startPos.x + targetPos.x) / 2; + const midY = Math.max(startPos.y, targetPos.y) + 200; + + const dist = Vec3.distance(startPos, targetPos); + const duration = Math.min(0.6, Math.max(0.3, dist / 800)); + + const proxy = { ratio: 0 }; + tween(proxy) + .to(duration, { ratio: 1 }, { + easing: 'sineOut', + onUpdate: () => { + if (!node.isValid) return; + const r = proxy.ratio; + const x = (1 - r) * (1 - r) * startPos.x + 2 * r * (1 - r) * midX + r * r * targetPos.x; + const y = (1 - r) * (1 - r) * startPos.y + 2 * r * (1 - r) * midY + r * r * targetPos.y; + node.setPosition(new Vec3(x, y, startPos.z)); + node.setScale(new Vec3(1 - r * 0.3, 1 - r * 0.3, 1)); + node.angle = -r * 720; + } + }) + .call(() => { + if (node.isValid) node.destroy(); + callback(); + }) + .start(); + } + + private applyActualFriendlyEffect(target: HeroViewComp, kind: SkillKind, sAp: number, _cAttrsComp: HeroAttrsComp, config: SkillConfig, sUp: any) { + if (!target.ent) return; + const model = target.ent.get(HeroAttrsComp); + if (!model || model.is_dead) return; + if (kind === SkillKind.Heal && sAp !== 0) { + const addHp = Math.floor(sAp*_cAttrsComp.ap/100); + model.add_hp(addHp); + target.health(addHp); + } else if (kind === SkillKind.Shield && sAp !== 0) { + const addShield = Math.max(0, Math.floor(sAp)); + model.add_shield(addShield); + } + if (!config.buffs || config.buffs.length === 0) return; + for (const buffConf of config.buffs) { + if (!buffConf) continue; + const sBuffAp=buffConf.value+sUp.buff_ap + const sBuffHp=buffConf.value+sUp.buff_hp + switch (buffConf.buff){ + case Attrs.ap: + model.add_ap(sBuffAp) + break + case Attrs.hp_max: + model.add_hp_max(sBuffHp) + break + } + } + } + private pickRandomFriendlyTargets(targets: HeroViewComp[], hitCount: number): HeroViewComp[] { if (!targets || targets.length === 0) return []; const validHitCount = Math.max(1, Math.floor(hitCount));