r2mods/ilspy_dump/ror2_csproj/RoR2/BackstabManager.cs

297 lines
8.0 KiB
C#

using System;
using System.Collections.Generic;
using HG;
using UnityEngine;
namespace RoR2;
public static class BackstabManager
{
private class BackstabVisualizer
{
private class IndicatorInfo
{
public GameObject gameObject;
public Transform transform;
public ParticleSystem particleSystem;
public ParticleSystemRenderer renderer;
public float lastDisplayTime;
}
private CameraRigController camera;
public CharacterBody targetBody;
private readonly Dictionary<CharacterBody, IndicatorInfo> bodyToIndicator = new Dictionary<CharacterBody, IndicatorInfo>();
private static readonly Dictionary<CharacterBody, IndicatorInfo> buffer = new Dictionary<CharacterBody, IndicatorInfo>();
private readonly Stack<IndicatorInfo> indicatorPool = new Stack<IndicatorInfo>();
private static GameObject indicatorPrefab;
public void Install(CameraRigController newCamera)
{
camera = newCamera;
RoR2Application.onLateUpdate += UpdateIndicators;
}
public void Uninstall()
{
RoR2Application.onLateUpdate -= UpdateIndicators;
camera = null;
foreach (KeyValuePair<CharacterBody, IndicatorInfo> item in bodyToIndicator)
{
UnityEngine.Object.Destroy(item.Value.gameObject);
}
bodyToIndicator.Clear();
foreach (IndicatorInfo item2 in indicatorPool)
{
UnityEngine.Object.Destroy(item2.gameObject);
}
indicatorPool.Clear();
}
[InitDuringStartup]
private static void OnLoad()
{
LegacyResourcesAPI.LoadAsyncCallback("Prefabs/VFX/BackstabIndicator", delegate(GameObject operationResult)
{
indicatorPrefab = operationResult;
});
}
private void UpdateIndicators()
{
Vector3 corePosition = targetBody.corePosition;
TeamIndex teamIndex = targetBody.teamComponent.teamIndex;
buffer.Clear();
float unscaledTime = Time.unscaledTime;
foreach (CharacterBody readOnlyInstances in CharacterBody.readOnlyInstancesList)
{
bool num = TeamManager.IsTeamEnemy(teamIndex, readOnlyInstances.teamComponent.teamIndex);
bool flag = false;
if (num)
{
flag = IsBackstab(readOnlyInstances.corePosition - corePosition, readOnlyInstances);
}
if (num && flag)
{
IndicatorInfo value = null;
if (!bodyToIndicator.TryGetValue(readOnlyInstances, out value))
{
value = AddIndicator(readOnlyInstances);
}
value.lastDisplayTime = unscaledTime;
}
}
List<CharacterBody> list = CollectionPool<CharacterBody, List<CharacterBody>>.RentCollection();
foreach (KeyValuePair<CharacterBody, IndicatorInfo> item in bodyToIndicator)
{
if (item.Value.lastDisplayTime != unscaledTime)
{
list.Add(item.Key);
}
}
foreach (CharacterBody item2 in list)
{
RemoveIndicator(item2);
}
list = CollectionPool<CharacterBody, List<CharacterBody>>.ReturnCollection(list);
}
private IndicatorInfo AddIndicator(CharacterBody victimBody)
{
IndicatorInfo indicatorInfo = null;
if (indicatorPool.Count > 0)
{
indicatorInfo = indicatorPool.Pop();
}
else
{
indicatorInfo = new IndicatorInfo();
indicatorInfo.gameObject = UnityEngine.Object.Instantiate(indicatorPrefab);
indicatorInfo.transform = indicatorInfo.gameObject.transform;
indicatorInfo.particleSystem = indicatorInfo.gameObject.GetComponent<ParticleSystem>();
indicatorInfo.renderer = indicatorInfo.gameObject.GetComponent<ParticleSystemRenderer>();
indicatorInfo.renderer.enabled = false;
}
indicatorInfo.gameObject.SetActive(value: true);
indicatorInfo.particleSystem.Play();
bodyToIndicator[victimBody] = indicatorInfo;
return indicatorInfo;
}
private void RemoveIndicator(CharacterBody victimBody)
{
IndicatorInfo indicatorInfo = bodyToIndicator[victimBody];
if ((bool)indicatorInfo.gameObject)
{
indicatorInfo.particleSystem.Stop();
indicatorInfo.gameObject.SetActive(value: false);
}
bodyToIndicator.Remove(victimBody);
indicatorPool.Push(indicatorInfo);
}
public void OnPreCull()
{
foreach (KeyValuePair<CharacterBody, IndicatorInfo> item in bodyToIndicator)
{
CharacterBody key = item.Key;
Transform transform = item.Value.transform;
if ((bool)key)
{
Vector3? bodyForward = GetBodyForward(key);
if (bodyForward.HasValue)
{
transform.forward = -bodyForward.Value;
}
transform.position = key.corePosition - transform.forward * key.radius;
item.Value.renderer.enabled = true;
}
}
}
public void OnPostRender()
{
foreach (KeyValuePair<CharacterBody, IndicatorInfo> item in bodyToIndicator)
{
item.Value.renderer.enabled = false;
}
}
private void Update()
{
UpdateIndicators();
}
}
public static GameObject backstabImpactEffectPrefab = null;
private static readonly bool enableVisualizerSystem = false;
private static readonly float showBackstabThreshold = Mathf.Cos(MathF.PI / 4f);
private static readonly Dictionary<CameraRigController, BackstabVisualizer> camToVisualizer = new Dictionary<CameraRigController, BackstabVisualizer>();
public static bool IsBackstab(Vector3 attackerCorePositionToHitPosition, CharacterBody victimBody)
{
if (!victimBody.canReceiveBackstab)
{
return false;
}
Vector3? bodyForward = GetBodyForward(victimBody);
if (bodyForward.HasValue)
{
return Vector3.Dot(attackerCorePositionToHitPosition, bodyForward.Value) > 0f;
}
return false;
}
private static Vector3? GetBodyForward(CharacterBody characterBody)
{
Vector3? vector = null;
return (!characterBody.characterDirection) ? new Vector3?(characterBody.transform.forward) : new Vector3?(characterBody.characterDirection.forward);
}
[InitDuringStartup]
private static void Init()
{
if (enableVisualizerSystem)
{
InitVisualizerSystem();
}
LegacyResourcesAPI.LoadAsyncCallback("Effects/ImpactEffects/BackstabSpark", delegate(GameObject operationResult)
{
backstabImpactEffectPrefab = operationResult;
});
}
private static bool ShouldShowBackstab(Vector3 attackerCorePosition, CharacterBody victimBody)
{
if (!victimBody.canReceiveBackstab)
{
return false;
}
Vector3? bodyForward = GetBodyForward(victimBody);
if (bodyForward.HasValue)
{
return Vector3.Dot((attackerCorePosition - victimBody.corePosition).normalized, bodyForward.Value) > showBackstabThreshold;
}
return false;
}
private static void InitVisualizerSystem()
{
CameraRigController.onCameraTargetChanged += OnCameraTargetChanged;
CameraRigController.onCameraEnableGlobal += OnCameraDiscovered;
CameraRigController.onCameraDisableGlobal += OnCameraLost;
SceneCamera.onSceneCameraPreCull += OnSceneCameraPreCull;
SceneCamera.onSceneCameraPostRender += OnSceneCameraPostRender;
}
private static void OnCameraTargetChanged(CameraRigController camera, GameObject target)
{
RefreshCamera(camera);
}
private static void OnCameraDiscovered(CameraRigController camera)
{
RefreshCamera(camera);
}
private static void OnCameraLost(CameraRigController camera)
{
RefreshCamera(camera);
}
private static void OnSceneCameraPreCull(SceneCamera sceneCam)
{
if (camToVisualizer.TryGetValue(sceneCam.cameraRigController, out var value))
{
value.OnPreCull();
}
}
private static void OnSceneCameraPostRender(SceneCamera sceneCam)
{
if (camToVisualizer.TryGetValue(sceneCam.cameraRigController, out var value))
{
value.OnPostRender();
}
}
private static void RefreshCamera(CameraRigController camera)
{
BackstabVisualizer value;
bool num = camToVisualizer.TryGetValue(camera, out value);
GameObject gameObject = (camera.isActiveAndEnabled ? camera.target : null);
CharacterBody characterBody = (gameObject ? gameObject.GetComponent<CharacterBody>() : null);
bool flag = (bool)characterBody && characterBody.canPerformBackstab;
if (num != flag)
{
if (flag)
{
value = new BackstabVisualizer();
camToVisualizer.Add(camera, value);
value.Install(camera);
}
else
{
value.Uninstall();
camToVisualizer.Remove(camera);
value = null;
}
}
if (value != null)
{
value.targetBody = characterBody;
}
}
}