#224: refuse to build a structure on top of another
BuildingField.place() dropped a structure at the fleet centroid with no
overlap check of any kind, so they could be stacked.
It reads worse than it looks. BuildingField decides which structure the
fleet is standing on by testing the centroid against interact_radius and
returning the FIRST match, so two structures inside one another make that a
question of list order rather than of where the player flew - you could fly
to your workshop and open the crafter.
The separation is interact_radius itself (150) rather than a new number,
because that is exactly the circle the ambiguity comes from. Buildings draw
to a radius of roughly 60, so this leaves a visible gap rather than letting
them touch.
Gated in three places: the info popup (the button greys out and says which
structure is in the way), _confirm_build, and _try_place - the preview goes
stale as the fleet keeps moving.
Ordering matters in one case. A unique structure replaces itself by
demolishing the old one BEFORE placing the new one, so a placement refused
afterwards would leave the player with neither. The check runs before the
demolition and excludes the structure being replaced. Case D pins it.
Two existing tests encoded the old permissive behaviour and now fly clear
first; neither is about placement:
test_build_info_popup builds every menu option from one position, so
each structure blocked the next
test_payments_use_fleet_hold builds a mothership on the ship lab that
an earlier case injects at the origin
Also fixes a bug from 37e2e89: Sfx.warm() called add_child() from _ready(),
which Godot refuses outright - it printed an error and never pre-built the
pool, defeating the point of warming it. Deferred, like Music.ensure().
173/173.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019AJMdB7iuHuLFZM1aBu3GD
This commit is contained in:
parent
37e2e89cd3
commit
840f9aa9a0
6 changed files with 214 additions and 4 deletions
|
|
@ -2707,6 +2707,28 @@ func has_mothership() -> bool:
|
|||
return get_mothership_position() != null
|
||||
|
||||
|
||||
# Space structures may not be stacked (#224). The distance is Building's own
|
||||
# interact_radius, rather than a new number: that is the circle BuildingField
|
||||
# tests the fleet centroid against to decide which structure you are standing
|
||||
# on, and it returns the FIRST match - so two structures inside one another
|
||||
# make that a question of list order rather than of where you flew.
|
||||
const MIN_BUILDING_SEPARATION: float = 150.0
|
||||
|
||||
|
||||
# The structure a new one at this position would sit on top of, or an empty
|
||||
# dictionary when the spot is clear. ignore_type skips a type that is about
|
||||
# to be demolished, which is how the unique structures replace themselves -
|
||||
# without it a mothership could never be rebuilt where the old one stood.
|
||||
func building_blocking(at_position: Vector2, ignore_type: String = "") -> Dictionary:
|
||||
for building in buildings:
|
||||
if ignore_type != "" and String(building.get("type", "")) == ignore_type:
|
||||
continue
|
||||
var at: Vector2 = building.get("position", Vector2.ZERO)
|
||||
if at.distance_to(at_position) < MIN_BUILDING_SEPARATION:
|
||||
return building
|
||||
return {}
|
||||
|
||||
|
||||
func has_building_of_type(type: String) -> bool:
|
||||
for building in buildings:
|
||||
if building.type == type:
|
||||
|
|
|
|||
Loading…
Reference in a new issue