Jamie Greunbaum e042d089a5 - Choice cards are synced across the network, and receive data from the host.
- KNOWN ISSUE: Cards don't randomise correctly across the network.
2025-05-30 04:32:25 -04:00

295 lines
7.4 KiB
C#

using UdonSharp;
using UnityEngine;
using UnityEngine.UI;
using VRC.SDK3.Data;
using VRC.SDK3.UdonNetworkCalling;
using VRC.Udon.Common.Interfaces;
using VRC.SDKBase;
using System.Linq;
using VRC.SDK3.StringLoading;
using System.Runtime.CompilerServices;
using TMPro;
public enum QuestionType
{
None,
MultipleChoice,
LightningRound,
TheChase,
FinalRound,
Tiebreaker
}
public enum MusicEventType
{
None,
WhereInTheWorld,
RockapellaIdent
}
public enum SFXEventType
{
None,
Buzzer
}
[UdonBehaviourSyncMode(BehaviourSyncMode.Manual)]
public class GameManager : UdonSharpBehaviour
{
[SerializeField] private GameObject _AdminPanel;
[UdonSynced] private bool BuzzInAllowed = false;
[UdonSynced] private bool[] PlayerBuzzInAllowed;
[UdonSynced] private int _BuzzedInPlayer = -1;
private DataDictionary _CurrentQuestion;
[UdonSynced] private QuestionType _CurrentQuestionType = QuestionType.MultipleChoice;
[UdonSynced] private int _CurrentQuestionStage = 0;
[UdonSynced] private int _CurrentQuestionCorrectResponse = -1;
public PlayerPodium[] PlayerPodiums;
[UdonSynced] public VRCUrl QuestionURL;
[Header("Multiple Choice Card UI")]
[SerializeField] private TextMeshProUGUI _InfoHeader;
[SerializeField] private TextMeshProUGUI[] _InfoClues;
[SerializeField] private TextMeshProUGUI[] _InfoChoices;
[SerializeField] private Image[] _InfoChoiceButtons;
[SerializeField] private TextMeshProUGUI _Answer;
[Header("Audio")]
[SerializeField] private AudioClip BuzzerSound = null;
[SerializeField] private AudioClip WhereInTheWorld = null;
[SerializeField] private AudioClip RockapellaIdent = null;
[SerializeField] private AudioSource MusicPlayer = null;
[SerializeField] private AudioSource SFXPlayer = null;
void Start()
{
PlayerBuzzInAllowed = new bool[PlayerPodiums.Length];
ResetBuzzers();
// Download our test question.
VRCStringDownloader.LoadUrl(QuestionURL, (IUdonEventReceiver)this);
}
public override void OnStringLoadSuccess(IVRCStringDownload DownloadedString)
{
string JSONString = DownloadedString.Result;
if (VRCJson.TryDeserializeFromJson(JSONString, out DataToken JSONResult))
{
if (JSONResult.TokenType == TokenType.DataDictionary)
{
NetworkCalling.SendCustomNetworkEvent((IUdonEventReceiver)this, NetworkEventTarget.All, nameof(UpdateInfoCard), JSONString);
}
}
else
{
Debug.LogError("The question should be a Dictionary type.");
}
}
[NetworkCallable]
public void UpdateInfoCard(string Data)
{
DisableChoiceCards();
if (VRCJson.TryDeserializeFromJson(Data, out DataToken ResultToken))
{
_CurrentQuestion = ResultToken.DataDictionary;
string Type = _CurrentQuestion["Type"].ToString();
if (Type == "Multiple Choice")
{
NewMultipleChoiceQuestion();
}
}
}
private void NewMultipleChoiceQuestion()
{
_CurrentQuestionType = QuestionType.MultipleChoice;
_CurrentQuestionStage = 0;
_InfoHeader.text = _CurrentQuestion["Type"].ToString();
_InfoClues[0].text = _CurrentQuestion["Clues"].DataList[0].ToString();
_InfoClues[1].text = _CurrentQuestion["Clues"].DataList[1].ToString();
_InfoClues[2].text = _CurrentQuestion["Clues"].DataList[2].ToString();
DataList Choices = _CurrentQuestion["Choices"].DataList;
_InfoChoices[0].text = Choices[0].ToString();
_InfoChoices[1].text = Choices[1].ToString();
_InfoChoices[2].text = Choices[2].ToString();
_CurrentQuestionCorrectResponse = (int)_CurrentQuestion["Correct Response"].Double;
_Answer.text = Choices[_CurrentQuestionCorrectResponse].ToString();
}
private void MultipleChoiceRevealChoices()
{
Debug.LogError("Advancing the current question stage now.");
SendCustomEvent(nameof(MultipleChoiceRevealChoice1));
SendCustomEventDelayedSeconds(nameof(MultipleChoiceRevealChoice2), 1.25f);
SendCustomEventDelayedSeconds(nameof(MultipleChoiceRevealChoice3), 2.5f);
}
public void MultipleChoiceRevealChoice1()
{
_InfoChoiceButtons[0].color = (_CurrentQuestionCorrectResponse == 0) ? Color.green : Color.red;
}
public void MultipleChoiceRevealChoice2()
{
_InfoChoiceButtons[1].color = (_CurrentQuestionCorrectResponse == 1) ? Color.green : Color.red;
}
public void MultipleChoiceRevealChoice3()
{
_InfoChoiceButtons[2].color = (_CurrentQuestionCorrectResponse == 2) ? Color.green : Color.red;
DataList Choices = _CurrentQuestion["Choices"].DataList;
EnableChoiceCards();
for (int i = 0; i < PlayerPodiums.Length; i++)
{
NetworkCalling.SendCustomNetworkEvent((IUdonEventReceiver)PlayerPodiums[i], NetworkEventTarget.Owner, "SetCardChoices", Choices[0].ToString(), Choices[1].ToString(), Choices[2].ToString());
}
}
public void EnableChoiceCards()
{
for (int i = 0; i < PlayerPodiums.Length; i++)
{
NetworkCalling.SendCustomNetworkEvent((IUdonEventReceiver)PlayerPodiums[i], NetworkEventTarget.All, "EnableChoiceCards", true);
}
}
public void DisableChoiceCards()
{
for (int i = 0; i < PlayerPodiums.Length; i++)
{
NetworkCalling.SendCustomNetworkEvent((IUdonEventReceiver)PlayerPodiums[i], NetworkEventTarget.All, "EnableChoiceCards", false);
}
}
public void EnableBuzzInPeriodForAllPlayers()
{
BuzzInAllowed = true;
ResetBuzzers();
}
[NetworkCallable]
public void PlayerBuzzedIn(int PlayerNumber)
{
int PlayerIndex = PlayerNumber - 1;
if (!BuzzInAllowed || !PlayerBuzzInAllowed[PlayerIndex]) { return; }
// Prevent new buzz-ins and store which player is currently buzzed in.
BuzzInAllowed = false;
PlayerBuzzInAllowed[PlayerIndex] = false;
_BuzzedInPlayer = PlayerNumber;
RequestSerialization();
NetworkCalling.SendCustomNetworkEvent(
(IUdonEventReceiver)PlayerPodiums[PlayerIndex],
NetworkEventTarget.All,
"EnableBuzzInEffect", true);
// Play the buzzer sound globally.
SendCustomNetworkEvent(NetworkEventTarget.All, nameof(PlaySFX), SFXEventType.Buzzer);
}
public void WaitForBuzzInsWithoutLastPlayer() {
BuzzInAllowed = true;
NetworkCalling.SendCustomNetworkEvent(
(IUdonEventReceiver)PlayerPodiums[_BuzzedInPlayer - 1],
NetworkEventTarget.All,
"EnableBuzzInEffect", false);
_BuzzedInPlayer = -1;
RequestSerialization();
}
public void EndBuzzInPeriod()
{
BuzzInAllowed = false;
ResetBuzzers();
}
public void ResetBuzzers()
{
for (int i = 0; i < PlayerPodiums.Length; i++) { PlayerBuzzInAllowed[i] = true; }
_BuzzedInPlayer = -1;
}
private void AdvanceQuestionStage()
{
_CurrentQuestionStage++;
switch(_CurrentQuestionType)
{
case QuestionType.MultipleChoice:
AdvanceMultipleChoiceStage();
break;
}
RequestSerialization();
}
private void AdvanceMultipleChoiceStage()
{
switch(_CurrentQuestionStage)
{
case 1:
MultipleChoiceRevealChoices();
break;
default:
return;
}
}
[NetworkCallable]
public void PlayMusic(MusicEventType MusicEvent)
{
MusicPlayer.Stop();
switch (MusicEvent)
{
case MusicEventType.WhereInTheWorld: MusicPlayer.clip = WhereInTheWorld; break;
case MusicEventType.RockapellaIdent: MusicPlayer.clip = RockapellaIdent; break;
default: MusicPlayer.clip = null; break;
}
if (MusicPlayer.clip != null)
MusicPlayer.Play();
}
[NetworkCallable]
public void PlaySFX(SFXEventType SFXEvent)
{
SFXPlayer.Stop();
switch (SFXEvent)
{
case SFXEventType.Buzzer: SFXPlayer.clip = BuzzerSound; break;
default: SFXPlayer.clip = null; break;
}
if (SFXPlayer.clip != null)
SFXPlayer.Play();
}
public override void OnPickupUseDown()
{
AdvanceQuestionStage();
base.OnPickupUseDown();
}
}