Compare commits

...

2 commits

Author SHA1 Message Date
Sara 68abfdd383 feat: implemented rifle reload with placeholder anim 2025-08-06 18:45:02 +02:00
Sara 150231c67c feat: started work on reloading 2025-08-05 16:20:55 +02:00
37 changed files with 26838 additions and 36 deletions

View file

@ -10,6 +10,7 @@ String PlayerInput::sig_run{ "run" };
String PlayerInput::sig_jump{ "jump" }; String PlayerInput::sig_jump{ "jump" };
String PlayerInput::sig_crouch{ "crouch" }; String PlayerInput::sig_crouch{ "crouch" };
String PlayerInput::sig_activate{ "activate" }; String PlayerInput::sig_activate{ "activate" };
String PlayerInput::sig_reload{ "reload" };
void PlayerInput::_bind_methods() { void PlayerInput::_bind_methods() {
ADD_SIGNAL(MethodInfo(sig_movement_input, PropertyInfo(Variant::VECTOR2, "axes"))); ADD_SIGNAL(MethodInfo(sig_movement_input, PropertyInfo(Variant::VECTOR2, "axes")));
@ -21,6 +22,7 @@ void PlayerInput::_bind_methods() {
ADD_SIGNAL(MethodInfo(sig_jump)); ADD_SIGNAL(MethodInfo(sig_jump));
ADD_SIGNAL(MethodInfo(sig_crouch, PropertyInfo(Variant::BOOL, "is_crouching"))); ADD_SIGNAL(MethodInfo(sig_crouch, PropertyInfo(Variant::BOOL, "is_crouching")));
ADD_SIGNAL(MethodInfo(sig_activate)); ADD_SIGNAL(MethodInfo(sig_activate));
ADD_SIGNAL(MethodInfo(sig_reload));
} }
void PlayerInput::normalize_input() { void PlayerInput::normalize_input() {
@ -88,4 +90,7 @@ void PlayerInput::unhandled_input(Ref<InputEvent> const &event) {
if (event->is_action("activate") && event->is_pressed()) { if (event->is_action("activate") && event->is_pressed()) {
emit_signal(sig_activate); emit_signal(sig_activate);
} }
if (event->is_action("reload") && event->is_pressed()) {
emit_signal(sig_reload);
}
} }

View file

@ -20,6 +20,7 @@ public:
static String sig_jump; static String sig_jump;
static String sig_crouch; static String sig_crouch;
static String sig_activate; static String sig_activate;
static String sig_reload;
private: private:
bool was_paused{ false }; bool was_paused{ false };

View file

@ -7,6 +7,11 @@
void WeaponBase::_bind_methods() { void WeaponBase::_bind_methods() {
BIND_HPROPERTY(Variant::OBJECT, anim, PROPERTY_HINT_NODE_TYPE, AnimationPlayer::get_class_static()); BIND_HPROPERTY(Variant::OBJECT, anim, PROPERTY_HINT_NODE_TYPE, AnimationPlayer::get_class_static());
BIND_PROPERTY(Variant::INT, max_ammo);
BIND_PROPERTY(Variant::INT, loaded_ammo);
ClassDB::bind_method(D_METHOD("reload_full"), &self_type::reload_full);
ClassDB::bind_method(D_METHOD("reload_num", "num"), &self_type::reload_num);
ClassDB::bind_method(D_METHOD("ammo_empty"), &self_type::ammo_empty);
} }
void WeaponBase::ready() { void WeaponBase::ready() {
@ -64,3 +69,44 @@ void WeaponBase::set_body(PlayerBody *body) {
PlayerBody *WeaponBase::get_body() const { PlayerBody *WeaponBase::get_body() const {
return this->body; return this->body;
} }
void WeaponBase::set_max_ammo(int amount) {
this->max_ammo = amount;
}
int WeaponBase::get_max_ammo() const {
return MAX(0, this->max_ammo);
}
void WeaponBase::set_loaded_ammo(int amount) {
this->loaded_ammo = CLAMP(amount, 0, this->max_ammo);
}
int WeaponBase::get_loaded_ammo() const {
return this->loaded_ammo;
}
bool WeaponBase::try_use_ammo(int amount) {
if (this->loaded_ammo >= amount) {
loaded_ammo -= amount;
return true;
} else {
return false;
}
}
bool WeaponBase::ammo_empty() const {
return this->loaded_ammo <= 0;
}
void WeaponBase::reload_full() {
// TODO: take difference between loaded and max out of inventory
set_loaded_ammo(this->max_ammo);
}
void WeaponBase::reload_num(int num) {
int const space{ this->max_ammo - this->loaded_ammo };
num = MIN(num, space);
// TODO: take num out of ammo inventory
set_loaded_ammo(this->loaded_ammo + num);
}

View file

@ -26,6 +26,15 @@ public:
void set_body(PlayerBody *body); void set_body(PlayerBody *body);
PlayerBody *get_body() const; PlayerBody *get_body() const;
void set_max_ammo(int amount);
int get_max_ammo() const;
void set_loaded_ammo(int amount);
int get_loaded_ammo() const;
bool try_use_ammo(int amount = 1);
bool ammo_empty() const;
void reload_full();
void reload_num(int num);
virtual bool allows_running() const { return false; } virtual bool allows_running() const { return false; }
virtual bool allows_jumping() const { return true; } virtual bool allows_jumping() const { return true; }
virtual void notify_selected() {} virtual void notify_selected() {}
@ -35,6 +44,9 @@ private:
AnimationPlayer *anim{ nullptr }; AnimationPlayer *anim{ nullptr };
PlayerCamera *camera{ nullptr }; PlayerCamera *camera{ nullptr };
PlayerBody *body{ nullptr }; PlayerBody *body{ nullptr };
int loaded_ammo{ 0 };
int max_ammo{ 1 };
}; };
#endif // !WEAPON_BASE_H #endif // !WEAPON_BASE_H

View file

@ -35,6 +35,9 @@ private:
WeaponBase *current_weapon{ nullptr }; WeaponBase *current_weapon{ nullptr };
Ref<PackedScene> starting_weapon{}; Ref<PackedScene> starting_weapon{};
int pistol_ammo{ 60 };
int rifle_ammo{ 0 };
}; };
#endif // !WEAPON_INVENTORY_H #endif // !WEAPON_INVENTORY_H

View file

@ -26,6 +26,11 @@ void Revolver::queue_idle_anim() {
void Revolver::start_running() { void Revolver::start_running() {
if (this->run_animation_timer <= 0.0) { 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"); get_anim()->queue("run");
} }
} }
@ -36,7 +41,7 @@ void Revolver::stop_running() {
if (current == "run") { if (current == "run") {
get_anim()->stop(); get_anim()->stop();
} }
if (current.begins_with("run")) { if (current.begins_with("run") || current.ends_with("run")) {
if (this->alt_active) { if (this->alt_active) {
get_anim()->queue("run_to_single"); get_anim()->queue("run_to_single");
} else { } else {
@ -87,10 +92,14 @@ void Revolver::on_alt_mode(bool pressed) {
} }
} }
void Revolver::on_reload() {
}
void Revolver::ready() { void Revolver::ready() {
this->muzzle = cast_to<HitscanMuzzle>(get_node(NodePath("%HitscanMuzzle"))); 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_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_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(); play_equip_anim();
} }

View file

@ -16,6 +16,7 @@ class Revolver : public WeaponBase {
void cock_hammer(); void cock_hammer();
void on_primary_fire(bool pressed); void on_primary_fire(bool pressed);
void on_alt_mode(bool pressed); void on_alt_mode(bool pressed);
void on_reload();
void ready(); void ready();
void process(double delta); void process(double delta);
@ -43,7 +44,7 @@ private:
double recoil_time{ 0.1 }; double recoil_time{ 0.1 };
double recoil_timer{ 0.0 }; double recoil_timer{ 0.0 };
double run_animation_delay{ 0.3 }; double run_animation_delay{ 0.8 };
double run_animation_timer{ 0.0 }; double run_animation_timer{ 0.0 };
}; };

View file

@ -42,7 +42,7 @@ void Rifle::exit_run() {
} }
void Rifle::shoot() { void Rifle::shoot() {
if (!is_animating()) { if (!is_animating() && try_use_ammo()) {
this->muzzle->shoot(); this->muzzle->shoot();
if (this->request_alt_mode) { if (this->request_alt_mode) {
get_anim()->queue("fire_aim"); get_anim()->queue("fire_aim");
@ -52,6 +52,16 @@ void Rifle::shoot() {
} }
} }
void Rifle::start_reload_animation() {
if (!is_animating() && get_loaded_ammo() != get_max_ammo()) {
if (this->in_alt_mode) {
get_anim()->queue("aim_to_hip");
}
get_anim()->queue("reload");
get_anim()->queue("hip");
}
}
void Rifle::play_equip_anim() { void Rifle::play_equip_anim() {
get_anim()->play("equip", 0.0); get_anim()->play("equip", 0.0);
get_anim()->queue("hip"); get_anim()->queue("hip");
@ -68,6 +78,10 @@ void Rifle::on_alt_mode(bool alt_mode) {
this->request_alt_mode = alt_mode; this->request_alt_mode = alt_mode;
} }
void Rifle::on_reload() {
start_reload_animation();
}
void Rifle::on_animation_changed(String new_animation) { void Rifle::on_animation_changed(String new_animation) {
if (new_animation == "aim") { if (new_animation == "aim") {
this->in_alt_mode = true; this->in_alt_mode = true;
@ -85,6 +99,7 @@ void Rifle::ready() {
get_anim()->connect("current_animation_changed", callable_mp(this, &self_type::on_animation_changed)); get_anim()->connect("current_animation_changed", callable_mp(this, &self_type::on_animation_changed));
get_input()->connect(PlayerInput::sig_primary_fire, callable_mp(this, &self_type::on_primary_fire)); 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_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(); play_equip_anim();
} }

View file

@ -14,11 +14,12 @@ class Rifle : public WeaponBase {
void queue_enter_run(); void queue_enter_run();
void exit_run(); void exit_run();
void shoot(); void shoot();
void start_reload_animation();
void play_equip_anim(); void play_equip_anim();
void on_primary_fire(bool down); void on_primary_fire(bool down);
void on_alt_mode(bool alt_mode); void on_alt_mode(bool alt_mode);
void on_reload();
void on_animation_changed(String new_anim); void on_animation_changed(String new_anim);
void on_run_input(bool run);
void ready(); void ready();
void process(double delta); void process(double delta);

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
[gd_scene load_steps=6 format=3 uid="uid://snjgu4yp5swd"] [gd_scene load_steps=6 format=3 uid="uid://snjgu4yp5swd"]
[ext_resource type="PackedScene" uid="uid://cfgwif53qypko" path="res://objects/weapons/revolver.tscn" id="1_eqqp1"] [ext_resource type="PackedScene" uid="uid://ce40pq785yoyi" path="res://objects/weapons/rifle.tscn" id="1_eqqp1"]
[sub_resource type="SphereShape3D" id="SphereShape3D_eqqp1"] [sub_resource type="SphereShape3D" id="SphereShape3D_eqqp1"]
radius = 0.2 radius = 0.2

View file

@ -11,41 +11,13 @@ func trigger() -> void:
[node name="Revolver" type="Revolver" node_paths=PackedStringArray("anim")] [node name="Revolver" type="Revolver" node_paths=PackedStringArray("anim")]
anim = NodePath("revolver/AnimationPlayer") anim = NodePath("revolver/AnimationPlayer")
max_ammo = 6
loaded_ammo = 6
single_action_spread = 0.003 single_action_spread = 0.003
double_action_spread = 0.02 double_action_spread = 0.02
[node name="revolver" parent="." instance=ExtResource("1_5ynga")] [node name="revolver" parent="." instance=ExtResource("1_5ynga")]
[node name="Skeleton3D" parent="revolver/Character" index="0"]
bones/1/position = Vector3(0.077683, 0.15356629, 0.22951864)
bones/1/rotation = Quaternion(0.5851843, 0.4764963, 0.47324383, -0.45447868)
bones/2/rotation = Quaternion(-0.37339994, -0.012608625, 0.4248388, 0.8245759)
bones/3/rotation = Quaternion(0.13469099, 0.084066905, 0.5777786, 0.8006018)
bones/4/rotation = Quaternion(0.2787549, 0.10335517, 0.061925787, 0.9527742)
bones/5/rotation = Quaternion(-0.16385715, 0.07371643, -0.117167264, 0.9767234)
bones/6/rotation = Quaternion(-0.10018807, 0.001737441, -0.017251449, 0.99481744)
bones/7/rotation = Quaternion(-5.5135492e-06, -8.1514554e-07, -0.000472692, 0.9999999)
bones/8/rotation = Quaternion(-0.67974395, 0.15276042, 0.07346374, 0.7135934)
bones/9/rotation = Quaternion(-0.52413255, -0.0052551557, 0.008540811, 0.85157764)
bones/10/rotation = Quaternion(-0.45302963, 0.0016381529, -0.0032266718, 0.89148813)
bones/11/rotation = Quaternion(-0.6447599, 0.17695156, 0.030249279, 0.74300593)
bones/12/rotation = Quaternion(-0.61815894, -0.0058423695, 0.008146204, 0.78598917)
bones/13/rotation = Quaternion(-0.28957173, 0.0008908786, -0.0035062442, 0.95714945)
bones/14/rotation = Quaternion(-0.4137267, 0.18337816, -0.055713132, 0.88999933)
bones/15/rotation = Quaternion(-0.56248397, 0.008516232, 0.01857911, 0.82655555)
bones/16/rotation = Quaternion(-0.5171131, -0.003298891, -0.013025877, 0.8558117)
bones/17/position = Vector3(-0.035217345, 0.031610142, 0.010926659)
bones/17/rotation = Quaternion(-0.23086587, 0.40491727, 0.5210391, 0.7150253)
bones/18/rotation = Quaternion(-0.027613077, -0.014708879, 0.040168725, 0.998703)
bones/19/rotation = Quaternion(0.008477317, 0.0136856465, -0.3318223, 0.9432046)
bones/20/rotation = Quaternion(0.5851843, -0.4764963, -0.47324383, -0.45447868)
bones/39/position = Vector3(0.09835215, -0.26794472, -0.3457696)
bones/39/rotation = Quaternion(0.24137872, 3.1304803e-18, 1.1981784e-16, 0.9704311)
bones/40/position = Vector3(0.015597563, 0.030223738, 0.0061558606)
bones/40/rotation = Quaternion(-0.5071953, 0.4361461, -0.43880603, 0.5999824)
bones/43/rotation = Quaternion(0.16942807, 1.17632844e-07, -1.932268e-08, 0.98554254)
bones/44/rotation = Quaternion(0.9970487, -9.152002e-09, 1.18857486e-07, -0.0767723)
[node name="Body" parent="revolver/Character/Skeleton3D" index="0"] [node name="Body" parent="revolver/Character/Skeleton3D" index="0"]
layers = 2 layers = 2
@ -53,7 +25,7 @@ layers = 2
layers = 2 layers = 2
[node name="BoneAttachment3D" type="BoneAttachment3D" parent="revolver/Character/Skeleton3D" index="2"] [node name="BoneAttachment3D" type="BoneAttachment3D" parent="revolver/Character/Skeleton3D" index="2"]
transform = Transform3D(1, -2.3103859e-16, 6.391877e-17, 2.3406112e-16, 0.8834727, -0.46848273, 5.176711e-17, 0.46848273, 0.8834727, 0.09835215, -0.26794472, -0.3457696) 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_name = "root"
bone_idx = 39 bone_idx = 39

View file

@ -11,6 +11,8 @@ func trigger() -> void:
[node name="Rifle" type="Rifle" node_paths=PackedStringArray("anim")] [node name="Rifle" type="Rifle" node_paths=PackedStringArray("anim")]
anim = NodePath("rifle/AnimationPlayer") anim = NodePath("rifle/AnimationPlayer")
max_ammo = 10
loaded_ammo = 10
[node name="rifle" parent="." instance=ExtResource("1_afgyw")] [node name="rifle" parent="." instance=ExtResource("1_afgyw")]

View file

@ -87,6 +87,11 @@ activate={
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":69,"key_label":0,"unicode":101,"location":0,"echo":false,"script":null) "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":69,"key_label":0,"unicode":101,"location":0,"echo":false,"script":null)
] ]
} }
reload={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":82,"key_label":0,"unicode":114,"location":0,"echo":false,"script":null)
]
}
[layer_names] [layer_names]