#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(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; }