Files
mmo/systems/aggro/aggro_tracker.gd
Marek Lenczewski f1d34ebf1d update
2026-04-04 00:00:15 +02:00

97 lines
3.2 KiB
GDScript

extends Node
var aggro_tables: Dictionary = {}
var players_in_range: Dictionary = {}
func add_aggro(enemy: Node, player: Node, amount: float) -> void:
if enemy not in aggro_tables:
aggro_tables[enemy] = {}
if player in aggro_tables[enemy]:
aggro_tables[enemy][player] += amount
else:
aggro_tables[enemy][player] = amount
func remove_aggro(enemy: Node, player: Node, amount: float) -> void:
if enemy in aggro_tables and player in aggro_tables[enemy]:
aggro_tables[enemy][player] -= amount
if aggro_tables[enemy][player] <= 0:
aggro_tables[enemy].erase(player)
func add_player_in_range(enemy: Node, player: Node) -> void:
if enemy not in players_in_range:
players_in_range[enemy] = []
if player not in players_in_range[enemy]:
players_in_range[enemy].append(player)
func remove_player_in_range(enemy: Node, player: Node) -> void:
if enemy in players_in_range:
players_in_range[enemy].erase(player)
func is_player_in_any_range(player: Node) -> bool:
for enemy in players_in_range:
if is_instance_valid(enemy) and player in players_in_range[enemy]:
return true
return false
func get_top_target(table: Dictionary) -> Node:
var top: Node = null
var top_val := 0.0
for player in table:
if is_instance_valid(player) and table[player] > top_val:
top_val = table[player]
top = player
return top
func update_target(enemy: Node) -> void:
var table: Dictionary = aggro_tables[enemy]
var top: Node = get_top_target(table)
var data_source: Node = _get_data_source(enemy)
if not data_source:
return
var state: int = data_source.get_stat(enemy, "state")
if top and top != data_source.get_stat(enemy, "target"):
data_source.set_stat(enemy, "target", top)
if state == 0 or state == 3:
data_source.set_stat(enemy, "state", 1)
elif not top and state != 0 and state != 3:
data_source.set_stat(enemy, "target", null)
data_source.set_stat(enemy, "state", 3)
func get_enemies_in_radius(source: Node, radius: float) -> Array:
var result: Array = []
for enemy in get_tree().get_nodes_in_group("enemies"):
if enemy != source and is_instance_valid(enemy):
var dist: float = source.global_position.distance_to(enemy.global_position)
if dist <= radius:
result.append(enemy)
return result
func get_alert_radius(entity: Node) -> float:
var data_source: Node = _get_data_source(entity)
if data_source:
var base: EnemyStats = data_source.get_base(entity)
if base:
return base.alert_radius
return 10.0
func erase_entity(entity: Node) -> void:
aggro_tables.erase(entity)
players_in_range.erase(entity)
for enemy in aggro_tables:
if is_instance_valid(enemy):
aggro_tables[enemy].erase(entity)
var data_source: Node = _get_data_source(enemy)
if data_source and data_source.get_stat(enemy, "target") == entity:
data_source.set_stat(enemy, "target", null)
data_source.set_stat(enemy, "state", 3)
for enemy in players_in_range:
if is_instance_valid(enemy):
players_in_range[enemy].erase(entity)
func _get_data_source(entity: Node) -> Node:
if entity.is_in_group("boss"):
return BossData
elif entity.is_in_group("enemies"):
return EnemyData
return null