extends Node var tracker: Node var decay: Node var config: AggroConfig func _ready() -> void: EventBus.damage_dealt.connect(_on_damage_dealt) EventBus.heal_requested.connect(_on_heal_requested) EventBus.entity_died.connect(_on_entity_died) EventBus.enemy_detected.connect(_on_enemy_detected) EventBus.enemy_lost.connect(_on_enemy_lost) func _on_enemy_detected(enemy: Node, player: Node) -> void: if not enemy.is_in_group("enemies"): return if "state" in enemy: if enemy.state == enemy.State.CHASE or enemy.state == enemy.State.ATTACK: return tracker.add_player_in_range(enemy, player) tracker.add_aggro(enemy, player, 1.0) if "state" in enemy: enemy.target = player enemy.state = enemy.State.CHASE EventBus.enemy_engaged.emit(enemy, player) decay.alert_nearby(enemy, player) func _on_enemy_lost(enemy: Node, player: Node) -> void: tracker.remove_player_in_range(enemy, player) func _on_damage_dealt(attacker: Node, target: Node, amount: float) -> void: if not target.is_in_group("enemies") and not target.is_in_group("portals"): return decay.reset_combat_timer(attacker) var multiplier := 1.0 var role: Node = attacker.get_node_or_null("Role") if role and role.current_role == 0: multiplier = config.tank_multiplier var aggro: float = amount * multiplier tracker.add_aggro(target, attacker, aggro) decay.spread_aggro(target, attacker, aggro * config.spread_multiplier) func _on_heal_requested(healer: Node, _target: Node, amount: float) -> void: if not healer.is_in_group("player"): return for enemy in tracker.aggro_tables: if is_instance_valid(enemy) and healer in tracker.aggro_tables[enemy]: tracker.add_aggro(enemy, healer, amount * config.heal_multiplier) func _on_entity_died(entity: Node) -> void: tracker.erase_entity(entity) decay.erase_entity(entity)