using System;
using System.Collections;
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 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.1.3")]
public sealed class RainDancePlugin : BaseUnityPlugin
{
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.Value)
{
return "Disabled";
}
long num = NowMs();
long globalCooldownEndMs = GetGlobalCooldownEndMs();
string text = ((CfgSelfDestructAfterUse != null && CfgSelfDestructAfterUse.Value) ? "\n<color=#9fdcff>The wood smells of storm.</color>" : "");
if (globalCooldownEndMs > num)
{
int num2 = Mathf.CeilToInt((float)(globalCooldownEndMs - num) / 1000f);
return $"[E] Tempt the skies (cooldown {num2}s){text}";
}
return "[E] Tempt the skies" + text;
}
public bool Interact(Humanoid user, bool hold, bool alt)
{
//IL_00b4: 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)
if (hold)
{
return false;
}
if (!CfgEnabled.Value)
{
return true;
}
long num = NowMs();
long globalCooldownEndMs = GetGlobalCooldownEndMs();
if (globalCooldownEndMs > num)
{
return true;
}
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) ? CfgDrumVolume.Value : 0.75f);
PlayOneShot(_drumClip, ((Component)val).transform.position, volume);
}
}
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;
}
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();
TryRegisterRpcs(force: true);
}
[HarmonyPatch(typeof(ObjectDB), "Awake")]
[HarmonyPostfix]
private static void ObjectDB_Awake_Postfix(ObjectDB __instance)
{
EnsurePrefabLoaded();
TryAddToHammer(__instance);
ApplyBuildCostIfPossible();
}
[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
[HarmonyPostfix]
private static void ObjectDB_CopyOtherDB_Postfix(ObjectDB __instance)
{
EnsurePrefabLoaded();
TryAddToHammer(__instance);
ApplyBuildCostIfPossible();
}
[HarmonyPatch(typeof(Player), "PlacePiece")]
[HarmonyPrefix]
private static void Player_PlacePiece_Prefix(object[] __args)
{
try
{
if (__args != null && __args.Length >= 1)
{
object obj = __args[0];
Piece val = (Piece)((obj is Piece) ? obj : null);
if (IsRainDanceTotemPiece(val))
{
ForceStripAllEffects(((Component)val).gameObject);
}
}
}
catch
{
}
}
[HarmonyPatch(typeof(EnvMan), "Update")]
[HarmonyPostfix]
private static void EnvMan_Update_Postfix(EnvMan __instance)
{
if (CfgEnabled.Value)
{
TryRegisterRpcs(force: false);
long num = NowMs();
if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer())
{
ServerTick();
}
else if (_clientForcedUntilMs > num)
{
ApplyEnvLocal(_clientForcedEnv);
}
else if (_clientForcedUntilMs != 0)
{
_clientForcedUntilMs = 0L;
_clientForcedEnv = "";
ApplyEnvLocal("");
}
}
}
}
[CompilerGenerated]
private sealed class <LoadClipCoroutine>d__94 : 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__94(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.1.3";
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 RpcServerBeginRitual = "RD_ServerBeginRitual";
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 static ConfigEntry<bool> CfgEnabled;
private static ConfigEntry<string> CfgPreset;
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<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 bool _rpcsRegistered;
private static long _nextRpcRetryMs;
private static bool _registeredInZNetScene;
private static bool _addedToHammer;
private static bool _costApplied;
private static string _serverForcedEnv = "";
private static long _serverForcedUntilMs = 0L;
private static string _clientForcedEnv = "";
private static long _clientForcedUntilMs = 0L;
private static long _globalCooldownEndMs = 0L;
private static long _clientGlobalCooldownEndMs = 0L;
private static bool _pending;
private static ZDOID _pendingTotemZdoid;
private static Vector3 _pendingTotemPos;
private static long _pendingResolveAtMs;
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 Dictionary<Type, FieldInfo[]> _effectListFieldsCache = new Dictionary<Type, FieldInfo[]>(8);
private void Awake()
{
_instance = this;
Log = ((BaseUnityPlugin)this).Logger;
CfgEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable/disable RainDance.");
CfgPreset = ((BaseUnityPlugin)this).Config.Bind<string>("General", "Preset", "MostlyClear", "Preset: Custom, MostlyClear, ChaosWeather");
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 weather is forced (seconds).");
CfgChanceWeatherChange = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ChanceWeatherChange", 0.75f, "Chance (0-1) the ritual changes weather (vs no change).");
CfgChanceGoodWhenChanging = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ChanceGoodWhenChanging", 0.65f, "If changing weather, chance (0-1) it is Good vs Bad.");
CfgGoodEnvsCsv = ((BaseUnityPlugin)this).Config.Bind<string>("General", "GoodEnvsCsv", "Clear", "Good env pool.");
CfgBadEnvsCsv = ((BaseUnityPlugin)this).Config.Bind<string>("General", "BadEnvsCsv", "Rain,LightRain,ThunderStorm,Misty,Snow,SnowStorm", "Bad env pool.");
CfgClearWeatherBadBias = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ClearWeatherBadBias", 0.25f, "When weather is clear-ish, reduce Good chance by this amount.");
CfgClearWeatherChangeBoost = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ClearWeatherChangeBoost", 0.1f, "When weather is clear-ish, boost ChanceWeatherChange by this amount.");
CfgPlayDrumOnInteract = ((BaseUnityPlugin)this).Config.Bind<bool>("Audio", "PlayDrumOnInteract", true, "Play drum on interact (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", 0.85f, "Verdict volume (0-1).");
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 weather.");
CfgMythLinesRevealEnvInLogs = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "RevealEnvInLogs", false, "Debug only: print the chosen env to log.");
CfgLogDebug = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "LogDebug", false, "Debug logs.");
CfgDebugForceWeatherChange = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "DebugForceWeatherChange", false, "Always change weather (testing).");
ApplyPresetIfNeeded();
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))
{
if (text.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 (text.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>();
}
ForceStripAllEffects(_totemPrefab);
}
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 void ApplyBuildCostIfPossible()
{
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_0094: 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;
}
GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("Wood");
if (!((Object)(object)itemPrefab == (Object)null))
{
ItemDrop component2 = itemPrefab.GetComponent<ItemDrop>();
if (!((Object)(object)component2 == (Object)null))
{
Requirement val = new Requirement();
val.m_resItem = component2;
val.m_amount = 10;
val.m_recover = true;
component.m_resources = (Requirement[])(object)new Requirement[1] { val };
_costApplied = true;
}
}
}
catch
{
}
}
private static void TryRegisterRpcs(bool force)
{
if (_rpcsRegistered && !force)
{
return;
}
long num = NowMs();
if (!force && num < _nextRpcRetryMs)
{
return;
}
_nextRpcRetryMs = num + 1000;
ZRoutedRpc instance = ZRoutedRpc.instance;
if (instance == null || _rpcsRegistered)
{
return;
}
_rpcsRegistered = true;
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);
}
});
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_0057: 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) ? CfgVerdictVolume.Value : 0.85f);
PlayOneShot(_verdictClip, pos, volume);
}
});
instance.Register<Vector3>("RD_ClientLightningVfx", (Action<long, Vector3>)delegate(long sender, Vector3 pos)
{
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
try
{
if (CfgAlsoPlayClientLightningVfx == null || CfgAlsoPlayClientLightningVfx.Value)
{
SpawnLightningAoe_LocalVisual(pos);
}
}
catch
{
}
});
instance.Register<string>("RD_ClientMythLine", (Action<long, string>)delegate(long sender, string line)
{
try
{
if ((CfgEnableMythLines == null || CfgEnableMythLines.Value) && (Object)(object)MessageHud.instance != (Object)null && !string.IsNullOrWhiteSpace(line))
{
MessageHud.instance.ShowMessage((MessageType)2, line, 0, (Sprite)null, false);
}
}
catch
{
}
});
}
private static long GetGlobalCooldownEndMs()
{
if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer())
{
return _globalCooldownEndMs;
}
return _clientGlobalCooldownEndMs;
}
private static void SetGlobalCooldownEndMs(long untilMs)
{
_globalCooldownEndMs = Math.Max(_globalCooldownEndMs, untilMs);
try
{
if (ZRoutedRpc.instance != null)
{
ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "RD_SetGlobalCooldown", new object[1] { _globalCooldownEndMs });
}
}
catch
{
}
}
private static void ServerBeginRitual(ZDOID totemZdoid)
{
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
//IL_00a1: 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_00a7: 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)
long num = NowMs();
if (_pending)
{
return;
}
long globalCooldownEndMs = GetGlobalCooldownEndMs();
if (globalCooldownEndMs <= num)
{
ZDO val = ((ZDOMan.instance != null) ? ZDOMan.instance.GetZDO(totemZdoid) : null);
if (val != null)
{
long num2 = (long)(Mathf.Max(5f, CfgGlobalCooldownSeconds.Value) * 1000f);
SetGlobalCooldownEndMs(num + num2);
Vector3 position = val.GetPosition();
long num3 = (long)(Mathf.Max(1f, CfgAnticipationSeconds.Value) * 1000f);
_pending = true;
_pendingTotemZdoid = totemZdoid;
_pendingTotemPos = position;
_pendingResolveAtMs = num + num3;
long num4 = (long)(Mathf.Max(5f, CfgGlobalCooldownSeconds.Value) * 1000f);
val.Set("RD_CooldownEndMs", num + num4);
}
}
}
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 (_nextForcedEnvBroadcastMs <= num)
{
_nextForcedEnvBroadcastMs = num + 10000;
BroadcastEnvToClients(_serverForcedEnv, _serverForcedUntilMs);
}
}
else if (_serverForcedUntilMs != 0)
{
_serverForcedUntilMs = 0L;
_serverForcedEnv = "";
ApplyEnvLocal("");
BroadcastEnvToClients("", 0L);
}
TickPendingDestructs(num);
}
private static void ResolvePending()
{
//IL_001c: 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)
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_0153: Unknown result type (might be due to invalid IL or missing references)
//IL_015e: 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_0251: Unknown result type (might be due to invalid IL or missing references)
//IL_025c: Unknown result type (might be due to invalid IL or missing references)
//IL_0261: Unknown result type (might be due to invalid IL or missing references)
long val = NowMs();
_pending = false;
ZDO val2 = ((ZDOMan.instance != null) ? ZDOMan.instance.GetZDO(_pendingTotemZdoid) : null);
if (val2 == null)
{
BroadcastVerdict(_pendingTotemPos);
MaybeScheduleSelfDestruct(_pendingTotemZdoid, _pendingTotemPos);
SendMythLineForEnv("Interrupted");
return;
}
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);
SendMythLineForEnv("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, val) + num3;
if (CfgMythLinesRevealEnvInLogs != null && CfgMythLinesRevealEnvInLogs.Value)
{
Dbg("Chosen env: " + _serverForcedEnv);
}
ApplyEnvLocal(_serverForcedEnv);
BroadcastEnvToClients(_serverForcedEnv, _serverForcedUntilMs);
BroadcastVerdict(_pendingTotemPos);
MaybeScheduleSelfDestruct(_pendingTotemZdoid, _pendingTotemPos);
SendMythLineForEnv(_serverForcedEnv);
}
private static void SendMythLineForEnv(string env)
{
try
{
if (CfgEnableMythLines == null || CfgEnableMythLines.Value)
{
string mythLineForEnv = GetMythLineForEnv(env ?? "");
if (!string.IsNullOrWhiteSpace(mythLineForEnv) && ZRoutedRpc.instance != null)
{
ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "RD_ClientMythLine", new object[1] { mythLineForEnv });
}
}
}
catch
{
}
}
private static string GetMythLineForEnv(string env)
{
string text = (env ?? "").Trim();
if (text.Equals("NoChange", StringComparison.OrdinalIgnoreCase))
{
return "The gods watch... and say nothing.";
}
if (text.Equals("Interrupted", StringComparison.OrdinalIgnoreCase))
{
return "The thread is cut short. The skies refuse the tale.";
}
if (text.Equals("ThunderStorm", StringComparison.OrdinalIgnoreCase))
{
return "Thor answers your call.";
}
if (text.Equals("Clear", StringComparison.OrdinalIgnoreCase) || text.Equals("LightClouds", StringComparison.OrdinalIgnoreCase) || text.Equals("Twilight_Clear", StringComparison.OrdinalIgnoreCase))
{
return "Freya swings her blade.";
}
if (text.Equals("Rain", StringComparison.OrdinalIgnoreCase) || text.Equals("LightRain", StringComparison.OrdinalIgnoreCase))
{
return "Njord turns his gaze seaward.";
}
if (text.Equals("Misty", StringComparison.OrdinalIgnoreCase))
{
return "Odin veils the world with one eye.";
}
if (text.Equals("Snow", StringComparison.OrdinalIgnoreCase) || text.Equals("SnowStorm", StringComparison.OrdinalIgnoreCase))
{
return "Skadi walks the white road.";
}
return "Something ancient 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_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
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)
{
Dbg("Server could not find prefab 'lightningAOE' in ZNetScene.");
}
else
{
ZNetScene.instance.SpawnObject(pos, Quaternion.identity, prefab);
}
}
}
catch (Exception arg)
{
Dbg($"SpawnLightningAoe_ServerAuthoritative exception: {arg}");
}
}
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 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 void ApplyEnvLocal(string env)
{
try
{
if (!((Object)(object)EnvMan.instance == (Object)null))
{
EnvMan.instance.m_debugEnv = (env ?? "").Trim();
}
}
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 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 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__94))]
private static IEnumerator LoadClipCoroutine(Func<string> getFileName, Action<AudioClip> assign)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <LoadClipCoroutine>d__94(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 IsRainDanceTotemPiece(Piece piece)
{
try
{
if ((Object)(object)piece == (Object)null)
{
return false;
}
GameObject gameObject = ((Component)piece).gameObject;
if ((Object)(object)gameObject == (Object)null)
{
return false;
}
return string.Equals(((Object)gameObject).name, "RD_Totem_Root", StringComparison.OrdinalIgnoreCase);
}
catch
{
return false;
}
}
private static EffectList MakeEmptyEffectList()
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Expected O, but got Unknown
return new EffectList
{
m_effectPrefabs = Array.Empty<EffectData>()
};
}
private static FieldInfo[] GetEffectListFieldsCached(Type t)
{
if (t == null)
{
return Array.Empty<FieldInfo>();
}
if (_effectListFieldsCache.TryGetValue(t, out var value))
{
return value;
}
FieldInfo[] array = (from f in t.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
where f != null && f.FieldType == typeof(EffectList)
select f).ToArray();
_effectListFieldsCache[t] = array;
return array;
}
private static void StripEffectListsOnComponent(Component c)
{
try
{
if ((Object)(object)c == (Object)null)
{
return;
}
FieldInfo[] effectListFieldsCached = GetEffectListFieldsCached(((object)c).GetType());
if (effectListFieldsCached.Length == 0)
{
return;
}
foreach (FieldInfo fieldInfo in effectListFieldsCached)
{
if (!(fieldInfo == null))
{
fieldInfo.SetValue(c, MakeEmptyEffectList());
}
}
}
catch
{
}
}
private static void ForceStripAllEffects(GameObject totemPrefabOrInstance)
{
try
{
if (!((Object)(object)totemPrefabOrInstance == (Object)null))
{
Piece val = totemPrefabOrInstance.GetComponent<Piece>() ?? totemPrefabOrInstance.GetComponentInChildren<Piece>(true);
if ((Object)(object)val != (Object)null)
{
val.m_placeEffect = MakeEmptyEffectList();
StripEffectListsOnComponent((Component)(object)val);
}
WearNTear val2 = totemPrefabOrInstance.GetComponent<WearNTear>() ?? totemPrefabOrInstance.GetComponentInChildren<WearNTear>(true);
if ((Object)(object)val2 != (Object)null)
{
StripEffectListsOnComponent((Component)(object)val2);
}
}
}
catch
{
}
}
}
}