r2mods/ilspy_dump/ror2_csproj/RoR2/RouletteChestController.cs

469 lines
12 KiB
C#

using System;
using EntityStates;
using JetBrains.Annotations;
using RoR2.Networking;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Networking;
namespace RoR2;
[RequireComponent(typeof(PurchaseInteraction))]
[RequireComponent(typeof(EntityStateMachine))]
public class RouletteChestController : NetworkBehaviour
{
public struct Entry
{
public PickupIndex pickupIndex;
public Run.FixedTimeStamp endTime;
}
private class RouletteChestControllerBaseState : EntityState
{
protected RouletteChestController rouletteChestController { get; private set; }
public override void OnEnter()
{
base.OnEnter();
rouletteChestController = GetComponent<RouletteChestController>();
}
public virtual void HandleInteractionServer(Interactor activator)
{
}
}
private class Idle : RouletteChestControllerBaseState
{
private static int IdleStateHash = Animator.StringToHash("Idle");
public override void OnEnter()
{
base.OnEnter();
PlayAnimation("Body", IdleStateHash);
base.rouletteChestController.purchaseInteraction.Networkavailable = true;
}
public override void HandleInteractionServer(Interactor activator)
{
base.HandleInteractionServer(activator);
outer.SetNextState(new Startup());
}
}
private class Startup : RouletteChestControllerBaseState
{
public static float baseDuration;
public static string soundEntryEvent;
private static int IdleToActiveStateHash = Animator.StringToHash("IdleToActive");
public override void OnEnter()
{
base.OnEnter();
PlayAnimation("Body", IdleToActiveStateHash);
base.rouletteChestController.purchaseInteraction.Networkavailable = false;
base.rouletteChestController.purchaseInteraction.costType = CostTypeIndex.None;
Util.PlaySound(soundEntryEvent, base.gameObject);
}
public override void FixedUpdate()
{
base.FixedUpdate();
if (NetworkServer.active && base.fixedAge > baseDuration)
{
outer.SetNextState(new Cycling());
}
}
}
private class Cycling : RouletteChestControllerBaseState
{
public static string soundCycleEvent;
public static string soundCycleSpeedRtpc;
public static float soundCycleSpeedRtpcScale;
private static int ActiveLoopStateHash = Animator.StringToHash("ActiveLoop");
private static int ActiveLoopParamHash = Animator.StringToHash("ActiveLoop.playbackRate");
public override void OnEnter()
{
base.OnEnter();
base.rouletteChestController.onChangedEntryClient.AddListener(OnChangedEntryClient);
if (NetworkServer.active)
{
base.rouletteChestController.BeginCycleServer();
base.rouletteChestController.onCycleCompletedServer.AddListener(OnCycleCompleted);
}
base.rouletteChestController.purchaseInteraction.Networkavailable = true;
base.rouletteChestController.purchaseInteraction.costType = CostTypeIndex.None;
}
private void OnCycleCompleted()
{
outer.SetNextState(new Opening());
}
public override void OnExit()
{
base.rouletteChestController.onCycleCompletedServer.RemoveListener(OnCycleCompleted);
base.rouletteChestController.onChangedEntryClient.RemoveListener(OnChangedEntryClient);
base.OnExit();
}
private void OnChangedEntryClient()
{
int entryIndexForTime = base.rouletteChestController.GetEntryIndexForTime(Run.FixedTimeStamp.now);
float num = base.rouletteChestController.CalcEntryDuration(entryIndexForTime);
PlayAnimation("Body", ActiveLoopStateHash, ActiveLoopParamHash, num);
float num2 = Util.Remap(num, minTime, minTime + base.rouletteChestController.bonusTime, 1f, 0f);
Util.PlaySound(soundCycleEvent, base.gameObject, soundCycleSpeedRtpc, num2 * soundCycleSpeedRtpcScale);
}
public override void HandleInteractionServer(Interactor activator)
{
base.HandleInteractionServer(activator);
base.rouletteChestController.EndCycleServer(activator);
}
}
private class Opening : RouletteChestControllerBaseState
{
public static float baseDuration;
public static string soundEntryEvent;
private static int ActiveToOpeningStateHash = Animator.StringToHash("ActiveToOpening");
public override void OnEnter()
{
base.OnEnter();
PlayAnimation("Body", ActiveToOpeningStateHash);
base.rouletteChestController.purchaseInteraction.Networkavailable = false;
base.rouletteChestController.purchaseInteraction.costType = CostTypeIndex.None;
Util.PlaySound(soundEntryEvent, base.gameObject);
}
public override void FixedUpdate()
{
base.FixedUpdate();
if (NetworkServer.active && base.fixedAge > baseDuration)
{
outer.SetNextState(new Opened());
}
}
}
private class Opened : RouletteChestControllerBaseState
{
private static int OpenedStateHash = Animator.StringToHash("Opened");
public override void OnEnter()
{
base.OnEnter();
PlayAnimation("Body", OpenedStateHash);
base.rouletteChestController.purchaseInteraction.Networkavailable = false;
base.rouletteChestController.purchaseInteraction.costType = CostTypeIndex.None;
base.rouletteChestController.networkIdentity.isPingable = false;
}
}
public int maxEntries = 1;
public float bonusTime;
public AnimationCurve bonusTimeDecay;
public PickupDropTable dropTable;
public Transform ejectionTransform;
public Vector3 localEjectionVelocity;
public Animator modelAnimator;
public PickupDisplay pickupDisplay;
private EntityStateMachine stateMachine;
private PurchaseInteraction purchaseInteraction;
private NetworkIdentity networkIdentity;
private static readonly float averageHgReactionTime = 0.20366667f;
private static readonly float lowestHgReactionTime = 0.15f;
private static readonly float recognitionWindow = 0.15f;
private static readonly float minTime = lowestHgReactionTime + recognitionWindow;
private static readonly float rewindTime = 0.05f;
private Run.FixedTimeStamp activationTime = Run.FixedTimeStamp.positiveInfinity;
private Entry[] entries = Array.Empty<Entry>();
private Xoroshiro128Plus rng;
private static readonly uint activationTimeDirtyBit = 1u;
private static readonly uint entriesDirtyBit = 2u;
private static readonly uint enabledDirtyBit = 4u;
private static readonly uint allDirtyBitsMask = activationTimeDirtyBit | entriesDirtyBit;
public int dropCount = 1;
private int previousEntryIndexClient = -1;
public UnityEvent onCycleBeginServer;
public UnityEvent onCycleCompletedServer;
public UnityEvent onChangedEntryClient;
private bool isCycling => !activationTime.isPositiveInfinity;
private float CalcEntryDuration(int i)
{
float time = (float)i / (float)maxEntries;
return bonusTimeDecay.Evaluate(time) * bonusTime + minTime;
}
public override bool OnSerialize(NetworkWriter writer, bool initialState)
{
uint num = base.syncVarDirtyBits;
if (initialState)
{
num = allDirtyBitsMask;
}
writer.WritePackedUInt32(num);
if ((num & activationTimeDirtyBit) != 0)
{
writer.Write(activationTime);
}
if ((num & entriesDirtyBit) != 0)
{
writer.WritePackedUInt32((uint)entries.Length);
for (int i = 0; i < entries.Length; i++)
{
writer.Write(entries[i].pickupIndex);
}
}
return num != 0;
}
public override void OnDeserialize(NetworkReader reader, bool initialState)
{
uint num = reader.ReadPackedUInt32();
if ((num & activationTimeDirtyBit) != 0)
{
activationTime = reader.ReadFixedTimeStamp();
}
if ((num & entriesDirtyBit) != 0)
{
Array.Resize(ref entries, (int)reader.ReadPackedUInt32());
Run.FixedTimeStamp endTime = activationTime;
for (int i = 0; i < entries.Length; i++)
{
ref Entry reference = ref entries[i];
reference.pickupIndex = reader.ReadPickupIndex();
reference.endTime = endTime + CalcEntryDuration(i);
endTime = reference.endTime;
}
}
}
private void Awake()
{
stateMachine = GetComponent<EntityStateMachine>();
purchaseInteraction = GetComponent<PurchaseInteraction>();
networkIdentity = GetComponent<NetworkIdentity>();
}
private void Start()
{
if (NetworkServer.active)
{
rng = new Xoroshiro128Plus(Run.instance.treasureRng.nextUlong);
}
}
private void OnEnable()
{
SetDirtyBit(enabledDirtyBit);
if ((bool)pickupDisplay)
{
pickupDisplay.enabled = true;
}
}
private void OnDisable()
{
if ((bool)pickupDisplay)
{
pickupDisplay.SetPickupIndex(PickupIndex.none);
pickupDisplay.enabled = false;
}
SetDirtyBit(enabledDirtyBit);
}
[Server]
private void GenerateEntriesServer(Run.FixedTimeStamp startTime)
{
if (!NetworkServer.active)
{
Debug.LogWarning("[Server] function 'System.Void RoR2.RouletteChestController::GenerateEntriesServer(RoR2.Run/FixedTimeStamp)' called on client");
return;
}
Array.Resize(ref entries, maxEntries);
for (int i = 0; i < entries.Length; i++)
{
ref Entry reference = ref entries[i];
reference.endTime = startTime + CalcEntryDuration(i);
startTime = reference.endTime;
}
PickupIndex pickupIndex = PickupIndex.none;
for (int j = 0; j < entries.Length; j++)
{
ref Entry reference2 = ref entries[j];
PickupIndex pickupIndex2 = dropTable.GenerateDrop(rng);
if (pickupIndex2 == pickupIndex)
{
pickupIndex2 = dropTable.GenerateDrop(rng);
}
reference2.pickupIndex = pickupIndex2;
pickupIndex = pickupIndex2;
}
SetDirtyBit(entriesDirtyBit);
}
[Server]
public void HandleInteractionServer(Interactor activator)
{
if (!NetworkServer.active)
{
Debug.LogWarning("[Server] function 'System.Void RoR2.RouletteChestController::HandleInteractionServer(RoR2.Interactor)' called on client");
}
else
{
((RouletteChestControllerBaseState)stateMachine.state).HandleInteractionServer(activator);
}
}
[Server]
private void BeginCycleServer()
{
if (!NetworkServer.active)
{
Debug.LogWarning("[Server] function 'System.Void RoR2.RouletteChestController::BeginCycleServer()' called on client");
return;
}
activationTime = Run.FixedTimeStamp.now;
SetDirtyBit(activationTimeDirtyBit);
GenerateEntriesServer(activationTime);
onCycleBeginServer?.Invoke();
}
[Server]
private void EndCycleServer([CanBeNull] Interactor activator)
{
if (!NetworkServer.active)
{
Debug.LogWarning("[Server] function 'System.Void RoR2.RouletteChestController::EndCycleServer(RoR2.Interactor)' called on client");
return;
}
float num = 0f;
if ((bool)activator)
{
NetworkUser networkUser = Util.LookUpBodyNetworkUser(activator.gameObject);
if ((object)networkUser != null)
{
num = RttManager.GetConnectionRTT(networkUser.connectionToClient);
}
}
Run.FixedTimeStamp time = Run.FixedTimeStamp.now - num - rewindTime;
PickupIndex pickupIndexForTime = GetPickupIndexForTime(time);
EjectPickupServer(pickupIndexForTime);
activationTime = Run.FixedTimeStamp.positiveInfinity;
onCycleCompletedServer.Invoke();
}
private void FixedUpdate()
{
if ((bool)pickupDisplay)
{
pickupDisplay.SetPickupIndex(isCycling ? GetPickupIndexForTime(Run.FixedTimeStamp.now) : PickupIndex.none);
}
if (NetworkClient.active)
{
int entryIndexForTime = GetEntryIndexForTime(Run.FixedTimeStamp.now);
if (entryIndexForTime != previousEntryIndexClient)
{
previousEntryIndexClient = entryIndexForTime;
onChangedEntryClient.Invoke();
}
}
if (NetworkServer.active && isCycling && entries.Length != 0)
{
Run.FixedTimeStamp endTime = entries[entries.Length - 1].endTime;
if (endTime.hasPassed)
{
EndCycleServer(null);
}
}
}
private int GetEntryIndexForTime(Run.FixedTimeStamp time)
{
for (int i = 0; i < entries.Length; i++)
{
if (time < entries[i].endTime)
{
return i;
}
}
if (entries.Length != 0)
{
return entries.Length - 1;
}
return -1;
}
private PickupIndex GetPickupIndexForTime(Run.FixedTimeStamp time)
{
int entryIndexForTime = GetEntryIndexForTime(time);
if (entryIndexForTime != -1)
{
return entries[entryIndexForTime].pickupIndex;
}
return PickupIndex.none;
}
private void EjectPickupServer(PickupIndex pickupIndex)
{
if (!(pickupIndex == PickupIndex.none))
{
for (int i = 0; i < dropCount; i++)
{
PickupDropletController.CreatePickupDroplet(pickupIndex, ejectionTransform.position, ejectionTransform.rotation * localEjectionVelocity);
}
}
}
private void UNetVersion()
{
}
public override void PreStartClient()
{
}
}