feat: added revolver
This commit is contained in:
parent
3b22cd86f7
commit
6eba3b0454
Binary file not shown.
Binary file not shown.
|
@ -19,6 +19,7 @@
|
|||
#include "wave_survival/state_machine.h"
|
||||
#include "wave_survival/weapon_base.h"
|
||||
#include "wave_survival/weapon_inventory.h"
|
||||
#include "wave_survival/weapons/revolver.h"
|
||||
#include "wave_survival/weapons/rifle.h"
|
||||
|
||||
void initialize_wave_survival_module(ModuleInitializationLevel p_level) {
|
||||
|
@ -47,6 +48,7 @@ void initialize_wave_survival_module(ModuleInitializationLevel p_level) {
|
|||
GDREGISTER_CLASS(DamageBox);
|
||||
GDREGISTER_CLASS(PlayerInteractor);
|
||||
GDREGISTER_CLASS(Interactable);
|
||||
GDREGISTER_CLASS(Revolver);
|
||||
}
|
||||
|
||||
void uninitialize_wave_survival_module(ModuleInitializationLevel p_level) {
|
||||
|
|
|
@ -13,9 +13,6 @@ void WeaponBase::ready() {
|
|||
this->input = cast_to<PlayerInput>(get_parent()->get_node(NodePath("%PlayerInput")));
|
||||
this->camera = cast_to<PlayerCamera>(get_parent());
|
||||
this->body = cast_to<PlayerBody>(get_parent()->get_owner());
|
||||
if (this->anim) {
|
||||
this->anim->play("RESET");
|
||||
}
|
||||
}
|
||||
|
||||
void WeaponBase::_notification(int what) {
|
||||
|
@ -30,6 +27,20 @@ void WeaponBase::_notification(int what) {
|
|||
}
|
||||
}
|
||||
|
||||
PackedStringArray WeaponBase::get_configuration_warnings() const {
|
||||
PackedStringArray warnings{ super_type::get_configuration_warnings() };
|
||||
|
||||
if (this->anim == nullptr) {
|
||||
warnings.push_back("Weapons need something to animate them.\nRemember to configure the 'anim' property on this weapon");
|
||||
}
|
||||
|
||||
return warnings;
|
||||
}
|
||||
|
||||
bool WeaponBase::is_animating() const {
|
||||
return !get_anim()->get_current_animation().is_empty() || !get_anim()->get_queue().is_empty();
|
||||
}
|
||||
|
||||
void WeaponBase::set_anim(AnimationPlayer *anim) {
|
||||
this->anim = anim;
|
||||
}
|
||||
|
|
|
@ -14,8 +14,10 @@ class WeaponBase : public Node3D {
|
|||
|
||||
protected:
|
||||
void _notification(int what);
|
||||
virtual PackedStringArray get_configuration_warnings() const override;
|
||||
|
||||
public:
|
||||
bool is_animating() const;
|
||||
void set_anim(AnimationPlayer *player);
|
||||
AnimationPlayer *get_anim() const;
|
||||
PlayerInput *get_input() const;
|
||||
|
@ -24,7 +26,7 @@ public:
|
|||
void set_body(PlayerBody *body);
|
||||
PlayerBody *get_body() const;
|
||||
|
||||
virtual bool allows_running() const { return true; }
|
||||
virtual bool allows_running() const { return false; }
|
||||
virtual bool allows_jumping() const { return true; }
|
||||
virtual void notify_selected() {}
|
||||
|
||||
|
|
66
modules/wave_survival/weapons/revolver.cpp
Normal file
66
modules/wave_survival/weapons/revolver.cpp
Normal file
|
@ -0,0 +1,66 @@
|
|||
#include "revolver.h"
|
||||
#include "scene/animation/animation_player.h"
|
||||
#include "wave_survival/player_input.h"
|
||||
|
||||
void Revolver::_bind_methods() {
|
||||
}
|
||||
|
||||
void Revolver::play_equip_anim() {
|
||||
get_anim()->play("equip", 0.0);
|
||||
get_anim()->queue("idle_double");
|
||||
get_anim()->advance(0.0);
|
||||
}
|
||||
|
||||
void Revolver::shoot() {
|
||||
if (!is_animating()) {
|
||||
this->muzzle->shoot();
|
||||
if (this->alt_requested) {
|
||||
get_anim()->queue("fire_single");
|
||||
get_anim()->queue("idle_single");
|
||||
} else {
|
||||
get_anim()->queue("fire_double");
|
||||
get_anim()->queue("idle_double");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Revolver::on_primary_fire(bool pressed) {
|
||||
if (pressed) {
|
||||
shoot();
|
||||
}
|
||||
}
|
||||
|
||||
void Revolver::on_alt_mode(bool pressed) {
|
||||
this->alt_requested = pressed;
|
||||
}
|
||||
|
||||
void Revolver::ready() {
|
||||
this->muzzle = cast_to<HitscanMuzzle>(get_node(NodePath("%HitscanMuzzle")));
|
||||
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));
|
||||
play_equip_anim();
|
||||
}
|
||||
|
||||
void Revolver::process(double delta) {
|
||||
}
|
||||
|
||||
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() {
|
||||
play_equip_anim();
|
||||
}
|
27
modules/wave_survival/weapons/revolver.h
Normal file
27
modules/wave_survival/weapons/revolver.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
#ifndef WEAPONS_REVOLVER_H
|
||||
#define WEAPONS_REVOLVER_H
|
||||
|
||||
#include "wave_survival/hitscan_muzzle.h"
|
||||
#include "wave_survival/weapon_base.h"
|
||||
|
||||
class Revolver : public WeaponBase {
|
||||
GDCLASS(Revolver, WeaponBase);
|
||||
static void _bind_methods();
|
||||
void play_equip_anim();
|
||||
void shoot();
|
||||
void on_primary_fire(bool pressed);
|
||||
void on_alt_mode(bool pressed);
|
||||
void ready();
|
||||
void process(double delta);
|
||||
|
||||
protected:
|
||||
void _notification(int what);
|
||||
virtual void notify_selected() override;
|
||||
|
||||
private:
|
||||
bool alt_requested{ false };
|
||||
bool alt_active{ false };
|
||||
HitscanMuzzle *muzzle{ nullptr };
|
||||
};
|
||||
|
||||
#endif // !WEAPONS_REVOLVER_H
|
|
@ -12,24 +12,24 @@ void Rifle::_bind_methods() {
|
|||
BIND_PROPERTY(Variant::FLOAT, recoil_time);
|
||||
}
|
||||
|
||||
void Rifle::queue_start_aim() {
|
||||
void Rifle::queue_enter_alt() {
|
||||
get_anim()->queue("hip_to_aim");
|
||||
get_anim()->queue("aim");
|
||||
}
|
||||
|
||||
void Rifle::queue_stop_ads_anim() {
|
||||
void Rifle::queue_exit_alt() {
|
||||
get_anim()->queue("aim_to_hip");
|
||||
get_anim()->queue("hip");
|
||||
}
|
||||
|
||||
void Rifle::queue_start_run_anim() {
|
||||
void Rifle::queue_enter_run() {
|
||||
this->running = true;
|
||||
get_anim()->clear_queue();
|
||||
get_anim()->queue("hip_to_run");
|
||||
get_anim()->queue("run");
|
||||
}
|
||||
|
||||
void Rifle::stop_run_anim() {
|
||||
void Rifle::exit_run() {
|
||||
this->running = false;
|
||||
get_anim()->clear_queue();
|
||||
if (this->request_alt_mode) {
|
||||
|
@ -55,6 +55,7 @@ void Rifle::shoot() {
|
|||
void Rifle::play_equip_anim() {
|
||||
get_anim()->play("equip", 0.0);
|
||||
get_anim()->queue("hip");
|
||||
get_anim()->advance(0.0);
|
||||
}
|
||||
|
||||
void Rifle::on_primary_fire(bool pressed) {
|
||||
|
@ -90,8 +91,11 @@ void Rifle::ready() {
|
|||
void Rifle::process(double delta) {
|
||||
String const current{ get_anim()->get_current_animation() };
|
||||
bool run_requested{ this->run_requested() };
|
||||
// track animation progress
|
||||
double const animation_time{ get_anim()->get_current_animation_position() };
|
||||
// percentually
|
||||
float const progress{ float(CLAMP(animation_time / get_anim()->get_current_animation_length(), 0.0, 1.0)) };
|
||||
// lerp the current FOV factor depending on the ongoing animation
|
||||
if (current == "hip_to_aim") {
|
||||
get_camera()->set_fov_factor(Math::lerp(1.f, this->ads_factor, progress));
|
||||
} else if (current == "aim_to_hip") {
|
||||
|
@ -102,21 +106,23 @@ void Rifle::process(double delta) {
|
|||
get_camera()->set_fov_factor(Math::lerp(1.f, this->run_factor, progress));
|
||||
} else if (current == "run_to_hip") {
|
||||
get_camera()->set_fov_factor(Math::lerp(this->run_factor, 1.f, progress));
|
||||
// animation is not one of the transitory ones ( x_to_y ),
|
||||
// check if there is a request for a transitory animation
|
||||
} else if (this->request_alt_mode != this->in_alt_mode && !is_animating()) {
|
||||
if (this->request_alt_mode) {
|
||||
queue_start_aim();
|
||||
queue_enter_alt();
|
||||
} else {
|
||||
queue_stop_ads_anim();
|
||||
queue_exit_alt();
|
||||
}
|
||||
} else if (this->running != run_requested) {
|
||||
if (run_requested && !is_animating()) {
|
||||
queue_start_run_anim();
|
||||
queue_enter_run();
|
||||
} else if (!run_requested) {
|
||||
stop_run_anim();
|
||||
exit_run();
|
||||
}
|
||||
}
|
||||
|
||||
if (current == "fire_hip" || current == "fire_aim") {
|
||||
// apply fire recoil
|
||||
else if (current == "fire_hip" || current == "fire_aim") {
|
||||
double t{ animation_time / this->recoil_time };
|
||||
get_camera()->recoil(Math::lerp((double)this->recoil_force, 0.0, CLAMP(t, 0.0, 1.0)) * delta);
|
||||
}
|
||||
|
@ -139,6 +145,14 @@ void Rifle::_notification(int what) {
|
|||
}
|
||||
}
|
||||
|
||||
PackedStringArray Rifle::get_configuration_warnings() const {
|
||||
PackedStringArray warnings{ super_type::get_configuration_warnings() };
|
||||
if (get_node(NodePath("%HitscanMuzzle")) == nullptr) {
|
||||
warnings.push_back("Rifle needs a hitscan muzzle.\nConsider adding a node called '%HitscanMuzzle' of type HitscanMuzzle");
|
||||
}
|
||||
return warnings;
|
||||
}
|
||||
|
||||
bool Rifle::allows_running() const {
|
||||
String const animation{ get_anim()->get_current_animation() };
|
||||
return animation == "run" && !this->request_alt_mode;
|
||||
|
@ -149,11 +163,7 @@ bool Rifle::run_requested() const {
|
|||
}
|
||||
|
||||
void Rifle::notify_selected() {
|
||||
get_anim()->play("equip");
|
||||
}
|
||||
|
||||
bool Rifle::is_animating() const {
|
||||
return !get_anim()->get_current_animation().is_empty() || !get_anim()->get_queue().is_empty();
|
||||
play_equip_anim();
|
||||
}
|
||||
|
||||
void Rifle::set_ads_factor(float value) {
|
||||
|
|
|
@ -9,10 +9,10 @@ class HitscanMuzzle;
|
|||
class Rifle : public WeaponBase {
|
||||
GDCLASS(Rifle, WeaponBase);
|
||||
static void _bind_methods();
|
||||
void queue_start_aim();
|
||||
void queue_stop_ads_anim();
|
||||
void queue_start_run_anim();
|
||||
void stop_run_anim();
|
||||
void queue_enter_alt();
|
||||
void queue_exit_alt();
|
||||
void queue_enter_run();
|
||||
void exit_run();
|
||||
void shoot();
|
||||
void play_equip_anim();
|
||||
void on_primary_fire(bool down);
|
||||
|
@ -24,11 +24,11 @@ class Rifle : public WeaponBase {
|
|||
|
||||
public:
|
||||
void _notification(int what);
|
||||
virtual PackedStringArray get_configuration_warnings() const override;
|
||||
|
||||
virtual bool allows_running() const override;
|
||||
bool run_requested() const;
|
||||
virtual void notify_selected() override;
|
||||
bool is_animating() const;
|
||||
|
||||
void set_ads_factor(float value);
|
||||
float get_ads_factor() const;
|
||||
|
|
Binary file not shown.
|
@ -37,7 +37,25 @@ import_script/path=""
|
|||
materials/extract=0
|
||||
materials/extract_format=0
|
||||
materials/extract_path=""
|
||||
_subresources={}
|
||||
_subresources={
|
||||
"materials": {
|
||||
"body": {
|
||||
"use_external/enabled": true,
|
||||
"use_external/fallback_path": "res://assets/materials/weapons/arms.tres",
|
||||
"use_external/path": "uid://dgl8ygpyta7b0"
|
||||
},
|
||||
"metal": {
|
||||
"use_external/enabled": true,
|
||||
"use_external/fallback_path": "res://assets/materials/weapons/metal.tres",
|
||||
"use_external/path": "uid://cey2t4uje80f3"
|
||||
},
|
||||
"wood": {
|
||||
"use_external/enabled": true,
|
||||
"use_external/fallback_path": "res://assets/materials/weapons/wood.tres",
|
||||
"use_external/path": "uid://bvy3xngb287wd"
|
||||
}
|
||||
}
|
||||
}
|
||||
blender/nodes/visible=0
|
||||
blender/nodes/active_collection_only=false
|
||||
blender/nodes/punctual_lights=true
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,6 +1,6 @@
|
|||
[gd_scene load_steps=6 format=3 uid="uid://snjgu4yp5swd"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://ce40pq785yoyi" path="res://objects/weapons/rifle.tscn" id="1_eqqp1"]
|
||||
[ext_resource type="PackedScene" uid="uid://cfgwif53qypko" path="res://objects/weapons/revolver.tscn" id="1_eqqp1"]
|
||||
|
||||
[sub_resource type="SphereShape3D" id="SphereShape3D_eqqp1"]
|
||||
radius = 0.2
|
||||
|
|
29
project/objects/weapons/revolver.tscn
Normal file
29
project/objects/weapons/revolver.tscn
Normal file
|
@ -0,0 +1,29 @@
|
|||
[gd_scene load_steps=2 format=3 uid="uid://cfgwif53qypko"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://bkw6pt33nbn2" path="res://assets/models/weapons/revolver.blend" id="1_5ynga"]
|
||||
|
||||
[node name="Revolver" type="Revolver" node_paths=PackedStringArray("anim")]
|
||||
anim = NodePath("revolver/AnimationPlayer")
|
||||
|
||||
[node name="revolver" parent="." instance=ExtResource("1_5ynga")]
|
||||
|
||||
[node name="Body" parent="revolver/Character/Skeleton3D" index="0"]
|
||||
layers = 2
|
||||
|
||||
[node name="Cube" parent="revolver/Character/Skeleton3D" index="1"]
|
||||
layers = 2
|
||||
|
||||
[node name="BoneAttachment3D" type="BoneAttachment3D" parent="revolver/Character/Skeleton3D" index="2"]
|
||||
transform = Transform3D(1, -6.350722e-17, 4.732016e-17, 4.732016e-17, 0.95822614, 0.28601173, -6.350722e-17, -0.28601173, 0.95822614, -1.1196792e-16, -0.03667751, 0.009908612)
|
||||
bone_name = "root"
|
||||
bone_idx = 39
|
||||
|
||||
[node name="HitscanMuzzle" type="HitscanMuzzle" parent="revolver/Character/Skeleton3D/BoneAttachment3D"]
|
||||
unique_name_in_owner = true
|
||||
transform = Transform3D(1, 6.3507215e-17, 4.732015e-17, -6.350722e-17, 0.28601167, 0.958226, 4.7320157e-17, -0.958226, 0.28601167, 1.0408685e-17, 0.13487417, -0.03951955)
|
||||
target_position = Vector3(0, 200, 0)
|
||||
collision_mask = 6
|
||||
collide_with_areas = true
|
||||
spread = 0.03
|
||||
|
||||
[editable path="revolver"]
|
|
@ -20,13 +20,14 @@ bone_idx = 39
|
|||
|
||||
[node name="HitscanMuzzle" type="HitscanMuzzle" parent="rifle/Character/Skeleton3D/BoneAttachment3D"]
|
||||
unique_name_in_owner = true
|
||||
transform = Transform3D(1, 0, 0, 0, 0.99999833, -0.0017453281, 0, 0.0017453281, 0.99999833, 1.4540284e-26, 0, 0.027612558)
|
||||
target_position = Vector3(0, 100, 0)
|
||||
transform = Transform3D(1, 0, 0, 0, 0.9999968, 0.0024609112, 0, -0.0024609112, 0.9999968, 1.1099746e-16, 0.053034816, 0.03427495)
|
||||
target_position = Vector3(0, 200, 0)
|
||||
collision_mask = 6
|
||||
collide_with_areas = true
|
||||
spread = 0.003
|
||||
damage = 3
|
||||
|
||||
[node name="AnimationPlayer" parent="rifle" index="1"]
|
||||
[node name="AnimationPlayer" parent="rifle" index="2"]
|
||||
playback_default_blend_time = 0.1
|
||||
|
||||
[editable path="rifle"]
|
||||
|
|
Loading…
Reference in a new issue