using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Gamemode_Lib; using Gamemode_Lib.ConfigSync; using Gamemode_Lib.Events; using Gamemode_Lib.Patches.Features; using Gamemode_Lib.Teams; using HarmonyLib; using Microsoft.CodeAnalysis; using Mirror; using SharksAndMinnows.Configuration; using SharksAndMinnows.Patches; using TMPro; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: IgnoresAccessChecksTo("GameAssembly")] [assembly: IgnoresAccessChecksTo("SharedAssembly")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("com.github.glarmer.SharksAndMinnows")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("0.5.1.0")] [assembly: AssemblyInformationalVersion("0.5.1+65949ddd2fd8a6850fd772a5548740279b70bc85")] [assembly: AssemblyProduct("com.github.glarmer.SharksAndMinnows")] [assembly: AssemblyTitle("SharksAndMinnows")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.5.1.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace BepInEx { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] [Microsoft.CodeAnalysis.Embedded] internal sealed class BepInAutoPluginAttribute : Attribute { public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace BepInEx.Preloader.Core.Patching { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] [Microsoft.CodeAnalysis.Embedded] internal sealed class PatcherAutoPluginAttribute : Attribute { public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace Microsoft.CodeAnalysis { [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace SharksAndMinnows { public class MinnowManager : MonoBehaviour { [CompilerGenerated] private sealed class d__21 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public PlayerInfo victim; public PlayerTeam victimTeam; public TeamManager teamManager; public MinnowManager <>4__this; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__21(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 1; return true; case 1: <>1__state = -1; if ((Object)(object)victim == (Object)null || (Object)(object)victimTeam == (Object)null || (Object)(object)teamManager == (Object)null) { return false; } victimTeam.SetLocalTeam(SharksAndMinnows.SHARKS_TEAM); teamManager.SendTeamToClients(victim, SharksAndMinnows.SHARKS_TEAM); <>4__this.AddMinnowTagged(victim.PlayerId.guid); victim.Movement.TryBeginRespawn(false, (RespawnTarget)0); Plugin.Log.LogInfo((object)$"[MinnowManager] Conversion complete. victimGuid={victim.PlayerId.guid} tagged={<>4__this._minnowsThatHaveBeenTagged.Count}/{<>4__this._originalMinnowRoster.Count} scored={<>4__this._minnowsThatScored.Count}/{<>4__this._originalMinnowRoster.Count}"); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private readonly HashSet _originalMinnowRoster = new HashSet(); private readonly HashSet _minnowsThatScored = new HashSet(); private readonly HashSet _minnowsThatHaveBeenTagged = new HashSet(); public static MinnowManager Instance; public void Awake() { Plugin.Log.LogInfo((object)"[MinnowManager] Awake() called"); if ((Object)(object)Instance == (Object)null) { Instance = this; Object.DontDestroyOnLoad((Object)(object)Instance); Plugin.Log.LogInfo((object)"[MinnowManager] Instance set + DontDestroyOnLoad"); SceneEvents.OnNextHole += OnNextHole; SceneEvents.OnReturnToLobby += OnReturnToLobby; PlayerTag.PlayerTagged += OnPlayerTagged; Plugin.Log.LogInfo((object)"[MinnowManager] Subscribed: PlayerTag.PlayerTagged"); if ((Object)(object)TeamManager.Instance != (Object)null) { TeamManager.Instance.AllPlayersOnOneTeam += OnAllPlayersOnOneTeam; Plugin.Log.LogInfo((object)"[MinnowManager] Subscribed: TeamManager.AllPlayersOnOneTeam"); } else { Plugin.Log.LogInfo((object)"[MinnowManager] TeamManager.Instance was null in Awake(); AllPlayersOnOneTeam not subscribed (yet?)"); } } else { Plugin.Log.LogInfo((object)"[MinnowManager] Duplicate instance detected; destroying the old component"); Object.Destroy((Object)(object)Instance); Instance = this; } } public bool HasMinnowBeenCaptured(ulong minnow) { return _minnowsThatHaveBeenTagged.Contains(minnow); } public bool HasMinnowScored(ulong minnow) { return _minnowsThatScored.Contains(minnow); } public void Start() { Plugin.Log.LogInfo((object)"[MinnowManager] Start() called; initializing minnow roster"); SetInitialMinnowRoster(); Plugin.Log.LogInfo((object)$"[MinnowManager] Initial roster loaded. originalMinnowRoster={_originalMinnowRoster.Count}"); } public void OnDestroy() { Plugin.Log.LogInfo((object)"[MinnowManager] OnDestroy() called; unsubscribing events"); PlayerTag.PlayerTagged -= OnPlayerTagged; SceneEvents.OnNextHole -= OnNextHole; SceneEvents.OnReturnToLobby -= OnReturnToLobby; if ((Object)(object)TeamManager.Instance != (Object)null) { TeamManager.Instance.AllPlayersOnOneTeam -= OnAllPlayersOnOneTeam; Plugin.Log.LogInfo((object)"[MinnowManager] Unsubscribed: TeamManager.AllPlayersOnOneTeam"); } else { Plugin.Log.LogInfo((object)"[MinnowManager] TeamManager.Instance was null in OnDestroy(); skipping AllPlayersOnOneTeam unsubscribe"); } Plugin.Log.LogInfo((object)"[MinnowManager] Unsubscribed: PlayerTag.PlayerTagged"); } private void OnAllPlayersOnOneTeam(TeamData teamData) { Plugin.Log.LogInfo((object)$"[MinnowManager] OnAllPlayersOnOneTeam(teamId={teamData?.ID}) called"); if (teamData != null && teamData.ID == SharksAndMinnows.SHARKS_TEAM) { Plugin.Log.LogInfo((object)$"[MinnowManager] AllPlayersOnOneTeam -> Sharks. originalMinnowRoster={_originalMinnowRoster.Count} tagged={_minnowsThatHaveBeenTagged.Count} scored={_minnowsThatScored.Count}. Ending game"); SharksAndMinnows.EndCurrentHole(isEndGame: true); } } private void OnNextHole(Scene scenePrev, Scene sceneNew) { Plugin.Log.LogInfo((object)"On Next Hole Reset Zone Timer"); PlayerMovementPatches.ResetZoneTimer(); ClearMinnowsThatHaveScored(); } public void Update() { if (_originalMinnowRoster.Count == 0) { SetInitialMinnowRoster(); } if (_minnowsThatScored.Count != 0 && _minnowsThatScored.Count + _minnowsThatHaveBeenTagged.Count >= _originalMinnowRoster.Count) { Plugin.Log.LogInfo((object)$"[MinnowManager] All Minnows accounted for (scored/tagged). originalMinnowRoster={_originalMinnowRoster.Count} tagged={_minnowsThatHaveBeenTagged.Count} scored={_minnowsThatScored.Count}. Ending hole"); SharksAndMinnows.EndCurrentHole(isEndGame: false); ClearMinnowsThatHaveScored(); } } public void SetInitialMinnowRoster() { if ((Object)(object)TeamManager.Instance == (Object)null) { Plugin.Log.LogInfo((object)"[MinnowManager] TeamManager.Instance is null; cannot build initial roster"); return; } int num = 0; int num2 = 0; foreach (KeyValuePair item in TeamManager.Instance.SavedTeamIdByGuid) { num++; if (item.Value == SharksAndMinnows.MINNOWS_TEAM) { _originalMinnowRoster.Add(item.Key); num2++; Plugin.Log.LogInfo((object)$"[MinnowManager] Added initial minnow guid={item.Key}"); } } } private void OnReturnToLobby(Scene scene, Scene scene1) { Plugin.Log.LogInfo((object)"[MinnowManager] OnReturnToLobby() called"); ClearAllMinnows(); } private void ClearAllMinnows() { _minnowsThatHaveBeenTagged.Clear(); _minnowsThatScored.Clear(); _originalMinnowRoster.Clear(); } public void ClearMinnowsThatHaveScored() { Plugin.Log.LogInfo((object)$"[MinnowManager] ClearMinnowsThatHaveScored() clearing {_minnowsThatScored.Count} scored minnows (tagged={_minnowsThatHaveBeenTagged.Count} roster={_originalMinnowRoster.Count})"); _minnowsThatScored.Clear(); } public void ClearMinnowsThatHaveBeenTagged() { Plugin.Log.LogInfo((object)$"[MinnowManager] ClearMinnowsThatHaveBeenTagged() clearing {_minnowsThatHaveBeenTagged.Count} tagged minnows (scored={_minnowsThatScored.Count} roster={_originalMinnowRoster.Count})"); _minnowsThatHaveBeenTagged.Clear(); } public void ClearOriginalMinnowRoster() { _originalMinnowRoster.Clear(); Plugin.Log.LogInfo((object)"[MinnowManager] ClearOriginalMinnowRoster() cleared roster"); } public void AddMinnowTagged(ulong minnow) { if (_minnowsThatScored.Contains(minnow)) { Plugin.Log.LogInfo((object)$"[MinnowManager] AddMinnowTagged(guid={minnow}) already scored; skipping"); return; } bool flag = _minnowsThatHaveBeenTagged.Add(minnow); Plugin.Log.LogInfo((object)$"[MinnowManager] AddMinnowTagged(guid={minnow}) added={flag} tagged={_minnowsThatHaveBeenTagged.Count} scored={_minnowsThatScored.Count} roster={_originalMinnowRoster.Count}"); } public void AddMinnowScored(ulong minnow) { if (_minnowsThatHaveBeenTagged.Contains(minnow)) { Plugin.Log.LogInfo((object)$"[MinnowManager] AddMinnowScored(guid={minnow}) already tagged; skipping"); return; } bool flag = _minnowsThatScored.Add(minnow); Plugin.Log.LogInfo((object)$"[MinnowManager] AddMinnowScored(guid={minnow}) added={flag} scored={_minnowsThatScored.Count} tagged={_minnowsThatHaveBeenTagged.Count} roster={_originalMinnowRoster.Count}"); } private void OnPlayerTagged(PlayerInfo victim, PlayerInfo hitter, TagHitType hitType) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) Plugin.Log.LogInfo((object)string.Format("[MinnowManager] OnPlayerTagged(victim={0}, hitter={1}, hitType={2}, serverActive={3})", ((Object)(object)victim == (Object)null) ? "null" : victim.PlayerId.guid.ToString(), ((Object)(object)hitter == (Object)null) ? "null" : hitter.PlayerId.guid.ToString(), hitType, NetworkServer.active)); if ((Object)(object)victim == (Object)null || (Object)(object)hitter == (Object)null) { return; } TeamManager instance = TeamManager.Instance; PlayerTeam val = instance.EnsurePlayerTeam(victim); PlayerTeam val2 = instance.EnsurePlayerTeam(hitter); if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { Plugin.Log.LogInfo((object)$"[MinnowManager] EnsurePlayerTeam failed. victimTeamNull={(Object)(object)val == (Object)null} hitterTeamNull={(Object)(object)val2 == (Object)null}"); } else { if (HasMinnowScored(victim.PlayerId.guid)) { return; } if (((NetworkBehaviour)victim).isLocalPlayer && val.teamId == SharksAndMinnows.MINNOWS_TEAM && val2.teamId == SharksAndMinnows.SHARKS_TEAM) { Plugin.Log.LogInfo((object)$"[MinnowManager] Victim is local player; applying slow (minnows speed multiplier / 2) victimGuid={victim.PlayerId.guid}"); SharksAndMinnows.SetMoveSpeedsShark(); } if (!NetworkServer.active) { return; } if ((Object)(object)instance == (Object)null) { Plugin.Log.LogInfo((object)"[MinnowManager] TeamManager.Instance is null; aborting tag handling"); return; } if (val2.teamId != SharksAndMinnows.SHARKS_TEAM) { Plugin.Log.LogInfo((object)$"[MinnowManager] Tag ignored; hitter not a shark. hitterTeam={val2.teamId} expectedSharks={SharksAndMinnows.SHARKS_TEAM}"); return; } if (val.teamId != SharksAndMinnows.MINNOWS_TEAM) { Plugin.Log.LogInfo((object)$"[MinnowManager] Tag ignored; victim not a minnow. victimTeam={val.teamId} expectedMinnows={SharksAndMinnows.MINNOWS_TEAM}"); return; } if ((Object)(object)SingletonNetworkBehaviour.Instance != (Object)null) { SingletonNetworkBehaviour.Instance.ServerShowMessageForAllClients(new EliminationMessaqeData(hitter.PlayerId.Guid, victim.PlayerId.Guid, (InfoFeedIconType)1)); } Plugin.Log.LogInfo((object)$"[MinnowManager] Valid tag: minnow->shark conversion. victimGuid={victim.PlayerId.guid} hitterGuid={hitter.PlayerId.guid}"); ((MonoBehaviour)this).StartCoroutine(ConvertMinnowToSharkAfterDelay(victim, val, instance)); } } [IteratorStateMachine(typeof(d__21))] private IEnumerator ConvertMinnowToSharkAfterDelay(PlayerInfo victim, PlayerTeam victimTeam, TeamManager teamManager) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__21(0) { <>4__this = this, victim = victim, victimTeam = victimTeam, teamManager = teamManager }; } } [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("com.github.glarmer.SharksAndMinnows", "SharksAndMinnows", "0.5.1")] public class Plugin : BaseUnityPlugin { public static ConfigurationHandler ConfigurationHandler; public const string Id = "com.github.glarmer.SharksAndMinnows"; internal static ManualLogSource Log { get; private set; } public static string Name => "SharksAndMinnows"; public static string Version => "0.5.1"; private void Awake() { Log = ((BaseUnityPlugin)this).Logger; ConfigurationHandler = new ConfigurationHandler(((BaseUnityPlugin)this).Config); GameModeUtilities.RegisterGameMode((IGamemode)(object)new SharksAndMinnows()); Log.LogInfo((object)("Plugin " + Name + " is loaded!")); } } public class ProximityTag : MonoBehaviour { private PlayerMovement owner; private Rigidbody ownerRigidbody; private readonly HashSet hitThisOverlap = new HashSet(); public void Initialize(PlayerMovement ownerMovement) { owner = ownerMovement; if ((Object)(object)owner != (Object)null) { ownerRigidbody = ((Component)owner).GetComponent(); } } private void OnTriggerEnter(Collider other) { TryTriggerDiveHit(other, "enter"); } private void OnTriggerStay(Collider other) { TryTriggerDiveHit(other, "stay"); } private void OnTriggerExit(Collider other) { Hittable hittable = GetHittable(other); if (!((Object)(object)hittable == (Object)null)) { hitThisOverlap.Remove(hittable); } } private void TryTriggerDiveHit(Collider other, string triggerEvent) { //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_0236: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)owner == (Object)null || !((NetworkBehaviour)owner).isLocalPlayer || (Object)(object)other == (Object)null) { return; } Entity entity = GetEntity(other); if ((Object)(object)entity == (Object)null || !entity.IsPlayer || !entity.IsHittable || (Object)(object)entity == (Object)(object)owner.PlayerInfo.AsEntity) { return; } Hittable asHittable = entity.AsHittable; if (!((Object)(object)asHittable == (Object)null) && asHittable.DiveSettings.CanBeHit) { PlayerTeam component = ((Component)owner).GetComponent(); PlayerTeam component2 = ((Component)entity).GetComponent(); ulong guid = component2.playerInfo.PlayerId.guid; if (!((Object)(object)MinnowManager.Instance == (Object)null) && !MinnowManager.Instance.HasMinnowBeenCaptured(guid) && !MinnowManager.Instance.HasMinnowScored(guid) && !((Object)(object)component == (Object)null) && !((Object)(object)component2 == (Object)null) && component.teamId != component2.teamId && !hitThisOverlap.Contains(asHittable)) { hitThisOverlap.Add(asHittable); Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(0f, 0f, 0f); Plugin.Log.LogInfo((object)("Player tag aura triggered dive hit | event=" + triggerEvent + " | owner=" + GetPlayerName(owner.PlayerInfo) + " | target=" + GetEntityName(entity) + " | " + $"velocity={val} | " + $"speed={((Vector3)(ref val)).magnitude:F2}")); asHittable.HitWithDive(val, owner); } } } private static Entity GetEntity(Collider other) { if ((Object)(object)other == (Object)null) { return null; } return ((Object)(object)other.attachedRigidbody != (Object)null) ? ((Component)other.attachedRigidbody).GetComponentInParent(true) : ((Component)other).GetComponentInParent(true); } private static Hittable GetHittable(Collider other) { Entity entity = GetEntity(other); if ((Object)(object)entity == (Object)null) { return null; } if (!entity.IsHittable) { return null; } return entity.AsHittable; } private static string GetEntityName(Entity entity) { if ((Object)(object)entity == (Object)null) { return "null"; } if (entity.IsPlayer && (Object)(object)entity.PlayerInfo != (Object)null) { return GetPlayerName(entity.PlayerInfo); } return ((Object)entity).name; } private static string GetPlayerName(PlayerInfo playerInfo) { if ((Object)(object)playerInfo == (Object)null) { return "null"; } return $"{playerInfo.PlayerId.PlayerName} ({playerInfo.PlayerId.guid})"; } } public class SharksAndMinnows : IGamemode { public static int SHARKS_TEAM = 0; public static int MINNOWS_TEAM = 1; private static bool _cached = false; private static float _defaultMoveSpeed; private static float _walkMoveSpeed; private static float _wadingSpeed; private static float _speedBoostFactor; private static float _diveHorizontalSpeed; private static float _diveUpwardsSpeed; private static float _diveGetUpDuration; private static float _jumpUpwardsSpeed; private static float _swingChargingSpeed; private static float _swingAimingSpeed; public Harmony GamemodeHarmony { get; init; } public string Name { get; } = "SharksAndMinnows"; public string ModId { get; } = "com.github.glarmer.SharksAndMinnows"; public int MinPlayers { get; } = 2; public int MaxPlayers { get; } = 200; public bool IsTeamBased { get; } = true; public bool IsNormalStartProcedure { get; } = true; public int TeamCount { get; } = 2; public string Description { get; } = "The Minnows must score their ball at all costs, but can they do it with the Sharks hunting them? Only time will tell!"; public bool IsTaggingEnabled { get; } = true; public SharksAndMinnows() { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown GamemodeHarmony = new Harmony(((IGamemode)this).GameModeId); } public void OnGameStart() { Plugin.Log.LogInfo((object)"[SharksAndMinnows] OnGameStart"); StopAutoNextHole.END_GAME = false; GamemodeHarmony.PatchAll(typeof(ItemSpawnerPatches)); GamemodeHarmony.PatchAll(typeof(HoleProgressBarUIPatches)); GamemodeHarmony.PatchAll(typeof(StopCountdownToMatchEnd)); GamemodeHarmony.PatchAll(typeof(StopAutoNextHole)); GamemodeHarmony.PatchAll(typeof(PlayerMovementPatches)); GamemodeHarmony.PatchAll(typeof(AheadOfBallMessagePatches)); GamemodeHarmony.PatchAll(typeof(PlayerGolferPatches)); GamemodeHarmony.PatchAll(typeof(InfoFeedPatches)); GamemodeHarmony.PatchAll(typeof(TeeOffCountdownPatches)); GamemodeHarmony.PatchAll(typeof(DiveHitboxPatches)); GamemodeHarmony.PatchAll(typeof(ProximityTagPatches)); ConfigurationHandler.Instance.MovementConfigChanged += ApplyLocalPlayerMovementSpeeds; ConfigurationHandler.Instance.SyncConfiguration(); GameObject val = GameObject.Find("Hole progress bar"); if ((Object)(object)val != (Object)null) { val.SetActive(false); } TeamManager instance = TeamManager.Instance; ApplyLocalPlayerMovementSpeeds(); ((Component)SingletonBehaviour.Instance).gameObject.AddComponent(); } public void OnGameEnd() { Plugin.Log.LogInfo((object)"[SharksAndMinnows] OnGameEnd"); if (ConfigurationHandler.Instance != null) { ConfigurationHandler.Instance.MovementConfigChanged -= ApplyLocalPlayerMovementSpeeds; } RestoreMovementSpeeds(); ProximityTagPatches.DestroyProximityColliders(); if ((Object)(object)MinnowManager.Instance != (Object)null) { Object.Destroy((Object)(object)MinnowManager.Instance); } GamemodeHarmony.UnpatchSelf(); } private void ApplyLocalPlayerMovementSpeeds() { TeamManager instance = TeamManager.Instance; if ((Object)(object)instance.LocalPlayerTeam != (Object)null && instance.LocalPlayerTeam.teamId == SHARKS_TEAM) { SetMoveSpeedsShark(); } else { SetMoveSpeedsMinnow(); } } public bool CanStart(int playerCount) { return true; } public static void EndCurrentHole(bool isEndGame) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Invalid comparison between Unknown and I4 //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) if (NetworkServer.active && !((Object)(object)SingletonNetworkBehaviour.Instance == (Object)null)) { Plugin.Log.LogInfo((object)"[SharksAndMinnows] Ending this hole"); StopAutoNextHole.END_GAME = isEndGame; if ((int)SingletonNetworkBehaviour.Instance.matchState != 6) { MatchState matchState = SingletonNetworkBehaviour.Instance.matchState; SingletonNetworkBehaviour.Instance.matchState = (MatchState)6; SingletonNetworkBehaviour.Instance.OnMatchStateChanged(matchState, (MatchState)6); Plugin.Log.LogInfo((object)"[SharksAndMinnows] Ending this hole"); } } } private static void CacheOriginalSpeeds() { if (!_cached) { PlayerMovementSettings playerMovementSettings = SingletonBehaviour.Instance.playerMovementSettings; _defaultMoveSpeed = playerMovementSettings.DefaultMoveSpeed; _walkMoveSpeed = playerMovementSettings.WalkMoveSpeed; _wadingSpeed = playerMovementSettings.WadingInWaterSpeed; _speedBoostFactor = playerMovementSettings.SpeedBoostSpeedFactor; _diveHorizontalSpeed = playerMovementSettings.DiveHorizontalSpeed; _diveUpwardsSpeed = playerMovementSettings.DiveUpwardsSpeed; _diveGetUpDuration = playerMovementSettings.DiveGetUpDuration; _jumpUpwardsSpeed = playerMovementSettings.JumpUpwardsSpeed; _swingChargingSpeed = playerMovementSettings.SwingChargingSpeed; _swingAimingSpeed = playerMovementSettings.SwingAimingSpeed; _cached = true; } } private void RestoreMovementSpeeds() { PlayerMovementSettings playerMovementSettings = SingletonBehaviour.Instance.playerMovementSettings; playerMovementSettings.DefaultMoveSpeed = _defaultMoveSpeed; playerMovementSettings.WalkMoveSpeed = _walkMoveSpeed; playerMovementSettings.WadingInWaterSpeed = _wadingSpeed; playerMovementSettings.SpeedBoostSpeedFactor = _speedBoostFactor; playerMovementSettings.DiveHorizontalSpeed = _diveHorizontalSpeed; playerMovementSettings.DiveUpwardsSpeed = _diveUpwardsSpeed; playerMovementSettings.DiveGetUpDuration = _diveGetUpDuration; playerMovementSettings.JumpUpwardsSpeed = _jumpUpwardsSpeed; playerMovementSettings.SwingChargingSpeed = _swingChargingSpeed; playerMovementSettings.SwingAimingSpeed = _swingAimingSpeed; } private void SetMoveSpeedsMinnow() { CacheOriginalSpeeds(); PlayerMovementSettings playerMovementSettings = SingletonBehaviour.Instance.playerMovementSettings; ConfigurationHandler instance = ConfigurationHandler.Instance; playerMovementSettings.DefaultMoveSpeed = _defaultMoveSpeed * instance.MinnowDefaultMoveSpeedMultiplier; playerMovementSettings.WalkMoveSpeed = _walkMoveSpeed * instance.MinnowWalkMoveSpeedMultiplier; playerMovementSettings.WadingInWaterSpeed = _wadingSpeed * instance.MinnowWadingInWaterSpeedMultiplier; playerMovementSettings.SpeedBoostSpeedFactor = _speedBoostFactor * instance.MinnowSpeedBoostSpeedFactorMultiplier; playerMovementSettings.DiveHorizontalSpeed = _diveHorizontalSpeed * instance.MinnowDiveHorizontalSpeedMultiplier; playerMovementSettings.DiveGetUpDuration = _diveGetUpDuration * instance.MinnowDiveGetUpDurationMultiplier; playerMovementSettings.JumpUpwardsSpeed = _jumpUpwardsSpeed * instance.MinnowJumpUpwardsSpeedMultiplier; } public static void SetMoveSpeedsShark() { CacheOriginalSpeeds(); PlayerMovementSettings playerMovementSettings = SingletonBehaviour.Instance.playerMovementSettings; ConfigurationHandler instance = ConfigurationHandler.Instance; playerMovementSettings.DefaultMoveSpeed = _defaultMoveSpeed * instance.SharkDefaultMoveSpeedMultiplier; playerMovementSettings.WalkMoveSpeed = _walkMoveSpeed * instance.SharkWalkMoveSpeedMultiplier; playerMovementSettings.WadingInWaterSpeed = _wadingSpeed * instance.SharkWadingInWaterSpeedMultiplier; playerMovementSettings.SpeedBoostSpeedFactor = _speedBoostFactor * instance.SharkSpeedBoostSpeedFactorMultiplier; playerMovementSettings.DiveUpwardsSpeed = _diveUpwardsSpeed * instance.SharkDiveUpwardsSpeedMultiplier; playerMovementSettings.DiveHorizontalSpeed = _diveHorizontalSpeed * instance.SharkDiveHorizontalSpeedMultiplier; playerMovementSettings.SwingChargingSpeed = _swingChargingSpeed * instance.SharkSwingChargingSpeedMultiplier; playerMovementSettings.SwingAimingSpeed = _swingAimingSpeed * instance.SharkSwingAimingSpeedMultiplier; } void IGamemode.set_GamemodeHarmony(Harmony value) { GamemodeHarmony = value; } } } namespace SharksAndMinnows.Patches { public class AheadOfBallMessagePatches { [HarmonyPatch(typeof(AheadOfBallMessage), "Update")] [HarmonyPrefix] public static void Update_Prefix(AheadOfBallMessage __instance) { if (TeamManager.Instance.LocalPlayerTeam.teamId == SharksAndMinnows.SHARKS_TEAM) { if (SingletonBehaviour.HasInstance) { RestartPrompt instance = SingletonBehaviour.Instance; Object.Destroy((Object)(object)instance); } Transform val = ((Component)__instance).transform.Find("Background"); if (PlayerMovementPatches.IsInZone) { TextMeshProUGUI component = ((Component)val.Find("Message")).GetComponent(); int num = Mathf.CeilToInt(PlayerMovementPatches.GetRemainingZoneBudget()); ((TMP_Text)component).text = $"Turn back Sharky!\n{num}"; __instance.ShowInternal(); } else { __instance.HideInternal(); } } } } public class DiveHitboxPatches { private static readonly Dictionary DiveTagTriggers = new Dictionary(); private const float MinimumDiveHitSpeed = 7f; [HarmonyPatch(typeof(PlayerMovement), "OnDivingStateChanged")] [HarmonyPostfix] public static void OnDivingStateChanged_Postfix(PlayerMovement __instance, DivingState previousState, DivingState currentState) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Invalid comparison between Unknown and I4 if (!NetworkClient.active || (Object)(object)__instance == (Object)null || !((NetworkBehaviour)__instance).isLocalPlayer) { return; } CapsuleCollider divingCollider = __instance.DivingCollider; if (!((Object)(object)divingCollider == (Object)null)) { if ((int)currentState == 1) { ApplyDiveTagTrigger(__instance, divingCollider); Plugin.Log.LogInfo((object)"Dive tag trigger enabled"); } else { RestoreDiveTagTrigger(__instance); Plugin.Log.LogInfo((object)"Dive tag trigger disabled"); } } } private static void ApplyDiveTagTrigger(PlayerMovement movement, CapsuleCollider divingCollider) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown //IL_008a: 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_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: 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_0129: Unknown result type (might be due to invalid IL or missing references) if (!DiveTagTriggers.ContainsKey(movement)) { ConfigurationHandler instance = ConfigurationHandler.Instance; float num = instance?.DiveHorizontalDiscMultiplier ?? 10f; float num2 = instance?.DiveVerticalDiscMultiplier ?? 1f; float num3 = instance?.DiveForwardCenterOffset ?? 0.15f; float num4 = instance?.DiveMinDiscHeight ?? 0.15f; GameObject val = new GameObject("SharksAndMinnows_DiveTagTrigger"); val.transform.SetParent(((Component)divingCollider).transform, false); val.transform.localPosition = divingCollider.center + new Vector3(0f, 0f, num3); val.transform.localRotation = Quaternion.identity; val.transform.localScale = Vector3.one; val.layer = ((Component)divingCollider).gameObject.layer; BoxCollider val2 = val.AddComponent(); ((Collider)val2).isTrigger = true; float num5 = divingCollider.radius * 2f; float num6 = num5 * num; float num7 = Mathf.Max(num5 * num2, num4); val2.size = new Vector3(num6, num7, num6); val2.center = Vector3.zero; DiveTagTrigger diveTagTrigger = val.AddComponent(); diveTagTrigger.Initialize(movement, 7f); DiveTagTriggers[movement] = diveTagTrigger; } } private static void RestoreDiveTagTrigger(PlayerMovement movement) { if (DiveTagTriggers.TryGetValue(movement, out DiveTagTrigger value)) { if ((Object)(object)value != (Object)null) { Object.Destroy((Object)(object)((Component)value).gameObject); } DiveTagTriggers.Remove(movement); } } } public class DiveTagTrigger : MonoBehaviour { private PlayerMovement owner; private Rigidbody ownerRigidbody; private float minimumDiveHitSpeed; private readonly HashSet hitThisDive = new HashSet(); public void Initialize(PlayerMovement ownerMovement, float minimumSpeed) { owner = ownerMovement; minimumDiveHitSpeed = minimumSpeed; if ((Object)(object)owner != (Object)null) { ownerRigidbody = ((Component)owner).GetComponent(); } } private void OnTriggerEnter(Collider other) { TryTag(other, "enter"); } private void OnTriggerStay(Collider other) { TryTag(other, "stay"); } private void TryTag(Collider other, string triggerEvent) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Invalid comparison between Unknown and I4 //IL_0126: 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_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: 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_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_026f: 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_0298: Unknown result type (might be due to invalid IL or missing references) //IL_02b0: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)owner == (Object)null || !((NetworkBehaviour)owner).isLocalPlayer || (int)owner.DivingState != 1 || (Object)(object)other == (Object)null) { return; } Entity val = (((Object)(object)other.attachedRigidbody != (Object)null) ? ((Component)other.attachedRigidbody).GetComponentInParent(true) : ((Component)other).GetComponentInParent(true)); if ((Object)(object)val == (Object)null || !val.IsHittable || (Object)(object)val == (Object)(object)owner.PlayerInfo.AsEntity) { return; } Hittable asHittable = val.AsHittable; if (!((Object)(object)asHittable == (Object)null) && asHittable.DiveSettings.CanBeHit && !hitThisDive.Contains(asHittable)) { hitThisDive.Add(asHittable); Vector3 val2 = ((Component)val).transform.position - ((Component)owner).transform.position; val2.y = 0f; if (((Vector3)(ref val2)).sqrMagnitude < 0.001f) { val2 = ((Component)owner).transform.forward; } else { ((Vector3)(ref val2)).Normalize(); } Vector3 val3 = (((Object)(object)ownerRigidbody != (Object)null) ? ownerRigidbody.linearVelocity : owner.SyncedVelocity); Vector3 networkedVelocity = val.GetNetworkedVelocity(); Vector3 val4 = val3 - networkedVelocity; float num = Vector3.Dot(val4, val2); float num2 = num; if (num2 < minimumDiveHitSpeed) { num2 = minimumDiveHitSpeed; } Vector3 val5 = val2 * num2; string playerName = GetPlayerName(owner.PlayerInfo); string entityName = GetEntityName(val); Plugin.Log.LogInfo((object)("Dive tag trigger hit player/entity | event=" + triggerEvent + " | owner=" + playerName + " | target=" + entityName + " | " + $"rawSpeed={num:F2} | " + $"appliedSpeed={num2:F2} | " + $"ownerVelocity={val3} | " + $"targetVelocity={networkedVelocity} | " + $"direction={val2}")); asHittable.HitWithDive(val5, owner); } } private static string GetEntityName(Entity entity) { if ((Object)(object)entity == (Object)null) { return "null"; } if (entity.IsPlayer && (Object)(object)entity.PlayerInfo != (Object)null) { return GetPlayerName(entity.PlayerInfo); } return ((Object)entity).name; } private static string GetPlayerName(PlayerInfo playerInfo) { if ((Object)(object)playerInfo == (Object)null) { return "null"; } return $"{playerInfo.PlayerId.PlayerName} ({playerInfo.PlayerId.guid})"; } } public class HoleProgressBarUIPatches { [HarmonyPatch(typeof(HoleProgressBarUi), "Awake")] [HarmonyPrefix] public static bool Awake_Prefix(HoleProgressBarUi __instance) { ((Component)((Component)__instance).transform).gameObject.SetActive(false); return false; } [HarmonyPatch(typeof(HoleProgressBarUi), "Start")] [HarmonyPrefix] public static bool Start_Prefix(HoleProgressBarUi __instance) { ((Component)((Component)__instance).transform).gameObject.SetActive(false); return false; } } public class InfoFeedPatches { [HarmonyPatch(typeof(InfoFeed), "ShowKnockoutMessage")] [HarmonyPrefix] public static bool StartOrCancelMatch_Prefix(PlayerInfo responsiblePlayer, PlayerInfo knockedOutPlayer, KnockoutType knockoutType) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Invalid comparison between Unknown and I4 if ((Object)(object)responsiblePlayer == (Object)null || (Object)(object)knockedOutPlayer == (Object)null) { return true; } PlayerTeam val = TeamManager.Instance.EnsurePlayerTeam(responsiblePlayer); PlayerTeam val2 = TeamManager.Instance.EnsurePlayerTeam(knockedOutPlayer); if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { return true; } if (val.teamId == SharksAndMinnows.SHARKS_TEAM && val2.teamId == SharksAndMinnows.MINNOWS_TEAM) { return (int)knockoutType > 0; } return true; } [HarmonyPatch(typeof(InfoFeed), "ColorizePlayerName")] [HarmonyPrefix] public static bool ColorizePlayerName_Prefix(string playerName, Color playerColor, ref string __result) { //IL_0055: 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) if (TryGetTeamColorForPlayerName(playerName, out var color)) { __result = "" + playerName + ""; return false; } __result = "" + playerName + ""; return false; } private static bool TryGetTeamColorForPlayerName(string playerName, out Color color) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //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) color = default(Color); if (string.IsNullOrEmpty(playerName)) { return false; } if ((Object)(object)TeamManager.Instance == (Object)null) { return false; } foreach (PlayerTeam player in TeamManager.Instance.Players) { if ((Object)(object)player == (Object)null) { continue; } ulong guid = player.playerInfo.PlayerId.Guid; if (CourseManager.GetPlayerName(guid) != playerName) { continue; } PlayerTeam val = TeamManager.Instance.EnsurePlayerTeam(player.playerInfo); if ((Object)(object)val == (Object)null) { return false; } color = TeamManager.Instance.Teams[val.teamId].Color; return true; } return false; } } public class ItemSpawnerPatches { [HarmonyPatch(typeof(ItemSpawner), "OnTriggerEnter")] [HarmonyPrefix] public static bool OnTriggerEnter_Prefix(ItemSpawner __instance, Collider other) { PlayerTeam val = default(PlayerTeam); ComponentExtensions.TryGetComponentInParent((Component)(object)other, ref val, true); if ((Object)(object)val == (Object)null) { return true; } if (val.teamId == SharksAndMinnows.MINNOWS_TEAM) { return false; } return true; } } public class PlayerGolferPatches { [HarmonyPatch(typeof(PlayerGolfer), "InformScored")] [HarmonyPrefix] public static void InformScored_Prefix(PlayerGolfer __instance) { TeamManager instance = TeamManager.Instance; if ((Object)(object)instance == (Object)null || (Object)(object)MinnowManager.Instance == (Object)null || MinnowManager.Instance.HasMinnowBeenCaptured(__instance.PlayerInfo.PlayerId.guid)) { return; } PlayerInfo val = (((Object)(object)__instance != (Object)null) ? __instance.PlayerInfo : null); if (!((Object)(object)val == (Object)null)) { PlayerTeam val2 = instance.EnsurePlayerTeam(val); if (!((Object)(object)val2 == (Object)null) && val2.teamId == SharksAndMinnows.MINNOWS_TEAM) { MinnowManager.Instance.AddMinnowScored(val.PlayerId.guid); } } } } public class PlayerMovementPatches { internal static float ZoneBudget = 30f; internal static float TimeSpentInZone = 0f; internal static float ZoneEnterTime = -1f; internal static bool IsInZone = false; internal static float LastForcedRespawnTime = -999f; private const float ForcedRespawnCooldownSeconds = 1f; internal static bool MustExitZoneAfterForcedRespawn = false; [HarmonyPatch(typeof(PlayerMovement), "Start")] [HarmonyPostfix] public static void Start_Prefix(PlayerMovement __instance) { if (!((Object)(object)__instance.PlayerInfo == (Object)null) && ((NetworkBehaviour)__instance.PlayerInfo).isLocalPlayer) { ResetZoneTimer(); } } public static void ResetZoneTimer() { Plugin.Log.LogInfo((object)"Resetting shark zone budget for new hole"); ZoneBudget = 30f; TimeSpentInZone = 0f; ZoneEnterTime = -1f; IsInZone = false; LastForcedRespawnTime = -999f; MustExitZoneAfterForcedRespawn = false; } internal static float GetCurrentTimeSpentInZone() { if (IsInZone && ZoneEnterTime >= 0f) { return TimeSpentInZone + (Time.time - ZoneEnterTime); } return TimeSpentInZone; } internal static float GetRemainingZoneBudget() { return Mathf.Max(ZoneBudget - GetCurrentTimeSpentInZone(), 0f); } private static bool IsOnGreen(PlayerMovement movement) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) TerrainLayer groundTerrainDominantGlobalLayer = movement.GroundTerrainDominantGlobalLayer; if (((object)(TerrainLayer)(ref groundTerrainDominantGlobalLayer)).ToString().ToLower().Contains("green")) { return true; } return false; } [HarmonyPatch(typeof(PlayerMovement), "Update")] [HarmonyPostfix] public static void Update_Prefix(PlayerMovement __instance) { if ((Object)(object)__instance.PlayerInfo == (Object)null || (Object)(object)TeamManager.Instance.LocalPlayerTeam == (Object)null || !((NetworkBehaviour)__instance.PlayerInfo).isLocalPlayer || TeamManager.Instance.LocalPlayerTeam.teamId != SharksAndMinnows.SHARKS_TEAM) { return; } if (IsOnGreen(__instance)) { if (!MustExitZoneAfterForcedRespawn) { if (!IsInZone) { IsInZone = true; ZoneEnterTime = Time.time; Plugin.Log.LogInfo((object)"Shark entered the protected area."); } float currentTimeSpentInZone = GetCurrentTimeSpentInZone(); if (currentTimeSpentInZone >= ZoneBudget && Time.time - LastForcedRespawnTime >= 1f) { __instance.TryBeginRespawn(false, (RespawnTarget)0); LastForcedRespawnTime = Time.time; TimeSpentInZone = ZoneBudget; ZoneEnterTime = -1f; IsInZone = false; MustExitZoneAfterForcedRespawn = true; Plugin.Log.LogInfo((object)"Shark used entire protected-area budget, teleporting back."); } } } else { if (MustExitZoneAfterForcedRespawn) { MustExitZoneAfterForcedRespawn = false; } if (IsInZone) { TimeSpentInZone += Time.time - ZoneEnterTime; ZoneEnterTime = -1f; IsInZone = false; Plugin.Log.LogInfo((object)$"Shark left protected area. Total used: {TimeSpentInZone:0.00}s / {ZoneBudget:0.00}s"); } } } [HarmonyPatch(typeof(PlayerMovement), "StartKnockoutImmunity")] [HarmonyPostfix] public static void StartKnockoutImmunity_Postfix(PlayerMovement __instance) { try { if (((NetworkBehaviour)__instance).isLocalPlayer && TeamManager.Instance.LocalPlayerTeam.teamId == SharksAndMinnows.MINNOWS_TEAM) { __instance.CancelKnockoutImmunity(); } } catch { Plugin.Log.LogError((object)"Failed to cancel knockout immunity, ignoring, probably just too early."); } } } public class ProximityTagPatches { private static readonly Dictionary CreatedAuras = new Dictionary(); [HarmonyPatch(typeof(PlayerMovement), "UpdateEnabledColliders")] [HarmonyPostfix] public static void UpdateEnabledColliders_Postfix(PlayerMovement __instance) { if (NetworkClient.active && !((Object)(object)__instance == (Object)null) && ((NetworkBehaviour)__instance).isLocalPlayer && !CreatedAuras.ContainsKey(__instance)) { CreateAura(__instance); } } private static void CreateAura(PlayerMovement movement) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) float radius = ConfigurationHandler.Instance?.ProximityTagAuraRadius ?? 3f; GameObject val = new GameObject("SharksAndMinnows_PlayerTagAura"); val.transform.SetParent(((Component)movement).transform, false); val.transform.localPosition = Vector3.zero; val.transform.localRotation = Quaternion.identity; val.transform.localScale = Vector3.one; val.layer = ((Component)movement).gameObject.layer; SphereCollider val2 = val.AddComponent(); ((Collider)val2).isTrigger = true; val2.radius = radius; ProximityTag proximityTag = val.AddComponent(); CreatedAuras.Add(movement, proximityTag); proximityTag.Initialize(movement); Plugin.Log.LogInfo((object)("Player tag aura created for " + GetPlayerName(movement.PlayerInfo))); } private static string GetPlayerName(PlayerInfo playerInfo) { if ((Object)(object)playerInfo == (Object)null) { return "null"; } return $"{playerInfo.PlayerId.PlayerName} ({playerInfo.PlayerId.guid})"; } public static void DestroyProximityColliders() { try { foreach (KeyValuePair createdAura in CreatedAuras) { Object.Destroy((Object)(object)createdAura.Value); } } catch { Plugin.Log.LogError((object)"Failed to destroy proximity colliders"); } } } public class TeeOffCountdownPatches { private static int _lastHoleIndex = -1; [HarmonyPatch(typeof(TeeOffCountdown), "ApplyVisibility")] [HarmonyPrefix] public static void Show_Prefix(TeeOffCountdown __instance) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Invalid comparison between Unknown and I4 if (!NetworkServer.active || (int)CourseManager.MatchState != 2) { return; } Plugin.Log.LogInfo((object)"Shark spawn server"); if (!((Object)(object)TeamManager.Instance == (Object)null) && !((Object)(object)SingletonNetworkBehaviour.Instance == (Object)null) && SingletonNetworkBehaviour.Instance.allCheckpoints != null && SingletonNetworkBehaviour.Instance.allCheckpoints.Count != 0 && GolfHoleManager.HasMaxReferenceDistance) { var list = (from x in SingletonNetworkBehaviour.Instance.allCheckpoints.Where((Checkpoint checkpoint) => (Object)(object)checkpoint != (Object)null).Select(delegate(Checkpoint checkpoint) { //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_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)checkpoint).transform.position; Vector3 val5 = position - ((Component)GolfHoleManager.MainHole).transform.position; float progress = 1f - BMath.Clamp01(((Vector3)(ref val5)).magnitude / GolfHoleManager.MaxReferenceDistance); return new { Checkpoint = checkpoint, Progress = progress }; }) orderby x.Progress descending select x).ToList(); int val = Math.Max(1, (int)Math.Floor((float)list.Count / 2f)); TeamData val2 = TeamManager.Instance.Teams[SharksAndMinnows.SHARKS_TEAM]; HashSet members = val2.Members; List list2 = (from shark in members where (Object)(object)shark != (Object)null && (Object)(object)shark.playerInfo != (Object)null orderby shark.playerInfo.PlayerId.guid select shark).ToList(); Random random = new Random(); for (int num = list2.Count - 1; num > 0; num--) { int num2 = random.Next(num + 1); List list3 = list2; int index = num; int index2 = num2; PlayerTeam value = list2[num2]; PlayerTeam value2 = list2[num]; list3[index] = value; list2[index2] = value2; } int val3 = Math.Min(val, list2.Count); val3 = Math.Max(1, val3); for (int i = 0; i < list2.Count; i++) { PlayerTeam val4 = list2[i]; int num3 = i % val3; Checkpoint checkpoint2 = list[num3].Checkpoint; CheckpointManager.TryActivate(checkpoint2, val4.playerInfo); Plugin.Log.LogInfo((object)$"Shark spawn server assigned {val4.playerInfo.PlayerId.guid} to checkpoint {num3}"); } Plugin.Log.LogInfo((object)"Shark spawn server done"); } } [HarmonyPatch(typeof(TeeOffCountdown), "ApplyVisibility")] [HarmonyPostfix] public static void Show_Postfix(TeeOffCountdown __instance) { if ((Object)(object)MinnowManager.Instance != (Object)null) { MinnowManager.Instance.SetInitialMinnowRoster(); } if (NetworkClient.active) { int currentHoleCourseIndex = CourseManager.CurrentHoleCourseIndex; if (currentHoleCourseIndex != _lastHoleIndex && !((Object)(object)TeamManager.Instance == (Object)null) && !((Object)(object)TeamManager.Instance.LocalPlayerTeam == (Object)null) && !((Object)(object)GameManager.LocalPlayerInfo == (Object)null) && TeamManager.Instance.LocalPlayerTeam.teamId == SharksAndMinnows.SHARKS_TEAM) { GameManager.LocalPlayerInfo.Movement.TryBeginRespawn(false, (RespawnTarget)0); _lastHoleIndex = currentHoleCourseIndex; Plugin.Log.LogInfo((object)"Shark spawn client respawned local shark"); } } } } } namespace SharksAndMinnows.Configuration { public class ConfigurationHandler { private ConfigFile _config; private BepInExConfigSync _bepInExConfigSync; private ConfigEntry ConfigMinnowDefaultMoveSpeedMultiplier; private ConfigEntry ConfigMinnowWalkMoveSpeedMultiplier; private ConfigEntry ConfigMinnowWadingInWaterSpeedMultiplier; private ConfigEntry ConfigMinnowSpeedBoostSpeedFactorMultiplier; private ConfigEntry ConfigMinnowDiveHorizontalSpeedMultiplier; private ConfigEntry ConfigMinnowDiveGetUpDurationMultiplier; private ConfigEntry ConfigMinnowJumpUpwardsSpeedMultiplier; private ConfigEntry ConfigSharkDefaultMoveSpeedMultiplier; private ConfigEntry ConfigSharkWalkMoveSpeedMultiplier; private ConfigEntry ConfigSharkWadingInWaterSpeedMultiplier; private ConfigEntry ConfigSharkSpeedBoostSpeedFactorMultiplier; private ConfigEntry ConfigSharkDiveUpwardsSpeedMultiplier; private ConfigEntry ConfigSharkDiveHorizontalSpeedMultiplier; private ConfigEntry ConfigSharkSwingChargingSpeedMultiplier; private ConfigEntry ConfigSharkSwingAimingSpeedMultiplier; private ConfigEntry ConfigDiveHorizontalDiscMultiplier; private ConfigEntry ConfigDiveVerticalDiscMultiplier; private ConfigEntry ConfigDiveForwardCenterOffset; private ConfigEntry ConfigDiveMinDiscHeight; private ConfigEntry ConfigProximityTagAuraRadius; public static ConfigurationHandler Instance { get; private set; } public float MinnowDefaultMoveSpeedMultiplier => ConfigMinnowDefaultMoveSpeedMultiplier.Value; public float MinnowWalkMoveSpeedMultiplier => ConfigMinnowWalkMoveSpeedMultiplier.Value; public float MinnowWadingInWaterSpeedMultiplier => ConfigMinnowWadingInWaterSpeedMultiplier.Value; public float MinnowSpeedBoostSpeedFactorMultiplier => ConfigMinnowSpeedBoostSpeedFactorMultiplier.Value; public float MinnowDiveHorizontalSpeedMultiplier => ConfigMinnowDiveHorizontalSpeedMultiplier.Value; public float MinnowDiveGetUpDurationMultiplier => ConfigMinnowDiveGetUpDurationMultiplier.Value; public float MinnowJumpUpwardsSpeedMultiplier => ConfigMinnowJumpUpwardsSpeedMultiplier.Value; public float SharkDefaultMoveSpeedMultiplier => ConfigSharkDefaultMoveSpeedMultiplier.Value; public float SharkWalkMoveSpeedMultiplier => ConfigSharkWalkMoveSpeedMultiplier.Value; public float SharkWadingInWaterSpeedMultiplier => ConfigSharkWadingInWaterSpeedMultiplier.Value; public float SharkSpeedBoostSpeedFactorMultiplier => ConfigSharkSpeedBoostSpeedFactorMultiplier.Value; public float SharkDiveUpwardsSpeedMultiplier => ConfigSharkDiveUpwardsSpeedMultiplier.Value; public float SharkDiveHorizontalSpeedMultiplier => ConfigSharkDiveHorizontalSpeedMultiplier.Value; public float SharkSwingChargingSpeedMultiplier => ConfigSharkSwingChargingSpeedMultiplier.Value; public float SharkSwingAimingSpeedMultiplier => ConfigSharkSwingAimingSpeedMultiplier.Value; public float DiveHorizontalDiscMultiplier => ConfigDiveHorizontalDiscMultiplier.Value; public float DiveVerticalDiscMultiplier => ConfigDiveVerticalDiscMultiplier.Value; public float DiveForwardCenterOffset => ConfigDiveForwardCenterOffset.Value; public float DiveMinDiscHeight => ConfigDiveMinDiscHeight.Value; public float ProximityTagAuraRadius => ConfigProximityTagAuraRadius.Value; public event Action MovementConfigChanged; public ConfigurationHandler(ConfigFile configFile) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown Instance = this; _config = configFile; Plugin.Log.LogInfo((object)$"ConfigurationHandler initialising {configFile}"); BindMovementSpeedConfigurations(); BindDivingHitboxConfigurations(); BindProximityTagConfigurations(); _bepInExConfigSync = new BepInExConfigSync(_config, "com.github.glarmer.SharksAndMinnows:SharksAndMinnows"); _bepInExConfigSync.SyncedValueChanged += delegate { this.MovementConfigChanged?.Invoke(); }; Plugin.Log.LogInfo((object)"ConfigurationHandler initialised"); } private void BindMovementSpeedConfigurations() { ConfigMinnowDefaultMoveSpeedMultiplier = Bind("Movement Minnows", "MinnowDefaultMoveSpeedMultiplier", 2f, "Multiplier for minnow default move speed", delegate { this.MovementConfigChanged?.Invoke(); }, (float v) => Mathf.Clamp(v, 0.1f, 100f)); ConfigMinnowWalkMoveSpeedMultiplier = Bind("Movement Minnows", "MinnowWalkMoveSpeedMultiplier", 2f, "Multiplier for minnow walk move speed", delegate { this.MovementConfigChanged?.Invoke(); }, (float v) => Mathf.Clamp(v, 0.1f, 100f)); ConfigMinnowWadingInWaterSpeedMultiplier = Bind("Movement Minnows", "MinnowWadingInWaterSpeedMultiplier", 2f, "Multiplier for minnow wading in water speed", delegate { this.MovementConfigChanged?.Invoke(); }, (float v) => Mathf.Clamp(v, 0.1f, 100f)); ConfigMinnowSpeedBoostSpeedFactorMultiplier = Bind("Movement Minnows", "MinnowSpeedBoostSpeedFactorMultiplier", 2f, "Multiplier for minnow speed boost factor", delegate { this.MovementConfigChanged?.Invoke(); }, (float v) => Mathf.Clamp(v, 0.1f, 100f)); ConfigMinnowDiveHorizontalSpeedMultiplier = Bind("Movement Minnows", "MinnowDiveHorizontalSpeedMultiplier", 1.5f, "Multiplier for minnow dive horizontal speed", delegate { this.MovementConfigChanged?.Invoke(); }, (float v) => Mathf.Clamp(v, 0.1f, 100f)); ConfigMinnowDiveGetUpDurationMultiplier = Bind("Movement Minnows", "MinnowDiveGetUpDurationMultiplier", 0.75f, "Multiplier for minnow dive get up duration", delegate { this.MovementConfigChanged?.Invoke(); }, (float v) => Mathf.Clamp(v, 0.1f, 100f)); ConfigMinnowJumpUpwardsSpeedMultiplier = Bind("Movement Minnows", "MinnowJumpUpwardsSpeedMultiplier", 1.25f, "Multiplier for minnow jump upwards speed", delegate { this.MovementConfigChanged?.Invoke(); }, (float v) => Mathf.Clamp(v, 0.1f, 100f)); ConfigSharkDefaultMoveSpeedMultiplier = Bind("Movement Sharks", "SharkDefaultMoveSpeedMultiplier", 1f, "Multiplier for shark default move speed", delegate { this.MovementConfigChanged?.Invoke(); }, (float v) => Mathf.Clamp(v, 0.1f, 100f)); ConfigSharkWalkMoveSpeedMultiplier = Bind("Movement Sharks", "SharkWalkMoveSpeedMultiplier", 1f, "Multiplier for shark walk move speed", delegate { this.MovementConfigChanged?.Invoke(); }, (float v) => Mathf.Clamp(v, 0.1f, 100f)); ConfigSharkWadingInWaterSpeedMultiplier = Bind("Movement Sharks", "SharkWadingInWaterSpeedMultiplier", 1f, "Multiplier for shark wading in water speed", delegate { this.MovementConfigChanged?.Invoke(); }, (float v) => Mathf.Clamp(v, 0.1f, 100f)); ConfigSharkSpeedBoostSpeedFactorMultiplier = Bind("Movement Sharks", "SharkSpeedBoostSpeedFactorMultiplier", 1f, "Multiplier for shark speed boost factor", delegate { this.MovementConfigChanged?.Invoke(); }, (float v) => Mathf.Clamp(v, 0.1f, 100f)); ConfigSharkDiveUpwardsSpeedMultiplier = Bind("Movement Sharks", "SharkDiveUpwardsSpeedMultiplier", 1f, "Multiplier for shark dive upwards speed", delegate { this.MovementConfigChanged?.Invoke(); }, (float v) => Mathf.Clamp(v, 0.1f, 100f)); ConfigSharkDiveHorizontalSpeedMultiplier = Bind("Movement Sharks", "SharkDiveHorizontalSpeedMultiplier", 2.5f, "Multiplier for shark dive horizontal speed", delegate { this.MovementConfigChanged?.Invoke(); }, (float v) => Mathf.Clamp(v, 0.1f, 100f)); ConfigSharkSwingChargingSpeedMultiplier = Bind("Movement Sharks", "SharkSwingChargingSpeedMultiplier", 1.5f, "Multiplier for shark swing charging speed", delegate { this.MovementConfigChanged?.Invoke(); }, (float v) => Mathf.Clamp(v, 0.1f, 100f)); ConfigSharkSwingAimingSpeedMultiplier = Bind("Movement Sharks", "SharkSwingAimingSpeedMultiplier", 1.5f, "Multiplier for shark swing aiming speed", delegate { this.MovementConfigChanged?.Invoke(); }, (float v) => Mathf.Clamp(v, 0.1f, 100f)); } private void BindDivingHitboxConfigurations() { ConfigDiveHorizontalDiscMultiplier = Bind("Diving Hitbox", "HorizontalDiscMultiplier", 10f, "Multiplier applied to diving collider diameter for hitbox width/depth", null, (float v) => Mathf.Clamp(v, 0.01f, 100f)); ConfigDiveVerticalDiscMultiplier = Bind("Diving Hitbox", "VerticalDiscMultiplier", 1f, "Multiplier applied to diving collider diameter for hitbox height", null, (float v) => Mathf.Clamp(v, 0.01f, 100f)); ConfigDiveForwardCenterOffset = Bind("Diving Hitbox", "ForwardCenterOffset", 0.15f, "Forward (local Z) offset applied to the dive hitbox center", null, (float v) => Mathf.Clamp(v, -10f, 10f)); ConfigDiveMinDiscHeight = Bind("Diving Hitbox", "MinDiscHeight", 0.15f, "Minimum height of the dive hitbox (prevents extremely thin hitboxes)", null, (float v) => Mathf.Clamp(v, 0.01f, 10f)); } private void BindProximityTagConfigurations() { ConfigProximityTagAuraRadius = Bind("Proximity Tag", "TagAuraRadius", 3f, "Radius of the proximity tag aura trigger (in meters)", null, (float v) => Mathf.Clamp(v, 0.1f, 100f)); } public void SyncConfiguration() { if (NetworkServer.active) { _bepInExConfigSync.PushHostConfigToScope(); } else if (NetworkClient.active) { _bepInExConfigSync.RequestFromHost(); } } private ConfigEntry Bind(string section, string key, T defaultValue, string description, Action onChanged = null, Func clamp = null) { Func clamp2 = clamp; Action onChanged2 = onChanged; ConfigEntry entry = _config.Bind(section, key, defaultValue, description); if (clamp2 != null) { entry.Value = clamp2(entry.Value); } Plugin.Log.LogInfo((object)$"{key} set to: {entry.Value}"); if (onChanged2 != null) { entry.SettingChanged += delegate { if (clamp2 != null) { T val = clamp2(entry.Value); if (!object.Equals(entry.Value, val)) { entry.Value = val; return; } } onChanged2(); }; } return entry; } } } namespace System.Diagnostics.CodeAnalysis { [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class ConstantExpectedAttribute : Attribute { public object? Min { get; set; } public object? Max { get; set; } } [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class ExperimentalAttribute : Attribute { public string DiagnosticId { get; } public string? UrlFormat { get; set; } public ExperimentalAttribute(string diagnosticId) { DiagnosticId = diagnosticId; } } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] [ExcludeFromCodeCoverage] internal sealed class MemberNotNullAttribute : Attribute { public string[] Members { get; } public MemberNotNullAttribute(string member) { Members = new string[1] { member }; } public MemberNotNullAttribute(params string[] members) { Members = members; } } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] [ExcludeFromCodeCoverage] internal sealed class MemberNotNullWhenAttribute : Attribute { public bool ReturnValue { get; } public string[] Members { get; } public MemberNotNullWhenAttribute(bool returnValue, string member) { ReturnValue = returnValue; Members = new string[1] { member }; } public MemberNotNullWhenAttribute(bool returnValue, params string[] members) { ReturnValue = returnValue; Members = members; } } [AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class SetsRequiredMembersAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class StringSyntaxAttribute : Attribute { public const string CompositeFormat = "CompositeFormat"; public const string DateOnlyFormat = "DateOnlyFormat"; public const string DateTimeFormat = "DateTimeFormat"; public const string EnumFormat = "EnumFormat"; public const string GuidFormat = "GuidFormat"; public const string Json = "Json"; public const string NumericFormat = "NumericFormat"; public const string Regex = "Regex"; public const string TimeOnlyFormat = "TimeOnlyFormat"; public const string TimeSpanFormat = "TimeSpanFormat"; public const string Uri = "Uri"; public const string Xml = "Xml"; public string Syntax { get; } public object?[] Arguments { get; } public StringSyntaxAttribute(string syntax) { Syntax = syntax; Arguments = new object[0]; } public StringSyntaxAttribute(string syntax, params object?[] arguments) { Syntax = syntax; Arguments = arguments; } } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class UnscopedRefAttribute : Attribute { } } namespace System.Runtime.Versioning { [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class RequiresPreviewFeaturesAttribute : Attribute { public string? Message { get; } public string? Url { get; set; } public RequiresPreviewFeaturesAttribute() { } public RequiresPreviewFeaturesAttribute(string? message) { Message = message; } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class CallerArgumentExpressionAttribute : Attribute { public string ParameterName { get; } public CallerArgumentExpressionAttribute(string parameterName) { ParameterName = parameterName; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class CollectionBuilderAttribute : Attribute { public Type BuilderType { get; } public string MethodName { get; } public CollectionBuilderAttribute(Type builderType, string methodName) { BuilderType = builderType; MethodName = methodName; } } [AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class CompilerFeatureRequiredAttribute : Attribute { public const string RefStructs = "RefStructs"; public const string RequiredMembers = "RequiredMembers"; public string FeatureName { get; } public bool IsOptional { get; set; } public CompilerFeatureRequiredAttribute(string featureName) { FeatureName = featureName; } } [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class InterpolatedStringHandlerArgumentAttribute : Attribute { public string[] Arguments { get; } public InterpolatedStringHandlerArgumentAttribute(string argument) { Arguments = new string[1] { argument }; } public InterpolatedStringHandlerArgumentAttribute(params string[] arguments) { Arguments = arguments; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class InterpolatedStringHandlerAttribute : Attribute { } [EditorBrowsable(EditorBrowsableState.Never)] [ExcludeFromCodeCoverage] internal static class IsExternalInit { } [AttributeUsage(AttributeTargets.Method, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class ModuleInitializerAttribute : Attribute { } [AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class OverloadResolutionPriorityAttribute : Attribute { public int Priority { get; } public OverloadResolutionPriorityAttribute(int priority) { Priority = priority; } } [AttributeUsage(AttributeTargets.Parameter, Inherited = true, AllowMultiple = false)] [ExcludeFromCodeCoverage] internal sealed class ParamCollectionAttribute : Attribute { } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class RequiredMemberAttribute : Attribute { } [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] [EditorBrowsable(EditorBrowsableState.Never)] [ExcludeFromCodeCoverage] internal sealed class RequiresLocationAttribute : Attribute { } [AttributeUsage(AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event | AttributeTargets.Interface, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class SkipLocalsInitAttribute : Attribute { } }