135 lines
4.1 KiB
C++
135 lines
4.1 KiB
C++
#include "player_body.h"
|
|
#include "health_status.h"
|
|
#include "macros.h"
|
|
#include "player_camera.h"
|
|
#include "player_input.h"
|
|
#include "weapon_base.h"
|
|
#include "weapon_inventory.h"
|
|
|
|
PlayerBody *PlayerBody::singleton_instance{ nullptr };
|
|
|
|
void PlayerBody::_bind_methods() {
|
|
}
|
|
|
|
void PlayerBody::on_child_entered(Node *node) {
|
|
node->connect("child_entered_tree", callable_mp(this, &self_type::on_child_entered));
|
|
if (PlayerInput * input{ cast_to<PlayerInput>(node) }) {
|
|
input->connect(PlayerInput::sig_movement_input, callable_mp(this, &self_type::set_movement_input));
|
|
input->connect(PlayerInput::sig_jump, callable_mp(this, &self_type::on_jump_input));
|
|
input->connect(PlayerInput::sig_run, callable_mp(this, &self_type::on_run_input));
|
|
}
|
|
if (WeaponInventory * inventory{ cast_to<WeaponInventory>(node) }) {
|
|
this->weapons = inventory;
|
|
}
|
|
if (HealthStatus * health{ cast_to<HealthStatus>(node) }) {
|
|
this->health = health;
|
|
}
|
|
if (PlayerCamera * camera{ cast_to<PlayerCamera>(node) }) {
|
|
this->camera = camera;
|
|
}
|
|
}
|
|
|
|
void PlayerBody::process(double delta) {
|
|
float const target_fov{ get_is_running() ? 1.25f : 1.0f };
|
|
fov = Math::move_toward(fov, target_fov, float(delta * 2.0));
|
|
this->camera->set_fov_factor(fov);
|
|
}
|
|
|
|
void PlayerBody::physics_process(double delta) {
|
|
GETSET(velocity, {
|
|
Vector2 input{ this->movement_input.normalized() };
|
|
if (get_is_running()) {
|
|
input.y *= this->run_speed;
|
|
input.x *= this->walk_speed;
|
|
} else {
|
|
input *= this->walk_speed;
|
|
}
|
|
Basis const basis{ this->camera->get_global_basis() };
|
|
Vector3 forward{ -basis.get_column(2) };
|
|
forward.y = 0.f;
|
|
forward.normalize();
|
|
Vector3 left{ -basis.get_column(0) };
|
|
left.y = 0.f;
|
|
left.normalize();
|
|
velocity = velocity.move_toward(Vector3{ input.y * forward + input.x * left } + Vector3{ 0.f, velocity.y, 0.f }, delta * this->acceleration);
|
|
velocity += get_gravity() * delta;
|
|
});
|
|
move_and_slide();
|
|
}
|
|
|
|
void PlayerBody::set_movement_input(Vector2 state) {
|
|
this->movement_input = state;
|
|
}
|
|
|
|
void PlayerBody::on_jump_input() {
|
|
if (this->is_on_floor()) {
|
|
GETSET(velocity, {
|
|
velocity.y = this->jump_strength;
|
|
});
|
|
}
|
|
}
|
|
|
|
void PlayerBody::on_run_input(bool run) {
|
|
this->try_running = run;
|
|
}
|
|
|
|
void PlayerBody::_notification(int what) {
|
|
if (Engine::get_singleton()->is_editor_hint()) {
|
|
return; // don't run in editor
|
|
}
|
|
switch (what) {
|
|
default:
|
|
return;
|
|
case NOTIFICATION_ENTER_TREE:
|
|
singleton_instance = this;
|
|
connect("child_entered_tree", callable_mp(this, &self_type::on_child_entered));
|
|
return;
|
|
case NOTIFICATION_EXIT_TREE:
|
|
singleton_instance = nullptr;
|
|
return;
|
|
case NOTIFICATION_READY:
|
|
set_process(true);
|
|
set_physics_process(true);
|
|
return;
|
|
case NOTIFICATION_PROCESS:
|
|
process(get_process_delta_time());
|
|
return;
|
|
case NOTIFICATION_PHYSICS_PROCESS:
|
|
physics_process(get_physics_process_delta_time());
|
|
return;
|
|
}
|
|
}
|
|
|
|
PackedStringArray PlayerBody::get_configuration_warnings() const {
|
|
PackedStringArray warnings{ super_type::get_configuration_warnings() };
|
|
if (find_children("*", HealthStatus::get_class_static()).is_empty()) {
|
|
warnings.push_back("This node has no health status and will cause crashes.\nConsider adding HealthStatus node as a child.");
|
|
}
|
|
if (find_children("*", PlayerInput::get_class_static()).is_empty()) {
|
|
warnings.push_back("This node has no input dispatcher and will cause crashes.\nConsider adding a PlayerInput node as a child.");
|
|
}
|
|
if (find_children("*", WeaponInventory::get_class_static()).is_empty()) {
|
|
warnings.push_back("This node has no inventory and will cause crashes.\nConsider adding a WeaponInventory node as a child.");
|
|
}
|
|
if (find_children("*", PlayerCamera::get_class_static()).is_empty()) {
|
|
warnings.push_back("This node has no camera of type PlayerCamera, expect crashes.\nConsider adding a PlayerCamera node as a child.");
|
|
}
|
|
return warnings;
|
|
}
|
|
|
|
PlayerBody *PlayerBody::get_singleton() {
|
|
return singleton_instance;
|
|
}
|
|
|
|
bool PlayerBody::get_is_running() const {
|
|
return get_wants_to_run() && this->weapons->get_current_weapon()->allows_running();
|
|
}
|
|
|
|
bool PlayerBody::get_wants_to_run() const {
|
|
return this->try_running && this->movement_input.y > 0.f;
|
|
}
|
|
|
|
HealthStatus *PlayerBody::get_health() const {
|
|
return this->health;
|
|
}
|