diff --git a/gui/buy_menu/buy_menu.gd b/gui/buy_menu/buy_menu.gd index 60382e8..de0e6e3 100644 --- a/gui/buy_menu/buy_menu.gd +++ b/gui/buy_menu/buy_menu.gd @@ -6,24 +6,13 @@ func _ready() -> void: func on_round_state_changed(state: int) -> void: if state != Session.ROUND_STATES.BUY: visible = false - if visible: - Input.mouse_mode = Input.MOUSE_MODE_VISIBLE - else: - if Session.session_started_flag: - Input.mouse_mode = Input.MOUSE_MODE_CAPTURED - else: - Input.mouse_mode = Input.MOUSE_MODE_VISIBLE + MouseConfiner.stop_borrow() func _input(event: InputEvent) -> void: if event.is_action_pressed("plr_buy"): if Session.round_state == Session.ROUND_STATES.BUY: visible = not visible - else: + MouseConfiner.borrow() + elif visible: visible = false - if visible: - Input.mouse_mode = Input.MOUSE_MODE_VISIBLE - else: - if Session.session_started_flag: - Input.mouse_mode = Input.MOUSE_MODE_CAPTURED - else: - Input.mouse_mode = Input.MOUSE_MODE_VISIBLE + MouseConfiner.stop_borrow() diff --git a/gui/client_settings/client_settings_menu.gd b/gui/client_settings/client_settings_menu.gd index c785111..ffb5328 100644 --- a/gui/client_settings/client_settings_menu.gd +++ b/gui/client_settings/client_settings_menu.gd @@ -14,12 +14,9 @@ func _input(event: InputEvent) -> void: if event.is_action_pressed("menu_settings"): visible = not visible if visible: - Input.mouse_mode = Input.MOUSE_MODE_VISIBLE + MouseConfiner.borrow() else: - if Session.session_started_flag: - Input.mouse_mode = Input.MOUSE_MODE_CAPTURED - else: - Input.mouse_mode = Input.MOUSE_MODE_VISIBLE + MouseConfiner.stop_borrow() func _on_gameplay_main_slider_value_changed(value: float) -> void: diff --git a/gui/mouse_confiner.gd b/gui/mouse_confiner.gd new file mode 100644 index 0000000..b71a5fb --- /dev/null +++ b/gui/mouse_confiner.gd @@ -0,0 +1,20 @@ +extends Node + +var global_mode: Input.MouseMode = Input.MouseMode.MOUSE_MODE_VISIBLE +var borrowed_visibiles: int = 0 + +func set_global_mode(to: Input.MouseMode) -> void: + global_mode = to + Input.mouse_mode = to + borrowed_visibiles = 0 + +func borrow() -> void: + borrowed_visibiles += 1 + Input.mouse_mode = Input.MOUSE_MODE_VISIBLE + +func stop_borrow() -> void: + if borrowed_visibiles == 0: + return + borrowed_visibiles -= 1 + if borrowed_visibiles == 0: + Input.mouse_mode = global_mode diff --git a/gui/mouse_confiner.gd.uid b/gui/mouse_confiner.gd.uid new file mode 100644 index 0000000..f01c13c --- /dev/null +++ b/gui/mouse_confiner.gd.uid @@ -0,0 +1 @@ +uid://t5safg1xv074 diff --git a/gui/team_choice/team_choice_menu.gd b/gui/team_choice/team_choice_menu.gd index 2b6439c..b5d0d6f 100644 --- a/gui/team_choice/team_choice_menu.gd +++ b/gui/team_choice/team_choice_menu.gd @@ -4,34 +4,28 @@ func _on_spectator_button_pressed() -> void: if Lobby.get_team() != Session.TEAMS.SPECTATE: Lobby.switch_team(Session.TEAMS.SPECTATE) visible = false - update_mouse() + MouseConfiner.stop_borrow() func _on_attack_button_pressed() -> void: if Lobby.get_team() != Session.TEAMS.ATTACK: Lobby.switch_team(Session.TEAMS.ATTACK) visible = false - update_mouse() + MouseConfiner.stop_borrow() func _on_defence_button_pressed() -> void: if Lobby.get_team() != Session.TEAMS.DEFENCE: Lobby.switch_team(Session.TEAMS.DEFENCE) visible = false - update_mouse() + MouseConfiner.stop_borrow() func _on_cancel_button_pressed() -> void: visible = false - update_mouse() + MouseConfiner.stop_borrow() func _input(event: InputEvent) -> void: if event.is_action_pressed("menu_team_choice"): visible = not visible - update_mouse() - -func update_mouse() -> void: - if visible: - Input.mouse_mode = Input.MOUSE_MODE_VISIBLE - else: - if Session.session_started_flag: - Input.mouse_mode = Input.MOUSE_MODE_CAPTURED + if visible: + MouseConfiner.borrow() else: - Input.mouse_mode = Input.MOUSE_MODE_VISIBLE + MouseConfiner.stop_borrow() diff --git a/gui/team_won_text.gd b/gui/team_won_text.gd new file mode 100644 index 0000000..56ed58b --- /dev/null +++ b/gui/team_won_text.gd @@ -0,0 +1,15 @@ +extends Label + +func _ready() -> void: + Session.team_won.connect(on_team_won) + +func on_team_won(team: Session.TEAMS): + match team: + Session.TEAMS.DEFENCE: + text = "ПОБЕДА КОМАНДЫ ЗАЩИТНИКОВ" + Session.TEAMS.ATTACK: + text = "ПОБЕДА КОМАНДЫ АТАКУЮЩИХ" + var tween = create_tween() + tween.tween_property(self,"modulate",Color.WHITE,2) + tween.tween_interval(3.5) + tween.tween_property(self,"modulate",Color.TRANSPARENT,1) diff --git a/gui/team_won_text.gd.uid b/gui/team_won_text.gd.uid new file mode 100644 index 0000000..461d4c6 --- /dev/null +++ b/gui/team_won_text.gd.uid @@ -0,0 +1 @@ +uid://btbpe8hgf0knl diff --git a/levels/prototype_scene.tscn b/levels/prototype_scene.tscn index 8286305..2204a83 100644 --- a/levels/prototype_scene.tscn +++ b/levels/prototype_scene.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=25 format=3 uid="uid://cqrh2cc7m2i7f"] +[gd_scene load_steps=27 format=3 uid="uid://cqrh2cc7m2i7f"] [ext_resource type="Environment" uid="uid://d0cfgtx2yxw13" path="res://environments/prototype_environment.tres" id="1_i6jab"] [ext_resource type="Material" uid="uid://bx3f5vx71ynh5" path="res://materials/Graymat.tres" id="4_y6i55"] @@ -20,6 +20,7 @@ [ext_resource type="Script" uid="uid://bos7nftlx8tv3" path="res://gui/hud/player_round_time.gd" id="18_0hcup"] [ext_resource type="PackedScene" uid="uid://cmon3g1lsm3q" path="res://gui/team_choice/team_choice_menu.tscn" id="19_gcyg7"] [ext_resource type="PackedScene" uid="uid://j5lgbg8c0pq" path="res://gui/buy_menu/buy_menu.tscn" id="20_gcyg7"] +[ext_resource type="Script" uid="uid://btbpe8hgf0knl" path="res://gui/team_won_text.gd" id="21_tdf5c"] [sub_resource type="BoxShape3D" id="BoxShape3D_ysk2e"] size = Vector3(15.324341, 0.96273804, 21.381592) @@ -33,6 +34,11 @@ size = Vector3(58.51023, 8.172485, 33.813843) [sub_resource type="BoxShape3D" id="BoxShape3D_5uqia"] size = Vector3(9.06966, 8.172485, 17.716736) +[sub_resource type="LabelSettings" id="LabelSettings_gcyg7"] +font_size = 70 +outline_size = 20 +outline_color = Color(0, 0, 0, 1) + [node name="PrototypeScene" type="Node3D"] [node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] @@ -381,3 +387,17 @@ script = ExtResource("17_wsuwo") [node name="BuyMenu" parent="CanvasLayer" instance=ExtResource("20_gcyg7")] visible = false + +[node name="CenterContainer" type="CenterContainer" parent="CanvasLayer"] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 + +[node name="WinLabel" type="Label" parent="CanvasLayer/CenterContainer"] +modulate = Color(1, 1, 1, 0) +layout_mode = 2 +label_settings = SubResource("LabelSettings_gcyg7") +script = ExtResource("21_tdf5c") diff --git a/multiplayer/lobby.gd b/multiplayer/lobby.gd index 71b9435..7ed9b83 100644 --- a/multiplayer/lobby.gd +++ b/multiplayer/lobby.gd @@ -74,15 +74,17 @@ func set_teams(attack: Array[int],defence: Array[int],spectators: Array[int]): defence_team = defence specators_team = spectators update_teams_state.emit() + if is_multiplayer_authority(): + set_teams.rpc(attack,defence,spectators) func switch_team(team: int) -> void: team_switch_notification.rpc(multiplayer.get_unique_id(),team) func swap_teams() -> void: - if not multiplayer.is_server(): + if not is_multiplayer_authority(): return - set_teams.rpc(defence_team,attack_team,specators_team) + set_teams(defence_team,attack_team,specators_team) @rpc("any_peer","call_local","reliable") func team_switch_notification(id: int, team: int) -> void: diff --git a/multiplayer/session.gd b/multiplayer/session.gd index ca40adf..57afe4f 100644 --- a/multiplayer/session.gd +++ b/multiplayer/session.gd @@ -25,9 +25,9 @@ const DEFENCE_LAYER: int = 0b100000 signal session_started signal session_ended signal round_started -signal late_player_connected(id: int) signal round_state_changed(state: int) signal player_stopped_interacting(id: int) +signal team_won(team: TEAMS) var player_nodes: Dictionary[int,Player] = {} var player_data: Dictionary[int,Dictionary] = {} @@ -39,11 +39,14 @@ var plant_deadzones: Dictionary[StringName, Area3D] var session_started_flag: bool = false var round_state: ROUND_STATES + var current_round: int = 0 var attacker_score: int = 0 var defender_score: int = 0 + var attackers_alive: int = 0 var defenders_alive: int = 0 + var reference_round_time: float var bomb_timer: Timer @@ -73,53 +76,25 @@ func _ready() -> void: add_child(round_timer) add_child(buy_timer) - multiplayer.peer_connected.connect(sync_session_server) + multiplayer.peer_connected.connect(send_session_data) multiplayer.peer_disconnected.connect(delete_player) -func sync_session_server(id: int): +func send_session_data(peer_id: int = -1): if multiplayer.is_server() == false or session_started_flag == false: return var data: PackedByteArray - data.resize(6) + data.resize(5) data.encode_u8(0,current_round) - data.encode_u8(1,attacker_score) - data.encode_u8(2,defender_score) - data.encode_u8(3,attackers_alive) - data.encode_u8(4,defenders_alive) - data.encode_u8(5,round_state) + data.encode_u8(1,attackers_alive) + data.encode_u8(2,defenders_alive) + data.encode_u8(3,round_state) + data.encode_u8(4,session_started_flag) - sync_session_client.rpc_id(id,data,player_data) - late_player_connected.emit(id) - -@rpc("authority","call_remote","reliable") -func sync_session_client(data: PackedByteArray,players_data_sent: Dictionary[int,Dictionary]): - if not is_server_request(): - return - - current_round = data.decode_u8(0) - attacker_score = data.decode_u8(1) - defender_score = data.decode_u8(2) - attackers_alive = data.decode_u8(3) - defenders_alive = data.decode_u8(4) - round_state = data.decode_u8(5) as ROUND_STATES - session_started.emit() - player_data = players_data_sent - -func send_session_data(): - if multiplayer.is_server() == false or session_started_flag == false: - return - - var data: PackedByteArray - data.resize(6) - data.encode_u8(0,current_round) - data.encode_u8(1,attacker_score) - data.encode_u8(2,defender_score) - data.encode_u8(3,attackers_alive) - data.encode_u8(4,defenders_alive) - data.encode_u8(5,round_state) - - recieve_session_data.rpc(data,player_data) + if peer_id == -1: + recieve_session_data.rpc(data,player_data) + else: + recieve_session_data.rpc_id(peer_id,data,player_data) @rpc("authority","call_remote","unreliable") func recieve_session_data(data: PackedByteArray,players_data_sent: Dictionary[int,Dictionary]): @@ -127,12 +102,15 @@ func recieve_session_data(data: PackedByteArray,players_data_sent: Dictionary[in return current_round = data.decode_u8(0) - attacker_score = data.decode_u8(1) - defender_score = data.decode_u8(2) - attackers_alive = data.decode_u8(3) - defenders_alive = data.decode_u8(4) - round_state = data.decode_u8(5) as ROUND_STATES - session_started.emit() + attackers_alive = data.decode_u8(1) + defenders_alive = data.decode_u8(2) + round_state = data.decode_u8(3) as ROUND_STATES + if session_started_flag != bool(data.decode_u8(4)): + session_started_flag = bool(data.decode_u8(4)) + if session_started_flag: + session_started.emit() + else: + session_ended.emit() player_data = players_data_sent func _process(_delta: float) -> void: @@ -235,15 +213,6 @@ func start_round() -> void: func end_round(win_team: int) -> void: if not is_server_request(): return - if multiplayer.is_server(): - get_tree().create_timer(5).timeout.connect(start_round) - end_round.rpc(win_team) - if current_round == Lobby.half_rounds: - Lobby.swap_teams() - var temp_rounds = attacker_score - attacker_score = defender_score - defender_score = temp_rounds - sync_score.rpc(attacker_score,defender_score) if win_team == TEAMS.DEFENCE: defender_score += 1 @@ -251,13 +220,31 @@ func end_round(win_team: int) -> void: player_data[defender].money += WIN_MONEY for attacker in Lobby.attack_team: player_data[attacker].money += LOSE_MONEY + if defender_score >= LobbySettings.win_score: + win_session(TEAMS.DEFENCE) + elif win_team == TEAMS.ATTACK: attacker_score += 1 for defender in Lobby.defence_team: player_data[defender].money += LOSE_MONEY for attacker in Lobby.attack_team: player_data[attacker].money += WIN_MONEY + + if attacker_score >= LobbySettings.win_score: + win_session(TEAMS.ATTACK) + if multiplayer.is_server(): + end_round.rpc(win_team) + if defender_score >= LobbySettings.win_score or attacker_score >= LobbySettings.win_score: + get_tree().create_timer(7.5).timeout.connect(end_session) + else: + get_tree().create_timer(5).timeout.connect(start_round) + if current_round == LobbySettings.half_rounds: + Lobby.swap_teams() + var temp_rounds = attacker_score + attacker_score = defender_score + defender_score = temp_rounds + sync_score.rpc(attacker_score,defender_score) round_state = ROUND_STATES.AFTER_ROUND round_state_changed.emit(round_state) @@ -291,6 +278,15 @@ func defuse_win() -> void: bomb_timer.stop() end_round(TEAMS.DEFENCE) +@rpc("reliable") +func win_session(team: int): + team_won.emit(team) + + MouseConfiner.set_global_mode(Input.MOUSE_MODE_VISIBLE) + + if is_multiplayer_authority(): + win_session.rpc(team) + func add_dead(team: int): if multiplayer.is_server() == false: return @@ -350,7 +346,6 @@ func shoot(id:int , limb_damage: int, torso_damage: int,head_damage: int, distan hit_player.take_damage(int(float(damage) * reduction)) - func interact(id: int) -> void: if multiplayer.is_server() == false: return @@ -398,6 +393,11 @@ func kill_site(site: StringName) -> void: func sync_score(attack: int, defence: int): attacker_score = attack defender_score = defence + + if defender_score >= LobbySettings.win_score: + win_session(TEAMS.DEFENCE) + elif attacker_score >= LobbySettings.win_score: + win_session(TEAMS.ATTACK) @rpc("authority","call_remote","reliable") func delete_player(id: int): diff --git a/multiplayer/team_spawner.gd b/multiplayer/team_spawner.gd index bba5b25..6f786f8 100644 --- a/multiplayer/team_spawner.gd +++ b/multiplayer/team_spawner.gd @@ -9,7 +9,7 @@ func _ready() -> void: return Session.round_started.connect(spawn) if team == Session.TEAMS.SPECTATE: - Session.late_player_connected.connect(spawn_spectator) + multiplayer.peer_connected.connect(spawn_spectator) func _exit_tree() -> void: diff --git a/players/player/player_camera.gd b/players/player/player_camera.gd index 82091a0..55f6242 100644 --- a/players/player/player_camera.gd +++ b/players/player/player_camera.gd @@ -14,7 +14,7 @@ func _ready() -> void: if not is_multiplayer_authority(): return # Move to level controller when possible - Input.mouse_mode = Input.MOUSE_MODE_CAPTURED + MouseConfiner.set_global_mode(Input.MOUSE_MODE_CAPTURED) current = true func _process(delta: float) -> void: diff --git a/spectator.gd b/players/spectator.gd similarity index 94% rename from spectator.gd rename to players/spectator.gd index f6ff85d..0115a9f 100644 --- a/spectator.gd +++ b/players/spectator.gd @@ -9,7 +9,7 @@ func _ready() -> void: if not is_multiplayer_authority(): return # Move to level controller when possible - Input.mouse_mode = Input.MOUSE_MODE_CAPTURED + MouseConfiner.set_global_mode(Input.MOUSE_MODE_CAPTURED) current = true func _process(delta: float) -> void: diff --git a/spectator.gd.uid b/players/spectator.gd.uid similarity index 100% rename from spectator.gd.uid rename to players/spectator.gd.uid diff --git a/players/spectator.tscn b/players/spectator.tscn index 6366600..2f803b8 100644 --- a/players/spectator.tscn +++ b/players/spectator.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=2 format=3 uid="uid://ckjabjcvgki6n"] -[ext_resource type="Script" uid="uid://cikw7fcykkpd5" path="res://spectator.gd" id="1_jjbhc"] +[ext_resource type="Script" uid="uid://cikw7fcykkpd5" path="res://players/spectator.gd" id="1_jjbhc"] [node name="Spectator" type="Camera3D"] transform = Transform3D(-1, 0, -8.742278e-08, 0, 1, 0, 8.742278e-08, 0, -1, 0, 0, 0) diff --git a/project.godot b/project.godot index 9268526..65f21f6 100644 --- a/project.godot +++ b/project.godot @@ -26,6 +26,7 @@ Session="*res://multiplayer/session.gd" ClientSettings="*res://gui/client_settings/client_settings.gd" Registry="*res://systems/registry.gd" Shop="*res://gui/buy_menu/shop.gd" +MouseConfiner="*res://gui/mouse_confiner.gd" [display]