Decompiled source of TechtonicaFramework v1.2.0

TechtonicaFramework.dll

Decompiled 5 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using EquinoxsModUtils;
using FMOD.Studio;
using FMODUnity;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using TechtonicaFramework.BuildMenu;
using TechtonicaFramework.Core;
using TechtonicaFramework.Environment;
using TechtonicaFramework.Equipment;
using TechtonicaFramework.Health;
using TechtonicaFramework.Narrative;
using TechtonicaFramework.TechTree;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("TechtonicaFramework")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+f15d001593873bafffb76c154572225ced34798a")]
[assembly: AssemblyProduct("TechtonicaFramework")]
[assembly: AssemblyTitle("TechtonicaFramework")]
[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 TechtonicaFramework
{
	[BepInPlugin("com.certifired.TechtonicaFramework", "TechtonicaFramework", "1.2.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class TechtonicaFrameworkPlugin : BaseUnityPlugin
	{
		public const string MyGUID = "com.certifired.TechtonicaFramework";

		public const string PluginName = "TechtonicaFramework";

		public const string VersionString = "1.2.0";

		public static readonly Harmony Harmony = new Harmony("com.certifired.TechtonicaFramework");

		public static ConfigEntry<bool> EnableHealthModule;

		public static ConfigEntry<bool> EnableEnvironmentModule;

		public static ConfigEntry<bool> EnableNarrativeModule;

		public static ConfigEntry<bool> EnableEquipmentModule;

		public static ConfigEntry<bool> DebugMode;

		public static ManualLogSource Log { get; private set; }

		public static TechtonicaFrameworkPlugin Instance { get; private set; }

		public static HealthModule HealthModule { get; private set; }

		public static EnvironmentModule EnvironmentModule { get; private set; }

		public static NarrativeModule NarrativeModule { get; private set; }

		public static EquipmentModule EquipmentModule { get; private set; }

		private void Awake()
		{
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			Log.LogInfo((object)"TechtonicaFramework v1.2.0 is loading...");
			InitializeConfig();
			Harmony.PatchAll();
			ModdedTabModule.Initialize(Log);
			Log.LogInfo((object)"ModdedTab system initialized - all mods can use category 7 for unlocks");
			BuildMenuModule.Initialize(Log);
			Log.LogInfo((object)"BuildMenu module initialized - modded items will have their own tab");
			InitializeModules();
			FrameworkEvents.Initialize();
			CorruptedUnlockCleanup.Initialize();
			Log.LogInfo((object)"TechtonicaFramework v1.2.0 loaded successfully!");
		}

		private void InitializeConfig()
		{
			EnableHealthModule = ((BaseUnityPlugin)this).Config.Bind<bool>("Modules", "Enable Health Module", true, "Enable the Health/Damage system for machines and entities");
			EnableEnvironmentModule = ((BaseUnityPlugin)this).Config.Bind<bool>("Modules", "Enable Environment Module", true, "Enable environmental hazards and status effects");
			EnableNarrativeModule = ((BaseUnityPlugin)this).Config.Bind<bool>("Modules", "Enable Narrative Module", true, "Enable dialogue and quest creation helpers");
			EnableEquipmentModule = ((BaseUnityPlugin)this).Config.Bind<bool>("Modules", "Enable Equipment Module", true, "Enable custom equipment and vehicle systems");
			DebugMode = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Debug Mode", false, "Enable verbose debug logging");
		}

		private void InitializeModules()
		{
			if (EnableHealthModule.Value)
			{
				HealthModule = new HealthModule();
				HealthModule.Initialize();
				LogDebug("Health Module initialized");
			}
			if (EnableEnvironmentModule.Value)
			{
				EnvironmentModule = new EnvironmentModule();
				EnvironmentModule.Initialize();
				LogDebug("Environment Module initialized");
			}
			if (EnableNarrativeModule.Value)
			{
				NarrativeModule = new NarrativeModule();
				NarrativeModule.Initialize();
				LogDebug("Narrative Module initialized");
			}
			if (EnableEquipmentModule.Value)
			{
				EquipmentModule = new EquipmentModule();
				EquipmentModule.Initialize();
				LogDebug("Equipment Module initialized");
			}
		}

		private void Update()
		{
			HealthModule?.Update();
			EnvironmentModule?.Update();
			EquipmentModule?.Update();
		}

		private void OnDestroy()
		{
			HealthModule?.Shutdown();
			EnvironmentModule?.Shutdown();
			NarrativeModule?.Shutdown();
			EquipmentModule?.Shutdown();
		}

		public static void LogDebug(string message)
		{
			if (DebugMode != null && DebugMode.Value)
			{
				Log.LogInfo((object)("[DEBUG] " + message));
			}
		}

		public static void LogWarning(string message)
		{
			Log.LogWarning((object)message);
		}

		public static void LogError(string message)
		{
			Log.LogError((object)message);
		}
	}
	[HarmonyPatch]
	internal static class LogFilterPatches
	{
		private static readonly string[] SuppressedMessages = new string[5] { "Can't handle reading unlock save info for", "FMOD Studio Listener", "Could not find Audio Clip Entry", "_caveSounds_Ambient", "Historic ResourceId" };

		[HarmonyPatch(typeof(Debug), "LogWarning", new Type[] { typeof(object) })]
		[HarmonyPrefix]
		private static bool FilterLogWarning(object message)
		{
			if (message == null)
			{
				return true;
			}
			string text = message.ToString();
			string[] suppressedMessages = SuppressedMessages;
			foreach (string value in suppressedMessages)
			{
				if (text.Contains(value))
				{
					return false;
				}
			}
			return true;
		}

		[HarmonyPatch(typeof(Debug), "LogError", new Type[] { typeof(object) })]
		[HarmonyPrefix]
		private static bool FilterLogError(object message)
		{
			if (message == null)
			{
				return true;
			}
			string text = message.ToString();
			string[] suppressedMessages = SuppressedMessages;
			foreach (string value in suppressedMessages)
			{
				if (text.Contains(value))
				{
					return false;
				}
			}
			return true;
		}

		[HarmonyPatch(typeof(Debug), "LogWarningFormat", new Type[]
		{
			typeof(string),
			typeof(object[])
		})]
		[HarmonyPrefix]
		private static bool FilterLogWarningFormat(string format, object[] args)
		{
			if (format == null)
			{
				return true;
			}
			string[] suppressedMessages = SuppressedMessages;
			foreach (string value in suppressedMessages)
			{
				if (format.Contains(value))
				{
					return false;
				}
			}
			try
			{
				string text = string.Format(format, args);
				string[] suppressedMessages2 = SuppressedMessages;
				foreach (string value2 in suppressedMessages2)
				{
					if (text.Contains(value2))
					{
						return false;
					}
				}
			}
			catch
			{
			}
			return true;
		}

		[HarmonyPatch(typeof(Debug), "LogErrorFormat", new Type[]
		{
			typeof(string),
			typeof(object[])
		})]
		[HarmonyPrefix]
		private static bool FilterLogErrorFormat(string format, object[] args)
		{
			if (format == null)
			{
				return true;
			}
			string[] suppressedMessages = SuppressedMessages;
			foreach (string value in suppressedMessages)
			{
				if (format.Contains(value))
				{
					return false;
				}
			}
			try
			{
				string text = string.Format(format, args);
				string[] suppressedMessages2 = SuppressedMessages;
				foreach (string value2 in suppressedMessages2)
				{
					if (text.Contains(value2))
					{
						return false;
					}
				}
			}
			catch
			{
			}
			return true;
		}
	}
	[HarmonyPatch]
	internal static class FMODListenerFix
	{
		private static bool listenerAdded;

		[HarmonyPatch(typeof(UIManager), "Start")]
		[HarmonyPostfix]
		private static void AddFMODListener()
		{
			if (listenerAdded)
			{
				return;
			}
			try
			{
				Camera main = Camera.main;
				if ((Object)(object)main != (Object)null)
				{
					StudioListener component = ((Component)main).GetComponent<StudioListener>();
					if ((Object)(object)component == (Object)null)
					{
						((Component)main).gameObject.AddComponent<StudioListener>();
						TechtonicaFrameworkPlugin.LogDebug("Added FMOD Studio Listener to main camera");
					}
					listenerAdded = true;
				}
			}
			catch (Exception ex)
			{
				TechtonicaFrameworkPlugin.LogDebug("Could not add FMOD listener: " + ex.Message);
			}
		}
	}
	internal static class CorruptedUnlockCleanup
	{
		private static readonly HashSet<string> ExactCorruptedNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "LOG%", "Atlantum Smelter", "Atlantum Planter" };

		private static HashSet<string> cleanedUnlocks = new HashSet<string>();

		public static void Initialize()
		{
			Events.GameDefinesLoaded += OnGameDefinesLoaded;
			Events.TechTreeStateLoaded += OnTechTreeStateLoaded;
		}

		private static void OnGameDefinesLoaded()
		{
			cleanedUnlocks.Clear();
		}

		private static void OnTechTreeStateLoaded()
		{
			try
			{
				CleanupCorruptedUnlocks();
			}
			catch (Exception ex)
			{
				TechtonicaFrameworkPlugin.Log.LogWarning((object)("Error during unlock cleanup: " + ex.Message));
			}
		}

		private static void CleanupCorruptedUnlocks()
		{
			if ((Object)(object)GameDefines.instance == (Object)null)
			{
				return;
			}
			List<Unlock> unlocks = GameDefines.instance.unlocks;
			if (unlocks == null)
			{
				return;
			}
			int num = 0;
			List<Unlock> list = new List<Unlock>();
			foreach (Unlock item in unlocks)
			{
				if ((Object)(object)item == (Object)null)
				{
					continue;
				}
				string displayName = item.displayName;
				if (IsCorruptedUnlock(displayName))
				{
					list.Add(item);
					if (!cleanedUnlocks.Contains(displayName ?? "null"))
					{
						TechtonicaFrameworkPlugin.Log.LogInfo((object)("Hiding corrupted unlock: '" + displayName + "'"));
						cleanedUnlocks.Add(displayName ?? "null");
					}
					num++;
				}
			}
			foreach (Unlock item2 in list)
			{
				item2.treePosition = -9999f;
			}
			if (num > 0)
			{
				TechtonicaFrameworkPlugin.Log.LogInfo((object)$"Cleaned up {num} corrupted unlock entries from tech tree");
			}
		}

		private static bool IsCorruptedUnlock(string displayName)
		{
			if (string.IsNullOrEmpty(displayName))
			{
				return false;
			}
			if (ExactCorruptedNames.Contains(displayName))
			{
				return true;
			}
			if (displayName.Contains("LOG") && displayName.Contains("%"))
			{
				return true;
			}
			return false;
		}
	}
}
namespace TechtonicaFramework.TechTree
{
	public static class ModdedTabModule
	{
		public const int MODDED_CATEGORY_INDEX = 7;

		public const string MODDED_CATEGORY_NAME = "Modded";

		public const int EXTENDED_CATEGORY_COUNT = 8;

		private static bool isInitialized;

		private static TechTreeCategoryContainer moddedContainer;

		private static TechTreeCategoryButton moddedButton;

		private static ManualLogSource log;

		public static bool IsModdedTabActive => (Object)(object)moddedButton != (Object)null && (Object)(object)moddedContainer != (Object)null;

		public static TechCategory ModdedCategory => (TechCategory)7;

		public static void Initialize(ManualLogSource logger = null)
		{
			if (!isInitialized)
			{
				log = logger ?? TechtonicaFrameworkPlugin.Log;
				isInitialized = true;
				ManualLogSource obj = log;
				if (obj != null)
				{
					obj.LogInfo((object)"ModdedTabModule: Initialized");
				}
			}
		}

		public static void RegisterUnlockToModdedTab(Unlock unlock, int treePosition = 50)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)unlock == (Object)null))
			{
				unlock.category = ModdedCategory;
				unlock.treePosition = treePosition;
			}
		}

		public static void MapModdedUnlocks()
		{
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Invalid comparison between Unknown and I4
			if (TechTreeState.instance == null || GameDefines.instance?.unlocks == null)
			{
				ManualLogSource obj = log;
				if (obj != null)
				{
					obj.LogWarning((object)"ModdedTabModule: MapModdedUnlocks - TechTreeState or GameDefines not ready");
				}
				return;
			}
			try
			{
				List<List<int>> categoryMapping = TechTreeState.instance.categoryMapping;
				if (categoryMapping == null)
				{
					ManualLogSource obj2 = log;
					if (obj2 != null)
					{
						obj2.LogWarning((object)"ModdedTabModule: categoryMapping is null");
					}
					return;
				}
				ManualLogSource obj3 = log;
				if (obj3 != null)
				{
					obj3.LogInfo((object)$"ModdedTabModule: categoryMapping has {categoryMapping.Count} entries");
				}
				while (categoryMapping.Count < 8)
				{
					categoryMapping.Add(new List<int>());
					ManualLogSource obj4 = log;
					if (obj4 != null)
					{
						obj4.LogInfo((object)$"ModdedTabModule: Added categoryMapping entry, now have {categoryMapping.Count}");
					}
				}
				List<int> list = categoryMapping[7];
				if (list == null)
				{
					list = (categoryMapping[7] = new List<int>());
				}
				int num = 0;
				int num2 = 0;
				ManualLogSource obj5 = log;
				if (obj5 != null)
				{
					obj5.LogInfo((object)$"ModdedTabModule: Scanning {GameDefines.instance.unlocks.Count} total unlocks...");
				}
				foreach (Unlock unlock in GameDefines.instance.unlocks)
				{
					if (!((Object)(object)unlock == (Object)null) && (int)unlock.category == 7)
					{
						num2++;
						string arg = ((!string.IsNullOrEmpty(unlock.displayNameHash)) ? LocsUtility.TranslateStringFromHash(unlock.displayNameHash, (string)null, (Object)null) : $"(id={((UniqueIdScriptableObject)unlock).uniqueId})");
						ManualLogSource obj6 = log;
						if (obj6 != null)
						{
							obj6.LogInfo((object)$"ModdedTabModule: Found modded unlock: '{arg}' id={((UniqueIdScriptableObject)unlock).uniqueId}");
						}
						if (!list.Contains(((UniqueIdScriptableObject)unlock).uniqueId))
						{
							list.Add(((UniqueIdScriptableObject)unlock).uniqueId);
							num++;
						}
					}
				}
				ManualLogSource obj7 = log;
				if (obj7 != null)
				{
					obj7.LogInfo((object)$"ModdedTabModule: Found {num2} unlocks with category 7, mapped {num} new ones. Total in mapping: {list.Count}");
				}
				if (list.Count > 0)
				{
					list.Sort(delegate(int a, int b)
					{
						//IL_000c: Unknown result type (might be due to invalid IL or missing references)
						//IL_0011: Unknown result type (might be due to invalid IL or missing references)
						//IL_001d: Unknown result type (might be due to invalid IL or missing references)
						//IL_0022: 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_002b: Unknown result type (might be due to invalid IL or missing references)
						//IL_0044: Unknown result type (might be due to invalid IL or missing references)
						//IL_004f: Unknown result type (might be due to invalid IL or missing references)
						UnlockState val = TechTreeState.instance.unlockStates[a];
						UnlockState val2 = TechTreeState.instance.unlockStates[b];
						int num3 = ((Enum)(ResearchTier)(ref val.tier)).CompareTo((object?)val2.tier);
						return (num3 != 0) ? num3 : val.unlockRef.treePosition.CompareTo(val2.unlockRef.treePosition);
					});
				}
			}
			catch (Exception arg2)
			{
				ManualLogSource obj8 = log;
				if (obj8 != null)
				{
					obj8.LogError((object)$"ModdedTabModule: Error mapping unlocks: {arg2}");
				}
			}
		}

		internal static void SetLogger(ManualLogSource logger)
		{
			if (log == null)
			{
				log = logger;
			}
		}

		internal static void OnTechTreeStateInitPostfix(TechTreeState instance)
		{
			try
			{
				FieldInfo field = typeof(TechTreeState).GetField("categoryMapping", BindingFlags.Instance | BindingFlags.Public);
				if (!(field != null))
				{
					return;
				}
				object value = field.GetValue(instance);
				if (value == null || !(value is IList list))
				{
					return;
				}
				ManualLogSource obj = log;
				if (obj != null)
				{
					obj.LogInfo((object)$"ModdedTabModule: categoryMapping now has {list.Count} entries after Init");
				}
				if (list.Count != 7)
				{
					return;
				}
				Type type = list[0].GetType();
				object obj2 = Activator.CreateInstance(type);
				MethodInfo method = value.GetType().GetMethod("Add");
				if (method != null)
				{
					method.Invoke(value, new object[1] { obj2 });
					ManualLogSource obj3 = log;
					if (obj3 != null)
					{
						obj3.LogInfo((object)"ModdedTabModule: Added 8th entry in Postfix fallback");
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource obj4 = log;
				if (obj4 != null)
				{
					obj4.LogError((object)("ModdedTabModule: Error in Init Postfix: " + ex.Message));
				}
			}
		}

		internal static void OnTechTreeUIInitPostfix(TechTreeUI instance)
		{
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Expected O, but got Unknown
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Expected O, but got Unknown
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Expected O, but got Unknown
			try
			{
				FieldInfo field = typeof(TechTreeUI).GetField("gridUI", BindingFlags.Instance | BindingFlags.NonPublic);
				FieldInfo field2 = typeof(TechTreeUI).GetField("cachedButtons", BindingFlags.Instance | BindingFlags.NonPublic);
				FieldInfo field3 = typeof(TechTreeUI).GetField("categoryButtonPrefab", BindingFlags.Instance | BindingFlags.NonPublic);
				FieldInfo field4 = typeof(TechTreeUI).GetField("categoryButtonParent", BindingFlags.Instance | BindingFlags.NonPublic);
				if (field == null || field2 == null || field3 == null || field4 == null)
				{
					ManualLogSource obj = log;
					if (obj != null)
					{
						obj.LogError((object)"ModdedTabModule: Could not find required TechTreeUI fields");
					}
					return;
				}
				TechTreeGrid val = (TechTreeGrid)field.GetValue(instance);
				List<TechTreeCategoryButton> list = (List<TechTreeCategoryButton>)field2.GetValue(instance);
				TechTreeCategoryButton val2 = (TechTreeCategoryButton)field3.GetValue(instance);
				RectTransform val3 = (RectTransform)field4.GetValue(instance);
				if ((Object)(object)val == (Object)null || list == null || (Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null)
				{
					ManualLogSource obj2 = log;
					if (obj2 != null)
					{
						obj2.LogError((object)"ModdedTabModule: Required TechTreeUI field values are null");
					}
					return;
				}
				if (list.Count > 7)
				{
					ManualLogSource obj3 = log;
					if (obj3 != null)
					{
						obj3.LogInfo((object)"ModdedTabModule: Modded button already exists");
					}
					return;
				}
				moddedButton = Object.Instantiate<TechTreeCategoryButton>(val2, (Transform)(object)val3);
				((Object)((Component)moddedButton).gameObject).name = "Modded Button";
				InitializeModdedButton(moddedButton, val);
				list.Add(moddedButton);
				MapModdedUnlocks();
				ManualLogSource obj4 = log;
				if (obj4 != null)
				{
					obj4.LogInfo((object)"ModdedTabModule: Added Modded tab button to tech tree UI");
				}
			}
			catch (Exception arg)
			{
				ManualLogSource obj5 = log;
				if (obj5 != null)
				{
					obj5.LogError((object)$"ModdedTabModule: Error adding Modded tab button: {arg}");
				}
			}
		}

		internal static void OnTechTreeGridInitPostfix(TechTreeGrid instance)
		{
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Expected O, but got Unknown
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Expected O, but got Unknown
			try
			{
				FieldInfo field = typeof(TechTreeGrid).GetField("categoryContainers", BindingFlags.Instance | BindingFlags.NonPublic);
				FieldInfo field2 = typeof(TechTreeGrid).GetField("categoryPrefab", BindingFlags.Instance | BindingFlags.Public);
				FieldInfo field3 = typeof(TechTreeGrid).GetField("scrollXfm", BindingFlags.Instance | BindingFlags.Public);
				if (field == null)
				{
					ManualLogSource obj = log;
					if (obj != null)
					{
						obj.LogError((object)"ModdedTabModule: Could not find categoryContainers field");
					}
					return;
				}
				TechTreeCategoryContainer[] array = (TechTreeCategoryContainer[])field.GetValue(instance);
				TechTreeCategoryContainer val = (TechTreeCategoryContainer)(field2?.GetValue(instance));
				RectTransform val2 = (RectTransform)(field3?.GetValue(instance));
				if (array == null)
				{
					ManualLogSource obj2 = log;
					if (obj2 != null)
					{
						obj2.LogError((object)"ModdedTabModule: categoryContainers is null");
					}
					return;
				}
				if (array.Length > 7)
				{
					ManualLogSource obj3 = log;
					if (obj3 != null)
					{
						obj3.LogInfo((object)"ModdedTabModule: Category containers already expanded");
					}
					return;
				}
				if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
				{
					ManualLogSource obj4 = log;
					if (obj4 != null)
					{
						obj4.LogError((object)"ModdedTabModule: categoryPrefab or scrollXfm is null");
					}
					return;
				}
				TechTreeCategoryContainer[] array2 = (TechTreeCategoryContainer[])(object)new TechTreeCategoryContainer[8];
				Array.Copy(array, array2, 7);
				moddedContainer = Object.Instantiate<TechTreeCategoryContainer>(val, (Transform)(object)val2);
				((Object)((Component)moddedContainer).gameObject).name = "Modded Category Container";
				MethodInfo method = typeof(TechTreeCategoryContainer).GetMethod("Init", BindingFlags.Instance | BindingFlags.Public);
				if (method != null)
				{
					method.Invoke(moddedContainer, new object[2]
					{
						(object)(TechCategory)7,
						instance
					});
				}
				array2[7] = moddedContainer;
				field.SetValue(instance, array2);
				ManualLogSource obj5 = log;
				if (obj5 != null)
				{
					obj5.LogInfo((object)"ModdedTabModule: Added Modded category container to tech tree grid");
				}
			}
			catch (Exception arg)
			{
				ManualLogSource obj6 = log;
				if (obj6 != null)
				{
					obj6.LogError((object)$"ModdedTabModule: Error adding Modded category container: {arg}");
				}
			}
		}

		internal static bool OnInitButtonPrefix(TechTreeCategoryButton instance, TechTreeGrid gridUI, TechCategory category, bool grayOut)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_0024: 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_0090: Unknown result type (might be due to invalid IL or missing references)
			if ((int)category != 7)
			{
				return true;
			}
			ManualLogSource obj = log;
			if (obj != null)
			{
				obj.LogInfo((object)$"ModdedTabModule: Prefix intercepting InitButton for category {category}");
			}
			try
			{
				if (instance.categoryNames != null)
				{
					TextMeshProUGUI[] categoryNames = instance.categoryNames;
					foreach (TextMeshProUGUI val in categoryNames)
					{
						if ((Object)(object)val != (Object)null)
						{
							((TMP_Text)val).text = "Modded";
						}
					}
				}
				instance._myCategory = category;
				instance.myGrid = gridUI;
				instance.grayedOut = false;
				instance.hovered = false;
				if ((Object)(object)instance.grayedOutCanvasGroup != (Object)null)
				{
					instance.grayedOutCanvasGroup.alpha = 0f;
					instance.grayedOutCanvasGroup.interactable = false;
					instance.grayedOutCanvasGroup.blocksRaycasts = false;
				}
				if ((Object)(object)instance.hoverCanvasGroup != (Object)null)
				{
					instance.hoverCanvasGroup.alpha = 0f;
					instance.hoverCanvasGroup.interactable = false;
					instance.hoverCanvasGroup.blocksRaycasts = false;
				}
				if ((Object)(object)instance.unselectedCanvasGroup != (Object)null)
				{
					instance.unselectedCanvasGroup.alpha = 1f;
					instance.unselectedCanvasGroup.interactable = true;
					instance.unselectedCanvasGroup.blocksRaycasts = true;
				}
				if ((Object)(object)instance.selectedCategoryCanvasGroup != (Object)null)
				{
					instance.selectedCategoryCanvasGroup.alpha = 0f;
				}
				if ((Object)(object)instance.newNotificationBadge != (Object)null)
				{
					instance.newNotificationBadge.alpha = 0f;
					instance.newNotificationBadge.interactable = false;
					instance.newNotificationBadge.blocksRaycasts = false;
				}
				TechTreeCategoryButton capturedInstance = instance;
				TechTreeGrid capturedGrid = gridUI;
				((MouseInteraction)instance).SetCallbacks((Action)delegate
				{
					capturedInstance.hovered = true;
				}, (Action)delegate
				{
					capturedInstance.hovered = false;
				}, (Action)delegate
				{
					if (!capturedInstance.grayedOut && (Object)(object)capturedGrid != (Object)null)
					{
						capturedGrid.InitForCategory((TechCategory)7);
					}
				}, (Action)null, (Action)null, (Action)null);
				ManualLogSource obj2 = log;
				if (obj2 != null)
				{
					obj2.LogInfo((object)("ModdedTabModule: Prefix completed - mouseLeftClickCallback is " + ((((MouseInteraction)instance).mouseLeftClickCallback != null) ? "SET" : "NULL")));
				}
			}
			catch (Exception arg)
			{
				ManualLogSource obj3 = log;
				if (obj3 != null)
				{
					obj3.LogError((object)$"ModdedTabModule: Prefix error: {arg}");
				}
				return true;
			}
			return false;
		}

		internal static void OnInitButtonPostfix(TechTreeCategoryButton instance, TechCategory category)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			if ((int)category != 7)
			{
				return;
			}
			if (instance.categoryNames != null)
			{
				TextMeshProUGUI[] categoryNames = instance.categoryNames;
				foreach (TextMeshProUGUI val in categoryNames)
				{
					if ((Object)(object)val != (Object)null && ((TMP_Text)val).text != "Modded")
					{
						((TMP_Text)val).text = "Modded";
					}
				}
			}
			ManualLogSource obj = log;
			if (obj != null)
			{
				obj.LogInfo((object)string.Format("ModdedTabModule: Postfix - category={0}, grayedOut={1}, clickCallback={2}", instance._myCategory, instance.grayedOut, (((MouseInteraction)instance).mouseLeftClickCallback != null) ? "SET" : "NULL"));
			}
		}

		internal static void OnInitForCategoryPrefix(TechTreeGrid instance, TechCategory category)
		{
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Invalid comparison between Unknown and I4
			try
			{
				int valueOrDefault = (TechTreeState.instance?.unlockStates?.Length).GetValueOrDefault();
				if (instance.techTreeNodes != null && instance.techTreeNodes.Length < valueOrDefault)
				{
					TechTreeNode[] array = (TechTreeNode[])(object)new TechTreeNode[valueOrDefault + 10];
					Array.Copy(instance.techTreeNodes, array, instance.techTreeNodes.Length);
					instance.techTreeNodes = array;
				}
			}
			catch (Exception ex)
			{
				ManualLogSource obj = log;
				if (obj != null)
				{
					obj.LogError((object)("ModdedTabModule: Error expanding techTreeNodes: " + ex.Message));
				}
			}
			if ((int)category == 7)
			{
				MapModdedUnlocks();
			}
		}

		internal static void OnInitForCategoryPostfix(TechTreeGrid instance, TechCategory category)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			if ((int)category != 7)
			{
				return;
			}
			try
			{
				FieldInfo field = typeof(TechTreeGrid).GetField("categoryContainers", BindingFlags.Instance | BindingFlags.NonPublic);
				if (field == null)
				{
					return;
				}
				TechTreeCategoryContainer[] array = (TechTreeCategoryContainer[])field.GetValue(instance);
				if (array == null || array.Length <= 7)
				{
					return;
				}
				TechTreeCategoryContainer val = array[7];
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				List<int> categoryMapping = val.categoryMapping;
				ManualLogSource obj = log;
				if (obj != null)
				{
					obj.LogInfo((object)"ModdedTabModule POSTFIX: After InitForCategory(7), checking nodes...");
				}
				int num = 0;
				foreach (int item in categoryMapping)
				{
					if (item < 0 || item >= instance.techTreeNodes.Length)
					{
						continue;
					}
					TechTreeNode val2 = instance.techTreeNodes[item];
					if ((Object)(object)val2 != (Object)null)
					{
						num++;
						RectTransform xfm = val2.xfm;
						Vector2 val3 = ((xfm != null) ? xfm.anchoredPosition : Vector2.zero);
						ManualLogSource obj2 = log;
						if (obj2 != null)
						{
							obj2.LogInfo((object)$"  Node[{item}]: pos=({val3.x:F1}, {val3.y:F1}), active={((Component)val2).gameObject.activeSelf}");
						}
					}
				}
				ManualLogSource obj3 = log;
				if (obj3 != null)
				{
					obj3.LogInfo((object)$"ModdedTabModule POSTFIX: {num} nodes created");
				}
			}
			catch (Exception ex)
			{
				ManualLogSource obj4 = log;
				if (obj4 != null)
				{
					obj4.LogError((object)("ModdedTabModule POSTFIX error: " + ex.Message));
				}
			}
		}

		internal static bool OnGetNeighboringCategoriesPrefix(TechTreeGrid instance, TechCategory category, ref TechCategory prev, ref TechCategory next)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected I4, but got Unknown
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected I4, but got Unknown
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Invalid comparison between I4 and Unknown
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Invalid comparison between I4 and Unknown
			prev = (TechCategory)(category - 1);
			next = (TechCategory)(category + 1);
			MethodInfo hasUnlockedMethod = typeof(TechTreeGrid).GetMethod("HasUnlockedCategory", BindingFlags.Instance | BindingFlags.Public);
			if (hasUnlockedMethod == null)
			{
				return true;
			}
			Func<TechCategory, bool> func = delegate(TechCategory cat)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0003: Invalid comparison between Unknown and I4
				//IL_000d: Unknown result type (might be due to invalid IL or missing references)
				//IL_000f: Invalid comparison between Unknown and I4
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				//IL_0013: Invalid comparison between Unknown and I4
				//IL_0034: Unknown result type (might be due to invalid IL or missing references)
				if ((int)cat == 7)
				{
					return true;
				}
				return (int)cat >= 0 && (int)cat <= 7 && (bool)hasUnlockedMethod.Invoke(instance, new object[1] { cat });
			};
			while (!func(prev))
			{
				if ((int)prev < 0)
				{
					prev = (TechCategory)7;
				}
				else
				{
					prev = (TechCategory)((int)prev - 1);
				}
				if ((int)prev == (int)category)
				{
					break;
				}
			}
			while (!func(next))
			{
				if ((int)next > 7)
				{
					next = (TechCategory)0;
				}
				else
				{
					next = (TechCategory)((int)next + 1);
				}
				if ((int)next == (int)category)
				{
					break;
				}
			}
			return false;
		}

		private static void InitializeModdedButton(TechTreeCategoryButton button, TechTreeGrid gridUI)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (button.categoryNames != null)
				{
					TextMeshProUGUI[] categoryNames = button.categoryNames;
					foreach (TextMeshProUGUI val in categoryNames)
					{
						if ((Object)(object)val != (Object)null)
						{
							((TMP_Text)val).text = "Modded";
						}
					}
				}
				button._myCategory = (TechCategory)7;
				button.myGrid = gridUI;
				button.grayedOut = false;
				button.hovered = false;
				if ((Object)(object)button.grayedOutCanvasGroup != (Object)null)
				{
					button.grayedOutCanvasGroup.alpha = 0f;
					button.grayedOutCanvasGroup.interactable = false;
					button.grayedOutCanvasGroup.blocksRaycasts = false;
				}
				if ((Object)(object)button.hoverCanvasGroup != (Object)null)
				{
					button.hoverCanvasGroup.alpha = 0f;
					button.hoverCanvasGroup.interactable = false;
					button.hoverCanvasGroup.blocksRaycasts = false;
				}
				if ((Object)(object)button.unselectedCanvasGroup != (Object)null)
				{
					button.unselectedCanvasGroup.alpha = 1f;
					button.unselectedCanvasGroup.interactable = true;
					button.unselectedCanvasGroup.blocksRaycasts = true;
				}
				if ((Object)(object)button.selectedCategoryCanvasGroup != (Object)null)
				{
					button.selectedCategoryCanvasGroup.alpha = 0f;
				}
				if (!((Component)button).gameObject.activeSelf)
				{
					((Component)button).gameObject.SetActive(true);
				}
				TechTreeGrid capturedGrid = gridUI;
				TechTreeCategoryButton capturedButton = button;
				((MouseInteraction)button).SetCallbacks((Action)delegate
				{
					capturedButton.hovered = true;
				}, (Action)delegate
				{
					capturedButton.hovered = false;
				}, (Action)delegate
				{
					if ((Object)(object)capturedGrid != (Object)null && !capturedButton.grayedOut)
					{
						capturedGrid.InitForCategory((TechCategory)7);
					}
				}, (Action)null, (Action)null, (Action)null);
				ManualLogSource obj = log;
				if (obj != null)
				{
					obj.LogInfo((object)"ModdedTabModule: Modded button initialized");
				}
			}
			catch (Exception arg)
			{
				ManualLogSource obj2 = log;
				if (obj2 != null)
				{
					obj2.LogError((object)$"ModdedTabModule: Error initializing Modded button: {arg}");
				}
			}
		}
	}
	[HarmonyPatch]
	internal static class ModdedTabPatches
	{
		[HarmonyPatch(typeof(TechTreeState), "Init")]
		[HarmonyTranspiler]
		[HarmonyPriority(800)]
		public static IEnumerable<CodeInstruction> TechTreeState_Init_Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Expected O, but got Unknown
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			int num = 0;
			for (int i = 0; i < list.Count; i++)
			{
				if (list[i].opcode == OpCodes.Ldc_I4_7)
				{
					list[i] = new CodeInstruction(OpCodes.Ldc_I4_8, (object)null);
					num++;
					ManualLogSource log = TechtonicaFrameworkPlugin.Log;
					if (log != null)
					{
						log.LogInfo((object)$"ModdedTabPatches: Patched constant 7 -> 8 at IL offset {i}");
					}
				}
				else if (list[i].opcode == OpCodes.Ldc_I4_S && list[i].operand is sbyte b && b == 7)
				{
					list[i] = new CodeInstruction(OpCodes.Ldc_I4_S, (object)(sbyte)8);
					num++;
					ManualLogSource log2 = TechtonicaFrameworkPlugin.Log;
					if (log2 != null)
					{
						log2.LogInfo((object)$"ModdedTabPatches: Patched constant 7 -> 8 (ldc.i4.s) at IL offset {i}");
					}
				}
				else if (list[i].opcode == OpCodes.Ldc_I4 && list[i].operand is int num2 && num2 == 7)
				{
					list[i] = new CodeInstruction(OpCodes.Ldc_I4, (object)8);
					num++;
					ManualLogSource log3 = TechtonicaFrameworkPlugin.Log;
					if (log3 != null)
					{
						log3.LogInfo((object)$"ModdedTabPatches: Patched constant 7 -> 8 (ldc.i4) at IL offset {i}");
					}
				}
			}
			ManualLogSource log4 = TechtonicaFrameworkPlugin.Log;
			if (log4 != null)
			{
				log4.LogInfo((object)$"ModdedTabPatches: Transpiler patched {num} occurrences of '7' to '8' in TechTreeState.Init");
			}
			return list;
		}

		[HarmonyPatch(typeof(TechTreeState), "Init")]
		[HarmonyPostfix]
		[HarmonyPriority(0)]
		public static void TechTreeState_Init_Postfix(TechTreeState __instance)
		{
			ModdedTabModule.OnTechTreeStateInitPostfix(__instance);
		}

		[HarmonyPatch(typeof(TechTreeUI), "Init")]
		[HarmonyPostfix]
		public static void TechTreeUI_Init_Postfix(TechTreeUI __instance)
		{
			ModdedTabModule.OnTechTreeUIInitPostfix(__instance);
		}

		[HarmonyPatch(typeof(TechTreeGrid), "Init")]
		[HarmonyPostfix]
		public static void TechTreeGrid_Init_Postfix(TechTreeGrid __instance)
		{
			ModdedTabModule.OnTechTreeGridInitPostfix(__instance);
		}

		[HarmonyPatch(typeof(TechTreeCategoryButton), "InitButton")]
		[HarmonyPrefix]
		public static bool TechTreeCategoryButton_InitButton_Prefix(TechTreeCategoryButton __instance, TechTreeGrid gridUI, TechCategory category, bool grayOut)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			return ModdedTabModule.OnInitButtonPrefix(__instance, gridUI, category, grayOut);
		}

		[HarmonyPatch(typeof(TechTreeCategoryButton), "InitButton")]
		[HarmonyPostfix]
		public static void TechTreeCategoryButton_InitButton_Postfix(TechTreeCategoryButton __instance, TechTreeGrid gridUI, TechCategory category)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			ModdedTabModule.OnInitButtonPostfix(__instance, category);
		}

		[HarmonyPatch(typeof(TechTreeGrid), "InitForCategory")]
		[HarmonyPrefix]
		public static void TechTreeGrid_InitForCategory_Prefix(TechTreeGrid __instance, TechCategory category)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			ModdedTabModule.OnInitForCategoryPrefix(__instance, category);
		}

		[HarmonyPatch(typeof(TechTreeGrid), "InitForCategory")]
		[HarmonyPostfix]
		public static void TechTreeGrid_InitForCategory_Postfix(TechTreeGrid __instance, TechCategory category)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			ModdedTabModule.OnInitForCategoryPostfix(__instance, category);
		}

		[HarmonyPatch(typeof(TechTreeGrid), "GetNeighboringCategories")]
		[HarmonyPrefix]
		public static bool TechTreeGrid_GetNeighboringCategories_Prefix(TechTreeGrid __instance, TechCategory category, ref TechCategory prev, ref TechCategory next)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return ModdedTabModule.OnGetNeighboringCategoriesPrefix(__instance, category, ref prev, ref next);
		}

		[HarmonyPatch(typeof(TechTreeState), "ReadSaveState")]
		[HarmonyPostfix]
		public static void TechTreeState_ReadSaveState_Postfix()
		{
			ModdedTabModule.MapModdedUnlocks();
		}
	}
}
namespace TechtonicaFramework.Narrative
{
	public class NarrativeModule : IFrameworkModule
	{
		private Dictionary<string, CustomDialogueEntry> customDialogues = new Dictionary<string, CustomDialogueEntry>();

