From e7039d3e079274782c27792bea16c5d8e6b3e935 Mon Sep 17 00:00:00 2001 From: Evan Date: Sat, 30 Nov 2024 20:54:42 -0800 Subject: [PATCH] add defense post unit (no execution) --- TODO.txt | 3 +- resources/images/ShieldIcon.png | Bin 0 -> 112 bytes resources/images/ShieldIconWhite.svg | 57 ++++++++++++++++++ src/client/graphics/layers/StructureLayer.ts | 6 ++ src/client/graphics/layers/UnitLayer.ts | 3 - .../graphics/layers/radial/BuildMenu.ts | 4 +- src/core/configuration/DefaultConfig.ts | 5 ++ src/core/configuration/DevConfig.ts | 2 +- src/core/execution/DefensePostExecution.ts | 43 +++++++++++++ src/core/execution/ExecutionManager.ts | 3 + src/core/execution/PortExecution.ts | 1 + src/core/game/Game.ts | 1 + src/core/game/PlayerImpl.ts | 6 +- 13 files changed, 126 insertions(+), 8 deletions(-) create mode 100644 resources/images/ShieldIcon.png create mode 100644 resources/images/ShieldIconWhite.svg create mode 100644 src/core/execution/DefensePostExecution.ts diff --git a/TODO.txt b/TODO.txt index 492603226..a519958ee 100644 --- a/TODO.txt +++ b/TODO.txt @@ -200,8 +200,9 @@ * make mini map for path finding DONE 11/29/2024 * have NPCs build destroyers and battleships DONE 11/30/2024 * add info view on top right DONE 11/30/2024 -* add info view for units +* add info view for units DONE 11/30/2024 * add defense post +* record single player games * add radiation from nuke * add cities * create alternate view to show friendly & enemy units diff --git a/resources/images/ShieldIcon.png b/resources/images/ShieldIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..391902d6c77f4edd8520966df2ebad4f506e8867 GIT binary patch literal 112 zcmeAS@N?(olHy`uVBq!ia0vp^oFL4>1|%O$WD@{VjKx9jP7LeL$-D$|v^-rLLo|Yu zQyLon2S`aDJ>lWN7;%|FL+R8*7wtn!1)dmgct3%$sN&#L21h1NwgMraSfDNjPgg&e IbxsLQ0JoMN#{d8T literal 0 HcmV?d00001 diff --git a/resources/images/ShieldIconWhite.svg b/resources/images/ShieldIconWhite.svg new file mode 100644 index 000000000..495260851 --- /dev/null +++ b/resources/images/ShieldIconWhite.svg @@ -0,0 +1,57 @@ + + + + + + + + + + + diff --git a/src/client/graphics/layers/StructureLayer.ts b/src/client/graphics/layers/StructureLayer.ts index aad5cd671..110e42de8 100644 --- a/src/client/graphics/layers/StructureLayer.ts +++ b/src/client/graphics/layers/StructureLayer.ts @@ -7,6 +7,7 @@ import { EventBus } from "../../../core/EventBus"; import anchorIcon from '../../../../resources/images/AnchorIcon.png'; import missileSiloIcon from '../../../../resources/images/MissileSiloUnit.png'; +import shieldIcon from '../../../../resources/images/ShieldIcon.png'; interface UnitRenderConfig { icon: string; @@ -32,6 +33,11 @@ export class StructureLayer implements Layer { icon: missileSiloIcon, borderRadius: 8, territoryRadius: 6 + }, + [UnitType.DefensePost]: { + icon: shieldIcon, + borderRadius: 8, + territoryRadius: 6 } }; diff --git a/src/client/graphics/layers/UnitLayer.ts b/src/client/graphics/layers/UnitLayer.ts index ab83e815d..5d3a03934 100644 --- a/src/client/graphics/layers/UnitLayer.ts +++ b/src/client/graphics/layers/UnitLayer.ts @@ -5,8 +5,6 @@ import { bfs, dist, euclDist } from "../../../core/Util"; import { Layer } from "./Layer"; import { EventBus } from "../../../core/EventBus"; -import anchorIcon from '../../../../resources/images/AnchorIcon.png'; - export class UnitLayer implements Layer { private canvas: HTMLCanvasElement; private context: CanvasRenderingContext2D; @@ -164,7 +162,6 @@ export class UnitLayer implements Layer { } } - paintCell(cell: Cell, color: Colord, alpha: number) { this.clearCell(cell) this.context.fillStyle = color.alpha(alpha / 255).toRgbString(); diff --git a/src/client/graphics/layers/radial/BuildMenu.ts b/src/client/graphics/layers/radial/BuildMenu.ts index 29d7ebc5b..f98556e74 100644 --- a/src/client/graphics/layers/radial/BuildMenu.ts +++ b/src/client/graphics/layers/radial/BuildMenu.ts @@ -10,6 +10,7 @@ import battleshipIcon from '../../../../../resources/images/BattleshipIconWhite. import missileSiloIcon from '../../../../../resources/images/MissileSiloIconWhite.svg'; import goldCoinIcon from '../../../../../resources/images/GoldCoinIcon.svg'; import portIcon from '../../../../../resources/images/PortIcon.svg'; +import shieldIcon from '../../../../../resources/images/ShieldIconWhite.svg'; import { renderNumber } from '../../Utils'; import { ContextMenuEvent } from '../../../InputHandler'; @@ -25,7 +26,8 @@ const buildTable: BuildItemDisplay[][] = [ { unitType: UnitType.Destroyer, icon: destroyerIcon }, { unitType: UnitType.Battleship, icon: battleshipIcon }, { unitType: UnitType.Port, icon: portIcon }, - { unitType: UnitType.MissileSilo, icon: missileSiloIcon } + { unitType: UnitType.MissileSilo, icon: missileSiloIcon }, + { unitType: UnitType.DefensePost, icon: shieldIcon } ] ]; diff --git a/src/core/configuration/DefaultConfig.ts b/src/core/configuration/DefaultConfig.ts index b4917202f..8db846c5d 100644 --- a/src/core/configuration/DefaultConfig.ts +++ b/src/core/configuration/DefaultConfig.ts @@ -64,6 +64,11 @@ export class DefaultConfig implements Config { cost: () => 1_000_000, territoryBound: true } + case UnitType.DefensePost: + return { + cost: (p: Player) => Math.pow(2, p.units(UnitType.Port).length) * 100_000, + territoryBound: true + } default: assertNever(type) } diff --git a/src/core/configuration/DevConfig.ts b/src/core/configuration/DevConfig.ts index abf52d718..bb3edb960 100644 --- a/src/core/configuration/DevConfig.ts +++ b/src/core/configuration/DevConfig.ts @@ -5,7 +5,7 @@ export const devConfig = new class extends DefaultConfig { unitInfo(type: UnitType): UnitInfo { const info = super.unitInfo(type) const oldCost = info.cost - // info.cost = (p: Player) => oldCost(p) / 1000 + info.cost = (p: Player) => oldCost(p) / 1000 return info } diff --git a/src/core/execution/DefensePostExecution.ts b/src/core/execution/DefensePostExecution.ts new file mode 100644 index 000000000..0427f3ff2 --- /dev/null +++ b/src/core/execution/DefensePostExecution.ts @@ -0,0 +1,43 @@ +import { Cell, Execution, MutableGame, MutablePlayer, MutableUnit, PlayerID, Tile, UnitType } from "../game/Game"; + +export class DefensePostExecution implements Execution { + + private player: MutablePlayer + private mg: MutableGame + private post: MutableUnit + private tile: Tile + private active: boolean = true + + constructor(private ownerId: PlayerID, private cell: Cell) { } + + init(mg: MutableGame, ticks: number): void { + this.mg = mg + this.tile = mg.tile(this.cell) + this.player = mg.player(this.ownerId) + } + + tick(ticks: number): void { + if (this.post == null) { + const spawnTile = this.player.canBuild(UnitType.DefensePost, this.tile) + if (spawnTile == false) { + console.warn('cannot build Defense Post') + this.active = false + return + } + this.post = this.player.buildUnit(UnitType.DefensePost, 0, spawnTile) + } + } + + owner(): MutablePlayer { + return null + } + + isActive(): boolean { + return this.active + } + + activeDuringSpawnPhase(): boolean { + return false + } + +} \ No newline at end of file diff --git a/src/core/execution/ExecutionManager.ts b/src/core/execution/ExecutionManager.ts index 15b3536eb..4ba1dbf3b 100644 --- a/src/core/execution/ExecutionManager.ts +++ b/src/core/execution/ExecutionManager.ts @@ -22,6 +22,7 @@ import { MissileSiloExecution } from "./MissileSiloExecution"; import { BattleshipExecution } from "./BattleshipExecution"; import { PathFinder } from "../pathfinding/PathFinding"; import { WorkerClient } from "../worker/WorkerClient"; +import { DefensePostExecution } from "./DefensePostExecution"; @@ -97,6 +98,8 @@ export class Executor { return new PortExecution(intent.player, new Cell(intent.x, intent.y), this.workerClient) case UnitType.MissileSilo: return new MissileSiloExecution(intent.player, new Cell(intent.x, intent.y)) + case UnitType.DefensePost: + return new DefensePostExecution(intent.player, new Cell(intent.x, intent.y)) default: throw Error(`unit type ${intent.unit} not supported`) } diff --git a/src/core/execution/PortExecution.ts b/src/core/execution/PortExecution.ts index a6515f3da..64d1589d2 100644 --- a/src/core/execution/PortExecution.ts +++ b/src/core/execution/PortExecution.ts @@ -31,6 +31,7 @@ export class PortExecution implements Execution { tick(ticks: number): void { if (this.port == null) { + // TODO: use canBuild const tile = this.mg.tile(this.cell) const player = this.mg.player(this._owner) if (!player.canBuild(UnitType.Port, tile)) { diff --git a/src/core/game/Game.ts b/src/core/game/Game.ts index 5ad144bee..f6ee5b53f 100644 --- a/src/core/game/Game.ts +++ b/src/core/game/Game.ts @@ -39,6 +39,7 @@ export enum UnitType { HydrogenBomb = "Hydrogen Bomb", TradeShip = "Trade Ship", MissileSilo = "Missile Silo", + DefensePost = "Defense Post" } export class Nation { diff --git a/src/core/game/PlayerImpl.ts b/src/core/game/PlayerImpl.ts index dc3e82874..82b3e1387 100644 --- a/src/core/game/PlayerImpl.ts +++ b/src/core/game/PlayerImpl.ts @@ -365,7 +365,9 @@ export class PlayerImpl implements MutablePlayer { case UnitType.Shell: return targetTile case UnitType.MissileSilo: - return this.missileSiloSpawn(targetTile) + return this.landBasedStructureSpawn(targetTile) + case UnitType.DefensePost: + return this.landBasedStructureSpawn(targetTile) case UnitType.TransportShip: return this.transportShipSpawn(targetTile) case UnitType.TradeShip: @@ -406,7 +408,7 @@ export class PlayerImpl implements MutablePlayer { return spawns[0].tile() } - missileSiloSpawn(tile: Tile): Tile | false { + landBasedStructureSpawn(tile: Tile): Tile | false { if (tile.owner() != this) { return false }