技能逻辑修改,怪物只攻击最前方,友方和地方逻辑分开

This commit is contained in:
2025-03-18 16:17:46 +08:00
parent 3a7b0e4762
commit 7f82edf4f9

View File

@@ -131,59 +131,49 @@ export class HeroSkillSystem extends ecs.ComblockSystem implements ecs.ISystemUp
view.at = view.at-view.cd; // 重置普攻计时器 view.at = view.at-view.cd; // 重置普攻计时器
break; break;
} }
if (config.TargetGroup === TargetGroup.Enemy) {
const targets = this.selectEnemyTargets(caster, config);
if (targets.length === 0) return;
const skillEntity = ecs.getEntity<Skill>(Skill);
skillEntity.load(
view.node.position, // 起始位置
view.fac, // 阵营
view.node.parent, // 父节点
config.uuid, // 技能ID
targets[0]?.get(HeroViewComp).node.position // 目标位置
);
targets.forEach(target => {
this.applySkillEffect(caster, target, config);
});
}
if (config.TargetGroup === TargetGroup.Ally) {
const targets = this.selectAllyTargets(caster, config);
if (targets.length === 0) return;
targets.forEach(target => {
this.applySkillEffect(caster, target, config);
});
}
// 选择目标 if (config.TargetGroup === TargetGroup.Self) {
const targets = this.selectTargets(caster, config); this.applySkillEffect(caster, caster, config);
if (targets.length === 0) return; }
// 创建技能实体
const skillEntity = ecs.getEntity<Skill>(Skill);
skillEntity.load(
view.node.position, // 起始位置
view.fac, // 阵营
view.node.parent, // 父节点
config.uuid, // 技能ID
targets[0]?.get(HeroViewComp).node.position // 目标位置
);
// 应用技能效果
targets.forEach(target => {
this.applySkillEffect(caster, target, config);
});
} }
/** 选择技能目标 */ private selectEnemyTargets(caster: ecs.Entity, config: typeof SkillSet[keyof typeof SkillSet]): ecs.Entity[] {
private selectTargets(caster: ecs.Entity, config: typeof SkillSet[keyof typeof SkillSet]): ecs.Entity[] {
const casterView = caster.get(HeroViewComp); const casterView = caster.get(HeroViewComp);
const team = casterView.fac; const team = casterView.fac;
const isEnemyTeam = team === 0 ? 1 : 0; const isEnemyTeam = team === 0 ? 1 : 0;
const candidates= ecs.query(ecs.allOf(HeroViewComp)).filter(e => e.get(HeroViewComp).fac !== team);
// 第一阶段:基础目标筛选 return this.filterFrontRow(candidates, isEnemyTeam);
let candidates = ecs.query(ecs.allOf(HeroViewComp)).filter(e => { }
const view = e.get(HeroViewComp); private selectAllyTargets(caster: ecs.Entity, config: typeof SkillSet[keyof typeof SkillSet]): ecs.Entity[] {
// 根据技能目标类型筛选 const casterView = caster.get(HeroViewComp);
switch(config.TargetGroup) { const team = casterView.fac;
case TargetGroup.Enemy: const candidates= ecs.query(ecs.allOf(HeroViewComp)).filter(e => e.get(HeroViewComp).fac === team);
return view.fac !== team;
case TargetGroup.Ally:
return view.fac === team && e !== caster;
case TargetGroup.Self:
return e === caster;
default:
return true;
}
});
// 第二阶段:位置/血量等精细筛选 // 第二阶段:位置/血量等精细筛选
switch(config.TargetType) { switch(config.TargetType) {
case TargetType.Frontline:
return this.filterFrontRow(candidates, isEnemyTeam);
// case TargetType.Backline:
// return this.filterBackRow(candidates, isEnemyTeam);
// case TargetType.LowestHP:
// return this.filterLowestHealth(candidates);
// case TargetType.HighestHP:
// return this.filterHighestHealth(candidates);
case TargetType.Melee: case TargetType.Melee:
return candidates.filter(e => e.get(HeroViewComp).type === 0); return candidates.filter(e => e.get(HeroViewComp).type === 0);
case TargetType.Ranged: case TargetType.Ranged:
@@ -196,7 +186,7 @@ export class HeroSkillSystem extends ecs.ComblockSystem implements ecs.ISystemUp
return candidates; return candidates;
} }
} }
/** 筛选最前排单位 */ /** 筛选最前排单位 */
private filterFrontRow(entities: ecs.Entity[], isEnemyTeam: number): ecs.Entity[] { private filterFrontRow(entities: ecs.Entity[], isEnemyTeam: number): ecs.Entity[] {
// 敌方最前排是x坐标最大的我方最前排是x坐标最小的 // 敌方最前排是x坐标最大的我方最前排是x坐标最小的
@@ -209,30 +199,6 @@ export class HeroSkillSystem extends ecs.ComblockSystem implements ecs.ISystemUp
); );
} }
/** 筛选最后排单位 */
private filterBackRow(entities: ecs.Entity[], isEnemyTeam: number): ecs.Entity[] {
// 敌方最后排是x坐标最小的我方最后排是x坐标最大的
const keyPos = isEnemyTeam ?
Math.max(...entities.map(e => e.get(HeroViewComp).node.position.x)) :
Math.min(...entities.map(e => e.get(HeroViewComp).node.position.x));
return entities.filter(e =>
Math.abs(e.get(HeroViewComp).node.position.x - keyPos) < 10
);
}
/** 筛选血量最低单位 */
private filterLowestHealth(entities: ecs.Entity[]): ecs.Entity[] {
const minHp = Math.min(...entities.map(e => e.get(HeroViewComp).hp));
return entities.filter(e => e.get(HeroViewComp).hp === minHp);
}
/** 筛选血量最高单位 */
private filterHighestHealth(entities: ecs.Entity[]): ecs.Entity[] {
const maxHp = Math.max(...entities.map(e => e.get(HeroViewComp).hp));
return entities.filter(e => e.get(HeroViewComp).hp === maxHp);
}
/** 随机选择目标 */ /** 随机选择目标 */
private pickRandomTarget(entities: ecs.Entity[], count: number): ecs.Entity[] { private pickRandomTarget(entities: ecs.Entity[], count: number): ecs.Entity[] {
const shuffled = [...entities].sort(() => 0.5 - Math.random()); const shuffled = [...entities].sort(() => 0.5 - Math.random());
@@ -272,7 +238,6 @@ export class HeroSkillSystem extends ecs.ComblockSystem implements ecs.ISystemUp
result.delay = distance / config.speed; result.delay = distance / config.speed;
} }
const targetView = target.get(HeroViewComp);
const sourceView = caster.get(HeroViewComp); const sourceView = caster.get(HeroViewComp);
let final = sourceView.ap * config.ap / 100; let final = sourceView.ap * config.ap / 100;
@@ -281,34 +246,8 @@ export class HeroSkillSystem extends ecs.ComblockSystem implements ecs.ISystemUp
final *= damageFloat; final *= damageFloat;
final = Math.round(final); final = Math.round(final);
// 闪避判定
if (Math.random()*100 < targetView.dodge) {
result.isDodged = true
return result
}
// 护甲减伤
if (!result.ignoreDefense) {
const effectiveArmor = Math.min(targetView.def, 300); // 最大减伤75%
const damageReduction = effectiveArmor / (effectiveArmor + 100);
final *= (1 - damageReduction);
final = Math.round(final); // 四舍五入取整
}
// 暴击判定
let isCrit = false;
if (result.canCrit) {
const critRate = sourceView.crit;
if (Math.random() * 100 < critRate) {
final *= 1.5;
isCrit = true;
}
}
result.value = Math.max(1, final); // 确保最小伤害为1 result.value = Math.max(1, final); // 确保最小伤害为1
result.isCrit = isCrit; result.isCrit = false;
return result; return result;
} }
@@ -318,12 +257,7 @@ export class HeroSkillSystem extends ecs.ComblockSystem implements ecs.ISystemUp
callback: () => { callback: () => {
const view = target.get(HeroViewComp); const view = target.get(HeroViewComp);
if (!view?.ent.has(HeroViewComp)) return; if (!view?.ent.has(HeroViewComp)) return;
if(result.isDodged){
view.BUFFCOMP.tooltip(5,"*闪避*");
return;
}
let remainingDamage = result.value; let remainingDamage = result.value;
if (view.shield > 0) { if (view.shield > 0) {
const shieldAbsorb = Math.min(view.shield, remainingDamage); const shieldAbsorb = Math.min(view.shield, remainingDamage);
@@ -341,7 +275,7 @@ export class HeroSkillSystem extends ecs.ComblockSystem implements ecs.ISystemUp
view.BUFFCOMP.dead() view.BUFFCOMP.dead()
view.to_grave(); view.to_grave();
} }
view.showDamage(result.value, result.isCrit); view.showDamage(result.value, true);
} else { } else {
view.BUFFCOMP.tooltip(5,"*吸收*"); view.BUFFCOMP.tooltip(5,"*吸收*");
} }
@@ -364,17 +298,6 @@ export class HeroSkillSystem extends ecs.ComblockSystem implements ecs.ISystemUp
// 实现debuff逻辑... // 实现debuff逻辑...
} }
/** 外部调用重置冷却 */
public resetSkillCooldown(entity: ecs.Entity, skillId: number) {
const comp = entity.get(HeroSkillsComp);
comp.resetCooldown(skillId);
}
/** 重置所有技能冷却 */
public resetAllCooldowns(entity: ecs.Entity) {
const comp = entity.get(HeroSkillsComp);
comp.resetAllCooldowns();
}
} }