using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using CanvasUtil;
using HarmonyLib;
using HutongGames.PlayMaker;
using HutongGames.PlayMaker.Actions;
using Microsoft.CodeAnalysis;
using TeamCherry.Localization;
using UnityEngine;
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("StunDisplay")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0+f897177a31604af2dd50165940e0c61825579d31")]
[assembly: AssemblyProduct("StunDisplay")]
[assembly: AssemblyTitle("StunDisplay")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/Clazex/Silksong.StunDisplay")]
[assembly: NeutralResourcesLanguage("EN")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.0.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 BepInEx
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
[Conditional("CodeGeneration")]
internal sealed class BepInAutoPluginAttribute : Attribute
{
public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
{
}
}
}
namespace BepInEx.Preloader.Core.Patching
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
[Conditional("CodeGeneration")]
internal sealed class PatcherAutoPluginAttribute : Attribute
{
public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
{
}
}
}
namespace StunDisplay
{
internal static class Configs
{
internal static ConfigEntry<TextAnchor> Location { get; private set; }
internal static ConfigEntry<int> FontSize { get; private set; }
internal static ConfigEntry<float> Padding { get; private set; }
internal static void Bind(ConfigFile config)
{
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Expected O, but got Unknown
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: Expected O, but got Unknown
Location = config.Bind<TextAnchor>("Style", "Location", (TextAnchor)7, "Location of the text");
FontSize = config.Bind<int>("Style", "FontSize", 24, new ConfigDescription("Font size", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 48), Array.Empty<object>()));
Padding = config.Bind<float>("Style", "Padding", 10f, new ConfigDescription("Padding", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 40f), Array.Empty<object>()));
}
}
internal sealed class EnemyStunInfo
{
private readonly HealthManager hm;
private readonly Fsm stunFsm;
private bool initialHiding = true;
private readonly FsmFloat hit = FsmFloat.op_Implicit(0f);
private readonly int max;
private readonly int comboMax;
private readonly float comboTime;
private readonly Wait comboWait;
private readonly bool hasComboBonus = true;
private readonly LocalisedString? name;
private StunState State
{
get
{
switch (stunFsm.ActiveStateName)
{
case "In Combo":
case "Continue Combo":
return StunState.InCombo;
case "Stun End":
case "Stun":
case "Dazed Effect":
case "Stunned":
case "Quick End":
return StunState.Stunned;
case "Stop":
case "Stop Daze Effect 2":
case "Stop Daze Effect 3":
case "Unstun Increment":
case "Reset":
return StunState.Disabled;
default:
return StunState.Idle;
}
}
}
private float ComboTimeLeft
{
get
{
if (State != StunState.InCombo)
{
return 0f;
}
return comboTime - comboWait.timer;
}
}
internal bool IsDead
{
get
{
if (!((Object)(object)hm == (Object)null))
{
return hm.isDead;
}
return true;
}
}
internal EnemyStunInfo(HealthManager hm)
{
//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
//IL_00bd: Expected O, but got Unknown
//IL_0101: Unknown result type (might be due to invalid IL or missing references)
this.hm = hm;
stunFsm = hm.stunControlFsm.Fsm;
FsmVariables variables = stunFsm.Variables;
hit = variables.GetFsmFloat("Hits Total");
max = variables.GetFsmInt("Stun Hit Max").Value;
comboMax = variables.GetFsmInt("Stun Combo").Value;
comboTime = variables.GetFsmFloat("Combo Time").Value;
comboWait = (Wait)stunFsm.GetState("In Combo").Actions[4];
hasComboBonus = comboMax != max;
if ((Object)(object)hm.enemyDeathEffects != (Object)null && (Object)(object)hm.enemyDeathEffects.journalRecord != (Object)null)
{
name = hm.enemyDeathEffects.journalRecord.DisplayName;
}
}
internal bool CheckInitialHiding()
{
if (!initialHiding)
{
return false;
}
if (!hm.IsInvincible)
{
return initialHiding = false;
}
return true;
}
internal StringBuilder BuildString(StringBuilder sb, bool includeName = false)
{
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
if (includeName)
{
string? value;
if (!name.HasValue)
{
value = ((Object)hm).name;
}
else
{
LocalisedString value2 = name.Value;
value = ((object)(LocalisedString)(ref value2)).ToString();
}
sb.Append(value).Append(' ');
}
sb.Append(Lang.Stun).Append(Lang.Colon).AppendFormat("{0:F2}", hit)
.Append('/')
.Append(max);
if (hasComboBonus)
{
sb.Append(' ').Append(Lang.Combo).Append(Lang.Colon)
.Append(comboMax)
.Append(' ')
.AppendFormat("{0:F2}", ComboTimeLeft)
.Append('/')
.Append(comboTime);
}
switch (State)
{
case StunState.Stunned:
sb.Append(Lang.StunStateStunned);
break;
case StunState.Disabled:
sb.Append(Lang.StunStateDisabled);
break;
}
return sb;
}
public override string ToString()
{
return BuildString(new StringBuilder(), includeName: true).ToString();
}
}
internal static class Lang
{
internal static string Colon => Get("Colon");
internal static string Stun => Get("Stun");
internal static string Combo => Get("Combo");
internal static string StunStateStunned => Get("StunStateStunned");
internal static string StunStateDisabled => Get("StunStateDisabled");
private static string Get(string key)
{
return Language.Get(key, "Mods.dev.clazex.stundisplay");
}
}
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInPlugin("dev.clazex.stundisplay", "StunDisplay", "0.1.0")]
public sealed class StunDisplayPlugin : BaseUnityPlugin
{
public const string Id = "dev.clazex.stundisplay";
public static StunDisplayPlugin Instance { get; private set; }
internal static ManualLogSource Logger { get; private set; }
private Harmony Harmony { get; } = new Harmony("dev.clazex.stundisplay");
public static string Name => "StunDisplay";
public static string Version => "0.1.0";
private void Awake()
{
Instance = this;
Logger = ((BaseUnityPlugin)this).Logger;
Configs.Bind(((BaseUnityPlugin)this).Config);
Harmony.PatchAll(typeof(StunDisplayPlugin));
Logger.LogInfo((object)("Plugin " + Name + " (dev.clazex.stundisplay) v" + Version + " has loaded!"));
}
private void OnDestroy()
{
Logger.LogWarning((object)"Unloading in release build");
Harmony.UnpatchSelf();
Logger.LogInfo((object)("Plugin " + Name + " (dev.clazex.stundisplay) v" + Version + " has unloaded!"));
}
[HarmonyPatch(typeof(HeroController), "Start")]
[HarmonyWrapSafe]
[HarmonyPostfix]
private static void Setup()
{
StunHud.Setup();
}
[HarmonyPatch(typeof(HealthManager), "Start")]
[HarmonyWrapSafe]
[HarmonyPostfix]
private static void AddEnemy(HealthManager __instance)
{
if (!__instance.isDead && Object.op_Implicit((Object)(object)__instance.stunControlFsm))
{
StunHud.AddEnemy(__instance);
}
}
}
[RequireComponent(typeof(RectTransform), typeof(Text))]
internal sealed class StunHud : MonoBehaviour
{
[CompilerGenerated]
private sealed class <>c__DisplayClass8_0
{
public GameManager gm;
internal bool <AddEnemyCoro>b__0()
{
return gm.HasFinishedEnteringScene;
}
}
[CompilerGenerated]
private sealed class <AddEnemyCoro>d__8 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
public HealthManager hm;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <AddEnemyCoro>d__8(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Expected O, but got Unknown
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<>2__current = (object)new WaitUntil((Func<bool>)new <>c__DisplayClass8_0
{
gm = GameManager.instance
}.<AddEnemyCoro>b__0);
<>1__state = 1;
return true;
case 1:
<>1__state = -1;
<>2__current = null;
<>1__state = 2;
return true;
case 2:
<>1__state = -1;
enemies.Add(new EnemyStunInfo(hm));
StunDisplayPlugin.Logger.LogDebug((object)("Adding enemy: " + ((Object)hm).name));
RemoveDeadEnemy();
return false;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
private static StunHud? instance = null;
private static readonly List<EnemyStunInfo> enemies = new List<EnemyStunInfo>();
private RectTransform rt;
private Text text;
internal static StunHud Instance
{
get
{
if (!((Object)(object)instance != (Object)null))
{
throw new InvalidOperationException("instance not present");
}
return instance;
}
}
private static bool MultiEnemies => enemies.Count > 1;
internal static void Setup()
{
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_006e: Expected O, but got Unknown
if ((Object)(object)instance != (Object)null)
{
StunDisplayPlugin.Logger.LogDebug((object)"HUD already existed");
return;
}
StunDisplayPlugin.Logger.LogDebug((object)"Creating HUD");
GameObject obj = CanvasUtil.CreateCanvas((RenderMode)0, new Vector2(1920f, 1080f));
((Object)obj).name = "Stun Display HUD";
Object.DontDestroyOnLoad((Object)(object)obj);
GameObject obj2 = CanvasUtil.CreateTextPanel(obj, "", 1, (TextAnchor)7, new RectData(Vector2.zero, Vector2.zero), false);
((Object)obj2).name = "Text Panel";
obj2.AddComponent<StunHud>();
}
internal static void AddEnemy(HealthManager hm)
{
((MonoBehaviour)Instance).StartCoroutine(AddEnemyCoro(hm));
}
[IteratorStateMachine(typeof(<AddEnemyCoro>d__8))]
private static IEnumerator AddEnemyCoro(HealthManager hm)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <AddEnemyCoro>d__8(0)
{
hm = hm
};
}
private static void RemoveDeadEnemy()
{
enemies.RemoveAll((EnemyStunInfo i) => i.IsDead);
}
private void Awake()
{
instance = this;
rt = ((Component)this).GetComponent<RectTransform>();
text = ((Component)this).GetComponent<Text>();
UpdateStyles();
}
private void Update()
{
UpdateStyles();
GameManager unsafeInstance = GameManager.UnsafeInstance;
if ((Object)(object)unsafeInstance == (Object)null)
{
enemies.Clear();
}
else
{
if (unsafeInstance.IsGamePaused())
{
return;
}
RemoveDeadEnemy();
StringBuilder stringBuilder = new StringBuilder();
EnemyStunInfo enemyStunInfo = enemies.FirstOrDefault();
if (enemyStunInfo != null && !enemyStunInfo.CheckInitialHiding())
{
enemyStunInfo.BuildString(stringBuilder, MultiEnemies);
}
foreach (EnemyStunInfo item in enemies.Skip(1))
{
if (!item.CheckInitialHiding())
{
stringBuilder.Append('\t');
item.BuildString(stringBuilder, includeName: true);
}
}
text.text = stringBuilder.ToString();
}
}
private void UpdateStyles()
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: 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_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
text.alignment = Configs.Location.Value;
text.fontSize = Configs.FontSize.Value;
Vector2 val = new Vector2((float)Screen.width, (float)Screen.height) * 1920f / (float)Screen.width;
rt.sizeDelta = val - 2f * Configs.Padding.Value * Vector2.one;
}
}
internal enum StunState
{
Idle,
InCombo,
Stunned,
Disabled
}
}