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;
}
}
}