extends KinematicBody export(String, "red", "blue") var team #item variables var can_swap = true var has_items = [false,false,false,false,false] var items = [null,null,null,null,null] export(String) var item0path export(String) var item1path export(String) var item2path export(String) var item3path export(String) var item4path var weapon export(int) var health = 100 var unit var move_axis := Vector2() var velocity := Vector3() var direction := Vector3() var parentvel := Vector3() var tugging = false var tug_target export(float) var friction = 4 export(float) var _airspeed_cap = 1 var is_duck = 0 const duck_height = .5*.6*1.8 #one half the hitbox duck height var duck_speed = 2.3 var knockback_mult = 1 var duck_progress = 0 var can_switch = true const gravity = 9.8 const FLOOR_MAX_ANGLE: float = deg2rad(46.0) const jump_constant = 12 const walk_speed = 6 const tug_speed = 1.5 const acceleration = 70 const air_control = 0.3 const tug_force = 500 const tug_distance = 3.5 const push_distance = 1 const duck_knockback_mult = 1.35 const jump_vel = 5 static func compare_floats(a, b, epsilon = 0.00001): return abs(a - b) <= epsilon # Called when the node enters the scene tree for the first time. func _ready(): $Camera/UseRay.add_exception(self) $Camera/MeleeRay.add_exception(self) func damage(amount, attacker, point = Vector3.ZERO): health -= amount rpc("update_health",health) if health <= 0: if is_network_master(): get_node("/root/Game/Camera").current = true rpc("die") # Called every frame. 'delta' is the elapsed time since the previous frame. func _process(delta): if is_network_master() and !get_node('/root/Game/HUD/Selection').is_visible_in_tree(): if Input.is_action_just_pressed("use"): pass move_axis.x = Input.get_action_strength("walk_forward") - Input.get_action_strength("walk_backward") move_axis.y = Input.get_action_strength("strafe_right") - Input.get_action_strength("strafe_left") is_duck = Input.get_action_strength("duck") if Input.is_action_just_pressed("attack1"): weapon.attack() if Input.is_action_just_pressed("attack2"): weapon.attack2() if Input.is_action_just_pressed("slot1"): rpc('switch_weapon',0) if Input.is_action_just_pressed("slot2"): rpc('switch_weapon',1) func initiate_use(): if tugging: tugging = false elif $Camera/UseRay.is_colliding(): var type = $Camera/UseRay.get_collider().name match type: "TugArea": tugging = true tug_target = $Camera/UseRay.get_collider().get_parent() _: pass func check_tug(): if !$Camera/UseRay.is_colliding() or !($Camera/UseRay.get_collider().name != tug_target.name): tugging = false func _physics_process(delta): if is_network_master() or (get_tree().get_network_unique_id() == 1 and get_network_master() == -1): if is_network_master(): player_move(delta) else: ai_move(delta) rpc("_set_position", global_transform) remotesync func update_health(new_h): health = new_h if is_network_master(): get_tree().get_root().get_node('Game/HUD/Health').text = str(health) func ai_move(delta): if !is_on_floor(): velocity.y -= gravity * delta move_and_slide(velocity,Vector3.UP) func player_move(delta): # Input direction = Vector3() var aim: Basis = get_global_transform().basis if move_axis.x >= 0.5: direction -= aim.z elif move_axis.x <= -0.5: direction += aim.z if move_axis.y <= -0.5: direction -= aim.x elif move_axis.y >= 0.5: direction += aim.x direction.y = 0 direction = direction.normalized() # Jump var snap = Vector3.ZERO if is_on_floor(): snap = Vector3.DOWN if Input.is_action_just_pressed("jump"): snap = Vector3.ZERO velocity.y += jump_vel else: velocity += parentvel velocity.y -= gravity * delta if abs(velocity.y) > 1: snap = Vector3.ZERO #max walk speed var _speed = walk_speed if not is_duck else walk_speed*0.5 var _temp_accel: float = acceleration if is_on_floor(): var _cspeed = sqrt(pow(velocity.x,2)+pow(velocity.z,2)) if _cspeed != 0: var walkdir = Vector2(velocity.x,velocity.z) var fvar = _cspeed*friction if direction.length() != 0 else _cspeed*2*friction #fvar *= 4 if is_duck else 1 velocity.x -= walkdir.normalized().x*fvar*delta velocity.z -= walkdir.normalized().y*fvar*delta animationcontroller.rpc("run",_cspeed/walk_speed) else: animationcontroller.rpc("run",0) #rpc("_play_animation",false,"idle_single") var projVel = Vector2(velocity.x,velocity.z).dot(Vector2(direction.x,direction.z)) _temp_accel *= delta if is_on_floor(): if _speed - (projVel + _temp_accel) > 0: velocity.x += direction.x*_temp_accel velocity.z += direction.z*_temp_accel else: velocity.x += direction.x*(_speed-projVel) velocity.z += direction.z*(_speed-projVel) elif _airspeed_cap - projVel > 0: velocity.x += direction.x*_temp_accel velocity.z += direction.z*_temp_accel # clamping (to stop on slopes) if direction.dot(velocity) == 0: var _vel_clamp := 0.25 if abs(velocity.x) < _vel_clamp: velocity.x = 0 if abs(velocity.z) < _vel_clamp: velocity.z = 0 # Move var moving = move_and_slide_with_snap(velocity, snap, Vector3.UP, false, 4, FLOOR_MAX_ANGLE) if is_on_wall(): velocity = moving else: velocity.y = moving.y remotesync func die(): get_node("/root/Game").update_chars_delay() queue_free() remote func _set_position(pos): global_transform = pos #set net master of this player to the id func _set_master(id): if get_network_master() == -1: $Camera.current = true $Armature/Skeleton/Cube.set_layer_mask(524288) for unit in get_tree().get_nodes_in_group("units"): if unit.get_network_master() == id: unit.rpc("_set_master_helper",-1) #nit.set_network_master(-1) rpc("_set_master_helper", id) remotesync func _set_master_helper(id): set_network_master(id) update_health(health) if id == -1: $Armature/Skeleton/Cube.set_layer_mask(1) get_node("/root/Game").update_chars()