blank weapon fire system

This commit is contained in:
Alexey 2025-07-18 18:41:44 +03:00
commit 16b1d0f701
11 changed files with 92 additions and 51 deletions

View file

@ -20,23 +20,6 @@ tracks/0/keys = {
"values": [null] "values": [null]
} }
[sub_resource type="Animation" id="Animation_8sdfx"]
resource_name = "shoot"
length = 0.30001
step = 0.1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:texture")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.1, 0.2, 0.3),
"transitions": PackedFloat32Array(1, 1, 1, 1),
"update": 1,
"values": [ExtResource("1_yheqn"), ExtResource("9_6fi3a"), ExtResource("10_mjqfp"), ExtResource("11_0d256")]
}
[sub_resource type="Animation" id="Animation_ma1q3"] [sub_resource type="Animation" id="Animation_ma1q3"]
resource_name = "static" resource_name = "static"
length = 0.001 length = 0.001
@ -54,9 +37,43 @@ tracks/0/keys = {
"values": [ExtResource("1_yheqn")] "values": [ExtResource("1_yheqn")]
} }
[sub_resource type="Animation" id="Animation_8sdfx"]
resource_name = "shoot"
length = 0.30001
step = 0.1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:texture")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.1, 0.2),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 1,
"values": [ExtResource("9_6fi3a"), ExtResource("10_mjqfp"), ExtResource("11_0d256")]
}
tracks/1/type = "method"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("../..")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0.2, 0.3),
"transitions": PackedFloat32Array(1, 1),
"values": [{
"args": [],
"method": &"fire_task_finish"
}, {
"args": [],
"method": &"on_fire_animation_end"
}]
}
[resource] [resource]
_data = { _data = {
&"RESET": SubResource("Animation_i1xqq"), &"RESET": SubResource("Animation_i1xqq"),
&"shoot": SubResource("Animation_8sdfx"), &"fire": SubResource("Animation_8sdfx"),
&"static": SubResource("Animation_ma1q3") &"static": SubResource("Animation_ma1q3")
} }

View file

@ -1,6 +1,7 @@
[gd_scene load_steps=4 format=3 uid="uid://dwx5tcatj35gu"] [gd_scene load_steps=5 format=3 uid="uid://dwx5tcatj35gu"]
[ext_resource type="Script" uid="uid://dts8lbivkgsmj" path="res://base/scripts/player/player.gd" id="1_1w3ab"] [ext_resource type="Script" uid="uid://dts8lbivkgsmj" path="res://base/scripts/player/player.gd" id="1_1w3ab"]
[ext_resource type="Texture2D" uid="uid://cfw6p5g680c55" path="res://base/assets/guns/placeholder/shoot1.png" id="2_i1xqq"]
[ext_resource type="PackedScene" uid="uid://bb6ovrbusyxpi" path="res://base/scenes/weapons/weapon_base.tscn" id="2_ma1q3"] [ext_resource type="PackedScene" uid="uid://bb6ovrbusyxpi" path="res://base/scenes/weapons/weapon_base.tscn" id="2_ma1q3"]
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_jjqxs"] [sub_resource type="CapsuleShape3D" id="CapsuleShape3D_jjqxs"]
@ -28,6 +29,7 @@ grow_horizontal = 2
grow_vertical = 2 grow_vertical = 2
size_flags_horizontal = 3 size_flags_horizontal = 3
size_flags_vertical = 3 size_flags_vertical = 3
texture = ExtResource("2_i1xqq")
stretch_mode = 6 stretch_mode = 6
[node name="AnimationPlayer" type="AnimationPlayer" parent="HUD/Weapon"] [node name="AnimationPlayer" type="AnimationPlayer" parent="HUD/Weapon"]

View file

