using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Networking;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("0.0.0.0")]
[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 Pix.RainDance
{
[BepInPlugin("Pix.RainDance", "RainDance", "0.3.6")]
public sealed class RainDancePlugin : BaseUnityPlugin
{
private enum PendingMode
{
Weather,
Sun
}
private struct PendingDestruct
{
public ZDOID Zdoid;
public Vector3 Pos;
public long StrikeAtMs;
public long DestroyAtMs;
public bool Struck;
}
private sealed class RainDanceTotem : MonoBehaviour, Hoverable, Interactable
{
private ZNetView _nview;
private void Awake()
{
_nview = ((Component)this).GetComponent<ZNetView>();
}
public string GetHoverName()
{
return "Rain Dance Totem";
}
public string GetHoverText()
{
if (CfgEnabled == null || !CfgEnabled.Value)
{
return "Disabled";
}
long num = NowMs();
long num2 = 0L;
long val = 0L;
if ((Object)(object)_nview != (Object)null && _nview.IsValid() && _nview.GetZDO() != null)
{
ZDO zDO = _nview.GetZDO();
num2 = zDO.GetLong("RD_RitualEndMs", 0L);
val = zDO.GetLong("RD_CooldownEndMs", 0L);
}
if (num2 > num)
{
return "[E] Tempt the skies\n[F] Tempt the sun\n<color=#cfd7df>(ritual in progress)</color>";
}
long num3 = Math.Max(GetGlobalCooldownEndMs(), val);
string text = ((CfgSelfDestructAfterUse != null && CfgSelfDestructAfterUse.Value) ? "\n<color=#9fdcff>The wood smells of storm.</color>" : "");
if (num3 > num)
{
int num4 = Mathf.CeilToInt((float)(num3 - num) / 1000f);
return $"[E] Tempt the skies\n[F] Tempt the sun\n<color=#cfd7df>(cooldown {num4}s)</color>{text}";
}
return "[E] Tempt the skies\n[F] Tempt the sun" + text;
}
private bool ClientCanStartRitual()
{
long num = NowMs();
long num2 = 0L;
long val = 0L;
if ((Object)(object)_nview != (Object)null && _nview.IsValid() && _nview.GetZDO() != null)
{
ZDO zDO = _nview.GetZDO();
num2 = zDO.GetLong("RD_RitualEndMs", 0L);
val = zDO.GetLong("RD_CooldownEndMs", 0L);
}
if (num2 > num)
{
return false;
}
long num3 = Math.Max(GetGlobalCooldownEndMs(), val);
if (num3 > num)
{
return false;
}
return true;
}
public bool Interact(Humanoid user, bool hold, bool alt)
{
//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
if (hold)
{
return false;
}
if (CfgEnabled == null || !CfgEnabled.Value)
{
return true;
}
if (!ClientCanStartRitual())
{
return true;
}
StartLocalRitualVibe(user);
TryRegisterRpcs(force: false);
ZRoutedRpc instance = ZRoutedRpc.instance;
if (instance == null)
{
return true;
}
if ((Object)(object)_nview != (Object)null && _nview.IsValid() && _nview.GetZDO() != null)
{
instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "RD_ServerBeginRitual", new object[1] { _nview.GetZDO().m_uid });
}
return true;
}
internal void TriggerSunRitual(Humanoid user)
{
//IL_009e: Unknown result type (might be due to invalid IL or missing references)
if (CfgEnabled != null && CfgEnabled.Value && ClientCanStartRitual())
{
StartLocalRitualVibe(user);
TryRegisterRpcs(force: false);
ZRoutedRpc instance = ZRoutedRpc.instance;
if (instance != null && (Object)(object)_nview != (Object)null && _nview.IsValid() && _nview.GetZDO() != null)
{
instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "RD_ServerBeginSunRitual", new object[1] { _nview.GetZDO().m_uid });
}
}
}
private static void StartLocalRitualVibe(Humanoid user)
{
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
Player val = (Player)(object)((user is Player) ? user : null);
if ((Object)(object)val != (Object)null)
{
try
{
val.StartEmote("dance", true);
}
catch
{
}
if (CfgPlayDrumOnInteract != null && CfgPlayDrumOnInteract.Value)
{
float volume = ((CfgDrumVolume != null) ? Mathf.Clamp01(CfgDrumVolume.Value) : 0.75f);
PlayOneShot(_drumClip, ((Component)val).transform.position, volume);
}
}
}
public bool UseItem(Humanoid user, ItemData item)
{
return false;
}
}
private static class Patches
{
[HarmonyPatch(typeof(ZNetScene), "Awake")]
[HarmonyPostfix]
private static void ZNetScene_Awake_Postfix(ZNetScene __instance)
{
EnsurePrefabLoaded();
RegisterPrefabInZNetScene();
ApplyPlacementAndBreakEffectsIfPossible();
TryRegisterRpcs(force: true);
}
[HarmonyPatch(typeof(ObjectDB), "Awake")]
[HarmonyPostfix]
private static void ObjectDB_Awake_Postfix(ObjectDB __instance)
{
EnsurePrefabLoaded();
TryAddToHammer(__instance);
ApplyBuildCostIfPossible();
ApplyPlacementAndBreakEffectsIfPossible();
}
[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
[HarmonyPostfix]
private static void ObjectDB_CopyOtherDB_Postfix(ObjectDB __instance)
{
EnsurePrefabLoaded();
TryAddToHammer(__instance);
ApplyBuildCostIfPossible();
ApplyPlacementAndBreakEffectsIfPossible();
}
[HarmonyPatch(typeof(EnvMan), "Update")]
[HarmonyPostfix]
private static void EnvMan_Update_Postfix(EnvMan __instance)
{
if (CfgEnabled == null || !CfgEnabled.Value)
{
return;
}
TryRegisterRpcs(force: false);
LateInitOnce();
ApplyPlacementAndBreakEffectsIfPossible();
long num = NowMs();
if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer())
{
ServerTick();
}
else if (_clientForcedUntilMs > num)
{
ApplyEnvLocal(_clientForcedEnv);
if (_clientForcedTimeEnabled)
{
ApplyDebugTimeLocal(enabled: true, _clientForcedTimeOfDay);
}
}
else if (_clientForcedUntilMs != 0)
{
_clientForcedUntilMs = 0L;
_clientForcedEnv = "";
ApplyEnvLocal("");
if (_clientForcedTimeEnabled)
{
_clientForcedTimeEnabled = false;
ApplyDebugTimeLocal(enabled: false, 0.5f);
}
}
}
[HarmonyPatch(typeof(Player), "Update")]
[HarmonyPostfix]
private static void Player_Update_Postfix(Player __instance)
{
//IL_008a: 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)
try
{
if ((Object)(object)__instance == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || CfgEnabled == null || !CfgEnabled.Value || CfgSunHotkey == null || IsTextInputOpen())
{
return;
}
KeyboardShortcut value = CfgSunHotkey.Value;
if (!((KeyboardShortcut)(ref value)).IsDown())
{
return;
}
long num = NowMs();
long globalCooldownEndMs = GetGlobalCooldownEndMs();
if (globalCooldownEndMs > num)
{
return;
}
GameObject val = TryGetLocalHoverObject(__instance);
if (!((Object)(object)val == (Object)null))
{
RainDanceTotem rainDanceTotem = val.GetComponent<RainDanceTotem>() ?? val.GetComponentInParent<RainDanceTotem>() ?? val.GetComponentInChildren<RainDanceTotem>(true);
if (!((Object)(object)rainDanceTotem == (Object)null))
{
rainDanceTotem.TriggerSunRitual((Humanoid)(object)__instance);
}
}
}
catch
{
}
}
}
[CompilerGenerated]
private sealed class <LoadClipCoroutine>d__129 : IEnumerator<object>, IDisposable, IEnumerator
{
private int <>1__state;
private object <>2__current;
public Func<string> getFileName;
public Action<AudioClip> assign;
private string <pluginFolder>5__1;
private string <fileName>5__2;
private string <path>5__3;
private string <url>5__4;
private UnityWebRequest <req>5__5;
private AudioClip <clip>5__6;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <LoadClipCoroutine>d__129(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
int num = <>1__state;
if (num == -3 || num == 1)
{
try
{
}
finally
{
<>m__Finally1();
}
}
<pluginFolder>5__1 = null;
<fileName>5__2 = null;
<path>5__3 = null;
<url>5__4 = null;
<req>5__5 = null;
<clip>5__6 = null;
<>1__state = -2;
}
private bool MoveNext()
{
//IL_013d: Unknown result type (might be due to invalid IL or missing references)
//IL_0143: Invalid comparison between Unknown and I4
bool result;
try
{
switch (<>1__state)
{
default:
result = false;
break;
case 0:
<>1__state = -1;
<pluginFolder>5__1 = Path.GetDirectoryName(typeof(RainDancePlugin).Assembly.Location) ?? Paths.PluginPath;
<fileName>5__2 = ((getFileName != null) ? getFileName() : null) ?? "";
<fileName>5__2 = <fileName>5__2.Trim();
if (<fileName>5__2.Length == 0)
{
result = false;
break;
}
<path>5__3 = Path.Combine(<pluginFolder>5__1, <fileName>5__2);
if (!File.Exists(<path>5__3))
{
result = false;
break;
}
<url>5__4 = "file://" + <path>5__3.Replace("\\", "/");
<req>5__5 = UnityWebRequestMultimedia.GetAudioClip(<url>5__4, (AudioType)14);
<>1__state = -3;
<>2__current = <req>5__5.SendWebRequest();
<>1__state = 1;
result = true;
break;
case 1:
<>1__state = -3;
if ((int)<req>5__5.result != 1)
{
result = false;
<>m__Finally1();
break;
}
<clip>5__6 = null;
try
{
<clip>5__6 = DownloadHandlerAudioClip.GetContent(<req>5__5);
}
catch
{
<clip>5__6 = null;
}
if ((Object)(object)<clip>5__6 != (Object)null)
{
assign?.Invoke(<clip>5__6);
}
<clip>5__6 = null;
<>m__Finally1();
<req>5__5 = null;
result = false;
break;
}
}
catch
{
//try-fault
((IDisposable)this).Dispose();
throw;
}
return result;
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
private void <>m__Finally1()
{
<>1__state = -1;
if (<req>5__5 != null)
{
((IDisposable)<req>5__5).Dispose();
}
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
public const string PluginGuid = "Pix.RainDance";
public const string PluginName = "RainDance";
public const string PluginVersion = "0.3.6";
internal static ManualLogSource Log;
private static RainDancePlugin _instance;
private static AssetBundle _bundle;
private static GameObject _totemPrefab;
private const string ZdoTotemCooldownEndMs = "RD_CooldownEndMs";
private const string ZdoTotemRitualEndMs = "RD_RitualEndMs";
private const string ZdoTotemRitualMode = "RD_RitualMode";
private const string ZdoTotemRitualNonce = "RD_RitualNonce";
private const string RpcServerBeginRitual = "RD_ServerBeginRitual";
private const string RpcServerBeginSunRitual = "RD_ServerBeginSunRitual";
private const string RpcClientSetEnv = "RD_ClientSetEnv";
private const string RpcClientVerdict = "RD_ClientVerdict";
private const string RpcClientSetGlobalCooldown = "RD_SetGlobalCooldown";
private const string RpcClientLightningVfx = "RD_ClientLightningVfx";
private const string RpcClientMythLine = "RD_ClientMythLine";
private const string RpcClientSetDebugTime = "RD_ClientSetDebugTime";
private static ConfigEntry<bool> CfgEnabled;
private static ConfigEntry<string> CfgPreset;
private static ConfigEntry<bool> CfgApplyMostlyClearNow;
private static ConfigEntry<bool> CfgApplyChaosWeatherNow;
private static ConfigEntry<float> CfgGlobalCooldownSeconds;
private static ConfigEntry<float> CfgAnticipationSeconds;
private static ConfigEntry<float> CfgForcedDurationSeconds;
private static ConfigEntry<float> CfgChanceWeatherChange;
private static ConfigEntry<float> CfgChanceGoodWhenChanging;
private static ConfigEntry<string> CfgGoodEnvsCsv;
private static ConfigEntry<string> CfgBadEnvsCsv;
private static ConfigEntry<float> CfgClearWeatherBadBias;
private static ConfigEntry<float> CfgClearWeatherChangeBoost;
private static ConfigEntry<KeyboardShortcut> CfgSunHotkey;
private static ConfigEntry<float> CfgSunChanceChange;
private static ConfigEntry<float> CfgSunChanceGoodWhenChanging;
private static ConfigEntry<string> CfgSunGoodEnvsCsv;
private static ConfigEntry<string> CfgSunBadEnvsCsv;
private static ConfigEntry<string> CfgSunGoodTimesCsv;
private static ConfigEntry<string> CfgSunBadTimesCsv;
private static ConfigEntry<bool> CfgPlayDrumOnInteract;
private static ConfigEntry<float> CfgDrumVolume;
private static ConfigEntry<string> CfgDrumFileName;
private static ConfigEntry<bool> CfgPlayVerdictOnVerdict;
private static ConfigEntry<float> CfgVerdictVolume;
private static ConfigEntry<string> CfgVerdictFileName;
private static ConfigEntry<bool> CfgEnableVerdictVfx;
private static ConfigEntry<bool> CfgSelfDestructAfterUse;
private static ConfigEntry<float> CfgSelfDestructDelaySeconds;
private static ConfigEntry<bool> CfgSpawnLightningAoeServer;
private static ConfigEntry<bool> CfgAlsoPlayClientLightningVfx;
private static ConfigEntry<bool> CfgEnableMythLines;
private static ConfigEntry<bool> CfgMythLinesRevealEnvInLogs;
private static ConfigEntry<bool> CfgLogDebug;
private static ConfigEntry<bool> CfgDebugForceWeatherChange;
private static ConfigEntry<string> CfgBuildCostCsv;
private static bool _rpcsRegistered;
private static long _nextRpcRetryMs;
private static bool _registeredInZNetScene;
private static bool _addedToHammer;
private static bool _costApplied;
private static bool _effectsApplied;
private static bool _iconApplied;
private static string _serverForcedEnv = "";
private static long _serverForcedUntilMs = 0L;
private static string _clientForcedEnv = "";
private static long _clientForcedUntilMs = 0L;
private static bool _serverForcedTimeEnabled = false;
private static float _serverForcedTimeOfDay = 0.5f;
private static bool _clientForcedTimeEnabled = false;
private static float _clientForcedTimeOfDay = 0.5f;
private static long _serverGlobalCooldownEndMs = 0L;
private static long _clientGlobalCooldownEndMs = 0L;
private static bool _pending;
private static PendingMode _pendingMode;
private static ZDOID _pendingTotemZdoid;
private static Vector3 _pendingTotemPos;
private static long _pendingResolveAtMs;
private static long _pendingNonce;
private static AudioClip _drumClip;
private static bool _drumClipRequested;
private static AudioClip _verdictClip;
private static bool _verdictClipRequested;
private static long _nextForcedEnvBroadcastMs = 0L;
private const string LightningAoePrefabName = "lightningAOE";
private static readonly List<PendingDestruct> _pendingDestructs = new List<PendingDestruct>(8);
private static readonly FieldRef<Player, GameObject> PlayerHoveringRef = AccessTools.FieldRefAccess<Player, GameObject>("m_hovering");
private void Awake()
{
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: Expected O, but got Unknown
//IL_0240: Unknown result type (might be due to invalid IL or missing references)
_instance = this;
Log = ((BaseUnityPlugin)this).Logger;
_registeredInZNetScene = false;
_addedToHammer = false;
_costApplied = false;
_effectsApplied = false;
_iconApplied = false;
_serverForcedTimeEnabled = false;
_clientForcedTimeEnabled = false;
CfgEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable/disable RainDance.");
CfgPreset = ((BaseUnityPlugin)this).Config.Bind<string>("General", "Preset", "MostlyClear", new ConfigDescription("Preset: Custom, MostlyClear, ChaosWeather", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[2] { "MostlyClear", "ChaosWeather" }), Array.Empty<object>()));
CfgApplyMostlyClearNow = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ApplyMostlyClearNow", false, "Click to apply MostlyClear values now (auto-resets).");
CfgApplyChaosWeatherNow = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ApplyChaosWeatherNow", false, "Click to apply ChaosWeather values now (auto-resets).");
CfgGlobalCooldownSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("General", "GlobalCooldownSeconds", 240f, "GLOBAL cooldown (seconds).");
CfgAnticipationSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("General", "AnticipationSeconds", 7f, "Dance time before verdict (seconds).");
CfgForcedDurationSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ForcedDurationSeconds", 300f, "How long the chosen env is forced (seconds).");
CfgChanceWeatherChange = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ChanceWeatherChange", 0.75f, "WEATHER: Chance (0-1) the ritual changes weather (vs no change).");
CfgChanceGoodWhenChanging = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ChanceGoodWhenChanging", 0.65f, "WEATHER: If changing weather, chance (0-1) it is Good vs Bad.");
CfgGoodEnvsCsv = ((BaseUnityPlugin)this).Config.Bind<string>("General", "GoodEnvsCsv", "Clear", "WEATHER: Good env pool.");
CfgBadEnvsCsv = ((BaseUnityPlugin)this).Config.Bind<string>("General", "BadEnvsCsv", "Rain,LightRain,ThunderStorm,Misty,Snow,SnowStorm", "WEATHER: Bad env pool.");
CfgClearWeatherBadBias = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ClearWeatherBadBias", 0.25f, "WEATHER: When weather is clear-ish, reduce Good chance by this amount.");
CfgClearWeatherChangeBoost = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ClearWeatherChangeBoost", 0.1f, "WEATHER: When weather is clear-ish, boost ChanceWeatherChange by this amount.");
CfgSunHotkey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("SunRitual", "SunHotkey", new KeyboardShortcut((KeyCode)102, Array.Empty<KeyCode>()), "Hotkey to Tempt the sun while hovering the totem.");
CfgSunChanceChange = ((BaseUnityPlugin)this).Config.Bind<float>("SunRitual", "SunChanceChange", 0.8f, "SUN: Chance (0-1) to change to a sun/night outcome (vs no change). Default 0.80 (20% no change).");
CfgSunChanceGoodWhenChanging = ((BaseUnityPlugin)this).Config.Bind<float>("SunRitual", "SunChanceGoodWhenChanging", 0.75f, "SUN: If changing, chance (0-1) of 'good' (dawn/day/evening) vs 'bad' (night). Default 0.75.");
CfgSunGoodEnvsCsv = ((BaseUnityPlugin)this).Config.Bind<string>("SunRitual", "SunGoodEnvsCsv", "Clear,LightClouds,Twilight_Clear", "SUN: Good env pool (sun-ish).");
CfgSunBadEnvsCsv = ((BaseUnityPlugin)this).Config.Bind<string>("SunRitual", "SunBadEnvsCsv", "Darklands_dark,Misty", "SUN: Bad env pool (night-ish).");
CfgSunGoodTimesCsv = ((BaseUnityPlugin)this).Config.Bind<string>("SunRitual", "SunGoodTimesCsv", "0.22,0.30,0.38,0.50,0.65,0.72", "SUN: Good time-of-day pool (0..1): dawn/morning/noon/evening.");
CfgSunBadTimesCsv = ((BaseUnityPlugin)this).Config.Bind<string>("SunRitual", "SunBadTimesCsv", "0.00,0.05,0.90,0.95", "SUN: Bad time-of-day pool (0..1): midnight/late night.");
CfgPlayDrumOnInteract = ((BaseUnityPlugin)this).Config.Bind<bool>("Audio", "PlayDrumOnInteract", true, "Play drum on ritual start (client-side).");
CfgDrumVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "DrumVolume", 0.75f, "Drum volume (0-1).");
CfgDrumFileName = ((BaseUnityPlugin)this).Config.Bind<string>("Audio", "DrumFileName", "RD_Drums.ogg", "Drum filename.");
CfgPlayVerdictOnVerdict = ((BaseUnityPlugin)this).Config.Bind<bool>("Audio", "PlayVerdictOnVerdict", true, "Play verdict sting at verdict (client-side).");
CfgVerdictVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "VerdictVolume", 1f, "Verdict volume (0-1). Default 1.0 (100%).");
CfgVerdictFileName = ((BaseUnityPlugin)this).Config.Bind<string>("Audio", "VerdictFileName", "RD_Verdict.ogg", "Verdict filename.");
CfgEnableVerdictVfx = ((BaseUnityPlugin)this).Config.Bind<bool>("VFX", "EnableVerdictVfx", true, "Spawn verdict VFX at verdict.");
CfgSelfDestructAfterUse = ((BaseUnityPlugin)this).Config.Bind<bool>("Lore", "SelfDestructAfterUse", true, "After a ritual, the totem destroys itself.");
CfgSelfDestructDelaySeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Lore", "SelfDestructDelaySeconds", 1.05f, "Delay between verdict and destruction (seconds).");
CfgSpawnLightningAoeServer = ((BaseUnityPlugin)this).Config.Bind<bool>("Lightning", "SpawnLightningAoeServer", true, "Spawn lightningAOE via ZNetScene.SpawnObject on the server (authoritative).");
CfgAlsoPlayClientLightningVfx = ((BaseUnityPlugin)this).Config.Bind<bool>("Lightning", "AlsoPlayClientLightningVfx", true, "Also tell every client to locally spawn lightningAOE for visuals (reliable).");
CfgEnableMythLines = ((BaseUnityPlugin)this).Config.Bind<bool>("Lore", "EnableMythLines", true, "Show cryptic myth lines instead of naming the env.");
CfgMythLinesRevealEnvInLogs = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "RevealEnvInLogs", false, "Debug only: print the chosen env/time to log.");
CfgLogDebug = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "LogDebug", false, "Debug logs.");
CfgDebugForceWeatherChange = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "DebugForceWeatherChange", false, "WEATHER: Always change weather (testing).");
CfgBuildCostCsv = ((BaseUnityPlugin)this).Config.Bind<string>("BuildCost", "CostCsv", "Wood:10,Thunderstone:1", "Build cost as CSV: ItemName:Amount,ItemName:Amount ... Example: Wood:10,Thunderstone:1");
CfgBuildCostCsv.SettingChanged += delegate
{
_costApplied = false;
};
CfgApplyMostlyClearNow.SettingChanged += delegate
{
if (CfgApplyMostlyClearNow.Value)
{
ApplyPresetValues("MostlyClear");
CfgPreset.Value = "MostlyClear";
CfgApplyMostlyClearNow.Value = false;
}
};
CfgApplyChaosWeatherNow.SettingChanged += delegate
{
if (CfgApplyChaosWeatherNow.Value)
{
ApplyPresetValues("ChaosWeather");
CfgPreset.Value = "ChaosWeather";
CfgApplyChaosWeatherNow.Value = false;
}
};
Harmony.CreateAndPatchAll(typeof(Patches), "Pix.RainDance");
EnsurePrefabLoaded();
TryRegisterRpcs(force: true);
TryRequestDrumClipLoad();
TryRequestVerdictClipLoad();
}
private static void ApplyPresetIfNeeded()
{
string text = ((CfgPreset != null) ? CfgPreset.Value : "MostlyClear") ?? "MostlyClear";
text = text.Trim();
if (!text.Equals("Custom", StringComparison.OrdinalIgnoreCase))
{
ApplyPresetValues(text);
}
}
private static void ApplyPresetValues(string preset)
{
if (!string.IsNullOrWhiteSpace(preset))
{
preset = preset.Trim();
if (preset.Equals("MostlyClear", StringComparison.OrdinalIgnoreCase))
{
CfgGlobalCooldownSeconds.Value = 240f;
CfgAnticipationSeconds.Value = 7f;
CfgForcedDurationSeconds.Value = 300f;
CfgChanceWeatherChange.Value = 0.75f;
CfgChanceGoodWhenChanging.Value = 0.68f;
CfgGoodEnvsCsv.Value = "Clear";
CfgBadEnvsCsv.Value = "Rain,LightRain,ThunderStorm,Misty,Snow,SnowStorm";
CfgClearWeatherBadBias.Value = 0.25f;
CfgClearWeatherChangeBoost.Value = 0.1f;
}
else if (preset.Equals("ChaosWeather", StringComparison.OrdinalIgnoreCase))
{
CfgGlobalCooldownSeconds.Value = 120f;
CfgAnticipationSeconds.Value = 7f;
CfgForcedDurationSeconds.Value = 240f;
CfgChanceWeatherChange.Value = 1f;
CfgChanceGoodWhenChanging.Value = 0.5f;
string value = "Clear,Rain,LightRain,ThunderStorm,Misty,Snow,SnowStorm";
CfgGoodEnvsCsv.Value = value;
CfgBadEnvsCsv.Value = value;
CfgClearWeatherBadBias.Value = 0.1f;
CfgClearWeatherChangeBoost.Value = 0f;
}
}
}
private static void Dbg(string msg)
{
try
{
if (CfgLogDebug != null && CfgLogDebug.Value && Log != null)
{
Log.LogInfo((object)msg);
}
}
catch
{
}
}
private static long NowMs()
{
try
{
if ((Object)(object)ZNet.instance != (Object)null)
{
return (long)(ZNet.instance.GetTimeSeconds() * 1000.0);
}
}
catch
{
}
return (long)((double)Time.realtimeSinceStartup * 1000.0);
}
private static void EnsurePrefabLoaded()
{
if ((Object)(object)_totemPrefab != (Object)null)
{
return;
}
try
{
string directoryName = Path.GetDirectoryName(typeof(RainDancePlugin).Assembly.Location);
string text = Path.Combine(directoryName ?? Paths.PluginPath, "raindance");
if (!File.Exists(text))
{
Log.LogError((object)("AssetBundle not found: " + text));
return;
}
if ((Object)(object)_bundle == (Object)null)
{
_bundle = AssetBundle.LoadFromFile(text);
if ((Object)(object)_bundle == (Object)null)
{
Log.LogError((object)("Failed to load AssetBundle (null): " + text));
return;
}
}
_totemPrefab = _bundle.LoadAsset<GameObject>("RD_Totem_Root");
if ((Object)(object)_totemPrefab == (Object)null)
{
Log.LogError((object)"Failed to load prefab 'RD_Totem_Root' from AssetBundle.");
return;
}
Piece val = _totemPrefab.GetComponent<Piece>() ?? _totemPrefab.GetComponentInChildren<Piece>(true);
if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).gameObject != (Object)(object)_totemPrefab)
{
_totemPrefab = ((Component)val).gameObject;
}
if ((Object)(object)_totemPrefab.GetComponent<RainDanceTotem>() == (Object)null)
{
_totemPrefab.AddComponent<RainDanceTotem>();
}
}
catch (Exception arg)
{
Log.LogError((object)$"Exception preparing prefab: {arg}");
}
}
private static void RegisterPrefabInZNetScene()
{
if (!_registeredInZNetScene && !((Object)(object)ZNetScene.instance == (Object)null) && !((Object)(object)_totemPrefab == (Object)null))
{
List<GameObject> prefabs = ZNetScene.instance.m_prefabs;
if (prefabs != null && !prefabs.Contains(_totemPrefab))
{
prefabs.Add(_totemPrefab);
}
_registeredInZNetScene = true;
}
}
private static void TryAddToHammer(ObjectDB db)
{
if (_addedToHammer || (Object)(object)_totemPrefab == (Object)null || (Object)(object)db == (Object)null || db.m_items == null || db.m_items.Count == 0)
{
return;
}
GameObject itemPrefab = db.GetItemPrefab("Hammer");
if ((Object)(object)itemPrefab == (Object)null)
{
return;
}
PieceTable val = itemPrefab.GetComponent<ItemDrop>()?.m_itemData?.m_shared?.m_buildPieces;
if (!((Object)(object)val == (Object)null))
{
if (!val.m_pieces.Contains(_totemPrefab))
{
val.m_pieces.Add(_totemPrefab);
}
_addedToHammer = true;
}
}
private static List<(string item, int amount)> ParseCostCsv(string csv)
{
List<(string, int)> list = new List<(string, int)>(4);
try
{
if (string.IsNullOrWhiteSpace(csv))
{
return list;
}
string[] array = csv.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < array.Length; i++)
{
string text = (array[i] ?? "").Trim();
if (text.Length == 0)
{
continue;
}
int num = text.IndexOf(':');
if (num > 0)
{
string text2 = text.Substring(0, num).Trim();
string s = text.Substring(num + 1).Trim();
if (text2.Length != 0 && int.TryParse(s, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) && result > 0)
{
list.Add((text2, result));
}
}
}
}
catch
{
}
return list;
}
private static void ApplyBuildCostIfPossible()
{
//IL_0114: Unknown result type (might be due to invalid IL or missing references)
//IL_0119: 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)
//IL_0129: Unknown result type (might be due to invalid IL or missing references)
//IL_0135: Expected O, but got Unknown
if (_costApplied || (Object)(object)ObjectDB.instance == (Object)null || (Object)(object)_totemPrefab == (Object)null)
{
return;
}
try
{
Piece component = _totemPrefab.GetComponent<Piece>();
if ((Object)(object)component == (Object)null)
{
return;
}
string csv = ((CfgBuildCostCsv != null) ? CfgBuildCostCsv.Value : "Wood:10,Thunderstone:1") ?? "";
List<(string, int)> list = ParseCostCsv(csv);
if (list.Count == 0)
{
return;
}
List<Requirement> list2 = new List<Requirement>(list.Count);
for (int i = 0; i < list.Count; i++)
{
(string, int) tuple = list[i];
string item = tuple.Item1;
int item2 = tuple.Item2;
GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(item);
ItemDrop val = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null);
if ((Object)(object)val == (Object)null)
{
Dbg("BuildCost item not found or not an ItemDrop: '" + item + "'");
continue;
}
list2.Add(new Requirement
{
m_resItem = val,
m_amount = item2,
m_recover = true
});
}
if (list2.Count > 0)
{
component.m_resources = list2.ToArray();
_costApplied = true;
}
}
catch
{
}
}
private static Piece FindReferenceWoodPiece()
{
try
{
if ((Object)(object)ZNetScene.instance == (Object)null)
{
return null;
}
string[] array = new string[7] { "wood_wall_1x1", "wood_wall_2x1", "wood_wall", "wood_floor_1x1", "wood_floor", "wood_pole", "wood_beam_2m" };
for (int i = 0; i < array.Length; i++)
{
GameObject prefab = ZNetScene.instance.GetPrefab(array[i]);
if (!((Object)(object)prefab == (Object)null))
{
Piece component = prefab.GetComponent<Piece>();
if (!((Object)(object)component == (Object)null) && component.m_placeEffect.m_effectPrefabs != null && component.m_placeEffect.m_effectPrefabs.Length != 0)
{
return component;
}
}
}
}
catch
{
}
return null;
}
private static void ApplyPlacementAndBreakEffectsIfPossible()
{
if (_effectsApplied || (Object)(object)_totemPrefab == (Object)null || (Object)(object)ZNetScene.instance == (Object)null)
{
return;
}
try
{
Piece component = _totemPrefab.GetComponent<Piece>();
if ((Object)(object)component == (Object)null)
{
return;
}
Piece val = FindReferenceWoodPiece();
if ((Object)(object)val == (Object)null)
{
return;
}
if (val.m_placeEffect.m_effectPrefabs != null && val.m_placeEffect.m_effectPrefabs.Length != 0)
{
component.m_placeEffect = val.m_placeEffect;
}
WearNTear component2 = _totemPrefab.GetComponent<WearNTear>();
WearNTear component3 = ((Component)val).gameObject.GetComponent<WearNTear>();
if ((Object)(object)component2 != (Object)null && (Object)(object)component3 != (Object)null)
{
if (component3.m_destroyedEffect.m_effectPrefabs != null && component3.m_destroyedEffect.m_effectPrefabs.Length != 0)
{
component2.m_destroyedEffect = component3.m_destroyedEffect;
}
if (component3.m_hitEffect.m_effectPrefabs != null && component3.m_hitEffect.m_effectPrefabs.Length != 0)
{
component2.m_hitEffect = component3.m_hitEffect;
}
}
_effectsApplied = true;
}
catch
{
}
}
private static void TryRegisterRpcs(bool force)
{
if (_rpcsRegistered && !force)
{
return;
}
long num = NowMs();
if (!force && num < _nextRpcRetryMs)
{
return;
}
_nextRpcRetryMs = num + 500;
ZRoutedRpc instance = ZRoutedRpc.instance;
if (instance == null || _rpcsRegistered)
{
return;
}
try
{
instance.Register<ZDOID>("RD_ServerBeginRitual", (Action<long, ZDOID>)delegate(long sender, ZDOID totemZdoid)
{
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer())
{
ServerBeginRitual(totemZdoid, PendingMode.Weather);
}
});
instance.Register<ZDOID>("RD_ServerBeginSunRitual", (Action<long, ZDOID>)delegate(long sender, ZDOID totemZdoid)
{
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer())
{
ServerBeginRitual(totemZdoid, PendingMode.Sun);
}
});
instance.Register<string, long>("RD_ClientSetEnv", (Action<long, string, long>)delegate(long sender, string env, long untilMs)
{
_clientForcedEnv = (env ?? "").Trim();
_clientForcedUntilMs = untilMs;
ApplyEnvLocal(_clientForcedEnv);
});
instance.Register<long>("RD_SetGlobalCooldown", (Action<long, long>)delegate(long sender, long untilMs)
{
_clientGlobalCooldownEndMs = untilMs;
});
instance.Register<Vector3>("RD_ClientVerdict", (Action<long, Vector3>)delegate(long sender, Vector3 pos)
{
//IL_0019: 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)
if (CfgEnableVerdictVfx != null && CfgEnableVerdictVfx.Value)
{
SpawnVerdictVfx(pos);
}
if (CfgPlayVerdictOnVerdict != null && CfgPlayVerdictOnVerdict.Value)
{
float volume = ((CfgVerdictVolume != null) ? Mathf.Clamp01(CfgVerdictVolume.Value) : 1f);
PlayOneShot(_verdictClip, pos, volume);
}
});
instance.Register<Vector3>("RD_ClientLightningVfx", (Action<long, Vector3>)delegate(long sender, Vector3 pos)
{
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
if (CfgAlsoPlayClientLightningVfx == null || CfgAlsoPlayClientLightningVfx.Value)
{
SpawnLightningAoe_LocalVisual(pos);
}
});
instance.Register<string>("RD_ClientMythLine", (Action<long, string>)delegate(long sender, string line)
{
if ((CfgEnableMythLines == null || CfgEnableMythLines.Value) && (Object)(object)MessageHud.instance != (Object)null && !string.IsNullOrWhiteSpace(line))
{
MessageHud.instance.ShowMessage((MessageType)2, line, 0, (Sprite)null, false);
}
});
instance.Register<bool, float>("RD_ClientSetDebugTime", (Action<long, bool, float>)delegate(long sender, bool enabled, float tod)
{
_clientForcedTimeEnabled = enabled;
_clientForcedTimeOfDay = Mathf.Repeat(tod, 1f);
ApplyDebugTimeLocal(_clientForcedTimeEnabled, _clientForcedTimeOfDay);
});
_rpcsRegistered = true;
}
catch (Exception arg)
{
_rpcsRegistered = false;
try
{
ManualLogSource log = Log;
if (log != null)
{
log.LogWarning((object)$"[RainDance] RPC registration failed; will retry. {arg}");
}
}
catch
{
}
}
}
private static long GetGlobalCooldownEndMs()
{
if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer())
{
return _serverGlobalCooldownEndMs;
}
return _clientGlobalCooldownEndMs;
}
private static void SetServerGlobalCooldownEndMs(long untilMs)
{
_serverGlobalCooldownEndMs = Math.Max(_serverGlobalCooldownEndMs, untilMs);
try
{
if (ZRoutedRpc.instance != null)
{
ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "RD_SetGlobalCooldown", new object[1] { _serverGlobalCooldownEndMs });
}
}
catch
{
}
}
private static void BroadcastEnvToClients(string env, long untilMs)
{
try
{
if (ZRoutedRpc.instance != null)
{
ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "RD_ClientSetEnv", new object[2]
{
(env ?? "").Trim(),
untilMs
});
}
}
catch
{
}
}
private static void BroadcastDebugTimeToClients(bool enabled, float tod)
{
try
{
if (ZRoutedRpc.instance != null)
{
ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "RD_ClientSetDebugTime", new object[2]
{
enabled,
Mathf.Repeat(tod, 1f)
});
}
}
catch
{
}
}
private static void BroadcastVerdict(Vector3 pos)
{
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
try
{
if (ZRoutedRpc.instance != null)
{
ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "RD_ClientVerdict", new object[1] { pos });
}
}
catch
{
}
}
private static void BroadcastLightningVfx(Vector3 pos)
{
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
try
{
if (ZRoutedRpc.instance != null)
{
ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "RD_ClientLightningVfx", new object[1] { pos });
}
}
catch
{
}
}
private static void BroadcastMythLine(string line)
{
try
{
if (ZRoutedRpc.instance != null)
{
ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "RD_ClientMythLine", new object[1] { line ?? "" });
}
}
catch
{
}
}
private static void ServerBeginRitual(ZDOID totemZdoid, PendingMode mode)
{
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_010c: Unknown result type (might be due to invalid IL or missing references)
//IL_0111: Unknown result type (might be due to invalid IL or missing references)
//IL_011f: Unknown result type (might be due to invalid IL or missing references)
//IL_0120: Unknown result type (might be due to invalid IL or missing references)
//IL_0125: Unknown result type (might be due to invalid IL or missing references)
//IL_0127: Unknown result type (might be due to invalid IL or missing references)
long num = NowMs();
if (_pending)
{
return;
}
long globalCooldownEndMs = GetGlobalCooldownEndMs();
if (globalCooldownEndMs > num)
{
return;
}
ZDO val = ((ZDOMan.instance != null) ? ZDOMan.instance.GetZDO(totemZdoid) : null);
if (val == null)
{
return;
}
long @long = val.GetLong("RD_RitualEndMs", 0L);
if (@long <= num)
{
long long2 = val.GetLong("RD_CooldownEndMs", 0L);
if (long2 <= num)
{
long num2 = (long)(Mathf.Max(1f, CfgAnticipationSeconds.Value) * 1000f);
long num3 = (long)(Mathf.Max(5f, CfgGlobalCooldownSeconds.Value) * 1000f);
val.Set("RD_RitualEndMs", num + num2);
val.Set("RD_RitualMode", (int)mode);
val.Set("RD_RitualNonce", num);
SetServerGlobalCooldownEndMs(num + num3);
val.Set("RD_CooldownEndMs", num + num3);
Vector3 position = val.GetPosition();
_pending = true;
_pendingMode = mode;
_pendingTotemZdoid = totemZdoid;
_pendingTotemPos = position;
_pendingResolveAtMs = num + num2;
_pendingNonce = num;
}
}
}
private static void ServerTick()
{
if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer())
{
return;
}
long num = NowMs();
if (_pending && num >= _pendingResolveAtMs)
{
ResolvePending();
}
if (_serverForcedUntilMs > num)
{
ApplyEnvLocal(_serverForcedEnv);
if (_serverForcedTimeEnabled)
{
ApplyDebugTimeLocal(enabled: true, _serverForcedTimeOfDay);
}
if (_nextForcedEnvBroadcastMs <= num)
{
_nextForcedEnvBroadcastMs = num + 10000;
BroadcastEnvToClients(_serverForcedEnv, _serverForcedUntilMs);
if (_serverForcedTimeEnabled)
{
BroadcastDebugTimeToClients(enabled: true, _serverForcedTimeOfDay);
}
}
}
else if (_serverForcedUntilMs != 0)
{
_serverForcedUntilMs = 0L;
_serverForcedEnv = "";
ApplyEnvLocal("");
BroadcastEnvToClients("", 0L);
if (_serverForcedTimeEnabled)
{
_serverForcedTimeEnabled = false;
ApplyDebugTimeLocal(enabled: false, 0.5f);
BroadcastDebugTimeToClients(enabled: false, 0.5f);
}
}
TickPendingDestructs(num);
}
private static void ResolvePending()
{
//IL_001c: 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_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
long now = NowMs();
_pending = false;
ZDO val = ((ZDOMan.instance != null) ? ZDOMan.instance.GetZDO(_pendingTotemZdoid) : null);
if (val == null)
{
BroadcastVerdict(_pendingTotemPos);
MaybeScheduleSelfDestruct(_pendingTotemZdoid, _pendingTotemPos);
SendMythLine(_pendingMode, "Interrupted");
return;
}
long @long = val.GetLong("RD_RitualNonce", 0L);
if (@long == _pendingNonce)
{
val.Set("RD_RitualEndMs", 0L);
if (_pendingMode == PendingMode.Sun)
{
ResolvePending_Sun(now);
}
else
{
ResolvePending_Weather(now);
}
}
}
private static void ResolvePending_Weather(long now)
{
//IL_00f1: 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_0101: Unknown result type (might be due to invalid IL or missing references)
//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
float num = Mathf.Clamp01(CfgChanceWeatherChange.Value);
float num2 = Mathf.Clamp01(CfgChanceGoodWhenChanging.Value);
string env = "";
try
{
if ((Object)(object)EnvMan.instance != (Object)null)
{
EnvSetup currentEnvironment = EnvMan.instance.GetCurrentEnvironment();
if (currentEnvironment != null && !string.IsNullOrWhiteSpace(currentEnvironment.m_name))
{
env = currentEnvironment.m_name.Trim();
}
}
}
catch
{
env = "";
}
if (IsClearish(env))
{
num = Mathf.Clamp01(num + Mathf.Clamp01(CfgClearWeatherChangeBoost.Value));
num2 = Mathf.Clamp01(num2 - Mathf.Clamp01(CfgClearWeatherBadBias.Value));
}
if (CfgDebugForceWeatherChange != null && CfgDebugForceWeatherChange.Value)
{
num = 1f;
}
if (!(Random.value <= num))
{
BroadcastVerdict(_pendingTotemPos);
MaybeScheduleSelfDestruct(_pendingTotemZdoid, _pendingTotemPos);
SendMythLine(PendingMode.Weather, "NoChange");
return;
}
bool flag = Random.value <= num2;
string text = PickEnvFromCsv(flag ? CfgGoodEnvsCsv.Value : CfgBadEnvsCsv.Value);
if (string.IsNullOrWhiteSpace(text))
{
text = (flag ? "Clear" : "Rain");
}
long num3 = (long)(Mathf.Max(10f, CfgForcedDurationSeconds.Value) * 1000f);
_serverForcedEnv = text.Trim();
_serverForcedUntilMs = Math.Max(_serverForcedUntilMs, now) + num3;
_serverForcedTimeEnabled = false;
ApplyEnvLocal(_serverForcedEnv);
BroadcastEnvToClients(_serverForcedEnv, _serverForcedUntilMs);
BroadcastVerdict(_pendingTotemPos);
MaybeScheduleSelfDestruct(_pendingTotemZdoid, _pendingTotemPos);
SendMythLine(PendingMode.Weather, _serverForcedEnv);
}
private static void ResolvePending_Sun(long now)
{
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
//IL_0163: Unknown result type (might be due to invalid IL or missing references)
//IL_016e: 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)
float num = Mathf.Clamp01(CfgSunChanceChange.Value);
float num2 = Mathf.Clamp01(CfgSunChanceGoodWhenChanging.Value);
if (!(Random.value <= num))
{
BroadcastVerdict(_pendingTotemPos);
MaybeScheduleSelfDestruct(_pendingTotemZdoid, _pendingTotemPos);
SendMythLine(PendingMode.Sun, "NoChange");
return;
}
bool flag = Random.value <= num2;
string text = PickEnvFromCsv(flag ? CfgSunGoodEnvsCsv.Value : CfgSunBadEnvsCsv.Value);
if (string.IsNullOrWhiteSpace(text))
{
text = (flag ? "Clear" : "Darklands_dark");
}
float num3 = PickTimeFromCsv(flag ? CfgSunGoodTimesCsv.Value : CfgSunBadTimesCsv.Value, flag ? 0.5f : 0f);
long num4 = (long)(Mathf.Max(10f, CfgForcedDurationSeconds.Value) * 1000f);
_serverForcedEnv = text.Trim();
_serverForcedUntilMs = Math.Max(_serverForcedUntilMs, now) + num4;
_serverForcedTimeEnabled = true;
_serverForcedTimeOfDay = Mathf.Repeat(num3, 1f);
ApplyEnvLocal(_serverForcedEnv);
ApplyDebugTimeLocal(enabled: true, _serverForcedTimeOfDay);
BroadcastEnvToClients(_serverForcedEnv, _serverForcedUntilMs);
BroadcastDebugTimeToClients(enabled: true, _serverForcedTimeOfDay);
BroadcastVerdict(_pendingTotemPos);
MaybeScheduleSelfDestruct(_pendingTotemZdoid, _pendingTotemPos);
SendMythLine(PendingMode.Sun, flag ? "SunGood" : "SunBad");
}
private static void SendMythLine(PendingMode mode, string key)
{
try
{
if (CfgEnableMythLines == null || CfgEnableMythLines.Value)
{
string mythLine = GetMythLine(mode, key ?? "");
if (!string.IsNullOrWhiteSpace(mythLine))
{
BroadcastMythLine(mythLine);
}
}
}
catch
{
}
}
private static string PickRandom(string[] lines)
{
try
{
if (lines == null || lines.Length == 0)
{
return "";
}
int num = Random.Range(0, lines.Length);
if (num < 0 || num >= lines.Length)
{
num = 0;
}
return lines[num] ?? "";
}
catch
{
return "";
}
}
private static string GetMythLine(PendingMode mode, string key)
{
string text = (key ?? "").Trim();
if (text.Equals("NoChange", StringComparison.OrdinalIgnoreCase))
{
if (mode == PendingMode.Sun)
{
string[] lines = new string[3] { "Sól listens... and keeps her pace.", "Máni turns his face away.", "Heimdall hears you—yet the sky holds steady." };
return PickRandom(lines);
}
string[] lines2 = new string[4] { "Odin watches... and offers no omen.", "Heimdall keeps the gate closed.", "Freya turns away without a word.", "Thor does not lift Mjölnir today." };
return PickRandom(lines2);
}
if (text.Equals("Interrupted", StringComparison.OrdinalIgnoreCase))
{
if (mode == PendingMode.Sun)
{
string[] lines3 = new string[3] { "Heimdall cuts the rite short.", "Odin snaps the thread—day and night refuse you.", "Máni blinks, and the moment is gone." };
return PickRandom(lines3);
}
string[] lines4 = new string[3] { "Odin cuts the thread. The skies refuse the tale.", "Heimdall scatters the rite before it takes root.", "Freya withdraws her hand—the omen breaks." };
return PickRandom(lines4);
}
if (mode == PendingMode.Sun)
{
if (text.Equals("SunGood", StringComparison.OrdinalIgnoreCase))
{
string[] lines5 = new string[5] { "Sól smiles upon your steps.", "Freyr lifts the veil—warmth returns.", "Heimdall opens the gate of light.", "Odin's ravens circle, and the day stands tall.", "Baldr's calm drifts over the fields." };
return PickRandom(lines5);
}
if (text.Equals("SunBad", StringComparison.OrdinalIgnoreCase))
{
string[] lines6 = new string[4] { "Máni draws the world into shadow.", "Skadi walks the long dark road.", "Odin closes one eye—and the night deepens.", "Hel's hush creeps into the grass." };
return PickRandom(lines6);
}
return "Heimdall shifts his gaze across the horizon.";
}
if (text.Equals("ThunderStorm", StringComparison.OrdinalIgnoreCase))
{
string[] lines7 = new string[2] { "Thor answers your call.", "Thor raises Mjölnir in the clouds." };
return PickRandom(lines7);
}
if (text.Equals("Clear", StringComparison.OrdinalIgnoreCase) || text.Equals("LightClouds", StringComparison.OrdinalIgnoreCase) || text.Equals("Twilight_Clear", StringComparison.OrdinalIgnoreCase))
{
string[] lines8 = new string[2] { "Freya swings her blade.", "Freya lays a calm hand on the sky." };
return PickRandom(lines8);
}
if (text.Equals("Rain", StringComparison.OrdinalIgnoreCase) || text.Equals("LightRain", StringComparison.OrdinalIgnoreCase))
{
string[] lines9 = new string[2] { "Njord turns his gaze seaward.", "Njord sends his saltwind through the clouds." };
return PickRandom(lines9);
}
if (text.Equals("Misty", StringComparison.OrdinalIgnoreCase))
{
string[] lines10 = new string[2] { "Odin veils the world with one eye.", "Odin's ravens vanish into the fog." };
return PickRandom(lines10);
}
if (text.Equals("Snow", StringComparison.OrdinalIgnoreCase) || text.Equals("SnowStorm", StringComparison.OrdinalIgnoreCase))
{
string[] lines11 = new string[2] { "Skadi walks the white road.", "Skadi draws her cloak across the land." };
return PickRandom(lines11);
}
return "Odin stirs above.";
}
private static void MaybeScheduleSelfDestruct(ZDOID totemZdoid, Vector3 pos)
{
//IL_0089: Unknown result type (might be due to invalid IL or missing references)
//IL_008a: 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_0092: Unknown result type (might be due to invalid IL or missing references)
try
{
if (CfgSelfDestructAfterUse != null && CfgSelfDestructAfterUse.Value)
{
float num = ((CfgSelfDestructDelaySeconds != null) ? Mathf.Max(0.05f, CfgSelfDestructDelaySeconds.Value) : 1.05f);
long num2 = NowMs();
long strikeAtMs = num2 + Math.Max(0L, (long)(Mathf.Max(0f, num - 0.12f) * 1000f));
long destroyAtMs = num2 + (long)(num * 1000f);
_pendingDestructs.Add(new PendingDestruct
{
Zdoid = totemZdoid,
Pos = pos,
StrikeAtMs = strikeAtMs,
DestroyAtMs = destroyAtMs,
Struck = false
});
}
}
catch
{
}
}
private static void TickPendingDestructs(long now)
{
//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
//IL_00b9: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
if (_pendingDestructs.Count == 0)
{
return;
}
for (int num = _pendingDestructs.Count - 1; num >= 0; num--)
{
PendingDestruct value = _pendingDestructs[num];
if (!value.Struck && now >= value.StrikeAtMs)
{
value.Struck = true;
_pendingDestructs[num] = value;
if (CfgSpawnLightningAoeServer != null && CfgSpawnLightningAoeServer.Value)
{
SpawnLightningAoe_ServerAuthoritative(value.Pos);
if (CfgAlsoPlayClientLightningVfx != null && CfgAlsoPlayClientLightningVfx.Value)
{
BroadcastLightningVfx(value.Pos);
}
}
else
{
BroadcastLightningVfx(value.Pos);
}
}
if (now >= value.DestroyAtMs)
{
_pendingDestructs.RemoveAt(num);
DestroyTotemByZdoid(value.Zdoid);
}
}
}
private static void DestroyTotemByZdoid(ZDOID zdoid)
{
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
try
{
if ((Object)(object)ZNetScene.instance == (Object)null)
{
return;
}
GameObject val = null;
try
{
val = ZNetScene.instance.FindInstance(zdoid);
}
catch
{
val = null;
}
if (!((Object)(object)val == (Object)null))
{
ZNetView component = val.GetComponent<ZNetView>();
if ((Object)(object)component != (Object)null && component.IsValid())
{
component.Destroy();
}
else
{
Object.Destroy((Object)(object)val);
}
}
}
catch
{
}
}
private static void SpawnLightningAoe_ServerAuthoritative(Vector3 pos)
{
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
try
{
if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && !((Object)(object)ZNetScene.instance == (Object)null))
{
GameObject prefab = ZNetScene.instance.GetPrefab("lightningAOE");
if (!((Object)(object)prefab == (Object)null))
{
ZNetScene.instance.SpawnObject(pos, Quaternion.identity, prefab);
}
}
}
catch
{
}
}
private static void SpawnLightningAoe_LocalVisual(Vector3 pos)
{
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
try
{
if (!((Object)(object)ZNetScene.instance == (Object)null))
{
GameObject prefab = ZNetScene.instance.GetPrefab("lightningAOE");
if (!((Object)(object)prefab == (Object)null))
{
Object.Instantiate<GameObject>(prefab, pos, Quaternion.identity);
}
}
}
catch
{
}
}
private static bool IsClearish(string env)
{
if (string.IsNullOrWhiteSpace(env))
{
return false;
}
string text = env.Trim();
if (text.Equals("Clear", StringComparison.OrdinalIgnoreCase))
{
return true;
}
if (text.Equals("LightClouds", StringComparison.OrdinalIgnoreCase))
{
return true;
}
if (text.Equals("Twilight_Clear", StringComparison.OrdinalIgnoreCase))
{
return true;
}
if (text.IndexOf("clear", StringComparison.OrdinalIgnoreCase) >= 0)
{
return true;
}
return false;
}
private static string PickEnvFromCsv(string csv)
{
try
{
if (string.IsNullOrWhiteSpace(csv))
{
return "";
}
string[] array = (from s in csv.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries)
select (s ?? "").Trim() into s
where s.Length > 0
select s).ToArray();
if (array.Length == 0)
{
return "";
}
return array[Random.Range(0, array.Length)];
}
catch
{
return "";
}
}
private static float PickTimeFromCsv(string csv, float fallback)
{
try
{
if (string.IsNullOrWhiteSpace(csv))
{
return Mathf.Repeat(fallback, 1f);
}
string[] array = (from s in csv.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries)
select (s ?? "").Trim() into s
where s.Length > 0
select s).ToArray();
if (array.Length == 0)
{
return Mathf.Repeat(fallback, 1f);
}
List<float> list = new List<float>(array.Length);
for (int i = 0; i < array.Length; i++)
{
if (float.TryParse(array[i], NumberStyles.Float, CultureInfo.InvariantCulture, out var result) && !float.IsNaN(result) && !float.IsInfinity(result))
{
list.Add(Mathf.Repeat(result, 1f));
}
}
if (list.Count == 0)
{
return Mathf.Repeat(fallback, 1f);
}
return list[Random.Range(0, list.Count)];
}
catch
{
return Mathf.Repeat(fallback, 1f);
}
}
private static void ApplyEnvLocal(string env)
{
try
{
if (!((Object)(object)EnvMan.instance == (Object)null))
{
EnvMan.instance.m_debugEnv = (env ?? "").Trim();
}
}
catch
{
}
}
private static void ApplyDebugTimeLocal(bool enabled, float tod)
{
try
{
if (!((Object)(object)EnvMan.instance == (Object)null))
{
EnvMan.instance.m_debugTimeOfDay = enabled;
if (enabled)
{
EnvMan.instance.m_debugTime = Mathf.Repeat(tod, 1f);
}
}
}
catch
{
}
}
private static void SpawnVerdictVfx(Vector3 pos)
{
//IL_0082: 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_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_0097: Unknown result type (might be due to invalid IL or missing references)
try
{
if ((Object)(object)ZNetScene.instance == (Object)null)
{
return;
}
string[] array = new string[4] { "vfx_Potion_health_medium", "vfx_Potion_health_small", "vfx_Potion_health", "vfx_Healing" };
GameObject val = null;
for (int i = 0; i < array.Length; i++)
{
val = ZNetScene.instance.GetPrefab(array[i]);
if ((Object)(object)val != (Object)null)
{
break;
}
}
if (!((Object)(object)val == (Object)null))
{
Object.Instantiate<GameObject>(val, pos + Vector3.up * 1f, Quaternion.identity);
}
}
catch
{
}
}
private static void TryRequestDrumClipLoad()
{
if (!_drumClipRequested && !((Object)(object)_instance == (Object)null) && CfgPlayDrumOnInteract != null && CfgPlayDrumOnInteract.Value)
{
_drumClipRequested = true;
((MonoBehaviour)_instance).StartCoroutine(LoadClipCoroutine(() => (CfgDrumFileName != null) ? CfgDrumFileName.Value : "RD_Drums.ogg", delegate(AudioClip clip)
{
_drumClip = clip;
}));
}
}
private static void TryRequestVerdictClipLoad()
{
if (!_verdictClipRequested && !((Object)(object)_instance == (Object)null) && CfgPlayVerdictOnVerdict != null && CfgPlayVerdictOnVerdict.Value)
{
_verdictClipRequested = true;
((MonoBehaviour)_instance).StartCoroutine(LoadClipCoroutine(() => (CfgVerdictFileName != null) ? CfgVerdictFileName.Value : "RD_Verdict.ogg", delegate(AudioClip clip)
{
_verdictClip = clip;
}));
}
}
[IteratorStateMachine(typeof(<LoadClipCoroutine>d__129))]
private static IEnumerator LoadClipCoroutine(Func<string> getFileName, Action<AudioClip> assign)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <LoadClipCoroutine>d__129(0)
{
getFileName = getFileName,
assign = assign
};
}
private static void PlayOneShot(AudioClip clip, Vector3 pos, float volume)
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
try
{
if (!((Object)(object)clip == (Object)null))
{
float num = Mathf.Clamp01(volume);
if (!(num <= 0f))
{
AudioSource.PlayClipAtPoint(clip, pos, num);
}
}
}
catch
{
}
}
private static bool IsTextInputOpen()
{
try
{
if ((Object)(object)Chat.instance != (Object)null && Chat.instance.HasFocus())
{
return true;
}
}
catch
{
}
try
{
if (Console.IsVisible())
{
return true;
}
}
catch
{
}
try
{
if (TextInput.IsVisible())
{
return true;
}
}
catch
{
}
return false;
}
private static GameObject TryGetLocalHoverObject(Player p)
{
try
{
return ((Object)(object)p == (Object)null) ? null : PlayerHoveringRef.Invoke(p);
}
catch
{
return null;
}
}
private static void LateInitOnce()
{
try
{
if (!_addedToHammer || !_costApplied)
{
EnsurePrefabLoaded();
if ((Object)(object)ZNetScene.instance != (Object)null)
{
RegisterPrefabInZNetScene();
}
if ((Object)(object)ObjectDB.instance != (Object)null)
{
TryAddToHammer(ObjectDB.instance);
ApplyBuildCostIfPossible();
}
ApplyPlacementAndBreakEffectsIfPossible();
}
}
catch
{
}
}
}
}