From 7a13823c9734f90c6c7a45d6c7fbdc704d1670e6 Mon Sep 17 00:00:00 2001 From: Sara Date: Mon, 11 Aug 2025 16:49:49 +0200 Subject: [PATCH] feat: weapon swapping --- modules/wave_survival/weapon_base.h | 2 ++ modules/wave_survival/weapon_inventory.cpp | 26 +++++++++++++--------- modules/wave_survival/weapons/revolver.cpp | 13 +++++++---- modules/wave_survival/weapons/revolver.h | 1 + modules/wave_survival/weapons/rifle.cpp | 18 +++++++++++---- modules/wave_survival/weapons/rifle.h | 2 ++ 6 files changed, 44 insertions(+), 18 deletions(-) diff --git a/modules/wave_survival/weapon_base.h b/modules/wave_survival/weapon_base.h index c56e6d11..b4b495d3 100644 --- a/modules/wave_survival/weapon_base.h +++ b/modules/wave_survival/weapon_base.h @@ -39,7 +39,9 @@ public: virtual bool allows_running() const { return false; } virtual bool allows_jumping() const { return true; } + virtual bool allows_swapping() const { return true; } virtual void notify_selected() {} + virtual void notify_deselected() {} private: PlayerInput *input{ nullptr }; diff --git a/modules/wave_survival/weapon_inventory.cpp b/modules/wave_survival/weapon_inventory.cpp index 0f76a9bb..768e7c31 100644 --- a/modules/wave_survival/weapon_inventory.cpp +++ b/modules/wave_survival/weapon_inventory.cpp @@ -1,5 +1,6 @@ #include "weapon_inventory.h" #include "macros.h" +#include "player_input.h" #include "weapon_base.h" void WeaponInventory::_bind_methods() { @@ -10,13 +11,18 @@ void WeaponInventory::_bind_methods() { } void WeaponInventory::on_switch_input() { - this->current = (this->current + 1) % 1; - this->select_weapon(this->weapons[this->current]); + unsigned next{ (this->current + 1) % 2 }; + if (this->weapons[next] != nullptr) { + this->select_weapon(this->weapons[next]); + } } void WeaponInventory::ready() { callable_mp(this, &self_type::pickup_weapon).call_deferred(this->starting_weapon); this->weapon_parent = cast_to(get_node(NodePath("%PlayerCamera"))); + if (PlayerInput * input{ cast_to(get_node(NodePath("%PlayerInput"))) }) { + input->connect(PlayerInput::sig_switch_weapon, callable_mp(this, &self_type::on_switch_input)); + } } void WeaponInventory::_notification(int what) { @@ -37,6 +43,9 @@ void WeaponInventory::select_weapon(WeaponBase *new_weapon) { print_error("WeaponInventory::select_weapon: Weapon invalid, returning before taking any action."); return; } + if (this->current_weapon != nullptr && !this->current_weapon->allows_swapping()) { + return; + } if (new_weapon == this->weapons[0]) { this->current = 0; } else if (new_weapon == this->weapons[1]) { @@ -48,6 +57,7 @@ void WeaponInventory::select_weapon(WeaponBase *new_weapon) { if (this->current_weapon != nullptr) { this->current_weapon->set_process_mode(PROCESS_MODE_DISABLED); this->current_weapon->set_visible(false); + this->current_weapon->notify_deselected(); } this->current_weapon = new_weapon; if (this->current_weapon != nullptr) { @@ -63,7 +73,7 @@ WeaponBase *WeaponInventory::get_current_weapon() const { void WeaponInventory::pickup_weapon(Ref weapon_scene) { if (!weapon_scene.is_valid()) { - print_error("WeaponInventory::pickup_weapon: passed weapon scene"); + print_error("WeaponInventory::pickup_weapon: passed weapon scene is invalid"); return; } Node *weapon_as_node{ weapon_scene->instantiate() }; @@ -73,22 +83,18 @@ void WeaponInventory::pickup_weapon(Ref weapon_scene) { // Where to put the new weapon, consider empty slot 1, then empty slot 2, then replace current. if (this->weapons[0] == nullptr) { this->weapons[0] = weapon; - select_weapon(weapon); - return; } else if (this->weapons[1] == nullptr) { this->weapons[1] = weapon; - select_weapon(weapon); - return; } else { // replace current weapon, assign the slot this->weapons[this->current] = weapon; // free the current weapon this->current_weapon->queue_free(); - // set the point to null, so select_weapon will skip dropping the current weapon. + // set the current to null, so select_weapon will skip dropping it this->current_weapon = nullptr; - // equip new weapon - select_weapon(weapon); } + // equip new weapon + select_weapon(weapon); } else if (weapon_as_node != nullptr) { print_error(vformat("WeaponInventory::pickup_weapon: weapon scene '%s' instantiated a node of type '%s', which does not inherit from 'WeaponBase'", weapon_scene->get_path(), weapon_as_node->get_class())); weapon_as_node->queue_free(); diff --git a/modules/wave_survival/weapons/revolver.cpp b/modules/wave_survival/weapons/revolver.cpp index 140ab3eb..aafb063b 100644 --- a/modules/wave_survival/weapons/revolver.cpp +++ b/modules/wave_survival/weapons/revolver.cpp @@ -141,10 +141,6 @@ void Revolver::ready() { this->muzzle = cast_to(get_node(NodePath("%HitscanMuzzle"))); get_anim()->connect("animation_changed", callable_mp(this, &self_type::on_animation_changed)); get_anim()->connect("animation_finished", callable_mp(this, &self_type::on_animation_finished)); - get_input()->connect(PlayerInput::sig_primary_fire, callable_mp(this, &self_type::on_primary_fire)); - get_input()->connect(PlayerInput::sig_alt_mode, callable_mp(this, &self_type::on_alt_mode)); - get_input()->connect(PlayerInput::sig_reload, callable_mp(this, &self_type::on_reload)); - play_equip_anim(); } void Revolver::process(double delta) { @@ -187,9 +183,18 @@ void Revolver::_notification(int what) { } void Revolver::notify_selected() { + get_input()->connect(PlayerInput::sig_primary_fire, callable_mp(this, &self_type::on_primary_fire)); + get_input()->connect(PlayerInput::sig_alt_mode, callable_mp(this, &self_type::on_alt_mode)); + get_input()->connect(PlayerInput::sig_reload, callable_mp(this, &self_type::on_reload)); play_equip_anim(); } +void Revolver::notify_deselected() { + get_input()->disconnect(PlayerInput::sig_primary_fire, callable_mp(this, &self_type::on_primary_fire)); + get_input()->disconnect(PlayerInput::sig_alt_mode, callable_mp(this, &self_type::on_alt_mode)); + get_input()->disconnect(PlayerInput::sig_reload, callable_mp(this, &self_type::on_reload)); +} + bool Revolver::allows_running() const { return true; } diff --git a/modules/wave_survival/weapons/revolver.h b/modules/wave_survival/weapons/revolver.h index 00b0c3c3..2933c8da 100644 --- a/modules/wave_survival/weapons/revolver.h +++ b/modules/wave_survival/weapons/revolver.h @@ -30,6 +30,7 @@ class Revolver : public WeaponBase { protected: void _notification(int what); virtual void notify_selected() override; + virtual void notify_deselected() override; virtual bool allows_running() const override; public: diff --git a/modules/wave_survival/weapons/rifle.cpp b/modules/wave_survival/weapons/rifle.cpp index 25a836ec..4763653b 100644 --- a/modules/wave_survival/weapons/rifle.cpp +++ b/modules/wave_survival/weapons/rifle.cpp @@ -102,10 +102,6 @@ void Rifle::on_animation_changed(String new_animation) { void Rifle::ready() { this->muzzle = cast_to(get_node(NodePath("%HitscanMuzzle"))); get_anim()->connect("current_animation_changed", callable_mp(this, &self_type::on_animation_changed)); - get_input()->connect(PlayerInput::sig_primary_fire, callable_mp(this, &self_type::on_primary_fire)); - get_input()->connect(PlayerInput::sig_alt_mode, callable_mp(this, &self_type::on_alt_mode)); - get_input()->connect(PlayerInput::sig_reload, callable_mp(this, &self_type::on_reload)); - play_equip_anim(); } void Rifle::process(double delta) { @@ -173,6 +169,11 @@ PackedStringArray Rifle::get_configuration_warnings() const { return warnings; } +bool Rifle::allows_swapping() const { + String const current{ get_anim()->get_current_animation() }; + return !this->in_alt_mode && (current == "reload" || !is_animating()); +} + bool Rifle::allows_running() const { String const animation{ get_anim()->get_current_animation() }; return animation == "run" && !this->request_alt_mode; @@ -183,9 +184,18 @@ bool Rifle::run_requested() const { } void Rifle::notify_selected() { + get_input()->connect(PlayerInput::sig_primary_fire, callable_mp(this, &self_type::on_primary_fire)); + get_input()->connect(PlayerInput::sig_alt_mode, callable_mp(this, &self_type::on_alt_mode)); + get_input()->connect(PlayerInput::sig_reload, callable_mp(this, &self_type::on_reload)); play_equip_anim(); } +void Rifle::notify_deselected() { + get_input()->disconnect(PlayerInput::sig_primary_fire, callable_mp(this, &self_type::on_primary_fire)); + get_input()->disconnect(PlayerInput::sig_alt_mode, callable_mp(this, &self_type::on_alt_mode)); + get_input()->disconnect(PlayerInput::sig_reload, callable_mp(this, &self_type::on_reload)); +} + void Rifle::reload_full() { int const available = get_inventory()->withdraw_rifle_ammo(get_max_ammo()); reload_num(available); diff --git a/modules/wave_survival/weapons/rifle.h b/modules/wave_survival/weapons/rifle.h index 12538183..16ad2f98 100644 --- a/modules/wave_survival/weapons/rifle.h +++ b/modules/wave_survival/weapons/rifle.h @@ -27,9 +27,11 @@ public: void _notification(int what); virtual PackedStringArray get_configuration_warnings() const override; + virtual bool allows_swapping() const override; virtual bool allows_running() const override; bool run_requested() const; virtual void notify_selected() override; + virtual void notify_deselected() override; void reload_full(); void set_ads_factor(float value);