From beb0f9feb44e1414d72a2cc9772e70659f10618c Mon Sep 17 00:00:00 2001 From: walkpan Date: Wed, 31 Dec 2025 19:50:27 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E6=8A=80=E8=83=BD=E7=B3=BB=E7=BB=9F):=20?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=B2=BB=E7=96=97=E5=92=8C=E6=8A=A4=E7=9B=BE?= =?UTF-8?q?=E6=8A=80=E8=83=BD=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 实现治疗和护盾技能的基础功能,包括: 1. 在SACastSystem中添加对治疗和护盾技能类型的支持 2. 新增技能目标选择逻辑,根据技能类型选择敌人或友军 3. 添加buff动画效果和技能提示 4. 更新刘邦的技能配置为护盾技能 5. 移除不再使用的EndAnm相关文件 --- .../resources/game/skill/buff/heathed.prefab | 23 ++- assets/script/game/common/config/SkillSet.ts | 2 +- assets/script/game/common/config/heroSet.ts | 2 +- assets/script/game/hero/HeroSpine.ts | 3 + assets/script/game/hero/HeroViewComp.ts | 4 + assets/script/game/hero/SACastSystem.ts | 182 +++++++++++++++++- assets/script/game/skill/EndAnm.ts | 34 ---- assets/script/game/skill/EndAnm.ts.meta | 9 - assets/script/game/skill/EndAnmCom.ts | 24 --- assets/script/game/skill/EndAnmCom.ts.meta | 9 - 10 files changed, 204 insertions(+), 88 deletions(-) delete mode 100644 assets/script/game/skill/EndAnm.ts delete mode 100644 assets/script/game/skill/EndAnm.ts.meta delete mode 100644 assets/script/game/skill/EndAnmCom.ts delete mode 100644 assets/script/game/skill/EndAnmCom.ts.meta diff --git a/assets/resources/game/skill/buff/heathed.prefab b/assets/resources/game/skill/buff/heathed.prefab index a713ed31..6a005734 100644 --- a/assets/resources/game/skill/buff/heathed.prefab +++ b/assets/resources/game/skill/buff/heathed.prefab @@ -29,10 +29,13 @@ }, { "__id__": 10 + }, + { + "__id__": 12 } ], "_prefab": { - "__id__": 12 + "__id__": 14 }, "_lpos": { "__type__": "cc.Vec3", @@ -259,6 +262,24 @@ "__type__": "cc.CompPrefabInfo", "fileId": "c6LOemuvJKyYCqlF/yUJcr" }, + { + "__type__": "0f3c4JhFbFO2rEFqBJJ7hFv", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 1 + }, + "_enabled": true, + "__prefab": { + "__id__": 13 + }, + "_id": "" + }, + { + "__type__": "cc.CompPrefabInfo", + "fileId": "5dZdUy5cVPjLHtC1SlLIIB" + }, { "__type__": "cc.PrefabInfo", "root": { diff --git a/assets/script/game/common/config/SkillSet.ts b/assets/script/game/common/config/SkillSet.ts index 7067f1f7..4c4c940a 100644 --- a/assets/script/game/common/config/SkillSet.ts +++ b/assets/script/game/common/config/SkillSet.ts @@ -185,7 +185,7 @@ export const SkillSet: Record = { buffs:[],neAttrs:[],info:"治疗自己,回复30%最大生命值", }, 6101:{ - uuid:6101,name:"魔法盾",sp_name:"buff_wind",icon:"3036",TGroup:TGroup.Self,SType:SType.buff,act:"buff",DTType:DTType.single,DType:DType.WIND, + uuid:6101,name:"魔法盾",sp_name:"buff_wind",icon:"3036",TGroup:TGroup.Self,SType:SType.shield,act:"buff",DTType:DTType.single,DType:DType.WIND, ap:30,map:0,cd:1,t_num:1,hit_num:1,hit:1,hitcd:0.2,speed:720,cost:0,with:0,dis:80,ready:0,EAnm:0,DAnm:9001,RType:RType.fixed,EType:EType.animationEnd, buffs:[],neAttrs:[],info:"获得30%最大生命值的护盾", } diff --git a/assets/script/game/common/config/heroSet.ts b/assets/script/game/common/config/heroSet.ts index e2dbdaeb..f0350d67 100644 --- a/assets/script/game/common/config/heroSet.ts +++ b/assets/script/game/common/config/heroSet.ts @@ -110,7 +110,7 @@ export const HeroInfo: Record = { // 刘邦 - 领导型战士(善于用人,知人善任) 5001:{uuid:5001,name:"刘邦",path:"hk1", fac:FacSet.HERO, kind:1,as:1.5, - type:HType.warrior,lv:1,hp:1000,mp:85,map:10,def:9,mdef:0,ap:15,dis:100,speed:120,skills:[6002,6001], + type:HType.warrior,lv:1,hp:1000,mp:85,map:10,def:9,mdef:0,ap:15,dis:100,speed:120,skills:[6002,6101], buff:[],tal:[7101,7201,7301],info:"楚汉争霸领袖,领导统御型战士"}, // 荆轲 - 刺客(敏捷型,高速度和暴击率) diff --git a/assets/script/game/hero/HeroSpine.ts b/assets/script/game/hero/HeroSpine.ts index 334aceda..54baf240 100644 --- a/assets/script/game/hero/HeroSpine.ts +++ b/assets/script/game/hero/HeroSpine.ts @@ -76,6 +76,9 @@ export class HeroSpine extends Component { do_buff(){ this.anm.buff() } + buff(){ + this.anm.buff() + } move(){ // console.log("change to move",this.status); if(this.status=="move") return diff --git a/assets/script/game/hero/HeroViewComp.ts b/assets/script/game/hero/HeroViewComp.ts index b03a620f..7ed74eea 100644 --- a/assets/script/game/hero/HeroViewComp.ts +++ b/assets/script/game/hero/HeroViewComp.ts @@ -438,6 +438,10 @@ export class HeroViewComp extends CCComp { case "atk": this.as.atk() break + case "buff": + this.as.buff() + this.tooltip(TooltipTypes.skill, skill.name) + break } } diff --git a/assets/script/game/hero/SACastSystem.ts b/assets/script/game/hero/SACastSystem.ts index 9549d64d..34bbef3a 100644 --- a/assets/script/game/hero/SACastSystem.ts +++ b/assets/script/game/hero/SACastSystem.ts @@ -49,20 +49,24 @@ export class SACastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdat const readySkills = skills.getReadySkills(heroAttrs.mp); if (readySkills.length === 0) return; - // 选择第一个可施放的伤害技能 - for (const s_uuid of readySkills) { + // 选择第一个可施放的技能(支持伤害/治疗/护盾) + for (const s_uuid of readySkills) { const skill = skills.getSkill(s_uuid); if (!skill) continue; if (skill.hset === HSSet.max && !skills.max_auto) continue; const config = SkillSet[skill.s_uuid]; - if (!config || config.SType !== SType.damage) continue; + if (!config) continue; - // 检查是否有敌人在技能攻击范围内 - if (!this.hasEnemyInSkillRange(heroView, heroAttrs, skill.dis)) continue; + // 根据技能类型检查目标 + if (config.SType === SType.damage) { + if (!this.hasEnemyInSkillRange(heroView, heroAttrs, skill.dis)) continue; + } else if (config.SType === SType.heal || config.SType === SType.shield) { + if (!this.hasAllyInSkillRange(heroView, heroAttrs, skill.dis)) continue; + } // ✅ 开始执行施法 - this.startCast(e,skill,skill.hset); + this.startCast(e, skill, skill.hset); // 一次只施放一个技能 break; @@ -151,8 +155,15 @@ export class SACastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdat if (hset === HSSet.max) talComp.updateCur(TriType.MAX); } /**********************天赋处理*************************************************************************/ - // 获取目标位置 - let targets = this.sTargets(heroView, s_uuid); + // 根据技能类型执行不同逻辑 + if (config.SType === SType.heal) { + return this.executeHealSkill(casterEntity, s_uuid, heroView, hset); + } else if (config.SType === SType.shield) { + return this.executeShieldSkill(casterEntity, s_uuid, heroView, hset); + } + + // 获取目标位置(伤害技能) + let targets = this.sTargets(heroView, s_uuid); if (targets.length === 0) { console.warn("[SACastSystem] 没有找到有效目标"); return false; @@ -348,6 +359,159 @@ export class SACastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdat }); return found; } - + + /** + * 检查技能范围内是否有友军 + */ + private hasAllyInSkillRange(heroView: HeroViewComp, heroAttrs: HeroAttrsComp, skillDistance: number): boolean { + if (!heroView || !heroView.node) return false; + + const currentPos = heroView.node.position; + const team = heroAttrs.fac; + + let found = false; + ecs.query(ecs.allOf(HeroAttrsComp, HeroViewComp)).some(e => { + const model = e.get(HeroAttrsComp); + const view = e.get(HeroViewComp); + if (!view || !view.node) return false; + const distance = Math.abs(currentPos.x - view.node.position.x); + if (model.fac === team && !model.is_dead) { + if (distance <= skillDistance) { + found = true; + return true; + } + } + }); + return found; + } + + /** + * 执行治疗技能 + */ + private executeHealSkill(casterEntity: ecs.Entity, s_uuid: number, heroView: HeroViewComp, hset: HSSet): boolean { + const heroAttrs = casterEntity.get(HeroAttrsComp); + const config = SkillSet[s_uuid]; + if (!config) return false; + + const targets = this.sHealTargets(heroView, heroAttrs, config); + if (targets.length === 0) return false; + + const healAmount = config.ap; + const delay = 0.3; + + heroView.scheduleOnce(() => { + for (const targetEntity of targets) { + const targetAttrs = targetEntity.get(HeroAttrsComp); + const targetView = targetEntity.get(HeroViewComp); + if (!targetAttrs || !targetView) continue; + + targetAttrs.add_hp(healAmount, false); + targetView.health(healAmount); + } + }, delay); + + return true; + } + + /** + * 执行护盾技能 + */ + private executeShieldSkill(casterEntity: ecs.Entity, s_uuid: number, heroView: HeroViewComp, hset: HSSet): boolean { + const heroAttrs = casterEntity.get(HeroAttrsComp); + const config = SkillSet[s_uuid]; + if (!config) return false; + + const targets = this.sShieldTargets(heroView, heroAttrs, config); + if (targets.length === 0) return false; + + const shieldAmount = config.ap; + const delay = 0.3; + + heroView.scheduleOnce(() => { + for (const targetEntity of targets) { + const targetAttrs = targetEntity.get(HeroAttrsComp); + const targetView = targetEntity.get(HeroViewComp); + if (!targetAttrs || !targetView) continue; + + targetAttrs.add_shield(shieldAmount, false); + targetView.add_shield(shieldAmount); + } + }, delay); + + return true; + } + + /** + * 选择治疗目标 + */ + private sHealTargets(caster: HeroViewComp, heroAttrs: HeroAttrsComp, config: any): ecs.Entity[] { + const targets: ecs.Entity[] = []; + const maxTargets = Math.max(1, Number(config.t_num ?? 1)); + const range = Number(config.dis ?? 300); + + ecs.query(ecs.allOf(HeroAttrsComp, HeroViewComp)).forEach(e => { + const model = e.get(HeroAttrsComp); + const view = e.get(HeroViewComp); + if (!model || !view || !view.node) return; + if (model.fac !== heroAttrs.fac) return; + if (model.is_dead) return; + + const distance = Math.abs(caster.node.position.x - view.node.position.x); + if (distance <= range) { + targets.push(e); + } + }); + + targets.sort((a, b) => { + const attrsA = a.get(HeroAttrsComp); + const attrsB = b.get(HeroAttrsComp); + if (!attrsA || !attrsB) return 0; + return attrsA.hp - attrsB.hp; + }); + + return targets.slice(0, maxTargets); + } + + /** + * 选择护盾目标 + */ + private sShieldTargets(caster: HeroViewComp, heroAttrs: HeroAttrsComp, config: any): ecs.Entity[] { + const targets: ecs.Entity[] = []; + const maxTargets = Math.max(1, Number(config.t_num ?? 1)); + const range = Number(config.dis ?? 300); + + ecs.query(ecs.allOf(HeroAttrsComp, HeroViewComp)).forEach(e => { + const model = e.get(HeroAttrsComp); + const view = e.get(HeroViewComp); + if (!model || !view || !view.node) return; + if (model.fac !== heroAttrs.fac) return; + if (model.is_dead) return; + + const distance = Math.abs(caster.node.position.x - view.node.position.x); + if (distance <= range) { + targets.push(e); + } + }); + + return targets.slice(0, maxTargets); + } + + /** + * 根据位置查找实体 + */ + private findEntityAtPosition(pos: Vec3): ecs.Entity | null { + let foundEntity: ecs.Entity | null = null; + ecs.query(ecs.allOf(HeroAttrsComp, HeroViewComp)).some(e => { + const view = e.get(HeroViewComp); + if (!view || !view.node) return false; + const distance = Vec3.distance(pos, view.node.position); + if (distance < 50) { + foundEntity = e; + return true; + } + return false; + }); + return foundEntity; + } } \ No newline at end of file diff --git a/assets/script/game/skill/EndAnm.ts b/assets/script/game/skill/EndAnm.ts deleted file mode 100644 index 65181d24..00000000 --- a/assets/script/game/skill/EndAnm.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS"; - -/** EndAnm 模块 */ -@ecs.register(`EndAnm`) -export class EndAnm extends ecs.Entity { - /** ---------- 数据层 ---------- */ - // EndAnmModel!: EndAnmModelComp; - - /** ---------- 业务层 ---------- */ - // EndAnmBll!: EndAnmBllComp; - - /** ---------- 视图层 ---------- */ - // EndAnmView!: EndAnmViewComp; - - /** 实始添加的数据层组件 */ - protected init() { - // this.addComponents(); - } - - /** 模块资源释放 */ - destroy() { - // 注: 自定义释放逻辑,视图层实现 ecs.IComp 接口的 ecs 组件需要手动释放 - super.destroy(); - } -} - -/** EndAnm 模块业务逻辑系统组件,如无业务逻辑处理可删除此对象 */ -export class EcsEndAnmSystem extends ecs.System { - constructor() { - super(); - - // this.add(new ecs.ComblockSystem()); - } -} diff --git a/assets/script/game/skill/EndAnm.ts.meta b/assets/script/game/skill/EndAnm.ts.meta deleted file mode 100644 index f7cfdb04..00000000 --- a/assets/script/game/skill/EndAnm.ts.meta +++ /dev/null @@ -1,9 +0,0 @@ -{ - "ver": "4.0.24", - "importer": "typescript", - "imported": true, - "uuid": "1262d5a7-b1a1-49dc-9715-b7e28619304f", - "files": [], - "subMetas": {}, - "userData": {} -} diff --git a/assets/script/game/skill/EndAnmCom.ts b/assets/script/game/skill/EndAnmCom.ts deleted file mode 100644 index 6e48f67b..00000000 --- a/assets/script/game/skill/EndAnmCom.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS"; -import { smc } from "../common/SingletonModuleComp"; - -/** 业务层对象 */ -@ecs.register('EndAnmCom') -export class EndAnmComComp extends ecs.Comp { - /** 业务层组件移除时,重置所有数据为默认值 */ - reset() { - - } -} - -/** 业务层业务逻辑处理对象 */ -export class EndAnmComSystem extends ecs.ComblockSystem implements ecs.IEntityEnterSystem { - filter(): ecs.IMatcher { - return ecs.allOf(EndAnmComComp); - } - - entityEnter(e: ecs.Entity): void { - // 注:自定义业务逻辑 - if(!smc.mission.play || smc.mission.pause) return; - e.remove(EndAnmComComp); - } -} \ No newline at end of file diff --git a/assets/script/game/skill/EndAnmCom.ts.meta b/assets/script/game/skill/EndAnmCom.ts.meta deleted file mode 100644 index 66ccba4c..00000000 --- a/assets/script/game/skill/EndAnmCom.ts.meta +++ /dev/null @@ -1,9 +0,0 @@ -{ - "ver": "4.0.24", - "importer": "typescript", - "imported": true, - "uuid": "e0728072-f94e-4741-b172-4157e7a3b335", - "files": [], - "subMetas": {}, - "userData": {} -}