		private Dictionary<string, CustomSpeaker> customSpeakers = new Dictionary<string, CustomSpeaker>();

		private HashSet<string> playedDialogues = new HashSet<string>();

		internal static HashSet<NarrativeEntryData> customNarrativeEntries = new HashSet<NarrativeEntryData>();

		private static readonly Dictionary<string, Speaker> SpeakerMap = new Dictionary<string, Speaker>
		{
			{
				"sparks",
				(Speaker)3
			},
			{
				"paladin",
				(Speaker)4
			},
			{
				"mirage",
				(Speaker)14
			},
			{
				"system",
				(Speaker)2
			},
			{
				"unknown",
				(Speaker)7
			},
			{
				"groundbreaker",
				(Speaker)16
			},
			{
				"sparks_radio",
				(Speaker)5
			},
			{
				"mirage_radio",
				(Speaker)15
			},
			{
				"tapwire_a",
				(Speaker)8
			},
			{
				"tapwire_b",
				(Speaker)9
			},
			{
				"ancient_ai",
				(Speaker)7
			},
			{
				"corrupted_sparks",
				(Speaker)7
			}
		};

		private static readonly Dictionary<string, string> CustomSpeakerNames = new Dictionary<string, string>
		{
			{ "ancient_ai", "Ancient AI" },
			{ "corrupted_sparks", "S\u0337p\u0334a\u0335r\u0337k\u0338s\u0335" }
		};

		public bool IsActive { get; private set; }

		public void Initialize()
		{
			IsActive = true;
			ApplyPatches();
			TechtonicaFrameworkPlugin.LogDebug("NarrativeModule: Initialized with game dialogue integration and localization bypass");
		}

		private void ApplyPatches()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			try
			{
				Harmony harmony = TechtonicaFrameworkPlugin.Harmony;
				MethodInfo methodInfo = AccessTools.Method(typeof(DialogueEntryPopupUI), "StartNarrativeString", (Type[])null, (Type[])null);
				HarmonyMethod val = new HarmonyMethod(typeof(NarrativePatches), "StartNarrativeString_Prefix", (Type[])null);
				if (methodInfo != null)
				{
					harmony.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					TechtonicaFrameworkPlugin.LogDebug("NarrativeModule: Patched StartNarrativeString for localization bypass");
				}
				else
				{
					TechtonicaFrameworkPlugin.Log.LogWarning((object)"NarrativeModule: Could not find StartNarrativeString method");
				}
			}
			catch (Exception ex)
			{
				TechtonicaFrameworkPlugin.Log.LogError((object)("NarrativeModule: Failed to apply patches: " + ex.Message));
			}
		}

		public void Update()
		{
		}

		public void Shutdown()
		{
			IsActive = false;
			customDialogues.Clear();
			customSpeakers.Clear();
			TechtonicaFrameworkPlugin.LogDebug("NarrativeModule: Shutdown");
		}

