Skip to content

Commit c2fa3a6

Browse files
authored
Merge pull request #789 from C7-Game/twrner/scenario-civ-picking
Support picking which civ to play as in a scenario
2 parents 73a68b5 + e48e29a commit c2fa3a6

File tree

6 files changed

+309
-5
lines changed

6 files changed

+309
-5
lines changed

C7/Game.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ public override void _Ready() {
115115
GamePaths.LuaRulesDir,
116116
GamePaths.DefaultBicPath,
117117
(scenarioSearchPath) => {
118-
// WHen the game loading logic tries to load the PediaIcons file, set the
118+
// When the game loading logic tries to load the PediaIcons file, set the
119119
// scenario search path and then use our Civ3MediaPath searching logic to
120120
// find the correct version of the file.
121121
//

C7/UIElements/Civ3FileDialog.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ public partial class Civ3FileDialog : FileDialog {
99
GlobalSingleton Global;
1010
private ILogger log;
1111

12+
// If true, go to scenario setup after loading, for scenarios.
13+
public bool GoToScenarioSetupAfterLoading = false;
14+
1215
public override void _Ready() {
1316
base._Ready();
1417
log = LogManager.ForContext<Civ3FileDialog>();
@@ -34,7 +37,11 @@ private void OnFileSelected(string path) {
3437
if (FileMode == FileDialog.FileModeEnum.OpenFile) {
3538
log.Information($"loading {path}");
3639
Global.LoadGamePath = path;
37-
GetTree().ChangeSceneToFile("res://C7Game.tscn");
40+
if (GoToScenarioSetupAfterLoading) {
41+
GetTree().ChangeSceneToFile("res://UIElements/NewGame/scenario_setup.tscn");
42+
} else {
43+
GetTree().ChangeSceneToFile("res://C7Game.tscn");
44+
}
3845
} else {
3946
if (!path.EndsWith(".json")) {
4047
path = path + ".json";

C7/UIElements/MainMenu/MainMenu.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ private void DisplayTitleScreen() {
4141

4242
LoadDialog.SetDirectoryForLoading(@"Conquests/Saves");
4343
LoadScenarioDialog.SetDirectoryForLoading(@"Conquests/Scenarios");
44+
LoadScenarioDialog.GoToScenarioSetupAfterLoading = true;
4445

4546
ButtonContainer.NewGame.Pressed += GoToWorldSetup;
4647
ButtonContainer.QuickStart.Pressed += GoToWorldSetup;
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
using Godot;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Threading;
6+
using C7GameData;
7+
using C7Engine;
8+
using ConvertCiv3Media;
9+
using C7GameData.Save;
10+
using Serilog;
11+
12+
[Tool]
13+
public partial class ScenarioSetup : Control {
14+
private static ILogger log = LogManager.ForContext<ScenarioSetup>();
15+
16+
[Export] TextureRect background;
17+
18+
[Export] GridContainer playerListContainer;
19+
List<Civilization> civilizations = new();
20+
Civilization civilization = null;
21+
ButtonGroup playerListButtonGroup = new();
22+
TextureRect leaderHead = new();
23+
[Export] Label civLabel;
24+
25+
[Export] GridContainer difficultyContainer;
26+
27+
Difficulty difficulty = null;
28+
ButtonGroup difficultyButtonGroup = new();
29+
30+
[Export] TextureButton confirm;
31+
[Export] TextureButton cancel;
32+
33+
[Export] Label loadingLabel;
34+
35+
// Called when the node enters the scene tree for the first time.
36+
public override void _Ready() {
37+
background.Texture = TextureLoader.Load("player_setup.background");
38+
39+
SaveGame save = GetSave();
40+
41+
// Set up buttons for the civs the player can play as.
42+
civilizations = save.Civilizations;
43+
playerListContainer.Columns = (int)Math.Ceiling(save.Civilizations.Count / 12.0);
44+
string initiallySelectedCiv = save.Civilizations[1].name;
45+
foreach (Civilization civ in save.Civilizations) {
46+
if (civ.name == "A Barbarian Chiefdom") {
47+
continue;
48+
}
49+
50+
Civ3MenuButton button = new() {
51+
Text = civ.name,
52+
FontSize = 12,
53+
textPosition = Civ3MenuButton.TextPosition.TextLeftOfIcon,
54+
ButtonGroup = playerListButtonGroup,
55+
ToggleMode = true,
56+
};
57+
button.Pressed += () => {
58+
this.civilization = civ;
59+
DisplaySelectedLeader();
60+
};
61+
playerListContainer.AddChild(button);
62+
63+
if (civ.name == initiallySelectedCiv) {
64+
button.ButtonPressed = true;
65+
this.civilization = civ;
66+
}
67+
}
68+
background.AddChild(leaderHead);
69+
DisplaySelectedLeader();
70+
71+
// Set up the difficulty buttons
72+
difficultyContainer.Columns = save.Difficulties.Count;
73+
string initiallySelectedDifficulty = save.Difficulties.Any(x => x.Name == "Regent") ? "Regent" : save.Difficulties[0].Name;
74+
foreach (Difficulty difficulty in save.Difficulties) {
75+
CenterContainer container = new();
76+
difficultyContainer.AddChild(container);
77+
78+
Civ3MenuButton button = new(Civ3MenuButton.TextPosition.TextAboveIcon) {
79+
Text = difficulty.Name,
80+
ButtonGroup = difficultyButtonGroup,
81+
ToggleMode = true,
82+
};
83+
button.Pressed += () => { this.difficulty = difficulty; };
84+
container.AddChild(button);
85+
if (difficulty.Name == initiallySelectedDifficulty) {
86+
button.ButtonPressed = true;
87+
this.difficulty = difficulty;
88+
}
89+
container.CustomMinimumSize = new Vector2(843.0f / difficultyContainer.Columns, 0);
90+
}
91+
92+
TextureLoader.SetButtonTextures(confirm, "ui.confirm");
93+
confirm.Pressed += CreateGame;
94+
95+
TextureLoader.SetButtonTextures(cancel, "ui.cancel");
96+
cancel.Pressed += BackToMainMenu;
97+
}
98+
99+
private void BackToMainMenu() {
100+
GetTree().ChangeSceneToFile("res://UIElements/MainMenu/main_menu.tscn");
101+
}
102+
103+
private void DisplaySelectedLeader() {
104+
leaderHead.Texture = TextureLoader.Load("leader_heads", civilization);
105+
leaderHead.Scale = new Vector2(1.7f, 1.7f);
106+
leaderHead.SetPosition(new Vector2(414, 46));
107+
108+
string traits = string.Join(", ", civilization.traits);
109+
civLabel.Text = $"{civilization.leader} of the {civilization.noun}\n({traits})";
110+
}
111+
112+
private SaveGame GetSave() {
113+
string loadGamePath;
114+
try {
115+
loadGamePath = GetNode<GlobalSingleton>("/root/GlobalSingleton").LoadGamePath;
116+
} catch (Exception e) {
117+
// Provide a default for the editor, which can't use GlobalSingleton
118+
loadGamePath = Util.Civ3MediaPath("Conquests/Conquests/9 WWII in the Pacific.biq");
119+
}
120+
return SaveManager.LoadSave(loadGamePath,
121+
GamePaths.DefaultBicPath,
122+
(string scenarioSearchPath) => {
123+
// See corresponding logic in Game.cs
124+
Util.setModPath(scenarioSearchPath);
125+
log.Debug("RelativeModPath ", scenarioSearchPath);
126+
return Util.Civ3MediaPath("Text/PediaIcons.txt");
127+
});
128+
}
129+
130+
private void CreateGame() {
131+
GlobalSingleton global = GetNode<GlobalSingleton>("/root/GlobalSingleton");
132+
loadingLabel.Visible = true;
133+
SaveGame save = GetSave();
134+
135+
// World generation can take a bit of time if multiple attempts are
136+
// needed, so we don't want to tie up the UI thread.
137+
Thread thread = new(() => { UpdateSaveAndStartGame(save, global); });
138+
thread.Start();
139+
}
140+
141+
private void UpdateSaveAndStartGame(SaveGame save, GlobalSingleton Global) {
142+
foreach (SavePlayer sp in save.Players) {
143+
sp.human = sp.civilization == this.civilization.name;
144+
}
145+
save.GameDifficulty = difficulty;
146+
147+
log.Information("saving updated scenario");
148+
save.Save(GamePaths.DefaultGeneratedGamePath);
149+
Global.LoadGamePath = GamePaths.DefaultGeneratedGamePath;
150+
151+
log.Information("opening map");
152+
CallDeferred("StartGame");
153+
}
154+
155+
private void StartGame() {
156+
GetTree().ChangeSceneToFile("res://C7Game.tscn");
157+
}
158+
}
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
[gd_scene load_steps=9 format=3 uid="uid://3453656756"]
2+
3+
[ext_resource type="Script" path="res://UIElements/NewGame/ScenarioSetup.cs" id="1"]
4+
[ext_resource type="Script" uid="uid://doqipc4rnaotx" path="res://UIElements/Civ3TextureRect.cs" id="2"]
5+
[ext_resource type="Script" uid="uid://dcrdcjop64t6t" path="res://UIElements/Civ3TextureButton.cs" id="3"]
6+
7+
[sub_resource type="InputEventKey" id="InputEventKey_8ublj"]
8+
device = -1
9+
keycode = 4194309
10+
11+
[sub_resource type="Shortcut" id="Shortcut_33b04"]
12+
events = [SubResource("InputEventKey_8ublj")]
13+
14+
[sub_resource type="InputEventKey" id="InputEventKey_klcu1"]
15+
device = -1
16+
keycode = 4194305
17+
18+
[sub_resource type="Shortcut" id="Shortcut_7oyjg"]
19+
events = [SubResource("InputEventKey_klcu1")]
20+
21+
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ld2d8"]
22+
23+
[node name="Control" type="CenterContainer" node_paths=PackedStringArray("background", "playerListContainer", "civLabel", "difficultyContainer", "confirm", "cancel", "loadingLabel")]
24+
anchors_preset = 15
25+
anchor_right = 1.0
26+
anchor_bottom = 1.0
27+
grow_horizontal = 2
28+
grow_vertical = 2
29+
script = ExtResource("1")
30+
background = NodePath("Background")
31+
playerListContainer = NodePath("Background/CenterContainer/PlayerListContainer")
32+
civLabel = NodePath("Background/CivLabel")
33+
difficultyContainer = NodePath("Background/DifficultyContainer")
34+
confirm = NodePath("Background/Confirm")
35+
cancel = NodePath("Background/Cancel")
36+
loadingLabel = NodePath("Background/LoadingLabel")
37+
38+
[node name="Background" type="TextureRect" parent="."]
39+
layout_mode = 2
40+
script = ExtResource("2")
41+
42+
[node name="Label" type="Label" parent="Background"]
43+
layout_mode = 0
44+
offset_left = 114.0
45+
offset_top = 25.0
46+
offset_right = 326.0
47+
offset_bottom = 57.0
48+
theme_override_font_sizes/font_size = 24
49+
text = "PLAYER SETUP"
50+
horizontal_alignment = 1
51+
vertical_alignment = 1
52+
53+
[node name="Label2" type="Label" parent="Background"]
54+
layout_mode = 0
55+
offset_left = 147.0
56+
offset_top = 77.0
57+
offset_right = 294.0
58+
offset_bottom = 99.0
59+
theme_override_font_sizes/font_size = 15
60+
text = "YOUR CIVILIZATION"
61+
horizontal_alignment = 1
62+
vertical_alignment = 1
63+
64+
[node name="Label4" type="Label" parent="Background"]
65+
layout_mode = 0
66+
offset_left = 110.0
67+
offset_top = 642.0
68+
offset_right = 257.0
69+
offset_bottom = 664.0
70+
theme_override_font_sizes/font_size = 15
71+
text = "DIFFICULTY"
72+
vertical_alignment = 1
73+
74+
[node name="CenterContainer" type="CenterContainer" parent="Background"]
75+
layout_mode = 0
76+
offset_left = 72.0
77+
offset_top = 122.0
78+
offset_right = 386.0
79+
offset_bottom = 460.0
80+
81+
[node name="PlayerListContainer" type="GridContainer" parent="Background/CenterContainer"]
82+
layout_mode = 2
83+
theme_override_constants/h_separation = 10
84+
theme_override_constants/v_separation = 10
85+
columns = 3
86+
87+
[node name="DifficultyContainer" type="GridContainer" parent="Background"]
88+
layout_mode = 0
89+
offset_left = 91.0
90+
offset_top = 690.0
91+
offset_right = 934.0
92+
offset_bottom = 750.0
93+
columns = 8
94+
95+
[node name="CivLabel" type="Label" parent="Background"]
96+
layout_mode = 0
97+
offset_left = 421.0
98+
offset_top = 289.0
99+
offset_right = 608.0
100+
offset_bottom = 368.0
101+
text = "Hannibal of the Carthaginians
102+
(Industrious, Seafaring)"
103+
horizontal_alignment = 1
104+
vertical_alignment = 1
105+
autowrap_mode = 2
106+
107+
[node name="Confirm" type="TextureButton" parent="Background"]
108+
layout_mode = 0
109+
offset_left = 960.0
110+
offset_top = 728.0
111+
offset_right = 979.0
112+
offset_bottom = 747.0
113+
shortcut = SubResource("Shortcut_33b04")
114+
script = ExtResource("3")
115+
116+
[node name="Cancel" type="TextureButton" parent="Background"]
117+
layout_mode = 0
118+
offset_left = 988.0
119+
offset_top = 729.0
120+
offset_right = 1007.0
121+
offset_bottom = 748.0
122+
shortcut = SubResource("Shortcut_7oyjg")
123+
script = ExtResource("3")
124+
125+
[node name="LoadingLabel" type="Label" parent="Background"]
126+
visible = false
127+
layout_mode = 0
128+
offset_left = 310.0
129+
offset_top = 325.0
130+
offset_right = 717.0
131+
offset_bottom = 434.0
132+
theme_override_font_sizes/font_size = 38
133+
theme_override_styles/normal = SubResource("StyleBoxFlat_ld2d8")
134+
text = "Loading..."
135+
horizontal_alignment = 1
136+
vertical_alignment = 1

C7Engine/C7GameData/ID.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,11 @@ public static ID None(string key) {
3434
}
3535

3636
public static ID FromString(string str) {
37-
string[] split = str.Split('-', 2);
38-
string key = split[0];
39-
int n = split[1] == "none" ? magicNoneIdNumber : int.Parse(split[1]);
37+
List<string> split = str.Split('-').ToList();
38+
// To handle units like "Man-O-War" we need to only look at the final
39+
// element of the .Split call to get the id.
40+
string key = string.Join("-", split.GetRange(0, split.Count - 1));
41+
int n = split[split.Count - 1] == "none" ? magicNoneIdNumber : int.Parse(split[split.Count - 1]);
4042
if (n < 0) {
4143
throw new Exception($"ID cannot have a negative number, got {n}");
4244
}

0 commit comments

Comments
 (0)