feat: reloading withdraws ammo from inventory

This commit is contained in:
Sara 2025-08-10 16:37:02 +02:00
parent a2035e0db0
commit ed85b557a7
8 changed files with 92 additions and 17 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_HPROPERTY(Variant::OBJECT, anim, PROPERTY_HINT_NODE_TYPE, AnimationPlayer::get_class_static());
BIND_PROPERTY(Variant::INT, max_ammo); BIND_PROPERTY(Variant::INT, max_ammo);
BIND_PROPERTY(Variant::INT, loaded_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("reload_num", "num"), &self_type::reload_num);
ClassDB::bind_method(D_METHOD("ammo_empty"), &self_type::ammo_empty); ClassDB::bind_method(D_METHOD("ammo_empty"), &self_type::ammo_empty);
} }
@ -62,6 +61,14 @@ PlayerCamera *WeaponBase::get_camera() const {
return this->camera; 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) { void WeaponBase::set_body(PlayerBody *body) {
this->body = body; this->body = body;
} }
@ -99,11 +106,6 @@ bool WeaponBase::ammo_empty() const {
return this->loaded_ammo <= 0; 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) { void WeaponBase::reload_num(int num) {
int const space{ this->max_ammo - this->loaded_ammo }; int const space{ this->max_ammo - this->loaded_ammo };
num = MIN(num, space); num = MIN(num, space);

View file

@ -6,6 +6,7 @@ class AnimationPlayer;
class PlayerCamera; class PlayerCamera;
class PlayerBody; class PlayerBody;
class PlayerInput; class PlayerInput;
class WeaponInventory;
class WeaponBase : public Node3D { class WeaponBase : public Node3D {
GDCLASS(WeaponBase, Node3D); GDCLASS(WeaponBase, Node3D);
@ -22,6 +23,8 @@ public:
AnimationPlayer *get_anim() const; AnimationPlayer *get_anim() const;
PlayerInput *get_input() const; PlayerInput *get_input() const;
PlayerCamera *get_camera() const; PlayerCamera *get_camera() const;
WeaponInventory *get_inventory() const;
void _set_inventory(WeaponInventory *inventory);
void set_body(PlayerBody *body); void set_body(PlayerBody *body);
PlayerBody *get_body() const; PlayerBody *get_body() const;
@ -32,8 +35,7 @@ public:
int get_loaded_ammo() const; int get_loaded_ammo() const;
bool try_use_ammo(int amount = 1); bool try_use_ammo(int amount = 1);
bool ammo_empty() const; bool ammo_empty() const;
void reload_full(); 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.
void reload_num(int num);
virtual bool allows_running() const { return false; } virtual bool allows_running() const { return false; }
virtual bool allows_jumping() const { return true; } virtual bool allows_jumping() const { return true; }
@ -44,6 +46,7 @@ private:
AnimationPlayer *anim{ nullptr }; AnimationPlayer *anim{ nullptr };
PlayerCamera *camera{ nullptr }; PlayerCamera *camera{ nullptr };
PlayerBody *body{ nullptr }; PlayerBody *body{ nullptr };
WeaponInventory *inventory{ nullptr };
int loaded_ammo{ 0 }; int loaded_ammo{ 0 };
int max_ammo{ 1 }; int max_ammo{ 1 };

View file

@ -4,6 +4,8 @@
void WeaponInventory::_bind_methods() { void WeaponInventory::_bind_methods() {
BIND_HPROPERTY(Variant::OBJECT, starting_weapon, PROPERTY_HINT_RESOURCE_TYPE, "PackedScene"); 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() { void WeaponInventory::on_switch_input() {
@ -65,6 +67,7 @@ void WeaponInventory::pickup_weapon(Ref<PackedScene> weapon_scene) {
} }
Node *weapon_as_node{ weapon_scene->instantiate() }; Node *weapon_as_node{ weapon_scene->instantiate() };
if (WeaponBase * weapon{ cast_to<WeaponBase>(weapon_as_node) }) { if (WeaponBase * weapon{ cast_to<WeaponBase>(weapon_as_node) }) {
weapon->_set_inventory(this);
this->weapon_parent->add_child(weapon_as_node); 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. // Where to put the new weapon, consider empty slot 1, then empty slot 2, then replace current.
if (this->weapons[0] == nullptr) { if (this->weapons[0] == nullptr) {
@ -100,3 +103,49 @@ void WeaponInventory::set_starting_weapon(Ref<PackedScene> scene) {
Ref<PackedScene> WeaponInventory::get_starting_weapon() const { Ref<PackedScene> WeaponInventory::get_starting_weapon() const {
return this->starting_weapon; 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(); void pickup_demo_pack();
bool try_use_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: private:
Node3D *weapon_parent{ nullptr }; Node3D *weapon_parent{ nullptr };
unsigned current{ 0 }; unsigned current{ 0 };
@ -36,8 +45,8 @@ private:
Ref<PackedScene> starting_weapon{}; Ref<PackedScene> starting_weapon{};
int pistol_ammo{ 60 }; int pistol_ammo{ 16 };
int rifle_ammo{ 0 }; int rifle_ammo{ 30 };
}; };
#endif // !WEAPON_INVENTORY_H #endif // !WEAPON_INVENTORY_H

View file

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

View file

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

View file

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

View file

@ -1,6 +1,6 @@
[gd_scene load_steps=6 format=3 uid="uid://snjgu4yp5swd"] [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"] [sub_resource type="SphereShape3D" id="SphereShape3D_eqqp1"]
radius = 0.2 radius = 0.2