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.
97 lines
2.8 KiB
GDScript
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)
|