@ -1,13 +1,13 @@
[gd_scene load_steps=6 format=3 uid="uid://bb6ovrbusyxpi"] [gd_scene load_steps=6 format=3 uid="uid://bb6ovrbusyxpi"]
[ext_resource type="Script" uid="uid://bf0q3xe6oavqa" path="res://base/scripts/weapons/weapon_base.gd" id="1_rwatx"] [ext_resource type="Script" uid="uid://bf0q3xe6oavqa" path="res://base/scripts/weapons/weapon_base.gd" id="1_rwatx"]
[ext_resource type="Script" path="res://base/scripts/weapons/fire_mode/single_fire_mode.gd" id="2_bt0tf"] [ext_resource type="Script" uid="uid://ckexgw71dd5jc" path="res://base/scripts/weapons/fire_mode/single_fire_mode.gd" id="2_bt0tf"]
[ext_resource type="Script" uid="uid://bvurg687pt06s" path="res://base/scripts/weapons/barrel.gd" id="2_n0n7m"] [ext_resource type="Script" uid="uid://bvurg687pt06s" path="res://base/scripts/weapons/barrel.gd" id="2_n0n7m"]
[ext_resource type="AnimationLibrary" uid="uid://cw8bt4hqxpk55" path="res://base/assets/guns/placeholder/placeholder.tres" id="2_p83j3"] [ext_resource type="AnimationLibrary" uid="uid://cw8bt4hqxpk55" path="res://base/assets/guns/placeholder/placeholder.tres" id="2_p83j3"]
[sub_resource type="Resource" id="Resource_ij06d"] [sub_resource type="Resource" id="Resource_ij06d"]
script = ExtResource("2_bt0tf") script = ExtResource("2_bt0tf")
fire_delay = 0.3 fire_delay = 0.5
metadata/_custom_type_script = "uid://ckexgw71dd5jc" metadata/_custom_type_script = "uid://ckexgw71dd5jc"
[node name="Weapon" type="Node3D"] [node name="Weapon" type="Node3D"]

View file

