import { ISystem, System, Component, Components } from '../engine/system'; import { IEntity, State, DoSet, IAction } from '../engine/state'; import { IHudWindow } from '../../client/engine/ui'; interface IStat { name: string; current: number; min: number; max: number; regen: number; } interface IStatsComponent { [key: string]: IStat; } const clampStat = (stat: IStat) => { stat.current = Math.max(stat.current, stat.min); stat.current = Math.min(stat.current, stat.max); }; const tickStat = (stat: IStat, delta: number) => { stat.current += stat.regen * delta; clampStat(stat); // console.log(stat.name + ' ' + Math.floor(stat.current)); }; export interface IDamageAction extends IAction { type: 'DAMAGE'; entityId: string; stat: string; amount: number; } export const DoDamage = (entity: IEntity, stat: string, amount: number): IDamageAction => { return { type: 'DAMAGE', entityId: entity.id, stat, amount }; }; @Components('stats') export class Stats extends System { add(entity: IEntity) { super.add(entity); this.dispatch(DoSet(entity.id, 'stats', Object.assign({}, entity.stats))); this.update(entity, 'stats'); } HandleDamage(a: IDamageAction) { const entity = this.entities[a.entityId]; const stat = entity.stats[a.stat]; if (stat === undefined) return; const before = stat.current; stat.current -= a.amount; clampStat(stat); const after = stat.current; const dealt = before - after; const newStats = Object.assign({}, entity.stats) as IStatsComponent; newStats[a.stat] = stat; // TODO - it might be optimal to capture all 'dirty' stats and do a batch update after all actions are handled this.dispatch(DoSet(entity.id, 'stats', newStats)); } tick(delta) { this.actions({ DAMAGE: this.HandleDamage }); Object.keys(this.entities).forEach(id => { const entity = this.entities[id]; const newStats = Object.assign({}, entity.stats) as IStatsComponent; Object.keys(newStats).forEach(k => { const stat = newStats[k]; tickStat(stat, delta); }); this.dispatch(DoSet(entity.id, 'stats', newStats)); // TODO - move this out of here and make it only happen for the the player entity const hw = window as IHudWindow; hw.hud.updateStats(entity.stats['health'].current); }); } }