394 lines
9.6 KiB
C#

using UdonSharp;
using UnityEngine;
using VRC.SDK3.Data;
using VRC.SDK3.UdonNetworkCalling;
using VRC.SDKBase;
using VRC.Udon.Common;
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
{
[SerializeField] private CaseManager _CaseManager;
[SerializeField] private FloorMap[] _Maps;
[SerializeField] private FloorMapMarker[] _Markers;
[SerializeField] private AudioManager _AudioManager;
[UdonSynced, FieldChangeCallback(nameof(CurrentlyActiveMap))] private ContinentMap _CurrentlyActiveMap = ContinentMap.INDEX_MAX;
[UdonSynced] private int _StageIndex = 0;
private DataDictionary _ContinentData;
[UdonSynced] private GameStatus _GameStatus = GameStatus.Pregame;
[UdonSynced] private int _Timer = TIMER_LENGTH;
private const float LENGTH_OF_ONE_SECOND = 1.022222222222222222222f;
private const int TIMER_LENGTH = 45;
[UdonSynced] private int _SuccessCounter = 0;
[UdonSynced] private int _FailureCounter = 0;
private const int MAX_FAILURE_COUNT = 2;
private const int MAX_SUCCESS_COUNT = 8;
public override void InitialiseGameMode()
{
_StageIndex = 0;
_SuccessCounter = 0;
_FailureCounter = 0;
_Timer = TIMER_LENGTH;
// We'll need to reset the markers here, too.
RequestSerialization();
base.InitialiseGameMode();
}
public override void LoadQuestionData(DataToken Data)
{
_ContinentData = Data.DataDictionary;
if (_ContinentData.ContainsKey("Continent"))
{
CurrentlyActiveMap = (ContinentMap)(int)_ContinentData["Continent"].Number;
RequestSerialization();
SendCustomEventDelayedSeconds(nameof(GenerateRandomMapLocations), 1.0f);
}
else
{
Debug.LogError("Malformed round data. Ensure Round 3 contains a continent to use for the map.");
}
EnableInteraction("Display Briefing");
}
public void GenerateRandomMapLocations()
{
FloorMap Map = GetCurrentMap();
Map.RandomiseCountries();
}
private void ActivateMap()
{
for (int i = 0; i < _Maps.Length; i++)
{
FloorMap Map = _Maps[i];
if (Map != null)
{
Map.gameObject.SetActive(false);
}
}
FloorMap CurrentMap = _Maps[(int)CurrentlyActiveMap];
if (CurrentMap != null)
{
CurrentMap.gameObject.SetActive(true);
}
}
private void DisplayBriefing()
{
HostCardCaptureCarmenExplainerInterface CaptureCarmenExplainerInterface =
(HostCardCaptureCarmenExplainerInterface)GetHostCardInterface(RoundSegmentType.CaptureCarmenExplainer);
CaptureCarmenExplainerInterface.HeaderUI.text = RoundSegmentTypeToString(RoundSegmentType.CaptureCarmenExplainer);
EnableInteraction("Begin");
}
public void BeginRound()
{
NetworkCalling.SendCustomNetworkEvent(
(IUdonEventReceiver)GetCurrentMarker(),
NetworkEventTarget.Owner,
"Activated", true);
UpdateInterface();
StartTimer();
}
private void StartTimer()
{
NetworkCalling.SendCustomNetworkEvent((IUdonEventReceiver)_AudioManager, NetworkEventTarget.All,
"PlayMusicLoop", MusicEventType.CarmenChaseMusic);
_GameStatus = GameStatus.Begin;
_Timer = TIMER_LENGTH;
SendCustomEventDelayedSeconds(nameof(TickTimer), LENGTH_OF_ONE_SECOND);
RequestSerialization();
}
public void TickTimer()
{
_Timer--;
if (_Timer < 0)
{
NetworkCalling.SendCustomNetworkEvent((IUdonEventReceiver)this, NetworkEventTarget.Owner,
nameof(GameHasBeenLost), false);
return;
}
SendCustomEventDelayedSeconds(nameof(TickTimer), LENGTH_OF_ONE_SECOND);
RequestSerialization();
}
public void CorrectResponse()
{
PlayCorrectSound();
NetworkCalling.SendCustomNetworkEvent(
(IUdonEventReceiver)GetCurrentMarker(),
NetworkEventTarget.Owner,
"Activated", false);
_FailureCounter = 0;
_SuccessCounter++;
if (_SuccessCounter >= MAX_SUCCESS_COUNT)
{
NetworkCalling.SendCustomNetworkEvent((IUdonEventReceiver)this, NetworkEventTarget.Owner,
nameof(GameHasBeenWon));
}
else
{
SetUpNextCountry();
}
RequestSerialization();
}
public void IncorrectResponse()
{
_FailureCounter++;
if (_FailureCounter >= MAX_FAILURE_COUNT)
{
_FailureCounter = 0;
NetworkCalling.SendCustomNetworkEvent(
(IUdonEventReceiver)GetCurrentMarker(),
NetworkEventTarget.Owner,
"Activated", false);
SetUpNextCountry();
}
PlayIncorrectSound();
}
public FloorMap GetCurrentMap()
{
return _Maps[(int)CurrentlyActiveMap];
}
public FloorMapMarker GetCurrentMarker()
{
return _Markers[GetCurrentMap().GetCurrentCountryIndex()];
}
public string GetCurrentCountry()
{
return GetCurrentMap().GetCurrentCountry();
}
public string GetCurrentCity()
{
return GetCurrentMap().GetCurrentCity();
}
public void SetUpNextCountry()
{
int NextCountry = GetCurrentMap().NextCountry();
if (NextCountry < 0)
{
// If we ran out of countries, lose the game here.
NetworkCalling.SendCustomNetworkEvent((IUdonEventReceiver)this, NetworkEventTarget.Owner,
nameof(GameHasBeenLost), true);
return;
}
NetworkCalling.SendCustomNetworkEvent(
(IUdonEventReceiver)GetCurrentMarker(),
NetworkEventTarget.Owner,
"Activated", true);
UpdateInterface();
}
[NetworkCallable]
public void GameHasBeenWon()
{
if ((int)_GameStatus <= (int)GameStatus.Begin)
{
GameStatusUpdate(GameStatus.Win);
HostCardBetweenRoundsInterface GameWinInterface =
(HostCardBetweenRoundsInterface)GetHostCardInterface(RoundSegmentType.BetweenSegments);
GameWinInterface.HeaderUI.text = "The player has won the game. " + _Timer + " seconds to spare.";
NetworkCalling.SendCustomNetworkEvent((IUdonEventReceiver)_AudioManager, NetworkEventTarget.All,
"PlaySFXLoop", SFXEventType.CarmenInJail);
SendCustomEventDelayedSeconds(nameof(StopFinalRoundMusic), 1.0f);
SendCustomEventDelayedSeconds(nameof(PlayWindDownMusic), 5.0f);
SendCustomEventDelayedSeconds(nameof(EndCarmenInJailSFX), 7.0f);
}
}
public void StopFinalRoundMusic()
{
NetworkCalling.SendCustomNetworkEvent((IUdonEventReceiver)_AudioManager, NetworkEventTarget.All, "StopMusic");
}
public void PlayWindDownMusic()
{
NetworkCalling.SendCustomNetworkEvent((IUdonEventReceiver)_AudioManager, NetworkEventTarget.All,
"PlayMusicLoop", MusicEventType.CarmenSandiegoWindDown);
EnableInteraction("Do It, Rockapella!");
}
public void EndCarmenInJailSFX()
{
NetworkCalling.SendCustomNetworkEvent((IUdonEventReceiver)_AudioManager, NetworkEventTarget.All, "StopSFX");
}
[NetworkCallable]
public void GameHasBeenLost(bool RanOutOfMarkers)
{
if ((int)_GameStatus != (int)GameStatus.Win)
{
for (int i = 0; i < _Markers.Length; i++)
{
NetworkCalling.SendCustomNetworkEvent(
(IUdonEventReceiver)_Markers[i],
NetworkEventTarget.Owner,
"Activated", false);
}
GameStatusUpdate(RanOutOfMarkers ? GameStatus.RanOutOfMarkers : GameStatus.RanOutOfTime);
HostCardBetweenRoundsInterface GameLossInterface =
(HostCardBetweenRoundsInterface)GetHostCardInterface(RoundSegmentType.BetweenSegments);
GameLossInterface.HeaderUI.text = "The player has lost. " + _SuccessCounter + " countries in " + TIMER_LENGTH + " seconds.";
StopFinalRoundMusic();
SendCustomEventDelayedSeconds(nameof(PlayWindDownMusic), 2.5f);
}
}
private void DoItRockapella()
{
HostCardBetweenRoundsInterface Interface =
(HostCardBetweenRoundsInterface)GetHostCardInterface(RoundSegmentType.BetweenSegments);
Interface.HeaderUI.text = "Rockin' it acapella";
NetworkCalling.SendCustomNetworkEvent((IUdonEventReceiver)_AudioManager, NetworkEventTarget.All,
"PlayMusicLoop", MusicEventType.CarmenSandiegoTheme);
EnableInteraction("End Game");
}
private void EndGame()
{
HostCardBetweenRoundsInterface Interface =
(HostCardBetweenRoundsInterface)GetHostCardInterface(RoundSegmentType.BetweenSegments);
Interface.HeaderUI.text = "Game is over. Load a new case file to start again.";
NetworkCalling.SendCustomNetworkEvent((IUdonEventReceiver)_AudioManager, NetworkEventTarget.All, "StopMusic");
EnableInteraction("Game is over. Load a new case file to start again.");
}
private void GameStatusUpdate(GameStatus NewStatus)
{
if ((int)_GameStatus <= (int)GameStatus.Begin)
{
_GameStatus = NewStatus;
}
RequestSerialization();
}
public void PlayCorrectSound()
{
NetworkCalling.SendCustomNetworkEvent((IUdonEventReceiver)_AudioManager, NetworkEventTarget.All,
"PlaySFX", SFXEventType.MapCorrect);
}
public void PlayIncorrectSound()
{
NetworkCalling.SendCustomNetworkEvent((IUdonEventReceiver)_AudioManager, NetworkEventTarget.All,
"PlaySFX", SFXEventType.MapIncorrect);
}
private void UpdateInterface()
{
HostCardCaptureCarmenInterface CaptureCarmenInterface =
(HostCardCaptureCarmenInterface)GetHostCardInterface(RoundSegmentType.CaptureCarmen);
CaptureCarmenInterface.HeaderUI.text = RoundSegmentTypeToString(RoundSegmentType.CaptureCarmen);
CaptureCarmenInterface.CommentUI.text = GetCurrentCity() + ", " + GetCurrentCountry();
}
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;
}
}