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 Wagonborn v1.3.3
Wagonborn.dll
Decompiled 3 days agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Reflection; using System.Runtime.CompilerServices; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using HarmonyLib; using Jotunn; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using Splatform; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("blackhearthx")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Your wagon is a truck now.")] [assembly: AssemblyFileVersion("1.3.3.0")] [assembly: AssemblyInformationalVersion("1.3.3+a1cf276b77986285ccfe81360dc321bb19dc61a4")] [assembly: AssemblyProduct("Wagonborn")] [assembly: AssemblyTitle("Wagonborn")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.3.3.0")] [module: UnverifiableCode] [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 Wagonborn { [HarmonyPatch] internal static class CartCrew { private const string BetterCartsGuid = "TastyChickenLegs.BetterCarts"; private static bool? _betterCartsPresent; private static readonly List<Player> PlayerBuffer = new List<Player>(); internal static bool OwnCrewActive() { if (!_betterCartsPresent.HasValue) { _betterCartsPresent = Chainloader.PluginInfos != null && Chainloader.PluginInfos.ContainsKey("TastyChickenLegs.BetterCarts"); if (_betterCartsPresent == true) { Logger.LogInfo((object)"Wagonborn: BetterCarts detected — buddy mass deferred to it (Hauling XP for helpers still runs)."); } } return _betterCartsPresent != true; } internal static int CountHelpers(Vagon cart) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)cart == (Object)null || !PluginConfig.EnableBuddyHelp.Value || !cart.IsAttached()) { return 0; } PlayerBuffer.Clear(); Player.GetPlayersInRange(((Component)cart).transform.position, PluginConfig.BuddyRange.Value, PlayerBuffer); int num = 0; bool flag = false; for (int i = 0; i < PlayerBuffer.Count; i++) { Player val = PlayerBuffer[i]; if (!((Object)(object)val == (Object)null)) { if (cart.IsAttached((Character)(object)val)) { flag = true; } else { num++; } } } bool flag2 = (Object)(object)cart.m_nview != (Object)null && cart.m_nview.IsOwner(); if (!flag && !flag2 && num > 0) { num--; } return Mathf.Min(num, PluginConfig.MaxBuddies.Value); } internal static float GetBuddyMassMultiplier(Vagon cart) { if (!OwnCrewActive() || !PluginConfig.EnableBuddyHelp.Value) { return 1f; } int num = CountHelpers(cart); if (num <= 0) { return 1f; } float num2 = (float)num * Mathf.Clamp01(PluginConfig.BuddyMassReduction.Value); return Mathf.Max(0.1f, 1f - num2); } internal static Vagon FindCartBeingHelped(Player local) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)local == (Object)null || !PluginConfig.EnableBuddyHelp.Value) { return null; } float value = PluginConfig.BuddyRange.Value; List<Vagon> instances = Vagon.m_instances; Vagon result = null; float num = value; for (int i = 0; i < instances.Count; i++) { Vagon val = instances[i]; if (!((Object)(object)val == (Object)null) && val.IsAttached() && !val.IsAttached((Character)(object)local)) { float num2 = Vector3.Distance(((Component)local).transform.position, ((Component)val).transform.position); if (num2 <= num) { num = num2; result = val; } } } return result; } [HarmonyPrefix] [HarmonyPatch(typeof(Vagon), "CanAttach")] private static bool CanAttachPrefix(Vagon __instance, GameObject go, ref bool __result) { //IL_0064: 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_0083: 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_0093: Unknown result type (might be due to invalid IL or missing references) if (!OwnCrewActive() || !PluginConfig.AllowOutOfPlaceAttach.Value) { return true; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || (Object)(object)go != (Object)(object)((Component)localPlayer).gameObject || (Object)(object)__instance == (Object)null || (Object)(object)__instance.m_attachPoint == (Object)null) { return true; } if (__instance.IsAttached((Character)(object)localPlayer) || __instance.IsAttached()) { return true; } if (((Component)__instance).transform.up.y < 0.1f) { return true; } float num = Vector3.Distance(go.transform.position + __instance.m_attachOffset, __instance.m_attachPoint.position); __result = !((Character)localPlayer).IsTeleporting() && !((Character)localPlayer).InDodge() && num < PluginConfig.AttachDistance.Value; return false; } } [HarmonyPatch] internal static class CartMapPin { private sealed class TrackedPin { public Vagon Cart; public PinData Pin; public Minimap Map; } private struct Pending { public bool Hidden; public float Until; } private const string HiddenKeyPrefix = "Wagonborn_PinHidden_"; private const string RpcSetHidden = "Wagonborn_SetPinHidden"; private const string CartPrefab = "Cart"; private const float PinUiScale = 0.85f; private const float ResyncInterval = 0.5f; private const float PendingHold = 3f; private static readonly Dictionary<ZDOID, TrackedPin> Pins = new Dictionary<ZDOID, TrackedPin>(); private static readonly Dictionary<ZDOID, Vagon> Loaded = new Dictionary<ZDOID, Vagon>(); private static readonly HashSet<ZDOID> WorldCarts = new HashSet<ZDOID>(); private static readonly HashSet<ZDOID> Wanted = new HashSet<ZDOID>(); private static readonly List<ZDOID> ScratchRemove = new List<ZDOID>(); private static readonly List<ZDO> ScanBuffer = new List<ZDO>(); private static readonly Dictionary<ZDOID, Pending> PendingChoice = new Dictionary<ZDOID, Pending>(); private static FieldRef<Minimap, bool> s_pinUpdateRequired; private static Sprite _wheelSprite; private static float _resyncAt; private static int _scanIndex; internal static bool IsEnabled() { if (PluginConfig.EnableCartMapPin != null) { return PluginConfig.EnableCartMapPin.Value; } return false; } private static string HiddenKey(long playerId) { return "Wagonborn_PinHidden_" + playerId; } private static bool IsHiddenForMe(ZDO zdo) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (zdo == null || (Object)(object)localPlayer == (Object)null) { return false; } if (PendingChoice.TryGetValue(zdo.m_uid, out var value)) { if (Time.time < value.Until) { return value.Hidden; } PendingChoice.Remove(zdo.m_uid); } return zdo.GetBool(HiddenKey(localPlayer.GetPlayerID()), false); } internal static bool IsMarked(Vagon cart) { if ((Object)(object)cart == (Object)null || (Object)(object)cart.m_nview == (Object)null || !cart.m_nview.IsValid()) { return false; } return !IsHiddenForMe(cart.m_nview.GetZDO()); } internal static void ToggleMarked(Vagon cart) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (IsEnabled() && !((Object)(object)cart == (Object)null) && !((Object)(object)localPlayer == (Object)null) && !((Object)(object)cart.m_nview == (Object)null) && cart.m_nview.IsValid()) { bool flag = !IsMarked(cart); ZDOID uid = cart.m_nview.GetZDO().m_uid; PendingChoice[uid] = new Pending { Hidden = !flag, Until = Time.time + 3f }; cart.m_nview.InvokeRPC("Wagonborn_SetPinHidden", new object[2] { localPlayer.GetPlayerID(), !flag }); _resyncAt = 0f; string text = (flag ? "$wagonborn_mappin_on" : "$wagonborn_mappin_off"); string text2 = ((Localization.instance != null) ? Localization.instance.Localize(text) : (flag ? "On the map" : "Off the map")); ((Character)localPlayer).Message((MessageType)2, text2, 0, (Sprite)null, false); } } private static void RPC_SetHidden(Vagon cart, long playerId, bool hidden) { if (!((Object)(object)cart == (Object)null) && !((Object)(object)cart.m_nview == (Object)null) && cart.m_nview.IsValid() && cart.m_nview.IsOwner()) { ZDO zDO = cart.m_nview.GetZDO(); string text = HiddenKey(playerId); if (hidden) { zDO.Set(text, true); } else if (zDO.GetBool(text, false)) { zDO.Set(text, false); } } } internal static void Tick() { if (!IsEnabled()) { ClearAll(); return; } Minimap instance = Minimap.instance; if ((Object)(object)instance == (Object)null || ZDOMan.instance == null || (Object)(object)Player.m_localPlayer == (Object)null) { ClearAll(); return; } if (Time.time >= _resyncAt) { _resyncAt = Time.time + 0.5f; AdvanceWorldScan(); Resync(instance); } UpdatePinPositions(instance); } internal static void LateTickUi() { if (!IsEnabled() || Pins.Count == 0) { return; } Minimap instance = Minimap.instance; if ((Object)(object)instance == (Object)null) { return; } foreach (TrackedPin value in Pins.Values) { if (value?.Pin != null) { ApplyWheelIcon(value.Pin); ApplyPinUiSize(value.Pin, instance); } } } private static void AdvanceWorldScan() { //IL_005e: Unknown result type (might be due to invalid IL or missing references) bool allZDOsWithPrefabIterative; try { allZDOsWithPrefabIterative = ZDOMan.instance.GetAllZDOsWithPrefabIterative("Cart", ScanBuffer, ref _scanIndex); } catch { ScanBuffer.Clear(); _scanIndex = 0; return; } if (!allZDOsWithPrefabIterative) { return; } WorldCarts.Clear(); for (int i = 0; i < ScanBuffer.Count; i++) { ZDO val = ScanBuffer[i]; if (val != null && val.IsValid()) { WorldCarts.Add(val.m_uid); } } ScanBuffer.Clear(); _scanIndex = 0; } private static void Resync(Minimap map) { //IL_005c: 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_00a2: 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_0075: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Unknown result type (might be due to invalid IL or missing references) Loaded.Clear(); Wanted.Clear(); List<Vagon> instances = Vagon.m_instances; for (int i = 0; i < instances.Count; i++) { Vagon val = instances[i]; if (!((Object)(object)val == (Object)null) && !((Object)(object)val.m_nview == (Object)null) && val.m_nview.IsValid()) { ZDO zDO = val.m_nview.GetZDO(); Loaded[zDO.m_uid] = val; if (!IsHiddenForMe(zDO)) { Wanted.Add(zDO.m_uid); } } } foreach (ZDOID worldCart in WorldCarts) { if (!Wanted.Contains(worldCart) && !Loaded.ContainsKey(worldCart)) { ZDO zDO2 = ZDOMan.instance.GetZDO(worldCart); if (zDO2 != null && zDO2.IsValid() && !IsHiddenForMe(zDO2)) { Wanted.Add(worldCart); } } } ScratchRemove.Clear(); foreach (KeyValuePair<ZDOID, TrackedPin> pin in Pins) { if (!Wanted.Contains(pin.Key) || (Object)(object)pin.Value.Map != (Object)(object)map) { ScratchRemove.Add(pin.Key); } } for (int j = 0; j < ScratchRemove.Count; j++) { RemoveTracked(ScratchRemove[j]); } foreach (ZDOID item in Wanted) { Loaded.TryGetValue(item, out var value); Vector3 pos; if (Pins.TryGetValue(item, out var value2)) { value2.Cart = value; } else if (TryGetPosition(item, value, out pos)) { AddPin(item, value, pos, map); } } } private static bool TryGetPosition(ZDOID id, Vagon cart, out Vector3 pos) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //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) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: 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) if ((Object)(object)cart != (Object)null && Object.op_Implicit((Object)(object)cart)) { pos = ((Component)cart).transform.position; return true; } ZDO val = ((ZDOMan.instance != null) ? ZDOMan.instance.GetZDO(id) : null); if (val != null && val.IsValid()) { pos = val.GetPosition(); return true; } pos = Vector3.zero; return false; } private static void AddPin(ZDOID id, Vagon cart, Vector3 pos, Minimap map) { //IL_001f: 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) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) string text = ((Localization.instance != null) ? Localization.instance.Localize("$wagonborn_mappin_name") : "Cart"); try { PinData val = map.AddPin(pos, (PinType)3, text, false, false, 0L, default(PlatformUserID)); val.m_doubleSize = false; ApplyWheelIcon(val); ApplyPinUiSize(val, map); RequestPinUiRefresh(map); Pins[id] = new TrackedPin { Cart = cart, Pin = val, Map = map }; } catch { } } private static void UpdatePinPositions(Minimap map) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_009e: 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) ScratchRemove.Clear(); bool flag = false; foreach (KeyValuePair<ZDOID, TrackedPin> pin in Pins) { TrackedPin value = pin.Value; Vector3 pos; if (value?.Pin == null || (Object)(object)value.Map != (Object)(object)map) { ScratchRemove.Add(pin.Key); } else if (!TryGetPosition(pin.Key, value.Cart, out pos)) { ScratchRemove.Add(pin.Key); } else if (value.Pin.m_pos != pos) { value.Pin.m_pos = pos; flag = true; } } for (int i = 0; i < ScratchRemove.Count; i++) { RemoveTracked(ScratchRemove[i]); } if (flag) { RequestPinUiRefresh(map); } } private static void RemoveTracked(ZDOID id) { //IL_0005: 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) if (!Pins.TryGetValue(id, out var value)) { return; } Pins.Remove(id); if (value?.Pin == null || !((Object)(object)Minimap.instance != (Object)null)) { return; } try { Minimap.instance.RemovePin(value.Pin); RequestPinUiRefresh(Minimap.instance); } catch { } } private static void ClearAll() { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) if (Pins.Count == 0) { return; } ScratchRemove.Clear(); foreach (ZDOID key in Pins.Keys) { ScratchRemove.Add(key); } for (int i = 0; i < ScratchRemove.Count; i++) { RemoveTracked(ScratchRemove[i]); } } private static void RequestPinUiRefresh(Minimap map) { if ((Object)(object)map == (Object)null) { return; } if (s_pinUpdateRequired == null) { try { s_pinUpdateRequired = AccessTools.FieldRefAccess<Minimap, bool>("m_pinUpdateRequired"); } catch { s_pinUpdateRequired = null; } } if (s_pinUpdateRequired != null) { s_pinUpdateRequired.Invoke(map) = true; } } private static void ApplyWheelIcon(PinData pin) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) if (pin == null) { return; } Sprite orCreateWheelSprite = GetOrCreateWheelSprite(); if (!((Object)(object)orCreateWheelSprite == (Object)null)) { pin.m_doubleSize = false; pin.m_icon = orCreateWheelSprite; if ((Object)(object)pin.m_iconElement != (Object)null) { pin.m_iconElement.sprite = orCreateWheelSprite; ((Graphic)pin.m_iconElement).color = Color.white; } } } private static void ApplyPinUiSize(PinData pin, Minimap map) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Invalid comparison between Unknown and I4 if (!((Object)(object)pin?.m_uiElement == (Object)null) && !((Object)(object)map == (Object)null)) { float num = (((int)map.m_mode == 2) ? map.m_pinSizeLarge : map.m_pinSizeSmall) * 0.85f; pin.m_uiElement.SetSizeWithCurrentAnchors((Axis)0, num); pin.m_uiElement.SetSizeWithCurrentAnchors((Axis)1, num); } } private static Sprite GetOrCreateWheelSprite() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_010e: 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 ((Object)(object)_wheelSprite != (Object)null) { return _wheelSprite; } Texture2D val = new Texture2D(32, 32, (TextureFormat)4, false); ((Texture)val).filterMode = (FilterMode)1; ((Texture)val).wrapMode = (TextureWrapMode)1; float num = 15.5f; float num2 = 15.5f; Color val2 = default(Color); ((Color)(ref val2))..ctor(0.78f, 0.52f, 0.22f, 1f); Color val3 = default(Color); ((Color)(ref val3))..ctor(0.55f, 0.34f, 0.14f, 1f); Color val4 = default(Color); ((Color)(ref val4))..ctor(0.62f, 0.62f, 0.66f, 1f); Color clear = Color.clear; for (int i = 0; i < 32; i++) { for (int j = 0; j < 32; j++) { float num3 = (float)j - num; float num4 = (float)i - num2; float num5 = Mathf.Sqrt(num3 * num3 + num4 * num4); Color val5 = clear; if (num5 < 14.5f && num5 > 11.5f) { val5 = val2; } else if (num5 <= 11.5f && num5 > 3.5f) { val5 = ((Mathf.Abs(Mathf.Sin(Mathf.Atan2(num4, num3) * 4f)) > 0.72f) ? val3 : clear); } if (num5 <= 3.5f) { val5 = val4; } if (num5 <= 1.4f) { ((Color)(ref val5))..ctor(0.22f, 0.22f, 0.24f, 1f); } val.SetPixel(j, i, val5); } } val.Apply(false, true); _wheelSprite = Sprite.Create(val, new Rect(0f, 0f, 32f, 32f), new Vector2(0.5f, 0.5f), 100f); ((Object)_wheelSprite).name = "Wagonborn_MapWheel"; return _wheelSprite; } [HarmonyPostfix] [HarmonyPatch(typeof(Vagon), "Awake")] private static void VagonAwakePostfix(Vagon __instance) { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__instance.m_nview == (Object)null) && __instance.m_nview.GetZDO() != null) { Vagon cart = __instance; cart.m_nview.Register<long, bool>("Wagonborn_SetPinHidden", (Action<long, long, bool>)delegate(long sender, long playerId, bool hidden) { RPC_SetHidden(cart, playerId, hidden); }); } } [HarmonyPrefix] [HarmonyPatch(typeof(Vagon), "Interact")] private static bool InteractPrefix(Vagon __instance, Humanoid character, bool hold, bool alt) { if (!alt || hold || !IsEnabled() || (Object)(object)__instance == (Object)null) { return true; } if ((Object)(object)character != (Object)(object)Player.m_localPlayer) { return true; } ToggleMarked(__instance); return false; } } internal static class CartMass { internal static float GetMultiplier(Player player) { float level = HaulingSkill.GetLevel(player); float num = Mathf.Clamp01(PluginConfig.MaxSkillMassReduction.Value) * (level / 100f); return 1f - num; } internal static int GetPullWeightPercent(Player player) { return Mathf.RoundToInt(GetMultiplier(player) * 100f); } } [HarmonyPatch(typeof(Vagon))] internal static class CartPatches { [HarmonyPrefix] [HarmonyPatch("SetMass")] private static void SetMassPrefix(Vagon __instance, ref float mass) { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__instance.m_nview == (Object)null) && __instance.m_nview.IsOwner()) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null && __instance.IsAttached((Character)(object)localPlayer)) { mass *= CartMass.GetMultiplier(localPlayer); } mass *= CartCrew.GetBuddyMassMultiplier(__instance); } } [HarmonyPostfix] [HarmonyPatch("AttachTo")] private static void AttachToPostfix(Vagon __instance) { RefreshMass(__instance); } [HarmonyPostfix] [HarmonyPatch("Detach")] private static void DetachPostfix(Vagon __instance) { RefreshMass(__instance); } private static void RefreshMass(Vagon cart) { if (!((Object)(object)cart == (Object)null) && !((Object)(object)cart.m_nview == (Object)null) && cart.m_nview.IsValid() && cart.m_nview.IsOwner()) { cart.UpdateMass(); } } [HarmonyPostfix] [HarmonyPatch("GetHoverText")] private static void GetHoverTextPostfix(Vagon __instance, ref string __result) { if (!((Object)(object)__instance == (Object)null) && !string.IsNullOrEmpty(__result)) { Player localPlayer = Player.m_localPlayer; string text = Mathf.FloorToInt(HaulingSkill.GetLevel(localPlayer)).ToString(); string text2 = CartMass.GetPullWeightPercent(localPlayer).ToString(); __result = __result + "\n" + L("$wagonborn_hover", text, text2); if (CartPortal.IsActive() && (Object)(object)localPlayer != (Object)null && __instance.IsAttached((Character)(object)localPlayer)) { __result = __result + "\n" + L("$wagonborn_cart_portal_hint"); } int num = CartCrew.CountHelpers(__instance); if (num > 0) { __result = __result + "\n" + L("$wagonborn_buddy_hover", num.ToString()); } if (CartMapPin.IsEnabled()) { __result = __result + "\n" + (CartMapPin.IsMarked(__instance) ? L("$wagonborn_mappin_hover_on") : L("$wagonborn_mappin_hover_off")); } } } private static string L(string key, params string[] args) { if (Localization.instance == null) { return key; } if (args == null || args.Length == 0) { return Localization.instance.Localize(key); } return Localization.instance.Localize(key, args); } } [HarmonyPatch] internal static class CartPortal { private const float ExitExtraDistance = 3f; private const string TeleportEverythingGuid = "zenox.teleporteverything"; private static readonly Collider[] ColliderBuffer = (Collider[])(object)new Collider[512]; private static readonly Action<Vagon, GameObject> AttachTo = AccessTools.MethodDelegate<Action<Vagon, GameObject>>(AccessTools.Method(typeof(Vagon), "AttachTo", (Type[])null, (Type[])null), (object)null, true); private static readonly Func<Vagon, GameObject, bool> CanAttach = AccessTools.MethodDelegate<Func<Vagon, GameObject, bool>>(AccessTools.Method(typeof(Vagon), "CanAttach", (Type[])null, (Type[])null), (object)null, true); private static readonly HashSet<Vagon> SeenBuffer = new HashSet<Vagon>(); private static ZDOID? _pendingReattachCartId; private static Vagon _pendingCart; private static bool? _teleportEverythingPresent; internal static bool IsActive() { if (PluginConfig.EnableCartPortal.Value) { return !TeleportEverythingPresent(); } return false; } private static bool TeleportEverythingPresent() { if (!_teleportEverythingPresent.HasValue) { _teleportEverythingPresent = Chainloader.PluginInfos != null && Chainloader.PluginInfos.ContainsKey("zenox.teleporteverything"); if (_teleportEverythingPresent == true) { Logger.LogInfo((object)"Wagonborn: TeleportEverything detected — cart portal transport deferred to it."); } } return _teleportEverythingPresent == true; } private static Vagon FindAttachedCart(Vector3 pos, Character player) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) int num = Physics.OverlapSphereNonAlloc(pos, PluginConfig.CartSearchRadius.Value, ColliderBuffer); Vagon result = null; SeenBuffer.Clear(); for (int i = 0; i < num; i++) { if (!((Object)(object)ColliderBuffer[i] == (Object)null)) { Vagon componentInParent = ((Component)ColliderBuffer[i]).GetComponentInParent<Vagon>(); if (!((Object)(object)componentInParent == (Object)null) && SeenBuffer.Add(componentInParent) && componentInParent.IsAttached(player)) { result = componentInParent; break; } } } return result; } private static Vagon FindCartByZdoid(Vector3 pos, ZDOID id) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) int num = Physics.OverlapSphereNonAlloc(pos, PluginConfig.CartSearchRadius.Value, ColliderBuffer); for (int i = 0; i < num; i++) { if ((Object)(object)ColliderBuffer[i] == (Object)null) { continue; } Vagon componentInParent = ((Component)ColliderBuffer[i]).GetComponentInParent<Vagon>(); if (!((Object)(object)componentInParent == (Object)null)) { ZNetView component = ((Component)componentInParent).GetComponent<ZNetView>(); if ((Object)(object)component != (Object)null && component.IsValid() && component.GetZDO().m_uid == id) { return componentInParent; } } } return null; } private static void PlaceCartForAttach(Vagon cart, Vector3 referencePos, Quaternion referenceRot) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0039: 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_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_0049: 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_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0056: 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_005c: Unknown result type (might be due to invalid IL or missing references) //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_0071: 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_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: 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) if ((Object)(object)cart == (Object)null || (Object)(object)cart.m_attachPoint == (Object)null) { return; } Vector3 val = Quaternion.Inverse(((Component)cart).transform.rotation) * (cart.m_attachPoint.position - ((Component)cart).transform.position); Vector3 val2 = referencePos + cart.m_attachOffset - referenceRot * val - ((Component)cart).transform.position; Rigidbody component = ((Component)cart).GetComponent<Rigidbody>(); Rigidbody[] componentsInChildren = ((Component)cart).GetComponentsInChildren<Rigidbody>(); foreach (Rigidbody val3 in componentsInChildren) { val3.isKinematic = true; Transform transform = ((Component)val3).transform; transform.position += val2; val3.linearVelocity = Vector3.zero; val3.angularVelocity = Vector3.zero; if ((Object)(object)val3 == (Object)(object)component) { ((Component)val3).transform.rotation = referenceRot; } } ((Component)cart).transform.rotation = referenceRot; Physics.SyncTransforms(); } private static void TransportAttachedCart(Vector3 fromPos, Player player, Vector3 targetPos, Quaternion targetRot) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005e: 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) Vagon val = FindAttachedCart(fromPos, (Character)(object)player); if ((Object)(object)val == (Object)null) { return; } ZNetView component = ((Component)val).GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null || !component.IsValid()) { return; } if (!component.IsOwner()) { component.ClaimOwnership(); } ZDO zDO = component.GetZDO(); if (zDO != null) { PlaceCartForAttach(val, targetPos, targetRot); zDO.SetPosition(((Component)val).transform.position); _pendingReattachCartId = zDO.m_uid; _pendingCart = val; Logger.LogInfo((object)$"Wagonborn: cart '{((Object)val).name}' teleported with player to {((Component)val).transform.position}"); MessageHud instance = MessageHud.instance; if (instance != null) { instance.ShowMessage((MessageType)1, (Localization.instance != null) ? Localization.instance.Localize("$wagonborn_cart_portal") : "Cart travels with you", 0, (Sprite)null, false, true); } } } [HarmonyPrefix] [HarmonyPatch(typeof(Player), "TeleportTo")] private static void TeleportToClearancePrefix(Player __instance, ref Vector3 pos, Quaternion rot) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_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_0042: 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) if (IsActive() && !((Object)(object)__instance == (Object)null) && !((Object)(object)FindAttachedCart(((Component)__instance).transform.position, (Character)(object)__instance) == (Object)null)) { pos += rot * Vector3.forward * 3f; } } [HarmonyPostfix] [HarmonyPatch(typeof(Player), "TeleportTo")] private static void TeleportToTransportPostfix(Player __instance, Vector3 pos, Quaternion rot, bool __result) { //IL_001a: 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_0021: Unknown result type (might be due to invalid IL or missing references) if (__result && IsActive() && !((Object)(object)__instance == (Object)null)) { TransportAttachedCart(((Component)__instance).transform.position, __instance, pos, rot); } } [HarmonyPostfix] [HarmonyPatch(typeof(Player), "UpdateTeleport")] private static void UpdateTeleportReattachPostfix(Player __instance, bool ___m_teleporting) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) if (___m_teleporting || !_pendingReattachCartId.HasValue || (Object)(object)__instance == (Object)null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } ZDOID value = _pendingReattachCartId.Value; Vagon pendingCart = _pendingCart; _pendingReattachCartId = null; _pendingCart = null; Vagon val = FindCartByZdoid(((Component)__instance).transform.position, value); if ((Object)(object)val == (Object)null && (Object)(object)pendingCart != (Object)null && Object.op_Implicit((Object)(object)pendingCart)) { val = pendingCart; } if ((Object)(object)val == (Object)null) { Logger.LogInfo((object)"Wagonborn: cart reattach skipped — cart not found after teleport."); return; } PlaceCartForAttach(val, ((Component)__instance).transform.position, ((Component)__instance).transform.rotation); ZNetView component = ((Component)val).GetComponent<ZNetView>(); if ((Object)(object)component != (Object)null && component.IsValid()) { ZDO zDO = component.GetZDO(); if (zDO != null) { zDO.SetPosition(((Component)val).transform.position); } } if (CanAttach != null && AttachTo != null && CanAttach(val, ((Component)__instance).gameObject)) { AttachTo(val, ((Component)__instance).gameObject); Logger.LogInfo((object)("Wagonborn: re-attached cart '" + ((Object)val).name + "' after portal.")); } else { Logger.LogInfo((object)("Wagonborn: could not re-attach cart '" + ((Object)val).name + "' (CanAttach failed).")); } Rigidbody[] componentsInChildren = ((Component)val).GetComponentsInChildren<Rigidbody>(); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].isKinematic = false; } } [HarmonyPrefix] [HarmonyPatch(typeof(Vagon), "Update")] private static void VagonUpdatePreventDetachPrefix(Vagon __instance, out float __state) { __state = (((Object)(object)__instance != (Object)null) ? __instance.m_detachDistance : 0f); if (PluginConfig.PreventCartAutoDetach.Value && !TeleportEverythingPresent() && !((Object)(object)__instance == (Object)null)) { float detachDistance = Mathf.Max(__state, PluginConfig.AttachLeash.Value); __instance.m_detachDistance = detachDistance; } } [HarmonyPostfix] [HarmonyPatch(typeof(Vagon), "Update")] private static void VagonUpdatePreventDetachPostfix(Vagon __instance, float __state) { if ((Object)(object)__instance != (Object)null) { __instance.m_detachDistance = __state; } } } internal static class HaulingProgress { private const float RescanInterval = 0.5f; private const float MaxPlausibleSpeed = 20f; private static Vagon _cart; private static bool _pulling; private static Vector3 _lastPos; private static float _speed; private static float _rescanAt; internal static void Tick() { //IL_0000: 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_0099: 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_0128: Unknown result type (might be due to invalid IL or missing references) if ((int)HaulingSkill.SkillType == 0) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { SetCart(null, pulling: false); return; } if (!IsStillEarning(localPlayer)) { if (Time.time < _rescanAt) { return; } _rescanAt = Time.time + 0.5f; Vagon val = FindAttachedCart(localPlayer); if ((Object)(object)val != (Object)null) { SetCart(val, pulling: true); } else { SetCart(CartCrew.FindCartBeingHelped(localPlayer), pulling: false); } if ((Object)(object)_cart == (Object)null) { return; } } float deltaTime = Time.deltaTime; if (!(deltaTime <= 0f)) { Vector3 position = ((Component)_cart).transform.position; float num = Vector3.Distance(position, _lastPos) / deltaTime; _lastPos = position; if (num > 20f) { num = 0f; } _speed = Mathf.Lerp(_speed, num, 0.2f); if (!(_speed < PluginConfig.MinSpeedForXp.Value)) { float num2 = CartLoadMass(_cart); float num3 = Mathf.Max(1f, num2 / Mathf.Max(1f, PluginConfig.LoadXpScale.Value)); float num4 = (_pulling ? 1f : PluginConfig.BuddyXpMultiplier.Value); ((Character)localPlayer).RaiseSkill(HaulingSkill.SkillType, PluginConfig.XpPerSecond.Value * deltaTime * num3 * num4); } } } internal static float CartLoadMass(Vagon cart) { float num = cart.m_baseMass; Inventory val = (((Object)(object)cart.m_container != (Object)null) ? cart.m_container.GetInventory() : null); if (val != null) { num += val.GetTotalWeight() * cart.m_itemWeightMassFactor; } return num; } private static bool IsStillEarning(Player player) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_cart == (Object)null || !Object.op_Implicit((Object)(object)_cart)) { return false; } if (_pulling) { return _cart.IsAttached((Character)(object)player); } if (PluginConfig.EnableBuddyHelp.Value && _cart.IsAttached() && !_cart.IsAttached((Character)(object)player)) { return Vector3.Distance(((Component)player).transform.position, ((Component)_cart).transform.position) <= PluginConfig.BuddyRange.Value; } return false; } private static void SetCart(Vagon cart, bool pulling) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)cart != (Object)(object)_cart) { _speed = 0f; if ((Object)(object)cart != (Object)null) { _lastPos = ((Component)cart).transform.position; } } _cart = cart; _pulling = pulling; } private static Vagon FindAttachedCart(Player player) { List<Vagon> instances = Vagon.m_instances; for (int i = 0; i < instances.Count; i++) { Vagon val = instances[i]; if ((Object)(object)val != (Object)null && val.IsAttached((Character)(object)player)) { return val; } } return null; } } internal static class HaulingSkill { internal const string Identifier = "com.blackhearthx.wagonborn.hauling"; internal static SkillType SkillType { get; private set; } internal static void Register() { PrefabManager.OnVanillaPrefabsAvailable -= OnVanillaPrefabsAvailable; PrefabManager.OnVanillaPrefabsAvailable += OnVanillaPrefabsAvailable; } private static void OnVanillaPrefabsAvailable() { //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_0035: 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_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Expected O, but got Unknown //IL_006a: Unknown result type (might be due to invalid IL or missing references) PrefabManager.OnVanillaPrefabsAvailable -= OnVanillaPrefabsAvailable; SkillType = SkillManager.Instance.AddSkill(new SkillConfig { Identifier = "com.blackhearthx.wagonborn.hauling", Name = "$skill_wagonborn_hauling", Description = "$skill_wagonborn_hauling_desc", IncreaseStep = 1f, Icon = (FindCartIcon() ?? CreateWheelIcon()) }); } internal static float GetLevel(Player player) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || (int)SkillType == 0) { return 0f; } return ((Character)player).GetSkillFactor(SkillType) * 100f; } private static Sprite FindCartIcon() { string[] array = new string[3] { "Cart", "piece_cart", "CartWood" }; for (int i = 0; i < array.Length; i++) { GameObject prefab = PrefabManager.Instance.GetPrefab(array[i]); if (!((Object)(object)prefab == (Object)null)) { Piece component = prefab.GetComponent<Piece>(); if ((Object)(object)component != (Object)null && (Object)(object)component.m_icon != (Object)null) { return component.m_icon; } } } return null; } private static Sprite CreateWheelIcon() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: 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_0188: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: 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_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: 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_0101: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(64, 64, (TextureFormat)5, false); ((Texture)val).filterMode = (FilterMode)1; ((Texture)val).wrapMode = (TextureWrapMode)1; float num = 31.5f; float num2 = 31.5f; Color val2 = default(Color); ((Color)(ref val2))..ctor(0.45f, 0.28f, 0.12f, 1f); Color val3 = default(Color); ((Color)(ref val3))..ctor(0.72f, 0.5f, 0.26f, 1f); Color val4 = default(Color); ((Color)(ref val4))..ctor(0.55f, 0.55f, 0.58f, 1f); Color clear = Color.clear; for (int i = 0; i < 64; i++) { for (int j = 0; j < 64; j++) { float num3 = (float)j - num; float num4 = (float)i - num2; float num5 = Mathf.Sqrt(num3 * num3 + num4 * num4); Color val5 = clear; if (num5 < 30f && num5 > 24f) { val5 = val2; } else if (num5 <= 24f && num5 > 8f) { val5 = ((Mathf.Abs(Mathf.Sin(Mathf.Atan2(num4, num3) * 4f)) > 0.72f) ? val3 : clear); } if (num5 <= 8f) { val5 = val4; } if (num5 <= 3.2f) { ((Color)(ref val5))..ctor(0.25f, 0.25f, 0.27f, 1f); } val.SetPixel(j, i, val5); } } val.Apply(); return Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 64f); } } [HarmonyPatch] internal static class HaulingSkillBackup { private const string BackupKey = "Wagonborn_HaulingBackup"; [HarmonyPrefix] [HarmonyPatch(typeof(Player), "Save")] private static void SavePrefix(Player __instance) { //IL_001c: 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) Skills val = (((Object)(object)__instance != (Object)null) ? __instance.m_skills : null); if (!((Object)(object)val == (Object)null) && (int)HaulingSkill.SkillType != 0) { float num = 0f; float num2 = 0f; if (val.m_skillData.TryGetValue(HaulingSkill.SkillType, out var value) && value != null) { num = value.m_level; num2 = value.m_accumulator; } __instance.m_customData["Wagonborn_HaulingBackup"] = num.ToString("R", CultureInfo.InvariantCulture) + "|" + num2.ToString("R", CultureInfo.InvariantCulture); } } [HarmonyPostfix] [HarmonyPatch(typeof(Player), "Load")] private static void LoadPostfix(Player __instance) { //IL_001c: 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_0075: Unknown result type (might be due to invalid IL or missing references) Skills val = (((Object)(object)__instance != (Object)null) ? __instance.m_skills : null); if ((Object)(object)val == (Object)null || (int)HaulingSkill.SkillType == 0 || !__instance.m_customData.TryGetValue("Wagonborn_HaulingBackup", out var value) || !TryParse(value, out var level, out var accumulator) || level <= 0f) { return; } val.m_skillData.TryGetValue(HaulingSkill.SkillType, out var value2); if (value2 == null || !(value2.m_level >= level)) { Skill val2 = value2 ?? val.GetSkill(HaulingSkill.SkillType); if (val2 != null) { float num = value2?.m_level ?? 0f; val2.m_level = level; val2.m_accumulator = accumulator; Logger.LogInfo((object)$"Wagonborn: Hauling restored from backup ({num:0.#} -> {level:0.#})."); } } } private static bool TryParse(string raw, out float level, out float accumulator) { level = 0f; accumulator = 0f; if (string.IsNullOrEmpty(raw)) { return false; } string[] array = raw.Split(new char[1] { '|' }); if (!float.TryParse(array[0], NumberStyles.Float, CultureInfo.InvariantCulture, out level)) { return false; } if (array.Length > 1) { float.TryParse(array[1], NumberStyles.Float, CultureInfo.InvariantCulture, out accumulator); } return true; } } internal static class ModLocalization { internal static void Register() { CustomLocalization localization = LocalizationManager.Instance.GetLocalization(); Add(localization, "English", "Hauling", "Earned by pulling or helping push a moving cart. Higher Hauling makes carts easier to pull.", "Hauling $1 — pull weight $2%", "Cart travels with you", "Portals take the cart", "Friends nearby lighten the load — and train Hauling"); Add(localization, "Portuguese_Brazilian", "Carreto", "Sobe puxando ou ajudando a empurrar uma carroça em movimento. Quanto maior o nível, mais leve ela fica.", "Carreto $1 — peso de puxar $2%", "Carroça vem junto", "Portais levam a carroça", "Amigos por perto aliviam o peso — e sobem Carreto"); Add(localization, "Portuguese_European", "Carreto", "Aumenta ao puxar ou ajudar a empurrar um carro em movimento. Quanto mais alto o nível, mais leve fica.", "Carreto $1 — peso a puxar $2%", "Carro vem consigo", "Portais levam o carro", "Amigos por perto aliviam o peso — e sobem Carreto"); Add(localization, "Spanish", "Acarrero", "Sube al tirar o ayudar a empujar un carro en movimiento. A más nivel, más fácil de arrastrar.", "Acarrero $1 — peso de tiro $2%", "El carro viaja contigo", "Los portales llevan el carro", "Amigos cerca alivian la carga — y suben Acarrero"); Add(localization, "French", "Traction", "Augmente en tirant ou en aidant à pousser une charrette en mouvement. Plus le niveau est élevé, plus elle est légère.", "Traction $1 — poids de traction $2%", "La charrette voyage avec vous", "Les portails emportent la charrette", "Les amis proches allègent la charge — et montent Traction"); Add(localization, "German", "Ziehen", "Steigt, wenn du einen fahrenden Karren ziehst oder mitschiebst. Höheres Level macht ihn leichter.", "Ziehen $1 — Zuggewicht $2%", "Karren reist mit", "Portale nehmen den Karren mit", "Freunde in der Nähe erleichtern die Last — und trainieren Ziehen"); Add(localization, "Italian", "Traino", "Sale tirando o aiutando a spingere un carro in movimento. Più alto è il livello, più è leggero.", "Traino $1 — peso di traino $2%", "Il carro viaggia con te", "I portali portano il carro", "Amici vicini alleggeriscono il carico — e allenano Traino"); Add(localization, "Dutch", "Slepen", "Stijgt door een rijdende kar te trekken of mee te duwen. Hoe hoger, hoe lichter de kar.", "Slepen $1 — trekkgewicht $2%", "Kar reist mee", "Portalen nemen de kar mee", "Vrienden in de buurt verlichten de last — en trainen Slepen"); Add(localization, "Swedish", "Dragning", "Ökar när du drar eller hjälper till att knuffa en vagn i rörelse. Högre nivå gör den lättare.", "Dragning $1 — dragvikt $2%", "Vagnen följer med", "Portaler tar vagnen", "Vänner nära lättar lasten — och tränar Dragning"); Add(localization, "Polish", "Wożenie", "Rośnie podczas ciągnięcia lub pomocy w pchaniu jadącego wozu. Wyższy poziom ułatwia ciągnięcie.", "Wożenie $1 — ciężar ciągu $2%", "Wóz podróżuje z tobą", "Portale zabierają wóz", "Znajomi w pobliżu odciążają — i trenują Wożenie"); Add(localization, "Russian", "Возка", "Растёт, когда вы везёте телегу или помогаете толкать. Чем выше навык, тем легче тянуть.", "Возка $1 — вес тяги $2%", "Телега идёт с вами", "Порталы забирают телегу", "Друзья рядом облегчают груз — и качают Возку"); Add(localization, "Ukrainian", "Перевезення", "Зростає, коли ви тягнете віз або допомагаєте штовхати. Вищий рівень робить його легшим.", "Перевезення $1 — вага тяги $2%", "Віз іде з вами", "Портали забирають віз", "Друзі поруч полегшують вагу — і качають Перевезення"); Add(localization, "Czech", "Tahání", "Stoupá tažením nebo pomocí tlačení jedoucího vozu. Vyšší úroveň ho odlehčí.", "Tahání $1 — tahová váha $2%", "Vůz cestuje s tebou", "Portály berou vůz", "Přátelé poblíž odlehčí náklad — a trénují Tahání"); Add(localization, "Hungarian", "Húzás", "Mozgó szekér húzásával vagy tolásával nő. Magasabb szint könnyebbé teszi.", "Húzás $1 — húzósúly $2%", "A szekér veled utazik", "A portálok elviszik a szekeret", "Közeli barátok könnyítik a terhet — és fejlesztik a Húzást"); Add(localization, "Romanian", "Transport", "Crește trăgând sau ajutând la împins un car în mișcare. Nivelul mai mare îl face mai ușor.", "Transport $1 — greutate de tracțiune $2%", "Carul călătorește cu tine", "Portalurile iau carul", "Prietenii apropiați ușurează sarcina — și antrenează Transport"); Add(localization, "Turkish", "Çekme", "Hareket halindeki arabayı çekerek veya itmeye yardım ederek artar. Seviye yükseldikçe araba hafifler.", "Çekme $1 — çekiş ağırlığı $2%", "Araba seninle gider", "Portallar arabayı alır", "Yakındaki dostlar yükü hafifletir — ve Çekme yükseltir"); Add(localization, "Chinese", "拉车", "拉动或帮忙推动行驶中的推车可提升。等级越高,推车越轻。", "拉车 $1 — 牵引重量 $2%", "推车与你同行", "传送门带走推车", "附近的朋友减轻负担 — 也提升拉车"); Add(localization, "Chinese_Trad", "拉車", "拉動或幫忙推動行進中的推車可提升。等級越高,推車越輕。", "拉車 $1 — 牽引重量 $2%", "推車與你同行", "傳送門帶走推車", "附近的朋友減輕負擔 — 也提升拉車"); Add(localization, "Japanese", "運搬", "動いている荷車を引く、または押す手伝いをすると上がる。レベルが高いほど引きやすくなる。", "運搬 $1 — 引き重さ $2%", "荷車も一緒に移動", "ポータルで荷車も運ぶ", "近くの仲間が負担を軽くする — 運搬も上がる"); Add(localization, "Korean", "운반", "움직이는 수레를 끌거나 밀어 도우면 오른다. 레벨이 높을수록 수레가 가벼워진다.", "운반 $1 — 견인 무게 $2%", "수레가 함께 이동", "포털이 수레를 데려감", "근처 친구가 짐을 덜어 줌 — 운반도 오른다"); AddMapPin(localization, "English", "On the map [<color=yellow><b>Shift+E</b></color>] hide", "Off the map [<color=yellow><b>Shift+E</b></color>] show", "On the map", "Off the map", "Cart", "$1 nearby — lighter haul"); AddMapPin(localization, "Portuguese_Brazilian", "No mapa [<color=yellow><b>Shift+E</b></color>] tirar", "Fora do mapa [<color=yellow><b>Shift+E</b></color>] marcar", "No mapa", "Fora do mapa", "Carroça", "$1 por perto — carga mais leve"); AddMapPin(localization, "Portuguese_European", "No mapa [<color=yellow><b>Shift+E</b></color>] tirar", "Fora do mapa [<color=yellow><b>Shift+E</b></color>] marcar", "No mapa", "Fora do mapa", "Carro", "$1 por perto — carga mais leve"); AddMapPin(localization, "Spanish", "En el mapa [<color=yellow><b>Shift+E</b></color>] quitar", "Fuera del mapa [<color=yellow><b>Shift+E</b></color>] marcar", "En el mapa", "Fuera del mapa", "Carro", "$1 cerca — carga más ligera"); AddMapPin(localization, "French", "Sur la carte [<color=yellow><b>Shift+E</b></color>] retirer", "Hors carte [<color=yellow><b>Shift+E</b></color>] afficher", "Sur la carte", "Hors carte", "Charrette", "$1 proches — charge plus légère"); AddMapPin(localization, "German", "Auf der Karte [<color=yellow><b>Shift+E</b></color>] ausblenden", "Nicht auf der Karte [<color=yellow><b>Shift+E</b></color>] zeigen", "Auf der Karte", "Nicht auf der Karte", "Karren", "$1 in der Nähe — leichtere Last"); AddMapPin(localization, "Italian", "Sulla mappa [<color=yellow><b>Shift+E</b></color>] nascondi", "Fuori mappa [<color=yellow><b>Shift+E</b></color>] mostra", "Sulla mappa", "Fuori mappa", "Carro", "$1 vicini — carico più leggero"); AddMapPin(localization, "Dutch", "Op de kaart [<color=yellow><b>Shift+E</b></color>] verbergen", "Niet op de kaart [<color=yellow><b>Shift+E</b></color>] tonen", "Op de kaart", "Niet op de kaart", "Kar", "$1 dichtbij — lichtere vracht"); AddMapPin(localization, "Swedish", "På kartan [<color=yellow><b>Shift+E</b></color>] dölj", "Inte på kartan [<color=yellow><b>Shift+E</b></color>] visa", "På kartan", "Inte på kartan", "Vagn", "$1 nära — lättare last"); AddMapPin(localization, "Polish", "Na mapie [<color=yellow><b>Shift+E</b></color>] ukryj", "Poza mapą [<color=yellow><b>Shift+E</b></color>] pokaż", "Na mapie", "Poza mapą", "Wóz", "$1 w pobliżu — lżejszy ładunek"); AddMapPin(localization, "Russian", "На карте [<color=yellow><b>Shift+E</b></color>] скрыть", "Не на карте [<color=yellow><b>Shift+E</b></color>] показать", "На карте", "Не на карте", "Телега", "Рядом: $1 — груз легче"); AddMapPin(localization, "Ukrainian", "На мапі [<color=yellow><b>Shift+E</b></color>] сховати", "Не на мапі [<color=yellow><b>Shift+E</b></color>] показати", "На мапі", "Не на мапі", "Віз", "Поруч: $1 — вантаж легший"); AddMapPin(localization, "Czech", "Na mapě [<color=yellow><b>Shift+E</b></color>] skrýt", "Mimo mapu [<color=yellow><b>Shift+E</b></color>] zobrazit", "Na mapě", "Mimo mapu", "Vůz", "$1 poblíž — lehčí náklad"); AddMapPin(localization, "Hungarian", "A térképen [<color=yellow><b>Shift+E</b></color>] elrejt", "Nincs a térképen [<color=yellow><b>Shift+E</b></color>] mutat", "A térképen", "Nincs a térképen", "Szekér", "$1 a közelben — könnyebb teher"); AddMapPin(localization, "Romanian", "Pe hartă [<color=yellow><b>Shift+E</b></color>] ascunde", "Nu e pe hartă [<color=yellow><b>Shift+E</b></color>] arată", "Pe hartă", "Nu e pe hartă", "Car", "$1 aproape — încărcătură mai ușoară"); AddMapPin(localization, "Turkish", "Haritada [<color=yellow><b>Shift+E</b></color>] gizle", "Haritada değil [<color=yellow><b>Shift+E</b></color>] göster", "Haritada", "Haritada değil", "Araba", "Yakında $1 kişi — yük hafif"); AddMapPin(localization, "Chinese", "在地图上 [<color=yellow><b>Shift+E</b></color>] 隐藏", "不在地图上 [<color=yellow><b>Shift+E</b></color>] 显示", "在地图上", "不在地图上", "推车", "附近 $1 人 — 负担更轻"); AddMapPin(localization, "Chinese_Trad", "在地圖上 [<color=yellow><b>Shift+E</b></color>] 隱藏", "不在地圖上 [<color=yellow><b>Shift+E</b></color>] 顯示", "在地圖上", "不在地圖上", "推車", "附近 $1 人 — 負擔更輕"); AddMapPin(localization, "Japanese", "地図に表示中 [<color=yellow><b>Shift+E</b></color>] 隠す", "地図に非表示 [<color=yellow><b>Shift+E</b></color>] 表示", "地図に表示", "地図から外した", "荷車", "近くに $1 人 — 荷が軽い"); AddMapPin(localization, "Korean", "지도에 표시됨 [<color=yellow><b>Shift+E</b></color>] 숨기기", "지도에 없음 [<color=yellow><b>Shift+E</b></color>] 표시", "지도에 표시", "지도에서 숨김", "수레", "근처 $1명 — 짐이 가벼워짐"); } private static void AddMapPin(CustomLocalization loc, string language, string hoverOn, string hoverOff, string on, string off, string name, string buddyHover) { loc.AddTranslation(ref language, new Dictionary<string, string> { { "wagonborn_mappin_hover_on", hoverOn }, { "wagonborn_mappin_hover_off", hoverOff }, { "wagonborn_mappin_on", on }, { "wagonborn_mappin_off", off }, { "wagonborn_mappin_name", name }, { "wagonborn_buddy_hover", buddyHover } }); } private static void Add(CustomLocalization loc, string language, string skill, string description, string hover, string cartPortal, string cartPortalHint, string buddyHint) { loc.AddTranslation(ref language, new Dictionary<string, string> { { "skill_wagonborn_hauling", skill }, { "skill_wagonborn_hauling_desc", description }, { "wagonborn_hover", hover }, { "wagonborn_cart_portal", cartPortal }, { "wagonborn_cart_portal_hint", cartPortalHint }, { "wagonborn_buddy_hint", buddyHint } }); } } internal static class PluginConfig { internal static ConfigEntry<float> MaxSkillMassReduction; internal static ConfigEntry<float> XpPerSecond; internal static ConfigEntry<float> MinSpeedForXp; internal static ConfigEntry<float> LoadXpScale; internal static ConfigEntry<bool> EnableCartPortal; internal static ConfigEntry<float> CartSearchRadius; internal static ConfigEntry<bool> PreventCartAutoDetach; internal static ConfigEntry<float> AttachLeash; internal static ConfigEntry<float> AttachDistance; internal static ConfigEntry<bool> AllowOutOfPlaceAttach; internal static ConfigEntry<bool> EnableBuddyHelp; internal static ConfigEntry<float> BuddyRange; internal static ConfigEntry<int> MaxBuddies; internal static ConfigEntry<float> BuddyMassReduction; internal static ConfigEntry<float> BuddyXpMultiplier; internal static ConfigEntry<bool> EnableCartMapPin; internal static void Bind(ConfigFile config) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Expected O, but got Unknown //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Expected O, but got Unknown //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Expected O, but got Unknown //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Expected O, but got Unknown //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Expected O, but got Unknown //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Expected O, but got Unknown //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Expected O, but got Unknown //IL_0287: Unknown result type (might be due to invalid IL or missing references) //IL_0291: Expected O, but got Unknown MaxSkillMassReduction = config.Bind<float>("Hauling", "MaxSkillMassReduction", 0.5f, new ConfigDescription("Cart mass reduction at Hauling 100 (0.50 = 50%). Hills still matter.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.8f), Array.Empty<object>())); XpPerSecond = config.Bind<float>("Hauling", "XpPerSecond", 0.35f, "Base Hauling XP per second while pulling a moving cart."); MinSpeedForXp = config.Bind<float>("Hauling", "MinSpeedForXp", 0.6f, "Cart must move faster than this (m/s) to grant XP."); LoadXpScale = config.Bind<float>("Hauling", "LoadXpScale", 240f, new ConfigDescription("A full cart teaches more. XP is multiplied by (cart + cargo weight) / this, never below 1. An empty cart weighs about 20.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(20f, 2000f), Array.Empty<object>())); EnableCartPortal = config.Bind<bool>("Portal", "EnableCartPortal", true, "Attached cart teleports with you through portals and dungeon rune stones."); CartSearchRadius = config.Bind<float>("Portal", "CartSearchRadius", 10f, new ConfigDescription("Meters around the teleport point to find your attached cart.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 30f), Array.Empty<object>())); PreventCartAutoDetach = config.Bind<bool>("Portal", "PreventCartAutoDetach", true, "While pulling, allow a longer leash before the cart auto-drops (see AttachLeash). Unhitch with Use (E) anytime."); AttachLeash = config.Bind<float>("Portal", "AttachLeash", 8f, new ConfigDescription("Max meters from the hitch before auto-detach when PreventCartAutoDetach is on (vanilla is ~2).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(3f, 20f), Array.Empty<object>())); AttachDistance = config.Bind<float>("Crew", "AttachDistance", 3f, new ConfigDescription("Max meters from the hitch point when attaching with Use (E).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 5f), Array.Empty<object>())); AllowOutOfPlaceAttach = config.Bind<bool>("Crew", "AllowOutOfPlaceAttach", true, "Allow attach with Use (E) when not perfectly lined up (uses AttachDistance)."); EnableBuddyHelp = config.Bind<bool>("Crew", "EnableBuddyHelp", true, "Nearby friends lighten a pulled cart. Helpers also earn Hauling XP while it moves."); BuddyRange = config.Bind<float>("Crew", "BuddyRange", 5f, new ConfigDescription("Meters around the cart to count as helping.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 12f), Array.Empty<object>())); MaxBuddies = config.Bind<int>("Crew", "MaxBuddies", 4, new ConfigDescription("Max helpers (not counting the puller) that reduce mass.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 8), Array.Empty<object>())); BuddyMassReduction = config.Bind<float>("Crew", "BuddyMassReduction", 0.15f, new ConfigDescription("Mass cut per helper (0.15 = 15% each). Stacks up to MaxBuddies.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 0.4f), Array.Empty<object>())); BuddyXpMultiplier = config.Bind<float>("Crew", "BuddyXpMultiplier", 1f, new ConfigDescription("Hauling XP rate for helpers vs the puller (1 = same rate).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 1.5f), Array.Empty<object>())); EnableCartMapPin = config.Bind<bool>("Map", "EnableCartMapPin", true, "Every cart shows a live map pin by default. Shift+E on a cart hides or shows that one, just for you."); } } [BepInPlugin("com.blackhearthx.wagonborn", "Wagonborn", "1.3.3")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public class WagonbornPlugin : BaseUnityPlugin { public const string PluginGUID = "com.blackhearthx.wagonborn"; public const string PluginName = "Wagonborn"; public const string PluginVersion = "1.3.3"; internal static WagonbornPlugin Instance { get; private set; } internal static Harmony Harmony { get; private set; } private void Awake() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown Instance = this; PluginConfig.Bind(((BaseUnityPlugin)this).Config); ModLocalization.Register(); HaulingSkill.Register(); Harmony = new Harmony("com.blackhearthx.wagonborn"); try { Harmony.PatchAll(Assembly.GetExecutingAssembly()); } catch (Exception arg) { Logger.LogError((object)$"Harmony patch failed: {arg}"); } Logger.LogInfo((object)"Wagonborn 1.3.3 loaded (com.blackhearthx.wagonborn)"); } private void Update() { HaulingProgress.Tick(); CartMapPin.Tick(); } private void LateUpdate() { CartMapPin.LateTickUi(); } private void OnDestroy() { Harmony harmony = Harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } }