extends CharacterBody3D class_name Character const NORMAL_SPEED = 6.0 const SPRINT_SPEED = 10.0 const JUMP_VELOCITY = 10 enum SkinColor { BLUE, YELLOW, GREEN, RED } @onready var nickname: Label3D = $PlayerNick/Nickname @export_category("Objects") @export var _body: Node3D = null @export var _spring_arm_offset: Node3D = null @export_category("Skin Colors") @export var blue_texture : CompressedTexture2D @export var yellow_texture : CompressedTexture2D @export var green_texture : CompressedTexture2D @export var red_texture : CompressedTexture2D @onready var _bottom_mesh: MeshInstance3D = get_node("3DGodotRobot/RobotArmature/Skeleton3D/Bottom") @onready var _chest_mesh: MeshInstance3D = get_node("3DGodotRobot/RobotArmature/Skeleton3D/Chest") @onready var _face_mesh: MeshInstance3D = get_node("3DGodotRobot/RobotArmature/Skeleton3D/Face") @onready var _limbs_head_mesh: MeshInstance3D = get_node("3DGodotRobot/RobotArmature/Skeleton3D/Llimbs and head") var _current_speed: float var _respawn_point = Vector3(0, 5, 0) var gravity = ProjectSettings.get_setting("physics/3d/default_gravity") func _enter_tree(): set_multiplayer_authority(str(name).to_int()) $SpringArmOffset/SpringArm3D/Camera3D.current = is_multiplayer_authority() func _ready(): return func _physics_process(delta): if not is_multiplayer_authority(): return var current_scene = get_tree().get_current_scene() if current_scene and current_scene.has_method("is_chat_visible") and current_scene.is_chat_visible() and is_on_floor(): freeze() return if not is_on_floor(): velocity.y -= gravity * delta _body.animate(velocity) if is_on_floor(): if Input.is_action_just_pressed("jump"): velocity.y = JUMP_VELOCITY else: velocity.y -= gravity * delta _move() move_and_slide() _body.animate(velocity) func _process(_delta): if not is_multiplayer_authority(): return _check_fall_and_respawn() func freeze(): velocity.x = 0 velocity.z = 0 _current_speed = 0 _body.animate(Vector3.ZERO) func _move() -> void: var _input_direction: Vector2 = Vector2.ZERO if is_multiplayer_authority(): _input_direction = Input.get_vector( "move_left", "move_right", "move_forward", "move_backward" ) var _direction: Vector3 = transform.basis * Vector3(_input_direction.x, 0, _input_direction.y).normalized() is_running() _direction = _direction.rotated(Vector3.UP, _spring_arm_offset.rotation.y) if _direction: velocity.x = _direction.x * _current_speed velocity.z = _direction.z * _current_speed _body.apply_rotation(velocity) return velocity.x = move_toward(velocity.x, 0, _current_speed) velocity.z = move_toward(velocity.z, 0, _current_speed) func is_running() -> bool: if Input.is_action_pressed("shift"): _current_speed = SPRINT_SPEED return true else: _current_speed = NORMAL_SPEED return false func _check_fall_and_respawn(): if global_transform.origin.y < -15.0: _respawn() func _respawn(): global_transform.origin = _respawn_point velocity = Vector3.ZERO @rpc("any_peer", "reliable") func change_nick(new_nick: String): if nickname: nickname.text = new_nick func get_texture_from_name(skin_color: SkinColor) -> CompressedTexture2D: match skin_color: SkinColor.BLUE: return blue_texture SkinColor.GREEN: return green_texture SkinColor.RED: return red_texture SkinColor.YELLOW: return yellow_texture _: return blue_texture @rpc("any_peer", "reliable") func set_player_skin(skin_name: SkinColor) -> void: var texture = get_texture_from_name(skin_name) set_mesh_texture(_bottom_mesh, texture) set_mesh_texture(_chest_mesh, texture) set_mesh_texture(_face_mesh, texture) set_mesh_texture(_limbs_head_mesh, texture) func set_mesh_texture(mesh_instance: MeshInstance3D, texture: CompressedTexture2D) -> void: if mesh_instance: var material := mesh_instance.get_surface_override_material(0) if material and material is StandardMaterial3D: var new_material := material new_material.albedo_texture = texture mesh_instance.set_surface_override_material(0, new_material)