Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of SharingIsCaring v0.3.0
plugins/SharingIsCaring/SharingIsCaring.dll
Decompiled 12 hours agousing System; using System.Collections.Generic; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using Photon.Pun; using Photon.Realtime; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyVersion("0.0.0.0")] namespace SharingIsCaring; [BepInPlugin("mvffyn.SharingIsCaring", "Sharing Is Caring", "0.3.0")] public class Plugin : BaseUnityPlugin { public const string GUID = "mvffyn.SharingIsCaring"; public const string NAME = "Sharing Is Caring"; public const string VERSION = "0.3.0"; internal static ManualLogSource Log; internal static ConfigEntry<bool> SharedUpgrades; internal static ConfigEntry<bool> SharedHealing; internal static ConfigEntry<float> SharedHealingFraction; internal static ConfigEntry<float> ShopPriceMultiplier; internal static ConfigEntry<int> MaxPlayers; private void Awake() { //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Expected O, but got Unknown //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Expected O, but got Unknown //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Expected O, but got Unknown //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Expected O, but got Unknown //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; SharedUpgrades = ((BaseUnityPlugin)this).Config.Bind<bool>("Sharing", "SharedUpgrades", true, "When any player uses an upgrade item, every player in the lobby receives the same upgrade."); SharedHealing = ((BaseUnityPlugin)this).Config.Bind<bool>("Sharing", "SharedHealing", true, "When any player uses a health pack, every other player is healed too."); SharedHealingFraction = ((BaseUnityPlugin)this).Config.Bind<float>("Sharing", "SharedHealingFraction", 1f, new ConfigDescription("How much of the health pack's healing the other players receive (1 = full amount, 0.5 = half).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); ShopPriceMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Shop", "PriceMultiplier", 0.5f, new ConfigDescription("Multiplier on every shop price. 0.5 = half price, 1 = vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 2f), Array.Empty<object>())); MaxPlayers = ((BaseUnityPlugin)this).Config.Bind<int>("Lobby", "MaxPlayers", 10, new ConfigDescription("Maximum players in a lobby you host. Vanilla is 6; the game's networking allows up to 20. Beyond 6, players share spawn spots and colours.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 20), Array.Empty<object>())); TeamConfig.Bind(((BaseUnityPlugin)this).Config); Harmony val = new Harmony("mvffyn.SharingIsCaring"); if (MaxPlayers.Value != 6) { val.PatchAll(typeof(LobbyPatches)); } if (TeamConfig.ManyHands.Value) { val.PatchAll(typeof(ManyHandsPatch)); } if (TeamConfig.SafetyInNumbers.Value) { val.PatchAll(typeof(SafetyPatches)); } if (TeamConfig.RescueRewards.Value) { val.PatchAll(typeof(RescuePatches)); } if (TeamConfig.TeamMilestones.Value || TeamConfig.ClutchMode.Value) { val.PatchAll(typeof(RoundPatches)); } TeamEvents.Register(); if (TeamConfig.Ping.Value) { GameObject val2 = new GameObject("SharingIsCaring.Ping"); Object.DontDestroyOnLoad((Object)(object)val2); val2.AddComponent<PingInput>(); } if (SharedUpgrades.Value) { UpgradePatches.Apply(val); } if (SharedHealing.Value) { val.PatchAll(typeof(HealingPatches)); } if (Math.Abs(ShopPriceMultiplier.Value - 1f) > 0.001f) { val.PatchAll(typeof(ShopPatches)); } Log.LogInfo((object)"Sharing Is Caring 0.3.0 loaded. Host-side rules need only the host; Safety In Numbers, head-carry speed, messages and pings need the mod on each player."); } internal static bool IsHost() { try { return SemiFunc.IsMasterClientOrSingleplayer(); } catch { return true; } } internal static List<PlayerAvatar> Players() { try { return SemiFunc.PlayerGetAll() ?? new List<PlayerAvatar>(); } catch { return new List<PlayerAvatar>(); } } } internal static class UpgradePatches { private static readonly string[] Methods = new string[13] { "UpgradePlayerHealth", "UpgradePlayerEnergy", "UpgradePlayerExtraJump", "UpgradeMapPlayerCount", "UpgradePlayerTumbleLaunch", "UpgradePlayerTumbleClimb", "UpgradeDeathHeadBattery", "UpgradePlayerTumbleWings", "UpgradePlayerSprintSpeed", "UpgradePlayerCrouchRest", "UpgradePlayerGrabStrength", "UpgradePlayerThrowStrength", "UpgradePlayerGrabRange" }; [ThreadStatic] private static bool reentrant; internal static void Apply(Harmony harmony) { //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Expected O, but got Unknown int num = 0; string[] methods = Methods; foreach (string text in methods) { MethodInfo methodInfo = AccessTools.Method(typeof(PunManager), text, new Type[2] { typeof(string), typeof(int) }, (Type[])null); if (methodInfo == null) { Plugin.Log.LogWarning((object)("Upgrade method not found: " + text)); continue; } MethodInfo methodInfo2 = methodInfo; HarmonyMethod val = new HarmonyMethod(typeof(UpgradePatches), "Postfix", (Type[])null); harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); num++; } Plugin.Log.LogInfo((object)("Shared upgrades: hooked " + num + " upgrade types.")); } private static void Postfix(PunManager __instance, MethodBase __originalMethod, string _steamID, int value) { if (reentrant || value <= 0 || !Plugin.IsHost()) { return; } reentrant = true; try { int num = 0; foreach (PlayerAvatar item in Plugin.Players()) { if (!((Object)(object)item == (Object)null)) { string text = SemiFunc.PlayerGetSteamID(item); if (!string.IsNullOrEmpty(text) && !(text == _steamID)) { __originalMethod.Invoke(__instance, new object[2] { text, value }); num++; } } } if (num > 0) { Plugin.Log.LogInfo((object)(__originalMethod.Name + " shared with " + num + " other player(s).")); } } catch (Exception ex) { Plugin.Log.LogError((object)("Shared upgrade failed: " + ex)); } finally { reentrant = false; } } } [HarmonyPatch] internal static class HealingPatches { private static bool inHealthPack; private static bool reentrant; [HarmonyPatch(typeof(ItemHealthPack), "Update")] [HarmonyPrefix] private static void HealthPackPrefix() { inHealthPack = true; } [HarmonyPatch(typeof(ItemHealthPack), "Update")] [HarmonyPostfix] private static void HealthPackPostfix() { inHealthPack = false; } [HarmonyPatch(typeof(PlayerHealth), "HealOther", new Type[] { typeof(int), typeof(bool) })] [HarmonyPostfix] private static void HealOtherPostfix(PlayerHealth __instance, int healAmount, bool effect) { if (!inHealthPack || reentrant || healAmount <= 0 || !Plugin.IsHost()) { return; } int num = Mathf.RoundToInt((float)healAmount * Plugin.SharedHealingFraction.Value); if (num <= 0) { return; } reentrant = true; try { int num2 = 0; foreach (PlayerAvatar item in Plugin.Players()) { if (!((Object)(object)item == (Object)null) && !((Object)(object)item.playerHealth == (Object)null) && !((Object)(object)item.playerHealth == (Object)(object)__instance)) { item.playerHealth.HealOther(num, effect); num2++; } } if (num2 > 0) { Plugin.Log.LogInfo((object)("Health pack shared: +" + num + " to " + num2 + " other player(s).")); } } catch (Exception ex) { Plugin.Log.LogError((object)("Shared healing failed: " + ex)); } finally { reentrant = false; } } } [HarmonyPatch(typeof(ShopManager), "Awake")] internal static class ShopPatches { private static readonly FieldInfo MultField = AccessTools.Field(typeof(ShopManager), "itemValueMultiplier"); [HarmonyPostfix] private static void Postfix(ShopManager __instance) { try { if (MultField == null) { Plugin.Log.LogWarning((object)"itemValueMultiplier not found."); return; } float num = (float)MultField.GetValue(__instance); float num2 = num * Plugin.ShopPriceMultiplier.Value; MultField.SetValue(__instance, num2); Plugin.Log.LogInfo((object)("Shop price multiplier " + num + " -> " + num2)); } catch (Exception ex) { Plugin.Log.LogError((object)("Shop price patch failed: " + ex)); } } } [HarmonyPatch(typeof(GameManager), "Awake")] internal static class LobbyPatches { [HarmonyPostfix] private static void Postfix(GameManager __instance) { try { int num = (__instance.maxPlayers = Mathf.Clamp(Plugin.MaxPlayers.Value, 1, Mathf.Max(1, __instance.maxPlayersPhoton))); Plugin.Log.LogInfo((object)("Lobby size set to " + num + " players.")); } catch (Exception ex) { Plugin.Log.LogError((object)("Lobby size patch failed: " + ex)); } } } internal static class TeamConfig { internal static ConfigEntry<bool> ManyHands; internal static ConfigEntry<float> ManyHandsStrengthPerHelper; internal static ConfigEntry<float> ManyHandsFragility; internal static ConfigEntry<bool> SafetyInNumbers; internal static ConfigEntry<float> SafetyRadius; internal static ConfigEntry<float> SafetyStaminaRegen; internal static ConfigEntry<float> SafetyDamageReduction; internal static ConfigEntry<bool> RescueRewards; internal static ConfigEntry<float> HeadCarrySpeed; internal static ConfigEntry<int> ReviveHeal; internal static ConfigEntry<bool> TeamMilestones; internal static ConfigEntry<int> MilestoneHeal; internal static ConfigEntry<bool> ClutchMode; internal static ConfigEntry<int> ClutchHeal; internal static ConfigEntry<bool> Ping; internal static ConfigEntry<string> PingKey; internal static ConfigEntry<float> PingDuration; internal static void Bind(ConfigFile cfg) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Expected O, but got Unknown //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Expected O, but got Unknown //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Expected O, but got Unknown //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Expected O, but got Unknown //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Expected O, but got Unknown //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Expected O, but got Unknown //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Expected O, but got Unknown //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Expected O, but got Unknown //IL_02c4: Unknown result type (might be due to invalid IL or missing references) //IL_02ce: Expected O, but got Unknown ManyHands = cfg.Bind<bool>("Many Hands", "Enabled", true, "Two or more players grabbing the same object get bonus grab strength and the object is harder to break. Host-side."); ManyHandsStrengthPerHelper = cfg.Bind<float>("Many Hands", "StrengthPerHelper", 0.3f, new ConfigDescription("Extra grab strength per additional grabber (0.3 = +30% each).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); ManyHandsFragility = cfg.Bind<float>("Many Hands", "FragilityMultiplier", 0.5f, new ConfigDescription("Impact damage multiplier for objects held by 2+ players (0.5 = half damage).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); SafetyInNumbers = cfg.Bind<bool>("Safety In Numbers", "Enabled", true, "Players near a living teammate regain stamina faster and take less damage. Client-side: each player needs the mod for their own buff."); SafetyRadius = cfg.Bind<float>("Safety In Numbers", "Radius", 8f, new ConfigDescription("How close (meters) a teammate must be.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 30f), Array.Empty<object>())); SafetyStaminaRegen = cfg.Bind<float>("Safety In Numbers", "StaminaRegenPerSecond", 6f, new ConfigDescription("Extra stamina per second while near a teammate (full bar is 40).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 40f), Array.Empty<object>())); SafetyDamageReduction = cfg.Bind<float>("Safety In Numbers", "DamageReduction", 0.2f, new ConfigDescription("Fraction of incoming damage removed while near a teammate.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.75f), Array.Empty<object>())); RescueRewards = cfg.Bind<bool>("Rescue Rewards", "Enabled", true, "Carrying a teammate's head makes you faster; a revive heals both the revived player and the nearest rescuer."); HeadCarrySpeed = cfg.Bind<float>("Rescue Rewards", "HeadCarrySpeedMultiplier", 1.35f, new ConfigDescription("Sprint speed multiplier while carrying a death head (client-side).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 2.5f), Array.Empty<object>())); ReviveHeal = cfg.Bind<int>("Rescue Rewards", "ReviveHeal", 30, new ConfigDescription("Health given to the revived player and the nearest living rescuer (host-side).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); TeamMilestones = cfg.Bind<bool>("Team Milestones", "Enabled", true, "At 25/50/75/100% of the haul goal everyone gets a message and a small heal. Host-side; message shows for players with the mod."); MilestoneHeal = cfg.Bind<int>("Team Milestones", "Heal", 10, new ConfigDescription("Health given to every player at each milestone.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 50), Array.Empty<object>())); ClutchMode = cfg.Bind<bool>("Clutch Mode", "Enabled", true, "When only one player is left alive they get a one-time heal and full stamina. Host-side; stamina refill needs the mod on that player."); ClutchHeal = cfg.Bind<int>("Clutch Mode", "Heal", 40, new ConfigDescription("Health given to the last player standing.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); Ping = cfg.Bind<bool>("Ping", "Enabled", true, "Press the ping key to mark what you're looking at for every player who has the mod."); PingKey = cfg.Bind<string>("Ping", "Key", "MiddleButton", "Key that places a ping. Mouse: LeftButton, RightButton, MiddleButton, ForwardButton, BackButton. Keyboard: any Unity InputSystem key name, e.g. T, G, F, Q, CapsLock."); PingDuration = cfg.Bind<float>("Ping", "Duration", 6f, new ConfigDescription("Seconds a ping marker stays visible.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 20f), Array.Empty<object>())); } } internal static class Team { internal static readonly Color Pink = new Color(1f, 0.55f, 0.75f); internal static readonly Color Mint = new Color(0.55f, 1f, 0.8f); internal static readonly Color Gold = new Color(1f, 0.85f, 0.3f); internal static bool IsAlive(PlayerAvatar a) { if ((Object)(object)a == (Object)null) { return false; } try { Traverse val = Traverse.Create((object)a); return !val.Field<bool>("deadSet").Value && !val.Field<bool>("isDisabled").Value; } catch { return true; } } internal static PlayerAvatar Local() { try { return SemiFunc.PlayerAvatarLocal(); } catch { return null; } } internal static bool InLevel() { try { return SemiFunc.RunIsLevel(); } catch { return false; } } internal static bool TeammateNear(PlayerAvatar me, float radius) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0060: 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_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)me == (Object)null) { return false; } Vector3 position = ((Component)me).transform.position; foreach (PlayerAvatar item in Plugin.Players()) { if (!((Object)(object)item == (Object)null) && !((Object)(object)item == (Object)(object)me) && IsAlive(item)) { Vector3 val = ((Component)item).transform.position - position; if (((Vector3)(ref val)).sqrMagnitude <= radius * radius) { return true; } } } return false; } internal static PlayerAvatar NearestAlive(Vector3 pos, PlayerAvatar exclude, float maxDist) { //IL_004c: 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_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) PlayerAvatar result = null; float num = maxDist * maxDist; foreach (PlayerAvatar item in Plugin.Players()) { if (!((Object)(object)item == (Object)null) && !((Object)(object)item == (Object)(object)exclude) && IsAlive(item)) { Vector3 val = ((Component)item).transform.position - pos; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; if (sqrMagnitude < num) { num = sqrMagnitude; result = item; } } } return result; } internal static void BigMessage(string text, string emoji, Color color) { //IL_0007: 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) try { SemiFunc.UIBigMessage(text, emoji, 25f, color, Color.white); } catch (Exception ex) { Plugin.Log.LogWarning((object)("BigMessage failed: " + ex.Message)); } } internal static void FocusText(string text, Color color, float time) { //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) try { SemiFunc.UIFocusText(text, color, Color.white, time); } catch (Exception ex) { Plugin.Log.LogWarning((object)("FocusText failed: " + ex.Message)); } } internal static void RefillLocalStamina() { try { PlayerController instance = PlayerController.instance; if ((Object)(object)instance != (Object)null) { instance.EnergyCurrent = instance.EnergyStart; } } catch { } } } internal class TeamEvents : IOnEventCallback { internal const byte EventCode = 92; internal const byte KindMilestone = 1; internal const byte KindClutch = 2; internal const byte KindPing = 3; private static TeamEvents instance; internal static void Register() { if (instance == null) { instance = new TeamEvents(); PhotonNetwork.AddCallbackTarget((object)instance); } } internal static void Broadcast(byte kind, string text, Vector3 pos) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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) Handle(kind, text, pos); try { if (PhotonNetwork.InRoom) { RaiseEventOptions val = new RaiseEventOptions(); val.Receivers = (ReceiverGroup)0; RaiseEventOptions val2 = val; PhotonNetwork.RaiseEvent((byte)92, (object)new object[3] { kind, text, pos }, val2, SendOptions.SendReliable); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Team event send failed: " + ex.Message)); } } public void OnEvent(EventData photonEvent) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (photonEvent.Code != 92) { return; } try { if (photonEvent.CustomData is object[] array && array.Length >= 3) { Handle((byte)array[0], array[1] as string, (Vector3)array[2]); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Team event receive failed: " + ex.Message)); } } private static void Handle(byte kind, string text, Vector3 pos) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) switch (kind) { case 1: Team.BigMessage(text, "{heart}", Team.Mint); break; case 2: { Team.BigMessage(text, "{fire}", Team.Gold); PlayerAvatar val = Team.Local(); if ((Object)(object)val != (Object)null && Team.IsAlive(val)) { Team.RefillLocalStamina(); } break; } case 3: PingMarker.Show(pos, text); break; } } } [HarmonyPatch(typeof(PhysGrabObject), "FixedUpdate")] internal static class ManyHandsPatch { [HarmonyPostfix] private static void Postfix(PhysGrabObject __instance) { try { if (Plugin.IsHost() && __instance.playerGrabbing != null) { int count = __instance.playerGrabbing.Count; if (count >= 2) { float num = 1f + TeamConfig.ManyHandsStrengthPerHelper.Value * (float)(count - 1); __instance.OverrideGrabStrength(num, 0.1f); __instance.OverrideFragility(TeamConfig.ManyHandsFragility.Value); } } } catch { } } } [HarmonyPatch] internal static class SafetyPatches { internal static bool nearTeammate; private static float checkTimer; [HarmonyPatch(typeof(PlayerController), "Update")] [HarmonyPostfix] private static void ControllerUpdate(PlayerController __instance) { try { if (!Team.InLevel()) { nearTeammate = false; return; } checkTimer -= Time.deltaTime; if (checkTimer <= 0f) { checkTimer = 0.5f; nearTeammate = Team.TeammateNear(Team.Local(), TeamConfig.SafetyRadius.Value); } if (nearTeammate && __instance.EnergyCurrent < __instance.EnergyStart) { __instance.EnergyCurrent = Mathf.Min(__instance.EnergyStart, __instance.EnergyCurrent + TeamConfig.SafetyStaminaRegen.Value * Time.deltaTime); } } catch { } } [HarmonyPatch(typeof(PlayerHealth), "Hurt", new Type[] { typeof(int), typeof(bool), typeof(int), typeof(bool) })] [HarmonyPrefix] private static void HurtPrefix(PlayerHealth __instance, ref int damage) { try { if (nearTeammate && damage > 0) { PlayerAvatar val = Team.Local(); if (!((Object)(object)val == (Object)null) && !((Object)(object)val.playerHealth != (Object)(object)__instance)) { int num = Mathf.Max(1, Mathf.RoundToInt((float)damage * (1f - TeamConfig.SafetyDamageReduction.Value))); damage = num; } } } catch { } } } [HarmonyPatch] internal static class RescuePatches { private static bool boosting; private static float savedSprint; [HarmonyPatch(typeof(PlayerController), "Update")] [HarmonyPostfix] private static void CarryBoost(PlayerController __instance) { //IL_00a8: Unknown result type (might be due to invalid IL or missing references) try { bool flag = false; PlayerAvatar val = Team.Local(); if ((Object)(object)val != (Object)null && (Object)(object)val.physGrabber != (Object)null && val.physGrabber.grabbed) { PhysGrabObject value = Traverse.Create((object)val.physGrabber).Field<PhysGrabObject>("grabbedPhysGrabObject").Value; flag = (Object)(object)value != (Object)null && (Object)(object)((Component)value).GetComponent<PlayerDeathHead>() != (Object)null; } if (flag && !boosting) { boosting = true; savedSprint = __instance.SprintSpeed; __instance.SprintSpeed = savedSprint * TeamConfig.HeadCarrySpeed.Value; Team.FocusText("Carrying a friend: speed boost!", Team.Mint, 2f); } else if (!flag && boosting) { boosting = false; __instance.SprintSpeed = savedSprint; } } catch { } } [HarmonyPatch(typeof(PlayerAvatar), "ReviveRPC")] [HarmonyPostfix] private static void ReviveHeal(PlayerAvatar __instance, bool _revivedByTruck) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) try { if (Plugin.IsHost() && !_revivedByTruck && TeamConfig.ReviveHeal.Value > 0) { if ((Object)(object)__instance.playerHealth != (Object)null) { __instance.playerHealth.HealOther(TeamConfig.ReviveHeal.Value, true); } PlayerAvatar val = Team.NearestAlive(((Component)__instance).transform.position, __instance, 8f); if ((Object)(object)val != (Object)null && (Object)(object)val.playerHealth != (Object)null) { val.playerHealth.HealOther(TeamConfig.ReviveHeal.Value, true); } Plugin.Log.LogInfo((object)("Rescue reward: healed revived player" + ((!((Object)(object)val != (Object)null)) ? string.Empty : " and rescuer") + ".")); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Revive heal failed: " + ex.Message)); } } } [HarmonyPatch] internal static class RoundPatches { private static readonly int[] Thresholds = new int[4] { 25, 50, 75, 100 }; private static readonly string[] Messages = new string[4] { "Quarter of the way there, team!", "Halfway! Keep it up!", "Almost there!! 75%!", "GOAL REACHED! Everybody back to the truck!" }; private static int nextMilestone; private static bool clutchFired; private static float pollTimer; [HarmonyPatch(typeof(LevelGenerator), "GenerateDone")] [HarmonyPostfix] private static void ResetForLevel() { nextMilestone = 0; clutchFired = false; } [HarmonyPatch(typeof(RoundDirector), "Update")] [HarmonyPostfix] private static void Poll(RoundDirector __instance) { //IL_0291: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) try { if (!Plugin.IsHost() || !Team.InLevel()) { return; } pollTimer -= Time.deltaTime; if (pollTimer > 0f) { return; } pollTimer = 0.5f; if (TeamConfig.TeamMilestones.Value && nextMilestone < Thresholds.Length) { Traverse val = Traverse.Create((object)__instance); int value = val.Field<int>("currentHaul").Value; int value2 = val.Field<int>("haulGoal").Value; if (value2 > 0) { int num = Mathf.FloorToInt(100f * (float)value / (float)value2); while (nextMilestone < Thresholds.Length && num >= Thresholds[nextMilestone]) { string text = Messages[nextMilestone]; nextMilestone++; TeamEvents.Broadcast(1, text, Vector3.zero); if (TeamConfig.MilestoneHeal.Value > 0) { foreach (PlayerAvatar item in Plugin.Players()) { if ((Object)(object)item != (Object)null && (Object)(object)item.playerHealth != (Object)null && Team.IsAlive(item)) { item.playerHealth.HealOther(TeamConfig.MilestoneHeal.Value, true); } } } Plugin.Log.LogInfo((object)("Team milestone: " + text)); } } } if (!TeamConfig.ClutchMode.Value || clutchFired) { return; } List<PlayerAvatar> list = Plugin.Players(); if (list.Count < 2) { return; } PlayerAvatar val2 = null; int num2 = 0; foreach (PlayerAvatar item2 in list) { if (Team.IsAlive(item2)) { num2++; val2 = item2; } } if (num2 == 1 && (Object)(object)val2 != (Object)null) { clutchFired = true; if (TeamConfig.ClutchHeal.Value > 0 && (Object)(object)val2.playerHealth != (Object)null) { val2.playerHealth.HealOther(TeamConfig.ClutchHeal.Value, true); } string text2 = "Someone"; try { text2 = SemiFunc.PlayerGetName(val2); } catch { } TeamEvents.Broadcast(2, text2 + " is the last one standing! Everyone's counting on you!", Vector3.zero); Plugin.Log.LogInfo((object)("Clutch mode for " + text2)); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Round poll failed: " + ex.Message)); } } } internal class PingInput : MonoBehaviour { private float cooldown; private static bool warned; private static bool PingPressed() { //IL_01a0: 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) string text = TeamConfig.PingKey.Value ?? string.Empty; try { Mouse current = Mouse.current; if (current != null) { switch (text.ToLowerInvariant()) { case "middlebutton": case "mouse2": return current.middleButton.wasPressedThisFrame; case "leftbutton": case "mouse0": return current.leftButton.wasPressedThisFrame; case "rightbutton": case "mouse1": return current.rightButton.wasPressedThisFrame; case "forwardbutton": case "mouse4": return current.forwardButton.wasPressedThisFrame; case "backbutton": case "mouse3": return current.backButton.wasPressedThisFrame; } } Keyboard current2 = Keyboard.current; if (current2 == null) { return false; } if (!Enum.TryParse<Key>(text, ignoreCase: true, out Key result)) { if (!warned) { warned = true; Plugin.Log.LogWarning((object)("Unknown ping key '" + text + "', using T.")); } result = (Key)34; } return ((ButtonControl)current2[result]).wasPressedThisFrame; } catch (Exception ex) { if (!warned) { warned = true; Plugin.Log.LogWarning((object)("Ping input unavailable: " + ex.Message)); } return false; } } private void Update() { //IL_00ef: 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_0083: 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_0096: 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) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: 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) cooldown -= Time.deltaTime; if (cooldown > 0f || !PingPressed()) { return; } try { if (!SemiFunc.NoTextInputsActive()) { return; } PlayerAvatar val = Team.Local(); Camera main = Camera.main; if (!((Object)(object)val == (Object)null) && !((Object)(object)main == (Object)null) && Team.IsAlive(val)) { Ray val2 = default(Ray); ((Ray)(ref val2))..ctor(((Component)main).transform.position, ((Component)main).transform.forward); Vector3 pos = ((Ray)(ref val2)).origin + ((Ray)(ref val2)).direction * 25f; RaycastHit val3 = default(RaycastHit); if (Physics.Raycast(val2, ref val3, 60f, -1, (QueryTriggerInteraction)1)) { pos = ((RaycastHit)(ref val3)).point; } string text = "Someone"; try { text = SemiFunc.PlayerGetName(val); } catch { } cooldown = 1f; TeamEvents.Broadcast(3, text, pos); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Ping failed: " + ex.Message)); } } } internal static class PingMarker { internal static void Show(Vector3 pos, string who) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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_0043: 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_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Expected O, but got Unknown //IL_00a9: Unknown result type (might be due to invalid IL or missing references) try { GameObject val = GameObject.CreatePrimitive((PrimitiveType)0); ((Object)val).name = "TeamPing"; Object.Destroy((Object)(object)val.GetComponent<Collider>()); val.transform.position = pos + Vector3.up * 0.3f; val.transform.localScale = Vector3.one * 0.35f; Renderer component = val.GetComponent<Renderer>(); Shader val2 = Shader.Find("Universal Render Pipeline/Unlit") ?? Shader.Find("Unlit/Color") ?? Shader.Find("Standard"); if ((Object)(object)val2 != (Object)null) { component.material = new Material(val2); component.material.color = Team.Gold; } Light val3 = val.AddComponent<Light>(); val3.type = (LightType)2; val3.color = Team.Gold; val3.range = 4f; val3.intensity = 3f; val.AddComponent<PingLife>().life = TeamConfig.PingDuration.Value; Team.FocusText(who + " pinged something!", Team.Gold, 2.5f); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Ping marker failed: " + ex.Message)); } } } internal class PingLife : MonoBehaviour { internal float life = 6f; private float t; private Vector3 baseScale; private void Start() { //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) baseScale = ((Component)this).transform.localScale; } private void Update() { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0069: 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) t += Time.deltaTime; float num = 1f + 0.35f * Mathf.Sin(t * 6f); ((Component)this).transform.localScale = baseScale * num; Transform transform = ((Component)this).transform; transform.position += Vector3.up * Mathf.Sin(t * 3f) * 0.002f; if (t >= life) { Object.Destroy((Object)(object)((Component)this).gameObject); } } }