Files
mmo/systems/invasion_system.gd
Marek Lenczewski f21e30eb55 prototype vibe
2026-04-16 17:20:57 +02:00

89 lines
2.7 KiB
GDScript

extends Node
const ENEMY_SCENE: PackedScene = preload("res://scenes/enemy/enemy.tscn")
const BOSS_STATS: Resource = preload("res://scenes/enemy/boss_stats.tres")
const INVASION_COUNT := 16
const SPAWN_RADIUS := 45.0
var active: bool = false
var invasion_enemies: Array[Node] = []
func _ready() -> void:
EventBus.wave_timer_tick.connect(_on_wave_timer_tick)
EventBus.entity_died.connect(_on_entity_died)
EventBus.tavern_destroyed.connect(_on_tavern_destroyed)
func _on_wave_timer_tick(seconds_remaining: float) -> void:
if active:
return
if seconds_remaining > 0:
return
var has_alive_red := false
for p in get_tree().get_nodes_in_group("red_portal"):
if is_instance_valid(p) and PortalData.is_alive(p):
has_alive_red = true
break
if not has_alive_red:
return
trigger()
func trigger() -> void:
active = true
invasion_enemies.clear()
var tavern: Node = get_tree().get_first_node_in_group("tavern")
if not tavern:
active = false
return
var world: Node = get_tree().current_scene
var scale: float = PlayerData.level_scale * 10.0
for enemy in get_tree().get_nodes_in_group("red_enemies"):
if is_instance_valid(enemy):
_convert_to_invasion(enemy, tavern)
for i in range(INVASION_COUNT):
var angle: float = randf() * TAU
var pos := Vector3(cos(angle) * SPAWN_RADIUS, 0, sin(angle) * SPAWN_RADIUS)
var enemy: Node = ENEMY_SCENE.instantiate()
enemy.spawn_scale = scale
world.add_child(enemy)
enemy.global_position = pos
_convert_to_invasion(enemy, tavern)
var boss_angle: float = randf() * TAU
var boss_pos := Vector3(cos(boss_angle) * SPAWN_RADIUS, 0, sin(boss_angle) * SPAWN_RADIUS)
var boss: Node = ENEMY_SCENE.instantiate()
boss.add_to_group("boss")
boss.stats = BOSS_STATS
boss.spawn_scale = scale
world.add_child(boss)
boss.global_position = boss_pos
_convert_to_invasion(boss, tavern)
EventBus.invasion_started.emit(invasion_enemies)
func _convert_to_invasion(enemy: Node, tavern: Node) -> void:
enemy.add_to_group("invasion")
var data_source: Node = BossData if enemy.is_in_group("boss") else EnemyData
data_source.set_stat(enemy, "target", tavern)
data_source.set_stat(enemy, "state", 1)
invasion_enemies.append(enemy)
func _on_entity_died(entity: Node) -> void:
if not active:
return
if entity not in invasion_enemies:
return
invasion_enemies.erase(entity)
var alive_count := 0
for e in invasion_enemies:
if is_instance_valid(e):
alive_count += 1
if alive_count == 0:
_end_invasion(true)
func _end_invasion(success: bool) -> void:
active = false
invasion_enemies.clear()
EventBus.invasion_ended.emit(success)
func _on_tavern_destroyed() -> void:
active = false
EventBus.game_over.emit()