using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("")] [assembly: AssemblyCompany("REPOJP")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("zabuMod")] [assembly: AssemblyTitle("zabuMod")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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 REPOJP.ShopItemClone { [BepInPlugin("REPOJP.ShopItemClone", "Shop Item Clone", "4.0.0")] public sealed class ShopItemClonePlugin : BaseUnityPlugin { public const string PluginGuid = "REPOJP.ShopItemClone"; public const string PluginName = "Shop Item Clone"; public const string PluginVersion = "4.0.0"; internal static ManualLogSource LogSource; internal static ShopItemClonePlugin Instance; internal static ConfigEntry CloneUpgrades; internal static ConfigEntry CloneMeleeWeapons; internal static ConfigEntry CloneGuns; internal static ConfigEntry CloneCarts; internal static ConfigEntry ClonePocketCarts; internal static ConfigEntry CloneDrones; internal static ConfigEntry CloneOrbs; internal static ConfigEntry CloneHealthPacks; internal static ConfigEntry CloneExplosives; internal static ConfigEntry CloneEnergyCrystals; internal static ConfigEntry CloneTrackers; internal static ConfigEntry CloneTools; internal static ConfigEntry CloneVehicles; internal static ConfigEntry CloneLaunchers; internal static ConfigEntry PreventCloneInExtractionPoint; internal static ConfigEntry MaxUpgradesPerShop; internal static ConfigEntry MaxMeleeWeaponsPerShop; internal static ConfigEntry MaxGunsPerShop; internal static ConfigEntry MaxCartsPerShop; internal static ConfigEntry MaxPocketCartsPerShop; internal static ConfigEntry MaxDronesPerShop; internal static ConfigEntry MaxOrbsPerShop; internal static ConfigEntry MaxHealthPacksPerShop; internal static ConfigEntry MaxExplosivesPerShop; internal static ConfigEntry MaxEnergyCrystalsPerShop; internal static ConfigEntry MaxTrackersPerShop; internal static ConfigEntry MaxToolsPerShop; internal static ConfigEntry MaxVehiclesPerShop; internal static ConfigEntry MaxLaunchersPerShop; internal static ConfigEntry MinCloneIntervalSeconds; internal static ConfigEntry RequireImpactThreshold; internal static ConfigEntry MinimumImpactForce; internal static ConfigEntry EnableDebugLog; private Harmony harmony; private void Awake() { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown try { Instance = this; LogSource = ((BaseUnityPlugin)this).Logger; ((Component)this).gameObject.transform.parent = null; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); BindConfig(); ShopItemCloneRuntime.EnsureCreated(); harmony = new Harmony("REPOJP.ShopItemClone"); harmony.PatchAll(typeof(ShopItemClonePlugin).Assembly); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Shop Item Clone 4.0.0 loaded"); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Failure: Failed to initialize Shop Item Clone\n" + ex)); } } private void OnDestroy() { try { if (harmony != null) { harmony.UnpatchSelf(); } } catch { } } private void BindConfig() { //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Expected O, but got Unknown //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Expected O, but got Unknown CloneUpgrades = ((BaseUnityPlugin)this).Config.Bind("Category Toggle", "Clone Upgrades", true, "Clone item upgrades and player upgrades. アップグレード系アイテムの複製"); CloneMeleeWeapons = ((BaseUnityPlugin)this).Config.Bind("Category Toggle", "Clone Melee Weapons", true, "Clone melee weapons. 近接武器の複製"); CloneGuns = ((BaseUnityPlugin)this).Config.Bind("Category Toggle", "Clone Guns", true, "Clone guns. 銃の複製"); CloneCarts = ((BaseUnityPlugin)this).Config.Bind("Category Toggle", "Clone Carts", true, "Clone carts. カートの複製"); ClonePocketCarts = ((BaseUnityPlugin)this).Config.Bind("Category Toggle", "Clone Pocket Carts", true, "Clone pocket carts. ポケットカートの複製"); CloneDrones = ((BaseUnityPlugin)this).Config.Bind("Category Toggle", "Clone Drones", true, "Clone drones. ドローンの複製"); CloneOrbs = ((BaseUnityPlugin)this).Config.Bind("Category Toggle", "Clone Orbs", true, "Clone orbs. オーブの複製"); CloneHealthPacks = ((BaseUnityPlugin)this).Config.Bind("Category Toggle", "Clone Health Packs", true, "Clone health packs. ヘルスパックの複製"); CloneExplosives = ((BaseUnityPlugin)this).Config.Bind("Category Toggle", "Clone Explosives", true, "Clone grenades and mines. グレネードと地雷の複製"); CloneEnergyCrystals = ((BaseUnityPlugin)this).Config.Bind("Category Toggle", "Clone Energy Crystals", true, "Clone energy crystals. エナジークリスタルの複製"); CloneTrackers = ((BaseUnityPlugin)this).Config.Bind("Category Toggle", "Clone Trackers", true, "Clone trackers. トラッカー系アイテムの複製"); CloneTools = ((BaseUnityPlugin)this).Config.Bind("Category Toggle", "Clone Tools", true, "Clone tools added in v0.4.0 and later. v0.4.0以降のツール系アイテムの複製"); CloneVehicles = ((BaseUnityPlugin)this).Config.Bind("Category Toggle", "Clone Vehicles", true, "Clone vehicles added in v0.4.0 and later. v0.4.0以降の乗り物系アイテムの複製"); CloneLaunchers = ((BaseUnityPlugin)this).Config.Bind("Category Toggle", "Clone Launchers", true, "Clone launchers and staff-like launcher items. ランチャーや杖系アイテムの複製"); PreventCloneInExtractionPoint = ((BaseUnityPlugin)this).Config.Bind("General", "Prevent Clone In Extraction Point", true, "Prevent cloning while the held item is inside the extraction point. 納品所内にある手持ちアイテムの複製を禁止"); MinCloneIntervalSeconds = ((BaseUnityPlugin)this).Config.Bind("General", "Min Clone Interval Seconds", 0.15f, new ConfigDescription("Minimum seconds between clones from the same source item. 同じ元アイテムから次に複製できるまでの最小秒数", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 5f), Array.Empty())); RequireImpactThreshold = ((BaseUnityPlugin)this).Config.Bind("Impact Requirement", "Require Impact Threshold", true, "Require impact force threshold instead of cloning on any ground contact. 地面接触だけでなく一定以上の衝撃を必要にする"); MinimumImpactForce = ((BaseUnityPlugin)this).Config.Bind("Impact Requirement", "Minimum Impact Force", 60f, new ConfigDescription("Minimum PhysGrabObjectImpactDetector impact force required for cloning. 20=Light, 80=Medium, 150=Heavy. 複製に必要な衝撃値 20=軽 80=中 150=強", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 200f), Array.Empty())); MaxUpgradesPerShop = BindMax("Max Upgrades Per Shop", 0, "Max upgrade clones per shop. 0 means unlimited. ショップごとのアップグレード複製上限 0は無制限"); MaxMeleeWeaponsPerShop = BindMax("Max Melee Weapons Per Shop", 0, "Max melee weapon clones per shop. 0 means unlimited. ショップごとの近接武器複製上限 0は無制限"); MaxGunsPerShop = BindMax("Max Guns Per Shop", 0, "Max gun clones per shop. 0 means unlimited. ショップごとの銃複製上限 0は無制限"); MaxCartsPerShop = BindMax("Max Carts Per Shop", 5, "Max cart clones per shop. 0 means unlimited. ショップごとのカート複製上限 0は無制限"); MaxPocketCartsPerShop = BindMax("Max Pocket Carts Per Shop", 5, "Max pocket cart clones per shop. 0 means unlimited. ショップごとのポケットカート複製上限 0は無制限"); MaxDronesPerShop = BindMax("Max Drones Per Shop", 0, "Max drone clones per shop. 0 means unlimited. ショップごとのドローン複製上限 0は無制限"); MaxOrbsPerShop = BindMax("Max Orbs Per Shop", 0, "Max orb clones per shop. 0 means unlimited. ショップごとのオーブ複製上限 0は無制限"); MaxHealthPacksPerShop = BindMax("Max Health Packs Per Shop", 0, "Max health pack clones per shop. 0 means unlimited. ショップごとのヘルスパック複製上限 0は無制限"); MaxExplosivesPerShop = BindMax("Max Explosives Per Shop", 0, "Max explosive clones per shop. 0 means unlimited. ショップごとの爆破物複製上限 0は無制限"); MaxEnergyCrystalsPerShop = BindMax("Max Energy Crystals Per Shop", 0, "Max energy crystal clones per shop. 0 means unlimited. ショップごとのエナジークリスタル複製上限 0は無制限"); MaxTrackersPerShop = BindMax("Max Trackers Per Shop", 0, "Max tracker clones per shop. 0 means unlimited. ショップごとのトラッカー複製上限 0は無制限"); MaxToolsPerShop = BindMax("Max Tools Per Shop", 0, "Max tool clones per shop. 0 means unlimited. ショップごとのツール複製上限 0は無制限"); MaxVehiclesPerShop = BindMax("Max Vehicles Per Shop", 0, "Max vehicle clones per shop. 0 means unlimited. ショップごとの乗り物複製上限 0は無制限"); MaxLaunchersPerShop = BindMax("Max Launchers Per Shop", 0, "Max launcher clones per shop. 0 means unlimited. ショップごとのランチャー複製上限 0は無制限"); EnableDebugLog = ((BaseUnityPlugin)this).Config.Bind("Debug", "Enable Debug Log", false, "Enable detailed clone decision logs. 詳細な複製判定ログを出力"); } private ConfigEntry BindMax(string key, int defaultValue, string description) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown return ((BaseUnityPlugin)this).Config.Bind("Category Max Per Shop", key, defaultValue, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange(0, 999), Array.Empty())); } internal static void LogDebug(string message) { if (EnableDebugLog != null && EnableDebugLog.Value && LogSource != null) { LogSource.LogInfo((object)message); } } } internal sealed class ShopItemCloneRuntime : MonoBehaviour { private sealed class ContactState { internal PhysGrabObject Source; internal bool Latched; internal float LastValidGroundContactTime; internal float LastCloneTime; } [CompilerGenerated] private sealed class d__52 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public PhysGrabObject source; public ItemAttributes sourceItem; public GameObject cloneObject; public ShopItemCloneRuntime <>4__this; private ItemAttributes 5__1; private PhotonView 5__2; private Rigidbody 5__3; private Rigidbody 5__4; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__52(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 5__1 = null; 5__2 = null; 5__3 = null; 5__4 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; <>2__current = null; <>1__state = 2; return true; case 2: <>1__state = -1; if ((Object)(object)source == (Object)null || (Object)(object)sourceItem == (Object)null || (Object)(object)cloneObject == (Object)null) { return false; } 5__1 = cloneObject.GetComponent(); 5__2 = cloneObject.GetComponent(); 5__3 = source.rb; 5__4 = cloneObject.GetComponent(); if ((Object)(object)5__1 == (Object)null) { return false; } TryApplyInitialMotion(5__3, 5__4); CopyItemValue(sourceItem, 5__1, 5__2); CopyToggleState(source, cloneObject); CopyBatteryState(source, cloneObject, 5__2); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__56 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public GameObject sourceObject; public GameObject cloneObject; public float duration; public ShopItemCloneRuntime <>4__this; private Collider[] 5__1; private Collider[] 5__2; private int 5__3; private Collider 5__4; private int 5__5; private Collider 5__6; private int 5__7; private Collider 5__8; private int 5__9; private Collider 5__10; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__56(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 5__1 = null; 5__2 = null; 5__4 = null; 5__6 = null; 5__8 = null; 5__10 = null; <>1__state = -2; } private bool MoveNext() { //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; if ((Object)(object)sourceObject == (Object)null || (Object)(object)cloneObject == (Object)null) { return false; } 5__1 = sourceObject.GetComponentsInChildren(true); 5__2 = cloneObject.GetComponentsInChildren(true); 5__3 = 0; while (5__3 < 5__1.Length) { 5__4 = 5__1[5__3]; if (!((Object)(object)5__4 == (Object)null)) { 5__5 = 0; while (5__5 < 5__2.Length) { 5__6 = 5__2[5__5]; if (!((Object)(object)5__6 == (Object)null)) { Physics.IgnoreCollision(5__4, 5__6, true); 5__6 = null; } 5__5++; } 5__4 = null; } 5__3++; } <>2__current = (object)new WaitForSeconds(duration); <>1__state = 1; return true; case 1: <>1__state = -1; if ((Object)(object)sourceObject == (Object)null || (Object)(object)cloneObject == (Object)null) { return false; } 5__7 = 0; while (5__7 < 5__1.Length) { 5__8 = 5__1[5__7]; if (!((Object)(object)5__8 == (Object)null)) { 5__9 = 0; while (5__9 < 5__2.Length) { 5__10 = 5__2[5__9]; if (!((Object)(object)5__10 == (Object)null)) { Physics.IgnoreCollision(5__8, 5__10, false); 5__10 = null; } 5__9++; } 5__8 = null; } 5__7++; } return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private const float DefaultCloneHeightOffset = 0.01f; private const float CartCloneHeightOffset = 1f; private const float VehicleCloneHeightOffset = 1f; private const float CloneCollisionIgnoreSeconds = 0.2f; private const float CloneImpactDisableSeconds = 0.2f; private const float RearmNoContactSeconds = 0.08f; private const float GroundNormalMinY = 0.35f; private const string CategoryUpgrades = "Upgrades"; private const string CategoryMeleeWeapons = "MeleeWeapons"; private const string CategoryGuns = "Guns"; private const string CategoryCarts = "Carts"; private const string CategoryPocketCarts = "PocketCarts"; private const string CategoryDrones = "Drones"; private const string CategoryOrbs = "Orbs"; private const string CategoryHealthPacks = "HealthPacks"; private const string CategoryExplosives = "Explosives"; private const string CategoryEnergyCrystals = "EnergyCrystals"; private const string CategoryTrackers = "Trackers"; private const string CategoryTools = "Tools"; private const string CategoryVehicles = "Vehicles"; private const string CategoryLaunchers = "Launchers"; private const string CategoryUnknown = "Unknown"; private static ShopItemCloneRuntime instance; private static readonly FieldInfo ItemValueField = AccessTools.Field(typeof(ItemAttributes), "value"); private static readonly FieldInfo InExtractionPointField = AccessTools.Field(typeof(RoomVolumeCheck), "inExtractionPoint"); private static readonly FieldInfo ImpactForceField = AccessTools.Field(typeof(PhysGrabObjectImpactDetector), "impactForce"); private static readonly MethodInfo BatteryFullPercentChangeMethod = AccessTools.Method(typeof(ItemBattery), "BatteryFullPercentChange", (Type[])null, (Type[])null); private readonly Dictionary contactStates = new Dictionary(); private readonly Dictionary categoryCloneCounts = new Dictionary(); private bool wasShopMainPhase; internal static ShopItemCloneRuntime Instance => instance; internal static void EnsureCreated() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown if (!((Object)(object)instance != (Object)null)) { GameObject val = new GameObject("ShopItemCloneRuntime"); val.transform.parent = null; ((Object)val).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)val); instance = val.AddComponent(); } } private void Update() { try { bool flag = IsShopMainPhase(); if (flag && !wasShopMainPhase) { ResetShopCounters(); } else if (!flag && wasShopMainPhase) { ResetShopCounters(); contactStates.Clear(); } wasShopMainPhase = flag; if (contactStates.Count == 0) { return; } float unscaledTime = Time.unscaledTime; List removeKeys = null; foreach (KeyValuePair contactState in contactStates) { ContactState value = contactState.Value; PhysGrabObject source = value.Source; if ((Object)(object)source == (Object)null) { AddRemoveKey(ref removeKeys, contactState.Key); continue; } bool flag2 = IsActuallyHeld(source); bool flag3 = IsShopMainPhase(); if (!flag2 || !flag3) { AddRemoveKey(ref removeKeys, contactState.Key); } else if (unscaledTime - value.LastValidGroundContactTime > 0.08f) { value.Latched = false; } } if (removeKeys != null) { for (int i = 0; i < removeKeys.Count; i++) { contactStates.Remove(removeKeys[i]); } } } catch (Exception ex) { if (ShopItemClonePlugin.LogSource != null) { ShopItemClonePlugin.LogSource.LogError((object)("Failure: Runtime update failed\n" + ex)); } } } private static void AddRemoveKey(ref List removeKeys, int key) { if (removeKeys == null) { removeKeys = new List(); } removeKeys.Add(key); } internal void OnImpactStay(PhysGrabObjectImpactDetector detector, Collision collision) { try { if ((Object)(object)detector == (Object)null || collision == null || !IsHostAuthority() || !IsShopMainPhase()) { return; } PhysGrabObject component = ((Component)detector).GetComponent(); if ((Object)(object)component == (Object)null) { return; } ItemAttributes component2 = ((Component)component).GetComponent(); if ((Object)(object)component2 == (Object)null || (Object)(object)component2.item == (Object)null || (Object)(object)((Component)component).GetComponent() != (Object)null) { return; } string categoryKey = GetCategoryKey(component2); if (!IsCategoryEnabled(categoryKey) || !IsActuallyHeld(component) || (ShopItemClonePlugin.PreventCloneInExtractionPoint != null && ShopItemClonePlugin.PreventCloneInExtractionPoint.Value && IsInsideExtractionPoint(component)) || !IsGroundLikeEnvironmentCollision(collision)) { return; } int instanceID = ((Object)component).GetInstanceID(); if (!contactStates.TryGetValue(instanceID, out var value)) { value = new ContactState(); value.Source = component; value.LastCloneTime = -999f; contactStates[instanceID] = value; } float num = (value.LastValidGroundContactTime = Time.unscaledTime); if (value.Latched) { return; } float num2 = Mathf.Clamp(ShopItemClonePlugin.MinCloneIntervalSeconds.Value, 0f, 5f); if (num - value.LastCloneTime < num2) { return; } float impactForce = GetImpactForce(detector, collision); if (ShopItemClonePlugin.RequireImpactThreshold != null && ShopItemClonePlugin.RequireImpactThreshold.Value) { float num3 = Mathf.Clamp(ShopItemClonePlugin.MinimumImpactForce.Value, 0f, 200f); if (impactForce < num3) { ShopItemClonePlugin.LogDebug("Impact skipped category=" + categoryKey + " force=" + impactForce.ToString("0.00") + " required=" + num3.ToString("0.00")); return; } } if (!CanCloneCategoryThisShop(categoryKey)) { ShopItemClonePlugin.LogDebug("Category max skipped category=" + categoryKey); return; } value.Latched = true; value.LastCloneTime = num; CloneHeldShopItem(component, component2, categoryKey); } catch (Exception ex) { if (ShopItemClonePlugin.LogSource != null) { ShopItemClonePlugin.LogSource.LogError((object)("Failure: Impact handling failed\n" + ex)); } } } private static bool IsHostAuthority() { try { if (!GameManager.Multiplayer()) { return true; } } catch { if (!PhotonNetwork.InRoom) { return true; } } return PhotonNetwork.IsMasterClient; } private static bool IsShopMainPhase() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Invalid comparison between Unknown and I4 try { if (!SemiFunc.RunIsShop()) { return false; } if ((Object)(object)GameDirector.instance == (Object)null) { return false; } return (int)GameDirector.instance.currentState == 2; } catch { return false; } } private static string GetCategoryKey(ItemAttributes itemAttributes) { if ((Object)(object)itemAttributes == (Object)null || (Object)(object)itemAttributes.item == (Object)null) { return "Unknown"; } string empty = string.Empty; try { empty = ((object)(itemType)(ref itemAttributes.item.itemType)).ToString(); } catch { empty = string.Empty; } if (empty == "item_upgrade" || empty == "player_upgrade") { return "Upgrades"; } switch (empty) { case "melee": return "MeleeWeapons"; case "gun": return "Guns"; case "cart": return "Carts"; case "pocket_cart": return "PocketCarts"; case "drone": return "Drones"; case "orb": return "Orbs"; case "healthPack": return "HealthPacks"; default: if (!(empty == "mine")) { return empty switch { "power_crystal" => "EnergyCrystals", "tracker" => "Trackers", "tool" => "Tools", "vehicle" => "Vehicles", "launcher" => "Launchers", _ => "Unknown", }; } goto case "grenade"; case "grenade": return "Explosives"; } } private static bool IsCategoryEnabled(string category) { return category switch { "Upgrades" => ShopItemClonePlugin.CloneUpgrades != null && ShopItemClonePlugin.CloneUpgrades.Value, "MeleeWeapons" => ShopItemClonePlugin.CloneMeleeWeapons != null && ShopItemClonePlugin.CloneMeleeWeapons.Value, "Guns" => ShopItemClonePlugin.CloneGuns != null && ShopItemClonePlugin.CloneGuns.Value, "Carts" => ShopItemClonePlugin.CloneCarts != null && ShopItemClonePlugin.CloneCarts.Value, "PocketCarts" => ShopItemClonePlugin.ClonePocketCarts != null && ShopItemClonePlugin.ClonePocketCarts.Value, "Drones" => ShopItemClonePlugin.CloneDrones != null && ShopItemClonePlugin.CloneDrones.Value, "Orbs" => ShopItemClonePlugin.CloneOrbs != null && ShopItemClonePlugin.CloneOrbs.Value, "HealthPacks" => ShopItemClonePlugin.CloneHealthPacks != null && ShopItemClonePlugin.CloneHealthPacks.Value, "Explosives" => ShopItemClonePlugin.CloneExplosives != null && ShopItemClonePlugin.CloneExplosives.Value, "EnergyCrystals" => ShopItemClonePlugin.CloneEnergyCrystals != null && ShopItemClonePlugin.CloneEnergyCrystals.Value, "Trackers" => ShopItemClonePlugin.CloneTrackers != null && ShopItemClonePlugin.CloneTrackers.Value, "Tools" => ShopItemClonePlugin.CloneTools != null && ShopItemClonePlugin.CloneTools.Value, "Vehicles" => ShopItemClonePlugin.CloneVehicles != null && ShopItemClonePlugin.CloneVehicles.Value, "Launchers" => ShopItemClonePlugin.CloneLaunchers != null && ShopItemClonePlugin.CloneLaunchers.Value, _ => false, }; } private bool CanCloneCategoryThisShop(string category) { int categoryMax = GetCategoryMax(category); if (categoryMax <= 0) { return true; } if (!categoryCloneCounts.TryGetValue(category, out var value)) { value = 0; } return value < categoryMax; } private void RegisterCategoryClone(string category) { if (!categoryCloneCounts.TryGetValue(category, out var value)) { value = 0; } categoryCloneCounts[category] = value + 1; } private static int GetCategoryMax(string category) { return category switch { "Upgrades" => ShopItemClonePlugin.MaxUpgradesPerShop.Value, "MeleeWeapons" => ShopItemClonePlugin.MaxMeleeWeaponsPerShop.Value, "Guns" => ShopItemClonePlugin.MaxGunsPerShop.Value, "Carts" => ShopItemClonePlugin.MaxCartsPerShop.Value, "PocketCarts" => ShopItemClonePlugin.MaxPocketCartsPerShop.Value, "Drones" => ShopItemClonePlugin.MaxDronesPerShop.Value, "Orbs" => ShopItemClonePlugin.MaxOrbsPerShop.Value, "HealthPacks" => ShopItemClonePlugin.MaxHealthPacksPerShop.Value, "Explosives" => ShopItemClonePlugin.MaxExplosivesPerShop.Value, "EnergyCrystals" => ShopItemClonePlugin.MaxEnergyCrystalsPerShop.Value, "Trackers" => ShopItemClonePlugin.MaxTrackersPerShop.Value, "Tools" => ShopItemClonePlugin.MaxToolsPerShop.Value, "Vehicles" => ShopItemClonePlugin.MaxVehiclesPerShop.Value, "Launchers" => ShopItemClonePlugin.MaxLaunchersPerShop.Value, _ => 0, }; } private static bool IsActuallyHeld(PhysGrabObject source) { if ((Object)(object)source == (Object)null) { return false; } if (!source.grabbed) { return false; } List playerGrabbing = source.playerGrabbing; if (playerGrabbing == null || playerGrabbing.Count == 0) { return false; } for (int i = 0; i < playerGrabbing.Count; i++) { PhysGrabber val = playerGrabbing[i]; if (!((Object)(object)val == (Object)null) && val.grabbed && !((Object)(object)val.grabbedPhysGrabObject != (Object)(object)source)) { return true; } } return false; } private static bool IsInsideExtractionPoint(PhysGrabObject source) { if ((Object)(object)source == (Object)null) { return false; } RoomVolumeCheck val = ((Component)source).GetComponent(); if ((Object)(object)val == (Object)null) { val = ((Component)source).GetComponentInChildren(); } if ((Object)(object)val == (Object)null) { val = ((Component)source).GetComponentInParent(); } if ((Object)(object)val == (Object)null) { return false; } try { val.CheckSet(); if (InExtractionPointField != null) { object value = InExtractionPointField.GetValue(val); if (value is bool) { return (bool)value; } } } catch { } return false; } private static bool IsGroundLikeEnvironmentCollision(Collision collision) { //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) if (collision == null) { return false; } Transform transform = collision.transform; if ((Object)(object)transform == (Object)null) { return false; } MaterialSurface val = ((Component)transform).GetComponent(); if ((Object)(object)val == (Object)null) { val = ((Component)transform).GetComponentInParent(); } if ((Object)(object)val == (Object)null) { return false; } if ((Object)(object)((Component)transform).GetComponentInParent() != (Object)null) { return false; } if (((Component)transform).CompareTag("Player") || (Object)(object)((Component)transform).GetComponentInParent() != (Object)null) { return false; } if ((Object)(object)((Component)transform).GetComponentInParent() != (Object)null) { return false; } if ((Object)(object)((Component)transform).GetComponentInParent() != (Object)null) { return false; } float num = -1f; ContactPoint[] contacts = collision.contacts; for (int i = 0; i < contacts.Length; i++) { if (((ContactPoint)(ref contacts[i])).normal.y > num) { num = ((ContactPoint)(ref contacts[i])).normal.y; } } return num >= 0.35f; } private static float GetImpactForce(PhysGrabObjectImpactDetector detector, Collision collision) { //IL_00a4: 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) float num = 0f; try { if (ImpactForceField != null && (Object)(object)detector != (Object)null) { object value = ImpactForceField.GetValue(detector); if (value is float) { num = (float)value; } } } catch { num = 0f; } if (num > 0.01f) { return num; } try { Rigidbody val = (((Object)(object)detector != (Object)null) ? ((Component)detector).GetComponent() : null); float num2 = (((Object)(object)val != (Object)null) ? Mathf.Max(val.mass, 1f) : 1f); Vector3 relativeVelocity = collision.relativeVelocity; num = ((Vector3)(ref relativeVelocity)).magnitude * num2 * 10f; } catch { num = 0f; } return num; } private static bool IsCartLikeCategory(string category) { return category == "Carts" || category == "PocketCarts" || category == "Vehicles"; } private Vector3 GetCloneSpawnPosition(PhysGrabObject source, ItemAttributes sourceItem, string category) { //IL_004d: 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_0058: 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) //IL_0065: Unknown result type (might be due to invalid IL or missing references) float num = 0.01f; if (category == "Carts" || category == "PocketCarts") { num = 1f; } else if (category == "Vehicles") { num = 1f; } return ((Component)source).transform.position + Vector3.up * num; } private void ResetShopCounters() { categoryCloneCounts.Clear(); } private void CloneHeldShopItem(PhysGrabObject source, ItemAttributes sourceItem, string category) { //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: 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) //IL_0100: 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) if ((Object)(object)source == (Object)null || (Object)(object)sourceItem == (Object)null || (Object)(object)sourceItem.item == (Object)null || !CanCloneCategoryThisShop(category)) { return; } string text = null; if (sourceItem.item.prefab != null) { text = sourceItem.item.prefab.ResourcePath; } if (string.IsNullOrEmpty(text)) { if (ShopItemClonePlugin.LogSource != null) { ShopItemClonePlugin.LogSource.LogWarning((object)("Skipped clone because resource path was missing: " + ((Object)source).name)); } return; } Vector3 cloneSpawnPosition = GetCloneSpawnPosition(source, sourceItem, category); Quaternion rotation = ((Component)source).transform.rotation; GameObject val = null; if (GameManager.Multiplayer()) { val = PhotonNetwork.InstantiateRoomObject(text, cloneSpawnPosition, rotation, (byte)0, (object[])null); } else { GameObject prefab = sourceItem.item.prefab.Prefab; if ((Object)(object)prefab != (Object)null) { val = Object.Instantiate(prefab, cloneSpawnPosition, rotation); } } if (!((Object)(object)val == (Object)null)) { RegisterCategoryClone(category); Rigidbody rb = source.rb; Rigidbody component = val.GetComponent(); TryApplyInitialMotion(rb, component); PhysGrabObjectImpactDetector component2 = val.GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.ImpactDisable(0.2f); } ((MonoBehaviour)this).StartCoroutine(FinalizeCloneAfterStart(source, sourceItem, val)); ((MonoBehaviour)this).StartCoroutine(IgnoreCloneCollisionTemporary(((Component)source).gameObject, val, 0.2f)); ShopItemClonePlugin.LogDebug("Cloned item=" + ((Object)source).name + " category=" + category); } } private static void TryApplyInitialMotion(Rigidbody sourceRb, Rigidbody cloneRb) { //IL_002c: 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) if ((Object)(object)sourceRb == (Object)null || (Object)(object)cloneRb == (Object)null || cloneRb.isKinematic) { return; } try { cloneRb.velocity = sourceRb.velocity; cloneRb.angularVelocity = sourceRb.angularVelocity; } catch { } } [IteratorStateMachine(typeof(d__52))] private IEnumerator FinalizeCloneAfterStart(PhysGrabObject source, ItemAttributes sourceItem, GameObject cloneObject) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__52(0) { <>4__this = this, source = source, sourceItem = sourceItem, cloneObject = cloneObject }; } private static void CopyItemValue(ItemAttributes sourceItem, ItemAttributes cloneItem, PhotonView clonePhotonView) { if (ItemValueField == null || (Object)(object)sourceItem == (Object)null || (Object)(object)cloneItem == (Object)null) { return; } try { object value = ItemValueField.GetValue(sourceItem); if (value is int) { int num = (int)value; if (GameManager.Multiplayer() && (Object)(object)clonePhotonView != (Object)null) { clonePhotonView.RPC("GetValueRPC", (RpcTarget)0, new object[1] { num }); } else { cloneItem.GetValueRPC(num); } } } catch { } } private static void CopyToggleState(PhysGrabObject source, GameObject cloneObject) { if ((Object)(object)source == (Object)null || (Object)(object)cloneObject == (Object)null) { return; } try { ItemToggle component = ((Component)source).GetComponent(); ItemToggle component2 = cloneObject.GetComponent(); if ((Object)(object)component != (Object)null && (Object)(object)component2 != (Object)null && component2.toggleState != component.toggleState) { component2.ToggleItem(component.toggleState, -1); } } catch { } } private static void CopyBatteryState(PhysGrabObject source, GameObject cloneObject, PhotonView clonePhotonView) { if ((Object)(object)source == (Object)null || (Object)(object)cloneObject == (Object)null) { return; } try { ItemBattery component = ((Component)source).GetComponent(); ItemBattery component2 = cloneObject.GetComponent(); if (!((Object)(object)component == (Object)null) && !((Object)(object)component2 == (Object)null) && component2.batteryBars > 0) { int num = Mathf.Clamp(Mathf.RoundToInt(component.batteryLife / (100f / (float)component2.batteryBars)), 0, component2.batteryBars); if (GameManager.Multiplayer() && (Object)(object)clonePhotonView != (Object)null) { clonePhotonView.RPC("BatteryFullPercentChangeRPC", (RpcTarget)0, new object[2] { num, false }); } else if (BatteryFullPercentChangeMethod != null) { BatteryFullPercentChangeMethod.Invoke(component2, new object[2] { num, false }); } } } catch { } } [IteratorStateMachine(typeof(d__56))] private IEnumerator IgnoreCloneCollisionTemporary(GameObject sourceObject, GameObject cloneObject, float duration) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__56(0) { <>4__this = this, sourceObject = sourceObject, cloneObject = cloneObject, duration = duration }; } } [HarmonyPatch(typeof(PhysGrabObjectImpactDetector), "OnCollisionStay")] internal static class PhysGrabObjectImpactDetectorPatch { private static void Postfix(PhysGrabObjectImpactDetector __instance, Collision collision) { ShopItemCloneRuntime instance = ShopItemCloneRuntime.Instance; if (!((Object)(object)instance == (Object)null)) { instance.OnImpactStay(__instance, collision); } } } }