		public void RegisterSpeaker(string id, string displayName, Color textColor, Sprite portrait = null)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			CustomSpeaker value = new CustomSpeaker
			{
				Id = id,
				DisplayName = displayName,
				TextColor = textColor,
				Portrait = portrait
			};
			customSpeakers[id] = value;
			TechtonicaFrameworkPlugin.LogDebug("NarrativeModule: Registered speaker '" + id + "' (" + displayName + ")");
		}

		public CustomSpeaker GetSpeaker(string id)
		{
			CustomSpeaker value;
			return customSpeakers.TryGetValue(id, out value) ? value : null;
		}

		public Speaker GetGameSpeaker(string speakerId)
		{
			//IL_001d: 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_0019: 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)
			if (SpeakerMap.TryGetValue(speakerId.ToLower(), out var value))
			{
				return value;
			}
			return (Speaker)7;
		}

		public CustomDialogueEntry RegisterDialogue(string id, string speakerId, string text, float duration = 5f, string voKey = null)
		{
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			string text2 = null;
			CustomSpeaker speaker = GetSpeaker(speakerId);
			string value;
			if (speaker != null)
			{
				text2 = speaker.DisplayName;
			}
			else if (CustomSpeakerNames.TryGetValue(speakerId.ToLower(), out value))
			{
				text2 = value;
			}
			CustomDialogueEntry customDialogueEntry = new CustomDialogueEntry
			{
				Id = id,
				SpeakerId = speakerId,
				Text = text,
				Duration = duration,
				NextDialogueId = null,
				Condition = null,
				GameSpeaker = GetGameSpeaker(speakerId),
				CustomSpeakerName = text2,
				VOKey = voKey
			};
			customDialogues[id] = customDialogueEntry;
			TechtonicaFrameworkPlugin.LogDebug("NarrativeModule: Registered dialogue '" + id + "' for speaker '" + speakerId + "' (name=" + (text2 ?? "default") + ")");
			return customDialogueEntry;
		}

		public void ChainDialogue(string dialogueId, string nextDialogueId)
		{
			if (customDialogues.TryGetValue(dialogueId, out var value))
			{
				value.NextDialogueId = nextDialogueId;
			}
		}

		public void SetDialogueCondition(string dialogueId, Func<bool> condition)
		{
			if (customDialogues.TryGetValue(dialogueId, out var value))
			{
				value.Condition = condition;
			}
		}

		public void TriggerDialogue(string dialogueId)
		{
			if (!customDialogues.TryGetValue(dialogueId, out var value))
			{
				TechtonicaFrameworkPlugin.LogDebug("NarrativeModule: Dialogue '" + dialogueId + "' not found");
				return;
			}
			if (value.Condition != null && !value.Condition())
			{
				TechtonicaFrameworkPlugin.LogDebug("NarrativeModule: Dialogue '" + dialogueId + "' condition not met");
				return;
			}
			DisplayDialogueViaGameUI(value);
			playedDialogues.Add(dialogueId);
			FrameworkEvents.RaiseDialogueStarted(dialogueId);
		}

		public bool HasDialoguePlayed(string dialogueId)
		{
			return playedDialogues.Contains(dialogueId);
		}

		public void ResetPlayedDialogues()
		{
			playedDialogues.Clear();
		}

		private void DisplayDialogueViaGameUI(CustomDialogueEntry entry)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				DialogueEntryPopupUI val = UIManager.instance?.dialoguePopup;
				if ((Object)(object)val == (Object)null)
				{
					TechtonicaFrameworkPlugin.LogDebug("NarrativeModule: DialoguePopup not available, using fallback");
					DisplayFallbackDialogue(entry);
					return;
				}
				NarrativeEntryData val2 = ScriptableObject.CreateInstance<NarrativeEntryData>();
				val2.shortText = entry.Text;
				val2.speaker = entry.GameSpeaker;
				val2.durationOnScreen = entry.Duration;
				val2.addToLogAfterFirstPlayback = false;
				((Object)val2).name = entry.CustomSpeakerName ?? "";
				val2.shortTextVOKey = entry.VOKey ?? "";
				customNarrativeEntries.Add(val2);
				val.OnTriggerNarrativeEntry(val2, false);
				TechtonicaFrameworkPlugin.LogDebug("NarrativeModule: Triggered dialogue '" + entry.Id + "' via game UI (localization bypass active)");
				if (!string.IsNullOrEmpty(entry.NextDialogueId))
				{
					TechtonicaFrameworkPlugin instance = TechtonicaFrameworkPlugin.Instance;
					if (instance != null)
					{
						((MonoBehaviour)instance).StartCoroutine(TriggerChainedDialogue(entry.NextDialogueId, entry.Duration + 1f));
					}
				}
			}
			catch (Exception ex)
			{
				TechtonicaFrameworkPlugin.LogDebug("NarrativeModule: Error displaying dialogue: " + ex.Message);
				DisplayFallbackDialogue(entry);
			}
		}

		private IEnumerator TriggerChainedDialogue(string dialogueId, float delay)
		{
			yield return (object)new WaitForSeconds(delay);
			TriggerDialogue(dialogueId);
		}

		private void DisplayFallbackDialogue(CustomDialogueEntry entry)
		{
			string text = GetSpeaker(entry.SpeakerId)?.DisplayName ?? entry.SpeakerId;
			try
			{
				SystemLogUI val = UIManager.instance?.systemLog;
				if ((Object)(object)val != (Object)null)
				{
					val.FlashMessage("[" + text + "] " + entry.Text);
				}
			}
			catch
			{
				TechtonicaFrameworkPlugin.Log.LogInfo((object)("[DIALOGUE] [" + text + "] " + entry.Text));
			}
			if (!string.IsNullOrEmpty(entry.NextDialogueId))
			{
				TechtonicaFrameworkPlugin instance = TechtonicaFrameworkPlugin.Instance;
				if (instance != null)
				{
					((MonoBehaviour)instance).StartCoroutine(TriggerChainedDialogue(entry.NextDialogueId, entry.Duration + 1f));
				}
			}
		}

		public DialogueSequenceBuilder CreateSequence(string sequenceId)
		{
			return new DialogueSequenceBuilder(this, sequenceId);
		}

		public void CreateQuestDialogueTrigger(string questId, string startDialogueId, string endDialogueId)
		{
			TechtonicaFrameworkPlugin.LogDebug("NarrativeModule: Created quest dialogue trigger for '" + questId + "'");
		}
	}
	public class CustomSpeaker
	{
		public string Id;

		public string DisplayName;

		public Color TextColor;

		public Sprite Portrait;
	}
	public class CustomDialogueEntry
	{
		public string Id;

		public string SpeakerId;

		public string Text;

		public float Duration;

		public string NextDialogueId;

		public Func<bool> Condition;

		public Speaker GameSpeaker;

		public string CustomSpeakerName;

		public string VOKey;
	}
	public class DialogueSequenceBuilder
	{
		private NarrativeModule module;

		private string sequenceId;

		private List<string> dialogueIds = new List<string>();

		private string lastDialogueId;

		public DialogueSequenceBuilder(NarrativeModule module, string sequenceId)
		{
			this.module = module;
			this.sequenceId = sequenceId;
		}

		public DialogueSequenceBuilder AddLine(string speakerId, string text, float duration = 5f)
		{
			string text2 = $"{sequenceId}_{dialogueIds.Count}";
			CustomDialogueEntry customDialogueEntry = module.RegisterDialogue(text2, speakerId, text, duration);
			if (!string.IsNullOrEmpty(lastDialogueId))
			{
				module.ChainDialogue(lastDialogueId, text2);
			}
			dialogueIds.Add(text2);
			lastDialogueId = text2;
			return this;
		}

		public DialogueSequenceBuilder WithCondition(Func<bool> condition)
		{
			if (dialogueIds.Count > 0)
			{
				module.SetDialogueCondition(dialogueIds[0], condition);
			}
			return this;
		}

		public string GetStartId()
		{
			return (dialogueIds.Count > 0) ? dialogueIds[0] : null;
		}

		public void Play()
		{
			string startId = GetStartId();
			if (!string.IsNullOrEmpty(startId))
			{
				module.TriggerDialogue(startId);
			}
		}
	}
	internal static class NarrativePatches
	{
		public static bool StartNarrativeString_Prefix(DialogueEntryPopupUI __instance, NarrativeEntryData entryData)
		{
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Invalid comparison between Unknown and I4
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0320: Unknown result type (might be due to invalid IL or missing references)
			//IL_0312: Unknown result type (might be due to invalid IL or missing references)
			//IL_0317: Unknown result type (might be due to invalid IL or missing references)
			if (!NarrativeModule.customNarrativeEntries.Contains(entryData))
			{
				return true;
			}
			try
			{
				FieldInfo fieldInfo = AccessTools.Field(typeof(DialogueEntryPopupUI), "messageText");
				FieldInfo fieldInfo2 = AccessTools.Field(typeof(DialogueEntryPopupUI), "speakerNameText");
				FieldInfo fieldInfo3 = AccessTools.Field(typeof(DialogueEntryPopupUI), "speakerPortraitCanvasGroup");
				FieldInfo fieldInfo4 = AccessTools.Field(typeof(DialogueEntryPopupUI), "speakerPortraitImage");
				FieldInfo fieldInfo5 = AccessTools.Field(typeof(DialogueEntryPopupUI), "_showingMessage");
				FieldInfo fieldInfo6 = AccessTools.Field(typeof(DialogueEntryPopupUI), "_currentEntryBeingShown");
				FieldInfo fieldInfo7 = AccessTools.Field(typeof(DialogueEntryPopupUI), "timeOnScreen");
				object? obj = fieldInfo?.GetValue(__instance);
				TextMeshProUGUI val = (TextMeshProUGUI)((obj is TextMeshProUGUI) ? obj : null);
				object? obj2 = fieldInfo2?.GetValue(__instance);
				TextMeshProUGUI val2 = (TextMeshProUGUI)((obj2 is TextMeshProUGUI) ? obj2 : null);
				object? obj3 = fieldInfo3?.GetValue(__instance);
				CanvasGroup val3 = (CanvasGroup)((obj3 is CanvasGroup) ? obj3 : null);
				object? obj4 = fieldInfo4?.GetValue(__instance);
				Image val4 = (Image)((obj4 is Image) ? obj4 : null);
				if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
				{
					TechtonicaFrameworkPlugin.LogDebug("NarrativePatches: Could not find text fields, falling back to original");
					return true;
				}
				fieldInfo5?.SetValue(__instance, true);
				fieldInfo6?.SetValue(__instance, entryData);
				((TMP_Text)val).text = entryData.shortText;
				if ((int)entryData.speaker == 0)
				{
					((TMP_Text)val2).text = string.Empty;
					if (val3 != null)
					{
						FHG_Utils.ToggleAlpha(val3, false);
					}
				}
				else
				{
					string text = ((Object)entryData).name;
					if (string.IsNullOrEmpty(text))
					{
						GameDefines instance = GameDefines.instance;
						text = ((instance != null) ? instance.GetSpeakerInfo(entryData.speaker) : null)?._displayName ?? ((object)(Speaker)(ref entryData.speaker)).ToString();
					}
					((TMP_Text)val2).text = text;
					GameDefines instance2 = GameDefines.instance;
					SpeakerInfo val5 = ((instance2 != null) ? instance2.GetSpeakerInfo(entryData.speaker) : null);
					if ((Object)(object)val5?._speakerPortrait != (Object)null)
					{
						if (val3 != null)
						{
							FHG_Utils.ToggleAlpha(val3, true);
						}
						if ((Object)(object)val4 != (Object)null)
						{
							val4.sprite = val5._speakerPortrait;
						}
					}
					else if (val3 != null)
					{
						FHG_Utils.ToggleAlpha(val3, false);
					}
				}
				if (entryData.durationOnScreen >= 0f)
				{
					fieldInfo7?.SetValue(__instance, entryData.durationOnScreen);
				}
				if (!string.IsNullOrEmpty(entryData.shortTextVOKey) && (Object)(object)VOPlaybackManager.instance != (Object)null)
				{
					float num = default(float);
					EventInstance dialogueEventInstance = VOPlaybackManager.instance.GetDialogueEventInstance(entryData.shortTextVOKey, entryData.speaker, ref num);
					if (((EventInstance)(ref dialogueEventInstance)).isValid())
					{
						EventDescription val6 = default(EventDescription);
						((EventInstance)(ref dialogueEventInstance)).getDescription(ref val6);
						bool flag = default(bool);
						((EventDescription)(ref val6)).is3D(ref flag);
						if (flag)
						{
							((EventInstance)(ref dialogueEventInstance)).set3DAttributes(RuntimeUtils.To3DAttributes(((Component)__instance).transform));
						}
						((EventInstance)(ref dialogueEventInstance)).start();
						TechtonicaFrameworkPlugin.LogDebug("NarrativePatches: Started VO playback for key '" + entryData.shortTextVOKey + "'");
					}
				}
				MethodInfo methodInfo = AccessTools.Method(typeof(DialogueEntryPopupUI), "AnimCoroutine", (Type[])null, (Type[])null);
				if (methodInfo != null && methodInfo.Invoke(__instance, null) is IEnumerator enumerator)
				{
					((MonoBehaviour)__instance).StartCoroutine(enumerator);
				}
				NarrativeModule.customNarrativeEntries.Remove(entryData);
				TechtonicaFrameworkPlugin.LogDebug("NarrativePatches: Custom dialogue displayed (bypassed localization)");
				return false;
			}
			catch (Exception ex)
			{
				TechtonicaFrameworkPlugin.Log.LogError((object)("NarrativePatches: Error in prefix: " + ex.Message));
				return true;
			}
		}
	}
}
namespace TechtonicaFramework.Health
{
	public class HealthModule : IFrameworkModule
	{
		private Dictionary<uint, MachineHealthData> machineHealthRegistry = new Dictionary<uint, MachineHealthData>();

