Files
mmo/scenes/entities/gate/gate.gd
2026-05-14 19:11:10 +02:00

86 lines
2.8 KiB
GDScript

extends StaticBody3D
@export var stats_resource: GateStats
@export var is_red: bool = false
@onready var mesh: MeshInstance3D = $Mesh
@onready var healthbar: MeshInstance3D = $Healthbar
@onready var name_label: Label3D = $NameLabel
@onready var spawn_point: Node3D = $SpawnPoint
var spawn_timer: float = 0.0
var spawned_count: int = 0
var dead: bool = false
var attacked: bool = false
func _enter_tree() -> void:
set_multiplayer_authority(1)
func _ready() -> void:
add_to_group("gates")
if is_red:
add_to_group("red_gate")
if stats_resource == null:
stats_resource = GateStats.new()
if is_red:
stats_resource.max_health = 600.0
stats_resource.spawn_count = 8
else:
stats_resource.max_health = 200.0
stats_resource.spawn_count = 5
stats_resource.is_red = is_red
Stats.register(self, stats_resource)
EventBus.health_changed.connect(_on_health_changed)
EventBus.entity_died.connect(_on_entity_died)
if is_red:
var mat: StandardMaterial3D = StandardMaterial3D.new()
mat.albedo_color = Color(0.95, 0.2, 0.15)
mat.emission_enabled = true
mat.emission = Color(1.0, 0.4, 0.2)
mat.emission_energy_multiplier = 0.6
mesh.material_override = mat
name_label.text = "Red Gate"
else:
name_label.text = "Gate"
set_physics_process(true)
func _exit_tree() -> void:
Stats.deregister(self)
func _physics_process(delta: float) -> void:
if dead:
return
if not multiplayer.is_server() and multiplayer.multiplayer_peer != null:
return
if not attacked:
return
spawn_timer = max(0.0, spawn_timer - delta)
if spawn_timer <= 0.0 and spawned_count < int(Stats.get_stat(self, "spawn_count", 5)):
var spawn_sys: Node = get_node_or_null("/root/World/Systems/SpawnSystem")
if spawn_sys and spawn_sys.has_method("spawn_enemy_at"):
spawn_sys.spawn_enemy_at(spawn_point.global_position + Vector3(randf_range(-1.5, 1.5), 0.0, randf_range(-1.5, 1.5)), is_red)
spawned_count += 1
spawn_timer = float(Stats.get_stat(self, "spawn_interval", 4.0))
func _on_health_changed(entity: Node, current: float, max: float) -> void:
if entity != self:
return
if not attacked and current < max:
attacked = true
var ratio: float = clamp(current / max if max > 0 else 0.0, 0.0, 1.0)
healthbar.scale.x = max(0.01, ratio * 2.0)
func _on_entity_died(entity: Node) -> void:
if entity != self or dead:
return
dead = true
if multiplayer.is_server() or multiplayer.multiplayer_peer == null:
var spawn_sys: Node = get_node_or_null("/root/World/Systems/SpawnSystem")
if spawn_sys and spawn_sys.has_method("spawn_portal_at"):
spawn_sys.spawn_portal_at(global_position, is_red)
EventBus.gate_destroyed.emit(self)
var t := get_tree().create_timer(0.5)
t.timeout.connect(func():
if is_instance_valid(self):
queue_free())