#include "weapon_inventory.h" #include "macros.h" #include "player_input.h" #include "weapon_base.h" 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); ClassDB::bind_method(D_METHOD("pickup_weapon"), &self_type::pickup_weapon); } void WeaponInventory::on_switch_input() { 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) { if (Engine::get_singleton()->is_editor_hint()) { return; } switch (what) { default: return; case NOTIFICATION_READY: ready(); return; } } void WeaponInventory::select_weapon(WeaponBase *new_weapon) { if (new_weapon == nullptr) { 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]) { this->current = 1; } else { print_error("WeaponInventory::select_weapon: Attempt to select weapon that is not in inventory. Exiting with no current weapon."); return; } 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) { this->current_weapon->set_process_mode(PROCESS_MODE_PAUSABLE); this->current_weapon->set_visible(true); this->current_weapon->notify_selected(); } } WeaponBase *WeaponInventory::get_current_weapon() const { return this->current_weapon; } void WeaponInventory::pickup_weapon(Ref weapon_scene) { if (!weapon_scene.is_valid()) { print_error("WeaponInventory::pickup_weapon: passed weapon scene is invalid"); return; } Node *weapon_as_node{ weapon_scene->instantiate() }; if (WeaponBase * weapon{ cast_to(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) { this->weapons[0] = weapon; } else if (this->weapons[1] == nullptr) { this->weapons[1] = weapon; } else { // replace current weapon, assign the slot this->weapons[this->current] = weapon; // free the current weapon this->current_weapon->queue_free(); // set the current to null, so select_weapon will skip dropping it this->current_weapon = nullptr; } // 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(); } else { print_error(vformat("WeaponInventory::pickup_weapon: passed weapon scene '%s' did not instantiate a valid node", weapon_scene->get_path())); } } void WeaponInventory::set_starting_weapon(Ref scene) { this->starting_weapon = scene; } Ref 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; } }