From 3303d937fd26c5dad550bea85fa908e21618e14c Mon Sep 17 00:00:00 2001 From: henry Date: Fri, 26 Jun 2026 23:54:53 +0100 Subject: [PATCH] Added grouped shots as sub resources, as well as the abilit to mirror pairs. --- .../player_weapon_resources/patterns/fwd.tres | 9 ++ .../patterns/phallanx.tres | 11 ++ .../player_weapon_resources/vanguard+.tres | 22 +++ scenes/player.tscn | 3 +- scripts/shoot_component.gd | 130 +++++++++++++----- scripts/weapon_projectile_group.gd | 21 +++ scripts/weapon_projectile_group.gd.uid | 1 + scripts/weapon_shot.gd | 3 + 8 files changed, 166 insertions(+), 34 deletions(-) create mode 100644 resources/player_weapon_resources/patterns/fwd.tres create mode 100644 resources/player_weapon_resources/patterns/phallanx.tres create mode 100644 resources/player_weapon_resources/vanguard+.tres create mode 100644 scripts/weapon_projectile_group.gd create mode 100644 scripts/weapon_projectile_group.gd.uid diff --git a/resources/player_weapon_resources/patterns/fwd.tres b/resources/player_weapon_resources/patterns/fwd.tres new file mode 100644 index 0000000..6008dfb --- /dev/null +++ b/resources/player_weapon_resources/patterns/fwd.tres @@ -0,0 +1,9 @@ +[gd_resource type="Resource" script_class="WeaponProjectileGroup" format=3 uid="uid://tdmd8jq8cm4y"] + +[ext_resource type="Script" uid="uid://d0ios82vubijg" path="res://scripts/weapon_projectile_group.gd" id="1_mhej7"] + +[resource] +script = ExtResource("1_mhej7") +bullet_count = 5 +group_delay = 5.0 +stagger_offset = 2.0 diff --git a/resources/player_weapon_resources/patterns/phallanx.tres b/resources/player_weapon_resources/patterns/phallanx.tres new file mode 100644 index 0000000..48f630f --- /dev/null +++ b/resources/player_weapon_resources/patterns/phallanx.tres @@ -0,0 +1,11 @@ +[gd_resource type="Resource" script_class="WeaponProjectileGroup" format=3 uid="uid://ch8qch6lx1mdx"] + +[ext_resource type="Script" uid="uid://d0ios82vubijg" path="res://scripts/weapon_projectile_group.gd" id="1_m23g4"] + +[resource] +script = ExtResource("1_m23g4") +spread_angle = 3.0 +angle_offset = 8.0 +horizontal_offset = 20.0 +group_delay = 0.25 +stagger_offset = 0.5 diff --git a/resources/player_weapon_resources/vanguard+.tres b/resources/player_weapon_resources/vanguard+.tres new file mode 100644 index 0000000..4d2d490 --- /dev/null +++ b/resources/player_weapon_resources/vanguard+.tres @@ -0,0 +1,22 @@ +[gd_resource type="Resource" script_class="WeaponShot" format=3 uid="uid://c41aoyka7nfr8"] + +[ext_resource type="PackedScene" uid="uid://ddpclu2vdy2ve" path="res://scenes/player_weapons/weapon_stock.tscn" id="1_lqlv8"] +[ext_resource type="Script" uid="uid://d0ios82vubijg" path="res://scripts/weapon_projectile_group.gd" id="2_qeb4b"] +[ext_resource type="Script" uid="uid://7n1itonn35fm" path="res://scripts/weapon_shot.gd" id="3_fh2eq"] +[ext_resource type="Resource" uid="uid://ch8qch6lx1mdx" path="res://resources/player_weapon_resources/patterns/phallanx.tres" id="3_qeb4b"] + +[resource] +script = ExtResource("3_fh2eq") +shot_name = "vanguard+" +bullet_scene = ExtResource("1_lqlv8") +damage = 5 +speed = 500 +projectiles = 5 +spacing = 30.0 +origin = -15 +horizontal_offset = 8.25 +stagger_offset = 0.5 +stagger_animation = true +follow_angle = true +groups = Array[ExtResource("2_qeb4b")]([ExtResource("3_qeb4b")]) +metadata/_custom_type_script = "uid://7n1itonn35fm" diff --git a/scenes/player.tscn b/scenes/player.tscn index e56122c..92a9dc9 100644 --- a/scenes/player.tscn +++ b/scenes/player.tscn @@ -14,6 +14,7 @@ [ext_resource type="Resource" uid="uid://cck3gmnhu5agc" path="res://resources/player_weapon_resources/tri.tres" id="11_3v2ag"] [ext_resource type="Script" uid="uid://65d3hbrpm21x" path="res://scripts/effects/effects_component.gd" id="12_effcomp"] [ext_resource type="Resource" uid="uid://ds53sryglmf27" path="res://resources/player_weapon_resources/spread.tres" id="13_f1ej7"] +[ext_resource type="Resource" uid="uid://c41aoyka7nfr8" path="res://resources/player_weapon_resources/vanguard+.tres" id="14_oprun"] [sub_resource type="AtlasTexture" id="AtlasTexture_tuyoq"] atlas = ExtResource("5_qlg0r") @@ -158,7 +159,7 @@ script = ExtResource("6_y4r1p") unique_name_in_owner = true script = ExtResource("7_d2wvv") weapon_data = ExtResource("8_stock") -available_weapons = Array[ExtResource("10_d2wvv")]([ExtResource("8_stock"), ExtResource("11_3v2ag"), ExtResource("9_ur7pv"), ExtResource("13_f1ej7")]) +available_weapons = Array[ExtResource("10_d2wvv")]([ExtResource("8_stock"), ExtResource("11_3v2ag"), ExtResource("9_ur7pv"), ExtResource("13_f1ej7"), ExtResource("14_oprun")]) weapon_change_flash = SubResource("Resource_jej6c") metadata/_custom_type_script = "uid://ylmao2ndp22y" diff --git a/scripts/shoot_component.gd b/scripts/shoot_component.gd index 5ed160b..789970d 100644 --- a/scripts/shoot_component.gd +++ b/scripts/shoot_component.gd @@ -6,50 +6,114 @@ class_name ShootComponent extends Node func shoot(): var weapon_data = weapon_component.weapon_data var current_time = Time.get_ticks_msec() / 1000.0 - var total_projectiles = weapon_data.projectiles if player.travel > weapon_data.spacing: + _shoot_standard(weapon_data, current_time) + _shoot_grouped(weapon_data, current_time) - # Calculate center index for symmetrical staggering - var center_index = (total_projectiles - 1) / 2.0 + # Reset travel after firing to prevent multiple bursts per tap + player.travel = 0.0 - if total_projectiles > 0: - for b in range(total_projectiles): - var bullet := weapon_data.bullet_scene.instantiate() as Area2D - get_tree().root.add_child(bullet) - # Calculate index relative to center (0 = center, -1/+1 = first from center) - var index_from_center: float = b - center_index +# Standard projectile logic (backward compatible) +func _shoot_standard(weapon_data: WeaponShot, current_time: float): + var total_projectiles = weapon_data.projectiles + var center_index = (total_projectiles - 1) / 2.0 - # Calculate timing offset for staggered firing (center-first, pairs outward) - var time_offset: float = abs(index_from_center) * weapon_data.stagger_offset + if total_projectiles > 0: + for b in range(total_projectiles): + var bullet := weapon_data.bullet_scene.instantiate() as Area2D + get_tree().root.add_child(bullet) - # Calculate horizontal offset for this bullet (symmetrical: left=-ve, right=+ve) - var bullet_horizontal_offset: float = index_from_center * weapon_data.horizontal_offset + # Calculate index relative to center (0 = center, -1/+1 = first from center) + var index_from_center: float = b - center_index - # Calculate vertical offset from center point (symmetrical vertical spread) - var distance_from_center: float = abs(index_from_center) - var vertical_offset: float = (distance_from_center * weapon_data.origin * -1) / 2 + # Calculate timing offset for staggered firing (center-first, pairs outward) + var time_offset: float = abs(index_from_center) * weapon_data.stagger_offset - # Final position combines symmetrical horizontal spread with symmetrical vertical spacing - bullet.position = player.position + Vector2(bullet_horizontal_offset, weapon_data.origin + (vertical_offset + weapon_data.origin - total_projectiles)) + # Calculate horizontal offset for this bullet (symmetrical: left=-ve, right=+ve) + var bullet_horizontal_offset: float = index_from_center * weapon_data.horizontal_offset - # Calculate angle for this bullet (only when projectiles >= 3) - var bullet_angle: float = 0.0 - if total_projectiles >= 3: - bullet_angle = (index_from_center / center_index) * (weapon_data.spread_angle / 2.0) + # Calculate vertical offset from center point (symmetrical vertical spread) + var distance_from_center: float = abs(index_from_center) + var vertical_offset: float = (distance_from_center * weapon_data.origin * -1) / 2 - # Set timing properties on the bullet - bullet.time_offset = time_offset - bullet.fire_time = current_time + time_offset - bullet.angle = bullet_angle + # Final position combines symmetrical horizontal spread with symmetrical vertical spacing + bullet.position = player.position + Vector2(bullet_horizontal_offset, weapon_data.origin + (vertical_offset + weapon_data.origin - total_projectiles)) - # Set the bullet data - bullet.set_weapon_data(weapon_data.bullet_scene, weapon_data) + # Calculate angle for this bullet (only when projectiles >= 3) + var bullet_angle: float = 0.0 + if total_projectiles >= 3: + bullet_angle = (index_from_center / center_index) * (weapon_data.spread_angle / 2.0) - # Offset animation playback per projectile if enabled - if weapon_data.stagger_animation: - bullet.set_animation_offset(index_from_center * weapon_data.stagger_offset) + # Set timing properties on the bullet + bullet.time_offset = time_offset + bullet.fire_time = current_time + time_offset + bullet.angle = bullet_angle - # Reset travel after firing to prevent multiple bursts per tap - player.travel = 0.0 + # Set the bullet data + bullet.set_weapon_data(weapon_data.bullet_scene, weapon_data) + + # Offset animation playback per projectile if enabled + if weapon_data.stagger_animation: + bullet.set_animation_offset(index_from_center * weapon_data.stagger_offset) + + +# Grouped projectile logic (new functionality) +func _shoot_grouped(weapon_data: WeaponShot, current_time: float): + for group: WeaponProjectileGroup in weapon_data.groups.filter(func(g): return g != null): + for b in range(group.bullet_count): + var bullet := weapon_data.bullet_scene.instantiate() as Area2D + get_tree().root.add_child(bullet) + + _fire_grouped_bullet(bullet, group, b, current_time, weapon_data, false) + + # If mirroring is enabled, fire a mirrored copy + if group.mirror: + var mirror_bullet := weapon_data.bullet_scene.instantiate() as Area2D + get_tree().root.add_child(mirror_bullet) + _fire_grouped_bullet(mirror_bullet, group, b, current_time, weapon_data, true) + + +# Fire a single grouped bullet (original or mirrored) +func _fire_grouped_bullet(bullet: Area2D, group: WeaponProjectileGroup, b: int, + current_time: float, weapon_data: WeaponShot, mirror: bool): + # Calculate index relative to this group's center + var center_index: float = (group.bullet_count - 1) / 2.0 + var index_from_center: float = b - center_index + + # Horizontal offset: group offset + within-group spread + # Mirror: negate the horizontal offset contribution + var bullet_horizontal_offset: float = group.horizontal_offset + index_from_center * group.horizontal_spacing + if mirror: + bullet_horizontal_offset = -bullet_horizontal_offset + + # Base angle for the group, plus within-group spread + # Mirror: negate the angle and the spread contribution + var bullet_angle: float = group.angle_offset + if mirror: + bullet_angle = -group.angle_offset + if group.bullet_count >= 3: + var spread_contribution = (index_from_center / center_index) * (group.spread_angle / 2.0) + if mirror: + bullet_angle -= spread_contribution + else: + bullet_angle += spread_contribution + + # Position: apply horizontal offset and vertical origin from weapon data + bullet.position = player.position + Vector2(bullet_horizontal_offset, weapon_data.origin) + + # Timing: group delay + within-group stagger + var time_offset: float = group.group_delay + abs(index_from_center) * group.stagger_offset + + # Set timing properties on the bullet + bullet.time_offset = time_offset + bullet.fire_time = current_time + time_offset + bullet.angle = bullet_angle + + # Set the bullet data + bullet.set_weapon_data(weapon_data.bullet_scene, weapon_data) + + # Offset animation playback per projectile if enabled + if weapon_data.stagger_animation: + bullet.set_animation_offset(index_from_center * weapon_data.stagger_offset) diff --git a/scripts/weapon_projectile_group.gd b/scripts/weapon_projectile_group.gd new file mode 100644 index 0000000..89b511e --- /dev/null +++ b/scripts/weapon_projectile_group.gd @@ -0,0 +1,21 @@ +class_name WeaponProjectileGroup +extends Resource + +@export_category("Group Settings") +@export var bullet_count: int = 3 +# Horizontal distance between bullets in this group +@export var horizontal_spacing: float = 6.5 +# Total spread angle for bullets in this group (in degrees) +@export var spread_angle: float = 0.0 +# Angle of the entire group from the shot origin (positive = right/up, negative = left) +@export var angle_offset: float = 0.0 +# Horizontal offset from the center line (positive = right, negative = left) +@export var horizontal_offset: float = 0.0 +@export_category("Timing") +# Time delay for this group's first bullet (relative to shot start) +@export var group_delay: float = 0.0 +# Stagger delay between bullets within this group +@export var stagger_offset: float = 0.25 +@export_category("Mirroring") +# If true, duplicate this group's bullets mirrored across the ship's vertical axis +@export var mirror: bool = false diff --git a/scripts/weapon_projectile_group.gd.uid b/scripts/weapon_projectile_group.gd.uid new file mode 100644 index 0000000..65a3b0d --- /dev/null +++ b/scripts/weapon_projectile_group.gd.uid @@ -0,0 +1 @@ +uid://d0ios82vubijg diff --git a/scripts/weapon_shot.gd b/scripts/weapon_shot.gd index c4d9bd7..a85e798 100644 --- a/scripts/weapon_shot.gd +++ b/scripts/weapon_shot.gd @@ -25,3 +25,6 @@ extends Resource @export var stagger_animation: bool = false # Rotate projectiles to point along their travel direction (requires >2 projectiles and spread_angle > 0) @export var follow_angle: bool = false + +@export_category("Grouped Projectiles") +@export var groups: Array[WeaponProjectileGroup] = []