diff --git a/src/client/SkinTestController.ts b/src/client/SkinTestController.ts index 94c5fe8a6..bab761fb2 100644 --- a/src/client/SkinTestController.ts +++ b/src/client/SkinTestController.ts @@ -1,5 +1,5 @@ import { EventBus } from "../core/EventBus"; -import { GameView, PlayerView } from "../core/game/GameView"; +import { GameView } from "../core/game/GameView"; import { ClientID } from "../core/Schemas"; import { SkinTestWinModal } from "./hud/layers/SkinTestWinModal"; import { SendAttackIntentEvent } from "./Transport"; @@ -7,6 +7,7 @@ import { SendAttackIntentEvent } from "./Transport"; const INITIAL_ATTACK_DELAY_MS = 100; const MAX_PLAYER_LOOKUP_RETRIES = 50; const MODAL_TIMEOUT_MS = 120_000; +const INITIAL_ATTACK_TROOPS = 1_000_000; /** * Client-side controller for the "preview a skin" singleplayer game. @@ -17,7 +18,6 @@ const MODAL_TIMEOUT_MS = 120_000; * the EventBus + DOM — neither of which belong in src/core. */ export class SkinTestController { - private myPlayer: PlayerView | null = null; private attackTimer: ReturnType | null = null; private modalTimer: ReturnType | null = null; private lookupRetries = 0; @@ -70,19 +70,16 @@ export class SkinTestController { private runAttack(): void { if (!this.active) return; - if (this.myPlayer === null) { - const found = this.gameView.playerByClientID(this.clientID); - if (found === null) { - if (++this.lookupRetries >= MAX_PLAYER_LOOKUP_RETRIES) { - console.error("Skin test: gave up finding player"); - return; - } - this.scheduleAttack(); + // Wait for the player to exist in the GameView before firing — gives the + // worker time to addPlayer() once the spawn execution runs. + if (this.gameView.playerByClientID(this.clientID) === null) { + if (++this.lookupRetries >= MAX_PLAYER_LOOKUP_RETRIES) { + console.error("Skin test: gave up finding player"); return; } - this.myPlayer = found; + this.scheduleAttack(); + return; } - const troops = Math.floor(this.myPlayer.troops() / 2); - this.eventBus.emit(new SendAttackIntentEvent(null, troops)); + this.eventBus.emit(new SendAttackIntentEvent(null, INITIAL_ATTACK_TROOPS)); } } diff --git a/tests/client/SkinTestController.test.ts b/tests/client/SkinTestController.test.ts index 80a82ec4a..65f5cee20 100644 --- a/tests/client/SkinTestController.test.ts +++ b/tests/client/SkinTestController.test.ts @@ -40,14 +40,14 @@ describe("SkinTestController", () => { return { controller, onAttack, modal, onPreviewEnded }; } - it("schedules an initial attack with half the player's troops", () => { + it("schedules an initial attack with a fixed troop count", () => { const { controller, onAttack } = makeController(); controller.start(); vi.advanceTimersByTime(200); expect(onAttack).toHaveBeenCalledTimes(1); expect(onAttack.mock.calls[0][0]).toMatchObject({ targetID: null, - troops: 50, + troops: 1_000_000, }); }); diff --git a/tests/core/configuration/StartingTroops.test.ts b/tests/core/configuration/StartingTroops.test.ts new file mode 100644 index 000000000..eb266bc23 --- /dev/null +++ b/tests/core/configuration/StartingTroops.test.ts @@ -0,0 +1,48 @@ +import { describe, expect, it } from "vitest"; +import { Config } from "../../../src/core/configuration/Config"; +import { + Difficulty, + GameMapSize, + GameMapType, + GameMode, + GameType, + PlayerInfo, + PlayerType, +} from "../../../src/core/game/Game"; +import { UserSettings } from "../../../src/core/game/UserSettings"; +import { GameConfig } from "../../../src/core/Schemas"; + +function makeConfig(overrides: Partial = {}): Config { + const gameConfig: GameConfig = { + gameMap: GameMapType.Iceland, + gameMapSize: GameMapSize.Compact, + gameMode: GameMode.FFA, + gameType: GameType.Singleplayer, + difficulty: Difficulty.Easy, + nations: "disabled", + donateGold: false, + donateTroops: false, + bots: 0, + infiniteGold: true, + infiniteTroops: true, + instantBuild: false, + randomSpawn: true, + ...overrides, + }; + return new Config(gameConfig, new UserSettings(), false); +} + +const humanInfo = (): PlayerInfo => + new PlayerInfo("test", PlayerType.Human, "client1", "p1", false, null, []); + +describe("Config.startManpower with startingTroops override", () => { + it("uses startingTroops when set", () => { + const config = makeConfig({ startingTroops: 10_000_000 }); + expect(config.startManpower(humanInfo())).toBe(10_000_000); + }); + + it("falls back to 1_000_000 for infinite-troops human when override is absent", () => { + const config = makeConfig({ infiniteTroops: true }); + expect(config.startManpower(humanInfo())).toBe(1_000_000); + }); +});