Skip to content

Commit 5d50fba

Browse files
authored
Add script for editing TeamDelays
1 parent 827ce5c commit 5d50fba

File tree

2 files changed

+363
-0
lines changed

2 files changed

+363
-0
lines changed
Lines changed: 359 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,359 @@
1+
// Script for setting the difficulty settings of the map (for missions against the AI)
2+
3+
// Using clauses.
4+
// Unless you know what's in the WAE code-base, you want to always include
5+
// these "standard usings".
6+
using Microsoft.Xna.Framework;
7+
using Rampastring.Tools;
8+
using Rampastring.XNAUI;
9+
using Rampastring.XNAUI.XNAControls;
10+
using System;
11+
using System.Collections.Generic;
12+
using System.Diagnostics;
13+
using System.IO;
14+
using System.Linq;
15+
using System.Text;
16+
using TSMapEditor;
17+
using TSMapEditor.GameMath;
18+
using TSMapEditor.Initialization;
19+
using TSMapEditor.Misc;
20+
using TSMapEditor.Models;
21+
using TSMapEditor.Mutations;
22+
using TSMapEditor.Rendering;
23+
using TSMapEditor.Scripts;
24+
using TSMapEditor.UI;
25+
using TSMapEditor.UI.Controls;
26+
using TSMapEditor.UI.Windows;
27+
28+
namespace WAEScript
29+
{
30+
/// <summary>
31+
/// Script for setting the map's difficulty settings.
32+
/// Currently only support getting and setting the map's Team Delays.
33+
/// </summary>
34+
public class SetMapDifficultySettingsScript
35+
{
36+
/// <summary>
37+
/// Our custom window class.
38+
/// </summary>
39+
class SetMapDifficultySettingsWindow : INItializableWindow
40+
{
41+
public SetMapDifficultySettingsWindow(WindowManager windowManager, ScriptDependencies scriptDependencies) : base(windowManager)
42+
{
43+
this.scriptDependencies = scriptDependencies;
44+
}
45+
46+
private readonly ScriptDependencies scriptDependencies;
47+
48+
private XNACheckBox chkOverrideTeamDelays;
49+
private XNALabel lblTeamDelayHard;
50+
private XNALabel lblTeamDelayMedium;
51+
private XNALabel lblTeamDelayEasy;
52+
private EditorNumberTextBox tbTeamDelayHard;
53+
private EditorNumberTextBox tbTeamDelayMedium;
54+
private EditorNumberTextBox tbTeamDelayEasy;
55+
private EditorButton btnApply;
56+
57+
private List<XNAControl> teamDelayControls = new List<XNAControl>();
58+
59+
private readonly string sectionName = "General";
60+
private readonly string keyName = "TeamDelays";
61+
62+
public override void Initialize()
63+
{
64+
Name = nameof(SetMapDifficultySettingsWindow);
65+
string uiConfig =
66+
@"
67+
[SetMapDifficultySettingsWindow]
68+
$CC0=lblHeader:XNALabel
69+
$CC01=lblDescription:XNALabel
70+
$Width=400
71+
$Height=180
72+
$CC02=chkOverrideTeamDelays:XNACheckBox
73+
$CC03=lblTeamDelayHard:XNALabel
74+
$CC04=tbTeamDelayHard:EditorNumberTextBox
75+
$CC05=lblTeamDelayMedium:XNALabel
76+
$CC06=tbTeamDelayMedium:EditorNumberTextBox
77+
$CC07=lblTeamDelayEasy:XNALabel
78+
$CC08=tbTeamDelayEasy:EditorNumberTextBox
79+
$CC09=btnApply:EditorButton
80+
HasCloseButton=yes
81+
82+
[lblHeader]
83+
$X=EMPTY_SPACE_SIDES
84+
$Y=EMPTY_SPACE_TOP
85+
$Text=translate(Difficulty Settings)
86+
FontIndex=1
87+
88+
[lblDescription]
89+
$X=getX(lblHeader)
90+
$Y=getBottom(lblHeader) + (VERTICAL_SPACING * 2)
91+
$Text=translate(Manage difficulty settings for the map.)
92+
93+
[chkOverrideTeamDelays]
94+
$X=getX(lblHeader)
95+
$Y=getBottom(lblDescription) + (VERTICAL_SPACING * 3)
96+
$Text=translate(Override Team Delays)
97+
98+
[lblTeamDelayHard]
99+
$X=getX(lblHeader) + 20
100+
$Y=getBottom(chkOverrideTeamDelays) + (VERTICAL_SPACING * 2)
101+
$Text=translate(Hard:)
102+
103+
[tbTeamDelayHard]
104+
$X=getRight(lblTeamDelayHard) + HORIZONTAL_SPACING
105+
$Y=getY(lblTeamDelayHard)
106+
Width=50
107+
108+
[lblTeamDelayMedium]
109+
$X=getRight(tbTeamDelayHard) + 15
110+
$Y=getY(lblTeamDelayHard)
111+
$Text=translate(Medium:)
112+
113+
[tbTeamDelayMedium]
114+
$X=getRight(lblTeamDelayMedium) + HORIZONTAL_SPACING
115+
$Y=getY(lblTeamDelayHard)
116+
Width=50
117+
118+
[lblTeamDelayEasy]
119+
$X=getRight(tbTeamDelayMedium) + 15
120+
$Y=getY(lblTeamDelayHard)
121+
$Text=translate(Easy:)
122+
123+
[tbTeamDelayEasy]
124+
$X=getRight(lblTeamDelayEasy) + HORIZONTAL_SPACING
125+
$Y=getY(lblTeamDelayHard)
126+
Width=50
127+
128+
[btnApply]
129+
$Width=100
130+
$X=horizontalCenterOnParent()
131+
$Y=getHeight(SetMapDifficultySettingsWindow) - getHeight(btnApply) - (VERTICAL_SPACING * 2)
132+
$Text=translate(Apply)
133+
";
134+
135+
var bytes = Encoding.UTF8.GetBytes(uiConfig);
136+
using (var stream = new MemoryStream(bytes))
137+
{
138+
ConfigIni = new IniFile(stream, Encoding.UTF8);
139+
}
140+
141+
base.Initialize();
142+
143+
chkOverrideTeamDelays = FindChild<XNACheckBox>(nameof(chkOverrideTeamDelays));
144+
145+
lblTeamDelayHard = FindChild<XNALabel>(nameof(lblTeamDelayHard));
146+
lblTeamDelayMedium = FindChild<XNALabel>(nameof(lblTeamDelayMedium));
147+
lblTeamDelayEasy = FindChild<XNALabel>(nameof(lblTeamDelayEasy));
148+
149+
tbTeamDelayHard = FindChild<EditorNumberTextBox>(nameof(tbTeamDelayHard));
150+
tbTeamDelayMedium = FindChild<EditorNumberTextBox>(nameof(tbTeamDelayMedium));
151+
tbTeamDelayEasy = FindChild<EditorNumberTextBox>(nameof(tbTeamDelayEasy));
152+
btnApply = FindChild<EditorButton>(nameof(btnApply));
153+
154+
teamDelayControls.AddRange(new List<XNAControl>
155+
{
156+
lblTeamDelayHard, lblTeamDelayMedium, lblTeamDelayEasy,
157+
tbTeamDelayHard, tbTeamDelayMedium, tbTeamDelayEasy
158+
});
159+
160+
chkOverrideTeamDelays.CheckedChanged += ChkOverrideTeamDelays_CheckedChanged;
161+
btnApply.LeftClick += BtnApply_LeftClick;
162+
}
163+
164+
private void ChkOverrideTeamDelays_CheckedChanged(object sender, EventArgs e)
165+
{
166+
foreach (var teamDelayControl in teamDelayControls)
167+
{
168+
if (chkOverrideTeamDelays.Checked)
169+
teamDelayControl.Enable();
170+
else
171+
teamDelayControl.Disable();
172+
}
173+
}
174+
175+
private void BtnApply_LeftClick(object sender, InputEventArgs e)
176+
{
177+
bool writeTeamDelays = chkOverrideTeamDelays.Checked;
178+
179+
if (writeTeamDelays)
180+
{
181+
if (!IsValidTeamDelay(tbTeamDelayHard.Value) ||
182+
!IsValidTeamDelay(tbTeamDelayMedium.Value) ||
183+
!IsValidTeamDelay(tbTeamDelayEasy.Value))
184+
{
185+
EditorMessageBox.Show(WindowManager,
186+
Translator.Translate("SetMapDifficultySettings.InvalidTeamDelay.Title", "Invalid Team Delay"),
187+
Translator.Translate("SetMapDifficultySettings.InvalidTeamDelay.Description", "One or more of the team delay values are not valid. Team Delays must be positive integers."),
188+
MessageBoxButtons.OK);
189+
190+
return;
191+
}
192+
}
193+
194+
var loadedMapIni = scriptDependencies.Map.LoadedINI;
195+
196+
var section = loadedMapIni.GetSection(sectionName);
197+
if (writeTeamDelays)
198+
{
199+
// Create section if does not exist yet
200+
if (section == null)
201+
{
202+
section = new IniSection(sectionName);
203+
loadedMapIni.AddSection(section);
204+
}
205+
206+
List<int> teamDelays = new List<int> { tbTeamDelayHard.Value, tbTeamDelayMedium.Value, tbTeamDelayEasy.Value };
207+
section.SetListValue(keyName, teamDelays, ',');
208+
}
209+
else
210+
{
211+
if (section != null)
212+
{
213+
section.RemoveKey(keyName);
214+
215+
// If there are no other keys for the General section after removing the Team Delays key, remove the section entirely.
216+
if (section.Keys.Count == 0)
217+
loadedMapIni.RemoveSection(sectionName);
218+
}
219+
}
220+
221+
EditorMessageBox.Show(WindowManager,
222+
Translator.Translate("SetMapDifficultySettings.Apply.Title", "Success!"),
223+
Translator.Translate("SetMapDifficultySettings.Apply.Description", "Difficulty settings were were successfully set. Save the map in order to write the values to it."),
224+
MessageBoxButtons.OK);
225+
226+
Hide();
227+
}
228+
229+
private bool LoadTeamDelayValues()
230+
{
231+
bool writeTeamDelays = false;
232+
string[] teamDelays = null;
233+
234+
var section = scriptDependencies.Map.LoadedINI.GetSection(sectionName);
235+
if (section != null)
236+
{
237+
teamDelays = section.GetListValue(keyName, ',', s => s.Trim()).ToArray();
238+
if (teamDelays.Length > 0)
239+
{
240+
if (teamDelays.Length != 3)
241+
{
242+
EditorMessageBox.Show(WindowManager,
243+
Translator.Translate("InvalidTeamDelaysLoadingCount.Title", "Invalid TeamDelays= length"),
244+
Translator.Translate("InvalidTeamDelaysLoadingCount.Description", $"Invalid amount of TeamDelays=, expected 3 but got {teamDelays.Length}. Defaulting to no team delays."),
245+
MessageBoxButtons.OK);
246+
247+
return false;
248+
}
249+
250+
foreach (var teamDelay in teamDelays)
251+
{
252+
if (!IsValidTeamDelay(teamDelay))
253+
{
254+
EditorMessageBox.Show(WindowManager,
255+
Translator.Translate("InvalidTeamDelaysLoadingValue.Title", "Invalid TeamDelays values"),
256+
Translator.Translate("InvalidTeamDelaysLoadingValue.Description", $"One or more TeamDelays= values are invalid. Check that each TeamDelay value is a positive integer."),
257+
MessageBoxButtons.OK);
258+
259+
return false;
260+
}
261+
}
262+
263+
writeTeamDelays = true;
264+
}
265+
else
266+
{
267+
teamDelays = null;
268+
}
269+
}
270+
271+
if (writeTeamDelays)
272+
{
273+
chkOverrideTeamDelays.Checked = true;
274+
foreach (var teamDelayControl in teamDelayControls)
275+
{
276+
teamDelayControl.Enable();
277+
}
278+
}
279+
else
280+
{
281+
chkOverrideTeamDelays.Checked = false;
282+
foreach (var teamDelayControl in teamDelayControls)
283+
{
284+
teamDelayControl.Disable();
285+
}
286+
}
287+
288+
tbTeamDelayHard.Text = teamDelays == null ? string.Empty : teamDelays[0];
289+
tbTeamDelayMedium.Text = teamDelays == null ? string.Empty : teamDelays[1];
290+
tbTeamDelayEasy.Text = teamDelays == null ? string.Empty : teamDelays[2];
291+
292+
return true;
293+
}
294+
295+
private bool IsValidTeamDelay(int teamDelay)
296+
{
297+
return teamDelay > 0;
298+
}
299+
300+
private bool IsValidTeamDelay(string teamDelay)
301+
{
302+
bool valid = int.TryParse(teamDelay, out int parsedTeamDelay);
303+
304+
if (!valid)
305+
return false;
306+
307+
return IsValidTeamDelay(parsedTeamDelay);
308+
}
309+
310+
public void Open()
311+
{
312+
bool isLoadingSucceeded = LoadTeamDelayValues();
313+
if (!isLoadingSucceeded)
314+
return;
315+
316+
Show();
317+
}
318+
319+
/// <summary>
320+
/// Unsubscribe from event handlers to allow the garbage collector to clean up memory when the window is destroyed.
321+
/// </summary>
322+
public override void Kill()
323+
{
324+
btnApply.LeftClick -= BtnApply_LeftClick;
325+
base.Kill();
326+
}
327+
}
328+
329+
/// <summary>
330+
/// This needs to be declared as 2 so the script runner knows we support ScriptDependencies.
331+
/// </summary>
332+
public int ApiVersion { get; } = 2;
333+
334+
/// <summary>
335+
/// Script dependencies object that is assigned by editor when the script is run.
336+
/// Contains Map, CursorActionTarget (MapView instance), EditorState, WindowManager, and WindowController.
337+
/// </summary>
338+
public ScriptDependencies ScriptDependencies { get; set; }
339+
340+
private SetMapDifficultySettingsWindow setMapDifficultySettingsWindow;
341+
342+
/// <summary>
343+
/// Main function for executing the script.
344+
/// </summary>
345+
public void Perform()
346+
{
347+
setMapDifficultySettingsWindow = new SetMapDifficultySettingsWindow(ScriptDependencies.WindowManager, ScriptDependencies);
348+
ScriptDependencies.WindowController.AddWindow(setMapDifficultySettingsWindow);
349+
setMapDifficultySettingsWindow.Closed += SetMapDifficultySettingsWindow_Closed;
350+
ScriptDependencies.WindowManager.AddCallback(new Action(() => setMapDifficultySettingsWindow.Open()));
351+
}
352+
353+
private void SetMapDifficultySettingsWindow_Closed(object sender, EventArgs e)
354+
{
355+
setMapDifficultySettingsWindow.Closed -= SetMapDifficultySettingsWindow_Closed;
356+
ScriptDependencies.WindowController.RemoveWindow(setMapDifficultySettingsWindow);
357+
}
358+
}
359+
}

src/TSMapEditor/TSMapEditor.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
<Compile Remove="Config\Scripts\Replace Autumn Jungle Grass With Summer Grass.cs" />
3636
<Compile Remove="Config\Scripts\Replace Autumn Trees With Summer Trees.cs" />
3737
<Compile Remove="Config\Scripts\Replace Frost With Clear.cs" />
38+
<Compile Remove="Config\Scripts\Set Map Difficulty Settings.cs" />
3839
</ItemGroup>
3940
<ItemGroup>
4041
<None Update="Config\DefaultSettings.ini">
@@ -530,6 +531,9 @@
530531
<None Include="Config\Scripts\Replace Frost With Clear.cs">
531532
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
532533
</None>
534+
<None Include="Config\Scripts\Set Map Difficulty Settings.cs">
535+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
536+
</None>
533537
</ItemGroup>
534538
<ItemGroup>
535539
<Compile Update="Config\Scripts\Add Map Reveal Trigger.cs">

0 commit comments

Comments
 (0)