using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Managers; using Microsoft.CodeAnalysis; using Splatform; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("VentureValheim.MultiplayerTweaks")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("VentureValheim.MultiplayerTweaks")] [assembly: AssemblyCopyright("Copyright © 2022")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("18EFA4BF-41BC-4ABE-916B-34F034DD5DCE")] [assembly: AssemblyFileVersion("0.11.8")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.11.8.0")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace VentureValheim.MultiplayerTweaks { [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("com.orianaventure.mod.MultiplayerTweaks", "MultiplayerTweaks", "0.11.8")] public class MultiplayerTweaksPlugin : BaseUnityPlugin { private const string ModName = "MultiplayerTweaks"; private const string ModVersion = "0.11.8"; private const string Author = "com.orianaventure.mod"; private const string ModGUID = "com.orianaventure.mod.MultiplayerTweaks"; private static string ConfigFileName = "com.orianaventure.mod.MultiplayerTweaks.cfg"; private static string ConfigFileFullPath; private readonly Harmony HarmonyInstance = new Harmony("com.orianaventure.mod.MultiplayerTweaks"); public static readonly ManualLogSource MultiplayerTweaksLogger; internal static ConfigEntry CE_AdminBypass; internal static ConfigEntry CE_GameDayOffset; internal static ConfigEntry CE_OverridePlayerPVP; internal static ConfigEntry CE_ForcePlayerPVPOn; internal static ConfigEntry CE_TeleportOnAnyDeath; internal static ConfigEntry CE_TeleportOnPVPDeath; internal static ConfigEntry CE_SkillLossOnAnyDeath; internal static ConfigEntry CE_SkillLossOnPVPDeath; internal static ConfigEntry CE_HidePlatformTag; internal static ConfigEntry CE_PlayerDefaultSpawnPoint; internal static ConfigEntry CE_EnableValkrie; internal static ConfigEntry CE_EnableArrivalMessage; internal static ConfigEntry CE_EnableArrivalMessageShout; internal static ConfigEntry CE_OverrideArrivalMessage; internal static ConfigEntry CE_EnableTempleMapPin; internal static ConfigEntry CE_EnableHaldorMapPin; internal static ConfigEntry CE_EnableHildirMapPin; internal static ConfigEntry CE_EnableBogWitchMapPin; internal static ConfigEntry CE_OverridePlayerMapPins; internal static ConfigEntry CE_ForcePlayerMapPinsOn; internal static ConfigEntry CE_AllowMapPings; internal static ConfigEntry CE_AllowShoutPings; private readonly ConfigurationManagerAttributes AdminConfig = new ConfigurationManagerAttributes { IsAdminOnly = true }; private readonly ConfigurationManagerAttributes ClientConfig = new ConfigurationManagerAttributes { IsAdminOnly = false }; public static bool GetAdminBypass() { return CE_AdminBypass.Value; } public static int GetGameDayOffset() { return CE_GameDayOffset.Value; } public static bool GetOverridePlayerPVP() { if (GetAdminBypass() && SynchronizationManager.Instance.PlayerIsAdmin) { return false; } return CE_OverridePlayerPVP.Value; } public static bool GetForcePlayerPVPOn() { return CE_ForcePlayerPVPOn.Value; } public static bool GetTeleportOnAnyDeath() { return CE_TeleportOnAnyDeath.Value; } public static bool GetTeleportOnPVPDeath() { return CE_TeleportOnPVPDeath.Value; } public static bool GetSkillLossOnAnyDeath() { return CE_SkillLossOnAnyDeath.Value; } public static bool GetSkillLossOnPVPDeath() { return CE_SkillLossOnPVPDeath.Value; } public static bool GetHidePlatformTag() { return CE_HidePlatformTag.Value; } public static string GetPlayerDefaultSpawnPoint() { return CE_PlayerDefaultSpawnPoint.Value; } public static bool GetEnableValkrie() { return CE_EnableValkrie.Value; } public static bool GetEnableArrivalMessage() { return CE_EnableArrivalMessage.Value; } public static bool GetEnableArrivalMessageShout() { return CE_EnableArrivalMessageShout.Value; } public static string GetOverrideArrivalMessage() { return CE_OverrideArrivalMessage.Value; } public static bool GetEnableTempleMapPin() { if (GetAdminBypass() && SynchronizationManager.Instance.PlayerIsAdmin) { return true; } return CE_EnableTempleMapPin.Value; } public static bool GetEnableHaldorMapPin() { if (GetAdminBypass() && SynchronizationManager.Instance.PlayerIsAdmin) { return true; } return CE_EnableHaldorMapPin.Value; } public static bool GetEnableHildirMapPin() { if (GetAdminBypass() && SynchronizationManager.Instance.PlayerIsAdmin) { return true; } return CE_EnableHildirMapPin.Value; } public static bool GetEnableBogWitchMapPin() { if (GetAdminBypass() && SynchronizationManager.Instance.PlayerIsAdmin) { return true; } return CE_EnableBogWitchMapPin.Value; } public static bool GetOverridePlayerMapPins() { if (GetAdminBypass() && SynchronizationManager.Instance.PlayerIsAdmin) { return false; } return CE_OverridePlayerMapPins.Value; } public static bool GetForcePlayerMapPinsOn() { return CE_ForcePlayerMapPinsOn.Value; } public static bool GetAllowMapPings() { if (GetAdminBypass() && SynchronizationManager.Instance.PlayerIsAdmin) { return true; } return CE_AllowMapPings.Value; } public static bool GetAllowShoutPings() { if (GetAdminBypass() && SynchronizationManager.Instance.PlayerIsAdmin) { return true; } return CE_AllowShoutPings.Value; } private void AddConfig(string key, string section, string description, bool synced, T value, ref ConfigEntry configEntry) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown string extendedDescription = GetExtendedDescription(description, synced); configEntry = ((BaseUnityPlugin)this).Config.Bind(section, key, value, new ConfigDescription(extendedDescription, (AcceptableValueBase)null, new object[1] { synced ? AdminConfig : ClientConfig })); } public string GetExtendedDescription(string description, bool synchronizedSetting) { return description + (synchronizedSetting ? " [Synced with Server]" : " [Not Synced with Server]"); } public void Awake() { ((BaseUnityPlugin)this).Config.SaveOnConfigSet = false; AddConfig("AdminBypass", "General", "True to allow admins to bypass some setting restrictions (boolean).", synced: true, value: false, ref CE_AdminBypass); AddConfig("GameDayOffset", "General", "Number to offset the game day display (int).", synced: true, 0, ref CE_GameDayOffset); AddConfig("OverridePlayerPVP", "General", "Override Player pvp behavior (boolean).", synced: true, value: false, ref CE_OverridePlayerPVP); AddConfig("ForcePlayerPVPOn", "General", "True to set pvp always on when OverridePlayerPVP is True (boolean).", synced: true, value: true, ref CE_ForcePlayerPVPOn); AddConfig("TeleportOnAnyDeath", "General", "False to respawn players at their graves on any death (boolean).", synced: true, value: true, ref CE_TeleportOnAnyDeath); AddConfig("TeleportOnPVPDeath", "General", "False to respawn players at their graves on a PVP death (boolean).", synced: true, value: true, ref CE_TeleportOnPVPDeath); AddConfig("SkillLossOnAnyDeath", "General", "False to prevent skill loss on any death (boolean).", synced: true, value: true, ref CE_SkillLossOnAnyDeath); AddConfig("SkillLossOnPVPDeath", "General", "False to prevent skill loss on a PVP death (boolean).", synced: true, value: true, ref CE_SkillLossOnPVPDeath); AddConfig("HidePlatformTag", "General", "When true hides steam/xbox platform tags from pings and chat messages (boolean).", synced: true, value: false, ref CE_HidePlatformTag); AddConfig("PlayerDefaultSpawnPoint", "Arrival", "Coordinates for the default player spawn point (x,y,z) no parentheses, leave empty to use game default (comma-separated floats).", synced: true, "", ref CE_PlayerDefaultSpawnPoint); AddConfig("EnableValkrie", "Arrival", "True to enable Valkrie Intro (boolean).", synced: true, value: true, ref CE_EnableValkrie); AddConfig("EnableArrivalMessage", "Arrival", "True to enable Arrival Message on player login (boolean).", synced: true, value: true, ref CE_EnableArrivalMessage); AddConfig("UseArrivalShout", "Arrival", "False to use a Normal message when EnableArrivalMessage is True (boolean).", synced: true, value: true, ref CE_EnableArrivalMessageShout); AddConfig("OverrideArrivalMessage", "Arrival", "Set a new arrival message, leave blank to use default (string).", synced: true, "", ref CE_OverrideArrivalMessage); AddConfig("EnableTempleMapPin", "Map", "False to hide Starting Temple map pin on Minimap (boolean).", synced: true, value: true, ref CE_EnableTempleMapPin); AddConfig("EnableHaldorMapPin", "Map", "False to hide Haldor map pin on Minimap (boolean).", synced: true, value: true, ref CE_EnableHaldorMapPin); AddConfig("EnableHildirMapPin", "Map", "False to hide Hildir map pin on Minimap (boolean).", synced: true, value: true, ref CE_EnableHildirMapPin); AddConfig("EnableBogWitchMapPin", "Map", "False to hide Bog Witch map pin on Minimap (boolean).", synced: true, value: true, ref CE_EnableBogWitchMapPin); AddConfig("OverridePlayerMapPositions", "Map", "Override Player map pin position behavior for Minimap (boolean).", synced: true, value: false, ref CE_OverridePlayerMapPins); AddConfig("ForcePlayerMapPositionOn", "Map", "True to always show Player position on Minimap when OverridePlayerMapPositions is True (boolean).", synced: true, value: true, ref CE_ForcePlayerMapPinsOn); AddConfig("AllowMapPings", "Map", "False to disable pings on the map from players (boolean).", synced: true, value: true, ref CE_AllowMapPings); AddConfig("AllowShoutPings", "Map", "False to disable pings on the map when players shout messages (boolean).", synced: true, value: true, ref CE_AllowShoutPings); ((BaseUnityPlugin)this).Config.Save(); ((BaseUnityPlugin)this).Config.SaveOnConfigSet = true; MultiplayerTweaksLogger.LogInfo((object)"Watch me Tweak, now watch me Neigh Neigh."); Assembly executingAssembly = Assembly.GetExecutingAssembly(); HarmonyInstance.PatchAll(executingAssembly); SetupWatcher(); } private void OnDestroy() { ((BaseUnityPlugin)this).Config.Save(); } private void SetupWatcher() { FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Paths.ConfigPath, ConfigFileName); fileSystemWatcher.Changed += ReadConfigValues; fileSystemWatcher.Created += ReadConfigValues; fileSystemWatcher.Renamed += ReadConfigValues; fileSystemWatcher.IncludeSubdirectories = true; fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject; fileSystemWatcher.EnableRaisingEvents = true; } private void ReadConfigValues(object sender, FileSystemEventArgs e) { if (!File.Exists(ConfigFileFullPath)) { return; } try { MultiplayerTweaksLogger.LogDebug((object)"Attempting to reload configuration..."); ((BaseUnityPlugin)this).Config.Reload(); } catch { MultiplayerTweaksLogger.LogError((object)("There was an issue loading " + ConfigFileName)); } } static MultiplayerTweaksPlugin() { string configPath = Paths.ConfigPath; char directorySeparatorChar = Path.DirectorySeparatorChar; ConfigFileFullPath = configPath + directorySeparatorChar + ConfigFileName; MultiplayerTweaksLogger = Logger.CreateLogSource("MultiplayerTweaks"); CE_AdminBypass = null; CE_GameDayOffset = null; CE_OverridePlayerPVP = null; CE_ForcePlayerPVPOn = null; CE_TeleportOnAnyDeath = null; CE_TeleportOnPVPDeath = null; CE_SkillLossOnAnyDeath = null; CE_SkillLossOnPVPDeath = null; CE_HidePlatformTag = null; CE_PlayerDefaultSpawnPoint = null; CE_EnableValkrie = null; CE_EnableArrivalMessage = null; CE_EnableArrivalMessageShout = null; CE_OverrideArrivalMessage = null; CE_EnableTempleMapPin = null; CE_EnableHaldorMapPin = null; CE_EnableHildirMapPin = null; CE_EnableBogWitchMapPin = null; CE_OverridePlayerMapPins = null; CE_ForcePlayerMapPinsOn = null; CE_AllowMapPings = null; CE_AllowShoutPings = null; } } public class ArrivalTweaks { [HarmonyPatch(typeof(Game), "UpdateRespawn")] public static class Patch_Game_UpdateRespawn { private static IEnumerable Transpiler(IEnumerable instructions) { //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Expected O, but got Unknown List list = new List(instructions); MethodInfo obj = AccessTools.Method(typeof(Chat), "SendText", (Type[])null, (Type[])null); for (int i = 5; i < list.Count; i++) { if (list[i].opcode == OpCodes.Callvirt) { object operand = list[i].operand; if (operand != null && operand.Equals(obj)) { list[i - 5].opcode = OpCodes.Nop; list[i - 4].opcode = OpCodes.Nop; list[i - 3].opcode = OpCodes.Nop; list[i - 2].opcode = OpCodes.Nop; list[i - 1].opcode = OpCodes.Nop; MethodInfo methodInfo = AccessTools.Method(typeof(ArrivalTweaks), "SendArrivalMessage", (Type[])null, (Type[])null); list[i] = new CodeInstruction(OpCodes.Call, (object)methodInfo); break; } } } return list.AsEnumerable(); } } [HarmonyPatch(typeof(Game), "SpawnPlayer")] public static class Patch_Game_SpawnPlayer { private static void Prefix(Game __instance, ref Vector3 spawnPoint, ref bool spawnValkyrie) { if (spawnValkyrie && !MultiplayerTweaksPlugin.GetEnableValkrie()) { spawnValkyrie = false; if (__instance.m_inIntro) { __instance.SkipIntro(); } } if (MultiplayerTweaksPlugin.GetOverridePlayerMapPins()) { ZNet.instance.SetPublicReferencePosition(MultiplayerTweaksPlugin.GetForcePlayerMapPinsOn()); } } } [HarmonyPatch(typeof(Game), "ShowIntro")] public static class Patch_Game_ShowIntro { private static bool Prefix(Game __instance) { if (!MultiplayerTweaksPlugin.GetEnableValkrie()) { __instance.m_inIntro = false; return false; } return true; } } [HarmonyPatch(typeof(Game), "FindSpawnPoint")] public static class Patch_Game_FindSpawnPoint { private static void Prefix(Game __instance) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) if (!__instance.m_playerProfile.HaveLogoutPoint() && !__instance.m_playerProfile.HaveCustomSpawnPoint() && GetCustomSpawnPoint(out var position)) { __instance.m_respawnAfterDeath = false; __instance.m_playerProfile.SetLogoutPoint(position); } } } [HarmonyPatch(typeof(BaseAI), "Awake")] public static class Patch_BaseAI_Awake { private static IEnumerable Transpiler(IEnumerable instructions) { return ReplaceMessageAll(instructions); } } [HarmonyPatch(typeof(BaseAI), "OnDeath")] public static class Patch_BaseAI_OnDeath { private static IEnumerable Transpiler(IEnumerable instructions) { return ReplaceMessageAll(instructions); } } [HarmonyPatch(typeof(BaseAI), "SetAlerted")] public static class Patch_BaseAI_SetAlerted { private static IEnumerable Transpiler(IEnumerable instructions) { return ReplaceMessageAll(instructions); } } private static void SendArrivalMessage() { //IL_0008: 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_0035: Unknown result type (might be due to invalid IL or missing references) if (MultiplayerTweaksPlugin.GetEnableArrivalMessage()) { Type val = (Type)2; if (!MultiplayerTweaksPlugin.GetEnableArrivalMessageShout()) { val = (Type)1; } string text = MultiplayerTweaksPlugin.GetOverrideArrivalMessage(); if (Utility.IsNullOrWhiteSpace(text)) { text = Localization.instance.Localize("$text_player_arrived"); } Chat.instance.SendText(val, text); } } private static void SendMessageInRange(BaseAI baseAI, MessageType type, string message) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) Player.MessageAllInRange(((Component)baseAI).transform.position, 100f, type, message, (Sprite)null); } public static bool GetCustomSpawnPoint(out Vector3 position) { //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_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) string playerDefaultSpawnPoint = MultiplayerTweaksPlugin.GetPlayerDefaultSpawnPoint(); if (!Utility.IsNullOrWhiteSpace(playerDefaultSpawnPoint)) { string[] array = playerDefaultSpawnPoint.Split(new char[1] { ',' }); if (array.Length >= 3) { try { float num = float.Parse(array[0]); float num2 = float.Parse(array[1]); float num3 = float.Parse(array[2]); position = new Vector3(num, num2, num3); return true; } catch (Exception ex) { MultiplayerTweaksPlugin.MultiplayerTweaksLogger.LogError((object)"Error setting the new spawn point. Check your configuration for formatting issues."); MultiplayerTweaksPlugin.MultiplayerTweaksLogger.LogWarning((object)ex); } } else { MultiplayerTweaksPlugin.MultiplayerTweaksLogger.LogError((object)"Error setting the new spawn point. Check your configuration for formatting issues."); } } position = Vector3.zero; return false; } private static IEnumerable ReplaceMessageAll(IEnumerable instructions) { //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Expected O, but got Unknown List list = new List(instructions); MethodInfo obj = AccessTools.Method(typeof(MessageHud), "MessageAll", (Type[])null, (Type[])null); for (int i = 4; i < list.Count; i++) { if (list[i].opcode == OpCodes.Callvirt) { object operand = list[i].operand; if (operand != null && operand.Equals(obj)) { list[i - 4].opcode = OpCodes.Ldarg_0; MethodInfo methodInfo = AccessTools.Method(typeof(ArrivalTweaks), "SendMessageInRange", (Type[])null, (Type[])null); list[i] = new CodeInstruction(OpCodes.Call, (object)methodInfo); break; } } } return list.AsEnumerable(); } } public static class ResetCommands { [HarmonyPatch(typeof(Terminal), "InitTerminal")] private static class Patch_Terminal_InitTerminal { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static ConsoleEvent <>9__1_0; internal void b__1_0(ConsoleEventArgs args) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown args.Context.AddString("The Gods Accept Your Sacrifice."); if (!((Object)(object)Player.m_localPlayer == (Object)null) && Game.instance.m_playerProfile != null) { GeneralTweaks.OverrideRespawn(); HitData val = new HitData { m_damage = { m_damage = 99999f }, m_hitType = (HitType)14 }; ((Character)Player.m_localPlayer).Damage(val); } } } [HarmonyPriority(800)] private static void Prefix(out bool __state) { __state = Terminal.m_terminalInitialized; } private static void Postfix(bool __state) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //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_003c: Expected O, but got Unknown if (__state) { return; } MultiplayerTweaksPlugin.MultiplayerTweaksLogger.LogInfo((object)"Adding Terminal Commands."); object obj = <>c.<>9__1_0; if (obj == null) { ConsoleEvent val = delegate(ConsoleEventArgs args) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown args.Context.AddString("The Gods Accept Your Sacrifice."); if (!((Object)(object)Player.m_localPlayer == (Object)null) && Game.instance.m_playerProfile != null) { GeneralTweaks.OverrideRespawn(); HitData val2 = new HitData { m_damage = { m_damage = 99999f }, m_hitType = (HitType)14 }; ((Character)Player.m_localPlayer).Damage(val2); } }; <>c.<>9__1_0 = val; obj = (object)val; } new ConsoleCommand("surrender", "", (ConsoleEvent)obj, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } } } public class GeneralTweaks { [HarmonyPriority(0)] [HarmonyPatch(typeof(Player), "ShowTutorial")] public static class Patch_Player_ShowTutorial { private static bool Prefix(Player __instance, string name) { if (!Raven.m_tutorialsEnabled) { __instance.SetSeenTutorial(name); return false; } return true; } } [HarmonyPatch(typeof(Player), "OnSpawned")] public static class Patch_Player_OnSpawned { private static void Postfix(Player __instance) { if (MultiplayerTweaksPlugin.GetOverridePlayerPVP()) { ZNetView nview = ((Character)__instance).m_nview; if (nview != null) { ZDO zDO = nview.GetZDO(); if (zDO != null) { zDO.Set(ZDOVars.s_pvp, MultiplayerTweaksPlugin.GetForcePlayerPVPOn()); } } __instance.m_pvp = MultiplayerTweaksPlugin.GetForcePlayerPVPOn(); InventoryGui.instance.m_pvp.isOn = MultiplayerTweaksPlugin.GetForcePlayerPVPOn(); } _lastSpawnTime = ZNet.instance.GetTimeSeconds(); _lastHitByPlayer = false; } } [HarmonyPatch(typeof(Player), "CanSwitchPVP")] public static class Patch_Player_CanSwitchPVP { private static void Postfix(ref bool __result) { if (MultiplayerTweaksPlugin.GetOverridePlayerPVP()) { __result = false; } } } [HarmonyPatch(typeof(Player), "OnDamaged")] public static class Patch_Player_OnDamaged { private static void Postfix(HitData hit) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) if (IsPlayer(hit.m_attacker)) { _lastHitByPlayer = true; } else { _lastHitByPlayer = false; } } } [HarmonyPatch(typeof(PlayerProfile), "SetDeathPoint")] public static class Patch_PlayerProfile_SetDeathPoint { private static void Postfix(PlayerProfile __instance, Vector3 point) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) if (_overrideRespawn) { _overrideRespawn = false; } else if (!MultiplayerTweaksPlugin.GetTeleportOnAnyDeath() || (!MultiplayerTweaksPlugin.GetTeleportOnPVPDeath() && _lastHitByPlayer)) { __instance.SetLogoutPoint(point); } } } [HarmonyPatch(typeof(Game), "RequestRespawn")] public static class Patch_Game_RequestRespawn { private static void Prefix(ref bool afterDeath) { if (!MultiplayerTweaksPlugin.GetTeleportOnAnyDeath() || (!MultiplayerTweaksPlugin.GetTeleportOnPVPDeath() && _lastHitByPlayer)) { afterDeath = false; } } } [HarmonyPatch(typeof(Skills), "LowerAllSkills")] public static class Patch_Skills_LowerAllSkills { [HarmonyPriority(500)] private static bool Prefix() { if (!MultiplayerTweaksPlugin.GetSkillLossOnAnyDeath() || (!MultiplayerTweaksPlugin.GetSkillLossOnPVPDeath() && _lastHitByPlayer)) { return false; } return true; } } [HarmonyPatch(typeof(Skills), "Clear")] public static class Patch_Skills_Clear { [HarmonyPriority(500)] private static bool Prefix() { if (!MultiplayerTweaksPlugin.GetSkillLossOnAnyDeath() || (!MultiplayerTweaksPlugin.GetSkillLossOnPVPDeath() && _lastHitByPlayer)) { return false; } return true; } } [HarmonyPatch(typeof(Character), "CheckDeath")] public static class Patch_Character_CheckDeath { private static bool Prefix(Character __instance) { if (__instance.IsPlayer() && (Object)(object)__instance == (Object)(object)Player.m_localPlayer && ZNet.instance.GetTimeSeconds() - _lastSpawnTime < 15.0) { return false; } return true; } } [HarmonyPatch(typeof(EnvMan), "GetCurrentDay")] public static class Patch_EnvMan_GetCurrentDay { private static void Postfix(ref int __result) { int gameDayOffset = MultiplayerTweaksPlugin.GetGameDayOffset(); __result -= gameDayOffset; if (__result < 0) { __result = 0; } } } [HarmonyPatch(typeof(Minimap), "AddPin")] public static class Patch_Minimap_AddPin { private static void Prefix(PinType type, ref string name) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 if ((int)type == 4) { name = $"$hud_mapday {EnvMan.instance.GetCurrentDay()}"; } } } private static bool _overrideRespawn; private static bool _lastHitByPlayer; private static double _lastSpawnTime; public static bool IsPlayer(ZDOID id) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (!((ZDOID)(ref id)).IsNone() && Player.s_players != null) { List s_players = Player.s_players; for (int i = 0; i < s_players.Count; i++) { ZDOID zDOID = ((Character)s_players[i]).GetZDOID(); if (((ZDOID)(ref zDOID)).Equals(id)) { return true; } } } return false; } public static void OverrideRespawn() { Game.instance.m_playerProfile.ClearLoguoutPoint(); _overrideRespawn = true; } } public class MapTweaks { [HarmonyPatch(typeof(Player), "OnSpawned")] public static class Patch_Player_OnSpawned { private static void Postfix() { if (MultiplayerTweaksPlugin.GetOverridePlayerMapPins()) { ZNet.instance.SetPublicReferencePosition(MultiplayerTweaksPlugin.GetForcePlayerMapPinsOn()); } } } [HarmonyPatch(typeof(ZNet), "SetPublicReferencePosition")] public static class Patch_ZNet_SetPublicReferencePosition { private static void Prefix(ref bool pub) { if (MultiplayerTweaksPlugin.GetOverridePlayerMapPins()) { pub = MultiplayerTweaksPlugin.GetForcePlayerMapPinsOn(); } } } [HarmonyPatch(typeof(Chat), "GetShoutWorldTexts")] public static class Patch_Chat_GetShoutWorldTexts { private static bool Prefix() { if (!MultiplayerTweaksPlugin.GetAllowShoutPings()) { return false; } return true; } } [HarmonyPatch(typeof(Chat), "SendPing")] public static class Patch_Chat_SendPing { [HarmonyPriority(300)] private static bool Prefix(ref bool __runOriginal) { if (!MultiplayerTweaksPlugin.GetAllowMapPings() || !__runOriginal) { return false; } return true; } } } public class TraderMapTweaks { [HarmonyPatch(typeof(Minimap))] private static class Patch_Minimap_GetMapData { [HarmonyPriority(700)] [HarmonyPatch("GetSharedMapData")] [HarmonyPatch("GetMapData")] private static void Prefix(ref Minimap __instance) { TransformPinIdsToSave(ref __instance.m_pins); } [HarmonyPriority(100)] [HarmonyPatch("GetSharedMapData")] [HarmonyPatch("GetMapData")] private static void Postfix(ref Minimap __instance) { TransformPinIdsToPlay(ref __instance.m_pins); } } [HarmonyPatch(typeof(Minimap), "Start")] private static class Patch_Minimap_Start { [HarmonyPriority(100)] private static void Postfix(Minimap __instance) { bool[] array = new bool[__instance.m_visibleIconTypes.Length + 3]; for (int i = 0; i < __instance.m_visibleIconTypes.Length; i++) { array[i] = __instance.m_visibleIconTypes[i]; } haldorIndex = __instance.m_visibleIconTypes.Length; hildirIndex = __instance.m_visibleIconTypes.Length + 1; bogWitchIndex = __instance.m_visibleIconTypes.Length + 2; array[haldorIndex] = true; array[hildirIndex] = true; array[bogWitchIndex] = true; __instance.m_visibleIconTypes = array; } } [HarmonyPatch(typeof(Minimap), "AddPin")] private static class Patch_Minimap_AddPin { [HarmonyPriority(800)] private static void Prefix(PinType type, out int __state) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Expected I4, but got Unknown __state = (int)type; } [HarmonyPriority(200)] private static void Postfix(ref PinData __result, PinType type, int __state) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) if (__state == haldorIndex || __state == 123) { __result.m_icon = Minimap.instance.GetLocationIcon("Vendor_BlackForest"); __result.m_type = (PinType)haldorIndex; } else if (__state == hildirIndex || __state == 124) { __result.m_icon = Minimap.instance.GetLocationIcon("Hildir_camp"); __result.m_type = (PinType)hildirIndex; } else if (__state == bogWitchIndex || __state == 125) { __result.m_icon = Minimap.instance.GetLocationIcon("BogWitch_Camp"); __result.m_type = (PinType)bogWitchIndex; } } } [HarmonyPatch(typeof(Trader), "Interact")] private static class Patch_Trader_Interact { private static void Postfix(Trader __instance) { //IL_0053: 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_0080: 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) string prefabName = Utils.GetPrefabName(((Object)__instance).name); int num = -1; switch (prefabName) { case "Haldor": num = 123; break; case "Hildir": num = 124; break; case "BogWitch": num = 125; break; } if (num != -1 && !Minimap.instance.HavePinInRange(((Component)__instance).transform.position, 1f)) { Minimap.instance.AddPin(((Component)__instance).transform.position, (PinType)num, "", true, false, 0L, default(PlatformUserID)); } } } [HarmonyPatch(typeof(ZoneSystem), "GetLocationIcons")] private static class Patch_ZoneSystem_GetLocationIcons { private static void Postfix(ref Dictionary icons) { //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) bool flag = !MultiplayerTweaksPlugin.GetEnableTempleMapPin() && Utility.IsNullOrWhiteSpace(MultiplayerTweaksPlugin.GetPlayerDefaultSpawnPoint()); if (!flag && MultiplayerTweaksPlugin.GetEnableTempleMapPin() && MultiplayerTweaksPlugin.GetEnableHaldorMapPin() && MultiplayerTweaksPlugin.GetEnableHildirMapPin() && MultiplayerTweaksPlugin.GetEnableBogWitchMapPin()) { return; } List list = new List(); foreach (KeyValuePair icon in icons) { switch (icon.Value) { case "StartTemple": if (!MultiplayerTweaksPlugin.GetEnableTempleMapPin() && !flag) { list.Add(icon.Key); } break; case "Vendor_BlackForest": if (!MultiplayerTweaksPlugin.GetEnableHaldorMapPin()) { list.Add(icon.Key); } break; case "Hildir_camp": if (!MultiplayerTweaksPlugin.GetEnableHildirMapPin()) { list.Add(icon.Key); } break; case "BogWitch_Camp": if (!MultiplayerTweaksPlugin.GetEnableBogWitchMapPin()) { list.Add(icon.Key); } break; } } foreach (Vector3 item in list) { icons.Remove(item); } } } private const string HALDOR_LOC = "Vendor_BlackForest"; private const string HILDIR_LOC = "Hildir_camp"; private const string BOGWITCH_LOC = "BogWitch_Camp"; private const int HALDOR_INT = 123; private const int HILDIR_INT = 124; private const int BOGWITCH_INT = 125; private static int haldorIndex = -1; private static int hildirIndex = -1; private static int bogWitchIndex = -1; private static void TransformPinIdsToSave(ref List pins) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected I4, but got Unknown //IL_0024: 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_0048: Unknown result type (might be due to invalid IL or missing references) foreach (PinData pin in pins) { int num = (int)pin.m_type; if (num == haldorIndex) { pin.m_type = (PinType)123; } else if (num == hildirIndex) { pin.m_type = (PinType)124; } else if (num == bogWitchIndex) { pin.m_type = (PinType)125; } } } private static void TransformPinIdsToPlay(ref List pins) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected I4, but got Unknown //IL_0024: 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_0048: Unknown result type (might be due to invalid IL or missing references) foreach (PinData pin in pins) { switch ((int)pin.m_type) { case 123: pin.m_type = (PinType)haldorIndex; break; case 124: pin.m_type = (PinType)hildirIndex; break; case 125: pin.m_type = (PinType)bogWitchIndex; break; } } } } }