222 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			222 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#include "revolver.h"
 | 
						|
#include "scene/animation/animation_player.h"
 | 
						|
#include "wave_survival/macros.h"
 | 
						|
#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);
 | 
						|
	BIND_PROPERTY(Variant::FLOAT, single_action_spread);
 | 
						|
	BIND_PROPERTY(Variant::FLOAT, double_action_spread);
 | 
						|
}
 | 
						|
 | 
						|
void Revolver::queue_idle_anim() {
 | 
						|
	if (get_anim()->get_current_animation() == "run") {
 | 
						|
		stop_running();
 | 
						|
	}
 | 
						|
	// set a delay between the end of an action and (re)starting the run animation
 | 
						|
	this->run_animation_timer = this->run_animation_delay;
 | 
						|
	if (this->alt_active == true) {
 | 
						|
		get_anim()->queue("idle_single");
 | 
						|
	} else {
 | 
						|
		get_anim()->queue("idle_double");
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void Revolver::start_running() {
 | 
						|
	if (this->run_animation_timer <= 0.0) {
 | 
						|
		if (this->alt_active) {
 | 
						|
			get_anim()->queue("single_to_run");
 | 
						|
		} else {
 | 
						|
			get_anim()->queue("double_to_run");
 | 
						|
		}
 | 
						|
		get_anim()->queue("run");
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void Revolver::stop_running() {
 | 
						|
	String const current{ get_anim()->get_current_animation() };
 | 
						|
 | 
						|
	if (current == "run") {
 | 
						|
		get_anim()->stop();
 | 
						|
	}
 | 
						|
	if (current.begins_with("run") || current.ends_with("run")) {
 | 
						|
		if (this->alt_active) {
 | 
						|
			get_anim()->queue("run_to_single");
 | 
						|
		} else {
 | 
						|
			get_anim()->queue("run_to_double");
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
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::stop_reloading() {
 | 
						|
	if (get_anim()->get_current_animation() == "reload_one") {
 | 
						|
		get_anim()->queue("reload_to_double");
 | 
						|
		get_anim()->queue("idle_double");
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void Revolver::play_equip_anim() {
 | 
						|
	get_anim()->play("equip", 0.0);
 | 
						|
	queue_idle_anim();
 | 
						|
	get_anim()->advance(0.0);
 | 
						|
}
 | 
						|
 | 
						|
void Revolver::shoot() {
 | 
						|
	if (animation_is_idle() && try_use_ammo(1)) {
 | 
						|
		stop_running();
 | 
						|
		if (this->alt_active) {
 | 
						|
			this->alt_active = false;
 | 
						|
			this->muzzle->set_spread(this->single_action_spread);
 | 
						|
			get_anim()->queue("fire_single");
 | 
						|
		} else {
 | 
						|
			this->muzzle->set_spread(this->double_action_spread);
 | 
						|
			get_anim()->queue("fire_double");
 | 
						|
		}
 | 
						|
		queue_idle_anim();
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void Revolver::cock_hammer() {
 | 
						|
	if (!this->alt_active && animation_is_idle()) {
 | 
						|
		this->alt_active = true;
 | 
						|
		stop_running();
 | 
						|
		get_anim()->queue("to_single");
 | 
						|
		queue_idle_anim();
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void Revolver::on_primary_fire(bool pressed) {
 | 
						|
	if (pressed) {
 | 
						|
		if (get_anim()->get_queue().is_empty() && get_anim()->get_current_animation() == "reload_one") {
 | 
						|
			stop_reloading();
 | 
						|
		} else {
 | 
						|
			shoot();
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void Revolver::on_alt_mode(bool pressed) {
 | 
						|
	if (!this->alt_active && pressed) {
 | 
						|
		cock_hammer();
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void Revolver::on_reload() {
 | 
						|
	if (get_loaded_ammo() < get_max_ammo() && !is_animating()) {
 | 
						|
		start_reloading();
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void Revolver::on_animation_changed(String old_anim, String new_anim) {
 | 
						|
	on_animation_finished(old_anim);
 | 
						|
}
 | 
						|
 | 
						|
void Revolver::on_animation_finished(String old_anim) {
 | 
						|
	if (old_anim == "reload_one") {
 | 
						|
		int const available{ get_inventory()->withdraw_pistol_ammo(1) };
 | 
						|
		reload_num(available);
 | 
						|
		if (get_anim()->get_queue().is_empty()) {
 | 
						|
			if (available > 0 && get_loaded_ammo() < get_max_ammo()) {
 | 
						|
				get_anim()->queue("reload_one");
 | 
						|
			} else {
 | 
						|
				get_anim()->queue("reload_to_double");
 | 
						|
				get_anim()->queue("idle_double");
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void Revolver::ready() {
 | 
						|
	this->muzzle = cast_to<HitscanMuzzle>(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));
 | 
						|
}
 | 
						|
 | 
						|
void Revolver::process(double delta) {
 | 
						|
	//String const current{ get_anim()->get_current_animation() };
 | 
						|
	//double animation_time{ get_anim()->get_current_animation_position() };
 | 
						|
	if (this->recoil_timer > 0.0) {
 | 
						|
		this->recoil_timer -= delta;
 | 
						|
		double t{ 1.0 - CLAMP(this->recoil_timer / this->recoil_time, 0.0, 1.0) };
 | 
						|
		get_camera()->recoil(Math::lerp((double)this->recoil_force, 0.0, t) * delta);
 | 
						|
	}
 | 
						|
	if (this->run_animation_timer > 0.0) {
 | 
						|
		this->run_animation_timer -= delta;
 | 
						|
	}
 | 
						|
	if (!is_animating() && get_body()->get_is_running()) {
 | 
						|
		start_running();
 | 
						|
	} else if (!get_body()->get_is_running() && get_anim()->get_current_animation() == "run") {
 | 
						|
		queue_idle_anim();
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
bool Revolver::animation_is_idle() const {
 | 
						|
	return !is_animating() || get_anim()->get_current_animation() == "run";
 | 
						|
}
 | 
						|
 | 
						|
void Revolver::_notification(int what) {
 | 
						|
	if (Engine::get_singleton()->is_editor_hint()) {
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	switch (what) {
 | 
						|
		default:
 | 
						|
			return;
 | 
						|
		case NOTIFICATION_READY:
 | 
						|
			set_process(true);
 | 
						|
			ready();
 | 
						|
			return;
 | 
						|
		case NOTIFICATION_PROCESS:
 | 
						|
			process(get_process_delta_time());
 | 
						|
			return;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
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() {
 | 
						|
	this->alt_active = false;
 | 
						|
	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;
 | 
						|
}
 | 
						|
 | 
						|
void Revolver::start_recoil() {
 | 
						|
	this->recoil_timer = this->recoil_time;
 | 
						|
}
 | 
						|
 | 
						|
void Revolver::set_single_action_spread(float value) {
 | 
						|
	this->single_action_spread = value;
 | 
						|
}
 | 
						|
 | 
						|
float Revolver::get_single_action_spread() const {
 | 
						|
	return this->single_action_spread;
 | 
						|
}
 | 
						|
 | 
						|
void Revolver::set_double_action_spread(float value) {
 | 
						|
	this->double_action_spread = value;
 | 
						|
}
 | 
						|
 | 
						|
float Revolver::get_double_action_spread() const {
 | 
						|
	return this->double_action_spread;
 | 
						|
}
 |