74 lines
2.3 KiB
TypeScript
74 lines
2.3 KiB
TypeScript
import { oops } from "db://oops-framework/core/Oops";
|
|
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
|
import { HeroViewComp } from "../hero/HeroViewComp";
|
|
import { DamageRequest, DamageResult } from "./DamageComp";
|
|
|
|
@ecs.register('DamageSystem')
|
|
export class DamageSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate {
|
|
private _timers: { [key: string]: number } = {};
|
|
|
|
filter(): ecs.IMatcher {
|
|
return ecs.allOf(DamageRequest);
|
|
}
|
|
|
|
update(e: ecs.Entity) {
|
|
const req = e.get(DamageRequest);
|
|
const result = this.calculateDamage(req);
|
|
this.applyDamage(req.target, result);
|
|
e.remove(DamageRequest);
|
|
}
|
|
|
|
private calculateDamage(req: DamageRequest): DamageResult {
|
|
const targetView = req.target.get(HeroViewComp);
|
|
const sourceView = req.source.get(HeroViewComp);
|
|
let final = req.baseValue;
|
|
|
|
// 闪避判定
|
|
if (Math.random() < targetView.dodge) {
|
|
const result = new DamageResult();
|
|
result.isDodged = true;
|
|
return result;
|
|
}
|
|
|
|
// 护甲减伤
|
|
if (!req.ignoreDefense) {
|
|
final -= targetView.def * 0.5;
|
|
}
|
|
|
|
// 暴击判定
|
|
let isCrit = false;
|
|
if (req.canCrit) {
|
|
const critRate = sourceView.crit;
|
|
if (Math.random() < critRate) {
|
|
final *= 1.5;
|
|
isCrit = true;
|
|
}
|
|
}
|
|
|
|
const result = new DamageResult();
|
|
result.value = Math.max(0, final);
|
|
result.isCrit = isCrit;
|
|
result.position = req.target.get(HeroViewComp).node.position;
|
|
result.delay = req.delay;
|
|
return result;
|
|
}
|
|
|
|
private applyDamage(target: ecs.Entity, result: DamageResult) {
|
|
const view = target.get(HeroViewComp);
|
|
view.hp -= result.value;
|
|
// 添加伤害结果组件
|
|
const comp = target.add(DamageResult);
|
|
comp.value = result.value;
|
|
comp.isCrit = result.isCrit;
|
|
comp.position = result.position;
|
|
comp.delay = result.delay;
|
|
comp.isDodged = result.isDodged;
|
|
|
|
// 触发伤害事件
|
|
oops.message.dispatchEvent("OnDamage", {
|
|
target,
|
|
damage: result.value,
|
|
isCrit: result.isCrit
|
|
});
|
|
}
|
|
}
|