Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Valquake v0.1.7
Valquake.dll
Decompiled a year ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using HarmonyLib; using UnityEngine; using UnityEngine.Networking; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("Valquake")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Valquake")] [assembly: AssemblyCopyright("Copyright © 2024")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("9f8a1b6e-6d0e-4dab-bbd8-9ed433836544")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] internal sealed class ConfigurationManagerAttributes { public delegate void CustomHotkeyDrawerFunc(ConfigEntryBase setting, ref bool isCurrentlyAcceptingInput); public bool? ShowRangeAsPercent; public Action<ConfigEntryBase> CustomDrawer; public CustomHotkeyDrawerFunc CustomHotkeyDrawer; public bool? Browsable; public string Category; public object DefaultValue; public bool? HideDefaultButton; public bool? HideSettingName; public string Description; public string DispName; public int? Order; public bool? ReadOnly; public bool? IsAdvanced; public Func<object, string> ObjToStr; public Func<string, object> StrToObj; } namespace neobotics.ValheimMods; public class AudioHelper : MonoBehaviour { private Dictionary<string, AudioClip> audioClips = new Dictionary<string, AudioClip>(); public void Awake() { Logging.GetLogger().Debug("AudioHelper.Awake"); LoadAudioResources(); ZRoutedRpc.instance.Register<Vector3, string>("NeoPlayClip", (Action<long, Vector3, string>)RPC_NeoPlayClip); } public void RPC_NeoPlayClip(long sender, Vector3 sourcePoint, string clipName) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) Logging.GetLogger().Debug("AudioHelper.RPC_NeoPlayClip"); if (ZNet.instance.IsDedicated()) { return; } try { NeoPlayClip(sourcePoint, clipName); } catch (Exception e) { Logging.GetLogger().Error(e, stackTrace: false); } } public void Play(Vector3 sourcePoint, string clipName) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) Logging.GetLogger().Debug("AudioHelper.Play"); ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "NeoPlayClip", new object[2] { sourcePoint, clipName }); } public void NeoPlayClip(Vector3 sourcePoint, string clipName) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)Player.m_localPlayer).transform.position; NeoPlayClip(sourcePoint, position, clipName); } public void NeoPlayClip(Vector3 sourcePoint, Vector3 targetPoint, string clipName) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) Logging.GetLogger().Debug("AudioHelper.NeoPlayClip"); Vector3 val = sourcePoint - targetPoint; Vector3 normalized = ((Vector3)(ref val)).normalized; float num = (Vector3.Distance(sourcePoint, targetPoint) + 1f) / 10f; if (audioClips.TryGetValue(clipName.ToLower(), out var value)) { AudioSource.PlayClipAtPoint(value, targetPoint + normalized * num, 1f); } else { Logging.GetLogger().Warning("Couldn't find audio clip for " + clipName); } } public float GetClipDuration(string clipName) { if (!audioClips.TryGetValue(clipName.ToLower(), out var value)) { return -1f; } return value.length; } private void LoadAudioResources() { FileInfo fileInfo = new FileInfo(Assembly.GetExecutingAssembly().Location); string[] array = new string[0]; Dictionary<string, AudioType> obj = new Dictionary<string, AudioType> { { "*.wav", (AudioType)20 }, { "*.mp3", (AudioType)13 } }; string directoryName = fileInfo.DirectoryName; audioClips.Clear(); Logging.GetLogger().Debug("LoadAudioResources"); foreach (string key in obj.Keys) { array = CollectionExtensions.AddRangeToArray<string>(array, Directory.GetFiles(fileInfo.DirectoryName, key, SearchOption.TopDirectoryOnly)); } ((MonoBehaviour)this).StartCoroutine(Co_LoadAudio(directoryName, array)); } private IEnumerator Co_LoadAudio(string filePath, string[] audioFiles) { UnityWebRequest URL = null; Logging.GetLogger().Debug("Co_LoadAudio loading files from " + filePath); for (int f = 0; f < audioFiles.Length; f++) { string clipUri = new Uri(audioFiles[f]).AbsoluteUri; string clipName = audioFiles[f].Substring(filePath.Length + 1); Logging.GetLogger().Debug("Loading audio clip " + clipName); try { URL = UnityWebRequestMultimedia.GetAudioClip(clipUri, (AudioType)0); } catch (Exception ex) { Logging.GetLogger().Warning("Can't find audio resource: " + ex.Message); } yield return URL.SendWebRequest(); if (URL != null) { try { AudioClip content = DownloadHandlerAudioClip.GetContent(URL); audioClips.Add(clipName.ToLower(), content); } catch (Exception ex2) { Logging.GetLogger().Warning("Failed to load clip " + clipUri + ": " + ex2.Message); } } else { Logging.GetLogger().Warning("Failed to get URL for " + clipUri); } } } } public class CrossPlatformRandom : Random { private const int LCG_MULTIPLIER = 134775813; private const int LCG_INCREMENT = 1; private int _seed; public float value => (float)NextDouble(); public CrossPlatformRandom() { Random random = new Random(); _seed = random.Next(); } public CrossPlatformRandom(int seed) { _seed = seed; } public float Range(int min, int max) { return Next(min, max); } public float Range(float min, float max) { return Mathf.Lerp(min, max, (float)NextDouble()); } private int GetNext() { _seed = _seed * 134775813 + 1; return _seed; } public override int Next() { return Next(int.MaxValue); } public override int Next(int maxValue) { if (maxValue < 0) { throw new ArgumentOutOfRangeException("maxValue is less than zero."); } return (int)((long)(uint)GetNext() * (long)(uint)maxValue >>> 32); } public override int Next(int minValue, int maxValue) { if (minValue > maxValue) { throw new ArgumentOutOfRangeException("minValue is greater than maxValue."); } return minValue + Next(maxValue - minValue); } public override double NextDouble() { return Sample(); } protected override double Sample() { return (double)Next() / 2147483647.0; } } internal class DebugUtils { public static void ObjectInspector(object o) { if (o == null) { Debug.Log((object)"Object is null"); return; } BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; Type type = o.GetType(); Debug.Log((object)(o.ToString() + " Type " + type.Name)); PropertyInfo[] properties = type.GetProperties(bindingAttr); foreach (PropertyInfo propertyInfo in properties) { Debug.Log((object)$"{type.Name}.{propertyInfo.Name} = {propertyInfo.GetValue(o)}"); } FieldInfo[] fields = type.GetFields(bindingAttr); foreach (FieldInfo field in fields) { FieldPrinter(o, type, field); } } public static void MethodInspector(object o) { if (o == null) { Debug.Log((object)"Object is null"); return; } BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; Type type = o.GetType(); Debug.Log((object)(o.ToString() + " Type " + type.Name)); MethodInfo[] methods = type.GetMethods(bindingAttr); foreach (MethodInfo methodInfo in methods) { methodInfo.GetParameters(); string arg = string.Join(", ", (from x in methodInfo.GetParameters() select x.ParameterType?.ToString() + " " + x.Name).ToArray()); Debug.Log((object)$"{methodInfo.ReturnType} {methodInfo.Name} ({arg})"); } } private static void ItemDataInspector(ItemData item) { ObjectInspector(item); ObjectInspector(item.m_shared); } private static void FieldPrinter(object o, Type t, FieldInfo field) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Expected O, but got Unknown try { if (field.FieldType == typeof(ItemData)) { ItemData val = (ItemData)field.GetValue(o); if (val != null) { ItemDataInspector(val); } else { Debug.Log((object)$"{t.Name}.{field.Name} = {field.GetValue(o)} [null]"); } } else if (field.FieldType == typeof(Transform)) { Transform val2 = (Transform)field.GetValue(o); if ((Object)(object)val2 != (Object)null) { Debug.Log((object)("\tTransform.parent = " + ((Object)val2.parent).name)); } else { Debug.Log((object)$"{t.Name}.{field.Name} = {field.GetValue(o)} [null]"); } } else if (field.FieldType == typeof(EffectList)) { EffectList val3 = (EffectList)field.GetValue(o); if (val3 != null) { Debug.Log((object)$"{t.Name}.{field.Name} = {field.GetValue(o)}:"); EffectData[] effectPrefabs = val3.m_effectPrefabs; foreach (EffectData val4 in effectPrefabs) { Debug.Log((object)("\tEffectData.m_prefab = " + ((Object)val4.m_prefab).name)); } } else { Debug.Log((object)$"{t.Name}.{field.Name} = {field.GetValue(o)} [null]"); } } else { Debug.Log((object)$"{t.Name}.{field.Name} = {field.GetValue(o)}"); } } catch (Exception) { Debug.Log((object)("Exception accessing " + t?.Name + "." + field?.Name)); } } public static void GameObjectInspector(GameObject go) { Debug.Log((object)("\n\nInspecting GameObject " + ((Object)go).name)); ObjectInspector(go); Component[] componentsInChildren = go.GetComponentsInChildren<Component>(); foreach (Component val in componentsInChildren) { try { string obj = ((val != null) ? ((Object)val).name : null); object obj2; if (val == null) { obj2 = null; } else { Transform transform = val.transform; if (transform == null) { obj2 = null; } else { Transform parent = transform.parent; obj2 = ((parent != null) ? ((Object)parent).name : null); } } Debug.Log((object)("\n\nInspecting Component " + obj + " with parent " + (string?)obj2)); ObjectInspector(val); } catch (Exception) { } } } public static void PrintList<T>(List<T> l) { foreach (T item in l) { Debug.Log((object)item.ToString()); } } public static void ComponentInspector(Component c) { Debug.Log((object)("\n\nInspecting Component " + ((Object)c).name)); ObjectInspector(c); } public static void EffectsInspector(EffectList e) { EffectData[] effectPrefabs = e.m_effectPrefabs; Debug.Log((object)$"Effect list has effects {e.HasEffects()} count {effectPrefabs.Length}"); EffectData[] array = effectPrefabs; foreach (EffectData val in array) { Debug.Log((object)$"Effect Data {val} prefab name {((Object)val.m_prefab).name} prefab GameObject name {((Object)val.m_prefab.gameObject).name}"); } } public static void PrintInventory() { foreach (ItemData allItem in ((Humanoid)Player.m_localPlayer).GetInventory().GetAllItems()) { Debug.Log((object)allItem.m_shared.m_name); } } public static void PrintAllObjects() { ZNetScene.instance.m_prefabs.ForEach(delegate(GameObject x) { Debug.Log((object)("GameObject " + ((Object)x).name)); }); } public static void PrintAllCharacters() { Character.GetAllCharacters().ForEach(delegate(Character x) { Debug.Log((object)("Character " + ((Object)x).name)); }); } public static void PrintAllLayers() { string[] array = (from index in Enumerable.Range(0, 31) select LayerMask.LayerToName(index) into l where !string.IsNullOrEmpty(l) select l).ToArray(); foreach (string text in array) { Debug.Log((object)("Layer " + text + " " + Convert.ToString(LayerMask.NameToLayer(text), 2).PadLeft(32, '0'))); } } } public class DelegatedConfigEntry<T> : DelegatedConfigEntryBase { private ConfigEntry<T> _entry; private EventHandler rootHandler; private Action<object, EventArgs> clientDelegate; private Logging Log; public ConfigEntry<T> ConfigEntry { get { return _entry; } set { _entry = value; if (_entry != null && rootHandler != null) { _entry.SettingChanged += rootHandler; } Name = ((ConfigEntryBase)_entry).Definition.Key; Section = ((ConfigEntryBase)_entry).Definition.Section; ServerValue = ((ConfigEntryBase)_entry).GetSerializedValue(); Log.Trace("Set " + Section + " " + Name + " to serialized value " + ServerValue); } } public T Value { get { return _entry.Value; } set { _entry.Value = value; } } public DelegatedConfigEntry(bool useServerDelegate = false) : this((Action<object, EventArgs>)null, useServerDelegate) { } public DelegatedConfigEntry(Action<object, EventArgs> delegateHandler, bool useServerDelegate = false) { Log = Logging.GetLogger(); Log.Trace("DelegatedConfigEntry"); if (delegateHandler != null) { clientDelegate = delegateHandler; } if (useServerDelegate) { Log.Trace("Configuring server delegate"); rootHandler = delegate(object s, EventArgs e) { ServerDelegate(s, e); }; ServerConfiguration.ServerDelegatedEntries.Add(this); } else if (clientDelegate != null) { rootHandler = delegate(object s, EventArgs e) { clientDelegate(s, e); }; } } private void ServerDelegate(object sender, EventArgs args) { //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Expected O, but got Unknown Logging.GetLogger().Trace("ServerDelegate"); _entry.SettingChanged -= rootHandler; ZNet instance = ZNet.instance; bool? flag = ((instance != null) ? new bool?(instance.IsServer()) : null); if (flag.HasValue) { if (flag == false && ServerConfiguration.Instance.ReceivedServerValues) { if (ServerValue != null) { ((ConfigEntryBase)_entry).SetSerializedValue(ServerValue); Log.Debug("Setting " + Name + " to server value " + ServerValue); } } else if (flag.GetValueOrDefault()) { ServerValue = ((ConfigEntryBase)_entry).GetSerializedValue(); ServerConfiguration.Instance.SendConfigToAllClients(sender, (SettingChangedEventArgs)args); } } if (clientDelegate != null) { clientDelegate(sender, args); } _entry.SettingChanged += rootHandler; } public void EnableHandler(bool setActive) { if (setActive) { _entry.SettingChanged += rootHandler; } else { _entry.SettingChanged -= rootHandler; } } public bool IsKeyPressed() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) if (ConfigEntry is ConfigEntry<KeyboardShortcut> val) { KeyboardShortcut value = val.Value; foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers) { if (!Input.GetKey(modifier)) { return false; } } if (!Input.GetKeyDown(((KeyboardShortcut)(ref value)).MainKey)) { return false; } return true; } Log.Error("Keyboard read attempted on non-KeyboardShortcut config."); return false; } public bool IsKeyDown() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) if (ConfigEntry is ConfigEntry<KeyboardShortcut> val) { KeyboardShortcut value = val.Value; foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers) { if (!Input.GetKey(modifier)) { return false; } } if (!Input.GetKey(((KeyboardShortcut)(ref value)).MainKey)) { return false; } return true; } Log.Error("Keyboard read attempted on non-KeyboardShortcut config."); return false; } public bool IsKeyReleased() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) if (ConfigEntry is ConfigEntry<KeyboardShortcut> val) { KeyboardShortcut value = val.Value; foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers) { if (!Input.GetKeyUp(modifier)) { return false; } } if (!Input.GetKeyUp(((KeyboardShortcut)(ref value)).MainKey)) { return false; } return true; } Log.Error("Keyboard read attempted on non-KeyboardShortcut config."); return false; } } public class DelegatedConfigEntryBase { public string Name; public string Section; public string ServerValue; } internal class HarmonyHelper { public enum PatchType { Prefix, Postfix, Transpiler, Finalizer } private static Dictionary<string, string> detectionSet = new Dictionary<string, string>(); private static Dictionary<string, string> unpatchMods = new Dictionary<string, string>(); public static void GetDetectionSet(Dictionary<string, string> harmonyIds) { Logging logger = Logging.GetLogger(); foreach (KeyValuePair<string, string> harmonyId in harmonyIds) { if (Harmony.HasAnyPatches(harmonyId.Key)) { logger.Debug("Detected " + harmonyId.Value + " from Harmony"); if (!detectionSet.ContainsKey(harmonyId.Key)) { detectionSet.Add(harmonyId.Key, harmonyId.Value); } } else if (Chainloader.PluginInfos.ContainsKey(harmonyId.Key)) { logger.Debug("Detected " + harmonyId.Value + " from BepInEx"); if (!detectionSet.ContainsKey(harmonyId.Key)) { detectionSet.Add(harmonyId.Key, harmonyId.Value); } } } } public static void AddExclusion(string key) { if (detectionSet.ContainsKey(key)) { unpatchMods.Add(key, detectionSet[key]); } } public static void UnpatchMods(Harmony harmony) { Logging logger = Logging.GetLogger(); foreach (KeyValuePair<string, string> unpatchMod in unpatchMods) { logger.Warning("Not compatible with " + unpatchMod.Value); harmony.UnpatchAll(unpatchMod.Key); detectionSet.Remove(unpatchMod.Key); logger.Warning("Disabled " + unpatchMod.Value); } } public static bool IsModDetected(string key) { return detectionSet.ContainsKey(key); } public static bool IsModNameDetected(string value) { return detectionSet.ContainsValue(value); } public static bool TryGetDetectedModName(string key, out string mod) { return detectionSet.TryGetValue(key, out mod); } public static bool TryGetDetectedModKey(string value, out string key) { key = null; foreach (string key2 in detectionSet.Keys) { if (detectionSet[key2] == value) { key = key2; return true; } } return false; } public static string AddAnonymousPatch(string baseMethodName, PatchType patchType, string modName, string patchMethodName = null) { string text = null; int num = 0; Logging logger = Logging.GetLogger(); foreach (MethodBase item in Harmony.GetAllPatchedMethods().ToList()) { MethodBaseExtensions.HasMethodBody(item); Patches patchInfo = Harmony.GetPatchInfo(item); ReadOnlyCollection<Patch> readOnlyCollection = patchInfo.Prefixes; switch (patchType) { case PatchType.Postfix: readOnlyCollection = patchInfo.Postfixes; break; case PatchType.Prefix: readOnlyCollection = patchInfo.Prefixes; break; case PatchType.Transpiler: readOnlyCollection = patchInfo.Transpilers; break; case PatchType.Finalizer: readOnlyCollection = patchInfo.Finalizers; break; } foreach (Patch item2 in readOnlyCollection) { if (!item2.owner.StartsWith("harmony-auto") || !(item.Name == baseMethodName)) { continue; } if (patchMethodName != null) { if (item2.PatchMethod.Name == patchMethodName) { num++; text = item2.owner; } } else { num++; text = item2.owner; } } if (num == 1) { detectionSet.Add(text, modName); logger.Info($"Added unique anonymous {baseMethodName} {patchType}: {text} as {modName}"); } else if (num > 1) { text = null; logger.Warning($"Found multiple anonymous {baseMethodName} {patchType} entries. Can't identify correct patch to remove or modify."); } } if (num == 0) { logger.Info("No patch found for " + modName); } return text; } } public class IterativeStopwatch : Stopwatch { private double startMillis; private Logging Log = Logging.GetLogger(); public long Iterations { get; private set; } public double IterationMicroseconds { get; private set; } public double TotalElapsedMicroseconds { get; private set; } public double IterationMilliseconds { get; private set; } public double TotalElapsedMilliseconds { get; private set; } public double AverageMicroseconds { get; private set; } public double AverageMilliseconds { get; private set; } public IterativeStopwatch() { Iterations = 0L; } public new void Start() { startMillis = base.Elapsed.TotalMilliseconds; base.Start(); } public new void Stop() { if (base.IsRunning) { base.Stop(); Iterations++; IterationMilliseconds = base.Elapsed.TotalMilliseconds - startMillis; IterationMicroseconds = IterationMilliseconds * 1000.0; TotalElapsedMilliseconds = base.Elapsed.TotalMilliseconds; TotalElapsedMicroseconds = base.Elapsed.TotalMilliseconds * 1000.0; AverageMilliseconds = TotalElapsedMilliseconds / (double)Iterations; AverageMicroseconds = TotalElapsedMicroseconds / (double)Iterations; } } public new void Reset() { startMillis = 0.0; Iterations = 0L; base.Reset(); } public new void Restart() { startMillis = 0.0; Iterations = 0L; base.Restart(); } } public class Logging { public enum LogLevels { Critical, Error, Warning, Info, Debug, Trace } private static Logging _logger; public LogLevels LogLevel { get; set; } public string ModName { get; set; } private Logging(LogLevels level, string name) { LogLevel = level; ModName = name; } public static Logging GetLogger(LogLevels level, string name) { if (_logger == null) { _logger = new Logging(level, name); } return _logger; } public static Logging GetLogger() { if (_logger == null) { throw new NullReferenceException("Logger not initialized"); } return _logger; } public void Trace(string msg) { if (LogLevel >= LogLevels.Trace) { Debug.Log((object)Message(msg)); } } public void Debug(string msg) { if (LogLevel >= LogLevels.Debug) { Debug.Log((object)Message(msg)); } } public void Info(string msg) { if (LogLevel >= LogLevels.Info) { Debug.Log((object)Message(msg)); } } public void Warning(string msg) { if (LogLevel >= LogLevels.Warning) { Debug.LogWarning((object)Message(msg)); } } public void Error(string msg) { if (LogLevel >= LogLevels.Error) { Debug.LogWarning((object)Message(msg)); } } public void Error(Exception e) { Error(e, stackTrace: false); } public void Error(Exception e, bool stackTrace) { if (LogLevel >= LogLevels.Error) { Warning(Message(e.Message)); if (stackTrace) { Warning(e.StackTrace); } } } public void Critical(Exception e) { if (LogLevel >= LogLevels.Critical) { Debug(Message(e.Message)); Error(e.StackTrace); } } private string Message(string msg) { return ModName + ": " + msg; } public static void ChangeLogging(object s, EventArgs e) { SettingChangedEventArgs val = (SettingChangedEventArgs)(object)((e is SettingChangedEventArgs) ? e : null); GetLogger().Debug($"ChangeLog {val.ChangedSetting.Definition.Key} to {val.ChangedSetting.BoxedValue}"); GetLogger().LogLevel = Cfg.debugLevel.Value; } } public class ServerConfiguration { [HarmonyPatch(typeof(ZNet), "StopAll")] private static class ZNet_Shutdown_Patch { [HarmonyPrefix] private static void ZNet_StopAll_Prefix(ZNet __instance) { Log.Debug("ZNet_StopAll_Patch_Prefix"); if (Instance != null) { Instance.ReceivedServerValues = false; } } } [HarmonyPatch(typeof(ZNet), "OnNewConnection")] private static class ZNet_OnNewConnection_Patch { private static void Postfix(ZNet __instance, ZNetPeer peer) { Log.Debug("ZNet OnNewConnection postfix"); if (!__instance.IsServer()) { try { peer.m_rpc.Register<ZPackage>("ClientConfigReceiver." + GetPluginGuid(), (Action<ZRpc, ZPackage>)Instance.RPC_ClientConfigReceiver); Log.Debug("Player registered RPC_ClientConfigReceiver"); return; } catch (Exception) { Log.Warning("Failed to register RPC"); return; } } try { Instance.SendConfigToClient(peer); } catch (Exception) { Log.Warning("Error sending server configuration to client"); } } } public static List<DelegatedConfigEntryBase> ServerDelegatedEntries = new List<DelegatedConfigEntryBase>(); private static ConfigFile LocalConfig; private static BaseUnityPlugin Mod; private static string ConfigFileName; private static ServerConfiguration _instance; private static Logging Log; public bool IsSetup; public bool ReceivedServerValues; public FileSystemWatcher ConfigWatcher; private const string NOT_CONFIGURED = "ServerConfiguration not initialized. Setup first."; public static ServerConfiguration Instance { get { if (_instance == null) { _instance = new ServerConfiguration(); } return _instance; } } private ServerConfiguration() { } public void Setup(ConfigFile config, BaseUnityPlugin modInstance) { LocalConfig = config; Log = Logging.GetLogger(); Log.Trace("ServerConfiguration Setup"); Mod = modInstance; ConfigFileName = Path.GetFileName(LocalConfig.ConfigFilePath); IsSetup = true; } public void CreateConfigWatcher() { ConfigWatcher = Utils.CreateFileWatcher(LocalConfig.ConfigFilePath, LoadConfig); } private void LoadConfig(object sender, FileSystemEventArgs e) { if (!File.Exists(LocalConfig.ConfigFilePath)) { return; } try { Log.Debug($"Loading configuration {e.ChangeType}"); LocalConfig.Reload(); } catch { Log.Error("Error loading configuration file " + ConfigFileName); } } public static string GetPluginGuid() { return Mod.Info.Metadata.GUID; } public void RPC_ClientConfigReceiver(ZRpc zrpc, ZPackage package) { if (!Instance.IsSetup) { Log.Error("ServerConfiguration not initialized. Setup first."); return; } Log.Debug("ClientConfigReceiver"); string section; string name; while (package.GetPos() < package.Size()) { section = package.ReadString(); name = package.ReadString(); string text = package.ReadString(); Log.Trace("Reading " + section + " " + name + " value " + text + " from ZPackage"); DelegatedConfigEntryBase delegatedConfigEntryBase = ServerDelegatedEntries.Find((DelegatedConfigEntryBase e) => e.Name == name && e.Section == section); if (delegatedConfigEntryBase != null) { Log.Trace("Found DCEB on client and setting to server value " + text); delegatedConfigEntryBase.ServerValue = text; } ConfigEntryBase val = LocalConfig[section, name]; if (val != null) { Log.Trace("Found local CEB and setting underlying config value " + text); val.SetSerializedValue(text); } } ReceivedServerValues = true; } internal void WriteConfigEntries(ZPackage zpkg) { foreach (DelegatedConfigEntryBase serverDelegatedEntry in ServerDelegatedEntries) { Log.Trace("Writing " + serverDelegatedEntry.Section + " " + serverDelegatedEntry.Name + " value " + serverDelegatedEntry.ServerValue + " to ZPackage"); zpkg.Write(serverDelegatedEntry.Section); zpkg.Write(serverDelegatedEntry.Name); zpkg.Write(serverDelegatedEntry.ServerValue); } } internal void SendConfigToClient(ZNetPeer peer) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown if (!Instance.IsSetup) { Log.Error("ServerConfiguration not initialized. Setup first."); return; } Log.Debug("SendConfigToClient"); ZPackage val = new ZPackage(); WriteConfigEntries(val); peer.m_rpc.Invoke("ClientConfigReceiver." + GetPluginGuid(), new object[1] { val }); Log.Trace("Invoked ClientConfigReceiver on peer"); } public void SendConfigToAllClients(object o, SettingChangedEventArgs e) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown if (!IsSetup) { Log.Error("ServerConfiguration not initialized. Setup first."); } else if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer() && ZNet.instance.GetPeerConnections() > 0) { Log.Debug("SendConfigToAllClients"); ZPackage zpkg = new ZPackage(); WriteConfigEntries(zpkg); ((MonoBehaviour)Mod).StartCoroutine(_instance.Co_BroadcastConfig(zpkg)); } } private IEnumerator Co_BroadcastConfig(ZPackage zpkg) { Log.Debug("Co_BroadcastConfig"); List<ZNetPeer> connectedPeers = ZNet.instance.GetConnectedPeers(); foreach (ZNetPeer item in connectedPeers) { if (item != ZNet.instance.GetServerPeer()) { item.m_rpc.Invoke("ClientConfigReceiver." + GetPluginGuid(), new object[1] { zpkg }); Log.Trace("Invoked ClientConfigReceiver on peer"); } yield return null; } } } internal class Utils { public static TEnum Guardrails<TEnum>(string value, TEnum enumDefault) where TEnum : struct { if (Enum.TryParse<TEnum>(value, ignoreCase: true, out var result)) { return result; } return enumDefault; } public static int Guardrails(int value, int lbound, int ubound) { if (value < lbound) { return lbound; } if (value > ubound) { return ubound; } return value; } public static string truncate(string value, int maxChars) { if (value == null) { return null; } if (value.Length <= maxChars) { return value; } return value.Substring(0, maxChars); } public static void GetCharactersInRangeXZ(Vector3 point, float radius, List<Character> characters) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) float num = radius * radius; foreach (Character s_character in Character.s_characters) { if (DistanceSqrXZ(((Component)s_character).transform.position, point) < num) { characters.Add(s_character); } } } public static float DistanceSqr(Vector3 v0, Vector3 v1) { //IL_0000: 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_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) float num = v1.x - v0.x; float num2 = v1.y - v0.y; float num3 = v1.z - v0.z; return num * num + num2 * num2 + num3 * num3; } public static float DistanceSqrXZ(Vector3 v0, Vector3 v1) { //IL_0000: 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_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) float num = v1.x - v0.x; float num2 = v1.z - v0.z; return num * num + num2 * num2; } public static float DistanceXZ(Vector3 v0, Vector3 v1) { //IL_0000: 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_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) float num = v1.x - v0.x; float num2 = v1.z - v0.z; return Mathf.Sqrt(num * num + num2 * num2); } public static float Guardrails(float value, float lbound, float ubound) { if (value < lbound) { return lbound; } if (value > ubound) { return ubound; } return value; } public static string UnClonifiedName(string name) { if (name == null) { return null; } int num = name.IndexOf("(Clone)"); if (num < 1) { return name; } return name.Substring(0, num); } public static void SetTranslator(int id, string idText) { typeof(Localization).GetMethod("AddWord", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(Localization.instance, new object[2] { "skill_" + id, idText }); } public static string GetTranslated(int id) { Logging.GetLogger().Debug(string.Format("Got translation for id {0} to {1}", id, Localization.instance.Localize("skill_" + id))); return Localization.instance.Localize("$skill_" + id); } public static string GetAssemblyPathedFile(string fileName) { return new FileInfo(Assembly.GetExecutingAssembly().Location).DirectoryName.Replace('\\', '/') + "/" + fileName; } public static Sprite GetPrefabIcon(string prefabName) { Sprite result = null; GameObject prefab = GetPrefab(prefabName); ItemDrop val = default(ItemDrop); if ((Object)(object)prefab != (Object)null && prefab.TryGetComponent<ItemDrop>(ref val)) { result = val.m_itemData.GetIcon(); } return result; } public static Player GetPlayerByZDOID(ZDOID zid) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) foreach (Player allPlayer in Player.GetAllPlayers()) { ZDOID zDOID = ((Character)allPlayer).GetZDOID(); if (((ZDOID)(ref zDOID)).Equals(zid)) { return allPlayer; } } return null; } public static Character GetCharacterByZDOID(string cid) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) foreach (Character allCharacter in Character.GetAllCharacters()) { ZDOID zDOID = allCharacter.GetZDOID(); if (((object)(ZDOID)(ref zDOID)).ToString().Equals(cid)) { return allCharacter; } } return null; } public static Character GetCharacterByZDOID(ZDOID cid) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) foreach (Character allCharacter in Character.GetAllCharacters()) { ZDOID zDOID = allCharacter.GetZDOID(); if (((ZDOID)(ref zDOID)).Equals(cid)) { return allCharacter; } } return null; } public static ZNetPeer GetPeerByRPC(ZRpc rpc) { foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { if (peer.m_rpc == rpc) { return peer; } } return null; } public static List<GameObject> GetGameObjectsOfType(Type t) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) List<GameObject> list = new List<GameObject>(); Object[] array = Object.FindObjectsOfType(t); foreach (Object val in array) { list.Add(((Component)val).gameObject); } return list; } public static GameObject GetClosestGameObjectOfType(Type t, Vector3 point, float radius) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return GetGameObjectsOfTypeInRangeByDistance(t, point, radius)?[0]; } public static List<GameObject> GetGameObjectsOfTypeInRangeByDistance(Type t, Vector3 point, float radius) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) List<KeyValuePair<GameObject, float>> list = new List<KeyValuePair<GameObject, float>>(); List<GameObject> gameObjectsOfTypeInRange = GetGameObjectsOfTypeInRange(t, point, radius); if (gameObjectsOfTypeInRange.Count > 0) { foreach (GameObject item in gameObjectsOfTypeInRange) { list.Add(new KeyValuePair<GameObject, float>(item, Vector3.Distance(item.transform.position, point))); } list.Sort((KeyValuePair<GameObject, float> pair1, KeyValuePair<GameObject, float> pair2) => pair1.Value.CompareTo(pair2.Value)); return list.ConvertAll((KeyValuePair<GameObject, float> x) => x.Key); } return null; } public static List<GameObject> GetGameObjectsOfTypeInRange(Type t, Vector3 point, float radius) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) return (from x in GetGameObjectsOfType(t) where Vector3.Distance(x.transform.position, point) < radius select x).ToList(); } public static float GetPointDepth(Vector3 p) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) return ZoneSystem.instance.m_waterLevel - GetSolidHeight(p); } public static List<string> GetDelimitedStringAsList(string delimitedString, char delimiter) { List<string> list = new List<string>(); string[] array = delimitedString.Split(new char[1] { delimiter }, StringSplitOptions.RemoveEmptyEntries); foreach (string text in array) { list.Add(text.Trim()); } return list; } public static float GetSolidHeight(Vector3 p) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) int solidRayMask = ZoneSystem.instance.m_solidRayMask; float result = 0f; p.y += 1000f; RaycastHit val = default(RaycastHit); if (Physics.Raycast(p, Vector3.down, ref val, 2000f, solidRayMask) && !Object.op_Implicit((Object)(object)((RaycastHit)(ref val)).collider.attachedRigidbody)) { result = ((RaycastHit)(ref val)).point.y; } return result; } public static Transform FindChild(Transform aParent, string aName) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown foreach (Transform item in aParent) { Transform val = item; if (((Object)val).name == aName) { return val; } Transform val2 = FindChild(val, aName); if ((Object)(object)val2 != (Object)null) { return val2; } } return null; } public static Transform FindParent(Transform go) { while ((Object)(object)go.parent != (Object)null) { go = go.parent; } return go; } public static GameObject GetPrefab(int prefabHash) { return GetPrefabByHash(prefabHash); } public static GameObject GetPrefabByHash(int prefabHash) { GameObject val = ObjectDB.instance.GetItemPrefab(prefabHash); Logging logger = Logging.GetLogger(); if ((Object)(object)val != (Object)null) { logger.Debug("Found prefab in ObjectDB"); } else { ZNetScene instance = ZNetScene.instance; val = ((instance != null) ? instance.GetPrefab(prefabHash) : null); if ((Object)(object)val != (Object)null) { logger.Debug("Found prefab in Scene"); } } return val; } public static GameObject GetPrefab(string prefabName) { GameObject val = ObjectDB.instance.GetItemPrefab(prefabName); Logging logger = Logging.GetLogger(); if ((Object)(object)val != (Object)null) { logger.Debug("Found " + prefabName + " in ObjectDB"); } else { ZNetScene instance = ZNetScene.instance; val = ((instance != null) ? instance.GetPrefab(prefabName) : null); if ((Object)(object)val != (Object)null) { logger.Debug("Found " + prefabName + " in Scene"); } } return val; } public static string SerializeFromDictionary<K, V>(string delimp, string delimc, IDictionary<K, V> dict) { if (dict == null) { return null; } IEnumerable<string> values = dict.Select(delegate(KeyValuePair<K, V> kvp) { KeyValuePair<K, V> keyValuePair = kvp; string? obj = keyValuePair.Key?.ToString(); string text = delimc; keyValuePair = kvp; return obj + text + keyValuePair.Value; }); return string.Join(delimp, values); } public static void DeserializeToDictionary<K, V>(string serializedString, string delimp, string delimc, ref IDictionary<K, V> dict) { if (dict == null) { return; } dict.Clear(); string[] separator = new string[1] { delimp }; string[] separator2 = new string[1] { delimc }; string[] array = serializedString.Split(separator, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split(separator2, StringSplitOptions.RemoveEmptyEntries); if (array2.Length == 2) { dict.Add(TypedValue<K>(array2[0]), TypedValue<V>(array2[1])); } } } public static FileSystemWatcher CreateFileWatcher(string fullPath, FileSystemEventHandler handler) { string fileName = Path.GetFileName(fullPath); FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(fullPath.Substring(0, fullPath.Length - fileName.Length), fileName); fileSystemWatcher.NotifyFilter = NotifyFilters.Attributes | NotifyFilters.Size | NotifyFilters.LastWrite | NotifyFilters.CreationTime; fileSystemWatcher.Changed += handler; fileSystemWatcher.Created += handler; fileSystemWatcher.IncludeSubdirectories = false; fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject; fileSystemWatcher.EnableRaisingEvents = true; return fileSystemWatcher; } public static T TypedValue<T>(object a) { return (T)Convert.ChangeType(a, typeof(T)); } public static float TimeAdjustedRamp(float maxValue, float duration, float elapsedTime, float pctFromStartRise, float pctFromEndFall) { float num = elapsedTime / duration; if (num <= pctFromStartRise) { return maxValue * (num / pctFromStartRise); } if (num >= 1f - pctFromEndFall) { return maxValue * ((1f - num) / pctFromEndFall); } return maxValue; } public static bool CopyComponentToGameObject(Component original, ref GameObject destination) { //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown Logging logger = Logging.GetLogger(); Type type = ((object)original).GetType(); logger.Debug($"Original Type is {type}"); GameObject obj = destination; logger.Debug("Destination GameObject " + ((obj != null) ? ((Object)obj).name : null)); Component val = destination.GetComponent(type); if ((Object)(object)val == (Object)null) { val = destination.AddComponent(type); } if ((Object)(object)val == (Object)null) { logger.Debug("Destination component is null"); return false; } Component val2 = (Component)Activator.CreateInstance(type); if ((Object)(object)val2 == (Object)null) { logger.Debug("Destination component is null"); return false; } if ((Object)(object)val2 == (Object)null) { logger.Debug("Boxed component is null"); return false; } FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { fieldInfo.SetValue(val2, fieldInfo.GetValue(original)); } val = val2; return true; } public static bool CopyObject(object original, object target) { Logging logger = Logging.GetLogger(); Type type = original.GetType(); Type type2 = target.GetType(); if (type == null) { logger.Warning("Copy Object: Source object is null"); Activator.CreateInstance(type); return false; } if (type2 == null) { logger.Warning("Copy Object: Destination object is null"); return false; } if (type2 != type) { logger.Warning("Copy Object: Source and destination components are different types"); return false; } FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { fieldInfo.SetValue(target, fieldInfo.GetValue(original)); } return true; } } internal class Cfg { public static DelegatedConfigEntry<int> displacementChance; public static DelegatedConfigEntry<int> maxPieceDamage; public static DelegatedConfigEntry<int> maxTreeDamage; public static DelegatedConfigEntry<bool> allowFullDestruction; public static DelegatedConfigEntry<float> faultChance; public static DelegatedConfigEntry<bool> activeWardsPreventDamage; public static DelegatedConfigEntry<bool> activeShieldsPreventDamage; public static DelegatedConfigEntry<bool> monstersFlee; public static DelegatedConfigEntry<bool> showDust; public static DelegatedConfigEntry<bool> charactersStagger; public static DelegatedConfigEntry<bool> hookedItemsFall; public static DelegatedConfigEntry<bool> activeItemsMove; public static DelegatedConfigEntry<int> earthquakeRadius; public static DelegatedConfigEntry<bool> cameraShakeOverride; public static DelegatedConfigEntry<int> cameraShakeIntensity; public static DelegatedConfigEntry<int> cameraShakeFrequency; public static DelegatedConfigEntry<bool> biomeMeadows; public static DelegatedConfigEntry<bool> biomeSwamp; public static DelegatedConfigEntry<bool> biomeBlackForest; public static DelegatedConfigEntry<bool> biomeMistlands; public static DelegatedConfigEntry<bool> biomeAshlands; public static DelegatedConfigEntry<bool> biomeDeepNorth; public static DelegatedConfigEntry<bool> biomeMountains; public static DelegatedConfigEntry<bool> biomePlains; public static DelegatedConfigEntry<float> fissureMaxDepth; public static DelegatedConfigEntry<float> fissureDeepenPct; public static DelegatedConfigEntry<int> minInterval; public static DelegatedConfigEntry<int> maxInterval; public static DelegatedConfigEntry<Logging.LogLevels> debugLevel; public static void BepInExConfig(BaseUnityPlugin _instance) { //IL_02d4: Unknown result type (might be due to invalid IL or missing references) //IL_02de: Expected O, but got Unknown //IL_037b: Unknown result type (might be due to invalid IL or missing references) //IL_0385: Expected O, but got Unknown //IL_0442: Unknown result type (might be due to invalid IL or missing references) //IL_044c: Expected O, but got Unknown //IL_048b: Unknown result type (might be due to invalid IL or missing references) //IL_0495: Expected O, but got Unknown //IL_04d4: Unknown result type (might be due to invalid IL or missing references) //IL_04de: Expected O, but got Unknown //IL_0521: Unknown result type (might be due to invalid IL or missing references) //IL_052b: Expected O, but got Unknown //IL_056e: Unknown result type (might be due to invalid IL or missing references) //IL_0578: Expected O, but got Unknown //IL_0641: Unknown result type (might be due to invalid IL or missing references) //IL_064b: Expected O, but got Unknown //IL_0684: Unknown result type (might be due to invalid IL or missing references) //IL_068e: Expected O, but got Unknown ServerConfiguration.Instance.Setup(_instance.Config, _instance); debugLevel = new DelegatedConfigEntry<Logging.LogLevels>(Logging.ChangeLogging); debugLevel.ConfigEntry = _instance.Config.Bind<Logging.LogLevels>("Utility", "LogLevel", Logging.LogLevels.Info, "Controls the level of information contained in the log"); Valquake.Log.LogLevel = debugLevel.Value; biomeMeadows = new DelegatedConfigEntry<bool>(useServerDelegate: true); biomeMeadows.ConfigEntry = _instance.Config.Bind<bool>("Biomes", "Meadows", true, "Earthquakes trigger in the Meadows.@"); biomeSwamp = new DelegatedConfigEntry<bool>(useServerDelegate: true); biomeSwamp.ConfigEntry = _instance.Config.Bind<bool>("Biomes", "Swamp", false, "Earthquakes trigger in the Swamp.@"); biomeBlackForest = new DelegatedConfigEntry<bool>(useServerDelegate: true); biomeBlackForest.ConfigEntry = _instance.Config.Bind<bool>("Biomes", "Black Forest", false, "Earthquakes trigger in the Black Forest.@"); biomeMountains = new DelegatedConfigEntry<bool>(useServerDelegate: true); biomeMountains.ConfigEntry = _instance.Config.Bind<bool>("Biomes", "Mountains", true, "Earthquakes trigger in the Mountains.@"); biomePlains = new DelegatedConfigEntry<bool>(useServerDelegate: true); biomePlains.ConfigEntry = _instance.Config.Bind<bool>("Biomes", "Plains", false, "Earthquakes trigger in the Plains.@"); biomeMistlands = new DelegatedConfigEntry<bool>(useServerDelegate: true); biomeMistlands.ConfigEntry = _instance.Config.Bind<bool>("Biomes", "Mistlands", true, "Earthquakes trigger in the Mistlands.@"); biomeAshlands = new DelegatedConfigEntry<bool>(useServerDelegate: true); biomeAshlands.ConfigEntry = _instance.Config.Bind<bool>("Biomes", "Ashlands", true, "Earthquakes trigger in the Ashlands.@"); biomeDeepNorth = new DelegatedConfigEntry<bool>(useServerDelegate: true); biomeDeepNorth.ConfigEntry = _instance.Config.Bind<bool>("Biomes", "Deep North", false, "Earthquakes trigger in the Deep North.@"); showDust = new DelegatedConfigEntry<bool>(useServerDelegate: true); showDust.ConfigEntry = _instance.Config.Bind<bool>("Effects", "A. Show Dust", true, "If enabled, will display a cloud of dust along the fault line during a quake. Only meaningful if Fissure Chance is > 0%.@"); monstersFlee = new DelegatedConfigEntry<bool>(useServerDelegate: true); monstersFlee.ConfigEntry = _instance.Config.Bind<bool>("Effects", "B. Creatures Scatter", true, "If enabled, creatures close enough to quake zone will scatter for a short time.@"); charactersStagger = new DelegatedConfigEntry<bool>(useServerDelegate: true); charactersStagger.ConfigEntry = _instance.Config.Bind<bool>("Effects", "C. Staggering", true, "If enabled, players and creatures can stagger during the quake while inside the quake zone.@"); allowFullDestruction = new DelegatedConfigEntry<bool>(useServerDelegate: true); allowFullDestruction.ConfigEntry = _instance.Config.Bind<bool>("Effects", "D. Allow Piece Destruction", false, "If enabled, allows the full destruction of pieces duing the quake (dropping materials). If disabled, pieces can only be reduced to 1 health.@"); displacementChance = new DelegatedConfigEntry<int>(useServerDelegate: true); displacementChance.ConfigEntry = _instance.Config.Bind<int>("Effects", "E. Piece Displacement Chance", 0, new ConfigDescription("The percent chance pieces are displaced in the horizontal plane during a quake. A value of zero (0) never displaces pieces.@", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); hookedItemsFall = new DelegatedConfigEntry<bool>(useServerDelegate: true); hookedItemsFall.ConfigEntry = _instance.Config.Bind<bool>("Effects", "F. Items Can Fall", true, "If enabled, things mounted on items stands can be shaken loose and fall during a quake.@"); activeItemsMove = new DelegatedConfigEntry<bool>(useServerDelegate: true); activeItemsMove.ConfigEntry = _instance.Config.Bind<bool>("Effects", "G. Things Can Move", true, "If enabled, some 'active' things like carts & ships, will move with the quake.@"); earthquakeRadius = new DelegatedConfigEntry<int>(useServerDelegate: true); earthquakeRadius.ConfigEntry = _instance.Config.Bind<int>("Control", "A. Quake Radius", 100, new ConfigDescription("Radius (in meters) of the earthquake zone. Effects will diminish farther from the epicenter.@", (AcceptableValueBase)(object)new AcceptableValueRange<int>(20, 200), Array.Empty<object>())); minInterval = new DelegatedConfigEntry<int>(Valquake.ChangeMinInterval, useServerDelegate: true); minInterval.ConfigEntry = _instance.Config.Bind<int>("Control", "B. Min Interval", 30, "Minimum possible time (in minutes) between earthquakes. Minimum value is 1.@"); maxInterval = new DelegatedConfigEntry<int>(Valquake.ChangeMaxInterval, useServerDelegate: true); maxInterval.ConfigEntry = _instance.Config.Bind<int>("Control", "C. Max Interval", 120, "Maximum possible time (in minutes) between earthquakes. Value must be equal to or greater than Min Interval.@"); faultChance = new DelegatedConfigEntry<float>(useServerDelegate: true); faultChance.ConfigEntry = _instance.Config.Bind<float>("Control", "D. Fault Zone Chance", 20f, new ConfigDescription("The percent chance of a zone having a 'fault line'. Quakes will only create a fissure in a zone with a fault line. A value of 0% will prevent any fissures from forming.@", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())); maxPieceDamage = new DelegatedConfigEntry<int>(useServerDelegate: true); maxPieceDamage.ConfigEntry = _instance.Config.Bind<int>("Control", "E. Max Piece Damage", 1000, new ConfigDescription("The maximum damage that can be applied to pieces in the quake zone. A value of 0 will not apply any damage. Damage is attenuated by distance from the epicenter and degree of support.@", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 2000), Array.Empty<object>())); maxTreeDamage = new DelegatedConfigEntry<int>(useServerDelegate: true); maxTreeDamage.ConfigEntry = _instance.Config.Bind<int>("Control", "F. Max Tree Damage", 200, new ConfigDescription("The maximum damage that can be applied to trees in the quake zone. A value of 0 will not apply any damage. Damage is attenuated by distance from the epicenter.@", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 200), Array.Empty<object>())); fissureMaxDepth = new DelegatedConfigEntry<float>(useServerDelegate: true); fissureMaxDepth.ConfigEntry = _instance.Config.Bind<float>("Control", "G. Max Fissure Depth", 2f, new ConfigDescription("The maximum depth (in meters) of the fissure for the first quake along a fault line. Subsequent quakes along the same fault line are controlled by Successive Quake Depth as a percentage of this value.@", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 6f), Array.Empty<object>())); fissureDeepenPct = new DelegatedConfigEntry<float>(useServerDelegate: true); fissureDeepenPct.ConfigEntry = _instance.Config.Bind<float>("Control", "H. Successive Quake Depth", 0.2f, new ConfigDescription("Sets the percent of the Max Fissure Depth to apply to each successive quake along the same fault line. A value of 0% will not deepen the fissure.@", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); activeWardsPreventDamage = new DelegatedConfigEntry<bool>(useServerDelegate: true); activeWardsPreventDamage.ConfigEntry = _instance.Config.Bind<bool>("Control", "I. Active Wards Reduce Damage", false, "If enabled, an active ward will reduce damage to pieces if the quake epicenter is within the ward's area of protection.@"); activeShieldsPreventDamage = new DelegatedConfigEntry<bool>(useServerDelegate: true); activeShieldsPreventDamage.ConfigEntry = _instance.Config.Bind<bool>("Control", "J. Active Shields Reduce Damage", false, "If enabled, a fueled Shield Generator will reduce damage to pieces if the quake epicenter is within the shield's area of protection.@"); cameraShakeOverride = new DelegatedConfigEntry<bool>(); cameraShakeOverride.ConfigEntry = _instance.Config.Bind<bool>("Camera", "Camera Sway Override", false, "If enabled, will override Valheim's camera shake setting (just for quakes) and 'sway' camera. If disabled, will use Valheim's setting."); cameraShakeIntensity = new DelegatedConfigEntry<int>(); cameraShakeIntensity.ConfigEntry = _instance.Config.Bind<int>("Camera", "Camera Sway Intensity", 100, new ConfigDescription("Sets how much the camera 'sways'. Lower values will reduce the amount of camera movement.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); cameraShakeFrequency = new DelegatedConfigEntry<int>(); cameraShakeFrequency.ConfigEntry = _instance.Config.Bind<int>("Camera", "Camera Sway Frequency", 10, new ConfigDescription("Sets how fast the camera 'sways'. Lower values will reduce how quickly the camera moves.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 20), Array.Empty<object>())); ServerConfiguration.Instance.CreateConfigWatcher(); } } public class QuakeShaker { private float angle; public static float s_baseIntensity = 3f; public static float PctRise = 0.2f; public static float PctFall = 0.5f; private const float twoPi = (float)Math.PI * 2f; private float lastTime; public Vector3 Epicenter { get; set; } public float Frequency { get; set; } public float Duration { get; set; } public float Intensity { get; set; } public float Radius { get; set; } private float StopTime { get; set; } public QuakeShaker(Vector3 epicenter, float radius, float intensity, float duration, float frequency = 30f) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) Epicenter = epicenter; Frequency = frequency; Duration = duration; Intensity = intensity; Radius = radius; StopTime = 0f; } public bool isActive() { return Time.time < StopTime; } public void Start() { StopTime = Time.time + Duration; } public void Stop() { StopTime = 0f; } public float PctOfDuration() { return 1f - (StopTime - Time.time) / Duration; } public bool HasPeaked() { return PctOfDuration() >= PctRise; } public bool InPeakWindow() { float num = PctOfDuration(); if (num >= PctRise) { return num <= PctFall; } return false; } public float ElapsedTime() { return Time.time + Duration - StopTime; } public float TimeRemaining() { return StopTime - Time.time; } public float TimeAdjustedIntensity() { return Utils.TimeAdjustedRamp(Intensity, Duration, ElapsedTime(), PctRise, PctFall); } public float GetCurrentAngle() { return angle; } public void Update(float dt) { //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) if (!isActive()) { lastTime = 0f; return; } GameCamera instance = GameCamera.instance; float time = Time.time; if (lastTime != 0f) { dt = time - lastTime; } lastTime = time; float num = (float)Cfg.cameraShakeIntensity.Value / 100f; float num2 = TimeAdjustedIntensity() * num; angle += dt * Frequency; if (angle > (float)Math.PI * 2f) { angle -= (float)Math.PI * 2f; } Quaternion val = Quaternion.Euler(Mathf.Sin(angle) * num2, 0f, Mathf.Cos(angle * 0.9f) * num2); ((Component)instance).transform.rotation = ((Component)instance).transform.rotation * val; } } [BepInPlugin("neobotics.valheim_mod.valquake", "Valquake", "0.1.7")] [BepInProcess("valheim.exe")] [BepInProcess("valheim_server.exe")] public class Valquake : BaseUnityPlugin { [HarmonyPatch(typeof(Heightmap), "Regenerate")] private static class Heightmap_Regenerate_Patch { [HarmonyPrefix] private static bool Heightmap_Regenerate_Prefix(Heightmap __instance) { if (isCracking) { Log.Trace("Skipping Regenerate until fissure complete"); return false; } return true; } } [HarmonyPatch(typeof(AnimalAI), "UpdateAI")] private static class AnimalAI_UpdateAI_Patch { [HarmonyPrefix] private static bool AnimalAI_UpdateAI_Prefix(AnimalAI __instance, float dt) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0017: 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) if (IsShaking() && Vector3.Distance(((Component)__instance).transform.position, quakeShaker.Epicenter) < quakeShaker.Radius) { ((BaseAI)__instance).SetAlerted(true); ((BaseAI)__instance).Flee(dt, quakeShaker.Epicenter); return false; } return true; } } [HarmonyPatch(typeof(MonsterAI), "UpdateAI")] private static class MonsterAI_UpdateAI_Patch { [HarmonyPrefix] private static bool MonsterAI_UpdateAI_Prefix(MonsterAI __instance, float dt) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (IsShaking() && Vector3.Distance(((Component)__instance).transform.position, quakeShaker.Epicenter) < quakeShaker.Radius * 0.75f) { ((BaseAI)__instance).SetAlerted(true); ((BaseAI)__instance).Flee(dt, quakeShaker.Epicenter); return false; } return true; } } [HarmonyPatch(typeof(Game), "Start")] private static class Game_Start_Patch { [HarmonyPostfix] private static void Game_Start_Patch_Postfix(Game __instance) { Log.Debug("Game_Start_Patch_Postfix"); audioHelper = ((Component)__instance).gameObject.AddComponent<AudioHelper>(); ZRoutedRpc.instance.Register<Vector3, float, float, float>("ValquakeShake", (Method<Vector3, float, float, float>)RPC_ValquakeShake); Log.Debug(string.Format("Registered RPC ValquakeShake {0}", StringExtensionMethods.GetStableHashCode("ValquakeShake"))); ZRoutedRpc.instance.Register("ValquakeReset", (Action<long>)RPC_ValquakeReset); Log.Debug(string.Format("Registered RPC ValquakeReset {0}", StringExtensionMethods.GetStableHashCode("ValquakeReset"))); } } [HarmonyPatch(typeof(Game), "Logout")] private static class Game_Logout_Patch { [HarmonyPrefix] private static void Game_Logout_Patch_Prefix(Game __instance) { nextQuakeTime = 0f; } } [HarmonyPatch(typeof(Player), "Update")] public static class Player_Update_Patch { private static void Prefix(Player __instance) { if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer && nextQuakeTime > 0f && Time.time > nextQuakeTime) { StartQuake(); } } } [HarmonyPatch(typeof(GameCamera), "UpdateCameraShake")] private static class GameCamera_UpdateCameraShake_Patch { [HarmonyPostfix] private static void GameCamera_UpdateCameraShake_Postfix(GameCamera __instance, float dt) { if (quakeShaker != null) { quakeShaker.Update(dt); if (!quakeShaker.isActive()) { quakeShaker = null; } } } } [HarmonyPatch(typeof(Player), "OnSpawned")] public static class Player_OnSpawned_Patch { public static void Postfix(Player __instance) { Log.Debug("Player_OnSpawned_Patch_Postfix"); SetNextQuake(Cfg.minInterval.Value, Cfg.maxInterval.Value); } } [HarmonyPatch(typeof(Terminal), "InitTerminal")] private static class Terminal_InitTerminal_Patch { [HarmonyPostfix] private static void Terminal_InitTerminal_Postfix(Terminal __instance) { AddValquakeConsoleCommand(); } } [HarmonyPatch(typeof(ItemStand), "DropItem")] private static class ItemStand_DropItem_Patch { [HarmonyPrefix] private static bool ItemStand_DropItem_Prefix(ItemStand __instance) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: 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_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) if (!IsShaking()) { return true; } Log.Debug("ItemStand_DropItem_Patch_Prefix"); if (!__instance.HaveAttachment()) { return false; } GameObject prefab = Utils.GetPrefab(__instance.m_nview.GetZDO().GetString(ZDOVars.s_item, "")); if (Object.op_Implicit((Object)(object)prefab)) { Vector3 val = Vector3.zero; Quaternion val2 = Quaternion.identity; Transform val3 = prefab.transform.Find("attach"); if (Object.op_Implicit((Object)(object)prefab.transform.Find("attachobj")) && Object.op_Implicit((Object)(object)val3)) { val2 = ((Component)val3).transform.localRotation; val = ((Component)val3).transform.localPosition; } GameObject obj = Object.Instantiate<GameObject>(prefab, __instance.m_dropSpawnPoint.position + val, __instance.m_dropSpawnPoint.rotation * val2); obj.GetComponent<ItemDrop>().LoadFromExternalZDO(__instance.m_nview.GetZDO()); obj.GetComponent<Rigidbody>().rotation = Quaternion.Euler(0.3f, 0.1f, 0.5f); } __instance.m_nview.GetZDO().Set(ZDOVars.s_item, ""); __instance.m_nview.InvokeRPC(ZNetView.Everybody, "SetVisualItem", new object[3] { "", 0, 0 }); return false; } } [HarmonyPatch(typeof(TerrainComp), "RaiseTerrain")] private static class TerrainComp_RaiseTerrain_Patch { [HarmonyPrefix] private static bool TerrainComp_RaiseTerrain_Prefix(TerrainComp __instance, Vector3 worldPos, float radius, float delta, bool square, float power) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (isCracking) { DigFissure(__instance, __instance.m_hmap, __instance.m_width, worldPos, radius, delta, square, power); return false; } return true; } } [HarmonyPatch(typeof(TreeBase), "Awake")] private static class TreeBase_Awake_Patch { [HarmonyPostfix] private static void TreeBase_Awake_Postfix(TreeBase __instance) { ZDO val = __instance?.m_nview?.m_zdo; if (val != null && !treeManager.ContainsKey(val)) { treeManager.Add(val, __instance); } } } [HarmonyPatch(typeof(ZNetScene), "Destroy")] private static class ZNetScene_Destroy_Patch { [HarmonyPrefix] private static void ZNetScene_Destroy_Prefix(ZNetScene __instance, GameObject go) { ZNetView val = default(ZNetView); if (go.TryGetComponent<ZNetView>(ref val) && val.m_zdo != null && treeManager.Remove(val.m_zdo)) { Log.Trace("Removed tree from manager"); } } } [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static ConsoleEvent <>9__32_0; public static Func<bool> <>9__35_0; public static Func<bool> <>9__40_0; public static Func<bool> <>9__41_0; public static Func<bool> <>9__42_0; public static Func<bool> <>9__46_0; public static Func<bool> <>9__55_0; internal void <AddValquakeConsoleCommand>b__32_0(ConsoleEventArgs <p0>) { if (OkToQuake(Player.m_localPlayer)) { StartQuake(); } } internal bool <Co_Clatter>b__35_0() { return quakeShaker.HasPeaked(); } internal bool <Co_DropAttachedPieces>b__40_0() { return quakeShaker.HasPeaked(); } internal bool <Co_DamagePieces>b__41_0() { return quakeShaker.HasPeaked(); } internal bool <Co_DamageTrees>b__42_0() { return quakeShaker.HasPeaked(); } internal bool <Co_StaggerController>b__46_0() { return halfCracked; } internal bool <Co_ModifyTerrain>b__55_0() { return quakeShaker.HasPeaked(); } } internal static Valquake _modInstance; private static string Mod = "Valquake"; private static string LcMod = Mod.ToLower(); public static Logging Log; public static float nextQuakeTime = 0f; public static QuakeShaker quakeShaker = null; public static bool isCracking = false; public static bool halfCracked = false; internal static AudioHelper audioHelper; internal static GameObject fissure_vfx; internal static GameObject cracking_sfx; internal static Vector2Int lastFissureXY = Vector2Int.zero; internal static Vector3 lastWorldPos = Vector3.zero; private const float delayUntilPeak = 2f; private static float fissureRadius = 1f; private static float fissureSpacing = 1f; public static float baseCamShakeFrequency = 10f; private const string vfx_fissure_prefab = "vfx_Place_mud_road"; private const string sfx_crack_prefab = "sfx_stonegolem_attack_hit"; private const string sfx_rumble = "quake_outdoor_major.mp3"; private const string sfx_clatter = "clatter.mp3"; private const string sfx_clunk = "clunk.mp3"; public static Dictionary<ZDO, TreeBase> treeManager = new Dictionary<ZDO, TreeBase>(); private static Harmony harmony = null; public static Valquake GetInstance() { return _modInstance; } private void Awake() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown _modInstance = this; harmony = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID); harmony.PatchAll(Assembly.GetExecutingAssembly()); ConfigureMod(); Log.Info("Awake"); } private void ConfigureMod() { Log = Logging.GetLogger(Logging.LogLevels.Info, Mod); Cfg.BepInExConfig((BaseUnityPlugin)(object)_modInstance); } private void OnDestroy() { harmony.UnpatchSelf(); } public static void ChangeMinInterval(object s, EventArgs e) { SettingChangedEventArgs val = (SettingChangedEventArgs)(object)((e is SettingChangedEventArgs) ? e : null); Log.Debug($"ChangeLog {val.ChangedSetting.Definition.Key} to {val.ChangedSetting.BoxedValue}"); if (Cfg.minInterval.Value < 1) { Log.Info("Min Interval must be >= 1"); Cfg.minInterval.Value = 1; } if (Cfg.maxInterval.Value < Cfg.minInterval.Value) { Cfg.maxInterval.Value = Cfg.minInterval.Value; } } public static void ChangeMaxInterval(object s, EventArgs e) { SettingChangedEventArgs val = (SettingChangedEventArgs)(object)((e is SettingChangedEventArgs) ? e : null); Log.Debug($"ChangeLog {val.ChangedSetting.Definition.Key} to {val.ChangedSetting.BoxedValue}"); if (Cfg.maxInterval.Value < 1 || Cfg.maxInterval.Value < Cfg.minInterval.Value) { Log.Info("Max Interval must be >= the Min Interval"); Cfg.maxInterval.Value = Cfg.minInterval.Value; } } private static void SetFissureTerrainOpSettings(Settings settings, float radius, float delta) { //IL_0065: Unknown result type (might be due to invalid IL or missing references) settings.m_levelOffset = delta; settings.m_level = false; settings.m_levelRadius = radius; settings.m_square = true; settings.m_raise = true; settings.m_raiseRadius = radius; settings.m_raisePower = 0f; settings.m_raiseDelta = delta; settings.m_smooth = false; settings.m_smoothRadius = radius; settings.m_smoothPower = 1f; settings.m_paintCleared = false; settings.m_paintHeightCheck = false; settings.m_paintType = (PaintType)0; settings.m_paintRadius = radius; } private static bool InQuakeBiome(Player aPlayer) { //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_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Invalid comparison between Unknown and I4 //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Invalid comparison between Unknown and I4 //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected I4, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Invalid comparison between Unknown and I4 //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Invalid comparison between Unknown and I4 //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Invalid comparison between Unknown and I4 //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Invalid comparison between Unknown and I4 Biome currentBiome = aPlayer.GetCurrentBiome(); if ((int)currentBiome <= 16) { switch (currentBiome - 1) { default: if ((int)currentBiome != 8) { if ((int)currentBiome != 16) { break; } return Cfg.biomePlains.Value; } return Cfg.biomeBlackForest.Value; case 0: return Cfg.biomeMeadows.Value; case 1: return Cfg.biomeSwamp.Value; case 3: return Cfg.biomeMountains.Value; case 2: break; } } else { if ((int)currentBiome == 32) { return Cfg.biomeAshlands.Value; } if ((int)currentBiome == 64) { return Cfg.biomeDeepNorth.Value; } if ((int)currentBiome == 512) { return Cfg.biomeMistlands.Value; } } return false; } private static void AddValquakeConsoleCommand() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown if (!Terminal.m_terminalInitialized) { return; } object obj = <>c.<>9__32_0; if (obj == null) { ConsoleEvent val = delegate { if (OkToQuake(Player.m_localPlayer)) { StartQuake(); } }; <>c.<>9__32_0 = val; obj = (object)val; } new ConsoleCommand("valquake", "Starts an earthquake near the player location", (ConsoleEvent)obj, true, false, false, true, false, (ConsoleOptionsFetcher)null, false, false, false); } private static bool IsShaking() { if (quakeShaker != null) { return quakeShaker.isActive(); } return false; } private static void StartQuake() { //IL_008e: 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_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: 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_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) Log.Debug("StartQuake"); Player localPlayer = Player.m_localPlayer; nextQuakeTime += (float)Cfg.maxInterval.Value * 60f; if (!OkToQuake(localPlayer)) { Log.Debug("Not OK to start quake. Resetting"); SetNextQuake(5f, 15f); return; } float s_baseIntensity = QuakeShaker.s_baseIntensity; float num = audioHelper.GetClipDuration("quake_outdoor_major.mp3"); if (num <= 0f) { num = 11f; } float num2 = Cfg.earthquakeRadius.Value; Heightmap val = Heightmap.FindHeightmap(((Component)localPlayer).transform.position); Vector3 position = ((Component)val).transform.position; audioHelper.Play(position, "quake_outdoor_major.mp3"); if (localPlayer.InShelter()) { ((MonoBehaviour)_modInstance).StartCoroutine(_modInstance.Co_Clatter(((Component)localPlayer).transform.position, 2f)); } ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "ValquakeShake", new object[4] { position, num2, s_baseIntensity, num }); DamageThings(position, Cfg.earthquakeRadius.Value, num); bool flag = true; if (Cfg.faultChance.Value > 0f) { flag = CreateFissure(val); } if (flag) { StartStaggering(position, Cfg.earthquakeRadius.Value, -1f); } ResetNextQuake(); } private IEnumerator Co_Clatter(Vector3 position, float delay) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) if (IsShaking()) { yield return (object)new WaitUntil((Func<bool>)(() => quakeShaker.HasPeaked())); } else { yield return (object)new WaitForSeconds(delay); } audioHelper.Play(position, "clatter.mp3"); } private static void DamageThings(Vector3 epicenter, float radius, float duration) { //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_0250: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_014b: 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_02c0: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) Log.Debug("DamageThings"); _ = Player.m_localPlayer; if (Cfg.maxPieceDamage.Value == 0 && Cfg.maxTreeDamage.Value == 0 && !Cfg.hookedItemsFall.Value && !Cfg.activeItemsMove.Value) { return; } Dictionary<WearNTear, float> dictionary = new Dictionary<WearNTear, float>(); Dictionary<TreeBase, float> dictionary2 = new Dictionary<TreeBase, float>(); Dictionary<ItemStand, float> dictionary3 = new Dictionary<ItemStand, float>(); Ship ship = default(Ship); Vagon vagon = default(Vagon); ItemStand val = default(ItemStand); WearNTear val2 = default(WearNTear); foreach (WearNTear allInstance in WearNTear.GetAllInstances()) { GameObject gameObject = ((Component)allInstance).gameObject; if (gameObject.TryGetComponent<Ship>(ref ship)) { if (Cfg.activeItemsMove.Value && IsShaking()) { ((MonoBehaviour)_modInstance).StartCoroutine(_modInstance.Co_ShakeShip(ship)); } continue; } if (gameObject.TryGetComponent<Vagon>(ref vagon)) { if (Cfg.activeItemsMove.Value && IsShaking()) { ((MonoBehaviour)_modInstance).StartCoroutine(_modInstance.Co_ShakeVagon(vagon)); } continue; } if (Cfg.hookedItemsFall.Value && gameObject.TryGetComponent<ItemStand>(ref val)) { float value = Vector3.Distance(epicenter, ((Component)val).transform.position); if (!dictionary3.ContainsKey(val)) { dictionary3.Add(val, value); } } if (Cfg.maxPieceDamage.Value > 0 && gameObject.TryGetComponent<WearNTear>(ref val2)) { float value2 = Vector3.Distance(epicenter, ((Component)val2).transform.position); if (!dictionary.ContainsKey(val2)) { dictionary.Add(val2, value2); } } } if (Cfg.maxTreeDamage.Value > 0) { foreach (TreeBase value4 in treeManager.Values) { if ((Object)(object)value4 != (Object)null && Random.value > 0.66f) { float value3 = Vector3.Distance(epicenter, ((Component)value4).transform.position); if (!dictionary2.ContainsKey(value4)) { dictionary2.Add(value4, value3); } } } } float num = Cfg.maxPieceDamage.Value; if (TryGetClosestActiveWard(epicenter, 0f, out var distance)) { float num2 = 1f - distance / radius; num *= 0.5f * num2; Log.Debug("Active ward reduced max damage"); } if (TryGetClosestShieldGenerator(epicenter, 0f, out var distance2)) { float num3 = 1f - distance2 / radius; num *= 0.5f * num3; Log.Debug("Active shield generator reduced max damage"); } if (dictionary.Count > 0) { ((MonoBehaviour)_modInstance).StartCoroutine(_modInstance.Co_DamagePieces(dictionary, radius, num, duration, 1f)); } if (dictionary2.Count > 0) { ((MonoBehaviour)_modInstance).StartCoroutine(_modInstance.Co_DamageTrees(dictionary2, epicenter, radius, Cfg.maxTreeDamage.Value, duration, 1f)); } if (dictionary3.Count > 0) { ((MonoBehaviour)_modInstance).StartCoroutine(_modInstance.Co_DropAttachedPieces(dictionary3, radius, duration, 2f)); } } private IEnumerator Co_ShakeVagon(Vagon vagon) { Log.Trace("Co_ShakeVagon"); object obj; if (vagon == null) { obj = null; } else { GameObject gameObject = ((Component)vagon).gameObject; obj = ((gameObject != null) ? gameObject.GetComponent<Rigidbody>() : null); } Rigidbody rb = (Rigidbody)obj; while (IsShaking()) { if ((Object)(object)rb == (Object)null) { yield break; } float num = Mathf.Sign(Mathf.Sin(quakeShaker.GetCurrentAngle())); float num2 = quakeShaker.TimeAdjustedIntensity(); rb.AddRelativeForce(new Vector3(0f, 0f, num2 * 2f * num), (ForceMode)1); yield return null; } rb.velocity = Vector3.zero; } private IEnumerator Co_RollLog(TreeLog log) { Log.Trace("Co_RollLog"); object obj; if (log == null) { obj = null; } else { GameObject gameObject = ((Component)log).gameObject; obj = ((gameObject != null) ? gameObject.GetComponent<Rigidbody>() : null); } Rigidbody rb = (Rigidbody)obj; while (IsShaking()) { if ((Object)(object)rb == (Object)null) { yield break; } float num = Mathf.Sign(Mathf.Sin(quakeShaker.GetCurrentAngle())); float num2 = quakeShaker.TimeAdjustedIntensity(); rb.AddRelativeTorque(new Vector3(0f, 0f, num2 * 25f * num), (ForceMode)1); yield return null; } rb.angularVelocity = Vector3.zero; } private IEnumerator Co_ShakeShip(Ship ship) { Log.Trace("Co_ShakeVagon"); object obj; if (ship == null) { obj = null; } else { GameObject gameObject = ((Component)ship).gameObject; obj = ((gameObject != null) ? gameObject.GetComponent<Rigidbody>() : null); } Rigidbody rb = (Rigidbody)obj; while (IsShaking()) { if ((Object)(object)rb == (Object)null) { yield break; } float num = Mathf.Sign(Mathf.Sin(quakeShaker.GetCurrentAngle())); float num2 = quakeShaker.TimeAdjustedIntensity(); rb.AddRelativeTorque(new Vector3(0f, 0f, num2 / 4f * num), (ForceMode)1); yield return null; } rb.angularVelocity = Vector3.zero; } private IEnumerator Co_DropAttachedPieces(Dictionary<ItemStand, float> st, float radius, float duration, float delay) { Log.Debug("Co_DropAttachedPieces"); float num; if (IsShaking()) { yield return (object)new WaitUntil((Func<bool>)(() => quakeShaker.HasPeaked())); num = quakeShaker.TimeRemaining(); } else { yield return (object)new WaitForSeconds(delay); num = duration - delay; } float wait = Mathf.Clamp01(num / 2f / (float)st.Count); foreach (KeyValuePair<ItemStand, float> item in st) { if (Random.value < 0.5f) { item.Key.DropItem(); } yield return (object)new WaitForSeconds(wait); } } private IEnumerator Co_DamagePieces(Dictionary<WearNTear, float> wnt, float radius, float damage, float duration, float delay) { Log.Debug("Co_DamagePieces"); float num; if (IsShaking()) { yield return (object)new WaitUntil((Func<bool>)(() => quakeShaker.HasPeaked())); num = quakeShaker.TimeRemaining(); } else { yield return (object)new WaitForSeconds(delay); num = duration - delay; } float wait = Mathf.Clamp01(num / 2f / (float)wnt.Count); Container val = default(Container); foreach (KeyValuePair<WearNTear, float> item in wnt) { WearNTear key = item.Key; float value = item.Value; if ((Object)(object)key != (Object)null && !((Component)key).gameObject.TryGetComponent<Container>(ref val)) { float num2 = damage * (1f - value / radius); float maxSupport = key.GetMaxSupport(); float num3 = 1f - key.m_support * 0.9f / maxSupport; DamagePiece(key, num2 * num3); } yield return (object)new WaitForSeconds(wait); } } private IEnumerator Co_DamageTrees(Dictionary<TreeBase, float> tb, Vector3 epicenter, float radius, float damage, float duration, float delay) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) Log.Debug("Co_DamageTrees"); float num; if (IsShaking()) { yield return (object)new WaitUntil((Func<bool>)(() => quakeShaker.HasPeaked())); num = quakeShaker.TimeRemaining(); } else { yield return (object)new WaitForSeconds(delay); num = duration - delay; } float wait = Mathf.Clamp01(num / 2f / (float)tb.Count); foreach (KeyValuePair<TreeBase, float> item in tb) { TreeBase key = item.Key; float value = item.Value; float distanceAdjDamage = damage * (1f - value / radius); DamageTree(key, epicenter, distanceAdjDamage); yield return (object)new WaitForSeconds(wait); } } private static void DamagePiece(WearNTear wnt, float distanceAdjDamage) { if ((Object)(object)wnt == (Object)null || (Object)(object)wnt.m_nview == (Object)null || !wnt.m_nview.IsValid() || !wnt.m_nview.IsOwner()) { return; } float @float = wnt.m_nview.GetZDO().GetFloat(ZDOVars.s_health, wnt.m_health); float num = RandomToMax(distanceAdjDamage, 0.75f); float num2 = @float - num; if (num2 <= 0f && Cfg.allowFullDestruction.Value) { wnt.Destroy((HitData)null, false); return; } num2 = Mathf.Clamp(num2, 1f, num2); if (@float > 1f) { if ((float)Cfg.displacementChance.Value > 0f) { Displace(((Component)wnt).transform); } wnt.m_nview.GetZDO().Set(ZDOVars.s_health, num2); wnt.m_nview.InvokeRPC(ZNetView.Everybody, "RPC_HealthChanged", new object[1] { num2 }); wnt.SetHealthVisual(num2 / wnt.m_health, true); } } private static void DamageTree(TreeBase treeBase, Vector3 epicenter, float distanceAdjDamage) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)treeBase == (Object)null) && treeBase.m_nview.IsValid()) { treeBase.m_nview.m_zdo.Owned = true; treeBase.m_nview.m_zdo.Owner = true; HitData val = new HitData(); val.m_attacker = ZDOID.None; val.m_itemWorldLevel = 100; val.m_toolTier = 100; val.m_damage.m_chop = RandomToMax(distanceAdjDamage, 0.75f); val.m_dir = epicenter - ((Component)treeBase).transform.position; val.m_dir.y = 0f; val.m_dir = Vector3.Normalize(val.m_dir); treeBase.Damage(val); } } private static void StartStaggering(Vector3 epicenter, float radius, float delay = 0f) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) Log.Debug("StartStaggering"); if (Cfg.charactersStagger.Value) { ((MonoBehaviour)_modInstance).StartCoroutine(_modInstance.Co_StaggerController(epicenter, radius, delay)); } } private IEnumerator Co_StaggerController(Vector3 epicenter, float radius, float delay) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (!IsShaking() || quakeShaker.TimeRemaining() < quakeShaker.Duration * 0.2f) { yield break; } if (delay < 0f) { yield return (object)new WaitUntil((Func<bool>)(() => halfCracked)); } else if (delay > 0f) { yield return (object)new WaitForSeconds(delay); } List<Character> characters = new List<Character>(); Utils.GetCharactersInRangeXZ(epicenter, radius, characters); Object.Instantiate<GameObject>(cracking_sfx, epicenter, Quaternion.identity); bool randomize = false; float randomChance = 0.5f; do { foreach (Character item in characters) { if ((!randomize || Random.value < randomChance) && (Object)(object)item != (Object)null && OkToStagger(item)) { item.Stagger(((Component)item).transform.position); } yield return null; } randomize = true; randomChance = Mathf.Clamp01(randomChance - 0.1f); radius *= 0.8f; yield return (object)new WaitForSeconds(2f); } while (quakeShaker.InPeakWindow()); } private static void PseudoApplyOperation(ZNetView m_nview, Vector3 epicenter, Settings tos) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown //IL_0016: Unknown result type (might be due to invalid IL or missing references) Log.Trace("PseudoApplyOperation"); ZPackage val = new ZPackage(); val.Write(epicenter); tos.Serialize(val); m_nview.InvokeRPC("ApplyOperation", new object[1] { val }); } private static bool FissureExists(Heightmap hm, Vector3 point) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) float num = default(float); hm.GetWorldHeight(point, ref num); float num2 = default(float); hm.GetWorldBaseHeight(point, ref num2); return num < num2 - Cfg.fissureMaxDepth.Value * 0.9f; } private static int GetSeedFromHeightmap(Heightmap hm) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) int num = Convert.ToInt32(Mathf.Clamp(Mathf.Abs(((Component)hm).transform.position.x * 3f + ((Component)hm).transform.position.z * 2f + ((Component)hm).transform.position.y), 0f, 2.1474836E+09f)); Log.Debug($"Seed from heightmap {num}"); return num; } private static Vector2Int[] GetActionPoints(Vector2Int curXY, Vector3 worldPos) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) int x = ((Vector2Int)(ref curXY)).x; int y = ((Vector2Int)(ref curXY)).y; List<Vector2Int> list = new List<Vector2Int> { curXY }; if (Vector2Int.op_Implicit(lastFissureXY) != Vector2.zero) { if (((Vector2Int)(ref lastFissureXY)).x == ((Vector2Int)(ref curXY)).x && ((Vector2Int)(ref lastFissureXY)).y == ((Vector2Int)(ref curXY)).y) { if (Mathf.Abs(worldPos.x - lastWorldPos.x) > Mathf.Abs(worldPos.y - lastWorldPos.y)) { x = ((worldPos.x > lastWorldPos.x) ? (x + 1) : (x - 1)); list.Add(new Vector2Int(x, ((Vector2Int)(ref curXY)).y)); y = ((worldPos.y > lastWorldPos.y) ? (y + 1) : (y - 1)); list.Add(new Vector2Int(((Vector2Int)(ref curXY)).x, y)); } } else if (((Vector2Int)(ref lastFissureXY)).x != ((Vector2Int)(ref curXY)).x && ((Vector2Int)(ref lastFissureXY)).y != ((Vector2Int)(ref curXY)).y) { list.Add(new Vector2Int(((Vector2Int)(ref lastFissureXY)).x, ((Vector2Int)(ref curXY)).y)); list.Add(new Vector2Int(((Vector2Int)(ref curXY)).x, ((Vector2Int)(ref lastFissureXY)).y)); } else if (((Vector2Int)(ref lastFissureXY)).x == ((Vector2Int)(ref curXY)).x) { x = ((worldPos.x > lastWorldPos.x) ? (x + 1) : (x - 1)); list.Add(new Vector2Int(x, ((Vector2Int)(ref curXY)).y)); } else if (((Vector2Int)(ref lastFissureXY)).y == ((Vector2Int)(ref curXY)).y) { y = ((worldPos.y > lastWorldPos.y) ? (y + 1) : (y - 1)); list.Add(new Vector2Int(((Vector2Int)(ref curXY)).x, y)); } } return list.ToArray(); } private static float RestrictedRandomDirection(CrossPlatformRandom random) { float num = random.Range(5f, 40f); return (float)(int)random.Range(0, 9) * 45f + num; } public static float GetDogLegDirection(float angle, CrossPlatformRandom random) { return (angle + 180f + random.Range(15f, 35f)) % 360f; } private static bool CreateFissure(Heightmap hm) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) Log.Debug("CreateFissure"); bool result = true; float num = Cfg.fissureMaxDepth.Value; CrossPlatformRandom crossPlatformRandom = new CrossPlatformRandom(GetSeedFromHeightmap(hm)); if (crossPlatformRandom.value * 100f > Cfg.faultChance.Value) { Log.Debug("No fault line in current zone"); return result; } if (FissureExists(hm, ((Bounds)(ref hm.m_bounds)).center)) { num *= Cfg.fissureDeepenPct.Value; Log.Debug("Fissure already exists. Using percentage of max depth."); } if (fissure_vfx == null) { fissure_vfx = Utils.GetPrefab("vfx_Place_mud_road"); } if (cracking_sfx == null) { cracking_sfx = Utils.GetPrefab("sfx_stonegolem_attack_hit"); } float num2 = RestrictedRandomDirection(crossPlatformRandom); float num3 = GetDogLegDirection(num2, crossPlatformRandom); Vector3 center = ((Bounds)(ref hm.m_bounds)).center; int num4 = default(int); int num5 = default(int); hm.WorldToVertex(center, ref num4, ref num5); float num6 = Mathf.Min((float)hm.m_width * crossPlatformRandom.Range(0.7f, 0.9f), (float)Cfg.earthquakeRadius.Value); float num7 = fissureSpacing; int num8 = Mathf.CeilToInt(num6 / 4f / num7); Vector3 val = center; Vector3 val2 = center; float num9 = 0f; List<Vector3> list = new List<Vector3>(); List<Vector3> list2 = new List<Vector3>(); list.Add(center); int num10 = 0; int num11 = 1; int num12 = 1; while (num9 < num6) { float num13 = num7; float num14 = num7; Vector3 val3 = val + Quaternion.Euler(0f, num3, 0f) * Vector3.forward * num13; Vector3 val4 = val2 + Quaternion.Euler(0f, num2, 0f) * Vector3.forward * num14; num9 += num13 + num14; num11 += 2; list.Add(val3); list2.Add(val4); val = val3; val2 = val4; if (++num10 % num8 == 0) { num3 += crossPlatformRandom.Range(20, 30) * (float)(-num12); num2 += crossPlatformRandom.Range(20, 30) * (float)num12; num12 = -num12; } } list2.Reverse(); list2.AddRange(list); Vector3[] tpa = list2.ToArray(); ((MonoBehaviour)_modInstance).StartCoroutine(_modInstance.Co_ModifyTerrain(tpa, center, fissureRadius, num, num11, 2f)); return result; } public static float GraduatedDepth(int nbrSegments, int seg, float depth) { float num = (float)nbrSegments / 2f; float num2 = Mathf.Abs((float)seg - num) / num; return depth * (1f - num2); } private IEnumerator Co_ModifyTerrain(Vector3[] tpa, Vector3 epicenter, float radius, float depth, int nbrSegments, float delay) { //IL_000e: Unknown result type (might be due to inval