Multiple healths as shields
This commit is contained in:
parent
e1ba738ea0
commit
9a1fb9b655
|
|
@ -65,7 +65,10 @@ export class Stat<T = {}> extends Component<StatState & T> {
|
|||
}
|
||||
|
||||
@component
|
||||
export class Health extends Stat {
|
||||
export class Health extends Stat<{ damageTypes?: string[]; priority?: number }> {
|
||||
get damageTypes(): readonly string[] { return this.state.damageTypes ?? []; }
|
||||
get priority(): number { return this.state.priority ?? 0; }
|
||||
|
||||
@action
|
||||
kill() {
|
||||
this.set(0);
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ export class CombatSystem extends System {
|
|||
let random: Random | undefined;
|
||||
|
||||
for (const [target] of world.query(Attacked)) {
|
||||
const health = target.get(Health);
|
||||
if (!health) {
|
||||
const healths = target.getAll(Health).sort((a, b) => b.priority - a.priority);
|
||||
if (healths.length === 0) {
|
||||
console.warn(`[CombatSystem] Target ${target.id} has no Health component`);
|
||||
for (const attack of target.getAll(Attacked)) target.remove(attack);
|
||||
continue;
|
||||
|
|
@ -116,14 +116,43 @@ export class CombatSystem extends System {
|
|||
|
||||
if (damageSum === 0) continue;
|
||||
|
||||
const wasAlive = health.value > 0;
|
||||
health.update(-damageSum);
|
||||
let totalBefore = 0;
|
||||
for (const pool of healths) totalBefore += pool.value;
|
||||
|
||||
for (const hit of hitEvents) {
|
||||
let remaining = hit.amount;
|
||||
|
||||
if (hit.damageType) {
|
||||
for (const pool of healths) {
|
||||
if (remaining <= 0) break;
|
||||
if (pool.value <= 0) continue;
|
||||
if (!pool.damageTypes.includes(hit.damageType)) continue;
|
||||
const take = Math.min(pool.value, remaining);
|
||||
pool.update(-take);
|
||||
remaining -= take;
|
||||
}
|
||||
}
|
||||
|
||||
if (remaining > 0) {
|
||||
for (const pool of healths) {
|
||||
if (remaining <= 0) break;
|
||||
if (pool.value <= 0) continue;
|
||||
if (pool.damageTypes.length > 0) continue;
|
||||
const take = Math.min(pool.value, remaining);
|
||||
pool.update(-take);
|
||||
remaining -= take;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const info of hitEvents) {
|
||||
target.emit('Combat.hit', info);
|
||||
}
|
||||
|
||||
if (wasAlive && health.value <= 0 && lastHit) {
|
||||
let totalAfter = 0;
|
||||
for (const pool of healths) totalAfter += pool.value;
|
||||
|
||||
if (totalBefore > 0 && totalAfter <= 0 && lastHit) {
|
||||
target.emit('Combat.killed', lastHit);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue