Files
OpenFrontIO/src/core/game/UnitImpl.ts
T
2025-02-01 12:05:11 -08:00

116 lines
3.2 KiB
TypeScript

import { MessageType } from "../../client/graphics/layers/EventsDisplay";
import { UnitViewData, ViewData, ViewSerializable } from "../GameView";
import { simpleHash, within } from "../Util";
import { MutableUnit, Tile, TerraNullius, UnitType, Player, UnitInfo } from "./Game";
import { GameImpl } from "./GameImpl";
import { PlayerImpl } from "./PlayerImpl";
import { TerraNulliusImpl } from "./TerraNulliusImpl";
export class UnitImpl implements MutableUnit, ViewSerializable<UnitViewData> {
private _active = true;
private _health: number
constructor(
private _type: UnitType,
private g: GameImpl,
private _tile: Tile,
private _troops: number,
public _owner: PlayerImpl,
) {
// default to half health (or 1 is no health specified)
this._health = (this.g.unitInfo(_type).maxHealth ?? 2) / 2
}
toViewData(): ViewData<UnitViewData> {
return {
type: this._type,
troops: this._troops,
x: this.tile().cell().x,
y: this.tile().cell().y,
owner: this.owner().id(),
isActive: this.isActive(),
health: this._health,
}
}
type(): UnitType {
return this._type
}
move(tile: Tile): void {
if (tile == null) {
throw new Error("tile cannot be null")
}
const oldTile = this._tile;
this._tile = tile;
this.g.fireUnitUpdateEvent(this, oldTile);
}
setTroops(troops: number): void {
this._troops = troops;
}
troops(): number {
return this._troops;
}
health(): number {
return this._health
}
hasHealth(): boolean {
return this.info().maxHealth != undefined
}
tile(): Tile {
return this._tile;
}
owner(): PlayerImpl {
return this._owner;
}
info(): UnitInfo {
return this.g.unitInfo(this._type)
}
setOwner(newOwner: Player): void {
const oldOwner = this._owner
oldOwner._units = oldOwner._units.filter(u => u != this)
this._owner = newOwner as PlayerImpl
this.g.fireUnitUpdateEvent(this, this.tile())
this.g.displayMessage(
`Your ${this.type()} was captured by ${newOwner.displayName()}`,
MessageType.ERROR,
oldOwner.id()
)
}
modifyHealth(delta: number): void {
this._health = within(
this._health + delta,
0,
this.info().maxHealth ?? 1
)
}
delete(displayMessage: boolean = true): void {
if (!this.isActive()) {
throw new Error(`cannot delete ${this} not active`)
}
this._owner._units = this._owner._units.filter(b => b != this);
this._active = false;
this.g.fireUnitUpdateEvent(this, this._tile);
if (displayMessage) {
this.g.displayMessage(`Your ${this.type()} was destroyed`, MessageType.ERROR, this.owner().id())
}
}
isActive(): boolean {
return this._active;
}
hash(): number {
return this.tile().cell().x + this.tile().cell().y + simpleHash(this.type())
}
toString(): string {
return `Unit:${this._type},owner:${this.owner().name()}`
}
}