Weapons no longer reload by spinning the gun 360 (that was the upside-down
flip; nothing detached). New ViewmodelAnim module drives per-style manual-of-
arms sequences on the existing model_root + named arm pivots, with a temporary
magazine/shell/rocket/cell prop that visibly leaves and returns to the gun:
- mag (M4/AK/MP7/DMR): roll gun to present the well, hand rips the mag
down and away, fresh mag up, seat, charge. Gun stays UPRIGHT.
- boltmag (AWP): mag swap + a distinct bolt-cycle rock.
- break (double barrel): hinge open, flick both shells out, drop fresh
shells in, snap shut.
- tube (rocket launcher): tip the tube in, shove a rocket home, shoulder.
- cell (plasma/nail gun): glowing energy cell swapped on the side.
Per-shot viewmodel recoil kick (ViewmodelAnim.apply_kick) scaled by each
weapon's recoil_amplitude, so an AWP slams and an MP7 chatters — replaces the
old flat model behaviour. Weapons expose reload_style; base classes call
play_reload / stop (on unequip) / apply_kick.
Knife: the old barely-visible flick is now a real diagonal slash that
alternates backhand/forehand, whips the blade through screen centre, and
fires the third-person melee arm-swing action (synced to other players).
Hair/materials: specular fully to 0 (even a 2% stepped glint swept as shine
across Taila's hair when the camera moved); rim trimmed to a whisper. Fully
matte cloth/hair now.
Verify: debug/fp_weapon_capture.gd screenshots each weapon's reload phases,
the knife slash, and the fire kick.
Co-Authored-By: Claude Fable 5 <[email protected]>
86 lines
2.3 KiB
GDScript
86 lines
2.3 KiB
GDScript
extends BaseHitscanWeapon
|
|
class_name AWP
|
|
|
|
var default_fov: float = 75.0
|
|
var target_fov: float = 75.0
|
|
var ads_fov: float = 20.0 # Extremely high zoom
|
|
var is_ads: bool = false
|
|
|
|
func _init() -> void:
|
|
weapon_name = "AWP"
|
|
fire_rate = 1.5 # Slow
|
|
max_ammo = 3
|
|
reload_time = 3.0
|
|
base_damage = 200.0 # 1 hit kill
|
|
min_damage = 130.0 # Long falloff
|
|
falloff_start = 100.0
|
|
max_range = 300.0
|
|
automatic = false
|
|
spread_angle = 0.0
|
|
reload_style = "boltmag"
|
|
penetration_count = 1
|
|
penetration_damage_penalty = 0.5
|
|
|
|
func _build_model() -> void:
|
|
position = Vector3(0.3, -0.3, -0.729)
|
|
|
|
var model_scene = load("res://assets/weapons/awp/source/L118a1.fbx")
|
|
if model_scene:
|
|
var model = model_scene.instantiate()
|
|
model_root.add_child(model)
|
|
model.scale = Vector3(0.275, 0.275, 0.275)
|
|
model.rotation_degrees.y = 90
|
|
for light in model.find_children("*", "Light3D", true, false):
|
|
light.queue_free()
|
|
# Audio
|
|
fire_sound = AudioStreamPlayer3D.new()
|
|
fire_sound.bus = "SFX"
|
|
fire_sound.stream = AudioManager.stream_for("awp_fire", "res://assets/sounds/awp_fire.wav")
|
|
fire_sound.volume_db = 0.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 rig = camera.get_parent()
|
|
if rig and rig.has_method("set_weapon_fov"):
|
|
rig.set_weapon_fov(ads_fov if is_ads else -1.0)
|
|
|
|
# Move model slightly based on ADS
|
|
var target_pos = Vector3(0.0, -0.15, -0.608) if is_ads else Vector3(0.3, -0.3, -0.729)
|
|
position = position.lerp(target_pos, 15.0 * delta)
|
|
|
|
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 = not is_ads
|
|
target_fov = ads_fov if is_ads else default_fov
|
|
|
|
func _start_reload() -> void:
|
|
super._start_reload()
|
|
is_ads = false # Drop out of ADS on reload
|
|
target_fov = default_fov
|
|
|
|
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)
|
|
target_fov = default_fov
|
|
position = Vector3(0.3, -0.3, -0.729)
|