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
85
UI/DebugUI.tscn
Normal file
85
UI/DebugUI.tscn
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
[gd_scene load_steps=2 format=3 uid="uid://b0w0oxbtax5si"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://bblhlxj8sqtql" path="res://UI/_scripts/debug_ui.gd" id="1_pwlud"]
|
||||
|
||||
[node name="DebugUi" type="Control"]
|
||||
layout_mode = 3
|
||||
anchors_preset = 0
|
||||
script = ExtResource("1_pwlud")
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="."]
|
||||
offset_left = 13.0
|
||||
offset_top = 15.0
|
||||
offset_right = 91.0
|
||||
offset_bottom = 173.0
|
||||
theme_override_constants/margin_left = 5
|
||||
theme_override_constants/margin_top = 5
|
||||
theme_override_constants/margin_right = 5
|
||||
theme_override_constants/margin_bottom = 5
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 5
|
||||
|
||||
[node name="FPS" type="HBoxContainer" parent="MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="FPSLabel" type="Label" parent="MarginContainer/VBoxContainer/FPS"]
|
||||
layout_mode = 2
|
||||
text = "FPS: "
|
||||
|
||||
[node name="FPSValue" type="Label" parent="MarginContainer/VBoxContainer/FPS"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
text = "123"
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="PlayerWeapon" type="HBoxContainer" parent="MarginContainer/VBoxContainer"]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="PlayerWeaponLabel" type="Label" parent="MarginContainer/VBoxContainer/PlayerWeapon"]
|
||||
layout_mode = 2
|
||||
text = "Player Weapon:"
|
||||
|
||||
[node name="PlayerWeaponValue" type="Label" parent="MarginContainer/VBoxContainer/PlayerWeapon"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="PlayerWeaponMods" type="HBoxContainer" parent="MarginContainer/VBoxContainer"]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 2
|
||||
|
||||
[node name="PlayerWeaponModsLabel" type="Label" parent="MarginContainer/VBoxContainer/PlayerWeaponMods"]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
text = "Mods:"
|
||||
|
||||
[node name="PlayerWeaponModsValue" type="Label" parent="MarginContainer/VBoxContainer/PlayerWeaponMods"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
text = "123
|
||||
456
|
||||
678"
|
||||
|
||||
[node name="ModifierButtons" type="VBoxContainer" parent="MarginContainer/VBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Button" type="Button" parent="MarginContainer/VBoxContainer/ModifierButtons"]
|
||||
layout_mode = 2
|
||||
text = "123"
|
||||
|
||||
[node name="PlayerStats" type="HBoxContainer" parent="MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 2
|
||||
|
||||
[node name="PlayerStatsValue" type="Label" parent="MarginContainer/VBoxContainer/PlayerStats"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
text = "123
|
||||
456
|
||||
678"
|
||||
107
UI/_scripts/debug_ui.gd
Normal file
107
UI/_scripts/debug_ui.gd
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
extends Control
|
||||
class_name DebugUI
|
||||
|
||||
var fps_label: Label
|
||||
var player_weapon_mods_label: Label
|
||||
|
||||
var player: Player
|
||||
var was_debug_key_pressed: bool = false
|
||||
|
||||
var is_mouse_over_ui: bool = false
|
||||
|
||||
func _ready():
|
||||
self.visible = false
|
||||
player = get_tree().get_first_node_in_group("player")
|
||||
|
||||
fps_label = %FPSValue
|
||||
player_weapon_mods_label = %PlayerWeaponModsValue
|
||||
|
||||
self.position = Vector2.ZERO
|
||||
self.size = get_viewport_rect().size
|
||||
self.scale = Vector2(1.2, 1.2)
|
||||
|
||||
# Connect the mouse entered/exited signals to track when mouse is over UI
|
||||
self.mouse_entered.connect(_on_mouse_entered)
|
||||
self.mouse_exited.connect(_on_mouse_exited)
|
||||
|
||||
# Make the UI control consume input events
|
||||
self.mouse_filter = Control.MOUSE_FILTER_STOP
|
||||
|
||||
func _on_mouse_entered() -> void:
|
||||
is_mouse_over_ui = true
|
||||
|
||||
func _on_mouse_exited() -> void:
|
||||
is_mouse_over_ui = false
|
||||
|
||||
func _input(event: InputEvent) -> void:
|
||||
# Only process if debug UI is visible
|
||||
if not self.visible:
|
||||
return
|
||||
|
||||
# Check if it's a mouse button event and if mouse is over UI
|
||||
if event is InputEventMouseButton:
|
||||
if is_mouse_over_ui:
|
||||
# Consume the event so it doesn't propagate to the game
|
||||
get_viewport().set_input_as_handled()
|
||||
|
||||
func _process(_delta):
|
||||
if Input.is_action_pressed("debug_menu"):
|
||||
if not was_debug_key_pressed:
|
||||
populate_modifier_buttons()
|
||||
was_debug_key_pressed = true
|
||||
self.visible = !self.visible
|
||||
else:
|
||||
was_debug_key_pressed = false
|
||||
|
||||
var current_fps = Engine.get_frames_per_second()
|
||||
fps_label.text = str(current_fps)
|
||||
|
||||
var player_stats = player.stats.get_nested_stat("ranged")
|
||||
var player_stats_label = %PlayerStatsValue
|
||||
player_stats_label.text = ""
|
||||
for stat in player_stats:
|
||||
player_stats_label.text += str(stat) + ": " + str(player_stats[stat]) + "\n"
|
||||
|
||||
|
||||
var player_mods = player.ranged.modifier_manager.modifiers
|
||||
player_weapon_mods_label.text = ""
|
||||
for mod in player_mods:
|
||||
player_weapon_mods_label.text += str(mod.id) + " (" + str(mod.description) + ") \n"
|
||||
|
||||
|
||||
func populate_modifier_buttons() -> void:
|
||||
# Clear existing buttons
|
||||
for child in %ModifierButtons.get_children():
|
||||
if child is Button:
|
||||
child.queue_free()
|
||||
|
||||
# Create buttons for each modifier
|
||||
for modifier in ModLib.get_all_modifiers():
|
||||
var button = Button.new()
|
||||
button.mouse_filter = Control.MOUSE_FILTER_STOP
|
||||
button.toggle_mode = true
|
||||
button.text = modifier.id + " [" + modifier.description + "]"
|
||||
|
||||
# If the modifier exists in the player's weapon, set the button to "pressed"
|
||||
if player.ranged.modifier_manager.has_modifier(modifier.id):
|
||||
button.button_pressed = true
|
||||
else:
|
||||
button.button_pressed = false
|
||||
|
||||
# Store modifier id in the button's metadata for reference in the callback
|
||||
button.set_meta("modifier_id", modifier.id)
|
||||
|
||||
# Connect the toggled signal to a callback function
|
||||
button.toggled.connect(_on_modifier_button_toggled.bind(modifier.id))
|
||||
|
||||
%ModifierButtons.add_child(button)
|
||||
|
||||
func _on_modifier_button_toggled(button_pressed: bool, modifier_id: String) -> void:
|
||||
if button_pressed:
|
||||
# Add the modifier if the button is pressed
|
||||
var modifier = ModLib.get_modifier_by_id(modifier_id)
|
||||
if modifier:
|
||||
player.ranged.modifier_manager.add_modifier(modifier)
|
||||
else:
|
||||
# Remove the modifier if the button is unpressed
|
||||
player.ranged.modifier_manager.remove_modifier(modifier_id)
|
||||
1
UI/_scripts/debug_ui.gd.uid
Normal file
1
UI/_scripts/debug_ui.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
|||
uid://bblhlxj8sqtql
|
||||
16
assets/themes/main_theme.tres
Normal file
16
assets/themes/main_theme.tres
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
[gd_resource type="Theme" load_steps=2 format=3 uid="uid://ddgipwj5yd0vw"]
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_6ioqn"]
|
||||
bg_color = Color(0.6, 0.6, 0.6, 0.560784)
|
||||
border_width_left = 1
|
||||
border_width_top = 1
|
||||
border_width_right = 1
|
||||
border_width_bottom = 1
|
||||
border_color = Color(0.888331, 0.274714, 0.539223, 1)
|
||||
corner_radius_top_left = 3
|
||||
corner_radius_top_right = 3
|
||||
corner_radius_bottom_right = 3
|
||||
corner_radius_bottom_left = 3
|
||||
|
||||
[resource]
|
||||
Button/styles/pressed = SubResource("StyleBoxFlat_6ioqn")
|
||||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -8,6 +8,5 @@ func _init():
|
|||
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)
|
||||
|
|
@ -9,6 +9,5 @@ func _init():
|
|||
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
|
||||
|
|
@ -3,15 +3,68 @@ extends Node2D
|
|||
class_name RangedWeaponComponent
|
||||
|
||||
@export var stats: StatsComponent
|
||||
@export var basic_projectile: PackedScene = preload("res://assets/projectiles/basic_projectile.tscn")
|
||||
|
||||
@onready var modifier_manager = $ModifierManager
|
||||
@onready var projectile_scene: PackedScene = basic_projectile
|
||||
|
||||
var can_fire: bool = true
|
||||
var cooldown: Timer
|
||||
|
||||
func _init() -> void:
|
||||
cooldown = Timer.new()
|
||||
add_child(cooldown)
|
||||
cooldown.one_shot = true
|
||||
|
||||
func _ready() -> void:
|
||||
Log.pr("RangedWeaponComponent initialized")
|
||||
modifier_manager.set_stats(stats)
|
||||
modifier_manager.connect("modifier_added", _on_modifier_added)
|
||||
modifier_manager.connect("modifier_removed", _on_modifier_removed)
|
||||
cooldown.connect("timeout", _on_fire_timer_timeout)
|
||||
|
||||
func add_modifier(modifier: Modifier) -> void:
|
||||
modifier_manager.add_modifier(modifier)
|
||||
|
||||
func remove_modifier(modifier_id: String) -> void:
|
||||
modifier_manager.remove_modifier(modifier_id)
|
||||
|
||||
func fire(direction: Vector2, target_position: Vector2) -> void:
|
||||
if !can_fire:
|
||||
return
|
||||
|
||||
spawn_projectile(global_position, direction, target_position)
|
||||
|
||||
can_fire = false
|
||||
cooldown.start(1 / stats.get_stat("ranged.attack_rate"))
|
||||
|
||||
func set_projectile_scene() -> void:
|
||||
projectile_scene = basic_projectile
|
||||
modifier_manager.check_and_call("set_projectile_scene", [self])
|
||||
|
||||
func spawn_projectile(spawn_position: Vector2, spawn_direction: Vector2, target_position: Vector2) -> void:
|
||||
Log.pr("Spawning projectile")
|
||||
modifier_manager.check_and_call("spawn_projectile", [self])
|
||||
|
||||
## TODO: Handle multiple shots per fire
|
||||
|
||||
var projectile = projectile_scene.instantiate()
|
||||
projectile.global_position = spawn_position
|
||||
projectile.target_position = target_position
|
||||
projectile.speed = 200 # stats.get_stat("projectile_speed")
|
||||
projectile.damage = 10 # stats.get_stat("damage")
|
||||
projectile.lifetime = 2 # stats.get_stat("projectile_lifetime")
|
||||
projectile.source_weapon = self
|
||||
var size = stats.get_stat("ranged.projectile_size")
|
||||
projectile.set_projectile_scale(Vector2(size, size))
|
||||
if get_tree() and get_tree().get_root():
|
||||
get_tree().get_root().add_child(projectile)
|
||||
|
||||
func _on_modifier_added(_modifier: Modifier) -> void:
|
||||
set_projectile_scene()
|
||||
|
||||
func _on_modifier_removed(_modifier: Modifier) -> void:
|
||||
set_projectile_scene()
|
||||
|
||||
func _on_fire_timer_timeout() -> void:
|
||||
can_fire = true
|
||||
|
|
|
|||
|
|
@ -31,14 +31,14 @@ var base_stats: Dictionary[String, Variant] = {
|
|||
}
|
||||
}
|
||||
|
||||
var stats: Dictionary
|
||||
var stats: Dictionary = {}
|
||||
|
||||
func _init() -> void:
|
||||
if not stats:
|
||||
reset_stats()
|
||||
|
||||
func reset_stats() -> void:
|
||||
stats = base_stats.duplicate()
|
||||
stats = base_stats.duplicate(true)
|
||||
Log.pr("StatsComponent reset to base stats")
|
||||
|
||||
func get_stat(stat_name: String) -> Variant:
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
[gd_scene load_steps=86 format=3 uid="uid://bo5aw2cad3akl"]
|
||||
[gd_scene load_steps=87 format=3 uid="uid://bo5aw2cad3akl"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://bq038uo4cm6nv" path="res://player/scripts/player.gd" id="1_oul6g"]
|
||||
[ext_resource type="Texture2D" uid="uid://dqgq2c1h6yk3k" path="res://assets/sprites/characters/pink/Pink_Monster_Attack1_4.png" id="2_yllr7"]
|
||||
|
|
@ -17,6 +17,7 @@
|
|||
[ext_resource type="PackedScene" uid="uid://dud7c465danl4" path="res://combat/weapons/RangedWeaponComponent.tscn" id="15_wodsf"]
|
||||
[ext_resource type="PackedScene" uid="uid://dqful6et42ok8" path="res://combat/weapons/MeleeWeaponComponent.tscn" id="16_32hag"]
|
||||
[ext_resource type="PackedScene" uid="uid://bjybfg0xrowb5" path="res://entities/StatsComponent.tscn" id="17_tqiix"]
|
||||
[ext_resource type="PackedScene" uid="uid://b0w0oxbtax5si" path="res://UI/DebugUI.tscn" id="18_e7oew"]
|
||||
|
||||
[sub_resource type="CircleShape2D" id="CircleShape2D_rkbax"]
|
||||
|
||||
|
|
@ -545,11 +546,12 @@ animations = [{
|
|||
"speed": 5.0
|
||||
}]
|
||||
|
||||
[node name="Player" type="CharacterBody2D" node_paths=PackedStringArray("ranged", "melee") groups=["friendly"]]
|
||||
[node name="Player" type="CharacterBody2D" node_paths=PackedStringArray("ranged", "melee", "stats") groups=["friendly", "player"]]
|
||||
collision_mask = 14
|
||||
script = ExtResource("1_oul6g")
|
||||
ranged = NodePath("RangedWeaponComponent")
|
||||
melee = NodePath("MeleeWeaponComponent")
|
||||
stats = NodePath("StatsComponent")
|
||||
|
||||
[node name="PlayerCollision" type="CollisionShape2D" parent="."]
|
||||
position = Vector2(0, 7)
|
||||
|
|
@ -572,3 +574,15 @@ stats = NodePath("../StatsComponent")
|
|||
[node name="MeleeWeaponComponent" parent="." instance=ExtResource("16_32hag")]
|
||||
|
||||
[node name="StatsComponent" parent="." instance=ExtResource("17_tqiix")]
|
||||
|
||||
[node name="CanvasLayer" type="CanvasLayer" parent="."]
|
||||
layer = 100
|
||||
|
||||
[node name="DebugUi" parent="CanvasLayer" instance=ExtResource("18_e7oew")]
|
||||
offset_left = -288.0
|
||||
offset_top = -161.0
|
||||
offset_right = 870.0
|
||||
offset_bottom = 492.0
|
||||
scale = Vector2(0.499389, 0.499439)
|
||||
size_flags_horizontal = 4
|
||||
size_flags_vertical = 4
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
extends CharacterBody2D
|
||||
|
||||
class_name Player
|
||||
|
||||
@export var speed = 200
|
||||
@export var special_ability: Ability
|
||||
@export var ranged: RangedWeaponComponent
|
||||
@export var melee: MeleeWeaponComponent
|
||||
@export var stats: StatsComponent
|
||||
|
||||
var movement: PlayerMovement
|
||||
var combat: PlayerCombat
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ var explosion_projectile_speed: float = 300.0
|
|||
var explosion_spread_angle: float = 360.0 # Full circle by default
|
||||
|
||||
# References
|
||||
var source_weapon: RangedWeapon # Reference to the weapon that fired this
|
||||
var source_weapon: RangedWeaponComponent # Reference to the weapon that fired this
|
||||
var lifetime_timer: Timer
|
||||
# Add a variable to track the entity that triggered the explosion
|
||||
var ignore_target = []
|
||||
|
|
|
|||
|
|
@ -106,7 +106,6 @@ func add_modifier(modifier: Modifier):
|
|||
func remove_modifier(modifier_id: String):
|
||||
pass
|
||||
#stats.remove_modifier(modifier_id)
|
||||
|
||||
func _on_stats_updated():
|
||||
# Update any visual components based on new stats
|
||||
# For example, if weapon appearance changes based on damage/fire rate
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ Global="*res://utility/Globals.gd"
|
|||
SceneSelector="*res://utility/SceneSelector.gd"
|
||||
MapBuilder="*res://utility/MapBuilder.gd"
|
||||
DebugMenu="*res://addons/debug_menu/debug_menu.tscn"
|
||||
ModLib="*res://utility/ModifierLibrary.gd"
|
||||
|
||||
[display]
|
||||
|
||||
|
|
@ -36,11 +37,17 @@ enabled=PackedStringArray("res://addons/debug_menu/plugin.cfg", "res://addons/lo
|
|||
[file_customization]
|
||||
|
||||
folder_colors={
|
||||
"res://UI/": "green",
|
||||
"res://combat/": "red",
|
||||
"res://combat/modifiers/": "green",
|
||||
"res://combat/weapons/": "red"
|
||||
"res://combat/weapons/": "red",
|
||||
"res://utility/": "purple"
|
||||
}
|
||||
|
||||
[gui]
|
||||
|
||||
theme/custom="uid://ddgipwj5yd0vw"
|
||||
|
||||
[input]
|
||||
|
||||
move_up={
|
||||
|
|
@ -68,6 +75,11 @@ fire={
|
|||
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":1,"position":Vector2(115, 24),"global_position":Vector2(129, 97),"factor":1.0,"button_index":1,"canceled":false,"pressed":true,"double_click":false,"script":null)
|
||||
]
|
||||
}
|
||||
debug_menu={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194332,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
|
||||
[layer_names]
|
||||
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
62
utility/ModifierLibrary.gd
Normal file
62
utility/ModifierLibrary.gd
Normal 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
|
||||
1
utility/ModifierLibrary.gd.uid
Normal file
1
utility/ModifierLibrary.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
|||
uid://di51ocdha4fx7
|
||||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue