技能逻辑修改,怪物只攻击最前方,友方和地方逻辑分开
This commit is contained in:
@@ -131,12 +131,9 @@ export class HeroSkillSystem extends ecs.ComblockSystem implements ecs.ISystemUp
|
||||
view.at = view.at-view.cd; // 重置普攻计时器
|
||||
break;
|
||||
}
|
||||
|
||||
// 选择目标
|
||||
const targets = this.selectTargets(caster, config);
|
||||
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, // 起始位置
|
||||
@@ -145,45 +142,38 @@ export class HeroSkillSystem extends ecs.ComblockSystem implements ecs.ISystemUp
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
||||
/** 选择技能目标 */
|
||||
private selectTargets(caster: ecs.Entity, config: typeof SkillSet[keyof typeof SkillSet]): ecs.Entity[] {
|
||||
if (config.TargetGroup === TargetGroup.Self) {
|
||||
this.applySkillEffect(caster, caster, config);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private selectEnemyTargets(caster: ecs.Entity, config: typeof SkillSet[keyof typeof SkillSet]): ecs.Entity[] {
|
||||
const casterView = caster.get(HeroViewComp);
|
||||
const team = casterView.fac;
|
||||
const isEnemyTeam = team === 0 ? 1 : 0;
|
||||
|
||||
// 第一阶段:基础目标筛选
|
||||
let candidates = ecs.query(ecs.allOf(HeroViewComp)).filter(e => {
|
||||
const view = e.get(HeroViewComp);
|
||||
// 根据技能目标类型筛选
|
||||
switch(config.TargetGroup) {
|
||||
case TargetGroup.Enemy:
|
||||
return view.fac !== team;
|
||||
case TargetGroup.Ally:
|
||||
return view.fac === team && e !== caster;
|
||||
case TargetGroup.Self:
|
||||
return e === caster;
|
||||
default:
|
||||
return true;
|
||||
const candidates= ecs.query(ecs.allOf(HeroViewComp)).filter(e => e.get(HeroViewComp).fac !== team);
|
||||
return this.filterFrontRow(candidates, isEnemyTeam);
|
||||
}
|
||||
});
|
||||
|
||||
private selectAllyTargets(caster: ecs.Entity, config: typeof SkillSet[keyof typeof SkillSet]): ecs.Entity[] {
|
||||
const casterView = caster.get(HeroViewComp);
|
||||
const team = casterView.fac;
|
||||
const candidates= ecs.query(ecs.allOf(HeroViewComp)).filter(e => e.get(HeroViewComp).fac === team);
|
||||
// 第二阶段:位置/血量等精细筛选
|
||||
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:
|
||||
return candidates.filter(e => e.get(HeroViewComp).type === 0);
|
||||
case TargetType.Ranged:
|
||||
@@ -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[] {
|
||||
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;
|
||||
}
|
||||
|
||||
const targetView = target.get(HeroViewComp);
|
||||
const sourceView = caster.get(HeroViewComp);
|
||||
let final = sourceView.ap * config.ap / 100;
|
||||
|
||||
@@ -281,34 +246,8 @@ export class HeroSkillSystem extends ecs.ComblockSystem implements ecs.ISystemUp
|
||||
final *= damageFloat;
|
||||
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.isCrit = isCrit;
|
||||
|
||||
result.isCrit = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -319,11 +258,6 @@ export class HeroSkillSystem extends ecs.ComblockSystem implements ecs.ISystemUp
|
||||
const view = target.get(HeroViewComp);
|
||||
if (!view?.ent.has(HeroViewComp)) return;
|
||||
|
||||
if(result.isDodged){
|
||||
view.BUFFCOMP.tooltip(5,"*闪避*");
|
||||
return;
|
||||
}
|
||||
|
||||
let remainingDamage = result.value;
|
||||
if (view.shield > 0) {
|
||||
const shieldAbsorb = Math.min(view.shield, remainingDamage);
|
||||
@@ -341,7 +275,7 @@ export class HeroSkillSystem extends ecs.ComblockSystem implements ecs.ISystemUp
|
||||
view.BUFFCOMP.dead()
|
||||
view.to_grave();
|
||||
}
|
||||
view.showDamage(result.value, result.isCrit);
|
||||
view.showDamage(result.value, true);
|
||||
} else {
|
||||
view.BUFFCOMP.tooltip(5,"*吸收*");
|
||||
}
|
||||
@@ -364,17 +298,6 @@ export class HeroSkillSystem extends ecs.ComblockSystem implements ecs.ISystemUp
|
||||
// 实现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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user