Decompiled source of CrowbarShop v1.0.0

CrowbarShop.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using Bifrost.Cooked;
using Bifrost.ShopGroup;
using CrowbarShop;
using HarmonyLib;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using Mimic;
using Mimic.Actors;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyTitle("CrowbarShop")]
[assembly: AssemblyProduct("CrowbarShop")]
[assembly: AssemblyCompany("dsh")]
[assembly: MelonInfo(typeof(Core), "CrowbarShop", "0.1.0", "dsh", null)]
[assembly: MelonGame("ReLUGames", "MIMESIS")]
[assembly: HarmonyDontPatchAll]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.0.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace CrowbarShop
{
	public sealed class Core : MelonMod
	{
		private float _timer;

		public override void OnInitializeMelon()
		{
			ModPreferences.Initialize();
			ApplyPatches();
			MelonLogger.Msg("[CrowbarShop] loaded");
		}

		private void ApplyPatches()
		{
			int num = 0;
			Type[] types = typeof(Core).Assembly.GetTypes();
			foreach (Type type in types)
			{
				if (type.GetCustomAttributes(typeof(HarmonyPatch), inherit: true).Any())
				{
					try
					{
						((MelonBase)this).HarmonyInstance.PatchAll(type);
						num++;
					}
					catch (Exception arg)
					{
						MelonLogger.Error($"[CrowbarShop] 补丁 {type.Name} 应用失败:{arg}");
					}
				}
			}
			MelonLogger.Msg($"[CrowbarShop] Harmony 补丁:{num} 个类,{((MelonBase)this).HarmonyInstance.GetPatchedMethods().Count()} 个方法。");
		}

		public override void OnUpdate()
		{
			if (!((Object)(object)Hub.s == (Object)null))
			{
				_timer += Time.unscaledDeltaTime;
				if (!(_timer < 1f))
				{
					_timer = 0f;
					ShopGroupInjector.EnsureInjected();
					CrowbarUnlock.Apply();
					CrowbarCombatTuning.Apply();
				}
			}
		}
	}
	[HarmonyPatch(typeof(MaintenanceScene), "Start")]
	internal static class MaintenanceSceneStartPatch
	{
		private static void Prefix(MaintenanceScene __instance)
		{
			try
			{
				ShopGroupInjector.EnsureInjected();
				CrowbarUnlock.Apply();
				CrowbarCombatTuning.Apply();
				VendingMachineSpawner.Spawn(__instance);
			}
			catch (Exception arg)
			{
				MelonLogger.Error($"[CrowbarShop] 放置撬棒售货机失败:{arg}");
			}
		}
	}
	internal static class CrowbarCombatTuning
	{
		private static bool _applied;

		internal static void Apply()
		{
			if (!_applied)
			{
				ExcelDataManager excelDataManager = ShopGroupInjector.GetExcelDataManager();
				if (excelDataManager != null)
				{
					_applied = true;
					ApplySequence(excelDataManager);
					ApplyDamage(excelDataManager);
					ApplyCooldown(excelDataManager);
				}
			}
		}

		private static void ApplySequence(ExcelDataManager excel)
		{
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: 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)
			SkillSequenceInfo val = default(SkillSequenceInfo);
			if (!excel.SkillSequenceInfoDict.TryGetValue(18006, ref val) || val == null)
			{
				MelonLogger.Warning($"[CrowbarShop] 找不到技能序列 {18006}。");
				return;
			}
			try
			{
				if (ModPreferences.HitFeedback)
				{
					SetField(typeof(SkillSequenceInfo), val, "SkillTagetEffectId", 40007);
					AbnormalInfo val2 = default(AbnormalInfo);
					if (excel.AbnormalDict.TryGetValue(18006, ref val2) && val2 != null)
					{
						Enumerator<int, IAbnormalElementInfo> enumerator = val2.ElementList.GetEnumerator();
						try
						{
							while (enumerator.MoveNext())
							{
								IAbnormalElementInfo value = enumerator.Current.Value;
								if (value != null && value.SkillTargetEffectId == 40008)
								{
									SetField(typeof(IAbnormalElementInfo), value, "SkillTargetEffectId", 0);
								}
							}
						}
						finally
						{
							((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
						}
					}
				}
				SetField(typeof(SkillSequenceInfo), val, "MutableValue", -ModPreferences.EffectiveDamage);
				if (ModPreferences.HitStun && !val.AbnormalMasterIDs.Contains(20001))
				{
					val.AbnormalMasterIDs = val.AbnormalMasterIDs.Add(20001);
				}
				MelonLogger.Msg($"[CrowbarShop] 撬棍序列 {18006}:伤害 {ModPreferences.EffectiveDamage}({ModPreferences.Damage}×{ModPreferences.DamageMultiplier},走 ActiveAttack 结算),冷却 {ModPreferences.EffectiveCooldownMs}ms,反馈 {40007},硬直 {ModPreferences.HitStun}");
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("[CrowbarShop] 调整撬棍序列失败:" + ex.Message);
			}
		}

		private static void ApplyDamage(ExcelDataManager excel)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: 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_0046: Invalid comparison between Unknown and I4
			AbnormalInfo val = default(AbnormalInfo);
			if (!excel.AbnormalDict.TryGetValue(18006, ref val) || val == null)
			{
				return;
			}
			try
			{
				Enumerator<int, IAbnormalElementInfo> enumerator = val.ElementList.GetEnumerator();
				try
				{
					while (enumerator.MoveNext())
					{
						IAbnormalElementInfo value = enumerator.Current.Value;
						AbnormalStatsElementInfo val2 = (AbnormalStatsElementInfo)(object)((value is AbnormalStatsElementInfo) ? value : null);
						if (val2 != null && (int)val2.MutableStatType == 1)
						{
							SetField(typeof(AbnormalStatsElementInfo), val2, "Value", 0L);
						}
					}
				}
				finally
				{
					((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("[CrowbarShop] 调整撬棍伤害失败:" + ex.Message);
			}
		}

		private static void ApplyCooldown(ExcelDataManager excel)
		{
			SkillInfo val = default(SkillInfo);
			if (!excel.SkillInfoDict.TryGetValue(10806, ref val) || val == null)
			{
				return;
			}
			try
			{
				SetField(typeof(SkillInfo), val, "Cooltime", ModPreferences.EffectiveCooldownMs);
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("[CrowbarShop] 调整撬棍冷却失败:" + ex.Message);
			}
		}

		private static void SetField(Type type, object instance, string name, object value)
		{
			FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field == null)
			{
				MelonLogger.Warning("[CrowbarShop] 找不到字段 " + type.Name + "." + name + "。");
			}
			else
			{
				field.SetValue(instance, value);
			}
		}
	}
	internal sealed class CrowbarDisplay : MonoBehaviour
	{
		private static readonly FieldInfo? ItemRootField = AccessTools.Field(typeof(VendingMachineLevelObject), "vendingMachineItemRoot");

		private static readonly FieldInfo? VanillaRootField = AccessTools.Field(typeof(VendingMachineLevelObject), "vendingMachineVanillaRoot");

		private Transform? _itemRoot;

		private Transform? _vanillaRoot;

		private GameObject? _item;

		private float _timer;

		internal static void Attach(VendingMachineLevelObject machine)
		{
			try
			{
				CrowbarDisplay crowbarDisplay = ((Component)machine).gameObject.AddComponent<CrowbarDisplay>();
				ref Transform? itemRoot = ref crowbarDisplay._itemRoot;
				object? obj = ItemRootField?.GetValue(machine);
				itemRoot = (Transform?)((obj is Transform) ? obj : null);
				ref Transform? vanillaRoot = ref crowbarDisplay._vanillaRoot;
				object? obj2 = VanillaRootField?.GetValue(machine);
				vanillaRoot = (Transform?)((obj2 is Transform) ? obj2 : null);
				if ((Object)(object)crowbarDisplay._itemRoot == (Object)null)
				{
					MelonLogger.Warning("[CrowbarShop] 找不到 vendingMachineItemRoot,陈列物品可能显示不正确。");
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("[CrowbarShop] 挂载陈列显示失败:" + ex.Message);
			}
		}

		private void Update()
		{
			_timer += Time.unscaledDeltaTime;
			if (_timer < 0.25f)
			{
				return;
			}
			_timer = 0f;
			if ((Object)(object)_itemRoot == (Object)null)
			{
				return;
			}
			if ((Object)(object)_vanillaRoot != (Object)null && ((Component)_vanillaRoot).gameObject.activeSelf)
			{
				((Component)_vanillaRoot).gameObject.SetActive(false);
			}
			if ((Object)(object)_item != (Object)null)
			{
				return;
			}
			GameMainBase main = Hub.Main;
			if ((Object)(object)main == (Object)null)
			{
				return;
			}
			try
			{
				_item = main.TrySpawnItemObject(2900, _itemRoot).Item2;
				if ((Object)(object)_item != (Object)null)
				{
					ModPreferences.Log("[CrowbarShop] 陈列物品已生成:" + ((Object)_item).name);
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("[CrowbarShop] 陈列物品生成失败:" + ex.Message);
			}
		}
	}
	internal static class CrowbarUnlock
	{
		private static bool _applied;

		internal static void Apply()
		{
			if (_applied || !ModPreferences.UnlockCrowbar)
			{
				return;
			}
			ExcelDataManager excelDataManager = ShopGroupInjector.GetExcelDataManager();
			if (excelDataManager == null)
			{
				return;
			}
			ItemMasterInfo itemInfo = excelDataManager.GetItemInfo(2900);
			if (itemInfo == null)
			{
				return;
			}
			_applied = true;
			try
			{
				FieldInfo field = typeof(ItemMasterInfo).GetField("ForbidChange", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field == null)
				{
					MelonLogger.Warning("[CrowbarShop] 找不到 ItemMasterInfo.ForbidChange 字段,改用捡取补丁兜底。");
					return;
				}
				field.SetValue(itemInfo, false);
				MelonLogger.Msg($"[CrowbarShop] 已解除撬棒 ForbidChange(当前值 {field.GetValue(itemInfo)})");
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("[CrowbarShop] 改写 ForbidChange 失败:" + ex.Message + "(使用捡取补丁兜底)");
			}
		}
	}
	internal static class Constants
	{
		internal const int CrowbarMasterId = 2900;

		internal const int ShopGroupId = 990001;

		internal const int CrowbarSkillId = 10806;

		internal const int CrowbarSequenceId = 18006;

		internal const int CrowbarAbnormalId = 18006;

		internal const int HitEffectFrom = 40008;

		internal const int HitEffectTo = 40007;

		internal const int HitStunAbnormalId = 20001;

		internal const string RoomAnchors = "bg_Maintenance=Vending machine_electricflyswatter,-1.8,0,0; bg_Maintenance_b_a=Vending machine_flash,-1.8,0,0; bg_Maintenance_c=Vending machine_electricflyswatter,-1.8,0,0";

		internal const string RoomPositions = "bg_Maintenance_d=-13.88,0,29.39,180";

		internal const float DefaultOffsetX = 1.8f;

		internal const float ItemYOffset = 0.2f;

		internal const float ItemXRotation = 60f;

		internal const float ItemScale = 1.5f;
	}
	internal static class ModPreferences
	{
		private const string CategoryId = "CrowbarShop";

		private const string CategoryDisplayName = "CrowbarShop";

		private static MelonPreferences_Category? _category;

		private static MelonPreferences_Entry<bool>? _enabled;

		private static MelonPreferences_Entry<bool>? _verbose;

		private static MelonPreferences_Entry<int>? _price;

		private static MelonPreferences_Entry<int>? _damage;

		private static MelonPreferences_Entry<float>? _damageMultiplier;

		private static MelonPreferences_Entry<int>? _attackCooldownMs;

		private static MelonPreferences_Entry<float>? _cooldownMultiplier;

		private static MelonPreferences_Entry<bool>? _hitFeedback;

		private static MelonPreferences_Entry<bool>? _hitStun;

		private static MelonPreferences_Entry<bool>? _unlockCrowbar;

		private static MelonPreferences_Entry<string>? _monsterDamageMultipliers;

		private static MelonPreferences_Entry<string>? _placement;

		internal static bool Enabled => Entry(ref _enabled).Value;

		internal static bool Verbose => Entry(ref _verbose).Value;

		internal static int Price => Math.Max(0, Entry(ref _price).Value);

		internal static int Damage => Math.Max(1, Entry(ref _damage).Value);

		internal static float DamageMultiplier => Mathf.Clamp(Entry(ref _damageMultiplier).Value, 0.01f, 100f);

		internal static int AttackCooldownMs => Math.Max(50, Entry(ref _attackCooldownMs).Value);

		internal static float CooldownMultiplier => Mathf.Clamp(Entry(ref _cooldownMultiplier).Value, 0.05f, 100f);

		internal static bool HitFeedback => Entry(ref _hitFeedback).Value;

		internal static bool HitStun => Entry(ref _hitStun).Value;

		internal static bool UnlockCrowbar => Entry(ref _unlockCrowbar).Value;

		internal static string MonsterDamageMultipliers => Entry(ref _monsterDamageMultipliers).Value;

		internal static string Placement => Entry(ref _placement).Value;

		internal static int EffectiveDamage => Math.Max(1, (int)Math.Round((float)Damage * DamageMultiplier));

		internal static int EffectiveCooldownMs => Math.Max(50, (int)Math.Round((float)AttackCooldownMs * CooldownMultiplier));

		internal static void Initialize()
		{
			if (_category == null)
			{
				_category = MelonPreferences.CreateCategory("CrowbarShop", "CrowbarShop");
				_enabled = CreateEntry("Enabled", defaultValue: true, "Enabled", "Add a crowbar vending machine and crowbar combat tweaks.");
				_verbose = CreateEntry("Verbose", defaultValue: false, "Verbose logging", "Log injections, placement and damage calculations.");
				_price = CreateEntry("Price", 488, "Crowbar price", "Price shown on the vending machine.");
				_damage = CreateEntry("Damage", 90, "Crowbar damage", "Base HP damage per crowbar hit.");
				_damageMultiplier = CreateEntry("DamageMultiplier", 0.6f, "Damage multiplier", "Final damage = Damage x DamageMultiplier.");
				_attackCooldownMs = CreateEntry("AttackCooldownMs", 850, "Attack cooldown (ms)", "Base crowbar swing cooldown in milliseconds.");
				_cooldownMultiplier = CreateEntry("CooldownMultiplier", 1f, "Cooldown multiplier", "Final cooldown = AttackCooldownMs x CooldownMultiplier.");
				_hitFeedback = CreateEntry("HitFeedback", defaultValue: true, "Hit sound / effect", "Play the teddy bat hit sound and VFX on every crowbar hit.");
				_hitStun = CreateEntry("HitStun", defaultValue: true, "Hit stun", "Add the teddy bat flinch abnormal to crowbar hits.");
				_unlockCrowbar = CreateEntry("UnlockCrowbar", defaultValue: true, "Unlock crowbar restriction", "Remove the 'put this item down first' restriction while holding the crowbar.");
				_monsterDamageMultipliers = CreateEntry("MonsterDamageMultipliers", "", "Per-monster damage multipliers", "Format: mimic=1.5; HeavyD=0.5. Match by MonsterData name. Default 1.0.");
				_placement = CreateEntry("Placement", "NextToExisting", "Placement mode (NextToExisting / ReplaceExisting)", "NextToExisting clones an existing vending machine next to the anchor; ReplaceExisting changes an existing machine instead.");
			}
		}

		internal static void Log(string message)
		{
			if (Verbose)
			{
				MelonLogger.Msg(message);
			}
		}

		internal static float GetMonsterDamageMultiplier(string? monsterName)
		{
			string monsterDamageMultipliers = MonsterDamageMultipliers;
			if (string.IsNullOrWhiteSpace(monsterDamageMultipliers) || string.IsNullOrEmpty(monsterName))
			{
				return 1f;
			}
			string[] array = monsterDamageMultipliers.Split(';');
			for (int i = 0; i < array.Length; i++)
			{
				string[] array2 = array[i].Split('=');
				if (array2.Length == 2 && string.Equals(array2[0].Trim(), monsterName, StringComparison.OrdinalIgnoreCase) && float.TryParse(array2[1].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
				{
					return Mathf.Clamp(result, 0f, 100f);
				}
			}
			return 1f;
		}

		private static MelonPreferences_Entry<T> Entry<T>(ref MelonPreferences_Entry<T>? field)
		{
			if (field == null)
			{
				throw new InvalidOperationException("ModPreferences.Initialize() must run first.");
			}
			return field;
		}

		private static MelonPreferences_Entry<T> CreateEntry<T>(string identifier, T defaultValue, string displayName, string? description = null)
		{
			if (_category == null)
			{
				throw new InvalidOperationException("Preference category not initialized.");
			}
			return _category.CreateEntry<T>(identifier, defaultValue, displayName, description, false, false, (ValueValidator)null, (string)null);
		}
	}
	[HarmonyPatch(typeof(LootingLevelObject), "CanGrap")]
	internal static class CanGrapPatch
	{
		private static bool Prefix(ProtoActor protoActor, ref bool __result)
		{
			if (!ModPreferences.UnlockCrowbar)
			{
				return true;
			}
			try
			{
				InventoryItem val = ((protoActor != null) ? protoActor.GetSelectedInventoryItem() : null);
				if (((val != null) ? val.MasterInfo : null) != null && val.MasterInfo.MasterID == 2900)
				{
					__result = true;
					return false;
				}
			}
			catch
			{
			}
			return true;
		}
	}
	internal static class ShopGroupInjector
	{
		private static bool _injected;

		internal static bool EnsureInjected()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			//IL_0044: 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_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			if (_injected)
			{
				return true;
			}
			ExcelDataManager excelDataManager = GetExcelDataManager();
			if (excelDataManager == null)
			{
				return false;
			}
			try
			{
				int num = 990001;
				ShopGroup_MasterData val = new ShopGroup_MasterData
				{
					id = num,
					item_masterid = 2900,
					item_price = ModPreferences.Price
				};
				val.ShopGroup_rateval.Add(new ShopGroup_rate
				{
					item_rate = 10000,
					discount_ratio = 0
				});
				ImmutableDictionary<int, ShopGroup_MasterData> val2 = excelDataManager.ShopGroupDict.SetItem(num, val);
				MethodInfo methodInfo = typeof(ExcelDataManager).GetProperty("ShopGroupDict", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetSetMethod(nonPublic: true);
				if (methodInfo == null)
				{
					MelonLogger.Error("[CrowbarShop] ExcelDataManager.ShopGroupDict 不可写,无法注入商店组。");
					return false;
				}
				methodInfo.Invoke(excelDataManager, new object[1] { val2 });
				_injected = true;
				MelonLogger.Msg($"[CrowbarShop] 商店组 {num}:物品 {2900},价格 {ModPreferences.Price}");
				return true;
			}
			catch (Exception arg)
			{
				MelonLogger.Error($"[CrowbarShop] 注入商店组失败:{arg}");
				return false;
			}
		}

		internal static ExcelDataManager? GetExcelDataManager()
		{
			Hub s = Hub.s;
			if ((Object)(object)s == (Object)null)
			{
				return null;
			}
			object obj = null;
			try
			{
				obj = AccessTools.Property(typeof(Hub), "dataman")?.GetValue(s);
			}
			catch
			{
			}
			if (obj == null)
			{
				try
				{
					obj = AccessTools.Field(typeof(Hub), "<dataman>k__BackingField")?.GetValue(s);
				}
				catch
				{
				}
			}
			object obj4 = ((obj is DataManager) ? obj : null);
			if (obj4 == null)
			{
				return null;
			}
			return ((DataManager)obj4).ExcelDataManager;
		}
	}
	internal static class VendingMachineSpawner
	{
		private const string MachineObjectName = "CrowbarShopMachine";

		private static readonly FieldInfo? RoomRootField = AccessTools.Field(typeof(MaintenanceScene), "maintenanceRoomRoot");

		private static readonly FieldInfo? ItemRootField = AccessTools.Field(typeof(VendingMachineLevelObject), "vendingMachineItemRoot");

		private static GameObject? _template;

		private static string _templateLevelObjectName = string.Empty;

		internal static void Spawn(MaintenanceScene scene)
		{
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: 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_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			if (!ModPreferences.Enabled || (Object)(object)scene == (Object)null || !ShopGroupInjector.EnsureInjected())
			{
				return;
			}
			object? obj = RoomRootField?.GetValue(scene);
			Transform val = (Transform)((obj is Transform) ? obj : null);
			if ((Object)(object)val == (Object)null)
			{
				MelonLogger.Warning("[CrowbarShop] 找不到 maintenanceRoomRoot,跳过。");
				return;
			}
			VendingMachineLevelObject[] componentsInChildren = ((Component)val).GetComponentsInChildren<VendingMachineLevelObject>(true);
			if (componentsInChildren == null || componentsInChildren.Length == 0)
			{
				SpawnWithoutAnchor(val);
				return;
			}
			if (ModPreferences.Verbose)
			{
				MelonLogger.Msg($"[CrowbarShop] 房间 '{((Object)val).name}':{componentsInChildren.Length} 台售货机");
			}
			if (string.Equals(ModPreferences.Placement, "ReplaceExisting", StringComparison.OrdinalIgnoreCase))
			{
				VendingMachineLevelObject val2 = PickAnchor(componentsInChildren);
				if (!((Object)(object)val2 == (Object)null))
				{
					val2.shopGroupID = 990001;
					MelonLogger.Msg($"[CrowbarShop] 已把 '{((Object)val2).name}' 改为撬棒售货机(组 {990001},价格 {ModPreferences.Price})");
				}
				return;
			}
			if ((Object)(object)val.Find("CrowbarShopMachine") != (Object)null)
			{
				ModPreferences.Log("[CrowbarShop] 撬棒售货机已存在,跳过。");
				return;
			}
			VendingMachineLevelObject val3 = PickAnchor(componentsInChildren);
			if (!((Object)(object)val3 == (Object)null))
			{
				string levelObjectName = ((LevelObject)val3).levelObjectName;
				GameObject val4 = Object.Instantiate<GameObject>(((Component)val3).gameObject, val, true);
				((Object)val4).name = "CrowbarShopMachine";
				if (TryGetRoomAnchor(val, out Transform anchor, out Vector3 offset, out float yaw))
				{
					Quaternion rotation = anchor.rotation;
					val4.transform.SetPositionAndRotation(anchor.position + rotation * offset, rotation * Quaternion.Euler(0f, yaw, 0f));
				}
				else
				{
					Vector3 val5 = default(Vector3);
					((Vector3)(ref val5))..ctor(1.8f, 0f, 0f);
					val4.transform.SetPositionAndRotation(((Component)val3).transform.position + ((Component)val3).transform.rotation * val5, ((Component)val3).transform.rotation);
				}
				ConfigureMachine(val4, ((Object)val3).name, levelObjectName);
				CacheTemplate(((Component)val3).gameObject);
			}
		}

		private static void ConfigureMachine(GameObject clone, string anchorName, string? levelObjectName)
		{
			//IL_00d4: 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_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: 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_00b8: Unknown result type (might be due to invalid IL or missing references)
			VendingMachineLevelObject component = clone.GetComponent<VendingMachineLevelObject>();
			if ((Object)(object)component == (Object)null)
			{
				Object.Destroy((Object)(object)clone);
				MelonLogger.Warning("[CrowbarShop] 克隆出来的物体上没有 VendingMachineLevelObject,已销毁。");
				return;
			}
			component.shopGroupID = 990001;
			((LevelObject)component).levelObjectName = "CrowbarShopMachine";
			if (!string.IsNullOrEmpty(levelObjectName) && levelObjectName != "CrowbarShopMachine")
			{
				RewriteStateActions(component, levelObjectName, "CrowbarShopMachine");
			}
			object? obj = ItemRootField?.GetValue(component);
			Transform val = (Transform)((obj is Transform) ? obj : null);
			if (val != null)
			{
				val.localPosition += Vector3.up * 0.2f;
				val.eulerAngles = new Vector3(60f, 0f, 0f);
				val.localScale = Vector3.one * 1.5f;
			}
			CrowbarDisplay.Attach(component);
			MelonLogger.Msg($"[CrowbarShop] 在 '{anchorName}' 旁边放置撬棒售货机:pos={clone.transform.position},价格 {ModPreferences.Price}");
		}

		private static void RewriteStateActions(VendingMachineLevelObject machine, string oldName, string newName)
		{
			int num = 0;
			foreach (Dictionary<int, StateActionInfo> value in ((LevelObject)machine).StateActionsMap.Values)
			{
				foreach (StateActionInfo value2 in value.Values)
				{
					if (!string.IsNullOrEmpty(value2.action) && value2.action.Contains(oldName))
					{
						value2.action = value2.action.Replace(oldName, newName);
						num++;
					}
					if (!string.IsNullOrEmpty(value2.condition) && value2.condition.Contains(oldName))
					{
						value2.condition = value2.condition.Replace(oldName, newName);
					}
				}
			}
			MelonLogger.Msg($"[CrowbarShop] state action 名字重写:'{oldName}' -> '{newName}'({num} 条)");
		}

		private static VendingMachineLevelObject? PickAnchor(VendingMachineLevelObject[] machines)
		{
			return ((IEnumerable<VendingMachineLevelObject>)machines).LastOrDefault((Func<VendingMachineLevelObject, bool>)((VendingMachineLevelObject machine) => (Object)(object)machine != (Object)null));
		}

		private static void CacheTemplate(GameObject source)
		{
			if ((Object)(object)_template != (Object)null || (Object)(object)source == (Object)null)
			{
				return;
			}
			try
			{
				GameObject obj = Object.Instantiate<GameObject>(source);
				((Object)obj).name = "CrowbarShopTemplate";
				obj.SetActive(false);
				Object.DontDestroyOnLoad((Object)(object)obj);
				_template = obj;
				_templateLevelObjectName = ((LevelObject)(source.GetComponent<VendingMachineLevelObject>()?)).levelObjectName ?? string.Empty;
				ModPreferences.Log("[CrowbarShop] 已缓存售货机模板。");
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("[CrowbarShop] 缓存售货机模板失败:" + ex.Message);
			}
		}

		private static void SpawnWithoutAnchor(Transform roomRoot)
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)roomRoot.Find("CrowbarShopMachine") != (Object)null)
			{
				return;
			}
			if (!TryGetRoomPosition(((Object)roomRoot).name, out var position, out var yaw))
			{
				MelonLogger.Warning("[CrowbarShop] 房间 '" + ((Object)roomRoot).name + "' 里没有售货机,且没有预置坐标,跳过。");
				return;
			}
			if ((Object)(object)_template == (Object)null)
			{
				MelonLogger.Warning("[CrowbarShop] 房间 '" + ((Object)roomRoot).name + "' 需要模板,但还没有缓存(请先进一次有售货机的房间)。");
				return;
			}
			try
			{
				GameObject obj = Object.Instantiate<GameObject>(_template, roomRoot, true);
				((Object)obj).name = "CrowbarShopMachine";
				obj.SetActive(true);
				obj.transform.SetPositionAndRotation(position, Quaternion.Euler(0f, yaw, 0f));
				ConfigureMachine(obj, ((Object)roomRoot).name, _templateLevelObjectName);
			}
			catch (Exception arg)
			{
				MelonLogger.Error($"[CrowbarShop] 用模板放置失败:{arg}");
			}
		}

		private static bool TryGetRoomAnchor(Transform roomRoot, out Transform anchor, out Vector3 offset, out float yaw)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			anchor = null;
			offset = Vector3.zero;
			yaw = 0f;
			string[] array = "bg_Maintenance=Vending machine_electricflyswatter,-1.8,0,0; bg_Maintenance_b_a=Vending machine_flash,-1.8,0,0; bg_Maintenance_c=Vending machine_electricflyswatter,-1.8,0,0".Split(';');
			foreach (string obj in array)
			{
				string[] array2 = obj.Split('=');
				if (array2.Length == 2 && string.Equals(array2[0].Trim(), ((Object)roomRoot).name, StringComparison.OrdinalIgnoreCase))
				{
					string[] array3 = array2[1].Split(',');
					if (array3.Length < 4)
					{
						return false;
					}
					string targetName = array3[0].Trim();
					if (!TryParseNumbers(string.Join(",", array3.Skip(1)), out offset, out yaw))
					{
						return false;
					}
					Transform[] componentsInChildren = ((Component)roomRoot).GetComponentsInChildren<Transform>(true);
					Transform val = ((IEnumerable<Transform>)componentsInChildren).FirstOrDefault((Func<Transform, bool>)((Transform t) => string.Equals(((Object)t).name, targetName, StringComparison.OrdinalIgnoreCase))) ?? ((IEnumerable<Transform>)componentsInChildren).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name.IndexOf(targetName, StringComparison.OrdinalIgnoreCase) >= 0));
					if ((Object)(object)val == (Object)null)
					{
						return false;
					}
					anchor = val;
					return true;
				}
			}
			return false;
		}

		private static bool TryGetRoomPosition(string roomName, out Vector3 position, out float yaw)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			position = Vector3.zero;
			yaw = 0f;
			string[] array = "bg_Maintenance_d=-13.88,0,29.39,180".Split(';');
			for (int i = 0; i < array.Length; i++)
			{
				string[] array2 = array[i].Split('=');
				if (array2.Length == 2 && string.Equals(array2[0].Trim(), roomName, StringComparison.OrdinalIgnoreCase))
				{
					return TryParseNumbers(array2[1], out position, out yaw);
				}
			}
			return false;
		}

		private static bool TryParseNumbers(string text, out Vector3 offset, out float yaw)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			offset = Vector3.zero;
			yaw = 0f;
			string[] array = (from v in text.Split(',')
				select v.Trim() into v
				where v.Length > 0
				select v).ToArray();
			if (array.Length < 3)
			{
				return false;
			}
			float[] array2 = new float[array.Length];
			for (int num = 0; num < array.Length; num++)
			{
				if (!float.TryParse(array[num], NumberStyles.Float, CultureInfo.InvariantCulture, out array2[num]))
				{
					return false;
				}
			}
			offset = new Vector3(array2[0], array2[1], array2[2]);
			yaw = ((array2.Length >= 4) ? array2[3] : 0f);
			return true;
		}
	}
}
namespace CrowbarShop.Patches
{
	[HarmonyPatch(typeof(AbnormalController), "ApplyAbnormalInternal")]
	internal static class CrowbarCasterPatch
	{
		private static void Prefix(AbnormalController __instance, ref int casterObjectID, AbnormalInfo? info)
		{
			if (info == null || info.MasterID != 18006)
			{
				return;
			}
			try
			{
				VCreature victim = __instance.Self;
				IVroom val = ((VActor)(victim?)).VRoom;
				if (victim == null || val == null || val.FindActorByObjectID(casterObjectID) is VPlayer)
				{
					return;
				}
				VPlayer nearest = null;
				float best = float.MaxValue;
				val.IterateAllPlayer((Action<VPlayer>)delegate(VPlayer player)
				{
					//IL_000d: 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)
					if (player != null && ((VActor)player).IsAliveStatus())
					{
						float num = Vector3.Distance(((VActor)player).PositionVector, ((VActor)victim).PositionVector);
						if (num < best)
						{
							best = num;
							nearest = player;
						}
					}
				});
				if (nearest != null && !(best > 6f))
				{
					MelonLogger.Msg($"[CrowbarShop] 撬棍伤害来源修正:caster {casterObjectID} -> {((VActor)nearest).ObjectID}({best:0.##}m)");
					casterObjectID = ((VActor)nearest).ObjectID;
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("[CrowbarShop] 修正撬棍伤害来源失败:" + ex.Message);
			}
		}
	}
	[HarmonyPatch(typeof(VWorldCombatUtil), "CalculateDamage")]
	internal static class MonsterDamagePatch
	{
		private static void Postfix(VCreature? victim, int skillSeqMasterID, ref DamageAttribute __result)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Expected O, but got Unknown
			if (__result == null || victim == null || skillSeqMasterID != 18006)
			{
				return;
			}
			try
			{
				if (!(victim is VPlayer))
				{
					CreatureAIInfo creatureAIData = victim.GetCreatureAIData();
					float monsterDamageMultiplier = ModPreferences.GetMonsterDamageMultiplier((creatureAIData != null) ? creatureAIData.Name : null);
					if (!(Math.Abs(monsterDamageMultiplier - 1f) < 0.001f))
					{
						__result = new DamageAttribute((long)Math.Round((double)__result.Damage * (double)monsterDamageMultiplier), __result.GroggyValue, __result.Critical);
						CreatureAIInfo creatureAIData2 = victim.GetCreatureAIData();
						ModPreferences.Log($"[CrowbarShop] 怪物 {((creatureAIData2 != null) ? creatureAIData2.Name : null)} 伤害倍率 {monsterDamageMultiplier}:最终 {__result.Damage}");
					}
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("[CrowbarShop] 怪物伤害倍率处理失败:" + ex.Message);
			}
		}
	}
}