		public bool IsActive { get; private set; }

		public float DefaultMachineHealth { get; set; } = 100f;


		public float DefaultRepairRate { get; set; } = 10f;


		public void Initialize()
		{
			IsActive = true;
			TechtonicaFrameworkPlugin.LogDebug("HealthModule: Initialized");
		}

		public void Update()
		{
			if (IsActive)
			{
				ProcessHealthUpdates();
			}
		}

		public void Shutdown()
		{
			IsActive = false;
			machineHealthRegistry.Clear();
			TechtonicaFrameworkPlugin.LogDebug("HealthModule: Shutdown");
		}

		public void RegisterMachine(uint machineId, float maxHealth = 0f)
		{
			if (maxHealth <= 0f)
			{
				maxHealth = DefaultMachineHealth;
			}
			if (!machineHealthRegistry.ContainsKey(machineId))
			{
				machineHealthRegistry[machineId] = new MachineHealthData
				{
					MachineId = machineId,
					MaxHealth = maxHealth,
					CurrentHealth = maxHealth,
					IsDestroyed = false,
					IsBeingRepaired = false
				};
				TechtonicaFrameworkPlugin.LogDebug($"HealthModule: Registered machine {machineId} with {maxHealth} HP");
			}
		}

		public void UnregisterMachine(uint machineId)
		{
			machineHealthRegistry.Remove(machineId);
		}

		public MachineHealthData GetMachineHealth(uint machineId)
		{
			MachineHealthData value;
			return machineHealthRegistry.TryGetValue(machineId, out value) ? value : null;
		}

		public void DamageMachine(uint machineId, float damage, DamageType damageType = DamageType.Generic)
		{
			if (machineHealthRegistry.TryGetValue(machineId, out var value) && !value.IsDestroyed)
			{
				float currentHealth = value.CurrentHealth;
				value.CurrentHealth = Mathf.Max(0f, value.CurrentHealth - damage);
				value.LastDamageType = damageType;
				value.LastDamageTime = Time.time;
				FrameworkEvents.RaiseMachineHealthChanged(machineId, currentHealth, value.CurrentHealth);
				FrameworkEvents.RaiseMachineDamaged(machineId);
				TechtonicaFrameworkPlugin.LogDebug($"HealthModule: Machine {machineId} took {damage} damage ({damageType}), HP: {value.CurrentHealth}/{value.MaxHealth}");
				if (value.CurrentHealth <= 0f)
				{
					DestroyMachine(machineId);
				}
			}
		}

		public void HealMachine(uint machineId, float amount)
		{
			if (machineHealthRegistry.TryGetValue(machineId, out var value) && !value.IsDestroyed)
			{
				float currentHealth = value.CurrentHealth;
				value.CurrentHealth = Mathf.Min(value.MaxHealth, value.CurrentHealth + amount);
				if (value.CurrentHealth > currentHealth)
				{
					FrameworkEvents.RaiseMachineHealthChanged(machineId, currentHealth, value.CurrentHealth);
					TechtonicaFrameworkPlugin.LogDebug($"HealthModule: Machine {machineId} healed {amount}, HP: {value.CurrentHealth}/{value.MaxHealth}");
				}
			}
		}

		public void StartRepair(uint machineId)
		{
			if (machineHealthRegistry.TryGetValue(machineId, out var value) && !value.IsDestroyed && !(value.CurrentHealth >= value.MaxHealth))
			{
				value.IsBeingRepaired = true;
				TechtonicaFrameworkPlugin.LogDebug($"HealthModule: Started repairing machine {machineId}");
			}
		}

		public void StopRepair(uint machineId)
		{
			if (machineHealthRegistry.TryGetValue(machineId, out var value))
			{
				value.IsBeingRepaired = false;
				TechtonicaFrameworkPlugin.LogDebug($"HealthModule: Stopped repairing machine {machineId}");
			}
		}

		public void FullRepair(uint machineId)
		{
			if (machineHealthRegistry.TryGetValue(machineId, out var value) && !value.IsDestroyed)
			{
				float currentHealth = value.CurrentHealth;
				value.CurrentHealth = value.MaxHealth;
				value.IsBeingRepaired = false;
				FrameworkEvents.RaiseMachineHealthChanged(machineId, currentHealth, value.CurrentHealth);
				FrameworkEvents.RaiseMachineRepaired(machineId);
				TechtonicaFrameworkPlugin.LogDebug($"HealthModule: Machine {machineId} fully repaired");
			}
		}

		private void DestroyMachine(uint machineId)
		{
			if (machineHealthRegistry.TryGetValue(machineId, out var value))
			{
				value.IsDestroyed = true;
				value.IsBeingRepaired = false;
				FrameworkEvents.RaiseMachineDestroyed(machineId);
				TechtonicaFrameworkPlugin.LogDebug($"HealthModule: Machine {machineId} destroyed!");
			}
		}

		public bool IsMachineAlive(uint machineId)
		{
			if (!machineHealthRegistry.TryGetValue(machineId, out var value))
			{
				return false;
			}
			return !value.IsDestroyed && value.CurrentHealth > 0f;
		}

		public float GetHealthPercent(uint machineId)
		{
			if (!machineHealthRegistry.TryGetValue(machineId, out var value))
			{
				return 1f;
			}
			if (value.MaxHealth <= 0f)
			{
				return 1f;
			}
			return value.CurrentHealth / value.MaxHealth;
		}

		private void ProcessHealthUpdates()
		{
			float deltaTime = Time.deltaTime;
			foreach (KeyValuePair<uint, MachineHealthData> item in machineHealthRegistry)
			{
				MachineHealthData value = item.Value;
				if (value.IsBeingRepaired && !value.IsDestroyed && value.CurrentHealth < value.MaxHealth)
				{
					HealMachine(item.Key, DefaultRepairRate * deltaTime);
					if (value.CurrentHealth >= value.MaxHealth)
					{
						value.IsBeingRepaired = false;
						FrameworkEvents.RaiseMachineRepaired(item.Key);
					}
				}
			}
		}

		public List<uint> GetDamagedMachines(float healthThreshold = 1f)
		{
			List<uint> list = new List<uint>();
			foreach (KeyValuePair<uint, MachineHealthData> item in machineHealthRegistry)
			{
				if (!item.Value.IsDestroyed && GetHealthPercent(item.Key) < healthThreshold)
				{
					list.Add(item.Key);
				}
			}
			return list;
		}

		public int GetTrackedMachineCount()
		{
			return machineHealthRegistry.Count;
		}
	}
	public class MachineHealthData
	{
		public uint MachineId;

		public float MaxHealth;

		public float CurrentHealth;

		public bool IsDestroyed;

		public bool IsBeingRepaired;

		public DamageType LastDamageType;

		public float LastDamageTime;
	}
	public enum DamageType
	{
		Generic,
		Environmental,
		PowerSurge,
		Overload,
		Explosion,
		Corrosion,
		Radiation,
		Fire,
		Frost
	}
}
namespace TechtonicaFramework.Equipment
{
	public class EquipmentModule : IFrameworkModule
	{
		private Dictionary<string, CustomEquipmentDefinition> equipmentDefinitions = new Dictionary<string, CustomEquipmentDefinition>();

