mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-22 03:34:03 +00:00
149 lines
3.7 KiB
TypeScript
149 lines
3.7 KiB
TypeScript
import { MessageType } from "./Game";
|
|
import { UnitUpdate } from "./GameUpdates";
|
|
import { GameUpdateType } from "./GameUpdates";
|
|
import { simpleHash, toInt, within, withinInt } 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: bigint;
|
|
private _lastTile: TileRef = null;
|
|
|
|
private _constructionType: UnitType = undefined;
|
|
|
|
constructor(
|
|
private _type: UnitType,
|
|
private mg: GameImpl,
|
|
private _tile: TileRef,
|
|
private _troops: number,
|
|
private _id: number,
|
|
public _owner: PlayerImpl,
|
|
) {
|
|
// default to 60% health (or 1.2 is no health specified)
|
|
this._health = (this.mg.unitInfo(_type).maxHealth ?? 2) * 0.6;
|
|
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: this._tile,
|
|
lastPos: this._lastTile,
|
|
health: this.hasHealth() ? Number(this._health) : undefined,
|
|
constructionType: this._constructionType,
|
|
};
|
|
}
|
|
|
|
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 Number(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 = withinInt(
|
|
this._health + toInt(delta),
|
|
0n,
|
|
toInt(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;
|
|
}
|
|
|
|
constructionType(): UnitType | null {
|
|
if (this.type() != UnitType.Construction) {
|
|
throw new Error(`Cannot get construction type on ${this.type()}`);
|
|
}
|
|
return this._constructionType;
|
|
}
|
|
|
|
setConstructionType(type: UnitType): void {
|
|
if (this.type() != UnitType.Construction) {
|
|
throw new Error(`Cannot set construction type on ${this.type()}`);
|
|
}
|
|
this._constructionType = type;
|
|
this.mg.addUpdate(this.toUpdate());
|
|
}
|
|
|
|
hash(): number {
|
|
return this.tile() + simpleHash(this.type()) * this._id;
|
|
}
|
|
|
|
toString(): string {
|
|
return `Unit:${this._type},owner:${this.owner().name()}`;
|
|
}
|
|
}
|