using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using InControl;
using Microsoft.CodeAnalysis;
using NineSolsAPI;
using NineSolsAPI.Utils;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("DpsMeter")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.2.2.0")]
[assembly: AssemblyInformationalVersion("0.2.2+df8d39406b40794ef117da5e46f6c30bf3b4d0c8")]
[assembly: AssemblyProduct("DpsMeter")]
[assembly: AssemblyTitle("DpsMeter")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.2.2.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace DpsMeter
{
public class DpsDisplay
{
[CompilerGenerated]
private DpsTracker <tracker>P;
[CompilerGenerated]
private ConfigEntry<bool> <configShowDamageNumbers>P;
[CompilerGenerated]
private ConfigEntry<bool> <updateOnHits>P;
[CompilerGenerated]
private TMP_Text <statsPanel>P;
private const float MoveAmount = 50f;
private const float FadeDuration = 2f;
private const float ScaleFactor = 1.2f;
private List<TMP_Text> objects;
public DpsDisplay(DpsTracker tracker, ConfigEntry<bool> configShowDamageNumbers, ConfigEntry<bool> updateOnHits, TMP_Text statsPanel)
{
<tracker>P = tracker;
<configShowDamageNumbers>P = configShowDamageNumbers;
<updateOnHits>P = updateOnHits;
<statsPanel>P = statsPanel;
objects = new List<TMP_Text>();
base..ctor();
}
public IEnumerator OnDamage(EffectHitData data, float value, bool internalDamage)
{
if (<configShowDamageNumbers>P.Value)
{
Color color = (Color)(internalDamage ? new Color(0.5f, 1f, 1f, 1f) : Color.white);
yield return SpawnText(data.hitPos, $"{value:0.##}", color);
}
}
public IEnumerator OnInaccurateParry(EffectHitData data, float parryTime, float requiredParryTime, float spamLevel)
{
if (<configShowDamageNumbers>P.Value)
{
float num = parryTime - requiredParryTime;
string text = $"Missed by {num * 1000f:F0}ms";
if (spamLevel > 0f)
{
text += $" (Spam {spamLevel})";
}
if (requiredParryTime == 0f)
{
text = "Parry Spam";
}
yield return SpawnText(data.hitPos, text, new Color(1f, 0f, 0.28f, 1f));
}
}
private IEnumerator SpawnText(Vector3 pos, string str, Color color)
{
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
TMP_Text text = CreateDamageText(str, color);
objects.Add(text);
yield return AnimateText(text, pos);
objects.Remove(text);
}
public void Update()
{
List<HitData> recentHits = <tracker>P.RecentHits;
if (recentHits.Count == 0)
{
<statsPanel>P.text = "";
return;
}
float num = recentHits.Sum((HitData hit) => hit.Value);
float totalDamage = recentHits.Sum((HitData hit) => hit.Value);
List<(string, float, float, int)> list = (from x in recentHits.GroupBy((HitData hit) => hit.Type, (HitData hit) => hit.Value, delegate(string type, IEnumerable<float> @group)
{
float num4 = @group.Sum();
float num5 = num4 / totalDamage * 100f;
int item2 = (int)num5;
return (type, num4, num5, item2);
})
where x.groupSum > 0f
select x).ToList();
int count = 100 - list.Sum<(string, float, float, int)>(((string type, float groupSum, float percentage, int percentageFloored) x) => x.percentageFloored);
foreach (var item3 in (from x in list.Select<(string, float, float, int), (int, float)>(((string type, float groupSum, float percentage, int percentageFloored) x, int index) => (index, x.percentage - (float)x.percentageFloored))
orderby x.fract descending
select x).Take(count))
{
int item = item3.Item1;
(string, float, float, int) value = list[item];
value.Item4 = list[item].Item4 + 1;
list[item] = value;
}
string arg = GeneralExtensions.Join<string>(from x in list
orderby x.groupSum descending
select $"{x.type}: {x.groupSum:0.##} {x.percentageFloored}%", (Func<string, string>)null, "\n");
<statsPanel>P.text = $"Total: {totalDamage:0.##} 100%\n{arg}";
float num2 = ((!<updateOnHits>P.Value) ? <tracker>P.RunningTime : ((recentHits.Count <= 0) ? 0f : (ListExtensions.Last<HitData>(recentHits).Time - ListExtensions.First<HitData>(recentHits).Time)));
if (num2 != 0f)
{
float num3 = num / num2;
TMP_Text obj = <statsPanel>P;
obj.text += $"\nDPS: {num3:F1}";
}
}
public void OnDestroy()
{
foreach (TMP_Text @object in objects)
{
Object.Destroy((Object)(object)((Component)@object).gameObject);
}
}
private static Vector2 WorldToCanvas(Vector3 worldPosition)
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
Transform transform = ((Component)NineSolsAPICore.FullscreenCanvas).transform;
Vector3 val = SingletonBehaviour<CameraManager>.Instance.camera2D.GameCamera.WorldToScreenPoint(worldPosition);
Vector2 result = default(Vector2);
RectTransformUtility.ScreenPointToLocalPointInRectangle(((Component)transform).GetComponent<RectTransform>(), Vector2.op_Implicit(val), (Camera)null, ref result);
return result;
}
private static TMP_Text CreateDamageText(string str, Color color)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
Transform transform = ((Component)NineSolsAPICore.FullscreenCanvas).transform;
GameObject val = new GameObject();
val.transform.SetParent(transform);
TextMeshProUGUI obj = val.AddComponent<TextMeshProUGUI>();
((TMP_Text)obj).fontSize = 25f;
((TMP_Text)obj).alignment = (TextAlignmentOptions)1026;
((TMP_Text)obj).fontWeight = (FontWeight)700;
((TMP_Text)obj).text = str;
((Graphic)obj).color = color;
RectTransform component = ((Component)obj).GetComponent<RectTransform>();
component.pivot = new Vector2(0.5f, 0f);
component.sizeDelta = new Vector2(200f, 10f);
return (TMP_Text)(object)obj;
}
private static IEnumerator AnimateText(TMP_Text text, Vector3 worldPosition)
{
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
Vector2 anchoredPosition = WorldToCanvas(worldPosition);
RectTransform rectTransform = ((Component)text).GetComponent<RectTransform>();
rectTransform.anchoredPosition = anchoredPosition;
Vector3 targetPositionWorld = worldPosition + new Vector3(0f, 50f, 0f);
float elapsedTime = 0f;
Color originalColor = ((Graphic)text).color;
float originalScale = ((Transform)rectTransform).localScale.x;
while (elapsedTime < 2f)
{
rectTransform.anchoredPosition = WorldToCanvas(Vector3.Lerp(worldPosition, targetPositionWorld, elapsedTime / 2f));
Color color = ((Graphic)text).color;
color.a = Mathf.Lerp(1f, 0f, elapsedTime / 2f);
((Graphic)text).color = color;
float num = Mathf.Lerp(originalScale, 1.2f, elapsedTime / 1f);
if (elapsedTime > 1f)
{
num = Mathf.Lerp(1.2f, originalScale, (elapsedTime - 1f) / 1f);
}
((Transform)rectTransform).localScale = new Vector3(num, num, num);
elapsedTime += Time.deltaTime;
yield return null;
}
((Graphic)text).color = new Color(originalColor.r, originalColor.g, originalColor.b, 0f);
Object.Destroy((Object)(object)((Component)text).gameObject);
}
}
internal static class Extensions
{
public static string Name(this EffectType type)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
if ((type & 0x40000) != 0)
{
return "Heavy";
}
if ((type & 0x20) != 0)
{
return "Talisman Attach";
}
if ((type & 0x2000000) != 0)
{
return "Talisman Explode";
}
if ((type & 0x200) != 0)
{
return "Tai-Chi";
}
return ((object)(EffectType)(ref type)).ToString();
}
}
public enum DpsResetMode
{
ManualResets,
ResetOnEnemyChange,
LockToFirstEnemy
}
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInPlugin("DpsMeter", "DpsMeter", "0.2.2")]
public class DpsMeterMod : BaseUnityPlugin
{
private ConfigEntry<DpsResetMode> configResetMode;
private ConfigEntry<bool> configUpdateOnHits;
private ConfigEntry<bool> configShowDamageNumbers;
private ConfigEntry<KeyboardShortcut> configShortcutPause;
private ConfigEntry<KeyboardShortcut> configShortcutReset;
public static DpsMeterMod Instance;
private Harmony harmony;
private DpsTracker dpsTracker;
private DpsDisplay dpsDisplay;
private GameObject dummy;
public TMP_Text statsPanel;
private void Awake()
{
//IL_0090: Unknown result type (might be due to invalid IL or missing references)
//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
Instance = this;
Log.Init(((BaseUnityPlugin)this).Logger);
RCGLifeCycle.DontDestroyForever(((Component)this).gameObject);
try
{
configResetMode = ((BaseUnityPlugin)this).Config.Bind<DpsResetMode>("General", "Reset Mode", DpsResetMode.LockToFirstEnemy, "When to reset the DPS tracking.\nManual Resets = You have to hit the reset shortcut manually\nLock To First Enemy = After hitting an enemy, only damage to that enemy will be tracked (until manually reset)\nReset On Enemy Change = Switching the enemy automatically resets the DPS tracking");
configUpdateOnHits = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Only update DPS on hits", true, "When enabled, the DPS value is only calculated on every hit. Otherwise, it will continuously adapt as time goes on.");
configShowDamageNumbers = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Show damage numbers", true, "Show floating popup texts when you deal damage");
configShortcutPause = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Shortcuts", "Pause DPS Tracking", KeyboardShortcut.Empty, "Temporarily disable DPS tracking");
configShortcutReset = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Shortcuts", "Reset DPS Tracking", KeyboardShortcut.Empty, "Reset the DPS statistics. Also clears locked in enemy if reset mode is 'Lock To First Enemy'");
statsPanel = CreateStatsPanel();
harmony = Harmony.CreateAndPatchAll(typeof(DpsMeterMod).Assembly, (string)null);
dpsTracker = new DpsTracker(configResetMode);
dpsDisplay = new DpsDisplay(dpsTracker, configShowDamageNumbers, configUpdateOnHits, statsPanel);
KeybindManager.Add((MonoBehaviour)(object)this, (Action)delegate
{
dpsTracker.Pause();
}, (Func<KeyboardShortcut>)(() => configShortcutPause.Value));
KeybindManager.Add((MonoBehaviour)(object)this, (Action)delegate
{
dpsTracker.Reset();
}, (Func<KeyboardShortcut>)(() => configShortcutReset.Value));
((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin DpsMeter is loaded!");
}
catch (Exception ex)
{
ToastManager.Toast((object)ex);
}
}
private static TMP_Text CreateStatsPanel()
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
GameObject val = new GameObject("Stats");
val.transform.SetParent(((Component)NineSolsAPICore.FullscreenCanvas).transform);
TextMeshProUGUI obj = val.AddComponent<TextMeshProUGUI>();
((TMP_Text)obj).alignment = (TextAlignmentOptions)1028;
((TMP_Text)obj).fontSize = 20f;
((Graphic)obj).color = Color.white;
((TMP_Text)obj).text = "";
RectTransform component = ((Component)obj).GetComponent<RectTransform>();
component.anchorMin = new Vector2(1f, 0.5f);
component.anchorMax = new Vector2(1f, 0.5f);
component.pivot = new Vector2(1f, 0f);
component.anchoredPosition = new Vector2(-10f, 10f);
component.sizeDelta = new Vector2((float)Screen.width, 0f);
return (TMP_Text)(object)obj;
}
private void Update()
{
dpsTracker.Update();
dpsDisplay.Update();
}
private void SpawnTrainingDummy()
{
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
Player i = Player.i;
if (i != null)
{
Object.Instantiate<GameObject>(dummy, ((Component)Instance).gameObject.transform).transform.position = ((Component)i).transform.position;
}
}
private void OnDestroy()
{
harmony.UnpatchSelf();
dpsDisplay.OnDestroy();
if (Object.op_Implicit((Object)(object)dummy))
{
Object.Destroy((Object)(object)dummy);
}
if (Object.op_Implicit((Object)(object)statsPanel))
{
Object.Destroy((Object)(object)((Component)statsPanel).gameObject);
}
}
public void OnDamage(EffectHitData hitData, Patches.CurrentHealth before, Patches.CurrentHealth after)
{
float num = before.HealthValue - after.HealthValue;
float num2 = after.InternalInjury - before.InternalInjury;
float num3 = before.TotalHealth - after.TotalHealth;
Log.Info($"Health Before: {before}");
Log.Info($"Health After: {after}");
Log.Info($"Damage: base {num} / internal {num2} / procced {num3}");
if (num3 > 0f)
{
((MonoBehaviour)this).StartCoroutine(dpsDisplay.OnDamage(hitData, num3, internalDamage: false));
}
if (num2 > 0f)
{
((MonoBehaviour)this).StartCoroutine(dpsDisplay.OnDamage(hitData, num2, internalDamage: true));
}
dpsTracker.OnDamage(hitData, num);
}
public void OnInaccurateParry(EffectHitData hitData, float parryTime, float requiredParryTime, float spamLevel)
{
((MonoBehaviour)this).StartCoroutine(dpsDisplay.OnInaccurateParry(hitData, parryTime, requiredParryTime, spamLevel));
}
private static GameObject LoadObjectFromResources(string resourceName, string scenePath, string objectName)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
GameObject val = null;
AssetBundle embeddedAssetBundle = AssemblyUtils.GetEmbeddedAssetBundle(resourceName);
SceneManager.LoadScene(scenePath, (LoadSceneMode)1);
Scene sceneByPath = SceneManager.GetSceneByPath(scenePath);
GameObject[] rootGameObjects = ((Scene)(ref sceneByPath)).GetRootGameObjects();
foreach (GameObject val2 in rootGameObjects)
{
if (((Object)val2).name == objectName)
{
val = Object.Instantiate<GameObject>(val2);
((Object)val).name = "Training Dummy";
RCGLifeCycle.DontDestroyForever(val);
break;
}
Object.Destroy((Object)(object)val2);
}
SceneManager.UnloadSceneAsync(sceneByPath);
embeddedAssetBundle.Unload(true);
if (val == null)
{
ToastManager.Toast((object)embeddedAssetBundle);
ToastManager.Toast((object)sceneByPath);
ToastManager.Toast((object)((Scene)(ref sceneByPath)).GetRootGameObjects().Length);
throw new Exception(objectName + " not found in " + resourceName + "/" + scenePath);
}
return val;
}
}
public record struct HitData(float Time, float Value, string Type, GameObject Owner);
public class DpsTracker
{
[CompilerGenerated]
private ConfigEntry<DpsResetMode> <resetMode>P;
public readonly List<HitData> RecentHits;
public bool Running;
public float RunningTime;
private GameObject? lockedInToOwner;
private readonly Dictionary<string, string> dealerNames;
public DpsTracker(ConfigEntry<DpsResetMode> resetMode)
{
<resetMode>P = resetMode;
RecentHits = new List<HitData>();
Running = true;
dealerNames = new Dictionary<string, string>
{
{ "AttackFront", "Attack" },
{ "Third Attack", "Third Attack" },
{ "ChargedAttackFront", "Charge Attack" },
{ "Foo", "Talisman Attach" },
{ "FooExplode", "Talisman Explode" },
{ "JumpSpinKick", "Tai Chi" },
{ "[Dealer] Internal Damage", "UC" },
{ "--ReflectNode", "Reflect Projectile" },
{ "NormalArrow Shoot 穿雲 Lv1(Clone)", "Bow" },
{ "NormalArrow Shoot 穿雲 Lv2(Clone)", "Bow" },
{ "NormalArrow Shoot 穿雲 Lv3(Clone)", "Bow" },
{ "rayCastDetector", "Bow Arrow" },
{ "Explosion Damage 爆破箭 閃電 lv2(Clone)", "Bow Explosion" },
{ "[最新爆炸]Boom Explosion DamageEffect Sting 鐵蒺藜爆炸傷害(Clone)", "Jiequan Explosion" },
{ "[Jade]AccurateParryReflect", "Hedgehog Jade" }
};
base..ctor();
}
public void Pause()
{
Running = !Running;
ToastManager.Toast((object)$"DPS tracking enabled: {Running}");
}
public void Reset()
{
RecentHits.Clear();
RunningTime = 0f;
lockedInToOwner = null;
ToastManager.Toast((object)"DPS tracking reset");
}
public void Update()
{
if (Running)
{
RunningTime += Time.deltaTime;
}
}
public void OnDamage(EffectHitData data, float value)
{
if (!Running)
{
return;
}
GameObject gameObject = data.receiver.OwnerComponent.gameObject;
switch (<resetMode>P.Value)
{
case DpsResetMode.ResetOnEnemyChange:
if (RecentHits.Count > 0 && (Object)(object)ListExtensions.Last<HitData>(RecentHits).Owner != (Object)(object)gameObject)
{
Reset();
ToastManager.Toast((object)"New enemy, resetting DPS stats");
}
break;
case DpsResetMode.LockToFirstEnemy:
if (lockedInToOwner == null)
{
lockedInToOwner = gameObject;
}
else if ((Object)(object)gameObject != (Object)(object)lockedInToOwner)
{
return;
}
break;
default:
throw new ArgumentOutOfRangeException();
case DpsResetMode.ManualResets:
break;
}
string value2 = null;
Transform val = ((Component)data.dealer).transform;
while (Object.op_Implicit((Object)(object)val) && !dealerNames.TryGetValue(((Object)val).name, out value2))
{
val = val.parent;
}
if (value2 == null)
{
Log.Warning("Unknown attack name: " + ObjectUtils.ObjectPath(((Component)data.dealer).gameObject));
value2 = ((Object)data.dealer).name;
}
RecentHits.Add(new HitData(Time.time, value, value2, gameObject));
}
}
internal static class Log
{
private static ManualLogSource logSource;
internal static void Init(ManualLogSource logSource)
{
Log.logSource = logSource;
}
internal static void Debug(object data)
{
logSource.LogDebug(data);
}
internal static void Error(object data)
{
logSource.LogError(data);
}
internal static void Fatal(object data)
{
logSource.LogFatal(data);
}
internal static void Info(object data)
{
logSource.LogInfo(data);
}
internal static void Message(object data)
{
logSource.LogMessage(data);
}
internal static void Warning(object data)
{
logSource.LogWarning(data);
}
}
[HarmonyPatch]
public class Patches
{
public record struct CurrentHealth(float HealthValue, float InternalInjury, bool wasLockPostureInvincible)
{
public float TotalHealth => HealthValue + InternalInjury;
internal static CurrentHealth From(PostureSystem health)
{
return new CurrentHealth(health.CurrentHealthValue, health.CurrentInternalInjury, health.BindMonster.monsterStat.IsLockPostureInvincible);
}
internal void Restore(PostureSystem health)
{
if (wasLockPostureInvincible)
{
health.PostureValue = health.MaxPostureValue;
health.CurrentInternalInjury = 0f;
health.BindMonster.monsterStat.IsLockPostureInvincible = true;
}
}
}
private static FieldRef<PlayerInputCommandQueue, Dictionary<PlayerAction, List<float>>> actionDict = AccessTools.FieldRefAccess<PlayerInputCommandQueue, Dictionary<PlayerAction, List<float>>>("actionDict");
private static FieldRef<PlayerParryState, float[]> spamDatas = AccessTools.FieldRefAccess<PlayerParryState, float[]>("spamDatas");
[HarmonyPatch(typeof(PlayerParryState), "Parried")]
[HarmonyPrefix]
public static void Parried(ref PlayerParryState __instance, EffectHitData hitData)
{
Player i = Player.i;
List<float> list = actionDict.Invoke(i.inputCommandQueue)[i.playerInput.gameplayActions.Parry];
float num;
if (list.Count <= 0)
{
num = -1f;
}
else
{
num = list[list.Count - 1];
}
float num2 = num;
float[] array = spamDatas.Invoke(__instance);
int spamLevel = __instance.spamLevel;
float num3 = Time.time - num2;
if (!__instance.IsAlwaysAccurate && !i.IsInQTETutorial && !(num3 < array[spamLevel]))
{
DpsMeterMod.Instance.OnInaccurateParry(hitData, num3, array[spamLevel], spamLevel);
}
}
[HarmonyPatch(typeof(MonsterBase), "HittedByPlayerDecreasePosture")]
[HarmonyPrefix]
private static void OnDamagePrefix(MonsterBase __instance, out CurrentHealth __state)
{
__state = CurrentHealth.From(__instance.postureSystem);
if (__instance.monsterStat.IsLockPostureInvincible)
{
__instance.monsterStat.IsLockPostureInvincible = false;
}
}
[HarmonyPatch(typeof(MonsterBase), "HittedByPlayerDecreasePosture")]
[HarmonyPostfix]
private static void OnDamage(MonsterBase __instance, CurrentHealth __state, EffectHitData hitData)
{
CurrentHealth after = CurrentHealth.From(__instance.postureSystem);
__state.Restore(__instance.postureSystem);
DpsMeterMod.Instance.OnDamage(hitData, __state, after);
}
[HarmonyPatch(typeof(MonsterBase), "InternalInjuryVirtual")]
[HarmonyPrefix]
private static void OnDamageInternalPrefix(MonsterBase __instance, out CurrentHealth __state)
{
__state = CurrentHealth.From(__instance.postureSystem);
}
[HarmonyPatch(typeof(MonsterBase), "InternalInjuryVirtual")]
[HarmonyPrefix]
private static void OnDamageInternal(MonsterBase __instance, CurrentHealth __state, EffectHitData data)
{
CurrentHealth after = CurrentHealth.From(__instance.postureSystem);
__state.Restore(__instance.postureSystem);
DpsMeterMod.Instance.OnDamage(data, __state, after);
}
}
public static class PluginInfo
{
public const string PLUGIN_GUID = "DpsMeter";
public const string PLUGIN_NAME = "DpsMeter";
public const string PLUGIN_VERSION = "0.2.2";
}
}