116 lines
3.5 KiB
C++
116 lines
3.5 KiB
C++
#include "player_body.h"
|
|
#include "health_status.h"
|
|
#include "macros.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) {
|
|
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_look_input, callable_mp(this, &self_type::on_look_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;
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
velocity = velocity.move_toward(Vector3{ input.y * get_global_basis().get_column(2) + input.x * get_global_basis().get_column(0) } + 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_look_input(Vector2 look) {
|
|
rotate_y(look.x);
|
|
}
|
|
|
|
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_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.");
|
|
}
|
|
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 && this->is_on_floor();
|
|
}
|
|
|
|
HealthStatus *PlayerBody::get_health() const {
|
|
return this->health;
|
|
}
|