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.
This commit is contained in:
parent
9f66ab0a73
commit
70839387ca
22 changed files with 432 additions and 40 deletions
|
|
@ -18,6 +18,12 @@ func _ready() -> void:
|
|||
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())
|
||||
|
|
@ -63,6 +69,29 @@ func recalculate_stats() -> void:
|
|||
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ class_name FireRateAdditive extends Modifier
|
|||
func _init():
|
||||
id = "fire_rate_additive"
|
||||
display_name = "Rapid Fire"
|
||||
description = "Increases fire rate by %0.1f shots per second" % fire_rate_bonus
|
||||
description = "Increases fire rate by %0.1f shots per round" % fire_rate_bonus
|
||||
modifier_type = ModifierType.ADDITIVE
|
||||
|
||||
func apply_stats_modification(stats: StatsComponent) -> void:
|
||||
|
|
|
|||
|
|
@ -3,11 +3,10 @@ class_name FireRateMultiplicative extends Modifier
|
|||
@export var fire_rate_multiplier: float = 1.2 # 20% faster firing
|
||||
|
||||
func _init():
|
||||
id = "fire_rate_multiplicative"
|
||||
display_name = "Frenzy"
|
||||
description = "Increases fire rate by %d%%" % ((fire_rate_multiplier - 1.0) * 100)
|
||||
modifier_type = ModifierType.MULTIPLICATIVE
|
||||
id = "fire_rate_multiplicative"
|
||||
display_name = "Frenzy"
|
||||
description = "Increases fire rate by %d%%" % ((fire_rate_multiplier - 1.0) * 100)
|
||||
modifier_type = ModifierType.MULTIPLICATIVE
|
||||
|
||||
func apply_stats_modification(final_stats: Dictionary, _base_stats: Dictionary) -> void:
|
||||
if final_stats.has("fire_rate"):
|
||||
final_stats.fire_rate *= fire_rate_multiplier
|
||||
func apply_stats_modification(stats: StatsComponent) -> void:
|
||||
stats.update_stat("ranged.attack_rate", stats.get_stat("ranged.attack_rate") * fire_rate_multiplier)
|
||||
|
|
@ -17,15 +17,15 @@ enum ModifierType {
|
|||
|
||||
# Called when the modifier is added to a weapon or ability
|
||||
func on_equip(_owner) -> void:
|
||||
pass
|
||||
pass
|
||||
|
||||
# Called when the modifier is removed
|
||||
func on_unequip(_owner) -> void:
|
||||
pass
|
||||
pass
|
||||
|
||||
# Override in child classes for specific modification logic
|
||||
func modify_projectile(_projectile) -> void:
|
||||
pass
|
||||
pass
|
||||
|
||||
func modify_ability(_ability) -> void:
|
||||
pass
|
||||
pass
|
||||
|
|
@ -3,12 +3,11 @@ class_name ProjectileSizeMultiplicative extends Modifier
|
|||
@export var size_multiplier: float = 1.5 # 50% bigger
|
||||
|
||||
func _init():
|
||||
id = "size_multiplicative"
|
||||
display_name = "Giant Projectiles"
|
||||
description = "Multiplies projectile size by %0.1fx" % size_multiplier
|
||||
modifier_type = ModifierType.MULTIPLICATIVE
|
||||
priority = 10 # Higher priority than the additive version
|
||||
id = "size_multiplicative"
|
||||
display_name = "Giant Projectiles"
|
||||
description = "Multiplies projectile size by %0.1fx" % size_multiplier
|
||||
modifier_type = ModifierType.MULTIPLICATIVE
|
||||
priority = 10 # Higher priority than the additive version
|
||||
|
||||
func apply_stats_modification(final_stats: Dictionary, base_stats: Dictionary) -> void:
|
||||
if final_stats.has("projectile_size"):
|
||||
final_stats.projectile_size *= size_multiplier
|
||||
func apply_stats_modification(stats: StatsComponent) -> void:
|
||||
stats.update_stat("ranged.projectile_size", stats.get_stat("ranged.projectile_size") * size_multiplier)
|
||||
17
combat/modifiers/modifiers/unlimited_power.gd
Normal file
17
combat/modifiers/modifiers/unlimited_power.gd
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
class_name UnlimitedPower extends Modifier
|
||||
|
||||
@export var fire_rate_bonus: float = 1.0 # +1 shot per second
|
||||
@export var ranged_damage: float = 99.5
|
||||
|
||||
func _init():
|
||||
id = "unlimited_power"
|
||||
display_name = "Unlimited Power"
|
||||
description = "Shoot lightning bolts. Fire rate + %0.1f. Ranged damage + %0.1f" % [fire_rate_bonus, ranged_damage]
|
||||
modifier_type = ModifierType.ADDITIVE
|
||||
|
||||
func apply_stats_modification(stats: StatsComponent) -> void:
|
||||
stats.update_stat("ranged.attack_rate", stats.get_stat("ranged.attack_rate") + fire_rate_bonus)
|
||||
stats.update_stat("ranged.damage", stats.get_stat("ranged.damage") + ranged_damage)
|
||||
|
||||
func set_projectile_scene(weapon: RangedWeaponComponent) -> void:
|
||||
weapon.projectile_scene = preload("res://assets/projectiles/projectile_lightning.tscn")
|
||||
1
combat/modifiers/modifiers/unlimited_power.gd.uid
Normal file
1
combat/modifiers/modifiers/unlimited_power.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
|||
uid://b21isiwfqrjyi
|
||||
Loading…
Add table
Add a link
Reference in a new issue