Compare commits

...

3 Commits

7 changed files with 234 additions and 90 deletions

View File

@ -17,21 +17,19 @@ bg_color = Color(0.06469653, 0.064696535, 0.06469648, 0.34901962)
[sub_resource type="LabelSettings" id="LabelSettings_1cgct"]
font_size = 32
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_jbm04"]
bg_color = Color(0.30692267, 0.3069227, 0.30692264, 1)
[node name="lobby_world" type="LobbyWorld" unique_id=129662054 node_paths=PackedStringArray("lobby")]
menu_player_scene = ExtResource("3_q60fs")
lobby = NodePath("lobby")
[node name="lobby" type="LobbyPanel" parent="." unique_id=915192272 node_paths=PackedStringArray("players_list", "name_field", "ready_button", "map_selection", "options_panel", "options_grid", "alt_colors")]
[node name="lobby" type="LobbyPanel" parent="." unique_id=915192272 node_paths=PackedStringArray("players_list", "name_field", "ready_button", "map_selection", "options_panel", "options_grid", "options_tabs", "alt_colors")]
players_list = NodePath("v_box_container/players_list")
name_field = NodePath("v_box_container/h_box_container/text_edit")
player_listing_prefab = ExtResource("1_o1atq")
ready_button = NodePath("v_box_container3/ready_button")
map_selection = NodePath("v_box_container2/option_button")
options_panel = NodePath("options_panel")
options_grid = NodePath("options_panel/h_box_container/options_grid")
options_grid = NodePath("options_panel/h_box_container/tab_container/general")
options_tabs = NodePath("options_panel/h_box_container/tab_container")
alt_colors = NodePath("v_box_container/h_box_container/check_box")
start_game_icon = ExtResource("3_oipnb")
ready_icon = ExtResource("4_yad6j")
@ -107,7 +105,6 @@ theme_override_constants/icon_max_width = 100
metadata/_edit_lock_ = true
[node name="options_panel" type="Panel" parent="lobby" unique_id=1194589850]
visible = false
layout_mode = 1
anchors_preset = 8
anchor_left = 0.5
@ -120,35 +117,36 @@ offset_right = 291.5
offset_bottom = 213.5
grow_horizontal = 2
grow_vertical = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_jbm04")
[node name="options_close" type="Button" parent="lobby/options_panel" unique_id=2115857774]
layout_mode = 1
anchors_preset = 1
anchor_left = 1.0
anchor_right = 1.0
offset_left = -33.5
offset_bottom = 31.0
grow_horizontal = 0
text = "X"
[node name="h_box_container" type="VBoxContainer" parent="lobby/options_panel" unique_id=1163233032]
layout_mode = 0
offset_left = 0.5
offset_top = 3.5
offset_right = 115.5
offset_bottom = 43.5
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="label" type="Label" parent="lobby/options_panel/h_box_container" unique_id=1002581329]
[node name="h_box_container" type="HBoxContainer" parent="lobby/options_panel/h_box_container" unique_id=1966956919]
layout_mode = 2
[node name="label" type="Label" parent="lobby/options_panel/h_box_container/h_box_container" unique_id=1002581329]
layout_mode = 2
size_flags_horizontal = 3
text = "Game Options"
[node name="v_box_container" type="HBoxContainer" parent="lobby/options_panel/h_box_container" unique_id=1445409921]
[node name="options_close" type="Button" parent="lobby/options_panel/h_box_container/h_box_container" unique_id=2115857774]
layout_mode = 2
text = "X"
[node name="options_grid" type="GridContainer" parent="lobby/options_panel/h_box_container" unique_id=504671462]
[node name="tab_container" type="TabContainer" parent="lobby/options_panel/h_box_container" unique_id=1185146072]
layout_mode = 2
size_flags_vertical = 3
current_tab = 0
[node name="general" type="GridContainer" parent="lobby/options_panel/h_box_container/tab_container" unique_id=504671462]
layout_mode = 2
columns = 2
metadata/_tab_index = 0
[node name="chat_box" parent="lobby" unique_id=1125601400 instance=ExtResource("2_5gu6x")]
custom_minimum_size = Vector2(400, 300)
@ -229,7 +227,7 @@ current = true
[node name="two_towers_static" parent="background" unique_id=86902040 instance=ExtResource("6_apkv3")]
transform = Transform3D(-0.1736482, 0, -0.9848077, 0, 1, 0, 0.9848077, 0, -0.1736482, -15.664, -7, -7.637)
[connection signal="pressed" from="lobby/options_panel/options_close" to="lobby" method="close_options"]
[connection signal="pressed" from="lobby/options_panel/h_box_container/h_box_container/options_close" to="lobby" method="close_options"]
[connection signal="pressed" from="lobby/v_box_container3/h_box_container/exit_button" to="lobby" method="exit"]
[connection signal="pressed" from="lobby/v_box_container3/h_box_container/options_button" to="lobby" method="open_options"]
[connection signal="pressed" from="lobby/v_box_container3/h_box_container/settings_button" to="lobby/settings" method="open"]

