@@ -77,28 +77,15 @@ TInputDeviceConfig = record
7777 LATENCY_AUTODETECT = -1 ; // for field Latency
7878 DEFAULT_RESOLUTION = ' 800x600' ;
7979 DEFAULT_THEME = ' Modern' ;
80- // TODO: the menu options only go up to 6, but there are internals that still go up to 12
81- // IMaxPlayerCount is untouched because lowering (or raising) it causes very strange behaviour, such as:
82- // * the game starts in a completely different language than the config specifies
83- // * the game crashes randomly
84- // 8 and 12 players have never worked at any point in history
85- // it all needs refactoring at some point anyway because:
86- // * a lot of code works with the _index_ of IPlayers (instead of just the number of actual players)
87- // * it should be possible to play with 5 players [without duplicating a lot of code]
88- // * there might be a valid usecase for 0 players
89- IMaxPlayerCount = 12 ;
90- // Switch colors for players 2 and 4, since player 2 line color is used
91- // for the second part in duet, and yellow (4) looks better than red (2)
92- DefaultPlayerColors: array [0 ..IMaxPlayerCount-1 ] of integer = (1 , 4 , 3 , 2 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 );
93- IPlayers: array [0 ..4 ] of UTF8String = (' 1' , ' 2' , ' 3' , ' 4' , ' 6' );
94- IPlayersVals: array [0 ..4 ] of integer = ( 1 , 2 , 3 , 4 , 6 );
80+ IMaxPlayerCount = 24 ;
9581
9682type
9783 TUTF8StringArray = array of UTF8String;
9884 TIntegerArray = array of integer;
9985
10086function GetNameTemplateIndexFromKey (const Key: cardinal): integer;
10187function CreateNumericOptionArray (const FirstValue, LastValue: integer): TUTF8StringArray;
88+ function GetPlayerColorOptionCount : integer;
10289function TryGetMixedPlayerColorPair (ColorIndex: integer; out LeftColor, RightColor: integer): boolean;
10390
10491type
@@ -132,7 +119,7 @@ TIni = class
132119 // Players or Teams colors
133120 SingColor: array [0 ..(IMaxPlayerCount-1 )] of integer;
134121
135- Name : array [0 ..15 ] of UTF8String;
122+ Name : array [0 ..(IMaxPlayerCount- 1 ) ] of UTF8String;
136123 PlayerColor: array [0 ..(IMaxPlayerCount-1 )] of integer;
137124 TeamColor: array [0 ..2 ] of integer;
138125
@@ -469,7 +456,6 @@ TIni = class
469456 IJukeboxTimebarMode: array [0 ..2 ] of UTF8String = (' Current' , ' Remaining' , ' Total' );
470457
471458 // Recording options
472- IChannelPlayer: array [0 ..6 ] of UTF8String = (' Off' , ' 1' , ' 2' , ' 3' , ' 4' , ' 5' , ' 6' );
473459 IMicBoost: array [0 ..3 ] of UTF8String = (' Off' , ' +6dB' , ' +12dB' , ' +18dB' );
474460
475461 // Webcam
@@ -482,6 +468,9 @@ TIni = class
482468 *}
483469
484470var
471+ IPlayers: TUTF8StringArray;
472+ IPlayersVals: TIntegerArray;
473+ IChannelPlayer: TUTF8StringArray;
485474 ILanguageTranslated: array of UTF8String;
486475 ILyricsFont: array of UTF8String;
487476
@@ -536,7 +525,7 @@ TIni = class
536525 ILyricsEffectTranslated: array [0 ..4 ] of UTF8String = (' Simple' , ' Zoom' , ' Slide' , ' Ball' , ' Shift' );
537526 INoteLinesTranslated: array [0 ..1 ] of UTF8String = (' Off' , ' On' );
538527 IColorTranslated: array [0 ..8 ] of UTF8String = (' Blue' , ' Green' , ' Pink' , ' Red' , ' Violet' , ' Orange' , ' Yellow' , ' Brown' , ' Black' );
539- IPlayerColorTranslated: array [ 0 .. 15 ] of UTF8String = ( ' Blue ' , ' Red ' , ' Green ' , ' Yellow ' , ' Orange ' , ' Pink ' , ' Violet ' , ' Brown ' , ' Gray ' , ' Dark Blue ' , ' Sky ' , ' Cyan ' , ' Flame ' , ' Orchid ' , ' Harlequin ' , ' Lime ' ) ;
528+ IPlayerColorTranslated: TUTF8StringArray ;
540529
541530 // for lyric colors
542531 ILineTranslated: array [0 ..2 ] of UTF8String = (' Sing' , ' Actual' , ' Next' );
@@ -567,13 +556,13 @@ TIni = class
567556 IJukeboxTimebarModeTranslated: array [0 ..2 ] of UTF8String = (' Current' , ' Remaining' , ' Total' );
568557
569558 // Recording options
570- IChannelPlayerTranslated: array [ 0 ..IMaxPlayerCount] of UTF8String = ( ' Off ' , ' 1 ' , ' 2 ' , ' 3 ' , ' 4 ' , ' 5 ' , ' 6 ' , ' 7 ' , ' 8 ' , ' 9 ' , ' 10 ' , ' 11 ' , ' 12 ' ) ;
559+ IChannelPlayerTranslated: TUTF8StringArray ;
571560 IMicBoostTranslated: array [0 ..3 ] of UTF8String = (' Off' , ' +6dB' , ' +12dB' , ' +18dB' );
572561
573562 // Network
574563 ISendNameTranslated: array [0 ..1 ] of UTF8String = (' Off' , ' On' );
575564 IAutoModeTranslated: array [0 ..2 ] of UTF8String = (' Off' , ' Send' , ' Guardar' );
576- IAutoPlayerTranslated: array [ 0 ..IMaxPlayerCount] of UTF8String = ( ' Player 1 ' , ' Player 2 ' , ' Player 3 ' , ' Player 4 ' , ' Player 5 ' , ' Player 6 ' , ' Player 7 ' , ' Player 8 ' , ' Player 9 ' , ' Player 10 ' , ' Player 11 ' , ' Player 12 ' , ' All ' ) ;
565+ IAutoPlayerTranslated: TUTF8StringArray ;
577566 IAutoScoreEasyTranslated: array of UTF8String;
578567 IAutoScoreMediumTranslated: array of UTF8String;
579568 IAutoScoreHardTranslated: array of UTF8String;
@@ -586,7 +575,7 @@ TIni = class
586575 IWebcamEffectTranslated: array [0 ..10 ] of UTF8String;
587576
588577 // Name
589- IPlayerTranslated: array [ 0 ..(IMaxPlayerCount- 1 )] of UTF8String = ( ' Player 1 ' , ' Player 2 ' , ' Player 3 ' , ' Player 4 ' , ' Player 5 ' , ' Player 6 ' , ' Player 7 ' , ' Player 8 ' , ' Player 9 ' , ' Player 10 ' , ' Player 11 ' , ' Player 12 ' ) ;
578+ IPlayerTranslated: TUTF8StringArray ;
590579
591580 IRed: array [0 ..255 ] of UTF8String;
592581 IGreen: array [0 ..255 ] of UTF8String;
@@ -626,6 +615,20 @@ TSafeIniFile = class(TIniFile)
626615 IGNORE_INDEX = -1 ;
627616 BASE_PLAYER_COLOR_COUNT = 16 ;
628617
618+ PLAYER_COLOR_DEFAULTS: array [0 ..15 ] of UTF8String = (
619+ ' Blue' , ' Red' , ' Green' , ' Yellow' , ' Orange' , ' Pink' , ' Violet' , ' Brown' ,
620+ ' Gray' , ' Dark Blue' , ' Sky' , ' Cyan' , ' Flame' , ' Orchid' , ' Harlequin' , ' Lime'
621+ );
622+
623+ PLAYER_COLOR_TRANSLATION_KEYS: array [0 ..15 ] of UTF8String = (
624+ ' OPTION_VALUE_BLUE' , ' OPTION_VALUE_RED' , ' OPTION_VALUE_GREEN' ,
625+ ' OPTION_VALUE_YELLOW' , ' OPTION_VALUE_ORANGE' , ' OPTION_VALUE_PINK' ,
626+ ' OPTION_VALUE_VIOLET' , ' OPTION_VALUE_BROWN' , ' OPTION_VALUE_GRAY' ,
627+ ' OPTION_VALUE_DARKBLUE' , ' OPTION_VALUE_SKY' , ' OPTION_VALUE_CYAN' ,
628+ ' OPTION_VALUE_FLAME' , ' OPTION_VALUE_ORCHID' , ' OPTION_VALUE_HARLEQUIN' ,
629+ ' OPTION_VALUE_GREENYELLOW'
630+ );
631+
629632function GetNameTemplateIndexFromKey (const Key: cardinal): integer;
630633begin
631634 case Key of
@@ -661,6 +664,13 @@ function CreateNumericOptionArray(const FirstValue, LastValue: integer): TUTF8St
661664 Result[I] := IntToStr(FirstValue + I);
662665end ;
663666
667+ function GetPlayerColorOptionCount : integer;
668+ begin
669+ Result := (IMaxPlayerCount * 3 + 1 ) div 2 ;
670+ if Result < BASE_PLAYER_COLOR_COUNT then
671+ Result := BASE_PLAYER_COLOR_COUNT;
672+ end ;
673+
664674function TryGetMixedPlayerColorPair (ColorIndex: integer; out LeftColor, RightColor: integer): boolean;
665675var
666676 Remaining: integer;
@@ -704,6 +714,60 @@ function TryGetMixedPlayerColorPair(ColorIndex: integer; out LeftColor, RightCol
704714 end ;
705715end ;
706716
717+ function GetDefaultPlayerColor (PlayerIndex: integer): integer;
718+ begin
719+ if Length(IPlayerColorTranslated) = 0 then
720+ Exit(0 );
721+
722+ Result := (PlayerIndex mod Length(IPlayerColorTranslated)) + 1 ;
723+ end ;
724+
725+ procedure InitializePlayerOptionArrays ;
726+ var
727+ I: integer;
728+ LeftColor: integer;
729+ RightColor: integer;
730+ begin
731+ SetLength(IPlayerColorTranslated, GetPlayerColorOptionCount);
732+ for I := 0 to High(IPlayerColorTranslated) do
733+ begin
734+ if I < Length(PLAYER_COLOR_DEFAULTS) then
735+ IPlayerColorTranslated[I] := PLAYER_COLOR_DEFAULTS[I]
736+ else if TryGetMixedPlayerColorPair(I + 1 , LeftColor, RightColor) then
737+ IPlayerColorTranslated[I] := PLAYER_COLOR_DEFAULTS[LeftColor - 1 ] + ' + ' + PLAYER_COLOR_DEFAULTS[RightColor - 1 ]
738+ else
739+ IPlayerColorTranslated[I] := PLAYER_COLOR_DEFAULTS[I mod Length(PLAYER_COLOR_DEFAULTS)];
740+ end ;
741+
742+ SetLength(IPlayers, IMaxPlayerCount);
743+ SetLength(IPlayersVals, IMaxPlayerCount);
744+ for I := 0 to IMaxPlayerCount - 1 do
745+ begin
746+ IPlayers[I] := IntToStr(I + 1 );
747+ IPlayersVals[I] := I + 1 ;
748+ end ;
749+
750+ SetLength(IChannelPlayer, IMaxPlayerCount + 1 );
751+ IChannelPlayer[0 ] := ' Off' ;
752+ for I := 1 to IMaxPlayerCount do
753+ IChannelPlayer[I] := IntToStr(I);
754+
755+ SetLength(IChannelPlayerTranslated, IMaxPlayerCount + 1 );
756+ SetLength(IAutoPlayerTranslated, IMaxPlayerCount + 1 );
757+ SetLength(IPlayerTranslated, IMaxPlayerCount);
758+
759+ IChannelPlayerTranslated[0 ] := ' Off' ;
760+ for I := 1 to IMaxPlayerCount do
761+ IChannelPlayerTranslated[I] := IntToStr(I);
762+
763+ for I := 0 to IMaxPlayerCount - 1 do
764+ IPlayerTranslated[I] := ' Player ' + IntToStr(I + 1 );
765+
766+ for I := 0 to IMaxPlayerCount - 1 do
767+ IAutoPlayerTranslated[I] := ' Player ' + IntToStr(I + 1 );
768+ IAutoPlayerTranslated[IMaxPlayerCount] := ' All' ;
769+ end ;
770+
707771constructor TSafeIniFile.Create(const FileName, LogSource: string);
708772begin
709773 inherited Create(FileName);
@@ -753,7 +817,12 @@ procedure TIni.TranslateOptionValues;
753817var
754818 I: integer;
755819 Zeros: string;
820+ BasePlayerColorNames: array [0 ..BASE_PLAYER_COLOR_COUNT-1 ] of UTF8String;
821+ LeftColor: integer;
822+ RightColor: integer;
756823begin
824+ InitializePlayerOptionArrays;
825+
757826 // Load language file, fallback to config language if param is invalid
758827 if (Params.Language > -1 ) and (Params.Language < Length(ILanguage)) then
759828 ULanguage.Language.ChangeLanguage(ILanguage[Params.Language])
@@ -933,22 +1002,18 @@ procedure TIni.TranslateOptionValues;
9331002 IColorTranslated[7 ] := ULanguage.Language.Translate(' OPTION_VALUE_BROWN' );
9341003 IColorTranslated[8 ] := ULanguage.Language.Translate(' OPTION_VALUE_BLACK' );
9351004
936- IPlayerColorTranslated[0 ] := ULanguage.Language.Translate(' OPTION_VALUE_BLUE' );
937- IPlayerColorTranslated[1 ] := ULanguage.Language.Translate(' OPTION_VALUE_RED' );
938- IPlayerColorTranslated[2 ] := ULanguage.Language.Translate(' OPTION_VALUE_GREEN' );
939- IPlayerColorTranslated[3 ] := ULanguage.Language.Translate(' OPTION_VALUE_YELLOW' );
940- IPlayerColorTranslated[4 ] := ULanguage.Language.Translate(' OPTION_VALUE_ORANGE' );
941- IPlayerColorTranslated[5 ] := ULanguage.Language.Translate(' OPTION_VALUE_PINK' );
942- IPlayerColorTranslated[6 ] := ULanguage.Language.Translate(' OPTION_VALUE_VIOLET' );
943- IPlayerColorTranslated[7 ] := ULanguage.Language.Translate(' OPTION_VALUE_BROWN' );
944- IPlayerColorTranslated[8 ] := ULanguage.Language.Translate(' OPTION_VALUE_GRAY' );
945- IPlayerColorTranslated[9 ] := ULanguage.Language.Translate(' OPTION_VALUE_DARKBLUE' );
946- IPlayerColorTranslated[10 ] := ULanguage.Language.Translate(' OPTION_VALUE_SKY' );
947- IPlayerColorTranslated[11 ] := ULanguage.Language.Translate(' OPTION_VALUE_CYAN' );
948- IPlayerColorTranslated[12 ] := ULanguage.Language.Translate(' OPTION_VALUE_FLAME' );
949- IPlayerColorTranslated[13 ] := ULanguage.Language.Translate(' OPTION_VALUE_ORCHID' );
950- IPlayerColorTranslated[14 ] := ULanguage.Language.Translate(' OPTION_VALUE_HARLEQUIN' );
951- IPlayerColorTranslated[15 ] := ULanguage.Language.Translate(' OPTION_VALUE_GREENYELLOW' );
1005+ for I := 0 to High(BasePlayerColorNames) do
1006+ BasePlayerColorNames[I] := ULanguage.Language.Translate(PLAYER_COLOR_TRANSLATION_KEYS[I]);
1007+
1008+ for I := 0 to High(IPlayerColorTranslated) do
1009+ begin
1010+ if I < Length(BasePlayerColorNames) then
1011+ IPlayerColorTranslated[I] := BasePlayerColorNames[I]
1012+ else if TryGetMixedPlayerColorPair(I + 1 , LeftColor, RightColor) then
1013+ IPlayerColorTranslated[I] := BasePlayerColorNames[LeftColor - 1 ] + ' + ' + BasePlayerColorNames[RightColor - 1 ]
1014+ else
1015+ IPlayerColorTranslated[I] := BasePlayerColorNames[I mod Length(BasePlayerColorNames)];
1016+ end ;
9521017
9531018 // Advanced
9541019 ILoadAnimationTranslated[0 ] := ULanguage.Language.Translate(' OPTION_VALUE_OFF' );
@@ -1060,9 +1125,12 @@ procedure TIni.TranslateOptionValues;
10601125
10611126 for I:=0 to IMaxPlayerCount-1 do
10621127 begin
1063- IAutoPlayerTranslated[I] :=ULanguage.Language.Translate(' OPTION_PLAYER_' + IntToStr(I));
1128+ IAutoPlayerTranslated[I] := ULanguage.Language.Translate(' OPTION_PLAYER_' + IntToStr(I + 1 ));
10641129 end ;
1065- IAutoPlayerTranslated[12 ] := ULanguage.Language.Translate(' OPTION_ALL_PLAYERS' );
1130+ IAutoPlayerTranslated[IMaxPlayerCount] := ULanguage.Language.Translate(' OPTION_ALL_PLAYERS' );
1131+
1132+ for I := 0 to IMaxPlayerCount - 1 do
1133+ IPlayerTranslated[I] := ULanguage.Language.Translate(' OPTION_PLAYER_' + IntToStr(I + 1 ));
10661134
10671135 // Webcam
10681136 IWebcamFlipTranslated[0 ] := ULanguage.Language.Translate(' OPTION_VALUE_OFF' );
@@ -1586,6 +1654,7 @@ procedure TIni.Load();
15861654 Result := 100 ;
15871655 end ;
15881656begin
1657+ InitializePlayerOptionArrays;
15891658 LoadFontFamilyNames;
15901659 ILyricsFont := FontFamilyNames;
15911660 GamePath := Platform.GetGameUserPath;
@@ -1600,12 +1669,12 @@ procedure TIni.Load();
16001669 Log.LogStatus(' Using config : ' + FileName.ToNative, ' Ini' );
16011670 IniFile := TMemIniFile.Create(FileName.ToNative);
16021671
1603- for I := 0 to IMaxPlayerCount- 1 do
1672+ for I := 0 to High( Name ) do
16041673 begin
16051674 // Name
16061675 Name [I] := IniFile.ReadString(' Name' , ' P' +IntToStr(I+1 ), ' Player' +IntToStr(I+1 ));
16071676 // Color Player
1608- PlayerColor[I] := IniFile.ReadInteger(' PlayerColor' , ' P' +IntToStr(I+1 ), DefaultPlayerColors[I] );
1677+ PlayerColor[I] := IniFile.ReadInteger(' PlayerColor' , ' P' +IntToStr(I+1 ), GetDefaultPlayerColor(I) );
16091678 // Initialize session sing colors from the saved player colors so they are usable before the first song
16101679 SingColor[I] := PlayerColor[I];
16111680 // Avatar Player
@@ -1621,7 +1690,7 @@ procedure TIni.Load();
16211690 // Templates for Names Mod
16221691 for I := 0 to 2 do
16231692 NameTeam[I] := IniFile.ReadString(' NameTeam' , ' T' +IntToStr(I+1 ), ' Team' +IntToStr(I+1 ));
1624- for I := 0 to 11 do
1693+ for I := 0 to High(NameTemplate) do
16251694 NameTemplate[I] := IniFile.ReadString(' NameTemplate' , ' Name' +IntToStr(I+1 ), ' Template' +IntToStr(I+1 ));
16261695
16271696 // Players
0 commit comments