using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using TMPro;
using UnityEngine;
using UnityEngine.InputSystem;
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("FrogSkill")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.4.0.0")]
[assembly: AssemblyInformationalVersion("1.4.0+0abcb63e9f3a40671d64ab9ddc5449e5f247cc16")]
[assembly: AssemblyProduct("FrogSkill")]
[assembly: AssemblyTitle("FrogSkill")]
[assembly: AssemblyVersion("1.4.0.0")]
[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;
}
}
}
namespace FrogSkill
{
public sealed class CustomTongueMode : MonoBehaviour, ITongueMode
{
private const string FireRpc = "RPCA_FrogSkillFire";
private const string MissRpc = "RPCA_FrogSkillMiss";
private const string ReleaseRpc = "RPCA_FrogSkillRelease";
private const float TongueTravelDuration = 0.25f;
private const float FrogTargetTurnDuration = 0.5f;
private const float NetworkMaxDistance = 65f;
private Character _caster;
private TongueContext _context;
private Character? _target;
private Rigidbody? _targetRig;
private LineRenderer? _line;
private Material? _lineMaterial;
private float _firedAt;
private float _pullStartedAt;
private Vector3 _missEndpoint;
private bool _missActive;
private bool _pulling;
private ModConfig Config => Plugin.Instance.Settings;
bool ITongueMode.CanRelease => (Object)(object)_target != (Object)null;
bool ITongueMode.IsBusy
{
get
{
if (!((Object)(object)_target != (Object)null))
{
return _missActive;
}
return true;
}
}
private void Awake()
{
_caster = ((Component)this).GetComponent<Character>();
_context = new TongueContext(_caster);
CreateTongueVisual();
}
private void Update()
{
if ((Object)(object)_target != (Object)null && !IsValidActiveTarget())
{
ReleaseOrClear();
}
UpdateTongueVisual();
}
bool ITongueMode.TryFire()
{
//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
if (!_caster.IsLocal || (Object)(object)Plugin.Instance == (Object)null || !Config.Enabled.Value || (Object)(object)_target != (Object)null || _missActive || !_context.CanCasterAttack() || !_context.TryGetAim(Config.MaxDistance.Value, Config.AimForgivenessDegrees.Value, out Character target, out Vector3 endpoint))
{
return false;
}
if ((Object)(object)target != (Object)null)
{
if (!FrogPullProfile.TryGet(Plugin.Instance.ModLogger, out FrogPullProfile _))
{
return false;
}
((MonoBehaviourPun)_caster).photonView.RPC("RPCA_FrogSkillFire", (RpcTarget)0, new object[1] { ((MonoBehaviourPun)target).photonView.ViewID });
}
else
{
((MonoBehaviourPun)_caster).photonView.RPC("RPCA_FrogSkillMiss", (RpcTarget)0, new object[1] { endpoint });
}
return true;
}
void ITongueMode.Release()
{
if (_caster.IsLocal && (Object)(object)_target != (Object)null)
{
SendRelease();
}
}
private void FixedUpdate()
{
//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_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
//IL_006b: Unknown result type (might be due to invalid IL or missing references)
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
//IL_00a4: 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_00c7: Unknown result type (might be due to invalid IL or missing references)
//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
//IL_00da: Unknown result type (might be due to invalid IL or missing references)
//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
//IL_0105: 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_0180: Unknown result type (might be due to invalid IL or missing references)
//IL_0182: Unknown result type (might be due to invalid IL or missing references)
//IL_0184: Unknown result type (might be due to invalid IL or missing references)
//IL_018e: Unknown result type (might be due to invalid IL or missing references)
//IL_0193: Unknown result type (might be due to invalid IL or missing references)
//IL_0195: Unknown result type (might be due to invalid IL or missing references)
//IL_0197: Unknown result type (might be due to invalid IL or missing references)
//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
if (!_pulling || (Object)(object)_target == (Object)null || (Object)(object)_targetRig == (Object)null)
{
return;
}
if ((Object)(object)Plugin.Instance == (Object)null || !Config.Enabled.Value || !IsValidActiveTarget())
{
ReleaseOrClear();
return;
}
Vector3 mouthPosition = _context.GetMouthPosition();
Vector3 val = mouthPosition - _target.Center;
float magnitude = ((Vector3)(ref val)).magnitude;
if (!FrogPullProfile.TryGet(Plugin.Instance.ModLogger, out FrogPullProfile profile))
{
ReleaseOrClear();
return;
}
Vector3 val2 = ((magnitude > 0.001f) ? (val / magnitude) : Vector3.zero);
float num = profile.PullStrengthCurve.Evaluate(magnitude);
Vector3 val3 = val2 * Config.PullForce.Value * num;
Vector3 val4 = Vector3.up * Mathf.Clamp(val.y, 0f, profile.MaxLiftDistance) * Config.LiftForce.Value;
_target.refs.movement.ApplyExtraDrag(Config.ExtraDragOther.Value, true);
_target.data.sinceGrounded = Mathf.Clamp(_target.data.sinceGrounded, 0f, 1f);
if (((MonoBehaviourPun)_caster).photonView.IsMine)
{
_target.AddForceToBodyPart(_targetRig, (val3 + val4) * 0.2f, val3 + val4);
float num2 = Mathf.Max(Time.fixedDeltaTime, Config.MaxHookDuration.Value - 0.5f);
if (Vector3.Distance(mouthPosition, _targetRig.position) < Config.StopDistance.Value || Time.time - _pullStartedAt > num2)
{
SendRelease();
}
}
}
[PunRPC]
public void RPCA_FrogSkillFire(int targetViewId, PhotonMessageInfo info)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_006c: 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)
if (IsOwnerMessage(info.Sender) && !((Object)(object)_target != (Object)null))
{
PhotonView val = PhotonView.Find(targetViewId);
Character val2 = (((Object)(object)val == (Object)null) ? null : ((Component)val).GetComponent<Character>());
if (_context.IsPermittedTarget(val2) && !((Object)(object)Plugin.Instance == (Object)null) && FrogPullProfile.TryGet(Plugin.Instance.ModLogger, out FrogPullProfile _) && !(Vector3.Distance(_caster.Center, val2.Center) > 65f))
{
ClearMiss();
_target = val2;
_targetRig = val2.refs.ragdoll.partDict[(BodypartType)2].Rig;
_firedAt = Time.time;
_pulling = false;
((Renderer)_line).enabled = true;
}
}
}
[PunRPC]
public void RPCA_FrogSkillMiss(Vector3 endpoint, PhotonMessageInfo info)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: 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_0037: Unknown result type (might be due to invalid IL or missing references)
if (IsOwnerMessage(info.Sender) && !((Object)(object)_target != (Object)null) && !(Vector3.Distance(_caster.Center, endpoint) > 65f))
{
_missEndpoint = endpoint;
_firedAt = Time.time;
_missActive = true;
((Renderer)_line).enabled = true;
}
}
[PunRPC]
public void RPCA_FrogSkillRelease(PhotonMessageInfo info)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
if (IsOwnerMessage(info.Sender))
{
ClearTarget();
}
}
private bool IsValidActiveTarget()
{
if (_context.IsPermittedTarget(_target) && (Object)(object)_targetRig != (Object)null)
{
return !_caster.data.dead;
}
return false;
}
private bool IsOwnerMessage(Player sender)
{
if (sender != null && ((MonoBehaviourPun)_caster).photonView.Owner != null)
{
return sender.ActorNumber == ((MonoBehaviourPun)_caster).photonView.Owner.ActorNumber;
}
return false;
}
private void SendRelease()
{
if ((Object)(object)((MonoBehaviourPun)_caster).photonView != (Object)null)
{
((MonoBehaviourPun)_caster).photonView.RPC("RPCA_FrogSkillRelease", (RpcTarget)0, Array.Empty<object>());
}
}
private void ReleaseOrClear()
{
if (((MonoBehaviourPun)_caster).photonView.IsMine)
{
SendRelease();
}
else
{
ClearTarget();
}
}
private void ClearTarget()
{
if (_pulling && (Object)(object)_target != (Object)null && (Object)(object)_target.refs?.movement != (Object)null)
{
float num = (((Object)(object)Plugin.Instance == (Object)null) ? 0.1f : Config.ExtraDragLetGo.Value);
_target.refs.movement.ApplyExtraDrag(num, true);
_target.data.sinceGrounded = 0f;
}
_pulling = false;
_targetRig = null;
_target = null;
if ((Object)(object)_line != (Object)null && !_missActive)
{
((Renderer)_line).enabled = false;
}
}
private void ClearMiss()
{
_missActive = false;
if ((Object)(object)_line != (Object)null && (Object)(object)_target == (Object)null)
{
((Renderer)_line).enabled = false;
}
}
private void CreateTongueVisual()
{
_line = TongueVisual.CreateLine(((Component)this).transform, "FrogSkill Custom Tongue", out _lineMaterial);
}
private void UpdateTongueVisual()
{
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: 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)
//IL_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_0093: Unknown result type (might be due to invalid IL or missing references)
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)_line == (Object)null || !((Renderer)_line).enabled)
{
return;
}
Vector3 mouthPosition = _context.GetMouthPosition();
if (_missActive)
{
if (TongueVisual.UpdateMiss(_line, _firedAt, mouthPosition, _missEndpoint))
{
ClearMiss();
}
}
else if (!((Object)(object)_target == (Object)null))
{
float num = Mathf.Clamp01((Time.time - _firedAt) / 0.25f);
_line.SetPosition(0, mouthPosition);
_line.SetPosition(1, Vector3.Lerp(mouthPosition, _target.Center, num));
if (num >= 1f && !_pulling)
{
BeginPull();
}
}
}
private void BeginPull()
{
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0064: 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)
if ((Object)(object)_target == (Object)null)
{
return;
}
_pulling = true;
_pullStartedAt = Time.time;
Vector3 val = _context.GetMouthPosition() - _target.Center;
val.y = 0f;
if (((Vector3)(ref val)).sqrMagnitude > 0.0001f)
{
_target.data.lookValues = Vector2.op_Implicit(DirectionToLook(((Vector3)(ref val)).normalized));
}
if (((MonoBehaviourPun)_target).photonView.IsMine)
{
_target.refs.climbing.StopAnyClimbing();
GamefeelHandler instance = GamefeelHandler.instance;
if (instance != null)
{
instance.AddPerlinShake(5f, 0.2f, 15f);
}
}
_target.RPCA_Fall(1f, 0f);
}
private static Vector3 DirectionToLook(Vector3 direction)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//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_000b: 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_0013: 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_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
Quaternion val = Quaternion.LookRotation(direction, Vector3.up);
Vector3 eulerAngles = ((Quaternion)(ref val)).eulerAngles;
while (eulerAngles.x > 180f)
{
eulerAngles.x -= 360f;
}
return new Vector3(eulerAngles.y, 0f - eulerAngles.x, 0f);
}
private void OnDestroy()
{
ClearTarget();
ClearMiss();
if ((Object)(object)_lineMaterial != (Object)null)
{
Object.Destroy((Object)(object)_lineMaterial);
}
}
}
internal sealed class FrogPullProfile
{
private const float RetryInterval = 5f;
private static FrogPullProfile? _cached;
private static float _nextSearchTime;
private static bool _missingLogged;
public AnimationCurve PullStrengthCurve { get; }
public float MaxLiftDistance { get; }
private FrogPullProfile(FrogTongue source)
{
PullStrengthCurve = CloneCurve(source.pullStrengthCurve);
MaxLiftDistance = source.maxLiftDistance;
}
public static bool TryGet(ManualLogSource logger, out FrogPullProfile profile)
{
if (_cached != null)
{
profile = _cached;
return true;
}
if (Time.unscaledTime < _nextSearchTime)
{
profile = null;
return false;
}
_nextSearchTime = Time.unscaledTime + 5f;
FrogTongue[] array = Resources.FindObjectsOfTypeAll<FrogTongue>();
foreach (FrogTongue val in array)
{
if (!((Object)(object)val == (Object)null) && val.pullStrengthCurve != null && val.pullStrengthCurve.length != 0)
{
_cached = new FrogPullProfile(val);
_missingLogged = false;
logger.LogInfo((object)("Captured vanilla FrogTongue drag profile from " + ((Object)((Component)val).gameObject).name + ": " + $"curve keys={_cached.PullStrengthCurve.length}, max lift distance={_cached.MaxLiftDistance}."));
profile = _cached;
return true;
}
}
if (!_missingLogged)
{
_missingLogged = true;
logger.LogWarning((object)"A loaded FrogTongue prefab was not found yet; tongue firing is unavailable until the vanilla pull curve can be captured.");
}
profile = null;
return false;
}
private static AnimationCurve CloneCurve(AnimationCurve source)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Expected O, but got Unknown
return new AnimationCurve(source.keys)
{
preWrapMode = source.preWrapMode,
postWrapMode = source.postWrapMode
};
}
}
internal interface ITongueMode
{
bool IsBusy { get; }
bool CanRelease { get; }
bool TryFire();
void Release();
}
internal sealed class ModConfig
{
public ConfigEntry<bool> Enabled { get; }
public ConfigEntry<string> ActivationPath { get; }
public ConfigEntry<string> ModeSwitchPath { get; }
public ConfigEntry<float> MaxDistance { get; }
public ConfigEntry<float> AimForgivenessDegrees { get; }
public ConfigEntry<float> PullForce { get; }
public ConfigEntry<float> LiftForce { get; }
public ConfigEntry<float> MaxHookDuration { get; }
public ConfigEntry<float> StopDistance { get; }
public ConfigEntry<float> ExtraDragOther { get; }
public ConfigEntry<float> ExtraDragLetGo { get; }
public ConfigEntry<float> Cooldown { get; }
public ModConfig(ConfigFile config)
{
Enabled = config.Bind<bool>("General", "Enabled", true, "Enable the Scout tongue skill.");
ActivationPath = config.Bind<string>("Controls", "Activation Path", "<Keyboard>/g", "Unity Input System control path for firing the tongue.");
ModeSwitchPath = config.Bind<string>("Controls", "Mode Switch Path", "<Keyboard>/c", "Unity Input System control path for switching tongue modes.");
MaxDistance = BindRange(config, "Tongue", "Max Distance", 40f, 5f, 60f, "Maximum target distance in meters. Vanilla FrogTongue default: 40.");
AimForgivenessDegrees = BindRange(config, "Tongue", "Aim Forgiveness Degrees", 3f, 0f, 10f, "Aim-assist cone half-angle in degrees. Direct crosshair hits always take priority; set to 0 for strict targeting.");
PullForce = BindRange(config, "Tongue", "Pull Force", 450f, 0f, 2000f, "Directional pull acceleration before the vanilla distance curve. Current Frog prefab default: 450.");
LiftForce = BindRange(config, "Tongue", "Lift Force", 30f, 0f, 500f, "Additional upward acceleration per vertical meter. FrogSkill default: 30; set to 0 for no supplemental lift.");
MaxHookDuration = BindRange(config, "Tongue", "Max Hook Duration", 1f, 0.5f, 10f, "Vanilla-style maximum hook time in seconds, including the 0.5 second target-turn phase. Current Frog prefab default: 1.");
StopDistance = BindRange(config, "Tongue", "Stop Distance", 5f, 1f, 10f, "Release when the target reaches this distance. Vanilla FrogTongue default: 5.");
ExtraDragOther = BindRange(config, "Tongue", "Extra Drag Other", 0.95f, 0f, 1f, "Velocity retention applied each physics frame while pulling. Vanilla FrogTongue default: 0.95.");
ExtraDragLetGo = BindRange(config, "Tongue", "Extra Drag Let Go", 0.1f, 0f, 1f, "Velocity retention applied once when releasing. Vanilla FrogTongue default: 0.1.");
Cooldown = BindRange(config, "Tongue", "Cooldown", 0.5f, 0f, 60f, "Cooldown after successfully grabbing a target. Misses do not trigger it.");
}
private static ConfigEntry<float> BindRange(ConfigFile config, string section, string key, float value, float min, float max, string description)
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Expected O, but got Unknown
return config.Bind<float>(section, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(min, max), Array.Empty<object>()));
}
}
[BepInPlugin("com.github.lllei.FrogSkill", "FrogSkill", "1.4.0")]
[BepInIncompatibility("com.github.lllei.FrogSkillVanilla")]
public sealed class Plugin : BaseUnityPlugin
{
public const string PluginGuid = "com.github.lllei.FrogSkill";
public const string PluginName = "FrogSkill";
private const string VanillaPluginGuid = "com.github.lllei.FrogSkillVanilla";
private Harmony? _harmony;
internal static Plugin? Instance { get; private set; }
internal ModConfig Settings { get; private set; }
internal ManualLogSource ModLogger => ((BaseUnityPlugin)this).Logger;
private void Awake()
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Expected O, but got Unknown
Instance = this;
Settings = new ModConfig(((BaseUnityPlugin)this).Config);
_harmony = new Harmony("com.github.lllei.FrogSkill");
_harmony.PatchAll(typeof(CharacterStartPatch));
_harmony.PatchAll(typeof(FrogProxyAiPatch));
_harmony.PatchAll(typeof(FrogProxyCollisionPatch));
_harmony.PatchAll(typeof(FrogProxyReleasePatch));
((BaseUnityPlugin)this).Logger.LogInfo((object)"FrogSkill 1.4.0 loaded with Custom and Vanilla tongue modes.");
}
private void OnDestroy()
{
Harmony? harmony = _harmony;
if (harmony != null)
{
harmony.UnpatchSelf();
}
Instance = null;
}
}
[HarmonyPatch(typeof(FrogTongue), "RPCA_FrogAction")]
internal static class FrogProxyReleasePatch
{
private static void Postfix(FrogTongue __instance, FrogActionType frogActionType)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: Invalid comparison between Unknown and I4
if ((int)frogActionType == 3)
{
VanillaFrogProxy.DestroyAfterRelease(((MonoBehaviourPun)__instance).photonView);
}
}
}
[HarmonyPatch(typeof(FrogTongue), "OnCollisionEnter")]
internal static class FrogProxyCollisionPatch
{
private static bool Prefix(FrogTongue __instance)
{
return !VanillaFrogProxy.IsProxy(((MonoBehaviourPun)__instance).photonView);
}
}
[HarmonyPatch(typeof(FrogTongue), "CheckAllCharacters")]
internal static class FrogProxyAiPatch
{
private static bool Prefix(FrogTongue __instance)
{
return !VanillaFrogProxy.IsProxy(((MonoBehaviourPun)__instance).photonView);
}
}
[HarmonyPatch(typeof(Character), "Start")]
internal static class CharacterStartPatch
{
private static void Postfix(Character __instance)
{
if ((Object)(object)((Component)__instance).GetComponent<CustomTongueMode>() == (Object)null)
{
((Component)__instance).gameObject.AddComponent<CustomTongueMode>();
}
((MonoBehaviourPun)__instance).photonView.RefreshRpcMonoBehaviourCache();
if (__instance.IsLocal)
{
if ((Object)(object)((Component)__instance).GetComponent<VanillaTongueMode>() == (Object)null)
{
((Component)__instance).gameObject.AddComponent<VanillaTongueMode>();
}
if ((Object)(object)((Component)__instance).GetComponent<TongueModeController>() == (Object)null)
{
((Component)__instance).gameObject.AddComponent<TongueModeController>();
}
}
}
}
internal sealed class TongueContext
{
private const float MissDistanceRatio = 0.35f;
private const float VisibilityRayExtraDistance = 0.05f;
private static readonly Vector3 FallbackMouthLocalOffset = new Vector3(0f, 0.82f, 0.16f);
private readonly Character _caster;
private readonly Renderer? _mouthRenderer;
internal TongueContext(Character caster)
{
_caster = caster;
AnimatedMouth component = ((Component)caster).GetComponent<AnimatedMouth>();
_mouthRenderer = (((Object)(object)component != (Object)null) ? component.mouthRenderer : null);
if ((Object)(object)_mouthRenderer == (Object)null && (Object)(object)caster.refs?.customization?.refs != (Object)null)
{
_mouthRenderer = caster.refs.customization.refs.mouthRenderer;
}
}
internal bool TryGetAim(float maxDistance, float aimForgivenessDegrees, out Character? target, out Vector3 endpoint)
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
//IL_006b: Unknown result type (might be due to invalid IL or missing references)
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
//IL_007d: 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_00aa: Unknown result type (might be due to invalid IL or missing references)
//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
target = null;
endpoint = default(Vector3);
Camera val = (((Object)(object)MainCamera.instance != (Object)null) ? ((Component)MainCamera.instance).GetComponent<Camera>() : Camera.main);
if ((Object)(object)val == (Object)null)
{
return false;
}
Ray val2 = val.ScreenPointToRay(new Vector3((float)Screen.width * 0.5f, (float)Screen.height * 0.5f));
float num = maxDistance * 0.35f;
endpoint = ((Ray)(ref val2)).GetPoint(num);
int physicalMask = LayerMask.op_Implicit(HelperFunctions.GetMask((LayerType)7));
TryGetNearestPhysicalHit(val2, maxDistance, physicalMask, out var nearestHit);
if ((Object)(object)((RaycastHit)(ref nearestHit)).collider != (Object)null && ((RaycastHit)(ref nearestHit)).distance < num)
{
endpoint = ((RaycastHit)(ref nearestHit)).point;
}
Character val3 = default(Character);
if ((Object)(object)((RaycastHit)(ref nearestHit)).collider != (Object)null && CharacterRagdoll.TryGetCharacterFromCollider(((RaycastHit)(ref nearestHit)).collider, ref val3) && IsPermittedTarget(val3))
{
target = val3;
return true;
}
if (aimForgivenessDegrees > 0f)
{
target = FindAssistedTarget(val2, maxDistance, aimForgivenessDegrees, physicalMask);
}
return true;
}
private Character? FindAssistedTarget(Ray aimRay, float maxDistance, float aimForgivenessDegrees, int physicalMask)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_006a: 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_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_009c: Unknown result type (might be due to invalid IL or missing references)
//IL_00a1: 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_00a7: 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_00b3: 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)
//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
//IL_00be: Unknown result type (might be due to invalid IL or missing references)
//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
//IL_0101: Unknown result type (might be due to invalid IL or missing references)
//IL_0137: Unknown result type (might be due to invalid IL or missing references)
//IL_013c: Unknown result type (might be due to invalid IL or missing references)
//IL_0140: Unknown result type (might be due to invalid IL or missing references)
//IL_014b: Unknown result type (might be due to invalid IL or missing references)
float num = Mathf.Tan(aimForgivenessDegrees * (MathF.PI / 180f));
float num2 = float.MaxValue;
float num3 = float.MaxValue;
Character result = null;
Collider[] array = Physics.OverlapSphere(((Ray)(ref aimRay)).origin, maxDistance, physicalMask);
Character val2 = default(Character);
Ray ray = default(Ray);
Character val5 = default(Character);
foreach (Collider val in array)
{
if ((Object)(object)val == (Object)null || !CharacterRagdoll.TryGetCharacterFromCollider(val, ref val2) || !IsPermittedTarget(val2))
{
continue;
}
Bounds bounds = val.bounds;
float num4 = Vector3.Dot(((Bounds)(ref bounds)).center - ((Ray)(ref aimRay)).origin, ((Ray)(ref aimRay)).direction);
Vector3 point = ((Ray)(ref aimRay)).GetPoint(Mathf.Clamp(num4, 0f, maxDistance));
Vector3 val3 = val.ClosestPoint(point) - ((Ray)(ref aimRay)).origin;
float num5 = Vector3.Dot(val3, ((Ray)(ref aimRay)).direction);
float magnitude = ((Vector3)(ref val3)).magnitude;
if (num5 <= 0f || magnitude <= 0f || magnitude > maxDistance)
{
continue;
}
Vector3 val4 = Vector3.Cross(((Ray)(ref aimRay)).direction, val3);
float magnitude2 = ((Vector3)(ref val4)).magnitude;
float num6 = num5 * num;
if (magnitude2 > num6)
{
continue;
}
float num7 = magnitude2 / num5;
if (!(num7 > num2) && (!Mathf.Approximately(num7, num2) || !(magnitude >= num3)))
{
((Ray)(ref ray))..ctor(((Ray)(ref aimRay)).origin, val3 / magnitude);
if (TryGetNearestPhysicalHit(ray, magnitude + 0.05f, physicalMask, out var nearestHit) && CharacterRagdoll.TryGetCharacterFromCollider(((RaycastHit)(ref nearestHit)).collider, ref val5) && !((Object)(object)val5 != (Object)(object)val2))
{
num2 = num7;
num3 = magnitude;
result = val2;
}
}
}
return result;
}
private bool TryGetNearestPhysicalHit(Ray ray, float maxDistance, int physicalMask, out RaycastHit nearestHit)
{
//IL_0002: 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_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
nearestHit = default(RaycastHit);
float num = float.MaxValue;
RaycastHit[] array = Physics.RaycastAll(ray, maxDistance, physicalMask);
Character val2 = default(Character);
for (int i = 0; i < array.Length; i++)
{
RaycastHit val = array[i];
if (!((Object)(object)((RaycastHit)(ref val)).collider == (Object)null) && !(((RaycastHit)(ref val)).distance >= num))
{
CharacterRagdoll.TryGetCharacterFromCollider(((RaycastHit)(ref val)).collider, ref val2);
if (!((Object)(object)val2 == (Object)(object)_caster))
{
num = ((RaycastHit)(ref val)).distance;
nearestHit = val;
}
}
}
return (Object)(object)((RaycastHit)(ref nearestHit)).collider != (Object)null;
}
internal bool IsPermittedTarget(Character? target)
{
if ((Object)(object)target == (Object)null || (Object)(object)target == (Object)(object)_caster)
{
return false;
}
if ((target.isZombie || (!target.isBot && !target.isScoutmaster)) && (Object)(object)target.data != (Object)null && !target.data.dead && !target.data.fullyPassedOut && (Object)(object)target.refs?.ragdoll != (Object)null)
{
return target.refs.ragdoll.partDict.ContainsKey((BodypartType)2);
}
return false;
}
internal bool CanCasterAttack()
{
if ((Object)(object)_caster.data != (Object)null && !_caster.data.dead && !_caster.data.fullyPassedOut)
{
return !_caster.warping;
}
return false;
}
internal Vector3 GetMouthPosition()
{
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: 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)
if ((Object)(object)_mouthRenderer != (Object)null)
{
Bounds bounds = _mouthRenderer.bounds;
return ((Bounds)(ref bounds)).center;
}
return _caster.refs.head.transform.TransformPoint(FallbackMouthLocalOffset);
}
}
internal sealed class TongueModeController : MonoBehaviour
{
private enum TongueMode
{
Custom,
Vanilla
}
private ITongueMode _customTongue;
private ITongueMode _vanillaTongue;
private Character _caster;
private ModConfig _config;
private TongueMode _mode;
private float _nextFireTime;
private bool _refirePending;
private TextMeshProUGUI? _modeLabel;
private Material? _modeLabelMaterial;
private CanvasGroup? _modeLabelGroup;
private Coroutine? _modeLabelRoutine;
private InputAction? _activationAction;
private InputAction? _modeSwitchAction;
private ModConfig Config => _config;
private void Awake()
{
_caster = ((Component)this).GetComponent<Character>();
_customTongue = ((Component)this).GetComponent<CustomTongueMode>();
_vanillaTongue = ((Component)this).GetComponent<VanillaTongueMode>();
_config = Plugin.Instance.Settings;
_mode = TongueMode.Custom;
BindInputActions();
Config.ActivationPath.SettingChanged += OnInputPathChanged;
Config.ModeSwitchPath.SettingChanged += OnInputPathChanged;
}
private void Update()
{
if ((Object)(object)Plugin.Instance == (Object)null || !CanReadInput())
{
return;
}
int num;
if (!string.Equals(Config.ActivationPath.Value?.Trim(), Config.ModeSwitchPath.Value?.Trim(), StringComparison.OrdinalIgnoreCase))
{
InputAction? modeSwitchAction = _modeSwitchAction;
num = ((modeSwitchAction != null && modeSwitchAction.WasPressedThisFrame()) ? 1 : 0);
}
else
{
num = 0;
}
InputAction? activationAction = _activationAction;
bool flag = activationAction != null && activationAction.WasPressedThisFrame();
if (num != 0)
{
SwitchMode();
}
if (!flag || !(Time.time < _nextFireTime))
{
if (flag && _customTongue.CanRelease)
{
_customTongue.Release();
_refirePending = true;
}
else if (flag && _vanillaTongue.CanRelease)
{
_vanillaTongue.Release();
_refirePending = true;
}
else if (flag && !_customTongue.IsBusy && !_vanillaTongue.IsBusy)
{
TryFire();
}
if (_refirePending && !_customTongue.IsBusy && !_vanillaTongue.IsBusy)
{
_refirePending = false;
TryFire();
}
}
}
private void TryFire()
{
if (Config.Enabled.Value)
{
ITongueMode tongueMode = ((_mode == TongueMode.Custom) ? _customTongue : _vanillaTongue);
if (tongueMode.TryFire() && tongueMode.CanRelease)
{
_nextFireTime = Time.time + Config.Cooldown.Value;
}
}
}
private void SwitchMode()
{
_mode = ((_mode == TongueMode.Custom) ? TongueMode.Vanilla : TongueMode.Custom);
string text = ((_mode == TongueMode.Vanilla) ? "Vanilla" : "Custom");
ShowModeNotification(text);
Plugin? instance = Plugin.Instance;
if (instance != null)
{
instance.ModLogger.LogInfo((object)("Tongue mode switched to " + text + "."));
}
}
private void ShowModeNotification(string modeName)
{
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
if (EnsureModeLabel() && !((Object)(object)_modeLabel == (Object)null) && !((Object)(object)_modeLabelGroup == (Object)null))
{
Color playerColor = _caster.refs.customization.PlayerColor;
playerColor.a = 1f;
((Graphic)_modeLabel).color = playerColor;
((TMP_Text)_modeLabel).text = "Tongue mode: " + modeName;
((TMP_Text)_modeLabel).transform.SetAsLastSibling();
if (_modeLabelRoutine != null)
{
((MonoBehaviour)this).StopCoroutine(_modeLabelRoutine);
}
_modeLabelRoutine = ((MonoBehaviour)this).StartCoroutine(ShowModeLabelRoutine());
}
}
private bool EnsureModeLabel()
{
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
//IL_0077: Expected O, but got Unknown
//IL_00a3: 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)
//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
//IL_0202: Unknown result type (might be due to invalid IL or missing references)
//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
//IL_01d1: Expected O, but got Unknown
if ((Object)(object)_modeLabel != (Object)null && (Object)(object)_modeLabelGroup != (Object)null)
{
return true;
}
if ((Object)(object)GUIManager.instance == (Object)null || (Object)(object)GUIManager.instance.hudCanvas == (Object)null)
{
return false;
}
GameObject val = new GameObject("FrogSkill Mode Notification", new Type[3]
{
typeof(RectTransform),
typeof(CanvasGroup),
typeof(TextMeshProUGUI)
});
val.transform.SetParent(((Component)GUIManager.instance.hudCanvas).transform, false);
RectTransform component = val.GetComponent<RectTransform>();
component.anchorMin = new Vector2(0.5f, 1f);
component.anchorMax = new Vector2(0.5f, 1f);
component.pivot = new Vector2(0.5f, 1f);
component.anchoredPosition = new Vector2(0f, -96f);
component.sizeDelta = new Vector2(520f, 52f);
_modeLabelGroup = val.GetComponent<CanvasGroup>();
_modeLabelGroup.alpha = 0f;
_modeLabelGroup.blocksRaycasts = false;
_modeLabelGroup.interactable = false;
_modeLabel = val.GetComponent<TextMeshProUGUI>();
((TMP_Text)_modeLabel).alignment = (TextAlignmentOptions)514;
((TMP_Text)_modeLabel).fontSize = 30f;
TextMeshProUGUI val2 = GUIManager.instance.interactNameText ?? GUIManager.instance.itemPromptMain;
if ((Object)(object)val2 != (Object)null && (Object)(object)((TMP_Text)val2).font != (Object)null)
{
((TMP_Text)_modeLabel).font = ((TMP_Text)val2).font;
((TMP_Text)_modeLabel).fontStyle = ((TMP_Text)val2).fontStyle;
if ((Object)(object)((TMP_Text)val2).fontSharedMaterial != (Object)null)
{
_modeLabelMaterial = new Material(((TMP_Text)val2).fontSharedMaterial);
((TMP_Text)_modeLabel).fontSharedMaterial = _modeLabelMaterial;
}
}
((TMP_Text)_modeLabel).faceColor = Color32.op_Implicit(Color.white);
((TMP_Text)_modeLabel).outlineColor = Color32.op_Implicit(Color.black);
((TMP_Text)_modeLabel).outlineWidth = 0.08f;
((Graphic)_modeLabel).raycastTarget = false;
return true;
}
private IEnumerator ShowModeLabelRoutine()
{
if (!((Object)(object)_modeLabelGroup == (Object)null))
{
_modeLabelGroup.alpha = 1f;
yield return (object)new WaitForSecondsRealtime(1.25f);
float elapsed = 0f;
while (elapsed < 0.25f && (Object)(object)_modeLabelGroup != (Object)null)
{
elapsed += Time.unscaledDeltaTime;
_modeLabelGroup.alpha = 1f - Mathf.Clamp01(elapsed / 0.25f);
yield return null;
}
if ((Object)(object)_modeLabelGroup != (Object)null)
{
_modeLabelGroup.alpha = 0f;
}
_modeLabelRoutine = null;
}
}
private static bool CanReadInput()
{
if (Time.timeScale > 0f && (Object)(object)GUIManager.instance != (Object)null && !GUIManager.instance.windowBlockingInput)
{
return !GUIManager.instance.wheelActive;
}
return false;
}
private void OnInputPathChanged(object sender, EventArgs eventArgs)
{
BindInputActions();
}
private void BindInputActions()
{
InputAction? activationAction = _activationAction;
if (activationAction != null)
{
activationAction.Dispose();
}
_activationAction = CreateButtonAction("FrogSkillActivation", Config.ActivationPath.Value, "activation");
InputAction? modeSwitchAction = _modeSwitchAction;
if (modeSwitchAction != null)
{
modeSwitchAction.Dispose();
}
_modeSwitchAction = CreateButtonAction("FrogSkillModeSwitch", Config.ModeSwitchPath.Value, "mode-switch");
}
private static InputAction? CreateButtonAction(string actionName, string? controlPath, string logName)
{
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Expected O, but got Unknown
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
controlPath = controlPath?.Trim() ?? string.Empty;
if (controlPath.Length == 0)
{
Plugin? instance = Plugin.Instance;
if (instance != null)
{
instance.ModLogger.LogWarning((object)("The " + logName + " path is empty; the action is disabled."));
}
return null;
}
InputAction val = null;
try
{
val = new InputAction(actionName, (InputActionType)1, (string)null, (string)null, (string)null, (string)null);
InputActionSetupExtensions.AddBinding(val, controlPath, (string)null, (string)null, (string)null);
val.Enable();
return val;
}
catch (Exception ex)
{
if (val != null)
{
val.Dispose();
}
Plugin? instance2 = Plugin.Instance;
if (instance2 != null)
{
instance2.ModLogger.LogWarning((object)("Could not bind the configured " + logName + " path; the action is disabled: " + ex.Message));
}
return null;
}
}
private void OnDestroy()
{
Config.ActivationPath.SettingChanged -= OnInputPathChanged;
Config.ModeSwitchPath.SettingChanged -= OnInputPathChanged;
InputAction? activationAction = _activationAction;
if (activationAction != null)
{
activationAction.Dispose();
}
_activationAction = null;
InputAction? modeSwitchAction = _modeSwitchAction;
if (modeSwitchAction != null)
{
modeSwitchAction.Dispose();
}
_modeSwitchAction = null;
if ((Object)(object)_modeLabel != (Object)null)
{
Object.Destroy((Object)(object)((Component)_modeLabel).gameObject);
}
if ((Object)(object)_modeLabelMaterial != (Object)null)
{
Object.Destroy((Object)(object)_modeLabelMaterial);
}
}
}
internal static class TongueVisual
{
private const float MissExtendDuration = 0.12f;
private const float MissRetractDuration = 0.12f;
private static readonly Color Color = new Color(0.85f, 0.18f, 0.28f, 1f);
internal static LineRenderer CreateLine(Transform parent, string objectName, out Material? material)
{
//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_005a: 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_0081: Unknown result type (might be due to invalid IL or missing references)
GameObject val = new GameObject(objectName);
val.transform.SetParent(parent, false);
LineRenderer val2 = val.AddComponent<LineRenderer>();
val2.useWorldSpace = true;
val2.positionCount = 2;
val2.startWidth = 0.075f;
val2.endWidth = 0.035f;
val2.numCapVertices = 4;
Shader val3 = Shader.Find("Sprites/Default");
material = (((Object)(object)val3 == (Object)null) ? ((Material)null) : new Material(val3));
if ((Object)(object)material != (Object)null)
{
((Renderer)val2).material = material;
}
val2.startColor = Color;
val2.endColor = Color;
((Renderer)val2).enabled = false;
return val2;
}
internal static bool UpdateMiss(LineRenderer line, float startedAt, Vector3 origin, Vector3 endpoint)
{
//IL_0028: 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)
//IL_0031: 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)
float num = Time.time - startedAt;
float num2 = Mathf.Clamp01(num / 0.12f);
float num3 = Mathf.Clamp01((num - 0.12f) / 0.12f);
line.SetPosition(0, origin);
line.SetPosition(1, Vector3.Lerp(origin, endpoint, num2 * (1f - num3)));
return num3 >= 1f;
}
}
internal static class VanillaFrogProxy
{
private const int Marker = 1179799367;
private static readonly HashSet<int> PendingDestroy = new HashSet<int>();
internal static object[] InstantiationData { get; } = new object[1] { 1179799367 };
internal static bool IsProxy(PhotonView? view)
{
object[] array = ((view != null) ? view.InstantiationData : null);
if (array != null && array.Length == 1 && array[0] is int num)
{
return num == 1179799367;
}
return false;
}
internal static void DestroyAfterRelease(PhotonView? view)
{
if (!((Object)(object)view == (Object)null) && view.IsMine && IsProxy(view) && PendingDestroy.Add(view.ViewID) && !((Object)(object)Plugin.Instance == (Object)null))
{
((MonoBehaviour)Plugin.Instance).StartCoroutine(DestroyNextFrame(view, view.ViewID));
}
}
private static IEnumerator DestroyNextFrame(PhotonView view, int viewId)
{
yield return null;
PendingDestroy.Remove(viewId);
if (!((Object)(object)view == (Object)null) && view.IsMine && IsProxy(view))
{
if (PhotonNetwork.InRoom)
{
PhotonNetwork.Destroy(((Component)view).gameObject);
}
else
{
Object.Destroy((Object)(object)((Component)view).gameObject);
}
}
}
}
internal sealed class VanillaTongueMode : MonoBehaviour, ITongueMode
{
private const string FrogPrefabName = "0_Items/Frog";
private const string FrogActionRpc = "RPCA_FrogAction";
private const string SetKinematicRpc = "SetKinematicRPC";
private const float ProxySyncInterval = 0.08f;
private const float ProxyCleanupDelay = 0.2f;
private Character _caster;
private TongueContext _context;
private GameObject? _proxy;
private FrogTongue? _proxyTongue;
private PhotonView? _proxyView;
private LineRenderer? _missLine;
private Material? _missLineMaterial;
private float _nextProxySyncTime;
private float _cleanupAt = float.PositiveInfinity;
private float _missStartedAt;
private Vector3 _missEndpoint;
private bool _missActive;
private bool _releaseSent;
private ModConfig Config => Plugin.Instance.Settings;
bool ITongueMode.CanRelease
{
get
{
if ((Object)(object)_proxy != (Object)null)
{
return !_releaseSent;
}
return false;
}
}
bool ITongueMode.IsBusy
{
get
{
if (!((Object)(object)_proxy != (Object)null))
{
return _missActive;
}
return true;
}
}
private void Awake()
{
_caster = ((Component)this).GetComponent<Character>();
_context = new TongueContext(_caster);
CreateMissVisual();
}
private void Update()
{
UpdateMissVisual();
if (_caster.IsLocal && !((Object)(object)Plugin.Instance == (Object)null) && (Object)(object)_proxy != (Object)null)
{
FollowProxy();
if (Time.time >= _cleanupAt)
{
DestroyProxy();
}
}
}
bool ITongueMode.TryFire()
{
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
if (!_caster.IsLocal || (Object)(object)Plugin.Instance == (Object)null || !Config.Enabled.Value || (Object)(object)_proxy != (Object)null || _missActive || !_context.CanCasterAttack() || !_context.TryGetAim(Config.MaxDistance.Value, Config.AimForgivenessDegrees.Value, out Character target, out Vector3 endpoint))
{
return false;
}
if ((Object)(object)target != (Object)null)
{
return FireProxy(target);
}
StartMiss(endpoint);
return true;
}
void ITongueMode.Release()
{
if (_caster.IsLocal)
{
ReleaseProxy();
}
}
private bool FireProxy(Character target)
{
//IL_0023: 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_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: 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)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: 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_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
//IL_0114: Unknown result type (might be due to invalid IL or missing references)
//IL_0127: Unknown result type (might be due to invalid IL or missing references)
//IL_015d: Unknown result type (might be due to invalid IL or missing references)
if (!PhotonNetwork.InRoom)
{
Plugin.Instance.ModLogger.LogWarning((object)"A Photon room is required to create the vanilla frog proxy.");
return false;
}
Vector3 mouthPosition = _context.GetMouthPosition();
Quaternion proxyRotation = GetProxyRotation(target.Center - mouthPosition);
GameObject val;
try
{
val = PhotonNetwork.Instantiate("0_Items/Frog", mouthPosition, proxyRotation, (byte)0, VanillaFrogProxy.InstantiationData);
}
catch (Exception arg)
{
Plugin.Instance.ModLogger.LogError((object)$"Failed to instantiate the vanilla frog proxy: {arg}");
return false;
}
_proxy = val;
_proxyTongue = val.GetComponent<FrogTongue>();
_proxyView = val.GetComponent<PhotonView>();
Item component = val.GetComponent<Item>();
if ((Object)(object)_proxyTongue == (Object)null || (Object)(object)_proxyView == (Object)null || (Object)(object)component == (Object)null)
{
Plugin.Instance.ModLogger.LogError((object)"The vanilla Frog prefab is missing FrogTongue, Item, or PhotonView.");
DestroyProxy();
return false;
}
ConfigureOwnedProxy(component, _proxyTongue);
MoveProxy(mouthPosition, proxyRotation);
_proxyView.RPC("SetKinematicRPC", (RpcTarget)0, new object[3]
{
true,
val.transform.position,
val.transform.rotation
});
_proxyView.RPC("RPCA_FrogAction", (RpcTarget)0, new object[3]
{
((MonoBehaviourPun)target).photonView,
(object)(FrogActionType)1,
Vector3.zero
});
_nextProxySyncTime = Time.time + 0.08f;
_cleanupAt = Time.time + _proxyTongue.maxScoutHookTime + 1.25f;
_releaseSent = false;
return true;
}
private void ConfigureOwnedProxy(Item proxyItem, FrogTongue tongue)
{
//IL_0025: 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)
proxyItem.blockInteraction = true;
proxyItem.rig.useGravity = false;
proxyItem.rig.detectCollisions = false;
proxyItem.rig.linearVelocity = Vector3.zero;
proxyItem.rig.angularVelocity = Vector3.zero;
((Mob)tongue).sleeping = true;
tongue.dragForce = Config.PullForce.Value;
tongue.liftDragForce = Config.LiftForce.Value;
tongue.maxScoutHookTime = Config.MaxHookDuration.Value;
tongue.stopPullFriendDistance = Config.StopDistance.Value;
}
private void FollowProxy()
{
//IL_0031: 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_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: 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_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)_proxy == (Object)null) && !((Object)(object)_proxyView == (Object)null) && !((Object)(object)_proxyTongue == (Object)null))
{
Vector3 mouthPosition = _context.GetMouthPosition();
Quaternion proxyRotation = GetProxyRotation(_proxyTongue.tongueEnd.position - mouthPosition);
MoveProxy(mouthPosition, proxyRotation);
if (!(Time.time < _nextProxySyncTime))
{
_nextProxySyncTime = Time.time + 0.08f;
_proxyView.RPC("SetKinematicRPC", (RpcTarget)1, new object[3]
{
true,
_proxy.transform.position,
_proxy.transform.rotation
});
}
}
}
private void MoveProxy(Vector3 mouth, Quaternion rotation)
{
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: 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_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
//IL_0083: Unknown result type (might be due to invalid IL or missing references)
//IL_008e: Unknown result type (might be due to invalid IL or missing references)
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)_proxy == (Object)null) && !((Object)(object)_proxyTongue == (Object)null))
{
Transform transform = _proxy.transform;
transform.SetPositionAndRotation(mouth, rotation);
Vector3 val = _proxyTongue.dragPoint.position - transform.position;
transform.position -= val;
Rigidbody component = _proxy.GetComponent<Rigidbody>();
if (!((Object)(object)component == (Object)null))
{
component.position = transform.position;
component.rotation = transform.rotation;
component.linearVelocity = Vector3.zero;
component.angularVelocity = Vector3.zero;
}
}
}
private void ReleaseProxy()
{
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)_proxyView == (Object)null) && !_releaseSent)
{
_releaseSent = true;
_proxyView.RPC("RPCA_FrogAction", (RpcTarget)0, new object[3]
{
_proxyView,
(object)(FrogActionType)3,
Vector3.zero
});
_cleanupAt = Time.time + 0.2f;
}
}
private void DestroyProxy()
{
GameObject proxy = _proxy;
_proxy = null;
_proxyTongue = null;
_proxyView = null;
_cleanupAt = float.PositiveInfinity;
_releaseSent = false;
if (!((Object)(object)proxy == (Object)null))
{
PhotonView component = proxy.GetComponent<PhotonView>();
if (PhotonNetwork.InRoom && (Object)(object)component != (Object)null && component.IsMine)
{
PhotonNetwork.Destroy(proxy);
}
else
{
Object.Destroy((Object)(object)proxy);
}
}
}
private static Quaternion GetProxyRotation(Vector3 direction)
{
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: 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)
direction.y = 0f;
if (!(((Vector3)(ref direction)).sqrMagnitude > 0.0001f))
{
return Quaternion.identity;
}
return Quaternion.LookRotation(((Vector3)(ref direction)).normalized, Vector3.up);
}
private void CreateMissVisual()
{
_missLine = TongueVisual.CreateLine(((Component)this).transform, "FrogSkill Vanilla Miss Tongue", out _missLineMaterial);
}
private void StartMiss(Vector3 endpoint)
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)_missLine == (Object)null))
{
_missEndpoint = endpoint;
_missStartedAt = Time.time;
_missActive = true;
((Renderer)_missLine).enabled = true;
}
}
private void UpdateMissVisual()
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: 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)
if (_missActive && !((Object)(object)_missLine == (Object)null))
{
Vector3 mouthPosition = _context.GetMouthPosition();
if (TongueVisual.UpdateMiss(_missLine, _missStartedAt, mouthPosition, _missEndpoint))
{
_missActive = false;
((Renderer)_missLine).enabled = false;
}
}
}
private void OnDestroy()
{
DestroyProxy();
if ((Object)(object)_missLineMaterial != (Object)null)
{
Object.Destroy((Object)(object)_missLineMaterial);
}
}
}
internal static class BuildInfo
{
internal const string Version = "1.4.0";
}
}