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
|
@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
|
@action
|
||||||
kill() {
|
kill() {
|
||||||
this.set(0);
|
this.set(0);
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,8 @@ export class CombatSystem extends System {
|
||||||
let random: Random | undefined;
|
let random: Random | undefined;
|
||||||
|
|
||||||
for (const [target] of world.query(Attacked)) {
|
for (const [target] of world.query(Attacked)) {
|
||||||
const health = target.get(Health);
|
const healths = target.getAll(Health).sort((a, b) => b.priority - a.priority);
|
||||||
if (!health) {
|
if (healths.length === 0) {
|
||||||
console.warn(`[CombatSystem] Target ${target.id} has no Health component`);
|
console.warn(`[CombatSystem] Target ${target.id} has no Health component`);
|
||||||
for (const attack of target.getAll(Attacked)) target.remove(attack);
|
for (const attack of target.getAll(Attacked)) target.remove(attack);
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -116,14 +116,43 @@ export class CombatSystem extends System {
|
||||||
|
|
||||||
if (damageSum === 0) continue;
|
if (damageSum === 0) continue;
|
||||||
|
|
||||||
const wasAlive = health.value > 0;
|
let totalBefore = 0;
|
||||||
health.update(-damageSum);
|
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) {
|
for (const info of hitEvents) {
|
||||||
target.emit('Combat.hit', info);
|
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);
|
target.emit('Combat.killed', lastHit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue