diff --git a/Output/PartyModes/RuleRoulette.xml b/Output/PartyModes/RuleRoulette.xml new file mode 100644 index 00000000..13491669 --- /dev/null +++ b/Output/PartyModes/RuleRoulette.xml @@ -0,0 +1,21 @@ + + + 2 + + TR_PARTYMODE_NAME + McSchneidar + TR_PARTYMODE_DESCRIPTION + RuleRoulette + CPartyModeRuleRoulette + 1 + 0 + TR_PARTYMODE_AUDIENCE + + + CPartyScreenRuleRouletteMain + CPartyScreenRuleRouletteConfig + CPartyScreenRuleRouletteNames + CPartyScreenRuleRouletteSongs + CPartyScreenRuleRouletteRules + + diff --git a/Output/PartyModes/RuleRoulette/Languages/de.xml b/Output/PartyModes/RuleRoulette/Languages/de.xml new file mode 100644 index 00000000..eb544b18 --- /dev/null +++ b/Output/PartyModes/RuleRoulette/Languages/de.xml @@ -0,0 +1,84 @@ + + + Deutsch + Rule Roulette + Singt Duelle, bei denen ein Rad die Spielregel jeder Runde bestimmt. + Für 2 bis 12 Spieler, die Überraschungen mögen, 2 Mikrofone nötig. + Weiter + Zurück + Start + Beenden + Ja + Nein + Rad drehen + Rad drehen + Duell starten + Songs + Rule Roulette: Konfiguration + Anzahl der Spieler + Songs pro Spieler + Joker pro Spieler + Regeln + Zufällig + Manuell + Regeln auf dem Rad + Rule Roulette: Regeln + Immer dabei + Zufällig + Nie + Hoch/Runter = Regel wählen · Links/Rechts oder Klick = Ändern · Enter = Weiter · ESC = Zurück + Rule Roulette: Spieler auswählen + Zufällig wählen + Rule Roulette + Willst du das Spiel wirklich beenden? + Pos + Name + Punkte + Duell + gegen + Zielzahl: + %s wählt den Song + Joker: + Letztes Duell: + Sieger + Kurzversion + Es wird die Kurzversion gesungen. + Medley + Ein Medley aus 3 Songs, ohne Joker. + Doppelpack + Zwei Songs hintereinander, die Summe zählt. + Duett-Pflicht + Ein Duett-Song, jeder singt eine Stimme. + Freie Songwahl + Ihr sucht den Song selbst aus. + Wahl des Schwächeren + Wer in der Tabelle weiter hinten liegt, wählt den Song. + Goldrausch + Nur Punkte aus goldenen Noten zählen. Ohne Joker. + Perfekte Zeilen + Nur der Zeilenbonus zählt. + Zielpunkte + Wer näher an der Zielzahl liegt, gewinnt. + Verkehrte Welt + Wer weniger Punkte hat, gewinnt. + Teamwork + Zusammen über 12.000 Punkte, dann bekommen beide 2 Punkte. + Doppelsieg + Schaffen beide über 7.000, gewinnen beide. + Doppelte Punkte + Der Sieger bekommt 4 statt 2 Punkte. + Blitzrunde + Kurzversion, und der Sieg zählt doppelt. + Alles oder nichts + Der Sieger bekommt 3 Punkte, der Verlierer verliert 1. + Punkteklau + Der Sieger nimmt dem Verlierer 1 Punkt weg. + Vorsprung zählt + Je größer der Vorsprung, desto mehr Punkte (1 bis 4). + Underdog + Gewinnt der in der Tabelle Schwächere, bekommt er 3 Punkte. + Joker-Regen + Der Sieger bekommt 1 Joker dazu. + Ohne Netz + In diesem Duell sind keine Joker erlaubt. + diff --git a/Output/PartyModes/RuleRoulette/Languages/en.xml b/Output/PartyModes/RuleRoulette/Languages/en.xml new file mode 100644 index 00000000..630bf07e --- /dev/null +++ b/Output/PartyModes/RuleRoulette/Languages/en.xml @@ -0,0 +1,84 @@ + + + English + Rule Roulette + Sing duels where a wheel decides the rule of every round. + For 2 to 12 players who like surprises, 2 microphones needed. + Next + Back + Start + Exit + Yes + No + Spin wheel + Spin wheel + Start duel + Songs + Rule Roulette: Configuration + Number of players + Songs per player + Jokers per player + Rules + Random + Manual + Rules on the wheel + Rule Roulette: Rules + Always + Random + Never + Up/Down = Select rule · Left/Right or click = Change · Enter = Next · ESC = Back + Rule Roulette: Choose Players + Select random + Rule Roulette + Do you really want to exit the game? + Pos + Name + Points + Duel + vs. + Target score: + %s chooses the song + Jokers: + Last duel: + Winner + Short Song + The short version is sung. + Medley + A medley of 3 songs, without jokers. + Double Pack + Two songs in a row, the total counts. + Duet Time + A duet song, each singer takes one voice. + Free Choice + You choose the song yourselves. + Underdog Picks + The player further behind chooses the song. + Gold Rush + Only points from golden notes count. No jokers. + Perfect Lines + Only the line bonus counts. + Target Score + Whoever gets closer to the target score wins. + Upside Down + Whoever has fewer points wins. + Teamwork + More than 12,000 points together and both get 2 points. + Double Win + If both score more than 7,000, both win. + Double Points + The winner gets 4 points instead of 2. + Blitz + Short version, and the win counts double. + All or Nothing + The winner gets 3 points, the loser loses 1. + Point Steal + The winner takes 1 point from the loser. + Lead Counts + The bigger the lead, the more points (1 to 4). + Underdog + If the player further behind wins, they get 3 points. + Joker Rain + The winner gets 1 extra joker. + No Safety Net + No jokers allowed in this duel. + diff --git a/Output/PartyModes/RuleRoulette/Themes/Default.xml b/Output/PartyModes/RuleRoulette/Themes/Default.xml new file mode 100644 index 00000000..97392ded --- /dev/null +++ b/Output/PartyModes/RuleRoulette/Themes/Default.xml @@ -0,0 +1,10 @@ + + + 9 + + Default + McSchneidar + 0 + 1 + + diff --git a/Output/PartyModes/RuleRoulette/Themes/Default/Default.xml b/Output/PartyModes/RuleRoulette/Themes/Default/Default.xml new file mode 100644 index 00000000..d88d34b4 --- /dev/null +++ b/Output/PartyModes/RuleRoulette/Themes/Default/Default.xml @@ -0,0 +1,15 @@ + + + 4 + + Default + McSchneidar + 0 + 1 + + + + PartyModeIcon.png + + + diff --git a/Output/PartyModes/RuleRoulette/Themes/Default/PartyModeIcon.png b/Output/PartyModes/RuleRoulette/Themes/Default/PartyModeIcon.png new file mode 100644 index 00000000..b61c247d Binary files /dev/null and b/Output/PartyModes/RuleRoulette/Themes/Default/PartyModeIcon.png differ diff --git a/Output/PartyModes/RuleRoulette/Themes/Default/Screens/PartyScreenRuleRouletteConfig.xml b/Output/PartyModes/RuleRoulette/Themes/Default/Screens/PartyScreenRuleRouletteConfig.xml new file mode 100644 index 00000000..409603fa --- /dev/null +++ b/Output/PartyModes/RuleRoulette/Themes/Default/Screens/PartyScreenRuleRouletteConfig.xml @@ -0,0 +1,407 @@ + + + + PartyScreenRuleRouletteConfig + 1 + + + + Video + + + BG_Default + + + + + + + + + 0 + 60 + 1920 + 67.5 + 1 + + + + + + 960 + 75 + 0 + 40.5 + 0 + + + Center + Center + + Outline + TR_SCREENCONFIG_TITLE + + + 112.5 + 157.5 + 0 + 40.5 + 0 + + + Left + Center + + Outline + TR_SCREENCONFIG_NUMPLAYERS + + + 112.5 + 247.5 + 0 + 40.5 + 0 + + + Left + Center + + Outline + TR_SCREENCONFIG_SONGSPERPLAYER + + + 112.5 + 337.5 + 0 + 40.5 + 0 + + + Left + Center + + Outline + TR_SCREENCONFIG_NUMJOKERS + + + 112.5 + 427.5 + 0 + 40.5 + 0 + + + Left + Center + + Outline + TR_SCREENCONFIG_RULES + + + 112.5 + 517.5 + 0 + 40.5 + 0 + + + Left + Center + + Outline + TR_SCREENCONFIG_NUMRULES + + + + + + + + + + + + SelectSlideArrowLeft + SelectSlideArrowRight + SelectSlide + SelectSlideArrowLeft + SelectSlideArrowRight + + 750 + 150 + 1050 + 75 + 0 + + + 757.5 + 157.5 + 60 + 60 + 0 + + + 1732.5 + 157.5 + 60 + 60 + 0 + + + + + + + + 40.5 + 75 + 0 + 300 + Outline + Bold + 9 + + + + SelectSlideArrowLeft + SelectSlideArrowRight + SelectSlide + SelectSlideArrowLeft + SelectSlideArrowRight + + 750 + 240 + 1050 + 75 + 0 + + + 757.5 + 247.5 + 60 + 60 + 0 + + + 1732.5 + 247.5 + 60 + 60 + 0 + + + + + + + + 40.5 + 75 + 0 + 300 + Outline + Bold + 9 + + + + SelectSlideArrowLeft + SelectSlideArrowRight + SelectSlide + SelectSlideArrowLeft + SelectSlideArrowRight + + 750 + 330 + 1050 + 75 + 0 + + + 757.5 + 337.5 + 60 + 60 + 0 + + + 1732.5 + 337.5 + 60 + 60 + 0 + + + + + + + + 40.5 + 75 + 0 + 300 + Outline + Bold + 9 + + + + SelectSlideArrowLeft + SelectSlideArrowRight + SelectSlide + SelectSlideArrowLeft + SelectSlideArrowRight + + 750 + 420 + 1050 + 75 + 0 + + + 757.5 + 427.5 + 60 + 60 + 0 + + + 1732.5 + 427.5 + 60 + 60 + 0 + + + + + + + + 40.5 + 75 + 0 + 300 + Outline + Bold + 9 + + + + SelectSlideArrowLeft + SelectSlideArrowRight + SelectSlide + SelectSlideArrowLeft + SelectSlideArrowRight + + 750 + 510 + 1050 + 75 + 0 + + + 757.5 + 517.5 + 60 + 60 + 0 + + + 1732.5 + 517.5 + 60 + 60 + 0 + + + + + + + + 40.5 + 75 + 0 + 300 + Outline + Bold + 9 + + + + + + + + + diff --git a/Output/PartyModes/RuleRoulette/Themes/Default/Screens/PartyScreenRuleRouletteMain.xml b/Output/PartyModes/RuleRoulette/Themes/Default/Screens/PartyScreenRuleRouletteMain.xml new file mode 100644 index 00000000..adf78962 --- /dev/null +++ b/Output/PartyModes/RuleRoulette/Themes/Default/Screens/PartyScreenRuleRouletteMain.xml @@ -0,0 +1,675 @@ + + + + PartyScreenRuleRouletteMain + 1 + + + + Video + + + BG_Default + + + + + + + + + 0 + 60 + 1920 + 67.5 + 1 + + + + PopupBG + + + 0 + 0 + 1920 + 1080 + -1 + + + + + + 0.1 + 0.09 + 0.25 + 0.75 + + + 30 + 190 + 520 + 720 + 0.8 + + + + + + 1 + 0.8 + 0 + 0.18 + + + 40 + 0 + 500 + 46 + 0.6 + + + + + + + 98 + 0 + 40 + 40 + 0.4 + + + + + + 0.1 + 0.09 + 0.25 + 0.92 + + + 0 + 0 + 200 + 60 + 0.5 + + + + + + 1 + 0.8 + 0 + 1 + + + 0 + 0 + 208 + 68 + 0.6 + + + + + + + 1070 + 320 + 140 + 140 + 0.4 + + + + + + + 1270 + 320 + 140 + 140 + 0.4 + + + + + + 960 + 75 + 0 + 40.5 + 0 + + + Center + Center + + Outline + TR_SCREENMAIN_TITLE + + + 960 + 405 + -11 + 40.5 + 570 + + + Center + Center + + Outline + TR_SCREENMAIN_POPUP_REALLYEXIT + + + 85 + 205 + 0 + 32 + 0 + + 0.75 + 0.78 + 0.85 + 1 + + + Right + Center + + Outline + TR_SCREENMAIN_HEADER_POS + + + 148 + 205 + 0 + 32 + 0 + + 0.75 + 0.78 + 0.85 + 1 + + + Left + Center + + Outline + TR_SCREENMAIN_HEADER_NAME + + + 525 + 205 + 0 + 32 + 0 + + 0.75 + 0.78 + 0.85 + 1 + + + Right + Center + + Outline + TR_SCREENMAIN_HEADER_POINTS + + + 85 + 0 + 0 + 34 + 0 + + + Right + Center + + Outline + + + + 148 + 0 + 0 + 34 + 290 + + + Left + Center + + Outline + + + + 525 + 0 + 0 + 34 + 0 + + + Right + Center + + Outline + + + + 0 + 0 + 0 + 24 + 186 + + + Center + Center + + Outline + + + + 0 + 0 + 0 + 24 + 186 + + 1 + 0.8 + 0 + 1 + + + Center + Center + + Outline + + + + 1240 + 275 + 0 + 30 + 500 + + 0.75 + 0.78 + 0.85 + 1 + + + Center + Center + + Outline + + + + 1140 + 470 + 0 + 32 + 190 + + + Center + Center + + Outline + + + + 1340 + 470 + 0 + 32 + 190 + + + Center + Center + + Outline + + + + 1240 + 372 + 0 + 32 + 0 + + 1 + 0.8 + 0 + 1 + + + Center + Center + + Outline + TR_SCREENMAIN_VERSUS + + + 1240 + 528 + 0 + 44 + 640 + + 1 + 0.8 + 0 + 1 + + + Center + Center + + Outline + + + + 1240 + 584 + 0 + 28 + 720 + + + Center + Center + + Outline + + + + 1240 + 624 + 0 + 28 + 720 + + 0.31 + 0.82 + 0.91 + 1 + + + Center + Center + + Outline + + + + 1240 + 560 + 0 + 28 + 740 + + + Center + Center + + Outline + + + + 1240 + 230 + 0 + 36 + 0 + + 1 + 0.8 + 0 + 1 + + + Center + Center + + Outline + TR_SCREENMAIN_CHAMPION + + + 1240 + 272 + 0 + 64 + 640 + + 1 + 0.8 + 0 + 1 + + + Center + Center + + Outline + + + + + + + + + + + + + + + + + + + + Star + + 940 + 220 + 600 + 340 + -1 + + + 1 + 0.8 + 0 + 0.6 + + Star + 18 + 40 + + + + diff --git a/Output/PartyModes/RuleRoulette/Themes/Default/Screens/PartyScreenRuleRouletteNames.xml b/Output/PartyModes/RuleRoulette/Themes/Default/Screens/PartyScreenRuleRouletteNames.xml new file mode 100644 index 00000000..1ccd61ed --- /dev/null +++ b/Output/PartyModes/RuleRoulette/Themes/Default/Screens/PartyScreenRuleRouletteNames.xml @@ -0,0 +1,382 @@ + + + + PartyScreenRuleRouletteNames + 1 + + + + Video + + + BG_Default + + + + + + + + + 0 + 60 + 1920 + 67.5 + 1 + + + + + + 960 + 75 + 0 + 40.5 + 0 + + + Center + Center + + Outline + TR_SCREENNAMES_TITLE + + + + + + + + + + + + + + + + + SelectSlideArrowLeft + SelectSlideArrowRight + SelectSlide + SelectSlideArrowLeft + SelectSlideArrowRight + + 60 + 150 + 1800 + 75 + 0 + + + 67.5 + 157.5 + 60 + 60 + 0 + + + 1792.5 + 157.5 + 60 + 60 + 0 + + + + + + + + 40.5 + 75 + 0 + 300 + Outline + Bold + 2 + + + + SelectSlideArrowLeft + SelectSlideArrowRight + SelectSlidePlayer + SelectSlideArrowLeft + SelectSlideArrowRight + + 60 + 240 + 1800 + 225 + 0 + + + 67.5 + 315 + 60 + 60 + 0 + + + 1792.5 + 315 + 60 + 60 + 0 + + + + + + + + 40.5 + 75 + 5 + 300 + Outline + Bold + 8 + + + + + + + 142.5 + 525 + 1800 + 589.5 + 0 + + CoverTile + + PlayerSelector + + 150 + 150 + 10 + 2 + 15 + 15 + + -20 + 25.5 + Outline + + + + + + + + + + + diff --git a/Output/PartyModes/RuleRoulette/Themes/Default/Screens/PartyScreenRuleRouletteRules.xml b/Output/PartyModes/RuleRoulette/Themes/Default/Screens/PartyScreenRuleRouletteRules.xml new file mode 100644 index 00000000..e52e0beb --- /dev/null +++ b/Output/PartyModes/RuleRoulette/Themes/Default/Screens/PartyScreenRuleRouletteRules.xml @@ -0,0 +1,282 @@ + + + + PartyScreenRuleRouletteRules + 1 + + + + Video + + + BG_Default + + + + + + + + + 0 + 60 + 1920 + 67.5 + 1 + + + + + + 1 + 0.8 + 0 + 0.18 + + + 0 + 0 + 890 + 62 + 0.6 + + + + SelectSlideArrowLeft + + + 0 + 0 + 34 + 34 + 0.4 + + + + SelectSlideArrowRight + + + 0 + 0 + 34 + 34 + 0.4 + + + + + + 960 + 75 + 0 + 40.5 + 0 + + + Center + Center + + Outline + TR_SCREENRULES_TITLE + + + 0 + 0 + 0 + 30 + 575 + + + Left + Center + + Outline + + + + 0 + 0 + 0 + 22 + 575 + + 0.75 + 0.78 + 0.85 + 1 + + + Left + Center + + Outline + + + + 0 + 0 + 0 + 28 + 190 + + + Center + Center + + Outline + + + + 0 + 0 + 0 + 28 + 0 + + 0.31 + 0.82 + 0.91 + 1 + + + Center + Center + + Outline + TR_SCREENRULES_ALWAYS + + + 0 + 0 + 0 + 28 + 0 + + + Center + Center + + Outline + TR_SCREENRULES_RANDOM + + + 0 + 0 + 0 + 28 + 0 + + 0.6 + 0.62 + 0.68 + 1 + + + Center + Center + + Outline + TR_SCREENRULES_NEVER + + + 960 + 880 + 0 + 26 + 1100 + + 0.75 + 0.78 + 0.85 + 1 + + + Center + Center + + Outline + TR_SCREENRULES_HINT + + + + + + + + + + + + + + + + diff --git a/Output/PartyModes/RuleRoulette/Themes/Default/Screens/PartyScreenRuleRouletteSongs.xml b/Output/PartyModes/RuleRoulette/Themes/Default/Screens/PartyScreenRuleRouletteSongs.xml new file mode 100644 index 00000000..c647f8ee --- /dev/null +++ b/Output/PartyModes/RuleRoulette/Themes/Default/Screens/PartyScreenRuleRouletteSongs.xml @@ -0,0 +1,407 @@ + + + + PartyScreenRuleRouletteSongs + 1 + + + + Video + + + BG_Default + + + + + + + + + 0 + 60 + 1920 + 67.5 + 1 + + + + + + 960 + 75 + 0 + 40.5 + 0 + + + Center + Center + + Outline + TR_SCREENCONFIG_TITLE + + + 112.5 + 157.5 + 0 + 40.5 + 0 + + + Left + Center + + Outline + TR_SONGSOURCE + + + 112.5 + 435 + 0 + 40.5 + 0 + + + Left + Center + + Outline + TR_GAMEMODE + + + + + + + + + + + + SelectSlideArrowLeft + SelectSlideArrowRight + SelectSlide + SelectSlideArrowLeft + SelectSlideArrowRight + + 750 + 150 + 1050 + 75 + 0 + + + 757.5 + 157.5 + 60 + 60 + 0 + + + 1732.5 + 157.5 + 60 + 60 + 0 + + + + + + + + 40.5 + 75 + 0 + 308 + Outline + Bold + 3 + + + + SelectSlideArrowLeft + SelectSlideArrowRight + SelectSlide + SelectSlideArrowLeft + SelectSlideArrowRight + + 750 + 240 + 1050 + 75 + 0 + + + 757.5 + 247.5 + 60 + 60 + 0 + + + 1732.5 + 247.5 + 60 + 60 + 0 + + + + + + + + 40.5 + 75 + 0 + 900 + Outline + Bold + 3 + + + + SelectSlideArrowLeft + SelectSlideArrowRight + SelectSlide + SelectSlideArrowLeft + SelectSlideArrowRight + + 750 + 240 + 1050 + 75 + 0 + + + 757.5 + 247.5 + 60 + 60 + 0 + + + 1732.5 + 247.5 + 60 + 60 + 0 + + + + + + + + 40.5 + 75 + 0 + 900 + Outline + Bold + 3 + + + + SelectSlideArrowLeft + SelectSlideArrowRight + SelectSlide + SelectSlideArrowLeft + SelectSlideArrowRight + + 750 + 330 + 1050 + 75 + 0 + + + 757.5 + 337.5 + 60 + 60 + 0 + + + 1732.5 + 337.5 + 60 + 60 + 0 + + + + + + + + 40.5 + 75 + 0 + 900 + Outline + Bold + 1 + + + + SelectSlideArrowLeft + SelectSlideArrowRight + SelectSlide + SelectSlideArrowLeft + SelectSlideArrowRight + + 750 + 435 + 1050 + 75 + 0 + + + 757.5 + 442.5 + 60 + 60 + 0 + + + 1732.5 + 442.5 + 60 + 60 + 0 + + + + + + + + 40.5 + 75 + 0 + 308 + Outline + Bold + 2 + + + + SelectSlideArrowLeft + SelectSlideArrowRight + SelectSlide + SelectSlideArrowLeft + SelectSlideArrowRight + + 750 + 540 + 1050 + 75 + 0 + + + 757.5 + 547.5 + 60 + 60 + 0 + + + 1732.5 + 547.5 + 60 + 60 + 0 + + + + + + + + 40.5 + 75 + 0 + 308 + Outline + Bold + 5 + + + + + + + + + diff --git a/PartyModes/PartyModeRuleRoulette/CPartyModeRuleRoulette.cs b/PartyModes/PartyModeRuleRoulette/CPartyModeRuleRoulette.cs new file mode 100644 index 00000000..2f96653c --- /dev/null +++ b/PartyModes/PartyModeRuleRoulette/CPartyModeRuleRoulette.cs @@ -0,0 +1,984 @@ +#region license +// This file is part of Vocaluxe. +// +// Vocaluxe is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Vocaluxe is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Vocaluxe. If not, see . +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using VocaluxeLib.Menu; +using VocaluxeLib.Songs; +using VocaluxeLib.Utils; + +[assembly: ComVisible(false)] + +namespace VocaluxeLib.PartyModes.RuleRoulette +{ + public enum ERule + { + ShortSong, + Medley, + DoublePack, + DuetOnly, + FreeChoice, + UnderdogChoice, + GoldRush, + PerfectLines, + TargetScore, + Reverse, + Teamwork, + DoubleWin, + DoublePoints, + Blitz, + AllOrNothing, + PointSteal, + LeadCounts, + Underdog, + JokerRain, + NoNet + } + + public enum ERuleState + { + Random, + Always, + Never + } + + public class CRoulettePlayer + { + public Guid ProfileId; + public int TablePoints; + public int SingPoints; + public int Duels; + public int Wins; + public int Jokers; + } + + public class CRouletteDuel + { + public CRoulettePlayer[] Players = new CRoulettePlayer[2]; + public ERule Rule; + public int TargetScore; + public CRoulettePlayer Chooser; + public int[] Scores = new int[2]; + public int[] Awarded = new int[2]; + public bool Decided; + } + + public abstract class CPartyScreenRuleRoulette : CMenuParty + { + protected new CPartyModeRuleRoulette _PartyMode; + + public override void Init() + { + base.Init(); + _PartyMode = (CPartyModeRuleRoulette)base._PartyMode; + } + } + + public sealed class CPartyModeRuleRoulette : CPartyMode + { + public const int PlayersPerDuel = 2; + public const int MaxJokers = 3; + public const int MinRulesOnWheel = 6; + public const int MaxRulesOnWheel = 12; + public const int MaxSongsPerPlayer = 10; + public const int MinSongsForRule = 5; + public const int MedleySongs = 3; + public const int TeamworkScore = 12000; + public const int DoubleWinScore = 7000; + + public override int MinMics + { + get { return PlayersPerDuel; } + } + public override int MaxMics + { + get { return CBase.Config.GetMaxNumMics(); } + } + public override int MinPlayers + { + get { return 2; } + } + public override int MaxPlayers + { + get { return 12; } + } + public override int MinTeams + { + get { return 1; } + } + public override int MaxTeams + { + get { return 1; } + } + public override int MinPlayersPerTeam + { + get { return MinPlayers; } + } + public override int MaxPlayersPerTeam + { + get { return MaxPlayers; } + } + + private enum EStage + { + Config, + Rules, + Songs, + Names, + Main, + SongSelection, + Singing, + DirectSinging + } + + public struct SData + { + public int NumPlayer; + public int SongsPerPlayer; + public int NumJokers; + public bool ManualRules; + public int NumRulesOnWheel; + public Dictionary RuleStates; + public List ProfileIds; + + public ESongSource SongSource; + public ESongSorting Sorting; + public int CategoryIndex; + public int PlaylistId; + public EGameMode GameMode; + public int NumMedleySongs; + + public List Players; + public List Duels; + public int DuelIndex; + public List Wheel; + public List UsedInCycle; + public bool RuleChosen; + public CRouletteDuel LastDuel; + public int NumDuelsPlayed; + } + + public SData GameData; + private EStage _Stage; + private List _SourceSongs = new List(); + private readonly HashSet _SungSongs = new HashSet(); + + public CPartyModeRuleRoulette(int id) : base(id) + { + _ScreenSongOptions.Selection.RandomOnly = false; + _ScreenSongOptions.Selection.PartyMode = true; + _ScreenSongOptions.Selection.CategoryChangeAllowed = true; + _ScreenSongOptions.Selection.NumJokers = new int[] { 1, 1 }; + _ScreenSongOptions.Selection.TeamNames = new string[] { "foo", "bar" }; + + _ScreenSongOptions.Sorting.SearchString = string.Empty; + _ScreenSongOptions.Sorting.SearchActive = false; + _ScreenSongOptions.Sorting.DuetOptions = EDuetOptions.All; + _ScreenSongOptions.Sorting.FilterPlaylistId = -1; + + var states = new Dictionary(); + foreach (ERule rule in Enum.GetValues(typeof(ERule))) + { + states[rule] = ERuleState.Random; + } + + GameData = new SData + { + NumPlayer = 4, + SongsPerPlayer = 3, + NumJokers = 1, + ManualRules = false, + NumRulesOnWheel = 8, + RuleStates = states, + ProfileIds = new List(), + Sorting = CBase.Config.GetSongSorting(), + SongSource = ESongSource.TR_SONGSOURCE_ALLSONGS, + PlaylistId = 0, + CategoryIndex = 0, + GameMode = EGameMode.TR_GAMEMODE_NORMAL, + NumMedleySongs = MedleySongs, + Players = new List(), + Duels = new List(), + Wheel = new List(), + UsedInCycle = new List() + }; + } + + public override void SetDefaults() + { + _Stage = EStage.Config; + + _ScreenSongOptions.Sorting.IgnoreArticles = CBase.Config.GetIgnoreArticles(); + _ScreenSongOptions.Sorting.SongSorting = CBase.Config.GetSongSorting(); + _ScreenSongOptions.Sorting.Tabs = EOffOn.TR_CONFIG_OFF; + _ScreenSongOptions.Selection.SongIndex = -1; + _ScreenSongOptions.Selection.CategoryIndex = -1; + + if (CBase.Config.GetTabs() == EOffOn.TR_CONFIG_ON && _ScreenSongOptions.Sorting.SongSorting != ESongSorting.TR_CONFIG_NONE) + { + _ScreenSongOptions.Sorting.Tabs = EOffOn.TR_CONFIG_ON; + } + } + + public override bool Init() + { + if (!base.Init()) + { + return false; + } + + SetDefaults(); + return true; + } + + public override void UpdateGame() { } + + public bool IsFinished + { + get { return GameData.Duels.Count > 0 && GameData.DuelIndex >= GameData.Duels.Count; } + } + + public CRouletteDuel CurrentDuel + { + get { return IsFinished || GameData.Duels.Count == 0 ? null : GameData.Duels[GameData.DuelIndex]; } + } + + public List GetRanking() + { + return GameData.Players.OrderByDescending(player => player.TablePoints).ThenByDescending(player => player.SingPoints).ToList(); + } + + public static string GetRuleKey(ERule rule) + { + return "TR_RULE_" + rule.ToString().ToUpperInvariant(); + } + + private IMenu _GetNextScreen() + { + switch (_Stage) + { + case EStage.Config: + return _Screens["CPartyScreenRuleRouletteConfig"]; + case EStage.Rules: + return _Screens["CPartyScreenRuleRouletteRules"]; + case EStage.Songs: + return _Screens["CPartyScreenRuleRouletteSongs"]; + case EStage.Names: + return _Screens["CPartyScreenRuleRouletteNames"]; + case EStage.Main: + return _Screens["CPartyScreenRuleRouletteMain"]; + case EStage.SongSelection: + return CBase.Graphics.GetScreen(EScreen.Song); + case EStage.Singing: + case EStage.DirectSinging: + return CBase.Graphics.GetScreen(EScreen.Sing); + default: + throw new ArgumentException("Invalid stage: " + _Stage); + } + } + + private void _FadeToScreen() + { + CBase.Graphics.FadeTo(_GetNextScreen()); + } + + public void Next() + { + switch (_Stage) + { + case EStage.Config: + _Stage = GameData.ManualRules ? EStage.Rules : EStage.Songs; + break; + case EStage.Rules: + _Stage = EStage.Songs; + break; + case EStage.Songs: + _Stage = EStage.Names; + break; + case EStage.Names: + _Stage = EStage.Main; + _StartGame(); + break; + case EStage.Main: + if (CurrentDuel == null || !GameData.RuleChosen) + { + return; + } + + if (_IsDirectRule(CurrentDuel.Rule)) + { + _Stage = EStage.DirectSinging; + _PrepareRound(_PickDirectSongs(CurrentDuel.Rule)); + } + else + { + _Stage = EStage.SongSelection; + _PrepareSongSelection(); + } + + break; + case EStage.SongSelection: + _Stage = EStage.Singing; + break; + case EStage.Singing: + case EStage.DirectSinging: + _Stage = EStage.Main; + _UpdateScores(); + break; + default: + throw new ArgumentException("Invalid stage: " + _Stage); + } + + _FadeToScreen(); + } + + public void Back() + { + switch (_Stage) + { + case EStage.Config: + CBase.Graphics.FadeTo(EScreen.Party); + return; + case EStage.Rules: + _Stage = EStage.Config; + break; + case EStage.Songs: + _Stage = GameData.ManualRules ? EStage.Rules : EStage.Config; + break; + case EStage.Names: + _Stage = EStage.Songs; + break; + case EStage.Main: + _Stage = EStage.Names; + break; + default: + throw new ArgumentException("Invalid stage: " + _Stage); + } + + _FadeToScreen(); + } + + public override IMenu GetStartScreen() + { + return _Screens["CPartyScreenRuleRouletteConfig"]; + } + + public override SScreenSongOptions GetScreenSongOptions() + { + return _ScreenSongOptions; + } + + public override void OnSongChange(int songIndex, ref SScreenSongOptions screenSongOptions) + { + if (_ScreenSongOptions.Selection.SelectNextRandomSong && songIndex != -1) + { + _ScreenSongOptions.Selection.SelectNextRandomSong = false; + } + + _ScreenSongOptions.Selection.SongIndex = songIndex; + + screenSongOptions = _ScreenSongOptions; + } + + public override void OnCategoryChange(int categoryIndex, ref SScreenSongOptions screenSongOptions) + { + var freeChoice = CurrentDuel != null && _IsFreeChoiceRule(CurrentDuel.Rule); + if (!freeChoice && (categoryIndex != -1 || CBase.Config.GetTabs() == EOffOn.TR_CONFIG_OFF)) + { + _ScreenSongOptions.Selection.SelectNextRandomSong = true; + _ScreenSongOptions.Selection.RandomOnly = true; + } + else + { + _ScreenSongOptions.Selection.SongIndex = -1; + _ScreenSongOptions.Selection.RandomOnly = false; + } + + _ScreenSongOptions.Selection.CategoryIndex = categoryIndex; + + screenSongOptions = _ScreenSongOptions; + } + + public override void SetSearchString(string searchString, bool visible) + { + _ScreenSongOptions.Sorting.SearchString = searchString; + _ScreenSongOptions.Sorting.SearchActive = visible; + } + + public override void JokerUsed(int teamNr) + { + if (_ScreenSongOptions.Selection.NumJokers == null || teamNr >= _ScreenSongOptions.Selection.NumJokers.Length) + { + return; + } + + var duel = CurrentDuel; + if (duel != null && duel.Players[teamNr].Jokers > 0) + { + duel.Players[teamNr].Jokers--; + } + + _ScreenSongOptions.Selection.NumJokers[teamNr]--; + _ScreenSongOptions.Selection.RandomOnly = true; + _ScreenSongOptions.Selection.CategoryChangeAllowed = false; + } + + public override void SongSelected(int songId) + { + var songIds = new List { songId }; + if (CurrentDuel != null && CurrentDuel.Rule == ERule.DoublePack) + { + _SungSongs.Add(songId); + var extra = _PickSongs(song => !song.IsDuet, 1); + songIds.AddRange(extra); + } + + _PrepareRound(songIds.ToArray()); + + Next(); + } + + public override void LeavingHighscore() + { + for (var i = 0; i < CBase.Game.GetNumSongs(); i++) + { + CBase.Songs.AddPartySongSung(CBase.Game.GetSong(i).Id); + _SungSongs.Add(CBase.Game.GetSong(i).Id); + } + + Next(); + } + + public void SpinWheel(out int resultIndex) + { + resultIndex = -1; + var duel = CurrentDuel; + if (duel == null || GameData.Wheel.Count == 0) + { + return; + } + + var open = GameData.Wheel.Where(wheelRule => !GameData.UsedInCycle.Contains(wheelRule)).ToList(); + if (open.Count == 0) + { + GameData.UsedInCycle.Clear(); + open = new List(GameData.Wheel); + } + + var rule = open[CBase.Game.GetRandom(open.Count)]; + GameData.UsedInCycle.Add(rule); + resultIndex = GameData.Wheel.IndexOf(rule); + + duel.Rule = rule; + duel.Chooser = null; + duel.TargetScore = 0; + if (rule == ERule.TargetScore) + { + duel.TargetScore = 4000 + CBase.Game.GetRandom(41) * 100; + } + else if (rule == ERule.UnderdogChoice) + { + duel.Chooser = _GetWeaker(duel); + } + + GameData.RuleChosen = true; + } + + private CRoulettePlayer _GetWeaker(CRouletteDuel duel) + { + var a = duel.Players[0]; + var b = duel.Players[1]; + if (a.TablePoints != b.TablePoints) + { + return a.TablePoints < b.TablePoints ? a : b; + } + + if (a.SingPoints != b.SingPoints) + { + return a.SingPoints < b.SingPoints ? a : b; + } + + return duel.Players[CBase.Game.GetRandom(2)]; + } + + private static bool _IsDirectRule(ERule rule) + { + return rule == ERule.Medley || rule == ERule.GoldRush; + } + + private static bool _IsFreeChoiceRule(ERule rule) + { + return rule == ERule.FreeChoice || rule == ERule.UnderdogChoice; + } + + private static bool _HasGoldenNotes(CSong song) + { + return song.Notes.Voices.Any(voice => voice.Lines.Any(line => line.Notes.Any(note => note.IsGoldenNote))); + } + + private void _StartGame() + { + CBase.Songs.ResetSongSung(); + _SungSongs.Clear(); + _SourceSongs = _GetSourceSongs(); + + GameData.Players = new List(); + foreach (var profileId in GameData.ProfileIds) + { + GameData.Players.Add(new CRoulettePlayer { ProfileId = profileId, Jokers = GameData.NumJokers }); + } + + _BuildDuels(); + _BuildWheel(); + + GameData.DuelIndex = 0; + GameData.UsedInCycle = new List(); + GameData.RuleChosen = false; + GameData.LastDuel = null; + GameData.NumDuelsPlayed = 0; + } + + private void _BuildDuels() + { + var numDuels = Math.Max(1, (GameData.Players.Count * GameData.SongsPerPlayer + 1) / PlayersPerDuel); + var counts = GameData.Players.ToDictionary(player => player, player => 0); + var met = new Dictionary(); + GameData.Duels = new List(); + CRouletteDuel last = null; + + for (var d = 0; d < numDuels; d++) + { + CRoulettePlayer bestA = null; + CRoulettePlayer bestB = null; + var bestValue = int.MaxValue; + var players = new List(GameData.Players); + players.Shuffle(); + + foreach (var a in players) + { + foreach (var b in players) + { + if (a == b) + { + continue; + } + + int times; + met.TryGetValue(_PairKey(a, b), out times); + var repeat = last != null && (last.Players.Contains(a) || last.Players.Contains(b)) ? 1 : 0; + var value = (counts[a] + counts[b]) * 100 + times * 10 + repeat; + if (value < bestValue) + { + bestValue = value; + bestA = a; + bestB = b; + } + } + } + + var duel = new CRouletteDuel(); + duel.Players[0] = bestA; + duel.Players[1] = bestB; + GameData.Duels.Add(duel); + counts[bestA]++; + counts[bestB]++; + var key = _PairKey(bestA, bestB); + int count; + met.TryGetValue(key, out count); + met[key] = count + 1; + last = duel; + } + } + + private string _PairKey(CRoulettePlayer a, CRoulettePlayer b) + { + var ia = GameData.Players.IndexOf(a); + var ib = GameData.Players.IndexOf(b); + return Math.Min(ia, ib) + "-" + Math.Max(ia, ib); + } + + public bool IsRuleAvailable(ERule rule) + { + switch (rule) + { + case ERule.ShortSong: + case ERule.Blitz: + return _SourceSongs.Count(song => song.IsGameModeAvailable(EGameMode.TR_GAMEMODE_SHORTSONG)) >= MinSongsForRule; + case ERule.Medley: + return _SourceSongs.Count(song => !song.IsDuet && song.IsGameModeAvailable(EGameMode.TR_GAMEMODE_MEDLEY)) >= MinSongsForRule; + case ERule.DuetOnly: + return _SourceSongs.Count(song => song.IsDuet) >= 1; + case ERule.GoldRush: + return _SourceSongs.Count(song => !song.IsDuet && _HasGoldenNotes(song)) >= MinSongsForRule; + default: + return true; + } + } + + private void _BuildWheel() + { + var available = Enum.GetValues(typeof(ERule)).Cast().Where(IsRuleAvailable).ToList(); + var always = new List(); + var random = new List(); + foreach (var rule in available) + { + var state = GameData.ManualRules ? GameData.RuleStates[rule] : ERuleState.Random; + if (state == ERuleState.Always) + { + always.Add(rule); + } + else if (state == ERuleState.Random) + { + random.Add(rule); + } + } + + always.Shuffle(); + random.Shuffle(); + var size = Math.Max(Math.Min(always.Count, MaxRulesOnWheel), GameData.NumRulesOnWheel); + var wheel = always.Take(size).ToList(); + wheel.AddRange(random.Take(size - wheel.Count)); + if (wheel.Count == 0) + { + available.Shuffle(); + wheel = available.Take(size).ToList(); + } + + wheel.Shuffle(); + GameData.Wheel = wheel; + } + + private List _GetSourceSongs() + { + var songs = new List(); + switch (GameData.SongSource) + { + case ESongSource.TR_SONGSOURCE_PLAYLIST: + for (var i = 0; i < CBase.Playlist.GetSongCount(GameData.PlaylistId); i++) + { + var song = CBase.Songs.GetSongById(CBase.Playlist.GetSong(GameData.PlaylistId, i).SongId); + if (song != null) + { + songs.Add(song); + } + } + + break; + + case ESongSource.TR_SONGSOURCE_ALLSONGS: + songs.AddRange(CBase.Songs.GetSongs()); + break; + + case ESongSource.TR_SONGSOURCE_CATEGORY: + var oldSorting = CBase.Config.GetSongSorting(); + CBase.Songs.SortSongs(GameData.Sorting, EOffOn.TR_CONFIG_ON, CBase.Config.GetIgnoreArticles(), string.Empty, EDuetOptions.All, -1); + CBase.Songs.SetCategory(GameData.CategoryIndex); + songs.AddRange(CBase.Songs.GetVisibleSongs()); + CBase.Songs.SetCategory(-1); + CBase.Songs.SortSongs(oldSorting, CBase.Config.GetTabs(), CBase.Config.GetIgnoreArticles(), string.Empty, EDuetOptions.All, -1); + break; + } + + return songs; + } + + private List _PickSongs(Func filter, int count) + { + var candidates = _SourceSongs.Where(song => filter(song) && !_SungSongs.Contains(song.Id)).ToList(); + if (candidates.Count < count) + { + candidates = _SourceSongs.Where(filter).ToList(); + } + + candidates.Shuffle(); + return candidates.Take(count).Select(song => song.Id).ToList(); + } + + private int[] _PickDirectSongs(ERule rule) + { + if (rule == ERule.Medley) + { + return _PickSongs(song => !song.IsDuet && song.IsGameModeAvailable(EGameMode.TR_GAMEMODE_MEDLEY), MedleySongs).ToArray(); + } + + return _PickSongs(song => !song.IsDuet && _HasGoldenNotes(song), 1).ToArray(); + } + + private void _PrepareSongSelection() + { + var duel = CurrentDuel; + var freeChoice = _IsFreeChoiceRule(duel.Rule); + + _ScreenSongOptions.Selection.RandomOnly = !freeChoice; + _ScreenSongOptions.Selection.SelectNextRandomSong = !freeChoice; + _ScreenSongOptions.Sorting.IgnoreArticles = CBase.Config.GetIgnoreArticles(); + _ScreenSongOptions.Sorting.DuetOptions = duel.Rule == ERule.DuetOnly ? EDuetOptions.Duets : EDuetOptions.All; + + switch (GameData.SongSource) + { + case ESongSource.TR_SONGSOURCE_ALLSONGS: + _ScreenSongOptions.Sorting.SongSorting = CBase.Config.GetSongSorting(); + _ScreenSongOptions.Sorting.Tabs = CBase.Config.GetTabs(); + _ScreenSongOptions.Sorting.FilterPlaylistId = -1; + + _ScreenSongOptions.Selection.SongIndex = -1; + _ScreenSongOptions.Selection.CategoryIndex = -1; + _ScreenSongOptions.Selection.CategoryChangeAllowed = true; + break; + + case ESongSource.TR_SONGSOURCE_CATEGORY: + _ScreenSongOptions.Sorting.SongSorting = GameData.Sorting; + _ScreenSongOptions.Sorting.Tabs = EOffOn.TR_CONFIG_ON; + _ScreenSongOptions.Sorting.FilterPlaylistId = -1; + + _ScreenSongOptions.Selection.CategoryIndex = GameData.CategoryIndex; + _ScreenSongOptions.Selection.CategoryChangeAllowed = false; + break; + + case ESongSource.TR_SONGSOURCE_PLAYLIST: + _ScreenSongOptions.Sorting.SongSorting = CBase.Config.GetSongSorting(); + _ScreenSongOptions.Sorting.Tabs = EOffOn.TR_CONFIG_OFF; + _ScreenSongOptions.Sorting.FilterPlaylistId = GameData.PlaylistId; + + _ScreenSongOptions.Selection.CategoryChangeAllowed = false; + break; + } + + var noJokers = duel.Rule == ERule.NoNet || freeChoice; + _ScreenSongOptions.Selection.NumJokers = new int[] { noJokers ? 0 : duel.Players[0].Jokers, noJokers ? 0 : duel.Players[1].Jokers }; + _ScreenSongOptions.Selection.TeamNames = new string[] + { + CBase.Profiles.GetPlayerName(duel.Players[0].ProfileId), + CBase.Profiles.GetPlayerName(duel.Players[1].ProfileId) + }; + } + + private bool _PrepareRound(int[] songIds) + { + CBase.Game.Reset(); + CBase.Game.ClearSongs(); + + CBase.Game.SetNumPlayer(PlayersPerDuel); + var players = CBase.Game.GetPlayers(); + var duel = CurrentDuel; + if (players == null || players.Length < PlayersPerDuel || duel == null) + { + return false; + } + + for (var p = 0; p < PlayersPerDuel; p++) + { + players[p].ProfileId = duel.Players[p].ProfileId; + players[p].VoiceNr = p; + } + + var medley = duel.Rule == ERule.Medley; + var shortSong = duel.Rule == ERule.ShortSong || duel.Rule == ERule.Blitz; + foreach (var songId in songIds) + { + var song = CBase.Songs.GetSongById(songId); + EGameMode gameMode; + if (medley) + { + gameMode = EGameMode.TR_GAMEMODE_MEDLEY; + } + else if (song.IsDuet) + { + gameMode = EGameMode.TR_GAMEMODE_DUET; + } + else if (shortSong && song.IsGameModeAvailable(EGameMode.TR_GAMEMODE_SHORTSONG)) + { + gameMode = EGameMode.TR_GAMEMODE_SHORTSONG; + } + else if (song.IsGameModeAvailable(GameData.GameMode)) + { + gameMode = GameData.GameMode; + } + else + { + gameMode = EGameMode.TR_GAMEMODE_NORMAL; + } + + CBase.Game.AddSong(songId, gameMode); + } + + return true; + } + + private static int _LeadPoints(int lead) + { + if (lead <= 1000) + { + return 1; + } + + if (lead <= 4000) + { + return 2; + } + + return lead <= 6500 ? 3 : 4; + } + + private void _UpdateScores() + { + var duel = CurrentDuel; + if (duel == null) + { + return; + } + + var points = CBase.Game.GetPoints(); + if (points == null || points.NumRounds == 0) + { + return; + } + + var total = new double[PlayersPerDuel]; + var golden = new double[PlayersPerDuel]; + var lines = new double[PlayersPerDuel]; + for (var round = 0; round < points.NumRounds; round++) + { + var res = points.GetPlayer(round, PlayersPerDuel); + if (res == null || res.Length < PlayersPerDuel) + { + return; + } + + for (var p = 0; p < PlayersPerDuel; p++) + { + total[p] += res[p].Points; + golden[p] += res[p].PointsGoldenNotes; + lines[p] += res[p].PointsLineBonus; + } + } + + var divisor = duel.Rule == ERule.DoublePack ? 1 : points.NumRounds; + var metric = new int[PlayersPerDuel]; + for (var p = 0; p < PlayersPerDuel; p++) + { + duel.Scores[p] = (int)Math.Round(total[p] / divisor); + switch (duel.Rule) + { + case ERule.GoldRush: + metric[p] = (int)Math.Round(golden[p] / divisor); + break; + case ERule.PerfectLines: + metric[p] = (int)Math.Round(lines[p] / divisor); + break; + case ERule.TargetScore: + metric[p] = -Math.Abs(duel.Scores[p] - duel.TargetScore); + break; + case ERule.Reverse: + metric[p] = -duel.Scores[p]; + break; + default: + metric[p] = duel.Scores[p]; + break; + } + } + + var weaker = duel.Rule == ERule.Underdog ? _GetWeaker(duel) : null; + _Award(duel, metric, weaker); + + for (var p = 0; p < PlayersPerDuel; p++) + { + var player = duel.Players[p]; + player.TablePoints = Math.Max(0, player.TablePoints + duel.Awarded[p]); + player.SingPoints += duel.Scores[p]; + player.Duels++; + } + + duel.Decided = true; + GameData.LastDuel = duel; + GameData.NumDuelsPlayed++; + GameData.DuelIndex++; + GameData.RuleChosen = false; + } + + private void _Award(CRouletteDuel duel, int[] metric, CRoulettePlayer weaker) + { + duel.Awarded[0] = 0; + duel.Awarded[1] = 0; + + if (duel.Rule == ERule.Teamwork) + { + var together = duel.Scores[0] + duel.Scores[1] > TeamworkScore ? 2 : 0; + duel.Awarded[0] = together; + duel.Awarded[1] = together; + return; + } + + if (duel.Rule == ERule.DoubleWin && duel.Scores[0] > DoubleWinScore && duel.Scores[1] > DoubleWinScore) + { + duel.Awarded[0] = 2; + duel.Awarded[1] = 2; + duel.Players[0].Wins++; + duel.Players[1].Wins++; + return; + } + + if (metric[0] == metric[1]) + { + duel.Awarded[0] = 1; + duel.Awarded[1] = 1; + if (duel.Rule == ERule.JokerRain) + { + duel.Players[0].Jokers++; + duel.Players[1].Jokers++; + } + + return; + } + + var winner = metric[0] > metric[1] ? 0 : 1; + var loser = 1 - winner; + duel.Players[winner].Wins++; + if (duel.Rule == ERule.JokerRain) + { + duel.Players[winner].Jokers++; + } + + switch (duel.Rule) + { + case ERule.DoublePoints: + case ERule.Blitz: + duel.Awarded[winner] = 4; + break; + case ERule.AllOrNothing: + duel.Awarded[winner] = 3; + duel.Awarded[loser] = -1; + break; + case ERule.PointSteal: + duel.Awarded[winner] = 2 + (duel.Players[loser].TablePoints > 0 ? 1 : 0); + duel.Awarded[loser] = duel.Players[loser].TablePoints > 0 ? -1 : 0; + break; + case ERule.LeadCounts: + duel.Awarded[winner] = _LeadPoints(Math.Abs(duel.Scores[0] - duel.Scores[1])); + break; + case ERule.Underdog: + duel.Awarded[winner] = duel.Players[winner] == weaker ? 3 : 2; + break; + default: + duel.Awarded[winner] = 2; + break; + } + } + } +} diff --git a/PartyModes/PartyModeRuleRoulette/CPartyScreenRuleRouletteConfig.cs b/PartyModes/PartyModeRuleRoulette/CPartyScreenRuleRouletteConfig.cs new file mode 100644 index 00000000..05a0f2c2 --- /dev/null +++ b/PartyModes/PartyModeRuleRoulette/CPartyScreenRuleRouletteConfig.cs @@ -0,0 +1,165 @@ +#region license +// This file is part of Vocaluxe. +// +// Vocaluxe is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Vocaluxe is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Vocaluxe. If not, see . +#endregion + +using System.Windows.Forms; + +namespace VocaluxeLib.PartyModes.RuleRoulette +{ + public class CPartyScreenRuleRouletteConfig : CPartyScreenRuleRoulette + { + protected override int _ScreenVersion + { + get { return 1; } + } + + private const string _SelectSlideNumPlayers = "SelectSlideNumPlayers"; + private const string _SelectSlideSongsPerPlayer = "SelectSlideSongsPerPlayer"; + private const string _SelectSlideNumJokers = "SelectSlideNumJokers"; + private const string _SelectSlideRuleSelection = "SelectSlideRuleSelection"; + private const string _SelectSlideNumRules = "SelectSlideNumRules"; + private const string _ButtonNext = "ButtonNext"; + private const string _ButtonBack = "ButtonBack"; + + public override void Init() + { + base.Init(); + + _ThemeSelectSlides = new string[] { _SelectSlideNumPlayers, _SelectSlideSongsPerPlayer, _SelectSlideNumJokers, _SelectSlideRuleSelection, _SelectSlideNumRules }; + _ThemeButtons = new string[] { _ButtonNext, _ButtonBack }; + } + + public override bool HandleInput(SKeyEvent keyEvent) + { + base.HandleInput(keyEvent); + + if (!keyEvent.KeyPressed) + { + switch (keyEvent.Key) + { + case Keys.Back: + case Keys.Escape: + _PartyMode.Back(); + break; + + case Keys.Enter: + _UpdateSlides(); + + if (_Buttons[_ButtonBack].Selected) + { + _PartyMode.Back(); + } + + if (_Buttons[_ButtonNext].Selected) + { + _PartyMode.Next(); + } + + break; + + case Keys.Left: + case Keys.Right: + _UpdateSlides(); + break; + } + } + + return true; + } + + public override bool HandleMouse(SMouseEvent mouseEvent) + { + base.HandleMouse(mouseEvent); + + if (mouseEvent.LB && _IsMouseOverCurSelection(mouseEvent)) + { + _UpdateSlides(); + if (_Buttons[_ButtonBack].Selected) + { + _PartyMode.Back(); + } + + if (_Buttons[_ButtonNext].Selected) + { + _PartyMode.Next(); + } + } + + if (mouseEvent.RB) + { + _PartyMode.Back(); + } + + return true; + } + + public override void OnShow() + { + base.OnShow(); + + _SelectSlides[_SelectSlideNumPlayers].Clear(); + for (var i = _PartyMode.MinPlayers; i <= _PartyMode.MaxPlayers; i++) + { + _SelectSlides[_SelectSlideNumPlayers].AddValue(i.ToString()); + } + + _SelectSlides[_SelectSlideNumPlayers].SelectedValue = _PartyMode.GameData.NumPlayer.ToString(); + + _SelectSlides[_SelectSlideSongsPerPlayer].Clear(); + for (var i = 1; i <= CPartyModeRuleRoulette.MaxSongsPerPlayer; i++) + { + _SelectSlides[_SelectSlideSongsPerPlayer].AddValue(i.ToString()); + } + + _SelectSlides[_SelectSlideSongsPerPlayer].SelectedValue = _PartyMode.GameData.SongsPerPlayer.ToString(); + + _SelectSlides[_SelectSlideRuleSelection].Clear(); + _SelectSlides[_SelectSlideRuleSelection].AddValue(CBase.Language.Translate("TR_SCREENCONFIG_RULES_RANDOM", PartyModeId)); + _SelectSlides[_SelectSlideRuleSelection].AddValue(CBase.Language.Translate("TR_SCREENCONFIG_RULES_MANUAL", PartyModeId)); + _SelectSlides[_SelectSlideRuleSelection].Selection = _PartyMode.GameData.ManualRules ? 1 : 0; + + _SelectSlides[_SelectSlideNumRules].Clear(); + for (var i = CPartyModeRuleRoulette.MinRulesOnWheel; i <= CPartyModeRuleRoulette.MaxRulesOnWheel; i++) + { + _SelectSlides[_SelectSlideNumRules].AddValue(i.ToString()); + } + + _SelectSlides[_SelectSlideNumRules].SelectedValue = _PartyMode.GameData.NumRulesOnWheel.ToString(); + + _SelectSlides[_SelectSlideNumJokers].Clear(); + for (var i = 0; i <= CPartyModeRuleRoulette.MaxJokers; i++) + { + _SelectSlides[_SelectSlideNumJokers].AddValue(i.ToString()); + } + + _SelectSlides[_SelectSlideNumJokers].SelectedValue = _PartyMode.GameData.NumJokers.ToString(); + } + + public override bool UpdateGame() + { + return true; + } + + private void _UpdateSlides() + { + _PartyMode.GameData.NumPlayer = _SelectSlides[_SelectSlideNumPlayers].Selection + _PartyMode.MinPlayers; + _PartyMode.GameData.NumJokers = _SelectSlides[_SelectSlideNumJokers].Selection; + _PartyMode.GameData.SongsPerPlayer = _SelectSlides[_SelectSlideSongsPerPlayer].Selection + 1; + _PartyMode.GameData.ManualRules = _SelectSlides[_SelectSlideRuleSelection].Selection == 1; + _PartyMode.GameData.NumRulesOnWheel = _SelectSlides[_SelectSlideNumRules].Selection + CPartyModeRuleRoulette.MinRulesOnWheel; + } + } +} diff --git a/PartyModes/PartyModeRuleRoulette/CPartyScreenRuleRouletteMain.cs b/PartyModes/PartyModeRuleRoulette/CPartyScreenRuleRouletteMain.cs new file mode 100644 index 00000000..3c006652 --- /dev/null +++ b/PartyModes/PartyModeRuleRoulette/CPartyScreenRuleRouletteMain.cs @@ -0,0 +1,622 @@ +#region license +// This file is part of Vocaluxe. +// +// Vocaluxe is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Vocaluxe is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Vocaluxe. If not, see . +#endregion + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Windows.Forms; +using VocaluxeLib.Menu; + +namespace VocaluxeLib.PartyModes.RuleRoulette +{ + class CWheelCard + { + public CStatic Active; + public CStatic Box; + public CText Name; + } + + class CTableRow + { + public CStatic Highlight; + public CStatic Avatar; + public CText Pos; + public CText Name; + public CText Points; + } + + public class CPartyScreenRuleRouletteMain : CPartyScreenRuleRoulette + { + protected override int _ScreenVersion + { + get { return 1; } + } + + private const string _TextPopupReallyExit = "TextPopupReallyExit"; + private const string _TextDuel = "TextDuel"; + private const string _TextRowPos = "TextRowPos"; + private const string _TextRowName = "TextRowName"; + private const string _TextRowPoints = "TextRowPoints"; + private const string _TextCardName = "TextCardName"; + private const string _TextCardNameResult = "TextCardNameResult"; + private const string _TextName1 = "TextName1"; + private const string _TextName2 = "TextName2"; + private const string _TextVersus = "TextVersus"; + private const string _TextRuleTitle = "TextRuleTitle"; + private const string _TextRuleDescription = "TextRuleDescription"; + private const string _TextRuleInfo = "TextRuleInfo"; + private const string _TextLastResult = "TextLastResult"; + private const string _TextChampionLabel = "TextChampionLabel"; + private const string _TextChampion = "TextChampion"; + + private const string _ButtonNextRound = "ButtonNextRound"; + private const string _ButtonBack = "ButtonBack"; + private const string _ButtonExit = "ButtonExit"; + private const string _ButtonPopupYes = "ButtonPopupYes"; + private const string _ButtonPopupNo = "ButtonPopupNo"; + + private const string _StaticPopupBG = "StaticPopupBG"; + private const string _StaticRowHighlight = "StaticRowHighlight"; + private const string _StaticRowAvatar = "StaticRowAvatar"; + private const string _StaticCardBox = "StaticCardBox"; + private const string _StaticCardActive = "StaticCardActive"; + private const string _StaticAvatar1 = "StaticAvatar1"; + private const string _StaticAvatar2 = "StaticAvatar2"; + + private const string _ParticleEffectChampion = "ParticleEffectChampion"; + + private const float _WheelCenterX = 1240f; + private const float _WheelCenterY = 530f; + private const float _WheelRadiusX = 545f; + private const float _WheelRadiusY = 320f; + private const float _ActiveBorder = 4f; + private const float _UsedAlpha = 0.35f; + private const float _FirstRowY = 255f; + private const float _RowStep = 52f; + private const float _PopDuration = 700f; + private const int _SpinRounds = 3; + private const float _SpinMinStep = 50f; + private const float _SpinMaxStep = 420f; + + private readonly string[] _RankColors = new string[] { "Top1Color", "Top2Color", "Top3Color" }; + + private bool _ExitPopupVisible; + private List _Cards; + private List _Rows; + private readonly Stopwatch _AnimTimer = new Stopwatch(); + private readonly Stopwatch _SpinTimer = new Stopwatch(); + private List _SpinSteps; + private int _SpinTarget = -1; + private bool _Spinning; + private int _LastSeenDuels = -1; + private bool _ShowNewResult; + private float _LastResultHeight; + private float _ChampionHeight; + private SRectF _Avatar1Rect; + + public override void Init() + { + base.Init(); + + _ThemeTexts = new string[] + { + _TextPopupReallyExit, _TextDuel, _TextRowPos, _TextRowName, _TextRowPoints, _TextCardName, _TextCardNameResult, _TextName1, _TextName2, _TextVersus, + _TextRuleTitle, _TextRuleDescription, _TextRuleInfo, _TextLastResult, _TextChampionLabel, _TextChampion + }; + _ThemeButtons = new string[] { _ButtonNextRound, _ButtonBack, _ButtonExit, _ButtonPopupYes, _ButtonPopupNo }; + _ThemeStatics = new string[] { _StaticPopupBG, _StaticRowHighlight, _StaticRowAvatar, _StaticCardBox, _StaticCardActive, _StaticAvatar1, _StaticAvatar2 }; + _ThemeParticleEffects = new string[] { _ParticleEffectChampion }; + } + + public override void LoadTheme(string xmlPath) + { + base.LoadTheme(xmlPath); + + _Cards = new List(); + for (var i = 0; i < CPartyModeRuleRoulette.MaxRulesOnWheel; i++) + { + var card = new CWheelCard + { + Active = GetNewStatic(_Statics[_StaticCardActive]), + Box = GetNewStatic(_Statics[_StaticCardBox]), + Name = GetNewText(_Texts[_TextCardName]) + }; + _AddStatic(card.Active); + _AddStatic(card.Box); + _AddText(card.Name); + _Cards.Add(card); + } + + _Rows = new List(); + for (var i = 0; i < _PartyMode.MaxPlayers; i++) + { + var row = new CTableRow + { + Highlight = GetNewStatic(_Statics[_StaticRowHighlight]), + Avatar = GetNewStatic(_Statics[_StaticRowAvatar]), + Pos = GetNewText(_Texts[_TextRowPos]), + Name = GetNewText(_Texts[_TextRowName]), + Points = GetNewText(_Texts[_TextRowPoints]) + }; + row.Avatar.Aspect = EAspect.Crop; + var y = _FirstRowY + i * _RowStep; + row.Highlight.Y = y + (row.Name.H - row.Highlight.H) / 2; + row.Avatar.Y = y + (row.Name.H - row.Avatar.H) / 2; + row.Pos.Y = y; + row.Name.Y = y; + row.Points.Y = y; + _AddStatic(row.Highlight); + _AddStatic(row.Avatar); + _AddText(row.Pos); + _AddText(row.Name); + _AddText(row.Points); + _Rows.Add(row); + } + + _Statics[_StaticCardBox].Visible = false; + _Statics[_StaticCardActive].Visible = false; + _Statics[_StaticRowHighlight].Visible = false; + _Statics[_StaticRowAvatar].Visible = false; + _Texts[_TextCardName].Visible = false; + _Texts[_TextCardNameResult].Visible = false; + _Texts[_TextRowPos].Visible = false; + _Texts[_TextRowName].Visible = false; + _Texts[_TextRowPoints].Visible = false; + _Statics[_StaticAvatar1].Aspect = EAspect.Crop; + _Statics[_StaticAvatar2].Aspect = EAspect.Crop; + _Avatar1Rect = _Statics[_StaticAvatar1].Rect; + + _LastResultHeight = _Texts[_TextLastResult].Font.Height; + _ChampionHeight = _Texts[_TextChampion].Font.Height; + } + + public override bool HandleInput(SKeyEvent keyEvent) + { + base.HandleInput(keyEvent); + + if (!keyEvent.KeyPressed) + { + switch (keyEvent.Key) + { + case Keys.Back: + case Keys.Escape: + _OnBack(); + break; + + case Keys.Enter: + _OnSelect(); + break; + } + } + + return true; + } + + public override bool HandleMouse(SMouseEvent mouseEvent) + { + base.HandleMouse(mouseEvent); + + if (mouseEvent.LB && _IsMouseOverCurSelection(mouseEvent)) + { + _OnSelect(); + } + + if (mouseEvent.RB) + { + _OnBack(); + } + + return true; + } + + public override void OnShow() + { + base.OnShow(); + + _ShowNewResult = _PartyMode.GameData.LastDuel != null && _PartyMode.GameData.NumDuelsPlayed != _LastSeenDuels; + _LastSeenDuels = _PartyMode.GameData.NumDuelsPlayed; + _Spinning = false; + _SpinTarget = _PartyMode.GameData.RuleChosen && _PartyMode.CurrentDuel != null ? _PartyMode.GameData.Wheel.IndexOf(_PartyMode.CurrentDuel.Rule) : -1; + + _LayoutCards(); + _UpdateTable(); + _UpdateCenter(); + _UpdateCards(_SpinTarget); + _UpdateButtons(); + + _AnimTimer.Reset(); + _AnimTimer.Start(); + _UpdateAnimations(); + + _ShowPopup(false); + } + + public override bool UpdateGame() + { + if (_Spinning) + { + _UpdateSpin(); + } + + _UpdateAnimations(); + return true; + } + + private void _OnBack() + { + if (_Spinning) + { + return; + } + + if (_ExitPopupVisible) + { + _ShowPopup(false); + } + else if (_PartyMode.GameData.NumDuelsPlayed == 0 && !_PartyMode.GameData.RuleChosen) + { + _PartyMode.Back(); + } + else if (_PartyMode.IsFinished) + { + _EndParty(); + } + else + { + _ShowPopup(true); + } + } + + private void _OnSelect() + { + if (_Spinning) + { + return; + } + + if (_ExitPopupVisible) + { + if (_Buttons[_ButtonPopupYes].Selected) + { + _EndParty(); + } + + if (_Buttons[_ButtonPopupNo].Selected) + { + _ShowPopup(false); + } + + return; + } + + if (_Buttons[_ButtonNextRound].Selected && _Buttons[_ButtonNextRound].Visible) + { + if (_PartyMode.GameData.RuleChosen) + { + _PartyMode.Next(); + } + else + { + _StartSpin(); + } + } + + if (_Buttons[_ButtonBack].Selected && _Buttons[_ButtonBack].Visible) + { + _PartyMode.Back(); + } + + if (_Buttons[_ButtonExit].Selected && _Buttons[_ButtonExit].Visible) + { + if (_PartyMode.IsFinished) + { + _EndParty(); + } + else + { + _ShowPopup(true); + } + } + } + + private void _EndParty() + { + CBase.Graphics.FadeTo(EScreen.Party); + } + + private void _ShowPopup(bool visible) + { + _ExitPopupVisible = visible; + + _Statics[_StaticPopupBG].Visible = _ExitPopupVisible; + _Texts[_TextPopupReallyExit].Visible = _ExitPopupVisible; + _Buttons[_ButtonPopupYes].Visible = _ExitPopupVisible; + _Buttons[_ButtonPopupNo].Visible = _ExitPopupVisible; + + if (_ExitPopupVisible) + { + _SelectElement(_Buttons[_ButtonPopupNo]); + } + } + + private void _UpdateButtons() + { + var started = _PartyMode.GameData.NumDuelsPlayed > 0 || _PartyMode.GameData.RuleChosen; + _Buttons[_ButtonBack].Visible = !started; + _Buttons[_ButtonExit].Visible = started; + _Buttons[_ButtonNextRound].Visible = !_PartyMode.IsFinished; + _Buttons[_ButtonNextRound].Text.Text = _PartyMode.GameData.RuleChosen ? "TR_BUTTON_START_DUEL" : "TR_BUTTON_SPIN"; + + if (_PartyMode.IsFinished) + { + _SelectElement(_Buttons[_ButtonExit]); + } + else + { + _SelectElement(_Buttons[_ButtonNextRound]); + } + } + + private static float _EaseOutBack(float t) + { + const float c1 = 1.70158f; + const float c3 = c1 + 1f; + return 1f + c3 * (float)Math.Pow(t - 1f, 3) + c1 * (float)Math.Pow(t - 1f, 2); + } + + private string _GetName(CRoulettePlayer player) + { + return CBase.Profiles.GetPlayerName(player.ProfileId); + } + + private string _Translate(string key) + { + return CBase.Language.Translate(key, PartyModeId); + } + + private void _LayoutCards() + { + var wheel = _PartyMode.GameData.Wheel; + var box = _Statics[_StaticCardBox].Rect; + for (var i = 0; i < _Cards.Count; i++) + { + var card = _Cards[i]; + var visible = !_PartyMode.IsFinished && i < wheel.Count; + card.Box.Visible = visible; + card.Name.Visible = visible; + card.Active.Visible = false; + if (!visible) + { + continue; + } + + var angle = 2 * Math.PI * i / wheel.Count - Math.PI / 2; + var centerX = _WheelCenterX + _WheelRadiusX * (float)Math.Cos(angle); + var centerY = _WheelCenterY + _WheelRadiusY * (float)Math.Sin(angle); + card.Box.MaxRect = new SRectF(centerX - box.W / 2, centerY - box.H / 2, box.W, box.H, box.Z); + card.Active.MaxRect = new SRectF(centerX - box.W / 2 - _ActiveBorder, centerY - box.H / 2 - _ActiveBorder, box.W + 2 * _ActiveBorder, + box.H + 2 * _ActiveBorder, _Statics[_StaticCardActive].Rect.Z); + card.Name.X = centerX; + card.Name.Y = centerY - card.Name.H / 2; + card.Name.Text = CPartyModeRuleRoulette.GetRuleKey(wheel[i]); + } + } + + private void _UpdateCards(int highlight) + { + var wheel = _PartyMode.GameData.Wheel; + for (var i = 0; i < _Cards.Count && i < wheel.Count; i++) + { + var card = _Cards[i]; + if (!card.Box.Visible) + { + continue; + } + + var used = _PartyMode.GameData.UsedInCycle.Contains(wheel[i]) && i != _SpinTarget; + var isResult = !_Spinning && i == _SpinTarget; + var alpha = used && i != highlight ? _UsedAlpha : 1f; + var boxColor = _Statics[_StaticCardBox].Color; + card.Box.Color = new SColorF(boxColor.R, boxColor.G, boxColor.B, boxColor.A * alpha); + var nameColor = isResult ? _Texts[_TextCardNameResult].Color : _Texts[_TextCardName].Color; + card.Name.Color = new SColorF(nameColor.R, nameColor.G, nameColor.B, nameColor.A * alpha); + card.Active.Visible = i == highlight; + } + } + + private void _StartSpin() + { + int target; + _PartyMode.SpinWheel(out target); + if (target < 0) + { + return; + } + + _SpinTarget = target; + var count = _PartyMode.GameData.Wheel.Count; + var steps = _SpinRounds * count + target; + _SpinSteps = new List(); + var time = 0f; + for (var i = 0; i < steps; i++) + { + var progress = (float)i / steps; + time += _SpinMinStep + (_SpinMaxStep - _SpinMinStep) * progress * progress; + _SpinSteps.Add(time); + } + + _Spinning = true; + _SpinTimer.Reset(); + _SpinTimer.Start(); + _UpdateCenter(); + _Buttons[_ButtonNextRound].Visible = false; + _Buttons[_ButtonBack].Visible = false; + _Buttons[_ButtonExit].Visible = true; + } + + private void _UpdateSpin() + { + var elapsed = _SpinTimer.ElapsedMilliseconds; + var step = 0; + while (step < _SpinSteps.Count && _SpinSteps[step] <= elapsed) + { + step++; + } + + var count = _PartyMode.GameData.Wheel.Count; + if (step >= _SpinSteps.Count && elapsed >= _SpinSteps[_SpinSteps.Count - 1] + 300f) + { + _Spinning = false; + _UpdateCards(_SpinTarget); + _UpdateCenter(); + _UpdateButtons(); + _AnimTimer.Reset(); + _AnimTimer.Start(); + return; + } + + _UpdateCards(step % count); + } + + private void _UpdateTable() + { + var ranking = _PartyMode.GetRanking(); + for (var i = 0; i < _Rows.Count; i++) + { + var row = _Rows[i]; + var visible = i < ranking.Count; + row.Avatar.Visible = visible; + row.Pos.Visible = visible; + row.Name.Visible = visible; + row.Points.Visible = visible; + row.Highlight.Visible = visible && i == 0 && ranking[0].TablePoints > 0; + if (!visible) + { + continue; + } + + var player = ranking[i]; + row.Avatar.Texture = CBase.Profiles.GetAvatar(player.ProfileId); + row.Pos.Text = (i + 1) + "."; + row.Name.Text = _GetName(player); + row.Points.Text = player.TablePoints.ToString(); + + SColorF rankColor; + var color = _Texts[_TextRowName].Color; + if (_PartyMode.GameData.NumDuelsPlayed > 0 && i < _RankColors.Length && CBase.Themes.GetColor(_RankColors[i], PartyModeId, out rankColor)) + { + color = rankColor; + } + + row.Pos.Color = color; + row.Name.Color = color; + } + } + + private void _UpdateCenter() + { + var finished = _PartyMode.IsFinished; + var duel = _PartyMode.CurrentDuel; + var showDuel = !finished && duel != null; + var showRule = showDuel && _PartyMode.GameData.RuleChosen && !_Spinning; + + _Statics[_StaticAvatar2].Visible = showDuel; + _Texts[_TextName1].Visible = showDuel; + _Texts[_TextName2].Visible = showDuel; + _Texts[_TextVersus].Visible = showDuel; + _Texts[_TextDuel].Visible = showDuel; + _Texts[_TextRuleTitle].Visible = showRule; + _Texts[_TextRuleDescription].Visible = showRule; + _Texts[_TextRuleInfo].Visible = false; + _Texts[_TextLastResult].Visible = !finished && _PartyMode.GameData.LastDuel != null && !showRule && !_Spinning; + + _Statics[_StaticAvatar1].MaxRect = _Avatar1Rect; + _Statics[_StaticAvatar1].Visible = showDuel || finished; + + if (showDuel) + { + _Statics[_StaticAvatar1].Texture = CBase.Profiles.GetAvatar(duel.Players[0].ProfileId); + _Statics[_StaticAvatar2].Texture = CBase.Profiles.GetAvatar(duel.Players[1].ProfileId); + _Texts[_TextName1].Text = _GetName(duel.Players[0]); + _Texts[_TextName2].Text = _GetName(duel.Players[1]); + _Texts[_TextDuel].Text = _Translate("TR_SCREENMAIN_DUEL") + " " + (_PartyMode.GameData.DuelIndex + 1) + " / " + _PartyMode.GameData.Duels.Count; + } + + if (showRule) + { + var key = CPartyModeRuleRoulette.GetRuleKey(duel.Rule); + _Texts[_TextRuleTitle].Text = key; + _Texts[_TextRuleDescription].Text = key + "_DESC"; + if (duel.Rule == ERule.TargetScore) + { + _Texts[_TextRuleInfo].Visible = true; + _Texts[_TextRuleInfo].Text = _Translate("TR_SCREENMAIN_TARGET") + " " + duel.TargetScore.ToString("N0"); + } + else if (duel.Rule == ERule.UnderdogChoice && duel.Chooser != null) + { + _Texts[_TextRuleInfo].Visible = true; + _Texts[_TextRuleInfo].Text = _Translate("TR_SCREENMAIN_CHOOSER").Replace("%s", _GetName(duel.Chooser)); + } + else if (duel.Rule == ERule.JokerRain) + { + _Texts[_TextRuleInfo].Visible = true; + _Texts[_TextRuleInfo].Text = _Translate("TR_SCREENMAIN_JOKERS") + " " + _GetName(duel.Players[0]) + " " + duel.Players[0].Jokers + " · " + + _GetName(duel.Players[1]) + " " + duel.Players[1].Jokers; + } + } + + var last = _PartyMode.GameData.LastDuel; + if (last != null) + { + _Texts[_TextLastResult].Text = _Translate("TR_SCREENMAIN_LAST_DUEL") + " " + _GetName(last.Players[0]) + " " + last.Scores[0].ToString("N0") + " (" + + _FormatAward(last.Awarded[0]) + ") · " + _GetName(last.Players[1]) + " " + last.Scores[1].ToString("N0") + " (" + + _FormatAward(last.Awarded[1]) + ")"; + } + + _Texts[_TextChampionLabel].Visible = finished; + _Texts[_TextChampion].Visible = finished; + _ParticleEffects[_ParticleEffectChampion].Visible = finished; + if (finished) + { + var champion = _PartyMode.GetRanking()[0]; + _Texts[_TextChampion].Text = _GetName(champion); + _Statics[_StaticAvatar1].Texture = CBase.Profiles.GetAvatar(champion.ProfileId); + _Statics[_StaticAvatar1].X = _WheelCenterX - _Avatar1Rect.W / 2; + _Statics[_StaticAvatar1].Y = _Avatar1Rect.Y + 80f; + } + } + + private static string _FormatAward(int award) + { + return award > 0 ? "+" + award : award.ToString(); + } + + private void _UpdateAnimations() + { + var time = _AnimTimer.ElapsedMilliseconds; + var pop = time < _PopDuration ? 0.3f + 0.7f * _EaseOutBack(time / _PopDuration) : 1f; + + _Texts[_TextLastResult].Font.Height = _LastResultHeight * (_ShowNewResult ? pop : 1f); + + if (_PartyMode.IsFinished) + { + var scale = time < _PopDuration ? pop : 1f + 0.03f * (float)Math.Sin((time - _PopDuration) / 1000.0 * Math.PI * 1.4); + _Texts[_TextChampion].Font.Height = _ChampionHeight * scale; + } + } + } +} diff --git a/PartyModes/PartyModeRuleRoulette/CPartyScreenRuleRouletteNames.cs b/PartyModes/PartyModeRuleRoulette/CPartyScreenRuleRouletteNames.cs new file mode 100644 index 00000000..c040f8b4 --- /dev/null +++ b/PartyModes/PartyModeRuleRoulette/CPartyScreenRuleRouletteNames.cs @@ -0,0 +1,74 @@ +#region license +// This file is part of Vocaluxe. +// +// Vocaluxe is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Vocaluxe is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Vocaluxe. If not, see . +#endregion + +using System; +using System.Collections.Generic; +using VocaluxeLib.Menu; + +namespace VocaluxeLib.PartyModes.RuleRoulette +{ + public class CPartyScreenRuleRouletteNames : CMenuPartyNameSelection + { + protected override int _ScreenVersion + { + get { return 1; } + } + + private new CPartyModeRuleRoulette _PartyMode; + + public override void Init() + { + base.Init(); + _PartyMode = (CPartyModeRuleRoulette)base._PartyMode; + _AllowChangePlayerNum = false; + _Teams = false; + } + + public override void OnShow() + { + base.OnShow(); + SetPartyModeData(_PartyMode.GameData.NumPlayer); + while (_PartyMode.GameData.ProfileIds.Count > _NumPlayer) + { + _PartyMode.GameData.ProfileIds.RemoveAt(_PartyMode.GameData.ProfileIds.Count - 1); + } + + var ids = new List[] { _PartyMode.GameData.ProfileIds }; + SetPartyModeProfiles(ids); + } + + public override void Back() + { + if (_TeamList.Length == 1) + { + _PartyMode.GameData.ProfileIds = _TeamList[0]; + } + + _PartyMode.Back(); + } + + public override void Next() + { + if (_TeamList.Length == 1) + { + _PartyMode.GameData.ProfileIds = _TeamList[0]; + } + + _PartyMode.Next(); + } + } +} \ No newline at end of file diff --git a/PartyModes/PartyModeRuleRoulette/CPartyScreenRuleRouletteRules.cs b/PartyModes/PartyModeRuleRoulette/CPartyScreenRuleRouletteRules.cs new file mode 100644 index 00000000..324d37d7 --- /dev/null +++ b/PartyModes/PartyModeRuleRoulette/CPartyScreenRuleRouletteRules.cs @@ -0,0 +1,361 @@ +#region license +// This file is part of Vocaluxe. +// +// Vocaluxe is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Vocaluxe is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Vocaluxe. If not, see . +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Forms; +using VocaluxeLib.Menu; + +namespace VocaluxeLib.PartyModes.RuleRoulette +{ + class CRuleRow + { + public ERule Rule; + public CStatic Highlight; + public CText Name; + public CText Description; + public CText State; + public CStatic ArrowLeft; + public CStatic ArrowRight; + } + + public class CPartyScreenRuleRouletteRules : CPartyScreenRuleRoulette + { + protected override int _ScreenVersion + { + get { return 1; } + } + + private const string _ButtonNext = "ButtonNext"; + private const string _ButtonBack = "ButtonBack"; + + private const string _StaticRowHighlight = "StaticRowHighlight"; + private const string _StaticArrowLeft = "StaticArrowLeft"; + private const string _StaticArrowRight = "StaticArrowRight"; + private const string _TextRuleName = "TextRuleName"; + private const string _TextRuleDescription = "TextRuleDescription"; + private const string _TextRuleState = "TextRuleState"; + private const string _TextStateAlways = "TextStateAlways"; + private const string _TextStateRandom = "TextStateRandom"; + private const string _TextStateNever = "TextStateNever"; + + private const float _FirstRowY = 190f; + private const float _RowStep = 68f; + private const float _DescriptionOffset = 33f; + private const int _RowsPerColumn = 10; + private const float _StateWidth = 190f; + private const float _ArrowSpace = 6f; + + private readonly float[] _ColumnX = new float[] { 50f, 980f }; + + private List _Rows; + private int _SelectedRow; + private bool _OnButtons; + + public override void Init() + { + base.Init(); + + _ThemeButtons = new string[] { _ButtonNext, _ButtonBack }; + _ThemeStatics = new string[] { _StaticRowHighlight, _StaticArrowLeft, _StaticArrowRight }; + _ThemeTexts = new string[] { _TextRuleName, _TextRuleDescription, _TextRuleState, _TextStateAlways, _TextStateRandom, _TextStateNever }; + } + + public override void LoadTheme(string xmlPath) + { + base.LoadTheme(xmlPath); + + _Rows = new List(); + var rules = Enum.GetValues(typeof(ERule)).Cast().ToList(); + for (var i = 0; i < rules.Count; i++) + { + var x = _ColumnX[i / _RowsPerColumn]; + var y = _FirstRowY + (i % _RowsPerColumn) * _RowStep; + var row = new CRuleRow + { + Rule = rules[i], + Highlight = GetNewStatic(_Statics[_StaticRowHighlight]), + Name = GetNewText(_Texts[_TextRuleName]), + Description = GetNewText(_Texts[_TextRuleDescription]), + State = GetNewText(_Texts[_TextRuleState]), + ArrowLeft = GetNewStatic(_Statics[_StaticArrowLeft]), + ArrowRight = GetNewStatic(_Statics[_StaticArrowRight]) + }; + + var highlight = _Statics[_StaticRowHighlight].Rect; + row.Highlight.MaxRect = new SRectF(x, y, highlight.W, highlight.H, highlight.Z); + row.Name.X = x + 16f; + row.Name.Y = y + 3f; + row.Description.X = x + 16f; + row.Description.Y = y + _DescriptionOffset; + var arrow = _Statics[_StaticArrowRight].Rect; + var arrowY = y + (highlight.H - arrow.H) / 2; + var rightX = x + highlight.W - 12f - arrow.W; + var leftX = rightX - _ArrowSpace - _StateWidth - _ArrowSpace - arrow.W; + row.ArrowRight.MaxRect = new SRectF(rightX, arrowY, arrow.W, arrow.H, arrow.Z); + row.ArrowLeft.MaxRect = new SRectF(leftX, arrowY, arrow.W, arrow.H, arrow.Z); + row.State.X = leftX + arrow.W + _ArrowSpace + _StateWidth / 2; + row.State.Y = y + (highlight.H - row.State.H) / 2; + row.Name.Text = CPartyModeRuleRoulette.GetRuleKey(row.Rule); + row.Description.Text = CPartyModeRuleRoulette.GetRuleKey(row.Rule) + "_DESC"; + + _AddStatic(row.Highlight); + _AddText(row.Name); + _AddText(row.Description); + _AddText(row.State); + _AddStatic(row.ArrowLeft); + _AddStatic(row.ArrowRight); + _Rows.Add(row); + } + + _Statics[_StaticRowHighlight].Visible = false; + _Statics[_StaticArrowLeft].Visible = false; + _Statics[_StaticArrowRight].Visible = false; + _Texts[_TextRuleName].Visible = false; + _Texts[_TextRuleDescription].Visible = false; + _Texts[_TextRuleState].Visible = false; + _Texts[_TextStateAlways].Visible = false; + _Texts[_TextStateRandom].Visible = false; + _Texts[_TextStateNever].Visible = false; + } + + public override void OnShow() + { + base.OnShow(); + + _SelectedRow = 0; + _UpdateRows(); + _FocusRows(); + } + + public override bool UpdateGame() + { + return true; + } + + public override bool HandleInput(SKeyEvent keyEvent) + { + if (keyEvent.KeyPressed) + { + return true; + } + + switch (keyEvent.Key) + { + case Keys.Back: + case Keys.Escape: + _PartyMode.Back(); + break; + + case Keys.Enter: + if (_OnButtons && _Buttons[_ButtonBack].Selected) + { + _PartyMode.Back(); + } + else + { + _PartyMode.Next(); + } + + break; + + case Keys.Up: + if (_OnButtons) + { + _FocusRows(); + } + else + { + _SelectRow(_SelectedRow - 1); + } + + break; + + case Keys.Down: + if (_OnButtons) + { + break; + } + + if (_SelectedRow + 1 < _Rows.Count) + { + _SelectRow(_SelectedRow + 1); + } + else + { + _FocusButtons(); + } + + break; + + case Keys.Left: + case Keys.Right: + if (_OnButtons) + { + _SwitchButton(); + } + else + { + _ChangeState(_SelectedRow, keyEvent.Key == Keys.Left ? -1 : 1); + } + + break; + + case Keys.Tab: + if (_OnButtons) + { + _SwitchButton(); + } + else + { + _FocusButtons(); + } + + break; + } + + return true; + } + + public override bool HandleMouse(SMouseEvent mouseEvent) + { + base.HandleMouse(mouseEvent); + if (_Buttons[_ButtonBack].Selected || _Buttons[_ButtonNext].Selected) + { + _OnButtons = true; + } + + if (mouseEvent.LB) + { + for (var r = 0; r < _Rows.Count; r++) + { + if (CHelper.IsInBounds(_Rows[r].ArrowLeft.Rect, mouseEvent)) + { + _SelectRow(r); + _ChangeState(r, -1); + return true; + } + + if (CHelper.IsInBounds(_Rows[r].Highlight.Rect, mouseEvent)) + { + _SelectRow(r); + _ChangeState(r, 1); + return true; + } + } + + if (_IsMouseOverCurSelection(mouseEvent)) + { + if (_Buttons[_ButtonBack].Selected) + { + _PartyMode.Back(); + } + + if (_Buttons[_ButtonNext].Selected) + { + _PartyMode.Next(); + } + } + } + + if (mouseEvent.RB) + { + _PartyMode.Back(); + } + + return true; + } + + private void _FocusRows() + { + _OnButtons = false; + _Buttons[_ButtonBack].Selected = false; + _Buttons[_ButtonNext].Selected = false; + _UpdateRows(); + } + + private void _FocusButtons() + { + _OnButtons = true; + _SelectElement(_Buttons[_ButtonNext]); + _UpdateRows(); + } + + private void _SwitchButton() + { + _SelectElement(_Buttons[_ButtonNext].Selected ? _Buttons[_ButtonBack] : _Buttons[_ButtonNext]); + } + + private void _SelectRow(int row) + { + _OnButtons = false; + _Buttons[_ButtonBack].Selected = false; + _Buttons[_ButtonNext].Selected = false; + _SelectedRow = Math.Max(0, Math.Min(_Rows.Count - 1, row)); + _UpdateRows(); + } + + private void _ChangeState(int row, int direction) + { + if (row < 0 || row >= _Rows.Count) + { + return; + } + + var rule = _Rows[row].Rule; + var order = new ERuleState[] { ERuleState.Never, ERuleState.Random, ERuleState.Always }; + var index = Array.IndexOf(order, _PartyMode.GameData.RuleStates[rule]); + index = (index + direction + order.Length) % order.Length; + _PartyMode.GameData.RuleStates[rule] = order[index]; + _UpdateRows(); + } + + private void _UpdateRows() + { + for (var r = 0; r < _Rows.Count; r++) + { + var row = _Rows[r]; + row.Highlight.Visible = r == _SelectedRow && !_OnButtons; + var arrowColor = r == _SelectedRow && !_OnButtons ? _Statics[_StaticArrowRight].Color : _Statics[_StaticArrowLeft].Color; + row.ArrowLeft.Color = arrowColor; + row.ArrowRight.Color = arrowColor; + + CText template; + switch (_PartyMode.GameData.RuleStates[row.Rule]) + { + case ERuleState.Always: + template = _Texts[_TextStateAlways]; + break; + case ERuleState.Never: + template = _Texts[_TextStateNever]; + break; + default: + template = _Texts[_TextStateRandom]; + break; + } + + row.State.Text = template.Text; + row.State.Color = template.Color; + var nameColor = _Texts[_TextRuleName].Color; + row.Name.Color = _PartyMode.GameData.RuleStates[row.Rule] == ERuleState.Never + ? new SColorF(nameColor.R, nameColor.G, nameColor.B, nameColor.A * 0.45f) + : nameColor; + } + } + } +} diff --git a/PartyModes/PartyModeRuleRoulette/CPartyScreenRuleRouletteSongs.cs b/PartyModes/PartyModeRuleRoulette/CPartyScreenRuleRouletteSongs.cs new file mode 100644 index 00000000..934af99a --- /dev/null +++ b/PartyModes/PartyModeRuleRoulette/CPartyScreenRuleRouletteSongs.cs @@ -0,0 +1,66 @@ +using VocaluxeLib.Menu; + +namespace VocaluxeLib.PartyModes.RuleRoulette +{ + class CPartyScreenRuleRouletteSongs : CMenuPartySongSelection + { + protected override int _ScreenVersion + { + get { return 1; } + } + + private new CPartyModeRuleRoulette _PartyMode; + + public override void Init() + { + base.Init(); + _PartyMode = (CPartyModeRuleRoulette)base._PartyMode; + } + + public override void OnShow() + { + Source = _PartyMode.GameData.SongSource; + Sorting = _PartyMode.GameData.Sorting; + Category = _PartyMode.GameData.CategoryIndex; + Playlist = _PartyMode.GameData.PlaylistId; + SongMode = _PartyMode.GameData.GameMode; + NumMedleySongs = _PartyMode.GameData.NumMedleySongs; + + base.OnShow(); + } + + public override void Back() + { + _SaveConfig(); + _PartyMode.Back(); + } + + public override void Next() + { + _SaveConfig(); + _PartyMode.Next(); + } + + public override bool UpdateGame() + { + return true; + } + + protected override void _SetAllowedOptions() + { + base._SetAllowedOptions(); + + AllowedSongModes = new EGameMode[] { EGameMode.TR_GAMEMODE_NORMAL, EGameMode.TR_GAMEMODE_SHORTSONG }; + } + + private void _SaveConfig() + { + _PartyMode.GameData.SongSource = Source; + _PartyMode.GameData.Sorting = Sorting; + _PartyMode.GameData.CategoryIndex = Category; + _PartyMode.GameData.PlaylistId = Playlist; + _PartyMode.GameData.GameMode = SongMode; + _PartyMode.GameData.NumMedleySongs = NumMedleySongs; + } + } +} \ No newline at end of file diff --git a/PartyModes/PartyModeRuleRoulette/GlobalSuppressions.cs b/PartyModes/PartyModeRuleRoulette/GlobalSuppressions.cs new file mode 100644 index 00000000..e661ff03 Binary files /dev/null and b/PartyModes/PartyModeRuleRoulette/GlobalSuppressions.cs differ diff --git a/PartyModes/PartyModeRuleRoulette/PartyModeRuleRoulette.csproj b/PartyModes/PartyModeRuleRoulette/PartyModeRuleRoulette.csproj new file mode 100644 index 00000000..efadd403 --- /dev/null +++ b/PartyModes/PartyModeRuleRoulette/PartyModeRuleRoulette.csproj @@ -0,0 +1,119 @@ + + + + DebugWin + AnyCPU + 8.0.30703 + 2.0 + {2E6A9B48-71C3-4D05-8F2B-C4A7D19E6E3F} + Library + Properties + VocaluxeLib.PartyModes.RuleRoulette + RuleRoulette + v4.8.1 + + + 512 + + + AnyCPU + true + full + false + bin + TRACE;DEBUG;WIN + prompt + 4 + Off + ..\..\CheckingRules.ruleset + false + 9.0 + + + AnyCPU + pdbonly + true + bin + prompt + 4 + false + WIN + Off + false + true + 9.0 + + + AnyCPU + true + full + false + bin + TRACE;DEBUG;LINUX + prompt + 4 + Off + false + 9.0 + + + AnyCPU + pdbonly + true + bin + prompt + 4 + false + LINUX + Off + false + true + 9.0 + + + bin + WIN + true + AnyCPU + false + Off + prompt + ManagedMinimumRules.ruleset + false + pdbonly + true + 9.0 + + + + + + + + + + + + + {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC} + VocaluxeLib + False + + + + + + + + + + if exist "$(SolutionDir)Output\PartyModes\$(TargetName)\Code" rd "$(SolutionDir)Output\PartyModes\$(TargetName)\Code" /S /Q +cd $(SolutionDir)Partymodes\ +xcopy "$(ProjectDir)*.cs" "$(SolutionDir)Output\PartyModes\$(TargetName)\Code\" /EXCLUDE:Excludes.txt /I /Y + rm -rf "$(SolutionDir)Output\PartyModes\$(TargetName)\Code" +mkdir -p "$(SolutionDir)Output\PartyModes\$(TargetName)\Code\" +cp -R $(ProjectDir)*.cs "$(SolutionDir)Output\PartyModes\$(TargetName)\Code\" +rm -f "$(SolutionDir)Output\PartyModes\$(TargetName)\Code\GlobalSuppressions.cs" + + + \ No newline at end of file diff --git a/PartyModes/PartyModeRuleRoulette/Settings.StyleCop b/PartyModes/PartyModeRuleRoulette/Settings.StyleCop new file mode 100644 index 00000000..f4a4ea2a --- /dev/null +++ b/PartyModes/PartyModeRuleRoulette/Settings.StyleCop @@ -0,0 +1,809 @@ + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + + + \ No newline at end of file diff --git a/Vocaluxe.sln b/Vocaluxe.sln index ad929fc1..21d9d0f9 100644 --- a/Vocaluxe.sln +++ b/Vocaluxe.sln @@ -11,6 +11,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vocaluxe", "Vocaluxe\Vocalu {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC} = {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC} {5A4053F1-5AD5-441F-B254-D97A088127B6} = {5A4053F1-5AD5-441F-B254-D97A088127B6} {54A48AF7-515C-4EDD-B395-2BFFA096050A} = {54A48AF7-515C-4EDD-B395-2BFFA096050A} + {2E6A9B48-71C3-4D05-8F2B-C4A7D19E6E3F} = {2E6A9B48-71C3-4D05-8F2B-C4A7D19E6E3F} EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VocaluxeLib", "VocaluxeLib\VocaluxeLib.csproj", "{D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}" @@ -23,6 +24,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PartyModeChallenge", "Party EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebserverInitalConfig", "WebserverInitalConfig\WebserverInitalConfig.csproj", "{55F89808-4E79-4FFE-BC13-48258913F5C9}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PartyModeRuleRoulette", "PartyModes\PartyModeRuleRoulette\PartyModeRuleRoulette.csproj", "{2E6A9B48-71C3-4D05-8F2B-C4A7D19E6E3F}" +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PitchTracker", "PitchTracker\PitchTracker.vcxproj", "{54A48AF7-515C-4EDD-B395-2BFFA096050A}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj", "{8EDF4429-251A-416D-BB68-93F227191BCF}" @@ -159,6 +162,26 @@ Global {55F89808-4E79-4FFE-BC13-48258913F5C9}.ReleaseWin|x64.Build.0 = Release|Any CPU {55F89808-4E79-4FFE-BC13-48258913F5C9}.ReleaseWin|x86.ActiveCfg = Release|Any CPU {55F89808-4E79-4FFE-BC13-48258913F5C9}.ReleaseWin|x86.Build.0 = Release|Any CPU + {2E6A9B48-71C3-4D05-8F2B-C4A7D19E6E3F}.DebugLinux|x64.ActiveCfg = DebugLinux|Any CPU + {2E6A9B48-71C3-4D05-8F2B-C4A7D19E6E3F}.DebugLinux|x64.Build.0 = DebugLinux|Any CPU + {2E6A9B48-71C3-4D05-8F2B-C4A7D19E6E3F}.DebugLinux|x86.ActiveCfg = DebugLinux|Any CPU + {2E6A9B48-71C3-4D05-8F2B-C4A7D19E6E3F}.DebugLinux|x86.Build.0 = DebugLinux|Any CPU + {2E6A9B48-71C3-4D05-8F2B-C4A7D19E6E3F}.DebugWin|x64.ActiveCfg = DebugWin|Any CPU + {2E6A9B48-71C3-4D05-8F2B-C4A7D19E6E3F}.DebugWin|x64.Build.0 = DebugWin|Any CPU + {2E6A9B48-71C3-4D05-8F2B-C4A7D19E6E3F}.DebugWin|x86.ActiveCfg = DebugWin|Any CPU + {2E6A9B48-71C3-4D05-8F2B-C4A7D19E6E3F}.DebugWin|x86.Build.0 = DebugWin|Any CPU + {2E6A9B48-71C3-4D05-8F2B-C4A7D19E6E3F}.InstallerWin|x64.ActiveCfg = InstallerWin|Any CPU + {2E6A9B48-71C3-4D05-8F2B-C4A7D19E6E3F}.InstallerWin|x64.Build.0 = InstallerWin|Any CPU + {2E6A9B48-71C3-4D05-8F2B-C4A7D19E6E3F}.InstallerWin|x86.ActiveCfg = InstallerWin|Any CPU + {2E6A9B48-71C3-4D05-8F2B-C4A7D19E6E3F}.InstallerWin|x86.Build.0 = InstallerWin|Any CPU + {2E6A9B48-71C3-4D05-8F2B-C4A7D19E6E3F}.ReleaseLinux|x64.ActiveCfg = ReleaseLinux|Any CPU + {2E6A9B48-71C3-4D05-8F2B-C4A7D19E6E3F}.ReleaseLinux|x64.Build.0 = ReleaseLinux|Any CPU + {2E6A9B48-71C3-4D05-8F2B-C4A7D19E6E3F}.ReleaseLinux|x86.ActiveCfg = ReleaseLinux|Any CPU + {2E6A9B48-71C3-4D05-8F2B-C4A7D19E6E3F}.ReleaseLinux|x86.Build.0 = ReleaseLinux|Any CPU + {2E6A9B48-71C3-4D05-8F2B-C4A7D19E6E3F}.ReleaseWin|x64.ActiveCfg = ReleaseWin|Any CPU + {2E6A9B48-71C3-4D05-8F2B-C4A7D19E6E3F}.ReleaseWin|x64.Build.0 = ReleaseWin|Any CPU + {2E6A9B48-71C3-4D05-8F2B-C4A7D19E6E3F}.ReleaseWin|x86.ActiveCfg = ReleaseWin|Any CPU + {2E6A9B48-71C3-4D05-8F2B-C4A7D19E6E3F}.ReleaseWin|x86.Build.0 = ReleaseWin|Any CPU {54A48AF7-515C-4EDD-B395-2BFFA096050A}.DebugLinux|x64.ActiveCfg = Debug|x64 {54A48AF7-515C-4EDD-B395-2BFFA096050A}.DebugLinux|x64.Build.0 = Debug|x64 {54A48AF7-515C-4EDD-B395-2BFFA096050A}.DebugLinux|x86.ActiveCfg = Debug|Win32