using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Peak.Afflictions;
using Photon.Pun;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("com.github.GABRlEL.ConfigurableScorpions")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0")]
[assembly: AssemblyProduct("com.github.GABRlEL.ConfigurableScorpions")]
[assembly: AssemblyTitle("ConfigurableScorpions")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace BepInEx
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
[Conditional("CodeGeneration")]
internal sealed class BepInAutoPluginAttribute : Attribute
{
public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
{
}
}
}
namespace BepInEx.Preloader.Core.Patching
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
[Conditional("CodeGeneration")]
internal sealed class PatcherAutoPluginAttribute : Attribute
{
public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
{
}
}
}
namespace ConfigurableScorpions
{
[BepInPlugin("com.github.GABRlEL.ConfigurableScorpions", "ConfigurableScorpions", "0.1.0")]
public class Plugin : BaseUnityPlugin
{
internal enum DamageTypeOverride
{
Vanilla = -1,
Injury,
Hunger,
Cold,
Poison,
Crab,
Curse,
Drowsy,
Weight,
Hot,
Thorns,
Spores,
Web
}
private Harmony? _harmony;
public const string Id = "com.github.GABRlEL.ConfigurableScorpions";
internal static ManualLogSource Log { get; private set; }
internal static ConfigEntry<bool> CfgEnablePlayerTargeting { get; private set; }
internal static ConfigEntry<bool> CfgOnlyAggressiveWhenHeld { get; private set; }
internal static ConfigEntry<float> CfgAggroDistanceMultiplier { get; private set; }
internal static ConfigEntry<bool> CfgRequireLineOfSight { get; private set; }
internal static ConfigEntry<bool> CfgTargetPoisonedPlayers { get; private set; }
internal static ConfigEntry<float> CfgMovementSpeedMultiplier { get; private set; }
internal static ConfigEntry<float> CfgTurnRateMultiplier { get; private set; }
internal static ConfigEntry<float> CfgSleepDistanceMultiplier { get; private set; }
internal static ConfigEntry<float> CfgWakeRadiusMultiplier { get; private set; }
internal static ConfigEntry<float> CfgAttackStartDistance { get; private set; }
internal static ConfigEntry<float> CfgAttackDistance { get; private set; }
internal static ConfigEntry<float> CfgAttackAngle { get; private set; }
internal static ConfigEntry<float> CfgAttackCooldownSeconds { get; private set; }
internal static ConfigEntry<float> CfgStingDelaySeconds { get; private set; }
internal static ConfigEntry<float> CfgHeldStingTimeMultiplier { get; private set; }
internal static ConfigEntry<float> CfgDamageMultiplier { get; private set; }
internal static ConfigEntry<bool> CfgEnableInitialDamageTick { get; private set; }
internal static ConfigEntry<bool> CfgEnableOvertimeDamageTick { get; private set; }
internal static ConfigEntry<float> CfgInitialDamageMultiplier { get; private set; }
internal static ConfigEntry<float> CfgOvertimeDamageMultiplier { get; private set; }
internal static ConfigEntry<DamageTypeOverride> CfgDamageType { get; private set; }
public static string Name => "ConfigurableScorpions";
public static string Version => "0.1.0";
private void Awake()
{
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_0083: Expected O, but got Unknown
//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
//IL_0100: Expected O, but got Unknown
//IL_0133: Unknown result type (might be due to invalid IL or missing references)
//IL_013d: Expected O, but got Unknown
//IL_0170: Unknown result type (might be due to invalid IL or missing references)
//IL_017a: Expected O, but got Unknown
//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
//IL_01b7: Expected O, but got Unknown
//IL_020e: Unknown result type (might be due to invalid IL or missing references)
//IL_0218: Expected O, but got Unknown
//IL_024b: Unknown result type (might be due to invalid IL or missing references)
//IL_0255: Expected O, but got Unknown
//IL_0288: Unknown result type (might be due to invalid IL or missing references)
//IL_0292: Expected O, but got Unknown
//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
//IL_02cf: Expected O, but got Unknown
//IL_0302: Unknown result type (might be due to invalid IL or missing references)
//IL_030c: Expected O, but got Unknown
//IL_033f: Unknown result type (might be due to invalid IL or missing references)
//IL_0349: Expected O, but got Unknown
//IL_03bc: Unknown result type (might be due to invalid IL or missing references)
//IL_03c6: Expected O, but got Unknown
//IL_03f9: Unknown result type (might be due to invalid IL or missing references)
//IL_0403: Expected O, but got Unknown
//IL_0439: Unknown result type (might be due to invalid IL or missing references)
//IL_0443: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
CfgEnablePlayerTargeting = ((BaseUnityPlugin)this).Config.Bind<bool>("Targeting", "EnablePathfindingToPlayer", true, "Enable/disable player target acquisition for scorpions while they're on the ground. If disabled, scorpions will only patrol (and won't chase players) unless they're being held.");
CfgOnlyAggressiveWhenHeld = ((BaseUnityPlugin)this).Config.Bind<bool>("Targeting", "OnlyAggressiveWhenHeld", false, "If enabled, scorpions will only target/attack while held as an item. On the ground they will only patrol.");
CfgAggroDistanceMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Targeting", "AggroDistanceMultiplier", 1f, new ConfigDescription("Multiplier applied to the scorpion's aggro radius (Mob.aggroDistance). 1 = vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 20f), Array.Empty<object>()));
CfgRequireLineOfSight = ((BaseUnityPlugin)this).Config.Bind<bool>("Targeting", "RequireLineOfSight", true, "If true (vanilla), scorpions only target players they have line-of-sight to (terrain blocks). If false, they can target through terrain.");
CfgTargetPoisonedPlayers = ((BaseUnityPlugin)this).Config.Bind<bool>("Targeting", "TargetPoisonedPlayers", false, "If true, scorpions will target players even if they already have PoisonOverTime. false = vanilla.");
CfgMovementSpeedMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "MovementSpeedMultiplier", 1f, new ConfigDescription("Multiplier applied to the scorpion's movement speed (Mob.movementSpeed). 1 = vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 20f), Array.Empty<object>()));
CfgTurnRateMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "TurnRateMultiplier", 1f, new ConfigDescription("Multiplier applied to the scorpion's turn rate (Mob.turnRate). 1 = vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 20f), Array.Empty<object>()));
CfgSleepDistanceMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "SleepDistanceMultiplier", 1f, new ConfigDescription("Multiplier for the distance used when deciding a scorpion can go to sleep (vanilla uses Mob.sleepDistance for both sleep and wake). 1 = vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 20f), Array.Empty<object>()));
CfgWakeRadiusMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "WakeRadiusMultiplier", 1f, new ConfigDescription("Multiplier for the distance used when deciding a sleeping scorpion should wake up (vanilla uses Mob.sleepDistance for both sleep and wake). 1 = vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 20f), Array.Empty<object>()));
CfgStingDelaySeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Attack", "StingDelaySeconds", -1f, "Override for the delay (in seconds) between starting the attack and the sting happening. Set to -1 to keep the game's value.");
CfgHeldStingTimeMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Attack", "HeldStingTimeMultiplier", 1f, new ConfigDescription("Multiplier applied to scorpion sting delay while the scorpion is held as an item. 1 = vanilla. This multiplies the effective Mob.attackTime only while held (after any StingDelaySeconds override).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 20f), Array.Empty<object>()));
CfgAttackStartDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Attack", "AttackStartDistance", -1f, new ConfigDescription("Override for the distance at which scorpions begin an attack (Mob.attackStartDistance). Set to -1 to keep vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-1f, 50f), Array.Empty<object>()));
CfgAttackDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Attack", "AttackDistance", -1f, new ConfigDescription("Override for the distance at which scorpions can hit their attack (Mob.attackDistance). Set to -1 to keep vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-1f, 50f), Array.Empty<object>()));
CfgAttackAngle = ((BaseUnityPlugin)this).Config.Bind<float>("Attack", "AttackAngle", -1f, new ConfigDescription("Override for the attack cone angle in degrees (Mob.attackAngle). Set to -1 to keep vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-1f, 360f), Array.Empty<object>()));
CfgAttackCooldownSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Attack", "AttackCooldownSeconds", -1f, new ConfigDescription("Override for the base attack cooldown in seconds (Mob private field attackCooldown). Set to -1 to keep vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-1f, 60f), Array.Empty<object>()));
CfgDamageMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Attack", "DamageMultiplier", 1f, new ConfigDescription("Global multiplier for scorpion status damage (applies to BOTH the initial sting tick and the overtime tick). 1 = vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
CfgEnableInitialDamageTick = ((BaseUnityPlugin)this).Config.Bind<bool>("Attack", "EnableInitialDamageTick", true, "Enable/disable the single (instant) status tick applied when the sting connects. true = vanilla.");
CfgEnableOvertimeDamageTick = ((BaseUnityPlugin)this).Config.Bind<bool>("Attack", "EnableOvertimeDamageTick", true, "Enable/disable the over-time status application after the sting. true = vanilla.");
CfgInitialDamageMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Attack", "InitialDamageMultiplier", 1f, new ConfigDescription("Multiplier for ONLY the initial (instant) sting status tick. 1 = vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
CfgOvertimeDamageMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Attack", "OvertimeDamageMultiplier", 1f, new ConfigDescription("Multiplier for ONLY the over-time status tick rate (per second). 1 = vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
CfgDamageType = ((BaseUnityPlugin)this).Config.Bind<DamageTypeOverride>("Attack", "DamageType", DamageTypeOverride.Vanilla, "Controls the status/damage type a scorpion sting applies. Vanilla keeps the game's original setting (Poison).\nCold = freeze, Hot = burn, Spores = shroom.\nNote: Non-Poison over-time is applied locally (not via the game's built-in PoisonOverTime affliction).");
try
{
_harmony = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID);
_harmony.PatchAll();
}
catch (Exception arg)
{
Log.LogError((object)$"Failed to apply Harmony patches: {arg}");
}
Log.LogInfo((object)("Plugin " + Name + " is loaded!"));
}
}
[HarmonyPatch]
internal static class ScorpionPatches
{
private sealed class AttackAnimSyncState
{
public bool Initialized;
public float PrefabAttackTime;
public float BaseAnimSpeed = 1f;
public bool TriggeredThisAttack;
}
private static readonly MethodInfo? SetTargetChar = AccessTools.PropertySetter(typeof(Mob), "targetChar");
private static readonly FieldRef<Mob, bool> AttackingRef = AccessTools.FieldRefAccess<Mob, bool>("attacking");
private static readonly FieldRef<Mob, float> TimeLastCheckedForTargetRef = AccessTools.FieldRefAccess<Mob, float>("_timeLastCheckedForTarget");
private static readonly FieldRef<Mob, float> TimeLastSwitchedTargetRef = AccessTools.FieldRefAccess<Mob, float>("_timeLastSwitchedTarget");
private static readonly FieldRef<Mob, float> TargetSwitchCooldownRef = AccessTools.FieldRefAccess<Mob, float>("targetSwitchCooldown");
private static readonly FieldRef<Mob, float> TargetCheckCooldownRef = AccessTools.FieldRefAccess<Mob, float>("targetCheckCooldown");
private static readonly FieldRef<Mob, Character> TargetCharRef = AccessTools.FieldRefAccess<Mob, Character>("_targetChar");
private static readonly FieldRef<Mob, Vector3> NormalRef = AccessTools.FieldRefAccess<Mob, Vector3>("normal");
private static readonly FieldRef<Mob, float> AttackCooldownRef = AccessTools.FieldRefAccess<Mob, float>("attackCooldown");
private static readonly FieldRef<Mob, float> InRangeForAttackTimeRef = AccessTools.FieldRefAccess<Mob, float>("inRangeForAttackTime");
private static readonly FieldRef<Mob, float> TimeLastAttackedRef = AccessTools.FieldRefAccess<Mob, float>("_timeLastAttacked");
private static readonly FieldRef<Mob, float> PostAttackRestRef = AccessTools.FieldRefAccess<Mob, float>("postAttackRest");
private static readonly FieldRef<Mob, float> WhiffRefundRef = AccessTools.FieldRefAccess<Mob, float>("whiffRefund");
private static readonly MethodInfo? MobInflictAttackMI = AccessTools.Method(typeof(Mob), "InflictAttack", (Type[])null, (Type[])null);
private static readonly ConditionalWeakTable<Mob, AttackAnimSyncState> AttackAnimStates = new ConditionalWeakTable<Mob, AttackAnimSyncState>();
private static readonly FieldRef<Mob, MobItem> MobItemRef = AccessTools.FieldRefAccess<Mob, MobItem>("_mobItem");
private static readonly FieldRef<Mob, Rigidbody> RigRef = AccessTools.FieldRefAccess<Mob, Rigidbody>("rig");
private static readonly FieldInfo? MobStateField = AccessTools.Field(typeof(Mob), "_mobState");
private static readonly MethodInfo? MobStateGetter = AccessTools.PropertyGetter(typeof(Mob), "mobState");
private static AttackAnimSyncState GetAttackAnimState(Mob mob)
{
return AttackAnimStates.GetValue(mob, (Mob _) => new AttackAnimSyncState());
}
private static bool IsInAttackCooldown(Mob mob)
{
return Time.time < TimeLastAttackedRef.Invoke(mob) + AttackCooldownRef.Invoke(mob);
}
private static bool TryGetMobStateWalking(Mob mob, out bool isWalking)
{
isWalking = false;
try
{
object obj = null;
if (MobStateField != null)
{
obj = MobStateField.GetValue(mob);
}
else if (MobStateGetter != null)
{
obj = MobStateGetter.Invoke(mob, null);
}
if (obj == null)
{
return false;
}
isWalking = string.Equals(obj.ToString(), "Walking", StringComparison.Ordinal);
return true;
}
catch
{
return false;
}
}
private static bool InTargetingCooldown(Mob mob)
{
float time = Time.time;
return time < Mathf.Max(TimeLastCheckedForTargetRef.Invoke(mob) + TargetCheckCooldownRef.Invoke(mob), TimeLastSwitchedTargetRef.Invoke(mob) + TargetSwitchCooldownRef.Invoke(mob));
}
private static Vector3 Center(Mob mob)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
return ((Component)mob).transform.position + NormalRef.Invoke(mob) * 0.2f;
}
private static bool IsNearCharacterWithinRadius(Mob mob, float radius)
{
//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_0025: 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)
Vector3 val = Center(mob);
foreach (Character allCharacter in Character.AllCharacters)
{
if ((Object)(object)allCharacter != (Object)null && Vector3.Distance(val, allCharacter.Center) < radius)
{
return true;
}
}
return false;
}
private static bool IsHeldAsItem(Mob mob)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Invalid comparison between Unknown and I4
Item component = ((Component)mob).GetComponent<Item>();
if ((Object)(object)component != (Object)null)
{
return (int)component.itemState == 1;
}
return false;
}
private static void ClearTarget(Mob mob)
{
try
{
SetTargetChar?.Invoke(mob, new object[1]);
}
catch (Exception ex)
{
Plugin.Log.LogDebug((object)("Failed to clear scorpion target (safe to ignore): " + ex.Message));
}
}
[HarmonyPatch(typeof(Mob), "Start")]
[HarmonyPostfix]
private static void MobStart_Postfix(Mob __instance)
{
if (__instance is Scorpion)
{
float value = Plugin.CfgStingDelaySeconds.Value;
if (value >= 0f)
{
__instance.attackTime = value;
}
float num = Mathf.Max(0f, Plugin.CfgMovementSpeedMultiplier.Value);
if (!Mathf.Approximately(num, 1f))
{
__instance.movementSpeed *= num;
}
float num2 = Mathf.Max(0f, Plugin.CfgTurnRateMultiplier.Value);
if (!Mathf.Approximately(num2, 1f))
{
__instance.turnRate *= num2;
}
float value2 = Plugin.CfgAttackStartDistance.Value;
if (value2 >= 0f)
{
__instance.attackStartDistance = value2;
}
float value3 = Plugin.CfgAttackDistance.Value;
if (value3 >= 0f)
{
__instance.attackDistance = value3;
}
float value4 = Plugin.CfgAttackAngle.Value;
if (value4 >= 0f)
{
__instance.attackAngle = value4;
}
float value5 = Plugin.CfgAttackCooldownSeconds.Value;
if (value5 >= 0f)
{
AttackCooldownRef.Invoke(__instance) = value5;
}
}
}
[HarmonyPatch(typeof(Mob), "Attacking")]
[HarmonyPrefix]
private static bool MobAttacking_Prefix(Mob __instance)
{
//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_024f: Unknown result type (might be due to invalid IL or missing references)
//IL_0254: Unknown result type (might be due to invalid IL or missing references)
//IL_0258: Unknown result type (might be due to invalid IL or missing references)
//IL_025e: Unknown result type (might be due to invalid IL or missing references)
//IL_0269: Unknown result type (might be due to invalid IL or missing references)
//IL_026e: Unknown result type (might be due to invalid IL or missing references)
//IL_0273: Unknown result type (might be due to invalid IL or missing references)
//IL_0277: Unknown result type (might be due to invalid IL or missing references)
if (!(__instance is Scorpion))
{
return true;
}
float value = Plugin.CfgHeldStingTimeMultiplier.Value;
if (!IsHeldAsItem(__instance) || Mathf.Approximately(value, 1f))
{
AttackAnimSyncState attackAnimState = GetAttackAnimState(__instance);
if (attackAnimState.Initialized && (Object)(object)__instance.anim != (Object)null)
{
__instance.anim.speed = attackAnimState.BaseAnimSpeed;
}
attackAnimState.TriggeredThisAttack = false;
return true;
}
AttackAnimSyncState attackAnimState2 = GetAttackAnimState(__instance);
if (!attackAnimState2.Initialized)
{
attackAnimState2.PrefabAttackTime = Mathf.Max(0.01f, __instance.attackTime);
attackAnimState2.BaseAnimSpeed = (((Object)(object)__instance.anim != (Object)null) ? __instance.anim.speed : 1f);
attackAnimState2.Initialized = true;
}
Character val = TargetCharRef.Invoke(__instance);
if ((Object)(object)val != (Object)null)
{
if (!AttackingRef.Invoke(__instance))
{
if (__instance.distanceToTarget < __instance.attackStartDistance && !IsInAttackCooldown(__instance) && ((MonoBehaviourPun)__instance).photonView.IsMine)
{
((MonoBehaviourPun)__instance).photonView.RPC("RPC_StartAttack", (RpcTarget)0, Array.Empty<object>());
}
InRangeForAttackTimeRef.Invoke(__instance) = 0f;
attackAnimState2.TriggeredThisAttack = false;
if (!AttackingRef.Invoke(__instance))
{
return false;
}
}
float num = InRangeForAttackTimeRef.Invoke(__instance);
float num2 = Mathf.Max(0f, __instance.attackTime * value);
float num3 = Mathf.Max(0.01f, attackAnimState2.PrefabAttackTime);
float num4 = Mathf.Max(0f, num2 - num3);
float deltaTime = Time.deltaTime;
float num5 = num + deltaTime;
if (!attackAnimState2.TriggeredThisAttack && num5 >= num4)
{
if ((Object)(object)__instance.anim != (Object)null)
{
float speed = attackAnimState2.BaseAnimSpeed;
if (num2 > 0.01f && num2 < num3)
{
speed = attackAnimState2.BaseAnimSpeed * (num3 / num2);
}
__instance.anim.speed = speed;
__instance.anim.SetTrigger("Attack");
}
attackAnimState2.TriggeredThisAttack = true;
}
else if ((Object)(object)__instance.anim != (Object)null)
{
__instance.anim.speed = attackAnimState2.BaseAnimSpeed;
}
InRangeForAttackTimeRef.Invoke(__instance) = num5;
if (num5 > num2)
{
if (__instance.distanceToTarget < __instance.attackDistance)
{
Vector3 val2 = ((Component)__instance).transform.forward + Vector3.up;
Vector3 normalized = ((Vector3)(ref val2)).normalized;
val2 = val.Center - ((Component)__instance).transform.position;
if (Vector3.Angle(normalized, ((Vector3)(ref val2)).normalized) < __instance.attackAngle)
{
MobInflictAttackMI?.Invoke(__instance, new object[1] { val });
TimeLastAttackedRef.Invoke(__instance) = Time.time;
goto IL_0305;
}
}
float num6 = Mathf.Clamp01(WhiffRefundRef.Invoke(__instance));
float num7 = AttackCooldownRef.Invoke(__instance);
float num8 = PostAttackRestRef.Invoke(__instance);
TimeLastAttackedRef.Invoke(__instance) = Time.time - num6 * Mathf.Max(num7, num8);
goto IL_0305;
}
}
else
{
InRangeForAttackTimeRef.Invoke(__instance) = 0f;
attackAnimState2.TriggeredThisAttack = false;
if ((Object)(object)__instance.anim != (Object)null)
{
__instance.anim.speed = attackAnimState2.BaseAnimSpeed;
}
}
goto IL_0371;
IL_0305:
AttackingRef.Invoke(__instance) = false;
attackAnimState2.TriggeredThisAttack = false;
if ((Object)(object)__instance.anim != (Object)null)
{
__instance.anim.speed = attackAnimState2.BaseAnimSpeed;
}
goto IL_0371;
IL_0371:
return false;
}
[HarmonyPatch(typeof(Mob), "TestSleepMode")]
[HarmonyPrefix]
private static bool MobTestSleepMode_Prefix(Mob __instance)
{
//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
if (!(__instance is Scorpion))
{
return true;
}
float num = Mathf.Max(0f, Plugin.CfgSleepDistanceMultiplier.Value);
float num2 = Mathf.Max(0f, Plugin.CfgWakeRadiusMultiplier.Value);
if (Mathf.Approximately(num, 1f) && Mathf.Approximately(num2, 1f))
{
return true;
}
float sleepDistance = __instance.sleepDistance;
float radius = sleepDistance * num;
float radius2 = sleepDistance * num2;
if (__instance.sleeping)
{
if (IsNearCharacterWithinRadius(__instance, radius2))
{
__instance.sleeping = false;
__instance.UpdateSleeping();
}
}
else
{
MobItem val = MobItemRef.Invoke(__instance);
Rigidbody val2 = RigRef.Invoke(__instance);
if (!TryGetMobStateWalking(__instance, out var isWalking))
{
return true;
}
if (isWalking && ((Object)(object)val == (Object)null || (int)((Item)val).itemState == 0) && (Object)(object)val2 != (Object)null)
{
Vector3 linearVelocity = val2.linearVelocity;
if (((Vector3)(ref linearVelocity)).magnitude < 1f && !IsNearCharacterWithinRadius(__instance, radius))
{
__instance.sleeping = true;
__instance.UpdateSleeping();
}
}
}
return false;
}
[HarmonyPatch(typeof(Mob), "Targeting")]
[HarmonyPrefix]
private static bool MobTargeting_Prefix(Mob __instance, ref float __state)
{
//IL_0111: Unknown result type (might be due to invalid IL or missing references)
//IL_0116: Unknown result type (might be due to invalid IL or missing references)
//IL_0163: Unknown result type (might be due to invalid IL or missing references)
//IL_016a: Unknown result type (might be due to invalid IL or missing references)
//IL_019a: Unknown result type (might be due to invalid IL or missing references)
//IL_019e: Unknown result type (might be due to invalid IL or missing references)
//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
//IL_01af: Unknown result type (might be due to invalid IL or missing references)
__state = float.NaN;
if (!(__instance is Scorpion))
{
return true;
}
bool flag = IsHeldAsItem(__instance);
if (Plugin.CfgOnlyAggressiveWhenHeld.Value && !flag)
{
ClearTarget(__instance);
return false;
}
if (!Plugin.CfgEnablePlayerTargeting.Value && !flag)
{
ClearTarget(__instance);
return false;
}
float num = Mathf.Max(0f, Plugin.CfgAggroDistanceMultiplier.Value);
bool flag2 = !Mathf.Approximately(num, 1f);
bool flag3 = !Plugin.CfgRequireLineOfSight.Value;
bool value = Plugin.CfgTargetPoisonedPlayers.Value;
if (!flag2 && !flag3 && !value)
{
return true;
}
if (flag2 && !flag3 && !value)
{
__state = __instance.aggroDistance;
__instance.aggroDistance = __state * num;
return true;
}
if (InTargetingCooldown(__instance) || (AttackingRef.Invoke(__instance) && (Object)(object)TargetCharRef.Invoke(__instance) != (Object)null))
{
return false;
}
TimeLastCheckedForTargetRef.Invoke(__instance) = Time.time;
Character val = null;
float num2 = __instance.aggroDistance * num;
bool value2 = Plugin.CfgRequireLineOfSight.Value;
bool value3 = Plugin.CfgTargetPoisonedPlayers.Value;
Vector3 val2 = Center(__instance);
Character forcedCharacterTarget = __instance.forcedCharacterTarget;
Affliction val3 = default(Affliction);
foreach (Character allCharacter in Character.AllCharacters)
{
if (!allCharacter.data.fullyConscious || ((Object)(object)forcedCharacterTarget != (Object)null && (Object)(object)allCharacter != (Object)(object)forcedCharacterTarget))
{
continue;
}
float num3 = Vector3.Distance(((Component)__instance).transform.position, allCharacter.Center);
if (num3 >= num2 || (!value3 && allCharacter.refs.afflictions.HasAfflictionType((AfflictionType)0, ref val3)))
{
continue;
}
if (value2)
{
RaycastHit val4 = HelperFunctions.LineCheck(val2, allCharacter.Center, (LayerType)1, 0f, (QueryTriggerInteraction)1);
if (Object.op_Implicit((Object)(object)((RaycastHit)(ref val4)).transform))
{
continue;
}
}
num2 = num3;
val = allCharacter;
}
try
{
SetTargetChar?.Invoke(__instance, new object[1] { val });
}
catch (Exception ex)
{
Plugin.Log.LogDebug((object)("Failed to set scorpion target (safe to ignore): " + ex.Message));
}
return false;
}
[HarmonyPatch(typeof(Mob), "Targeting")]
[HarmonyPostfix]
private static void MobTargeting_Postfix(Mob __instance, float __state)
{
if (__instance is Scorpion && !float.IsNaN(__state))
{
__instance.aggroDistance = __state;
}
}
[HarmonyPatch(typeof(Scorpion), "InflictAttack")]
[HarmonyPrefix]
private static bool ScorpionInflictAttack_Prefix(Scorpion __instance, Character character)
{
//IL_0116: Unknown result type (might be due to invalid IL or missing references)
//IL_0194: Unknown result type (might be due to invalid IL or missing references)
//IL_0215: Unknown result type (might be due to invalid IL or missing references)
//IL_021a: Unknown result type (might be due to invalid IL or missing references)
//IL_0225: Unknown result type (might be due to invalid IL or missing references)
//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
//IL_01b5: Invalid comparison between Unknown and I4
//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
//IL_01d6: Expected O, but got Unknown
//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
bool flag = Plugin.CfgDamageType.Value == Plugin.DamageTypeOverride.Vanilla || Plugin.CfgDamageType.Value == Plugin.DamageTypeOverride.Poison;
bool flag2 = Mathf.Approximately(Plugin.CfgDamageMultiplier.Value, 1f);
bool value = Plugin.CfgEnableInitialDamageTick.Value;
bool value2 = Plugin.CfgEnableOvertimeDamageTick.Value;
bool flag3 = Mathf.Approximately(Plugin.CfgInitialDamageMultiplier.Value, 1f);
bool flag4 = Mathf.Approximately(Plugin.CfgOvertimeDamageMultiplier.Value, 1f);
if (flag && flag2 && value && value2 && flag3 && flag4)
{
return true;
}
if (!character.IsLocal)
{
return false;
}
float num = Mathf.Max(0f, Plugin.CfgDamageMultiplier.Value);
float num2 = Mathf.Max(0f, Plugin.CfgInitialDamageMultiplier.Value);
float num3 = Mathf.Max(0f, Plugin.CfgOvertimeDamageMultiplier.Value);
bool value3 = Plugin.CfgEnableInitialDamageTick.Value;
bool value4 = Plugin.CfgEnableOvertimeDamageTick.Value;
float num4 = num * num2;
float num5 = num * num3;
STATUSTYPE val = (STATUSTYPE)((Plugin.CfgDamageType.Value == Plugin.DamageTypeOverride.Vanilla) ? Plugin.DamageTypeOverride.Poison : Plugin.CfgDamageType.Value);
float num6 = 1f - character.refs.afflictions.statusSum;
float num7 = Mathf.Max(0.5f, num6 + 0.05f);
float totalPoisonTime = __instance.totalPoisonTime;
float num8 = (value3 ? (0.025f * num4) : 0f);
float num9 = (value4 ? (num7 / Mathf.Max(0.01f, totalPoisonTime) * num5) : 0f);
if (num8 > 0f)
{
character.refs.afflictions.AddStatus(val, num8, false, true);
}
if (totalPoisonTime > 0f && num9 > 0f)
{
if ((int)val == 3)
{
character.refs.afflictions.AddAffliction((Affliction)new Affliction_PoisonOverTime(totalPoisonTime, 0f, num9), false);
}
else
{
ScorpionCustomDotRunner scorpionCustomDotRunner = ((Component)character).gameObject.GetComponent<ScorpionCustomDotRunner>();
if ((Object)(object)scorpionCustomDotRunner == (Object)null)
{
scorpionCustomDotRunner = ((Component)character).gameObject.AddComponent<ScorpionCustomDotRunner>();
}
scorpionCustomDotRunner.Stack(val, num9, totalPoisonTime);
}
}
character.AddForceAtPosition(500f * ((Mob)__instance).mesh.forward, ((Component)__instance).transform.position, 2f);
return false;
}
}
internal sealed class ScorpionCustomDotRunner : MonoBehaviour
{
private Character? _character;
private STATUSTYPE _statusType;
private float _statusPerSecond;
private float _timeRemaining;
private void Awake()
{
_character = ((Component)this).GetComponent<Character>();
((Behaviour)this).enabled = false;
}
public void Stack(STATUSTYPE statusType, float statusPerSecond, float duration)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
_statusType = statusType;
_statusPerSecond = Mathf.Max(_statusPerSecond, statusPerSecond);
_timeRemaining += duration;
((Behaviour)this).enabled = true;
}
private void Update()
{
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)_character == (Object)null || !_character.IsLocal)
{
((Behaviour)this).enabled = false;
return;
}
if (_timeRemaining <= 0f || _statusPerSecond <= 0f)
{
Object.Destroy((Object)(object)this);
return;
}
float deltaTime = Time.deltaTime;
_timeRemaining -= deltaTime;
_character.refs.afflictions.AddStatus(_statusType, _statusPerSecond * deltaTime, false, true);
}
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}