diff --git a/assets/projectiles/components/bolt.gd b/assets/projectiles/components/bolt.gd index 5e2b89b..bf335bd 100644 --- a/assets/projectiles/components/bolt.gd +++ b/assets/projectiles/components/bolt.gd @@ -10,6 +10,7 @@ var emitting = true var final_goal: Vector2 @export var angle_var: float = 15 @onready var line: Line2D = $Line2D +#@onready var particles: CPUParticles2D = $Particles func _ready(): line.width = 2 @@ -48,6 +49,7 @@ func update_points(): curr_line_len = start_point.length() points.append(final_goal) + #particles.position = final_goal func set_line_width(amount): line.width = amount \ No newline at end of file diff --git a/assets/projectiles/components/bolt.tscn b/assets/projectiles/components/bolt.tscn index 406966d..ed51cdf 100644 --- a/assets/projectiles/components/bolt.tscn +++ b/assets/projectiles/components/bolt.tscn @@ -19,4 +19,9 @@ gradient = SubResource("Gradient_rrby1") [node name="Timer" type="Timer" parent="."] +[node name="Particles" type="CPUParticles2D" parent="."] +visible = false +emission_shape = 1 +emission_sphere_radius = 6.9 + [connection signal="timeout" from="Timer" to="." method="_on_timer_timeout"] diff --git a/combat/weapons/_scripts/ranged_weapon_component.gd b/combat/weapons/_scripts/ranged_weapon_component.gd index 1f91bc0..eabf209 100644 --- a/combat/weapons/_scripts/ranged_weapon_component.gd +++ b/combat/weapons/_scripts/ranged_weapon_component.gd @@ -11,6 +11,8 @@ class_name RangedWeaponComponent var can_fire: bool = true var cooldown: Timer +var projectile_spawn_location: Vector2 + func _init() -> void: cooldown = Timer.new() add_child(cooldown) @@ -33,7 +35,7 @@ func fire(direction: Vector2, target_position: Vector2) -> void: if !can_fire: return - spawn_projectile(global_position, direction, target_position) + spawn_projectile(direction, target_position) can_fire = false cooldown.start(1 / stats.get_stat("ranged.attack_rate")) @@ -42,21 +44,33 @@ 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: +## Get the projectile spawn location +## This defaults to the global position of the player +## but can be overridden by modifiers +func get_projectile_spawn_location() -> Vector2: + projectile_spawn_location = global_position + modifier_manager.check_and_call("get_projectile_spawn_location", [self]) + return projectile_spawn_location + +func spawn_projectile(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.global_position = get_projectile_spawn_location() 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.set_stats(stats.duplicate()) projectile.source_weapon = self var size = stats.get_stat("ranged.projectile_size") projectile.set_projectile_scale(Vector2(size, size)) + + for modifier in modifier_manager.modifiers: + Log.pr("Adding modifier to projectile: ", modifier) + if projectile.has_method("add_modifier"): + projectile.add_modifier(modifier) + if get_tree() and get_tree().get_root(): get_tree().get_root().add_child(projectile) diff --git a/map/Map.tscn b/map/Map.tscn index 671f18d..6534dc2 100644 --- a/map/Map.tscn +++ b/map/Map.tscn @@ -18,7 +18,7 @@ tile_set = ExtResource("2_3nv2f") tile_set = ExtResource("2_3nv2f") [node name="Player" parent="." instance=ExtResource("5_3nv2f")] -position = Vector2(20, 20) +position = Vector2(6, 0) [node name="TestEnemy" parent="." instance=ExtResource("4_raxr4")] position = Vector2(87, 72) diff --git a/player/weapons/projectile_base.gd b/player/weapons/projectile_base.gd index bb26a66..5ab16cd 100644 --- a/player/weapons/projectile_base.gd +++ b/player/weapons/projectile_base.gd @@ -5,6 +5,9 @@ signal on_hit(projectile, target) signal on_spawned(projectile) signal on_destroyed(projectile) +var stats = StatsComponent +var modifier_manager: ModifierManager + @export var speed: float = 500.0 @export var damage: float = 10.0 @export var lifetime: float = 2 @@ -26,6 +29,38 @@ var lifetime_timer: Timer # Add a variable to track the entity that triggered the explosion var ignore_target = [] +func _init() -> void: + Log.pr('Setting up ModifierManager for projectile...') + modifier_manager = ModifierManager.new() + +func _ready() -> void: + pass + +func set_stats(setting_stats: StatsComponent) -> void: + Log.pr('Snapshotting stats for projectile:', setting_stats) + self.stats = setting_stats + modifier_manager.set_stats(stats) + + # Set up the lifetime timer + lifetime_timer = Timer.new() + add_child(lifetime_timer) + lifetime_timer.one_shot = true + lifetime_timer.wait_time = lifetime + #lifetime_timer.connect("timeout", self, "_on_lifetime_timeout") + lifetime_timer.start() + + # Ensure we have a collision shape + #ensure_collision_shape() + + emit_signal("on_spawned", self) + #connect("body_entered", self, "_on_body_entered") + +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 _on_body_entered(body): if ignore_target.has(body): Log.pr("Ignoring body: ", body.name) @@ -98,4 +133,4 @@ func destroy(): queue_free() func _on_lifetime_timeout(): - destroy() \ No newline at end of file + destroy() diff --git a/player/weapons/projectile_lightning.gd b/player/weapons/projectile_lightning.gd index 437c780..bed9cf6 100644 --- a/player/weapons/projectile_lightning.gd +++ b/player/weapons/projectile_lightning.gd @@ -7,13 +7,16 @@ extends ProjectileBase # Add variables to track collision state var has_collided: bool = false var collision_point: Vector2 = Vector2.ZERO +var existing_shape: CollisionShape2D = null func _init() -> void: - #super._init() + super._init() Log.pr("ProjectileLightning _init") func _ready(): + super._ready() Log.pr(ignore_target) + Log.pr('Source Weapon: ', source_weapon) lifetime_timer = Timer.new() add_child(lifetime_timer) @@ -36,7 +39,7 @@ func _ready(): func ensure_collision_shape(): # Check if we already have a collision shape var has_collision_shape = false - var existing_shape = null + existing_shape = null for child in get_children(): if child is CollisionShape2D: @@ -75,6 +78,9 @@ func update_collision_shape(collision_shape = null): if collision_shape: var capsule = collision_shape.shape as CapsuleShape2D if capsule: + #collision_shape.global_position = source_weapon.global_position + global_position = source_weapon.global_position + var target = collision_point if has_collided else target_position var distance = global_position.distance_to(target) var dir = (target - global_position).normalized() @@ -87,12 +93,13 @@ func update_collision_shape(collision_shape = null): # Fix position: Move the shape so it starts at origin collision_shape.position = dir * (distance / 2) - + func _process(delta): # Update target positions for lightning bolts for child in lightning: if child is LightningBolt: + child.global_position = source_weapon.global_position child.goal_point = collision_point if has_collided else target_position # Update collision shape if it exists