|
|
|
@@ -1,5 +1,5 @@
|
|
|
|
import Phaser from 'phaser'
|
|
|
|
import Phaser from 'phaser'
|
|
|
|
import { TILE_SIZE, BUILDING_COSTS, DEMOLISH_REFUND_MS } from '../config'
|
|
|
|
import { TILE_SIZE, BUILDING_COSTS, DEMOLISH_REFUND_MS, FORESTER_ZONE_RADIUS } from '../config'
|
|
|
|
import { TileType, IMPASSABLE } from '../types'
|
|
|
|
import { TileType, IMPASSABLE } from '../types'
|
|
|
|
import type { BuildingType, BuildingState, ItemId } from '../types'
|
|
|
|
import type { BuildingType, BuildingState, ItemId } from '../types'
|
|
|
|
import { stateManager } from '../StateManager'
|
|
|
|
import { stateManager } from '../StateManager'
|
|
|
|
@@ -27,6 +27,7 @@ export class BuildingSystem {
|
|
|
|
private selectedBuilding: BuildingType = 'floor'
|
|
|
|
private selectedBuilding: BuildingType = 'floor'
|
|
|
|
private ghost!: Phaser.GameObjects.Rectangle
|
|
|
|
private ghost!: Phaser.GameObjects.Rectangle
|
|
|
|
private ghostLabel!: Phaser.GameObjects.Text
|
|
|
|
private ghostLabel!: Phaser.GameObjects.Text
|
|
|
|
|
|
|
|
private foresterRadiusOverlay!: Phaser.GameObjects.Graphics
|
|
|
|
private buildKey!: Phaser.Input.Keyboard.Key
|
|
|
|
private buildKey!: Phaser.Input.Keyboard.Key
|
|
|
|
private cancelKey!: Phaser.Input.Keyboard.Key
|
|
|
|
private cancelKey!: Phaser.Input.Keyboard.Key
|
|
|
|
|
|
|
|
|
|
|
|
@@ -63,6 +64,10 @@ export class BuildingSystem {
|
|
|
|
this.ghostLabel.setVisible(false)
|
|
|
|
this.ghostLabel.setVisible(false)
|
|
|
|
this.ghostLabel.setOrigin(0.5, 1)
|
|
|
|
this.ghostLabel.setOrigin(0.5, 1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.foresterRadiusOverlay = this.scene.add.graphics()
|
|
|
|
|
|
|
|
this.foresterRadiusOverlay.setDepth(999)
|
|
|
|
|
|
|
|
this.foresterRadiusOverlay.setVisible(false)
|
|
|
|
|
|
|
|
|
|
|
|
this.buildKey = this.scene.input.keyboard!.addKey(Phaser.Input.Keyboard.KeyCodes.B)
|
|
|
|
this.buildKey = this.scene.input.keyboard!.addKey(Phaser.Input.Keyboard.KeyCodes.B)
|
|
|
|
this.cancelKey = this.scene.input.keyboard!.addKey(Phaser.Input.Keyboard.KeyCodes.ESC)
|
|
|
|
this.cancelKey = this.scene.input.keyboard!.addKey(Phaser.Input.Keyboard.KeyCodes.ESC)
|
|
|
|
|
|
|
|
|
|
|
|
@@ -138,6 +143,7 @@ export class BuildingSystem {
|
|
|
|
this.active = false
|
|
|
|
this.active = false
|
|
|
|
this.ghost.setVisible(false)
|
|
|
|
this.ghost.setVisible(false)
|
|
|
|
this.ghostLabel.setVisible(false)
|
|
|
|
this.ghostLabel.setVisible(false)
|
|
|
|
|
|
|
|
this.foresterRadiusOverlay.setVisible(false)
|
|
|
|
this.onModeChange?.(false, this.selectedBuilding)
|
|
|
|
this.onModeChange?.(false, this.selectedBuilding)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@@ -193,6 +199,7 @@ export class BuildingSystem {
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* Updates the green/red build-mode ghost to follow the mouse, snapped to the tile grid.
|
|
|
|
* Updates the green/red build-mode ghost to follow the mouse, snapped to the tile grid.
|
|
|
|
|
|
|
|
* For forester_hut, also draws a semi-transparent radius preview overlay.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
private updateBuildGhost(): void {
|
|
|
|
private updateBuildGhost(): void {
|
|
|
|
const ptr = this.scene.input.activePointer
|
|
|
|
const ptr = this.scene.input.activePointer
|
|
|
|
@@ -213,6 +220,38 @@ export class BuildingSystem {
|
|
|
|
const costs = BUILDING_COSTS[this.selectedBuilding] ?? {}
|
|
|
|
const costs = BUILDING_COSTS[this.selectedBuilding] ?? {}
|
|
|
|
const costStr = Object.entries(costs).map(([k, v]) => `${v}${k[0].toUpperCase()}`).join(' ')
|
|
|
|
const costStr = Object.entries(costs).map(([k, v]) => `${v}${k[0].toUpperCase()}`).join(' ')
|
|
|
|
this.ghostLabel.setText(`${this.selectedBuilding} [${costStr}]`)
|
|
|
|
this.ghostLabel.setText(`${this.selectedBuilding} [${costStr}]`)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (this.selectedBuilding === 'forester_hut') {
|
|
|
|
|
|
|
|
this.updateForesterRadiusOverlay(tileX, tileY)
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
this.foresterRadiusOverlay.setVisible(false)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* Redraws the forester radius preview overlay centered on the given tile.
|
|
|
|
|
|
|
|
* Shows the Chebyshev-radius planting zone as a semi-transparent green fill
|
|
|
|
|
|
|
|
* with a dotted border.
|
|
|
|
|
|
|
|
* @param centerTileX - Tile column of the hut
|
|
|
|
|
|
|
|
* @param centerTileY - Tile row of the hut
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
private updateForesterRadiusOverlay(centerTileX: number, centerTileY: number): void {
|
|
|
|
|
|
|
|
const r = FORESTER_ZONE_RADIUS
|
|
|
|
|
|
|
|
const px = (centerTileX - r) * TILE_SIZE
|
|
|
|
|
|
|
|
const py = (centerTileY - r) * TILE_SIZE
|
|
|
|
|
|
|
|
const pw = (r * 2 + 1) * TILE_SIZE
|
|
|
|
|
|
|
|
const ph = (r * 2 + 1) * TILE_SIZE
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.foresterRadiusOverlay.clear()
|
|
|
|
|
|
|
|
this.foresterRadiusOverlay.setVisible(true)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Semi-transparent green fill
|
|
|
|
|
|
|
|
this.foresterRadiusOverlay.fillStyle(0x44ff44, 0.08)
|
|
|
|
|
|
|
|
this.foresterRadiusOverlay.fillRect(px, py, pw, ph)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Solid border
|
|
|
|
|
|
|
|
this.foresterRadiusOverlay.lineStyle(2, 0x44ff44, 0.5)
|
|
|
|
|
|
|
|
this.foresterRadiusOverlay.strokeRect(px, py, pw, ph)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
@@ -421,10 +460,11 @@ export class BuildingSystem {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* Cleans up ghost sprites on scene shutdown.
|
|
|
|
* Cleans up ghost sprites and overlays on scene shutdown.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
destroy(): void {
|
|
|
|
destroy(): void {
|
|
|
|
this.ghost.destroy()
|
|
|
|
this.ghost.destroy()
|
|
|
|
this.ghostLabel.destroy()
|
|
|
|
this.ghostLabel.destroy()
|
|
|
|
|
|
|
|
this.foresterRadiusOverlay.destroy()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|