		private Dictionary<string, MovementModifier> activeModifiers = new Dictionary<string, MovementModifier>();

		private float baseWalkSpeed = 5f;

		private float baseRunSpeed = 10f;

		private float baseJumpHeight = 2f;

		public bool IsActive { get; private set; }

		public float CurrentWalkSpeed { get; private set; }

		public float CurrentRunSpeed { get; private set; }

		public float CurrentJumpHeight { get; private set; }

		public void Initialize()
		{
			IsActive = true;
			CacheBaseMovementValues();
			TechtonicaFrameworkPlugin.LogDebug("EquipmentModule: Initialized");
		}

		public void Update()
		{
			if (IsActive)
			{
				ProcessMovementModifiers();
			}
		}

		public void Shutdown()
		{
			IsActive = false;
			equipmentDefinitions.Clear();
			activeModifiers.Clear();
			TechtonicaFrameworkPlugin.LogDebug("EquipmentModule: Shutdown");
		}

		private void CacheBaseMovementValues()
		{
			try
			{
				CurrentWalkSpeed = baseWalkSpeed;
				CurrentRunSpeed = baseRunSpeed;
				CurrentJumpHeight = baseJumpHeight;
			}
			catch (Exception ex)
			{
				TechtonicaFrameworkPlugin.LogDebug("EquipmentModule: Could not cache movement values: " + ex.Message);
			}
		}

		public CustomEquipmentDefinition RegisterEquipment(string id, string displayName, string description, EquipmentSlot slot, Action<Player> onEquip = null, Action<Player> onUnequip = null, Action<Player> onUse = null)
		{
			CustomEquipmentDefinition customEquipmentDefinition = new CustomEquipmentDefinition
			{
				Id = id,
				DisplayName = displayName,
				Description = description,
				Slot = slot,
				OnEquip = onEquip,
				OnUnequip = onUnequip,
				OnUse = onUse
			};
			equipmentDefinitions[id] = customEquipmentDefinition;
			TechtonicaFrameworkPlugin.LogDebug("EquipmentModule: Registered equipment '" + id + "' (" + displayName + ")");
			return customEquipmentDefinition;
		}

		public CustomEquipmentDefinition GetEquipmentDefinition(string id)
		{
			CustomEquipmentDefinition value;
			return equipmentDefinitions.TryGetValue(id, out value) ? value : null;
		}

		public List<CustomEquipmentDefinition> GetAllEquipmentDefinitions()
		{
			return new List<CustomEquipmentDefinition>(equipmentDefinitions.Values);
		}

		public void EquipCustomEquipment(string id)
		{
			if (!equipmentDefinitions.TryGetValue(id, out var value))
			{
				TechtonicaFrameworkPlugin.LogWarning("EquipmentModule: Equipment '" + id + "' not found");
				return;
			}
			Player instance = Player.instance;
			if ((Object)(object)instance == (Object)null)
			{
				TechtonicaFrameworkPlugin.LogWarning("EquipmentModule: No player instance");
				return;
			}
			value.OnEquip?.Invoke(instance);
			FrameworkEvents.RaiseEquipmentEquipped(id);
			TechtonicaFrameworkPlugin.LogDebug("EquipmentModule: Equipped '" + id + "'");
		}

		public void UnequipCustomEquipment(string id)
		{
			if (equipmentDefinitions.TryGetValue(id, out var value))
			{
				Player instance = Player.instance;
				if (!((Object)(object)instance == (Object)null))
				{
					value.OnUnequip?.Invoke(instance);
					FrameworkEvents.RaiseEquipmentUnequipped(id);
					TechtonicaFrameworkPlugin.LogDebug("EquipmentModule: Unequipped '" + id + "'");
				}
			}
		}

		public void UseCustomEquipment(string id)
		{
			if (equipmentDefinitions.TryGetValue(id, out var value))
			{
				Player instance = Player.instance;
				if (!((Object)(object)instance == (Object)null))
				{
					value.OnUse?.Invoke(instance);
					TechtonicaFrameworkPlugin.LogDebug("EquipmentModule: Used '" + id + "'");
				}
			}
		}

		public void ApplyMovementModifier(string id, float speedMultiplier = 1f, float jumpMultiplier = 1f, float duration = -1f)
		{
			MovementModifier value = new MovementModifier
			{
				Id = id,
				SpeedMultiplier = speedMultiplier,
				JumpMultiplier = jumpMultiplier,
				Duration = duration,
				TimeApplied = Time.time,
				IsActive = true
			};
			activeModifiers[id] = value;
			RecalculateMovement();
			TechtonicaFrameworkPlugin.LogDebug($"EquipmentModule: Applied movement modifier '{id}' (speed: {speedMultiplier}x, jump: {jumpMultiplier}x)");
		}

		public void RemoveMovementModifier(string id)
		{
			if (activeModifiers.Remove(id))
			{
				RecalculateMovement();
				TechtonicaFrameworkPlugin.LogDebug("EquipmentModule: Removed movement modifier '" + id + "'");
			}
		}

		public bool HasMovementModifier(string id)
		{
			return activeModifiers.ContainsKey(id);
		}

		public void ClearAllModifiers()
		{
			activeModifiers.Clear();
			RecalculateMovement();
		}

		private void ProcessMovementModifiers()
		{
			List<string> list = new List<string>();
			float time = Time.time;
			foreach (KeyValuePair<string, MovementModifier> activeModifier in activeModifiers)
			{
				MovementModifier value = activeModifier.Value;
				if (value.Duration > 0f)
				{
					float num = time - value.TimeApplied;
					if (num >= value.Duration)
					{
						list.Add(activeModifier.Key);
					}
				}
			}
			if (list.Count <= 0)
			{
				return;
			}
			foreach (string item in list)
			{
				activeModifiers.Remove(item);
			}
			RecalculateMovement();
		}

		private void RecalculateMovement()
		{
			float num = 1f;
			float num2 = 1f;
			foreach (MovementModifier value in activeModifiers.Values)
			{
				if (value.IsActive)
				{
					num *= value.SpeedMultiplier;
					num2 *= value.JumpMultiplier;
				}
			}
			CurrentWalkSpeed = baseWalkSpeed * num;
			CurrentRunSpeed = baseRunSpeed * num;
			CurrentJumpHeight = baseJumpHeight * num2;
		}

		public VehicleDefinition RegisterVehicle(string id, string displayName, float maxSpeed, Action<Player> onEnter = null, Action<Player> onExit = null)
		{
			VehicleDefinition vehicle = new VehicleDefinition
			{
				Id = id,
				DisplayName = displayName,
				MaxSpeed = maxSpeed,
				OnEnter = onEnter,
				OnExit = onExit
			};
			CustomEquipmentDefinition customEquipmentDefinition = RegisterEquipment(id, displayName, "Vehicle: " + displayName, EquipmentSlot.Vehicle, delegate(Player p)
			{
				vehicle.OnEnter?.Invoke(p);
				FrameworkEvents.RaiseVehicleEntered(id);
			}, delegate(Player p)
			{
				vehicle.OnExit?.Invoke(p);
				FrameworkEvents.RaiseVehicleExited(id);
			});
			TechtonicaFrameworkPlugin.LogDebug("EquipmentModule: Registered vehicle '" + id + "' (" + displayName + ")");
			return vehicle;
		}

		public void CreateSpeedZone(string id, Vector3 position, float radius, float speedMultiplier)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			EnvironmentModule environmentModule = TechtonicaFrameworkPlugin.EnvironmentModule;
			if (environmentModule == null)
			{
				return;
			}
			environmentModule.CreateHazardZone(id, position, radius, HazardType.Generic, 0f);
			FrameworkEvents.OnHazardZoneEntered += delegate(string zoneId, Vector3 pos)
			{
				if (zoneId == id)
				{
					ApplyMovementModifier("speedzone_" + id, speedMultiplier);
				}
			};
			FrameworkEvents.OnHazardZoneExited += delegate(string zoneId, Vector3 pos)
			{
				if (zoneId == id)
				{
					RemoveMovementModifier("speedzone_" + id);
				}
			};
			TechtonicaFrameworkPlugin.LogDebug($"EquipmentModule: Created speed zone '{id}' at {position} ({speedMultiplier}x speed)");
		}
	}
	public class CustomEquipmentDefinition
	{
		public string Id;

		public string DisplayName;

		public string Description;

		public EquipmentSlot Slot;

		public Sprite Icon;

		public Action<Player> OnEquip;

		public Action<Player> OnUnequip;

		public Action<Player> OnUse;
	}
	public class MovementModifier
	{
		public string Id;

		public float SpeedMultiplier;

		public float JumpMultiplier;

		public float Duration;

		public float TimeApplied;

		public bool IsActive;
	}
	public class VehicleDefinition
	{
		public string Id;

		public string DisplayName;

		public float MaxSpeed;

		public Action<Player> OnEnter;

		public Action<Player> OnExit;
	}
	public enum EquipmentSlot
	{
		Hand,
		Head,
		Body,
		Feet,
		Accessory,
		Vehicle
	}
}
namespace TechtonicaFramework.Environment
{
	public class EnvironmentModule : IFrameworkModule
	{
		private Dictionary<string, HazardZone> hazardZones = new Dictionary<string, HazardZone>();

		private Dictionary<string, StatusEffect> activeEffects = new Dictionary<string, StatusEffect>();

		private Transform playerTransform;

		public bool IsActive { get; private set; }

		public void Initialize()
		{
			IsActive = true;
			TechtonicaFrameworkPlugin.LogDebug("EnvironmentModule: Initialized");
		}

		public void Update()
		{
			if (!IsActive)
			{
				return;
			}
			if ((Object)(object)playerTransform == (Object)null)
			{
				Player instance = Player.instance;
				if ((Object)(object)instance != (Object)null)
				{
					playerTransform = ((Component)instance).transform;
				}
			}
			if ((Object)(object)playerTransform != (Object)null)
			{
				CheckHazardZones();
				ProcessStatusEffects();
			}
		}

		public void Shutdown()
		{
			IsActive = false;
			hazardZones.Clear();
			activeEffects.Clear();
			TechtonicaFrameworkPlugin.LogDebug("EnvironmentModule: Shutdown");
		}

