Compare commits

..
2 Commits
28 changed files with 259 additions and 14 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+32
View File
@@ -433,4 +433,36 @@ for i in range(int(sample_rate * mortar_duration)):
mortar_samples.append(thunk + ring)
write_wav('assets/sounds/mortar_fire.wav', mortar_samples)
# 21. Rocket Flight (Deep continuous looping whoosh/rumble)
flight_duration = 1.0 # 1 second loop
flight_samples = []
prev_f = 0.0
for i in range(int(sample_rate * flight_duration)):
t = i / sample_rate
noise = random.uniform(-1.0, 1.0)
alpha = 0.15 # Higher cutoff for more whoosh
filtered = prev_f + alpha * (noise - prev_f)
prev_f = filtered
rumble = math.sin(t * 70.0 * 2 * math.pi) * 1.5
raw = (filtered * 2.5 + rumble)
# Heavy soft clipping to make it sound intensely loud
flight_samples.append(math.tanh(raw * 2.0))
write_wav('assets/sounds/rocket_flight.wav', flight_samples)
# 22. Swarm Flight (Higher pitched continuous hiss)
swarm_flight_samples = []
prev_sf = 0.0
for i in range(int(sample_rate * flight_duration)):
t = i / sample_rate
noise = random.uniform(-1.0, 1.0)
alpha = 0.4 # Higher cutoff for hiss
filtered = prev_sf + alpha * (noise - prev_sf)
prev_sf = filtered
# Aggressive screaming tone
whine = math.sin(t * 800.0 * 2 * math.pi) * 1.5
raw = (filtered * 2.0 + whine)
# Heavy soft clipping
swarm_flight_samples.append(math.tanh(raw * 2.0))
write_wav('assets/sounds/swarm_flight.wav', swarm_flight_samples)
print("Generated all sounds!")
+1 -1
View File
@@ -77,7 +77,7 @@ class_name MovementParams
@export var rocket_jump_falloff: float = 1.5
# ── Shotgun Jump ──────────────────────────────────────────────────────────────
@export var shotgun_jump_impulse: float = 10.0
@export var shotgun_jump_impulse: float = 12.0
# ── Double Jump ───────────────────────────────────────────────────────────────
@export var double_jump_velocity: float = 8.0
+1 -1
View File
@@ -14,7 +14,7 @@ func _physics_process(delta: float) -> void:
fuse_time -= delta
if fuse_time <= 0.0:
_explode(global_position)
queue_free()
destroy()
return
# Apply gravity drop if any
+132 -5
View File
@@ -1,16 +1,141 @@
extends Projectile
class_name ExplosiveProjectile
var explosion_radius: float = 5.0
var explosion_radius: float = 2.5
var explosion_knockback: float = 20.0
var can_self_damage: bool = false
var falloff_curve: float = 1.0 # 1.0 is linear, 2.0 is quadratic (steep drop)
var flight_sound: AudioStreamPlayer3D
var smoke_sys: GPUParticles3D
var jet_sys: GPUParticles3D
static var _smoke_tex: GradientTexture2D
static func get_smoke_texture() -> GradientTexture2D:
if _smoke_tex: return _smoke_tex
_smoke_tex = GradientTexture2D.new()
_smoke_tex.fill = GradientTexture2D.FILL_RADIAL
_smoke_tex.fill_from = Vector2(0.5, 0.5)
_smoke_tex.fill_to = Vector2(1.0, 1.0)
var g = Gradient.new()
g.add_point(0.0, Color(1, 1, 1, 1))
g.add_point(0.5, Color(1, 1, 1, 0.5))
g.add_point(1.0, Color(1, 1, 1, 0))
_smoke_tex.gradient = g
_smoke_tex.width = 64
_smoke_tex.height = 64
return _smoke_tex
func _ready() -> void:
super._ready()
_setup_effects()
func destroy() -> void:
if is_instance_valid(smoke_sys):
smoke_sys.emitting = false
var p = smoke_sys.get_parent()
if p:
var trans = smoke_sys.global_transform
p.remove_child(smoke_sys)
get_tree().current_scene.add_child(smoke_sys)
smoke_sys.global_transform = trans
var timer = smoke_sys.get_tree().create_timer(smoke_sys.lifetime)
timer.timeout.connect(smoke_sys.queue_free)
if is_instance_valid(jet_sys):
jet_sys.emitting = false
var p = jet_sys.get_parent()
if p:
var trans = jet_sys.global_transform
p.remove_child(jet_sys)
get_tree().current_scene.add_child(jet_sys)
jet_sys.global_transform = trans
var timer = jet_sys.get_tree().create_timer(jet_sys.lifetime)
timer.timeout.connect(jet_sys.queue_free)
super.destroy()
func _setup_effects() -> void:
# Audio
flight_sound = AudioStreamPlayer3D.new()
flight_sound.stream = load("res://assets/sounds/rocket_flight.wav")
flight_sound.autoplay = true
if flight_sound.stream is AudioStreamWAV:
flight_sound.stream.loop_mode = AudioStreamWAV.LOOP_FORWARD
flight_sound.unit_size = 50.0
flight_sound.max_db = 6.0
flight_sound.volume_db = 6.0
add_child(flight_sound)
flight_sound.play()
# Jet Fire Particles
jet_sys = GPUParticles3D.new()
var jet_mat = ParticleProcessMaterial.new()
jet_mat.direction = Vector3(0, 0, 1) # Backwards (since model looks at -Z)
jet_mat.spread = 10.0
jet_mat.initial_velocity_min = 1.0
jet_mat.initial_velocity_max = 2.0
jet_mat.gravity = Vector3.ZERO
var jet_mesh = BoxMesh.new()
jet_mesh.size = Vector3(0.05, 0.05, 0.05)
var mat = StandardMaterial3D.new()
mat.albedo_color = Color(1.0, 0.6, 0.0)
mat.emission_enabled = true
mat.emission = Color(1.0, 0.5, 0.0)
jet_mesh.material = mat
jet_sys.draw_pass_1 = jet_mesh
jet_sys.process_material = jet_mat
jet_sys.amount = 16
jet_sys.lifetime = 0.2
jet_sys.position = Vector3(0, 0, 0.1)
add_child(jet_sys)
# Smoke Trail
smoke_sys = GPUParticles3D.new()
var smoke_mat = ParticleProcessMaterial.new()
smoke_mat.direction = Vector3(0, 0, 1)
smoke_mat.spread = 5.0
smoke_mat.initial_velocity_min = 0.0
smoke_mat.initial_velocity_max = 0.5
smoke_mat.gravity = Vector3(0, 0.5, 0)
var grad = Gradient.new()
grad.add_point(0.0, Color(0.5, 0.5, 0.5, 0.8))
grad.add_point(1.0, Color(0.8, 0.8, 0.8, 0.0))
var grad_tex = GradientTexture1D.new()
grad_tex.gradient = grad
smoke_mat.color_ramp = grad_tex
var curve = Curve.new()
curve.add_point(Vector2(0.0, 1.0))
curve.add_point(Vector2(1.0, 3.0))
var curve_tex = CurveTexture.new()
curve_tex.curve = curve
smoke_mat.scale_curve = curve_tex
var smoke_mesh = QuadMesh.new()
smoke_mesh.size = Vector2(0.2, 0.2)
var s_mat = StandardMaterial3D.new()
s_mat.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA
s_mat.vertex_color_use_as_albedo = true
s_mat.albedo_texture = get_smoke_texture()
s_mat.billboard_mode = BaseMaterial3D.BILLBOARD_PARTICLES
s_mat.billboard_keep_scale = true
smoke_mesh.material = s_mat
smoke_sys.draw_pass_1 = smoke_mesh
smoke_sys.process_material = smoke_mat
smoke_sys.amount = 32
smoke_sys.lifetime = 1.5
smoke_sys.position = Vector3(0, 0, 0.15)
add_child(smoke_sys)
func _on_hit(result: Dictionary) -> void:
if not result.collider.has_method("take_damage"):
ImpactSpawner.spawn(get_tree(), "crater", result.position, result.normal, explosion_radius * 1.5)
_explode(result.position)
queue_free()
destroy()
func _explode(pos: Vector3) -> void:
var space_state = get_world_3d().direct_space_state
@@ -49,10 +174,12 @@ func _explode(pos: Vector3) -> void:
# Normalised distance (0 = epicenter, 1 = edge)
var ndist = dist / explosion_radius
var intensity = clampf(1.0 - pow(ndist, falloff_curve), 0.0, 1.0)
var falloff = clampf(pow(ndist, falloff_curve), 0.0, 1.0)
var damage_intensity = lerpf(1.0, 0.33, falloff)
var knockback_intensity = 1.0 - falloff
var final_damage = damage * intensity
var final_knockback = explosion_knockback * intensity
var final_damage = damage * damage_intensity
var final_knockback = explosion_knockback * knockback_intensity
# Knockback direction: from explosion pos to target
var dir = (target_pos - pos).normalized()
+83
View File
@@ -8,6 +8,88 @@ var initial_aim_dir: Vector3 = Vector3.ZERO
var cruise_speed: float = 60.0
var ignition_timer: float = 0.5
var ignited: bool = false
var effects_started: bool = false
func _setup_effects() -> void:
pass # Wait until ignited
func _start_homing_effects() -> void:
if effects_started: return
effects_started = true
# Audio
flight_sound = AudioStreamPlayer3D.new()
flight_sound.stream = load("res://assets/sounds/swarm_flight.wav")
flight_sound.autoplay = true
if flight_sound.stream is AudioStreamWAV:
flight_sound.stream.loop_mode = AudioStreamWAV.LOOP_FORWARD
flight_sound.unit_size = 50.0
flight_sound.max_db = 6.0
flight_sound.volume_db = 6.0
add_child(flight_sound)
flight_sound.play()
# Jet Fire Particles
jet_sys = GPUParticles3D.new()
var jet_mat = ParticleProcessMaterial.new()
jet_mat.direction = Vector3(0, 0, 1)
jet_mat.spread = 10.0
jet_mat.initial_velocity_min = 0.5
jet_mat.initial_velocity_max = 1.0
jet_mat.gravity = Vector3.ZERO
var jet_mesh = BoxMesh.new()
jet_mesh.size = Vector3(0.02, 0.02, 0.02)
var mat = StandardMaterial3D.new()
mat.albedo_color = Color(1.0, 0.6, 0.0)
mat.emission_enabled = true
mat.emission = Color(1.0, 0.5, 0.0)
jet_mesh.material = mat
jet_sys.draw_pass_1 = jet_mesh
jet_sys.process_material = jet_mat
jet_sys.amount = 16
jet_sys.lifetime = 0.15
jet_sys.position = Vector3(0, 0, 0.05)
add_child(jet_sys)
# Smoke Trail
smoke_sys = GPUParticles3D.new()
var smoke_mat = ParticleProcessMaterial.new()
smoke_mat.direction = Vector3(0, 0, 1)
smoke_mat.spread = 5.0
smoke_mat.initial_velocity_min = 0.0
smoke_mat.initial_velocity_max = 0.2
smoke_mat.gravity = Vector3(0, 0.5, 0)
var grad = Gradient.new()
grad.add_point(0.0, Color(0.5, 0.5, 0.5, 0.8))
grad.add_point(1.0, Color(0.8, 0.8, 0.8, 0.0))
var grad_tex = GradientTexture1D.new()
grad_tex.gradient = grad
smoke_mat.color_ramp = grad_tex
var curve = Curve.new()
curve.add_point(Vector2(0.0, 1.0))
curve.add_point(Vector2(1.0, 3.0))
var curve_tex = CurveTexture.new()
curve_tex.curve = curve
smoke_mat.scale_curve = curve_tex
var smoke_mesh = QuadMesh.new()
smoke_mesh.size = Vector2(0.08, 0.08)
var s_mat = StandardMaterial3D.new()
s_mat.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA
s_mat.vertex_color_use_as_albedo = true
s_mat.albedo_texture = ExplosiveProjectile.get_smoke_texture()
s_mat.billboard_mode = BaseMaterial3D.BILLBOARD_PARTICLES
s_mat.billboard_keep_scale = true
smoke_mesh.material = s_mat
smoke_sys.draw_pass_1 = smoke_mesh
smoke_sys.process_material = smoke_mat
smoke_sys.amount = 32
smoke_sys.lifetime = 1.0
smoke_sys.position = Vector3(0, 0, 0.05)
add_child(smoke_sys)
func _physics_process(delta: float) -> void:
if not ignited:
@@ -15,6 +97,7 @@ func _physics_process(delta: float) -> void:
if ignition_timer <= 0.0:
ignited = true
drop_gravity = 0.0
_start_homing_effects()
if ignited and is_instance_valid(weapon_source):
var target_dir: Vector3 = initial_aim_dir
+1 -1
View File
@@ -76,7 +76,7 @@ func _spawn_custom_projectile(origin: Vector3, fire_dir: Vector3) -> void:
proj.bounciness = 0.4 # Heavy, loses momentum on bounce
# Explosive stats
proj.explosion_radius = 12.0 # Very large AoE
proj.explosion_radius = 10.0 # Very large AoE
proj.explosion_knockback = 60.0 # Massive knockback
proj.falloff_curve = 2.0 # Steep dropoff: "Should be an instant kill in closest 50%"
# (0-50% = dist<6. 6/12 = 0.5. 1.0 - 0.5^2 = 0.75 multiplier. 200 * 0.75 = 150 damage -> 1 shot kill)
+5 -2
View File
@@ -21,7 +21,7 @@ func _ready() -> void:
_previous_position = global_position
# Automatically destroy after 5 seconds to prevent leaks
var t = get_tree().create_timer(5.0)
t.timeout.connect(queue_free)
t.timeout.connect(destroy)
func _physics_process(delta: float) -> void:
# Apply gravity drop if any
@@ -33,7 +33,7 @@ func _physics_process(delta: float) -> void:
distance_traveled += movement.length()
if distance_traveled > max_range:
queue_free()
destroy()
return
_check_collision()
@@ -63,4 +63,7 @@ func _on_hit(result: Dictionary) -> void:
var size = 0.4 if impact_type == "plasma" else 0.15
ImpactSpawner.spawn(get_tree(), impact_type, result.position, result.normal, size)
destroy()
func destroy() -> void:
queue_free()
+1 -1
View File
@@ -98,7 +98,7 @@ func _spawn_custom_projectile(origin: Vector3, fire_dir: Vector3) -> void:
proj.owner_player = player
# Explosive stats
proj.explosion_radius = 8.0 # Moderate AoE
proj.explosion_radius = 4.0 # Moderate AoE
proj.explosion_knockback = 45.0 # Strong knockback!
proj.can_self_damage = false # As requested
+3 -3
View File
@@ -109,7 +109,7 @@ func _fire() -> void:
var tween = create_tween()
tween.tween_property(muzzle_flash, "light_energy", 0.0, 0.1)
var origin = camera.global_position + camera.global_transform.basis * Vector3(0.4, -0.2, -0.6)
var _origin = camera.global_position + camera.global_transform.basis * Vector3(0.4, -0.2, -0.6)
var base_dir = -camera.global_transform.basis.z
_current_aim_dir = base_dir
@@ -162,7 +162,7 @@ func _spawn_custom_projectile(origin: Vector3, fire_dir: Vector3) -> void:
# Logic
proj.weapon_source = self
proj.turn_speed = 4.0 # Slower turn radius so they sweep nicely
proj.turn_speed = 6.5 # Slower turn radius so they sweep nicely
proj.position = origin # Start at origin to spread outward around camera
proj.logical_source = origin
@@ -184,7 +184,7 @@ func _spawn_custom_projectile(origin: Vector3, fire_dir: Vector3) -> void:
proj.owner_player = player
# Explosive stats
proj.explosion_radius = 3.0 # Tiny AoE effect
proj.explosion_radius = 1.5 # Tiny AoE effect
proj.explosion_knockback = 5.0
proj.can_self_damage = false