154 lines
4.1 KiB
C++
154 lines
4.1 KiB
C++
#include "player_body.h"
|
|
#include "break_utopia/level_status.h"
|
|
#include "break_utopia/player_camera.h"
|
|
#include "core/config/engine.h"
|
|
#include "core/input/input.h"
|
|
#include "scene/3d/camera_3d.h"
|
|
#include "scene/main/node.h"
|
|
#include "scene/main/viewport.h"
|
|
|
|
void PlayerBody::_bind_methods() {
|
|
}
|
|
|
|
void PlayerBody::physics_process(double delta) {
|
|
move_and_slide();
|
|
}
|
|
|
|
void PlayerBody::on_child_entered(Node *node) {
|
|
if (CharacterState * state{ cast_to<CharacterState>(node) }) {
|
|
if (!this->default_state) {
|
|
this->default_state = state;
|
|
}
|
|
}
|
|
}
|
|
|
|
void PlayerBody::_notification(int what) {
|
|
if (Engine::get_singleton()->is_editor_hint()) {
|
|
return;
|
|
}
|
|
switch (what) {
|
|
default:
|
|
return;
|
|
case NOTIFICATION_ENTER_TREE:
|
|
singleton = this;
|
|
set_process_unhandled_input(true);
|
|
set_physics_process(true);
|
|
if (!is_ready()) {
|
|
connect("child_entered_tree", callable_mp(this, &self_type::on_child_entered));
|
|
}
|
|
Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED);
|
|
return;
|
|
case NOTIFICATION_READY:
|
|
if (this->default_state) {
|
|
this->default_state->set_state_active(true);
|
|
}
|
|
return;
|
|
case NOTIFICATION_PHYSICS_PROCESS:
|
|
physics_process(get_physics_process_delta_time());
|
|
return;
|
|
case NOTIFICATION_PAUSED:
|
|
this->movement_input = {};
|
|
return;
|
|
case NOTIFICATION_EXIT_TREE:
|
|
singleton = nullptr;
|
|
return;
|
|
}
|
|
}
|
|
|
|
void PlayerBody::process_movement_input() {
|
|
this->movement_input = {
|
|
Input::get_singleton()->get_axis("move_left", "move_right"),
|
|
Input::get_singleton()->get_axis("move_forward", "move_backward")
|
|
};
|
|
this->movement_input.normalize();
|
|
}
|
|
|
|
void PlayerBody::unhandled_input(Ref<InputEvent> const &what) {
|
|
if (what->is_action("move_forward") || what->is_action("move_backward") || what->is_action("move_left") || what->is_action("move_right")) {
|
|
process_movement_input();
|
|
}
|
|
}
|
|
|
|
PlayerBody *PlayerBody::get_singleton() {
|
|
return singleton;
|
|
}
|
|
|
|
void PlayerBody::deal_damage(double damage) {
|
|
double health{ LevelStatus::get_instance()->get_player_health() };
|
|
LevelStatus::get_instance()->set_player_health(health - damage);
|
|
for (Variant var : get_children()) {
|
|
if (CharacterState * as_state{ cast_to<CharacterState>(var) }) {
|
|
if (as_state->get_state_active()) {
|
|
as_state->set_state_active(false);
|
|
}
|
|
}
|
|
}
|
|
Node *node{ get_node(NodePath("PlayerHurtState")) };
|
|
if (CharacterState * as_state{ cast_to<CharacterState>(node) }) {
|
|
as_state->set_state_active(true);
|
|
}
|
|
}
|
|
|
|
Vector3 PlayerBody::get_transformed_movement_input() const {
|
|
Basis const basis{ get_viewport()->get_camera_3d()->get_global_basis() };
|
|
Vector3 forward{ basis.get_column(2) };
|
|
Vector3 left{ basis.get_column(0) };
|
|
forward.y = left.y = 0;
|
|
return forward.normalized() * this->movement_input.y + left.normalized() * this->movement_input.x;
|
|
}
|
|
|
|
PlayerBody *PlayerBody::singleton{ nullptr };
|
|
|
|
String const CharacterState::sig_state_entered{ "state_entered" };
|
|
String const CharacterState::sig_state_exited{ "state_exited" };
|
|
|
|
void CharacterState::_bind_methods() {
|
|
ADD_SIGNAL(MethodInfo(sig_state_entered));
|
|
ADD_SIGNAL(MethodInfo(sig_state_exited));
|
|
}
|
|
|
|
void CharacterState::_notification(int what) {
|
|
if (Engine::get_singleton()->is_editor_hint()) {
|
|
return;
|
|
}
|
|
switch (what) {
|
|
default:
|
|
return;
|
|
case NOTIFICATION_ENTER_TREE:
|
|
// turn these off just in case
|
|
set_process(false);
|
|
set_physics_process(false);
|
|
set_process_input(false);
|
|
set_process_unhandled_input(false);
|
|
Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED);
|
|
return;
|
|
}
|
|
}
|
|
|
|
void CharacterState::switch_state(NodePath path) {
|
|
this->set_state_active(false);
|
|
stack_state(path);
|
|
}
|
|
|
|
void CharacterState::stack_state(NodePath path) {
|
|
if (CharacterState * new_state{ cast_to<CharacterState>(get_node(path)) }) {
|
|
new_state->set_state_active(true);
|
|
}
|
|
}
|
|
|
|
void CharacterState::state_entered() {}
|
|
|
|
void CharacterState::state_exited() {}
|
|
|
|
void CharacterState::set_state_active(bool active) {
|
|
if (active != this->active_state) {
|
|
if (active) {
|
|
state_entered();
|
|
emit_signal(sig_state_entered);
|
|
} else {
|
|
state_exited();
|
|
emit_signal(sig_state_exited);
|
|
}
|
|
}
|
|
this->active_state = active;
|
|
}
|