Proper swap, generic mouse confinment and win

This commit is contained in:
Rendo 2025-12-12 16:49:20 +05:00
commit 5df5633c27
16 changed files with 136 additions and 96 deletions

View file

@ -6,24 +6,13 @@ func _ready() -> void:
func on_round_state_changed(state: int) -> void: func on_round_state_changed(state: int) -> void:
if state != Session.ROUND_STATES.BUY: if state != Session.ROUND_STATES.BUY:
visible = false visible = false
if visible: MouseConfiner.stop_borrow()
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
func _input(event: InputEvent) -> void: func _input(event: InputEvent) -> void:
if event.is_action_pressed("plr_buy"): if event.is_action_pressed("plr_buy"):
if Session.round_state == Session.ROUND_STATES.BUY: if Session.round_state == Session.ROUND_STATES.BUY:
visible = not visible visible = not visible
else: MouseConfiner.borrow()
elif visible:
visible = false visible = false
if visible: MouseConfiner.stop_borrow()
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

View file

@ -14,12 +14,9 @@ func _input(event: InputEvent) -> void:
if event.is_action_pressed("menu_settings"): if event.is_action_pressed("menu_settings"):
visible = not visible visible = not visible
if visible: if visible:
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE MouseConfiner.borrow()
else: else:
if Session.session_started_flag: MouseConfiner.stop_borrow()
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
else:
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
func _on_gameplay_main_slider_value_changed(value: float) -> void: func _on_gameplay_main_slider_value_changed(value: float) -> void:

20
gui/mouse_confiner.gd Normal file
View file

@ -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

View file

@ -0,0 +1 @@
uid://t5safg1xv074

View file

@ -4,34 +4,28 @@ func _on_spectator_button_pressed() -> void:
if Lobby.get_team() != Session.TEAMS.SPECTATE: if Lobby.get_team() != Session.TEAMS.SPECTATE:
Lobby.switch_team(Session.TEAMS.SPECTATE) Lobby.switch_team(Session.TEAMS.SPECTATE)
visible = false visible = false
update_mouse() MouseConfiner.stop_borrow()
func _on_attack_button_pressed() -> void: func _on_attack_button_pressed() -> void:
if Lobby.get_team() != Session.TEAMS.ATTACK: if Lobby.get_team() != Session.TEAMS.ATTACK:
Lobby.switch_team(Session.TEAMS.ATTACK) Lobby.switch_team(Session.TEAMS.ATTACK)
visible = false visible = false
update_mouse() MouseConfiner.stop_borrow()
func _on_defence_button_pressed() -> void: func _on_defence_button_pressed() -> void:
if Lobby.get_team() != Session.TEAMS.DEFENCE: if Lobby.get_team() != Session.TEAMS.DEFENCE:
Lobby.switch_team(Session.TEAMS.DEFENCE) Lobby.switch_team(Session.TEAMS.DEFENCE)
visible = false visible = false
update_mouse() MouseConfiner.stop_borrow()
func _on_cancel_button_pressed() -> void: func _on_cancel_button_pressed() -> void:
visible = false visible = false
update_mouse() MouseConfiner.stop_borrow()
func _input(event: InputEvent) -> void: func _input(event: InputEvent) -> void:
if event.is_action_pressed("menu_team_choice"): if event.is_action_pressed("menu_team_choice"):
visible = not visible visible = not visible
update_mouse() if visible:
MouseConfiner.borrow()
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
else: else:
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE MouseConfiner.stop_borrow()

15
gui/team_won_text.gd Normal file
View file

@ -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)

1
gui/team_won_text.gd.uid Normal file
View file

@ -0,0 +1 @@
uid://btbpe8hgf0knl

View file

