diff --git a/base/assets/sprites/guns/placeholder/placeholder.tres b/base/assets/sprites/guns/placeholder/placeholder.tres index e165676..c377e3a 100644 --- a/base/assets/sprites/guns/placeholder/placeholder.tres +++ b/base/assets/sprites/guns/placeholder/placeholder.tres @@ -1,9 +1,16 @@ -[gd_resource type="AnimationLibrary" load_steps=8 format=3 uid="uid://cw8bt4hqxpk55"] +[gd_resource type="AnimationLibrary" load_steps=16 format=3 uid="uid://cw8bt4hqxpk55"] [ext_resource type="Texture2D" uid="uid://cf7avgppv4kfk" path="res://base/assets/sprites/guns/placeholder/static.png" id="1_yheqn"] +[ext_resource type="Texture2D" uid="uid://ij02cx0xdckw" path="res://base/assets/sprites/guns/placeholder/reload1.png" id="5_ve5jf"] +[ext_resource type="Texture2D" uid="uid://baptu307a0dw5" path="res://base/assets/sprites/guns/placeholder/reload2.png" id="6_cr4tl"] +[ext_resource type="Texture2D" uid="uid://pb6jybpwasxj" path="res://base/assets/sprites/guns/placeholder/reload3.png" id="7_ripfx"] +[ext_resource type="Texture2D" uid="uid://v2m8ikar64o5" path="res://base/assets/sprites/guns/placeholder/reload4.png" id="8_y82fu"] [ext_resource type="Texture2D" uid="uid://cfw6p5g680c55" path="res://base/assets/sprites/guns/placeholder/shoot1.png" id="9_6fi3a"] +[ext_resource type="Texture2D" uid="uid://b40b8l3yctlax" path="res://base/assets/sprites/guns/placeholder/reload5.png" id="9_7aydm"] [ext_resource type="Texture2D" uid="uid://bwfkjfpk4dwx0" path="res://base/assets/sprites/guns/placeholder/shoot2.png" id="10_mjqfp"] +[ext_resource type="Texture2D" uid="uid://b55h6w4km2c3u" path="res://base/assets/sprites/guns/placeholder/reload6.png" id="10_x8exi"] [ext_resource type="Texture2D" uid="uid://bp1frp3sm8bic" path="res://base/assets/sprites/guns/placeholder/shoot3.png" id="11_0d256"] +[ext_resource type="Texture2D" uid="uid://b4fp0oo8qcino" path="res://base/assets/sprites/guns/placeholder/reload7.png" id="11_bkso5"] [sub_resource type="Animation" id="Animation_i1xqq"] length = 0.001 @@ -47,10 +54,41 @@ tracks/1/keys = { "transitions": PackedFloat32Array(1, 1), "values": [{ "args": [], -"method": &"fire_task_finish" +"method": &"finish_task" }, { "args": [], -"method": &"on_fire_animation_end" +"method": &"reset_animation" +}] +} + +[sub_resource type="Animation" id="Animation_08xoc"] +resource_name = "reload" +length = 1.10001 +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.3, 0.4, 0.7, 0.8, 1), +"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1, 1), +"update": 1, +"values": [ExtResource("5_ve5jf"), ExtResource("6_cr4tl"), ExtResource("7_ripfx"), ExtResource("8_y82fu"), ExtResource("9_7aydm"), ExtResource("10_x8exi"), ExtResource("11_bkso5")] +} +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(1.1), +"transitions": PackedFloat32Array(1), +"values": [{ +"args": [], +"method": &"finish_task" }] } @@ -75,5 +113,6 @@ tracks/0/keys = { _data = { &"RESET": SubResource("Animation_i1xqq"), &"fire": SubResource("Animation_8sdfx"), +&"reload": SubResource("Animation_08xoc"), &"static": SubResource("Animation_ma1q3") } diff --git a/base/scenes/player.tscn b/base/scenes/player.tscn index f2f43b3..d0fcbf3 100644 --- a/base/scenes/player.tscn +++ b/base/scenes/player.tscn @@ -35,6 +35,19 @@ stretch_mode = 6 [node name="AnimationPlayer" type="AnimationPlayer" parent="HUD/Weapon"] autoplay = "static" +[node name="Ammo" type="Label" parent="HUD"] +anchors_preset = 3 +anchor_left = 1.0 +anchor_top = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = -54.0 +offset_top = -23.0 +grow_horizontal = 0 +grow_vertical = 0 +theme_override_font_sizes/font_size = 32 +text = "0/0" + [node name="WeaponContainer" type="Node3D" parent="."] [node name="Weapon" parent="WeaponContainer" instance=ExtResource("2_ma1q3")] diff --git a/base/scripts/player/command_queue.gd b/base/scripts/player/command_queue.gd index 769c997..c2bc34f 100644 --- a/base/scripts/player/command_queue.gd +++ b/base/scripts/player/command_queue.gd @@ -22,7 +22,7 @@ signal command_popped(commands: Array[CommandQueue.Command]) enum Side { LEFT, RIGHT } ## Used anywhere you could get null -const DEFAULT_COMMAND = Command.NONE +const DEFAULT_COMMAND = CommandQueue.Command.NONE ## Dictionary filled with queues for each side var command_queue: Dictionary = {} diff --git a/base/scripts/player/player.gd b/base/scripts/player/player.gd index 4ec242f..0b20b29 100644 --- a/base/scripts/player/player.gd +++ b/base/scripts/player/player.gd @@ -11,8 +11,8 @@ var queue: CommandQueue = CommandQueue.new() @onready var weapon_player: AnimationPlayer = $"HUD/Weapon/AnimationPlayer" @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] +# Placeholder UI +@onready var ammo_label: Label = $"HUD/Ammo" var current_weapon: Weapon @@ -22,30 +22,31 @@ func _ready() -> void: current_weapon = weapons.get_child(0) as Weapon current_weapon.fired.connect(on_weapon_fired) + current_weapon.fire_failed.connect(finish_task) weapon_player.add_animation_library("current", current_weapon.animation_library) weapon_player.play("current/static") Input.mouse_mode = Input.MOUSE_MODE_CAPTURED + update_ammo_label() + func _process(_delta: float) -> void: - var can_queue_fire = true var weapon_sides = current_weapon.uses_hands - for side in weapon_sides: - if queue.current_command(side) != CommandQueue.DEFAULT_COMMAND: - can_queue_fire = false - break - if can_queue_fire: + var weapon_sides_are_free = not queue.sides_are_busy(weapon_sides) + if weapon_sides_are_free: + # Fire logic var fire_action = Input.is_action_just_pressed('shoot') if \ current_weapon.fire_mode is SingleFireMode else \ Input.is_action_pressed('shoot') if fire_action: - var fire_commands = {} - for side in weapon_sides: - fire_commands[side] = CommandQueue.Command.FIRE - queue.push(fire_commands) - + push_copied_command(CommandQueue.Command.FIRE, weapon_sides) + # Reload logic + var reload_action = Input.is_action_just_pressed('reload') + if reload_action: + if not queue.has_command(CommandQueue.Command.RELOAD): + push_copied_command(CommandQueue.Command.RELOAD, weapon_sides) for side in CommandQueue.Side.values(): var command = queue.current_command(side) match side: @@ -84,7 +85,18 @@ func on_queue_command_pushed(commands: Dictionary): CommandQueue.Side.RIGHT: handle_new_right_command(commands[side]) -func fire_task_finish(): +func push_copied_command(command: CommandQueue.Command, sides: Array[CommandQueue.Side]): + var commands = {} + for side in sides: + commands[side] = command + queue.push(commands) + + +func finish_task(): + queue.pop() + +func reset_animation_and_finish_task(): + weapon_player.play("current/static") queue.pop() func on_queue_command_popped(commands): @@ -95,52 +107,49 @@ func on_queue_command_popped(commands): CommandQueue.Side.RIGHT: handle_ended_right_command(commands[i]) +func update_ammo_label(): + ammo_label.text = "{ammo}/{max}".format({ + ammo = current_weapon.ammo, + max = current_weapon.max_ammo + }) + func on_weapon_fired(): weapon_player.play("current/fire") + update_ammo_label() -func on_fire_animation_end(): +func on_weapon_reload(): + weapon_player.play("current/reload") + +func reset_animation(): weapon_player.play("current/static") func handle_new_left_command(command: CommandQueue.Command): match command: - CommandQueue.Command.NONE: - pass - _: - print('New command %s is not implemented for left hand.' % command) + pass func handle_new_right_command(command: CommandQueue.Command): match command: - CommandQueue.Command.NONE | CommandQueue.Command.FIRE: - pass - _: - print('New command %s is not implemented for right hand.' % command) + CommandQueue.Command.RELOAD: + weapon_player.play('current/reload') func handle_ended_left_command(command: CommandQueue.Command): match command: - CommandQueue.Command.NONE: - pass - _: - print('Ended command %s is not implemented for left hand.' % command) + pass func handle_ended_right_command(command: CommandQueue.Command): match command: - CommandQueue.Command.NONE | CommandQueue.Command.FIRE: - pass - _: - print('Ended command %s is not implemented for right hand.' % command) + CommandQueue.Command.FIRE: + current_weapon.end_fire() + CommandQueue.Command.RELOAD: + weapon_player.play('current/static') + current_weapon.reload() + update_ammo_label() func handle_current_left_command(command: CommandQueue.Command): match command: - CommandQueue.Command.NONE: - pass - _: - print('Current command %s is not implemented for left hand.' % command) + pass func handle_current_right_command(command: CommandQueue.Command): match command: - CommandQueue.Command.NONE: - pass CommandQueue.Command.FIRE: current_weapon.request_fire() - _: - print('Current command %s is not implemented for right hand.' % command) diff --git a/base/scripts/weapons/weapon_base.gd b/base/scripts/weapons/weapon_base.gd index e66dded..9fb804f 100644 --- a/base/scripts/weapons/weapon_base.gd +++ b/base/scripts/weapons/weapon_base.gd @@ -3,6 +3,7 @@ extends Node3D class_name Weapon signal fired() +signal fire_failed() @onready var barrel = $"Barrel" @export var uses_hands: Array[CommandQueue.Side] @@ -25,7 +26,10 @@ func _ready() -> void: ## Begin to fire func request_fire() -> void: - fire_mode._on_fire_begin() + if not is_firing and ammo >= ammo_consumption: + fire_mode._on_fire_begin() + elif ammo < ammo_consumption: + fire_failed.emit() func _process(_dt) -> void: if is_firing: @@ -39,4 +43,8 @@ func end_fire() -> void: func on_barrel_fired() -> void: is_firing = true + ammo -= ammo_consumption fired.emit() + +func reload() -> void: + ammo = max_ammo diff --git a/project.godot b/project.godot index b422a26..b704b7d 100644 --- a/project.godot +++ b/project.godot @@ -46,6 +46,11 @@ shoot={ "events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":1,"position":Vector2(189, 15),"global_position":Vector2(198, 63),"factor":1.0,"button_index":1,"canceled":false,"pressed":true,"double_click":false,"script":null) ] } +reload={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":82,"key_label":0,"unicode":114,"location":0,"echo":false,"script":null) +] +} [layer_names]