1- using ClientCore ;
2- using Microsoft . Xna . Framework ;
31using System ;
42using System . Collections . Generic ;
5- using DTAClient . Domain ;
3+ using System . Globalization ;
64using System . IO ;
5+
6+ using ClientCore ;
7+ using ClientCore . Enums ;
8+ using ClientCore . Extensions ;
9+
710using ClientGUI ;
8- using Rampastring . XNAUI . XNAControls ;
9- using Rampastring . XNAUI ;
10- using Rampastring . Tools ;
11+
1112using ClientUpdater ;
12- using ClientCore . Extensions ;
13- using ClientCore . Enums ;
1413
15- namespace DTAClient . DXGUI . Generic
14+ using DTAClient . Domain ;
15+
16+ using Microsoft . Xna . Framework ;
17+
18+ using Rampastring . Tools ;
19+ using Rampastring . XNAUI ;
20+ using Rampastring . XNAUI . XNAControls ;
21+
22+ namespace DTAClient . DXGUI . Campaign
1623{
1724 public class CampaignSelector : XNAWindow
1825 {
1926 private const int DEFAULT_WIDTH = 650 ;
2027 private const int DEFAULT_HEIGHT = 600 ;
2128
29+ private const string SETTINGS_PATH = "Client/CampaignSettings.ini" ;
30+
2231 private static string [ ] DifficultyNames = new string [ ] { "Easy" , "Medium" , "Hard" } ;
2332
2433 private static string [ ] DifficultyIniPaths = new string [ ]
@@ -42,6 +51,11 @@ public CampaignSelector(WindowManager windowManager, DiscordHandler discordHandl
4251 private XNATrackbar trbDifficultySelector ;
4352
4453 private CheaterWindow cheaterWindow ;
54+
55+ public List < CampaignCheckBox > CheckBoxes { get ; } = new ( ) ;
56+ public List < CampaignDropDown > DropDowns { get ; } = new ( ) ;
57+
58+ private IniFile gameOptionsIni ;
4559
4660 private string [ ] filesToCheck = new string [ ]
4761 {
@@ -171,6 +185,9 @@ public override void Initialize()
171185 AddChild ( lblNormal ) ;
172186 AddChild ( lblHard ) ;
173187
188+ gameOptionsIni = new IniFile ( SafePath . CombineFilePath ( ProgramConstants . GetBaseResourcePath ( ) ,
189+ ClientConfiguration . GAME_OPTIONS ) ) ;
190+
174191 // Set control attributes from INI file
175192 base . Initialize ( ) ;
176193
@@ -189,6 +206,8 @@ public override void Initialize()
189206 cheaterWindow . CenterOnParent ( ) ;
190207 cheaterWindow . YesClicked += CheaterWindow_YesClicked ;
191208 cheaterWindow . Disable ( ) ;
209+
210+ LoadSettings ( ) ;
192211 }
193212
194213 private void LbCampaignList_SelectedIndexChanged ( object sender , EventArgs e )
@@ -222,11 +241,14 @@ private void LbCampaignList_SelectedIndexChanged(object sender, EventArgs e)
222241
223242 private void BtnCancel_LeftClick ( object sender , EventArgs e )
224243 {
244+ SaveSettings ( ) ;
225245 Disable ( ) ;
226246 }
227247
228248 private void BtnLaunch_LeftClick ( object sender , EventArgs e )
229249 {
250+ SaveSettings ( ) ;
251+
230252 int selectedMissionId = lbCampaignList . SelectedIndex ;
231253
232254 Mission mission = Missions [ selectedMissionId ] ;
@@ -268,54 +290,94 @@ private void CheaterWindow_YesClicked(object sender, EventArgs e)
268290 /// </summary>
269291 private void LaunchMission ( Mission mission )
270292 {
293+ string scenario = mission . Scenario ;
294+
295+ FileInfo spawnerSettingsFile = SafePath . GetFile ( ProgramConstants . GamePath , ProgramConstants . SPAWNER_SETTINGS ) ;
296+
297+ spawnerSettingsFile . Delete ( ) ;
298+
271299 bool copyMapsToSpawnmapINI = ClientConfiguration . Instance . CopyMissionsToSpawnmapINI ;
272300
273301 Logger . Log ( "About to write spawn.ini." ) ;
274- using ( var spawnStreamWriter = new StreamWriter ( SafePath . CombineFilePath ( ProgramConstants . GamePath , "spawn.ini" ) ) )
302+ IniFile spawnIni = new ( spawnerSettingsFile . FullName )
275303 {
276- spawnStreamWriter . WriteLine ( "; Generated by DTA Client" ) ;
277- spawnStreamWriter . WriteLine ( "[Settings]" ) ;
278- if ( copyMapsToSpawnmapINI )
279- spawnStreamWriter . WriteLine ( "Scenario=spawnmap.ini" ) ;
280- else
281- spawnStreamWriter . WriteLine ( "Scenario=" + mission . Scenario ) ;
282-
283- // No one wants to play missions on Fastest, so we'll change it to Faster
284- if ( UserINISettings . Instance . GameSpeed == 0 )
285- UserINISettings . Instance . GameSpeed . Value = 1 ;
286-
287- spawnStreamWriter . WriteLine ( "CampaignID=" + mission . CampaignID ) ;
288- spawnStreamWriter . WriteLine ( "GameSpeed=" + UserINISettings . Instance . GameSpeed ) ;
289-
290- if ( ClientConfiguration . Instance . ClientGameType == ClientType . YR ||
291- ClientConfiguration . Instance . ClientGameType == ClientType . Ares )
292- spawnStreamWriter . WriteLine ( "Ra2Mode=" + ! mission . RequiredAddon ) ;
293- else if ( ClientConfiguration . Instance . ClientGameType == ClientType . TS )
294- spawnStreamWriter . WriteLine ( "Firestorm=" + mission . RequiredAddon ) ;
295-
296- spawnStreamWriter . WriteLine ( "CustomLoadScreen=" + LoadingScreenController . GetLoadScreenName ( mission . Side . ToString ( ) ) ) ;
297- spawnStreamWriter . WriteLine ( "IsSinglePlayer=Yes" ) ;
298- spawnStreamWriter . WriteLine ( "SidebarHack=" + ClientConfiguration . Instance . SidebarHack ) ;
299- spawnStreamWriter . WriteLine ( "Side=" + mission . Side ) ;
300- spawnStreamWriter . WriteLine ( "BuildOffAlly=" + mission . BuildOffAlly ) ;
301-
302- UserINISettings . Instance . Difficulty . Value = trbDifficultySelector . Value ;
303-
304- spawnStreamWriter . WriteLine ( "DifficultyModeHuman=" + ( mission . PlayerAlwaysOnNormalDifficulty ? "1" : trbDifficultySelector . Value . ToString ( ) ) ) ;
305- spawnStreamWriter . WriteLine ( "DifficultyModeComputer=" + GetComputerDifficulty ( ) ) ;
306-
307- spawnStreamWriter . WriteLine ( ) ;
308- spawnStreamWriter . WriteLine ( ) ;
309- spawnStreamWriter . WriteLine ( ) ;
304+ Comment = "Generated by CnCNet Client"
305+ } ;
306+ IniSection spawnIniSettings = new ( "Settings" ) ;
307+
308+ if ( copyMapsToSpawnmapINI )
309+ spawnIniSettings . AddKey ( "Scenario" , "spawnmap.ini" ) ;
310+ else
311+ spawnIniSettings . AddKey ( "Scenario" , scenario . ToUpperInvariant ( ) ) ;
312+
313+ // No one wants to play missions on Fastest, so we'll change it to Faster
314+ if ( UserINISettings . Instance . GameSpeed == 0 )
315+ UserINISettings . Instance . GameSpeed . Value = 1 ;
316+
317+ spawnIniSettings . AddKey ( "CampaignID" , mission . CampaignID . ToString ( CultureInfo . InvariantCulture ) ) ;
318+ spawnIniSettings . AddKey ( "GameSpeed" , UserINISettings . Instance . GameSpeed . ToString ( ) ) ;
319+
320+ switch ( ClientConfiguration . Instance . ClientGameType )
321+ {
322+ case ClientType . YR or ClientType . Ares :
323+ spawnIniSettings . AddKey ( "Ra2Mode" , ( ! mission . RequiredAddon ) . ToString ( CultureInfo . InvariantCulture ) ) ;
324+ break ;
325+ case ClientType . TS :
326+ spawnIniSettings . AddKey ( "Firestorm" , mission . RequiredAddon . ToString ( CultureInfo . InvariantCulture ) ) ;
327+ break ;
328+ // TODO figure out the RA one
329+ }
330+
331+ spawnIniSettings . AddKey ( "CustomLoadScreen" , LoadingScreenController . GetLoadScreenName ( mission . Side . ToString ( ) ) ) ;
332+
333+ spawnIniSettings . AddKey ( "IsSinglePlayer" , "Yes" ) ;
334+ spawnIniSettings . AddKey ( "SidebarHack" , ClientConfiguration . Instance . SidebarHack . ToString ( CultureInfo . InvariantCulture ) ) ;
335+ spawnIniSettings . AddKey ( "Side" , mission . Side . ToString ( CultureInfo . InvariantCulture ) ) ;
336+ spawnIniSettings . AddKey ( "BuildOffAlly" , mission . BuildOffAlly . ToString ( CultureInfo . InvariantCulture ) ) ;
337+
338+ UserINISettings . Instance . Difficulty . Value = trbDifficultySelector . Value ;
339+
340+ spawnIniSettings . AddKey ( "DifficultyModeHuman" , mission . PlayerAlwaysOnNormalDifficulty ? "1" : trbDifficultySelector . Value . ToString ( CultureInfo . InvariantCulture ) ) ;
341+ spawnIniSettings . AddKey ( "DifficultyModeComputer" , GetComputerDifficulty ( ) . ToString ( CultureInfo . InvariantCulture ) ) ;
342+
343+ spawnIni . AddSection ( spawnIniSettings ) ;
344+
345+ foreach ( CampaignCheckBox chkBox in CheckBoxes )
346+ chkBox . ApplySpawnIniCode ( spawnIni ) ;
347+
348+ foreach ( CampaignDropDown dd in DropDowns )
349+ dd . ApplySpawnIniCode ( spawnIni ) ;
350+
351+ // Apply forced options from GameOptions.ini
352+
353+ List < string > forcedKeys = gameOptionsIni . GetSectionKeys ( "CampaignForcedSpawnIniOptions" ) ;
354+
355+ if ( forcedKeys != null )
356+ {
357+ foreach ( string key in forcedKeys )
358+ {
359+ spawnIni . SetStringValue ( "Settings" , key ,
360+ gameOptionsIni . GetStringValue ( "CampaignForcedSpawnIniOptions" , key , String . Empty ) ) ;
361+ }
310362 }
311363
364+ spawnIni . WriteIniFile ( ) ;
365+
312366 var difficultyIni = new IniFile ( SafePath . CombineFilePath ( ProgramConstants . GamePath , DifficultyIniPaths [ trbDifficultySelector . Value ] ) ) ;
313367 string difficultyName = DifficultyNames [ trbDifficultySelector . Value ] ;
314368
315369 if ( copyMapsToSpawnmapINI )
316370 {
317371 var mapIni = new IniFile ( SafePath . CombineFilePath ( ProgramConstants . GamePath , mission . Scenario ) ) ;
372+
318373 IniFile . ConsolidateIniFiles ( mapIni , difficultyIni ) ;
374+
375+ foreach ( CampaignCheckBox chkBox in CheckBoxes )
376+ chkBox . ApplyMapCode ( mapIni , gameMode : null ) ;
377+
378+ foreach ( CampaignDropDown dd in DropDowns )
379+ dd . ApplyMapCode ( mapIni , gameMode : null ) ;
380+
319381 mapIni . WriteIniFile ( SafePath . CombineFilePath ( ProgramConstants . GamePath , "spawnmap.ini" ) ) ;
320382 }
321383
@@ -420,6 +482,58 @@ private bool ParseBattleIni(string path)
420482 Logger . Log ( "Finished parsing " + path + "." ) ;
421483 return true ;
422484 }
485+
486+ /// <summary>
487+ /// Saves settings to an INI file on the file system.
488+ /// </summary>
489+ private void SaveSettings ( )
490+ {
491+ if ( ! ClientConfiguration . Instance . SaveCampaignGameOptions )
492+ return ;
493+
494+ try
495+ {
496+ FileInfo settingsFileInfo = SafePath . GetFile ( ProgramConstants . GamePath , SETTINGS_PATH ) ;
497+
498+ settingsFileInfo . Delete ( ) ;
499+
500+ var settingsIni = new IniFile ( settingsFileInfo . FullName ) ;
501+
502+ foreach ( CampaignDropDown dd in DropDowns )
503+ settingsIni . SetStringValue ( "GameOptions" , dd . Name , dd . SelectedIndex . ToString ( ) ) ;
504+
505+ foreach ( CampaignCheckBox cb in CheckBoxes )
506+ settingsIni . SetStringValue ( "GameOptions" , cb . Name , cb . Checked . ToString ( ) ) ;
507+
508+ settingsIni . WriteIniFile ( ) ;
509+ }
510+ catch ( Exception ex )
511+ {
512+ Logger . Log ( $ "Saving campaign settings failed! Reason: { ex } ") ;
513+ }
514+ }
515+
516+ /// <summary>
517+ /// Loads settings from an INI file on the file system.
518+ /// </summary>
519+ private void LoadSettings ( )
520+ {
521+ if ( ! ClientConfiguration . Instance . SaveCampaignGameOptions )
522+ return ;
523+
524+ var settingsIni = new IniFile ( SafePath . CombineFilePath ( ProgramConstants . GamePath , SETTINGS_PATH ) ) ;
525+
526+ foreach ( CampaignDropDown dd in DropDowns )
527+ {
528+ dd . SelectedIndex = settingsIni . GetIntValue ( "GameOptions" , dd . Name , dd . SelectedIndex ) ;
529+
530+ if ( dd . SelectedIndex > - 1 && dd . SelectedIndex < dd . Items . Count )
531+ dd . SelectedIndex = dd . SelectedIndex ;
532+ }
533+
534+ foreach ( CampaignCheckBox cb in CheckBoxes )
535+ cb . Checked = settingsIni . GetBooleanValue ( "GameOptions" , cb . Name , cb . Checked ) ;
536+ }
423537
424538 public override void Draw ( GameTime gameTime )
425539 {
0 commit comments