diff --git a/src/player_character.cpp b/src/player_character.cpp index 4208864..cc5bdd9 100644 --- a/src/player_character.cpp +++ b/src/player_character.cpp @@ -1,6 +1,8 @@ #include "player_character.hpp" +#include "projectile_pool.hpp" #include "utils/godot_macros.h" #include +#include #include namespace godot { @@ -13,13 +15,15 @@ void PlayerCharacter::_enter_tree() { GDGAMEONLY(); this->nav_agent = this->get_node("NavigationAgent3D"); this->target_rotation = this->get_global_transform().get_basis().get_quaternion(); this->health = this->get_node("Health"); + this->primary_weapon_pool = this->get_node("ProjectilePool"); } void PlayerCharacter::_process(double delta_time) { GDGAMEONLY(); this->process_rotation(delta_time); - if(!this->mode_manual) { + if(!this->mode_manual) this->process_ai(delta_time); - } + if(this->firing) + this->try_fire_weapon(); } void PlayerCharacter::_physics_process(double delta_time) { GDGAMEONLY(); @@ -37,8 +41,8 @@ void PlayerCharacter::move(Vector3 world_vector) { } void PlayerCharacter::aim(Vector3 at) { - // calculate the forward vector by normalized difference between this node and the target - Vector3 const position{this->get_global_position()}; + // calculate the forward vector by normalized difference between player character and the target + Vector3 const position{this->weapon_muzzle->get_global_position()}; Vector3 const forward{(Vector3{at.x, 0.f, at.z} - Vector3{position.x, 0.f, position.z}).normalized()}; // we always want up to be the global unit up Vector3 const up{0.f, 1.f, 0.f}; @@ -46,6 +50,10 @@ void PlayerCharacter::aim(Vector3 at) { this->target_rotation = Basis{up.cross(forward), up, forward}; } +void PlayerCharacter::set_firing(bool firing) { + this->firing = firing; +} + void PlayerCharacter::set_manual_mode(bool value) { this->mode_manual = value; this->nav_agent->set_process_mode(value ? ProcessMode::PROCESS_MODE_PAUSABLE : ProcessMode::PROCESS_MODE_DISABLED); @@ -67,6 +75,19 @@ Health const *PlayerCharacter::get_health() const { return this->health; } +void PlayerCharacter::set_character_data(Ref data) { + this->data = data; + UtilityFunctions::print("PlayerCharacter::set_character_data"); + UtilityFunctions::print(" - data: ", data->get_path()); + UtilityFunctions::print(" - weapon: ", data->get_weapon()->get_path()); + this->fire_interval = 1.f / this->data->get_weapon()->get_rounds_per_second(); + this->primary_weapon_pool->set_data(this->data->get_weapon()); +} + +void PlayerCharacter::set_weapon_muzzle(Node3D *node) { + this->weapon_muzzle = node; +} + void PlayerCharacter::process_ai(double delta_time) { this->velocity_target = this->nav_agent->get_velocity(); } @@ -85,11 +106,22 @@ void PlayerCharacter::process_rotation(double delta_time) { float const angle_step{float(this->rotation_speed_curve->sample(angle) * PlayerCharacter::ROTATION_SPEED * delta_time)}; // update this object's global transform with the new rotation basis.set_quaternion(angle < angle_step ? target_quaternion // to avoid overshooting, check if the max step is smaller than the angle distance - : current_quaternion.slerp(target_quaternion, angle_step / angle)); // convert the angle step to a lerp t value between current and target rotations + : current_quaternion.slerp(target_quaternion, angle_step / angle)); // convert the angle step to a lerp t value between current and target rotations trans.set_basis(basis); this->set_global_transform(trans); } +void PlayerCharacter::try_fire_weapon() { + if(float(Time::get_singleton()->get_ticks_msec()) / 1000.f < this->fire_timer) + return; + if(!this->data->get_weapon()->get_allow_automatic()) + this->set_firing(false); + this->fire_timer = float(Time::get_singleton()->get_ticks_msec()) / 1000.f + this->fire_interval; + Node3D *node = this->primary_weapon_pool->claim_projectile(); + if(node != nullptr) + node->set_global_transform(this->weapon_muzzle->get_global_transform()); +} + float const PlayerCharacter::ACCELERATION{100.f}; float const PlayerCharacter::WALK_SPEED{3.f}; float const PlayerCharacter::SPRINT_SPEED{5.f}; diff --git a/src/player_character.hpp b/src/player_character.hpp index e683c47..d7d1517 100644 --- a/src/player_character.hpp +++ b/src/player_character.hpp @@ -1,9 +1,11 @@ #ifndef PLAYER_CHARACTER_HPP #define PLAYER_CHARACTER_HPP -#include "godot_cpp/classes/curve.hpp" +#include "character_data.hpp" #include "health.hpp" +#include "projectile_pool.hpp" #include +#include namespace godot { class NavigationAgent3D; @@ -18,6 +20,7 @@ public: virtual void _physics_process(double delta_time) override; void move(Vector3 world_vector); void aim(Vector3 at); + void set_firing(bool firing); void set_manual_mode(bool value); void set_rotation_speed_curve(Ref curve); @@ -25,15 +28,26 @@ public: virtual Health *get_health() override; virtual Health const *get_health() const override; + + void set_character_data(Ref data); + + void set_weapon_muzzle(Node3D *node); protected: void process_ai(double delta_time); void process_rotation(double delta_time); + void try_fire_weapon(); private: Vector3 velocity_target{0.f,0.f,0.f}; Basis target_rotation{}; NavigationAgent3D *nav_agent{nullptr}; bool mode_manual{false}; Health *health{nullptr}; + ProjectilePool *primary_weapon_pool{nullptr}; + Ref data; + float fire_interval{0.f}; + bool firing{false}; + float fire_timer{0.f}; + Node3D *weapon_muzzle{nullptr}; Ref rotation_speed_curve{};