From 1d347e770fddcdd051890cdf070fd2779ab113bf Mon Sep 17 00:00:00 2001 From: Anson Bridges Date: Mon, 19 Sep 2022 17:44:22 -0400 Subject: problems: player controller perf, boat perf, NAVSERVER PERF --- src/PlayerController.gd | 297 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 297 insertions(+) create mode 100644 src/PlayerController.gd (limited to 'src/PlayerController.gd') diff --git a/src/PlayerController.gd b/src/PlayerController.gd new file mode 100644 index 0000000..241cbe0 --- /dev/null +++ b/src/PlayerController.gd @@ -0,0 +1,297 @@ +extends RigidBody + +# Game +export var team: String = "RED" +export var health: int = 100 +var weapon: Node = null +var world: Spatial = null + +# Camera +export var mouse_sensitivity:float = 12.0 +export var FOV:float = 90.0 +var mouse_axis: Vector2 = Vector2.ZERO +onready var head: Spatial = $Neck/Head +onready var neck: Spatial = $Neck + +# Move +var velocity := Vector3() +var direction := Vector3() +var move_axis := Vector2() +var floorspeed := Vector3() +var jumping:bool = false +var can_jump:bool = true +onready var nav: NavigationAgent = $NavigationAgent + +# Walk +const FLOOR_MAX_ANGLE: float = deg2rad(46.0) +export var jump_height: float = 300.0 +var in_water : bool = false +var swim_speed : float = 450.0 +var climb_speed : float = 5.0 + +# Control +var controlling_machine: bool = false #whether character is riding/controlling something +var machine : RigidBody = null +export var is_player: bool = false #whether character is currently controlled by a player +var ladder_m: Spatial = null + +#physics +var player_state: PhysicsDirectBodyState = null +var is_on_floor:bool +var floor_normal : Vector3 = Vector3.UP +var acceleration:float = 80.0 +export var walk_speed:float = 5.0 +var c_friction:float = 4.0 +var air_control:float = 0.3 + +# Called when the node enters the scene tree +func _ready() -> void: + weapon = preload("res://scenes/weapons/w_Rockets.tscn").instance() + add_child(weapon) + world = get_tree().get_root().get_node("GAMEWORLD") + + $"%UseRay".add_exception(self) + $"%MeleeRay".add_exception(self) + $"%UseRay".add_exception($AreaDetect) + $"%MeleeRay".add_exception($AreaDetect) + +func get_init_info() -> Dictionary: + return {"linear_velocity" : linear_velocity, "angular_velocity" : angular_velocity, "controlling_machine" : controlling_machine, "team" : team, "health" : health, "nametag" : $Nametag.text} + +func mp_init(init_info: Dictionary): + for variable in init_info.keys(): + set(variable, init_info[variable]) + $Nametag.text = init_info["nametag"] + +remote func set_phys_transform(trfrm: Transform, lvel: Vector3): + transform = trfrm + linear_velocity = lvel + +# Called every frame. 'delta' is the elapsed time since the previous frame +func _process(_delta: float) -> void: + if is_player and !world.is_chatting: + if Input.is_action_just_pressed("use"): + initiate_use() + + if controlling_machine: + if Input.is_action_just_pressed("fire"): + machine.attack1() + if Input.is_action_just_pressed("fire2"): + machine.attack2() + machine.direction_input(Input.get_action_strength("move_forward"),Input.get_action_strength("move_backward"), Input.get_action_strength("move_right"),Input.get_action_strength("move_left"), Input.get_action_strength("alt_right"),Input.get_action_strength("alt_left")) + machine.misc_input(Input.get_action_strength("move_duck"),Input.get_action_strength("move_jump"),Input.get_action_strength("move_walk")) + machine.mouse_input(Input.get_action_strength("fire"), Input.get_action_strength("fire3"),Input.get_action_strength("fire2")) + else: + jumping = Input.get_action_strength("move_jump") + if Input.is_action_just_pressed("fire"): + weapon.attack1() + move_axis.x = Input.get_action_strength("move_forward") - Input.get_action_strength("move_backward") + move_axis.y = Input.get_action_strength("move_right") - Input.get_action_strength("move_left") + + +func 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 + +remotesync func set_net_owner(owner_id: int): + $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() + +func 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) + +func take_control_of_machine(slave_machine: RigidBody): + machine = slave_machine + controlling_machine = true + +func lose_machine(): + if is_network_master(): world.cam.attach(self, "FIRSTPERSON", "./Neck/Head") + controlling_machine = false + machine = null + +# Called every physics tick. 'delta' is constant +func _physics_process(delta: float) -> void: + if is_network_master(): + if ladder_m != null: + climb_ladder(delta) + elif !on_floor_test() and in_water: + swim(delta) + else: + walk(delta) + is_on_floor = false #reset whether is on floor in between frames + +# called each physics frame +func on_floor_test() -> bool: + if $Feet.is_colliding(): + is_on_floor = true + floor_normal = Vector3.UP + floorspeed = $Feet.get_collider().get_linear_velocity() if $Feet.get_collider().has_method("get_linear_velocity") else Vector3.ZERO + return true + if player_state: + for i in range(player_state.get_contact_count()): + var contact_angle_from_up : float = 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 + +#modify simulated physics results +func _integrate_forces(state: PhysicsDirectBodyState) -> void: + if !is_network_master(): + return + player_state = state + velocity = state.get_linear_velocity() + $normal_vis.look_at($normal_vis.global_transform.origin + global_transform.basis.z, floor_normal) + for i in range(player_state.get_contact_count()): + var contact_angle_from_up : float = Vector3.UP.angle_to(player_state.get_contact_local_normal(i)) + if contact_angle_from_up > FLOOR_MAX_ANGLE and !is_on_floor: + friction = 0 + break + if i == player_state.get_contact_count() - 1: + friction = 1 + + rpc("set_phys_transform", transform, linear_velocity) + if global_transform.origin.y < -30: + rpc("damage", 500000, "drown", [1, "Davy Jones"]) + +func walk(_delta: float) -> void: + # 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 + + var projVel = Vector2(velocity.x-floorspeed.x,velocity.z-floorspeed.z).dot(Vector2(direction.x,direction.z)) + + if is_on_floor: + add_central_force(-mass*_cspeed*linear_velocity.normalized()*c_friction)#friction + if _speed - _cspeed > 0: + add_central_force (mass*Vector3(direction.x*_temp_accel, 0, direction.z*_temp_accel))#velocity.x += direction.x*_temp_accel + else: + add_central_force(mass*Vector3(direction.x*(_speed-projVel), 0, direction.z*(_speed-projVel))) + elif 1.0 - projVel > 0: + add_central_force (mass*Vector3(direction.x*_temp_accel, 0, direction.z*_temp_accel)) + +func jump(): + can_jump = false + apply_central_impulse(Vector3.UP*jump_height) + yield(get_tree().create_timer(0.05),"timeout") + can_jump = true + +func swim(_delta: float): + #drag and buoyancy + add_central_force(Vector3.UP*weight*1.0) + add_central_force(-1*linear_velocity*100) + #controls + var dir: Basis = head.get_global_transform().basis + var m_dir: Vector3 = -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*weight*0.5) + +func enter_water(): + in_water = true + +func exit_water(): + in_water = false + +func mount_ladder(target_ladder: Spatial): + 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) + +#called each frame while climbing ladder +func climb_ladder(delta: float): + 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() + +func 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 + +remotesync func damage(dmg_amt: int, _type: String, shooter: Array, extra: String): + 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") + +remotesync func remove_dead_character(): + if is_network_master() and machine != null: + machine.relinquish_control() + deselect_character() + queue_free() + +remotesync func net_apply_impulse(impulse_v: Vector3): + apply_central_impulse(impulse_v) -- cgit v1.2.3