randomgeon/combat/modifiers/_scripts/modifier_manager.gd
Dan Baker 70839387ca Implements modifier system for weapons
Adds a modifier system allowing dynamic modification of weapon
stats and behavior. This includes:

- Creating ModifierLibrary to manage available modifiers.
- Adds ModifierManager to handle equipping and unequipping modifiers
- Adds a new RangedWeaponComponent to handle firing projectiles and
  managing modifiers.
- Introduces a DebugUI for in-game modifier management.
- Introduces an "Unlimited Power" modifier that changes the projectile scene.
- Modifies stats components to work with the new modifier system.

This system allows for more flexible and customizable weapon
functionality.
2025-05-08 18:31:19 +01:00

97 lines
2.8 KiB
GDScript

@icon("res://assets/editor/64x64/fc1098.png")
extends Node2D
class_name ModifierManager
signal modifier_added(modifier)
signal modifier_removed(modifier)
signal stats_updated()
var stats_component: StatsComponent
# Stores all active modifiers
var modifiers: Array[Modifier] = []
func _ready() -> void:
Log.pr("ModifierManager initialized")
Log.pr("StatsComponent: ", stats_component)
func set_stats(stats: StatsComponent) -> void:
self.stats_component = stats
func has_modifier(modifier_id: String) -> bool:
for modifier in modifiers:
if modifier.id == modifier_id:
return true
return false
func add_modifier(modifier: Modifier) -> void:
modifiers.append(modifier)
modifier.on_equip(get_parent())
emit_signal("modifier_added", modifier)
recalculate_stats()
func remove_modifier(modifier_id: String) -> void:
for i in range(modifiers.size()):
if modifiers[i].id == modifier_id:
var modifier = modifiers[i]
modifier.on_unequip(get_parent())
modifiers.remove_at(i)
emit_signal("modifier_removed", modifier)
recalculate_stats()
break
func recalculate_stats() -> void:
# Reset stats to base values
stats_component.reset_stats()
# Sort modifiers by priority
modifiers.sort_custom(func(a, b): return a.priority > b.priority)
# First pass: Apply OVERRIDE modifiers (highest priority first)
for modifier in modifiers:
if modifier.modifier_type == Modifier.ModifierType.OVERRIDE:
_apply_modifier_stats(modifier)
# Second pass: Apply ADDITIVE modifiers
for modifier in modifiers:
if modifier.modifier_type == Modifier.ModifierType.ADDITIVE:
_apply_modifier_stats(modifier)
# Third pass: Apply MULTIPLICATIVE modifiers
for modifier in modifiers:
if modifier.modifier_type == Modifier.ModifierType.MULTIPLICATIVE:
_apply_modifier_stats(modifier)
# Last pass: Apply CONDITIONAL modifiers
for modifier in modifiers:
if modifier.modifier_type == Modifier.ModifierType.CONDITIONAL:
_apply_modifier_stats(modifier)
emit_signal("stats_updated")
func check_callable(func_name: String) -> Callable:
# Create a default callable that does nothing and returns null
var default_callable = func(): return null
# Check each modifier in priority order
for modifier in modifiers:
if modifier.has_method(func_name):
# Return the callable from this modifier
return Callable(modifier, func_name)
# Return the default callable if no modifier has the function
return default_callable
# Convenience method to check and call in one step
func check_and_call(func_name: String, args := []):
var callable = check_callable(func_name)
if callable.is_valid():
if args.size() > 0:
return callable.callv(args)
else:
return callable.call()
return null
func _apply_modifier_stats(modifier: Modifier) -> void:
if modifier.has_method("apply_stats_modification"):
modifier.apply_stats_modification(stats_component)