From f8c5d29b367ebbada84553a0a14b2e0ec9c2d754 Mon Sep 17 00:00:00 2001 From: Evan Date: Thu, 20 Feb 2025 10:45:55 -0800 Subject: [PATCH] bugfix: show updated cost when building a unit while another unit of same type is under construction --- src/client/graphics/layers/BuildMenu.ts | 23 +++++++++++++++++------ src/core/GameRunner.ts | 11 ++++++++--- src/core/configuration/DefaultConfig.ts | 17 +++++++++++++---- src/core/game/Game.ts | 9 ++++++++- src/core/game/PlayerImpl.ts | 10 ++++++++++ 5 files changed, 56 insertions(+), 14 deletions(-) diff --git a/src/client/graphics/layers/BuildMenu.ts b/src/client/graphics/layers/BuildMenu.ts index 471a75de8..a668a67f2 100644 --- a/src/client/graphics/layers/BuildMenu.ts +++ b/src/client/graphics/layers/BuildMenu.ts @@ -228,7 +228,22 @@ export class BuildMenu extends LitElement { if (this.myPlayer == null || this.playerActions == null) { return false; } - return this.playerActions.buildableUnits.some((u) => u == item.unitType); + const unit = this.playerActions.buildableUnits.filter( + (u) => u.type == item.unitType, + ); + if (!unit) { + return false; + } + return unit[0].canBuild; + } + + private cost(item: BuildItemDisplay): number { + for (const bu of this.playerActions.buildableUnits) { + if (bu.type == item.unitType) { + return bu.cost; + } + } + return 0; } public onBuildSelected = (item: BuildItemDisplay) => { @@ -265,11 +280,7 @@ export class BuildMenu extends LitElement { ${item.description} ${renderNumber( - this.game && this.myPlayer - ? this.game - .unitInfo(item.unitType) - .cost(this.myPlayer) - : 0, + this.game && this.myPlayer ? this.cost(item) : 0, )} player.canBuild(ut, tile) != false, - ), + buildableUnits: Object.values(UnitType).map((u) => { + return { + type: u, + canBuild: player.canBuild(u, tile) != false, + cost: this.game.config().unitInfo(u).cost(player), + } as BuildableUnit; + }), canSendEmojiAllPlayers: player.canSendEmoji(AllPlayers), } as PlayerActions; diff --git a/src/core/configuration/DefaultConfig.ts b/src/core/configuration/DefaultConfig.ts index d5bea4a21..2e26256e0 100644 --- a/src/core/configuration/DefaultConfig.ts +++ b/src/core/configuration/DefaultConfig.ts @@ -114,7 +114,8 @@ export class DefaultConfig implements Config { cost: (p: Player) => p.type() == PlayerType.Human && this.creativeMode() ? 0 - : (p.units(UnitType.Warship).length + 1) * 250_000, + : (p.unitsIncludingConstruction(UnitType.Warship).length + 1) * + 250_000, territoryBound: false, maxHealth: 1000, }; @@ -131,7 +132,10 @@ export class DefaultConfig implements Config { ? 0 : Math.min( 1_000_000, - Math.pow(2, p.units(UnitType.Port).length) * 250_000, + Math.pow( + 2, + p.unitsIncludingConstruction(UnitType.Port).length, + ) * 250_000, ), territoryBound: true, constructionDuration: this.creativeMode() ? 0 : 2 * 10, @@ -180,7 +184,9 @@ export class DefaultConfig implements Config { ? 0 : Math.min( 250_000, - (p.units(UnitType.DefensePost).length + 1) * 50_000, + (p.unitsIncludingConstruction(UnitType.DefensePost).length + + 1) * + 50_000, ), territoryBound: true, constructionDuration: this.creativeMode() ? 0 : 5 * 10, @@ -192,7 +198,10 @@ export class DefaultConfig implements Config { ? 0 : Math.min( 1_000_000, - Math.pow(2, p.units(UnitType.City).length) * 125_000, + Math.pow( + 2, + p.unitsIncludingConstruction(UnitType.City).length, + ) * 125_000, ), territoryBound: true, constructionDuration: this.creativeMode() ? 0 : 2 * 10, diff --git a/src/core/game/Game.ts b/src/core/game/Game.ts index 903c83f68..11e6bfc52 100644 --- a/src/core/game/Game.ts +++ b/src/core/game/Game.ts @@ -264,6 +264,7 @@ export interface Player { // Units units(...types: UnitType[]): Unit[]; + unitsIncludingConstruction(type: UnitType): Unit[]; canBuild(type: UnitType, targetTile: TileRef): TileRef | false; buildUnit(type: UnitType, troops: number, tile: TileRef): Unit; captureUnit(unit: Unit): void; @@ -367,11 +368,17 @@ export interface Game extends GameMap { export interface PlayerActions { canBoat: boolean; canAttack: boolean; - buildableUnits: UnitType[]; + buildableUnits: BuildableUnit[]; canSendEmojiAllPlayers: boolean; interaction?: PlayerInteraction; } +export interface BuildableUnit { + canBuild: boolean; + type: UnitType; + cost: number; +} + export interface PlayerProfile { relations: Record; alliances: number[]; diff --git a/src/core/game/PlayerImpl.ts b/src/core/game/PlayerImpl.ts index 20fed8325..c1019c59a 100644 --- a/src/core/game/PlayerImpl.ts +++ b/src/core/game/PlayerImpl.ts @@ -176,6 +176,16 @@ export class PlayerImpl implements Player { return this._units.filter((u) => ts.has(u.type())); } + unitsIncludingConstruction(type: UnitType): Unit[] { + const units = this.units(type); + units.push( + ...this.units(UnitType.Construction).filter( + (u) => u.constructionType() == type, + ), + ); + return units; + } + sharesBorderWith(other: Player | TerraNullius): boolean { for (const border of this._borderTiles) { for (const neighbor of this.mg.map().neighbors(border)) {