extends CharacterBody3D const SENSETIVITY = 0.009; enum Class_type { Spectator = 0, Astra = 1, BlackArch = 2, Kali = 3, Debian = 4, Arch = 5, Windows11 = -1, WindowsServer = -2, MacOS = -3, WindowsXP = -4, Windows10 = -5 } var Weapons = GameData.Weapons var properties var speed = 12 var walk = 12 var run = 24 var jump = 16 var gravity = 9.8 var acceleration = 2.5 var inertia = 20 var climbing = false var game_settings var client_settings var can_shoot = true var time_since_last_shot = 0 var round_status = { "cs_round_score" = 0, "os_round_score" = 0, "os_game_score" = 0, "cs_game_score" = 0, "round_number" = 0, } @onready var head = $Head @onready var camera: Camera3D = $Head/Camera @onready var playerCharacterBody = $"." @onready var collision_shapes = find_children("collision*","",false) var HUD var healthLabel var armorLabel var ammoLabel var magazineLabel var statusLabel var csScoreRoundLabel var csScoreGameLabel var osScoreRoundLabel var osScoreGameLabel var roundNumberLabel var timeLabel var winnerLabel var killLogList func set_properties(props): print("Got props from server: " + str(props)) properties = props $"Head/Nickname".text = properties["nickname"] name = "player" + str(properties["internal_id"]) position = properties["position"] if (game_settings != null): change_weapon(properties["current_weapon"]["number"]) func set_property(key, value): properties[key] = value update_state() func init_hud(): HUD = $HUD healthLabel = $"HUD/health_and_ammo_display/healthdisplay/text" armorLabel = $"HUD/health_and_ammo_display/armordisplay/text" ammoLabel = $"HUD/health_and_ammo_display/ammodisplay/text" magazineLabel = $"HUD/health_and_ammo_display/magazinedisplay/text" statusLabel = $"HUD/Status" csScoreRoundLabel = $"HUD/round_status/cs_score_round" csScoreGameLabel = $"HUD/round_status/cs_score_game" osScoreRoundLabel = $"HUD/round_status/os_score_round" osScoreGameLabel = $"HUD/round_status/os_score_game" roundNumberLabel = $"HUD/round_status/round_number" timeLabel = $"HUD/round_status/time" winnerLabel = $"HUD/round_status/winner" killLogList = $"HUD/kill_log" func update_hud(): healthLabel.text = str(properties["HP"]) armorLabel.text = str(properties["AP"]) ammoLabel.text = str(properties["current_weapon"]["ammo"]) magazineLabel.text = str(properties["current_weapon"]["magazine"]) if (properties["reloading"]): statusLabel.text = "Reloading..." else: statusLabel.text = "Reloaded" csScoreRoundLabel.text = str(round_status["cs_round_score"]) csScoreGameLabel.text = str(round_status["cs_game_score"]) osScoreRoundLabel.text = str(round_status["os_round_score"]) osScoreGameLabel.text = str(round_status["os_game_score"]) roundNumberLabel.text = "Round " + str(round_status["round_number"]) func find_weapon_name_by_number(number): var name = "" for weapon in game_settings["weapons"].keys(): if (game_settings["weapons"][weapon].number == number): name = weapon return name @rpc("authority", "call_local", "reliable") func change_weapon(new_weapon_number): var weapons = $"Head/Camera/Hand".get_children() for weapon in weapons: weapon.visible = false weapons[new_weapon_number].visible = true print("Changing weapon: " + str(new_weapon_number)) #if (properties["is_playable"]): #properties["current_weapon"] = properties["weapons"][find_weapon_name_by_number(new_weapon_number)] #properties["reloading"] = false func find_weapon_in_inventory(number): var found_weapon for weapon in properties["weapons"].values(): if weapon["number"] == number: found_weapon = weapon break return found_weapon func find_weapon_by_number(number): var found_weapon for weapon in game_settings["weapons"].keys(): if (game_settings["weapons"][weapon]["number"] == number): found_weapon = game_settings["weapons"][weapon].duplicate() break return found_weapon func find_current_weapon_by_number(number): var found_weapon for weapon in Weapons.keys(): if (Weapons[weapon]["number"] == number): found_weapon = Weapons[weapon] break return found_weapon func update_state(): camera.set_current(false) $"Head/Nickname".text = properties["nickname"] if (!properties["is_playable"]): return camera.set_current(true) if (HUD == null): var hud = load("res://scenes/HUD/hud.tscn").instantiate() add_child(hud) init_hud() update_hud() playerCharacterBody.up_direction = Vector3.UP; Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) func _ready(): update_state() func update_weapon_raycast(): var current_weapon_name = Weapons.find_key(properties["current_weapon"]) if(current_weapon_name == null): current_weapon_name = "knife" var raycast:RayCast3D = get_node("Head/Camera/viewRaycast") var weapon_raycast:RayCast3D = get_node("Head/Camera/Hand/" + str(current_weapon_name) + "/raycast") weapon_raycast.target_position = weapon_raycast.to_local(raycast.to_global(raycast.target_position) - weapon_raycast.position) func try_shoot(): print(str(properties["current_weapon"])) #var current_weapon = game_settings["weapons"].find_key(find_weapon_by_number(properties["current_weapon"]["number"])) var current_weapon = find_weapon_name_by_number(properties["current_weapon"]["number"])#game_settings["weapons"].find_key(find_weapon_by_number(properties["current_weapon"]["number"])) print("currect weapon: " + current_weapon) var current_weapon_settings = game_settings["weapons"][current_weapon] properties["reloading"] = false if (properties["current_weapon"]["magazine"] == 0): return if Input.is_action_pressed("shoot") and current_weapon_settings["fireRate"] >= 0.5 and not Input.is_action_just_pressed("shoot"): return time_since_last_shot = (Time.get_ticks_msec() - properties["last_shot"]) / 1000. if (time_since_last_shot > current_weapon_settings["fireRate"]): Networking.shot.rpc_id(1, multiplayer.get_unique_id()) properties["current_weapon"]["magazine"] -= 1 properties["last_shot"] = Time.get_ticks_msec() var raycast:RayCast3D = get_node("Head/Camera/viewRaycast") var weapon_raycast:RayCast3D = get_node("Head/Camera/Hand/" + str(current_weapon) + "/raycast") raycast.target_position.z = -current_weapon_settings["range"] raycast.force_raycast_update() raycast.force_update_transform() var target_point = raycast.get_collision_point() weapon_raycast.target_position = weapon_raycast.to_local(target_point) * 1.1 weapon_raycast.force_raycast_update() weapon_raycast.force_update_transform() weapon_raycast.rotation.y = atan((weapon_raycast.position.x - position.x) / ((-current_weapon_settings["range"]) - (abs(weapon_raycast.position.z - position.z)))) weapon_raycast.target_position.y += current_weapon_settings["spreading"] * randf() * sin(randf() * 2 * PI) weapon_raycast.target_position.z += current_weapon_settings["spreading"] * randf() * cos(randf() * 2 * PI) weapon_raycast.force_raycast_update() weapon_raycast.force_update_transform() var trace = preload("res://scenes/models/bullet_trace.tscn").instantiate() get_node("..").add_child(trace) trace.init((weapon_raycast.global_position), (weapon_raycast.get_collision_point())) func reload(): var current_weapon_instance = properties["current_weapon"] var current_weapon = game_settings["weapons"].find_key(find_weapon_by_number(current_weapon_instance["number"])) var current_weapon_settings = game_settings["weapons"][current_weapon] var to_reload = current_weapon_settings["magazine"] - current_weapon_instance["magazine"] if (properties["reloading"]): if (to_reload <= current_weapon_instance["ammo"]): current_weapon_instance["magazine"] += to_reload current_weapon_instance["ammo"] -= to_reload else: current_weapon_instance["magazine"] += current_weapon_instance["ammo"] current_weapon_instance["ammo"] = 0 properties["reloading"] = false if (HUD != null): update_hud() func _unhandled_input(event): if (!properties["is_playable"]): return var weapon_change = 0 if Input.is_action_pressed("MWU"): weapon_change = 1 if Input.is_action_pressed("MWD"): weapon_change = -1 if (weapon_change != 0): var new_weapon_number = wrap(properties["current_weapon"]["number"] + weapon_change, 0, game_settings["weapons"].size()) properties["current_weapon"] = find_weapon_in_inventory(new_weapon_number) print(str(properties["current_weapon"])) Networking.change_weapon.rpc_id(1, multiplayer.get_unique_id(), properties["current_weapon"]["number"]) if event is InputEventMouseMotion: rotate_y(-event.relative.x * SENSETIVITY) camera.rotate_x(-event.relative.y * SENSETIVITY) camera.rotation.x = clamp(camera.rotation.x, deg_to_rad(-50), deg_to_rad(60)) func _physics_process(delta): if (!properties["is_playable"]): return if (game_settings == null): return if (multiplayer.multiplayer_peer == null): properties["is_playable"] = false if Input.is_action_pressed("shoot"): try_shoot() if (HUD != null): update_hud() update_weapon_raycast() if Input.is_action_just_pressed("reload"): var current_weapon = game_settings["weapons"].find_key(find_weapon_by_number(properties["current_weapon"]["number"])) Networking.client_reloading.rpc_id(1, multiplayer.get_unique_id()) properties["reloading"] = true get_tree().create_timer(game_settings["weapons"][current_weapon]["reload"]).connect("timeout", reload) var input_dir = Input.get_vector("left", "right", "forward", "backward") var direction = (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized() if direction: velocity.x = lerp(velocity.x, direction.x * speed, delta * acceleration) velocity.z = lerp(velocity.z, direction.z * speed, delta * acceleration) if (climbing): print(str(input_dir)) velocity.y = -input_dir.y * jump / 2 if input_dir.x == 0 else abs(input_dir.x) * jump / 2 else: if is_on_floor(): velocity.x = lerp(velocity.x, direction.x * speed * 0.5, delta * inertia) velocity.z = lerp(velocity.z, direction.z * speed * 0.5, delta * inertia) elif not is_on_floor() and not climbing: velocity.x = lerp(velocity.x, direction.x * speed * 0.5, delta) velocity.z = lerp(velocity.z, direction.z * speed * 0.5, delta) if is_on_floor(): if Input.is_action_just_pressed("jump"): velocity.y = jump if Input.is_action_pressed("run"): speed = run else: speed = walk else: velocity.y -= 4 * gravity * delta velocity.x = lerp(velocity.x, direction.x * speed, delta) velocity.z = lerp(velocity.z, direction.z * speed, delta) move_and_slide() for index in get_slide_collision_count(): var collision := get_slide_collision(index) var body := collision.get_collider() if ("ladder" in body.name): climbing = true else: climbing = false #print("Collided with: " + body.name) if (!multiplayer.is_server()): Networking.sync_client.rpc_id(1, multiplayer.get_unique_id(), $".".position, {"y": rotation.y, "x": camera.rotation.x}) #print("I am " + $"..".name +", belonging of " + str(multiplayer.get_unique_id()) + ", with internal ID: " + str(properties["internal_id"])) @rpc ("authority", "call_remote", "unreliable") func sync_puppet(i_id, p, rot): if(!properties["ready"]): return if(properties["is_playable"]): return if (int(i_id) == properties["internal_id"]): playerCharacterBody.position = p rotation.y = rot.y camera.rotation.x = rot.x @rpc ("authority", "call_remote", "reliable") func set_hp(hp): if (!properties["is_playable"]): return properties["HP"] = hp @rpc ("authority", "call_remote", "reliable") func set_game_settings(s): game_settings = s gravity = game_settings["moving"]["gravity"] walk = game_settings["moving"]["walk"] run = game_settings["moving"]["run"] jump = game_settings["moving"]["jump"] acceleration = game_settings["moving"]["acceleration"] inertia = game_settings["moving"]["inertia"] change_weapon(properties["current_weapon"]["number"]) GameData.apply_weapon_settings(game_settings["weapons"]) Weapons = GameData.Weapons @rpc ("authority", "call_remote", "reliable") func teleport(pos): position = pos @rpc ("authority", "call_remote", "reliable") func change_weapon_puppet(i_id, new_weapon_number): if (int(i_id) == properties["internal_id"]): change_weapon(new_weapon_number) @rpc("authority", "call_remote", "reliable") func update_round_status(s): print("Updated round status: " + str(s)) round_status = s if(HUD != null): update_hud() @rpc("authority", "call_remote", "reliable") func end_round(result): print("Result: %s" % str(result)) winnerLabel.visible = true if (result > 0): winnerLabel.text = "OS WON" elif (result < 0 ): winnerLabel.text = "CS WON" await get_tree().create_timer(1).timeout winnerLabel.visible = false winnerLabel.text = "" @rpc("authority", "call_remote", "reliable") func kill_notification(killer, victim): var entry = load("res://scenes/models/kill_log_entry.tscn").instantiate() entry.get_node("killer").text = str(killer) entry.get_node("victim").text = str(victim) killLogList.add_child(entry)