159 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			159 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#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<Node3D>(get_node(NodePath("%PlayerCamera")));
 | 
						|
	if (PlayerInput * input{ cast_to<PlayerInput>(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<PackedScene> 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<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) {
 | 
						|
			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<PackedScene> scene) {
 | 
						|
	this->starting_weapon = 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;
 | 
						|
	}
 | 
						|
}
 |