diff --git a/scripts/enemies/anchor.gd b/scripts/enemies/anchor.gd index 9829536..c87607c 100644 --- a/scripts/enemies/anchor.gd +++ b/scripts/enemies/anchor.gd @@ -26,8 +26,8 @@ var _shot_timer: float = 1.0 var _anchor_timer: float = 0.0 func _ready() -> void: - max_health = 40.0 - current_health = 40.0 + max_health = 30.0 + current_health = 30.0 speed = 95.0 contact_damage = 0.5 super._ready() @@ -43,10 +43,13 @@ func _pick_floor_point() -> void: _target_pos = room_center + Vector2(rx, ry) func _physics_process(delta: float) -> void: + _tick_spawn_delay(delta) _find_player() _tick_contact(delta) _tick_flash(delta) _tick_slow(delta) + if not is_active(): + return match _state: State.DRIFTING: diff --git a/scripts/enemies/drifter.gd b/scripts/enemies/drifter.gd index 81481dd..7057975 100644 --- a/scripts/enemies/drifter.gd +++ b/scripts/enemies/drifter.gd @@ -17,10 +17,13 @@ func _ready() -> void: _wobble_phase = randf() * TAU func _physics_process(delta: float) -> void: + _tick_spawn_delay(delta) _find_player() _tick_contact(delta) _tick_flash(delta) _tick_slow(delta) + if not is_active(): + return _do_arc_chase(delta) velocity *= _slow_factor move_and_slide() diff --git a/scripts/enemies/enemy_base.gd b/scripts/enemies/enemy_base.gd index 4afea9b..0d0bca0 100644 --- a/scripts/enemies/enemy_base.gd +++ b/scripts/enemies/enemy_base.gd @@ -13,10 +13,13 @@ var contact_cooldown: float = 0.8 # --------------------------------------------------------------------------- # Internal state — shared across all enemies # --------------------------------------------------------------------------- +const SPAWN_DELAY: float = 0.5 + var _contact_timer: float = 0.0 var _flash_timer: float = 0.0 var _slow_factor: float = 1.0 var _slow_timer: float = 0.0 +var _spawn_timer: float = SPAWN_DELAY var _player: Node2D = null @onready var visual: Node2D = $Visual @@ -25,6 +28,13 @@ func _ready() -> void: add_to_group("enemies") $ContactArea.body_entered.connect(_on_contact_entered) +func is_active() -> bool: + return _spawn_timer <= 0.0 + +func _tick_spawn_delay(delta: float) -> void: + if _spawn_timer > 0.0: + _spawn_timer -= delta + # --------------------------------------------------------------------------- # Shared helpers — call from derived _physics_process as needed # --------------------------------------------------------------------------- @@ -83,6 +93,8 @@ func _spawn_drop() -> void: # Contact damage # --------------------------------------------------------------------------- func _on_contact_entered(body: Node) -> void: + if not is_active(): + return if body.is_in_group("player") and _contact_timer == 0.0: body.take_damage(contact_damage) _contact_timer = contact_cooldown \ No newline at end of file diff --git a/scripts/enemies/relay.gd b/scripts/enemies/relay.gd index 796f2a0..8cfffa7 100644 --- a/scripts/enemies/relay.gd +++ b/scripts/enemies/relay.gd @@ -51,6 +51,8 @@ var _contact_area : Area2D var _teleport_timer : float = 3.0 # initial delay before first teleport var _in_transit : bool = false +var _transit_timer : float = 0.0 +var _fade_out : bool = false var _teleport_count : int = 0 var _next_drifter_threshold : int = 0 @@ -75,12 +77,15 @@ func _ready() -> void: _room_center = global_position _roll_drifter_threshold() - _roll_teleport_cooldown() + _teleport_timer = 2.5 # initial delay before first teleport func _physics_process(delta: float) -> void: + _tick_spawn_delay(delta) if _phase == Phase.CLIMAX: _tick_climax(delta) return + if not is_active(): + return _tick_teleport(delta) _tick_burst_projs(delta) @@ -93,6 +98,9 @@ func _physics_process(delta: float) -> void: # --------------------------------------------------------------------------- func _tick_teleport(delta: float) -> void: if _in_transit: + _transit_timer -= delta + if _transit_timer <= 0.0: + _reappear() return _teleport_timer -= delta @@ -101,21 +109,21 @@ func _tick_teleport(delta: float) -> void: func _start_teleport() -> void: _in_transit = true + _fade_out = true - # Fade out + # Quick fade out var tw := create_tween() tw.tween_property(_visual, "modulate:a", 0.0, FADE_OUT_TIME) - tw.tween_callback(Callable(self, "_on_fade_out_done")) + tw.finished.connect(_on_fade_finished) -func _on_fade_out_done() -> void: +func _on_fade_finished() -> void: + if not _fade_out: + return + _fade_out = false _contact_area.monitoring = false _contact_area.monitorable = false _visual.visible = false - - # Transit delay then reappear - var tw := create_tween() - tw.tween_interval(TRANSIT_TIME) - tw.tween_callback(Callable(self, "_reappear")) + _transit_timer = TRANSIT_TIME func _reappear() -> void: # Pick random position within room bounds diff --git a/scripts/enemies/repeater.gd b/scripts/enemies/repeater.gd index d0dc840..374a21b 100644 --- a/scripts/enemies/repeater.gd +++ b/scripts/enemies/repeater.gd @@ -56,10 +56,13 @@ func _snap_to_wall() -> void: global_position = wall_pos func _physics_process(delta: float) -> void: + _tick_spawn_delay(delta) _find_player() _tick_contact(delta) _tick_flash(delta) _tick_slow(delta) + if not is_active(): + return velocity = Vector2.ZERO _do_fire(delta) velocity *= _slow_factor diff --git a/scripts/enemies/supervisor.gd b/scripts/enemies/supervisor.gd index ea1fd91..090c69f 100644 --- a/scripts/enemies/supervisor.gd +++ b/scripts/enemies/supervisor.gd @@ -110,10 +110,13 @@ func _update_facing(dir: Vector2) -> void: # Physics loop # --------------------------------------------------------------------------- func _physics_process(delta: float) -> void: + _tick_spawn_delay(delta) _find_player() _tick_contact(delta) _tick_beam(delta) _tick_flash(delta) + if not is_active(): + return var pct := current_health / max_health if _phase == Phase.ONE and pct <= 0.55: diff --git a/scripts/enemies/warden.gd b/scripts/enemies/warden.gd index 89f5d9c..3c0713a 100644 --- a/scripts/enemies/warden.gd +++ b/scripts/enemies/warden.gd @@ -79,10 +79,13 @@ func _ready() -> void: # Physics loop # --------------------------------------------------------------------------- func _physics_process(delta: float) -> void: + _tick_spawn_delay(delta) _find_player() _tick_contact(delta) _tick_flash(delta) _tick_sweep_projs(delta) + if not is_active(): + return if _phase == Phase.ONE and current_health / max_health <= 0.4: _enter_phase_two()