View File

@ -328,6 +328,8 @@ impl Game {
#[signal]
pub fn options_changed();
#[signal]
pub fn team_options_changed(team: u8);
#[signal]
pub fn on_goal();
#[signal]
pub fn on_game_finished();
@ -495,7 +497,7 @@ impl Game {
team.values.insert(opt, value);
}
self.run_deferred(move |s| {
s.signals().options_changed().emit();
s.signals().team_options_changed().emit(team);
if let Some(peer) = &mut NetworkManager::singleton().bind_mut().peer {
if let PeerKind::Server(peer, _) = peer {
peer.broadcast_reliable(Package::TeamGameOptionChanged(team, opt, value));
@ -1425,6 +1427,14 @@ impl Game {
None
}
}
pub fn get_player_team(&self, player_id: u16) -> u8 {
if let Some(player) = self.find_player(player_id) {
player.data.team
} else {
0
}
}
}
#[derive(Clone, Debug)]

View File

@ -59,6 +59,22 @@ impl GameOptions {
}
}
pub fn is_team_true(&self, team: u8, opt: GameOption) -> bool {
if let Some(opts) = self.teams.get(team as usize) {
let opt = opts
.values
.get(&opt)
.copied()
.unwrap_or(GameOptionValue::Boolean(false));
match opt {
GameOptionValue::Boolean(value) => value,
_ => false,
}
} else {
false
}
}
pub fn get_float(&self, opt: GameOption) -> f64 {
let opt = self
.values

View File

@ -202,6 +202,11 @@ impl NetworkManager {
game.bind_mut().change_option(opt, value);
}
}
Package::TeamGameOptionChanged(team, opt, value) => {
if let Some(game) = &mut Game::singleton() {
game.bind_mut().change_team_option(team, opt, value);
}
}
Package::Goal(scorer, teams) => {
if let Some(game) = &mut Game::singleton() {
game.bind_mut().handle_goal(scorer, teams);

View File

@ -449,7 +449,10 @@ impl ICharacterBody3D for LocalPlayer {
self.run_deferred(|s| {
s.telegrenades_allowed = if let Some(game) = Game::singleton() {
game.bind().opts.is_true(GameOption::TelegrenadesAllowed)
game.bind().opts.is_team_true(
game.bind().get_player_team(s.player_id.unwrap_or(0)),
GameOption::TelegrenadesAllowed,
)
} else {
false
};

View File

@ -380,7 +380,10 @@ impl ICharacterBody3D for RemotePlayer {
self.run_deferred(|s| {
s.telegrenades_allowed = if let Some(game) = Game::singleton() {
game.bind().opts.is_true(GameOption::TelegrenadesAllowed)
game.bind().opts.is_team_true(
game.bind().get_player_team(s.player_id.unwrap_or(0)),
GameOption::TelegrenadesAllowed,
)
} else {
false
};

View File

@ -3,7 +3,7 @@ use std::collections::HashMap;
use godot::{
classes::{
Button, CheckBox, CompressedTexture2D, Control, GridContainer, IPanel, Label, LineEdit,
OptionButton, Panel, SpinBox, VBoxContainer,
OptionButton, Panel, SpinBox, TabContainer, VBoxContainer,
},
prelude::*,
};
@ -12,7 +12,7 @@ use crate::{
bgm::{Music, MusicManager},
game::{
Game, GameManager,
opts::{GameOption, GameOptionValue, GameOptions},
opts::{GameOption, GameOptionValue, GameOptions, TeamOptions},
},
lobby_world::LobbyWorld,
net::network_manager::{NetworkManager, Package, PeerKind},
@ -37,9 +37,13 @@ pub struct LobbyPanel {
#[export]
options_grid: Option<Gd<GridContainer>>,
#[export]
options_tabs: Option<Gd<TabContainer>>,
#[export]
alt_colors: Option<Gd<CheckBox>>,
option_nodes: HashMap<GameOption, Gd<Control>>,
team_grids: HashMap<u8, Gd<GridContainer>>,
team_option_nodes: HashMap<u8, HashMap<GameOption, Gd<Control>>>,
#[export]
start_game_icon: Option<Gd<CompressedTexture2D>>,
@ -112,6 +116,23 @@ impl IPanel for LobbyPanel {
}
});
});
game.signals()
.team_options_changed()
.connect_other(self, |s, team| {
s.run_deferred(move |s| {
if let Some(game) = Game::singleton() {
if let Some(opts) = game.bind().get_team_opts(team) {
s.on_team_opts_update(team, &opts);
}
}
});
});
game.signals().on_map_changed().connect_other(self, |s, _| {
s.run_deferred(|s| {
s.generate_team_options();
});
});
let is_host = if let Some(peer) = &NetworkManager::singleton().bind().peer {
peer.is_host()
@ -186,53 +207,11 @@ impl IPanel for LobbyPanel {
self.update_ready_button();
let mut nodes = Vec::new();
if let Some(game) = Game::singleton() {
for (option, value) in &game.bind().opts.values {
let mut label = Label::new_alloc();
label.set_text(&format!("{}:", option.to_string()));
nodes.push(label.upcast());
let value_node = match value {
GameOptionValue::Boolean(value) => {
let mut checkbox = CheckBox::new_alloc();
checkbox.set_pressed(*value);
checkbox.set_disabled(!NetworkManager::singleton().bind().is_host());
let checkbox_clone = checkbox.clone();
let option = option.clone();
checkbox.signals().pressed().connect_other(self, move |s| {
s.option_changed(
option,
GameOptionValue::Boolean(checkbox_clone.is_pressed()),
);
});
self.option_nodes.insert(option, checkbox.clone().upcast());
checkbox.upcast::<Control>()
}
GameOptionValue::Number(value) => {
let mut spinbox = SpinBox::new_alloc();
spinbox.set_value(*value);
spinbox.set_editable(NetworkManager::singleton().bind().is_host());
let option = option.clone();
spinbox.signals().value_changed().connect_other(
self,
move |s, new_value| {
s.option_changed(option, GameOptionValue::Number(new_value));
},
);
self.option_nodes.insert(option, spinbox.clone().upcast());
spinbox.upcast()
}
};
nodes.push(value_node);
}
}
let nodes = if let Some(game) = Game::singleton() {
self.generate_options(&game.bind().opts.values, None)
} else {
Vec::new()
};
if let Some(grid) = &mut self.options_grid {
for node in nodes {
@ -240,6 +219,8 @@ impl IPanel for LobbyPanel {
}
}
self.generate_team_options();
MusicManager::singleton()
.bind_mut()
.play(Some(Music::MainMenu), false);
@ -283,6 +264,12 @@ impl LobbyPanel {
}
}
fn team_option_changed(&mut self, team: u8, key: GameOption, value: GameOptionValue) {
if let Some(game) = &mut Game::singleton() {
game.bind_mut().change_team_option(team, key, value);
}
}
fn on_game_opts_update(&mut self, opts: &GameOptions, is_host: bool) {
if let Some(selection) = &mut self.map_selection {
selection.set_disabled(!is_host && !opts.is_true(GameOption::AllowAnyMap));
@ -293,23 +280,26 @@ impl LobbyPanel {
self.run_deferred_gd(move |_| {
for (key, value) in values {
if let Some(control) = nodes.get(&key).cloned() {
match value {
GameOptionValue::Boolean(value) => {
if let Ok(mut checkbox) = control.try_cast::<CheckBox>() {
checkbox.set_pressed(value);
}
}
GameOptionValue::Number(value) => {
if let Ok(mut spinbox) = control.try_cast::<SpinBox>() {
spinbox.set_value(value);
}
}
}
update_control(control, value);
}
}
});
}
fn on_team_opts_update(&mut self, team: u8, opts: &TeamOptions) {
let values = opts.values.clone();
if let Some(nodes) = self.team_option_nodes.get(&team) {
let nodes = nodes.clone();
self.run_deferred_gd(move |_| {
for (key, value) in values {
if let Some(control) = nodes.get(&key).cloned() {
update_control(control, value);
}
}
});
}
}
fn update_ready_button(&mut self) {
if let Some(game) = Game::singleton()
&& let Some(peer) = &NetworkManager::singleton().bind().peer
@ -440,4 +430,123 @@ impl LobbyPanel {
}
idx
}
fn generate_team_options(&mut self) {
if let Some(mut tabs) = self.options_tabs.clone() {
for (_, grid) in self.team_grids.clone() {
tabs.remove_child(&grid);
}
self.team_grids.clear();
self.team_option_nodes.clear();
if let Some(game) = Game::singleton() {
for (id, team) in game.bind().get_teams().iter_shared().enumerate() {
let mut grid = GridContainer::new_alloc();
grid.set_name(&team.bind().name.to_string());
grid.set_columns(2);
if let Some(opts) = game.bind().get_team_opts(id as u8) {
let nodes = self.generate_options(&opts.values, Some(id as u8));
for node in nodes {
grid.add_child(&node);
}
}
tabs.add_child(&grid);
self.team_grids.insert(id as u8, grid);
}
}
}
}
fn generate_options(
&mut self,
opts: &HashMap<GameOption, GameOptionValue>,
team: Option<u8>,
) -> Vec<Gd<Control>> {
let mut nodes = Vec::new();
for (option, value) in opts {
let mut label = Label::new_alloc();
label.set_text(&format!("{}:", option.to_string()));
nodes.push(label.upcast());
let value_node = match value {
GameOptionValue::Boolean(value) => {
let mut checkbox = CheckBox::new_alloc();
checkbox.set_pressed(*value);
checkbox.set_disabled(!NetworkManager::singleton().bind().is_host());
let checkbox_clone = checkbox.clone();
let option = option.clone();
checkbox.signals().pressed().connect_other(self, move |s| {
if let Some(team) = team {
s.team_option_changed(
team,
option,
GameOptionValue::Boolean(checkbox_clone.is_pressed()),
);
} else {
s.option_changed(
option,
GameOptionValue::Boolean(checkbox_clone.is_pressed()),
);
}
});
checkbox.upcast::<Control>()
}
GameOptionValue::Number(value) => {
let mut spinbox = SpinBox::new_alloc();
spinbox.set_value(*value);
spinbox.set_editable(NetworkManager::singleton().bind().is_host());
let option = option.clone();
spinbox
.signals()
.value_changed()
.connect_other(self, move |s, new_value| {
if let Some(team) = team {
s.team_option_changed(
team,
option,
GameOptionValue::Number(new_value),
);
} else {
s.option_changed(option, GameOptionValue::Number(new_value));
}
});
spinbox.upcast()
}
};
if let Some(team) = team {
if let Some(nodes) = self.team_option_nodes.get_mut(&team) {
nodes.insert(option.clone(), value_node.clone());
} else {
let mut nodes = HashMap::new();
nodes.insert(option.clone(), value_node.clone());
self.team_option_nodes.insert(team, nodes);
}
} else {
self.option_nodes.insert(option.clone(), value_node.clone());
}
nodes.push(value_node);
}
nodes
}
}
fn update_control(control: Gd<Control>, value: GameOptionValue) {
match value {
GameOptionValue::Boolean(value) => {
if let Ok(mut checkbox) = control.try_cast::<CheckBox>() {
checkbox.set_pressed(value);
}
}
GameOptionValue::Number(value) => {
if let Ok(mut spinbox) = control.try_cast::<SpinBox>() {
spinbox.set_value(value);
}
}
}
}