@ -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="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"] [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="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://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="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"] [sub_resource type="BoxShape3D" id="BoxShape3D_ysk2e"]
size = Vector3(15.324341, 0.96273804, 21.381592) 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"] [sub_resource type="BoxShape3D" id="BoxShape3D_5uqia"]
size = Vector3(9.06966, 8.172485, 17.716736) 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="PrototypeScene" type="Node3D"]
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] [node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
@ -381,3 +387,17 @@ script = ExtResource("17_wsuwo")
[node name="BuyMenu" parent="CanvasLayer" instance=ExtResource("20_gcyg7")] [node name="BuyMenu" parent="CanvasLayer" instance=ExtResource("20_gcyg7")]
visible = false 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")

View file

@ -74,15 +74,17 @@ func set_teams(attack: Array[int],defence: Array[int],spectators: Array[int]):
defence_team = defence defence_team = defence
specators_team = spectators specators_team = spectators
update_teams_state.emit() update_teams_state.emit()
if is_multiplayer_authority():
set_teams.rpc(attack,defence,spectators)
func switch_team(team: int) -> void: func switch_team(team: int) -> void:
team_switch_notification.rpc(multiplayer.get_unique_id(),team) team_switch_notification.rpc(multiplayer.get_unique_id(),team)
func swap_teams() -> void: func swap_teams() -> void:
if not multiplayer.is_server(): if not is_multiplayer_authority():
return return
set_teams.rpc(defence_team,attack_team,specators_team) set_teams(defence_team,attack_team,specators_team)
@rpc("any_peer","call_local","reliable") @rpc("any_peer","call_local","reliable")
func team_switch_notification(id: int, team: int) -> void: func team_switch_notification(id: int, team: int) -> void:

View file

@ -25,9 +25,9 @@ const DEFENCE_LAYER: int = 0b100000
signal session_started signal session_started
signal session_ended signal session_ended
signal round_started signal round_started
signal late_player_connected(id: int)
signal round_state_changed(state: int) signal round_state_changed(state: int)
signal player_stopped_interacting(id: int) signal player_stopped_interacting(id: int)
signal team_won(team: TEAMS)
var player_nodes: Dictionary[int,Player] = {} var player_nodes: Dictionary[int,Player] = {}
var player_data: Dictionary[int,Dictionary] = {} var player_data: Dictionary[int,Dictionary] = {}
@ -39,11 +39,14 @@ var plant_deadzones: Dictionary[StringName, Area3D]
var session_started_flag: bool = false var session_started_flag: bool = false
var round_state: ROUND_STATES var round_state: ROUND_STATES
var current_round: int = 0 var current_round: int = 0
var attacker_score: int = 0 var attacker_score: int = 0
var defender_score: int = 0 var defender_score: int = 0
var attackers_alive: int = 0 var attackers_alive: int = 0
var defenders_alive: int = 0 var defenders_alive: int = 0
var reference_round_time: float var reference_round_time: float
var bomb_timer: Timer var bomb_timer: Timer
@ -73,53 +76,25 @@ func _ready() -> void:
add_child(round_timer) add_child(round_timer)
add_child(buy_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) 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: if multiplayer.is_server() == false or session_started_flag == false:
return return
var data: PackedByteArray var data: PackedByteArray
data.resize(6) data.resize(5)
data.encode_u8(0,current_round) data.encode_u8(0,current_round)
data.encode_u8(1,attacker_score) data.encode_u8(1,attackers_alive)
data.encode_u8(2,defender_score) data.encode_u8(2,defenders_alive)
data.encode_u8(3,attackers_alive) data.encode_u8(3,round_state)
data.encode_u8(4,defenders_alive) data.encode_u8(4,session_started_flag)
data.encode_u8(5,round_state)
sync_session_client.rpc_id(id,data,player_data) if peer_id == -1:
late_player_connected.emit(id) recieve_session_data.rpc(data,player_data)
else:
@rpc("authority","call_remote","reliable") recieve_session_data.rpc_id(peer_id,data,player_data)
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)
@rpc("authority","call_remote","unreliable") @rpc("authority","call_remote","unreliable")
func recieve_session_data(data: PackedByteArray,players_data_sent: Dictionary[int,Dictionary]): 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 return
current_round = data.decode_u8(0) current_round = data.decode_u8(0)
attacker_score = data.decode_u8(1) attackers_alive = data.decode_u8(1)
defender_score = data.decode_u8(2) defenders_alive = data.decode_u8(2)
attackers_alive = data.decode_u8(3) round_state = data.decode_u8(3) as ROUND_STATES
defenders_alive = data.decode_u8(4) if session_started_flag != bool(data.decode_u8(4)):
round_state = data.decode_u8(5) as ROUND_STATES session_started_flag = bool(data.decode_u8(4))
session_started.emit() if session_started_flag:
session_started.emit()
else:
session_ended.emit()
player_data = players_data_sent player_data = players_data_sent
func _process(_delta: float) -> void: func _process(_delta: float) -> void:
@ -235,15 +213,6 @@ func start_round() -> void:
func end_round(win_team: int) -> void: func end_round(win_team: int) -> void:
if not is_server_request(): if not is_server_request():
return 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: if win_team == TEAMS.DEFENCE:
defender_score += 1 defender_score += 1
@ -251,13 +220,31 @@ func end_round(win_team: int) -> void:
player_data[defender].money += WIN_MONEY player_data[defender].money += WIN_MONEY
for attacker in Lobby.attack_team: for attacker in Lobby.attack_team:
player_data[attacker].money += LOSE_MONEY player_data[attacker].money += LOSE_MONEY
if defender_score >= LobbySettings.win_score:
win_session(TEAMS.DEFENCE)
elif win_team == TEAMS.ATTACK: elif win_team == TEAMS.ATTACK:
attacker_score += 1 attacker_score += 1
for defender in Lobby.defence_team: for defender in Lobby.defence_team:
player_data[defender].money += LOSE_MONEY player_data[defender].money += LOSE_MONEY
for attacker in Lobby.attack_team: for attacker in Lobby.attack_team:
player_data[attacker].money += WIN_MONEY 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 = ROUND_STATES.AFTER_ROUND
round_state_changed.emit(round_state) round_state_changed.emit(round_state)
@ -291,6 +278,15 @@ func defuse_win() -> void:
bomb_timer.stop() bomb_timer.stop()
end_round(TEAMS.DEFENCE) 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): func add_dead(team: int):
if multiplayer.is_server() == false: if multiplayer.is_server() == false:
return 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)) hit_player.take_damage(int(float(damage) * reduction))
func interact(id: int) -> void: func interact(id: int) -> void:
if multiplayer.is_server() == false: if multiplayer.is_server() == false:
return return
@ -398,6 +393,11 @@ func kill_site(site: StringName) -> void:
func sync_score(attack: int, defence: int): func sync_score(attack: int, defence: int):
attacker_score = attack attacker_score = attack
defender_score = defence 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") @rpc("authority","call_remote","reliable")
func delete_player(id: int): func delete_player(id: int):

