Jamie Greunbaum 8b6604da24 - Modem now has markers for where players should stand to be teleported.
- Jail call camera overlay now syncs crook portraits properly.
- Ownership of wanted/missing posters and jail call overlay is properly set.
2026-05-09 13:59:29 -04:00

190 lines
4.3 KiB
C#

using UdonSharp;
using UnityEngine;
using VRC.SDK3.UdonNetworkCalling;
using VRC.SDKBase;
using VRC.Udon.Common;
using VRC.Udon.Common.Interfaces;
[UdonBehaviourSyncMode(BehaviourSyncMode.Manual)]
public class Modem : UdonSharpBehaviour
{
[SerializeField] private AudioManager _AudioManager;
[SerializeField] private PositionMarker[] _PlayerMarkers;
[SerializeField] private Animator _ModemAnimator;
[SerializeField] private Animator _ModemDestinationAnimator;
[SerializeField] private Modem _ModemDestination;
[UdonSynced] private bool _ActivateModem = false;
[UdonSynced] private string[] _PlayerNames = new string[3];
[UdonSynced] private bool _BeginTeleport = false;
[UdonSynced] private string[] _EnteredPlayers = new string[MAX_PLAYERS_IN_MODEM];
private const int MAX_PLAYERS_IN_MODEM = 10;
public override void OnDeserialization(DeserializationResult Result)
{
_Activate_Synced();
_Teleport_Synced();
base.OnDeserialization(Result);
}
public override void OnPlayerTriggerEnter(VRCPlayerApi Player)
{
for (int i = 0; i < MAX_PLAYERS_IN_MODEM; i++)
{
if (_EnteredPlayers[i] == null)
{
_EnteredPlayers[i] = Player.displayName;
break;
}
}
RequestSerialization();
base.OnPlayerTriggerEnter(Player);
}
public override void OnPlayerTriggerExit(VRCPlayerApi Player)
{
for (int i = 0; i < MAX_PLAYERS_IN_MODEM; i++)
{
if (_EnteredPlayers[i] == Player.displayName)
{
_EnteredPlayers[i] = null;
break;
}
}
RequestSerialization();
base.OnPlayerTriggerExit(Player);
}
public void SetHost(string Host)
{
_PlayerNames[0] = Host;
}
public void SetWinningPlayers(string[] WinningPlayers)
{
_PlayerNames[1] = WinningPlayers[0];
_PlayerNames[2] = WinningPlayers[1];
}
public void Activate(bool Active)
{
_ActivateModem = Active;
_Activate_Synced();
RequestSerialization();
}
private void _Activate_Synced()
{
if (_ActivateModem)
{
for (int i = 0; i < _PlayerMarkers.Length; i++)
{
_PlayerMarkers[i].SetPlayer((i < _PlayerNames.Length) ? _PlayerNames[i] : "");
}
}
else
{
for (int i = 0; i < _PlayerMarkers.Length && i < _PlayerNames.Length; i++)
{
_PlayerMarkers[i].ClearPlayer();
_PlayerNames[i] = "";
}
}
_ModemAnimator.SetBool("Enter", _ActivateModem);
}
public void Teleport()
{
Networking.SetOwner(Networking.LocalPlayer, gameObject);
_BeginTeleport = true;
_Teleport_Synced();
RequestSerialization();
}
private void _Teleport_Synced()
{
if (_BeginTeleport == _ModemAnimator.GetBool("Teleport"))
{
return;
}
if (_BeginTeleport)
{
ExecuteTeleportProcess();
}
else
{
ResetTeleportProcess();
}
}
private void ExecuteTeleportProcess()
{
// This is a synced function, so only play the sound effect locally.
_AudioManager.PlaySFX(SFXEventType.ModemOperation);
_ModemAnimator.SetBool("Teleport", true);
_ModemDestinationAnimator.SetBool("Teleport", true);
SendCustomEventDelayedSeconds(nameof(TeleportAllPlayers), 2.5f);
SendCustomEventDelayedSeconds(nameof(EndTeleport), 6.0f);
}
public void TeleportAllPlayers()
{
// Only the Modem owner should execute teleportations.
if (Networking.LocalPlayer.IsOwner(gameObject))
{
SendCustomNetworkEvent(NetworkEventTarget.All, nameof(TeleportLocalPlayerIfInModem));
}
}
public void ResetTeleportProcess()
{
_ModemAnimator.SetBool("Teleport", false);
_ModemDestinationAnimator.SetBool("Teleport", false);
}
public void EndTeleport()
{
_BeginTeleport = false;
_Teleport_Synced();
RequestSerialization();
}
[NetworkCallable]
public void TeleportLocalPlayerIfInModem()
{
for (int j = 0; j < _EnteredPlayers.Length; j++)
{
if (_EnteredPlayers[j] == Networking.LocalPlayer.displayName)
{
TeleportToModemDestination();
break;
}
}
}
private void TeleportToModemDestination()
{
Vector3 DeltaVector = Networking.LocalPlayer.GetPosition() - transform.position;
Quaternion DeltaRotation = _ModemDestination.transform.rotation * Quaternion.Inverse(transform.rotation);
Vector3 DestinationVectorRotated = DeltaRotation * DeltaVector.normalized;
Vector3 DestinationPositionDelta = DestinationVectorRotated * DeltaVector.magnitude;
Networking.LocalPlayer.TeleportTo(
_ModemDestination.transform.position + DestinationPositionDelta,
DeltaRotation * Networking.LocalPlayer.GetRotation());
}
}