Decompiled source of Scoutmasters Rampage v3.0.0
tony.and.Snoszs-Scoutmasters Rampage.dll
Decompiled 3 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using ExitGames.Client.Photon; using HarmonyLib; using Microsoft.CodeAnalysis; using PEAKLib.Core; using Peak.Afflictions; using Photon.Pun; using Photon.Realtime; using PhotonCustomPropsUtils; using TMPro; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; using Zorro.Core; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("Scoutmasters Rampage")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Scoutmasters Rampage")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("93833b97-8a74-49f6-98d7-bcfbfffef43e")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] 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; } } } namespace ScoutmasterRampage { [BepInPlugin("tony4twentys.scoutmastersrampage", "Scoutmasters Rampage", "3.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class ScoutmasterRampagePlugin : BaseUnityPlugin { [HarmonyPatch(typeof(RunManager), "StartRun")] public class StartRunPatch { private static void Postfix() { if (!((Object)(object)Singleton<MapHandler>.Instance == (Object)null) && PhotonNetwork.IsMasterClient) { Instance.RefreshRespawnDelays(); Instance.ResetRunState(); Instance.IncreaseLitFireCount(); } } } [HarmonyPatch(typeof(Scoutmaster), "FixedUpdate")] private static class FixedUpdatePatch { private static bool Prefix(Scoutmaster __instance) { if (ScoutmasterPassOutSupport.IsScoutmasterDisabledForGrabOrPhysics(__instance.character)) { return false; } return true; } } [HarmonyPatch(typeof(CharacterGrabbing), "GrabAction")] public class ScoutmasterGrabActionPatch { private static bool Prefix(CharacterGrabbing __instance, Collision collision) { //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Invalid comparison between Unknown and I4 //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Expected I4, but got Unknown //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) if (!__instance.character.data.isScoutmaster || !((MonoBehaviourPun)__instance.character).photonView.IsMine || Object.op_Implicit((Object)(object)__instance.character.data.grabJoint) || !__instance.character.data.isReaching || __instance.character.data.sinceLetGoOfFriend < 0.35f || !Object.op_Implicit((Object)(object)collision.rigidbody)) { return true; } if (!PhotonNetwork.IsMasterClient) { return true; } if (ScoutmasterPassOutSupport.IsScoutmasterDisabledForGrabOrPhysics(__instance.character)) { return false; } Scoutmaster component = ((Component)__instance.character).GetComponent<Scoutmaster>(); if ((Object)(object)component != (Object)null && ScoutmasterNapberrySupport.IsTargetRepellingScoutmaster(component)) { return false; } Character val = default(Character); if (!CharacterRagdoll.TryGetCharacterFromCollider(collision.collider, ref val) || !Object.op_Implicit((Object)(object)val) || (Object)(object)val == (Object)(object)__instance.character) { return false; } BodypartType partType = val.GetPartType(collision.rigidbody); if ((int)partType != -1 && (Object)(object)__instance.character.data.grabbedPlayer == (Object)null && Instance.sinceLastGrabbedTimer >= 3f) { ((MonoBehaviourPun)__instance.character).photonView.RPC("RPCA_GrabAttach", (RpcTarget)0, new object[3] { ((MonoBehaviourPun)val).photonView, (int)partType, ((Component)collision.rigidbody).transform.InverseTransformPoint(((Component)__instance.character.GetBodypart((BodypartType)10).Rig).transform.position) }); Instance.sinceLastGrabbedTimer = 0f; } return false; } } [HarmonyPatch] private static class ScoutmasterIThrowInjuryTranspiler { private static MethodBase TargetMethod() { Type[] nestedTypes = typeof(Scoutmaster).GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic); foreach (Type type in nestedTypes) { if (type.Name.Contains("IThrow")) { MethodInfo methodInfo = AccessTools.Method(type, "MoveNext", (Type[])null, (Type[])null); if (methodInfo != null) { return methodInfo; } } } throw new Exception("Scoutmasters Rampage: could not find Scoutmaster.<IThrow> MoveNext for GrabInjuryAmount patch."); } private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { MethodInfo getInjury = AccessTools.Method(typeof(ScoutmasterIThrowInjuryTranspiler), "GetConfiguredGrabInjuryAmount", (Type[])null, (Type[])null); bool replaced = false; foreach (CodeInstruction instruction in instructions) { if (!replaced && instruction.opcode == OpCodes.Ldc_R4 && instruction.operand is float value && Mathf.Approximately(value, 0.25f)) { yield return new CodeInstruction(OpCodes.Call, (object)getInjury); replaced = true; } else { yield return instruction; } } if (!replaced) { Debug.LogWarning((object)"[Scoutmasters Rampage] IThrow injury transpiler did not find ldc.r4 0.25 — GrabInjuryAmount may not apply."); } } private static float GetConfiguredGrabInjuryAmount() { if (Instance?.configGrabInjuryAmount == null) { return 0.25f; } return Mathf.Clamp(Instance.configGrabInjuryAmount.Value, 0f, 1f); } } [HarmonyPatch(typeof(Scoutmaster), "DoVisuals")] public static class DoVisualsPatch { private static bool Prefix(Scoutmaster __instance) { //IL_0078: 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) if (Instance.configDisableScreenEffect.Value || Instance.configScreenEffectPower.Value <= 0f) { __instance.mat.SetFloat("_Strength", 0f); return false; } float num = 0f; if ((Object)(object)__instance.currentTarget != (Object)null) { __instance.currentTarget.data.myersDistance = Vector3.Distance(__instance.character.Center, __instance.currentTarget.Center); } if ((Object)(object)__instance.currentTarget != (Object)null && __instance.currentTarget.IsLocal) { num = Mathf.InverseLerp(50f, 5f, __instance.distanceToTarget); } num *= Instance.configScreenEffectPower.Value; __instance.mat.SetFloat("_Strength", Mathf.Lerp(__instance.mat.GetFloat("_Strength"), num, Time.deltaTime * 0.5f)); return false; } } [HarmonyPatch(typeof(Scoutmaster), "Update")] public class ScoutmasterUpdatePatch { private static bool Prefix(Scoutmaster __instance) { //IL_012c: 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) if (!PhotonNetwork.IsMasterClient) { return true; } __instance.UpdateAchievement(); __instance.DoVisuals(); if (Instance.HandleFleeing(__instance)) { return false; } if (!Instance.scoutmasterHasSpawned) { return false; } if (ScoutmasterRescueHookSupport.IsPullingScoutmaster(__instance.character)) { return false; } if (Instance.resetInputRequest) { __instance.ResetInput(); Instance.resetInputRequest = false; } if (ScoutmasterPassOutSupport.HandlePassOut(__instance)) { return false; } if (ScoutmasterNapberrySupport.TryOrbRepelMovement(__instance)) { return false; } if ((Object)(object)__instance.character.data.grabbedPlayer == (Object)null) { Instance.sinceLastGrabbedTimer += Time.deltaTime; } __instance.tpCounter += Time.deltaTime; Instance.HandleTargeting(__instance); if ((Object)(object)__instance.currentTarget == (Object)null) { return false; } __instance.CalcVars(); __instance.distanceToTarget = Vector3.Distance(__instance.character.Center, __instance.currentTarget.Center); if (Instance.TryCloseGapTeleport(__instance)) { return false; } Instance.Chase(__instance); return false; } } [HarmonyPatch(typeof(Campfire), "Light_Rpc")] public class CampfireLight_RpcPatch { private static void Postfix(bool updateSegment) { if (updateSegment && PhotonNetwork.IsMasterClient) { Instance.IncreaseLitFireCount(); } } } [HarmonyPatch(typeof(ScoutmasterSpawner), "SpawnScoutmaster")] public class ScoutmasterSpawnerPatch { private static void Postfix() { Scoutmaster val = default(Scoutmaster); if (PhotonNetwork.IsMasterClient && Scoutmaster.GetPrimaryScoutmaster(ref val)) { Instance.scoutmaster = val; Instance.scoutmasterCharacter = val.character; Instance.LogInfo("Scoutmaster reference captured from spawner."); } } } [HarmonyPatch(typeof(Scoutmaster), "TeleportFarAway")] public class ScoutmasterTeleportPatch { private static void Postfix(Scoutmaster __instance) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) if (Instance.isFleeing && PhotonNetwork.IsMasterClient) { ((Component)__instance).GetComponent<PhotonView>().RPC("WarpPlayerRPC", (RpcTarget)0, new object[2] { (object)new Vector3(0f, 0f, 5000f), false }); ((Component)__instance).GetComponent<PhotonView>().RPC("StopClimbingRpc", (RpcTarget)0, new object[1] { 0f }); __instance.discovered = null; } } } [HarmonyPatch(typeof(Bonkable), "Bonk")] private static class BonkPatch { private static bool Prefix(Bonkable __instance, Collision coll) { //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) Character val = default(Character); if (!CharacterRagdoll.TryGetCharacterFromCollider(coll.collider, ref val) || !Object.op_Implicit((Object)(object)val) || !val.isScoutmaster) { return true; } Scoutmaster component = ((Component)val).GetComponent<Scoutmaster>(); if ((Object)(object)component == (Object)null || Time.time <= __instance.lastBonkedTime + __instance.bonkCooldown) { return (Object)(object)component != (Object)null; } ScoutmasterBlessingSupport.TryGrantFromBonk(__instance.item); if (!PhotonNetwork.IsMasterClient) { return true; } float num = __instance.bonkForce; if (__instance.bonkMassMultiplier) { num *= ((Component)__instance.item).GetComponent<ItemScaleSyncer>().currentScale; } ScoutmasterRampagePlugin instance = Instance; Character character = val; Vector3 relativeVelocity = coll.relativeVelocity; instance.ApplyScoutmasterBonk(character, component, ((Vector3)(ref relativeVelocity)).normalized, num, __instance.bonkRange, ((ContactPoint)(ref coll.contacts[0])).point); for (int i = 0; i < __instance.bonk.Length; i++) { __instance.bonk[i].Play(((Component)__instance).transform.position); } __instance.lastBonkedTime = Time.time; return false; } } [HarmonyPatch(typeof(BananaPeel), "Update")] private static class UpdatePatch { private static void Postfix(BananaPeel __instance) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 //IL_004a: 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) Scoutmaster val = default(Scoutmaster); if ((int)__instance.item.itemState == 0 && PhotonNetwork.IsMasterClient && Scoutmaster.GetPrimaryScoutmaster(ref val) && !(__instance.counter < 3f) && !(Vector3.Distance(val.character.Center, ((Component)__instance).transform.position) > 3f) && val.character.data.isGrounded && !(((Vector3)(ref val.character.data.avarageVelocity)).magnitude < 1.5f)) { __instance.counter = 0f; ((Component)__instance).GetComponent<PhotonView>().RPC("RPCA_TriggerBanana", (RpcTarget)0, new object[1] { val.character.view.ViewID }); PhotonNetwork.Destroy(((Component)__instance).gameObject); } } } public const string PluginGuid = "tony4twentys.scoutmastersrampage"; public const string PluginName = "Scoutmasters Rampage"; public const string PluginVersion = "3.0.0"; public const string PhotonCustomPropsPluginGuid = "com.snosz.photoncustompropsutils"; private ConfigEntry<float> configInitialSpawn; private ConfigEntry<float> configFire2Delay; private ConfigEntry<float> configFire3Delay; private ConfigEntry<float> configFire4Delay; private ConfigEntry<float> configFire5Delay; private ConfigEntry<bool> configEnableLogs; private ConfigEntry<float> configTeleportDistance; private ConfigEntry<float> configLostSightTeleportTime; private ConfigEntry<float> configTeleportCooldown; private ConfigEntry<float> configTeleportMinDistance; private ConfigEntry<float> configTeleportMaxDistance; private ConfigEntry<float> configTeleportMaxHeight; private ConfigEntry<float> configFleeDuration; private ConfigEntry<float> configSprintDistance; private ConfigEntry<float> configMovementBoostDistance; private ConfigEntry<float> configMovementBoostMultiplier; private ConfigEntry<bool> configInstaKillOnGrab; private ConfigEntry<float> configGrabInjuryAmount; private ConfigEntry<float> configClimbSpeed; private ConfigEntry<float> configRunSpeed; private ConfigEntry<float> configFaerieLanternFleeDistance; private ConfigEntry<float> configBonkStunDuration; private ConfigEntry<float> configForceRespawnBehindDistance; private ConfigEntry<float> configSpawnDropHeight; private ConfigEntry<KeyCode> configForceScoutmasterRespawn; private ConfigEntry<bool> configDisableScreenEffect; private ConfigEntry<float> configScreenEffectPower; private float[] respawnDelays; private int litFireCount = -1; private float respawnEndTime = -1f; private const string LogPrefix = "[Scoutmasters Rampage] "; private float lingerTimer = 0f; private float targetingTimer = 0f; private float sinceLastGrabbedTimer = 0f; private float fleeTimer = 0f; private bool scoutmasterHasSpawned = false; private bool resetInputRequest = false; private const float SpawnRetryDelay = 3f; private const float StuckHorizontalTolerance = 2f; private const float StuckLingerTime = 3f; private const float StuckMinVerticalSeparation = 10f; private const float StuckTeleportMinDistance = 30f; private const float StuckTeleportMaxDistance = 50f; private const float StuckTeleportMaxHeight = 15f; private const float TargetRetargetInterval = 3f; private const float GrabCooldown = 3f; private const float ForceRespawnAirborneHeight = 5f; private const float SpawnGroundRaycastHeight = 150f; private const float SpawnGroundRaycastDepth = 500f; private bool isSpawning = false; private Scoutmaster scoutmaster; private Character scoutmasterCharacter; private bool isFleeing; private bool passOutRetreatTriggersRespawn; private Vector3? fleeAwayFrom; internal static ScoutmasterRampagePlugin Instance { get; private set; } internal float FaerieLanternFleeDistance => configFaerieLanternFleeDistance.Value; internal bool IsFleeing => isFleeing; internal bool IsPassOutRetreatActive => passOutRetreatTriggersRespawn; internal bool IsTargetHoldingLitFaerieLantern(Character target) { object obj; if (target == null) { obj = null; } else { CharacterData data = target.data; obj = ((data != null) ? data.currentItem : null); } return (Object)obj != (Object)null && target.data.currentItem.itemID == 43 && target.data.currentItem.GetData<BoolItemData>((DataEntryKey)3).Value; } private void Awake() { //IL_00c4: Unknown result type (might be due to invalid IL or missing references) Instance = this; SetupConfig(); ScoutmasterBlowDartSupport.Initialize(((BaseUnityPlugin)this).Config); ScoutmasterRescueHookSupport.Initialize(((BaseUnityPlugin)this).Config); ScoutmasterOverheadStatus.Initialize(((BaseUnityPlugin)this).Config); ScoutmasterAfflictionSupport.Initialize(((BaseUnityPlugin)this).Config); ScoutmasterFallDamageSupport.Initialize(); ScoutmasterPassOutSupport.Initialize(((BaseUnityPlugin)this).Config); ScoutmasterNapberrySupport.Initialize(((BaseUnityPlugin)this).Config); ScoutmasterWindChillSupport.Initialize(((BaseUnityPlugin)this).Config); ScoutmasterLavaSupport.Initialize(((BaseUnityPlugin)this).Config); ScoutmasterKilnSupport.Initialize(((BaseUnityPlugin)this).Config); ScoutmasterTorchSupport.Initialize(((BaseUnityPlugin)this).Config); ScoutmasterLootSupport.Initialize(((BaseUnityPlugin)this).Config); ScoutmasterBlessingSupport.Initialize(((BaseUnityPlugin)this).Config); ScoutmasterConfigSyncService.Initialize(((BaseUnityPlugin)this).Config); ScoutmasterModAuthorizationService.Initialize(); RefreshRespawnDelays(); try { new Harmony("tony4twentys.scoutmastersrampage").PatchAll(); LogInfo("Plugin initialized and Harmony patches applied."); } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"Harmony PatchAll failed — some features may not work: {arg}"); } SceneManager.sceneLoaded += OnSceneLoaded; ScoutmasterBlessingSupport.EnsureEventHook(); } private void OnDestroy() { SceneManager.sceneLoaded -= OnSceneLoaded; } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { //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) //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (ShouldResetRunStateForScene(scene, mode)) { LogInfo($"Scene '{((Scene)(ref scene)).name}' ({mode}) — resetting run state for a fresh expedition."); ResetRunState(); } TryGetScoutmaster(out var _); ScoutmasterBlessingSupport.EnsureEventHook(); } private static bool ShouldResetRunStateForScene(Scene scene, LoadSceneMode mode) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Invalid comparison between Unknown and I4 if (!((Scene)(ref scene)).IsValid() || string.IsNullOrEmpty(((Scene)(ref scene)).name)) { return false; } if ((int)mode == 1) { return false; } string name = ((Scene)(ref scene)).name; if (name.Equals("Airport", StringComparison.OrdinalIgnoreCase) || name.Equals("Title", StringComparison.OrdinalIgnoreCase) || name.Equals("Pretitle", StringComparison.OrdinalIgnoreCase)) { return true; } return name.StartsWith("Level_", StringComparison.OrdinalIgnoreCase); } private void ResetRunState() { litFireCount = -1; respawnEndTime = -1f; scoutmasterHasSpawned = false; isSpawning = false; isFleeing = false; scoutmaster = null; scoutmasterCharacter = null; lingerTimer = 0f; targetingTimer = 0f; sinceLastGrabbedTimer = 0f; fleeTimer = 0f; passOutRetreatTriggersRespawn = false; fleeAwayFrom = null; ScoutmasterOverheadStatus.Reset(); ScoutmasterPassOutSupport.Reset(); ScoutmasterTorchSupport.Reset(); ScoutmasterAfflictionSupport.ResetStatusSync(); } internal void RefreshRespawnDelaysPublic() { RefreshRespawnDelays(); } private void RefreshRespawnDelays() { respawnDelays = new float[5] { configInitialSpawn.Value, configFire2Delay.Value, configFire3Delay.Value, configFire4Delay.Value, configFire5Delay.Value }; } internal bool TryGetScoutmaster(out Scoutmaster resolved) { if (Scoutmaster.GetPrimaryScoutmaster(ref resolved)) { scoutmaster = resolved; scoutmasterCharacter = resolved.character; return true; } if ((Object)(object)scoutmaster != (Object)null) { resolved = scoutmaster; return true; } resolved = null; return false; } private Character FindFurthestBehindPlayer() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) Character result = null; float num = float.MinValue; Vector3 position; bool hasCampfire = TryGetCurrentCampfirePosition(out position); foreach (Character allCharacter in Character.AllCharacters) { if (IsViablePlayer(allCharacter)) { float behindScore = GetBehindScore(allCharacter, hasCampfire, position); if (behindScore > num) { num = behindScore; result = allCharacter; } } } return result; } private static bool IsViablePlayer(Character character) { return (Object)(object)character != (Object)null && !character.isBot && !character.data.dead && !character.data.fullyPassedOut; } private float GetBehindScore(Character character, bool hasCampfire, Vector3 campfirePos) { //IL_0038: 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_000d: 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_0020: Unknown result type (might be due to invalid IL or missing references) if (hasCampfire) { float num = Vector3.Distance(character.Center, campfirePos); float num2 = Mathf.Max(0f, campfirePos.y - character.Center.y); return num + num2; } return 0f - character.Center.y; } private bool TryGetCurrentCampfirePosition(out Vector3 position) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_007c: 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) position = default(Vector3); if (!MapHandler.Exists) { return false; } MapHandler instance = Singleton<MapHandler>.Instance; if ((Object)(object)instance == (Object)null) { return false; } Campfire val = TryGetCampfireForSegment(instance.currentSegment); if ((Object)(object)val == (Object)null && instance.currentSegment > 0) { val = TryGetCampfireForSegment(instance.currentSegment - 1); } if ((Object)(object)val == (Object)null) { return false; } position = val.Center(); return true; } private static Campfire TryGetCampfireForSegment(int segmentIndex) { if (segmentIndex < 0) { return null; } GameObject campfireRoot = MapHandler.GetCampfireRoot(segmentIndex); if ((Object)(object)campfireRoot == (Object)null) { return null; } return campfireRoot.GetComponentInChildren<Campfire>(true); } private void ForceRespawnScoutmasterFromHotkey() { try { if (!TryGetScoutmaster(out var _)) { LogWarning("F1 force respawn — scoutmaster not found."); return; } Character val = FindFurthestBehindPlayer(); if ((Object)(object)val == (Object)null) { LogWarning("F1 force respawn — no valid players found."); } else { PlaceScoutmasterBehindPlayer(val, "F1 force respawn"); } } catch (Exception ex) { LogWarning("F1 force respawn failed (" + ex.Message + ")."); } } private void PlaceScoutmasterBehindPlayer(Character player, string reason) { if (!TryGetScoutmaster(out var resolved) || (Object)(object)player == (Object)null) { LogWarning("Cannot place Scoutmaster — scoutmaster or target character is missing."); return; } ScoutmasterSegmentSupport.EnsureScoutmasterSpawnable(resolved); isSpawning = false; isFleeing = false; fleeTimer = 0f; scoutmasterHasSpawned = true; ReleaseGrabIfNeeded(resolved); resolved.view.RPC("RPCA_SetCurrentTarget", (RpcTarget)0, new object[2] { -1, 0f }); Vector3 spawnPosition; bool flag = ScoutmasterKilnSupport.TryGetKilnSpawnPosition(player, out spawnPosition); WarpNearPlayer(resolved, player); targetingTimer = 3f; if (flag) { Player owner = player.refs.view.Owner; LogInfo(reason + " — placed on standable kiln ground near " + (((owner != null) ? owner.NickName : null) ?? "Unknown") + "."); } else { object arg = configForceRespawnBehindDistance.Value; Player owner2 = player.refs.view.Owner; LogInfo(string.Format("{0} — placed {1:F0}m behind {2} (furthest behind on climb).", reason, arg, ((owner2 != null) ? owner2.NickName : null) ?? "Unknown")); } resetInputRequest = true; } private void SetupConfig() { //IL_0308: Unknown result type (might be due to invalid IL or missing references) //IL_0312: Expected O, but got Unknown //IL_0346: Unknown result type (might be due to invalid IL or missing references) //IL_0350: Expected O, but got Unknown //IL_0384: Unknown result type (might be due to invalid IL or missing references) //IL_038e: Expected O, but got Unknown configForceScoutmasterRespawn = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "ForceScoutmasterRespawn", (KeyCode)282, "Keyboard key the host presses to instantly reposition the scoutmaster. Only works for the master client (host). He is placed behind whichever player is furthest behind on the climb (furthest from the current campfire, with height below the fire counting as extra \"behind\"). Useful if he is stuck, fell off the map, or you need to reset a bad chase. Does not restart spawn timers."); configDisableScreenEffect = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DisableScreenEffect", false, "Turns off the vanilla scoutmaster screen effect (grain/distortion on the targeted player) entirely when true. If false, intensity is controlled by ScreenEffectPower instead."); configScreenEffectPower = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ScreenEffectPower", 0.5f, "Multiplier for the scoutmaster screen effect on the player he is chasing. 0 = no effect, 0.5 = half intensity (default), 1 = full vanilla intensity. Effect ramps up as he gets closer (strongest inside roughly 5m, fades out toward ~50m). DisableScreenEffect overrides this when true."); configInitialSpawn = ((BaseUnityPlugin)this).Config.Bind<float>("Delays", "InitialSpawn", 300f, "Seconds after the expedition starts before the scoutmaster first appears. When the timer ends, he spawns behind the furthest-behind player. Default 300 = 5 minutes. Host-only. Set lower for faster first contact, higher to delay his debut."); configFire2Delay = ((BaseUnityPlugin)this).Config.Bind<float>("Delays", "Fire2Respawn", 600f, "Seconds to wait before respawning the scoutmaster after the first campfire segment is lit. When that fire is lit, he is sent away (flees, then teleports off the map) and returns after this delay. Default 600 = 10 minutes."); configFire3Delay = ((BaseUnityPlugin)this).Config.Bind<float>("Delays", "Fire3Respawn", 900f, "Seconds to wait before respawning the scoutmaster after the second campfire segment is lit. Same flee-then-respawn cycle as other fire delays. Default 900 = 15 minutes."); configFire4Delay = ((BaseUnityPlugin)this).Config.Bind<float>("Delays", "Fire4Respawn", 420f, "Seconds to wait before respawning the scoutmaster after the third campfire segment is lit. Default 420 = 7 minutes."); configFire5Delay = ((BaseUnityPlugin)this).Config.Bind<float>("Delays", "Fire5Respawn", 900f, "Seconds to wait before respawning the scoutmaster after the fourth campfire segment is lit. Also used when the fifth segment (kiln) is lit. Default 900 = 15 minutes."); configEnableLogs = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "EnableLogs", false, "Writes detailed scoutmaster events to the BepInEx LogOutput.log (spawns, teleports, fire timers, F1 respawns, warnings). Off by default. Turn on only when troubleshooting."); configTeleportDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Chase", "TeleportDistance", 80f, "If the chase target is farther away than this many meters, the scoutmaster attempts a close-gap teleport toward them (landing somewhere between TeleportMinDistance and TeleportMaxDistance away, within TeleportMaxHeight vertically). Lower = he teleports sooner when players spread out. Higher = he runs/climbs longer before blinking. Default matches vanilla ~80m."); configLostSightTeleportTime = ((BaseUnityPlugin)this).Config.Bind<float>("Chase", "LostSightTeleportTime", 30f, "If the scoutmaster has a target but cannot see them for this many seconds, AND no player currently has line-of-sight to him, he teleports closer using the same min/max distance and height rules as normal close teleports. Set to 0 to disable lost-sight teleports entirely. Default 30 seconds."); configTeleportCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("Chase", "TeleportCooldown", 5f, "Minimum seconds between close-gap teleports during chase. The game’s built-in Teleport() also enforces a 5 second floor, so values below 5 will not make in-chase teleports faster—only some internal timers use the lower value. Increase to make him blink less often."); configTeleportMinDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Chase", "TeleportMinDistance", 50f, "Closest the scoutmaster can land to his target when using a close-gap or lost-sight teleport (meters). Prevents him from appearing right on top of players. Default 50."); configTeleportMaxDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Chase", "TeleportMaxDistance", 70f, "Farthest he can land from his target on a close-gap or lost-sight teleport (meters). Works with TeleportMinDistance to define the landing ring around the target. Default 70."); configTeleportMaxHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Chase", "TeleportMaxHeight", 15f, "Maximum vertical difference between the scoutmaster’s landing spot and his target on close-gap / lost-sight teleports (meters). Stops him from teleporting to unrealistic heights above or below the target. Default 15."); configFleeDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Chase", "FleeDuration", 4f, "When a campfire respawn cycle sends the scoutmaster away, he runs from players for this many seconds before teleporting far off the map. Shorter = quicker despawn. Longer = more visible \"retreat\" before he vanishes. Default 4 seconds."); configSprintDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Chase", "SprintDistance", 15f, "While chasing, he holds sprint when farther than this many meters from his target (straight-line distance). Lower = sprints more often. Higher = jogs until he is closer. Default 15."); configMovementBoostDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Chase", "MovementBoostDistance", 15f, "Flat (XZ) distance within which MovementBoostMultiplier kicks in. This is a short-range closing boost when he is already near the target—not the same as ClimbSpeed/RunSpeed. Default 15 meters."); configMovementBoostMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Chase", "MovementBoostMultiplier", 1.2f, "Extra ground-speed multiplier only while within MovementBoostDistance of the target (default 1.2 = +20%). Stacks on top of RunSpeed. ClimbSpeed/RunSpeed scale his overall chase pace; this only speeds him up in the last stretch to help close for a grab."); configInstaKillOnGrab = ((BaseUnityPlugin)this).Config.Bind<bool>("Chase", "InstaKillOnGrab", false, "When true, grabbing a player instantly kills them (DieInstantly) instead of the normal hold-and-throw. Off by default."); configGrabInjuryAmount = ((BaseUnityPlugin)this).Config.Bind<float>("Chase", "GrabInjuryAmount", 0.25f, new ConfigDescription("Injury status applied to the grabbed player when the scoutmaster finishes his throw. Vanilla default is 0.25. Set to 0 for no throw injury. Ignored when InstaKillOnGrab is true.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); configClimbSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Chase", "ClimbSpeed", 1f, new ConfigDescription("Adjustment to the scoutmaster’s climb speed while chasing. 1.0 = vanilla. Higher = climbs faster. Capped at 5.0.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>())); configRunSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Chase", "RunSpeed", 1f, new ConfigDescription("Adjustment to the scoutmaster’s ground run/walk speed while chasing. 1.0 = vanilla. Stacks with MovementBoostMultiplier when in range. Capped at 5.0.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>())); configBonkStunDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Interactions", "BonkStunDuration", 5f, "How long the scoutmaster ragdolls/falls when hit by a bonkable object like a coconut (host only). Also interrupts grabs and throws. Default 5 seconds. Blow darts use drowsy afflictions instead."); configFaerieLanternFleeDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Interactions", "FaerieLanternFleeDistance", 20f, "If his target is holding a lit faerie lantern (item ID 43, flare active) and he is within this many meters (flat distance), he walks backward instead of toward them—vanilla-style lantern repel behavior preserved by the mod. Default 20."); configForceRespawnBehindDistance = ((BaseUnityPlugin)this).Config.Bind<float>("ForceRespawn", "BehindDistance", 10f, "Meters behind the furthest-behind player to place the scoutmaster on F1 force respawn and on scheduled fire respawns. \"Behind\" uses the player’s flat look direction. If the player is more than 5m above their ground position (climbing, So Fly, etc.), placement uses their body center instead of ground height."); configSpawnDropHeight = ((BaseUnityPlugin)this).Config.Bind<float>("ForceRespawn", "SpawnDropHeight", 12f, "Meters above the terrain surface to place the scoutmaster when respawning behind a player. He warps in the air and falls to the ground. Helps avoid spawning under the map on uneven terrain."); RefreshRespawnDelays(); } private void Update() { //IL_00ad: Unknown result type (might be due to invalid IL or missing references) if (!PhotonNetwork.IsMasterClient) { return; } if (isSpawning && !isFleeing) { HandleIsSpawning(); } if (TryGetScoutmaster(out var resolved)) { ScoutmasterTorchSupport.Tick(resolved); ScoutmasterAfflictionSupport.TickHostStatusSync(resolved.character); if (scoutmasterHasSpawned) { ScoutmasterLavaSupport.TickHostScoutmaster(resolved); } } if (isFleeing && !TryGetScoutmaster(out var _)) { LogWarning("Flee was active but scoutmaster not found — clearing flee so respawn timer can continue."); isFleeing = false; scoutmasterHasSpawned = false; } if (UnityInput.Current.GetKeyDown(configForceScoutmasterRespawn.Value)) { ForceRespawnScoutmasterFromHotkey(); } } private void WaitForValidCharacterAndSpawn() { if (isFleeing) { return; } try { if (!TryGetScoutmaster(out var _)) { LogWarning("Scoutmaster has not spawned yet — retrying soon."); respawnEndTime = 3f; return; } Character val = FindFurthestBehindPlayer(); if ((Object)(object)val == (Object)null) { LogWarning("No valid players found yet — retrying soon."); respawnEndTime = 3f; } else { LogInfo("Valid player found — proceeding with Scoutmaster spawn."); PlaceScoutmasterBehindPlayer(val, "Scheduled spawn"); isSpawning = false; } } catch (Exception ex) { LogWarning($"Scheduled spawn failed ({ex.Message}) — retrying in {3f}s."); respawnEndTime = 3f; } } private static bool IsScoutmasterOnMap(Scoutmaster activeScoutmaster) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)activeScoutmaster?.character == (Object)null) { return false; } return activeScoutmaster.character.Center.z < 4990f; } private void IncreaseLitFireCount() { if (!PhotonNetwork.IsMasterClient) { return; } isSpawning = false; respawnEndTime = -1f; Instance.litFireCount++; LogInfo($"Fire lit. Count: {Instance.litFireCount}"); if (litFireCount >= respawnDelays.Length) { LogInfo("Beyond final fire segment — despawning without new respawn timer."); DespawnScoutmaster(); return; } if (litFireCount == 0) { LogInfo("Starting initial spawn timer (fire 1)."); } else { LogInfo($"Despawning Scoutmaster and setting respawn timer from fire {litFireCount}."); DespawnScoutmaster(); } int num = Mathf.Min(litFireCount, respawnDelays.Length - 1); respawnEndTime = respawnDelays[num]; LogInfo($"Setting respawnEndTime: {respawnEndTime} (delay index {num}). Starting spawn delay"); isSpawning = true; } internal void ForcePassOutImmediateRetreat(Scoutmaster activeScoutmaster) { //IL_009a: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)activeScoutmaster == (Object)null)) { isFleeing = false; fleeTimer = 0f; passOutRetreatTriggersRespawn = false; fleeAwayFrom = null; ReleaseGrabIfNeeded(activeScoutmaster); activeScoutmaster.currentTarget = null; activeScoutmaster.view.RPC("RPCA_SetCurrentTarget", (RpcTarget)0, new object[2] { -1, 0f }); PhotonView component = ((Component)activeScoutmaster).GetComponent<PhotonView>(); component.RPC("WarpPlayerRPC", (RpcTarget)0, new object[2] { (object)new Vector3(0f, 0f, 5000f), false }); component.RPC("StopClimbingRpc", (RpcTarget)0, new object[1] { 0f }); activeScoutmaster.discovered = null; ScoutmasterPassOutSupport.OnRetreatComplete(activeScoutmaster); scoutmasterHasSpawned = false; isSpawning = true; respawnEndTime = ScoutmasterPassOutSupport.RecoveryRespawnDelay; LogInfo($"Pass-out failsafe — scoutmaster off-map; respawn in {ScoutmasterPassOutSupport.RecoveryRespawnDelay:F0}s."); } } internal void StartPassOutRetreat(Scoutmaster activeScoutmaster) { isFleeing = true; fleeTimer = 0f; passOutRetreatTriggersRespawn = true; fleeAwayFrom = GetNearestPlayerPosition(activeScoutmaster?.character); activeScoutmaster.currentTarget = null; activeScoutmaster.view.RPC("RPCA_SetCurrentTarget", (RpcTarget)0, new object[2] { -1, 0f }); activeScoutmaster.ResetInput(); resetInputRequest = true; } private Vector3? GetNearestPlayerPosition(Character scoutmasterCharacter) { //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_00a2: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)scoutmasterCharacter == (Object)null) { return null; } Character val = null; float num = float.MaxValue; foreach (Character allCharacter in Character.AllCharacters) { if (IsViablePlayer(allCharacter)) { float num2 = Vector3.Distance(scoutmasterCharacter.Center, allCharacter.Center); if (num2 < num) { num = num2; val = allCharacter; } } } return (val != null) ? new Vector3?(val.Center) : ((Vector3?)null); } internal void ReleaseGrabIfNeeded(Scoutmaster activeScoutmaster) { if (!((Object)(object)activeScoutmaster.character.data.grabbedPlayer == (Object)null)) { if (activeScoutmaster.isThrowing) { ((MonoBehaviour)activeScoutmaster).StopCoroutine("IThrow"); activeScoutmaster.isThrowing = false; } activeScoutmaster.character.view.RPC("RPCA_GrabUnattach", (RpcTarget)0, Array.Empty<object>()); activeScoutmaster.character.data.isReaching = false; activeScoutmaster.character.input.useSecondaryIsPressed = false; } } private void WarpNearPlayer(Scoutmaster activeScoutmaster, Character character) { //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_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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_0095: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_009a: 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_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: 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_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) Vector3 val; if (ScoutmasterKilnSupport.TryGetKilnSpawnPosition(character, out var spawnPosition)) { val = spawnPosition; } else { Vector3 val2 = character.data.lookDirection_Flat; if (((Vector3)(ref val2)).sqrMagnitude < 0.01f) { val2 = -((Component)character).transform.forward; } val2.y = 0f; ((Vector3)(ref val2)).Normalize(); float num = character.Center.y - character.data.groundPos.y; Vector3 val3 = ((num > 5f) ? character.Center : character.data.groundPos); Vector3 horizontalPoint = val3 + val2 * configForceRespawnBehindDistance.Value; val = GetSpawnPositionAboveGround(horizontalPoint, character.Center.y); } PhotonView component = ((Component)activeScoutmaster).GetComponent<PhotonView>(); component.RPC("WarpPlayerRPC", (RpcTarget)0, new object[2] { val, false }); component.RPC("StopClimbingRpc", (RpcTarget)0, new object[1] { 0f }); } private Vector3 GetSpawnPositionAboveGround(Vector3 horizontalPoint, float referenceHeight) { //IL_0002: 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_001d: 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_0029: 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_0034: 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) //IL_004a: 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_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: 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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: 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_0078: 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_00a0: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Max(referenceHeight, horizontalPoint.y) + 150f; Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(horizontalPoint.x, num, horizontalPoint.z); RaycastHit val2 = HelperFunctions.LineCheck(val, val + Vector3.down * 500f, (LayerType)1, 0f, (QueryTriggerInteraction)1); if (Object.op_Implicit((Object)(object)((RaycastHit)(ref val2)).transform)) { return ((RaycastHit)(ref val2)).point + Vector3.up * configSpawnDropHeight.Value; } return horizontalPoint + Vector3.up * configSpawnDropHeight.Value; } public void Chase(Scoutmaster scoutmaster) { //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) Character anchorPlayer = FindFurthestBehindPlayer() ?? scoutmaster.currentTarget; if (ScoutmasterKilnSupport.TryLostSightStandableTeleport(scoutmaster, anchorPlayer, configLostSightTeleportTime.Value, configTeleportCooldown.Value)) { return; } if (!ScoutmasterKilnSupport.BlocksCloseGapAndStuckTeleports() && configLostSightTeleportTime.Value > 0f && scoutmaster.sinceSeenTarget > configLostSightTeleportTime.Value && !scoutmaster.AnyoneCanSeeMe()) { scoutmaster.sinceSeenTarget = 0f; scoutmaster.tpCounter = Mathf.Max(configTeleportCooldown.Value, 5f); scoutmaster.Teleport(scoutmaster.currentTarget, configTeleportMinDistance.Value, configTeleportMaxDistance.Value, configTeleportMaxHeight.Value); return; } HandleClimbing(scoutmaster, scoutmaster.currentTarget.Center); if (!HandleGrabbedPlayer(scoutmaster)) { scoutmaster.LookAt(scoutmaster.currentTarget.Head); float num = Vector3.Distance(scoutmaster.character.Center, scoutmaster.currentTarget.Center); HandleWalkTowards(scoutmaster, scoutmaster.currentTarget.Head, 1f); scoutmaster.character.input.sprintIsPressed = num > configSprintDistance.Value; if (Vector3.Distance(scoutmaster.character.Center, scoutmaster.currentTarget.Center) < 3f && scoutmaster.character.data.sinceClimb > 1f && scoutmaster.character.data.isGrounded && !ScoutmasterPassOutSupport.IsScoutmasterDisabledForGrabOrPhysics(scoutmaster.character) && !ScoutmasterNapberrySupport.IsTargetRepellingScoutmaster(scoutmaster)) { scoutmaster.character.input.useSecondaryIsPressed = true; Instance.resetInputRequest = true; } } } internal void HandleWalkTowardsPublic(Scoutmaster scoutmaster, Vector3 targetPos, float mult) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) HandleWalkTowards(scoutmaster, targetPos, mult); } private void HandleWalkTowards(Scoutmaster scoutmaster, Vector3 targetPos, float mult) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0097: 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_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: 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) float num = HelperFunctions.FlatDistance(scoutmaster.character.Center, targetPos); float num2 = ((num <= configMovementBoostDistance.Value) ? configMovementBoostMultiplier.Value : 1f); scoutmaster.character.refs.movement.movementModifier = num2 * configRunSpeed.Value; ScoutmasterNapberrySupport.TryModifyChaseWalk(scoutmaster, ref targetPos, ref mult); if (IsTargetHoldingLitFaerieLanternCondition(scoutmaster) && num < configFaerieLanternFleeDistance.Value) { mult = 0f - mult; } scoutmaster.character.input.movementInput = new Vector2(0f, mult); TryToStartWallClimb(scoutmaster.character); if (!scoutmaster.character.data.isClimbing) { RaycastHit val = HelperFunctions.LineCheck(scoutmaster.character.Center, scoutmaster.character.Center + Vector3.down * 3f, (LayerType)1, 0f, (QueryTriggerInteraction)1); if (!((Object)(object)((RaycastHit)(ref val)).transform == (Object)null)) { } } if ((Object)(object)scoutmaster.currentTarget != (Object)null) { HandleStuckAboveOrBelowTarget(scoutmaster); } } private void HandleStuckAboveOrBelowTarget(Scoutmaster scoutmaster) { //IL_0043: 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_006a: 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_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: 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) if (ScoutmasterKilnSupport.BlocksCloseGapAndStuckTeleports()) { lingerTimer = 0f; } else { if ((Object)(object)((scoutmaster != null) ? scoutmaster.currentTarget : null) == (Object)null) { return; } Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(scoutmaster.character.Center.x, scoutmaster.character.Center.z); Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(scoutmaster.currentTarget.Center.x, scoutmaster.currentTarget.Center.z); float num = Vector2.Distance(val, val2); bool flag = num <= 2f; float num2 = Mathf.Abs(scoutmaster.character.Center.y - scoutmaster.currentTarget.Center.y); bool flag2 = num2 >= 10f; if (flag && flag2) { lingerTimer += Time.deltaTime; if (lingerTimer >= 3f) { TryTeleportNearTarget(scoutmaster); lingerTimer = 0f; } } else { lingerTimer = 0f; } } } private bool TryCloseGapTeleport(Scoutmaster scoutmaster) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) if (ScoutmasterKilnSupport.BlocksCloseGapAndStuckTeleports()) { return false; } if ((Object)(object)scoutmaster.currentTarget == (Object)null) { return false; } if (scoutmaster.tpCounter < configTeleportCooldown.Value) { return false; } float num = Vector3.Distance(scoutmaster.character.Center, scoutmaster.currentTarget.Center); if (num <= configTeleportDistance.Value) { return false; } LogInfo($"Target is {num:F0}m away (threshold {configTeleportDistance.Value:F0}m) — attempting close teleport."); scoutmaster.tpCounter = Mathf.Max(configTeleportCooldown.Value, 5f); scoutmaster.Teleport(scoutmaster.currentTarget, configTeleportMinDistance.Value, configTeleportMaxDistance.Value, configTeleportMaxHeight.Value); return true; } private bool TryTeleportNearTarget(Scoutmaster scoutmaster) { //IL_0026: 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_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_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0091: 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_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: 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_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0087: 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_00ca: 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_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)scoutmaster.currentTarget == (Object)null) { return false; } int num = 50; while (num > 0) { num--; Vector3 onUnitSphere = Random.onUnitSphere; Vector3 val = scoutmaster.currentTarget.Center + Vector3.up * 500f + onUnitSphere * 95f; Vector3 val2 = Vector3.down; if (num < 25) { val = scoutmaster.currentTarget.Center + Vector3.up; val2 = Random.onUnitSphere; } RaycastHit val3 = HelperFunctions.LineCheck(val, val + val2 * 1000f, (LayerType)1, 0f, (QueryTriggerInteraction)1); if (Object.op_Implicit((Object)(object)((RaycastHit)(ref val3)).transform)) { float num2 = Vector3.Distance(((RaycastHit)(ref val3)).point, scoutmaster.currentTarget.Center); float num3 = Mathf.Abs(((RaycastHit)(ref val3)).point.y - scoutmaster.currentTarget.Center.y); if (!scoutmaster.AnyoneCanSeePos(((RaycastHit)(ref val3)).point + Vector3.up) && num2 >= 30f && num2 <= 50f && num3 <= 15f) { scoutmaster.character.view.RPC("WarpPlayerRPC", (RpcTarget)0, new object[2] { ((RaycastHit)(ref val3)).point + Vector3.up, false }); scoutmaster.character.view.RPC("StopClimbingRpc", (RpcTarget)0, new object[1] { 0f }); scoutmaster.tpCounter = 0f; return true; } } } return false; } private void HandleClimbing(Scoutmaster scoutmaster, Vector3 target) { //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) //IL_0059: 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_0078: 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) if (!scoutmaster.character.data.isClimbing) { return; } scoutmaster.character.refs.climbing.climbSpeedMod = configClimbSpeed.Value; scoutmaster.ClimbTowards(target, 1f); if (!ScoutmasterKilnSupport.KeepsClimbingTowardTarget() && target.y < scoutmaster.character.Center.y) { RaycastHit val = HelperFunctions.LineCheck(scoutmaster.character.Center, target, (LayerType)1, 0f, (QueryTriggerInteraction)1); if (!Object.op_Implicit((Object)(object)((RaycastHit)(ref val)).transform)) { scoutmaster.character.refs.climbing.StopClimbing(); } } } private bool HandleGrabbedPlayer(Scoutmaster scoutmaster) { if (ScoutmasterPassOutSupport.IsScoutmasterDisabledForGrabOrPhysics(scoutmaster.character)) { ReleaseGrabIfNeeded(scoutmaster); return false; } if (ScoutmasterNapberrySupport.IsTargetRepellingScoutmaster(scoutmaster)) { ReleaseGrabIfNeeded(scoutmaster); scoutmaster.character.input.useSecondaryIsPressed = false; return false; } if ((Object)(object)scoutmaster.character.data.grabbedPlayer != (Object)null) { if (configInstaKillOnGrab.Value) { Character grabbedPlayer = scoutmaster.character.data.grabbedPlayer; if ((Object)(object)grabbedPlayer != (Object)null && !grabbedPlayer.data.dead) { grabbedPlayer.DieInstantly(); } ReleaseGrabIfNeeded(scoutmaster); Instance.resetInputRequest = true; return true; } scoutmaster.HoldPlayer(); Instance.resetInputRequest = true; return true; } return false; } private void HandleIsSpawning() { if (!Instance.isFleeing) { if (Instance.respawnEndTime > 0f) { Instance.respawnEndTime -= Time.deltaTime; } else { Instance.WaitForValidCharacterAndSpawn(); } } } private bool HandleFleeing(Scoutmaster __instance) { //IL_00e5: 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_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0130: 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_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0192: 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_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: 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_0208: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: 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) if (Instance.isFleeing) { fleeTimer += Time.deltaTime; if (fleeTimer >= configFleeDuration.Value) { __instance.TeleportFarAway(); fleeTimer = 0f; isFleeing = false; if (passOutRetreatTriggersRespawn) { passOutRetreatTriggersRespawn = false; fleeAwayFrom = null; ScoutmasterPassOutSupport.OnRetreatComplete(__instance); scoutmasterHasSpawned = false; isSpawning = true; respawnEndTime = ScoutmasterPassOutSupport.RecoveryRespawnDelay; LogInfo($"Pass-out retreat complete — scoutmaster will respawn in {ScoutmasterPassOutSupport.RecoveryRespawnDelay:F0}s."); } else { ScoutmasterPassOutSupport.FullyHealScoutmaster(__instance.character); scoutmasterHasSpawned = false; LogInfo("Flee complete — scoutmaster statuses cleared off-map."); } return true; } Vector3 val = default(Vector3); bool flag = false; Vector3 val2; if (fleeAwayFrom.HasValue) { val2 = __instance.character.Center - fleeAwayFrom.Value; Vector3 normalized = ((Vector3)(ref val2)).normalized; val = __instance.character.Center + normalized * 10f; flag = true; } else if ((Object)(object)__instance.currentTarget != (Object)null) { val2 = __instance.character.Center - __instance.currentTarget.Center; Vector3 normalized2 = ((Vector3)(ref val2)).normalized; val = __instance.character.Center + normalized2 * 10f; flag = true; } if (!flag) { Vector3 val3 = __instance.character.data.lookDirection_Flat; if (((Vector3)(ref val3)).sqrMagnitude < 0.01f) { val3 = -((Component)__instance).transform.forward; val3.y = 0f; } val = __instance.character.Center + ((Vector3)(ref val3)).normalized * 10f; } if (__instance.character.data.isClimbing) { Instance.HandleClimbing(__instance, val); return true; } HandleWalkTowards(__instance, val, 1f); __instance.character.input.sprintIsPressed = true; return true; } return false; } private void HandleTargeting(Scoutmaster scoutmaster) { //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) targetingTimer += Time.deltaTime; if (targetingTimer < 3f) { return; } List<Character> allCharacters = Character.AllCharacters; Character val = null; float num = float.MaxValue; foreach (Character item in allCharacters) { if (!item.isBot && !item.data.dead && !item.data.fullyPassedOut && !item.data.passedOut) { float num2 = Vector3.Distance(item.Center, scoutmaster.character.Center); if (num2 < num) { val = item; num = num2; } } } if ((Object)(object)val != (Object)null && (Object)(object)scoutmaster.currentTarget != (Object)(object)val && !scoutmaster.isThrowing) { scoutmaster.view.RPC("RPCA_SetCurrentTarget", (RpcTarget)0, new object[2] { val.view.ViewID, 0f }); } targetingTimer = 0f; } public bool CanClimb(Character character) { if (character.data.sinceClimb < 0.2f) { return false; } if (character.data.isRopeClimbing) { return false; } if (character.data.isVineClimbing) { return false; } return true; } private void TryToStartWallClimb(Character character) { //IL_0018: 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_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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_0036: 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) //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_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004a: 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_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: 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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: 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_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) if (!CanClimb(character)) { return; } Vector3 center = character.Center; Vector3 normalized = ((Vector3)(ref character.data.lookDirection_Flat)).normalized; Vector3 val = center + normalized * 1.25f; RaycastHit val2 = HelperFunctions.LineCheck(center, val, (LayerType)1, 0f, (QueryTriggerInteraction)1); if (!Object.op_Implicit((Object)(object)((RaycastHit)(ref val2)).transform)) { val2 = HelperFunctions.LineCheck(center, val, (LayerType)1, 0.05f, (QueryTriggerInteraction)1); } if (!Object.op_Implicit((Object)(object)((RaycastHit)(ref val2)).transform)) { val2 = HelperFunctions.LineCheck(center, val, (LayerType)1, 0.1f, (QueryTriggerInteraction)1); } if (Object.op_Implicit((Object)(object)((RaycastHit)(ref val2)).transform)) { bool flag = !character.refs.climbing.AcceptableGrabAngle(((RaycastHit)(ref val2)).normal, ((RaycastHit)(ref val2)).collider); bool flag2 = !(character.refs.climbing.sinceLastClimbStarted > 1f) && character.OutOfStamina(); if (!(flag || flag2)) { character.data.sinceCanClimb = 0f; character.refs.climbing.sinceLastClimbStarted = 0f; character.view.RPC("StartClimbRpc", (RpcTarget)0, new object[2] { ((RaycastHit)(ref val2)).point, ((RaycastHit)(ref val2)).normal }); } } } public bool IsTargetHoldingLitFaerieLanternCondition(Scoutmaster scoutmaster) { if ((Object)(object)scoutmaster.currentTarget == (Object)null) { return false; } return IsTargetHoldingLitFaerieLantern(scoutmaster.currentTarget); } private void ApplyScoutmasterBonk(Character character, Scoutmaster scoutmaster, Vector3 forceDirection, float forceMagnitude, float forceRange, Vector3 hitPoint) { //IL_0055: 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_0061: 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) character.Fall(configBonkStunDuration.Value, 0f); if (scoutmaster.isThrowing) { ((MonoBehaviour)scoutmaster).StopCoroutine("IThrow"); scoutmaster.isThrowing = false; } ReleaseGrabIfNeeded(scoutmaster); if (((Vector3)(ref forceDirection)).sqrMagnitude > 0.0001f) { character.AddForceAtPosition(-((Vector3)(ref forceDirection)).normalized * forceMagnitude, hitPoint, forceRange); } } public IEnumerator WaitAndCallback(float waitSeconds, Action callback) { yield return (object)new WaitForSeconds(waitSeconds); callback?.Invoke(); } private void DespawnScoutmaster() { if (!TryGetScoutmaster(out var resolved)) { scoutmasterHasSpawned = false; isFleeing = false; LogWarning("Despawn requested but scoutmaster not found — respawn timer will still run."); return; } ReleaseGrabIfNeeded(resolved); resolved.currentTarget = null; resolved.view.RPC("RPCA_SetCurrentTarget", (RpcTarget)0, new object[2] { -1, 0f }); fleeAwayFrom = GetNearestPlayerPosition(resolved.character); resetInputRequest = true; if (IsScoutmasterOnMap(resolved)) { isFleeing = true; fleeTimer = 0f; scoutmasterHasSpawned = true; LogInfo("Scoutmaster on map — fleeing before off-map despawn."); } else { isFleeing = false; scoutmasterHasSpawned = false; LogInfo("Scoutmaster already off-map — skipping flee, waiting on respawn timer."); } } internal void LogInfo(string msg) { ConfigEntry<bool> obj = configEnableLogs; if (obj != null && obj.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("[Scoutmasters Rampage] " + msg)); } } internal void LogWarning(string msg) { ConfigEntry<bool> obj = configEnableLogs; if (obj != null && obj.Value) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[Scoutmasters Rampage] " + msg)); } } } internal static class ScoutmasterBlowDartSupport { [HarmonyPatch(typeof(Action_RaycastDart), "FireDart")] private static class BlowDartFireDartPatch { private static bool Prefix(Action_RaycastDart __instance) { //IL_0045: 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_0065: 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_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: 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_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: 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_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: 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_0183: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) if (!Enabled) { return true; } if (Object.op_Implicit((Object)(object)__instance.shotSFX)) { __instance.shotSFX.Play(((Component)__instance).transform.position); } Physics.Raycast(__instance.spawnTransform.position, ((Component)MainCamera.instance).transform.forward, ref __instance.lineHit, __instance.maxDistance, LayerMask.op_Implicit(HelperFunctions.terrainMapMask), (QueryTriggerInteraction)1); if (!Object.op_Implicit((Object)(object)((RaycastHit)(ref __instance.lineHit)).collider)) { ((RaycastHit)(ref __instance.lineHit)).distance = __instance.maxDistance; ((RaycastHit)(ref __instance.lineHit)).point = __instance.spawnTransform.position + ((Component)MainCamera.instance).transform.forward * __instance.maxDistance; } int num = LayerMask.op_Implicit(HelperFunctions.GetMask((LayerType)6)); __instance.sphereHits = Physics.SphereCastAll(__instance.spawnTransform.position, __instance.dartCollisionSize, ((Component)MainCamera.instance).transform.forward, ((RaycastHit)(ref __instance.lineHit)).distance, num, (QueryTriggerInteraction)1); RaycastHit[] sphereHits = __instance.sphereHits; for (int i = 0; i < sphereHits.Length; i++) { RaycastHit val = sphereHits[i]; if (Object.op_Implicit((Object)(object)((RaycastHit)(ref val)).collider)) { Character componentInParent = ((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<Character>(); if (Object.op_Implicit((Object)(object)componentInParent) && (Object)(object)componentInParent != (Object)(object)((ItemActionBase)__instance).character) { __instance.DartImpact(componentInParent, __instance.spawnTransform.position, ((RaycastHit)(ref val)).point); return false; } } } __instance.DartImpact((Character)null, __instance.spawnTransform.position, ((RaycastHit)(ref __instance.lineHit)).point); return false; } } [HarmonyPatch(typeof(Item), "FinishCastPrimary")] private static class FinishCastPrimaryPostfix { private static void Postfix(Item __instance) { if (Enabled && !((Object)(object)__instance == (Object)null) && !((Object)(object)((Component)__instance).GetComponentInChildren<Action_RaycastDart>() == (Object)null)) { CompleteDartItemUse(__instance); } } private static void CompleteDartItemUse(Item item) { Character holderCharacter = item.holderCharacter; if ((Object)(object)holderCharacter == (Object)null || !holderCharacter.IsLocal) { return; } OptionableIntItemData data = item.GetData<OptionableIntItemData>((DataEntryKey)2); if (data.HasData && data.Value > 0) { Action_ReduceUses componentInChildren = ((Component)item).GetComponentInChildren<Action_ReduceUses>(true); if ((Object)(object)componentInChildren != (Object)null) { ((ItemActionBase)componentInChildren).RunAction(); data = item.GetData<OptionableIntItemData>((DataEntryKey)2); } } if (!item.consuming && (!data.HasData || data.Value <= 0)) { Action_Consume componentInChildren2 = ((Component)item).GetComponentInChildren<Action_Consume>(true); if ((Object)(object)componentInChildren2 != (Object)null) { ((ItemActionBase)componentInChildren2).RunAction(); } else { ((MonoBehaviour)item).StartCoroutine(item.ConsumeDelayed(false)); } } } } private static ConfigEntry<bool> configEnabled; internal static bool Enabled => configEnabled?.Value ?? true; internal static void Initialize(ConfigFile config) { configEnabled = config.Bind<bool>("Interactions", "BlowDartHitsScoutmaster", true, "When true, blow darts sphere-cast Character+Default layers (same colliders bonks use) so they can hit the scoutmaster."); } } internal static class ScoutmasterRescueHookSupport { [HarmonyPatch(typeof(RescueHook), "GetHit")] private static class GetHitPatch { private static bool Prefix(RescueHook __instance, out Vector3 endFire, ref RaycastHit __result) { //IL_0002: 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_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002d: 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_0058: 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_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) endFire = default(Vector3); if (!Enabled) { return true; } Ray middleScreenRay = GetMiddleScreenRay(); __instance.curRange = __instance.range; if (Vector3.Dot(((Ray)(ref middleScreenRay)).direction, Vector3.up) < 0f) { __instance.curRange = __instance.rangeDownward; } endFire = ((Ray)(ref middleScreenRay)).origin + ((Ray)(ref middleScreenRay)).direction * __instance.curRange; __result = FindBestHit(__instance, middleScreenRay, __instance.curRange); return false; } } [HarmonyPatch(typeof(RescueHook), "Fire")] private static class FirePatch { private static bool Prefix(RescueHook __instance) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_011c: 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) if (!Enabled) { return true; } __instance.sinceFire = 0f; for (int i = 0; i < __instance.rescueShot.Length; i++) { __instance.rescueShot[i].Play(((Component)__instance).transform.position); } Vector3 val = default(Vector3); RaycastHit hit = __instance.GetHit(ref val); if (Object.op_Implicit((Object)(object)((RaycastHit)(ref hit)).transform) && TryResolveCharacterFromCollider(((RaycastHit)(ref hit)).collider, ((ItemComponent)__instance).item.holderCharacter, out var character)) { ((MonoBehaviourPun)__instance).photonView.RPC("RPCA_RescueCharacter", (RpcTarget)0, new object[1] { ((MonoBehaviourPun)character).photonView }); } else if (Object.op_Implicit((Object)(object)((RaycastHit)(ref hit)).transform)) { ((MonoBehaviourPun)__instance).photonView.RPC("RPCA_RescueWall", (RpcTarget)0, new object[2] { false, ((RaycastHit)(ref hit)).point }); } else { ((MonoBehaviourPun)__instance).photonView.RPC("RPCA_RescueWall", (RpcTarget)0, new object[2] { true, val }); } return false; } } [HarmonyPatch(typeof(RescueHook), "RPCA_RescueCharacter")] private static class RescueCharacterPatch { private static void Postfix(RescueHook __instance, PhotonView characterView) { if (!Enabled || (Object)(object)characterView == (Object)null) { return; } Character component = ((Component)characterView).GetComponent<Character>(); if ((Object)(object)component == (Object)null || !component.data.isScoutmaster) { return; } PulledScoutmaster = component; if (!PhotonNetwork.IsMasterClient) { return; } Scoutmaster component2 = ((Component)component).GetComponent<Scoutmaster>(); if (!((Object)(object)component2 == (Object)null)) { ScoutmasterRampagePlugin.Instance?.ReleaseGrabIfNeeded(component2); if (component2.isThrowing) { ((MonoBehaviour)component2).StopCoroutine("IThrow"); component2.isThrowing = false; } } } } [HarmonyPatch(typeof(RescueHook), "RPCA_LetGo")] private static class LetGoPatch { private static Character lettingGoTarget; private static void Prefix(RescueHook __instance) { lettingGoTarget = __instance.targetPlayer; } private static void Postfix() { if ((Object)(object)lettingGoTarget != (Object)null && lettingGoTarget.data.isScoutmaster) { PulledScoutmaster = null; } lettingGoTarget = null; } } private static ConfigEntry<bool> configEnabled; internal static Character PulledScoutmaster { get; private set; } internal static bool Enabled => configEnabled?.Value ?? true; internal static bool IsPullingScoutmaster(Character character) { return (Object)(object)PulledScoutmaster != (Object)null && (Object)(object)PulledScoutmaster == (Object)(object)character; } internal static void Initialize(ConfigFile config) { configEnabled = config.Bind<bool>("Interactions", "RescueHookWorksOnScoutmaster", true, "When true, rescue hooks can target and pull the scoutmaster using the same Default-layer bodypart colliders bonks use. Releases grabs while pulling. Host chase AI pauses during the pull."); } private static Ray GetMiddleScreenRay() { //IL_0015: 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) //IL_001f: 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) return Camera.main.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0f)); } private static bool TryResolveCharacterFromCollider(Collider collider, Character holder, out Character character) { character = null; if ((Object)(object)collider == (Object)null) { return false; } if (CharacterRagdoll.TryGetCharacterFromCollider(collider, ref character) && (Object)(object)character != (Object)null && (Object)(object)character != (Object)(object)holder) { return true; } character = ((Component)collider).GetComponentInParent<Character>(); return (Object)(object)character != (Object)null && (Object)(object)character != (Object)(object)holder; } private static bool ShouldSkipHit(RescueHook hook, RaycastHit hit) { if ((Object)(object)((RaycastHit)(ref hit)).rigidbody == (Object)null) { return false; } Item component = ((Component)((RaycastHit)(ref hit)).rigidbody).GetComponent<Item>(); if ((Object)(object)component != (Object)null && (Object)(object)component.holderCharacter == (Object)(object)((ItemComponent)hook).item.holderCharacter) { return true; } if (TryResolveCharacterFromCollider(((RaycastHit)(ref hit)).collider, ((ItemComponent)hook).item.holderCharacter, out var character)) { return (Object)(object)character == (Object)(object)((ItemComponent)hook).item.holderCharacter; } return false; } private static RaycastHit FindBestHit(RescueHook hook, Ray ray, float maxRange) { //IL_0002: 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_001e: 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_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0161: 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_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: 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_00f2: Unknown result type (might be due to invalid IL or missing references) int num = LayerMask.op_Implicit(HelperFunctions.GetMask((LayerType)0)); List<RaycastHit> list = Physics.RaycastAll(ray, maxRange, num, (QueryTriggerInteraction)1).ToList(); RaycastHit result = default(RaycastHit); Character val = null; foreach (RaycastHit item in list) { RaycastHit current = item; if (ShouldSkipHit(hook, current)) { continue; } TryResolveCharacterFromCollider(((RaycastHit)(ref current)).collider, ((ItemComponent)hook).item.holderCharacter, out var character); if ((Object)(object)character != (Object)null && character.data.isScoutmaster) { if ((Object)(object)val == (Object)null || ((RaycastHit)(ref current)).distance < ((RaycastHit)(ref result)).distance) { result = current; val = character; } } else if (!((Object)(object)val != (Object)null) && (((RaycastHit)(ref result)).distance == 0f || ((RaycastHit)(ref current)).distance < ((RaycastHit)(ref result)).distance)) { result = current; } } if ((Object)(object)val != (Object)null) { return result; } if ((Object)(object)((RaycastHit)(ref result)).collider != (Object)null && Vector3.Distance(((Ray)(ref ray)).origin, ((RaycastHit)(ref result)).point) < hook.minRaycastDistance) { return default(RaycastHit); } return result; } } internal static class ScoutmasterOverheadStatus { [HarmonyPatch(typeof(GUIManager), "LateUpdate")] private static class GUIManagerLateUpdatePatch { private static void Postfix(GUIManager __instance) { if (!Enabled || (Object)(object)__instance == (Object)null) { display?.Hide(); return; } if (!TryGetScoutmasterCharacter(out var character)) { display?.Hide(); return; } if (!IsVisibleToLocalPlayer(character)) { display?.Hide(); return; } if (display == null) { display = new ScoutmasterOverheadBarDisplay(); } display.Refresh(__instance, character); } } private sealed class ScoutmasterOverheadBarDisplay { private sealed class StatusSegment { internal GameObject GameObject; internal RectTransform RootRect; internal RectTransform FillRect; internal Image Icon; internal STATUSTYPE StatusType; internal float TargetWidth; internal float LastAppliedWidth = -1f; internal bool IsActive; } private readonly List<StatusSegment> segments = new List<StatusSegment>(); private readonly List<float> sampledStatuses = new List<float>(16); private readonly List<float> lastStatuses = new List<float>(16); private GameObject rootObject; private RectTransform rootRect; private RectTransform barContainer; private RectTransform staminaEmpty; private RectTransform staminaFill; private RectTransform extraStaminaFill; private StaminaBar sourceBar; private float lastScale = -1f; private float lastMaxStamina = -1f; private float lastCurrentStamina = -1f; private float lastExtraStamina = -1f; private bool layoutInitialized; private bool isShown; internal void DestroyDisplay() { ClearSegments(); if ((Object)(object)rootObject != (Object)null) { Object.Destroy((Object)(object)rootObject); rootObject = null; rootRect = null; } layoutInitialized = false; isShown = false; } internal void Hide() { if ((Object)(object)rootObject != (Object)null && isShown) { rootObject.SetActive(false); isShown = false; } } internal void Refresh(GUIManager gui, Character targetCharacter) { if ((Object)(object)gui.hudCanvas == (Object)null || (Object)(object)gui.bar == (Object)null) { Hide(); return; } EnsureRoot(((Component)gui.hudCanvas).transform); CharacterAfflictions val = targetCharacter.refs?.afflictions; if ((Object)(object)val == (Object)null || !EnsureSegments(gui.bar)) { Hide(); return; } PositionOverHead(targetCharacter); if (NeedsLayoutUpdate(targetCharacter, val)) { UpdateLayout(targetCharacter, val); } if (!isShown) { rootObject.SetActive(true); isShown = true; } } private void EnsureRoot(Transform canvasTransform) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown //IL_005f: 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_008b: 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) if (!((Object)(object)rootObject != (Object)null)) { rootObject = new GameObject("ScoutmasterOverheadStatus", new Type[1] { typeof(RectTransform) }); rootRect = rootObject.GetComponent<RectTransform>(); ((Transform)rootRect).SetParent(canvasTransform, false); rootRect.anchorMin = Vector2.zero; rootRect.anchorMax = Vector2.zero; rootRect.pivot = new Vector2(0.5f, 0.5f); rootRect.sizeDelta = Vector2.zero; rootObject.SetActive(false); isShown = false; } } private void PositionOverHead(Character targetCharacter) { //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_003e: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) Camera camera = GetCamera(); if (!((Object)(object)camera == (Object)null) && !((Object)(object)rootRect == (Object)null)) { Vector3 head = targetCharacter.Head; head.y += 0.25f; Vector3 position = camera.WorldToScreenPoint(head); position.y += 28f * BarScale; ((Transform)rootRect).position = position; } } private bool EnsureSegments(StaminaBar bar) { //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Expected O, but got Unknown //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_017e: 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_0252: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_0290: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Unknown result type (might be due to invalid IL or missing references) //IL_02b7: Unknown result type (might be due to invalid IL or missing references) //IL_031f: Unknown result type (might be due to invalid IL or missing references) //IL_0316: Unknown result type (might be due to invalid IL or missing references) //IL_0324: Unknown result type (might be due to invalid IL or missing references) if (bar.afflictions == null || bar.afflictions.Length == 0) { return false; } if ((Object)(object)barContainer != (Object)null && (Object)(object)sourceBar == (Object)(object)bar && segments.Count > 0 && (Object)(object)staminaFill != (Object)null) { return true; } ClearSegments(); sourceBar = bar; GameObject val = new GameObject("ScoutmasterOverheadStaminaBar", new Type[1] { typeof(RectTransform) }); val.transform.SetParent((Transform)(object)rootRect, false); barContainer = val.GetComponent<RectTransform>(); barContainer.anchorMin = new Vector2(0.5f, 0.5f); barContainer.anchorMax = new Vector2(0.5f, 0.5f); barContainer.pivot = new Vector2(0.5f, 0.5f); barContainer.anchoredPosition = Vector2.zero; staminaEmpty = CreateColorBar("ScoutmasterOverheadStaminaEmpty", StaminaEmptyColor, bar); staminaFill = CreateColorBar("ScoutmasterOverheadStaminaFill", StaminaFillColor, bar); extraStaminaFill = CreateColorBar("ScoutmasterOverheadExtraStaminaFill", StaminaFillColor, bar); BarAffliction[] afflictions = bar.afflictions; foreach (BarAffliction val2 in afflictions) { if (!((Object)(object)val2 == (Object)null) && ScoutmasterAfflictionSupport.IsVanillaStatusType(val2.afflictionType)) { GameObject val3 = Object.Instantiate<GameObject>(((Component)val2).gameObject, (Transform)(object)barContainer); ((Object)val3).name = "ScoutmasterOverhead" + ((object)Unsafe.As<STATUSTYPE, STATUSTYPE>(ref val2.afflictionType)/*cast due to .constrained prefix*/).ToString(); RemoveStaminaInfoText(val3); BarAffliction component = val3.GetComponent<BarAffliction>(); if ((Object)(object)component != (Object)null) { ((Behaviour)component).enabled = false; } RectTransform component2 = val3.GetComponent<RectTransform>(); ConfigureLeftCenterChild(component2); ((Transform)component2).localScale = Vector3.one; RectTransform val4 = (((Object)(object)component != (Object)null && (Object)(object)component.rtf != (Object)null) ? component.rtf : component2); if ((Object)(object)val4 != (Object)(object)component2) { val4.anchorMin = Vector2.zero; val4.anchorMax = Vector2.one; val4.pivot = new Vector2(0.5f, 0.5f); val4.anchoredPosition = Vector2.zero; val4.sizeDelta = Vector2.zero; val4.offsetMin = Vector2.zero; val4.offsetMax = Vector2.zero; ((Transform)val4).localScale = Vector3.one; } SetRaycastTargets(val3, value: false); segments.Add(new StatusSegment { GameObject = val3, RootRect = component2, FillRect = val4, Icon = (((Object)(object)component != (Object)null) ? component.icon : null), StatusType = (((Object)(object)component != (Object)null) ? component.afflictionType : val2.afflictionType) }); val3.SetActive(false); } } if ((Object)(object)staminaEmpty != (Object)null) { ((Transform)staminaEmpty).SetAsFirstSibling(); } if ((Object)(object)staminaFill != (Object)null) { ((Transform)staminaFill).SetSiblingIndex(1); } layoutInitialized = false; lastStatuses.Clear(); return segments.Count > 0; } private RectTransform CreateColorBar(string objectName, Color color, StaminaBar source) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_00b8: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(objectName, new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image) }); val.transform.SetParent((Transform)(object)barContainer, false); RectTransform component = val.GetComponent<RectTransform>(); ConfigureLeftCenterChild(component); Image component2 = val.GetComponent<Image>(); Image val2 = FindFillImage(((Object)(object)source != (Object)null) ? source.staminaBar : null); if ((Object)(object)val2 != (Object)null && (Object)(object)val2.sprite != (Object)null) { component2.sprite = val2.sprite; component2.type = (Type)1; component2.pixelsPerUnitMultiplier = val2.pixelsPerUnitMultiplier; } ((Graphic)component2).color = color; ((Graphic)component2).ra