View file

@ -9,7 +9,7 @@ func _ready() -> void:
return return
Session.round_started.connect(spawn) Session.round_started.connect(spawn)
if team == Session.TEAMS.SPECTATE: if team == Session.TEAMS.SPECTATE:
Session.late_player_connected.connect(spawn_spectator) multiplayer.peer_connected.connect(spawn_spectator)
func _exit_tree() -> void: func _exit_tree() -> void:

View file

@ -14,7 +14,7 @@ func _ready() -> void:
if not is_multiplayer_authority(): if not is_multiplayer_authority():
return return
# Move to level controller when possible # Move to level controller when possible
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED MouseConfiner.set_global_mode(Input.MOUSE_MODE_CAPTURED)
current = true current = true
func _process(delta: float) -> void: func _process(delta: float) -> void:

View file

@ -9,7 +9,7 @@ func _ready() -> void:
if not is_multiplayer_authority(): if not is_multiplayer_authority():
return return
# Move to level controller when possible # Move to level controller when possible
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED MouseConfiner.set_global_mode(Input.MOUSE_MODE_CAPTURED)
current = true current = true
func _process(delta: float) -> void: func _process(delta: float) -> void:

View file

@ -1,6 +1,6 @@
[gd_scene load_steps=2 format=3 uid="uid://ckjabjcvgki6n"] [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"] [node name="Spectator" type="Camera3D"]
transform = Transform3D(-1, 0, -8.742278e-08, 0, 1, 0, 8.742278e-08, 0, -1, 0, 0, 0) transform = Transform3D(-1, 0, -8.742278e-08, 0, 1, 0, 8.742278e-08, 0, -1, 0, 0, 0)

View file

@ -26,6 +26,7 @@ Session="*res://multiplayer/session.gd"
ClientSettings="*res://gui/client_settings/client_settings.gd" ClientSettings="*res://gui/client_settings/client_settings.gd"
Registry="*res://systems/registry.gd" Registry="*res://systems/registry.gd"
Shop="*res://gui/buy_menu/shop.gd" Shop="*res://gui/buy_menu/shop.gd"
MouseConfiner="*res://gui/mouse_confiner.gd"
[display] [display]