✨ show forester planting radius preview while placing hut (Issue #47)
Semi-transparent green 11x11 tile overlay follows the ghost cursor when forester_hut is selected. Disappears on deactivate/cancel. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user