extends Node3D class_name Building @export_group("Defence") @export var max_hp: int = 100 ## Amount of damage this building can sustain before being destroyed. @export_group("Stacking") @export var can_stack: bool = true ## Whether this building can be stacked on top of other buildings. @export var can_be_stacked_on: bool = true ## Whether this building will accept other buildings being stacked on it. @export var stack_position: Vector3 = Vector3(0,2,0) ## The local position that stacked buildings will be placed at. @onready var build_position: Vector3 = global_position @onready var nav_obstacle: NavObstable = $NavObstacle @onready var consumer: Consumer = $Consumer @onready var producer: Producer = $Producer @onready var collision_shape: CollisionShape3D = $CollisionShape3D signal functional_changed(functional: bool) enum BuildState { UNPLACED, BUILDING, READY, DESTROYED } const PLACEMENT_POSITION_OK: int = 0b0001 const PLACEMENT_FOUNDATION_REQUIRED: int = 0b0010 const PLACEMENT_PART_ADDED: int = 0b0100 const PLACEMENT_COMPLETED: int = 0b1000 var hp: int = max_hp var stacked_buildings: Array[Building] = [] var build_state: BuildState = BuildState.READY: set(state): build_state = state functional_changed.emit(is_functional()) func _ready() -> void: if nav_obstacle != null: functional_changed.connect(func(enable:bool): nav_obstacle.enabled = enable) if consumer != null: functional_changed.connect(func(enable:bool): consumer.enabled = enable) if producer != null: functional_changed.connect(func(enable:bool): producer.enabled = enable) if collision_shape != null: functional_changed.connect(func(enable:bool): collision_shape.disabled = !enable) func _process(delta: float) -> void: if build_state == BuildState.UNPLACED: global_position = global_position.lerp(build_position, 0.4) var debug_text: String = "" debug_text += "State: %s\n" % build_state if consumer != null: var consumer_state: String if consumer.enabled: consumer_state = "OK" else: consumer_state = "Off" debug_text += "Input: %s \nStorage: %d\n" % [consumer_state, consumer.storage_total] if producer != null: var producer_state = "OK" if !producer.enabled: producer_state = "Off" elif !producer.can_produce(): producer_state = "Blocked" debug_text += "Output: %s\n" % producer_state $Label3D.text = debug_text func is_functional() -> bool: return build_state == BuildState.READY func _start_placement() -> void: build_state = BuildState.UNPLACED func _end_placement() -> void: build_state = BuildState.READY func _placement_select_building(building: Building, confirmed: bool) -> int: while !building.stacked_buildings.is_empty(): building = building.stacked_buildings[0] var stack_ok: bool = can_stack and building.can_be_stacked_on var ret: int = 0 if stack_ok: build_position = building.global_position + building.stack_position ret |= PLACEMENT_POSITION_OK if confirmed and stack_ok: global_position = build_position building.stacked_buildings.append(self) ret |= PLACEMENT_COMPLETED return ret func _placement_select_position(pos: Vector3, confirmed: bool) -> int: var ret: int = 0 ret |= PLACEMENT_POSITION_OK build_position = Vector3(roundf(pos.x), ceilf(pos.y-0.01), roundf(pos.z)) if confirmed: build_state = BuildState.BUILDING ret |= PLACEMENT_COMPLETED return ret