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 Tame Guild Wars v1.0.0
TameGuildWars.dll
Decompiled 14 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using Guilds; using HarmonyLib; using ItemManager; using JetBrains.Annotations; using Microsoft.CodeAnalysis; using ServerSync; using TMPro; using TameGuildWars.Compatibility; using UnityEngine; using UnityEngine.UI; using YamlDotNet.Core; using YamlDotNet.Core.Events; using YamlDotNet.Core.Tokens; using YamlDotNet.Helpers; using YamlDotNet.Serialization; using YamlDotNet.Serialization.BufferedDeserialization; using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators; using YamlDotNet.Serialization.Converters; using YamlDotNet.Serialization.EventEmitters; using YamlDotNet.Serialization.NamingConventions; using YamlDotNet.Serialization.NodeDeserializers; using YamlDotNet.Serialization.NodeTypeResolvers; using YamlDotNet.Serialization.ObjectFactories; using YamlDotNet.Serialization.ObjectGraphTraversalStrategies; using YamlDotNet.Serialization.ObjectGraphVisitors; using YamlDotNet.Serialization.Schemas; using YamlDotNet.Serialization.TypeInspectors; using YamlDotNet.Serialization.TypeResolvers; using YamlDotNet.Serialization.Utilities; using YamlDotNet.Serialization.ValueDeserializers; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("TameGuildWars")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyProduct("TameGuildWars")] [assembly: AssemblyCopyright("Copyright © 2022")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("1327040b-77e8-48df-918a-542534b5ec0f")] [assembly: AssemblyFileVersion("1.0.0")] [assembly: AssemblyCompany("WackyMole")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [<54445620-f45c-49a6-9f02-d5bbf8177ed1>Embedded] internal sealed class <54445620-f45c-49a6-9f02-d5bbf8177ed1>EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] [CompilerGenerated] [<54445620-f45c-49a6-9f02-d5bbf8177ed1>Embedded] internal sealed class <01a73d35-473a-4adb-86fb-c7fd269b4cb1>NullableAttribute : Attribute { public readonly byte[] NullableFlags; public <01a73d35-473a-4adb-86fb-c7fd269b4cb1>NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public <01a73d35-473a-4adb-86fb-c7fd269b4cb1>NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] [<54445620-f45c-49a6-9f02-d5bbf8177ed1>Embedded] [CompilerGenerated] internal sealed class <3caa0b4f-4b82-489f-b8ce-dd36932aef56>NullableContextAttribute : Attribute { public readonly byte Flag; public <3caa0b4f-4b82-489f-b8ce-dd36932aef56>NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace TameGuildWars { [BepInPlugin("WackyMole.TameGuildWars", "TameGuildWars", "1.0.0")] [<01a73d35-473a-4adb-86fb-c7fd269b4cb1>Nullable(0)] [<3caa0b4f-4b82-489f-b8ce-dd36932aef56>NullableContext(1)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class TameGuildWarsPlugin : BaseUnityPlugin { [HarmonyPatch(typeof(ZNet), "Awake")] [<3caa0b4f-4b82-489f-b8ce-dd36932aef56>NullableContext(0)] private static class ZNetAwakePatch { [HarmonyPostfix] private static void Postfix() { Instance?.TryRegisterAllyRpc(); } } [<3caa0b4f-4b82-489f-b8ce-dd36932aef56>NullableContext(0)] public enum Toggle { On = 1, Off = 0 } [<3caa0b4f-4b82-489f-b8ce-dd36932aef56>NullableContext(0)] private class ConfigurationManagerAttributes { [UsedImplicitly] public int? Order; [UsedImplicitly] public bool? Browsable; [<01a73d35-473a-4adb-86fb-c7fd269b4cb1>Nullable(2)] [UsedImplicitly] public string Category; [<01a73d35-473a-4adb-86fb-c7fd269b4cb1>Nullable(new byte[] { 2, 1 })] [UsedImplicitly] public Action<ConfigEntryBase> CustomDrawer; } [<01a73d35-473a-4adb-86fb-c7fd269b4cb1>Nullable(0)] private class AcceptableShortcuts : AcceptableValueBase { public AcceptableShortcuts() : base(typeof(KeyboardShortcut)) { } public override object Clamp(object value) { return value; } public override bool IsValid(object value) { return true; } public override string ToDescriptionString() { return "# Acceptable values: " + string.Join(", ", UnityInput.Current.SupportedKeyCodes); } } private static string _pendingAllyRequesterGuild = string.Empty; private static string _pendingAllyRequestedTarget = string.Empty; private static bool _showAllyRequestPopup; private static GUIStyle _allyPopupTitleStyle; private static GUIStyle _allyPopupLabelStyle; private bool _allyRpcRegistered; private bool _allyRpcRegistrationStarted; internal static TameGuildWarsPlugin Instance; internal const string ModName = "TameGuildWars"; internal const string ModVersion = "1.0.0"; internal const string Author = "WackyMole"; private const string ModGUID = "WackyMole.TameGuildWars"; private static string ConfigFileName = "WackyMole.TameGuildWars.cfg"; private static string ConfigFileFullPath; internal static string ConnectionError; private readonly Harmony _harmony = new Harmony("WackyMole.TameGuildWars"); public static readonly ManualLogSource TameGuildWarsLogger; private static readonly ConfigSync ConfigSync; public static ConfigEntry<float> ConfigObedienceDecayRate; public static ConfigEntry<float> ConfigNonGuildMemberDecayMultiplier; public static ConfigEntry<float> ConfigNoGuildDecayMultiplier; public static ConfigEntry<Toggle> ConfigHostileToNeutrals; public static ConfigEntry<float> ConfigConfusionDurationSeconds; public static ConfigEntry<float> ConfigCommandHornRadius; public static ConfigEntry<string> ConfigCommandHornSound; public static ConfigEntry<float> ConfigConfusionResistanceMinHealth; public static ConfigEntry<float> ConfigConfusionResistanceMaxHealth; public static ConfigEntry<float> ConfigConfusionResistanceMaxValue; public static ConfigEntry<float> ConfigConfusionResistanceLowHealthMultiplier; public static ConfigEntry<float> ConfigConfusionBomb1Min; public static ConfigEntry<float> ConfigConfusionBomb1Max; public static ConfigEntry<float> ConfigConfusionBomb2Min; public static ConfigEntry<float> ConfigConfusionBomb2Max; public static ConfigEntry<float> ConfigConfusionBomb3Min; public static ConfigEntry<float> ConfigConfusionBomb3Max; public static ConfigEntry<Toggle> ConfigAllowBossConfusion; public static ConfigEntry<Toggle> ConfigDeathNotifications; public static ConfigEntry<Toggle> ConfigShowGuildIcon; public static ConfigEntry<float> ConfigGuildIconOffsetX; public static ConfigEntry<float> ConfigGuildIconOffsetY; public static ConfigEntry<float> ConfigAlarmDurationSeconds; public static ConfigEntry<float> ConfigAlarmLeashDistance; public static ConfigEntry<float> ConfigAllyAddCooldownSeconds; public static ConfigEntry<float> ConfigGuardLeashDistance; public static ConfigEntry<float> ConfigSwarmRadius; public static ConfigEntry<float> ConfigSwarmCheckInterval; public static ConfigEntry<Toggle> ConfigMobActionLogging; public static readonly CustomSyncedValue<string> SyncedAllies; private static ConfigEntry<Toggle> _serverConfigLocked; private const string SharedChatInputRpc = "TGW_SendSharedChatInput"; private static readonly FieldInfo ChatInputField; private void OnGUI() { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown //IL_007f: Unknown result type (might be due to invalid IL or missing references) if (_showAllyRequestPopup && !string.IsNullOrEmpty(_pendingAllyRequesterGuild) && !string.IsNullOrEmpty(_pendingAllyRequestedTarget) && !((Object)(object)Player.m_localPlayer == (Object)null)) { EnsureAllyPopupStyles(); Rect val = default(Rect); ((Rect)(ref val))..ctor(((float)Screen.width - 520f) * 0.5f, ((float)Screen.height - 200f) * 0.5f, 520f, 200f); GUI.ModalWindow(938412, val, new WindowFunction(DrawAllyRequestPopupWindow), "Guild Ally Request"); } } private static void EnsureAllyPopupStyles() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_0049: 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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown if (_allyPopupTitleStyle == null) { _allyPopupTitleStyle = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)4, fontSize = 18, fontStyle = (FontStyle)1, wordWrap = true }; } if (_allyPopupLabelStyle == null) { _allyPopupLabelStyle = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)4, fontSize = 14, wordWrap = true }; } } private static void DrawAllyRequestPopupWindow(int windowId) { GUILayout.BeginVertical(Array.Empty<GUILayoutOption>()); GUILayout.Space(12f); GUILayout.Label("Guild '" + _pendingAllyRequesterGuild + "' is requesting an alliance with '" + _pendingAllyRequestedTarget + "'.", _allyPopupTitleStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(54f) }); GUILayout.Space(10f); GUILayout.Label("Accepting will make both sides allied. Denying will reject the request.", _allyPopupLabelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(36f) }); GUILayout.Space(14f); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.FlexibleSpace(); GUI.enabled = ZRoutedRpc.instance != null; if (GUILayout.Button("Accept", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(170f), GUILayout.Height(40f) })) { RespondToPendingAllyRequest(accept: true); } GUILayout.Space(16f); if (GUILayout.Button("Deny", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(170f), GUILayout.Height(40f) })) { RespondToPendingAllyRequest(accept: false); } GUI.enabled = true; GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); GUILayout.Space(8f); GUILayout.EndVertical(); GUI.DragWindow(); } private static void RespondToPendingAllyRequest(bool accept) { if (string.IsNullOrEmpty(_pendingAllyRequesterGuild) || string.IsNullOrEmpty(_pendingAllyRequestedTarget)) { _showAllyRequestPopup = false; return; } if (ZRoutedRpc.instance == null) { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, "Unable to respond right now (network not ready).", 0, (Sprite)null); } return; } string pendingAllyRequesterGuild = _pendingAllyRequesterGuild; string pendingAllyRequestedTarget = _pendingAllyRequestedTarget; TameGuildWarsLogger.LogInfo((object)("Popup ally response: action='" + (accept ? "accept" : "deny") + "', requester='" + pendingAllyRequesterGuild + "', target='" + pendingAllyRequestedTarget + "'.")); ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.instance.GetServerPeerID(), "TGW_RespondAllyRequest", new object[3] { pendingAllyRequesterGuild, pendingAllyRequestedTarget, accept }); _showAllyRequestPopup = false; _pendingAllyRequesterGuild = string.Empty; _pendingAllyRequestedTarget = string.Empty; } private static void ShowAllyRequestPopup(string requesterGuild, string requestedTarget) { _pendingAllyRequesterGuild = requesterGuild ?? string.Empty; _pendingAllyRequestedTarget = requestedTarget ?? string.Empty; _showAllyRequestPopup = !string.IsNullOrEmpty(_pendingAllyRequesterGuild) && !string.IsNullOrEmpty(_pendingAllyRequestedTarget); } private void TryRegisterAllyRpc() { if (!_allyRpcRegistered && ZRoutedRpc.instance != null) { ZRoutedRpc.instance.Register<string, string, bool>("TGW_SetAlly", (Action<long, string, string, bool>)RPC_TGW_SetAlly); ZRoutedRpc.instance.Register<string, string>("TGW_RequestAlly", (Action<long, string, string>)RPC_TGW_RequestAlly); ZRoutedRpc.instance.Register<string, string>("TGW_NotifyAllyRequest", (Action<long, string, string>)RPC_TGW_NotifyAllyRequest); ZRoutedRpc.instance.Register<string, string, bool>("TGW_RespondAllyRequest", (Action<long, string, string, bool>)RPC_TGW_RespondAllyRequest); ZRoutedRpc.instance.Register<string, string, bool>("TGW_NotifyAllyResponse", (Action<long, string, string, bool>)RPC_TGW_NotifyAllyResponse); ZRoutedRpc.instance.Register<string, string>("TGW_BroadcastAllyRemoved", (Action<long, string, string>)RPC_TGW_BroadcastAllyRemoved); ZRoutedRpc.instance.Register<string, string>("TGW_NotifyAllyRemoved", (Action<long, string, string>)RPC_TGW_NotifyAllyRemoved); ZRoutedRpc.instance.Register<string>("TGW_SendSharedChatInput", (Action<long, string>)RPC_TGW_SendSharedChatInput); _allyRpcRegistered = true; ((MonoBehaviour)this).CancelInvoke("TryRegisterAllyRpc"); } } private static void RPC_TGW_SetAlly(long sender, string myGuild, string targetNameOrGuild, bool ally) { if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer()) { TameGuildWarsLogger.LogInfo((object)string.Format("Received TGW_SetAlly RPC from sender {0}: guild='{1}', target='{2}', action='{3}'.", sender, myGuild, targetNameOrGuild, ally ? "add" : "remove")); if (!GuildUtils.TryGetSenderGuild(sender, out var guildName) || string.IsNullOrEmpty(guildName)) { TameGuildWarsLogger.LogWarning((object)$"Unable to resolve guild for ally update sender {sender}; accepting claimed guild '{myGuild}'."); } else if (!string.Equals(guildName, myGuild, StringComparison.Ordinal)) { TameGuildWarsLogger.LogWarning((object)$"Rejected ally update from sender {sender}: claimed guild '{myGuild}' but actual guild was '{guildName}'."); return; } if (GuildUtils.SetAlly(myGuild, targetNameOrGuild, ally)) { TameGuildWarsLogger.LogInfo((object)("Guild '" + myGuild + "' " + (ally ? "added" : "removed") + " ally '" + targetNameOrGuild + "'.")); } else { TameGuildWarsLogger.LogWarning((object)("Guild '" + myGuild + "' failed to " + (ally ? "add" : "remove") + " ally '" + targetNameOrGuild + "' (cooldown or invalid state).")); } } } private static void RPC_TGW_RequestAlly(long sender, string requesterGuild, string requestedTarget) { if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer()) { TameGuildWarsLogger.LogInfo((object)$"Received TGW_RequestAlly RPC from sender {sender}: requester='{requesterGuild}', target='{requestedTarget}'."); if (string.IsNullOrWhiteSpace(requesterGuild) || string.IsNullOrWhiteSpace(requestedTarget)) { TameGuildWarsLogger.LogWarning((object)"Rejected TGW_RequestAlly because requester guild or target was blank."); return; } if (GuildUtils.TryGetSenderGuild(sender, out var guildName) && !string.IsNullOrEmpty(guildName) && !string.Equals(guildName, requesterGuild, StringComparison.Ordinal)) { TameGuildWarsLogger.LogWarning((object)$"Rejected TGW_RequestAlly from sender {sender}: claimed guild '{requesterGuild}' but actual guild was '{guildName}'."); return; } GuildUtils.CreatePendingAllyRequest(requesterGuild, requestedTarget, sender); ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "TGW_NotifyAllyRequest", new object[2] { requesterGuild, requestedTarget }); } } private static void RPC_TGW_NotifyAllyRequest(long sender, string requesterGuild, string requestedTarget) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } foreach (string localPlayerAllyRequestTarget in GuildUtils.GetLocalPlayerAllyRequestTargets(localPlayer)) { if (string.Equals(localPlayerAllyRequestTarget, requestedTarget, StringComparison.OrdinalIgnoreCase)) { GuildUtils.CreatePendingAllyRequest(requesterGuild, requestedTarget, sender); TameGuildWarsLogger.LogInfo((object)("Received ally request prompt for local target '" + requestedTarget + "' from guild '" + requesterGuild + "'.")); ((Character)localPlayer).Message((MessageType)2, "Ally request from " + requesterGuild + ". Use guild_ally accept " + requesterGuild + " " + requestedTarget + " or guild_ally deny " + requesterGuild + " " + requestedTarget, 0, (Sprite)null); ShowAllyRequestPopup(requesterGuild, requestedTarget); break; } } } private static void RPC_TGW_RespondAllyRequest(long sender, string requesterGuild, string requestedTarget, bool accepted) { if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { return; } TameGuildWarsLogger.LogInfo((object)$"Received TGW_RespondAllyRequest RPC from sender {sender}: requester='{requesterGuild}', target='{requestedTarget}', accepted={accepted}."); if (!GuildUtils.TryGetPendingAllyRequest(requesterGuild, requestedTarget, out var _)) { TameGuildWarsLogger.LogWarning((object)("No pending ally request found for requester='" + requesterGuild + "', target='" + requestedTarget + "'.")); ZRoutedRpc.instance.InvokeRoutedRPC(sender, "TGW_NotifyAllyResponse", new object[3] { requesterGuild, requestedTarget, false }); return; } GuildUtils.RemovePendingAllyRequest(requesterGuild, requestedTarget); if (accepted) { bool flag = GuildUtils.SetAlly(requesterGuild, requestedTarget, ally: true); bool flag2 = GuildUtils.SetAlly(requestedTarget, requesterGuild, ally: true); string text = BuildAllianceFormedMessage(requesterGuild, requestedTarget); TameGuildWarsLogger.LogInfo((object)((flag && flag2) ? text : ("Alliance acceptance partially failed between " + requesterGuild + " and " + requestedTarget + "."))); ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "TGW_NotifyAllyResponse", new object[3] { requesterGuild, requestedTarget, flag && flag2 }); if (flag && flag2) { SendSharedChatInput(sender, "/s " + text); } } else { string text2 = "Alliance request from " + requesterGuild + " to " + requestedTarget + " was denied."; TameGuildWarsLogger.LogInfo((object)text2); ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "TGW_NotifyAllyResponse", new object[3] { requesterGuild, requestedTarget, false }); } } private static void RPC_TGW_NotifyAllyResponse(long sender, string requesterGuild, string requestedTarget, bool accepted) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { bool num = GuildUtils.GetLocalPlayerAllyRequestTargets(localPlayer).Any([<3caa0b4f-4b82-489f-b8ce-dd36932aef56>NullableContext(0)] (string target) => string.Equals(target, requestedTarget, StringComparison.OrdinalIgnoreCase) || string.Equals(target, requesterGuild, StringComparison.OrdinalIgnoreCase)); string playerGuildName = GuildUtils.GetPlayerGuildName(localPlayer); if (num || string.Equals(playerGuildName, requesterGuild, StringComparison.OrdinalIgnoreCase)) { string text = (accepted ? ("Alliance formed between " + requesterGuild + " and " + requestedTarget + ".") : ("Alliance request between " + requesterGuild + " and " + requestedTarget + " was denied or failed.")); TameGuildWarsLogger.LogInfo((object)$"Ally response notification: requester='{requesterGuild}', target='{requestedTarget}', accepted={accepted}. Message='{text}'"); ((Character)localPlayer).Message((MessageType)(accepted ? 1 : 2), text, 0, (Sprite)null); } } } private static void RPC_TGW_BroadcastAllyRemoved(long sender, string removerGuild, string removedTarget) { if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && !string.IsNullOrWhiteSpace(removerGuild) && !string.IsNullOrWhiteSpace(removedTarget)) { if (GuildUtils.TryGetSenderGuild(sender, out var guildName) && !string.IsNullOrEmpty(guildName) && !string.Equals(guildName, removerGuild, StringComparison.Ordinal)) { TameGuildWarsLogger.LogWarning((object)$"Rejected TGW_BroadcastAllyRemoved from sender {sender}: claimed guild '{removerGuild}' but actual guild was '{guildName}'."); return; } ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "TGW_NotifyAllyRemoved", new object[2] { removerGuild, removedTarget }); SendSharedChatInput(sender, "/s " + BuildAllianceRemovedMessage(removerGuild, removedTarget)); } } private static void RPC_TGW_NotifyAllyRemoved(long sender, string removerGuild, string removedTarget) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { string playerGuildName = GuildUtils.GetPlayerGuildName(localPlayer); if (string.Equals(playerGuildName, removerGuild, StringComparison.OrdinalIgnoreCase) || string.Equals(playerGuildName, removedTarget, StringComparison.OrdinalIgnoreCase) || string.Equals(localPlayer.GetPlayerName(), removedTarget, StringComparison.OrdinalIgnoreCase)) { string text = BuildAllianceRemovedMessage(removerGuild, removedTarget); ((Character)localPlayer).Message((MessageType)2, text, 0, (Sprite)null); TameGuildWarsLogger.LogInfo((object)("Ally removal notification: remover='" + removerGuild + "', target='" + removedTarget + "'.")); } } } private static string BuildAllianceFormedMessage(string requesterGuild, string requestedTarget) { return "Alliance formed between " + requesterGuild + " and " + requestedTarget + "."; } private static string BuildAllianceRemovedMessage(string removerGuild, string removedTarget) { return "Alliance between " + removerGuild + " and " + removedTarget + " has been removed."; } public void Awake() { Instance = this; ConfigObedienceDecayRate = config("1 - General", "Obedience Decay Rate", 0.1f, "Base Obedience Loss per update tick"); ConfigNonGuildMemberDecayMultiplier = config("1 - General", "Non-Guild Member Decay Multiplier", 3f, "Multiplier applied to obedience decay when near non-guild members"); ConfigNoGuildDecayMultiplier = config("1 - General", "No Guild Decay Multiplier", 5f, "Multiplier applied to obedience decay when the owner has no guild"); ConfigConfusionDurationSeconds = config("1 - General", "Confusion Duration", 120f, "Duration in seconds for maximum (100) confusion to wear off."); ConfigCommandHornRadius = config("1 - General", "Command Horn Radius", 30f, "Radius in meters for tamed guild mobs affected by the command horn."); ConfigCommandHornSound = config("1 - General", "Command Horn Sound", "sfx_viking-horn", "Sound effect played when using the command horn."); ConfigDeathNotifications = config("1 - General", "Death Notifications", Toggle.On, "If On, global notifications will be sent when high-value guild mobs (2+ stars) are killed by a player from another guild."); ConfigShowGuildIcon = config("1 - General", "Show Guild Icon", Toggle.On, "If On, shows the guild's icon image next to the mob's name plate."); ConfigGuildIconOffsetX = config("1 - General", "Guild Icon Offset X", -85f, "Horizontal offset for the guild icon relative to the mob nameplate."); ConfigGuildIconOffsetY = config("1 - General", "Guild Icon Offset Y", 0f, "Vertical offset for the guild icon relative to the mob nameplate."); ConfigHostileToNeutrals = config("3 - Combat", "Hostile To Neutral Players", Toggle.On, "If On, guild mobs will attack players who are not in any guild."); ConfigAlarmDurationSeconds = config("3 - Combat", "Alarm Duration", 30f, "How long a mob remembers the last hostile player before calming down."); ConfigAlarmLeashDistance = config("3 - Combat", "Alarm Leash Distance", 75f, "How far the alarmed player can get from the mob before the alarm is cleared."); ConfigAllyAddCooldownSeconds = config("3 - Combat", "Ally Add Cooldown Seconds", 10f, "Cooldown before adding the same ally target again with guild_ally add."); ConfigGuardLeashDistance = config("3 - Combat", "Guard Leash Distance", 125f, "Maximum distance a mob in Guard stance can move from its stance anchor before returning."); ConfigSwarmRadius = config("3 - Combat", "Swarm Radius", 50f, "Radius in meters for nearby same-guild mobs to join a swarm response."); ConfigSwarmCheckInterval = config("3 - Combat", "Swarm Check Interval", 2f, "How often idle guild mobs scan nearby same-guild mobs for a swarm target. Lower is more responsive; higher is cheaper."); ConfigMobActionLogging = config("4 - Debug", "Mob Action Logging", Toggle.Off, "If On, logs major guild mob actions such as stance changes, alarms, and target swaps.", synchronizedSetting: false); ConfigConfusionResistanceMinHealth = config("2 - Confusion", "Resistance Min Health", 25f, "Max health value where confusion resistance starts scaling."); ConfigConfusionResistanceMaxHealth = config("2 - Confusion", "Resistance Max Health", 1600f, "Max health value where confusion resistance reaches full configured strength (before multiplayer scaling)."); ConfigConfusionResistanceMaxValue = config("2 - Confusion", "Resistance Max Value", 0.9f, "Maximum confusion resistance at or above Resistance Max Health. 0 = none, 1 = full immunity."); ConfigConfusionResistanceLowHealthMultiplier = config("2 - Confusion", "Resistance At 0% Health Multiplier", 0.7f, "How much of baseline resistance remains when the mob is near 0 health. 0 = no resistance when low, 1 = full baseline."); ConfigConfusionBomb1Min = config("2 - Confusion", "Bomb Tier 1 Min", 12f, "Minimum confusion added by tgw_confusionbomb1 before resistance."); ConfigConfusionBomb1Max = config("2 - Confusion", "Bomb Tier 1 Max", 32f, "Maximum confusion added by tgw_confusionbomb1 before resistance."); ConfigConfusionBomb2Min = config("2 - Confusion", "Bomb Tier 2 Min", 24f, "Minimum confusion added by tgw_confusionbomb2 before resistance."); ConfigConfusionBomb2Max = config("2 - Confusion", "Bomb Tier 2 Max", 55f, "Maximum confusion added by tgw_confusionbomb2 before resistance."); ConfigConfusionBomb3Min = config("2 - Confusion", "Bomb Tier 3 Min", 40f, "Minimum confusion added by tgw_confusionbomb3 before resistance."); ConfigConfusionBomb3Max = config("2 - Confusion", "Bomb Tier 3 Max", 85f, "Maximum confusion added by tgw_confusionbomb3 before resistance."); ConfigAllowBossConfusion = config("2 - Confusion", "Allow Boss Confusion", Toggle.Off, "If On, boss-class enemies can be affected by Confusion Bombs. Default: Off (bosses immune). [Synced with Server]"); Item item = new Item("tamebundle", "tgw_confusionbomb1"); item.Name.English("Confusion Bomb I"); item.Description.English("Applies a low confusion amount to tamed mobs in an area."); item.RequiredItems.Add("Resin", 8); item.RequiredItems.Add("Coal", 4); item.RequiredItems.Add("LeatherScraps", 3); item.RequiredItems.Add("Ooze", 2); item.Crafting.Add(CraftingTable.Workbench, 2); item.Configurable = Configurability.Recipe | Configurability.Drop | Configurability.Trader; Item item2 = new Item("tamebundle", "tgw_confusionbomb2"); item2.Name.English("Confusion Bomb II"); item2.Description.English("Applies a medium confusion amount to tamed mobs in an area."); item2.RequiredItems.Add("Resin", 10); item2.RequiredItems.Add("Ooze", 4); item2.RequiredItems.Add("Obsidian", 3); item2.RequiredItems.Add("Crystal", 6); item2.Crafting.Add(CraftingTable.Workbench, 5); item2.Configurable = Configurability.Recipe | Configurability.Drop | Configurability.Trader; Item item3 = new Item("tamebundle", "tgw_confusionbomb3"); item3.Name.English("Confusion Bomb III"); item3.Description.English("Applies a high confusion amount to tamed mobs in an area."); item3.RequiredItems.Add("Resin", 12); item3.RequiredItems.Add("Ooze", 6); item3.RequiredItems.Add("Bilebag", 2); item3.RequiredItems.Add("BlackCore", 1); item3.Crafting.Add(CraftingTable.MageTable, 1); item3.Configurable = Configurability.Recipe | Configurability.Drop | Configurability.Trader; Item item4 = new Item("tamebundle", "tgw_command"); item4.Name.English("Command Horn"); item4.Description.English("Blow to cycle nearby guild tamed mob orders."); item4.RequiredItems.Add("FineWood", 10); item4.RequiredItems.Add("LeatherScraps", 4); item4.RequiredItems.Add("Bronze", 2); item4.Crafting.Add(CraftingTable.Workbench, 3); PrefabManager.RegisterPrefab("tamebundle", "sfx_viking-horn"); item4.Configurable = Configurability.Recipe | Configurability.Drop | Configurability.Trader; Assembly executingAssembly = Assembly.GetExecutingAssembly(); _harmony.PatchAll(executingAssembly); PortablePalsPatches.TryPatch(_harmony); SetupWatcher(); } private void OnDestroy() { ((BaseUnityPlugin)this).Config.Save(); } private void SetupWatcher() { TryRegisterAllyRpc(); if (!_allyRpcRegistered && !_allyRpcRegistrationStarted) { ((MonoBehaviour)this).InvokeRepeating("TryRegisterAllyRpc", 1f, 1f); _allyRpcRegistrationStarted = true; } FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Paths.ConfigPath, ConfigFileName); fileSystemWatcher.Changed += ReadConfigValues; fileSystemWatcher.Created += ReadConfigValues; fileSystemWatcher.Renamed += ReadConfigValues; fileSystemWatcher.IncludeSubdirectories = true; fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject; fileSystemWatcher.EnableRaisingEvents = true; FileSystemWatcher fileSystemWatcher2 = new FileSystemWatcher(Paths.ConfigPath, "TameGuildWarsAllies.txt"); fileSystemWatcher2.Changed += ReadAlliesValues; fileSystemWatcher2.Created += ReadAlliesValues; fileSystemWatcher2.Renamed += ReadAlliesValues; fileSystemWatcher2.IncludeSubdirectories = true; fileSystemWatcher2.SynchronizingObject = ThreadingHelper.SynchronizingObject; fileSystemWatcher2.EnableRaisingEvents = true; ReadAlliesValues(null, null); } private void ReadAlliesValues(object sender, FileSystemEventArgs e) { string path = Path.Combine(Paths.ConfigPath, "TameGuildWarsAllies.txt"); if (!File.Exists(path)) { File.WriteAllText(path, ""); } try { TameGuildWarsLogger.LogDebug((object)"ReadAlliesValues called"); string value = File.ReadAllText(path); SyncedAllies.Value = value; } catch (Exception arg) { TameGuildWarsLogger.LogError((object)$"There was an issue loading your TameGuildWarsAllies.txt\n{arg}"); } } private void ReadConfigValues(object sender, FileSystemEventArgs e) { if (!File.Exists(ConfigFileFullPath)) { return; } try { TameGuildWarsLogger.LogDebug((object)"ReadConfigValues called"); ((BaseUnityPlugin)this).Config.Reload(); } catch { TameGuildWarsLogger.LogError((object)("There was an issue loading your " + ConfigFileName)); TameGuildWarsLogger.LogError((object)"Please check your config entries for spelling and format!"); } } private ConfigEntry<T> config<[<01a73d35-473a-4adb-86fb-c7fd269b4cb1>Nullable(2)] T>(string group, string name, T value, ConfigDescription description, bool synchronizedSetting = true) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown ConfigDescription val = new ConfigDescription(description.Description + (synchronizedSetting ? " [Synced with Server]" : " [Not Synced with Server]"), description.AcceptableValues, description.Tags); ConfigEntry<T> val2 = ((BaseUnityPlugin)this).Config.Bind<T>(group, name, value, val); ConfigSync.AddConfigEntry<T>(val2).SynchronizedConfig = synchronizedSetting; return val2; } private ConfigEntry<T> config<[<01a73d35-473a-4adb-86fb-c7fd269b4cb1>Nullable(2)] T>(string group, string name, T value, string description, bool synchronizedSetting = true) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown return config(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting); } internal static void SendGuildChatInput(string message) { SendChatInput("/g", message); } internal static void SendShoutChatInput(string message) { SendChatInput("/s", message); } private static void SendSharedChatInput(long targetPeerId, string inputText) { if (!string.IsNullOrWhiteSpace(inputText) && ZRoutedRpc.instance != null) { long serverPeerID = ZRoutedRpc.instance.GetServerPeerID(); if (targetPeerId == serverPeerID && (Object)(object)Player.m_localPlayer != (Object)null) { SendRawChatInput(inputText); return; } ZRoutedRpc.instance.InvokeRoutedRPC(targetPeerId, "TGW_SendSharedChatInput", new object[1] { inputText }); } } private static void RPC_TGW_SendSharedChatInput(long sender, string inputText) { SendRawChatInput(inputText); } private static void SendChatInput(string command, string message) { if (!string.IsNullOrWhiteSpace(command) && !string.IsNullOrWhiteSpace(message)) { SendRawChatInput(command + " " + NormalizeChatMessage(message)); } } private static void SendRawChatInput(string inputText) { if ((Object)(object)Chat.instance == (Object)null || string.IsNullOrWhiteSpace(inputText)) { return; } object obj = ChatInputField?.GetValue(Chat.instance); PropertyInfo propertyInfo = obj?.GetType().GetProperty("text", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); string value = (propertyInfo?.GetValue(obj, null) as string) ?? string.Empty; try { if (obj == null || propertyInfo == null || !propertyInfo.CanWrite) { TameGuildWarsLogger.LogWarning((object)"Failed to send shared chat input: Chat.m_input.text was not available."); return; } propertyInfo.SetValue(obj, NormalizeChatMessage(inputText), null); ((Terminal)Chat.instance).InputText(); } catch (Exception ex) { TameGuildWarsLogger.LogWarning((object)("Failed to send shared chat input '" + inputText + "': " + ex.Message)); } finally { if (obj != null && propertyInfo != null && propertyInfo.CanWrite && !string.IsNullOrEmpty(value)) { propertyInfo.SetValue(obj, value, null); } } } private static string NormalizeChatMessage(string message) { return message.Replace('\r', ' ').Replace('\n', ' ').Trim(); } static TameGuildWarsPlugin() { string configPath = Paths.ConfigPath; char directorySeparatorChar = Path.DirectorySeparatorChar; ConfigFileFullPath = configPath + directorySeparatorChar + ConfigFileName; ConnectionError = ""; TameGuildWarsLogger = Logger.CreateLogSource("TameGuildWars"); ConfigSync = new ConfigSync("WackyMole.TameGuildWars") { DisplayName = "TameGuildWars", CurrentVersion = "1.0.0", MinimumRequiredVersion = "1.0.0" }; ConfigObedienceDecayRate = null; ConfigNonGuildMemberDecayMultiplier = null; ConfigNoGuildDecayMultiplier = null; ConfigHostileToNeutrals = null; ConfigConfusionDurationSeconds = null; ConfigCommandHornRadius = null; ConfigCommandHornSound = null; ConfigConfusionResistanceMinHealth = null; ConfigConfusionResistanceMaxHealth = null; ConfigConfusionResistanceMaxValue = null; ConfigConfusionResistanceLowHealthMultiplier = null; ConfigConfusionBomb1Min = null; ConfigConfusionBomb1Max = null; ConfigConfusionBomb2Min = null; ConfigConfusionBomb2Max = null; ConfigConfusionBomb3Min = null; ConfigConfusionBomb3Max = null; ConfigAllowBossConfusion = null; ConfigDeathNotifications = null; ConfigShowGuildIcon = null; ConfigGuildIconOffsetX = null; ConfigGuildIconOffsetY = null; ConfigAlarmDurationSeconds = null; ConfigAlarmLeashDistance = null; ConfigAllyAddCooldownSeconds = null; ConfigGuardLeashDistance = null; ConfigSwarmRadius = null; ConfigSwarmCheckInterval = null; ConfigMobActionLogging = null; SyncedAllies = new CustomSyncedValue<string>(ConfigSync, "TameGuildWarsAllies", ""); _serverConfigLocked = null; ChatInputField = typeof(Chat).GetField("m_input", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } } [<01a73d35-473a-4adb-86fb-c7fd269b4cb1>Nullable(0)] [<3caa0b4f-4b82-489f-b8ce-dd36932aef56>NullableContext(1)] public static class GuildUtils { [<3caa0b4f-4b82-489f-b8ce-dd36932aef56>NullableContext(0)] private struct CachedGuildName { [<01a73d35-473a-4adb-86fb-c7fd269b4cb1>Nullable(1)] public string GuildName; public long CachedAtTicks; } [<01a73d35-473a-4adb-86fb-c7fd269b4cb1>Nullable(0)] public struct PendingAllyRequest { public string RequesterGuild; public string RequestedTarget; public long SenderPeerId; public long ExpiresAtTicks; } private const double PlayerGuildCacheSeconds = 1.0; private const double AllianceBreakGraceSeconds = 10.0; private const double AllyRequestLifetimeSeconds = 60.0; private static readonly Dictionary<string, long> AllianceGraceUntilTicks = new Dictionary<string, long>(); private static readonly Dictionary<string, long> AllyAddCooldownUntilTicks = new Dictionary<string, long>(); private static readonly Dictionary<string, PendingAllyRequest> PendingIncomingAllyRequests = new Dictionary<string, PendingAllyRequest>(); private static readonly Dictionary<long, CachedGuildName> PlayerGuildCache = new Dictionary<long, CachedGuildName>(); public static string GetPlayerGuildName(Player player) { if ((Object)(object)player == (Object)null) { return string.Empty; } long playerID = player.GetPlayerID(); long ticks = DateTime.UtcNow.Ticks; if (playerID != 0L && PlayerGuildCache.TryGetValue(playerID, out var value) && new TimeSpan(ticks - value.CachedAtTicks).TotalSeconds <= 1.0) { return value.GuildName ?? string.Empty; } string text = string.Empty; if (API.IsLoaded()) { Guild playerGuild = API.GetPlayerGuild(player); if (playerGuild != null) { text = playerGuild.Name; } } if (playerID != 0L) { PlayerGuildCache[playerID] = new CachedGuildName { GuildName = text, CachedAtTicks = ticks }; } return text ?? string.Empty; } public static void InvalidatePlayerGuildCache(long playerId = 0L) { if (playerId == 0L) { PlayerGuildCache.Clear(); } else { PlayerGuildCache.Remove(playerId); } } public static bool IsAlly(string myGuild, string targetNameOrGuild) { if (string.IsNullOrEmpty(myGuild) || string.IsNullOrEmpty(targetNameOrGuild)) { return false; } string key = BuildAllyKey(myGuild, targetNameOrGuild); if (TameGuildWarsPlugin.SyncedAllies.Value == null) { return false; } return TameGuildWarsPlugin.SyncedAllies.Value.Split(new char[2] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries).Any([<3caa0b4f-4b82-489f-b8ce-dd36932aef56>NullableContext(0)] (string ally) => string.Equals(ally.Trim(), key, StringComparison.OrdinalIgnoreCase)); } public static bool IsAllianceBreakGraceActive(string myGuild, string targetNameOrGuild) { if (string.IsNullOrEmpty(myGuild) || string.IsNullOrEmpty(targetNameOrGuild)) { return false; } string key = BuildAllyKey(myGuild, targetNameOrGuild); if (!AllianceGraceUntilTicks.TryGetValue(key, out var value)) { return false; } if (DateTime.UtcNow.Ticks <= value) { return true; } AllianceGraceUntilTicks.Remove(key); return false; } public static string BuildPendingAllyRequestKey(string requesterGuild, string requestedTarget) { return requesterGuild.Trim().ToLowerInvariant() + "::" + requestedTarget.Trim().ToLowerInvariant(); } public static PendingAllyRequest CreatePendingAllyRequest(string requesterGuild, string requestedTarget, long senderPeerId) { PendingAllyRequest pendingAllyRequest = new PendingAllyRequest { RequesterGuild = requesterGuild.Trim(), RequestedTarget = requestedTarget.Trim(), SenderPeerId = senderPeerId, ExpiresAtTicks = DateTime.UtcNow.AddSeconds(60.0).Ticks }; PendingIncomingAllyRequests[BuildPendingAllyRequestKey(pendingAllyRequest.RequesterGuild, pendingAllyRequest.RequestedTarget)] = pendingAllyRequest; TameGuildWarsPlugin.TameGuildWarsLogger.LogInfo((object)$"Stored pending ally request: requester='{pendingAllyRequest.RequesterGuild}', target='{pendingAllyRequest.RequestedTarget}', sender={pendingAllyRequest.SenderPeerId}."); return pendingAllyRequest; } public static bool TryGetPendingAllyRequest(string requesterGuild, string requestedTarget, out PendingAllyRequest request) { string key = BuildPendingAllyRequestKey(requesterGuild, requestedTarget); if (!PendingIncomingAllyRequests.TryGetValue(key, out request)) { return false; } if (DateTime.UtcNow.Ticks <= request.ExpiresAtTicks) { return true; } PendingIncomingAllyRequests.Remove(key); request = default(PendingAllyRequest); return false; } public static bool RemovePendingAllyRequest(string requesterGuild, string requestedTarget) { string key = BuildPendingAllyRequestKey(requesterGuild, requestedTarget); bool flag = PendingIncomingAllyRequests.Remove(key); if (flag) { TameGuildWarsPlugin.TameGuildWarsLogger.LogInfo((object)("Removed pending ally request: requester='" + requesterGuild + "', target='" + requestedTarget + "'.")); } return flag; } public static string BuildAllyKey(string myGuild, string targetNameOrGuild) { return ("TGW_Ally_" + myGuild.Trim() + "_" + targetNameOrGuild.Trim()).ToLowerInvariant(); } public static bool TryGetAllyAddCooldownRemaining(string myGuild, string targetNameOrGuild, out double remainingSeconds) { remainingSeconds = 0.0; if (string.IsNullOrEmpty(myGuild) || string.IsNullOrEmpty(targetNameOrGuild)) { return false; } string key = BuildAllyKey(myGuild, targetNameOrGuild); if (!AllyAddCooldownUntilTicks.TryGetValue(key, out var value)) { return false; } remainingSeconds = new TimeSpan(value - DateTime.UtcNow.Ticks).TotalSeconds; if (remainingSeconds > 0.0) { return true; } AllyAddCooldownUntilTicks.Remove(key); remainingSeconds = 0.0; return false; } public static bool SetAlly(string myGuild, string targetNameOrGuild, bool ally) { if (string.IsNullOrEmpty(myGuild) || string.IsNullOrEmpty(targetNameOrGuild)) { return false; } string text = BuildAllyKey(myGuild, targetNameOrGuild); if (ally && TryGetAllyAddCooldownRemaining(myGuild, targetNameOrGuild, out var remainingSeconds)) { TameGuildWarsPlugin.TameGuildWarsLogger.LogInfo((object)$"Rejected ally add for '{text}' due to cooldown ({remainingSeconds:0.0}s remaining)."); return false; } if ((Object)(object)ZNet.instance != (Object)null && !ZNet.instance.IsServer()) { if (ZRoutedRpc.instance == null) { TameGuildWarsPlugin.TameGuildWarsLogger.LogWarning((object)("Unable to " + (ally ? "add" : "remove") + " ally '" + targetNameOrGuild + "' for guild '" + myGuild + "': ZRoutedRpc is not ready.")); return false; } TameGuildWarsPlugin.TameGuildWarsLogger.LogInfo((object)("Dispatching ally " + (ally ? "add" : "remove") + " RPC: guild='" + myGuild + "', target='" + targetNameOrGuild + "', key='" + text + "'.")); ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.instance.GetServerPeerID(), "TGW_SetAlly", new object[3] { myGuild, targetNameOrGuild, ally }); if (ally) { float num = ((TameGuildWarsPlugin.ConfigAllyAddCooldownSeconds != null) ? Mathf.Max(0f, TameGuildWarsPlugin.ConfigAllyAddCooldownSeconds.Value) : 0f); if (num > 0f) { AllyAddCooldownUntilTicks[text] = DateTime.UtcNow.AddSeconds(num).Ticks; } } return true; } TameGuildWarsPlugin.TameGuildWarsLogger.LogInfo((object)("Applying ally " + (ally ? "add" : "remove") + " locally on server: key='" + text + "'.")); InternalSetAlly(text, ally); return true; } public static List<string> ResolveAllyTargets(string targetNameOrGuild) { List<string> list = new List<string>(); if (string.IsNullOrWhiteSpace(targetNameOrGuild)) { return list; } string trimmedTarget = targetNameOrGuild.Trim(); list.Add(trimmedTarget); Player val = Player.GetAllPlayers().Find([<3caa0b4f-4b82-489f-b8ce-dd36932aef56>NullableContext(0)] (Player player) => (Object)(object)player != (Object)null && string.Equals(player.GetPlayerName(), trimmedTarget, StringComparison.OrdinalIgnoreCase)); if ((Object)(object)val == (Object)null) { return list; } string matchedGuild = GetPlayerGuildName(val); if (!string.IsNullOrWhiteSpace(matchedGuild) && !list.Any([<3caa0b4f-4b82-489f-b8ce-dd36932aef56>NullableContext(0)] (string target) => string.Equals(target, matchedGuild, StringComparison.OrdinalIgnoreCase))) { list.Add(matchedGuild); } return list; } public static List<string> GetLocalPlayerAllyRequestTargets(Player player) { List<string> list = new List<string>(); if ((Object)(object)player == (Object)null) { return list; } string playerGuildName = GetPlayerGuildName(player); if (!string.IsNullOrWhiteSpace(playerGuildName)) { list.Add(playerGuildName.Trim()); } string playerName = player.GetPlayerName(); if (!string.IsNullOrWhiteSpace(playerName) && !list.Any([<3caa0b4f-4b82-489f-b8ce-dd36932aef56>NullableContext(0)] (string target) => string.Equals(target, playerName, StringComparison.OrdinalIgnoreCase))) { list.Add(playerName.Trim()); } return list; } public static bool TryGetSenderGuild(long sender, out string guildName) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) guildName = string.Empty; if ((Object)(object)ZNet.instance == (Object)null) { return false; } foreach (PlayerInfo player in ZNet.instance.m_players) { if (TryGetPlayerInfoPeerId(player, out var peerId) && peerId == sender) { guildName = API.GetPlayerGuild(PlayerReference.fromPlayerInfo(player))?.Name ?? string.Empty; return true; } } return false; } private static bool TryGetPlayerInfoPeerId(PlayerInfo playerInfo, out long peerId) { //IL_003a: 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_009b: Unknown result type (might be due to invalid IL or missing references) peerId = 0L; string[] obj = new string[6] { "m_host", "m_hostID", "m_peerID", "m_sender", "m_userID", "m_characterID" }; Type type = ((object)playerInfo).GetType(); string[] array = obj; foreach (string name in array) { FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && TryConvertToLong(field.GetValue(playerInfo), out peerId)) { return true; } PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null && property.CanRead && TryConvertToLong(property.GetValue(playerInfo, null), out peerId)) { return true; } } return false; } private static bool TryConvertToLong(object value, out long result) { result = 0L; if (value == null) { return false; } if (value is long num) { result = num; return true; } if (value is int num2) { result = num2; return true; } if (value is uint num3) { result = num3; return true; } if (value is ulong num4 && num4 <= long.MaxValue) { result = (long)num4; return true; } return long.TryParse(value.ToString(), out result); } public static void InternalSetAlly(string key, bool ally) { string path = Path.Combine(Paths.ConfigPath, "TameGuildWarsAllies.txt"); if (!File.Exists(path)) { File.WriteAllText(path, ""); } List<string> list = (from line in File.ReadAllLines(path) select line.Trim() into line where line.Length > 0 select line).ToList(); int count = list.Count; if (ally) { if (!list.Any([<3caa0b4f-4b82-489f-b8ce-dd36932aef56>NullableContext(0)] (string line) => string.Equals(line, key, StringComparison.OrdinalIgnoreCase))) { list.Add(key); } AllianceGraceUntilTicks[key] = DateTime.UtcNow.AddSeconds(10.0).Ticks; float num = ((TameGuildWarsPlugin.ConfigAllyAddCooldownSeconds != null) ? Mathf.Max(0f, TameGuildWarsPlugin.ConfigAllyAddCooldownSeconds.Value) : 0f); if (num > 0f) { AllyAddCooldownUntilTicks[key] = DateTime.UtcNow.AddSeconds(num).Ticks; } else { AllyAddCooldownUntilTicks.Remove(key); } } else { list.RemoveAll([<3caa0b4f-4b82-489f-b8ce-dd36932aef56>NullableContext(0)] (string line) => string.Equals(line, key, StringComparison.OrdinalIgnoreCase)); AllianceGraceUntilTicks.Remove(key); AllyAddCooldownUntilTicks.Remove(key); } File.WriteAllLines(path, list); TameGuildWarsPlugin.SyncedAllies.Value = string.Join("\n", list); TameGuildWarsPlugin.TameGuildWarsLogger.LogInfo((object)string.Format("InternalSetAlly {0}: key='{1}', before={2}, after={3}.", ally ? "add" : "remove", key, count, list.Count)); } public static List<string> GetAlliesForGuild(string myGuild) { List<string> list = new List<string>(); if (string.IsNullOrEmpty(myGuild)) { return list; } if (TameGuildWarsPlugin.SyncedAllies.Value == null) { return list; } string text = "tgw_ally_" + myGuild.Trim().ToLowerInvariant() + "_"; string[] array = TameGuildWarsPlugin.SyncedAllies.Value.Split(new char[2] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string text2 = array[i].Trim(); if (text2.StartsWith(text, StringComparison.OrdinalIgnoreCase)) { list.Add(text2.Substring(text.Length)); } } return list; } public static Sprite GetGuildIcon(string guildName) { if (string.IsNullOrEmpty(guildName)) { return null; } if (API.IsLoaded()) { Guild guild = API.GetGuild(guildName); if (guild != null) { return API.GetGuildIcon(guild); } } return null; } public static bool API_SetTamedGuildMobData(string payload, Character character) { TamedGuildMob tamedGuildMob = default(TamedGuildMob); if (!((Component)character).TryGetComponent<TamedGuildMob>(ref tamedGuildMob)) { return false; } tamedGuildMob.RestoreMobdata(payload); return true; } public static bool API_CanCaptureCreature(Player player, Character character) { return true; } } public static class KeyboardExtensions { public static bool IsKeyDown(this KeyboardShortcut shortcut) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) if ((int)((KeyboardShortcut)(ref shortcut)).MainKey != 0 && Input.GetKeyDown(((KeyboardShortcut)(ref shortcut)).MainKey)) { return ((KeyboardShortcut)(ref shortcut)).Modifiers.All((Func<KeyCode, bool>)Input.GetKey); } return false; } public static bool IsKeyHeld(this KeyboardShortcut shortcut) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) if ((int)((KeyboardShortcut)(ref shortcut)).MainKey != 0 && Input.GetKey(((KeyboardShortcut)(ref shortcut)).MainKey)) { return ((KeyboardShortcut)(ref shortcut)).Modifiers.All((Func<KeyCode, bool>)Input.GetKey); } return false; } } public enum GuildMobStance { Guard, Stay, GuardWard, Follow, FollowAttack, Static } [<3caa0b4f-4b82-489f-b8ce-dd36932aef56>NullableContext(1)] [<01a73d35-473a-4adb-86fb-c7fd269b4cb1>Nullable(0)] public class TamedGuildMob : MonoBehaviour, Interactable { private static readonly HashSet<TamedGuildMob> ActiveGuildMobs = new HashSet<TamedGuildMob>(); private ZNetView m_nview; private BaseAI m_baseAI; public HitData m_lastHit; private const string ZdoGuildName = "TGW_GuildName"; private const string ZdoTamerId = "TGW_TamerID"; private const string ZdoTamerName = "TGW_TamerName"; private const string ZdoObedience = "TGW_Obedience"; private const string ZdoStance = "TGW_Stance"; private const string ZdoConfusion = "TGW_Confusion"; private const string ZdoAlarmPlayerId = "TGW_AlarmPlayerId"; private const string ZdoAlarmRaisedTicks = "TGW_AlarmRaisedTicks"; private const string ZdoFollowTargetPlayerId = "TGW_FollowTargetPlayerId"; private const string ZdoCommandLock = "TGW_CommandLock"; private const string ZdoSkipDecay = "TGW_SkipDecay"; private readonly float ObedienceRecoverRate = 1f; private readonly float MaxObedience = 100f; private readonly float UpdateInterval = 10f; private readonly float TamerProximityRange = 50f; private readonly float ObedienceDrop = 10f; private readonly float childStartingObedience = 20f; private float _swarmCheckTimer; private Character _rememberedSwarmTarget; private Vector3 _rememberedSwarmTargetLastKnownPos = Vector3.zero; private float _rememberedSwarmTargetUntil; private float _swarmTargetReassertTimer; private float _wardPatrolAngle; private Vector3 _currentWardPatrolPoint = Vector3.zero; private float _wardPatrolStuckTimer; private Vector3 _stanceAnchorPoint = Vector3.zero; private bool _ordersRefreshedForCurrentLoad; private float _stanceUpdateTimer; public MonsterAI MonsterAi { get; private set; } public Character Character { get; private set; } private float GuardMaxDistance => Mathf.Max(0f, TameGuildWarsPlugin.ConfigGuardLeashDistance.Value); private float ObedienceDecayRate => TameGuildWarsPlugin.ConfigObedienceDecayRate.Value; private float SwarmCheckInterval => Mathf.Max(0.1f, TameGuildWarsPlugin.ConfigSwarmCheckInterval.Value); private float SwarmRadius => Mathf.Max(0f, TameGuildWarsPlugin.ConfigSwarmRadius.Value); private bool MobActionLoggingEnabled { get { if (TameGuildWarsPlugin.ConfigMobActionLogging != null) { return TameGuildWarsPlugin.ConfigMobActionLogging.Value == TameGuildWarsPlugin.Toggle.On; } return false; } } public string GuildName { get { if (!((Object)(object)m_nview != (Object)null) || !m_nview.IsValid()) { return ""; } return m_nview.GetZDO().GetString("TGW_GuildName", ""); } private set { if ((Object)(object)m_nview != (Object)null && m_nview.IsValid()) { m_nview.GetZDO().Set("TGW_GuildName", value ?? ""); } } } public long TamerID { get { if (!((Object)(object)m_nview != (Object)null) || !m_nview.IsValid()) { return 0L; } return m_nview.GetZDO().GetLong("TGW_TamerID", 0L); } private set { if ((Object)(object)m_nview != (Object)null && m_nview.IsValid()) { m_nview.GetZDO().Set("TGW_TamerID", value); } } } public string TamerName { get { if (!((Object)(object)m_nview != (Object)null) || !m_nview.IsValid()) { return ""; } return m_nview.GetZDO().GetString("TGW_TamerName", ""); } private set { if ((Object)(object)m_nview != (Object)null && m_nview.IsValid()) { m_nview.GetZDO().Set("TGW_TamerName", value ?? ""); } } } public float Obedience { get { if (!((Object)(object)m_nview != (Object)null) || !m_nview.IsValid()) { return 0f; } return m_nview.GetZDO().GetFloat("TGW_Obedience", 0f); } private set { if ((Object)(object)m_nview != (Object)null && m_nview.IsValid()) { m_nview.GetZDO().Set("TGW_Obedience", Mathf.Clamp(value, 0f, MaxObedience)); } } } public GuildMobStance Stance { get { if (!((Object)(object)m_nview != (Object)null) || !m_nview.IsValid()) { return GuildMobStance.Guard; } return (GuildMobStance)m_nview.GetZDO().GetInt("TGW_Stance", 0); } private set { if ((Object)(object)m_nview != (Object)null && m_nview.IsValid()) { m_nview.GetZDO().Set("TGW_Stance", (int)value); } } } public float Confusion { get { if (!((Object)(object)m_nview != (Object)null) || !m_nview.IsValid()) { return 0f; } return m_nview.GetZDO().GetFloat("TGW_Confusion", 0f); } set { if ((Object)(object)m_nview != (Object)null && m_nview.IsValid()) { m_nview.GetZDO().Set("TGW_Confusion", Mathf.Clamp(value, 0f, 100f)); } } } public long AlarmPlayerId { get { if (!((Object)(object)m_nview != (Object)null) || !m_nview.IsValid()) { return 0L; } return m_nview.GetZDO().GetLong("TGW_AlarmPlayerId", 0L); } set { if ((Object)(object)m_nview != (Object)null && m_nview.IsValid() && m_nview.IsOwner()) { m_nview.GetZDO().Set("TGW_AlarmPlayerId", value); } } } public long AlarmRaisedTicks { get { if (!((Object)(object)m_nview != (Object)null) || !m_nview.IsValid()) { return 0L; } return m_nview.GetZDO().GetLong("TGW_AlarmRaisedTicks", 0L); } private set { if ((Object)(object)m_nview != (Object)null && m_nview.IsValid() && m_nview.IsOwner()) { m_nview.GetZDO().Set("TGW_AlarmRaisedTicks", value); } } } public bool CommandLocked { get { if (!((Object)(object)m_nview != (Object)null) || !m_nview.IsValid()) { return false; } return m_nview.GetZDO().GetBool("TGW_CommandLock", false); } set { if ((Object)(object)m_nview != (Object)null && m_nview.IsValid()) { m_nview.GetZDO().Set("TGW_CommandLock", value); } } } public long FollowTargetPlayerId { get { if (!((Object)(object)m_nview != (Object)null) || !m_nview.IsValid()) { return 0L; } return m_nview.GetZDO().GetLong("TGW_FollowTargetPlayerId", 0L); } private set { if ((Object)(object)m_nview != (Object)null && m_nview.IsValid()) { m_nview.GetZDO().Set("TGW_FollowTargetPlayerId", value); } } } public bool SkipDecay { get { if (!((Object)(object)m_nview != (Object)null) || !m_nview.IsValid()) { return false; } return m_nview.GetZDO().GetBool("TGW_SkipDecay", false); } set { if ((Object)(object)m_nview != (Object)null && m_nview.IsValid()) { m_nview.GetZDO().Set("TGW_SkipDecay", value); } } } private void Awake() { MonsterAi = ((Component)this).GetComponent<MonsterAI>(); m_baseAI = ((Component)this).GetComponent<BaseAI>(); Character = ((Component)this).GetComponent<Character>(); m_nview = ((Component)this).GetComponent<ZNetView>(); _wardPatrolAngle = Random.Range(0f, 360f); m_nview.Register("RPC_ObedienceDrop", (Action<long>)RPC_ObedienceDrop); m_nview.Register<float>("RPC_TGW_AddConfusion", (Action<long, float>)RPC_AddConfusion); if ((Object)(object)m_nview != (Object)null && m_nview.IsValid()) { ((MonoBehaviour)this).InvokeRepeating("UpdateObedience", Random.Range(1f, 5f), UpdateInterval); ((MonoBehaviour)this).InvokeRepeating("UpdateConfusion", Random.Range(1f, 5f), 2f); } } private void OnEnable() { ActiveGuildMobs.Add(this); _ordersRefreshedForCurrentLoad = false; ((MonoBehaviour)this).Invoke("RefreshOrdersForLoadedArea", 0.25f); } private void OnDisable() { ActiveGuildMobs.Remove(this); ((MonoBehaviour)this).CancelInvoke("RefreshOrdersForLoadedArea"); } public void RaiseAlarm(Character attacker) { if (!(Obedience <= 0f) && !((Object)(object)attacker == (Object)null) && !((Object)(object)attacker == (Object)(object)Character) && !((Object)(object)m_nview == (Object)null) && m_nview.IsValid() && m_nview.IsOwner()) { Player val = (Player)(object)((attacker is Player) ? attacker : null); bool num = (Object)(object)val != (Object)null; long num2 = (num ? val.GetPlayerID() : 0); long alarmPlayerId = AlarmPlayerId; long alarmRaisedTicks = AlarmRaisedTicks; long ticks = DateTime.UtcNow.Ticks; if (num) { AlarmPlayerId = num2; AlarmRaisedTicks = ticks; } LogMobAction("alarm raised on " + DescribeCharacter(attacker)); TryApplySwarmTarget(attacker, num2, ticks, "alarm"); if (!num || alarmPlayerId != num2 || alarmRaisedTicks == 0L || new TimeSpan(ticks - alarmRaisedTicks).TotalSeconds >= 1.0) { BroadcastSwarmAlarm(attacker, num2, ticks); } } } public void ClearAlarm() { if (!((Object)(object)m_nview == (Object)null) && m_nview.IsValid() && m_nview.IsOwner()) { bool num = AlarmPlayerId != 0L || AlarmRaisedTicks != 0; AlarmPlayerId = 0L; AlarmRaisedTicks = 0L; if (num) { LogMobAction("alarm cleared"); } } } private void BroadcastSwarmAlarm(Character attacker, long attackerPlayerId, long alarmTicks) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)attacker == (Object)null || attacker.IsDead() || string.IsNullOrEmpty(GuildName)) { return; } float num = SwarmRadius * SwarmRadius; Vector3 position = ((Component)this).transform.position; foreach (TamedGuildMob activeGuildMob in ActiveGuildMobs) { if (!((Object)(object)activeGuildMob == (Object)null) && !((Object)(object)activeGuildMob == (Object)(object)this) && !((Object)(object)activeGuildMob.Character == (Object)null) && activeGuildMob.IsSameGuild(GuildName)) { Vector3 val = ((Component)activeGuildMob).transform.position - position; if (!(((Vector3)(ref val)).sqrMagnitude > num)) { activeGuildMob.TryApplySwarmTarget(attacker, attackerPlayerId, alarmTicks, "broadcast swarm"); } } } } private bool TryApplySwarmTarget(Character target, long alarmPlayerId, long alarmTicks, string source) { if ((Object)(object)target == (Object)null || target.IsDead()) { return false; } if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid() || !m_nview.IsOwner()) { return false; } if ((Object)(object)MonsterAi == (Object)null || (Object)(object)Character == (Object)null || Character.IsDead()) { return false; } if (string.IsNullOrEmpty(GuildName) || Obedience <= 0f) { return false; } if (Stance == GuildMobStance.Stay || Stance == GuildMobStance.Follow) { return false; } if (target.IsPlayer()) { Player val = (Player)(object)((target is Player) ? target : null); if ((Object)(object)val == (Object)null || val.GetPlayerID() != alarmPlayerId || TargetingPatches.IsPlayerGhost(val)) { return false; } AlarmPlayerId = alarmPlayerId; AlarmRaisedTicks = alarmTicks; } Character targetCreature = ((BaseAI)MonsterAi).GetTargetCreature(); if (!ShouldPrioritizeSwarmTarget(targetCreature, target, alarmPlayerId)) { return false; } ForceCombatTarget(target); Character targetCreature2 = ((BaseAI)MonsterAi).GetTargetCreature(); if ((Object)(object)targetCreature2 == (Object)(object)target && (Object)(object)targetCreature != (Object)(object)target) { RememberSwarmTarget(target); LogMobAction(source + ": targeting " + DescribeCharacter(target) + (((Object)(object)targetCreature != (Object)null) ? (" instead of " + DescribeCharacter(targetCreature)) : string.Empty)); } else if ((Object)(object)targetCreature2 != (Object)(object)target) { LogMobAction(source + ": failed to hold target " + DescribeCharacter(target)); } return (Object)(object)targetCreature2 == (Object)(object)target; } private void RememberSwarmTarget(Character target) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)target == (Object)null || target.IsDead()) { ClearRememberedSwarmTarget(); return; } _rememberedSwarmTarget = target; _rememberedSwarmTargetLastKnownPos = ((Component)target).transform.position; _rememberedSwarmTargetUntil = Time.time + Mathf.Max(5f, TameGuildWarsPlugin.ConfigAlarmDurationSeconds.Value); } private void ClearTargetAndAlert(bool alerted) { if (!((Object)(object)MonsterAi == (Object)null)) { Traverse.Create((object)MonsterAi).Field("m_targetCreature").SetValue((object)null); ((BaseAI)MonsterAi).SetAlerted(alerted); ClearRememberedSwarmTarget(); } } private void ClearRememberedSwarmTarget() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) _rememberedSwarmTarget = null; _rememberedSwarmTargetLastKnownPos = Vector3.zero; _rememberedSwarmTargetUntil = 0f; _swarmTargetReassertTimer = 0f; } public void ClearGhostAggro() { ClearAlarm(); ClearTargetAndAlert(alerted: false); } private bool HasRememberedSwarmTarget() { if ((Object)(object)_rememberedSwarmTarget != (Object)null) { return Time.time <= _rememberedSwarmTargetUntil; } return false; } private void RefreshRememberedSwarmTargetPosition() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_rememberedSwarmTarget != (Object)null && !_rememberedSwarmTarget.IsDead()) { _rememberedSwarmTargetLastKnownPos = ((Component)_rememberedSwarmTarget).transform.position; } } private void ApplyRememberedSwarmChaseState() { //IL_0037: 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) if (!((Object)(object)MonsterAi == (Object)null)) { RefreshRememberedSwarmTargetPosition(); ((BaseAI)MonsterAi).SetAlerted(true); Traverse.Create((object)MonsterAi).Field("m_lastKnownTargetPos").SetValue((object)_rememberedSwarmTargetLastKnownPos); ((BaseAI)MonsterAi).SetPatrolPoint(_rememberedSwarmTargetLastKnownPos); } } private void MaintainRememberedSwarmTarget(float dt) { if ((Object)(object)_rememberedSwarmTarget == (Object)null) { return; } if (_rememberedSwarmTarget.IsPlayer() && TargetingPatches.IsPlayerGhost((Player)/*isinst with value type is only supported in some contexts*/)) { ClearRememberedSwarmTarget(); return; } if (_rememberedSwarmTarget.IsDead() || Time.time > _rememberedSwarmTargetUntil) { LogMobAction("forgot swarm target " + DescribeCharacter(_rememberedSwarmTarget)); ClearRememberedSwarmTarget(); return; } if ((Object)(object)MonsterAi == (Object)null || (Object)(object)Character == (Object)null || Character.IsDead() || Obedience <= 0f || Stance == GuildMobStance.Stay || Stance == GuildMobStance.Follow) { ClearRememberedSwarmTarget(); return; } ApplyRememberedSwarmChaseState(); if (!((Object)(object)((BaseAI)MonsterAi).GetTargetCreature() == (Object)(object)_rememberedSwarmTarget)) { _swarmTargetReassertTimer += dt; if (!(_swarmTargetReassertTimer < 0.5f)) { _swarmTargetReassertTimer = 0f; LogMobAction("reasserting swarm target " + DescribeCharacter(_rememberedSwarmTarget) + " after AI cleared target"); ForceCombatTarget(_rememberedSwarmTarget); ApplyRememberedSwarmChaseState(); } } } private void ForceCombatTarget(Character target) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) Traverse obj = Traverse.Create((object)MonsterAi); ((BaseAI)MonsterAi).SetAlerted(true); MonsterAi.SetTarget(target); obj.Field("m_targetCreature").SetValue((object)target); obj.Field("m_lastKnownTargetPos").SetValue((object)((Component)target).transform.position); } private void LogMobAction(string action) { if (MobActionLoggingEnabled) { TameGuildWarsPlugin.TameGuildWarsLogger.LogInfo((object)("[GuildMob:" + (Character?.m_name ?? ((Object)this).name) + "] " + action)); } } public string GetDebugHoverText() { if (!MobActionLoggingEnabled) { return string.Empty; } List<string> list = new List<string>(); Character val = (((Object)(object)MonsterAi != (Object)null) ? ((BaseAI)MonsterAi).GetTargetCreature() : null); if ((Object)(object)val != (Object)null && !val.IsDead()) { list.Add("Target: " + DescribeCharacter(val)); } else { list.Add("Target: none"); } if (AlarmPlayerId != 0L) { Player player = Player.GetPlayer(AlarmPlayerId); list.Add("Alarm: " + (((Object)(object)player != (Object)null) ? player.GetPlayerName() : AlarmPlayerId.ToString())); } list.Add($"Stance: {Stance}"); if (HasRememberedSwarmTarget()) { list.Add("Remembered: " + DescribeCharacter(_rememberedSwarmTarget)); } GameObject val2 = (((Object)(object)MonsterAi != (Object)null) ? MonsterAi.GetFollowTarget() : null); string text = ((Stance == GuildMobStance.Follow || Stance == GuildMobStance.FollowAttack) ? string.Empty : " (non-follow)"); list.Add("Follow: " + (((Object)(object)val2 != (Object)null) ? ((Object)val2).name : "none") + text); return "\n<color=orange>Debug:</color> " + string.Join(" | ", list); } private static string DescribeCharacter(Character character) { if ((Object)(object)character == (Object)null) { return "none"; } string text = ((!string.IsNullOrEmpty(character.m_name)) ? character.m_name : ((Object)character).name); if (!character.IsPlayer()) { return text; } return "player " + text; } private bool ShouldPrioritizeSwarmTarget(Character currentTarget, Character swarmTarget, long swarmAlarmPlayerId) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_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_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)swarmTarget == (Object)null || swarmTarget.IsDead()) { return false; } if ((Object)(object)currentTarget == (Object)null || currentTarget.IsDead() || (Object)(object)currentTarget == (Object)(object)swarmTarget) { return true; } bool flag = IsAlarmedPlayerTarget(swarmTarget, swarmAlarmPlayerId); bool flag2 = IsAlarmedPlayerTarget(currentTarget, AlarmPlayerId); if (flag != flag2) { return flag; } Vector3 val = ((Component)currentTarget).transform.position - ((Component)this).transform.position; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; val = ((Component)swarmTarget).transform.position - ((Component)this).transform.position; return ((Vector3)(ref val)).sqrMagnitude + 16f < sqrMagnitude; } private static bool IsAlarmedPlayerTarget(Character target, long alarmPlayerId) { if (alarmPlayerId == 0L || (Object)(object)target == (Object)null || !target.IsPlayer()) { return false; } Player val = (Player)(object)((target is Player) ? target : null); if ((Object)(object)val != (Object)null) { return val.GetPlayerID() == alarmPlayerId; } return false; } public void CycleStance(Player player) { int newStance = (int)(Stance + 1) % 6; SetStance((GuildMobStance)newStance, player); } public void ToggleCommandLock(Player player) { CommandLocked = !CommandLocked; ((Character)player).Message((MessageType)2, Character.m_name + " command lock: " + (CommandLocked ? "On" : "Off"), 0, (Sprite)null); if ((Object)(object)m_nview != (Object)null && m_nview.IsValid() && !m_nview.IsOwner()) { m_nview.ClaimOwnership(); } } public void ToggleSkipDecay(Player player) { SkipDecay = !SkipDecay; ((Character)player).Message((MessageType)2, Character.m_name + " skip obedience decay: " + (SkipDecay ? "On" : "Off"), 0, (Sprite)null); if ((Object)(object)m_nview != (Object)null && m_nview.IsValid() && !m_nview.IsOwner()) { m_nview.ClaimOwnership(); } } public bool SetStance(GuildMobStance newStance, Player player = null, bool notifyPlayer = true) { //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player != (Object)null) { if (Obedience <= 0f) { if (notifyPlayer) { ((Character)player).Message((MessageType)2, Character.m_name + " will not obey new orders.", 0, (Sprite)null); } return false; } if (CommandLocked) { if (notifyPlayer) { ((Character)player).Message((MessageType)2, Character.m_name + " command is locked!", 0, (Sprite)null); } return false; } } Stance = newStance; if ((Object)(object)player != (Object)null && notifyPlayer) { ((Character)player).Message((MessageType)2, $"{Character.m_name} order: {newStance}", 0, (Sprite)null); } string arg = (((Object)(object)player != (Object)null) ? player.GetPlayerName() : "system"); LogMobAction($"stance changed to {newStance} by {arg}"); if ((Object)(object)m_nview != (Object)null && m_nview.IsValid() && !m_nview.IsOwner()) { m_nview.ClaimOwnership(); } switch (newStance) { case GuildMobStance.Guard: case GuildMobStance.Stay: case GuildMobStance.Static: _stanceAnchorPoint = ((Component)this).transform.position; FollowTargetPlayerId = 0L; ClearNonFollowOrders(_stanceAnchorPoint, newStance == GuildMobStance.Stay || newStance == GuildMobStance.Static); ((BaseAI)MonsterAi).SetPatrolPoint(_stanceAnchorPoint); break; case GuildMobStance.GuardWard: FollowTargetPlayerId = 0L; ClearNonFollowOrders(((Component)this).transform.position, clearCombatState: false); break; case GuildMobStance.Follow: case GuildMobStance.FollowAttack: { Player val = player ?? Player.m_localPlayer; FollowTargetPlayerId = (((Object)(object)val != (Object)null) ? val.GetPlayerID() : TamerID); SetVanillaTameableFollowState(val); if ((Object)(object)player != (Object)null) { MonsterAi.SetFollowTarget(((Component)player).gameObject); ((BaseAI)MonsterAi).ResetPatrolPoint(); break; } MonsterAI monsterAi = MonsterAi; Player localPlayer = Player.m_localPlayer; monsterAi.SetFollowTarget((localPlayer != null) ? ((Component)localPlayer).gameObject : null); ((BaseAI)MonsterAi).ResetPatrolPoint(); break; } } return true; } private void EnsureStanceAnchor() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (_stanceAnchorPoint == Vector3.zero) { _stanceAnchorPoint = ((Component)this).transform.position; } } private void EnforceStanceLeash(float maxDistance, bool clearCombatTarget) { //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_0022: Unknown result type (might be due to invalid IL or missing references) EnsureStanceAnchor(); if (!(Vector3.Distance(((Component)this).transform.position, _stanceAnchorPoint) <= maxDistance)) { ClearNonFollowOrders(_stanceAnchorPoint, clearCombatState: false); if (clearCombatTarget && !((Object)(object)((BaseAI)MonsterAi).GetTargetCreature() == (Object)null)) { Traverse.Create((object)MonsterAi).Field("m_targetCreature").SetValue((object)null); Traverse.Create((object)MonsterAi).Method("SetAlerted", new object[1] { false }).GetValue(); } } } private void RefreshFollowTarget() { long num = FollowTargetPlayerId; if (num == 0L) { num = TamerID; if (num != 0L) { FollowTargetPlayerId = num; } } if (num == 0L) { ClearVanillaTameableFollowState(); MonsterAi.SetFollowTarget((GameObject)null); return; } Player player = Player.GetPlayer(num); if ((Object)(object)player == (Object)null) { MonsterAi.SetFollowTarget((GameObject)null); return; } SetVanillaTameableFollowState(player); if ((Object)(object)MonsterAi.GetFollowTarget() != (Object)(object)((Component)player).gameObject) { MonsterAi.SetFollowTarget(((Component)player).gameObject); ((BaseAI)MonsterAi).ResetPatrolPoint(); } } private void ClearNonFollowOrders(Vector3 patrolPoint, bool clearCombatState) { //IL_0068: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)MonsterAi == (Object)null)) { GameObject followTarget = MonsterAi.GetFollowTarget(); if ((Object)(object)followTarget != (Object)null) { LogMobAction($"clearing stale follow target {((Object)followTarget).name} for stance {Stance}"); } ClearVanillaTameableFollowState(); MonsterAi.SetFollowTarget((GameObject)null); ((BaseAI)MonsterAi).ResetPatrolPoint(); ((BaseAI)MonsterAi).SetPatrolPoint(patrolPoint); if (clearCombatState) { ClearAlarm(); ClearRememberedSwarmTarget(); ClearTargetAndAlert(alerted: false); } } } private void ClearVanillaTameableFollowState() { SetVanillaTameableFollowState(null); } private void SetVanillaTameableFollowState(Player followPlayer) { if (!((Object)(object)m_nview == (Object)null) && m_nview.IsValid()) { ZDO zDO = m_nview.GetZDO(); if (zDO != null) { zDO.Set(ZDOVars.s_follow, ((Object)(object)followPlayer != (Object)null) ? followPlayer.GetPlayerName() : string.Empty); } } } private void RefreshOrdersForLoadedArea() { //IL_0076: 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_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) if (_ordersRefreshedForCurrentLoad || (Object)(object)m_nview == (Object)null || !m_nview.IsValid() || !m_nview.IsOwner() || (Object)(object)MonsterAi == (Object)null || (Object)(object)Character == (Object)null || !Character.IsTamed()) { return; } _ordersRefreshedForCurrentLoad = true; if (Obedience <= 0f) { ClearNonFollowOrders(((Component)this).transform.position, clearCombatState: true); LogMobAction("refreshed loaded orders: no obedience"); return; } switch (Stance) { case GuildMobStance.Guard: EnsureStanceAnchor(); ClearRememberedSwarmTarget(); ClearNonFollowOrders(_stanceAnchorPoint, clearCombatState: false); break; case GuildMobStance.Stay: case GuildMobStance.Static: _stanceAnchorPoint = ((Component)this).transform.position; ClearNonFollowOrders(_stanceAnchorPoint, clearCombatState: true); break; case GuildMobStance.GuardWard: ClearRememberedSwarmTarget(); ClearNonFollowOrders(((Component)this).transform.position, clearCombatState: false); break; case GuildMobStance.Follow: case GuildMobStance.FollowAttack: RefreshFollowTarget(); break; } LogMobAction($"refreshed loaded orders for stance {Stance}"); } public bool TryClaim(Player player, string guildName) { long playerID = player.GetPlayerID(); if ((TamerID == 0L || Obedience <= 0f || TamerID == playerID) && guildName != "No Guild") { TamerID = playerID; TamerName = player.GetPlayerName(); GuildName = guildName; Obedience = MaxObedience; ClearAlarm(); ClearTargetAndAlert(alerted: false); if (!Object.op_Implicit((Object)(object)((Component)this).gameObject.GetComponent<MonsterAI>())) { return true; } SetStance(GuildMobStance.Guard); return true; } return false; } public bool TryChangeTamer(Player player) { long playerID = player.GetPlayerID(); if (Obedience <= 0f && TamerID != playerID) { TamerID = playerID; TamerName = player.GetPlayerName(); ClearAlarm(); ClearTargetAndAlert(alerted: false); return true; } return false; } public bool TryChangeGuild(Player player, string newGuildName) { if (TamerID == player.GetPlayerID() && Obedience > 0f) { GuildName = newGuildName; ClearAlarm(); ClearTargetAndAlert(alerted: false); return true; } return false; } public bool IsSameGuild(string otherGuildName) { string guildName = GuildName; if (string.IsNullOrEmpty(guildName) || string.IsNullOrEmpty(otherGuildName)) { return false; } return guildName == otherGuildName; } private void UpdateObedience() { //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid() || !m_nview.IsOwner() || SkipDecay) { return; } long tamerID = TamerID; bool flag = tamerID == 0; float obedience = Obedience; if (flag && obedience <= 0f) { return; } bool flag2 = false; Player val = null; string text = string.Empty; if (!flag) { val = Player.GetPlayer(tamerID); if ((Object)(object)val != (Object)null) { text = GuildUtils.GetPlayerGuildName(val); if (Vector3.Distance(((Component)this).transform.position, ((Component)val).transform.position) <= TamerProximityRange) { flag2 = true; } } } if (flag2) { if (obedience < MaxObedience) { Obedience = obedience + ObedienceRecoverRate; } return; } float num = ObedienceDecayRate; bool flag3 = false; bool flag4 = false; if (!flag) { foreach (Player allPlayer in Player.GetAllPlayers()) { if (Vector3.Distance(((Component)this).transform.position, ((Component)allPlayer).transform.position) <= TamerProximityRange) { string playerGuildName = GuildUtils.GetPlayerGuildName(allPlayer); if (!string.IsNullOrEmpty(playerGuildName) && playerGuildName == GuildName && playerGuildName != "No Guild") { flag3 = true; } else { flag4 = true; } } } } if (flag4 && !flag3) { num *= TameGuildWarsPlugin.ConfigNonGuildMemberDecayMultiplier.Value; } int num2; int num3; if (!string.IsNullOrEmpty(text)) { num2 = ((text == "No Guild") ? 1 : 0); if (num2 == 0 && !string.IsNullOrEmpty(GuildName)) { num3 = ((text != GuildName) ? 1 : 0); goto IL_01ae; } } else { num2 = 1; } num3 = 0; goto IL_01ae; IL_01ae: bool flag5 = (byte)num3 != 0; if (((uint)num2 | (flag5 ? 1u : 0u)) != 0) { num *= TameGuildWarsPlugin.ConfigNoGuildDecayMultiplier.Value; } float num4 = obedience - num; if (num4 <= 0f) { Obedience = 0f; ClearAlarm(); TameGuildWarsPlugin.TameGuildWarsLogger.LogInfo((object)$"Mob {Character.m_name} lost obedience to tamer {tamerID} and reverted to neutral."); } else { Obedience = num4; } } private void RPC_ObedienceDrop(long uid) { if (!((Object)(object)m_nview == (Object)null) && m_nview.IsValid() && m_nview.IsOwner() && !string.IsNullOrEmpty(GuildName) && !(Obedience <= 0f)) { if (Obedience <= ObedienceDrop) { Obedience = 0f; } Obedience -= ObedienceDrop; } } private void RPC_AddConfusion(long uid, float amount) { if (!((Object)(object)m_nview == (Object)null) && m_nview.IsValid() && m_nview.IsOwner() && !(amount <= 0f)) { Confusion = Mathf.Clamp(Confusion + amount, 0f, 100f); } } private void UpdateConfusion() { if (!((Object)(object)m_nview != (Object)null) || !m_nview.IsValid() || !m_nview.IsOwner()) { return; } float confusion = Confusion; if (!(confusion > 0f)) { return; } float num = TameGuildWarsPlugin.ConfigConfusionDurationSeconds.Value; if (num <= 0f) { num = 1f; } Confusion = Mathf.Max(0f, confusion - 100f / num * 2f); if (Confusion > 50f) { ClearAlarm(); if (Random.value < 0.3f) { List<Character> list = Character.GetAllCharacters().FindAll(IsValidConfusionTarget); if (list.Count > 0) { Character val = list[Random.Range(0, list.Count)]; ForceCombatTarget(val); LogMobAction("confused: targeting " + DescribeCharacter(val)); } else if (Random.value < 0.5f) { ClearTargetAndAlert(alerted: true); } } } else if ((Object)(object)MonsterAi != (Object)null && (Object)(object)((BaseAI)MonsterAi).GetTargetCreature() != (Object)null && AlarmPlayerId != 0L) { ClearAlarm(); } } private bool IsValidConfusionTarget(Character candidate) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)candidate == (Object)null || (Object)(object)candidate == (Object)(object)Character || candidate.IsDead()) { return false; } Vector3 val = ((Component)candidate).transform.position - ((Component)this).transform.position; if (((Vector3)(ref val)).sqrMagnitude > 900f) { return false; } if (candidate.IsPlayer() && TargetingPatches.IsPlayerGhost((Player)(object)((candidate is Player) ? candidate : null))) { return false; } return true; } public void UpdateSwarmAggro(float dt) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) MaintainRememberedSwarmTarget(dt); if (string.IsNullOrEmpty(GuildName) || Obedience <= 0f || Stance == GuildMobStance.Stay || Stance == GuildMobStance.Follow) { return; } _swarmCheckTimer += dt; if (_swarmCheckTimer < SwarmCheckInterval) { return; } _swarmCheckTimer = 0f; float num = SwarmRadius * SwarmRadius; Vector3 position = ((Component)this).transform.position; foreach (TamedGuildMob activeGuildMob in ActiveGuildMobs) { if ((Object)(object)activeGuildMob == (Object)null || (Object)(object)activeGuildMob == (Object)(object)this || (Object)(object)activeGuildMob.Character == (Object)null || (Object)(object)activeGuildMob.MonsterAi == (Object)null || !activeGuildMob.IsSameGuild(GuildName)) { continue; } Vector3 val = ((Component)activeGuildMob).transform.position - position; if (((Vector3)(ref val)).sqrMagnitude > num) { continue; } Character targetCreature = ((BaseAI)activeGuildMob.MonsterAi).GetTargetCreature(); if (!((Object)(object)targetCreature != (Object)null) || targetCreature.IsDead()) { continue; } bool flag = false; if (targetCreature.IsPlayer()) { Player val2 = (Player)(object)((targetCreature is Player) ? targetCreature : null); if ((Object)(object)val2 != (Object)null && activeGuildMob.AlarmPlayerId == val2.GetPlayerID()) { flag = true; } } else { flag = true; } if (flag) { TryApplySwarmTarget(targetCreature, activeGuildMob.AlarmPlayerId, activeGuildMob.AlarmRaisedTicks, "fallback swarm"); break; } } } public void UpdateStanceBehavior(float dt) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_02df: Unknown result type (might be due to invalid IL or missing references) //IL_035e: Unknown result type (might be due to invalid IL or missing references) //IL_0363: Unknown result type (might be due to invalid IL or missing references) //IL_037d: Unknown result type (might be due to invalid IL or missing references) //IL_0370: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_02c4: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: 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_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Unknown result type (might be due to invalid IL or missing references) //IL_0286: Unknown result type (might be due to invalid IL or missing references) RefreshOrdersForLoadedArea(); _stanceUpdateTimer += dt; if (_stanceUpdateTimer < 2f) { return; } _stanceUpdateTimer = 0f; UpdateAlarmState(); Character targetCreature = ((BaseAI)MonsterAi).GetTargetCreature(); if ((Object)(object)targetCreature != (Object)null && !((BaseAI)MonsterAi).IsEnemy(targetCreature)) { ClearAlarm(); ClearTargetAndAlert(alerted: false); } if (Obedience <= 0f) { ClearNonFollowOrders(((Component)this).transform.position, clearCombatState: true); if ((Object)(object)((BaseAI)MonsterAi).GetTargetCreature() != (Object)null) { Traverse.Create((object)MonsterAi).Field("m_targetCreature").SetValue((object)null); Traverse.Create((object)MonsterAi).Method("SetAlerted", new object[1] { false }).GetValue(); } } else if (HasRememberedSwarmTarget()) { ApplyRememberedSwarmChaseState(); } else if (Stance == GuildMobStance.GuardWard) { ClearNonFollowOrders(((Component)this).transform.position, clearCombatState: false); if ((Object)(object)((BaseAI)MonsterAi).GetTargetCreature() != (Object)null) { return; } PrivateArea val = null; float num = float.MaxValue; foreach (PrivateArea allArea in PrivateArea.m_allAreas) { if (allArea.IsEnabled()) { float num2 = Vector3.Distance(((Component)this).transform.position, ((Component)allArea).transform.position); if (num2 < num) { num = num2; val = allArea; } } } if ((Object)(object)val != (Object)null) { float radius = val.m_radius; float num3 = Vector3.Distance(((Component)this).transform.position, _currentWardPatrolPoint); _wardPatrolStuckTimer += dt; if (_currentWardPatrolPoint == Vector3.zero || num3 < 6f || _wardPatrolStuckTimer > 20f) { _wardPatrolStuckTimer = 0f; _wardPatrolAngle += Random.Range(30f, 60f); if (_wardPatrolAngle >= 360f) { _wardPatrolAngle -= 360f; } float num4 = _wardPatrolAngle * ((float)Math.PI / 180f); _currentWardPatrolPoint = ((Component)val).transform.position + new Vector3(Mathf.Cos(num4) * radius, 0f, Mathf.Sin(num4) * radius); float y = default(float); if ((Object)(object)ZoneSystem.instance != (Object)null && ZoneSystem.instance.GetSolidHeight(_currentWardPatrolPoint, ref y, 1000)) { _currentWardPatrolPoint.y = y; } } ((BaseAI)MonsterAi).SetPatrolPoint(_currentWardPatrolPoint); } else { ((BaseAI)MonsterAi).SetPatrolPoint(((Component)this).transform.position); } } else if (Stance == GuildMobStance.Stay) { ClearNonFollowOrders(((Component)this).transform.position, clearCombatState: true); if ((Object)(object)((BaseAI)MonsterAi).GetTargetCreature() != (Object)null) { Traverse.Create((object)MonsterAi).Field("m_targetCreature").SetValue((object)null); Traverse.Create((object)MonsterAi).Method("SetAlerted", new object[1] { false }).GetValue(); } } else if (Stance == GuildMobStance.Guard) { EnforceStanceLeash(GuardMaxDistance, clearCombatTarget: true); ClearNonFollowOrders((_stanceAnchorPoint == Vector3.zero) ? ((Component)this).transform.position : _stanceAnchorPoint, clearCombatState: false); } else if (Stance == GuildMobStance.Follow || Stance == GuildMobStance.FollowAttack) { RefreshFollowTarget(); } } public bool Interact(Humanoid user, bool hold, bool alt) { Tameable component = ((Component)this).GetComponent<Tameable>(); if (Object.op_Implicit((Object)(object)component)) { return component.Interact(user, hold, alt); } if (!m_nview.IsValid() || hold || (Object)(object)Character == (Object)null) { return false; } if (!Character.IsTamed()) { return false; } Player val = (Player)(object)((user is Player) ? user : null); if ((Object)(object)val == (Object)null || !Character.IsTamed()) { return true; } TamedGuildMob component2 = ((Component)this).GetComponent<TamedGuildMob>(); if ((Object)(object)component2 != (Object)null) { long playerID = val.GetPlayerID(); long tamerID = component2.TamerID; float obedience = component2.Obedience; string text = GuildUtils.GetPlayerGuildName(val); if (string.IsNullOrEmpty(text)) { text = "No Guild"; } if (tamerID == 0L || obedience <= 0f) { if (tamerID != 0L && tamerID != playerID) { if (!hold) { ((Character)val).Message((MessageType)2, "This beast is wild, but belongs to another.", 0, (Sprite)null); } return false; } if ((Input.GetKey((KeyCode)308) || Input.GetKey((KeyCode)307)) && text != "No Guild" && component2.TryClaim(val, text)) { ((Character)val).Message((MessageType)2, "Mob claimed for guild: " + text, 0, (Sprite)null); return false; } } else if (tamerID == playerID && text != component2.GuildName && text != "No Guild") { if (alt) { return true; } if (component2.TryChangeGuild(val, text)) { ((Character)val).Message((MessageType)2, "Mob updated to guild: " + text, 0, (Sprite)null); return false; } } } return false; } public bool UseItem(Humanoid user, ItemData item) { return false; } private void UpdateAlarmState() { //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) if (AlarmPlayerId == 0L) { return; } float num = Mathf.Max(0f, TameGuildWarsPlugin.ConfigAlarmDurationSeconds.Value); if (num == 0f) { ClearAlarm(); return; } long alarmRaisedTicks = AlarmRaisedTicks; if (alarmRaisedTicks > 0) { TimeSpan timeSpan = new TimeSpan(DateTime.UtcNow.Ticks - alarmRaisedTicks); if (timeSpan.TotalSeconds >= (double)num) { ClearAlarm(); return; } } Player player = Player.GetPlayer(AlarmPlayerId); if ((Object)(object)player == (Object)null) { return; } if (TargetingPatches.IsPlayerGhost(player)) { ClearAlarm(); return; } float num2 = Mathf.Max(0f, TameGuildWarsPlugin.ConfigAlarmLeashDistance.Value); if (num2 > 0f && Vector3.Distance(((Component)this).transform.position, ((Component)player).transform.position) > num2) { ClearAlarm(); } } public void inheritGuild(TamedGuildMob fromTGM, float obedience = -1f, bool newTamer = true) { if (!((Object)(object)fromTGM == (Object)null) && fromTGM.GuildName != null) { GuildName = fromTGM.GuildName; if (obedience >= 0f) { Obedience = obedience; } else { Obedience = childStartingObedience; } if (newTamer) { FindNearestTamer(); return; } TamerID = fromTGM.TamerID; TamerName = fromTGM.TamerName; } } public void EggStart(EggGrow growup) { if (!((Object)(object)growup == (Object)null)) { Obedience = childStartingObedience; FindNearestTamer(); } } private bool FindNearestTamer() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) if (TamerID != 0L) { return true; } TameGuildWarsPlugin.TameGuildWarsLogger.LogInfo((object)$"Creature:{((Object)this).name}, Guild:{GuildName}, loc:{((Component)this).transform.position}, obedience:{Obedience}");