Audio (all CC0 — Kenney packs + OpenGameArt, see assets/sounds/SOURCES.md): - Replace every procedural synth WAV with forged sounds (ffmpeg pitch/layer mixes): distinct fire sounds per weapon with 2-3 variations, explosions, footsteps x5, land/jump/dash/vault, knife swing, hit/kill confirms, bullet impacts, reload, flight loops, UI hover/click/confirm/error, match jingles, menu music - AudioManager.stream_for(): AudioStreamRandomizer per sound id — every weapon now gets variation + pitch randomization on each shot - Explosions and bullet impacts play positional audio; landing has its own sound instead of a pitched footstep; ambient wind bed on every map Visuals: - ExplosionVFX: shared cel-shaded burst (white-hot stepped core, ink shockwave ring, star spikes, flat smoke puffs) replaces the orange sphere in both local and remote-replay paths - Comic star muzzle flashes on all weapons; unified cel tracer bolts with ink outlines across hitscan/shotgun/remote paths - Impact decals: hard-stepped ink-splat gradients instead of soft airbrush - Toon shading on first-person view models + arms, third-person weapons, and the procedural humanoid fallback (no hull outlines on FBX weapons — their hard normals tear the inverted hull) - Fix: giant soft "blob" highlight on floors — toon rim/specular disabled on level-geometry materials (pre-existing artifact since the cel commit) - Fix: own third-person weapon rendered into the first-person camera (shadows-only now covers first_person_mode) UI: - UITheme: comic theme on the root window — Bangers display font (OFL), paper panels with thick ink borders + hard drop shadows, papaya accent, themed buttons/inputs/popups; hover/click sounds on all menu buttons - Main menu: tilted comic wordmark, sunset toon diorama, looping menu music - Match HUD: themed scoreboard/killfeed/kill counter Viewports: - 4x MSAA project-wide + viewmodel/diorama viewports (crisp ink lines) - Viewmodel camera near plane 0.01; third-person camera FOV syncs settings - debug/visual_capture.gd: dev tool to screenshot menu + level for review Verified: 11/11 movement tests, spawn smoke test 0 failures, before/after screenshot comparison of menu and level. Co-Authored-By: Claude Fable 5 <[email protected]>
99 lines
2.7 KiB
GDScript
99 lines
2.7 KiB
GDScript
extends BaseHitscanWeapon
|
|
class_name DMR
|
|
|
|
var is_ads: bool = false
|
|
var default_fov: float = 90.0
|
|
var ads_fov: float = 40.0
|
|
|
|
func _init() -> void:
|
|
weapon_name = "DMR"
|
|
fire_rate = 0.3 # Cooldown to prevent autoclicker spam
|
|
max_ammo = 15
|
|
reload_time = 2.2
|
|
base_damage = 75.0
|
|
min_damage = 60.0
|
|
falloff_start = 50.0
|
|
max_range = 300.0
|
|
automatic = false
|
|
spread_angle = 0.002 # Extremely accurate
|
|
|
|
func _ready() -> void:
|
|
super._ready()
|
|
if camera:
|
|
default_fov = camera.fov
|
|
|
|
func _build_model() -> void:
|
|
position = Vector3(0.3, -0.3, -0.49)
|
|
|
|
var model_scene = load("res://assets/weapons/dmr/source/M14 .blend")
|
|
if model_scene:
|
|
var model = model_scene.instantiate()
|
|
model_root.add_child(model)
|
|
model.scale = Vector3(0.1875, 0.1875, 0.1875)
|
|
model.rotation_degrees.y = 90
|
|
for light in model.find_children("*", "Light3D", true, false):
|
|
light.queue_free()
|
|
# Muzzle Flash
|
|
muzzle_flash = OmniLight3D.new()
|
|
muzzle_flash.light_color = Color(1.0, 0.8, 0.4)
|
|
muzzle_flash.light_energy = 0.0
|
|
muzzle_flash.omni_range = 6.0
|
|
muzzle_flash.position = Vector3(0, 0.03, -0.6)
|
|
model_root.add_child(muzzle_flash)
|
|
|
|
# Audio
|
|
fire_sound = AudioStreamPlayer3D.new()
|
|
fire_sound.bus = "SFX"
|
|
fire_sound.stream = AudioManager.stream_for("dmr_fire", "res://assets/sounds/dmr_fire.wav")
|
|
fire_sound.position = muzzle_flash.position
|
|
fire_sound.volume_db = -3.0
|
|
model_root.add_child(fire_sound)
|
|
|
|
reload_sound = AudioStreamPlayer3D.new()
|
|
reload_sound.bus = "SFX"
|
|
reload_sound.stream = AudioManager.stream_for("shotgun_reload", "res://assets/sounds/shotgun_reload.wav")
|
|
model_root.add_child(reload_sound)
|
|
|
|
func _process(delta: float) -> void:
|
|
super._process(delta)
|
|
|
|
if not visible:
|
|
return
|
|
|
|
|
|
if camera:
|
|
var target_fov = ads_fov if is_ads else -1.0
|
|
var rig = camera.get_parent()
|
|
if rig and rig.has_method("set_weapon_fov"):
|
|
rig.set_weapon_fov(target_fov)
|
|
|
|
# Move model to center when ADS
|
|
var target_pos = Vector3(0.0, -0.2, -0.5) if is_ads else Vector3(0.3, -0.3, -0.7)
|
|
position = position.lerp(target_pos, 15.0 * delta)
|
|
|
|
# Adjust sensitivity if player has a way to modify it (we can modify the camera rig later)
|
|
# For now, FOV alone gives the zoom effect.
|
|
|
|
func _input(event: InputEvent) -> void:
|
|
super._input(event)
|
|
|
|
if Input.get_mouse_mode() != Input.MOUSE_MODE_CAPTURED:
|
|
return
|
|
|
|
if event.is_action_pressed("fire_alt"):
|
|
is_ads = true
|
|
elif event.is_action_released("fire_alt"):
|
|
is_ads = false
|
|
|
|
func _start_reload() -> void:
|
|
super._start_reload()
|
|
is_ads = false # Drop out of ADS on reload
|
|
|
|
func unequip() -> void:
|
|
is_ads = false
|
|
if camera:
|
|
var rig = camera.get_parent()
|
|
if rig and rig.has_method("set_weapon_fov"):
|
|
rig.set_weapon_fov(-1.0)
|
|
position = Vector3(0.3, -0.3, -0.49)
|