feat: add state machine movement classes, double barrel shotgun weapon, and test level builder utility
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
extends Node3D
|
||||
class_name DoubleBarrelShotgun
|
||||
|
||||
@export var reload_time: float = 1.0
|
||||
|
||||
var shells: int = 2
|
||||
var reloading: bool = false
|
||||
var reload_timer: float = 0.0
|
||||
|
||||
var player: CharacterBody3D
|
||||
var camera: Camera3D
|
||||
|
||||
func _ready() -> void:
|
||||
set_process_input(true)
|
||||
set_process(true)
|
||||
_build_model()
|
||||
|
||||
func _build_model() -> void:
|
||||
# Simple FPS weapon placement (bottom right)
|
||||
position = Vector3(0.3, -0.3, -0.6)
|
||||
|
||||
# Stock
|
||||
var stock = MeshInstance3D.new()
|
||||
var stock_mesh = BoxMesh.new()
|
||||
stock_mesh.size = Vector3(0.1, 0.1, 0.4)
|
||||
var stock_mat = StandardMaterial3D.new()
|
||||
stock_mat.albedo_color = Color(0.4, 0.2, 0.1) # Brown wood
|
||||
stock_mesh.material = stock_mat
|
||||
stock.mesh = stock_mesh
|
||||
stock.position = Vector3(0, 0, 0.2)
|
||||
add_child(stock)
|
||||
|
||||
# Left Barrel
|
||||
var barrel_l = MeshInstance3D.new()
|
||||
var barrel_mesh = CylinderMesh.new()
|
||||
barrel_mesh.top_radius = 0.03
|
||||
barrel_mesh.bottom_radius = 0.03
|
||||
barrel_mesh.height = 0.6
|
||||
var barrel_mat = StandardMaterial3D.new()
|
||||
barrel_mat.albedo_color = Color(0.2, 0.2, 0.2) # Dark grey metal
|
||||
barrel_mat.metallic = 0.8
|
||||
barrel_mat.roughness = 0.4
|
||||
barrel_mesh.material = barrel_mat
|
||||
barrel_l.mesh = barrel_mesh
|
||||
barrel_l.rotation.x = deg_to_rad(90)
|
||||
barrel_l.position = Vector3(-0.04, 0.03, -0.1)
|
||||
add_child(barrel_l)
|
||||
|
||||
# Right Barrel
|
||||
var barrel_r = MeshInstance3D.new()
|
||||
barrel_r.mesh = barrel_mesh
|
||||
barrel_r.rotation.x = deg_to_rad(90)
|
||||
barrel_r.position = Vector3(0.04, 0.03, -0.1)
|
||||
add_child(barrel_r)
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
if reloading:
|
||||
reload_timer -= delta
|
||||
|
||||
# Spin vertically (flip) over the duration of the reload
|
||||
var spin_speed = (PI * 2.0) / reload_time
|
||||
rotation.x += spin_speed * delta
|
||||
|
||||
if reload_timer <= 0.0:
|
||||
shells = 2
|
||||
reloading = false
|
||||
rotation.x = 0.0 # Snap back to perfectly level
|
||||
print("Shotgun Reloaded!")
|
||||
|
||||
func _input(event: InputEvent) -> void:
|
||||
if Input.get_mouse_mode() != Input.MOUSE_MODE_CAPTURED:
|
||||
return
|
||||
|
||||
if event.is_action_pressed("fire"):
|
||||
_try_fire()
|
||||
elif event.is_action_released("fire"):
|
||||
_try_fire()
|
||||
|
||||
if event.is_action_pressed("reload"):
|
||||
if shells < 2 and not reloading:
|
||||
reloading = true
|
||||
reload_timer = reload_time
|
||||
|
||||
func _try_fire() -> void:
|
||||
if shells > 0 and not reloading:
|
||||
shells -= 1
|
||||
print("BANG! Shells left: ", shells)
|
||||
_apply_impulse()
|
||||
|
||||
# Start reload timer if we just shot the LAST shell
|
||||
if shells == 0:
|
||||
reloading = true
|
||||
reload_timer = reload_time
|
||||
|
||||
elif shells == 0 and not reloading:
|
||||
# Empty click, force reload
|
||||
reloading = true
|
||||
reload_timer = reload_time
|
||||
|
||||
func _apply_impulse() -> void:
|
||||
if not player or not camera:
|
||||
return
|
||||
|
||||
# Get the shotgun impulse parameter from the player's movement controller
|
||||
var impulse_strength = 20.0
|
||||
if player.has_method("get") and "params" in player:
|
||||
if player.params and "shotgun_jump_impulse" in player.params:
|
||||
impulse_strength = player.params.shotgun_jump_impulse
|
||||
|
||||
# Impulse direction is opposite to the camera's forward direction
|
||||
var push_dir = camera.global_transform.basis.z.normalized()
|
||||
|
||||
# Apply impulse to player velocity
|
||||
player.velocity += push_dir * impulse_strength
|
||||
|
||||
# Small hack to ensure we aren't considered on floor if we shoot down
|
||||
if push_dir.y > 0:
|
||||
# Just slightly lift the player to break floor contact immediately
|
||||
player.position.y += 0.05
|
||||
Reference in New Issue
Block a user