Forester Radius Preview beim Platzieren (Issue #47) #56

Open
claude wants to merge 1 commits from feature/forester-radius-preview into master
2 changed files with 43 additions and 2 deletions

View File

@@ -8,6 +8,7 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [Unreleased]
### Added
- **Forester Radius Preview** (Issue #47): When placing a Forester Hut, a semi-transparent green overlay shows the full planting zone radius (Chebyshev 5 = 11×11 tiles) following the ghost cursor; disappears on cancel
- **Demolish Mode** (Issue #50): New 💥 Demolish button in the action bar; hover shows a red ghost over any building with a refund percentage; buildings demolished within 3 minutes return 100% of costs (linear decay to 0%); mine footprint tiles are unblocked on teardown; Nisse working inside a demolished building are rescued and resume idle; tile types are restored where applicable (floor/wall/chest → grass)
- **Mine Building** (Issue #42): 3×2 building placeable only on resource-free ROCK tiles (costs: 200 wood + 50 stone); Nisse with mine priority walk to the entrance, disappear inside for 15 s, then reappear carrying 2 stone; up to 3 Nisse work simultaneously; ⛏ X/3 status label shown directly on the building in world space; surface rock harvesting remains functional alongside the building

View File

@@ -1,5 +1,5 @@
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 type { BuildingType, BuildingState, ItemId } from '../types'
import { stateManager } from '../StateManager'
@@ -27,6 +27,7 @@ export class BuildingSystem {
private selectedBuilding: BuildingType = 'floor'
private ghost!: Phaser.GameObjects.Rectangle
private ghostLabel!: Phaser.GameObjects.Text
private foresterRadiusOverlay!: Phaser.GameObjects.Graphics
private buildKey!: Phaser.Input.Keyboard.Key
private cancelKey!: Phaser.Input.Keyboard.Key
@@ -63,6 +64,10 @@ export class BuildingSystem {
this.ghostLabel.setVisible(false)
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.cancelKey = this.scene.input.keyboard!.addKey(Phaser.Input.Keyboard.KeyCodes.ESC)
@@ -138,6 +143,7 @@ export class BuildingSystem {
this.active = false
this.ghost.setVisible(false)
this.ghostLabel.setVisible(false)
this.foresterRadiusOverlay.setVisible(false)
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.
* For forester_hut, also draws a semi-transparent radius preview overlay.
*/
private updateBuildGhost(): void {
const ptr = this.scene.input.activePointer
@@ -213,6 +220,38 @@ export class BuildingSystem {
const costs = BUILDING_COSTS[this.selectedBuilding] ?? {}
const costStr = Object.entries(costs).map(([k, v]) => `${v}${k[0].toUpperCase()}`).join(' ')
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 {
this.ghost.destroy()
this.ghostLabel.destroy()
this.foresterRadiusOverlay.destroy()
}
}