feat(技能系统): 添加治疗和护盾技能支持
实现治疗和护盾技能的基础功能,包括: 1. 在SACastSystem中添加对治疗和护盾技能类型的支持 2. 新增技能目标选择逻辑,根据技能类型选择敌人或友军 3. 添加buff动画效果和技能提示 4. 更新刘邦的技能配置为护盾技能 5. 移除不再使用的EndAnm相关文件
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user