r2mods/ilspy_dump/ror2_csproj/RoR2/ExperienceManager.cs

235 lines
5.9 KiB
C#

using System;
using System.Collections.Generic;
using RoR2.Networking;
using UnityEngine;
using UnityEngine.Networking;
namespace RoR2;
public class ExperienceManager : MonoBehaviour
{
[Serializable]
private struct TimedExpAward
{
public float awardTime;
public ulong awardAmount;
public TeamIndex recipient;
}
private class CreateExpEffectMessage : MessageBase
{
public Vector3 origin;
public GameObject targetBody;
public ulong awardAmount;
public override void Serialize(NetworkWriter writer)
{
writer.Write(origin);
writer.Write(targetBody);
writer.WritePackedUInt64(awardAmount);
}
public override void Deserialize(NetworkReader reader)
{
origin = reader.ReadVector3();
targetBody = reader.ReadGameObject();
awardAmount = reader.ReadPackedUInt64();
}
}
private static GameObject experienceOrbPrefab;
private float localTime;
private List<TimedExpAward> pendingAwards = new List<TimedExpAward>();
private float nextAward;
private bool shouldPool;
private const float minOrbTravelTime = 0.5f;
public const float maxOrbTravelTime = 2f;
public static readonly float[] orbTimeOffsetSequence = new float[16]
{
0.841f, 0.394f, 0.783f, 0.799f, 0.912f, 0.197f, 0.335f, 0.768f, 0.278f, 0.554f,
0.477f, 0.629f, 0.365f, 0.513f, 0.953f, 0.917f
};
private static CreateExpEffectMessage currentOutgoingCreateExpEffectMessage = new CreateExpEffectMessage();
private static CreateExpEffectMessage currentIncomingCreateExpEffectMessage = new CreateExpEffectMessage();
public static ExperienceManager instance { get; private set; }
private static float CalcOrbTravelTime(float timeOffset)
{
return 0.5f + 1.5f * timeOffset;
}
private void OnEnable()
{
if ((bool)instance && instance != this)
{
Debug.LogError("Only one ExperienceManager can exist at a time.");
return;
}
instance = this;
if (!experienceOrbPrefab)
{
LegacyResourcesAPI.LoadAsyncCallback("Prefabs/ExpOrb", delegate(GameObject x)
{
experienceOrbPrefab = x;
shouldPool = EffectManager.ShouldUsePooledEffect(experienceOrbPrefab);
});
}
}
private void OnDisable()
{
if (instance == this)
{
instance = null;
}
}
private void Start()
{
localTime = 0f;
nextAward = float.PositiveInfinity;
}
private void FixedUpdate()
{
localTime += Time.fixedDeltaTime;
if (pendingAwards.Count <= 0 || !(nextAward <= localTime))
{
return;
}
nextAward = float.PositiveInfinity;
for (int num = pendingAwards.Count - 1; num >= 0; num--)
{
if (pendingAwards[num].awardTime <= localTime)
{
if ((bool)TeamManager.instance)
{
TeamManager.instance.GiveTeamExperience(pendingAwards[num].recipient, pendingAwards[num].awardAmount);
}
pendingAwards.RemoveAt(num);
}
else if (pendingAwards[num].awardTime < nextAward)
{
nextAward = pendingAwards[num].awardTime;
}
}
}
public void AwardExperience(Vector3 origin, CharacterBody body, ulong amount)
{
CharacterMaster master = body.master;
if (!master)
{
return;
}
TeamIndex teamIndex = master.teamIndex;
List<ulong> list = CalculateDenominations(amount);
uint num = 0u;
for (int i = 0; i < list.Count; i++)
{
AddPendingAward(localTime + 0.5f + 1.5f * orbTimeOffsetSequence[num], teamIndex, list[i]);
num++;
if (num >= orbTimeOffsetSequence.Length)
{
num = 0u;
}
}
currentOutgoingCreateExpEffectMessage.awardAmount = amount;
currentOutgoingCreateExpEffectMessage.origin = origin;
currentOutgoingCreateExpEffectMessage.targetBody = body.gameObject;
NetworkServer.SendToAll(55, currentOutgoingCreateExpEffectMessage);
}
private void AddPendingAward(float awardTime, TeamIndex recipient, ulong awardAmount)
{
pendingAwards.Add(new TimedExpAward
{
awardTime = awardTime,
recipient = recipient,
awardAmount = awardAmount
});
if (nextAward > awardTime)
{
nextAward = awardTime;
}
}
public List<ulong> CalculateDenominations(ulong total)
{
List<ulong> list = new List<ulong>();
while (total != 0)
{
ulong num = (ulong)Math.Pow(6.0, Mathf.Floor(Mathf.Log(total, 6f)));
total = Math.Max(total - num, 0uL);
list.Add(num);
}
return list;
}
[NetworkMessageHandler(msgType = 55, client = true)]
private static void HandleCreateExpEffect(NetworkMessage netMsg)
{
if ((bool)instance)
{
instance.HandleCreateExpEffectInternal(netMsg);
}
}
private void HandleCreateExpEffectInternal(NetworkMessage netMsg)
{
netMsg.ReadMessage(currentIncomingCreateExpEffectMessage);
if (!SettingsConVars.cvExpAndMoneyEffects.value)
{
return;
}
GameObject targetBody = currentIncomingCreateExpEffectMessage.targetBody;
if (!targetBody)
{
return;
}
HurtBox hurtBox = Util.FindBodyMainHurtBox(targetBody);
Transform targetTransform = (hurtBox ? hurtBox.transform : targetBody.transform);
List<ulong> list = CalculateDenominations(currentIncomingCreateExpEffectMessage.awardAmount);
uint num = 0u;
ExperienceOrbBehavior experienceOrbBehavior = null;
for (int i = 0; i < list.Count; i++)
{
if (!shouldPool)
{
experienceOrbBehavior = UnityEngine.Object.Instantiate(experienceOrbPrefab, currentIncomingCreateExpEffectMessage.origin, Quaternion.identity).GetComponent<ExperienceOrbBehavior>();
}
else
{
EffectManagerHelper pooledEffect = EffectManager.GetPooledEffect(experienceOrbPrefab, currentIncomingCreateExpEffectMessage.origin, Quaternion.identity);
experienceOrbBehavior = pooledEffect.GetComponent<ExperienceOrbBehavior>();
pooledEffect.Reset(inActivate: true);
pooledEffect.gameObject.SetActive(value: true);
pooledEffect.ResetPostActivate();
}
experienceOrbBehavior.targetTransform = targetTransform;
experienceOrbBehavior.travelTime = CalcOrbTravelTime(orbTimeOffsetSequence[num]);
experienceOrbBehavior.exp = list[i];
experienceOrbBehavior.SetupStartingValues();
num++;
if (num >= orbTimeOffsetSequence.Length)
{
num = 0u;
}
}
}
}