using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Photon.Pun;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("PalThrow")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("PalThrow")]
[assembly: AssemblyCopyright("Copyright © 2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("15a56718-251a-4536-8cc0-c9f38bd1b995")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace PalThrow;
[BepInPlugin("com.lamia.palthrow", "PalThrow", "1.6.5")]
public class Plugin : BaseUnityPlugin
{
public static ConfigEntry<float> MaxChargeTime;
public static ConfigEntry<float> StaminaCost;
public static ConfigEntry<float> MinThrowStrength;
public static ConfigEntry<float> MaxThrowStrength;
public static ConfigEntry<float> SpeedPerStrength;
public static ConfigEntry<float> ThrowLoft;
public static ConfigEntry<float> AirDrag;
public static ConfigEntry<float> AirTransition;
public static ConfigEntry<KeyCode> ThrowKey;
internal static ManualLogSource Log;
private Harmony harmony;
private void Awake()
{
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: Expected O, but got Unknown
//IL_0098: Unknown result type (might be due to invalid IL or missing references)
//IL_00a2: Expected O, but got Unknown
//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
//IL_00df: Expected O, but got Unknown
//IL_0112: Unknown result type (might be due to invalid IL or missing references)
//IL_011c: Expected O, but got Unknown
//IL_014f: Unknown result type (might be due to invalid IL or missing references)
//IL_0159: Expected O, but got Unknown
//IL_018c: Unknown result type (might be due to invalid IL or missing references)
//IL_0196: Expected O, but got Unknown
//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
//IL_01d3: Expected O, but got Unknown
//IL_0206: Unknown result type (might be due to invalid IL or missing references)
//IL_0210: Expected O, but got Unknown
//IL_021b: Unknown result type (might be due to invalid IL or missing references)
//IL_0225: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
ThrowKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "ThrowKey", (KeyCode)120, "Hold to charge a throw, release to throw.");
MaxChargeTime = ((BaseUnityPlugin)this).Config.Bind<float>("General", "MaxChargeTime", 3f, new ConfigDescription("Full charge time in seconds.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f), Array.Empty<object>()));
StaminaCost = ((BaseUnityPlugin)this).Config.Bind<float>("General", "StaminaCost", 1f, new ConfigDescription("Stamina drain multiplier while charging.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>()));
MinThrowStrength = ((BaseUnityPlugin)this).Config.Bind<float>("Throwing", "MinThrowStrength", 1.5f, new ConfigDescription("Strength at minimum charge.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 8f), Array.Empty<object>()));
MaxThrowStrength = ((BaseUnityPlugin)this).Config.Bind<float>("Throwing", "MaxThrowStrength", 4f, new ConfigDescription("Strength at full charge.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 8f), Array.Empty<object>()));
SpeedPerStrength = ((BaseUnityPlugin)this).Config.Bind<float>("Throwing", "SpeedPerStrength", 6f, new ConfigDescription("Launch metres per second for each strength unit. Default charge range gives 3 to 15 m/s.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f), Array.Empty<object>()));
ThrowLoft = ((BaseUnityPlugin)this).Config.Bind<float>("Throwing", "ThrowLoft", 1.25f, new ConfigDescription("Small upward lift for horizontal throws. Fades out when aiming straight up or down.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3f), Array.Empty<object>()));
AirDrag = ((BaseUnityPlugin)this).Config.Bind<float>("Throwing", "AirDrag", 0.8f, new ConfigDescription("Initial linear air resistance per second. Only removes speed; gravity and angular damping remain active.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 3f), Array.Empty<object>()));
AirTransition = ((BaseUnityPlugin)this).Config.Bind<float>("Throwing", "AirTransition", 1.8f, new ConfigDescription("Seconds to blend back to normal PEAK air drag, beginning immediately at launch.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 3f), Array.Empty<object>()));
harmony = new Harmony("com.lamia.palthrow");
harmony.PatchAll(typeof(Plugin).Assembly);
Character[] array = Object.FindObjectsByType<Character>((FindObjectsSortMode)0);
foreach (Character character in array)
{
Attach(character);
}
Log.LogInfo((object)"PalThrow loaded. Charge-based launch with gradual air drag. Multiplayer participants need the same build.");
}
internal static void Attach(Character character)
{
if (!Object.op_Implicit((Object)(object)((Component)character).GetComponent<PalThrowManager>()))
{
((Component)character).gameObject.AddComponent<PalThrowManager>();
}
PhotonView component = ((Component)character).GetComponent<PhotonView>();
if (Object.op_Implicit((Object)(object)component))
{
component.RefreshRpcMonoBehaviourCache();
}
}
private void OnDestroy()
{
Harmony obj = harmony;
if (obj != null)
{
obj.UnpatchSelf();
}
PalThrowManager[] array = Object.FindObjectsByType<PalThrowManager>((FindObjectsSortMode)0);
foreach (PalThrowManager palThrowManager in array)
{
palThrowManager.CancelFlight();
}
}
}
[HarmonyPatch(typeof(Character), "Awake")]
internal static class AttachThrowManager
{
private static void Postfix(Character __instance)
{
Plugin.Attach(__instance);
}
}
public class PalThrowManager : MonoBehaviourPun
{
private Character character;
private Character chargedTarget;
private float chargeTime;
private float lastThrowTime = float.NegativeInfinity;
private bool isCharging;
private int throwSequence;
private int lastReceivedSequence;
private float lastAcceptedThrow = float.NegativeInfinity;
private bool inThrowFlight;
private float flightStarted;
private float flightStrength;
private void Awake()
{
character = ((Component)this).GetComponent<Character>();
}
private void CancelCharge()
{
isCharging = false;
chargeTime = 0f;
chargedTarget = null;
}
internal void CancelFlight()
{
inThrowFlight = false;
}
private void OnDisable()
{
CancelCharge();
CancelFlight();
}
private void OnDestroy()
{
CancelFlight();
}
private void Update()
{
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
//IL_020f: Unknown result type (might be due to invalid IL or missing references)
//IL_021f: Unknown result type (might be due to invalid IL or missing references)
//IL_0223: Unknown result type (might be due to invalid IL or missing references)
//IL_0228: Unknown result type (might be due to invalid IL or missing references)
//IL_022f: Unknown result type (might be due to invalid IL or missing references)
//IL_0234: Unknown result type (might be due to invalid IL or missing references)
//IL_0239: Unknown result type (might be due to invalid IL or missing references)
//IL_023b: Unknown result type (might be due to invalid IL or missing references)
//IL_0245: 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_02cd: Unknown result type (might be due to invalid IL or missing references)
if (!Object.op_Implicit((Object)(object)character) || !character.IsLocal)
{
return;
}
if (Time.time < lastThrowTime + 3f)
{
CancelCharge();
return;
}
Character characterStandingOnMe = GetCharacterStandingOnMe();
if (!Object.op_Implicit((Object)(object)characterStandingOnMe))
{
CancelCharge();
return;
}
if (isCharging && (Object)(object)chargedTarget != (Object)(object)characterStandingOnMe)
{
CancelCharge();
}
if (Input.GetKey(Plugin.ThrowKey.Value))
{
if (!isCharging)
{
isCharging = true;
chargedTarget = characterStandingOnMe;
chargeTime = 0f;
}
chargeTime = Mathf.Min(chargeTime + Time.deltaTime, Plugin.MaxChargeTime.Value);
float num = Plugin.StaminaCost.Value * 0.2f * Time.deltaTime;
if (character.GetTotalStamina() < num)
{
CancelCharge();
character.PassOutInstantly();
}
else
{
character.AddStamina(0f - num);
character.data.sinceUseStamina = 0f;
}
}
else if (isCharging)
{
float num2 = Mathf.Clamp01(chargeTime / Mathf.Max(0.1f, Plugin.MaxChargeTime.Value));
float num3 = Mathf.Lerp(Plugin.MinThrowStrength.Value, Plugin.MaxThrowStrength.Value, num2);
float num4 = Mathf.Clamp(num3 * Plugin.SpeedPerStrength.Value, 0f, 30f);
Vector3 normalized = ((Vector3)(ref character.data.lookDirection)).normalized;
Vector3 val = Vector3.ClampMagnitude(BodyVelocity(character), 8f);
float num5 = Plugin.ThrowLoft.Value * (1f - Mathf.Abs(normalized.y));
Vector3 val2 = Vector3.ClampMagnitude(normalized * num4 + Vector3.up * num5 + val, 35f);
if (Finite(val2) && ((Vector3)(ref normalized)).sqrMagnitude > 0.5f && Object.op_Implicit((Object)(object)characterStandingOnMe.refs.view) && characterStandingOnMe.refs.view.Owner != null)
{
((MonoBehaviourPun)this).photonView.RPC("ThrowCharacterRpc", characterStandingOnMe.refs.view.Owner, new object[4]
{
characterStandingOnMe.refs.view.ViewID,
val2,
num4,
++throwSequence
});
lastThrowTime = Time.time;
}
CancelCharge();
}
}
private Character GetCharacterStandingOnMe()
{
foreach (Character allCharacter in Character.AllCharacters)
{
if (Object.op_Implicit((Object)(object)allCharacter) && (Object)(object)allCharacter != (Object)(object)character && !allCharacter.data.isRopeClimbing && (Object)(object)allCharacter.data.lastStoodOnPlayer == (Object)(object)character && allCharacter.data.sinceStandOnPlayer <= 0.3f)
{
return allCharacter;
}
}
return null;
}
private static bool Finite(Vector3 value)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: 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_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
return !float.IsNaN(value.x) && !float.IsInfinity(value.x) && !float.IsNaN(value.y) && !float.IsInfinity(value.y) && !float.IsNaN(value.z) && !float.IsInfinity(value.z);
}
private static Vector3 BodyVelocity(Character who)
{
//IL_0001: 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_00ac: Unknown result type (might be due to invalid IL or missing references)
//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: 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_0069: Unknown result type (might be due to invalid IL or missing references)
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
//IL_0073: Unknown result type (might be due to invalid IL or missing references)
//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
Vector3 val = Vector3.zero;
float num = 0f;
foreach (Bodypart part in who.refs.ragdoll.partList)
{
if (Object.op_Implicit((Object)(object)part.Rig) && !part.Rig.isKinematic)
{
val += part.Rig.linearVelocity * part.Rig.mass;
num += part.Rig.mass;
}
}
return (num > 0f) ? (val / num) : Vector3.zero;
}
[PunRPC]
public void ThrowCharacterRpc(int viewID, Vector3 launch, float speed, int sequence, PhotonMessageInfo info)
{
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
//IL_0243: Unknown result type (might be due to invalid IL or missing references)
//IL_0248: 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)
if (!Object.op_Implicit((Object)(object)character) || !Object.op_Implicit((Object)(object)((MonoBehaviourPun)this).photonView) || info.Sender == null || info.Sender != ((MonoBehaviourPun)this).photonView.Owner || sequence <= lastReceivedSequence || !Finite(launch) || ((Vector3)(ref launch)).magnitude > 35.01f || float.IsNaN(speed) || float.IsInfinity(speed) || speed < 0f || speed > 30f)
{
return;
}
double num = PhotonNetwork.Time - ((PhotonMessageInfo)(ref info)).SentServerTime;
if (num < -0.1 || num > 1.0)
{
return;
}
Character val = null;
foreach (Character allCharacter in Character.AllCharacters)
{
if (Object.op_Implicit((Object)(object)allCharacter) && Object.op_Implicit((Object)(object)allCharacter.refs.view) && allCharacter.refs.view.ViewID == viewID)
{
val = allCharacter;
break;
}
}
PalThrowManager palThrowManager = default(PalThrowManager);
if (!Object.op_Implicit((Object)(object)val) || !val.IsLocal || (Object)(object)val == (Object)(object)character || val.data.isRopeClimbing || (Object)(object)val.data.lastStoodOnPlayer != (Object)(object)character || val.data.sinceStandOnPlayer > 0.65f || !((Component)val).TryGetComponent<PalThrowManager>(ref palThrowManager) || Time.time < palThrowManager.lastAcceptedThrow + 0.5f)
{
return;
}
lastReceivedSequence = sequence;
palThrowManager.lastAcceptedThrow = Time.time;
Vector3 val2 = BodyVelocity(val);
if (!Finite(val2))
{
return;
}
Vector3 val3 = launch - val2;
foreach (Bodypart part in val.refs.ragdoll.partList)
{
if (Object.op_Implicit((Object)(object)part.Rig) && !part.Rig.isKinematic)
{
Rigidbody rig = part.Rig;
rig.linearVelocity += val3;
}
}
val.data.lastStoodOnPlayer = null;
val.data.sinceStandOnPlayer = 1f;
palThrowManager.inThrowFlight = speed > 0.5f;
palThrowManager.flightStarted = Time.time;
palThrowManager.flightStrength = Mathf.InverseLerp(0.5f, 12f, speed);
}
internal bool TryFlightRetention(float nativeRetention, out float retention)
{
retention = nativeRetention;
if (!inThrowFlight || !Object.op_Implicit((Object)(object)character) || !character.IsLocal)
{
return false;
}
float num = Mathf.Max(0f, Time.time - flightStarted);
float num2 = Mathf.Max(0.2f, Plugin.AirTransition.Value);
if (num >= num2 || character.data.isRopeClimbing || character.data.isClimbing || (num > 0.2f && character.data.isGrounded) || character.data.currentRagdollControll < 0.3f)
{
CancelFlight();
return false;
}
float num3 = flightStrength * (1f - Mathf.Clamp01(num / num2));
float num4 = Mathf.Exp((0f - Plugin.AirDrag.Value) * Time.fixedDeltaTime);
retention = Mathf.Lerp(nativeRetention, num4, num3);
return true;
}
}
[HarmonyPatch(typeof(Bodypart), "Drag")]
internal static class ThrownPlayerAirDrag
{
private static void Prefix(Bodypart __instance, Character ___character, float drag, bool ignoreRagdoll, out Vector3 __state)
{
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_0089: Unknown result type (might be due to invalid IL or missing references)
//IL_009b: 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)
__state = Vector3.zero;
PalThrowManager palThrowManager = default(PalThrowManager);
if (!ignoreRagdoll && !(drag <= 0f) && !(drag >= 1f) && Object.op_Implicit((Object)(object)___character) && ___character.IsLocal && ((Component)___character).TryGetComponent<PalThrowManager>(ref palThrowManager) && Object.op_Implicit((Object)(object)__instance.Rig) && !__instance.Rig.isKinematic)
{
float num = Mathf.Lerp(1f, drag, ___character.data.currentRagdollControll);
if (palThrowManager.TryFlightRetention(num, out var retention))
{
__state = __instance.Rig.linearVelocity * Mathf.Max(0f, retention - num);
}
}
}
private static void Postfix(Bodypart __instance, Vector3 __state)
{
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
if (Object.op_Implicit((Object)(object)__instance.Rig) && !__instance.Rig.isKinematic && ((Vector3)(ref __state)).sqrMagnitude > 0f)
{
__instance.Rig.AddForce(__state, (ForceMode)2);
}
}
}