summaryrefslogtreecommitdiff
path: root/src/playercontroller.cpp
diff options
context:
space:
mode:
authorAnson Bridges <bridges.anson@gmail.com>2022-09-19 17:44:22 -0400
committerAnson Bridges <bridges.anson@gmail.com>2022-09-19 17:44:22 -0400
commit1d347e770fddcdd051890cdf070fd2779ab113bf (patch)
tree6501fb000509819b7ba58df15c9a831c8bdc44fb /src/playercontroller.cpp
parent2fd755132f526c48fed2c1867530526971e1cf19 (diff)
problems: player controller perf, boat perf, NAVSERVER PERF
Diffstat (limited to 'src/playercontroller.cpp')
-rw-r--r--src/playercontroller.cpp313
1 files changed, 313 insertions, 0 deletions
diff --git a/src/playercontroller.cpp b/src/playercontroller.cpp
new file mode 100644
index 0000000..edf85be
--- /dev/null
+++ b/src/playercontroller.cpp
@@ -0,0 +1,313 @@
+#include "playercontroller.h"
+
+using namespace godot;
+
+PlayerController::PlayerController () { }
+PlayerController::~PlayerController () { }
+
+void PlayerController::_register_methods() {
+ register_method("_ready", &PlayerController::_ready);
+ register_method("get_init_info", &PlayerController::get_init_info);
+ register_method("mp_init", &PlayerController::mp_init);
+ register_method("set_phys_transform", &PlayerController::set_phys_transform, GODOT_METHOD_RPC_MODE_REMOTE);
+ register_method("_process", &PlayerController::_process);
+ register_method("initiate_use", &PlayerController::initiate_use);
+ register_method("set_net_owner", &PlayerController::set_net_owner, GODOT_METHOD_RPC_MODE_REMOTESYNC);
+ register_method("deselect_character", &PlayerController::deselect_character);
+ register_method("take_control_of_machine", &PlayerController::take_control_of_machine);
+ register_method("lose_machine", &PlayerController::lose_machine);
+ register_method("_physics_process", &PlayerController::_physics_process);
+ register_method("on_floor_test", &PlayerController::on_floor_test);
+ register_method("_integrate_forces", &PlayerController::_integrate_forces);
+ register_method("walk", &PlayerController::walk);
+ register_method("jump", &PlayerController::jump);
+ register_method("swim", &PlayerController::swim);
+ register_method("enter_water", &PlayerController::enter_water);
+ register_method("exit_water", &PlayerController::exit_water);
+ register_method("mount_ladder", &PlayerController::mount_ladder);
+ register_method("climb_ladder", &PlayerController::climb_ladder);
+ register_method("leave_ladder", &PlayerController::leave_ladder);
+ register_method("damage", &PlayerController::damage, GODOT_METHOD_RPC_MODE_REMOTESYNC);
+ register_method("remove_dead_character", &PlayerController::remove_dead_character, GODOT_METHOD_RPC_MODE_REMOTESYNC);
+ register_method("net_apply_impulse", &PlayerController::net_apply_impulse, GODOT_METHOD_RPC_MODE_REMOTESYNC);
+
+ register_property<PlayerController, String>("team", &PlayerController::team, String("RED"));
+ register_property<PlayerController, int>("health", &PlayerController::health, int(100));
+ register_property<PlayerController, float>("mouse_sensitivity", &PlayerController::mouse_sensitivity, float(12.0));
+ register_property<PlayerController, float>("FOV", &PlayerController::FOV, float(90.0));
+ register_property<PlayerController, float>("jump_height", &PlayerController::jump_height, float(300.0));
+ register_property<PlayerController, bool>("is_player", &PlayerController::is_player, bool(false));
+ register_property<PlayerController, float>("walk_speed", &PlayerController::walk_speed, float(5.0));
+}
+
+void PlayerController::_init() {
+ weapon = nullptr;
+ world = nullptr;
+ mouse_axis = Vector2::ZERO;
+ velocity = Vector3::ZERO;
+ direction = Vector3::ZERO;
+ move_axis = Vector2::ZERO;
+ floorspeed = Vector3::ZERO;
+ jumping = false;
+ can_jump = true;
+ FLOOR_MAX_ANGLE = deg2rad(46.0);
+ in_water = false;
+ swim_speed = 450.0;
+ climb_speed = 5.0;
+ controlling_machine = false;
+ machine = nullptr;
+ ladder_m = nullptr;
+ player_state = nullptr;
+ is_on_floor = false;
+ floor_normal = Vector3::UP;
+ acceleration = 80.0;
+ c_friction = 4.0;
+ air_control = 0.3;
+}
+
+void PlayerController::_ready() {
+ head = get_node<Spatial>(NodePath("Neck/Head"));
+ neck = get_node<Spatial>(NodePath("Neck"));
+ nav = get_node<NavigationAgent>(NodePath("NavigationAgent"));
+ weapon = (Node *)ResourceLoader::get_singleton()->load("res://scenes/weapons/w_Rockets.tscn")->instance()
+ add_child(weapon)
+ world = get_tree()->get_root()->get_node("GAMEWORLD")
+}
+
+Dictionary PlayerController::get_init_info() {
+ return Dictionary::make("linear_velocity", get_linear_velocity(), "angular_velocity", get_angular_velocity(), "controlling_machine", controlling_machine, "team", team, "health", health, "nametag", get_node<Label3D>("Nametag")->get_text());
+}
+
+void PlayerController::mp_init(Dictionary init_info) {
+ for(int i = 0; i < init_info.keys().size(); i++)
+ set(init_info.keys()[i], init_info[init_info.keys()[i]]);
+ get_node<Label3D>("Nametag")->set_text(init_info["nametag"]);
+}
+
+void PlayerController::set_phys_transform(Transform trfrm, Vector3 lvel) {
+ set_transform(trfrm);
+ set_linear_velocity(lvel);
+}
+
+PlayerController::_process(float _delta) {
+// if is_player and !world.is_chatting:
+// if Input.is_action_just_pressed("use"):
+// initiate_use()
+}
+
+void PlayerController::initiate_use() {
+// if controlling_machine:
+// machine.relinquish_control()
+// return
+// if ladder_m != null:
+// leave_ladder()
+// return
+// if $"%UseRay".is_colliding():
+// var area_c = $"%UseRay".get_collider()
+// match area_c.name:
+// "SteerArea":
+// world.rpc_id(1, "_call_on_server", "_client_request_control_vehicle", {"id" : world.client_id, "machine_path" : area_c.get_parent().get_path(), "char_name" : name})
+// "LadderArea":
+// mount_ladder(area_c.get_parent())
+// "TugArea":
+// pass
+// "PickupArea":
+// pass
+// _:
+// pass
+}
+
+void PlayerController::set_net_owner(int owner_id) {
+// $Nametag.text = ""
+// set_network_master(owner_id)
+// if owner_id != 1:
+// $Nametag.text = world.players_info[owner_id][0]
+// if get_tree().get_network_unique_id() != 1:
+// if owner_id == world.client_id:
+// $Nametag.visible = false
+// world.player_char = self
+// is_player = true
+// world.cam.attach(self, "FIRSTPERSON", "./Neck/Head")
+// else:
+// $Nametag.visible = true
+// is_player = false
+// world.get_node("HUD").update_characters()
+}
+
+void PlayerController::deselect_character() {
+// if is_network_master():
+// world.player_char = null
+// if world.client_id != 1: world.cam.attach(world, "STATIC", "./DEFAULTCAM")
+// rpc("set_net_owner", 1)
+}
+
+void PlayerController::take_control_of_machine(RigidBody *slave_machine) {
+ machine = slave_machine;
+ controlling_machine = true;
+}
+
+void PlayerController::lose_machine() {
+ if is_network_master()world.cam.attach(self, "FIRSTPERSON", "./Neck/Head");
+ controlling_machine = false;
+ machine = nullptr;
+}
+
+PlayerController::_physics_process(float delta) {
+ if(is_network_master()) {
+ if (ladder_m != nullptr)
+ climb_ladder(delta);
+ else if( !on_floor_test() && in_water)
+ swim(delta);
+ else
+ walk(delta);
+ is_on_floor = false;// #reset whether is on floor in between frames
+ }
+}
+
+bool PlayerController::on_floor_test() {
+ const RayCast *feet = get_node<RayCast>("Feet");
+ if(feet->is_colliding()){
+ is_on_floor = true;
+ floor_normal = Vector3::UP;
+ floorspeed = feet->get_collider()->has_method("get_linear_velocity") ? feet->get_collider()->get_linear_velocity() : Vector3::ZERO;
+ return true;
+ }
+ if(player_state){
+ for(int i = 0;i< player_state->get_contact_count()) {
+ float contact_angle_from_up = Vector3::UP.angle_to(player_state->get_contact_local_normal(i))
+ if(contact_angle_from_up < FLOOR_MAX_ANGLE) {
+ floor_normal = player_state->get_contact_local_normal(i);
+ is_on_floor = true;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+void PlayerController::_integrate_forces(PhysicsDirectBodyState *state) {
+ if(!is_network_master()) return;
+ player_state = state;
+ velocity = state->get_linear_velocity();
+ for(int i=0; i < player_state->get_contact_count(); i++) {
+ float contact_angle_from_up = Vector3::UP.angle_to(player_state->get_contact_local_normal(i));
+ if(contact_angle_from_up > FLOOR_MAX_ANGLE && !is_on_floor){
+ set_friction(0);
+ break;
+ }
+ if(i == player_state.get_contact_count() - 1)
+ set_friction(1);
+ }
+ rpc("set_phys_transform", get_transform(), get_linear_velocity());
+ if(get_global_transform().origin.y < -30)
+ rpc("damage", 500000, "drown", Array::make(1, "Davy Jones"]);
+}
+
+void PlayerController::walk(float _delta) {
+// # Input
+// direction = Vector3()
+// var aim: Basis = head.get_global_transform().basis
+// direction += -move_axis.x * aim.z + move_axis.y * aim.x
+// direction.y = 0
+// direction = direction.normalized()
+//
+// if floor_normal != Vector3.UP: direction = direction.rotated(floor_normal.cross(Vector3.UP).normalized(), Vector3.UP.angle_to(floor_normal))
+//
+// # Jump
+// if is_player and jumping and is_on_floor and can_jump:
+// jump()
+//
+// #max walk speed
+// var _speed = walk_speed
+// var _temp_accel: float = acceleration
+// var _cspeed = sqrt(pow(velocity.x-floorspeed.x,2)+pow(velocity.z-floorspeed.z,2))
+//
+// if not is_on_floor:
+// _temp_accel *= air_control
+}
+
+void PlayerController::jump() {
+ can_jump = false;
+ apply_central_impulse(Vector3.UP*jump_height);
+ yield(get_tree().create_timer(0.05),"timeout");
+ can_jump = true;
+}
+
+void PlayerController::swim(float _delta) {
+// #drag and buoyancy
+ add_central_force(Vector3.UP*weight*1.0);
+ add_central_force(-1*linear_velocity*100);
+// #controls
+ Basis dir = head->get_global_transform().basis;
+ Vector3 m_dir = -move_axis.x * dir.z + move_axis.y * dir.x;
+ m_dir = m_dir.normalized();
+ add_central_force(swim_speed*m_dir);
+ if(jumping) add_central_force(Vector3.UP*get_weight()*0.5);
+}
+
+void PlayerController::enter_water() {
+ in_water = true;
+}
+
+void PlayerController::exit_water() {
+ in_water = false;
+}
+
+void PlayerController::mount_ladder(Spatial target_ladder) {
+// var ladder_tracker = Spatial.new()
+// ladder_tracker.name = name
+// target_ladder.add_child(ladder_tracker)
+// ladder_tracker.transform = target_ladder.bottom.transform
+//
+// ladder_tracker.global_transform.origin = target_ladder.get_nearest_point_to_route(global_transform.origin)
+// look_at(global_transform.origin + target_ladder.global_transform.basis.x, target_ladder.global_transform.basis.y)
+//
+// ladder_m = ladder_tracker
+// global_transform.origin = ladder_m.global_transform.origin
+// global_transform.basis = ladder_m.global_transform.basis.orthonormalized()
+// linear_velocity = Vector3.ZERO
+// set_gravity_scale(0.0)
+}
+
+void PlayerController::climb_ladder(float delta) {
+// var new_ladder_pos = ladder_m.global_transform.origin + ladder_m.global_transform.basis.y.normalized() * move_axis.x * delta * climb_speed
+// var prog = ladder_m.get_parent().get_climb_scalar(new_ladder_pos)
+// if prog >= 0.0 and prog <= 1.0:
+// ladder_m.global_transform.origin = new_ladder_pos
+// global_transform.origin = ladder_m.global_transform.origin
+// global_transform.basis = ladder_m.global_transform.basis.orthonormalized()
+}
+
+void PlayerController::leave_ladder() {
+// if (ladder_m.get_parent().top.global_transform.origin - global_transform.origin).length_squared() < 0.01:
+// apply_central_impulse(-400*ladder_m.global_transform.basis.z)
+// global_transform.basis = world.global_transform.basis
+// set_gravity_scale(1.0)
+// ladder_m.queue_free()
+// ladder_m = null
+}
+
+void PlayerController::damage(int dmg_amt, String _type, Array shooter, String extra = ".") {
+ health -= dmg_amt;
+// if health <= 0 and is_network_master():
+// if shooter[0] != get_network_master() and shooter[0] != 1: world.rpc_id(shooter[0], "game_killsound")
+// if get_network_master() == 1:
+// world._call_on_server("_character_death", {"killer_id" : shooter[0], "killer" : shooter[1], "victim_mp_id" : get_network_master(), "victim" : name, "extra" : extra})
+// else:
+// world.rpc_id(1, "_call_on_server", "_character_death", {"killer_id" : shooter[0], "killer" : shooter[1], "victim_mp_id" : get_network_master(), "victim" : name, "extra" : extra})
+// elif is_network_master():
+// if shooter[0] != get_network_master() and shooter[0] != 1: world.rpc_id(shooter[0], "game_hitsound")
+}
+
+void PlayerController::remove_dead_character() {
+ if(is_network_master() && machine != nullptr)
+ machine->call("relinquish_control");
+ deselect_character();
+ queue_free();
+}
+
+void PlayerController::net_apply_impulse(Vector3 impulse_v) {
+ apply_central_impulse(impulse_v);
+}
+
+