		public HazardZone CreateHazardZone(string id, Vector3 position, float radius, HazardType type, float damagePerSecond = 5f)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: 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)
			HazardZone hazardZone = new HazardZone
			{
				Id = id,
				Position = position,
				Radius = radius,
				Type = type,
				DamagePerSecond = damagePerSecond,
				IsActive = true,
				PlayerInside = false
			};
			hazardZones[id] = hazardZone;
			TechtonicaFrameworkPlugin.LogDebug($"EnvironmentModule: Created hazard zone '{id}' at {position} with radius {radius}");
			return hazardZone;
		}

		public void RemoveHazardZone(string id)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			if (hazardZones.TryGetValue(id, out var value))
			{
				if (value.PlayerInside)
				{
					FrameworkEvents.RaiseHazardZoneExited(id, value.Position);
				}
				hazardZones.Remove(id);
				TechtonicaFrameworkPlugin.LogDebug("EnvironmentModule: Removed hazard zone '" + id + "'");
			}
		}

		public HazardZone GetHazardZone(string id)
		{
			HazardZone value;
			return hazardZones.TryGetValue(id, out value) ? value : null;
		}

		public void SetHazardZoneActive(string id, bool active)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			if (hazardZones.TryGetValue(id, out var value))
			{
				value.IsActive = active;
				if (!active && value.PlayerInside)
				{
					value.PlayerInside = false;
					FrameworkEvents.RaiseHazardZoneExited(id, value.Position);
				}
			}
		}

		private void CheckHazardZones()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: 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_00e4: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = playerTransform.position;
			foreach (KeyValuePair<string, HazardZone> hazardZone in hazardZones)
			{
				HazardZone value = hazardZone.Value;
				if (value.IsActive)
				{
					float num = Vector3.Distance(position, value.Position);
					bool flag = num <= value.Radius;
					if (flag && !value.PlayerInside)
					{
						value.PlayerInside = true;
						value.TimeEntered = Time.time;
						FrameworkEvents.RaiseHazardZoneEntered(value.Id, value.Position);
						TechtonicaFrameworkPlugin.LogDebug("EnvironmentModule: Player entered hazard zone '" + value.Id + "'");
						ApplyHazardEffect(value);
					}
					else if (!flag && value.PlayerInside)
					{
						value.PlayerInside = false;
						FrameworkEvents.RaiseHazardZoneExited(value.Id, value.Position);
						TechtonicaFrameworkPlugin.LogDebug("EnvironmentModule: Player exited hazard zone '" + value.Id + "'");
						RemoveHazardEffect(value);
					}
					if (value.PlayerInside && value.DamagePerSecond > 0f)
					{
						ApplyEnvironmentalDamage(value.DamagePerSecond * Time.deltaTime, value.Type);
					}
				}
			}
		}

		private void ApplyHazardEffect(HazardZone zone)
		{
			string id = "hazard_" + zone.Id;
			switch (zone.Type)
			{
			case HazardType.Toxic:
				ApplyStatusEffect(id, StatusEffectType.Poisoned, -1f, 0.1f);
				break;
			case HazardType.Radiation:
				ApplyStatusEffect(id, StatusEffectType.Irradiated, -1f, 0.2f);
				break;
			case HazardType.Fire:
				ApplyStatusEffect(id, StatusEffectType.Burning, -1f, 0.5f);
				break;
			case HazardType.Frost:
				ApplyStatusEffect(id, StatusEffectType.Frozen, -1f);
				break;
			}
		}

		private void RemoveHazardEffect(HazardZone zone)
		{
			string id = "hazard_" + zone.Id;
			RemoveStatusEffect(id);
		}

		private void ApplyEnvironmentalDamage(float damage, HazardType source)
		{
			TechtonicaFrameworkPlugin.LogDebug($"EnvironmentModule: Environmental damage {damage} from {source}");
		}

		public void ApplyStatusEffect(string id, StatusEffectType type, float duration, float damagePerSecond = 0f)
		{
			StatusEffect value = new StatusEffect
			{
				Id = id,
				Type = type,
				Duration = duration,
				TimeApplied = Time.time,
				DamagePerSecond = damagePerSecond,
				IsActive = true
			};
			activeEffects[id] = value;
			FrameworkEvents.RaiseStatusEffectApplied(id, duration);
			TechtonicaFrameworkPlugin.LogDebug($"EnvironmentModule: Applied status effect '{id}' ({type}) for {duration}s");
		}

		public void RemoveStatusEffect(string id)
		{
			if (activeEffects.Remove(id))
			{
				FrameworkEvents.RaiseStatusEffectRemoved(id);
				TechtonicaFrameworkPlugin.LogDebug("EnvironmentModule: Removed status effect '" + id + "'");
			}
		}

		public bool HasStatusEffect(string id)
		{
			return activeEffects.ContainsKey(id);
		}

		public bool HasStatusEffectType(StatusEffectType type)
		{
			foreach (StatusEffect value in activeEffects.Values)
			{
				if (value.Type == type && value.IsActive)
				{
					return true;
				}
			}
			return false;
		}

		public void ClearAllStatusEffects()
		{
			foreach (string item in new List<string>(activeEffects.Keys))
			{
				RemoveStatusEffect(item);
			}
		}

		private void ProcessStatusEffects()
		{
			List<string> list = new List<string>();
			float time = Time.time;
			foreach (KeyValuePair<string, StatusEffect> activeEffect in activeEffects)
			{
				StatusEffect value = activeEffect.Value;
				if (!value.IsActive)
				{
					continue;
				}
				if (value.Duration > 0f)
				{
					float num = time - value.TimeApplied;
					if (num >= value.Duration)
					{
						list.Add(activeEffect.Key);
						continue;
					}
				}
				if (value.DamagePerSecond > 0f)
				{
					TechtonicaFrameworkPlugin.LogDebug($"EnvironmentModule: Status effect '{value.Id}' dealing {value.DamagePerSecond * Time.deltaTime} damage");
				}
				ApplyEffectModifiers(value);
			}
			foreach (string item in list)
			{
				RemoveStatusEffect(item);
			}
		}

		private void ApplyEffectModifiers(StatusEffect effect)
		{
			switch (effect.Type)
			{
			}
		}

		public List<HazardZone> GetAllHazardZones()
		{
			return new List<HazardZone>(hazardZones.Values);
		}

		public List<StatusEffect> GetAllStatusEffects()
		{
			return new List<StatusEffect>(activeEffects.Values);
		}

		public bool IsPositionInHazard(Vector3 position, out HazardZone zone)
		{
			//IL_0029: 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)
			foreach (KeyValuePair<string, HazardZone> hazardZone in hazardZones)
			{
				HazardZone value = hazardZone.Value;
				if (value.IsActive && Vector3.Distance(position, value.Position) <= value.Radius)
				{
					zone = value;
					return true;
				}
			}
			zone = null;
			return false;
		}
	}
	public class HazardZone
	{
		public string Id;

		public Vector3 Position;

		public float Radius;

		public HazardType Type;

		public float DamagePerSecond;

		public bool IsActive;

		public bool PlayerInside;

		public float TimeEntered;
	}
	public class StatusEffect
	{
		public string Id;

		public StatusEffectType Type;

		public float Duration;

		public float TimeApplied;

		public float DamagePerSecond;

		public bool IsActive;
	}
	public enum HazardType
	{
		Generic,
		Toxic,
		Radiation,
		Fire,
		Frost,
		Electric,
		Corrosive
	}
	public enum StatusEffectType
	{
		None,
		Poisoned,
		Irradiated,
		Burning,
		Frozen,
		Electrified,
		Corroded,
		Haste,
		Slow,
		Regenerating
	}
}
namespace TechtonicaFramework.Core
{
	public static class FrameworkEvents
	{
		private static bool initialized;

		public static event Action OnFrameworkInitialized;

		public static event Action OnFrameworkShutdown;

		public static event Action<uint, float, float> OnMachineHealthChanged;

		public static event Action<uint> OnMachineDamaged;

		public static event Action<uint> OnMachineDestroyed;

		public static event Action<uint> OnMachineRepaired;

		public static event Action<string, Vector3> OnHazardZoneEntered;

		public static event Action<string, Vector3> OnHazardZoneExited;

		public static event Action<string, float> OnStatusEffectApplied;

		public static event Action<string> OnStatusEffectRemoved;

		public static event Action<string> OnDialogueStarted;

		public static event Action<string> OnDialogueEnded;

		public static event Action<string> OnQuestStarted;

		public static event Action<string> OnQuestCompleted;

		public static event Action<string> OnEquipmentEquipped;

		public static event Action<string> OnEquipmentUnequipped;

		public static event Action<string> OnVehicleEntered;

		public static event Action<string> OnVehicleExited;

		public static void Initialize()
		{
			if (!initialized)
			{
				Events.GameDefinesLoaded += OnGameDefinesLoaded;
				Events.GameLoaded += OnGameLoaded;
				Events.GameUnloaded += OnGameUnloaded;
				initialized = true;
				TechtonicaFrameworkPlugin.LogDebug("FrameworkEvents initialized");
			}
		}

		private static void OnGameDefinesLoaded()
		{
			TechtonicaFrameworkPlugin.LogDebug("Game defines loaded - framework ready");
			FrameworkEvents.OnFrameworkInitialized?.Invoke();
		}

		private static void OnGameLoaded()
		{
			TechtonicaFrameworkPlugin.LogDebug("Game loaded");
		}

		private static void OnGameUnloaded()
		{
			TechtonicaFrameworkPlugin.LogDebug("Game unloaded");
		}

		public static void Shutdown()
		{
			FrameworkEvents.OnFrameworkShutdown?.Invoke();
			initialized = false;
		}

		internal static void RaiseMachineHealthChanged(uint machineId, float oldHealth, float newHealth)
		{
			FrameworkEvents.OnMachineHealthChanged?.Invoke(machineId, oldHealth, newHealth);
		}

		internal static void RaiseMachineDamaged(uint machineId)
		{
			FrameworkEvents.OnMachineDamaged?.Invoke(machineId);
		}

		internal static void RaiseMachineDestroyed(uint machineId)
		{
			FrameworkEvents.OnMachineDestroyed?.Invoke(machineId);
		}

		internal static void RaiseMachineRepaired(uint machineId)
		{
			FrameworkEvents.OnMachineRepaired?.Invoke(machineId);
		}

		internal static void RaiseHazardZoneEntered(string hazardId, Vector3 position)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			FrameworkEvents.OnHazardZoneEntered?.Invoke(hazardId, position);
		}

		internal static void RaiseHazardZoneExited(string hazardId, Vector3 position)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			FrameworkEvents.OnHazardZoneExited?.Invoke(hazardId, position);
		}

		internal static void RaiseStatusEffectApplied(string effectId, float duration)
		{
			FrameworkEvents.OnStatusEffectApplied?.Invoke(effectId, duration);
		}

		internal static void RaiseStatusEffectRemoved(string effectId)
		{
			FrameworkEvents.OnStatusEffectRemoved?.Invoke(effectId);
		}

		internal static void RaiseDialogueStarted(string dialogueId)
		{
			FrameworkEvents.OnDialogueStarted?.Invoke(dialogueId);
		}

		internal static void RaiseDialogueEnded(string dialogueId)
		{
			FrameworkEvents.OnDialogueEnded?.Invoke(dialogueId);
		}

		internal static void RaiseQuestStarted(string questId)
		{
			FrameworkEvents.OnQuestStarted?.Invoke(questId);
		}

		internal static void RaiseQuestCompleted(string questId)
		{
			FrameworkEvents.OnQuestCompleted?.Invoke(questId);
		}

		internal static void RaiseEquipmentEquipped(string equipmentId)
		{
			FrameworkEvents.OnEquipmentEquipped?.Invoke(equipmentId);
		}

		internal static void RaiseEquipmentUnequipped(string equipmentId)
		{
			FrameworkEvents.OnEquipmentUnequipped?.Invoke(equipmentId);
		}

		internal static void RaiseVehicleEntered(string vehicleId)
		{
			FrameworkEvents.OnVehicleEntered?.Invoke(vehicleId);
		}

		internal static void RaiseVehicleExited(string vehicleId)
		{
			FrameworkEvents.OnVehicleExited?.Invoke(vehicleId);
		}
	}
	public interface IFrameworkModule
	{
		bool IsActive { get; }

		void Initialize();

		void Update();

		void Shutdown();
	}
}
namespace TechtonicaFramework.BuildMenu
{
	public static class BuildMenuModule
	{
		public const string MODDED_HEADER_NAME = "Modded";

		public const string MODDED_SUBHEADER_NAME = "Modded Items";

		public const int MODDED_HEADER_ORDER = 999;

		public const int MODDED_SUBHEADER_PRIORITY = 1;

		private static ManualLogSource log;

		private static bool initialized = false;

		private static SchematicsHeader moddedHeader;

		private static SchematicsSubHeader moddedSubHeader;

		private static HashSet<string> vanillaResourceNames = new HashSet<string>();

		public static SchematicsHeader ModdedHeader => moddedHeader;

		public static SchematicsSubHeader ModdedSubHeader => moddedSubHeader;

		public static void Initialize(ManualLogSource logger)
		{
			log = logger;
			Events.GameDefinesLoaded += OnGameDefinesLoaded;
			ManualLogSource obj = log;
			if (obj != null)
			{
				obj.LogInfo((object)"BuildMenuModule: Initialized - waiting for GameDefines");
			}
			initialized = true;
		}

		public static bool IsVanillaResource(string resourceName)
		{
			return vanillaResourceNames.Contains(resourceName);
		}

		public static void MoveToModdedTab(string resourceName)
		{
			if ((Object)(object)moddedSubHeader == (Object)null)
			{
				ManualLogSource obj = log;
				if (obj != null)
				{
					obj.LogWarning((object)("BuildMenuModule: Cannot move '" + resourceName + "' - Modded tab not ready"));
				}
				return;
			}
			try
			{
				Resources.UpdateResourceHeaderType(resourceName, moddedSubHeader, false);
				ManualLogSource obj2 = log;
				if (obj2 != null)
				{
					obj2.LogInfo((object)("BuildMenuModule: Moved '" + resourceName + "' to Modded tab"));
				}
			}
			catch (Exception ex)
			{
				ManualLogSource obj3 = log;
				if (obj3 != null)
				{
					obj3.LogError((object)("BuildMenuModule: Error moving '" + resourceName + "': " + ex.Message));
				}
			}
		}

