Runtime and build - Move all projects to .NET 10 with SDK-style project files and a shared Directory.Build.props (WIN/LINUX, x86/x64 defines) - Load managed and unmanaged dependencies from libs/managed and libs/unmanaged through assembly and native library resolvers - Compile party modes with Roslyn instead of CodeDom - Update AppVeyor to the .NET 10 SDK and dotnet test - Download the FFmpeg and gstreamer runtimes from the dependencies repository during the build - Remove the VC++ 2015-2022 runtime check, no dependency needs it anymore Graphics and windowing - Replace the Direct3D 9 renderer with Direct3D 11 (Vortice) - Pace Direct3D 11 frames with a frame latency waitable swap chain - Move window, input and message boxes to SDL3 - Replace System.Drawing with SkiaSharp and WinForms with SDL3 and a software renderer Video and audio - Replace Acinerella with FFmpeg 8.1.3 (FFmpeg.AutoGen) - Add hardware accelerated video decoding (D3D11VA, DXVA2, VideoToolbox, VAAPI, VDPAU) with software fallback - Convert YUV video frames to RGB on the GPU in Direct3D 11 and OpenGL - Add the video options HardwareDecoding, GpuColorConversion, DecoderThreads and VideoDownscaleResolution - Update OpenAL to OpenTK 4 and NAudio recording to WasapiRecorder Fixes - Fix the song preview start and shorten the reporter buttons - Fix a crash when opening the highscore without a selected song - Use the options slide highlight in the party mode screens to avoid brightness flicker on VRR displays - Disable GameInput in the x86 build, SDL3 crashes in GameInputCreate on 32-bit systems with the GameInput runtime installed - Fix a truncation warning in PitchTracker
1000 lines
37 KiB
C#
1000 lines
37 KiB
C#
#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 <http://www.gnu.org/licenses/>.
|
|
#endregion
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using VocaluxeLib.Menu;
|
|
|
|
namespace VocaluxeLib.PartyModes.TicTacToe
|
|
{
|
|
public enum EStatus
|
|
{
|
|
FieldChoosing,
|
|
JokerRetry,
|
|
FieldSelected,
|
|
None
|
|
}
|
|
|
|
// ReSharper disable UnusedMember.Global
|
|
public class CPartyScreenTicTacToeMain : CPartyScreenTicTacToe
|
|
// ReSharper restore UnusedMember.Global
|
|
{
|
|
// Version number for theme files. Increment it, if you've changed something on the theme files!
|
|
protected override int _ScreenVersion
|
|
{
|
|
get { return 3; }
|
|
}
|
|
|
|
private const string _TextPopupReallyExit = "TextPopupReallyExit";
|
|
private const string _TextTeamChoosing = "TextTeamChoosing";
|
|
private const string _TextFinishMessage = "TextFinishMessage";
|
|
private const string _TextNextPlayerT1 = "TextNextPlayerT1";
|
|
private const string _TextNextPlayerT2 = "TextNextPlayerT2";
|
|
private const string _TextNextPlayerNameT1 = "TextNextPlayerNameT1";
|
|
private const string _TextNextPlayerNameT2 = "TextNextPlayerNameT2";
|
|
private const string _TextJokerRandomT1 = "TextJokerRandomT1";
|
|
private const string _TextJokerRandomT2 = "TextJokerRandomT2";
|
|
private const string _TextJokerRetryT1 = "TextJokerRetryT1";
|
|
private const string _TextJokerRetryT2 = "TextJokerRetryT2";
|
|
|
|
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 _ButtonField = "ButtonField";
|
|
|
|
private const string _ButtonJokerRandomT1 = "ButtonJokerRandomT1";
|
|
private const string _ButtonJokerRandomT2 = "ButtonJokerRandomT2";
|
|
private const string _ButtonJokerRetryT1 = "ButtonJokerRetryT1";
|
|
private const string _ButtonJokerRetryT2 = "ButtonJokerRetryT2";
|
|
private const string _ButtonSwitchPlayerT1 = "ButtonSwitchPlayerT1";
|
|
private const string _ButtonSwitchPlayerT2 = "ButtonSwitchPlayerT2";
|
|
|
|
private const string _StaticPopupBG = "StaticPopupBG";
|
|
private const string _StaticAvatarT1 = "StaticAvatarT1";
|
|
private const string _StaticAvatarT2 = "StaticAvatarT2";
|
|
private const string _StaticTeam1 = "StaticTeam1";
|
|
private const string _StaticTeam2 = "StaticTeam2";
|
|
|
|
private readonly string[] _EqualizerTeam = new string[]
|
|
{ "EqualizerTeam1", "EqualizerTeam2" };
|
|
|
|
private bool _ExitPopupVisible;
|
|
|
|
private List<CButton> _Fields = new List<CButton>();
|
|
private float _FieldFirstX = 25;
|
|
private float _FieldFirstY = 25;
|
|
private const int _FieldSpace = 10;
|
|
private float _FieldSize = 100;
|
|
|
|
private int idPlayer1 = 0;
|
|
private int idPlayer2 = 0;
|
|
|
|
private static readonly Random random = new Random();
|
|
private static readonly object syncLock = new object();
|
|
|
|
private int _OldSelectedField = -1;
|
|
|
|
private int[,] _Possibilities;
|
|
private EStatus _Status;
|
|
|
|
private const float _FieldWonDuration = 700f;
|
|
private readonly Stopwatch _AnimTimer = new Stopwatch();
|
|
private readonly List<SRectF> _FieldRects = new List<SRectF>();
|
|
private int _AnimatedField = -1;
|
|
private int _WinningLine = -1;
|
|
|
|
public override void Init()
|
|
{
|
|
base.Init();
|
|
|
|
_ThemeTexts = new string[]
|
|
{
|
|
_TextPopupReallyExit, _TextTeamChoosing, _TextFinishMessage, _TextNextPlayerT1, _TextNextPlayerT2, _TextNextPlayerNameT1, _TextNextPlayerNameT2,
|
|
_TextJokerRandomT1, _TextJokerRandomT2, _TextJokerRetryT1, _TextJokerRetryT2
|
|
};
|
|
_ThemeButtons = new string[]
|
|
{
|
|
_ButtonNextRound, _ButtonBack, _ButtonExit, _ButtonPopupYes, _ButtonPopupNo, _ButtonField, _ButtonJokerRandomT1, _ButtonJokerRandomT2, _ButtonJokerRetryT1,
|
|
_ButtonJokerRetryT2, _ButtonSwitchPlayerT1, _ButtonSwitchPlayerT2
|
|
};
|
|
_ThemeStatics = new string[] { _StaticPopupBG, _StaticAvatarT1, _StaticAvatarT2, _StaticTeam1, _StaticTeam2 };
|
|
|
|
var texts = new List<string>();
|
|
texts.AddRange(_EqualizerTeam);
|
|
_ThemeEqualizers = texts.ToArray();
|
|
}
|
|
|
|
public override void LoadTheme(string xmlPath)
|
|
{
|
|
base.LoadTheme(xmlPath);
|
|
|
|
_CreateFields();
|
|
_Buttons[_ButtonField].Visible = false;
|
|
|
|
_Statics[_StaticAvatarT1].Aspect = EAspect.Crop;
|
|
_Statics[_StaticAvatarT2].Aspect = EAspect.Crop;
|
|
}
|
|
|
|
public override bool HandleInput(SKeyEvent keyEvent)
|
|
{
|
|
base.HandleInput(keyEvent);
|
|
|
|
if (keyEvent.KeyPressed) { }
|
|
else
|
|
{
|
|
switch (keyEvent.Key)
|
|
{
|
|
case Keys.Back:
|
|
case Keys.Escape:
|
|
if (!_ExitPopupVisible)
|
|
{
|
|
if (_PartyMode.GameData.CurrentRoundNr == 1 && _Status != EStatus.FieldSelected)
|
|
{
|
|
_Back();
|
|
}
|
|
else if (_Status == EStatus.None)
|
|
{
|
|
_EndParty();
|
|
}
|
|
else
|
|
{
|
|
_ShowPopup(true);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_ShowPopup(false);
|
|
}
|
|
|
|
break;
|
|
|
|
case Keys.Enter:
|
|
if (!_ExitPopupVisible)
|
|
{
|
|
if (_Buttons[_ButtonNextRound].Selected)
|
|
{
|
|
_NextRound();
|
|
}
|
|
|
|
if (_Buttons[_ButtonBack].Selected && _PartyMode.GameData.CurrentRoundNr == 1 && _Status != EStatus.FieldSelected)
|
|
{
|
|
_Back();
|
|
}
|
|
|
|
if (_Buttons[_ButtonExit].Selected && (_PartyMode.GameData.CurrentRoundNr > 1 || _Status == EStatus.FieldSelected) && _Status != EStatus.None)
|
|
{
|
|
_ShowPopup(true);
|
|
}
|
|
else if (_Status == EStatus.None)
|
|
{
|
|
_EndParty();
|
|
}
|
|
|
|
for (var i = 0; i < _PartyMode.GameData.NumFields; i++)
|
|
{
|
|
switch (_Status)
|
|
{
|
|
case EStatus.FieldChoosing:
|
|
if (_Fields[i].Selected)
|
|
{
|
|
_PartyMode.GameData.FieldNr = i;
|
|
_FieldSelected();
|
|
}
|
|
|
|
break;
|
|
|
|
case EStatus.JokerRetry:
|
|
if (_Fields[i].Selected)
|
|
{
|
|
_PartyMode.GameData.FieldNr = i;
|
|
_FieldSelectedAgain();
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (_Status == EStatus.FieldSelected)
|
|
{
|
|
if (_Buttons[_ButtonJokerRandomT1].Selected)
|
|
{
|
|
_UseJoker(0, 0);
|
|
}
|
|
|
|
if (_Buttons[_ButtonJokerRandomT2].Selected)
|
|
{
|
|
_UseJoker(1, 0);
|
|
}
|
|
|
|
if (_Buttons[_ButtonJokerRetryT1].Selected)
|
|
{
|
|
_UseJoker(0, 1);
|
|
}
|
|
|
|
if (_Buttons[_ButtonJokerRetryT2].Selected)
|
|
{
|
|
_UseJoker(1, 1);
|
|
}
|
|
|
|
if (_Buttons[_ButtonSwitchPlayerT1].Selected)
|
|
{
|
|
_ChangePlayer(0, true);
|
|
}
|
|
|
|
if (_Buttons[_ButtonSwitchPlayerT2].Selected)
|
|
{
|
|
_ChangePlayer(1, true);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (_Buttons[_ButtonPopupYes].Selected)
|
|
{
|
|
_EndParty();
|
|
}
|
|
|
|
if (_Buttons[_ButtonPopupNo].Selected)
|
|
{
|
|
_ShowPopup(false);
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public override bool HandleMouse(SMouseEvent mouseEvent)
|
|
{
|
|
base.HandleMouse(mouseEvent);
|
|
|
|
if (mouseEvent.LB && _IsMouseOverCurSelection(mouseEvent))
|
|
{
|
|
if (!_ExitPopupVisible)
|
|
{
|
|
if (_Buttons[_ButtonNextRound].Selected)
|
|
{
|
|
_NextRound();
|
|
}
|
|
|
|
if (_Buttons[_ButtonBack].Selected)
|
|
{
|
|
_Back();
|
|
}
|
|
|
|
if (_Buttons[_ButtonExit].Selected)
|
|
{
|
|
if (_Status == EStatus.None)
|
|
{
|
|
_EndParty();
|
|
}
|
|
else
|
|
{
|
|
_ShowPopup(true);
|
|
}
|
|
}
|
|
|
|
for (var i = 0; i < _PartyMode.GameData.NumFields; i++)
|
|
{
|
|
switch (_Status)
|
|
{
|
|
case EStatus.FieldChoosing:
|
|
if (_Fields[i].Selected)
|
|
{
|
|
_PartyMode.GameData.FieldNr = i;
|
|
_FieldSelected();
|
|
}
|
|
|
|
break;
|
|
|
|
case EStatus.JokerRetry:
|
|
if (_Fields[i].Selected)
|
|
{
|
|
_PartyMode.GameData.FieldNr = i;
|
|
_FieldSelectedAgain();
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (_Status == EStatus.FieldSelected)
|
|
{
|
|
if (_Buttons[_ButtonJokerRandomT1].Selected)
|
|
{
|
|
_UseJoker(0, 0);
|
|
}
|
|
|
|
if (_Buttons[_ButtonJokerRandomT2].Selected)
|
|
{
|
|
_UseJoker(1, 0);
|
|
}
|
|
|
|
if (_Buttons[_ButtonJokerRetryT1].Selected)
|
|
{
|
|
_UseJoker(0, 1);
|
|
}
|
|
|
|
if (_Buttons[_ButtonJokerRetryT2].Selected)
|
|
{
|
|
_UseJoker(1, 1);
|
|
}
|
|
|
|
if (_Buttons[_ButtonSwitchPlayerT1].Selected)
|
|
{
|
|
_ChangePlayer(0, true);
|
|
}
|
|
|
|
if (_Buttons[_ButtonSwitchPlayerT2].Selected)
|
|
{
|
|
_ChangePlayer(1, true);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (_Buttons[_ButtonPopupYes].Selected)
|
|
{
|
|
_EndParty();
|
|
}
|
|
|
|
if (_Buttons[_ButtonPopupNo].Selected)
|
|
{
|
|
_ShowPopup(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (mouseEvent.RB)
|
|
{
|
|
if (!_ExitPopupVisible)
|
|
{
|
|
if (_PartyMode.GameData.CurrentRoundNr == 1 && _Status != EStatus.FieldSelected)
|
|
{
|
|
_Back();
|
|
}
|
|
else if (_Status == EStatus.None)
|
|
{
|
|
_EndParty();
|
|
}
|
|
else
|
|
{
|
|
_ShowPopup(true);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_ShowPopup(false);
|
|
}
|
|
}
|
|
|
|
if (mouseEvent.Wheel != 0) { }
|
|
|
|
return true;
|
|
}
|
|
|
|
public override void OnClose()
|
|
{
|
|
base.OnClose();
|
|
CBase.Record.Stop();
|
|
}
|
|
|
|
public override void OnShow()
|
|
{
|
|
base.OnShow();
|
|
CBase.Record.Start();
|
|
|
|
if (_PartyMode.GameData.CurrentRoundNr == 1)
|
|
{
|
|
_BuildWinnerPossibilities();
|
|
_PartyMode.GameData.FieldNr = -1;
|
|
_Buttons[_ButtonBack].Visible = true;
|
|
_Buttons[_ButtonExit].Visible = false;
|
|
_SelectElement(_Buttons[_ButtonBack]);
|
|
}
|
|
else
|
|
{
|
|
_Buttons[_ButtonBack].Visible = false;
|
|
_Buttons[_ButtonExit].Visible = true;
|
|
_SelectElement(_Buttons[_ButtonExit]);
|
|
}
|
|
|
|
_Status = EStatus.FieldChoosing;
|
|
|
|
_UpdateFields();
|
|
_UpdateFieldContents();
|
|
|
|
_AnimatedField = _PartyMode.GameData.LastWonField;
|
|
_PartyMode.GameData.LastWonField = -1;
|
|
_AnimTimer.Reset();
|
|
_AnimTimer.Start();
|
|
|
|
var winner = _GetWinner();
|
|
_WinningLine = winner > 0 ? _GetWinningLine() : -1;
|
|
_SetJokerLabelsVisible(false);
|
|
if (_PartyMode.GameData.CurrentRoundNr <= _PartyMode.GameData.NumFields && winner == 0)
|
|
{
|
|
_UpdateTeamChoosingMessage();
|
|
_Texts[_TextNextPlayerT1].Visible = false;
|
|
_Texts[_TextNextPlayerT2].Visible = false;
|
|
_Texts[_TextNextPlayerNameT1].Visible = false;
|
|
_Texts[_TextNextPlayerNameT2].Visible = false;
|
|
_Statics[_StaticAvatarT1].Visible = false;
|
|
_Statics[_StaticAvatarT2].Visible = false;
|
|
_Statics[_StaticTeam1].Visible = false;
|
|
_Statics[_StaticTeam2].Visible = false;
|
|
_Equalizers[_EqualizerTeam[0]].Visible = false;
|
|
_Equalizers[_EqualizerTeam[1]].Visible = false;
|
|
_Buttons[_ButtonJokerRandomT1].Visible = false;
|
|
_Buttons[_ButtonJokerRandomT2].Visible = false;
|
|
_Buttons[_ButtonJokerRetryT1].Visible = false;
|
|
_Buttons[_ButtonJokerRetryT2].Visible = false;
|
|
_Buttons[_ButtonSwitchPlayerT1].Visible = false;
|
|
_Buttons[_ButtonSwitchPlayerT2].Visible = false;
|
|
_Buttons[_ButtonNextRound].Visible = false;
|
|
_Texts[_TextFinishMessage].Visible = false;
|
|
}
|
|
else
|
|
{
|
|
_Status = EStatus.None;
|
|
_Buttons[_ButtonNextRound].Visible = false;
|
|
_Texts[_TextFinishMessage].Visible = true;
|
|
_Texts[_TextTeamChoosing].Visible = false;
|
|
if (winner > 0)
|
|
{
|
|
if (_WinningLine >= 0)
|
|
{
|
|
_DimFieldsOutsideWinningLine();
|
|
}
|
|
|
|
_Texts[_TextFinishMessage].Color = CBase.Themes.GetPlayerColor(winner);
|
|
_Texts[_TextFinishMessage].Text = CBase.Language.Translate("TR_SCREENMAIN_WINNER", PartyModeId) + " " + CBase.Language.Translate("TR_TEAM", PartyModeId) + " " +
|
|
winner;
|
|
}
|
|
else
|
|
{
|
|
_Texts[_TextFinishMessage].Color = new SColorF(1, 1, 1, 1);
|
|
_Texts[_TextFinishMessage].Text = CBase.Language.Translate("TR_SCREENMAIN_NOWINNER", PartyModeId);
|
|
}
|
|
|
|
_SelectElement(_Buttons[_ButtonExit]);
|
|
}
|
|
|
|
_ShowPopup(false);
|
|
}
|
|
|
|
public override bool UpdateGame()
|
|
{
|
|
_UpdateFieldAnimations();
|
|
|
|
if (!_Equalizers[_EqualizerTeam[0]].Visible)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
for (var i = 0; i < 2; i++)
|
|
{
|
|
CBase.Record.AnalyzeBuffer(i);
|
|
_Equalizers["EqualizerTeam" + (i + 1)].Update(CBase.Record.ToneWeigth(i), CBase.Record.GetMaxVolume(i));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
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 void _SetFieldScale(int field, float scale)
|
|
{
|
|
var rect = _FieldRects[field];
|
|
var w = rect.W * scale;
|
|
var h = rect.H * scale;
|
|
_Fields[field].X = rect.X + (rect.W - w) / 2;
|
|
_Fields[field].Y = rect.Y + (rect.H - h) / 2;
|
|
_Fields[field].W = w;
|
|
_Fields[field].H = h;
|
|
}
|
|
|
|
private void _UpdateFieldAnimations()
|
|
{
|
|
var time = _AnimTimer.ElapsedMilliseconds;
|
|
|
|
if (_AnimatedField >= 0 && _AnimatedField < _FieldRects.Count)
|
|
{
|
|
var progress = Math.Min(1f, time / _FieldWonDuration);
|
|
_SetFieldScale(_AnimatedField, 1.25f - 0.25f * _EaseOutBack(progress));
|
|
|
|
var teamColor = CBase.Themes.GetPlayerColor(_PartyMode.GameData.Rounds[_AnimatedField].Winner);
|
|
var color = new SColorF(1f + (teamColor.R - 1f) * progress, 1f + (teamColor.G - 1f) * progress, 1f + (teamColor.B - 1f) * progress, teamColor.A);
|
|
_Fields[_AnimatedField].Color = color;
|
|
_Fields[_AnimatedField].SelColor = color;
|
|
|
|
if (progress >= 1f)
|
|
{
|
|
_SetFieldScale(_AnimatedField, 1f);
|
|
_AnimatedField = -1;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if (_WinningLine < 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var pulse = 1f + 0.04f * (float)Math.Sin(time / 1000.0 * Math.PI * 1.4);
|
|
for (var c = 0; c < _Possibilities.GetLength(1); c++)
|
|
{
|
|
_SetFieldScale(_Possibilities[_WinningLine, c], pulse);
|
|
}
|
|
}
|
|
|
|
private void _DimFieldsOutsideWinningLine()
|
|
{
|
|
var inLine = new List<int>();
|
|
for (var c = 0; c < _Possibilities.GetLength(1); c++)
|
|
{
|
|
inLine.Add(_Possibilities[_WinningLine, c]);
|
|
}
|
|
|
|
for (var i = 0; i < _PartyMode.GameData.Rounds.Count; i++)
|
|
{
|
|
if (inLine.Contains(i))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var color = _Fields[i].Color;
|
|
_Fields[i].Color = new SColorF(color.R, color.G, color.B, color.A * 0.35f);
|
|
_Fields[i].SelColor = _Fields[i].Color;
|
|
}
|
|
}
|
|
|
|
private void _SetJokerLabelsVisible(bool visible)
|
|
{
|
|
_Texts[_TextJokerRandomT1].Visible = visible;
|
|
_Texts[_TextJokerRandomT2].Visible = visible;
|
|
_Texts[_TextJokerRetryT1].Visible = visible;
|
|
_Texts[_TextJokerRetryT2].Visible = visible;
|
|
}
|
|
|
|
private void _CreateFields()
|
|
{
|
|
for (var i = 0; i < 25; i++)
|
|
{
|
|
var f = GetNewButton(_Buttons[_ButtonField]);
|
|
f.Visible = false;
|
|
_AddButton(f);
|
|
_Fields.Add(f);
|
|
}
|
|
}
|
|
|
|
private void _UpdateFields()
|
|
{
|
|
var numOneRow = (int)Math.Sqrt(_PartyMode.GameData.NumFields);
|
|
var fieldSizeY = ((float)CBase.Settings.GetRenderH() - 210 - numOneRow * _FieldSpace) / numOneRow;
|
|
var fieldSizeX = ((float)CBase.Settings.GetRenderW() - 300 - numOneRow * _FieldSpace) / numOneRow;
|
|
_FieldSize = Math.Min(fieldSizeX, fieldSizeY);
|
|
_FieldFirstX = (float)CBase.Settings.GetRenderW() / 2 - (numOneRow * _FieldSize + (numOneRow - 1) * _FieldSpace) / 2;
|
|
_FieldFirstY = 200 + (CBase.Settings.GetRenderH() - 200) / 2 - (numOneRow * _FieldSize + numOneRow * _FieldSpace) / 2;
|
|
var row = 0;
|
|
var column = 0;
|
|
var x = _FieldFirstX;
|
|
var y = _FieldFirstY;
|
|
_FieldRects.Clear();
|
|
for (var i = 0; i < _Fields.Count; i++)
|
|
{
|
|
if (i < _PartyMode.GameData.NumFields)
|
|
{
|
|
_Fields[i].W = _FieldSize;
|
|
_Fields[i].H = _FieldSize;
|
|
_Fields[i].X = x;
|
|
_Fields[i].Y = y;
|
|
_Fields[i].Visible = true;
|
|
_Fields[i].Selectable = true;
|
|
_FieldRects.Add(new SRectF(x, y, _FieldSize, _FieldSize, _Fields[i].Rect.Z));
|
|
column++;
|
|
if (i + 1 >= numOneRow * (row + 1))
|
|
{
|
|
column = 0;
|
|
row++;
|
|
y = _FieldFirstY + _FieldSize * row + _FieldSpace * row;
|
|
x = _FieldFirstX;
|
|
}
|
|
else
|
|
{
|
|
x = _FieldFirstX + _FieldSize * column + _FieldSpace * column;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_Fields[i].Visible = false;
|
|
_Fields[i].Selectable = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void _UpdateFieldContents()
|
|
{
|
|
for (var i = 0; i < _PartyMode.GameData.Rounds.Count; i++)
|
|
{
|
|
_Fields[i].Selectable = true;
|
|
_Fields[i].Texture = _Buttons[_ButtonField].Texture;
|
|
_Fields[i].Color = _Buttons[_ButtonField].Color;
|
|
_Fields[i].SelColor = _Buttons[_ButtonField].SelColor;
|
|
if (_PartyMode.GameData.Rounds[i].Finished)
|
|
{
|
|
_Fields[i].Selectable = false;
|
|
_Fields[i].Texture = CBase.Songs.GetSongById(_PartyMode.GameData.Rounds[i].SongIds[0]).CoverTextureBig;
|
|
_Fields[i].Color = CBase.Themes.GetPlayerColor(_PartyMode.GameData.Rounds[i].Winner);
|
|
_Fields[i].SelColor = CBase.Themes.GetPlayerColor(_PartyMode.GameData.Rounds[i].Winner);
|
|
}
|
|
|
|
if (_Status == EStatus.FieldSelected && _PartyMode.GameData.FieldNr == i)
|
|
{
|
|
_Fields[i].Texture = CBase.Songs.GetSongById(_PartyMode.GameData.Rounds[i].SongIds[0]).CoverTextureBig;
|
|
_Fields[i].Color = new SColorF(1, 1, 1, 1);
|
|
_Fields[i].SelColor = new SColorF(1, 1, 1, 1);
|
|
_Fields[i].Selectable = false;
|
|
}
|
|
|
|
if (_Status == EStatus.JokerRetry && _PartyMode.GameData.Rounds[i].Finished)
|
|
{
|
|
_Fields[i].SelColor = CBase.Themes.GetPlayerColor(_PartyMode.GameData.Team + 1);
|
|
_Fields[i].Selectable = true;
|
|
}
|
|
|
|
if (_Status == EStatus.JokerRetry && !_PartyMode.GameData.Rounds[i].Finished)
|
|
{
|
|
_Fields[i].Selectable = false;
|
|
}
|
|
|
|
if (_Status == EStatus.FieldSelected)
|
|
{
|
|
_Fields[i].Selectable = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void _FieldSelected(bool jokerUsed = false)
|
|
{
|
|
if (!jokerUsed)
|
|
{
|
|
_ChangePlayer();
|
|
}
|
|
|
|
_PartyMode.UpdateSongList();
|
|
var songIds = new int[_PartyMode.GameData.GameMode == EGameMode.TR_GAMEMODE_MEDLEY ? _PartyMode.GameData.NumMedleySongs : 1];
|
|
for (var i = 0; i < songIds.Length; i++)
|
|
{
|
|
songIds[i] = _PartyMode.GameData.Songs[0];
|
|
_PartyMode.GameData.Songs.RemoveAt(0);
|
|
}
|
|
|
|
_StartPreview(songIds[0]);
|
|
_Status = EStatus.FieldSelected;
|
|
_PartyMode.GameData.Rounds[_PartyMode.GameData.FieldNr].SongIds = songIds;
|
|
_UpdateFieldContents();
|
|
_UpdateJokerButtons();
|
|
_UpdateSwitchPlayerButtons();
|
|
|
|
_Buttons[_ButtonNextRound].Visible = true;
|
|
_Buttons[_ButtonExit].Visible = true;
|
|
_Buttons[_ButtonBack].Visible = false;
|
|
|
|
_SelectElement(_Buttons[_ButtonNextRound]);
|
|
}
|
|
|
|
private void _FieldSelectedAgain()
|
|
{
|
|
var songIds = _PartyMode.GameData.Rounds[_OldSelectedField].SongIds;
|
|
_StartPreview(songIds[0]);
|
|
_Status = EStatus.FieldSelected;
|
|
_PartyMode.GameData.Rounds[_PartyMode.GameData.FieldNr].SongIds = songIds;
|
|
_PartyMode.GameData.Rounds[_PartyMode.GameData.FieldNr].SingerTeam1 = _PartyMode.GameData.Rounds[_OldSelectedField].SingerTeam1;
|
|
_PartyMode.GameData.Rounds[_PartyMode.GameData.FieldNr].SingerTeam2 = _PartyMode.GameData.Rounds[_OldSelectedField].SingerTeam2;
|
|
_UpdateFieldContents();
|
|
|
|
_UpdatePlayerInformation();
|
|
_UpdateJokerButtons();
|
|
|
|
_Buttons[_ButtonNextRound].Visible = true;
|
|
_Buttons[_ButtonExit].Visible = true;
|
|
_Buttons[_ButtonBack].Visible = false;
|
|
|
|
_SelectElement(_Buttons[_ButtonNextRound]);
|
|
}
|
|
|
|
private void _StartPreview(int songId)
|
|
{
|
|
var song = CBase.Songs.GetSongById(songId);
|
|
CBase.BackgroundMusic.LoadPreview(song);
|
|
}
|
|
|
|
private int _GetRamdom(int max)
|
|
{
|
|
lock (syncLock)
|
|
{
|
|
return random.Next(max + 1);
|
|
}
|
|
}
|
|
|
|
private void _ChangePlayer(int teamNr = -1, bool next = false)
|
|
{
|
|
if (_PartyMode.GameData.ProfileIdsTeam1.Count > 0 && (teamNr == 0 || teamNr == -1))
|
|
{
|
|
idPlayer1 = _GetTeamPlayer(idPlayer1, _PartyMode.GameData.ProfileIdsTeam1.Count, next);
|
|
_PartyMode.GameData.Rounds[_PartyMode.GameData.FieldNr].SingerTeam1 = idPlayer1;
|
|
}
|
|
|
|
if (_PartyMode.GameData.ProfileIdsTeam2.Count > 0 && (teamNr == 1 || teamNr == -1))
|
|
{
|
|
idPlayer2 = _GetTeamPlayer(idPlayer2, _PartyMode.GameData.ProfileIdsTeam2.Count, next);
|
|
_PartyMode.GameData.Rounds[_PartyMode.GameData.FieldNr].SingerTeam2 = idPlayer2;
|
|
}
|
|
|
|
_UpdatePlayerInformation();
|
|
}
|
|
|
|
private int _GetTeamPlayer(int idPlayer, int teamCount, bool next)
|
|
{
|
|
if (next)
|
|
{
|
|
idPlayer++;
|
|
if (idPlayer >= _PartyMode.GameData.ProfileIdsTeam1.Count)
|
|
{
|
|
idPlayer = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
idPlayer = _GetRamdom(_PartyMode.GameData.ProfileIdsTeam1.Count - 1);
|
|
}
|
|
|
|
return idPlayer;
|
|
}
|
|
|
|
private void _UpdatePlayerInformation()
|
|
{
|
|
_Texts[_TextNextPlayerT1].Visible = true;
|
|
_Texts[_TextNextPlayerT2].Visible = true;
|
|
_Texts[_TextNextPlayerNameT1].Visible = true;
|
|
_Texts[_TextNextPlayerNameT2].Visible = true;
|
|
_Texts[_TextNextPlayerNameT1].Text =
|
|
CBase.Profiles.GetPlayerName(_PartyMode.GameData.ProfileIdsTeam1[_PartyMode.GameData.Rounds[_PartyMode.GameData.FieldNr].SingerTeam1]);
|
|
_Texts[_TextNextPlayerNameT2].Text =
|
|
CBase.Profiles.GetPlayerName(_PartyMode.GameData.ProfileIdsTeam2[_PartyMode.GameData.Rounds[_PartyMode.GameData.FieldNr].SingerTeam2]);
|
|
_Statics[_StaticAvatarT1].Visible = true;
|
|
_Statics[_StaticAvatarT2].Visible = true;
|
|
_Statics[_StaticAvatarT1].Texture = CBase.Profiles.GetAvatar(_PartyMode.GameData.ProfileIdsTeam1[_PartyMode.GameData.Rounds[_PartyMode.GameData.FieldNr].SingerTeam1]);
|
|
_Statics[_StaticAvatarT2].Texture = CBase.Profiles.GetAvatar(_PartyMode.GameData.ProfileIdsTeam2[_PartyMode.GameData.Rounds[_PartyMode.GameData.FieldNr].SingerTeam2]);
|
|
_Statics[_StaticTeam1].Visible = true;
|
|
_Statics[_StaticTeam2].Visible = true;
|
|
_Equalizers[_EqualizerTeam[0]].Visible = true;
|
|
_Equalizers[_EqualizerTeam[1]].Visible = true;
|
|
}
|
|
|
|
private void _UseJoker(int teamNr, int jokerNum)
|
|
{
|
|
switch (jokerNum)
|
|
{
|
|
//Random-Joker
|
|
case 0:
|
|
if (_PartyMode.GameData.NumJokerRandom[teamNr] > 0)
|
|
{
|
|
_PartyMode.GameData.NumJokerRandom[teamNr]--;
|
|
_FieldSelected(true);
|
|
}
|
|
|
|
break;
|
|
|
|
//Retry-Joker
|
|
case 1:
|
|
if (_PartyMode.GameData.NumJokerRetry[teamNr] > 0 && _PartyMode.GameData.CurrentRoundNr > 1)
|
|
{
|
|
_PartyMode.GameData.NumJokerRetry[teamNr]--;
|
|
_PartyMode.GameData.Team = teamNr;
|
|
_Status = EStatus.JokerRetry;
|
|
_OldSelectedField = _PartyMode.GameData.FieldNr;
|
|
_PartyMode.GameData.FieldNr = -1;
|
|
_UpdateFieldContents();
|
|
_Buttons[_ButtonNextRound].Visible = false;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
_UpdateJokerButtons();
|
|
}
|
|
|
|
private void _UpdateTeamChoosingMessage()
|
|
{
|
|
_Texts[_TextTeamChoosing].Color = CBase.Themes.GetPlayerColor(_PartyMode.GameData.Team + 1);
|
|
_Texts[_TextTeamChoosing].Text = CBase.Language.Translate("TR_TEAM", PartyModeId) + " " + (_PartyMode.GameData.Team + 1) + "! " +
|
|
CBase.Language.Translate("TR_SCREENMAIN_TEAM_CHOOSE", PartyModeId);
|
|
if (_Status == EStatus.JokerRetry || _Status == EStatus.FieldChoosing)
|
|
{
|
|
_Texts[_TextTeamChoosing].Visible = true;
|
|
}
|
|
else
|
|
{
|
|
_Texts[_TextTeamChoosing].Visible = false;
|
|
}
|
|
}
|
|
|
|
private void _UpdateJokerButtons()
|
|
{
|
|
_Buttons[_ButtonJokerRandomT1].Visible = true;
|
|
_Buttons[_ButtonJokerRandomT2].Visible = true;
|
|
_Buttons[_ButtonJokerRandomT1].Text.Text = _PartyMode.GameData.NumJokerRandom[0].ToString();
|
|
_Buttons[_ButtonJokerRandomT2].Text.Text = _PartyMode.GameData.NumJokerRandom[1].ToString();
|
|
_Buttons[_ButtonJokerRandomT1].Selectable = _PartyMode.GameData.NumJokerRandom[0] > 0;
|
|
_Buttons[_ButtonJokerRandomT2].Selectable = _PartyMode.GameData.NumJokerRandom[1] > 0;
|
|
_Buttons[_ButtonJokerRetryT1].Visible = true;
|
|
_Buttons[_ButtonJokerRetryT2].Visible = true;
|
|
_SetJokerLabelsVisible(true);
|
|
_Buttons[_ButtonJokerRetryT1].Text.Text = _PartyMode.GameData.NumJokerRetry[0].ToString();
|
|
_Buttons[_ButtonJokerRetryT2].Text.Text = _PartyMode.GameData.NumJokerRetry[1].ToString();
|
|
_Buttons[_ButtonJokerRetryT1].Selectable = _PartyMode.GameData.NumJokerRetry[0] > 0 && _PartyMode.GameData.CurrentRoundNr > 1;
|
|
_Buttons[_ButtonJokerRetryT2].Selectable = _PartyMode.GameData.NumJokerRetry[1] > 0 && _PartyMode.GameData.CurrentRoundNr > 1;
|
|
}
|
|
|
|
private void _UpdateSwitchPlayerButtons()
|
|
{
|
|
if (_PartyMode.GameData.SwitchPlayer == EOffOn.TR_CONFIG_ON)
|
|
{
|
|
_Buttons[_ButtonSwitchPlayerT1].Visible = true;
|
|
_Buttons[_ButtonSwitchPlayerT2].Visible = true;
|
|
}
|
|
}
|
|
|
|
private void _NextRound()
|
|
{
|
|
_PartyMode.Next();
|
|
}
|
|
|
|
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 _Back()
|
|
{
|
|
_PartyMode.Back();
|
|
}
|
|
|
|
private void _BuildWinnerPossibilities()
|
|
{
|
|
var numOneRow = (int)Math.Sqrt(_PartyMode.GameData.NumFields);
|
|
_Possibilities = new int[numOneRow * 2 + 2, numOneRow];
|
|
for (var i = 0; i < _Possibilities.GetLength(0); i++)
|
|
{
|
|
if (i < numOneRow)
|
|
{
|
|
for (var c = 0; c < numOneRow; c++)
|
|
{
|
|
_Possibilities[i, c] = i * numOneRow + c;
|
|
}
|
|
}
|
|
else if (i < numOneRow * 2)
|
|
{
|
|
for (var c = 0; c < numOneRow; c++)
|
|
{
|
|
_Possibilities[i, c] = i - numOneRow + c * numOneRow;
|
|
}
|
|
}
|
|
else if (i == _Possibilities.GetLength(0) - 2)
|
|
{
|
|
for (var c = 0; c < numOneRow; c++)
|
|
{
|
|
_Possibilities[i, c] = (numOneRow + 1) * c;
|
|
}
|
|
}
|
|
else if (i == _Possibilities.GetLength(0) - 1)
|
|
{
|
|
for (var c = 0; c < numOneRow; c++)
|
|
{
|
|
_Possibilities[i, c] = (numOneRow - 1) * c + (numOneRow - 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private int _GetWinningLine()
|
|
{
|
|
var winner = _GetWinner();
|
|
for (var i = 0; i < _Possibilities.GetLength(0); i++)
|
|
{
|
|
var complete = true;
|
|
for (var j = 0; j < _Possibilities.GetLength(1); j++)
|
|
{
|
|
if (_PartyMode.GameData.Rounds[_Possibilities[i, j]].Winner != winner)
|
|
{
|
|
complete = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (complete)
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
private int _GetWinner()
|
|
{
|
|
for (var i = 0; i < _Possibilities.GetLength(0); i++)
|
|
{
|
|
var check = new List<int>();
|
|
for (var j = 0; j < _Possibilities.GetLength(1); j++)
|
|
{
|
|
if (_PartyMode.GameData.Rounds[_Possibilities[i, j]].Winner > 0)
|
|
{
|
|
check.Add(_PartyMode.GameData.Rounds[_Possibilities[i, j]].Winner);
|
|
}
|
|
}
|
|
|
|
if (check.Count != _Possibilities.GetLength(1))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//Check for winner
|
|
if (check.Contains(1) && !check.Contains(2))
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
if (check.Contains(2) && !check.Contains(1))
|
|
{
|
|
return 2;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
} |