201 lines
5.8 KiB
TypeScript
201 lines
5.8 KiB
TypeScript
import { InvalidArgument } from "@sammo/util";
|
|
import { City } from "./City.js";
|
|
import type { IGeneralEntity } from "./Entity/GeneralEntity.js";
|
|
import type { IResourceController } from "./IResourceController.js";
|
|
import { DiplomaticPermission, type CityID, type GeneralID, type GeneralName, type NationID, OfficerLevel, type SquadID, NpcType, StaffLevel, CityOfficerLevel } from "./defs.js";
|
|
import { must } from "@sammo/util";
|
|
import { Nation } from "./Nation.js";
|
|
import { Squad } from "./Squad.js";
|
|
import { LazyEntityUpdater } from "./LazyEntityUpdater.js";
|
|
import type { IAction, IActionKey } from "./IAction.js";
|
|
import { addSeconds } from "date-fns";
|
|
|
|
export class General extends LazyEntityUpdater<IGeneralEntity> {
|
|
protected readonly _indirectNames: (keyof IGeneralEntity)[] = [
|
|
"id", "nationID", "squadID", "nationID", "turnTime"
|
|
];
|
|
protected readonly _entityType = "General";
|
|
protected readonly _raw: IGeneralEntity;
|
|
|
|
protected _city!: WeakRef<City>;
|
|
protected _squad!: WeakRef<Squad> | undefined;
|
|
protected _nation!: WeakRef<Nation>;
|
|
|
|
protected readonly iActionHandlers = new Map<IActionKey, IAction>;
|
|
|
|
constructor(
|
|
raw: IGeneralEntity,
|
|
protected readonly rsc: IResourceController
|
|
){
|
|
super();
|
|
this._raw = raw;
|
|
}
|
|
|
|
public bootstrap(){
|
|
const rsc = this.rsc;
|
|
const raw = this._raw;
|
|
this._city = new WeakRef(must(rsc.city(raw.cityID)));
|
|
this._nation = new WeakRef(must(rsc.nation(raw.nationID)));
|
|
|
|
if(raw.squadID){
|
|
this._squad = new WeakRef(must(rsc.squad(raw.squadID, raw.nationID)));
|
|
}
|
|
|
|
//TODO: iActionHandlers 초기화
|
|
}
|
|
|
|
public get id(): GeneralID {
|
|
return this._raw.id;
|
|
}
|
|
|
|
public get name(): GeneralName {
|
|
return this._raw.name;
|
|
}
|
|
|
|
public get city(): City {
|
|
return must(this._city.deref());
|
|
}
|
|
|
|
public get squad(): Squad | undefined {
|
|
return this._squad?.deref();
|
|
}
|
|
|
|
public get nation(): Nation {
|
|
return must(this._nation.deref());
|
|
}
|
|
|
|
public get isUser(): boolean {
|
|
return this._raw.npcType <= NpcType.user_borrowed_npc;
|
|
}
|
|
|
|
public get staffLevel(): StaffLevel | undefined {
|
|
if(this._raw.officerLevel < OfficerLevel.staffIntel3){
|
|
return undefined;
|
|
}
|
|
return this._raw.officerLevel as number as StaffLevel;
|
|
}
|
|
|
|
public get cityOfficerLevel(): CityOfficerLevel | undefined {
|
|
if(this._raw.officerLevel >= OfficerLevel.staffIntel3){
|
|
return undefined;
|
|
}
|
|
if(this._raw.officerLevel < OfficerLevel.cityLeadership){
|
|
return undefined;
|
|
}
|
|
|
|
return this._raw.officerLevel as number as CityOfficerLevel;
|
|
}
|
|
|
|
public changeCity(city: CityID | City){
|
|
const cityObj: City = (()=>{
|
|
if(city instanceof City){
|
|
return city;
|
|
}
|
|
const cityObj = this.rsc.city(city);
|
|
if(!cityObj){
|
|
throw new InvalidArgument(`City not found: ${city}`);
|
|
}
|
|
return cityObj;
|
|
})();
|
|
this._city = new WeakRef(cityObj);
|
|
|
|
//TODO: ResourceController에게 알려야 하는가?
|
|
this.forceUpdate((raw) => {
|
|
raw.cityID = cityObj.id;
|
|
});
|
|
}
|
|
|
|
public quitSquad(){
|
|
if(!this._squad){
|
|
return;
|
|
}
|
|
|
|
const squad = must(this._squad.deref());
|
|
if(squad.leader.id === this._raw.id){
|
|
squad.destroySquad(false);
|
|
}
|
|
else{
|
|
squad.members.delete(this._raw.id);
|
|
}
|
|
|
|
this._squad = undefined;
|
|
this.forceUpdate((raw) => {
|
|
raw.squadID = undefined;
|
|
});
|
|
}
|
|
|
|
public changeSquad(squad: SquadID | Squad){
|
|
this.quitSquad();
|
|
|
|
const squadObj: Squad = (()=>{
|
|
if(squad instanceof Squad){
|
|
return squad;
|
|
}
|
|
const squadObj = this.rsc.squad(squad, this._raw.nationID);
|
|
if(!squadObj){
|
|
throw new InvalidArgument(`Squad not found: ${squad}`);
|
|
}
|
|
return squadObj;
|
|
})();
|
|
|
|
squadObj.members.set(this._raw.id, new WeakRef(this));
|
|
this._squad = new WeakRef(squadObj);
|
|
this.forceUpdate((raw) => {
|
|
raw.squadID = squadObj.id;
|
|
});
|
|
}
|
|
|
|
public changeNation(nation: NationID | Nation){
|
|
const nationObj: Nation = (()=>{
|
|
if(nation instanceof Nation){
|
|
return nation;
|
|
}
|
|
const nationObj = this.rsc.nation(nation);
|
|
if(!nationObj){
|
|
throw new InvalidArgument(`Nation not found: ${nation}`);
|
|
}
|
|
return nationObj;
|
|
})();
|
|
this._nation = new WeakRef(nationObj);
|
|
this.quitSquad();
|
|
|
|
this.forceUpdate((raw) => {
|
|
raw.nationID = nationObj.id;
|
|
raw.diplomaticPermission = DiplomaticPermission.none;
|
|
if(nationObj.id == 0){
|
|
raw.officerLevel = OfficerLevel.none;
|
|
}
|
|
else{
|
|
raw.officerLevel = OfficerLevel.normal;
|
|
}
|
|
raw.nationJoinedYearMonth = this.rsc.gameEnv.raw.yearMonth;
|
|
});
|
|
}
|
|
|
|
public updateTurnTime(){
|
|
const secondsPerTurn = this.rsc.gameEnv.raw.secondsPerTurn;
|
|
|
|
this.forceUpdate((raw) => {
|
|
raw.turnTime = addSeconds(raw.turnTime, secondsPerTurn);
|
|
});
|
|
|
|
}
|
|
|
|
public compareTurnTime(other: General): number {
|
|
if(this._raw.turnTime < other._raw.turnTime){
|
|
return -1;
|
|
}
|
|
if(this._raw.turnTime > other._raw.turnTime){
|
|
return 1;
|
|
}
|
|
|
|
if(this._raw.id < other._raw.id){
|
|
return -1;
|
|
}
|
|
if(this._raw.id > other._raw.id){
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
} |