using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("ElementalStorms")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyDescription("A progression-driven storm system that adds dynamic hazards and atmospheric effects based on boss progression")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("ElementalStorms")] [assembly: AssemblyTitle("ElementalStorms")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ElementalStorms { [BepInPlugin("com.ruijven.elementalstorms", "ElementalStorms", "1.0.0")] internal class ElementalStormsPlugin : BaseUnityPlugin { private class StormClonerRunner : MonoBehaviour { private void Update() { if ((Object)(object)Player.m_localPlayer != (Object)null && (Object)(object)EnvMan.instance != (Object)null) { StormEnvironmentCloner.Initialize(); Object.Destroy((Object)(object)((Component)this).gameObject); } } } public const string PluginGUID = "com.ruijven.elementalstorms"; public const string PluginName = "ElementalStorms"; public const string PluginVersion = "1.0.0"; internal static ManualLogSource Logger; public static ConfigEntry EnableMod; public static ConfigEntry EnableStructuralDamage; public static ConfigEntry DungeonProtectionAltitude; public static ConfigEntry StructuralDamageAmount; public static float s_hudMessageTimer; public static bool s_hudMessageActive; public const float HUD_MESSAGE_DURATION = 5f; internal static ElementalStormsPlugin Instance { get; private set; } private void Awake() { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown Instance = this; Logger = ((BaseUnityPlugin)this).Logger; InitializeConfig(); ScheduleStormCloning(); ProjectileSpawner.Initialize(); StatusEffectManager.Initialize(); CreateUpdaterComponents(); CreateStormEventManager(); Harmony val = new Harmony("com.ruijven.elementalstorms"); val.PatchAll(Assembly.GetExecutingAssembly()); Logger.LogInfo((object)"ElementalStorms v1.0.0 loaded successfully!"); Logger.LogInfo((object)"Progression-driven storm hazards activated!"); } private void CreateUpdaterComponents() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown GameObject val = new GameObject("ElementalWeather_Updaters"); Object.DontDestroyOnLoad((Object)(object)val); val.AddComponent(); val.AddComponent(); } private void CreateStormEventManager() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown GameObject val = new GameObject("ElementalStorms_StormEventManager"); Object.DontDestroyOnLoad((Object)(object)val); val.AddComponent(); } private void ScheduleStormCloning() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown GameObject val = new GameObject("ElementalWeather_StormCloner"); Object.DontDestroyOnLoad((Object)(object)val); val.AddComponent(); } private void InitializeConfig() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Expected O, but got Unknown //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Expected O, but got Unknown EnableMod = ((BaseUnityPlugin)this).Config.Bind("General", "EnableMod", true, new ConfigDescription("Master toggle for the entire ElementalWeather mod.", (AcceptableValueBase)null, Array.Empty())); EnableStructuralDamage = ((BaseUnityPlugin)this).Config.Bind("Structural Damage", "EnableStructuralDamage", true, new ConfigDescription("Enable wind damage to exposed structures.", (AcceptableValueBase)null, Array.Empty())); DungeonProtectionAltitude = ((BaseUnityPlugin)this).Config.Bind("General", "DungeonProtectionAltitude", 2000f, new ConfigDescription("Altitude threshold above which weather hazards are disabled (protects dungeons).", (AcceptableValueBase)(object)new AcceptableValueRange(1000f, 5000f), Array.Empty())); StructuralDamageAmount = ((BaseUnityPlugin)this).Config.Bind("Structural Damage", "StructuralDamageAmount", 0.5f, new ConfigDescription("Damage dealt to structures per update when conditions are met.", (AcceptableValueBase)(object)new AcceptableValueRange(0.1f, 10f), Array.Empty())); } public static bool IsInDungeonAltitude() { //IL_0055: Unknown result type (might be due to invalid IL or missing references) if (EnableMod == null) { return false; } if (!EnableMod.Value) { return false; } if (DungeonProtectionAltitude == null) { return false; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return false; } return ((Component)localPlayer).transform.position.y > DungeonProtectionAltitude.Value; } public static bool IsBossDefeated(string bossKey) { if ((Object)(object)ZoneSystem.instance == (Object)null) { return false; } return ZoneSystem.instance.GetGlobalKey(bossKey); } public static void ShowWeatherWarning(string message) { if ((Object)(object)MessageHud.instance != (Object)null) { MessageHud.instance.ShowMessage((MessageType)2, message, 0, (Sprite)null, false); } } public static void ShowWeatherWarningTopLeft(string message) { if ((Object)(object)MessageHud.instance != (Object)null) { MessageHud.instance.ShowMessage((MessageType)1, message, 0, (Sprite)null, false); s_hudMessageActive = true; s_hudMessageTimer = 0f; } } public static void ShowWeatherWarningTopCenter(string message) { if ((Object)(object)MessageHud.instance != (Object)null) { MessageHud.instance.ShowMessage((MessageType)2, message, 0, (Sprite)null, false); s_hudMessageActive = true; s_hudMessageTimer = 0f; } } } public class HUDMessageUpdater : MonoBehaviour { private void Update() { if (!ElementalStormsPlugin.s_hudMessageActive) { return; } ElementalStormsPlugin.s_hudMessageTimer += Time.deltaTime; if (ElementalStormsPlugin.s_hudMessageTimer >= 5f) { ElementalStormsPlugin.s_hudMessageActive = false; ElementalStormsPlugin.s_hudMessageTimer = 0f; if ((Object)(object)MessageHud.instance != (Object)null) { MessageHud.instance.ShowMessage((MessageType)1, "", 0, (Sprite)null, false); } } } } public class ElementalStormManager : MonoBehaviour { private float checkTimer = 0f; private const float CheckInterval = 1656f; private const float TriggerChance = 0.2f; private void Awake() { } private void Update() { if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer()) { checkTimer += Time.deltaTime; if (checkTimer >= 1656f) { checkTimer = 0f; TryTriggerElementalStorm(); } } } private void TryTriggerElementalStorm() { if (Random.value > 0.2f) { return; } List list = new List(); if (ZoneSystem.instance.GetGlobalKey("defeated_eikthyr")) { list.Add("ES_Eikthyr"); } if (ZoneSystem.instance.GetGlobalKey("defeated_gdking")) { list.Add("ES_Elder"); } if (ZoneSystem.instance.GetGlobalKey("defeated_bonemass")) { list.Add("ES_Bonemass"); } if (ZoneSystem.instance.GetGlobalKey("defeated_moder")) { list.Add("ES_Moder"); } if (ZoneSystem.instance.GetGlobalKey("defeated_goblinking")) { list.Add("ES_Yagluth"); } if (ZoneSystem.instance.GetGlobalKey("defeated_thequeen")) { list.Add("ES_Queen"); } if (ZoneSystem.instance.GetGlobalKey("defeated_fader")) { list.Add("ES_Fader"); } if (list.Count == 0) { return; } string stormName = list[Random.Range(0, list.Count)]; Player randomActivePlayer = GetRandomActivePlayer(); if ((Object)(object)randomActivePlayer != (Object)null) { if (IsNearActiveBoss(randomActivePlayer)) { ElementalStormsPlugin.Logger.LogInfo((object)"ElementalStorm: Aborted trigger. Target player is in a boss fight."); } else { TriggerStormForPlayer(randomActivePlayer, stormName); } } } private bool IsNearActiveBoss(Player player) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) float num = 150f; List list = new List(); Character.GetCharactersInRange(((Component)player).transform.position, num, list); foreach (Character item in list) { if (item.IsBoss() && !item.IsDead()) { return true; } } return false; } private Player GetRandomActivePlayer() { List list = new List(); foreach (Player allPlayer in Player.GetAllPlayers()) { if ((Object)(object)allPlayer != (Object)null) { list.Add(allPlayer); } } if (list.Count == 0) { return null; } return list[Random.Range(0, list.Count)]; } private void TriggerStormForPlayer(Player player, string stormName) { if ((Object)(object)EnvMan.instance != (Object)null) { EnvSetup customStorm = StormEnvironmentCloner.GetCustomStorm(stormName); if (customStorm != null) { EnvMan.instance.SetEnv(customStorm, 0f, 0f, 0f, 0f, 0f); ElementalStormsPlugin.Logger.LogInfo((object)("ElementalStorm: Triggered " + stormName + " for player " + player.GetPlayerName())); ElementalStormsPlugin.ShowWeatherWarningTopCenter(stormName.Replace("ES_", "") + "'s storm is approaching!"); } else { ElementalStormsPlugin.Logger.LogWarning((object)("ElementalStorm: Could not find storm environment " + stormName)); } } } } public class LightningSystem { private static LightningSystem s_instance; private float m_lightningTimer = 0f; private float m_nextLightningTime = 0f; private bool m_isActive = false; public static LightningSystem Instance { get { if (s_instance == null) { s_instance = new LightningSystem(); } return s_instance; } } private LightningSystem() { ResetTimer(); } public void Update(float dt) { if (ElementalStormsPlugin.EnableMod == null) { return; } if (!ElementalStormsPlugin.EnableMod.Value) { m_isActive = false; return; } if ((Object)(object)Player.m_localPlayer != (Object)null && ((Character)Player.m_localPlayer).IsDead()) { m_isActive = false; return; } bool flag = ShouldBeActive(); if (flag && !m_isActive) { m_isActive = true; ResetTimer(); ElementalStormsPlugin.Logger.LogDebug((object)"Lightning system activated"); } else if (!flag && m_isActive) { m_isActive = false; ElementalStormsPlugin.Logger.LogDebug((object)"Lightning system deactivated"); return; } if (m_isActive && !ElementalStormsPlugin.IsInDungeonAltitude()) { m_lightningTimer += dt; if (m_lightningTimer >= m_nextLightningTime) { StrikeLightning(); ResetTimer(); } } } private bool ShouldBeActive() { if ((Object)(object)EnvMan.instance == (Object)null) { return false; } if (EnvMan.instance.m_currentEnv == null) { return false; } string name = EnvMan.instance.m_currentEnv.m_name; return name == "Eikthyr" || name == "ES_Eikthyr"; } private void ResetTimer() { m_lightningTimer = 0f; float num = 4f; float num2 = 12f; m_nextLightningTime = Random.Range(num, num2); } private void StrikeLightning() { //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: 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_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead()) { return; } float radialDistance = GetRadialDistance(); if (radialDistance < 0f) { ElementalStormsPlugin.Logger.LogDebug((object)"Lightning strike skipped (RNG roll)"); return; } if (localPlayer.InShelter() && radialDistance < 50f) { ElementalStormsPlugin.Logger.LogDebug((object)"Lightning strike skipped (player in shelter, distance < 50m)"); return; } Vector3 val = CalculateStrikePosition(((Component)localPlayer).transform.position, radialDistance); if ((Object)(object)ZoneSystem.instance != (Object)null) { val.y = ZoneSystem.instance.GetSolidHeight(val); } CreateLightningEffect(val); ApplyLightningDamage(val); ElementalStormsPlugin.Logger.LogDebug((object)$"Lightning struck at position: {val}"); } private Vector3 CalculateStrikePosition(Vector3 playerPosition, float distance) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) float num = Random.Range(0f, MathF.PI * 2f); Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(Mathf.Cos(num) * distance, 0f, Mathf.Sin(num) * distance); return playerPosition + val; } private float GetRadialDistance() { float num = Random.Range(0f, 1f); if (num < 0.05f) { return Random.Range(0f, 10f); } if (num < 0.55f) { return Random.Range(10f, 25f); } if (num < 0.8f) { return Random.Range(25f, 35f); } return -1f; } private void CreateLightningEffect(Vector3 position) { //IL_0012: 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) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZNetScene.instance == (Object)null) { CreateFallbackLightningEffect(position); return; } GameObject prefab = ZNetScene.instance.GetPrefab("fx_eikthyr_stomp"); if ((Object)(object)prefab != (Object)null) { GameObject val = Object.Instantiate(prefab, position, Quaternion.identity); ZNetView component = val.GetComponent(); if ((Object)(object)component == (Object)null && (Object)(object)val != (Object)null) { Object.Destroy((Object)(object)val, 1f); } } else { CreateFallbackLightningEffect(position); } } private void CreateFallbackLightningEffect(Vector3 position) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("LightningFlash"); val.transform.position = position; Light val2 = val.AddComponent(); val2.type = (LightType)2; val2.color = Color.white; val2.intensity = 10f; val2.range = 50f; Object.Destroy((Object)(object)val, 0.1f); } private void ApplyLightningDamage(Vector3 position) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown //IL_0073: 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_0093: 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_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Expected O, but got Unknown //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) float baseDamage = 20f; float num = CalculateScaledDamage(baseDamage); float num2 = 4f; Collider[] array = Physics.OverlapSphere(position, num2); Collider[] array2 = array; foreach (Collider val in array2) { Player component = ((Component)val).GetComponent(); if ((Object)(object)component != (Object)null && !component.InShelter()) { HitData val2 = new HitData(); val2.m_damage.m_lightning = num; val2.m_attacker = default(ZDOID); val2.m_pushForce = 10f; Vector3 val3 = ((Component)component).transform.position - position; val2.m_dir = ((Vector3)(ref val3)).normalized; ((Character)component).Damage(val2); ElementalStormsPlugin.Logger.LogDebug((object)$"Lightning dealt {num} damage to player"); continue; } WearNTear component2 = ((Component)val).GetComponent(); if ((Object)(object)component2 != (Object)null && (Object)(object)component2.m_piece != (Object)null) { HitData val4 = new HitData(); val4.m_damage.m_lightning = num; val4.m_attacker = default(ZDOID); val4.m_pushForce = 5f; val4.m_dir = Vector3.up; component2.Damage(val4); ElementalStormsPlugin.Logger.LogDebug((object)$"Lightning dealt {num} damage to structure: {((Object)component2).name}"); } } } private float CalculateScaledDamage(float baseDamage) { int num = 0; if (ElementalStormsPlugin.IsBossDefeated("defeated_eikthyr")) { num++; } if (ElementalStormsPlugin.IsBossDefeated("defeated_gdking")) { num++; } if (ElementalStormsPlugin.IsBossDefeated("defeated_bonemass")) { num++; } if (ElementalStormsPlugin.IsBossDefeated("defeated_moder")) { num++; } if (ElementalStormsPlugin.IsBossDefeated("defeated_goblinking")) { num++; } if (ElementalStormsPlugin.IsBossDefeated("defeated_thequeen")) { num++; } float num2 = 1f + (float)num * 0.1f; return baseDamage * num2; } public void ForceStrike(Vector3 position) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) if (ElementalStormsPlugin.EnableMod.Value) { CreateLightningEffect(position); ApplyLightningDamage(position); } } public string GetDebugInfo() { return $"Lightning System - Active: {m_isActive}, Timer: {m_lightningTimer:F1}s/{m_nextLightningTime:F1}s"; } } public class FireballSystem { private static FireballSystem s_instance; private float m_fireballTimer = 0f; private float m_nextFireballTime = 0f; private bool m_isActive = false; public static FireballSystem Instance { get { if (s_instance == null) { s_instance = new FireballSystem(); } return s_instance; } } private FireballSystem() { ResetTimer(); } public void Update(float dt) { if (ElementalStormsPlugin.EnableMod == null) { return; } if (!ElementalStormsPlugin.EnableMod.Value) { m_isActive = false; return; } if ((Object)(object)Player.m_localPlayer != (Object)null && ((Character)Player.m_localPlayer).IsDead()) { m_isActive = false; return; } bool flag = ShouldBeActive(); if (flag && !m_isActive) { m_isActive = true; ResetTimer(); ElementalStormsPlugin.Logger.LogDebug((object)"Fireball system activated"); } else if (!flag && m_isActive) { m_isActive = false; ElementalStormsPlugin.Logger.LogDebug((object)"Fireball system deactivated"); return; } if (m_isActive && !ElementalStormsPlugin.IsInDungeonAltitude()) { m_fireballTimer += dt; if (m_fireballTimer >= m_nextFireballTime) { DropFireball(); ResetTimer(); } } } private bool ShouldBeActive() { if ((Object)(object)EnvMan.instance == (Object)null) { return false; } if (EnvMan.instance.m_currentEnv == null) { return false; } string name = EnvMan.instance.m_currentEnv.m_name; return name == "Fader" || name == "GoblinKing"; } private void ResetTimer() { m_fireballTimer = 0f; float num = 2f; float num2 = 9f; m_nextFireballTime = Random.Range(num, num2); } private void DropFireball() { //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead()) { return; } float radialDistance = GetRadialDistance(); if (radialDistance < 0f) { ElementalStormsPlugin.Logger.LogDebug((object)"Fireball dropped (RNG roll)"); return; } if (localPlayer.InShelter() && radialDistance < 10f) { ElementalStormsPlugin.Logger.LogDebug((object)"Meteor skipped (player in shelter, distance < 10m)"); return; } Vector3 val = CalculateDropPosition(((Component)localPlayer).transform.position, radialDistance); if ((Object)(object)ZoneSystem.instance != (Object)null) { val.y = ZoneSystem.instance.GetSolidHeight(val); } CreateFireballEffect(val); ElementalStormsPlugin.Logger.LogDebug((object)$"Meteor dropped at position: {val}"); } private Vector3 CalculateDropPosition(Vector3 playerPosition, float distance) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) float num = Random.Range(0f, MathF.PI * 2f); Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(Mathf.Cos(num) * distance, 0f, Mathf.Sin(num) * distance); return playerPosition + val; } private float GetRadialDistance() { float num = Random.Range(0f, 1f); if (num < 0.01f) { return Random.Range(0f, 10f); } if (num < 0.16f) { return Random.Range(10f, 50f); } if (num < 0.36f) { return Random.Range(50f, 100f); } return -1f; } private void CreateFireballEffect(Vector3 position) { //IL_0012: 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_00e2: 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) if ((Object)(object)ZNetScene.instance == (Object)null) { CreateFallbackFireballEffect(position); return; } string name = EnvMan.instance.m_currentEnv.m_name; GameObject val = null; if (name == "GoblinKing") { val = ZNetScene.instance.GetPrefab("projectile_meteor"); } else if (name == "Fader") { val = ZNetScene.instance.GetPrefab("projectile_ashlandmeteor"); if ((Object)(object)val == (Object)null) { val = ZNetScene.instance.GetPrefab("projectile_ashlandmeteor2"); } } if ((Object)(object)val == (Object)null) { val = ZNetScene.instance.GetPrefab("fx_bonemass_explosion"); } if ((Object)(object)val == (Object)null) { val = ZNetScene.instance.GetPrefab("fx_eikthyr_stomp"); } if ((Object)(object)val != (Object)null) { GameObject val2 = Object.Instantiate(val, position, Quaternion.identity); ZNetView component = val2.GetComponent(); if ((Object)(object)component == (Object)null) { MeteorSmash component2 = val2.GetComponent(); if ((Object)(object)component2 == (Object)null && (Object)(object)val2 != (Object)null) { Object.Destroy((Object)(object)val2, 1f); } } } else { CreateFallbackFireballEffect(position); } } private void CreateFallbackFireballEffect(Vector3 position) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("FireballFlash"); val.transform.position = position; Light val2 = val.AddComponent(); val2.type = (LightType)2; val2.color = Color.red; val2.intensity = 10f; val2.range = 50f; Object.Destroy((Object)(object)val, 0.1f); } private void ApplyFireballDamage(Vector3 position) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown //IL_0073: 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_0093: 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_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Expected O, but got Unknown //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) float baseDamage = 15f; float num = CalculateScaledDamage(baseDamage); float num2 = 4f; Collider[] array = Physics.OverlapSphere(position, num2); Collider[] array2 = array; foreach (Collider val in array2) { Player component = ((Component)val).GetComponent(); if ((Object)(object)component != (Object)null && !component.InShelter()) { HitData val2 = new HitData(); val2.m_damage.m_fire = num; val2.m_attacker = default(ZDOID); val2.m_pushForce = 5f; Vector3 val3 = ((Component)component).transform.position - position; val2.m_dir = ((Vector3)(ref val3)).normalized; ((Character)component).Damage(val2); ElementalStormsPlugin.Logger.LogDebug((object)$"Fireball dealt {num} fire damage to player"); continue; } WearNTear component2 = ((Component)val).GetComponent(); if ((Object)(object)component2 != (Object)null && (Object)(object)component2.m_piece != (Object)null) { HitData val4 = new HitData(); val4.m_damage.m_fire = num; val4.m_attacker = default(ZDOID); val4.m_pushForce = 3f; val4.m_dir = Vector3.up; component2.Damage(val4); ElementalStormsPlugin.Logger.LogDebug((object)$"Fireball dealt {num} fire damage to structure: {((Object)component2).name}"); } } } private float CalculateScaledDamage(float baseDamage) { int num = 0; if (ElementalStormsPlugin.IsBossDefeated("defeated_eikthyr")) { num++; } if (ElementalStormsPlugin.IsBossDefeated("defeated_gdking")) { num++; } if (ElementalStormsPlugin.IsBossDefeated("defeated_bonemass")) { num++; } if (ElementalStormsPlugin.IsBossDefeated("defeated_moder")) { num++; } if (ElementalStormsPlugin.IsBossDefeated("defeated_goblinking")) { num++; } if (ElementalStormsPlugin.IsBossDefeated("defeated_thequeen")) { num++; } float num2 = 1f + (float)num * 0.1f; return baseDamage * num2; } public string GetDebugInfo() { return $"Fireball System - Active: {m_isActive}, Timer: {m_fireballTimer:F1}s/{m_nextFireballTime:F1}s"; } } public class LightningSystemUpdater : MonoBehaviour { private void Update() { LightningSystem.Instance.Update(Time.deltaTime); FireballSystem.Instance.Update(Time.deltaTime); } } [HarmonyPatch] internal class ElementalWeatherPatches { private static string s_previousWeather; [HarmonyPatch(typeof(EnvMan), "SetEnv")] [HarmonyPostfix] private static void OnEnvironmentChanged() { if (ElementalStormsPlugin.EnableMod == null || !ElementalStormsPlugin.EnableMod.Value || (Object)(object)EnvMan.instance == (Object)null || EnvMan.instance.m_currentEnv == null || (Object)(object)Player.m_localPlayer == (Object)null) { return; } string name = EnvMan.instance.m_currentEnv.m_name; if (s_previousWeather != null && s_previousWeather != name) { ElementalStormsPlugin.Logger.LogInfo((object)("[DEBUG] Weather system ending: " + s_previousWeather)); ElementalStormsPlugin.Logger.LogInfo((object)("[DEBUG] Weather system starting: " + name)); } s_previousWeather = name; switch (name) { case "Eikthyr": if (ElementalStormsPlugin.IsBossDefeated("defeated_eikthyr")) { ElementalStormsPlugin.ShowWeatherWarningTopCenter("Eikthyr's Thunderstorm"); } break; case "GDKing": if (ElementalStormsPlugin.IsBossDefeated("defeated_gdking")) { ElementalStormsPlugin.ShowWeatherWarningTopCenter("The Elder's Curse"); } break; case "Bonemass": if (ElementalStormsPlugin.IsBossDefeated("defeated_bonemass")) { ElementalStormsPlugin.ShowWeatherWarningTopCenter("Poisoned Rain"); } break; case "Moder": if (ElementalStormsPlugin.IsBossDefeated("defeated_moder")) { ElementalStormsPlugin.ShowWeatherWarningTopCenter("Blizzard"); } break; case "GoblinKing": if (ElementalStormsPlugin.IsBossDefeated("defeated_goblinking")) { ElementalStormsPlugin.ShowWeatherWarningTopCenter("Yagluth's Curse"); } break; case "Queen": if (ElementalStormsPlugin.IsBossDefeated("defeated_thequeen")) { ElementalStormsPlugin.ShowWeatherWarningTopCenter("Creeping Mist"); } break; case "Fader": if (ElementalStormsPlugin.IsBossDefeated("defeated_fader")) { ElementalStormsPlugin.ShowWeatherWarningTopCenter("Fader's Tears"); } break; } } } public static class PrefabDiscoverySystem { private class DiscoveryRunner : MonoBehaviour { private float m_delayTimer = 0f; private const float INITIALIZATION_DELAY = 5f; private void Update() { m_delayTimer += Time.deltaTime; if (m_delayTimer >= 5f) { if ((Object)(object)EnvMan.instance != (Object)null && (Object)(object)ZNetScene.instance != (Object)null) { ElementalStormsPlugin.Logger.LogInfo((object)"Game systems initialized, running prefab discovery..."); RunDiscovery(); Object.Destroy((Object)(object)((Component)this).gameObject); } else if (m_delayTimer >= 15f) { ElementalStormsPlugin.Logger.LogWarning((object)("Prefab discovery timeout - core systems not available. EnvMan: " + ((Object)(object)EnvMan.instance != (Object)null) + ", ZNetScene: " + ((Object)(object)ZNetScene.instance != (Object)null))); Object.Destroy((Object)(object)((Component)this).gameObject); } } } } private static bool s_hasRun = false; private static bool s_hasScheduled = false; private static readonly string DISCOVERY_FILE_PATH = Paths.ConfigPath + "/ElementalStorms_PrefabDiscovery.txt"; public static void ScheduleDiscovery() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown if (s_hasScheduled) { ElementalStormsPlugin.Logger.LogInfo((object)"Prefab discovery already scheduled, skipping."); return; } s_hasScheduled = true; ElementalStormsPlugin.Logger.LogInfo((object)"Scheduling prefab discovery system..."); GameObject val = new GameObject("ElementalWeather_Discovery"); Object.DontDestroyOnLoad((Object)(object)val); val.AddComponent(); } public static void RunDiscovery() { if (s_hasRun) { ElementalStormsPlugin.Logger.LogInfo((object)"Prefab discovery already run, skipping."); return; } s_hasRun = true; ElementalStormsPlugin.Logger.LogInfo((object)"Starting prefab discovery system..."); try { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("=== Elemental Storms - Prefab Discovery Log ==="); stringBuilder.AppendLine($"Generated: {DateTime.Now:yyyy-MM-dd HH:mm:ss}"); stringBuilder.AppendLine("Valheim Version: " + Application.version); stringBuilder.AppendLine(); DiscoverEnvironments(stringBuilder); DiscoverZNetScenePrefabs(stringBuilder); File.WriteAllText(DISCOVERY_FILE_PATH, stringBuilder.ToString()); ElementalStormsPlugin.Logger.LogInfo((object)("Prefab discovery complete. Log saved to: " + DISCOVERY_FILE_PATH)); } catch (Exception ex) { ElementalStormsPlugin.Logger.LogError((object)("Prefab discovery failed: " + ex.Message)); ElementalStormsPlugin.Logger.LogError((object)ex.StackTrace); } } private static void DiscoverEnvironments(StringBuilder logBuilder) { logBuilder.AppendLine("=== AVAILABLE ENVIRONMENTS ==="); if ((Object)(object)EnvMan.instance == (Object)null) { logBuilder.AppendLine("EnvMan.instance is null - cannot discover environments."); logBuilder.AppendLine(); return; } FieldInfo field = typeof(EnvMan).GetField("m_environments", BindingFlags.Instance | BindingFlags.NonPublic); if (field == null) { logBuilder.AppendLine("Could not access m_environments field via reflection."); logBuilder.AppendLine(); return; } if (!(field.GetValue(EnvMan.instance) is List list)) { logBuilder.AppendLine("m_environments is null or not a List."); logBuilder.AppendLine(); return; } logBuilder.AppendLine($"Total environments found: {list.Count}"); logBuilder.AppendLine(); List list2 = (from e in list where IsBossEnvironment(e.m_name) orderby e.m_name select e).ToList(); List list3 = (from e in list where IsBiomeEnvironment(e.m_name) orderby e.m_name select e).ToList(); List list4 = (from e in list where IsWeatherEnvironment(e.m_name) orderby e.m_name select e).ToList(); List list5 = (from e in list where !IsBossEnvironment(e.m_name) && !IsBiomeEnvironment(e.m_name) && !IsWeatherEnvironment(e.m_name) orderby e.m_name select e).ToList(); if (list2.Count > 0) { logBuilder.AppendLine("--- BOSS ENVIRONMENTS ---"); foreach (EnvSetup item in list2) { LogEnvironmentDetails(item, logBuilder); } logBuilder.AppendLine(); } if (list3.Count > 0) { logBuilder.AppendLine("--- BIOME ENVIRONMENTS ---"); foreach (EnvSetup item2 in list3) { LogEnvironmentDetails(item2, logBuilder); } logBuilder.AppendLine(); } if (list4.Count > 0) { logBuilder.AppendLine("--- WEATHER ENVIRONMENTS ---"); foreach (EnvSetup item3 in list4) { LogEnvironmentDetails(item3, logBuilder); } logBuilder.AppendLine(); } if (list5.Count <= 0) { return; } logBuilder.AppendLine("--- OTHER ENVIRONMENTS ---"); foreach (EnvSetup item4 in list5) { LogEnvironmentDetails(item4, logBuilder); } logBuilder.AppendLine(); } private static void LogEnvironmentDetails(EnvSetup env, StringBuilder logBuilder) { logBuilder.AppendLine("Name: " + env.m_name); logBuilder.AppendLine($" Default: {env.m_default}"); logBuilder.AppendLine($" Wet: {env.m_isWet}, Freezing: {env.m_isFreezing}, Cold: {env.m_isCold}"); logBuilder.AppendLine($" Always Dark: {env.m_alwaysDark}"); logBuilder.AppendLine($" Wind Min: {env.m_windMin}, Wind Max: {env.m_windMax}"); if (env.m_psystems != null && env.m_psystems.Length != 0) { logBuilder.AppendLine($" Particle Systems ({env.m_psystems.Length}):"); for (int i = 0; i < env.m_psystems.Length; i++) { if ((Object)(object)env.m_psystems[i] != (Object)null) { logBuilder.AppendLine($" [{i}] {((Object)env.m_psystems[i]).name}"); } } } if ((Object)(object)env.m_envObject != (Object)null) { logBuilder.AppendLine(" Environment Object: " + ((Object)env.m_envObject).name); } AudioClip ambientLoop = env.m_ambientLoop; if (!string.IsNullOrEmpty((ambientLoop != null) ? ((Object)ambientLoop).name : null)) { logBuilder.AppendLine(" Ambient Loop: " + ((Object)env.m_ambientLoop).name); } logBuilder.AppendLine(); } private static void DiscoverZNetScenePrefabs(StringBuilder logBuilder) { logBuilder.AppendLine("=== ZNETSCENE PREFABS ==="); if ((Object)(object)ZNetScene.instance == (Object)null) { logBuilder.AppendLine("ZNetScene.instance is null - cannot discover prefabs."); logBuilder.AppendLine(); return; } FieldInfo field = typeof(ZNetScene).GetField("m_namedPrefabs", BindingFlags.Instance | BindingFlags.NonPublic); if (field == null) { logBuilder.AppendLine("Could not access m_namedPrefabs field via reflection."); logBuilder.AppendLine(); return; } if (!(field.GetValue(ZNetScene.instance) is Dictionary dictionary)) { logBuilder.AppendLine("m_namedPrefabs is null or not a Dictionary."); logBuilder.AppendLine(); return; } logBuilder.AppendLine($"Total prefabs found: {dictionary.Count}"); logBuilder.AppendLine(); List list = (from p in dictionary.Values where (Object)(object)p != (Object)null where IsStormRelatedPrefab(((Object)p).name) orderby ((Object)p).name select p).ToList(); if (list.Count > 0) { logBuilder.AppendLine("--- STORM-RELATED PREFABS ---"); foreach (GameObject item in list) { logBuilder.AppendLine(" " + ((Object)item).name); } logBuilder.AppendLine(); } List list2 = (from p in dictionary.Values where (Object)(object)p != (Object)null where IsBossRelatedPrefab(((Object)p).name) orderby ((Object)p).name select p).ToList(); if (list2.Count <= 0) { return; } logBuilder.AppendLine("--- BOSS-RELATED PREFABS ---"); foreach (GameObject item2 in list2) { logBuilder.AppendLine(" " + ((Object)item2).name); } logBuilder.AppendLine(); } private static bool IsBossEnvironment(string name) { if (string.IsNullOrEmpty(name)) { return false; } string text = name.ToLower(); return text.Contains("eikthyr") || text.Contains("gdking") || text.Contains("elder") || text.Contains("bonemass") || text.Contains("moder") || text.Contains("dragon") || text.Contains("goblin") || text.Contains("yagluth") || text.Contains("queen") || text.Contains("seeker") || text.Contains("fader"); } private static bool IsBiomeEnvironment(string name) { if (string.IsNullOrEmpty(name)) { return false; } string text = name.ToLower(); return text.Contains("meadow") || text.Contains("forest") || text.Contains("blackforest") || text.Contains("swamp") || text.Contains("mountain") || text.Contains("plains") || text.Contains("mistland") || text.Contains("ashland") || text.Contains("deepnorth") || text.Contains("ocean") || text.Contains("ashlands"); } private static bool IsWeatherEnvironment(string name) { if (string.IsNullOrEmpty(name)) { return false; } string text = name.ToLower(); return text.Contains("rain") || text.Contains("thunder") || text.Contains("snow") || text.Contains("storm") || text.Contains("fog") || text.Contains("mist") || text.Contains("clear") || text.Contains("cinder") || text.Contains("cloud"); } private static bool IsStormRelatedPrefab(string name) { if (string.IsNullOrEmpty(name)) { return false; } string text = name.ToLower(); return text.Contains("meteor") || text.Contains("fireball") || text.Contains("lightning") || text.Contains("thunder") || text.Contains("rain") || text.Contains("snow") || text.Contains("fog") || text.Contains("mist") || text.Contains("storm") || text.Contains("tornado") || text.Contains("wind") || text.Contains("cinder") || text.Contains("ash"); } private static bool IsBossRelatedPrefab(string name) { if (string.IsNullOrEmpty(name)) { return false; } string text = name.ToLower(); return text.Contains("eikthyr") || text.Contains("gd_king") || text.Contains("gdking") || text.Contains("elder") || text.Contains("bonemass") || text.Contains("moder") || text.Contains("dragon") || text.Contains("goblin") || text.Contains("yagluth") || text.Contains("queen") || text.Contains("seeker") || text.Contains("fader") || text.Contains("boss"); } } public static class ProjectileSpawner { public class ProjectileConfig { public string PrefabName { get; set; } public float SpawnInterval { get; set; } = 5f; public float MinDistance { get; set; } = 1f; public float MaxDistance { get; set; } = 5f; public float Damage { get; set; } = 10f; public string StormName { get; set; } public string BossKey { get; set; } public float DamageMultiplier { get; set; } = 1f; public float SpawnRadius { get; set; } = 0f; public int SpawnCount { get; set; } = 1; public bool CheckEnvActive { get; set; } = false; } private class ProjectileSpawnerUpdater : MonoBehaviour { private Dictionary> m_spawnTimers = new Dictionary>(); private Dictionary> m_spawnedObjects = new Dictionary>(); private void Start() { foreach (KeyValuePair> s_projectileConfig in s_projectileConfigs) { m_spawnTimers[s_projectileConfig.Key] = new Dictionary(); foreach (ProjectileConfig item in s_projectileConfig.Value) { m_spawnTimers[s_projectileConfig.Key][item.PrefabName] = 0f; } m_spawnedObjects[s_projectileConfig.Key] = new List(); } } private void Update() { string text = (((Object)(object)EnvMan.instance != (Object)null) ? EnvMan.instance.GetCurrentEnvironment().m_name : ""); if (text == "ES_Queen" && (Object)(object)Player.m_localPlayer != (Object)null && !Object.op_Implicit((Object)(object)((Component)Player.m_localPlayer).GetComponent())) { TriggerQueenMist(); } foreach (KeyValuePair> s_projectileConfig in s_projectileConfigs) { string key = s_projectileConfig.Key; List value = s_projectileConfig.Value; string text2 = ((value.Count > 0) ? value[0].StormName : key); if (text != text2) { if (!m_spawnedObjects.ContainsKey(key)) { continue; } foreach (GameObject item in m_spawnedObjects[key]) { if ((Object)(object)item != (Object)null) { Object.Destroy((Object)(object)item); } } m_spawnedObjects[key].Clear(); continue; } foreach (ProjectileConfig item2 in value) { m_spawnTimers[key][item2.PrefabName] += Time.deltaTime; if (m_spawnTimers[key][item2.PrefabName] >= item2.SpawnInterval) { m_spawnTimers[key][item2.PrefabName] = 0f; TrySpawnProjectile(item2); } } } } private void TrySpawnProjectile(ProjectileConfig config) { if (!ElementalStormsPlugin.IsBossDefeated(config.BossKey)) { ElementalStormsPlugin.Logger.LogDebug((object)("Boss " + config.BossKey + " not defeated, skipping spawn of " + config.PrefabName)); } else { if ((Object)(object)EnvMan.instance == (Object)null) { return; } string name = EnvMan.instance.GetCurrentEnvironment().m_name; if (name != config.StormName) { ElementalStormsPlugin.Logger.LogDebug((object)("Current env " + name + " != " + config.StormName + ", skipping spawn of " + config.PrefabName)); return; } if (config.CheckEnvActive) { } Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { float minDistance = (localPlayer.InShelter() ? 20f : config.MinDistance); float maxDistance = (localPlayer.InShelter() ? 35f : config.MaxDistance); SpawnPrefabNearPlayer(config, localPlayer, minDistance, maxDistance); } } } private void SpawnPrefabNearPlayer(ProjectileConfig config, Player player, float minDistance, float maxDistance) { //IL_0008: 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_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_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007b: 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) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0038: 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_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) try { Vector3 position = ((Component)player).transform.position; Vector3 val = position; int num = ((config.SpawnCount <= 0) ? 1 : config.SpawnCount); if (config.SpawnRadius > 0f) { val = position; num = 1; } else { float num2 = Random.Range(minDistance, maxDistance); float num3 = Random.Range(0f, 360f); Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(Mathf.Cos(num3) * num2, 0f, Mathf.Sin(num3) * num2); val = position + val2; } if ((Object)(object)ZNetScene.instance == (Object)null) { ElementalStormsPlugin.Logger.LogWarning((object)"ZNetScene.instance is null, cannot spawn prefab."); return; } GameObject prefab = ZNetScene.instance.GetPrefab(StringExtensionMethods.GetStableHashCode(config.PrefabName)); if ((Object)(object)prefab == (Object)null) { ElementalStormsPlugin.Logger.LogWarning((object)("Could not find prefab: " + config.PrefabName)); return; } ElementalStormsPlugin.Logger.LogDebug((object)$"Spawning prefab {config.PrefabName} at {val}"); for (int i = 0; i < num; i++) { GameObject val3 = Object.Instantiate(prefab, val, Quaternion.identity); if (config.SpawnRadius > 0f && config.PrefabName == "MistArea") { Mister val4 = val3.GetComponent(); if ((Object)(object)val4 == (Object)null) { val4 = val3.AddComponent(); ElementalStormsPlugin.Logger.LogInfo((object)"Added Mister component to MistArea prefab"); } val4.m_radius = config.SpawnRadius; ElementalStormsPlugin.Logger.LogInfo((object)$"Set MistArea radius to {config.SpawnRadius}m at {val}"); } if (m_spawnedObjects.ContainsKey(config.StormName)) { m_spawnedObjects[config.StormName].Add(val3); } } ElementalStormsPlugin.Logger.LogDebug((object)$"Spawned {num} {config.PrefabName}(s) at {val}"); } catch (Exception ex) { ElementalStormsPlugin.Logger.LogError((object)("Failed to spawn prefab " + config.PrefabName + ": " + ex.Message)); } } } private class QueenStormMistEffect : MonoBehaviour { private GameObject instantiatedMist; private void Start() { SpawnMist(); } private void Update() { if ((Object)(object)EnvMan.instance != (Object)null) { string name = EnvMan.instance.GetCurrentEnvironment().m_name; if (name != "ES_Queen") { RemoveMist(); } } } private void SpawnMist() { //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) GameObject prefab = ZNetScene.instance.GetPrefab(StringExtensionMethods.GetStableHashCode("MistArea")); if ((Object)(object)prefab != (Object)null) { instantiatedMist = Object.Instantiate(prefab, ((Component)this).transform.position, Quaternion.identity); instantiatedMist.transform.SetParent(((Component)this).transform); Mister val = instantiatedMist.GetComponent(); if ((Object)(object)val == (Object)null) { val = instantiatedMist.AddComponent(); } val.m_radius = 20f; ElementalStormsPlugin.Logger.LogInfo((object)"Queen mist spawned and attached to player"); } else { ElementalStormsPlugin.Logger.LogWarning((object)"QueenStormMod: MistArea prefab not found!"); } } public void RemoveMist() { if ((Object)(object)instantiatedMist != (Object)null) { Object.Destroy((Object)(object)instantiatedMist); } Object.Destroy((Object)(object)this); } private void OnDestroy() { if ((Object)(object)instantiatedMist != (Object)null) { Object.Destroy((Object)(object)instantiatedMist); } } } private static Dictionary> s_projectileConfigs = new Dictionary>(); private static GameObject s_spawnerHolder; public static void Initialize() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown if ((Object)(object)s_spawnerHolder == (Object)null) { s_spawnerHolder = new GameObject("ElementalStorms_ProjectileSpawner"); Object.DontDestroyOnLoad((Object)(object)s_spawnerHolder); } s_projectileConfigs.Clear(); ConfigureElderProjectiles(); ConfigureBonemassAOEs(); ConfigureModerProjectiles(); ConfigureYagluthMeteors(); ConfigureFaderMeteors(); ConfigureQueenMist(); if ((Object)(object)s_spawnerHolder.GetComponent() == (Object)null) { s_spawnerHolder.AddComponent(); } } private static void ConfigureElderProjectiles() { ProjectileConfig item = new ProjectileConfig { PrefabName = "TentaRoot", SpawnInterval = 2f, MinDistance = 1f, MaxDistance = 3f, Damage = 10f, StormName = "ES_Elder", BossKey = "defeated_gdking", SpawnCount = 1 }; s_projectileConfigs["Elder"] = new List { item }; } private static void ConfigureBonemassAOEs() { ProjectileConfig item = new ProjectileConfig { PrefabName = "bonemass_aoe", SpawnInterval = 5f, MinDistance = 1f, MaxDistance = 3f, Damage = 0f, StormName = "ES_Bonemass", BossKey = "defeated_bonemass" }; ProjectileConfig item2 = new ProjectileConfig { PrefabName = "bee_aoe", SpawnInterval = 15f, MinDistance = 1f, MaxDistance = 3f, Damage = 0f, StormName = "ES_Bonemass", BossKey = "defeated_bonemass", CheckEnvActive = true }; s_projectileConfigs["Bonemass"] = new List { item, item2 }; } private static void ConfigureModerProjectiles() { s_projectileConfigs["Moder"] = new List(); } private static void ConfigureYagluthMeteors() { ProjectileConfig item = new ProjectileConfig { PrefabName = "DvergerStaffFire_clusterbomb_aoe", SpawnInterval = 3f, MinDistance = 1f, MaxDistance = 10f, Damage = 10f, StormName = "ES_Yagluth", BossKey = "defeated_goblinking", DamageMultiplier = 0.33f }; s_projectileConfigs["Yagluth"] = new List { item }; } private static void ConfigureFaderMeteors() { ProjectileConfig item = new ProjectileConfig { PrefabName = "Fader_DroppedFire_AOE", SpawnInterval = 5f, MinDistance = 3f, MaxDistance = 10f, Damage = 10f, StormName = "ES_Fader", BossKey = "defeated_fader", DamageMultiplier = 0.33f }; s_projectileConfigs["Fader"] = new List { item }; } private static void ConfigureQueenMist() { ProjectileConfig item = new ProjectileConfig { PrefabName = "MistArea", SpawnInterval = 10f, MinDistance = 0f, MaxDistance = 0f, Damage = 0f, StormName = "ES_Queen", BossKey = "defeated_thequeen", SpawnRadius = 20f }; s_projectileConfigs["Queen"] = new List { item }; } public static List GetConfigs(string name) { if (s_projectileConfigs.TryGetValue(name, out var value)) { return value; } return null; } public static void UpdateConfig(string name, Action updateAction) { if (!s_projectileConfigs.TryGetValue(name, out var value)) { return; } foreach (ProjectileConfig item in value) { updateAction(item); } } public static void TriggerQueenMist() { if ((Object)(object)Player.m_localPlayer != (Object)null && !Object.op_Implicit((Object)(object)((Component)Player.m_localPlayer).GetComponent())) { ((Component)Player.m_localPlayer).gameObject.AddComponent(); ElementalStormsPlugin.Logger.LogInfo((object)"Queen mist effect triggered on player"); } } } public class SE_GaleExposure : StatusEffect { private float m_originalStaminaRegenTimeMultiplier = 1f; private bool m_shouldRemove = false; public SE_GaleExposure() { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown ((Object)this).name = "Moder's Blizzard"; base.m_icon = null; base.m_tooltip = "Moder's Blizzard: Severe winds are draining your stamina."; base.m_ttl = 0f; base.m_startEffects = new EffectList(); base.m_stopEffects = new EffectList(); } public override void Setup(Character character) { ((StatusEffect)this).Setup(character); Player val = (Player)(object)((character is Player) ? character : null); if (val != null) { m_originalStaminaRegenTimeMultiplier = val.m_staminaRegenTimeMultiplier; ElementalStormsPlugin.Logger.LogDebug((object)("SE_GaleExposure applied to player, storing original stamina regen multiplier: " + m_originalStaminaRegenTimeMultiplier)); } } public override void UpdateStatusEffect(float dt) { ((StatusEffect)this).UpdateStatusEffect(dt); if (m_shouldRemove) { Character character = base.m_character; RestoreStaminaRegen((Player)(object)((character is Player) ? character : null)); base.m_ttl = 0f; } else { if (ElementalStormsPlugin.EnableMod == null || !ElementalStormsPlugin.EnableMod.Value) { return; } Character character2 = base.m_character; Player val = (Player)(object)((character2 is Player) ? character2 : null); if (val != null) { if (val.InShelter()) { ElementalStormsPlugin.Logger.LogDebug((object)"Player found shelter, removing Gale Exposure"); m_shouldRemove = true; } else { ApplyStaminaPenalty(val); } } } } private void ApplyStaminaPenalty(Player player) { float num = 0.4f; player.m_staminaRegenTimeMultiplier = m_originalStaminaRegenTimeMultiplier * (1f + num); } private void RestoreStaminaRegen(Player player) { player.m_staminaRegenTimeMultiplier = m_originalStaminaRegenTimeMultiplier; } } public class SE_ForestRain : StatusEffect { private float m_originalStaminaRegenTimeMultiplier = 1f; private bool m_shouldRemove = false; public SE_ForestRain() { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown ((Object)this).name = "The Elder's Curse"; base.m_icon = null; base.m_tooltip = "The Elder's Curse: The Elder's curse makes you weary."; base.m_ttl = 0f; base.m_startEffects = new EffectList(); base.m_stopEffects = new EffectList(); } public override void Setup(Character character) { ((StatusEffect)this).Setup(character); Player val = (Player)(object)((character is Player) ? character : null); if (val != null) { m_originalStaminaRegenTimeMultiplier = val.m_staminaRegenTimeMultiplier; ElementalStormsPlugin.Logger.LogDebug((object)("SE_ForestRain applied to player, storing original stamina regen multiplier: " + m_originalStaminaRegenTimeMultiplier)); } } public override void UpdateStatusEffect(float dt) { ((StatusEffect)this).UpdateStatusEffect(dt); if (m_shouldRemove) { Character character = base.m_character; RestoreStaminaRegen((Player)(object)((character is Player) ? character : null)); base.m_ttl = 0f; } else { if (ElementalStormsPlugin.EnableMod == null || !ElementalStormsPlugin.EnableMod.Value) { return; } Character character2 = base.m_character; Player val = (Player)(object)((character2 is Player) ? character2 : null); if (val != null) { if (val.InShelter()) { ElementalStormsPlugin.Logger.LogDebug((object)"Player found shelter, removing Forest Rain"); m_shouldRemove = true; } else { ApplyStaminaPenalty(val); } } } } private void ApplyStaminaPenalty(Player player) { float num = 0.5f; player.m_staminaRegenTimeMultiplier = m_originalStaminaRegenTimeMultiplier * (1f + num); } private void RestoreStaminaRegen(Player player) { player.m_staminaRegenTimeMultiplier = m_originalStaminaRegenTimeMultiplier; } } public static class StatusEffectManager { private static SE_GaleExposure s_galeExposureTemplate; private static SE_ForestRain s_forestRainTemplate; public static void Initialize() { s_galeExposureTemplate = ScriptableObject.CreateInstance(); s_forestRainTemplate = ScriptableObject.CreateInstance(); } public static void ApplyGaleExposure(Character character) { if (ElementalStormsPlugin.EnableMod != null && ElementalStormsPlugin.EnableMod.Value && !((Object)(object)character == (Object)null) && !character.IsDead()) { int stableHashCode = StringExtensionMethods.GetStableHashCode("Moder's Blizzard"); if (!((Object)(object)character.GetSEMan().GetStatusEffect(stableHashCode) != (Object)null)) { SE_GaleExposure sE_GaleExposure = Object.Instantiate(s_galeExposureTemplate); character.GetSEMan().AddStatusEffect((StatusEffect)(object)sE_GaleExposure, false, 0, 0f); ElementalStormsPlugin.Logger.LogDebug((object)("Applied Moder's Blizzard to: " + ((Object)character).name)); } } } public static void ApplyForestRain(Character character) { if (ElementalStormsPlugin.EnableMod != null && ElementalStormsPlugin.EnableMod.Value && !((Object)(object)character == (Object)null) && !character.IsDead()) { int stableHashCode = StringExtensionMethods.GetStableHashCode("The Elder's Curse"); if (!((Object)(object)character.GetSEMan().GetStatusEffect(stableHashCode) != (Object)null)) { SE_ForestRain sE_ForestRain = Object.Instantiate(s_forestRainTemplate); character.GetSEMan().AddStatusEffect((StatusEffect)(object)sE_ForestRain, false, 0, 0f); ElementalStormsPlugin.Logger.LogDebug((object)("Applied The Elder's Curse to: " + ((Object)character).name)); } } } public static void RemoveAllCustomEffects(Character character) { if ((Object)(object)character == (Object)null) { return; } SEMan sEMan = character.GetSEMan(); if (sEMan != null) { int stableHashCode = StringExtensionMethods.GetStableHashCode("Moder's Blizzard"); StatusEffect statusEffect = sEMan.GetStatusEffect(stableHashCode); if ((Object)(object)statusEffect != (Object)null) { sEMan.RemoveStatusEffect(statusEffect, false); } int stableHashCode2 = StringExtensionMethods.GetStableHashCode("The Elder's Curse"); StatusEffect statusEffect2 = sEMan.GetStatusEffect(stableHashCode2); if ((Object)(object)statusEffect2 != (Object)null) { sEMan.RemoveStatusEffect(statusEffect2, false); } } } } public static class StormEnvironmentCloner { private class PoisonMonitor : MonoBehaviour { private const float CHECK_INTERVAL = 0.5f; private float m_checkTimer = 0f; private void Update() { if (!((Object)(object)EnvMan.instance == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null)) { m_checkTimer += Time.deltaTime; if (!(m_checkTimer < 0.5f)) { m_checkTimer = 0f; Player localPlayer = Player.m_localPlayer; string name = EnvMan.instance.GetCurrentEnvironment().m_name; bool flag = name == "ES_Bonemass"; } } } } private static Dictionary s_customEnvironments = new Dictionary(); public static void Initialize() { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown if ((Object)(object)EnvMan.instance == (Object)null) { ElementalStormsPlugin.Logger.LogWarning((object)"EnvMan not available, cannot initialize storm environments yet."); return; } try { CreateCustomStorms(); RegisterCustomEnvironments(); GameObject val = new GameObject("ES_PoisonMonitor"); val.AddComponent(); Object.DontDestroyOnLoad((Object)(object)val); } catch (Exception ex) { ElementalStormsPlugin.Logger.LogError((object)("Failed to initialize storm environment cloner: " + ex.Message)); ElementalStormsPlugin.Logger.LogError((object)ex.StackTrace); } } private static void CreateCustomStorms() { if ((Object)(object)EnvMan.instance == (Object)null) { ElementalStormsPlugin.Logger.LogWarning((object)"EnvMan.instance is null, cannot create custom storms."); return; } CreateEikthyrStorm(); CreateElderStorm(); CreateBonemassStorm(); CreateModerStorm(); CreateYagluthStorm(); CreateQueenStorm(); CreateFaderStorm(); } private static void CreateEikthyrStorm() { EnvSetup env = EnvMan.instance.GetEnv("ThunderStorm"); if (env == null) { ElementalStormsPlugin.Logger.LogWarning((object)"Could not find ThunderStorm environment, trying Eikthyr."); env = EnvMan.instance.GetEnv("Eikthyr"); if (env == null) { ElementalStormsPlugin.Logger.LogWarning((object)"Could not find Eikthyr environment for cloning."); return; } } EnvSetup val = env.Clone(); val.m_name = "ES_Eikthyr"; val.m_windMin = 1.4f; val.m_windMax = 2f; s_customEnvironments["ES_Eikthyr"] = val; } private static void CreateElderStorm() { EnvSetup env = EnvMan.instance.GetEnv("Darklands_dark"); if (env == null) { ElementalStormsPlugin.Logger.LogWarning((object)"Could not find Darklands_dark environment, trying GDKing."); env = EnvMan.instance.GetEnv("GDKing"); if (env == null) { ElementalStormsPlugin.Logger.LogWarning((object)"Could not find GDKing environment for cloning."); return; } } EnvSetup val = env.Clone(); val.m_name = "ES_Elder"; val.m_isWet = true; val.m_windMin = 0.8f; val.m_windMax = 1.6f; s_customEnvironments["ES_Elder"] = val; } private static void CreateBonemassStorm() { EnvSetup env = EnvMan.instance.GetEnv("Bonemass"); if (env == null) { ElementalStormsPlugin.Logger.LogWarning((object)"Could not find Bonemass environment for cloning."); return; } EnvSetup val = env.Clone(); val.m_name = "ES_Bonemass"; val.m_isWet = true; val.m_windMin = 0.6f; val.m_windMax = 1.4f; s_customEnvironments["ES_Bonemass"] = val; } private static void CreateModerStorm() { EnvSetup env = EnvMan.instance.GetEnv("SnowStorm"); if (env == null) { ElementalStormsPlugin.Logger.LogWarning((object)"Could not find SnowStorm environment for cloning."); return; } EnvSetup val = env.Clone(); val.m_name = "ES_Moder"; val.m_isFreezing = true; val.m_isFreezingAtNight = true; val.m_isCold = true; val.m_windMin = 1.6f; val.m_windMax = 2f; s_customEnvironments["ES_Moder"] = val; } private static void CreateYagluthStorm() { EnvSetup env = EnvMan.instance.GetEnv("GoblinKing"); if (env == null) { ElementalStormsPlugin.Logger.LogWarning((object)"Could not find GoblinKing environment for cloning."); return; } EnvSetup val = env.Clone(); val.m_name = "ES_Yagluth"; val.m_windMin = 1.4f; val.m_windMax = 2f; s_customEnvironments["ES_Yagluth"] = val; } private static void CreateQueenStorm() { EnvSetup env = EnvMan.instance.GetEnv("Mistlands_rain"); if (env == null) { ElementalStormsPlugin.Logger.LogWarning((object)"Could not find Mistlands_rain environment for cloning."); return; } EnvSetup val = env.Clone(); val.m_name = "ES_Queen"; val.m_windMin = 1.4f; val.m_windMax = 2f; s_customEnvironments["ES_Queen"] = val; } private static void CreateFaderStorm() { EnvSetup env = EnvMan.instance.GetEnv("Fader"); if (env == null) { ElementalStormsPlugin.Logger.LogWarning((object)"Could not find Fader environment for cloning."); return; } EnvSetup val = env.Clone(); val.m_name = "ES_Fader"; val.m_windMin = 1.6f; val.m_windMax = 2f; s_customEnvironments["ES_Fader"] = val; } private static void RegisterCustomEnvironments() { foreach (KeyValuePair s_customEnvironment in s_customEnvironments) { try { if (EnvMan.instance.GetEnv(s_customEnvironment.Key) == null) { EnvMan.instance.AppendEnvironment(s_customEnvironment.Value); ElementalStormsPlugin.Logger.LogDebug((object)("Registered custom environment: " + s_customEnvironment.Key)); } else { ElementalStormsPlugin.Logger.LogDebug((object)("Environment " + s_customEnvironment.Key + " already registered, skipping.")); } } catch (Exception ex) { ElementalStormsPlugin.Logger.LogError((object)("Failed to register environment " + s_customEnvironment.Key + ": " + ex.Message)); } } } public static EnvSetup GetCustomStorm(string stormName) { if (s_customEnvironments.TryGetValue(stormName, out var value)) { return value; } return null; } public static string[] GetCustomStormNames() { return new List(s_customEnvironments.Keys).ToArray(); } } [HarmonyPatch] internal class WindSystem { [HarmonyPatch(typeof(WearNTear), "UpdateWear")] [HarmonyPostfix] private static void ApplyWindDamage(WearNTear __instance) { if (ElementalStormsPlugin.EnableMod == null || ElementalStormsPlugin.EnableStructuralDamage == null || !ElementalStormsPlugin.EnableMod.Value || !ElementalStormsPlugin.EnableStructuralDamage.Value || ElementalStormsPlugin.IsInDungeonAltitude() || (Object)(object)__instance.m_piece == (Object)null || (Object)(object)EnvMan.instance == (Object)null || EnvMan.instance.m_currentEnv == null) { return; } string name = EnvMan.instance.m_currentEnv.m_name; if (name.StartsWith("ES_")) { float windIntensity = EnvMan.instance.GetWindIntensity(); if (!float.IsNaN(windIntensity)) { windIntensity = GetEqualWindIntensity(windIntensity); ElementalStormsPlugin.Logger.LogDebug((object)$"Structural wind intensity: {windIntensity:F2}"); ApplyWindStructuralDamage(__instance); } } } private static float GetEqualWindIntensity(float baseIntensity) { if ((Object)(object)EnvMan.instance == (Object)null || EnvMan.instance.m_currentEnv == null) { return baseIntensity; } string name = EnvMan.instance.m_currentEnv.m_name; if (name.StartsWith("ES_")) { return Mathf.Max(baseIntensity, 0.7f); } return baseIntensity; } private static void ApplyWindStructuralDamage(WearNTear wearNTear) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_003d: 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_005c: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) if (ElementalStormsPlugin.StructuralDamageAmount != null) { float value = ElementalStormsPlugin.StructuralDamageAmount.Value; value *= 0.2f; HitData val = new HitData(); val.m_damage.m_pickaxe = value; val.m_attacker = default(ZDOID); val.m_pushForce = 0f; val.m_dir = (((Object)(object)EnvMan.instance != (Object)null) ? EnvMan.instance.GetWindDir() : Vector3.up); wearNTear.Damage(val); ElementalStormsPlugin.Logger.LogDebug((object)$"Applied wind damage: {value:F1} to {((Object)wearNTear).name}"); } } } [HarmonyPatch] internal class WeatherStatusEffects { private static float m_statusCheckTimer; private const float STATUS_CHECK_INTERVAL = 1f; [HarmonyPatch(typeof(Player), "Update")] [HarmonyPostfix] private static void CheckWeatherStatusEffects(Player __instance) { if (ElementalStormsPlugin.EnableMod == null || !ElementalStormsPlugin.EnableMod.Value || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || ElementalStormsPlugin.IsInDungeonAltitude()) { return; } m_statusCheckTimer += Time.deltaTime; if (m_statusCheckTimer < 1f) { return; } m_statusCheckTimer = 0f; if ((Object)(object)EnvMan.instance == (Object)null || EnvMan.instance.m_currentEnv == null) { return; } string name = EnvMan.instance.m_currentEnv.m_name; if (!string.IsNullOrEmpty(name)) { switch (name) { case "ES_Eikthyr": HandleEikthyr(__instance); break; case "ES_Bonemass": break; case "ES_Moder": HandleModer(__instance); break; case "ES_Yagluth": HandleGoblinKing(__instance); break; case "ES_Queen": HandleQueen(__instance); break; case "ES_Fader": HandleFader(__instance); break; default: StatusEffectManager.RemoveAllCustomEffects((Character)(object)__instance); break; } } } private static void HandleEikthyr(Player player) { } private static void HandleBonemass(Player player) { } private static void HandleModer(Player player) { if (ElementalStormsPlugin.IsBossDefeated("defeated_moder") && !player.InShelter()) { StatusEffectManager.ApplyGaleExposure((Character)(object)player); } } private static void HandleGoblinKing(Player player) { } private static void HandleQueen(Player player) { } private static void HandleFader(Player player) { } } }