randomgeon/player/weapons/projectile_base.gd
Dan Baker 70839387ca 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.
2025-05-08 18:31:19 +01:00

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()