diff --git a/src/player_character.cpp b/src/player_character.cpp index 799355c..eecc955 100644 --- a/src/player_character.cpp +++ b/src/player_character.cpp @@ -1,6 +1,5 @@ #include "player_character.hpp" #include "projectile_pool.hpp" -#include "state_machine.hpp" #include "utils/godot_macros.h" #include #include @@ -21,7 +20,6 @@ void PlayerCharacter::_enter_tree() { GDGAMEONLY(); 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"); - this->state_machine = this->get_node("StateMachine"); } void PlayerCharacter::_process(double delta_time) { GDGAMEONLY(); @@ -50,13 +48,15 @@ void PlayerCharacter::move(Vector3 world_vector) { void PlayerCharacter::aim(Vector3 at) { // calculate the forward vector by normalized difference between player character and the target on the XZ plane 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()}; - this->aim_direction(forward); + Vector3 const forward{Vector3{at.x, 0.f, at.z} - Vector3{position.x, 0.f, position.z}}; + this->aim_direction(forward.normalized()); } void PlayerCharacter::aim_direction(Vector3 direction) { - if(direction.is_zero_approx()) - return; // there is no situation in which rotation target would be 0 + if(!direction.is_normalized()) { + UtilityFunctions::push_error("'", this->get_path(), "' Cannot aim along a non-normalized direction vector", direction.length_squared()); + return; + } // we always want up to be the global unit up Vector3 const up{0.f, 1.f, 0.f}; // left is the cross product of the two @@ -84,7 +84,6 @@ void PlayerCharacter::set_manual_mode(bool value) { ProcessMode const mode = value ? ProcessMode::PROCESS_MODE_DISABLED : ProcessMode::PROCESS_MODE_PAUSABLE; //this->nav_agent->set_process_mode(mode); this->nav_agent->set_avoidance_priority(value ? 1.f : 0.9f); - this->state_machine->set_process_mode(mode); } void PlayerCharacter::set_rotation_speed_curve(Ref curve) { diff --git a/src/player_character.hpp b/src/player_character.hpp index 688a799..e140c7b 100644 --- a/src/player_character.hpp +++ b/src/player_character.hpp @@ -9,7 +9,6 @@ namespace godot { class NavigationAgent3D; -class StateMachine; class TunnelsPlayer; class PlayerCharacter : public CharacterBody3D, @@ -46,7 +45,6 @@ protected: void try_fire_weapon(); private: Vector3 velocity_target{0.f,0.f,0.f}; - StateMachine *state_machine{nullptr}; Basis target_rotation{}; NavigationAgent3D *nav_agent{nullptr}; bool mode_manual{false}; diff --git a/src/player_states.cpp b/src/player_states.cpp deleted file mode 100644 index ca8c2ab..0000000 --- a/src/player_states.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include "player_states.hpp" -#include "player_character.hpp" -#include "tunnels_game_mode.hpp" -#include "utils/game_root.hpp" -#include -#include - -namespace godot { -void PlayerState::_bind_methods() { -#define CLASSNAME PlayerState -} - -void PlayerState::init(Node *target, StateMachine *machine) { - this->state_machine = machine; - this->parent = Object::cast_to(target); - if(!this->parent) - UtilityFunctions::push_error("Attempt to apply player state to non-PlayerCharacter node of type '", target->get_class(), "'"); - Ref game_mode = GameRoot::get_singleton()->get_game_mode(); - this->player = game_mode->get_player_instance(); - if(!this->player) - UtilityFunctions::push_error("Failed to find valid TunnelsPlayer instance in game mode"); -} - -StringName PlayerState::get_next() const { - return this->get_class(); -} - -PlayerCharacter *PlayerState::get_manual_character() const { - return this->player->get_character(); -} - -Vector3 PlayerState::get_home_position() const { - Basis const player_basis = this->get_manual_character()->get_global_transform().basis; - Vector3 const player_origin = this->get_manual_character()->get_global_position(); - Vector3 const offset = this->parent->get_global_position() - player_origin; - Vector3 const local = Vector3(0.f, (std::signbit(player_basis.get_column(0).dot(offset)) ? 1.f : -1.f), -1.f).normalized() * 3.f; - return player_origin + player_basis.get_column(0) * local.x + player_basis.get_column(2) * local.z; -} - -#undef CLASSNAME // PlayerState - -void FollowingPlayer::_bind_methods() { -#define CLASSNAME FollowingPlayer -} - -void FollowingPlayer::_process(double delta_time) { - this->parent->move_to(this->get_home_position(), 1.f); - this->parent->aim_direction(this->parent->get_velocity_target()); -} - -#undef CLASSNAME // FollowingPlayer -} diff --git a/src/player_states.hpp b/src/player_states.hpp deleted file mode 100644 index ac04597..0000000 --- a/src/player_states.hpp +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef PLAYER_STATES_HPP -#define PLAYER_STATES_HPP - -#include "state.hpp" - -namespace godot { -class PlayerCharacter; -class StateMachine; -class TunnelsPlayer; - -class PlayerState : public Node, - public IState { - GDCLASS(PlayerState, Node); - static void _bind_methods(); -public: - virtual void init(Node *target, StateMachine *machine) override; - virtual StringName get_next() const override; -protected: - float get_distance_from_player(bool sqr = false) const; - PlayerCharacter *get_manual_character() const; - Vector3 get_home_position() const; - bool in_player_line_of_fire() const; -protected: - PlayerCharacter *parent{nullptr}; - StateMachine *state_machine{nullptr}; - TunnelsPlayer *player{nullptr}; -}; - -class FollowingPlayer : public PlayerState { - GDCLASS(FollowingPlayer, PlayerState); - static void _bind_methods(); -public: - virtual void _process(double delta_time) override; -}; -} - -#endif // !PLAYER_STATES_HPP diff --git a/src/register_types.cpp b/src/register_types.cpp index 92d2518..f54187a 100644 --- a/src/register_types.cpp +++ b/src/register_types.cpp @@ -4,10 +4,7 @@ #include "health.hpp" #include "pellet_projectile.hpp" #include "player_character.hpp" -#include "player_states.hpp" #include "projectile_pool.hpp" -#include "state.hpp" -#include "state_machine.hpp" #include "tunnels_game_mode.hpp" #include "tunnels_game_state.hpp" #include "tunnels_player.hpp" @@ -54,10 +51,6 @@ void initialize_gdextension_types(ModuleInitializationLevel p_level) ClassDB::register_class(); ClassDB::register_class(); - - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); } extern "C" diff --git a/src/state.cpp b/src/state.cpp deleted file mode 100644 index b877058..0000000 --- a/src/state.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "state.hpp" -#include "state_machine.hpp" - -namespace godot { -} diff --git a/src/state.hpp b/src/state.hpp deleted file mode 100644 index 90a5a8e..0000000 --- a/src/state.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef STATE_HPP -#define STATE_HPP - -#include "godot_cpp/core/defs.hpp" -#include - -namespace godot { -class StateMachine; - -class IState { - friend class StateMachine; -public: - virtual void init(Node *target, StateMachine *machine) = 0; - virtual StringName get_next() const = 0; - _ALWAYS_INLINE_ Node *as_node() { return dynamic_cast(this); } -}; -} - -#endif // !STATE_HPP diff --git a/src/state_machine.cpp b/src/state_machine.cpp deleted file mode 100644 index 647ad40..0000000 --- a/src/state_machine.cpp +++ /dev/null @@ -1,62 +0,0 @@ -#include "state_machine.hpp" -#include "state.hpp" -#include "utils/godot_macros.h" -#include -#include -#include - -namespace godot { -void StateMachine::_bind_methods() { -#define CLASSNAME StateMachine - GDPROPERTY(initial_state, Variant::STRING_NAME); -} - -void StateMachine::_enter_tree() { GDGAMEONLY(); - this->override_state(this->initial_state); -} - -void StateMachine::_exit_tree() { GDGAMEONLY(); - for(KeyValue kvp : available) - if(!kvp.value->as_node()->is_inside_tree()) - kvp.value->as_node()->queue_free(); -} - -void StateMachine::_process(double delta_time) { GDGAMEONLY(); - if(this->state) - this->override_state(this->state->get_next()); -} - -void StateMachine::override_state(StringName next) { - // don't change state if target is current - if(this->state != nullptr && next == this->state->as_node()->get_class()) - return; - if(this->state) - this->remove_child(this->state->as_node()); - if(next.is_empty()) { - this->state = nullptr; - return; - } - // instantiate new state if this type is not yet available - if(!this->available.has(next)) { - IState *instance = dynamic_cast(Object::cast_to(ClassDB::instantiate(next))); - if(instance == nullptr) { - UtilityFunctions::push_error("Failure to instantiate state with class '", next, "'"); - return; - } - this->available.insert(next, instance); - instance->init(this->get_parent(), this); - instance->as_node()->set_process_mode(ProcessMode::PROCESS_MODE_INHERIT); - } - // set the new state and add it to the tree - this->state = this->available.get(next); - this->add_child(this->state->as_node()); -} - -void StateMachine::set_initial_state(StringName name) { - this->initial_state = name; -} - -StringName StateMachine::get_initial_state() const { - return this->initial_state; -} -} diff --git a/src/state_machine.hpp b/src/state_machine.hpp deleted file mode 100644 index aa9f335..0000000 --- a/src/state_machine.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef STATE_MACHINE_HPP -#define STATE_MACHINE_HPP - -#include -#include -#include - -namespace godot { -class IState; - -class StateMachine : public Node { - GDCLASS(StateMachine, Node); - static void _bind_methods(); -public: - virtual void _enter_tree() override; - virtual void _exit_tree() override; - virtual void _process(double delta_time) override; - - void override_state(StringName new_state_class); - - void set_initial_state(StringName name); - StringName get_initial_state() const; -private: - String initial_state{}; - IState *state{nullptr}; - HashMap available{}; -}; -} - -#endif // !STATE_MACHINE_HPP