Files
OpenFrontIO/src/core/game/UnitImpl.ts
T
2025-02-08 09:56:07 -08:00

127 lines
3.2 KiB
TypeScript

import { MessageType } from "./Game";
import { UnitUpdate } from "./GameUpdates";
import { GameUpdateType } from "./GameUpdates";
import { simpleHash, within } from "../Util";
import { Unit, TerraNullius, UnitType, Player, UnitInfo } from "./Game";
import { GameImpl } from "./GameImpl";
import { PlayerImpl } from "./PlayerImpl";
import { TileRef } from "./GameMap";
export class UnitImpl implements Unit {
private _active = true;
private _health: number;
private _lastTile: TileRef = null;
constructor(
private _type: UnitType,
private mg: GameImpl,
private _tile: TileRef,
private _troops: number,
private _id: number,
public _owner: PlayerImpl
) {
// default to half health (or 1 is no health specified)
this._health = (this.mg.unitInfo(_type).maxHealth ?? 2) / 2;
this._lastTile = _tile;
}
toUpdate(): UnitUpdate {
return {
type: GameUpdateType.Unit,
unitType: this._type,
id: this._id,
troops: this._troops,
ownerID: this._owner.smallID(),
isActive: this._active,
pos: { x: this.mg.x(this._tile), y: this.mg.y(this._tile) },
lastPos: { x: this.mg.x(this._lastTile), y: this.mg.y(this._lastTile) },
health: this.hasHealth() ? this._health : undefined,
};
}
type(): UnitType {
return this._type;
}
lastTile(): TileRef {
return this._lastTile;
}
move(tile: TileRef): void {
if (tile == null) {
throw new Error("tile cannot be null");
}
this._lastTile = this._tile;
this._tile = tile;
this.mg.addUpdate(this.toUpdate());
}
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(): TileRef {
return this._tile;
}
owner(): PlayerImpl {
return this._owner;
}
info(): UnitInfo {
return this.mg.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.mg.addUpdate(this.toUpdate());
this.mg.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.mg.addUpdate(this.toUpdate());
if (this.type() == UnitType.DefensePost) {
this.mg.removeDefensePost(this);
}
if (displayMessage) {
this.mg.displayMessage(
`Your ${this.type()} was destroyed`,
MessageType.ERROR,
this.owner().id()
);
}
}
isActive(): boolean {
return this._active;
}
hash(): number {
return this.tile() + simpleHash(this.type());
}
toString(): string {
return `Unit:${this._type},owner:${this.owner().name()}`;
}
}