489 lines
11 KiB
C#

using UdonSharp;
using UnityEngine;
using VRC.SDK3.Data;
using VRC.SDK3.UdonNetworkCalling;
using VRC.SDKBase;
using VRC.Udon.Common.Interfaces;
public enum ContinentMap
{
Africa,
Asia,
Europe,
NorthAmerica,
Oceania,
SouthAmerica,
INDEX_MAX
}
public enum GameStatus
{
Pregame,
Begin,
RanOutOfTime,
RanOutOfMarkers,
Win
}
[UdonBehaviourSyncMode(BehaviourSyncMode.Manual)]
public class GameManagerRound3 : GameManagerBase
{
[Space]
[SerializeField] private FloorMap[] _Maps;
[SerializeField] private FloorMapMarker[] _Markers;
[SerializeField] private RandomVideoPlayer _EndingPlayer;
[UdonSynced, FieldChangeCallback(nameof(CurrentlyActiveMap))] private ContinentMap _CurrentlyActiveMap = ContinentMap.INDEX_MAX;
[UdonSynced, FieldChangeCallback(nameof(ActiveMarker))] private int _ActiveMarker = 0;
[UdonSynced] private int _StageIndex = 0;
private DataDictionary _ContinentData;
[UdonSynced] private GameStatus _GameStatus = GameStatus.Pregame;
[UdonSynced] private bool _RunTimer = false;
[UdonSynced] private int _Timer = TIMER_LENGTH;
private const float LENGTH_OF_ONE_SECOND = 1.022222222222222222222f;
private const int TIMER_LENGTH = 45;
[UdonSynced, FieldChangeCallback(nameof(SuccessCounter))] private int _SuccessCounter = 0;
[UdonSynced, FieldChangeCallback(nameof(FailureCounter))] private int _FailureCounter = 0;
private const int MAX_SUCCESS_COUNT = 8;
private const int MAX_FAILURE_COUNT = 2;
public override void InitialiseGameMode()
{
base.InitialiseGameMode();
_StageIndex = 0;
SuccessCounter = 0;
FailureCounter = 0;
_Timer = TIMER_LENGTH;
_RunTimer = false;
InitialiseMarkers();
GetCurrentMap().RandomiseCountries();
EnableAudienceSilencer(false);
RequestSerialization();
}
public override void DeinitialiseGameMode()
{
_EndingPlayer.PlayVideo = false;
base.DeinitialiseGameMode();
}
public override void SetOwnershipOfObjects(VRCPlayerApi NewOwner)
{
for (int i = 0; i < _Maps.Length; i++)
Networking.SetOwner(NewOwner, _Maps[i].gameObject);
for (int i = 0; i < _Markers.Length; i++)
Networking.SetOwner(NewOwner, _Markers[i].gameObject);
Networking.SetOwner(NewOwner, _EndingPlayer.gameObject);
base.SetOwnershipOfObjects(NewOwner);
}
private void InitialiseMarkers()
{
for (int i = 0; i < _Markers.Length; i++)
{
Networking.SetOwner(Networking.GetOwner(gameObject), _Markers[i].gameObject);
_Markers[i].SendCustomNetworkEvent(NetworkEventTarget.All, "Initialise");
}
_ActiveMarker = 0;
GetCurrentMarker().SendCustomNetworkEvent(NetworkEventTarget.All, "SetPickupable", true);
}
public override void LoadQuestionData(DataToken Data)
{
_ContinentData = Data.DataDictionary;
if (_ContinentData.ContainsKey("Continent"))
{
CurrentlyActiveMap = (ContinentMap)(int)_ContinentData["Continent"].Number;
RequestSerialization();
}
else
{
Debug.LogError("Malformed round data. Ensure Round 3 contains a continent to use for the map.");
}
InitialiseMarkers();
EnableInteraction("Display Briefing");
}
private void ActivateMap()
{
for (int i = 0; i < _Maps.Length; i++)
{
FloorMap Map = _Maps[i];
if (Map != null)
{
Map.Activate = false;
}
}
FloorMap CurrentMap = _Maps[(int)CurrentlyActiveMap];
if (CurrentMap != null)
{
CurrentMap.Activate = true;
}
}
private void DisplayBriefing()
{
HostCardCaptureCarmenExplainerInterface CaptureCarmenExplainerInterface =
(HostCardCaptureCarmenExplainerInterface)GetHostCardInterface(RoundSegmentType.CaptureCarmenExplainer);
CaptureCarmenExplainerInterface.HeaderUI.text = RoundSegmentTypeToString(RoundSegmentType.CaptureCarmenExplainer);
_AudioManager.SendCustomNetworkEvent(NetworkEventTarget.All, "FadeOutMusic");
EnableInteraction("Begin");
}
public void BeginRound()
{
GetCurrentMarker().SendCustomNetworkEvent(NetworkEventTarget.Owner, "Activated", true);
UpdateInterface();
_EndingPlayer.LoadRandomVideo();
StartTimer();
}
private void StartTimer()
{
_AudioManager.SendCustomNetworkEvent(NetworkEventTarget.All,
"PlayMusicLoop", MusicEventType.CarmenChaseMusic);
_GameStatus = GameStatus.Begin;
_Timer = TIMER_LENGTH;
SendCustomNetworkEvent(NetworkEventTarget.Owner, nameof(BeginTimerTick));
RequestSerialization();
}
[NetworkCallable]
public void BeginTimerTick()
{
_RunTimer = true;
SendCustomEventDelayedSeconds(nameof(TickTimer), LENGTH_OF_ONE_SECOND);
}
public void TickTimer()
{
if (!_RunTimer) return;
_Timer--;
if (_Timer < 0)
{
SendCustomNetworkEvent(NetworkEventTarget.Owner, nameof(GameHasBeenLost), false);
return;
}
BeginTimerTick();
RequestSerialization();
}
[NetworkCallable]
public void CorrectResponse()
{
PlayCorrectSound();
SuccessCounter++;
if (SuccessCounter >= MAX_SUCCESS_COUNT)
{
GameHasBeenWon();
}
else
{
SetUpNextCountry();
}
RequestSerialization();
}
[NetworkCallable]
public void IncorrectResponse()
{
PlayIncorrectSound();
FailureCounter++;
if (FailureCounter >= MAX_FAILURE_COUNT)
{
SetUpNextCountry();
}
RequestSerialization();
}
public FloorMap GetCurrentMap()
{
return _Maps[(int)CurrentlyActiveMap];
}
public FloorMapMarker GetCurrentMarker()
{
return _Markers[ActiveMarker];
}
public string GetCurrentCountry()
{
return GetCurrentMap().GetCountry(ActiveMarker);
}
public string GetCurrentRegion()
{
return GetCurrentMap().GetRegion(ActiveMarker);
}
public string GetCurrentCity()
{
return GetCurrentMap().GetCity(ActiveMarker);
}
public void SetUpNextCountry()
{
GetCurrentMarker().SendCustomNetworkEvent(NetworkEventTarget.All, "Activated", false);
FailureCounter = 0;
ActiveMarker++;
RequestSerialization();
}
private void ActivateMarker()
{
if (ActiveMarker >= FloorMap.MAX_SELECTED_COUNTRIES)
{
// If we ran out of countries, lose the game here.
SendCustomNetworkEvent(NetworkEventTarget.Owner, nameof(GameHasBeenLost), true);
return;
}
UpdateInterface();
GetCurrentMarker().SendCustomNetworkEvent(NetworkEventTarget.Owner, "Activated", true);
}
[NetworkCallable]
public void GameHasBeenWon()
{
_RunTimer = false;
if ((int)_GameStatus <= (int)GameStatus.Begin)
{
GameStatusUpdate(GameStatus.Win);
HostCardBetweenRoundsInterface GameWinInterface =
(HostCardBetweenRoundsInterface)GetHostCardInterface(RoundSegmentType.BetweenSegments);
GameWinInterface.HeaderUI.text = "The player has won the game.";
GameWinInterface.CommentUI.text =
"- " + _Timer + " seconds to spare.\n" +
"- There's one more thing I want you to do for us. You know what it is...";
_AudioManager.SendCustomNetworkEvent(NetworkEventTarget.All,
"PlaySFXLoop", SFXEventType.CarmenInJail);
_AudioManager.SendCustomNetworkEvent(NetworkEventTarget.All, "FadeOutMusic");
SendCustomEventDelayedSeconds(nameof(PlayWindDownMusic), 5.0f);
SendCustomEventDelayedSeconds(nameof(EndCarmenInJailSFX), 7.0f);
}
}
public void PlayWindDownMusic()
{
_AudioManager.SendCustomNetworkEvent(NetworkEventTarget.All,
"PlayMusicLoop", MusicEventType.CarmenSandiegoWindDown);
EnableInteraction("Do It, Rockapella!");
}
public void EndCarmenInJailSFX()
{
_AudioManager.SendCustomNetworkEvent(NetworkEventTarget.All, "StopSFX");
}
[NetworkCallable]
public void GameHasBeenLost(bool RanOutOfMarkers)
{
_RunTimer = false;
if (_GameStatus != GameStatus.Win)
{
GameStatusUpdate(RanOutOfMarkers ? GameStatus.RanOutOfMarkers : GameStatus.RanOutOfTime);
HostCardBetweenRoundsInterface GameLossInterface =
(HostCardBetweenRoundsInterface)GetHostCardInterface(RoundSegmentType.BetweenSegments);
GameLossInterface.HeaderUI.text = "The player has run out of " + (RanOutOfMarkers ? "markers" : "time") + ".";
GameLossInterface.CommentUI.text =
"- Found " + SuccessCounter + " countries in " + TIMER_LENGTH + " seconds.\n\n" +
"- There's one more thing I want you to do for us. You know what it is...";
_AudioManager.SendCustomNetworkEvent(NetworkEventTarget.All, "StopMusic");
SendCustomEventDelayedSeconds(nameof(PlayWindDownMusic), 2.5f);
}
}
private void DoItRockapella()
{
HostCardBetweenRoundsInterface Interface =
(HostCardBetweenRoundsInterface)GetHostCardInterface(RoundSegmentType.BetweenSegments);
Interface.HeaderUI.text = "Rockin' it a capella";
Interface.CommentUI.text = "";
_AudioManager.SendCustomNetworkEvent(NetworkEventTarget.All, "FadeOutMusic");
SendCustomEventDelayedSeconds(nameof(PlayEndingTheme), 1.25f);
EnableInteraction("End Game");
}
public void PlayEndingTheme()
{
_AudioManager.SendCustomNetworkEvent(NetworkEventTarget.All,
"PlayMusicLoop", MusicEventType.CarmenSandiegoTheme);
_EndingPlayer.PlayVideo = true;
}
private void EndGame()
{
HostCardBetweenRoundsInterface Interface =
(HostCardBetweenRoundsInterface)GetHostCardInterface(RoundSegmentType.BetweenSegments);
Interface.HeaderUI.text = "Game is over. Load a new case file to start again.";
Interface.CommentUI.text = "";
_AudioManager.SendCustomNetworkEvent(NetworkEventTarget.All, "FadeOutMusic");
DisableInteraction("Game Over");
}
public void PlayCorrectSound()
{
_AudioManager.SendCustomNetworkEvent(NetworkEventTarget.All,
"PlaySFX", SFXEventType.MapCorrect);
}
public void PlayIncorrectSound()
{
_AudioManager.SendCustomNetworkEvent(NetworkEventTarget.All,
"PlaySFX", SFXEventType.MapIncorrect);
}
private void GameStatusUpdate(GameStatus NewStatus)
{
if ((int)_GameStatus <= (int)GameStatus.Begin)
{
_GameStatus = NewStatus;
}
RequestSerialization();
}
private void UpdateInterface()
{
HostCardCaptureCarmenInterface CaptureCarmenInterface =
(HostCardCaptureCarmenInterface)GetHostCardInterface(RoundSegmentType.CaptureCarmen);
CaptureCarmenInterface.HeaderUI.text = RoundSegmentTypeToString(RoundSegmentType.CaptureCarmen);
string City = GetCurrentCity();
string Region = GetCurrentRegion();
string Country = GetCurrentCountry();
if (Region == "" || Region.Contains(City) || Region == Country)
{
Region = "";
}
else
{
Region += ", ";
}
CaptureCarmenInterface.CommentUI.text = City + ", " + Region + Country;
}
protected override HostCardInterfaceBase GetHostCardInterface(RoundSegmentType Question)
{
return _HostCard.EnableHostCardDisplay(RoundType.CaptureCarmen, Question);
}
protected override void _HostCardUseButtonDown_Internal()
{
DisableInteraction();
_StageIndex++;
switch (_StageIndex)
{
case 1: DisplayBriefing(); break;
case 2: BeginRound(); break;
case 3: DoItRockapella(); break;
case 4: EndGame(); break;
}
}
public ContinentMap CurrentlyActiveMap
{
set
{
_CurrentlyActiveMap = value;
ActivateMap();
}
get => _CurrentlyActiveMap;
}
public int ActiveMarker
{
set
{
_ActiveMarker = value;
ActivateMarker();
}
get => _ActiveMarker;
}
private int SuccessCounter
{
set
{
_SuccessCounter = value;
}
get => _SuccessCounter;
}
private int FailureCounter
{
set
{
_FailureCounter = value;
}
get => _FailureCounter;
}
}