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:
Dan Baker 2025-05-08 18:31:19 +01:00
parent 9f66ab0a73
commit 70839387ca
22 changed files with 432 additions and 40 deletions

View file

@ -5,13 +5,10 @@ class_name MapBuilderClass
# Function to copy a TileMap layer from one scene to a target TileMap at a specific grid position
func copy_tilemap_to_target(source_scene, target_tilemap: TileMapLayer, target_layer: String, grid_position: Vector2i):
# First, load and instantiate the source scene if it's a resource path
Log.pr("Copying tilemap from source scene to target tilemap at grid position: ", grid_position)
Log.pr("Source scene: ", source_scene)
var source_instance
if source_scene is String:
source_instance = load(source_scene).instantiate()
elif source_scene is PackedScene:
Log.pr("Source scene is a PackedScene, instantiating it")
source_instance = source_scene.instantiate()
else:
source_instance = source_scene
@ -68,8 +65,6 @@ func find_tilemap_by_name(root_node: Node, tilemap_name: String) -> TileMapLayer
func redraw_terrain(positions: Array, layer: TileMapLayer, terrain_set: int, terrain: int) -> void:
Log.pr("Filtering and redrawing surrounding tiles", positions)
# Filter positions to only include cells with terrainset 0 and terrain 0
var filtered_positions: Array = []
for cell in positions:
@ -80,7 +75,6 @@ func redraw_terrain(positions: Array, layer: TileMapLayer, terrain_set: int, ter
# Only redraw if we have filtered cells
if filtered_positions.size() > 0:
Log.pr("Redrawing filtered tiles:", filtered_positions)
layer.set_cells_terrain_connect(filtered_positions, terrain_set, terrain)
else:
Log.pr("No tiles to redraw after filtering")

View file

@ -0,0 +1,62 @@
extends Node
class_name ModifierLibrary
var modifiers: Array[Modifier] = []
func _ready() -> void:
## Check the modifier folder for any scripts that extend the Modifier class
var modifier_folder = "res://combat/modifiers/modifiers/"
var dir = DirAccess.open(modifier_folder)
if dir:
dir.list_dir_begin()
var file_name = dir.get_next()
while file_name != "":
if file_name.ends_with(".gd"):
var script_path = modifier_folder + file_name
var script = load(script_path)
var temp_instance = script.new() if script else null
var is_modifier = temp_instance is Modifier if temp_instance else false
if is_modifier and file_name != "modifier.gd":
modifiers.append(temp_instance)
file_name = dir.get_next()
dir.list_dir_end()
else:
print("Failed to open directory: ", modifier_folder)
Log.pr("ModifierLibrary initialized with %d modifiers" % modifiers.size())
Log.pr("Modifiers: ", modifiers)
func get_modifier_by_id(modifier_id: String) -> Modifier:
for modifier in modifiers:
if modifier.id == modifier_id:
return modifier.duplicate()
return null
func get_modifiers_by_type(modifier_type: int) -> Array[Modifier]:
var result: Array[Modifier] = []
for modifier in modifiers:
if modifier.modifier_type == modifier_type:
result.append(modifier)
return result
func get_modifiers_by_rarity(rarity: int) -> Array[Modifier]:
var result: Array[Modifier] = []
for modifier in modifiers:
if modifier.rarity == rarity:
result.append(modifier)
return result
func get_modifiers_by_priority(priority: int) -> Array[Modifier]:
var result: Array[Modifier] = []
for modifier in modifiers:
if modifier.priority == priority:
result.append(modifier)
return result
func get_all_modifiers() -> Array[Modifier]:
return modifiers

View file

@ -0,0 +1 @@
uid://di51ocdha4fx7

View file

@ -29,7 +29,7 @@ func initialize_cache(folder_path: String, preload_scenes: bool = false):
scene_files.append(folder_path + "/" + file_name)
file_name = dir.get_next()
Log.pr("Found %d scene files in %s" % [scene_files.size(), folder_path])
#Log.pr("Found %d scene files in %s" % [scene_files.size(), folder_path])
# Store in cache
_scene_paths_cache[folder_path] = scene_files
@ -37,7 +37,7 @@ func initialize_cache(folder_path: String, preload_scenes: bool = false):
if preload_scenes and scene_files.size() > 0:
_loaded_scenes_cache[folder_path] = []
for scene_path in scene_files:
Log.pr("Preloading scene: " + scene_path)
#Log.pr("Preloading scene: " + scene_path)
# Load the scene and store it in the cache
#var loaded_scene = preload(scene_path)
_loaded_scenes_cache[folder_path].append(load(scene_path))
@ -47,7 +47,7 @@ func initialize_cache(folder_path: String, preload_scenes: bool = false):
func get_random_scene(folder_path: String):
# Make sure the cache is initialized
if not _scene_paths_cache.has(folder_path):
Log.pr("Initializing cache for folder: " + folder_path)
#Log.pr("Initializing cache for folder: " + folder_path)
initialize_cache(folder_path, true)
var scene_paths = _scene_paths_cache[folder_path]
@ -60,10 +60,10 @@ func get_random_scene(folder_path: String):
# Return from loaded scenes cache if available
if _loaded_scenes_cache.has(folder_path):
Log.pr("Returning preloaded scene from cache")
#Log.pr("Returning preloaded scene from cache")
return _loaded_scenes_cache[folder_path][random_index]
# Otherwise load the scene
var scene = load(scene_paths[random_index])
Log.pr(scene)
#Log.pr(scene)
return scene