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+ }
0 commit comments