extends Node var active_debuffs: Dictionary = {} func _ready() -> void: EventBus.effect_requested.connect(_on_effect_requested) EventBus.entity_died.connect(_on_entity_died) func _process(delta: float) -> void: for entity in active_debuffs.keys(): if not is_instance_valid(entity): active_debuffs.erase(entity) continue var entries: Array = active_debuffs[entity] var i: int = entries.size() - 1 while i >= 0: var entry: Dictionary = entries[i] var effect: Effect = entry["effect"] if effect.duration > 0: entry["remaining"] -= delta if entry["remaining"] <= 0: entries.remove_at(i) EventBus.effect_expired.emit(entity, effect) i -= 1 continue if effect.tick_interval > 0: entry["tick_timer"] -= delta if entry["tick_timer"] <= 0: entry["tick_timer"] += effect.tick_interval var source: Node = entry["source"] if not is_instance_valid(source): source = entity EventBus.damage_requested.emit(source, entity, effect.value) i -= 1 func apply(target: Node, effect: Effect, source: Node) -> void: if effect.type != Effect.Type.DEBUFF: return if not active_debuffs.has(target): active_debuffs[target] = [] var replaced := false var entries: Array = active_debuffs[target] for i in range(entries.size()): if entries[i]["effect"].effect_name == effect.effect_name: entries[i]["effect"] = effect entries[i]["source"] = source entries[i]["remaining"] = effect.duration entries[i]["tick_timer"] = effect.tick_interval replaced = true break if not replaced: entries.append({ "effect": effect, "source": source, "remaining": effect.duration, "tick_timer": effect.tick_interval, }) EventBus.effect_applied.emit(target, effect) func _on_effect_requested(target: Node, effect: Effect, source: Node) -> void: if effect.type == Effect.Type.DEBUFF: apply(target, effect, source) func _on_entity_died(entity: Node) -> void: active_debuffs.erase(entity)