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.
101 lines
No EOL
2.9 KiB
GDScript
101 lines
No EOL
2.9 KiB
GDScript
class_name ProjectileBase
|
|
extends Area2D
|
|
|
|
signal on_hit(projectile, target)
|
|
signal on_spawned(projectile)
|
|
signal on_destroyed(projectile)
|
|
|
|
@export var speed: float = 500.0
|
|
@export var damage: float = 10.0
|
|
@export var lifetime: float = 2
|
|
@export var direction: Vector2 = Vector2.RIGHT
|
|
@export var target_position: Vector2
|
|
@export var is_friendly: bool = true
|
|
|
|
# Modifier-related properties
|
|
var pierce_count: int = 0
|
|
var has_explosive_impact: bool = true
|
|
var explosion_projectile_count: int = 3
|
|
var explosion_projectile_damage_mult: float = 0.5
|
|
var explosion_projectile_speed: float = 300.0
|
|
var explosion_spread_angle: float = 360.0 # Full circle by default
|
|
|
|
# References
|
|
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 = []
|
|
|
|
func _on_body_entered(body):
|
|
if ignore_target.has(body):
|
|
Log.pr("Ignoring body: ", body.name)
|
|
return
|
|
|
|
if body.is_in_group("enemies") and is_friendly:
|
|
Log.pr("Hit enemy: ", body.name)
|
|
# Deal damage to enemy
|
|
if body.has_method("take_damage"):
|
|
body.take_damage(damage)
|
|
|
|
# Emit signal for modifiers to react to
|
|
emit_signal("on_hit", self, body)
|
|
|
|
# Handle piercing
|
|
if pierce_count > 0:
|
|
pierce_count -= 1
|
|
else:
|
|
# Handle explosive impact
|
|
if has_explosive_impact:
|
|
# Store the target that triggered the explosion
|
|
ignore_target.append(body)
|
|
_trigger_explosion()
|
|
|
|
# Destroy the projectile
|
|
destroy()
|
|
|
|
func _trigger_explosion():
|
|
# Create the explosion VFX
|
|
# var explosion = preload("res://scenes/explosion_effect.tscn").instantiate()
|
|
# explosion.global_position = global_position
|
|
# get_tree().root.add_child(explosion)
|
|
# Spawn the additional projectiles
|
|
if explosion_projectile_count > 0:
|
|
_spawn_explosion_projectiles()
|
|
|
|
func _spawn_explosion_projectiles():
|
|
for i in range(explosion_projectile_count):
|
|
# Create a new projectile
|
|
Log.pr("Spawning explosion projectile")
|
|
var new_proj = duplicate()
|
|
Log.pr("New projectile: ", new_proj)
|
|
new_proj.global_position = global_position
|
|
|
|
# Calculate new direction based on spread
|
|
var random_angle = randf_range(0, 2 * PI)
|
|
var new_dir = Vector2.RIGHT.rotated(random_angle)
|
|
|
|
# Set properties for the new projectile
|
|
new_proj.direction = new_dir
|
|
new_proj.damage = damage * explosion_projectile_damage_mult
|
|
new_proj.speed = explosion_projectile_speed
|
|
|
|
# Clear explosive properties so we don't get infinite loops
|
|
new_proj.has_explosive_impact = true
|
|
new_proj.explosion_projectile_count = 1
|
|
|
|
# Pass the ignore_target to the new projectiles
|
|
new_proj.ignore_target = ignore_target
|
|
|
|
# Add to scene tree
|
|
get_tree().root.call_deferred("add_child", new_proj)
|
|
|
|
func set_projectile_scale(new_scale: Vector2):
|
|
# Set the scale of the projectile
|
|
self.scale = new_scale
|
|
|
|
func destroy():
|
|
emit_signal("on_destroyed", self)
|
|
queue_free()
|
|
|
|
func _on_lifetime_timeout():
|
|
destroy() |