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 Ravenview v1.5.1
plugins/Ravenview.dll
Decompiled a week ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Splatform; using Steamworks; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.InputSystem.LowLevel; using UnityEngine.InputSystem.Utilities; using UnityEngine.Rendering; using UnityEngine.UI; using Valheim.SettingsGui; using Valheim.UI; using ValheimOnline.Combat; using ValheimOnline.Compat; using ValheimOnline.Guilds; using ValheimOnline.Social; using ValheimOnline.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyVersion("0.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ValheimOnline { public static class ScalePlugin { public const int VanillaPlayerLimit = 10; public const int VanillaSteamSendRate = 153600; public const int VanillaZdoQueueLimit = 10240; public const float VanillaSyncInterval = 0.05f; public const int SteamLobbyHardLimit = 250; internal static ConfigEntry<int> MaxPlayers; internal static ConfigEntry<int> SteamSendRate; internal static ConfigEntry<int> ZdoQueueLimit; internal static ConfigEntry<float> SyncInterval; internal static ConfigEntry<int> MaxPeersPerFrame; internal static ConfigEntry<bool> EnableSendLoopRewrite; private static Harmony _harmony; internal static ManualLogSource Log => Plugin.Log; public static void Init(ConfigFile Config, Harmony harmony) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Expected O, but got Unknown //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Expected O, but got Unknown //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Expected O, but got Unknown //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Expected O, but got Unknown _harmony = harmony; MaxPlayers = Config.Bind<int>("1. Players", "MaxPlayers", 100, new ConfigDescription("Maximum players allowed on this server. Vanilla is 10.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 1000), Array.Empty<object>())); SteamSendRate = Config.Bind<int>("2. Bandwidth", "SteamSendRateBytesPerSecond", 1048576, new ConfigDescription("Steam per-connection send rate in bytes/sec (used for both min and max). Vanilla is 153600 (150 KB/s). The server's total upload can reach this x player count, so lower it if your upload bandwidth is limited.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(65536, 16777216), Array.Empty<object>())); ZdoQueueLimit = Config.Bind<int>("2. Bandwidth", "ZdoSendQueueLimitBytes", 32768, new ConfigDescription("How many bytes of world updates may be queued per player before the server waits. Vanilla is 10240. Higher = fewer delayed updates in busy areas.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10240, 1048576), Array.Empty<object>())); SyncInterval = Config.Bind<float>("3. Sync loop", "SyncIntervalSeconds", 0.05f, new ConfigDescription("Target time for one full world-update pass over all players. Vanilla is 0.05.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.02f, 1f), Array.Empty<object>())); MaxPeersPerFrame = Config.Bind<int>("3. Sync loop", "MaxPeersPerFrame", 0, new ConfigDescription("Cap on how many players get world updates in a single frame. 0 = automatic (spread all players evenly across SyncIntervalSeconds).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 1000), Array.Empty<object>())); EnableSendLoopRewrite = Config.Bind<bool>("3. Sync loop", "EnableSendLoopRewrite", true, "Replace vanilla's one-player-per-frame update loop. Vanilla only updates ONE player per frame, so with 100 players each one waits ~2 seconds between updates. Requires restart."); Apply(typeof(PlayerCapPatch)); Apply(typeof(SteamLobbySizePatch)); Apply(typeof(SteamSendRatePatch)); Apply(typeof(ZdoQueueLimitPatch)); if (EnableSendLoopRewrite.Value) { if (SendLoopPatch.Init()) { if (Apply(typeof(SendLoopPatch))) { Log.LogInfo((object)("Patched ZDOMan.SendZDOToPeers2 send loop (interval " + SyncInterval.Value + " s).")); } } else { Log.LogError((object)"Send loop rewrite disabled: game internals did not match. Vanilla loop is in use."); } } Log.LogInfo((object)$"Scale: max players {MaxPlayers.Value}, Steam send rate {SteamSendRate.Value} B/s, ZDO queue {ZdoQueueLimit.Value} B."); } private static bool Apply(Type patchClass) { try { _harmony.CreateClassProcessor(patchClass).Patch(); return true; } catch (Exception ex) { Log.LogError((object)("Failed to apply " + patchClass.Name + ": " + ex)); return false; } } public static int GetMaxPlayers() { return MaxPlayers.Value; } public static int GetSteamLobbySize() { return Math.Min(MaxPlayers.Value, 250); } public static int GetSteamSendRate() { return SteamSendRate.Value; } public static int GetZdoQueueLimit() { return ZdoQueueLimit.Value; } internal static bool IsLdcI4(CodeInstruction ci, int value) { if (ci.opcode == OpCodes.Ldc_I4 || ci.opcode == OpCodes.Ldc_I4_S) { if (ci.operand != null) { return Convert.ToInt32(ci.operand) == value; } return false; } return false; } internal static bool IsCallTo(CodeInstruction ci, string declaringType, string methodName) { if (ci.opcode != OpCodes.Call && ci.opcode != OpCodes.Callvirt) { return false; } MethodBase methodBase = ci.operand as MethodBase; if (methodBase != null && methodBase.Name == methodName && methodBase.DeclaringType != null) { return methodBase.DeclaringType.Name == declaringType; } return false; } internal static void ReplaceWithCall(CodeInstruction ci, string getterName) { ci.opcode = OpCodes.Call; ci.operand = AccessTools.Method(typeof(ScalePlugin), getterName, (Type[])null, (Type[])null); } internal static void ReportCount(string where, int found, int expected) { if (found == expected) { Log.LogInfo((object)("Patched " + where + " (" + found + " site(s)).")); } else { Log.LogError((object)("Patch mismatch in " + where + ": expected " + expected + " site(s), found " + found + ". The game may have updated; this patch was NOT applied.")); } } } [HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")] internal static class PlayerCapPatch { [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> list = new List<CodeInstruction>(instructions); List<int> list2 = new List<int>(); for (int i = 0; i + 1 < list.Count; i++) { if (ScalePlugin.IsCallTo(list[i], "ZNet", "GetNrOfPlayers") && ScalePlugin.IsLdcI4(list[i + 1], 10)) { list2.Add(i + 1); } } ScalePlugin.ReportCount("ZNet.RPC_PeerInfo player cap", list2.Count, 1); if (list2.Count == 1) { ScalePlugin.ReplaceWithCall(list[list2[0]], "GetMaxPlayers"); } return list; } } [HarmonyPatch(typeof(ZSteamMatchmaking), "RegisterServer")] internal static class SteamLobbySizePatch { [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> list = new List<CodeInstruction>(instructions); List<int> list2 = new List<int>(); for (int i = 0; i + 1 < list.Count; i++) { if (ScalePlugin.IsLdcI4(list[i], 10) && ScalePlugin.IsCallTo(list[i + 1], "SteamMatchmaking", "CreateLobby")) { list2.Add(i); } } ScalePlugin.ReportCount("ZSteamMatchmaking.RegisterServer lobby size", list2.Count, 1); if (list2.Count == 1) { ScalePlugin.ReplaceWithCall(list[list2[0]], "GetSteamLobbySize"); } return list; } } [HarmonyPatch(typeof(ZSteamSocket), "RegisterGlobalCallbacks")] internal static class SteamSendRatePatch { [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> list = new List<CodeInstruction>(instructions); List<int> list2 = new List<int>(); for (int i = 0; i < list.Count; i++) { if (ScalePlugin.IsLdcI4(list[i], 153600)) { list2.Add(i); } } ScalePlugin.ReportCount("ZSteamSocket send rate", list2.Count, 1); if (list2.Count == 1) { ScalePlugin.ReplaceWithCall(list[list2[0]], "GetSteamSendRate"); } return list; } } [HarmonyPatch(typeof(ZDOMan), "SendZDOs")] internal static class ZdoQueueLimitPatch { [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> list = new List<CodeInstruction>(instructions); List<int> list2 = new List<int>(); for (int i = 0; i < list.Count; i++) { if (ScalePlugin.IsLdcI4(list[i], 10240)) { list2.Add(i); } } ScalePlugin.ReportCount("ZDOMan.SendZDOs queue limit", list2.Count, 2); if (list2.Count == 2) { foreach (int item in list2) { ScalePlugin.ReplaceWithCall(list[item], "GetZdoQueueLimit"); } } return list; } } [HarmonyPatch(typeof(ZDOMan), "SendZDOToPeers2")] internal static class SendLoopPatch { private static FieldInfo _peersField; private static MethodInfo _sendZdos; private static readonly object[] _args = new object[2]; private static int _cursor = -1; private static float _timer; private static float _owed; internal static bool Init() { _peersField = AccessTools.Field(typeof(ZDOMan), "m_peers"); _sendZdos = AccessTools.Method(typeof(ZDOMan), "SendZDOs", (Type[])null, (Type[])null); if (_peersField == null || _sendZdos == null) { return false; } ParameterInfo[] parameters = _sendZdos.GetParameters(); if (parameters.Length != 2 || parameters[1].ParameterType != typeof(bool) || _sendZdos.ReturnType != typeof(bool)) { return false; } if (!typeof(IList).IsAssignableFrom(_peersField.FieldType)) { return false; } return true; } [HarmonyPrefix] private static bool Prefix(ZDOMan __instance, float dt) { IList list = (IList)_peersField.GetValue(__instance); int num = list?.Count ?? 0; if (num == 0) { _cursor = -1; return false; } float value = ScalePlugin.SyncInterval.Value; _timer += dt; if (_cursor < 0) { if (_timer < value) { return false; } _cursor = 0; _timer = 0f; _owed = 0f; } _owed += (float)num * dt / value; int num2 = (int)_owed; if (num2 < 1) { num2 = 1; } _owed -= num2; if (_owed < 0f) { _owed = 0f; } int value2 = ScalePlugin.MaxPeersPerFrame.Value; if (value2 > 0 && num2 > value2) { num2 = value2; } try { int num3 = 0; while (num3 < num2 && _cursor < list.Count) { _args[0] = list[_cursor]; _args[1] = false; _sendZdos.Invoke(__instance, _args); num3++; _cursor++; } } catch (TargetInvocationException ex) { _cursor++; ScalePlugin.Log.LogError((object)("SendZDOs failed: " + (ex.InnerException ?? ex))); } if (_cursor >= list.Count) { _cursor = -1; } return false; } } [HarmonyPatch] public static class Tweaks { public static ConfigEntry<bool> SkipIntro; public static ConfigEntry<bool> DevConsole; public static ConfigEntry<bool> AnnounceArrival; public static void Bind(ConfigFile c) { SkipIntro = c.Bind<bool>("0. Client", "SkipIntroCinematic", true, "Skip the intro cinematic when the game starts."); DevConsole = c.Bind<bool>("0. Client", "EnableDevConsole", false, "Turn on the F5 console for this session (like launching with -console). Takes effect at the next game start."); AnnounceArrival = c.Bind<bool>("0. Client", "AnnounceArrival", false, "Shout \"I have arrived!\" in world chat when you load into a world (the game's default)."); } [HarmonyPatch(typeof(Chat), "SendText")] [HarmonyPrefix] private static bool NoArrival(string __1) { if (AnnounceArrival == null || AnnounceArrival.Value || string.IsNullOrEmpty(__1) || Localization.instance == null) { return true; } return __1 != Localization.instance.Localize("$text_player_arrived"); } [HarmonyPatch(typeof(FejdStartup), "TryPlayIntroCinematic")] [HarmonyPrefix] private static bool IntroCo(FejdStartup __instance, ref IEnumerator __result) { if (SkipIntro == null || !SkipIntro.Value) { return true; } __result = Skip(__instance); return false; } [HarmonyPatch(typeof(Console), "Awake")] [HarmonyPostfix] private static void ConsoleOn() { if (DevConsole == null || !DevConsole.Value) { return; } try { MethodInfo methodInfo = AccessTools.Method(typeof(Console), "SetConsoleEnabledForThisSession", (Type[])null, (Type[])null); if (methodInfo != null) { methodInfo.Invoke(methodInfo.IsStatic ? null : Console.instance, null); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("EnableDevConsole: " + ex.Message)); } } private static IEnumerator Skip(FejdStartup f) { try { Animator value = Traverse.Create((object)f).Field("m_menuAnimator").GetValue<Animator>(); if ((Object)(object)value != (Object)null) { value.SetTrigger("FadeIn"); } GameObject value2 = Traverse.Create((object)f).Field("m_mainMenu").GetValue<GameObject>(); if ((Object)(object)value2 != (Object)null && !value2.activeSelf) { value2.SetActive(true); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("SkipIntro: " + ex.Message)); } yield break; } } [BepInPlugin("com.valheimonline", "Ravenview", "1.5.1")] public class Plugin : BaseUnityPlugin { public const string Guid = "com.valheimonline"; public const string Name = "Ravenview"; public const string Version = "1.5.1"; public static ManualLogSource Log; private Harmony _harmony; private void Awake() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Logger.Listeners.Add((ILogListener)(object)new ErrorCounter()); _harmony = new Harmony("com.valheimonline"); ScalePlugin.Init(((BaseUnityPlugin)this).Config, _harmony); Tweaks.Bind(((BaseUnityPlugin)this).Config); try { _harmony.CreateClassProcessor(typeof(Tweaks)).Patch(); } catch (Exception ex) { Log.LogError((object)("Tweaks failed: " + ex)); } GuildConfig.Bind(((BaseUnityPlugin)this).Config); UiConfig.Bind(((BaseUnityPlugin)this).Config); PadDebug.Bind(((BaseUnityPlugin)this).Config); if (GuildConfig.Enabled) { int num = 0; int num2 = 0; foreach (Type item in from t in typeof(Plugin).Assembly.GetTypes() where t.Namespace == "ValheimOnline.Guilds" && t.GetCustomAttributes(typeof(HarmonyPatch), inherit: false).Length != 0 select t) { try { _harmony.CreateClassProcessor(item).Patch(); num++; } catch (Exception ex2) { num2++; Log.LogError((object)("Guild patch " + item.Name + " failed: " + ex2)); } } ((Component)this).gameObject.AddComponent<GuildRuntime>(); ConfigReload.Watch(((BaseUnityPlugin)this).Config); Log.LogInfo((object)("Guilds: " + num + " patch group(s) applied" + ((num2 > 0) ? (", " + num2 + " FAILED") : "") + ".")); } else { Log.LogInfo((object)"Guilds are turned off in the config."); } ((Component)this).gameObject.AddComponent<ProgressionRuntime>(); foreach (Type item2 in from t in typeof(Plugin).Assembly.GetTypes() where t.Namespace == "ValheimOnline.UI" && t.GetCustomAttributes(typeof(HarmonyPatch), inherit: false).Length != 0 select t) { try { _harmony.CreateClassProcessor(item2).Patch(); } catch (Exception ex3) { Log.LogError((object)("UI patch " + item2.Name + " failed: " + ex3)); } } ModCompat.Bind(((BaseUnityPlugin)this).Config); foreach (Type item3 in from t in typeof(Plugin).Assembly.GetTypes() where t.Namespace == "ValheimOnline.Compat" && t.GetCustomAttributes(typeof(HarmonyPatch), inherit: false).Length != 0 select t) { try { _harmony.CreateClassProcessor(item3).Patch(); } catch (Exception ex4) { Log.LogError((object)("Mod compat patch " + item3.Name + " failed: " + ex4)); } } SocialRuntime.Bind(((BaseUnityPlugin)this).Config); ((Component)this).gameObject.AddComponent<SocialRuntime>(); foreach (Type item4 in from t in typeof(Plugin).Assembly.GetTypes() where t.Namespace == "ValheimOnline.Social" && t.GetCustomAttributes(typeof(HarmonyPatch), inherit: false).Length != 0 select t) { try { _harmony.CreateClassProcessor(item4).Patch(); } catch (Exception ex5) { Log.LogError((object)("Social patch " + item4.Name + " failed: " + ex5)); } } ValheimOnline.Combat.Combat.Bind(((BaseUnityPlugin)this).Config); if (ValheimOnline.Combat.Combat.GcoPresent) { Log.LogWarning((object)"Combat: Goo's Combat Overhaul is installed, so Ravenview's combat stays off (both change the same things)."); } else { int num3 = 0; int num4 = 0; foreach (Type item5 in from t in typeof(Plugin).Assembly.GetTypes() where t.Namespace == "ValheimOnline.Combat" && t.GetCustomAttributes(typeof(HarmonyPatch), inherit: false).Length != 0 select t) { try { _harmony.CreateClassProcessor(item5).Patch(); num3++; } catch (Exception ex6) { num4++; Log.LogError((object)("Combat patch " + item5.Name + " failed: " + ex6)); } } ((Component)this).gameObject.AddComponent<CombatRuntime>(); Log.LogInfo((object)("Combat: " + num3 + " patch group(s) applied" + ((num4 > 0) ? (", " + num4 + " FAILED") : "") + ".")); } Log.LogInfo((object)"Ravenview 1.5.1 loaded."); } } } namespace ValheimOnline.Guilds { public static class Util { private static string _coinToken; private static string CoinToken { get { if (_coinToken == null) { SharedData val = Shared("Coins"); if (val != null) { _coinToken = val.m_name; } } return _coinToken; } } public static GameObject ItemPrefab(string prefab) { if ((Object)(object)ObjectDB.instance == (Object)null || string.IsNullOrEmpty(prefab)) { return null; } return ObjectDB.instance.GetItemPrefab(prefab); } public static SharedData Shared(string prefab) { GameObject val = ItemPrefab(prefab); if ((Object)(object)val == (Object)null) { return null; } ItemDrop component = val.GetComponent<ItemDrop>(); if (!((Object)(object)component != (Object)null)) { return null; } return component.m_itemData.m_shared; } public static bool ItemExists(string prefab) { return Shared(prefab) != null; } public static int MaxStack(string prefab) { SharedData val = Shared(prefab); if (val == null) { return 1; } return Math.Max(1, val.m_maxStackSize); } public static string ItemDisplayName(string prefab) { SharedData val = Shared(prefab); if (val == null) { return prefab; } if (Localization.instance == null) { return val.m_name; } return Localization.instance.Localize(val.m_name); } public static Sprite Icon(string prefab) { SharedData val = Shared(prefab); if (val == null || val.m_icons == null || val.m_icons.Length == 0) { return null; } return val.m_icons[0]; } public static Sprite Icon(ItemRecord r) { SharedData val = Shared(r.Prefab); if (val == null || val.m_icons == null || val.m_icons.Length == 0) { return null; } return val.m_icons[Mathf.Clamp(r.Variant, 0, val.m_icons.Length - 1)]; } public static string CreatureName(string token) { if (Localization.instance == null) { return token; } return Localization.instance.Localize(token); } public static bool IsGear(string prefab) { //IL_000d: 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_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected I4, but got Unknown SharedData val = Shared(prefab); if (val == null) { return false; } ItemType itemType = val.m_itemType; switch (itemType - 3) { case 0: case 1: case 2: case 3: case 4: case 6: case 8: case 9: case 11: case 12: case 14: case 15: case 16: case 17: case 19: case 20: case 21: return true; default: return false; } } public static ItemRecord ToRecord(ItemData item, int amount) { ItemRecord itemRecord = new ItemRecord { Prefab = (((Object)(object)item.m_dropPrefab != (Object)null) ? ((Object)item.m_dropPrefab).name : ""), Stack = amount, Quality = item.m_quality, Variant = item.m_variant, Durability = item.m_durability, CrafterId = item.m_crafterID, CrafterName = (item.m_crafterName ?? ""), WorldLevel = item.m_worldLevel }; if (item.m_customData != null) { foreach (KeyValuePair<string, string> customDatum in item.m_customData) { itemRecord.Custom[customDatum.Key] = customDatum.Value; } } return itemRecord; } public static ItemData FromRecord(ItemRecord r) { GameObject val = ItemPrefab(r.Prefab); if ((Object)(object)val == (Object)null) { return null; } ItemData obj = val.GetComponent<ItemDrop>().m_itemData.Clone(); obj.m_dropPrefab = val; obj.m_stack = r.Stack; obj.m_quality = r.Quality; obj.m_variant = r.Variant; obj.m_durability = r.Durability; obj.m_crafterID = r.CrafterId; obj.m_crafterName = r.CrafterName; obj.m_worldLevel = r.WorldLevel; obj.m_customData = new Dictionary<string, string>(r.Custom); obj.m_equipped = false; return obj; } public static ItemRecord TakeItemForVault(ItemData item, int amount) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || item == null) { return null; } if (item.m_equipped) { Notify.Show(MsgKind.Error, "Unequip the item first."); return null; } if ((Object)(object)item.m_dropPrefab == (Object)null) { Notify.Show(MsgKind.Error, "This item cannot be stored."); return null; } if (GuildClient.Rules.Blocked.Contains(((Object)item.m_dropPrefab).name)) { Notify.Show(MsgKind.Error, "That item cannot be stored in the guild vault."); return null; } amount = Mathf.Clamp(amount, 1, item.m_stack); ItemRecord result = ToRecord(item, amount); Inventory inventory = ((Humanoid)localPlayer).GetInventory(); if (!inventory.ContainsItem(item)) { return null; } if (!inventory.RemoveItem(item, amount)) { return null; } return result; } public static int CountCoins() { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || CoinToken == null) { return 0; } return ((Humanoid)localPlayer).GetInventory().CountItems(CoinToken, -1, false); } public static bool TakeCoins(long amount) { if (amount <= 0) { return true; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || CoinToken == null) { return false; } Inventory inventory = ((Humanoid)localPlayer).GetInventory(); if (inventory.CountItems(CoinToken, -1, false) < amount) { return false; } inventory.RemoveItem(CoinToken, (int)amount, -1, false); return true; } public static void GiveToLocalPlayer(List<ItemRecord> items, long coins) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { Plugin.Log.LogWarning((object)("Received guild items with no local player; " + items.Count + " stacks and " + coins + " coins lost.")); return; } Inventory inventory = ((Humanoid)localPlayer).GetInventory(); bool flag = false; foreach (ItemRecord item in items) { ItemData val = FromRecord(item); if (val == null) { Plugin.Log.LogWarning((object)("Unknown item " + item.Prefab + " from the guild vault.")); } else if (!inventory.AddItem(val)) { Drop(localPlayer, val); flag = true; } } if (coins > 0) { int num = MaxStack("Coins"); long num2 = coins; while (num2 > 0) { int num3 = (int)Math.Min(num2, num); ItemData val2 = FromRecord(new ItemRecord { Prefab = "Coins", Stack = num3 }); if (val2 == null) { break; } if (!inventory.AddItem(val2)) { Drop(localPlayer, val2); flag = true; } num2 -= num3; } } if (flag) { Notify.Show(MsgKind.Center, "Your inventory is full; some items were dropped at your feet."); } } private static void Drop(Player p, ItemData it) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //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_0037: 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) Vector3 val = ((Component)p).transform.position + ((Component)p).transform.forward * 0.8f + Vector3.up; ItemDrop.DropItem(it, it.m_stack, val, Quaternion.identity); } public static bool PeerIsAdmin(ZNetPeer peer) { try { return peer != null && peer.m_socket != null && ZNet.instance.IsAdmin(peer.m_socket.GetHostName()); } catch { return false; } } public static string Ago(long ticks) { if (ticks <= 0) { return "never"; } TimeSpan timeSpan = TimeSpan.FromTicks(DateTime.UtcNow.Ticks - ticks); if (timeSpan.TotalMinutes < 1.0) { return "just now"; } if (timeSpan.TotalHours < 1.0) { return (int)timeSpan.TotalMinutes + " min ago"; } if (timeSpan.TotalDays < 1.0) { return (int)timeSpan.TotalHours + " h ago"; } return (int)timeSpan.TotalDays + " d ago"; } public static string Hex(Color c) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return ColorUtility.ToHtmlStringRGB(c); } public static int ColorToRgb(Color c) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) return (Mathf.RoundToInt(c.r * 255f) << 16) | (Mathf.RoundToInt(c.g * 255f) << 8) | Mathf.RoundToInt(c.b * 255f); } public static string Esc(string s) { return (s ?? "").Replace("<", "").Replace(">", ""); } } public static class Notify { public static void Show(MsgKind kind, string text) { switch (kind) { case MsgKind.GuildChat: { Guild mine = GuildClient.Mine; string text2 = ((mine != null) ? mine.ColorHex : "88CCFF"); ChatLine("<color=#" + text2 + ">[Guild] " + Util.Esc(text) + "</color>"); break; } case MsgKind.Notice: ChatLine("<color=#C8B78A>[Guild] " + Util.Esc(text) + "</color>"); Hud((MessageType)1, text); break; case MsgKind.Motd: ChatLine("<color=#E8C95A>[Message of the day] " + Util.Esc(text) + "</color>"); Hud((MessageType)2, text); break; case MsgKind.Center: ChatLine("<color=#E8C95A>[Guild] " + Util.Esc(text) + "</color>"); Hud((MessageType)2, text); break; case MsgKind.Error: Hud((MessageType)2, "<color=#FF7060>" + Util.Esc(text) + "</color>"); GuildWindow.LastError = text; break; default: Hud((MessageType)1, text); GuildWindow.LastInfo = text; break; } } public static void ChatLine(string rich) { if ((Object)(object)Chat.instance != (Object)null) { ((Terminal)Chat.instance).AddString(rich); } } private static void Hud(MessageType t, string text) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)MessageHud.instance != (Object)null) { MessageHud.instance.ShowMessage(t, text, 0, (Sprite)null, false, true); } } } public static class Keys { public static readonly int Guild = StringExtensionMethods.GetStableHashCode("vo_guild"); public static readonly int Reg = StringExtensionMethods.GetStableHashCode("vo_reg"); public static readonly int Levelled = StringExtensionMethods.GetStableHashCode("vo_lvl"); } public class GuildBanner : MonoBehaviour, Hoverable, Interactable { private ZNetView _nview; private Piece _piece; private float _tintTimer; private Color _lastTint = Color.clear; public GuildSummary Owner { get { //IL_0006: 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) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)this).transform.position; foreach (GuildSummary value in GuildClient.Summaries.Values) { if (value.HasBanner) { Vector2 val = new Vector2(value.BannerPos.x - position.x, value.BannerPos.z - position.z); if (((Vector2)(ref val)).sqrMagnitude < 2.5f) { return value; } } } return null; } } private void Awake() { _nview = ((Component)this).GetComponent<ZNetView>(); _piece = ((Component)this).GetComponent<Piece>(); } private void Start() { //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_nview == (Object)null || !_nview.IsValid()) { return; } ZDO zDO = _nview.GetZDO(); if (_nview.IsOwner() && (Object)(object)_piece != (Object)null && _piece.IsCreator() && !zDO.GetBool(Keys.Reg, false)) { zDO.Set(Keys.Reg, true); if (GuildClient.Mine != null) { zDO.Set(Keys.Guild, GuildClient.Mine.Id, false); } Vector3 pos = ((Component)this).transform.position; GuildClient.Send(Op.BannerPlaced, delegate(ZPackage p) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) p.Write(pos); }); } } private void Update() { //IL_0068: 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_006d: Unknown result type (might be due to invalid IL or missing references) //IL_006e: 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_007d: 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_0085: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_nview == (Object)null || !_nview.IsValid()) { return; } _tintTimer -= Time.deltaTime; if (!(_tintTimer > 0f)) { _tintTimer = 2f; GuildSummary owner = Owner; Color val = (Color)(((??)owner?.Color) ?? new Color(0.5f, 0.5f, 0.5f)); if (val != _lastTint) { Tint(val); _lastTint = val; } if (owner != null) { Territory.CheckLevelling(this, _nview, owner); } } } private void Tint(Color c) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) List<Renderer> list = (from r in ((Component)this).GetComponentsInChildren<Renderer>() where r is SkinnedMeshRenderer || (Object)(object)((Component)r).GetComponent<Cloth>() != (Object)null select r).ToList(); if (list.Count == 0) { list = ((Component)this).GetComponentsInChildren<Renderer>().ToList(); } MaterialPropertyBlock val = new MaterialPropertyBlock(); foreach (Renderer item in list) { item.GetPropertyBlock(val); val.SetColor("_Color", Color.Lerp(Color.white, c, 0.85f)); item.SetPropertyBlock(val); } } public string GetHoverText() { GuildSummary owner = Owner; if (owner == null) { return "Guild banner\n<color=#999999>(inactive — not registered to a guild)</color>"; } string text = "<color=#" + owner.ColorHex + ">" + Util.Esc(owner.Name) + " [" + owner.Tag + "]</color>\nGuild banner · territory " + owner.TerritorySize + " m"; if (GuildClient.Mine != null && GuildClient.Mine.Id == owner.Id) { text += "\n[<color=yellow><b>$KEY_Use</b></color>] Guild banner (upgrades)"; if (owner.UpgradeLevel("Respawn") > 0) { text += "\n[<color=yellow><b>$KEY_AltPlace + $KEY_Use</b></color>] Toggle respawn here"; } } if (Localization.instance == null) { return text; } return Localization.instance.Localize(text); } public string GetHoverName() { return "Guild banner"; } public float GetHoverOffset() { return 0f; } public bool Interact(Humanoid user, bool hold, bool alt) { //IL_008f: Unknown result type (might be due to invalid IL or missing references) if (hold || (Object)(object)user != (Object)(object)Player.m_localPlayer) { return false; } GuildSummary owner = Owner; if (owner == null || GuildClient.Mine == null || GuildClient.Mine.Id != owner.Id) { Notify.Show(MsgKind.Info, (owner == null) ? "This banner belongs to no guild." : ("The banner of " + owner.Name + " [" + owner.Tag + "].")); return true; } if (alt) { GuildClient.Send(Op.ToggleBannerRespawn); } else { GuildWindow.OpenAtBanner(((Component)this).transform.position); } return true; } public bool UseItem(Humanoid user, ItemData item) { return false; } } public static class Territory { private static int _currentTerritory; private static float _checkTimer; private static float _lastDenyMsg; private static readonly FieldRef<Character, Rigidbody> BodyRef = AccessTools.FieldRefAccess<Character, Rigidbody>("m_body"); private static readonly FieldRef<Player, GameObject> GhostRef = AccessTools.FieldRefAccess<Player, GameObject>("m_placementGhost"); private static readonly HashSet<ZDOID> _levelling = new HashSet<ZDOID>(); private static readonly FieldRef<TerrainComp, float[]> F_level = AccessTools.FieldRefAccess<TerrainComp, float[]>("m_levelDelta"); private static readonly FieldRef<TerrainComp, float[]> F_smooth = AccessTools.FieldRefAccess<TerrainComp, float[]>("m_smoothDelta"); private static readonly FieldRef<TerrainComp, bool[]> F_mod = AccessTools.FieldRefAccess<TerrainComp, bool[]>("m_modifiedHeight"); private static readonly FieldRef<TerrainComp, bool> F_init = AccessTools.FieldRefAccess<TerrainComp, bool>("m_initialized"); private static readonly FieldRef<TerrainComp, ZNetView> F_nview = AccessTools.FieldRefAccess<TerrainComp, ZNetView>("m_nview"); private static readonly MethodInfo M_save = AccessTools.Method(typeof(TerrainComp), "Save", new Type[1] { typeof(bool) }, (Type[])null); public static void RegisterRpcs(ZRoutedRpc rpc) { } public static void DenyMessage(string text) { if (!(Time.time - _lastDenyMsg < 1.5f)) { _lastDenyMsg = Time.time; Notify.Show(MsgKind.Error, text); } } public static bool LocalDenied(Vector3 pos, bool message) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) if (!GuildConfig.Enabled || !GuildClient.Rules.TerritoryClaim || (Object)(object)Player.m_localPlayer == (Object)null) { return false; } GuildSummary guildSummary = GuildClient.TerritoryAt(pos); if (guildSummary == null || GuildClient.HasTerritoryAccess(guildSummary, GuildClient.LocalPid)) { return false; } if (message) { DenyMessage("This land belongs to " + guildSummary.Name + " [" + guildSummary.Tag + "]."); } return true; } public static void ClientUpdate(Player lp, float dt) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) _checkTimer -= dt; if (_checkTimer <= 0f) { _checkTimer = 0.5f; Vector3 position = ((Component)lp).transform.position; GuildSummary t = GuildClient.TerritoryAt(position); int num = ((t != null) ? t.Id : 0); if (num != _currentTerritory) { GuildClient.Summaries.TryGetValue(_currentTerritory, out var value); _currentTerritory = num; if (t != null) { bool flag = t.IsMember(GuildClient.LocalPid); GuildSummary guildSummary = GuildClient.GuildOfPlayer(GuildClient.LocalPid); bool flag2 = guildSummary != null && GuildClient.RelationBetween(guildSummary.Id, t.Id) == Relation.War; if ((Object)(object)MessageHud.instance != (Object)null) { MessageHud.instance.ShowMessage((MessageType)2, "<color=#" + t.ColorHex + ">" + Util.Esc(t.Name) + " [" + t.Tag + "]</color>" + (flag2 ? "\n<color=#FF5544>ENEMY TERRITORY</color>" : ""), 0, Util.Icon(t.Emblem), false, false); } if (!flag) { GuildClient.Send(Op.Intruder, delegate(ZPackage p) { p.Write(t.Id); }); } } else if (value != null && (Object)(object)MessageHud.instance != (Object)null) { MessageHud.instance.ShowMessage((MessageType)1, "Leaving the territory of " + value.Name, 0, (Sprite)null, false, false); } } } TerritoryVisuals.Update(lp); } public static void Barrier(Player p) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0040: 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_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0102: 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_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) if (!GuildConfig.Enabled || !GuildClient.HasState || !GuildClient.Rules.TerritoryBarrier || ((Character)p).IsDead() || ((Character)p).IsTeleporting() || ((Character)p).IsAttachedToShip()) { return; } Vector3 position = ((Component)p).transform.position; GuildSummary guildSummary = GuildClient.TerritoryAt(position); if (guildSummary != null && !GuildClient.CanEnterTerritory(guildSummary, GuildClient.LocalPid)) { float num = guildSummary.TerritorySize * 0.5f + 0.6f; float num2 = position.x - guildSummary.BannerPos.x; float num3 = position.z - guildSummary.BannerPos.z; Vector3 val = position; if (num - Mathf.Abs(num2) < num - Mathf.Abs(num3)) { val.x = guildSummary.BannerPos.x + ((num2 >= 0f) ? num : (0f - num)); } else { val.z = guildSummary.BannerPos.z + ((num3 >= 0f) ? num : (0f - num)); } float num4 = default(float); if ((Object)(object)ZoneSystem.instance != (Object)null && ZoneSystem.instance.GetSolidHeight(val, ref num4, 1000)) { val.y = Mathf.Max(val.y, num4); } ((Component)p).transform.position = val; Rigidbody val2 = BodyRef.Invoke((Character)(object)p); if ((Object)(object)val2 != (Object)null) { val2.position = val; } ((Character)p).SetVelocity(Vector3.zero); DenyMessage("You cannot enter the territory of " + guildSummary.Name + " [" + guildSummary.Tag + "]."); } } public static string PlacementError(Player player, Piece piece) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)((Component)piece).GetComponent<GuildBanner>() != (Object)null)) { return null; } GameObject val = GhostRef.Invoke(player); Vector3 val2 = (((Object)(object)val != (Object)null) ? val.transform.position : ((Component)player).transform.position); Guild mine = GuildClient.Mine; GuildSummary mySummary = GuildClient.MySummary; if (mine == null || mySummary == null) { return "Found or join a guild first."; } Rules rules = GuildClient.Rules; if (!GuildClient.Has(Perm.Banner)) { return "Your rank cannot place the guild banner."; } if (mine.HasBanner) { return "Your guild already has a banner."; } float num = rules.TerritorySize(mine.UpgradeLevel("Territory")) * 0.5f; foreach (GuildSummary value in GuildClient.Summaries.Values) { if (value.Id != mine.Id && value.HasBanner) { float num2 = num + value.TerritorySize * 0.5f + rules.TerritoryGap; if (Mathf.Abs(value.BannerPos.x - val2.x) < num2 && Mathf.Abs(value.BannerPos.z - val2.z) < num2) { return "Too close to the territory of " + value.Name + " [" + value.Tag + "]."; } } } return null; } public static void CheckLevelling(GuildBanner banner, ZNetView nview, GuildSummary owner) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) if (!GuildClient.Rules.TerritoryLevelling || (Object)(object)Player.m_localPlayer == (Object)null || !owner.IsMember(GuildClient.LocalPid) || Vector3.Distance(((Component)Player.m_localPlayer).transform.position, ((Component)banner).transform.position) > owner.TerritorySize * 0.75f + 10f) { return; } ZDO zDO = nview.GetZDO(); if (!(zDO.GetFloat(Keys.Levelled, 0f) >= owner.TerritorySize - 0.01f) && !_levelling.Contains(zDO.m_uid)) { if (!nview.IsOwner()) { nview.ClaimOwnership(); } _levelling.Add(zDO.m_uid); ((MonoBehaviour)GuildRuntime.Instance).StartCoroutine(Level(((Component)banner).transform.position, owner.TerritorySize, zDO)); } } private static IEnumerator Level(Vector3 center, float size, ZDO zdo) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) Notify.Show(MsgKind.Info, "Levelling the guild territory…"); float target = center.y; float half = size * 0.5f + 1f; float outer = half + 6f; RemoveVegetation(center, outer, target); yield return null; List<Bounds> blocked = new List<Bounds>(); List<Piece> list = new List<Piece>(); Piece.GetAllPiecesInRadius(center, outer * 1.5f, list); foreach (Piece item in list) { if ((Object)(object)item == (Object)null || (Object)(object)((Component)item).GetComponent<GuildBanner>() != (Object)null) { continue; } Collider[] componentsInChildren = ((Component)item).GetComponentsInChildren<Collider>(); foreach (Collider val in componentsInChildren) { if (!val.isTrigger) { Bounds bounds = val.bounds; ((Bounds)(ref bounds)).Expand(new Vector3(1f, 0f, 1f)); blocked.Add(bounds); } } } List<Heightmap> list2 = new List<Heightmap>(); Heightmap.FindHeightmap(center, outer * 1.42f, list2); int done = 0; Vector3 val3 = default(Vector3); foreach (Heightmap hm in list2) { if ((Object)(object)hm == (Object)null) { continue; } TerrainComp tc = null; try { tc = hm.GetAndCreateTerrainCompiler(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Levelling: " + ex.Message)); } if ((Object)(object)tc == (Object)null) { continue; } float wait = 0f; while ((Object)(object)tc != (Object)null && !F_init.Invoke(tc) && wait < 5f) { wait += 0.1f; yield return (object)new WaitForSeconds(0.1f); } if ((Object)(object)tc == (Object)null || !F_init.Invoke(tc)) { continue; } ZNetView val2 = F_nview.Invoke(tc); if ((Object)(object)val2 != (Object)null && val2.IsValid() && !val2.IsOwner()) { val2.ClaimOwnership(); } float[] array = F_level.Invoke(tc); float[] array2 = F_smooth.Invoke(tc); bool[] array3 = F_mod.Invoke(tc); int num = hm.m_width + 1; float scale = hm.m_scale; int num2 = hm.m_width / 2; Vector3 position = ((Component)hm).transform.position; bool flag = false; for (int j = 0; j < num; j++) { for (int k = 0; k < num; k++) { ((Vector3)(ref val3))..ctor(position.x + (float)(k - num2) * scale, 0f, position.z + (float)(j - num2) * scale); float num3 = Mathf.Abs(val3.x - center.x); float num4 = Mathf.Abs(val3.z - center.z); float num5 = Mathf.Max(num3, num4); if (num5 > outer) { continue; } bool flag2 = false; foreach (Bounds item2 in blocked) { Bounds current2 = item2; if (val3.x >= ((Bounds)(ref current2)).min.x && val3.x <= ((Bounds)(ref current2)).max.x && val3.z >= ((Bounds)(ref current2)).min.z && val3.z <= ((Bounds)(ref current2)).max.z) { flag2 = true; break; } } if (!flag2) { int num6 = j * num + k; float num7 = hm.GetHeight(k, j) - array[num6] - array2[num6]; float num8; if (num5 <= half) { num8 = target; } else { float num9 = Mathf.Clamp01((num5 - half) / 6f); num9 = num9 * num9 * (3f - 2f * num9); num8 = Mathf.Lerp(target, num7, num9); } array[num6] = Mathf.Clamp(num8 - num7, -8f, 8f); array2[num6] = 0f; array3[num6] = true; flag = true; } } } if (flag) { try { M_save.Invoke(tc, new object[1] { false }); hm.Poke(1, false); done++; } catch (Exception ex2) { Plugin.Log.LogWarning((object)("Levelling save failed: " + ex2)); } } yield return null; } try { if ((Object)(object)ClutterSystem.instance != (Object)null) { ClutterSystem.instance.ResetGrass(center, outer * 1.42f); } } catch { } Plugin.Log.LogInfo((object)("Territory levelled (" + done + " terrain chunk(s)).")); if (zdo != null && zdo.IsValid()) { zdo.Set(Keys.Levelled, size); } _levelling.Remove(zdo.m_uid); Notify.Show(MsgKind.Info, "The guild territory has been levelled."); } private static void RemoveVegetation(Vector3 center, float half, float target) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) Collider[] array = Physics.OverlapBox(center, new Vector3(half, 60f, half), Quaternion.identity); HashSet<ZNetView> hashSet = new HashSet<ZNetView>(); Collider[] array2 = array; for (int i = 0; i < array2.Length; i++) { ZNetView componentInParent = ((Component)array2[i]).GetComponentInParent<ZNetView>(); if ((Object)(object)componentInParent == (Object)null || !componentInParent.IsValid() || hashSet.Contains(componentInParent)) { continue; } GameObject gameObject = ((Component)componentInParent).gameObject; if (!((Object)(object)gameObject.GetComponent<Piece>() != (Object)null) && !((Object)(object)gameObject.GetComponent<Character>() != (Object)null) && !((Object)(object)gameObject.GetComponent<ItemDrop>() != (Object)null) && ((Object)(object)gameObject.GetComponent<TreeBase>() != (Object)null || (Object)(object)gameObject.GetComponent<TreeLog>() != (Object)null || (Object)(object)gameObject.GetComponent<Destructible>() != (Object)null || (Object)(object)gameObject.GetComponent<MineRock>() != (Object)null || (Object)(object)gameObject.GetComponent<MineRock5>() != (Object)null || (Object)(object)gameObject.GetComponent<Pickable>() != (Object)null)) { Vector3 position = gameObject.transform.position; if (!(Mathf.Abs(ZoneSystem.instance.GetGroundHeight(position) - target) < 0.3f)) { hashSet.Add(componentInParent); componentInParent.ClaimOwnership(); ZNetScene.instance.Destroy(gameObject); } } } } } internal static class TerritoryVisuals { private class Vis { public LineRenderer Ground; public LineRenderer Curtain1; public LineRenderer Curtain2; public List<GameObject> Posts = new List<GameObject>(); public Vector3 Center; public float Size; public Color Color; } private static readonly Dictionary<int, Vis> _vis = new Dictionary<int, Vis>(); private static Material _mat; private static float _timer; private static Material Mat { get { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown if ((Object)(object)_mat == (Object)null) { _mat = new Material(Shader.Find("Sprites/Default") ?? Shader.Find("Unlit/Color") ?? Shader.Find("Standard")); } return _mat; } } public static void Update(Player lp) { //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_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) _timer -= Time.deltaTime; if (_timer > 0f) { return; } _timer = 0.25f; Vector3 position = ((Component)lp).transform.position; bool flag = ((Character)lp).InPlaceMode(); GameObject hoverObject = ((Humanoid)lp).GetHoverObject(); bool flag2 = (Object)(object)hoverObject != (Object)null && (Object)(object)hoverObject.GetComponentInParent<GuildBanner>() != (Object)null; HashSet<int> keep = new HashSet<int>(); foreach (GuildSummary value2 in GuildClient.Summaries.Values) { if (!value2.HasBanner) { continue; } float num = value2.TerritorySize * 0.5f; float num2 = Mathf.Max(Mathf.Abs(position.x - value2.BannerPos.x), Mathf.Abs(position.z - value2.BannerPos.z)) - num; if (!(num2 > 150f)) { bool flag3 = !GuildClient.CanEnterTerritory(value2, GuildClient.LocalPid); bool flag4 = Mathf.Abs(num2) < 12f; bool enabled = flag || flag2 || (flag3 && flag4); bool enabled2 = flag3 && flag4 && GuildClient.Rules.TerritoryBarrier; keep.Add(value2.Id); if (!_vis.TryGetValue(value2.Id, out var value)) { value = Create(); _vis[value2.Id] = value; } if (value.Center != value2.BannerPos || value.Size != value2.TerritorySize || value.Color != value2.Color) { Rebuild(value, value2); } ((Renderer)value.Ground).enabled = enabled; ((Renderer)value.Curtain1).enabled = enabled2; ((Renderer)value.Curtain2).enabled = enabled2; } } foreach (int item in _vis.Keys.Where((int k) => !keep.Contains(k)).ToList()) { Destroy(_vis[item]); _vis.Remove(item); } } private static Vis Create() { return new Vis { Ground = Line("vo_border", 0.15f), Curtain1 = Line("vo_curtain1", 0.6f), Curtain2 = Line("vo_curtain2", 0.35f) }; } private static LineRenderer Line(string name, float width) { //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_000c: Expected O, but got Unknown GameObject val = new GameObject(name); Object.DontDestroyOnLoad((Object)val); LineRenderer obj = val.AddComponent<LineRenderer>(); ((Renderer)obj).material = Mat; obj.loop = true; obj.widthMultiplier = width; obj.useWorldSpace = true; ((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)obj).receiveShadows = false; ((Renderer)obj).enabled = false; return obj; } private static void Rebuild(Vis v, GuildSummary s) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //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_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: 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) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_0285: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_0331: Unknown result type (might be due to invalid IL or missing references) //IL_0333: Unknown result type (might be due to invalid IL or missing references) //IL_033d: Unknown result type (might be due to invalid IL or missing references) //IL_0342: Unknown result type (might be due to invalid IL or missing references) //IL_0353: Unknown result type (might be due to invalid IL or missing references) //IL_035d: Unknown result type (might be due to invalid IL or missing references) //IL_0373: Unknown result type (might be due to invalid IL or missing references) //IL_0378: Unknown result type (might be due to invalid IL or missing references) //IL_037a: Unknown result type (might be due to invalid IL or missing references) //IL_0389: Expected O, but got Unknown //IL_0302: Unknown result type (might be due to invalid IL or missing references) v.Center = s.BannerPos; v.Size = s.TerritorySize; v.Color = s.Color; float num = s.TerritorySize * 0.5f; List<Vector3> list = new List<Vector3>(); Vector2[] array = (Vector2[])(object)new Vector2[4] { new Vector2(0f - num, 0f - num), new Vector2(num, 0f - num), new Vector2(num, num), new Vector2(0f - num, num) }; Vector3 val4 = default(Vector3); for (int i = 0; i < 4; i++) { Vector2 val = array[i]; Vector2 val2 = array[(i + 1) % 4]; int num2 = Mathf.Max(1, Mathf.CeilToInt(Vector2.Distance(val, val2) / 2f)); for (int j = 0; j < num2; j++) { Vector2 val3 = Vector2.Lerp(val, val2, (float)j / (float)num2); ((Vector3)(ref val4))..ctor(s.BannerPos.x + val3.x, 0f, s.BannerPos.z + val3.y); val4.y = (((Object)(object)ZoneSystem.instance != (Object)null) ? (ZoneSystem.instance.GetGroundHeight(val4) + 0.15f) : s.BannerPos.y); list.Add(val4); } } Vector3[] pts = list.ToArray(); Set(v.Ground, pts, 0f, new Color(s.Color.r, s.Color.g, s.Color.b, 0.95f)); Set(v.Curtain1, pts, 1.2f, new Color(s.Color.r, s.Color.g, s.Color.b, 0.45f)); Set(v.Curtain2, pts, 2.6f, new Color(s.Color.r, s.Color.g, s.Color.b, 0.25f)); foreach (GameObject post in v.Posts) { if ((Object)(object)post != (Object)null) { Object.Destroy((Object)(object)post); } } v.Posts.Clear(); Vector2[] array2 = array; Vector3 val6 = default(Vector3); foreach (Vector2 val5 in array2) { ((Vector3)(ref val6))..ctor(s.BannerPos.x + val5.x, 0f, s.BannerPos.z + val5.y); val6.y = (((Object)(object)ZoneSystem.instance != (Object)null) ? ZoneSystem.instance.GetGroundHeight(val6) : s.BannerPos.y); GameObject val7 = Prefabs.VisualOf("wood_pole2") ?? Prefabs.VisualOf("wood_pole"); if ((Object)(object)val7 != (Object)null) { val7.transform.position = val6; v.Posts.Add(val7); } GameObject val8 = GameObject.CreatePrimitive((PrimitiveType)0); Object.Destroy((Object)(object)val8.GetComponent<Collider>()); val8.transform.position = val6 + Vector3.up * 2.1f; val8.transform.localScale = Vector3.one * 0.35f; val8.GetComponent<Renderer>().material = new Material(Mat) { color = s.Color }; v.Posts.Add(val8); } } private static void Set(LineRenderer lr, Vector3[] pts, float lift, Color c) { //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_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: 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_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) lr.positionCount = pts.Length; for (int i = 0; i < pts.Length; i++) { lr.SetPosition(i, pts[i] + Vector3.up * lift); } Color startColor = (lr.endColor = c); lr.startColor = startColor; } private static void Destroy(Vis v) { LineRenderer[] array = (LineRenderer[])(object)new LineRenderer[3] { v.Ground, v.Curtain1, v.Curtain2 }; foreach (LineRenderer val in array) { if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)((Component)val).gameObject); } } foreach (GameObject post in v.Posts) { if ((Object)(object)post != (Object)null) { Object.Destroy((Object)(object)post); } } } } [HarmonyPatch] internal static class TerritoryPatches { private static readonly FieldRef<WearNTear, ZNetView> WntView = AccessTools.FieldRefAccess<WearNTear, ZNetView>("m_nview"); private static readonly FieldRef<Piece, ZNetView> PieceView = AccessTools.FieldRefAccess<Piece, ZNetView>("m_nview"); private static ZDO Zdo(ZNetView nv) { if (!((Object)(object)nv != (Object)null) || !nv.IsValid()) { return null; } return nv.GetZDO(); } [HarmonyPatch(typeof(PrivateArea), "CheckAccess")] [HarmonyPostfix] private static void CheckAccess(Vector3 point, bool flash, ref bool __result) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) if (__result && Territory.LocalDenied(point, flash)) { __result = false; } } [HarmonyPatch(typeof(CraftingStation), "Interact")] [HarmonyPrefix] private static bool Station(CraftingStation __instance, ref bool __result) { return Gate((Component)(object)__instance, ref __result); } [HarmonyPatch(typeof(Bed), "Interact")] [HarmonyPrefix] private static bool BedUse(Bed __instance, ref bool __result) { return Gate((Component)(object)__instance, ref __result); } [HarmonyPatch(typeof(Fireplace), "Interact")] [HarmonyPrefix] private static bool Fire(Fireplace __instance, ref bool __result) { return Gate((Component)(object)__instance, ref __result); } [HarmonyPatch(typeof(Fireplace), "UseItem")] [HarmonyPrefix] private static bool FireItem(Fireplace __instance, ref bool __result) { return Gate((Component)(object)__instance, ref __result); } [HarmonyPatch(typeof(Smelter), "OnAddOre")] [HarmonyPrefix] private static bool SmeltOre(Smelter __instance, ref bool __result) { return Gate((Component)(object)__instance, ref __result, handled: false); } [HarmonyPatch(typeof(Smelter), "OnAddFuel")] [HarmonyPrefix] private static bool SmeltFuel(Smelter __instance, ref bool __result) { return Gate((Component)(object)__instance, ref __result, handled: false); } [HarmonyPatch(typeof(Smelter), "OnEmpty")] [HarmonyPrefix] private static bool SmeltEmpty(Smelter __instance, ref bool __result) { return Gate((Component)(object)__instance, ref __result, handled: false); } [HarmonyPatch(typeof(CookingStation), "OnAddFoodSwitch")] [HarmonyPrefix] private static bool CookFood(CookingStation __instance, ref bool __result) { return Gate((Component)(object)__instance, ref __result, handled: false); } [HarmonyPatch(typeof(CookingStation), "OnAddFuelSwitch")] [HarmonyPrefix] private static bool CookFuel(CookingStation __instance, ref bool __result) { return Gate((Component)(object)__instance, ref __result, handled: false); } [HarmonyPatch(typeof(CookingStation), "OnInteract")] [HarmonyPrefix] private static bool CookTake(CookingStation __instance, ref bool __result) { return Gate((Component)(object)__instance, ref __result, handled: false); } private static bool Gate(Component c, ref bool result, bool handled = true) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) if (!Territory.LocalDenied(c.transform.position, message: true)) { return true; } result = handled; return false; } [HarmonyPatch(typeof(Player), "TryPlacePiece")] [HarmonyPrefix] private static bool TryPlace(Player __instance, Piece piece, ref bool __result) { if (!GuildConfig.Enabled || (Object)(object)piece == (Object)null) { return true; } string text = Territory.PlacementError(__instance, piece); if (text == null) { return true; } Territory.DenyMessage(text); __result = false; return false; } [HarmonyPatch(typeof(Player), "CheckCanRemovePiece")] [HarmonyPostfix] private static void CanRemove(Piece piece, ref bool __result) { if (__result && GuildConfig.Enabled && !((Object)(object)piece == (Object)null) && (Object)(object)((Component)piece).GetComponent<GuildBanner>() != (Object)null) { GuildSummary owner = ((Component)piece).GetComponent<GuildBanner>().Owner; if (owner != null && (GuildClient.Mine == null || GuildClient.Mine.Id != owner.Id || !GuildClient.Has(Perm.Banner))) { Territory.DenyMessage("Only members with the Banner permission can take down the banner."); __result = false; } } } [HarmonyPatch(typeof(WearNTear), "RPC_Damage")] [HarmonyPrefix] private static bool Damage(WearNTear __instance, HitData hit) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) if (!GuildConfig.Enabled) { return true; } if ((Object)(object)((Component)__instance).GetComponent<GuildBanner>() != (Object)null) { return false; } GuildView guildView = GuildData.TerritoryAt(((Component)__instance).transform.position); if (guildView != null && guildView.HasBanner && hit != null) { float num = Defs.Tier(Defs.SturdyReduction, guildView.UpgradeLevel("SturdyWalls")); if (num > 0f) { hit.ApplyModifier(1f - num); } } return true; } [HarmonyPatch(typeof(WearNTear), "Destroy", new Type[] { typeof(HitData), typeof(bool) })] [HarmonyPrefix] private static void Destroyed(WearNTear __instance) { //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 (GuildConfig.Enabled && !((Object)(object)((Component)__instance).GetComponent<GuildBanner>() == (Object)null) && Zdo(WntView.Invoke(__instance)) != null) { Vector3 pos = ((Component)__instance).transform.position; GuildClient.Send(Op.BannerRemoved, delegate(ZPackage p) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) p.Write(pos); }); } } [HarmonyPatch(typeof(Player), "FixedUpdate")] [HarmonyPostfix] private static void Barrier(Player __instance) { if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer) { Territory.Barrier(__instance); } } [HarmonyPatch(typeof(PrivateArea), "Interact")] [HarmonyPrefix] private static bool WardInteract(PrivateArea __instance, Humanoid human, bool hold, bool alt, ref bool __result) { if (!GuildConfig.Enabled || !alt || hold || !GuildClient.Rules.GuildWards || (Object)(object)human != (Object)(object)Player.m_localPlayer) { return true; } Piece component = ((Component)__instance).GetComponent<Piece>(); if ((Object)(object)component == (Object)null || !component.IsCreator()) { return true; } __result = true; Guild mine = GuildClient.Mine; if (mine == null) { Notify.Show(MsgKind.Error, "You are not in a guild."); return false; } if (!GuildClient.Has(Perm.BindWards)) { Notify.Show(MsgKind.Error, "Your rank cannot bind wards."); return false; } ZNetView component2 = ((Component)__instance).GetComponent<ZNetView>(); if ((Object)(object)component2 == (Object)null || !component2.IsValid()) { return false; } component2.ClaimOwnership(); int num = ((component2.GetZDO().GetInt(Keys.Guild, 0) != mine.Id) ? mine.Id : 0); component2.GetZDO().Set(Keys.Guild, num, false); Notify.Show(MsgKind.Info, (num != 0) ? ("Ward bound to " + mine.Name + ".") : "Ward unbound from the guild."); return false; } [HarmonyPatch(typeof(PrivateArea), "IsPermitted")] [HarmonyPostfix] private static void WardPermitted(PrivateArea __instance, long playerID, ref bool __result) { if (__result || !GuildConfig.Enabled || !GuildClient.Rules.GuildWards) { return; } ZDO val = Zdo(((Component)__instance).GetComponent<ZNetView>()); if (val == null) { return; } int num = val.GetInt(Keys.Guild, 0); if (num != 0 && GuildClient.Summaries.TryGetValue(num, out var value)) { Piece component = ((Component)__instance).GetComponent<Piece>(); if (!((Object)(object)component == (Object)null) && value.IsMember(component.GetCreator()) && value.WardMemberIds.Contains(playerID)) { __result = true; } } } [HarmonyPatch(typeof(PrivateArea), "GetHoverText")] [HarmonyPostfix] private static void WardHover(PrivateArea __instance, ref string __result) { if (!GuildConfig.Enabled || !GuildClient.Rules.GuildWards) { return; } ZDO val = Zdo(((Component)__instance).GetComponent<ZNetView>()); if (val != null) { int num = val.GetInt(Keys.Guild, 0); if (num != 0 && GuildClient.Summaries.TryGetValue(num, out var value)) { __result = __result + "\n<color=#" + value.ColorHex + ">Guild ward: " + Util.Esc(value.Name) + " [" + value.Tag + "]</color>"; } Piece component = ((Component)__instance).GetComponent<Piece>(); if ((Object)(object)component != (Object)null && component.IsCreator() && GuildClient.Mine != null) { __result = __result + "\n[<color=yellow><b>Shift + E</b></color>] " + ((num == GuildClient.Mine.Id) ? "Unbind from guild" : "Bind to guild"); } } } } public enum Op { Create = 1, Apply, WithdrawApplication, Invite, AcceptInvite, DeclineInvite, AcceptApplication, DeclineApplication, Leave, Disband, Kick, Promote, Demote, TransferLeader, SetInfo, Rename, RankAdd, RankEdit, RankMove, RankRemove, VaultDeposit, VaultWithdraw, CoinDeposit, CoinWithdraw, Donate, Diplomacy, BuyUpgrade, ToggleBannerRespawn, Chat, PinAdd, PinRemove, BannerPlaced, BannerRemoved, BuildingPlaced, BuildingRemoved, SetBarracksSpawn, StatReport, BossKill, Intruder, Admin, RequestSync } public enum DiploAction { ProposeAlliance = 1, BreakAlliance, DeclareWar, OfferPeace, AcceptOffer, DeclineOffer, WithdrawOffer } public enum MsgKind { Info, Error, Center, GuildChat, Notice, Motd } public static class Rpc { public const string Op = "VO_G_Op"; public const string Sync = "VO_G_Sync"; public const string Pos = "VO_G_Pos"; public const string Msg = "VO_G_Msg"; public const string Give = "VO_G_Give"; } public class UpgradeDef { public string Id; public string Label; public string Effect; public bool PointsOnly; public string DefaultCost; public ConfigEntry<string> CostEntry; public UpgradeDef(string id, string label, string effect, bool pointsOnly, string cost) { Id = id; Label = label; Effect = effect; PointsOnly = pointsOnly; DefaultCost = cost; } } public class LevelCost { public int Points; public int MinLevel; public long Coins; public List<KeyValuePair<string, int>> Items = new List<KeyValuePair<string, int>>(); public static List<LevelCost> ParseLevels(string s) { List<LevelCost> list = new List<LevelCost>(); if (string.IsNullOrEmpty(s)) { return list; } string[] array = s.Split(';'); foreach (string obj in array) { LevelCost levelCost = new LevelCost(); string[] array2 = obj.Split(','); for (int j = 0; j < array2.Length; j++) { string text = array2[j].Trim(); if (text.Length == 0) { continue; } int num = text.IndexOf(':'); if (num > 0) { if (int.TryParse(text.Substring(num + 1), out var result) && result > 0) { levelCost.Items.Add(new KeyValuePair<string, int>(text.Substring(0, num).Trim(), result)); } continue; } char c = char.ToUpperInvariant(text[0]); if (long.TryParse(text.Substring(1), out var result2)) { switch (c) { case 'P': levelCost.Points = (int)result2; break; case 'C': levelCost.Coins = result2; break; case 'L': levelCost.MinLevel = (int)result2; break; } } } list.Add(levelCost); } return list; } public string Describe() { List<string> list = new List<string>(); if (Points > 0) { list.Add(Points + " point" + ((Points == 1) ? "" : "s")); } if (Coins > 0) { list.Add(Coins + " coins"); } foreach (KeyValuePair<string, int> item in Items) { list.Add(item.Value + " " + Util.ItemDisplayName(item.Key)); } if (MinLevel > 0) { list.Add("guild level " + MinLevel); } if (list.Count != 0) { return string.Join(", ", list.ToArray()); } return "free"; } } public class AchievementDef { public string Id; public string Label; public string Category; public string[] Stats; public long[] Tiers; public AchievementDef(string id, string label, string cat, string[] stats, long b, long s, long g) { Id = id; Label = label; Category = cat; Stats = stats; Tiers = new long[3] { b, s, g }; } } public static class Defs { public static readonly UpgradeDef[] Upgrades = new UpgradeDef[10] { new UpgradeDef("Territory", "Territory", "+{0} m territory side per level", pointsOnly: true, "P1;P1;P2;P2;P3;P3;P4;P4"), new UpgradeDef("Vault", "Vault", "+{0} vault stacks per level (equipment and materials)", pointsOnly: true, "P1;P1;P1;P2;P2;P2;P3;P3;P3;P4"), new UpgradeDef("Members", "Members", "+{0} member slots per level", pointsOnly: true, "P1;P1;P2;P2;P3;P3;P4;P4;P5;P5"), new UpgradeDef("Regeneration", "Regeneration", "+5 / 10 / 15 % health, stamina and eitr regeneration for all members", pointsOnly: false, "C500,Wood:100,Stone:100,Resin:20;C1500,L5,Bronze:20,Guck:10,Chain:5;C4000,L10,BlackMetal:20,Needle:20,Eitr:10"), new UpgradeDef("Comfort", "Comfort", "+1 / +2 comfort while resting for all members", pointsOnly: false, "C800,FineWood:40,DeerHide:10,Resin:20;C3000,L8,Silver:20,WolfPelt:10,Crystal:5"), new UpgradeDef("MonsterWard", "Monster ward", "No monster spawns or raids inside the territory", pointsOnly: false, "C2000,L3,SurtlingCore:10,Iron:20,Stone:100"), new UpgradeDef("SturdyWalls", "Sturdy walls", "-20 / 35 / 50 % damage to structures inside the territory", pointsOnly: false, "C500,Stone:150,Wood:100;C1500,L5,Iron:30,Stone:300;C4000,L10,BlackMetal:30,BlackMarble:100"), new UpgradeDef("Workshops", "Workshops", "Smelters, kilns, fermenters and cooking built by members +5 / 10 / 15 % faster", pointsOnly: false, "C600,Copper:20,Tin:20;C2000,L6,Iron:30,Coal:50;C5000,L12,BlackMetal:20,Coal:100"), new UpgradeDef("FertileSoil", "Fertile soil", "Crops planted by members grow +10 / 20 / 30 % faster", pointsOnly: false, "C400,Wood:50,Dandelion:10;C1500,L5,Turnip:20,Guck:10;C4000,L10,Barley:40,Flax:40"), new UpgradeDef("Respawn", "Respawn at the banner", "Members can choose to respawn at the guild banner", pointsOnly: false, "C1500,L4,SurtlingCore:4,FineWood:20") }; public static readonly float[] RegenBonus = new float[4] { 0f, 0.05f, 0.1f, 0.15f }; public static readonly int[] ComfortBonus = new int[3] { 0, 1, 2 }; public static readonly float[] SturdyReduction = new float[4] { 0f, 0.2f, 0.35f, 0.5f }; public static readonly float[] WorkshopBonus = new float[4] { 0f, 0.05f, 0.1f, 0.15f }; public static readonly float[] FertileBonus = new float[4] { 0f, 0.1f, 0.2f, 0.3f }; public static readonly AchievementDef[] Achievements = new AchievementDef[17] { new AchievementDef("slayer", "Monster slayers", "Combat", new string[1] { "EnemyKills" }, 250L, 2500L, 15000L), new AchievementDef("bosses", "Boss hunters", "Combat", new string[1] { "BossKills" }, 3L, 15L, 50L), new AchievementDef("archers", "Volley masters", "Combat", new string[1] { "ArrowsShot" }, 500L, 5000L, 30000L), new AchievementDef("crafters", "Master crafters", "Crafting", new string[1] { "Crafts" }, 100L, 1000L, 5000L), new AchievementDef("upgraders", "Fine tuning", "Crafting", new string[1] { "Upgrades" }, 25L, 250L, 1000L), new AchievementDef("cooks", "Hearth keepers", "Crafting", new string[2] { "CraftFood", "CraftGrill" }, 100L, 1000L, 5000L), new AchievementDef("lumber", "Lumberjacks", "Gathering", new string[1] { "Tree" }, 300L, 3000L, 15000L), new AchievementDef("miners", "Deep miners", "Gathering", new string[1] { "Mines" }, 200L, 2000L, 10000L), new AchievementDef("farmers", "Farmers", "Gathering", new string[4] { "HarvestCrop", "HarvestBerry", "HarvestMushroom", "HarvestVine" }, 300L, 3000L, 15000L), new AchievementDef("fishers", "Fishers", "Gathering", new string[1] { "FishCaught" }, 25L, 250L, 1000L), new AchievementDef("builders", "Builders", "Building", new string[1] { "Builds" }, 500L, 5000L, 25000L), new AchievementDef("tamers", "Beast tamers", "Building", new string[1] { "CreatureTamed" }, 5L, 50L, 200L), new AchievementDef("travelers", "Wanderers", "Exploration", new string[1] { "DistanceTraveled" }, 50000L, 500000L, 2500000L), new AchievementDef("sailors", "Seafarers", "Exploration", new string[1] { "DistanceSail" }, 10000L, 100000L, 500000L), new AchievementDef("portals", "Gatewalkers", "Exploration", new string[1] { "PortalsUsed" }, 50L, 500L, 2500L), new AchievementDef("sleepers", "Well rested", "Other", new string[1] { "Sleep" }, 25L, 250L, 1000L), new AchievementDef("keepers", "Beekeepers and tappers", "Other", new string[2] { "BeesHarvested", "SapHarvested" }, 25L, 250L, 1000L) }; public static readonly Dictionary<string, float> StatXp = new Dictionary<string, float> { { "EnemyKills", 2f }, { "Crafts", 1f }, { "Upgrades", 2f }, { "CraftFood", 0.5f }, { "CraftGrill", 0.5f }, { "Tree", 1f }, { "Mines", 1f }, { "HarvestCrop", 0.3f }, { "HarvestBerry", 0.1f }, { "HarvestMushroom", 0.2f }, { "HarvestVine", 0.3f }, { "FishCaught", 3f }, { "Builds", 0.2f }, { "CreatureTamed", 10f }, { "DistanceTraveled", 0.002f }, { "DistanceSail", 0.002f }, { "BeesHarvested", 1f }, { "SapHarvested", 1f } }; public static readonly Dictionary<string, long> StatCap = new Dictionary<string, long> { { "EnemyKills", 60L }, { "ArrowsShot", 200L }, { "Crafts", 120L }, { "Upgrades", 60L }, { "CraftFood", 60L }, { "CraftGrill", 60L }, { "Tree", 40L }, { "Mines", 60L }, { "HarvestCrop", 200L }, { "HarvestBerry", 200L }, { "HarvestMushroom", 100L }, { "HarvestVine", 100L }, { "FishCaught", 15L }, { "Builds", 200L }, { "CreatureTamed", 5L }, { "DistanceTraveled", 3000L }, { "DistanceSail", 3000L }, { "PortalsUsed", 20L }, { "Sleep", 2L }, { "BeesHarvested", 20L }, { "SapHarvested", 20L } }; public const string DefaultEmblems = "TrophyEikthyr,TrophyTheElder,TrophyBonemass,TrophyDragonQueen,TrophyGoblinKing,TrophySeekerQueen,TrophyFader,TrophyDeer,TrophyBoar,TrophyNeck,TrophyGreydwarf,TrophyGreydwarfBrute,TrophyGreydwarfShaman,TrophyTroll,TrophySkeleton,TrophyDraugr,TrophyDraugrElite,TrophyBlob,TrophyWraith,TrophyLeech,TrophyWolf,TrophyFenring,TrophyHatchling,TrophySGolem,TrophyGoblin,TrophyGoblinBrute,TrophyGoblinShaman,TrophyLox,TrophyDeathsquito,TrophyGrowth,TrophySeeker,TrophySeekerBrute,TrophyTick,TrophyGjall,TrophyDvergr,TrophyHare,TrophySerpent,TrophyAbomination,TrophyCultist,TrophyUlv,TrophyBjorn,TrophyAsksvin,TrophyCharredMelee,TrophyMorgen,TrophyFallenValkyrie"; public const string DefaultBosses = "Eikthyr,gd_king,Bonemass,Dragon,GoblinKing,SeekerQueen,Fader"; public static UpgradeDef Upgrade(string id) { UpgradeDef[] upgrades = Upgrades; foreach (UpgradeDef upgradeDef in upgrades) { if (upgradeDef.Id == id) { return upgradeDef; } } return null; } public static float Tier(float[] table, int level) { return table[Math.Max(0, Math.Min(level, table.Length - 1))]; } public static int Tier(int[] table, int level) { return table[Math.Max(0, Math.Min(level, table.Length - 1))]; } } public class Rules { public long CreateCost = 1000L; public int MaxMembers = 15; public int MaxRanks = 8; public int VaultSlots = 40; public int GearSlots = 40; public int InviteExpireHours = 48; public int RejoinCooldownHours = 12; public bool AllowApplications = true; public bool GuildWards = true; public bool GuildChat = true; public string BlockedVaultItems = ""; public string Emblems = "TrophyEikthyr,TrophyTheElder,TrophyBonemass,TrophyDragonQueen,TrophyGoblinKing,TrophySeekerQueen,TrophyFader,TrophyDeer,TrophyBoar,TrophyNeck,TrophyGreydwarf,TrophyGreydwarfBrute,TrophyGreydwarfShaman,TrophyTroll,TrophySkeleton,TrophyDraugr,TrophyDraugrElite,TrophyBlob,TrophyWraith,TrophyLeech,TrophyWolf,TrophyFenring,TrophyHatchling,TrophySGolem,TrophyGoblin,TrophyGoblinBrute,TrophyGoblinShaman,TrophyLox,TrophyDeathsquito,TrophyGrowth,TrophySeeker,TrophySeekerBrute,TrophyTick,TrophyGjall,TrophyDvergr,TrophyHare,TrophySerpent,TrophyAbomination,TrophyCultist,TrophyUlv,TrophyBjorn,TrophyAsksvin,TrophyCharredMelee,TrophyMorgen,TrophyFallenValkyrie"; public int LevelXpBase = 1000; public float LevelXpGrowth = 1.25f; public int MaxLevel = 30; public int PointsPerLevel = 1; public int StartingPoints = 1; public float ActivityXpMultiplier = 1f; public int XpBossFirstKill = 1500; public int XpBossKill = 150; public int XpBronze = 300; public int XpSilver = 1000; public int XpGold = 3000; public int DonationCoinsPerXp = 10; public string BossNames = "Eikthyr,gd_king,Bonemass,Dragon,GoblinKing,SeekerQueen,Fader"; public bool TerritoryClaim = true; public bool TerritoryBarrier = true; public bool AlliesCanEnter = true; public bool TerritoryLevelling = true; public bool UpgradeOnlyAtBanner = true; public float TerritoryBaseSize = 70f; public float TerritorySizePerUpgrade = 10f; public float TerritoryGap = 20f; public int VaultSlotsPerUpgrade = 10; public int MembersPerUpgrade = 5; public string BannerRecipe = "Wood:20,LeatherScraps:8,DeerHide:4,Resin:4"; public bool ShareMemberPositions = true; public int MaxGuildPins = 100; public bool IntruderAlerts = true; public bool WarEnablesPvP = true; public bool NoFriendlyFire = true; public Dictionary<string, string> UpgradeCosts = new Dictionary<string, string>(); [NonSerialized] private HashSet<string> _blocked; [NonSerialized] private List<string> _emblems; [NonSerialized] private HashSet<string> _bosses; [NonSerialized] private Dictionary<string, List<LevelCost>> _costs; public HashSet<string> Blocked { get { if (_blocked == null) { _blocked = new HashSet<string>(Split(BlockedVaultItems)); } return _blocked; } } public List<string> EmblemList { get { if (_emblems == null) { _emblems = new List<string>(Split(Emblems)); } return _emblems; } } public HashSet<string> Bosses { get { if (_bosses == null) { _bosses = new HashSet<string>(Split(BossNames)); } return _bosses; } } public List<LevelCost> CostsFor(string upgradeId) { if (_costs == null) { _costs = new Dictionary<string, List<LevelCost>>(); } if (!_costs.TryGetValue(upgradeId, out var value)) { if (!UpgradeCosts.TryGetValue(upgradeId, out var value2)) { UpgradeDef upgradeDef = Defs.Upgrade(upgradeId); value2 = ((upgradeDef == null) ? "" : upgradeDef.DefaultCost); } value = LevelCost.ParseLevels(value2); _costs[upgradeId] = value; } return value; } public int MaxUpgradeLevel(string id) { return CostsFor(id).Count; } public long XpForLevel(int level) { return (long)Math.Round((double)LevelXpBase * Math.Pow(LevelXpGrowth, Math.Max(0, level - 1))); } public float TerritorySize(int territoryUpgrade) { return TerritoryBaseSize + TerritorySizePerUpgrade * (float)territoryUpgrade; } public int MembersMax(int membersUpgrade) { return MaxMembers + MembersPerUpgrade * membersUpgrade; } public int ArmoryCapacity(Guild g) { return GearSlots + VaultSlotsPerUpgrade * g.UpgradeLevel("Vault"); } public int WarehouseCapacity(Guild g) { return VaultSlots + VaultSlotsPerUpgrade * g.UpgradeLevel("Vault"); } private static IEnumerable<string> Split(string s) { if (string.IsNullOrEmpty(s)) { yield break; } string[] array = s.Split(','); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length > 0) { yield return text; } } } public void Write(ZPackage p) { p.Write(CreateCost); p.Write(MaxMembers); p.Write(MaxRanks); p.Write(VaultSlots); p.Write(GearSlots); p.Write(InviteExpireHours); p.Write(RejoinCooldownHours); p.Write(AllowApplications); p.Write(GuildWards); p.Write(GuildChat); p.Write(BlockedVaultItems); p.Write(Emblems); p.Write(LevelXpBase); p.Write(LevelXpGrowth); p.Write(MaxLevel); p.Write(PointsPerLevel); p.Write(StartingPoints); p.Write(ActivityXpMultiplier); p.Write(XpBossFirstKill); p.Write(XpBossKill); p.Write(XpBronze); p.Write(XpSilver); p.Write(XpGold); p.Write(DonationCoinsPerXp); p.Write(BossNames); p.Write(TerritoryClaim); p.Write(TerritoryBarrier); p.Write(AlliesCanEnter); p.Write(TerritoryLevelling); p.Write(UpgradeOnlyAtBanner); p.Write(TerritoryBaseSize); p.Write(TerritorySizePerUpgrade); p.Write(TerritoryGap); p.Write(VaultSlotsPerUpgrade); p.Write(MembersPerUpgrade); p.Write(BannerRecipe); p.Write(ShareMemberPositions); p.Write(MaxGuildPins); p.Write(IntruderAlerts); p.Write(WarEnablesPvP); p.Write(NoFriendlyFire); WriteMap(p, UpgradeCosts); } public static Rules Read(ZPackage p) { return new Rules { CreateCost = p.ReadLong(), MaxMembers = p.ReadInt(), MaxRanks = p.ReadInt(), VaultSlots = p.ReadInt(), GearSlots = p.ReadInt(), InviteExpireHours = p.ReadInt(), RejoinCooldownHours = p.ReadInt(), AllowApplications = p.ReadBool(), GuildWards = p.ReadBool(), GuildChat = p.ReadBool(), BlockedVaultItems = p.ReadString(), Emblems = p.ReadString(), LevelXpBase = p.ReadInt(), LevelXpGrowth = p.ReadSingle(), MaxLevel = p.ReadInt(), PointsPerLevel = p.ReadInt(), StartingPoints = p.ReadInt(), ActivityXpMultiplier = p.ReadSingle(), XpBossFirstKill = p.ReadInt(), XpBossKill = p.ReadInt(), XpBronze = p.ReadInt(), XpSilver = p.ReadInt(), XpGold = p.ReadInt(), DonationCoinsPerXp = p.ReadInt(), BossNames = p.ReadString(), TerritoryClaim = p.ReadBool(), TerritoryBarrier = p.ReadBool(), AlliesCanEnter = p.ReadBool(), TerritoryLevelling = p.ReadBool(), UpgradeOnlyAtBanner = p.ReadBool(), TerritoryBaseSize = p.ReadSingle(), TerritorySizePerUpgrade = p.ReadSingle(), TerritoryGap = p.ReadSingle(), VaultSlotsPerUpgrade = p.ReadInt(), MembersPerUpgrade = p.ReadInt(), BannerRecipe = p.ReadString(), ShareMemberPositions = p.ReadBool(), MaxGuildPins = p.ReadInt(), IntruderAlerts = p.ReadBool(), WarEnablesPvP = p.ReadBool(), NoFriendlyFire = p.ReadBool(), UpgradeCosts = ReadMap(p) }; } private static void WriteMap(ZPackage p, Dictionary<string, string> m) { p.Write(m.Count); foreach (KeyValuePair<string, string> item in m) { p.Write(item.Key); p.Write(item.Value); } } private static Dictionary<string, string> ReadMap(ZPackage p) { Dictionary<string, string> dictionary = new Dictionary<string, string>(); int num = p.ReadInt(); for (int i = 0; i < num; i++) { dictionary[p.ReadString()] = p.ReadString(); } return dictionary; } } [HarmonyPatch] internal static class EffectPatches { private static readonly FieldRef<SEMan, Character> SemanChar = AccessTools.FieldRefAccess<SEMan, Character>("m_character"); private static GuildView LocalGuild { get { if (!GuildConfig.Enabled || (Object)(object)Player.m_localPlayer == (Object)null) { return null; } GuildView guildView = GuildData.OfPlayer(Player.m_localPlayer.GetPlayerID()); if (guildView == null || !guildView.HasBanner) { return null; } return guildView; } } private static GuildView CreatorGuild(Component c) { if (!GuildConfig.Enabled) { return null; } Piece component = c.GetComponent<Piece>(); if ((Object)(object)component == (Object)null) { return null; } GuildView guildView = GuildData.OfPlayer(component.GetCreator()); if (guildView == null || !guildView.HasBanner) { return null; } return guildView; } private static float RegenBonus(SEMan seman) { if ((Object)(object)SemanChar.Invoke(seman) != (Object)(object)Player.m_localPlayer) { return 0f; } GuildView localGuild = LocalGuild; if (localGuild != null) { return Defs.Tier(Defs.RegenBonus, localGuild.UpgradeLevel("Regeneration")); } return 0f; } [HarmonyPatch(typeof(SEMan), "ModifyHealthRegen")] [HarmonyPostfix] private static void HealthRegen(SEMan __instance, ref float regenMultiplier) { regenMultiplier += RegenBonus(__instance); } [HarmonyPatch(typeof(SEMan), "ModifyStaminaRegen")] [HarmonyPostfix] private static void StaminaRegen(SEMan __instance, ref float staminaMultiplier) { staminaMultiplier += RegenBonus(__instance); } [HarmonyPatch(typeof(SEMan), "ModifyEitrRegen")] [HarmonyPostfix] private static void EitrRegen(SEMan __instance, ref float eitrMultiplier) { eitrMultiplier += RegenBonus(__instance); } [HarmonyPatch(typeof(SE_Rested), "CalculateComfortLevel", new Type[] { typeof(bool), typeof(Vector3) })] [HarmonyPostfix] private static void Comfort(bool inShelter, Vector3 position, ref int __result) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (inShelter && !((Object)(object)localPlayer == (Object)null) && !(Vector3.Distance(((Component)localPlayer).transform.position, position) > 1f)) { GuildView localGuild = LocalGuild; if (localGuild != null) { __result += Defs.Tier(Defs.ComfortBonus, localGuild.UpgradeLevel("Comfort")); } } } [HarmonyPatch(typeof(SpawnSystem), "IsSpawnPointGood")] [HarmonyPostfix] private static void NoSpawn(ref Vector3 spawnPoint, ref bool __result) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) if (__result && GuildConfig.Enabled) { GuildView guildView = GuildData.TerritoryAt(spawnPoint); if (guildView != null && guildView.UpgradeLevel("MonsterWard") > 0) { __result = false; } } } [HarmonyPatch(typeof(RandEventSystem), "GetValidEventPoints")] [HarmonyPostfix] private static void NoRaids(List<Vector3> __result) { if (GuildConfig.Enabled) { __result?.RemoveAll(delegate(Vector3 p) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) GuildView guildView = GuildData.TerritoryAt(p); return guildView != null && guildView.UpgradeLevel("MonsterWard") > 0; }); } } private static double WorkshopFactor(Component c) { GuildView guildView = CreatorGuild(c); if (guildView != null) { return 1.0 + (double)Defs.Tier(Defs.WorkshopBonus, guildView.UpgradeLevel("Workshops")); } return 1.0; } [HarmonyPatch(typeof(Smelter), "GetDeltaTime")] [HarmonyPostfix] private static void SmelterTime(Smelter __instance, ref double __result) { if (__result > 0.0) { __result *= WorkshopFactor((Component)(object)__instance); } } [HarmonyPatch(typeof(CookingStation), "GetDeltaTime")] [HarmonyPostfix] private static void CookTime(CookingStation __instance, ref float __result) { if (__result > 0f) { __result *= (float)WorkshopFactor((Component)(object)__instance); } } [HarmonyPatch(typeof(Fermenter), "GetFermentationTime")] [HarmonyPostfix] private static void FermentTime(Fermenter __instance, ref double __result) { if (__result > 0.0) { __result *= WorkshopFactor((Component)(object)__instance); } } [HarmonyPatch(typeof(Plant), "GetGrowTime")] [HarmonyPostfix] private static void GrowTime(Plant __instance, ref float __result) { GuildView guildView = CreatorGuild((Component)(object)__instance); if (guildView != null) { float num = Defs.Tier(Defs.FertileBonus, guildView.UpgradeLevel("FertileSoil")); if (num > 0f) { __result /= 1f + num; } } } [HarmonyPatch(typeof(Game), "FindSpawnPoint")] [HarmonyPrefix] private static bool Respawn(Game __instance, ref Vector3 point, ref bool usedLogoutPoint, ref bool __result) { //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_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) if (!GuildConfig.Enabled || !Traverse.Create((object)__instance).Field("m_respawnAfterDeath").GetValue<bool>()) { return true; } Guild mine = GuildClient.Mine; if (mine == null) { return true; } Member member = mine.GetMember(GuildClient.MyPid); if (member == null) { return true; } if (member.BannerRespawn && mine.HasBanner && mine.UpgradeLevel("Respawn") > 0) { Vector3 bannerPos = mine.BannerPos; ZNet.instance.SetReferencePosition(bannerPos); usedLogoutPoint = false; if (!ZNetScene.instance.IsAreaReady(bannerPos)) { point = Vector3.zero; __result = false; return false; } Vector3 val = bannerPos + new Vector3(2f, 0f, 2f); float y = default(float); if (ZoneSystem.instance.GetSolidHeight(val, ref y, 1000)) { val.y = y; } point = val + Vector3.up * 0.5f; __result = true; return false; } return true; } private static int WarState(Character a, Character b) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) if (!GuildConfig.Enabled || (Object)(object)a == (Object)null || (Object)(object)b == (Object)null || (Object)(object)a == (Object)(object)b || !a.IsPlayer() || !b.IsPlayer()) { return 0; } GuildSummary guildSummary = GuildClient.GuildOfPlayer(((Player)a).GetPlayerID()); GuildSummary guildSummary2 = GuildClient.GuildOfPlayer(((Player)b).GetPlayerID()); if (guildSummary == null || guildSummary2 == null) { return 0; } Relation relation = GuildClient.RelationBetween(guildSummary.Id, guildSummary2.Id); if (relation == Relation.War && GuildClient.Rules.WarEnablesPvP) { return 1; } if (relation == Relation.Alliance && GuildClient.Rules.NoFriendlyFire) { return -1; } return 0; } [HarmonyPatch(typeof(BaseAI), "IsEnemy", new Type[] { typeof(Character), typeof(Character) })] [HarmonyPostfix] private static void IsEnemy(Character a, Character b, ref bool __result) { if (WarState(a, b) == 1) { __result = true; } } [HarmonyPatch(typeof(Character), "Damage")] [HarmonyPrefix] private static bool Damage(Character __instance, HitData hit) { if (hit == null) { return true; } switch (WarState(hit.GetAttacker(), __instance)) { case 1: hit.m_ignorePVP = true; break; case -1: return false; } return true; } } public static class ConfigReload { private static ConfigFile _config; private static FileSystemWatcher _watcher; private static volatile bool _pending; private static DateTime _lastApply; public static bool Pending => _pending; public static void Watch(ConfigFile config) { _config = config; try { string configFilePath = config.ConfigFilePath; _watcher = new FileSystemWatcher(Path.GetDirectoryName(configFilePath), Path.GetFileName(configFilePath)); _watcher.NotifyFilter = NotifyFilters.Size | NotifyFilters.LastWrite; _watcher.Changed += delegate { _pending = true; }; _watcher.EnableRaisingEvents = true; } catch (Exception ex) { Plugin.Log.LogWarning((object)("Config file watcher unavailable: " + ex.Message)); } } public static voi