@ -7,7 +7,7 @@ class_name CommandQueue
enum Command { enum Command {
NONE, NONE,
TAKE_WEAPON, TAKE_WEAPON,
SHOOT, FIRE,
RELOAD, RELOAD,
HOLSTER_WEAPON, HOLSTER_WEAPON,
TAKE_ZAZA, TAKE_ZAZA,

View file

@ -11,6 +11,9 @@ var queue: CommandQueue = CommandQueue.new()
@onready var weapon_player: AnimationPlayer = $"HUD/Weapon/AnimationPlayer" @onready var weapon_player: AnimationPlayer = $"HUD/Weapon/AnimationPlayer"
@onready var weapons: Node3D = $"WeaponContainer" @onready var weapons: Node3D = $"WeaponContainer"
const DEFAULT_SIDES: Array[CommandQueue.Side] = [CommandQueue.Side.LEFT, CommandQueue.Side.RIGHT]
const ONEHANDED_FIRE_COMMAND: Array[CommandQueue.Command] = [CommandQueue.Command.NONE, CommandQueue.Command.FIRE]
var current_weapon: Weapon var current_weapon: Weapon
func _ready() -> void: func _ready() -> void:
@ -18,6 +21,7 @@ func _ready() -> void:
queue.command_popped.connect(on_queue_command_popped) queue.command_popped.connect(on_queue_command_popped)
current_weapon = weapons.get_child(0) as Weapon current_weapon = weapons.get_child(0) as Weapon
current_weapon.fired.connect(on_weapon_fired)
weapon_player.add_animation_library("current", current_weapon.animation_library) weapon_player.add_animation_library("current", current_weapon.animation_library)
weapon_player.play("current/static") weapon_player.play("current/static")
@ -25,16 +29,13 @@ func _ready() -> void:
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
func _process(_delta: float) -> void: func _process(_delta: float) -> void:
if Input.is_action_pressed("shoot") \ if queue.current_command(CommandQueue.Side.RIGHT) \
and queue.current_command(CommandQueue.Side.RIGHT) \
== CommandQueue.DEFAULT_COMMAND: == CommandQueue.DEFAULT_COMMAND:
queue.push([ var fire_action = Input.is_action_just_pressed('shoot') if \
CommandQueue.Command.NONE, current_weapon.fire_mode is SingleFireMode else \
CommandQueue.Command.SHOOT Input.is_action_pressed('shoot')
], [ if fire_action:
CommandQueue.Side.LEFT, queue.push(ONEHANDED_FIRE_COMMAND, DEFAULT_SIDES)
CommandQueue.Side.RIGHT
])
for side in CommandQueue.Side.values(): for side in CommandQueue.Side.values():
var command = queue.current_command(side) var command = queue.current_command(side)
@ -74,7 +75,7 @@ func on_queue_command_pushed(sides, commands):
CommandQueue.Side.RIGHT: CommandQueue.Side.RIGHT:
handle_new_right_command(commands[i]) handle_new_right_command(commands[i])
func shoot_animation_ended(): func fire_task_finish():
queue.pop() queue.pop()
func on_queue_command_popped(commands): func on_queue_command_popped(commands):
@ -85,6 +86,12 @@ func on_queue_command_popped(commands):
CommandQueue.Side.RIGHT: CommandQueue.Side.RIGHT:
handle_ended_right_command(commands[i]) handle_ended_right_command(commands[i])
func on_weapon_fired():
weapon_player.play("current/fire")
func on_fire_animation_end():
weapon_player.play("current/static")
func handle_new_left_command(command: CommandQueue.Command): func handle_new_left_command(command: CommandQueue.Command):
match command: match command:
CommandQueue.Command.NONE: CommandQueue.Command.NONE:
@ -94,7 +101,7 @@ func handle_new_left_command(command: CommandQueue.Command):
func handle_new_right_command(command: CommandQueue.Command): func handle_new_right_command(command: CommandQueue.Command):
match command: match command:
CommandQueue.Command.NONE | CommandQueue.Command.SHOOT: CommandQueue.Command.NONE | CommandQueue.Command.FIRE:
pass pass
_: _:
print('New command %s is not implemented for right hand.' % command) print('New command %s is not implemented for right hand.' % command)
@ -108,10 +115,8 @@ func handle_ended_left_command(command: CommandQueue.Command):
func handle_ended_right_command(command: CommandQueue.Command): func handle_ended_right_command(command: CommandQueue.Command):
match command: match command:
CommandQueue.Command.NONE: CommandQueue.Command.NONE | CommandQueue.Command.FIRE:
pass pass
CommandQueue.Command.SHOOT:
weapon_player.play('current/static')
_: _:
print('Ended command %s is not implemented for right hand.' % command) print('Ended command %s is not implemented for right hand.' % command)
@ -126,5 +131,7 @@ func handle_current_right_command(command: CommandQueue.Command):
match command: match command:
CommandQueue.Command.NONE: CommandQueue.Command.NONE:
pass pass
CommandQueue.Command.FIRE:
current_weapon.request_fire()
_: _:
print('Current command %s is not implemented for right hand.' % command) print('Current command %s is not implemented for right hand.' % command)

View file

@ -2,5 +2,10 @@ extends Node3D
class_name Barrel class_name Barrel
signal fired()
func can_fire() -> bool: func can_fire() -> bool:
return true return true
func fire() -> void:
fired.emit()

View file

@ -14,15 +14,15 @@ var cooldown : bool = false
## Reference to cooldown scene timer ## Reference to cooldown scene timer
var cooldown_timer : SceneTreeTimer = null var cooldown_timer : SceneTreeTimer = null
func _on_fire_begin(_tree : SceneTree) -> void: func _on_fire_begin() -> void:
cooldown = false cooldown = false
check_unfinished_timer(cooldown_timer,on_cooldown_timeout) check_unfinished_timer(cooldown_timer,on_cooldown_timeout)
func _process(tree : SceneTree) -> void: func _process() -> void:
if can_fire() : if can_fire() :
return return
if _fire(): if _fire():
on_fire(tree) on_fire()
## Invoked when cooldown has ended ## Invoked when cooldown has ended
@ -42,7 +42,7 @@ func can_fire() -> bool:
return cooldown return cooldown
## Invoked when fired ## Invoked when fired
func on_fire(tree : SceneTree) -> void: func on_fire() -> void:
cooldown = true cooldown = true
cooldown_timer = tree.create_timer(fire_delay) cooldown_timer = tree.create_timer(fire_delay)
cooldown_timer.timeout.connect(on_cooldown_timeout) cooldown_timer.timeout.connect(on_cooldown_timeout)

View file

@ -5,7 +5,7 @@ class_name BaseFireMode
## Assigned barrel to shoot out of ## Assigned barrel to shoot out of
var barrel : Barrel var barrel : Barrel
var tree : Tree var tree : SceneTree
func _init() -> void: func _init() -> void:
resource_local_to_scene = true resource_local_to_scene = true
@ -14,6 +14,7 @@ func _init() -> void:
## Returns [color=green]true[/color] if barrel can shoot,[br] ## Returns [color=green]true[/color] if barrel can shoot,[br]
## Returns [color=red]false[/color] if barrel cannot shoot ## Returns [color=red]false[/color] if barrel cannot shoot
func _fire() -> bool: func _fire() -> bool:
barrel.fire()
return true return true

View file

@ -20,15 +20,15 @@ var reloading : bool = false
## Reference to reload scene timer ## Reference to reload scene timer
var reload_timer : SceneTreeTimer = null var reload_timer : SceneTreeTimer = null
func _on_fire_begin(_tree : SceneTree) -> void: func _on_fire_begin() -> void:
super._on_fire_begin(_tree) super._on_fire_begin()
current_amount = 0 current_amount = 0
reloading = false reloading = false
check_unfinished_timer(reload_timer,on_reload_timeout) check_unfinished_timer(reload_timer,on_reload_timeout)
func on_fire(tree : SceneTree) -> void: func on_fire() -> void:
super.on_fire(tree) super.on_fire()
current_amount += 1 current_amount += 1
if current_amount >= burst_amount: if current_amount >= burst_amount:
reloading = true reloading = true

View file

@ -13,7 +13,7 @@ class_name SingleFireMode
var cooldown : bool = false var cooldown : bool = false
func _on_fire_begin(tree) -> void: func _on_fire_begin() -> void:
if cooldown: if cooldown:
return return

View file

@ -2,6 +2,8 @@ extends Node3D
class_name Weapon class_name Weapon
signal fired()
@onready var barrel = $"Barrel" @onready var barrel = $"Barrel"
@export var uses_hands: Array[CommandQueue.Side] @export var uses_hands: Array[CommandQueue.Side]
@ -10,6 +12,7 @@ var ammo: int = max_ammo
@export var ammo_consumption: int = 1 @export var ammo_consumption: int = 1
@export var fire_mode: BaseFireMode @export var fire_mode: BaseFireMode
## Weapon animation library. Should contain "static", "fire", "reload" animations ## Weapon animation library. Should contain "static", "fire", "reload" animations
@export var animation_library: AnimationLibrary @export var animation_library: AnimationLibrary
@ -17,17 +20,23 @@ var is_firing: bool = false
func _ready() -> void: func _ready() -> void:
fire_mode.barrel = barrel fire_mode.barrel = barrel
fire_mode.tree = get_tree()
barrel.fired.connect(on_barrel_fired)
## Begin to fire ## Begin to fire
func request_fire() -> void: func request_fire() -> void:
fire_mode.on_fire_begin(get_tree()) fire_mode._on_fire_begin()
is_firing = true
func _process(_dt) -> void: func _process(_dt) -> void:
if is_firing: if is_firing:
fire_mode._process(get_tree()) fire_mode._process()
## End fire ## End fire
func end_fire() -> void: func end_fire() -> void:
fire_mode.on_fire_end(get_tree()) if is_firing:
is_firing = false fire_mode._on_fire_end()
is_firing = false
func on_barrel_fired() -> void:
is_firing = true
fired.emit()