Compare commits

..

2 commits

Author SHA1 Message Date
Sara a4e158930d feat: added game.tscn 2025-08-10 16:37:18 +02:00
Sara ed85b557a7 feat: reloading withdraws ammo from inventory 2025-08-10 16:37:02 +02:00
10 changed files with 109 additions and 34 deletions

View file

@ -9,7 +9,6 @@ void WeaponBase::_bind_methods() {
BIND_HPROPERTY(Variant::OBJECT, anim, PROPERTY_HINT_NODE_TYPE, AnimationPlayer::get_class_static());
BIND_PROPERTY(Variant::INT, max_ammo);
BIND_PROPERTY(Variant::INT, loaded_ammo);
ClassDB::bind_method(D_METHOD("reload_full"), &self_type::reload_full);
ClassDB::bind_method(D_METHOD("reload_num", "num"), &self_type::reload_num);
ClassDB::bind_method(D_METHOD("ammo_empty"), &self_type::ammo_empty);
}
@ -62,6 +61,14 @@ PlayerCamera *WeaponBase::get_camera() const {
return this->camera;
}
WeaponInventory *WeaponBase::get_inventory() const {
return this->inventory;
}
void WeaponBase::_set_inventory(WeaponInventory *inventory) {
this->inventory = inventory;
}
void WeaponBase::set_body(PlayerBody *body) {
this->body = body;
}
@ -99,11 +106,6 @@ bool WeaponBase::ammo_empty() const {
return this->loaded_ammo <= 0;
}
void WeaponBase::reload_full() {
// TODO: take difference between loaded and max out of inventory
set_loaded_ammo(this->max_ammo);
}
void WeaponBase::reload_num(int num) {
int const space{ this->max_ammo - this->loaded_ammo };
num = MIN(num, space);

View file

@ -6,6 +6,7 @@ class AnimationPlayer;
class PlayerCamera;
class PlayerBody;
class PlayerInput;
class WeaponInventory;
class WeaponBase : public Node3D {
GDCLASS(WeaponBase, Node3D);
@ -22,6 +23,8 @@ public:
AnimationPlayer *get_anim() const;
PlayerInput *get_input() const;
PlayerCamera *get_camera() const;
WeaponInventory *get_inventory() const;
void _set_inventory(WeaponInventory *inventory);
void set_body(PlayerBody *body);
PlayerBody *get_body() const;
@ -32,8 +35,7 @@ public:
int get_loaded_ammo() const;
bool try_use_ammo(int amount = 1);
bool ammo_empty() const;
void reload_full();
void reload_num(int num);
void reload_num(int num); // !< Increase loaded_ammo by num up to a maximum of max_ammo. NOTE: this will _not_ check if the ammo is available. And assumes that the ammo was already subtracted from the weapon inventory's store.
virtual bool allows_running() const { return false; }
virtual bool allows_jumping() const { return true; }
@ -44,6 +46,7 @@ private:
AnimationPlayer *anim{ nullptr };
PlayerCamera *camera{ nullptr };
PlayerBody *body{ nullptr };
WeaponInventory *inventory{ nullptr };
int loaded_ammo{ 0 };
int max_ammo{ 1 };

View file

@ -4,6 +4,8 @@
void WeaponInventory::_bind_methods() {
BIND_HPROPERTY(Variant::OBJECT, starting_weapon, PROPERTY_HINT_RESOURCE_TYPE, "PackedScene");
BIND_PROPERTY(Variant::INT, pistol_ammo);
BIND_PROPERTY(Variant::INT, rifle_ammo);
}
void WeaponInventory::on_switch_input() {
@ -65,6 +67,7 @@ void WeaponInventory::pickup_weapon(Ref<PackedScene> weapon_scene) {
}
Node *weapon_as_node{ weapon_scene->instantiate() };
if (WeaponBase * weapon{ cast_to<WeaponBase>(weapon_as_node) }) {
weapon->_set_inventory(this);
this->weapon_parent->add_child(weapon_as_node);
// Where to put the new weapon, consider empty slot 1, then empty slot 2, then replace current.
if (this->weapons[0] == nullptr) {
@ -100,3 +103,49 @@ void WeaponInventory::set_starting_weapon(Ref<PackedScene> scene) {
Ref<PackedScene> WeaponInventory::get_starting_weapon() const {
return this->starting_weapon;
}
void WeaponInventory::deposit_pistol_ammo(int amount) {
this->pistol_ammo += amount;
}
void WeaponInventory::set_pistol_ammo(int amount) {
this->rifle_ammo = abs(amount);
}
int WeaponInventory::get_pistol_ammo() const {
return this->pistol_ammo;
}
int WeaponInventory::withdraw_pistol_ammo(int max_amount) {
if (max_amount < this->pistol_ammo) {
this->pistol_ammo -= max_amount;
return max_amount;
} else {
int const val{ this->pistol_ammo };
this->pistol_ammo = 0;
return val;
}
}
void WeaponInventory::deposit_rifle_ammo(int amount) {
this->rifle_ammo += amount;
}
void WeaponInventory::set_rifle_ammo(int amount) {
this->rifle_ammo = abs(amount);
}
int WeaponInventory::get_rifle_ammo() const {
return this->rifle_ammo;
}
int WeaponInventory::withdraw_rifle_ammo(int max_amount) {
if (max_amount < this->rifle_ammo) {
this->rifle_ammo -= max_amount;
return max_amount;
} else {
int const val{ this->rifle_ammo };
this->rifle_ammo = 0;
return val;
}
}

View file

@ -28,6 +28,15 @@ public:
void pickup_demo_pack();
bool try_use_demo_pack();
void deposit_pistol_ammo(int amount);
void set_pistol_ammo(int amount);
int get_pistol_ammo() const;
int withdraw_pistol_ammo(int max_amount);
void deposit_rifle_ammo(int amount);
void set_rifle_ammo(int amount);
int get_rifle_ammo() const;
int withdraw_rifle_ammo(int max_amount);
private:
Node3D *weapon_parent{ nullptr };
unsigned current{ 0 };
@ -36,8 +45,8 @@ private:
Ref<PackedScene> starting_weapon{};
int pistol_ammo{ 60 };
int rifle_ammo{ 0 };
int pistol_ammo{ 16 };
int rifle_ammo{ 30 };
};
#endif // !WEAPON_INVENTORY_H

View file

@ -4,6 +4,7 @@
#include "wave_survival/player_body.h"
#include "wave_survival/player_camera.h"
#include "wave_survival/player_input.h"
#include "wave_survival/weapon_inventory.h"
void Revolver::_bind_methods() {
ClassDB::bind_method(D_METHOD("start_recoil"), &self_type::start_recoil);
@ -51,10 +52,12 @@ void Revolver::stop_running() {
}
void Revolver::start_reloading() {
if (get_inventory()->get_pistol_ammo() > 0) {
this->alt_active = false;
get_anim()->queue("double_to_reload");
get_anim()->queue("reload_one");
}
}
void Revolver::play_equip_anim() {
get_anim()->play("equip", 0.0);
@ -106,8 +109,9 @@ void Revolver::on_reload() {
void Revolver::on_animation_finished(String old_anim) {
if (old_anim == "reload_one" && get_anim()->get_queue().is_empty()) {
reload_num(1);
if (get_loaded_ammo() < get_max_ammo()) {
int const available{ get_inventory()->withdraw_pistol_ammo(1) };
reload_num(available);
if (available > 0 && get_loaded_ammo() < get_max_ammo()) {
get_anim()->queue("reload_one");
} else {
get_anim()->queue("reload_to_double");

View file

@ -4,12 +4,14 @@
#include "wave_survival/macros.h"
#include "wave_survival/player_body.h"
#include "wave_survival/player_input.h"
#include "wave_survival/weapon_inventory.h"
void Rifle::_bind_methods() {
BIND_PROPERTY(Variant::FLOAT, ads_factor);
BIND_PROPERTY(Variant::FLOAT, run_factor);
BIND_PROPERTY(Variant::FLOAT, recoil_force);
BIND_PROPERTY(Variant::FLOAT, recoil_time);
ClassDB::bind_method(D_METHOD("reload_full"), &self_type::reload_full);
}
void Rifle::queue_enter_alt() {
@ -53,7 +55,7 @@ void Rifle::shoot() {
}
void Rifle::start_reload_animation() {
if (!is_animating() && get_loaded_ammo() != get_max_ammo()) {
if (!is_animating() && get_loaded_ammo() < get_max_ammo() && get_inventory()->get_rifle_ammo() > 0) {
if (this->in_alt_mode) {
get_anim()->queue("aim_to_hip");
}
@ -181,6 +183,11 @@ void Rifle::notify_selected() {
play_equip_anim();
}
void Rifle::reload_full() {
int const available = get_inventory()->withdraw_rifle_ammo(get_max_ammo());
reload_num(available);
}
void Rifle::set_ads_factor(float value) {
this->ads_factor = value;
}

View file

@ -30,6 +30,7 @@ public:
virtual bool allows_running() const override;
bool run_requested() const;
virtual void notify_selected() override;
void reload_full();
void set_ads_factor(float value);
float get_ads_factor() const;

View file

@ -1,9 +1,9 @@
[gd_scene load_steps=8 format=3 uid="uid://cc2adfb3sfrep"]
[ext_resource type="PackedScene" uid="uid://snjgu4yp5swd" path="res://objects/player.tscn" id="1_mhgjp"]
[ext_resource type="PackedScene" uid="uid://dllho5nkq2smw" path="res://maps/industrial_area_map.tscn" id="2_41t38"]
[ext_resource type="PackedScene" uid="uid://bt054d3ic71rf" path="res://menus/pause_menu.tscn" id="2_ien74"]
[ext_resource type="Texture2D" uid="uid://bwfkmwx6bd5u4" path="res://icon.svg" id="4_41t38"]
[ext_resource type="PackedScene" uid="uid://snjgu4yp5swd" path="res://objects/player.tscn" id="1_7vohb"]
[ext_resource type="PackedScene" uid="uid://dllho5nkq2smw" path="res://maps/industrial_area_map.tscn" id="2_hph0i"]
[ext_resource type="PackedScene" uid="uid://bt054d3ic71rf" path="res://menus/pause_menu.tscn" id="3_28e7h"]
[ext_resource type="Texture2D" uid="uid://bwfkmwx6bd5u4" path="res://icon.svg" id="4_buohg"]
[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_ien74"]
sky_horizon_color = Color(0.66224277, 0.6717428, 0.6867428, 1)
@ -22,14 +22,6 @@ glow_enabled = true
[node name="Node" type="Node"]
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
environment = SubResource("Environment_uqqn3")
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
transform = Transform3D(-0.8660254, -0.43301278, 0.25, 0, 0.49999997, 0.86602545, -0.50000006, 0.75, -0.43301266, 0, 0, 0)
shadow_enabled = true
directional_shadow_max_distance = 500.0
[node name="SubViewportContainer" type="SubViewportContainer" parent="."]
anchors_preset = 15
anchor_right = 1.0
@ -43,12 +35,20 @@ handle_input_locally = false
size = Vector2i(1152, 648)
render_target_update_mode = 4
[node name="PlayerBody" parent="SubViewportContainer/SubViewport" instance=ExtResource("1_mhgjp")]
[node name="WorldEnvironment" type="WorldEnvironment" parent="SubViewportContainer/SubViewport"]
environment = SubResource("Environment_uqqn3")
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="SubViewportContainer/SubViewport"]
transform = Transform3D(-0.8660254, -0.43301278, 0.25, 0, 0.49999997, 0.86602545, -0.50000006, 0.75, -0.43301266, 0, 0, 0)
shadow_enabled = true
directional_shadow_max_distance = 500.0
[node name="PlayerBody" parent="SubViewportContainer/SubViewport" instance=ExtResource("1_7vohb")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -20.417719, 1.340589, -8.014704)
[node name="Map" parent="SubViewportContainer/SubViewport" instance=ExtResource("2_41t38")]
[node name="IndustrialAreaMap" parent="SubViewportContainer/SubViewport" instance=ExtResource("2_hph0i")]
[node name="PauseMenu" parent="." instance=ExtResource("2_ien74")]
[node name="PauseMenu" parent="." instance=ExtResource("3_28e7h")]
[node name="CenterContainer" type="CenterContainer" parent="."]
anchors_preset = 15
@ -63,5 +63,5 @@ mouse_behavior_recursive = 1
[node name="TextureRect" type="TextureRect" parent="CenterContainer"]
custom_minimum_size = Vector2(10, 10)
layout_mode = 2
texture = ExtResource("4_41t38")
texture = ExtResource("4_buohg")
expand_mode = 4

View file

@ -3,7 +3,7 @@
[sub_resource type="GDScript" id="GDScript_kvqlu"]
script/source = "extends Control
@onready var next_scene := preload(\"res://maps/industrial_area.tscn\")
@onready var next_scene := preload(\"res://maps/game.tscn\")
func _ready():
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE

View file

@ -1,6 +1,6 @@
[gd_scene load_steps=6 format=3 uid="uid://snjgu4yp5swd"]
[ext_resource type="PackedScene" uid="uid://ce40pq785yoyi" path="res://objects/weapons/rifle.tscn" id="1_eqqp1"]
[ext_resource type="PackedScene" uid="uid://cfgwif53qypko" path="res://objects/weapons/revolver.tscn" id="1_eqqp1"]
[sub_resource type="SphereShape3D" id="SphereShape3D_eqqp1"]
radius = 0.2