update
This commit is contained in:
142
systems/buff_system.gd
Normal file
142
systems/buff_system.gd
Normal file
@@ -0,0 +1,142 @@
|
||||
extends Node
|
||||
|
||||
var active_buffs: Dictionary = {}
|
||||
|
||||
func _ready() -> void:
|
||||
EventBus.effect_requested.connect(_on_effect_requested)
|
||||
EventBus.role_changed.connect(_on_role_changed)
|
||||
EventBus.entity_died.connect(_on_entity_died)
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
for entity in active_buffs.keys():
|
||||
if not is_instance_valid(entity):
|
||||
active_buffs.erase(entity)
|
||||
continue
|
||||
var entries: Array = active_buffs[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:
|
||||
var is_aura_buff: bool = entry.get("is_aura_buff", false)
|
||||
entries.remove_at(i)
|
||||
if not is_aura_buff:
|
||||
EventBus.effect_expired.emit(entity, effect)
|
||||
_recalc(entity)
|
||||
i -= 1
|
||||
continue
|
||||
if effect.tick_interval > 0:
|
||||
entry["tick_timer"] -= delta
|
||||
if entry["tick_timer"] <= 0:
|
||||
entry["tick_timer"] += effect.tick_interval
|
||||
if not effect.is_multiplier and effect.type == Effect.Type.BUFF:
|
||||
var source: Node = entry["source"]
|
||||
if not is_instance_valid(source):
|
||||
source = entity
|
||||
EventBus.heal_requested.emit(source, entity, effect.value)
|
||||
i -= 1
|
||||
|
||||
func apply(target: Node, effect: Effect, source: Node) -> void:
|
||||
if effect.type != Effect.Type.BUFF and effect.type != Effect.Type.AURA:
|
||||
return
|
||||
if not active_buffs.has(target):
|
||||
active_buffs[target] = []
|
||||
var replaced := false
|
||||
var entries: Array = active_buffs[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)
|
||||
if effect.is_multiplier:
|
||||
_recalc(target)
|
||||
|
||||
func apply_aura_buff(target: Node, effect: Effect, source: Node) -> void:
|
||||
if not active_buffs.has(target):
|
||||
active_buffs[target] = []
|
||||
var entry := {
|
||||
"effect": effect,
|
||||
"source": source,
|
||||
"remaining": effect.duration,
|
||||
"tick_timer": effect.tick_interval,
|
||||
"aura_source": source,
|
||||
"is_aura_buff": true,
|
||||
}
|
||||
active_buffs[target].append(entry)
|
||||
if effect.is_multiplier:
|
||||
_recalc(target)
|
||||
|
||||
func has_aura_buff(target: Node, aura_name: String, source: Node) -> bool:
|
||||
if not active_buffs.has(target):
|
||||
return false
|
||||
for entry in active_buffs[target]:
|
||||
if entry["effect"].effect_name == aura_name and entry.get("aura_source") == source:
|
||||
return true
|
||||
return false
|
||||
|
||||
func refresh_aura_buff(target: Node, aura_name: String, source: Node, duration: float) -> void:
|
||||
if not active_buffs.has(target):
|
||||
return
|
||||
for entry in active_buffs[target]:
|
||||
if entry["effect"].effect_name == aura_name and entry.get("aura_source") == source:
|
||||
entry["remaining"] = duration
|
||||
return
|
||||
|
||||
func clear(entity: Node) -> void:
|
||||
active_buffs.erase(entity)
|
||||
_recalc(entity)
|
||||
|
||||
func _on_effect_requested(target: Node, effect: Effect, source: Node) -> void:
|
||||
if effect.type == Effect.Type.BUFF or effect.type == Effect.Type.AURA:
|
||||
apply(target, effect, source)
|
||||
|
||||
func _on_entity_died(entity: Node) -> void:
|
||||
active_buffs.erase(entity)
|
||||
_recalc(entity)
|
||||
|
||||
func _on_role_changed(player: Node, _role_type: int) -> void:
|
||||
_remove_permanent(player)
|
||||
|
||||
func _remove_permanent(entity: Node) -> void:
|
||||
if not active_buffs.has(entity):
|
||||
return
|
||||
var entries: Array = active_buffs[entity]
|
||||
var i: int = entries.size() - 1
|
||||
while i >= 0:
|
||||
if entries[i]["effect"].duration < 0:
|
||||
EventBus.effect_expired.emit(entity, entries[i]["effect"])
|
||||
entries.remove_at(i)
|
||||
i -= 1
|
||||
_recalc(entity)
|
||||
|
||||
func _recalc(entity: Node) -> void:
|
||||
var mults := { "damage": 1.0, "heal": 1.0, "shield": 1.0 }
|
||||
if active_buffs.has(entity):
|
||||
for entry in active_buffs[entity]:
|
||||
var effect: Effect = entry["effect"]
|
||||
if effect.is_multiplier and effect.stat in mults:
|
||||
mults[effect.stat] += effect.value
|
||||
var player: Node = get_tree().get_first_node_in_group("player")
|
||||
if entity == player:
|
||||
PlayerData.buff_damage = mults["damage"]
|
||||
PlayerData.buff_heal = mults["heal"]
|
||||
PlayerData.buff_shield = mults["shield"]
|
||||
if PlayerData.base:
|
||||
var new_max: float = PlayerData.base.max_shield * mults["shield"]
|
||||
PlayerData.max_shield = new_max
|
||||
PlayerData.shield = min(PlayerData.shield, new_max)
|
||||
PlayerData.set_shield(PlayerData.shield)
|
||||
EventBus.buff_changed.emit(entity, "damage", mults["damage"])
|
||||
Reference in New Issue
Block a user