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 var data_source: Node = tracker._get_data_source(enemy) if data_source: var state: int = data_source.get_stat(enemy, "state") if state == 1 or state == 2: return tracker.add_player_in_range(enemy, player) tracker.add_aggro(enemy, player, 1.0) if data_source: data_source.set_stat(enemy, "target", player) data_source.set_stat(enemy, "state", 1) 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 if PlayerData.current_role == PlayerData.Role.TANK: 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)