@@ -146,6 +146,8 @@ protected GameModeMap GameModeMap
146146 protected ToolTip mapListTooltip ;
147147 protected XNAClientDropDown ddGameModeMapFilter ;
148148 protected XNALabel lblGameModeSelect ;
149+ protected XNAClientDropDown ddDifficulty ;
150+ protected XNALabel lblDifficulty ;
149151 protected XNAContextMenu mapContextMenu ;
150152 private XNAContextMenuItem toggleFavoriteItem ;
151153
@@ -173,6 +175,7 @@ protected GameModeMap GameModeMap
173175 protected int UniqueGameID { get ; set ; }
174176 protected int SideCount { get ; private set ; }
175177 protected int RandomSelectorCount { get ; private set ; } = 1 ;
178+ protected int PreviousSelectedDifficulty { get ; set ; }
176179
177180 protected List < int [ ] > RandomSelectors = new List < int [ ] > ( ) ;
178181
@@ -299,6 +302,21 @@ public override void Initialize()
299302
300303 lblGameModeSelect = FindChild < XNALabel > ( nameof ( lblGameModeSelect ) ) ;
301304
305+ ddDifficulty = FindChild < XNAClientDropDown > ( nameof ( ddDifficulty ) , true ) ;
306+ lblDifficulty = FindChild < XNALabel > ( nameof ( lblDifficulty ) , true ) ;
307+
308+ if ( ddDifficulty != null )
309+ {
310+ // Hardcode difficulty items just in case someone tries something stupid.
311+ ddDifficulty . Items . Clear ( ) ;
312+
313+ foreach ( string difficultyName in ProgramConstants . DIFFICULTY_NAMES )
314+ ddDifficulty . AddItem ( difficultyName ) ;
315+
316+ ddDifficulty . SelectedIndex = - 1 ;
317+ ddDifficulty . SelectedIndexChanged += DdDifficulty_SelectedIndexChanged ;
318+ }
319+
302320 InitBtnMapSort ( ) ;
303321
304322 tbMapSearch = FindChild < XNASuggestionTextBox > ( nameof ( tbMapSearch ) ) ;
@@ -568,9 +586,23 @@ protected void DdGameModeMapFilter_SelectedIndexChanged(object sender, EventArgs
568586 ListMaps ( ) ;
569587
570588 if ( lbGameModeMapList . SelectedIndex == - 1 )
589+ {
571590 lbGameModeMapList . SelectedIndex = 0 ; // Select default GameModeMap
591+ UpdateDifficultyDropdown ( ) ;
592+ }
572593 else
594+ {
573595 ChangeMap ( GameModeMap ) ;
596+ }
597+ }
598+
599+ protected void DdDifficulty_SelectedIndexChanged ( object sender , EventArgs e )
600+ {
601+ if ( ddDifficulty . SelectedIndex >= 0 )
602+ PreviousSelectedDifficulty = ddDifficulty . SelectedIndex ;
603+
604+ OnGameOptionChanged ( ) ;
605+ SetMapLabels ( ) ;
574606 }
575607
576608 protected void BtnPlayerExtraOptions_LeftClick ( object sender , EventArgs e )
@@ -694,7 +726,7 @@ protected void ListMaps()
694726 {
695727 // Note: StatisticsManager.Statistics must be initialized to call `HasBeatCoOpMap()`. This means StatisticsWindow must be initialized before any lobbies extending GameLobbyBase.
696728 if ( StatisticsManager . Instance . HasBeatCoOpMap ( gameModeMap . Map . UntranslatedName , gameModeMap . GameMode . UntranslatedUIName ) )
697- rankItem . Texture = RankTextures [ Math . Abs ( 2 - gameModeMap . GameMode . CoopDifficultyLevel ) + 1 ] ;
729+ rankItem . Texture = RankTextures [ Math . Abs ( 2 - GetCoopDifficultyLevel ( ) ) + 1 ] ;
698730 else
699731 rankItem . Texture = RankTextures [ 0 ] ;
700732 }
@@ -747,6 +779,45 @@ protected void ListMaps()
747779 LbGameModeMapList_SelectedIndexChanged ( ) ;
748780 }
749781
782+ protected int GetCoopDifficultyLevel ( )
783+ {
784+ var gameMode = GameModeMap ? . GameMode ;
785+
786+ if ( gameMode != null )
787+ {
788+ if ( gameMode . UseDifficultyDropDown && ddDifficulty != null && ddDifficulty . SelectedIndex >= 0 )
789+ {
790+ return ddDifficulty . Items . Count - ddDifficulty . SelectedIndex - 1 ;
791+ }
792+ else
793+ {
794+ return gameMode . CoopDifficultyLevel ;
795+ }
796+ }
797+
798+ return 0 ;
799+ }
800+
801+ protected virtual void UpdateDifficultyDropdown ( )
802+ {
803+ bool enabled = GameModeMap != null && GameModeMap . GameMode != null && GameModeMap . GameMode . UseDifficultyDropDown ;
804+
805+ if ( ddDifficulty != null )
806+ {
807+ ddDifficulty . AllowDropDown = enabled ;
808+
809+ if ( enabled && ddDifficulty . SelectedIndex < 0 )
810+ ddDifficulty . SelectedIndex = PreviousSelectedDifficulty ;
811+ else if ( ! enabled )
812+ ddDifficulty . SelectedIndex = - 1 ;
813+ }
814+
815+ if ( lblDifficulty != null )
816+ {
817+ lblDifficulty . TextColor = enabled ? UISettings . ActiveSettings . TextColor : UISettings . ActiveSettings . DisabledItemColor ;
818+ }
819+ }
820+
750821 protected abstract int GetDefaultMapRankIndex ( GameModeMap gameModeMap ) ;
751822
752823 private void LbGameModeMapList_RightClick ( object sender , EventArgs e )
@@ -1587,7 +1658,7 @@ private PlayerHouseInfo[] WriteSpawnIni()
15871658
15881659 GameMode . ApplySpawnIniCode ( spawnIni ) ; // Forced options from the game mode
15891660 Map . ApplySpawnIniCode ( spawnIni , Players . Count + AIPlayers . Count ,
1590- AIPlayers . Count , GameMode . CoopDifficultyLevel ) ; // Forced options from the map
1661+ AIPlayers . Count , GetCoopDifficultyLevel ( ) ) ; // Forced options from the map
15911662
15921663 // Player options
15931664
@@ -1814,6 +1885,23 @@ private void WriteMap(PlayerHouseInfo[] houseInfos)
18141885 mapIni . SetStringValue ( "Basic" , "OriginalFilename" , mapIniFileName ) ;
18151886 }
18161887
1888+ if ( GameMode . UseDifficultyDropDown && ddDifficulty != null && ddDifficulty . SelectedIndex >= 0 )
1889+ {
1890+ var filePath = string . Empty ;
1891+
1892+ try
1893+ {
1894+ filePath = ClientConfiguration . Instance . CoopDifficultyINIPaths [ ddDifficulty . SelectedIndex ] ;
1895+ }
1896+ catch ( IndexOutOfRangeException )
1897+ {
1898+ Logger . Log ( $ "CoopDifficultyINIPaths does not contain file path for difficulty index { ddDifficulty . SelectedIndex } ") ;
1899+ }
1900+
1901+ IniFile difficultyIni = new IniFile ( filePath ) ;
1902+ MapCodeHelper . ApplyMapCode ( mapIni , difficultyIni ) ;
1903+ }
1904+
18171905 foreach ( GameLobbyCheckBox checkBox in CheckBoxes )
18181906 checkBox . ApplyMapCode ( mapIni , GameMode ) ;
18191907
@@ -2315,6 +2403,11 @@ protected virtual void SetMapLabels()
23152403 lblMapAuthor . Text = "By" . L10N ( "Client:Main:AuthorBy" ) + " " + Renderer . GetSafeString ( Map . Author , lblMapAuthor . FontIndex ) ;
23162404 lblGameMode . Text = "Game mode:" . L10N ( "Client:Main:GameModeLabel" ) + " " + GameMode . UIName ;
23172405 lblMapSize . Text = "Size:" . L10N ( "Client:Main:MapSize" ) + " " + Map . GetSizeString ( ) ;
2406+
2407+ if ( GameMode . UseDifficultyDropDown && ddDifficulty != null && ddDifficulty . SelectedIndex >= 0 )
2408+ {
2409+ lblGameMode . Text += " (" + "Difficulty: " . L10N ( "Client:Main:DifficultyLabel" ) + ddDifficulty . SelectedItem . Text + ")" ;
2410+ }
23182411 }
23192412
23202413 /// <summary>
@@ -2333,6 +2426,7 @@ protected virtual void ChangeMap(GameModeMap gameModeMap)
23332426 {
23342427 MapPreviewBox . GameModeMap = null ;
23352428 OnGameOptionChanged ( ) ;
2429+ UpdateDifficultyDropdown ( ) ;
23362430 return ;
23372431 }
23382432
@@ -2345,6 +2439,8 @@ protected virtual void ChangeMap(GameModeMap gameModeMap)
23452439 foreach ( var checkBox in CheckBoxes )
23462440 checkBox . AllowChecking = true ;
23472441
2442+ UpdateDifficultyDropdown ( ) ;
2443+
23482444 // We could either pass the CheckBoxes and DropDowns of this class
23492445 // to the Map and GameMode instances and let them apply their forced
23502446 // options, or we could do it in this class with helper functions.
0 commit comments