Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of WispTorchHeeler v1.1.0
WispTorchHeeler.dll
Decompiled 6 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ConditionalConfigSync; using HarmonyLib; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.SceneManagement; using WispTorchHeeler.Configuration; using WispTorchHeeler.Lighting; using WispTorchHeeler.Localization; using WispTorchHeeler.Painter; using WispTorchHeeler.Pieces; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("WispTorchHeeler")] [assembly: AssemblyDescription("Tiered Mistlands wisp torches and lamps with expanded mist clearance, interactive torch painting, and multiplayer color synchronization. For more information, visit https://github.com/dreamwraith")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("dreamwraith (https://github.com/dreamwraith)")] [assembly: AssemblyProduct("WispTorchHeeler")] [assembly: AssemblyCopyright("Copyright © 2026 dreamwraith")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("e8288be6-ca15-429d-9002-de73aa3f3ba7")] [assembly: AssemblyFileVersion("1.1.0")] [assembly: AssemblyInformationalVersion("1.1.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace WispTorchHeeler { [BepInPlugin("dreamwraith.WispTorchHeeler", "WispTorchHeeler", "1.1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string ModGUID = "dreamwraith.WispTorchHeeler"; public const string ModName = "WispTorchHeeler"; public const string ModVersion = "1.1.0"; internal static ManualLogSource Log; private Harmony? _harmony; internal static Plugin? Instance { get; private set; } private void Awake() { Instance = this; Log = ((BaseUnityPlugin)this).Logger; ModConfig.Initialize(((BaseUnityPlugin)this).Config); if (!ModConfig.EnableMod.Value) { Log.LogInfo((object)"WispTorchHeeler is disabled in configuration."); return; } ModLocalization.Initialize(); WispPieceManager.Initialize(); ModConfig.EnableMod.SettingChanged += delegate { WispTorchColorController.RefreshAll(); }; ModConfig.DefaultLightColor.SettingChanged += delegate { WispTorchColorController.RefreshAll(); }; ModConfig.ServerDefaultLightColor.SettingChanged += delegate { WispTorchColorController.RefreshAll(); }; ModConfig.EnforceServerDefaultColor.SettingChanged += delegate { WispTorchColorController.RefreshAll(); }; ModConfig.AffectNativeMistTorches.SettingChanged += delegate { WispTorchColorController.RefreshAll(); }; ModConfig.EnableAlphaCustomization.SettingChanged += delegate { WispTorchColorController.RefreshAll(); }; ModConfig.ShowMistSuppressionRadius.SettingChanged += delegate { WispTorchColorController.RefreshAllMarkers(); }; _harmony = Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "dreamwraith.WispTorchHeeler"); Log.LogInfo((object)"WispTorchHeeler v1.1.0 loaded successfully."); } private void Update() { if (ModConfig.EnableMod.Value && !((Object)(object)Player.m_localPlayer == (Object)null)) { if (ModConfig.ButtonResetConfig != null && ZInput.GetButtonDown(ModConfig.ButtonResetConfig.Name)) { TorchPainter.TryPaintOrReset(isReset: true); } else if (ModConfig.ButtonPaintConfig != null && ZInput.GetButtonDown(ModConfig.ButtonPaintConfig.Name)) { TorchPainter.TryPaintOrReset(isReset: false); } } } private void OnDestroy() { Harmony? harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } internal static void LogDebug(string message) { if (ModConfig.EnableDebugLogs != null && ModConfig.EnableDebugLogs.Value) { Log.LogInfo((object)("[DEBUG] " + message)); } } } internal static class VersionInfo { public const string Version = "1.1.0"; } } namespace WispTorchHeeler.Pieces { public static class WispPieceManager { public class PieceBaseStats { public float BaseHealth; public float[] ForceFieldStartRanges = Array.Empty<float>(); public float[] ForceFieldEndRanges = Array.Empty<float>(); public float[] LightIntensities = Array.Empty<float>(); public float[] LightRanges = Array.Empty<float>(); } public const string Tier1TorchPrefab = "piece_wisptorch_heeler_lg"; public const string Tier2SmallLampPrefab = "piece_wisplamp_heeler"; public const string Tier3LargeLampPrefab = "piece_wisplamp_heeler_lg"; public const string Tier4GrandLampPrefab = "piece_wisplamp_heeler_grand"; public const string NativeMistTorchPrefab = "piece_groundtorch_mist"; public const string NativeWallTorchPrefab = "piece_walltorch"; public const string NativeDvergrLanternPrefab = "piece_dvergr_lantern"; public const string NativeDemisterPrefab = "dverger_demister"; public const string NativeDemisterLargePrefab = "dverger_demister_large"; public const float NativePlayerBaseRadius = 20f; public const float NativeMistClearRadius = 24f; public const float NativeLightRange = 10f; private static bool s_piecesRegistered; public static readonly Dictionary<string, PieceBaseStats> BaseStats = new Dictionary<string, PieceBaseStats>(); private static GameObject? s_areaMarkerTemplate; public static GameObject? AreaMarkerTemplate { get { if ((Object)(object)s_areaMarkerTemplate == (Object)null) { GameObject val = ((PrefabManager.Instance != null) ? PrefabManager.Instance.GetPrefab("guard_stone") : (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab("guard_stone") : null)); if ((Object)(object)val != (Object)null) { PrivateArea component = val.GetComponent<PrivateArea>(); if ((Object)(object)component != (Object)null && (Object)(object)component.m_areaMarker != (Object)null) { s_areaMarkerTemplate = ((Component)component.m_areaMarker).gameObject; } } if ((Object)(object)s_areaMarkerTemplate == (Object)null) { GameObject val2 = ((PrefabManager.Instance != null) ? PrefabManager.Instance.GetPrefab("piece_workbench") : (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab("piece_workbench") : null)); if ((Object)(object)val2 != (Object)null) { CraftingStation component2 = val2.GetComponent<CraftingStation>(); if ((Object)(object)component2 != (Object)null && (Object)(object)component2.m_areaMarker != (Object)null) { s_areaMarkerTemplate = component2.m_areaMarker; } } } } return s_areaMarkerTemplate; } } public static void Initialize() { PrefabManager.OnVanillaPrefabsAvailable += RegisterCustomPieces; PieceManager.OnPiecesRegistered += OnPiecesRegistered; ModConfig.Torch_Recipe.SettingChanged += delegate { UpdatePieceConfiguration("piece_wisptorch_heeler_lg"); }; ModConfig.Torch_CraftingStation.SettingChanged += delegate { UpdatePieceConfiguration("piece_wisptorch_heeler_lg"); }; ModConfig.Torch_Health.SettingChanged += delegate { UpdatePieceConfiguration("piece_wisptorch_heeler_lg"); }; ModConfig.Torch_MistClearRangeMultiplier.SettingChanged += delegate { UpdatePieceConfiguration("piece_wisptorch_heeler_lg"); }; ModConfig.Torch_LightIntensityMultiplier.SettingChanged += delegate { UpdatePieceConfiguration("piece_wisptorch_heeler_lg"); }; ModConfig.Torch_LightRangeMultiplier.SettingChanged += delegate { UpdatePieceConfiguration("piece_wisptorch_heeler_lg"); }; ModConfig.SmallLamp_Recipe.SettingChanged += delegate { UpdatePieceConfiguration("piece_wisplamp_heeler"); }; ModConfig.SmallLamp_CraftingStation.SettingChanged += delegate { UpdatePieceConfiguration("piece_wisplamp_heeler"); }; ModConfig.SmallLamp_Health.SettingChanged += delegate { UpdatePieceConfiguration("piece_wisplamp_heeler"); }; ModConfig.SmallLamp_MistClearRangeMultiplier.SettingChanged += delegate { UpdatePieceConfiguration("piece_wisplamp_heeler"); }; ModConfig.SmallLamp_LightIntensityMultiplier.SettingChanged += delegate { UpdatePieceConfiguration("piece_wisplamp_heeler"); }; ModConfig.SmallLamp_LightRangeMultiplier.SettingChanged += delegate { UpdatePieceConfiguration("piece_wisplamp_heeler"); }; ModConfig.LargeLamp_Recipe.SettingChanged += delegate { UpdatePieceConfiguration("piece_wisplamp_heeler_lg"); }; ModConfig.LargeLamp_CraftingStation.SettingChanged += delegate { UpdatePieceConfiguration("piece_wisplamp_heeler_lg"); }; ModConfig.LargeLamp_Health.SettingChanged += delegate { UpdatePieceConfiguration("piece_wisplamp_heeler_lg"); }; ModConfig.LargeLamp_MistClearRangeMultiplier.SettingChanged += delegate { UpdatePieceConfiguration("piece_wisplamp_heeler_lg"); }; ModConfig.LargeLamp_LightIntensityMultiplier.SettingChanged += delegate { UpdatePieceConfiguration("piece_wisplamp_heeler_lg"); }; ModConfig.LargeLamp_LightRangeMultiplier.SettingChanged += delegate { UpdatePieceConfiguration("piece_wisplamp_heeler_lg"); }; ModConfig.GrandLamp_Recipe.SettingChanged += delegate { UpdatePieceConfiguration("piece_wisplamp_heeler_grand"); }; ModConfig.GrandLamp_CraftingStation.SettingChanged += delegate { UpdatePieceConfiguration("piece_wisplamp_heeler_grand"); }; ModConfig.GrandLamp_Health.SettingChanged += delegate { UpdatePieceConfiguration("piece_wisplamp_heeler_grand"); }; ModConfig.GrandLamp_MistClearRangeMultiplier.SettingChanged += delegate { UpdatePieceConfiguration("piece_wisplamp_heeler_grand"); }; ModConfig.GrandLamp_LightIntensityMultiplier.SettingChanged += delegate { UpdatePieceConfiguration("piece_wisplamp_heeler_grand"); }; ModConfig.GrandLamp_LightRangeMultiplier.SettingChanged += delegate { UpdatePieceConfiguration("piece_wisplamp_heeler_grand"); }; ModConfig.PlayerBaseMistRadiusBonus.SettingChanged += delegate { UpdateAllPieceConfigurations(); }; Plugin.LogDebug("[PieceManager] Subscribed to native prefab, piece lifecycle, and config property events."); } private static void RegisterCustomPieces() { //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: 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_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_0248: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) if (s_piecesRegistered) { return; } s_piecesRegistered = true; Plugin.LogDebug("[PieceManager] RegisterCustomPieces triggered."); GameObject prefab = PrefabManager.Instance.GetPrefab("piece_groundtorch_mist"); if ((Object)(object)prefab != (Object)null) { if ((Object)(object)prefab.GetComponent<WispTorchColorController>() == (Object)null) { prefab.AddComponent<WispTorchColorController>(); Plugin.LogDebug("[PieceManager] Injected WispTorchColorController into native prefab 'piece_groundtorch_mist'."); } EnsurePieceCollider(prefab, new Vector3(0f, 0.025f, 0f), new Vector3(0.25f, 1.35f, 0.25f)); } else { Plugin.Log.LogWarning((object)"[PieceManager] Native prefab 'piece_groundtorch_mist' not found for controller injection."); } RegisterPiece("piece_wisptorch_heeler_lg", "piece_groundtorch_mist", "$piece_wisptorch_heeler_lg", "$piece_wisptorch_heeler_lg_description", 1.25f, ModConfig.Torch_Recipe.Value, (string)((ConfigEntryBase)ModConfig.Torch_Recipe).DefaultValue, ModConfig.Torch_CraftingStation.Value, new Vector3(0f, 0.025f, 0f), new Vector3(0.25f, 1.35f, 0.25f)); RegisterPiece("piece_wisplamp_heeler", "dverger_demister", "$piece_wisplamp_heeler", "$piece_wisplamp_heeler_description", 1f, ModConfig.SmallLamp_Recipe.Value, (string)((ConfigEntryBase)ModConfig.SmallLamp_Recipe).DefaultValue, ModConfig.SmallLamp_CraftingStation.Value, new Vector3(0f, -0.1f, 0f), new Vector3(0.26f, 1.1f, 0.26f), "piece_walltorch", "piece_dvergr_lantern"); RegisterPiece("piece_wisplamp_heeler_lg", "dverger_demister_large", "$piece_wisplamp_heeler_lg", "$piece_wisplamp_heeler_lg_description", 1.1f, ModConfig.LargeLamp_Recipe.Value, (string)((ConfigEntryBase)ModConfig.LargeLamp_Recipe).DefaultValue, ModConfig.LargeLamp_CraftingStation.Value, new Vector3(0f, -0.18f, 0f), new Vector3(0.32f, 1.45f, 0.32f), "piece_walltorch", "piece_dvergr_lantern"); RegisterPiece("piece_wisplamp_heeler_grand", "dverger_demister_large", "$piece_wisplamp_heeler_grand", "$piece_wisplamp_heeler_grand_description", 1.5f, ModConfig.GrandLamp_Recipe.Value, (string)((ConfigEntryBase)ModConfig.GrandLamp_Recipe).DefaultValue, ModConfig.GrandLamp_CraftingStation.Value, new Vector3(0f, -0.18f, 0f), new Vector3(0.32f, 1.45f, 0.32f), "piece_walltorch", "piece_dvergr_lantern"); PrefabManager.OnVanillaPrefabsAvailable -= RegisterCustomPieces; } private static void RegisterPiece(string customPrefabName, string basePrefabName, string nameToken, string descriptionToken, float scaleFactor, string recipeString, string defaultRecipeString, string stationString, in Vector3 colliderCenter, in Vector3 colliderSize, string? placeEffectSource = null, string? wearEffectSource = null) { //IL_0479: Unknown result type (might be due to invalid IL or missing references) //IL_0480: Expected O, but got Unknown //IL_04de: Unknown result type (might be due to invalid IL or missing references) //IL_04e5: Expected O, but got Unknown //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Unknown result type (might be due to invalid IL or missing references) if (!TryParseAndValidateRecipe(recipeString, customPrefabName, out RequirementConfig[] requirements)) { Plugin.Log.LogError((object)("[PieceManager] Config recipe for piece '" + customPrefabName + "' is invalid ('" + recipeString + "'). Falling back to default recipe: '" + defaultRecipeString + "'.")); if (!TryParseAndValidateRecipe(defaultRecipeString, customPrefabName, out requirements)) { Plugin.Log.LogError((object)("[PieceManager] Default recipe for piece '" + customPrefabName + "' is also invalid ('" + defaultRecipeString + "'). Aborting piece registration.")); return; } } GameObject val = PrefabManager.Instance.CreateClonedPrefab(customPrefabName, basePrefabName); if ((Object)(object)val == (Object)null) { Plugin.Log.LogError((object)("[PieceManager] Failed to clone prefab '" + basePrefabName + "' as '" + customPrefabName + "'.")); return; } ParticleSystemForceField[] componentsInChildren = val.GetComponentsInChildren<ParticleSystemForceField>(true); Light[] componentsInChildren2 = val.GetComponentsInChildren<Light>(true); WearNTear component = val.GetComponent<WearNTear>(); PieceBaseStats pieceBaseStats = new PieceBaseStats { BaseHealth = (((Object)(object)component != (Object)null) ? component.m_health : 100f), ForceFieldStartRanges = new float[componentsInChildren.Length], ForceFieldEndRanges = new float[componentsInChildren.Length], LightIntensities = new float[componentsInChildren2.Length], LightRanges = new float[componentsInChildren2.Length] }; for (int i = 0; i < componentsInChildren.Length; i++) { pieceBaseStats.ForceFieldStartRanges[i] = componentsInChildren[i].startRange; pieceBaseStats.ForceFieldEndRanges[i] = 24f; } for (int j = 0; j < componentsInChildren2.Length; j++) { pieceBaseStats.LightIntensities[j] = componentsInChildren2[j].intensity; pieceBaseStats.LightRanges[j] = 10f; } BaseStats[customPrefabName] = pieceBaseStats; if (Mathf.Abs(scaleFactor - 1f) > 0.001f) { val.transform.localScale = val.transform.localScale * scaleFactor; Plugin.LogDebug($"[PieceManager] Scaled '{customPrefabName}' by {scaleFactor}x."); } if ((Object)(object)val.GetComponent<ZNetView>() == (Object)null) { val.AddComponent<ZNetView>().m_syncInitialScale = true; } Piece val2 = val.GetComponent<Piece>(); if ((Object)(object)val2 == (Object)null) { val2 = val.AddComponent<Piece>(); } val2.m_name = nameToken; val2.m_description = descriptionToken; val2.m_canBeRemoved = true; val2.m_category = (PieceCategory)0; HoverText val3 = val.GetComponent<HoverText>(); if ((Object)(object)val3 == (Object)null) { val3 = val.AddComponent<HoverText>(); } val3.m_text = nameToken; if (!string.IsNullOrEmpty(placeEffectSource)) { GameObject prefab = PrefabManager.Instance.GetPrefab(placeEffectSource); Piece val4 = ((prefab != null) ? prefab.GetComponent<Piece>() : null); if ((Object)(object)val4 != (Object)null && val4.m_placeEffect != null) { val2.m_placeEffect = val4.m_placeEffect; } } if ((Object)(object)val2.m_icon == (Object)null) { GameObject prefab2 = PrefabManager.Instance.GetPrefab("piece_groundtorch_mist"); Piece val5 = (((Object)(object)prefab2 != (Object)null) ? prefab2.GetComponent<Piece>() : null); if ((Object)(object)val5 != (Object)null && (Object)(object)val5.m_icon != (Object)null) { val2.m_icon = val5.m_icon; } } try { Sprite val6 = RenderManager.Instance.Render(val); if ((Object)(object)val6 != (Object)null) { val2.m_icon = val6; Plugin.LogDebug("[PieceManager] Generated custom 3D snapshot icon for '" + customPrefabName + "'."); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[PieceManager] Failed to render 3D icon for '" + customPrefabName + "': " + ex.Message)); } WearNTear val7 = val.GetComponent<WearNTear>(); if ((Object)(object)val7 == (Object)null) { val7 = val.AddComponent<WearNTear>(); } val7.m_noRoofWear = true; val7.m_noSupportWear = true; if (!string.IsNullOrEmpty(wearEffectSource)) { GameObject prefab3 = PrefabManager.Instance.GetPrefab(wearEffectSource); WearNTear val8 = ((prefab3 != null) ? prefab3.GetComponent<WearNTear>() : null); if ((Object)(object)val8 != (Object)null) { val7.m_hitEffect = val8.m_hitEffect; val7.m_destroyedEffect = val8.m_destroyedEffect; } } int num = LayerMask.NameToLayer("piece"); if (num >= 0) { val.layer = num; Collider[] componentsInChildren3 = val.GetComponentsInChildren<Collider>(true); foreach (Collider val9 in componentsInChildren3) { if (!val9.isTrigger) { ((Component)val9).gameObject.layer = num; } } } EnsurePieceCollider(val, in colliderCenter, in colliderSize); EnsurePlayerBase(val); ApplyProperties(val, customPrefabName); if ((Object)(object)val.GetComponent<WispTorchColorController>() == (Object)null) { val.AddComponent<WispTorchColorController>(); } PieceConfig val10 = new PieceConfig(); val10.Name = nameToken; val10.Description = descriptionToken; val10.PieceTable = PieceTables.Hammer; val10.Category = PieceCategories.Misc; val10.Usage = new string[2] { PieceUsages.Lighting, PieceUsages.Misc }; val10.CraftingStation = stationString; val10.Requirements = requirements; PieceConfig val11 = val10; CustomPiece val12 = new CustomPiece(val, true, val11); PieceManager.Instance.AddPiece(val12); Plugin.LogDebug("[PieceManager] Successfully registered CustomPiece '" + customPrefabName + "' in Hammer (Category=Misc, Usages=Lighting,Misc)."); } private static void OnPiecesRegistered() { Plugin.LogDebug("[PieceManager] OnPiecesRegistered triggered. Updating piece recipes and stations."); UpdateAllPieceConfigurations(); } public static void UpdateAllPieceConfigurations() { UpdatePieceConfiguration("piece_wisptorch_heeler_lg"); UpdatePieceConfiguration("piece_wisplamp_heeler"); UpdatePieceConfiguration("piece_wisplamp_heeler_lg"); UpdatePieceConfiguration("piece_wisplamp_heeler_grand"); } public static void UpdatePieceConfiguration(string prefabName) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: 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_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Expected O, but got Unknown Scene activeScene = SceneManager.GetActiveScene(); if (((Scene)(ref activeScene)).name != "main") { string[] obj = new string[5] { "[PieceManager] Active scene is '", null, null, null, null }; activeScene = SceneManager.GetActiveScene(); obj[1] = ((Scene)(ref activeScene)).name; obj[2] = "'. Deferring piece update for '"; obj[3] = prefabName; obj[4] = "' until game world loads."; Plugin.LogDebug(string.Concat(obj)); return; } CustomPiece piece = PieceManager.Instance.GetPiece(prefabName); if (piece == null || (Object)(object)piece.PiecePrefab == (Object)null) { Plugin.LogDebug("[PieceManager] CustomPiece '" + prefabName + "' not found in PieceManager registry for config update."); } else { if (!TryGetPieceConfig(prefabName, out string recipeString, out string stationString, out float _, out float _, out float _, out float _)) { return; } Piece component = piece.PiecePrefab.GetComponent<Piece>(); if (TryParseAndValidateRecipe(recipeString, prefabName, out RequirementConfig[] requirements)) { List<Requirement> list = new List<Requirement>(); RequirementConfig[] array = requirements; foreach (RequirementConfig val in array) { GameObject prefab = PrefabManager.Instance.GetPrefab(val.Item); ItemDrop val2 = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<ItemDrop>() : null); if ((Object)(object)val2 != (Object)null) { list.Add(new Requirement { m_resItem = val2, m_amount = val.Amount, m_amountPerLevel = val.AmountPerLevel, m_recover = val.Recover }); } else { Plugin.Log.LogError((object)("[PieceManager] Could not resolve ItemDrop for requirement '" + val.Item + "' on piece '" + prefabName + "'.")); } } if ((Object)(object)component != (Object)null) { component.m_resources = list.ToArray(); } } else { Plugin.Log.LogError((object)("[PieceManager] Rejecting recipe update for piece '" + prefabName + "' due to validation errors. Keeping existing recipe.")); } if ((Object)(object)component != (Object)null) { string internalName = CraftingStations.GetInternalName(stationString); if (string.IsNullOrEmpty(internalName) || internalName.Equals("None", StringComparison.OrdinalIgnoreCase)) { component.m_craftingStation = null; } else { GameObject prefab2 = PrefabManager.Instance.GetPrefab(internalName); if ((Object)(object)prefab2 != (Object)null) { component.m_craftingStation = prefab2.GetComponent<CraftingStation>(); } else { Plugin.Log.LogWarning((object)("[PieceManager] Crafting station prefab '" + internalName + "' not found for piece '" + prefabName + "'.")); component.m_craftingStation = null; } } } ApplyProperties(piece.PiecePrefab, prefabName); WispTorchColorController.RefreshPropertiesForPrefab(prefabName); if ((Object)(object)Player.m_localPlayer != (Object)null) { Player.m_localPlayer.UpdateKnownRecipesList(); Player.m_localPlayer.UpdateAvailablePiecesList(); } Plugin.LogDebug("[PieceManager] Updated '" + prefabName + "' configuration in real time."); } } public static bool TryGetPieceConfig(string prefabName, out string recipeString, out string stationString, out float health, out float mistClearRangeMultiplier, out float lightIntensityMultiplier, out float lightRangeMultiplier) { switch (prefabName) { case "piece_wisptorch_heeler_lg": recipeString = ModConfig.Torch_Recipe.Value; stationString = ModConfig.Torch_CraftingStation.Value; health = ModConfig.Torch_Health.Value; mistClearRangeMultiplier = ModConfig.Torch_MistClearRangeMultiplier.Value; lightIntensityMultiplier = ModConfig.Torch_LightIntensityMultiplier.Value; lightRangeMultiplier = ModConfig.Torch_LightRangeMultiplier.Value; return true; case "piece_wisplamp_heeler": recipeString = ModConfig.SmallLamp_Recipe.Value; stationString = ModConfig.SmallLamp_CraftingStation.Value; health = ModConfig.SmallLamp_Health.Value; mistClearRangeMultiplier = ModConfig.SmallLamp_MistClearRangeMultiplier.Value; lightIntensityMultiplier = ModConfig.SmallLamp_LightIntensityMultiplier.Value; lightRangeMultiplier = ModConfig.SmallLamp_LightRangeMultiplier.Value; return true; case "piece_wisplamp_heeler_lg": recipeString = ModConfig.LargeLamp_Recipe.Value; stationString = ModConfig.LargeLamp_CraftingStation.Value; health = ModConfig.LargeLamp_Health.Value; mistClearRangeMultiplier = ModConfig.LargeLamp_MistClearRangeMultiplier.Value; lightIntensityMultiplier = ModConfig.LargeLamp_LightIntensityMultiplier.Value; lightRangeMultiplier = ModConfig.LargeLamp_LightRangeMultiplier.Value; return true; case "piece_wisplamp_heeler_grand": recipeString = ModConfig.GrandLamp_Recipe.Value; stationString = ModConfig.GrandLamp_CraftingStation.Value; health = ModConfig.GrandLamp_Health.Value; mistClearRangeMultiplier = ModConfig.GrandLamp_MistClearRangeMultiplier.Value; lightIntensityMultiplier = ModConfig.GrandLamp_LightIntensityMultiplier.Value; lightRangeMultiplier = ModConfig.GrandLamp_LightRangeMultiplier.Value; return true; default: recipeString = string.Empty; stationString = string.Empty; health = 100f; mistClearRangeMultiplier = 1f; lightIntensityMultiplier = 1f; lightRangeMultiplier = 1f; return false; } } public static void ApplyProperties(GameObject targetGameObject, string prefabName) { //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)targetGameObject == (Object)null || !BaseStats.TryGetValue(prefabName, out PieceBaseStats value) || !TryGetPieceConfig(prefabName, out string _, out string _, out float health, out float mistClearRangeMultiplier, out float lightIntensityMultiplier, out float lightRangeMultiplier)) { return; } ParticleSystemForceField[] componentsInChildren = targetGameObject.GetComponentsInChildren<ParticleSystemForceField>(true); for (int i = 0; i < componentsInChildren.Length && i < value.ForceFieldStartRanges.Length; i++) { componentsInChildren[i].startRange = value.ForceFieldStartRanges[i] * mistClearRangeMultiplier; componentsInChildren[i].endRange = value.ForceFieldEndRanges[i] * mistClearRangeMultiplier; } Light[] componentsInChildren2 = targetGameObject.GetComponentsInChildren<Light>(true); for (int j = 0; j < componentsInChildren2.Length && j < value.LightIntensities.Length; j++) { componentsInChildren2[j].intensity = value.LightIntensities[j] * lightIntensityMultiplier; componentsInChildren2[j].range = value.LightRanges[j] * lightRangeMultiplier; } WearNTear component = targetGameObject.GetComponent<WearNTear>(); if ((Object)(object)component != (Object)null) { component.m_health = health; } Transform val = targetGameObject.transform.Find("PlayerBase"); if ((Object)(object)val != (Object)null) { SphereCollider component2 = ((Component)val).GetComponent<SphereCollider>(); if ((Object)(object)component2 != (Object)null) { float num = 24f * mistClearRangeMultiplier; float num2 = Mathf.Clamp01(ModConfig.PlayerBaseMistRadiusBonus.Value); float num3 = 20f + (num - 20f) * num2; Vector3 lossyScale = targetGameObject.transform.lossyScale; float num4 = Mathf.Max(Mathf.Abs(lossyScale.x), Mathf.Max(Mathf.Abs(lossyScale.y), Mathf.Abs(lossyScale.z))); component2.radius = ((num4 > 0.001f) ? (num3 / num4) : num3); } } } public static bool IsValidItemPrefab(string itemName) { if (string.IsNullOrWhiteSpace(itemName)) { return false; } if (itemName.Equals("<PrefabName>", StringComparison.OrdinalIgnoreCase)) { return false; } GameObject prefab = PrefabManager.Instance.GetPrefab(itemName); if ((Object)(object)prefab != (Object)null) { return (Object)(object)prefab.GetComponent<ItemDrop>() != (Object)null; } return false; } public static bool TryParseAndValidateRecipe(string recipeString, string pieceName, out RequirementConfig[] requirements) { //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Expected O, but got Unknown requirements = Array.Empty<RequirementConfig>(); if (string.IsNullOrWhiteSpace(recipeString)) { Plugin.Log.LogError((object)("[PieceManager] Recipe for piece '" + pieceName + "' is empty or whitespace.")); return false; } string[] array = recipeString.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); if (array.Length == 0) { Plugin.Log.LogError((object)("[PieceManager] Recipe for piece '" + pieceName + "' contains no valid tokens ('" + recipeString + "').")); return false; } List<RequirementConfig> list = new List<RequirementConfig>(); string[] array2 = array; foreach (string text in array2) { string[] array3 = text.Trim().Split(new char[1] { ':' }); if (array3.Length != 2) { Plugin.Log.LogError((object)("[PieceManager] Recipe for piece '" + pieceName + "' contains malformed token '" + text + "'. Expected 'ItemPrefab:Amount'.")); return false; } string text2 = array3[0].Trim(); if (string.IsNullOrEmpty(text2)) { Plugin.Log.LogError((object)("[PieceManager] Recipe for piece '" + pieceName + "' contains an empty item prefab name in token '" + text + "'.")); return false; } if (!int.TryParse(array3[1].Trim(), out var result) || result <= 0) { Plugin.Log.LogError((object)("[PieceManager] Recipe for piece '" + pieceName + "' contains invalid amount '" + array3[1] + "' in token '" + text + "'. Amount must be a positive integer.")); return false; } if (!IsValidItemPrefab(text2)) { Plugin.Log.LogError((object)("[PieceManager] Recipe for piece '" + pieceName + "' requires item '" + text2 + "' which does not exist in the game!")); return false; } list.Add(new RequirementConfig(text2, result, 0, true)); } requirements = list.ToArray(); return true; } private static void EnsurePieceCollider(GameObject targetGameObject, in Vector3 center, in Vector3 size) { //IL_0045: 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) if (!((Object)(object)targetGameObject == (Object)null)) { BoxCollider val = targetGameObject.GetComponent<BoxCollider>(); if ((Object)(object)val == (Object)null) { val = targetGameObject.AddComponent<BoxCollider>(); } int num = LayerMask.NameToLayer("piece"); if (num >= 0) { ((Component)val).gameObject.layer = num; } ((Collider)val).isTrigger = false; val.center = center; val.size = size; } } private static void EnsurePlayerBase(GameObject targetGameObject) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)targetGameObject == (Object)null)) { Transform val = targetGameObject.transform.Find("PlayerBase"); GameObject val2; if ((Object)(object)val != (Object)null) { val2 = ((Component)val).gameObject; } else { val2 = new GameObject("PlayerBase"); val2.transform.SetParent(targetGameObject.transform, false); val2.transform.localPosition = Vector3.zero; val2.transform.localRotation = Quaternion.identity; } int num = LayerMask.NameToLayer("character_trigger"); if (num >= 0) { val2.layer = num; } SphereCollider val3 = val2.GetComponent<SphereCollider>(); if ((Object)(object)val3 == (Object)null) { val3 = val2.AddComponent<SphereCollider>(); } ((Collider)val3).isTrigger = true; val3.center = Vector3.zero; EffectArea val4 = val2.GetComponent<EffectArea>(); if ((Object)(object)val4 == (Object)null) { val4 = val2.AddComponent<EffectArea>(); } val4.m_type = (Type)4; Plugin.LogDebug($"[PieceManager] Configured PlayerBase on '{((Object)targetGameObject).name}' (layer: {val2.layer})."); } } } } namespace WispTorchHeeler.Patches { public static class PiecePatches { [HarmonyPatch(typeof(Piece), "Awake")] public static class Piece_Awake_Patch { [HarmonyPostfix] public static void Postfix(Piece __instance) { if (ModConfig.EnableMod.Value && !((Object)(object)__instance == (Object)null) && !((Object)(object)((Component)__instance).gameObject == (Object)null)) { string prefabName = Utils.GetPrefabName(((Component)__instance).gameObject); if (!(prefabName != "piece_groundtorch_mist") && (Object)(object)((Component)__instance).gameObject.GetComponent<WispTorchColorController>() == (Object)null) { ((Component)__instance).gameObject.AddComponent<WispTorchColorController>(); Plugin.LogDebug("[PiecePatch] Injected WispTorchColorController into spawned '" + prefabName + "'."); } } } } [HarmonyPatch(typeof(HoverText), "GetHoverText")] public static class HoverText_GetHoverText_Patch { [HarmonyPostfix] public static void Postfix(HoverText __instance, ref string __result) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) if (!ModConfig.EnableMod.Value || !ModConfig.AllowTorchPainting.Value || (Object)(object)__instance == (Object)null) { return; } WispTorchColorController wispTorchColorController = ((Component)__instance).GetComponentInParent<WispTorchColorController>() ?? ((Component)__instance).GetComponentInChildren<WispTorchColorController>(); if (!((Object)(object)wispTorchColorController == (Object)null) && (!(Utils.GetPrefabName(((Component)wispTorchColorController).gameObject) == "piece_groundtorch_mist") || ModConfig.AffectNativeMistTorches.Value)) { string text = ((object)ModConfig.PaintTorchHotkey.Value/*cast due to .constrained prefix*/).ToString(); string text2 = ((object)ModConfig.ResetTorchHotkey.Value/*cast due to .constrained prefix*/).ToString(); string text3 = ColorUtility.ToHtmlStringRGB(ModConfig.PainterColor.Value); string text4 = ModLocalization.Localize("$prompt_torch_paint"); string text5 = ModLocalization.Localize("$prompt_torch_reset"); if (string.IsNullOrEmpty(__result)) { __result = ((Localization.instance != null) ? Localization.instance.Localize(__instance.m_text) : __instance.m_text); } __result = __result + "\n[<color=#" + text3 + "><b>" + text + "</b></color>] " + text4 + " [<color=yellow><b>" + text2 + "</b></color>] " + text5; } } } } } namespace WispTorchHeeler.Painter { public static class TorchPainter { private static int s_baseRaycastMask = -1; private static int GetBaseRaycastMask() { if (s_baseRaycastMask == -1) { s_baseRaycastMask = LayerMask.GetMask(new string[4] { "piece", "piece_nonsolid", "Default", "static_solid" }); } return s_baseRaycastMask; } public static void TryPaintOrReset(bool isReset) { //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_030c: Unknown result type (might be due to invalid IL or missing references) //IL_0311: Unknown result type (might be due to invalid IL or missing references) //IL_03ed: Unknown result type (might be due to invalid IL or missing references) //IL_0336: Unknown result type (might be due to invalid IL or missing references) //IL_035e: Unknown result type (might be due to invalid IL or missing references) //IL_0355: Unknown result type (might be due to invalid IL or missing references) //IL_0368: Unknown result type (might be due to invalid IL or missing references) if (!ModConfig.EnableMod.Value) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } WispTorchColorController wispTorchColorController = null; if ((Object)(object)localPlayer.m_hovering != (Object)null) { wispTorchColorController = ResolveControllerFromObject(localPlayer.m_hovering); if ((Object)(object)wispTorchColorController != (Object)null) { Plugin.LogDebug("[TorchPainter] Targeted torch via native hover: '" + ((Object)((Component)wispTorchColorController).gameObject).name + "'."); } } if ((Object)(object)wispTorchColorController == (Object)null && (Object)(object)localPlayer.m_hoveringPiece != (Object)null) { wispTorchColorController = ResolveControllerFromObject(((Component)localPlayer.m_hoveringPiece).gameObject); if ((Object)(object)wispTorchColorController != (Object)null) { Plugin.LogDebug("[TorchPainter] Targeted torch via hovering piece: '" + ((Object)((Component)wispTorchColorController).gameObject).name + "'."); } } if ((Object)(object)wispTorchColorController == (Object)null) { float value = ModConfig.PainterRaycastDistance.Value; int layerMask = GetBaseRaycastMask() | localPlayer.m_interactMask; Camera val = (((Object)(object)GameCamera.instance != (Object)null && (Object)(object)GameCamera.instance.m_camera != (Object)null) ? GameCamera.instance.m_camera : (((Object)(object)Camera.main != (Object)null) ? Camera.main : (((Object)(object)GameCamera.instance != (Object)null) ? ((Component)GameCamera.instance).GetComponent<Camera>() : null))); if ((Object)(object)val != (Object)null) { wispTorchColorController = RaycastForController(new Ray(((Component)val).transform.position, ((Component)val).transform.forward), value, layerMask); } if ((Object)(object)wispTorchColorController == (Object)null) { wispTorchColorController = RaycastForController(new Ray(((Character)localPlayer).GetEyePoint(), ((Character)localPlayer).GetLookDir()), value, layerMask); } } if ((Object)(object)wispTorchColorController == (Object)null) { Plugin.LogDebug("[TorchPainter] No valid wisp torch/lamp targeted."); return; } if (Utils.GetPrefabName(((Component)wispTorchColorController).gameObject) == "piece_groundtorch_mist" && (ModConfig.AffectNativeMistTorches == null || !ModConfig.AffectNativeMistTorches.Value)) { Plugin.LogDebug("[TorchPainter] Painting native mist torches is disabled in config."); return; } if (!ModConfig.AllowTorchPainting.Value) { Plugin.LogDebug("[TorchPainter] Painting is globally disabled by server policy."); if ((Object)(object)MessageHud.instance != (Object)null) { MessageHud.instance.ShowMessage((MessageType)2, ModLocalization.Localize("$msg_cantpaint_disabled"), 0, (Sprite)null, false, true); } return; } Vector3 position = ((Component)wispTorchColorController).transform.position; if (!ModConfig.AllowPaintingInProtectedWards.Value && !PrivateArea.CheckAccess(position, 0f, true, false)) { bool flag = (ModConfig.ConfigSync != null && ((ConditionalConfigSync)ModConfig.ConfigSync).IsAdmin) || (SynchronizationManager.Instance != null && SynchronizationManager.Instance.PlayerIsAdmin); if (!(ModConfig.AdminBypassesWardCheck.Value && flag)) { Plugin.LogDebug("[TorchPainter] Ward access denied. Painting blocked."); if ((Object)(object)MessageHud.instance != (Object)null) { MessageHud.instance.ShowMessage((MessageType)2, ModLocalization.Localize("$msg_cantpaint_warded"), 0, (Sprite)null, false, true); } return; } Plugin.LogDebug("[TorchPainter] Ward access denied, but player is admin and AdminBypassesWardCheck is enabled. Access granted."); } ZNetView component = ((Component)wispTorchColorController).GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null || !component.IsValid()) { Plugin.Log.LogWarning((object)"[TorchPainter] Target piece has no valid ZNetView."); return; } string text; string text2; if (isReset) { text = string.Empty; wispTorchColorController.RefreshColor(); text2 = ModLocalization.Localize("$msg_torch_reset"); } else { Color value2 = ModConfig.PainterColor.Value; bool flag2 = ModConfig.EnableAlphaCustomization != null && ModConfig.EnableAlphaCustomization.Value; value2.a = (flag2 ? Mathf.Clamp(value2.a, 0.15f, 1f) : 1f); text = (flag2 ? ColorUtility.ToHtmlStringRGBA(value2) : ColorUtility.ToHtmlStringRGB(value2)); wispTorchColorController.ApplyColor(value2); text2 = ModLocalization.Localize("$msg_torch_painted", "#" + text); } component.ClaimOwnership(); component.GetZDO().Set(WispTorchColorController.ColorKeyHash, text); component.InvokeRPC(ZNetView.Everybody, "WTH_SetColor", new object[1] { text }); if (ModConfig.ShowPainterFeedback.Value && (Object)(object)MessageHud.instance != (Object)null) { MessageHud.instance.ShowMessage((MessageType)2, text2, 0, (Sprite)null, false, true); } PlayFeedbackEffect(position); Plugin.LogDebug(isReset ? ("[TorchPainter] Reset color on '" + ((Object)((Component)wispTorchColorController).gameObject).name + "'.") : ("[TorchPainter] Applied color #" + text + " to '" + ((Object)((Component)wispTorchColorController).gameObject).name + "'.")); } private static WispTorchColorController? ResolveControllerFromObject(GameObject targetGameObject) { if ((Object)(object)targetGameObject == (Object)null) { return null; } return targetGameObject.GetComponent<WispTorchColorController>() ?? targetGameObject.GetComponentInParent<WispTorchColorController>() ?? targetGameObject.GetComponentInChildren<WispTorchColorController>(); } private static WispTorchColorController? RaycastForController(Ray ray, float maxDistance, int layerMask) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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) RaycastHit[] array = Physics.RaycastAll(ray, maxDistance, layerMask); if (array == null || array.Length == 0) { return null; } Array.Sort(array, (RaycastHit firstHit, RaycastHit secondHit) => ((RaycastHit)(ref firstHit)).distance.CompareTo(((RaycastHit)(ref secondHit)).distance)); RaycastHit[] array2 = array; for (int num = 0; num < array2.Length; num++) { RaycastHit val = array2[num]; if (!((Object)(object)((RaycastHit)(ref val)).collider == (Object)null)) { WispTorchColorController wispTorchColorController = ResolveControllerFromObject(((Component)((RaycastHit)(ref val)).collider).gameObject); if ((Object)(object)wispTorchColorController != (Object)null) { Plugin.LogDebug($"[TorchPainter] Targeted torch via raycast ({((RaycastHit)(ref val)).distance:F1}m): '{((Object)((Component)wispTorchColorController).gameObject).name}'."); return wispTorchColorController; } } } return null; } private static void PlayFeedbackEffect(Vector3 position) { //IL_004e: 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) if (!((Object)(object)ZNetScene.instance == (Object)null)) { GameObject val = ZNetScene.instance.GetPrefab("sfx_wisp_spawn") ?? ZNetScene.instance.GetPrefab("vfx_wisp_spawn") ?? ZNetScene.instance.GetPrefab("sfx_build_hammer_metal"); if ((Object)(object)val != (Object)null) { Object.Instantiate<GameObject>(val, position, Quaternion.identity); } } } } } namespace WispTorchHeeler.Localization { public static class ModLocalization { public const string TokenPieceTorchLg = "$piece_wisptorch_heeler_lg"; public const string TokenPieceTorchLgDesc = "$piece_wisptorch_heeler_lg_description"; public const string TokenPieceSmallLamp = "$piece_wisplamp_heeler"; public const string TokenPieceSmallLampDesc = "$piece_wisplamp_heeler_description"; public const string TokenPieceLampLg = "$piece_wisplamp_heeler_lg"; public const string TokenPieceLampLgDesc = "$piece_wisplamp_heeler_lg_description"; public const string TokenPieceLampGrand = "$piece_wisplamp_heeler_grand"; public const string TokenPieceLampGrandDesc = "$piece_wisplamp_heeler_grand_description"; public const string TokenMsgPainted = "$msg_torch_painted"; public const string TokenMsgReset = "$msg_torch_reset"; public const string TokenMsgCantPaintWarded = "$msg_cantpaint_warded"; public const string TokenMsgCantPaintDisabled = "$msg_cantpaint_disabled"; public const string TokenPromptPaint = "$prompt_torch_paint"; public const string TokenPromptReset = "$prompt_torch_reset"; public static void Initialize() { CustomLocalization localization = LocalizationManager.Instance.GetLocalization(); string text = "English"; localization.AddTranslation(ref text, new Dictionary<string, string> { { "$piece_wisptorch_heeler_lg", "Large Wisp Torch" }, { "$piece_wisptorch_heeler_lg_description", "A large wisp torch that clears mist across a wide area." }, { "$piece_wisplamp_heeler", "Dvergr Wisp Lamp" }, { "$piece_wisplamp_heeler_description", "A sturdy dwarven demister lamp that clears mist across a wide area." }, { "$piece_wisplamp_heeler_lg", "Large Dvergr Wisp Lamp" }, { "$piece_wisplamp_heeler_lg_description", "An advanced dwarven demister with an expanded core that clears mist across a wide radius." }, { "$piece_wisplamp_heeler_grand", "Grand Dvergr Wisp Lamp" }, { "$piece_wisplamp_heeler_grand_description", "A colossal, reinforced dwarven demister monument that clears mist across a vast perimeter." }, { "$msg_torch_painted", "Wisp piece painted: {0}" }, { "$msg_torch_reset", "Wisp piece color reset to default." }, { "$msg_cantpaint_warded", "Piece is protected by a ward." }, { "$msg_cantpaint_disabled", "Painting wisp pieces is disabled on this server." }, { "$prompt_torch_paint", "Paint Light" }, { "$prompt_torch_reset", "Reset Color" } }); Plugin.LogDebug("[ModLocalization] Default English localizations registered."); } public static string Localize(string token, params string[] arguments) { string text = LocalizationManager.Instance.GetLocalization().TryTranslate(token); if (arguments != null && arguments.Length != 0) { text = string.Format(text, arguments); } return text; } } } namespace WispTorchHeeler.Lighting { public class WispTorchColorController : MonoBehaviour, IPlaced { public static readonly int ColorKeyHash = StringExtensionMethods.GetStableHashCode("wisptorch_light_color"); private static readonly int s_emissionColor = Shader.PropertyToID("_EmissionColor"); private static readonly int s_color = Shader.PropertyToID("_Color"); private static readonly int s_tintColor = Shader.PropertyToID("_TintColor"); public static readonly Color NativeFallbackColor = new Color(0.706f, 0.941f, 1f, 1f); public const float MinimumAlphaFloor = 0.15f; private static readonly HashSet<string> s_targetedMaterialNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "demister_ball", "demister_ball_intense", "demister_ball_weak", "demister_ball_v_intense", "demister", "demister_sparcs", "wispysmoke", "slowwispysmoke" }; public static readonly HashSet<WispTorchColorController> Instances = new HashSet<WispTorchColorController>(); private ZNetView? _netView; private Light[] _lights = Array.Empty<Light>(); private ParticleSystem[] _particleSystems = Array.Empty<ParticleSystem>(); private Color[] _originalLightColors = Array.Empty<Color>(); private MinMaxGradient[] _originalParticleGradients = Array.Empty<MinMaxGradient>(); private Renderer[] _ballRenderers = Array.Empty<Renderer>(); private Material[] _originalSharedMaterials = Array.Empty<Material>(); private Color[] _originalEmissionColors = Array.Empty<Color>(); private Color[] _originalAlbedoColors = Array.Empty<Color>(); private Color[] _originalTintColors = Array.Empty<Color>(); private CircleProjector? _circleProjector; private GameObject? _areaMarkerGameObject; private void Awake() { //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) //IL_008b: 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) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) _netView = ((Component)this).GetComponent<ZNetView>(); _lights = ((Component)this).GetComponentsInChildren<Light>(true); _particleSystems = ((Component)this).GetComponentsInChildren<ParticleSystem>(true); _originalLightColors = (Color[])(object)new Color[_lights.Length]; for (int i = 0; i < _lights.Length; i++) { _originalLightColors[i] = _lights[i].color; } _originalParticleGradients = (MinMaxGradient[])(object)new MinMaxGradient[_particleSystems.Length]; for (int j = 0; j < _particleSystems.Length; j++) { MinMaxGradient[] originalParticleGradients = _originalParticleGradients; int num = j; MainModule main = _particleSystems[j].main; originalParticleGradients[num] = ((MainModule)(ref main)).startColor; } List<Renderer> list = new List<Renderer>(); Renderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !((Object)(object)val.sharedMaterial == (Object)null)) { string text = ((Object)val.sharedMaterial).name; int num2 = text.IndexOf(" (Instance)", StringComparison.OrdinalIgnoreCase); if (num2 >= 0) { text = text.Substring(0, num2); } if (s_targetedMaterialNames.Contains(text)) { list.Add(val); } } } _ballRenderers = list.ToArray(); _originalSharedMaterials = (Material[])(object)new Material[_ballRenderers.Length]; _originalEmissionColors = (Color[])(object)new Color[_ballRenderers.Length]; _originalAlbedoColors = (Color[])(object)new Color[_ballRenderers.Length]; _originalTintColors = (Color[])(object)new Color[_ballRenderers.Length]; for (int l = 0; l < _ballRenderers.Length; l++) { Material sharedMaterial = _ballRenderers[l].sharedMaterial; _originalSharedMaterials[l] = sharedMaterial; _originalEmissionColors[l] = (sharedMaterial.HasProperty(s_emissionColor) ? sharedMaterial.GetColor(s_emissionColor) : Color.white); _originalAlbedoColors[l] = (sharedMaterial.HasProperty(s_color) ? sharedMaterial.GetColor(s_color) : Color.white); _originalTintColors[l] = (sharedMaterial.HasProperty(s_tintColor) ? sharedMaterial.GetColor(s_tintColor) : Color.white); } if ((Object)(object)_netView != (Object)null) { _netView.Register<string>("WTH_SetColor", (Action<long, string>)RPC_SetColor); } } private void OnEnable() { Instances.Add(this); EnsureAreaMarker(); RefreshColor(); RefreshProperties(); } private void Start() { if ((Object)(object)_netView != (Object)null && !_netView.IsValid()) { ((MonoBehaviour)this).StartCoroutine(WaitForZDOAndInit()); } } private IEnumerator WaitForZDOAndInit() { int maxFrames = 30; while ((Object)(object)_netView != (Object)null && !_netView.IsValid() && maxFrames-- > 0) { yield return null; } if ((Object)(object)_netView != (Object)null && _netView.IsValid()) { RefreshColor(); } } public void OnPlaced() { //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) if (!ModConfig.EnableMod.Value || !ModConfig.AutoPaintOnPlacement.Value || !ModConfig.AllowTorchPainting.Value) { return; } string prefabName = Utils.GetPrefabName(((Component)this).gameObject); if (!(prefabName == "piece_groundtorch_mist") || (ModConfig.AffectNativeMistTorches != null && ModConfig.AffectNativeMistTorches.Value)) { if ((Object)(object)_netView == (Object)null) { _netView = ((Component)this).GetComponent<ZNetView>(); } if (!((Object)(object)_netView == (Object)null) && _netView.IsValid()) { Color value = ModConfig.PainterColor.Value; bool flag = ModConfig.EnableAlphaCustomization != null && ModConfig.EnableAlphaCustomization.Value; value.a = (flag ? Mathf.Clamp(value.a, 0.15f, 1f) : 1f); string text = (flag ? ColorUtility.ToHtmlStringRGBA(value) : ColorUtility.ToHtmlStringRGB(value)); _netView.ClaimOwnership(); _netView.GetZDO().Set(ColorKeyHash, text); _netView.InvokeRPC(ZNetView.Everybody, "WTH_SetColor", new object[1] { text }); ApplyColor(value); Plugin.LogDebug("[PiecePlacement] Auto-painted newly placed '" + prefabName + "' with color #" + text + "."); } } } private void OnDisable() { Instances.Remove(this); } private void OnDestroy() { Instances.Remove(this); for (int i = 0; i < _ballRenderers.Length; i++) { if ((Object)(object)_ballRenderers[i] != (Object)null && i < _originalSharedMaterials.Length) { Material sharedMaterial = _ballRenderers[i].sharedMaterial; if ((Object)(object)sharedMaterial != (Object)null && (Object)(object)sharedMaterial != (Object)(object)_originalSharedMaterials[i]) { Object.Destroy((Object)(object)sharedMaterial, 10f); } } } } private void RPC_SetColor(long sender, string hexColor) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) Color color = default(Color); if (string.IsNullOrEmpty(hexColor) || !ColorUtility.TryParseHtmlString(hexColor.StartsWith("#") ? hexColor : ("#" + hexColor), ref color)) { RefreshColor(); } else { ApplyColor(color); } } public void RefreshColor() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) if (ModConfig.AffectNativeMistTorches != null && !ModConfig.AffectNativeMistTorches.Value && Utils.GetPrefabName(((Component)this).gameObject) == "piece_groundtorch_mist") { RestoreOriginalColors(); } else { ApplyColor(ResolveColor()); } } public void RestoreOriginalColors() { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //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) //IL_007d: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < _lights.Length; i++) { if ((Object)(object)_lights[i] != (Object)null && i < _originalLightColors.Length) { _lights[i].color = _originalLightColors[i]; } } for (int j = 0; j < _particleSystems.Length; j++) { if ((Object)(object)_particleSystems[j] != (Object)null && j < _originalParticleGradients.Length) { MainModule main = _particleSystems[j].main; ((MainModule)(ref main)).startColor = _originalParticleGradients[j]; } } for (int k = 0; k < _ballRenderers.Length; k++) { if ((Object)(object)_ballRenderers[k] != (Object)null && k < _originalSharedMaterials.Length && (Object)(object)_ballRenderers[k].sharedMaterial != (Object)(object)_originalSharedMaterials[k]) { Object.Destroy((Object)(object)_ballRenderers[k].sharedMaterial); _ballRenderers[k].sharedMaterial = _originalSharedMaterials[k]; } } } public Color ResolveColor() { //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_netView != (Object)null && _netView.IsValid()) { string text = _netView.GetZDO().GetString(ColorKeyHash, string.Empty); Color result = default(Color); if (!string.IsNullOrEmpty(text) && ColorUtility.TryParseHtmlString(text.StartsWith("#") ? text : ("#" + text), ref result)) { return result; } } if (ModConfig.EnforceServerDefaultColor != null && ModConfig.EnforceServerDefaultColor.Value) { if (ModConfig.ServerDefaultLightColor == null) { return NativeFallbackColor; } return ModConfig.ServerDefaultLightColor.Value; } if (ModConfig.DefaultLightColor != null) { return ModConfig.DefaultLightColor.Value; } return NativeFallbackColor; } public void ApplyColor(Color color) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_008b: 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) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < _lights.Length; i++) { if ((Object)(object)_lights[i] != (Object)null) { _lights[i].color = color; } } float alphaMultiplier = ((ModConfig.EnableAlphaCustomization != null && ModConfig.EnableAlphaCustomization.Value) ? Mathf.Clamp(color.a, 0.15f, 1f) : 1f); for (int j = 0; j < _particleSystems.Length; j++) { if ((Object)(object)_particleSystems[j] != (Object)null && j < _originalParticleGradients.Length) { MainModule main = _particleSystems[j].main; ((MainModule)(ref main)).startColor = TintMinMaxGradient(in _originalParticleGradients[j], color, alphaMultiplier); } } for (int k = 0; k < _ballRenderers.Length; k++) { Renderer val = _ballRenderers[k]; if (!((Object)(object)val == (Object)null)) { Material material = val.material; if (!((Object)(object)material == (Object)null)) { TintMaterialProperty(material, s_emissionColor, in _originalEmissionColors[k], color, 1f); TintMaterialProperty(material, s_color, in _originalAlbedoColors[k], color, alphaMultiplier); TintMaterialProperty(material, s_tintColor, in _originalTintColors[k], color, alphaMultiplier); } } } } private static void TintMaterialProperty(Material material, int propertyId, in Color originalColor, Color targetColor, float alphaMultiplier) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) if (material.HasProperty(propertyId)) { float num = Mathf.Max(originalColor.r, Mathf.Max(originalColor.g, originalColor.b)); material.SetColor(propertyId, new Color(targetColor.r * num, targetColor.g * num, targetColor.b * num, originalColor.a * alphaMultiplier)); } } private static MinMaxGradient TintMinMaxGradient(in MinMaxGradient originalGradient, Color targetColor, float alphaMultiplier) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //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_0025: Expected I4, but got Unknown //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0045: 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) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) MinMaxGradient val = originalGradient; ParticleSystemGradientMode mode = ((MinMaxGradient)(ref val)).mode; switch ((int)mode) { case 0: { float r3 = targetColor.r; float g3 = targetColor.g; float b3 = targetColor.b; val = originalGradient; return MinMaxGradient.op_Implicit(new Color(r3, g3, b3, ((MinMaxGradient)(ref val)).color.a * alphaMultiplier)); } case 2: { float r = targetColor.r; float g = targetColor.g; float b = targetColor.b; val = originalGradient; Color val2 = new Color(r, g, b, ((MinMaxGradient)(ref val)).colorMin.a * alphaMultiplier); float r2 = targetColor.r; float g2 = targetColor.g; float b2 = targetColor.b; val = originalGradient; return new MinMaxGradient(val2, new Color(r2, g2, b2, ((MinMaxGradient)(ref val)).colorMax.a * alphaMultiplier)); } case 1: val = originalGradient; return MinMaxGradient.op_Implicit(TintGradient(((MinMaxGradient)(ref val)).gradient, targetColor, alphaMultiplier)); case 3: { val = originalGradient; Gradient obj = TintGradient(((MinMaxGradient)(ref val)).gradientMin, targetColor, alphaMultiplier); val = originalGradient; return new MinMaxGradient(obj, TintGradient(((MinMaxGradient)(ref val)).gradientMax, targetColor, alphaMultiplier)); } default: return originalGradient; } } private static Gradient TintGradient(Gradient? sourceGradient, Color targetColor, float alphaMultiplier) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Expected O, but got Unknown //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: 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_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Expected O, but got Unknown //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) if (sourceGradient != null) { GradientColorKey[] colorKeys = sourceGradient.colorKeys; GradientColorKey[] array = (GradientColorKey[])(object)new GradientColorKey[colorKeys.Length]; for (int i = 0; i < colorKeys.Length; i++) { array[i] = new GradientColorKey(new Color(targetColor.r, targetColor.g, targetColor.b), colorKeys[i].time); } GradientAlphaKey[] array2; if (alphaMultiplier < 0.999f) { GradientAlphaKey[] alphaKeys = sourceGradient.alphaKeys; array2 = (GradientAlphaKey[])(object)new GradientAlphaKey[alphaKeys.Length]; for (int j = 0; j < alphaKeys.Length; j++) { array2[j] = new GradientAlphaKey(alphaKeys[j].alpha * alphaMultiplier, alphaKeys[j].time); } } else { array2 = sourceGradient.alphaKeys; } Gradient val = new Gradient(); val.SetKeys(array, array2); return val; } return new Gradient(); } public void RefreshProperties() { string prefabName = Utils.GetPrefabName(((Component)this).gameObject); WispPieceManager.ApplyProperties(((Component)this).gameObject, prefabName); UpdateAreaMarkerRadius(); } public float GetMistSuppressionRadius() { ParticleSystemForceField componentInChildren = ((Component)this).GetComponentInChildren<ParticleSystemForceField>(true); if ((Object)(object)componentInChildren != (Object)null && componentInChildren.endRange > 0f) { return componentInChildren.endRange; } return 0f; } public void EnsureAreaMarker() { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown //IL_007a: 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_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_areaMarkerGameObject != (Object)null) { return; } GameObject areaMarkerTemplate = WispPieceManager.AreaMarkerTemplate; if (!((Object)(object)areaMarkerTemplate == (Object)null)) { CircleProjector val = areaMarkerTemplate.GetComponent<CircleProjector>() ?? areaMarkerTemplate.GetComponentInChildren<CircleProjector>(); if (!((Object)(object)val == (Object)null) && !((Object)(object)val.m_prefab == (Object)null)) { _areaMarkerGameObject = new GameObject("_MistSuppressionMarker"); _areaMarkerGameObject.transform.SetParent(((Component)this).transform, false); _areaMarkerGameObject.transform.localPosition = Vector3.zero; _areaMarkerGameObject.transform.localRotation = Quaternion.identity; _circleProjector = _areaMarkerGameObject.AddComponent<CircleProjector>(); _circleProjector.m_prefab = val.m_prefab; _circleProjector.m_mask = val.m_mask; _circleProjector.m_speed = val.m_speed; _circleProjector.m_turns = 1f; UpdateAreaMarkerRadius(); } } } public void UpdateAreaMarkerRadius() { if ((Object)(object)_circleProjector == (Object)null) { return; } float mistSuppressionRadius = GetMistSuppressionRadius(); if (mistSuppressionRadius <= 0f) { GameObject? areaMarkerGameObject = _areaMarkerGameObject; if (areaMarkerGameObject != null) { areaMarkerGameObject.SetActive(false); } } else { _circleProjector.m_radius = mistSuppressionRadius; _circleProjector.m_nrOfSegments = Mathf.Clamp(Mathf.RoundToInt(mistSuppressionRadius * 5f), 24, 250); _circleProjector.CreateSegments(); RefreshMarkerVisibility(); } } public void RefreshMarkerVisibility() { if ((Object)(object)_areaMarkerGameObject != (Object)null) { bool active = ModConfig.ShowMistSuppressionRadius != null && ModConfig.ShowMistSuppressionRadius.Value && GetMistSuppressionRadius() > 0f; _areaMarkerGameObject.SetActive(active); } } public static void RefreshAllMarkers() { foreach (WispTorchColorController instance in Instances) { if ((Object)(object)instance != (Object)null) { instance.EnsureAreaMarker(); instance.RefreshMarkerVisibility(); } } } public static void RefreshPropertiesForPrefab(string prefabName) { foreach (WispTorchColorController instance in Instances) { if ((Object)(object)instance != (Object)null && Utils.GetPrefabName(((Component)instance).gameObject) == prefabName) { instance.RefreshProperties(); } } } public static void RefreshAll() { foreach (WispTorchColorController instance in Instances) { if ((Object)(object)instance != (Object)null) { instance.RefreshColor(); instance.RefreshProperties(); } } } } } namespace WispTorchHeeler.Configuration { public class ConfigurationManagerAttributes { public Action<ConfigEntryBase>? CustomDrawer; public bool? Browsable; public bool? ReadOnly; public string? Category; public int? Order; } public static class ModConfig { public static ConfigSync ConfigSync = null; public static ConfigEntry<bool> EnableMod = null; public static ConfigEntry<bool> AffectNativeMistTorches = null; public static ConfigEntry<float> PlayerBaseMistRadiusBonus = null; public static ConfigEntry<float> Torch_MistClearRangeMultiplier = null; public static ConfigEntry<float> Torch_LightIntensityMultiplier = null; public static ConfigEntry<float> Torch_LightRangeMultiplier = null; public static ConfigEntry<float> Torch_Health = null; public static ConfigEntry<string> Torch_CraftingStation = null; public static ConfigEntry<string> Torch_Recipe = null; public static ConfigEntry<float> SmallLamp_MistClearRangeMultiplier = null; public static ConfigEntry<float> SmallLamp_LightIntensityMultiplier = null; public static ConfigEntry<float> SmallLamp_LightRangeMultiplier = null; public static ConfigEntry<float> SmallLamp_Health = null; public static ConfigEntry<string> SmallLamp_CraftingStation = null; public static ConfigEntry<string> SmallLamp_Recipe = null; public static ConfigEntry<float> LargeLamp_MistClearRangeMultiplier = null; public static ConfigEntry<float> LargeLamp_LightIntensityMultiplier = null; public static ConfigEntry<float> LargeLamp_LightRangeMultiplier = null; public static ConfigEntry<float> LargeLamp_Health = null; public static ConfigEntry<string> LargeLamp_CraftingStation = null; public static ConfigEntry<string> LargeLamp_Recipe = null; public static ConfigEntry<float> GrandLamp_MistClearRangeMultiplier = null; public static ConfigEntry<float> GrandLamp_LightIntensityMultiplier = null; public static ConfigEntry<float> GrandLamp_LightRangeMultiplier = null; public static ConfigEntry<float> GrandLamp_Health = null; public static ConfigEntry<string> GrandLamp_CraftingStation = null; public static ConfigEntry<string> GrandLamp_Recipe = null; public static ConfigEntry<bool> EnforceServerDefaultColor = null; public static ConfigEntry<Color> ServerDefaultLightColor = null; public static ConfigEntry<bool> AllowTorchPainting = null; public static ConfigEntry<bool> AllowPaintingInProtectedWards = null; public static ConfigEntry<bool> AdminBypassesWardCheck = null; public static ConfigEntry<bool> EnableAlphaCustomization = null; public static ConfigEntry<Color> DefaultLightColor = null; public static ConfigEntry<Color> PainterColor = null; public static ConfigEntry<KeyboardShortcut> PaintTorchHotkey = null; public static ConfigEntry<KeyboardShortcut> ResetTorchHotkey = null; public static ButtonConfig? ButtonPaintConfig; public static ButtonConfig? ButtonResetConfig; public static ConfigEntry<float> PainterRaycastDistance = null; public static ConfigEntry<bool> ShowPainterFeedback = null; public static ConfigEntry<bool> AutoPaintOnPlacement = null; public static ConfigEntry<bool> EnableDebugLogs = null; public static ConfigEntry<bool> ShowMistSuppressionRadius = null; private static readonly Color s_defaultCyan = new Color(0.706f, 0.941f, 1f, 1f); private static readonly Color s_defaultOrange = new Color(1f, 0.533f, 0f, 1f); public const string ButtonPaint = "WTH_Paint"; public const string ButtonReset = "WTH_Reset"; public static void Initialize(ConfigFile config) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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_0037: Expected O, but got Unknown //IL_0528: Unknown result type (might be due to invalid IL or missing references) //IL_05bd: Unknown result type (might be due to invalid IL or missing references) //IL_05de: Unknown result type (might be due to invalid IL or missing references) //IL_0606: Unknown result type (might be due to invalid IL or missing references) //IL_0637: Unknown result type (might be due to invalid IL or missing references) ConfigSync = new ConfigSync("dreamwraith.WispTorchHeeler") { DisplayName = "WispTorchHeeler", CurrentVersion = "1.1.0", MinimumRequiredVersion = "1.1.0", ModRequired = true }; EnableMod = BindSynced(config, "1 - General", "EnableMod (Requires Restart)", defaultValue: true, "Master switch to enable or disable the functionality of this mod. (Requires Restart)"); AffectNativeMistTorches = BindSynced(config, "1 - General", "AffectNativeMistTorches", defaultValue: true, "Allows painting and color defaults on standard native wisp torches."); PlayerBaseMistRadiusBonus = BindSynced(config, "1 - General", "PlayerBaseMistRadiusBonus", 0f, "Additive bonus percentage (0.0 to 1.0) scaling PlayerBase spawn suppression from a baseline of 20.0m toward active mist clearance radius. At 0.0, all custom pieces use the 20.0m baseline. At 1.0, the suppression radius matches the active mist reveal boundary. Note: higher values reduce native spawn balance in favor of mist sanctuary.", (AcceptableValueBase?)(object)new AcceptableValueRange<float>(0f, 1f)); Torch_MistClearRangeMultiplier = BindSynced(config, "2 - Large Torch", "Torch_MistClearRangeMultiplier", 1.5f, "Large torch mist clearance radius multiplier (relative to 24.0m baseline, range: 1.0 - 10.0).", (AcceptableValueBase?)(object)new AcceptableValueRange<float>(1f, 10f)); Torch_LightIntensityMultiplier = BindSynced(config, "2 - Large Torch", "Torch_LightIntensityMultiplier", 1.33f, "Large torch light emission intensity multiplier (relative to 1.0 baseline, range: 0.5 - 5.0).", (AcceptableValueBase?)(object)new AcceptableValueRange<float>(0.5f, 5f)); Torch_LightRangeMultiplier = BindSynced(config, "2 - Large Torch", "Torch_LightRangeMultiplier", 1.25f, "Large torch light emission range radius multiplier (relative to 10.0m baseline, range: 0.5 - 5.0).", (AcceptableValueBase?)(object)new AcceptableValueRange<float>(0.5f, 5f)); Torch_Health = BindSynced(config, "2 - Large Torch", "Torch_Health", 200f, "Large torch structural health points (1.0 - 5000.0).", (AcceptableValueBase?)(object)new AcceptableValueRange<float>(1f, 5000f)); Torch_CraftingStation = BindSynced(config, "2 - Large Torch", "Torch_CraftingStation", "", "Required station formatted as StationPrefab (e.g. piece_workbench, piece_forge, or \"\" for freeform hammer placement)."); Torch_Recipe = BindSynced(config, "2 - Large Torch", "Torch_Recipe", "Wisp:8,YggdrasilWood:5,Sap:1", "Crafting recipe string formatted as ItemPrefab:Amount,... parsed against ObjectDB.", null, RecipeConfigDrawer.Draw); SmallLamp_MistClearRangeMultiplier = BindSynced(config, "3 - Small Lamp", "SmallLamp_MistClearRangeMultiplier", 2.25f, "Tier 2 small lamp mist clearance radius multiplier (relative to 24.0m baseline, range: 1.0 - 10.0).", (AcceptableValueBase?)(object)new AcceptableValueRange<float>(1f, 10f)); SmallLamp_LightIntensityMultiplier = BindSynced(config, "3 - Small Lamp", "SmallLamp_LightIntensityMultiplier", 1.5f, "Tier 2 small lamp light emission intensity multiplier (relative to 1.0 baseline, range: 0.5 - 5.0).", (AcceptableValueBase?)(object)new AcceptableValueRange<float>(0.5f, 5f)); SmallLamp_LightRangeMultiplier = BindSynced(config, "3 - Small Lamp", "SmallLamp_LightRangeMultiplier", 1.5f, "Tier 2 small lamp light emission range radius multiplier (relative to 10.0m baseline, range: 0.5 - 5.0).", (AcceptableValueBase?)(object)new AcceptableValueRange<float>(0.5f, 5f)); SmallLamp_Health = BindSynced(config, "3 - Small Lamp", "SmallLamp_Health", 250f, "Tier 2 small lamp structural health points (1.0 - 5000.0).", (AcceptableValueBase?)(object)new AcceptableValueRange<float>(1f, 5000f)); SmallLamp_CraftingStation = BindSynced(config, "3 - Small Lamp", "SmallLamp_CraftingStation", "forge", "Required station formatted as StationPrefab or Jotunn name (defaults to 'forge')."); SmallLamp_Recipe = BindSynced(config, "3 - Small Lamp", "SmallLamp_Recipe", "Wisp:15,Copper:5,Iron:2,BlackMarble:2,Sap:2", "Crafting recipe string formatted as ItemPrefab:Amount,... parsed against ObjectDB.", null, RecipeConfigDrawer.Draw); LargeLamp_MistClearRangeMultiplier = BindSynced(config, "4 - Large Lamp", "LargeLamp_MistClearRangeMultiplier", 3f, "Tier 3 lamp mist clearance radius multiplier (relative to 24.0m baseline, range: 1.0 - 15.0).", (AcceptableValueBase?)(object)new AcceptableValueRange<float>(1f, 15f)); LargeLamp_LightIntensityMultiplier = BindSynced(config, "4 - Large Lamp", "LargeLamp_LightIntensityMultiplier", 2.25f, "Tier 3 lamp light emission intensity multiplier (relative to 1.0 baseline, range: 0.5 - 8.0).", (AcceptableValueBase?)(object)new AcceptableValueRange<float>(0.5f, 8f)); LargeLamp_LightRangeMultiplier = BindSynced(config, "4 - Large Lamp", "LargeLamp_LightRangeMultiplier", 1.75f, "Tier 3 lamp light emission range radius multiplier (relative to 10.0m baseline, range: 0.5 - 5.0).", (AcceptableValueBase?)(object)new AcceptableValueRange<float>(0.5f, 5f)); LargeLamp_Health = BindSynced(config, "4 - Large Lamp", "LargeLamp_Health", 500f, "Tier 3 lamp structural health points (1.0 - 5000.0).", (AcceptableValueBase?)(object)new AcceptableValueRange<float>(1f, 5000f)); LargeLamp_CraftingStation = BindSynced(config, "4 - Large Lamp", "LargeLamp_CraftingStation", "blackforge", "Required station formatted as StationPrefab or Jotunn name (defaults to 'blackforge')."); LargeLamp_Recipe = BindSynced(config, "4 - Large Lamp", "LargeLamp_Recipe", "Wisp:22,Copper:8,Iron:3,Eitr:2,BlackMarble:5", "Crafting recipe string formatted as ItemPrefab:Amount,... parsed against ObjectDB.", null, RecipeConfigDrawer.Draw); GrandLamp_MistClearRangeMultiplier = BindSynced(config, "5 - Grand Lamp", "GrandLamp_MistClearRangeMultiplier", 3.75f, "Tier 4 grand lamp mist clearance radius multiplier (relative to 24.0m baseline, range: 1.0 - 15.0).", (AcceptableValueBase?)(object)new AcceptableValueRange<float>(1f, 15f)); GrandLamp_LightIntensityMultiplier = BindSynced(config, "5 - Grand Lamp", "GrandLamp_LightIntensityMultiplier", 2.5f, "Tier 4 grand lamp light emission intensity multiplier (relative to 1.0 baseline, range: 0.5 - 8.0).", (AcceptableValueBase?)(object)new AcceptableValueRange<float>(0.5f, 8f)); GrandLamp_LightRangeMultiplier = BindSynced(config, "5 - Grand Lamp", "GrandLamp_LightRangeMultiplier", 2f, "Tier 4 grand lamp light emission range radius multiplier (relative to 10.0m baseline, range: 0.5 - 8.0).", (AcceptableValueBase?)(object)new AcceptableValueRange<float>(0.5f, 8f)); GrandLamp_Health = BindSynced(config, "5 - Grand Lamp", "GrandLamp_Health", 750f, "Tier 4 grand lamp structural health points (1.0 - 5000.0).", (AcceptableValueBase?)(object)new AcceptableValueRange<float>(1f, 5000f)); GrandLamp_CraftingStation = BindSynced(config, "5 - Grand Lamp", "GrandLamp_CraftingStation", "blackforge", "Required station formatted as StationPrefab or Jotunn name (defaults to 'blackforge')."); GrandLamp_Recipe = BindSynced(config, "5 - Grand Lamp", "GrandLamp_Recipe", "Wisp:30,Copper:10,Iron:4,Eitr:4,BlackMarble:10", "Crafting recipe string formatted as ItemPrefab:Amount,... parsed against ObjectDB.", null, RecipeConfigDrawer.Draw); EnforceServerDefaultColor = BindSynced(config, "6 - Lighting Policy", "EnforceServerDefaultColor", defaultValue: false, "If true, all clients must render unpainted pieces with the server's default color."); ServerDefaultLightColor = BindSynced<Color>(config, "6 - Lighting Policy", "ServerDefaultLightColor", s_defaultCyan, "Server-wide default color for unpainted pieces when enforced."); AllowTorchPainting = BindSynced(config, "6 - Lighting Policy", "AllowTorchPainting", defaultValue: true, "Server master toggle allowing players to paint individual pieces."); AllowPaintingInProtectedWards = BindSynced(config, "6 - Lighting Policy", "AllowPaintingInProtectedWards", defaultValue: false, "If false, players cannot paint pieces inside wards they lack access to."); AdminBypassesWardCheck = BindSynced(config, "6 - Lighting Policy", "AdminBypassesWardCheck", defaultValue: true, "If true, verified server admins bypass ward restrictions when painting."); EnableAlphaCustomization = BindSynced(config, "6 - Lighting Policy", "EnableAlphaCustomization", defaultValue: false, "Allows customizing light and particle transparency using the alpha slider in the color picker. When disabled, native opacity is strictly preserved. Alpha is safely clamped to a minimum of 15% to prevent pieces from becoming invisible."); DefaultLightColor = BindClient<Color>(config, "7 - Client Lighting", "DefaultLightColor", s_defaultCyan, "Client's personal default color for unpainted pieces (active when server does not enforce)."); PainterColor = BindClient<Color>(config, "8 - Torch Painter", "PainterColor", s_defaultOrange, "Active paint color selected by player via UI color picker drawer."); PaintTorchHotkey = BindClient<KeyboardShortcut>(config, "8 - Torch Painter", "PaintTorchHotkey", new KeyboardShortcut((KeyCode)112, Array.Empty<KeyCode>()), "Hotkey pressed while aiming at a torch/lamp to apply PainterColor."); ResetTorchHotkey = BindClient<KeyboardShortcut>(config, "8 - Torch Painter", "ResetTorchHotkey", new KeyboardShortcut((KeyCode)112, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Hotkey pressed while aiming at a torch/lamp to clear custom color."); PainterRaycastDistance = BindClient(config, "8 - Torch Painter", "PainterRaycastDistance", 10f, "Maximum distance in meters to aim and paint a piece (2.0 - 25.0).", (AcceptableValueBase?)(object)new AcceptableValueRange<float>(2f, 25f)); ShowPainterFeedback = BindClient(config, "8 - Torch Painter", "ShowPainterFeedback", defaultValue: true, "Shows on-screen HUD text confirmations upon painting/resetting."); AutoPaintOnPlacement = BindClient(config, "8 - Torch Painter", "AutoPaintOnPlacement", defaultValue: false, "If true, newly placed torches and lamps are automatically painted with your active PainterColor upon placement."); RegisterInputButtons(); EnableDebugLogs = BindClient(config, "9 - Debug", "EnableDebugLogs", defaultValue: false, "Enables verbose diagnostic logging in the BepInEx console."); ShowMistSuppressionRadius = BindClient(config, "9 - Debug", "ShowMistSuppressionRadius", defaultValue: false, "Projects a ground boundary ring around wisp torches and lamps showing their active mist suppression radius."); Plugin.LogDebug("Configuration initialized and bound."); } private static void RegisterInputButtons() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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_0032: Expected O, but got Unknown //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Expected O, but got Unknown try { ButtonPaintConfig = new ButtonConfig { Name = "WTH_Paint", ShortcutConfig = PaintTorchHotkey, ActiveInGUI = false, HintToken = "$prompt_torch_paint" }; InputManager.Instance.AddButton("dreamwraith.WispTorchHeeler", ButtonPaintConfig); ButtonResetConfig = new ButtonConfig { Name = "WTH_Reset", ShortcutConfig = ResetTorchHotkey, ActiveInGUI = false, HintToken = "$prompt_torch_reset" }; InputManager.Instance.AddButton("dreamwraith.WispTorchHeeler", ButtonResetConfig); Plugin.LogDebug("[ModConfig] Registered input buttons 'WTH_Paint' and 'WTH_Reset' via Jotunn InputManager."); } catch (Exception ex) { Plugin.Log.LogError((object)("[ModConfig] Failed to register Jotunn input buttons: " + ex.Message)); } } private static ConfigEntry<T> BindSynced<T>(ConfigFile config, string section, string key, T defaultValue, string description, AcceptableValueBase? acceptableValues = null, Action<ConfigEntryBase>? customDrawer = null) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown ConfigDescription val = ((customDrawer != null) ? new ConfigDescription(description, acceptableValues, new object[1] { new ConfigurationManagerAttributes { CustomDrawer = customDrawer } }) : new ConfigDescription(description, acceptableValues, Array.Empty<object>())); ConfigEntry<T> val2 = config.Bind<T>(section, key, defaultValue, val); ((ConditionalConfigSync)ConfigSync).AddConfigEntry<T>(val2); return val2; } private static ConfigEntry<T> BindClient<T>(ConfigFile config, string section, string key, T defaultValue, string description, AcceptableValueBase? acceptableValues = null, Action<ConfigEntryBase>? customDrawer = null) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown ConfigDescription val = ((customDrawer != null) ? new ConfigDescription(description, acceptableValues, new object[1] { new ConfigurationManagerAttributes { CustomDrawer = customDrawer } }) : new ConfigDescription(description, acceptableValues, Array.Empty<object>())); return config.Bind<T>(section, key, defaultValue, val); } } public static class RecipeConfigDrawer { public record struct RecipeItemEntry(string PrefabName, int Amount); public const string DefaultPlaceholderPrefab = "<PrefabName>"; private const char ItemSeparator = ','; private const char AmountSeparator = ':'; private static readonly GUILayoutOption s_amountWidth = GUILayout.Width(40f); private static readonly GUILayoutOption s_buttonWidth = GUILayout.Width(24f); public static void Draw(ConfigEntryBase entry) { if (entry == null) { return; } List<RecipeItemEntry> list = Deserialize((entry.BoxedValue as string) ?? string.Empty); bool flag = false; List<RecipeItemEntry> list2 = new List<RecipeItemEntry>(); GUILayout.BeginVertical(Array.Empty<GUILayoutOption>()); if (list.Count == 0) { if (GUILayout.Button("+ Add Requirement", Array.Empty<GUILayoutOption>())) { list2.Add(new RecipeItemEntry("<PrefabName>", 1)); flag = true; } } else { for (int i = 0; i < list.Count; i++) { RecipeItemEntry item = list[i]; GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); string text = GUILayout.TextField(item.PrefabName ?? string.Empty, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.ExpandWidth(true), GUILayout.MinWidth(60f) }); if (text != item.PrefabName) { item.PrefabName = text; flag = true; } if (int.TryParse(GUILayout.TextField(item.Amount.ToString(), (GUILayoutOption[])(object)new GUILayoutOption[1] { s_amountWidth }), out var result) && result != item.Amount) { item.Amount = result; flag = true; } if (GUILayout.Button("-", (GUILayoutOption[])(object)new GUILayoutOption[1] { s_buttonWidth })) { flag = true; } else { list2.Add(item); } if (GUILayout.Button("+", (GUILayoutOption[])(object)new GUILayoutOption[1] { s_buttonWidth })) { list2.Add(new RecipeItemEntry("<PrefabName>", 1)); flag = true; } GUILayout.EndHorizontal(); } } GUILayout.EndVertical(); if (flag) { entry.BoxedValue = Serialize(list2); } } public static List<RecipeItemEntry> Deserialize(string rawRecipeString) { List<RecipeItemEntry> list = new List<RecipeItemEntry>(); if (string.IsNullOrWhiteSpace(rawRecipeString)) { return list; } string[] array = rawRecipeString.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Trim().Split(new char[1] { ':' }); string prefabName = array2[0].Trim(); int amount = 1; if (array2.Length > 1 && int.TryParse(array2[1].Trim(), out var result)) { amount = result; } list.Add(new RecipeItemEntry(prefabName, amount)); } return list; } public static string Serialize(IEnumerable<RecipeItemEntry> entries) { if (entries == null) { return string.Empty; } return string.Join(','.ToString(), entries.Select((RecipeItemEntry entry) => $"{entry.PrefabName.Trim()}{':'}{Mathf.Max(1, entry.Amount)}")); } } }