using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BlackMagicAPI.Enums;
using BlackMagicAPI.Helpers;
using BlackMagicAPI.Managers;
using BlackMagicAPI.Modules.Spells;
using FishNet.Object;
using Steamworks;
using UnityEngine;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("TesticularTorsion")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("TesticularTorsion")]
[assembly: AssemblyCopyright("Copyright © 2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("6b93a891-7200-4c3e-80f9-8570b94fd510")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace TesticularTorsion;
[BepInPlugin("com.owls8.testiculartorsion", "Testicular Torsion", "1.1.0")]
[BepInProcess("MageArena.exe")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class TesticularTorsion : BaseUnityPlugin
{
internal class TesticularTorsionData : SpellData
{
public override SpellType SpellType => (SpellType)0;
public override string Name => "Testicular Torsion";
public override float Cooldown => 15f;
public override Color GlowColor => Color.magenta;
public override Texture2D GetMainTexture()
{
string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string text = Path.Combine(directoryName, ((SpellData)this).Name.Replace(" ", "") + "_Main.png");
if (File.Exists(text))
{
return Utils.LoadTextureFromDisk(text);
}
return Utils.LoadTextureFromResources(Assembly.GetExecutingAssembly(), "BlackMagicAPI.Resources.Items.Item_Main.png");
}
public override Texture2D GetEmissionTexture()
{
string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string text = Path.Combine(directoryName, ((SpellData)this).Name.Replace(" ", "") + "_Emission.png");
if (File.Exists(text))
{
return Utils.LoadTextureFromDisk(text);
}
return Utils.LoadTextureFromResources(Assembly.GetExecutingAssembly(), "BlackMagicAPI.Resources.Items.Item_Emission.png");
}
}
internal class TesticularTorsionLogic : SpellLogic
{
[CompilerGenerated]
private sealed class <FlashbangEffect>d__5 : IEnumerator<object>, IDisposable, IEnumerator
{
private int <>1__state;
private object <>2__current;
public float fadeInDuration;
public float holdDuration;
public float fadeOutDuration;
public float maxAlpha;
private GameObject <canvasObj>5__1;
private Canvas <canvas>5__2;
private CanvasScaler <scaler>5__3;
private GameObject <imageObj>5__4;
private RectTransform <rect>5__5;
private Image <image>5__6;
private float <elapsed>5__7;
private float <alpha>5__8;
private float <alpha>5__9;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <FlashbangEffect>d__5(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<canvasObj>5__1 = null;
<canvas>5__2 = null;
<scaler>5__3 = null;
<imageObj>5__4 = null;
<rect>5__5 = null;
<image>5__6 = null;
<>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
//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
//IL_00b3: Expected O, but got Unknown
//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
//IL_0109: Unknown result type (might be due to invalid IL or missing references)
//IL_011a: Unknown result type (might be due to invalid IL or missing references)
//IL_0150: Unknown result type (might be due to invalid IL or missing references)
//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
//IL_020c: Unknown result type (might be due to invalid IL or missing references)
//IL_021e: Unknown result type (might be due to invalid IL or missing references)
//IL_0228: Expected O, but got Unknown
//IL_0284: Unknown result type (might be due to invalid IL or missing references)
//IL_02e8: Unknown result type (might be due to invalid IL or missing references)
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<canvasObj>5__1 = new GameObject("FlashbangCanvas");
<canvas>5__2 = <canvasObj>5__1.AddComponent<Canvas>();
<canvas>5__2.renderMode = (RenderMode)0;
<canvas>5__2.sortingOrder = 9999;
<scaler>5__3 = <canvasObj>5__1.AddComponent<CanvasScaler>();
<scaler>5__3.uiScaleMode = (ScaleMode)1;
<canvasObj>5__1.AddComponent<GraphicRaycaster>();
<imageObj>5__4 = new GameObject("FlashbangImage");
<imageObj>5__4.transform.SetParent(<canvasObj>5__1.transform, false);
<rect>5__5 = <imageObj>5__4.AddComponent<RectTransform>();
<rect>5__5.anchorMin = Vector2.zero;
<rect>5__5.anchorMax = Vector2.one;
<rect>5__5.offsetMin = Vector2.zero;
<rect>5__5.offsetMax = Vector2.zero;
<image>5__6 = <imageObj>5__4.AddComponent<Image>();
((Graphic)<image>5__6).color = new Color(1f, 1f, 1f, 0f);
<elapsed>5__7 = 0f;
goto IL_01dc;
case 1:
<>1__state = -1;
goto IL_01dc;
case 2:
<>1__state = -1;
<elapsed>5__7 = 0f;
break;
case 3:
{
<>1__state = -1;
break;
}
IL_01dc:
if (<elapsed>5__7 < fadeInDuration)
{
<alpha>5__8 = Mathf.Lerp(0f, maxAlpha, <elapsed>5__7 / fadeInDuration);
((Graphic)<image>5__6).color = new Color(1f, 1f, 1f, <alpha>5__8);
<elapsed>5__7 += Time.deltaTime;
<>2__current = null;
<>1__state = 1;
return true;
}
((Graphic)<image>5__6).color = new Color(1f, 1f, 1f, maxAlpha);
<>2__current = (object)new WaitForSeconds(holdDuration);
<>1__state = 2;
return true;
}
if (<elapsed>5__7 < fadeOutDuration)
{
<alpha>5__9 = Mathf.Lerp(maxAlpha, 0f, <elapsed>5__7 / fadeOutDuration);
((Graphic)<image>5__6).color = new Color(1f, 1f, 1f, <alpha>5__9);
<elapsed>5__7 += Time.deltaTime;
<>2__current = null;
<>1__state = 3;
return true;
}
((Graphic)<image>5__6).color = new Color(1f, 1f, 1f, 0f);
Object.Destroy((Object)(object)<canvasObj>5__1);
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();
}
}
[CompilerGenerated]
private sealed class <SubtractTesticularTorsionDebuff>d__4 : IEnumerator<object>, IDisposable, IEnumerator
{
private int <>1__state;
private object <>2__current;
public float duration;
private FieldInfo <stewspeedboostField>5__1;
private PlayerMovement[] <allPlayers>5__2;
private PlayerMovement[] <>s__3;
private int <>s__4;
private PlayerMovement <player>5__5;
private float <currentValue>5__6;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <SubtractTesticularTorsionDebuff>d__4(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<stewspeedboostField>5__1 = null;
<allPlayers>5__2 = null;
<>s__3 = null;
<player>5__5 = null;
<>1__state = -2;
}
private bool MoveNext()
{
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Expected O, but got Unknown
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<>2__current = (object)new WaitForSeconds(duration);
<>1__state = 1;
return true;
case 1:
<>1__state = -1;
<stewspeedboostField>5__1 = typeof(PlayerMovement).GetField("stewspeedboost", BindingFlags.Instance | BindingFlags.NonPublic);
if (<stewspeedboostField>5__1 != null)
{
<allPlayers>5__2 = Object.FindObjectsByType<PlayerMovement>((FindObjectsSortMode)0);
<>s__3 = <allPlayers>5__2;
for (<>s__4 = 0; <>s__4 < <>s__3.Length; <>s__4++)
{
<player>5__5 = <>s__3[<>s__4];
if (((NetworkBehaviour)<player>5__5).IsOwner)
{
<currentValue>5__6 = (float)<stewspeedboostField>5__1.GetValue(<player>5__5);
<stewspeedboostField>5__1.SetValue(<player>5__5, <currentValue>5__6 + 6f);
break;
}
<player>5__5 = null;
}
<>s__3 = null;
<allPlayers>5__2 = null;
}
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();
}
}
[CompilerGenerated]
private sealed class <TesticularTorsionDamageTicks>d__3 : IEnumerator<object>, IDisposable, IEnumerator
{
private int <>1__state;
private object <>2__current;
public float duration;
public PlayerMovement targetMovement;
public int castingLevel;
private float <damageCooldown>5__1;
private float <damageTimer>5__2;
private float <elapsedTime>5__3;
private float <damageAmount>5__4;
private float <delta>5__5;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <TesticularTorsionDamageTicks>d__3(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<damageCooldown>5__1 = 0.3f;
<damageTimer>5__2 = 0f;
<elapsedTime>5__3 = 0f;
<damageAmount>5__4 = 1f;
break;
case 1:
<>1__state = -1;
<delta>5__5 = Time.deltaTime;
<elapsedTime>5__3 += <delta>5__5;
<damageTimer>5__2 -= <delta>5__5;
break;
}
if (<elapsedTime>5__3 < duration)
{
if (<damageTimer>5__2 <= 0f && targetMovement.currentSpeed > 0.5f)
{
targetMovement.NonRpcDamagePlayer(<damageAmount>5__4 + 0.1f * (float)castingLevel, (GameObject)null, "testiculartorsion");
<damageTimer>5__2 = <damageCooldown>5__1;
}
<>2__current = null;
<>1__state = 1;
return true;
}
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();
}
}
[CompilerGenerated]
private sealed class <TesticularTorsionEffect>d__2 : IEnumerator<object>, IDisposable, IEnumerator
{
private int <>1__state;
private object <>2__current;
public PlayerMovement targetMovement;
public int castingLevel;
private FieldInfo <stewspeedboostField>5__1;
private float <debuffDuration>5__2;
private float <currentValue>5__3;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <TesticularTorsionEffect>d__2(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<stewspeedboostField>5__1 = null;
<>1__state = -2;
}
private bool MoveNext()
{
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
targetMovement.NonRpcDamagePlayer(12f + (float)(3 * castingLevel), (GameObject)null, "testiculartorsion");
if (((NetworkBehaviour)targetMovement).IsOwner)
{
<stewspeedboostField>5__1 = typeof(PlayerMovement).GetField("stewspeedboost", BindingFlags.Instance | BindingFlags.NonPublic);
if (<stewspeedboostField>5__1 != null)
{
<currentValue>5__3 = (float)<stewspeedboostField>5__1.GetValue(targetMovement);
<stewspeedboostField>5__1.SetValue(targetMovement, <currentValue>5__3 - 6f);
}
<debuffDuration>5__2 = 5f;
((MonoBehaviour)targetMovement).StartCoroutine(SubtractTesticularTorsionDebuff(<debuffDuration>5__2));
((MonoBehaviour)targetMovement).StartCoroutine(TesticularTorsionDamageTicks(<debuffDuration>5__2, targetMovement, castingLevel));
((MonoBehaviour)targetMovement).StartCoroutine(FlashbangEffect());
PlayFlashSoundLocally();
<stewspeedboostField>5__1 = null;
}
if (affectedPlayers.ContainsKey(targetMovement))
{
affectedPlayers[targetMovement] = false;
}
<>2__current = null;
<>1__state = 1;
return true;
case 1:
<>1__state = -1;
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();
}
}
public static Dictionary<PlayerMovement, bool> affectedPlayers = new Dictionary<PlayerMovement, bool>();
public override void CastSpell(GameObject playerObj, PageController page, Vector3 spawnPos, Vector3 viewDirectionVector, int castingLevel)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
PlayerMovement component = playerObj.GetComponent<PlayerMovement>();
if ((Object)(object)component == (Object)null)
{
return;
}
GameObject[] array = GameObject.FindGameObjectsWithTag("Player");
Vector3 position = playerObj.transform.position;
Vector3 forward = playerObj.transform.forward;
string personaName = SteamFriends.GetPersonaName();
PlayerMovement val = null;
PlayerMovement[] array2 = Object.FindObjectsByType<PlayerMovement>((FindObjectsSortMode)0);
PlayerMovement[] array3 = array2;
foreach (PlayerMovement val2 in array3)
{
if (val2.playername == personaName)
{
val = val2;
break;
}
}
GameObject[] array4 = array;
foreach (GameObject val3 in array4)
{
if ((Object)(object)val3 == (Object)(object)playerObj)
{
continue;
}
float num = Vector3.Distance(position, val3.transform.position);
if (num <= 15f)
{
PlayerMovement component2 = val3.GetComponent<PlayerMovement>();
if ((Object)(object)component2 != (Object)null)
{
affectedPlayers[component2] = true;
((MonoBehaviour)component2).StartCoroutine(TesticularTorsionEffect(component2, castingLevel));
PlayTesticularTorsionSound(component2, 5f);
}
}
}
}
[IteratorStateMachine(typeof(<TesticularTorsionEffect>d__2))]
public static IEnumerator TesticularTorsionEffect(PlayerMovement targetMovement, int castingLevel)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <TesticularTorsionEffect>d__2(0)
{
targetMovement = targetMovement,
castingLevel = castingLevel
};
}
[IteratorStateMachine(typeof(<TesticularTorsionDamageTicks>d__3))]
private static IEnumerator TesticularTorsionDamageTicks(float duration, PlayerMovement targetMovement, int castingLevel)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <TesticularTorsionDamageTicks>d__3(0)
{
duration = duration,
targetMovement = targetMovement,
castingLevel = castingLevel
};
}
[IteratorStateMachine(typeof(<SubtractTesticularTorsionDebuff>d__4))]
private static IEnumerator SubtractTesticularTorsionDebuff(float duration)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <SubtractTesticularTorsionDebuff>d__4(0)
{
duration = duration
};
}
[IteratorStateMachine(typeof(<FlashbangEffect>d__5))]
public static IEnumerator FlashbangEffect(float fadeInDuration = 0.07f, float holdDuration = 0.1f, float fadeOutDuration = 2f, float maxAlpha = 0.8f)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <FlashbangEffect>d__5(0)
{
fadeInDuration = fadeInDuration,
holdDuration = holdDuration,
fadeOutDuration = fadeOutDuration,
maxAlpha = maxAlpha
};
}
private static void PlayFlashSoundLocally()
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Expected O, but got Unknown
if ((Object)(object)flashSound != (Object)null)
{
GameObject val = new GameObject("FlashbangLocalSound");
AudioSource val2 = val.AddComponent<AudioSource>();
val2.clip = flashSound;
val2.volume = 0.9f;
val2.spatialBlend = 0f;
val2.Play();
Object.Destroy((Object)(object)val, flashSound.length + 0.1f);
}
}
private static void PlayTesticularTorsionSound(PlayerMovement player, float duration)
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Expected O, but got Unknown
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_009e: Unknown result type (might be due to invalid IL or missing references)
try
{
if ((Object)(object)stretchSound != (Object)null)
{
GameObject val = new GameObject("TesticularTorsionAudio");
val.transform.position = ((Component)player).transform.position;
AudioSource val2 = val.AddComponent<AudioSource>();
val2.clip = stretchSound;
val2.volume = 0.6f;
val2.spatialBlend = 1f;
val2.rolloffMode = (AudioRolloffMode)1;
val2.minDistance = 5f;
val2.maxDistance = 50f;
val2.Play();
for (float num = 0f; num < duration; num += Time.deltaTime)
{
val.transform.position = ((Component)player).transform.position;
}
float num2 = stretchSound.length + 0.1f;
Object.Destroy((Object)(object)val, num2);
}
}
catch (Exception ex)
{
Debug.LogError((object)("[TesticularTorsion] Error playing sound: " + ex.Message));
}
}
}
private static AssetBundle testicularTorsionBundle;
public static AudioClip stretchSound;
public static AudioClip flashSound;
private void Awake()
{
LoadTesticularTorsionAssets();
BlackMagicManager.RegisterSpell((BaseUnityPlugin)(object)this, typeof(TesticularTorsionData), typeof(TesticularTorsionLogic));
((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin com.owls8.testiculartorsion is loaded!");
}
private void LoadTesticularTorsionAssets()
{
try
{
string directoryName = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
string text = Path.Combine(directoryName, "testebundle");
if (File.Exists(text))
{
testicularTorsionBundle = AssetBundle.LoadFromFile(text);
if ((Object)(object)testicularTorsionBundle != (Object)null)
{
stretchSound = testicularTorsionBundle.LoadAsset<AudioClip>("testesStretch");
if ((Object)(object)stretchSound == (Object)null)
{
Debug.LogWarning((object)"[TesticularTorsion] Could not find 'stretch' audio clip in AssetBundle");
}
flashSound = testicularTorsionBundle.LoadAsset<AudioClip>("flashbang");
if ((Object)(object)flashSound == (Object)null)
{
Debug.LogWarning((object)"[TesticularTorsion] Could not find 'flash' audio clip in AssetBundle");
}
}
else
{
Debug.LogError((object)"[TesticularTorsion] Failed to load AssetBundle");
}
}
else
{
Debug.LogError((object)("[TesticularTorsion] AssetBundle file does not exist at path: " + text));
}
}
catch (Exception ex)
{
Debug.LogError((object)("[TesticularTorsion] Error loading AssetBundle: " + ex.Message));
}
}
}