CarmenSandiego/Assets/UdonSharp/Maps/FloorMapMarker.cs

194 lines
4.2 KiB
C#

using UdonSharp;
using UnityEngine;
using VRC.SDK3.Components;
using VRC.SDK3.Data;
using static UnityEditor.FilePathAttribute;
[UdonBehaviourSyncMode(BehaviourSyncMode.Manual)]
public class FloorMapMarker : UdonSharpBehaviour
{
[UdonSynced, SerializeField, FieldChangeCallback(nameof(Enabled))] private bool _Enabled = false;
[UdonSynced, FieldChangeCallback(nameof(IsGrabbed))] private bool _IsGrabbed = false;
[SerializeField] private GameManagerRound3 _GameManager;
[SerializeField] private AudioManager _AudioManager;
private DataList _CollidingLocations = new DataList();
private int _CollisionCheckCounter = 0;
private int _FailureCounter = 0;
private const int MAX_REPEAT_COLLISION_CHECKS = 3;
private const float TIME_BETWEEN_REPEAT_COLLISION_CHECKS = 0.15f;
private const int MAX_FAILURE_COUNT = 2;
public void OnTriggerEnter(Collider OtherCollider)
{
FloorMapLocation Location = OtherCollider.GetComponent<FloorMapLocation>();
if (Location != null)
{
_CollidingLocations.Add(Location);
_CollisionCheckCounter = 0;
if (!IsGrabbed) CheckCollisions();
}
}
public void OnTriggerExit(Collider OtherCollider)
{
FloorMapLocation Location = OtherCollider.GetComponent<FloorMapLocation>();
if (Location != null)
{
_CollidingLocations.Remove(Location);
_CollisionCheckCounter = 0;
}
}
public override void OnPickup()
{
Rigidbody Body;
if (Body = GetComponent<Rigidbody>())
{
Body.constraints = RigidbodyConstraints.None;
}
Enabled = true;
IsGrabbed = true;
_CollidingLocations.Clear();
base.OnPickup();
}
public override void OnDrop()
{
IsGrabbed = false;
CheckCollisions();
base.OnDrop();
}
public void CheckCollisions()
{
if (!Enabled) return;
if (_CollidingLocations.Count > 0 && IsUpright() && !IsGrabbed)
{
for (int i = 0; i < _CollidingLocations.Count; i++)
{
FloorMapLocation Location = (FloorMapLocation)_CollidingLocations[i].Reference;
if (Location != null)
{
bool FoundCorrectResponse = ConfirmChoice(Location.Country, Location.City);
if (FoundCorrectResponse)
{
_AudioManager.PlaySFX(SFXEventType.MapCorrect);
Rigidbody Body;
if (Body = GetComponent<Rigidbody>())
{
Body.constraints = RigidbodyConstraints.FreezeAll;
}
transform.position = Location.transform.position;
StandUpright();
Enabled = false;
EnablePickup(false);
return;
}
}
}
// We should make sure to only reach here if we don't get a correct
// response from the previous loop.
if (_CollisionCheckCounter < MAX_REPEAT_COLLISION_CHECKS)
{
SendCustomEventDelayedSeconds(nameof(CheckCollisions), TIME_BETWEEN_REPEAT_COLLISION_CHECKS);
}
else
{
_AudioManager.PlaySFX(SFXEventType.MapIncorrect);
Rigidbody Body;
if (Body = GetComponent<Rigidbody>())
{
Body.constraints = RigidbodyConstraints.FreezeAll;
}
StandUpright();
_CollisionCheckCounter = 0;
_CollidingLocations.Clear();
// Stop checking for new collisions here, and if this results
// in too many fails, don't allow new pickups.
Enabled = false;
_FailureCounter++;
if (_FailureCounter >= MAX_FAILURE_COUNT)
{
EnablePickup(false);
}
}
_CollisionCheckCounter++;
}
else
{
// If the marker isn't sitting mostly upright and is not grabbed,
// don't check collisions until later, in case it becomes upright.
SendCustomEventDelayedSeconds(nameof(CheckCollisions), TIME_BETWEEN_REPEAT_COLLISION_CHECKS);
}
}
public bool ConfirmChoice(string Country, string City)
{
if (Country == _GameManager.GetCurrentCountry() &&
City == _GameManager.GetCurrentCity())
{
return true;
}
return false;
}
private void EnablePickup(bool Enable)
{
VRCPickup Pickup;
if (Pickup = GetComponent<VRCPickup>())
{
Pickup.pickupable = Enable;
}
}
private void StandUpright()
{
transform.eulerAngles = new Vector3(0.0f, transform.eulerAngles.y, 0.0f);
}
private bool IsUpright()
{
return (Vector3.Dot(transform.up, Vector3.up) >= 0.85f);
}
public bool Enabled
{
set
{
_Enabled = value;
}
get => _Enabled;
}
public bool IsGrabbed
{
set
{
_IsGrabbed = value;
}
get => _IsGrabbed;
}
}