This commit is contained in:
Marek Lenczewski
2026-04-02 18:33:53 +02:00
parent 47f4fe3d90
commit c7e6f8f4b5
25 changed files with 301 additions and 157 deletions

View File

@@ -0,0 +1,68 @@
extends Node
var tracker: Node
var config: AggroConfig
var last_damage_time: Dictionary = {}
func process(delta: float) -> void:
_update_combat_timers(delta)
for enemy in tracker.aggro_tables.keys():
if not is_instance_valid(enemy):
tracker.aggro_tables.erase(enemy)
tracker.players_in_range.erase(enemy)
continue
_decay_aggro(enemy, delta)
tracker.update_target(enemy)
func _update_combat_timers(delta: float) -> void:
for player in last_damage_time.keys():
if not is_instance_valid(player):
last_damage_time.erase(player)
else:
last_damage_time[player] += delta
func _decay_aggro(enemy: Node, delta: float) -> void:
var table: Dictionary = tracker.aggro_tables[enemy]
var base: BaseStats = Stats.get_base(enemy)
var aggro_decay: float = base.aggro_decay if base is EnemyStats else 1.0
for player in table.keys():
if is_in_combat(player):
continue
var time_since_combat: float = last_damage_time.get(player, config.combat_timeout) - config.combat_timeout
var decay: float = aggro_decay * delta
decay += _exponential_decay(table[player], time_since_combat, delta)
table[player] -= decay
if table[player] <= 0:
table.erase(player)
func reset_combat_timer(player: Node) -> void:
last_damage_time[player] = 0.0
func is_in_combat(player: Node) -> bool:
if tracker.is_player_in_any_range(player):
return true
return last_damage_time.get(player, config.combat_timeout + 1.0) < config.combat_timeout
func _exponential_decay(aggro: float, time_outside: float, delta: float) -> float:
if time_outside <= 0:
return 0.0
return aggro * config.exponential_decay_factor * pow(2, time_outside) * delta
func spread_aggro(source: Node, attacker: Node, amount: float) -> void:
if not is_instance_valid(source):
return
var radius: float = tracker.get_alert_radius(source)
for enemy in tracker.get_enemies_in_radius(source, radius):
tracker.add_aggro(enemy, attacker, amount)
func alert_nearby(enemy: Node, target: Node) -> void:
var radius: float = tracker.get_alert_radius(enemy)
for other in tracker.get_enemies_in_radius(enemy, radius):
if "state" in other and other.state == other.State.IDLE:
tracker.add_aggro(other, target, 1.0)
other.target = target
other.state = other.State.CHASE
EventBus.enemy_engaged.emit(other, target)
func erase_entity(entity: Node) -> void:
last_damage_time.erase(entity)