Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Slapsong v2.0.1
BepInEx/plugins/Slapsong.dll
Decompiled 2 weeks agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; 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 GlobalEnums; using HarmonyLib; using InControl; using Microsoft.CodeAnalysis; using Silksong.AssetHelper.ManagedAssets; using Silksong.UnityHelper.Util; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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] [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; } } } [BepInPlugin("lagerthon.Slapsong", "Slapsong", "2.0.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Slapsong : BaseUnityPlugin { internal static ManualLogSource Log; public static Slapsong Instance; private ConfigEntry<KeyCode> slapKey; public static ConfigEntry<int> dmg; public static ConfigEntry<float> recoil; public static ConfigEntry<float> recoilSpeed; public static ConfigEntry<float> recoilDuration; private static ConfigEntry<float> slapVol; private static ConfigEntry<float> runToSlap; public static ManagedAsset<GameObject> nuuGO; public static GameObject nuu; private static bool nuuBool; public static bool isSlapHit; private AudioClip cachedSlapAudio; private AudioSource slapAudioSource; public static BoxCollider2D slapBoxFront; public static BoxCollider2D slapBoxBack; private HeroController hero; private bool isHeroSlapping = false; private static bool attackCancelRequested; private bool queuedSlap = false; public static bool slapHasHitEnemy; private bool stickSlapArmed = true; private tk2dSpriteAnimationClip cloakLessSlap; private bool cloakLessSlapLoaded = false; public const string AnimationName = "CloaklessSlap"; public static Sprite[] Frames { get; private set; } public static tk2dSpriteAnimationClip Clip { get; private set; } private void Awake() { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Expected O, but got Unknown //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Expected O, but got Unknown //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Expected O, but got Unknown //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Expected O, but got Unknown //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Expected O, but got Unknown //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Expected O, but got Unknown //IL_0205: Unknown result type (might be due to invalid IL or missing references) Instance = this; Log = ((BaseUnityPlugin)this).Logger; slapKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Input", "SlapKey", (KeyCode)108, "Key to slap."); dmg = ((BaseUnityPlugin)this).Config.Bind<int>("Slap", "Damage dealt to enemies", 9999, new ConfigDescription("Damage dealt to enemies", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 9999), Array.Empty<object>())); recoil = ((BaseUnityPlugin)this).Config.Bind<float>("Slap", "Enemy recoil strength", 2f, new ConfigDescription("Enemy recoil strength upon slap", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f), Array.Empty<object>())); recoilSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Slap", "Enemy recoil speed", 30f, new ConfigDescription("Enemy recoil speed upon slap", (AcceptableValueBase)(object)new AcceptableValueRange<float>(15f, 30f), Array.Empty<object>())); recoilDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Slap", "Enemy recoil duration", 0.15f, new ConfigDescription("Enemy recoil duration upon slap", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.15f, 0.5f), Array.Empty<object>())); slapVol = ((BaseUnityPlugin)this).Config.Bind<float>("Slap", "Slap Volume", 1f, new ConfigDescription("Volume of the slap", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 1f), Array.Empty<object>())); runToSlap = ((BaseUnityPlugin)this).Config.Bind<float>("Slap", "Run to slap time (secs)", 0.2f, new ConfigDescription("Time that Hornet takes in stopping if slap is triggered while running", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.3f), Array.Empty<object>())); nuuGO = ManagedAsset<GameObject>.FromSceneAsset("halfway_01", "_NPCs/Hunter Fan Control/Nuu"); GameObject val = new GameObject("SlapsongAudio"); Object.DontDestroyOnLoad((Object)(object)val); slapAudioSource = val.AddComponent<AudioSource>(); slapAudioSource.playOnAwake = false; SceneManager.sceneLoaded += OnSceneLoaded; LoadCloakLessSlap(((BaseUnityPlugin)this).Info.Location); new Harmony("lagerthon.Slapsong").PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Slapsong loaded."); } private void Update() { //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)hero == (Object)null) { return; } if (isHeroSlapping) { HeroActions inputActions = ManagerSingleton<InputHandler>.Instance.inputActions; bool flag = ((OneAxisInputControl)inputActions.Attack).WasPressed || ((OneAxisInputControl)inputActions.Dash).WasPressed || ((OneAxisInputControl)inputActions.Cast).WasPressed || ((OneAxisInputControl)inputActions.QuickCast).WasPressed || ((OneAxisInputControl)inputActions.Taunt).WasPressed || ((OneAxisInputControl)inputActions.Jump).WasPressed || ((OneAxisInputControl)inputActions.Left).WasPressed || ((OneAxisInputControl)inputActions.Right).WasPressed; bool keyDown = Input.GetKeyDown(slapKey.Value); if (flag) { attackCancelRequested = true; } if (keyDown) { queuedSlap = true; attackCancelRequested = true; } } if (Input.GetKeyDown(slapKey.Value) && !isHeroSlapping && !hero.controlReqlinquished) { ((MonoBehaviour)this).StartCoroutine(Slap(hero)); } float rightStickX = GetRightStickX(); if (hero.cState.facingRight ? (rightStickX > 0.5f) : (rightStickX < -0.5f)) { if (stickSlapArmed && !hero.controlReqlinquished) { stickSlapArmed = false; if (isHeroSlapping) { queuedSlap = true; attackCancelRequested = true; } else { ((MonoBehaviour)this).StartCoroutine(Slap(hero)); } } } else if (Mathf.Abs(rightStickX) < 0.25f) { stickSlapArmed = true; } } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) hero = HeroController.instance; if ((Object)(object)hero == (Object)null) { return; } if (!cloakLessSlapLoaded) { tk2dSpriteAnimator component = ((Component)hero).GetComponent<tk2dSpriteAnimator>(); if (!component.Library.clips.Any((tk2dSpriteAnimationClip c) => c.name == "CloaklessSlap")) { component.Library.clips = component.Library.clips.Append(Clip).ToArray(); cloakLessSlap = component.GetClipByName("CloaklessSlap"); } cloakLessSlapLoaded = true; } SlapHitBox(hero); if ((Object)(object)hero != (Object)null && !nuuBool) { ((MonoBehaviour)this).StartCoroutine(Nuu()); } if (!PlayerData.instance.CaravanLechSpaAcceptState) { return; } GameObject val = GameObject.Find("Caravan Lech"); if (!((Object)(object)val == (Object)null)) { Transform val2 = val.transform.Find("Caravan Lech Wounded"); if ((Object)(object)val2 != (Object)null) { GameObject val3 = Object.Instantiate<GameObject>(((Component)val2).gameObject, val.transform.position, val.transform.rotation); ((Object)val3).name = "Caravan Lech Wounded Clone"; val3.layer = LayerMask.NameToLayer("Enemies"); CircleCollider2D val4 = val3.AddComponent<CircleCollider2D>(); val4.radius = 1f; ((Collider2D)val4).offset = new Vector2(0f, 0.5f); val3.transform.SetParent((Transform)null); val.SetActive(false); } } } private float GetRightStickX() { InputDevice val = ManagerSingleton<InputHandler>.Instance?.gameController; if (val == null) { return 0f; } return ((OneAxisInputControl)val.RightStickX).Value; } public static bool IsCloakLess() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) return PlayerData.instance.CurrentCrestID == ((object)(CrestType)7/*cast due to .constrained prefix*/).ToString(); } private IEnumerator Nuu() { nuuBool = true; ((ManagedAssetBase<GameObject>)(object)nuuGO).Load(); yield return (object)new WaitUntil((Func<bool>)(() => ((ManagedAssetBase<GameObject>)(object)nuuGO).IsLoaded)); nuu = ManagedAssetExtensions.InstantiateAsset<GameObject>(nuuGO); Object.DontDestroyOnLoad((Object)(object)nuu); nuu.SetActive(false); CacheSlapAudio(); } private void CacheSlapAudio() { if ((Object)(object)cachedSlapAudio != (Object)null) { return; } AudioClip[] array = Resources.FindObjectsOfTypeAll<AudioClip>(); foreach (AudioClip val in array) { if (((val != null) ? ((Object)val).name : null) == "hornet_slap_B_2") { cachedSlapAudio = val; break; } } } private IEnumerator Slap(HeroController hero) { if ((int)hero.hero_state != 1 && (int)hero.hero_state != 2) { yield break; } if (queuedSlap) { yield return (object)new WaitForSeconds(0.1f); queuedSlap = false; } isHeroSlapping = true; attackCancelRequested = false; slapHasHitEnemy = false; CancelSlapOnDamage.heroDamaged = false; HeroAnimationController heroAnim = ((Component)hero).GetComponent<HeroAnimationController>(); Rigidbody2D rb = ((Component)hero).GetComponent<Rigidbody2D>(); if ((Object)(object)rb != (Object)null && (int)hero.hero_state == 2) { Vector2 startVelocity = rb.velocity; float stopTime = runToSlap.Value; float t = 0f; while (t < stopTime) { if (CancelSlapOnDamage.heroDamaged || attackCancelRequested) { EndSlap(); yield break; } t += Time.deltaTime; float progress = Mathf.Clamp01(t / stopTime); rb.velocity = Vector2.Lerp(startVelocity, Vector2.zero, progress); yield return null; } rb.velocity = Vector2.zero; } hero.IgnoreInput(); hero.StopAnimationControl(); ((Behaviour)slapBoxFront).enabled = false; ((Behaviour)slapBoxBack).enabled = false; if (IsCloakLess()) { heroAnim.PlayClipForced(cloakLessSlap.name); } else { heroAnim.PlayClipForced("Idle Slap"); } tk2dSpriteAnimationClip animClip = heroAnim.animator.CurrentClip; float totalLength = heroAnim.GetClipDuration(animClip.name); float slapBoxStart = totalLength * 0.25f; float slapBoxMid = totalLength * 0.4f; float slapBoxEnd = totalLength * 0.85f; float elapsed = 0f; while (heroAnim.animator.IsPlaying(animClip) && elapsed < totalLength) { if (CancelSlapOnDamage.heroDamaged || attackCancelRequested) { EndSlap(); yield break; } elapsed += Time.deltaTime; ((Behaviour)slapBoxFront).enabled = elapsed >= slapBoxStart && elapsed < slapBoxMid; ((Behaviour)slapBoxBack).enabled = elapsed >= slapBoxMid && elapsed < slapBoxEnd; yield return null; } EndSlap(); } private void EndSlap() { ((Behaviour)slapBoxFront).enabled = false; ((Behaviour)slapBoxBack).enabled = false; hero.AcceptInput(); hero.StartAnimationControl(); if (queuedSlap) { attackCancelRequested = false; ((MonoBehaviour)this).StartCoroutine(Slap(hero)); } isHeroSlapping = false; attackCancelRequested = false; } public void PlaySlapSound() { slapAudioSource.PlayOneShot(cachedSlapAudio, slapVol.Value); } private void SlapHitBox(HeroController hero) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_0049: 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_006e: Expected O, but got Unknown //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)slapBoxFront != (Object)null) || !((Object)(object)slapBoxBack != (Object)null)) { GameObject val = new GameObject("SlapHitbox"); val.transform.SetParent(((Component)hero).transform, false); val.transform.localPosition = Vector3.zero; Rigidbody2D val2 = val.AddComponent<Rigidbody2D>(); val2.bodyType = (RigidbodyType2D)1; GameObject val3 = new GameObject("Slap Hit Box"); val3.transform.SetParent(((Component)hero).transform, false); slapBoxFront = val3.AddComponent<BoxCollider2D>(); ((Collider2D)slapBoxFront).isTrigger = true; ((Behaviour)slapBoxFront).enabled = false; slapBoxFront.size = new Vector2(1.25f, 0.5f); ((Collider2D)slapBoxFront).offset = new Vector2(-0.675f, 0f); slapBoxBack = val3.AddComponent<BoxCollider2D>(); ((Collider2D)slapBoxBack).isTrigger = true; ((Behaviour)slapBoxBack).enabled = false; slapBoxBack.size = new Vector2(1.25f, 0.5f); ((Collider2D)slapBoxBack).offset = new Vector2(0.575f, 0f); val3.AddComponent<SlapDamageHandler>(); } } public static void LoadCloakLessSlap(string modPath) { string directoryName = Path.GetDirectoryName(modPath); string path = Path.Combine(directoryName, "CloakLessSlap"); Frames = (from f in Directory.GetFiles(path, "*.png") orderby int.Parse(Path.GetFileNameWithoutExtension(f)) select SpriteUtil.LoadSpriteFromFile(f, 64f, (Vector2?)null, false)).ToArray(); Clip = Tk2dUtil.CreateTk2dAnimationClip("CloaklessSlap", 15, (IEnumerable<Sprite>)Frames, (WrapMode)2, 0, 64f); } } public class SlapDamageHandler : MonoBehaviour { public bool isFront; private string slapEvent; private float dir; private static FieldInfo recoilDurationField; private static void SetEnemyRecoilDuration(Recoil recoil, float duration) { if (recoilDurationField == null) { recoilDurationField = typeof(Recoil).GetField("recoilDuration", BindingFlags.Instance | BindingFlags.NonPublic); } if (recoilDurationField != null) { recoilDurationField.SetValue(recoil, duration); } } private void OnTriggerEnter2D(Collider2D other) { //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_024c: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) bool flag = (Object)(object)HeroController.instance != (Object)null && HeroController.instance.cState.facingRight; if (((Object)((Component)((Component)other).transform.root).gameObject).name == "Caravan Lech Wounded Clone") { GameObject gameObject = ((Component)((Component)other).transform.root).gameObject; PlayMakerFSM[] componentsInChildren = gameObject.GetComponentsInChildren<PlayMakerFSM>(true); PlayMakerFSM val = ((IEnumerable<PlayMakerFSM>)componentsInChildren).FirstOrDefault((Func<PlayMakerFSM, bool>)((PlayMakerFSM f) => f.FsmName == "Wounded Behaviour")); if ((Object)(object)val != (Object)null) { isFront = ((Behaviour)Slapsong.slapBoxFront).enabled; if (flag) { slapEvent = (isFront ? "HIT_RIGHT" : "HIT_LEFT"); } else { slapEvent = (isFront ? "HIT_LEFT" : "HIT_RIGHT"); } val.SendEvent(slapEvent); Slapsong.Instance.PlaySlapSound(); Slapsong.slapHasHitEnemy = true; } } else { if (((Component)other).gameObject.layer != LayerMask.NameToLayer("Enemies")) { return; } HealthManager component = ((Component)other).GetComponent<HealthManager>(); if (!((Object)(object)component == (Object)null)) { Recoil component2 = ((Component)other).GetComponent<Recoil>(); if ((Object)(object)component2 != (Object)null) { SetEnemyRecoilDuration(component2, Slapsong.recoilDuration.Value); } component2.SetRecoilSpeed(Slapsong.recoilSpeed.Value); isFront = ((Behaviour)Slapsong.slapBoxFront).enabled; if (flag) { dir = (isFront ? 0f : 180f); } else { dir = (isFront ? 180f : 0f); } HitInstance val2 = new HitInstance { Source = ((Component)this).gameObject, DamageDealt = Slapsong.dmg.Value, Multiplier = 1f, AttackType = (AttackTypes)1, HitEffectsType = (EffectsTypes)1, Direction = dir, IgnoreInvulnerable = false, MagnitudeMultiplier = Slapsong.recoil.Value + (float)Slapsong.dmg.Value / 9999f }; Slapsong.isSlapHit = true; component.Hit(val2); Slapsong.isSlapHit = false; Slapsong.Instance.PlaySlapSound(); Slapsong.slapHasHitEnemy = true; } } } } [HarmonyPatch(typeof(HeroController), "HeroDamaged")] internal class CancelSlapOnDamage { public static bool heroDamaged; private static void Prefix() { heroDamaged = true; } }