		public static void MoveAllModdedItems()
		{
			if ((Object)(object)GameDefines.instance == (Object)null || (Object)(object)moddedSubHeader == (Object)null)
			{
				ManualLogSource obj = log;
				if (obj != null)
				{
					obj.LogWarning((object)"BuildMenuModule: Cannot move items - not ready");
				}
				return;
			}
			int num = 0;
			foreach (ResourceInfo resource in GameDefines.instance.resources)
			{
				if ((Object)(object)resource == (Object)null)
				{
					continue;
				}
				string displayName = resource.displayName;
				if (string.IsNullOrEmpty(displayName) || vanillaResourceNames.Contains(displayName) || (Object)(object)resource.headerType == (Object)(object)moddedSubHeader)
				{
					continue;
				}
				try
				{
					resource.headerType = moddedSubHeader;
					num++;
					ManualLogSource obj2 = log;
					if (obj2 != null)
					{
						obj2.LogInfo((object)("BuildMenuModule: Moved '" + displayName + "' to Modded tab"));
					}
				}
				catch (Exception ex)
				{
					ManualLogSource obj3 = log;
					if (obj3 != null)
					{
						obj3.LogError((object)("BuildMenuModule: Error moving '" + displayName + "': " + ex.Message));
					}
				}
			}
			ManualLogSource obj4 = log;
			if (obj4 != null)
			{
				obj4.LogInfo((object)$"BuildMenuModule: Moved {num} modded items to Modded tab");
			}
		}

		private static void OnGameDefinesLoaded()
		{
			try
			{
				CaptureVanillaResources();
				CreateModdedHeader();
				CreateModdedSubHeader();
				ManualLogSource obj = log;
				if (obj != null)
				{
					obj.LogInfo((object)"BuildMenuModule: Modded build menu tab created successfully");
				}
			}
			catch (Exception arg)
			{
				ManualLogSource obj2 = log;
				if (obj2 != null)
				{
					obj2.LogError((object)$"BuildMenuModule: Error in OnGameDefinesLoaded: {arg}");
				}
			}
		}

		private static void CaptureVanillaResources()
		{
			vanillaResourceNames.Clear();
			if (GameDefines.instance?.resources == null)
			{
				return;
			}
			foreach (ResourceInfo resource in GameDefines.instance.resources)
			{
				if ((Object)(object)resource != (Object)null && !string.IsNullOrEmpty(resource.displayName))
				{
					vanillaResourceNames.Add(resource.displayName);
				}
			}
			ManualLogSource obj = log;
			if (obj != null)
			{
				obj.LogInfo((object)$"BuildMenuModule: Captured {vanillaResourceNames.Count} vanilla resource names");
			}
		}

		private static void CreateModdedHeader()
		{
			if ((Object)(object)GameDefines.instance == (Object)null)
			{
				ManualLogSource obj = log;
				if (obj != null)
				{
					obj.LogError((object)"BuildMenuModule: GameDefines not available");
				}
				return;
			}
			foreach (SchematicsHeader schematicsHeaderEntry in GameDefines.instance.schematicsHeaderEntries)
			{
				if ((Object)(object)schematicsHeaderEntry != (Object)null && schematicsHeaderEntry.title == "Modded")
				{
					moddedHeader = schematicsHeaderEntry;
					ManualLogSource obj2 = log;
					if (obj2 != null)
					{
						obj2.LogInfo((object)"BuildMenuModule: Modded header already exists");
					}
					return;
				}
			}
			moddedHeader = ScriptableObject.CreateInstance<SchematicsHeader>();
			moddedHeader.title = "Modded";
			moddedHeader.order = 999;
			int num = 0;
			foreach (SchematicsHeader schematicsHeaderEntry2 in GameDefines.instance.schematicsHeaderEntries)
			{
				if ((Object)(object)schematicsHeaderEntry2 != (Object)null && ((UniqueIdScriptableObject)schematicsHeaderEntry2).uniqueId > num)
				{
					num = ((UniqueIdScriptableObject)schematicsHeaderEntry2).uniqueId;
				}
			}
			FieldInfo field = typeof(UniqueIdScriptableObject).GetField("uniqueId", BindingFlags.Instance | BindingFlags.Public);
			if (field != null)
			{
				field.SetValue(moddedHeader, num + 1);
			}
			GameDefines.instance.schematicsHeaderEntries.Add(moddedHeader);
			ManualLogSource obj3 = log;
			if (obj3 != null)
			{
				obj3.LogInfo((object)$"BuildMenuModule: Created Modded header with ID {((UniqueIdScriptableObject)moddedHeader).uniqueId}");
			}
		}

		private static void CreateModdedSubHeader()
		{
			if ((Object)(object)GameDefines.instance == (Object)null || (Object)(object)moddedHeader == (Object)null)
			{
				ManualLogSource obj = log;
				if (obj != null)
				{
					obj.LogError((object)"BuildMenuModule: Cannot create subheader - prerequisites missing");
				}
				return;
			}
			foreach (SchematicsSubHeader schematicsSubHeaderEntry in GameDefines.instance.schematicsSubHeaderEntries)
			{
				if ((Object)(object)schematicsSubHeaderEntry != (Object)null && schematicsSubHeaderEntry.title == "Modded Items" && (Object)(object)schematicsSubHeaderEntry.filterTag == (Object)(object)moddedHeader)
				{
					moddedSubHeader = schematicsSubHeaderEntry;
					ManualLogSource obj2 = log;
					if (obj2 != null)
					{
						obj2.LogInfo((object)"BuildMenuModule: Modded subheader already exists");
					}
					return;
				}
			}
			moddedSubHeader = ScriptableObject.CreateInstance<SchematicsSubHeader>();
			moddedSubHeader.title = "Modded Items";
			moddedSubHeader.filterTag = moddedHeader;
			moddedSubHeader.priority = 1;
			int num = 0;
			foreach (SchematicsSubHeader schematicsSubHeaderEntry2 in GameDefines.instance.schematicsSubHeaderEntries)
			{
				if ((Object)(object)schematicsSubHeaderEntry2 != (Object)null && ((UniqueIdScriptableObject)schematicsSubHeaderEntry2).uniqueId > num)
				{
					num = ((UniqueIdScriptableObject)schematicsSubHeaderEntry2).uniqueId;
				}
			}
			FieldInfo field = typeof(UniqueIdScriptableObject).GetField("uniqueId", BindingFlags.Instance | BindingFlags.Public);
			if (field != null)
			{
				field.SetValue(moddedSubHeader, num + 1);
			}
			GameDefines.instance.schematicsSubHeaderEntries.Add(moddedSubHeader);
			ManualLogSource obj3 = log;
			if (obj3 != null)
			{
				obj3.LogInfo((object)$"BuildMenuModule: Created Modded subheader with ID {((UniqueIdScriptableObject)moddedSubHeader).uniqueId}");
			}
		}
	}
}
namespace TechtonicaFramework.API
{
	public static class FrameworkAPI
	{
		public static void RegisterMachineHealth(uint machineId, float maxHealth = 100f)
		{
			TechtonicaFrameworkPlugin.HealthModule?.RegisterMachine(machineId, maxHealth);
		}

		public static void DamageMachine(uint machineId, float damage, DamageType type = DamageType.Generic)
		{
			TechtonicaFrameworkPlugin.HealthModule?.DamageMachine(machineId, damage, type);
		}

		public static void HealMachine(uint machineId, float amount)
		{
			TechtonicaFrameworkPlugin.HealthModule?.HealMachine(machineId, amount);
		}

		public static float GetMachineHealthPercent(uint machineId)
		{
			return TechtonicaFrameworkPlugin.HealthModule?.GetHealthPercent(machineId) ?? 1f;
		}

		public static bool IsMachineAlive(uint machineId)
		{
			return TechtonicaFrameworkPlugin.HealthModule?.IsMachineAlive(machineId) ?? true;
		}

		public static void StartMachineRepair(uint machineId)
		{
			TechtonicaFrameworkPlugin.HealthModule?.StartRepair(machineId);
		}

		public static void StopMachineRepair(uint machineId)
		{
			TechtonicaFrameworkPlugin.HealthModule?.StopRepair(machineId);
		}

		public static void FullRepairMachine(uint machineId)
		{
			TechtonicaFrameworkPlugin.HealthModule?.FullRepair(machineId);
		}

		public static List<uint> GetDamagedMachines(float threshold = 1f)
		{
			return TechtonicaFrameworkPlugin.HealthModule?.GetDamagedMachines(threshold) ?? new List<uint>();
		}

		public static void CreateHazardZone(string id, Vector3 position, float radius, HazardType type, float damagePerSecond = 5f)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			TechtonicaFrameworkPlugin.EnvironmentModule?.CreateHazardZone(id, position, radius, type, damagePerSecond);
		}

		public static void RemoveHazardZone(string id)
		{
			TechtonicaFrameworkPlugin.EnvironmentModule?.RemoveHazardZone(id);
		}

		public static void ApplyStatusEffect(string id, StatusEffectType type, float duration, float damagePerSecond = 0f)
		{
			TechtonicaFrameworkPlugin.EnvironmentModule?.ApplyStatusEffect(id, type, duration, damagePerSecond);
		}

		public static void RemoveStatusEffect(string id)
		{
			TechtonicaFrameworkPlugin.EnvironmentModule?.RemoveStatusEffect(id);
		}

		public static bool HasStatusEffect(string id)
		{
			return TechtonicaFrameworkPlugin.EnvironmentModule?.HasStatusEffect(id) ?? false;
		}

		public static void ClearAllStatusEffects()
		{
			TechtonicaFrameworkPlugin.EnvironmentModule?.ClearAllStatusEffects();
		}

		public static void RegisterSpeaker(string id, string displayName, Color textColor, Sprite portrait = null)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			TechtonicaFrameworkPlugin.NarrativeModule?.RegisterSpeaker(id, displayName, textColor, portrait);
		}

		public static void RegisterDialogue(string id, string speakerId, string text, float duration = 5f)
		{
			TechtonicaFrameworkPlugin.NarrativeModule?.RegisterDialogue(id, speakerId, text, duration);
		}

		public static void ChainDialogue(string dialogueId, string nextDialogueId)
		{
			TechtonicaFrameworkPlugin.NarrativeModule?.ChainDialogue(dialogueId, nextDialogueId);
		}

		public static void TriggerDialogue(string dialogueId)
		{
			TechtonicaFrameworkPlugin.NarrativeModule?.TriggerDialogue(dialogueId);
		}

		public static bool HasDialoguePlayed(string dialogueId)
		{
			return TechtonicaFrameworkPlugin.NarrativeModule?.HasDialoguePlayed(dialogueId) ?? false;
		}

		public static DialogueSequenceBuilder CreateDialogueSequence(string sequenceId)
		{
			return TechtonicaFrameworkPlugin.NarrativeModule?.CreateSequence(sequenceId);
		}

		public static void RegisterEquipment(string id, string displayName, string description, EquipmentSlot slot, Action<Player> onEquip = null, Action<Player> onUnequip = null, Action<Player> onUse = null)
		{
			TechtonicaFrameworkPlugin.EquipmentModule?.RegisterEquipment(id, displayName, description, slot, onEquip, onUnequip, onUse);
		}

		public static void ApplyMovementModifier(string id, float speedMultiplier = 1f, float jumpMultiplier = 1f, float duration = -1f)
		{
			TechtonicaFrameworkPlugin.EquipmentModule?.ApplyMovementModifier(id, speedMultiplier, jumpMultiplier, duration);
		}

		public static void RemoveMovementModifier(string id)
		{
			TechtonicaFrameworkPlugin.EquipmentModule?.RemoveMovementModifier(id);
		}

		public static void CreateSpeedZone(string id, Vector3 position, float radius, float speedMultiplier)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			TechtonicaFrameworkPlugin.EquipmentModule?.CreateSpeedZone(id, position, radius, speedMultiplier);
		}

		public static void RegisterVehicle(string id, string displayName, float maxSpeed, Action<Player> onEnter = null, Action<Player> onExit = null)
		{
			TechtonicaFrameworkPlugin.EquipmentModule?.RegisterVehicle(id, displayName, maxSpeed, onEnter, onExit);
		}

		public static bool IsFrameworkReady()
		{
			return (Object)(object)TechtonicaFrameworkPlugin.Instance != (Object)null;
		}

		public static string GetFrameworkVersion()
		{
			return "1.2.0";
		}

		public static bool IsModuleEnabled(string moduleName)
		{
			string text = moduleName.ToLower();
			if (1 == 0)
			{
			}
			bool result = text switch
			{
				"health" => TechtonicaFrameworkPlugin.HealthModule?.IsActive ?? false, 
				"environment" => TechtonicaFrameworkPlugin.EnvironmentModule?.IsActive ?? false, 
				"narrative" => TechtonicaFrameworkPlugin.NarrativeModule?.IsActive ?? false, 
				"equipment" => TechtonicaFrameworkPlugin.EquipmentModule?.IsActive ?? false, 
				_ => false, 
			};
			if (1 == 0)
			{
			}
			return result;
		}
	}
}