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 Offliner v1.0.2
Offliner.dll
Decompiled a month agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Logging; using HarmonyLib; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Offliner.Core; using Offliner.Effects; using Offliner.Patches; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("Offliner")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+0359a4700e53b4186a27e33f60e9ed9fe4d510cd")] [assembly: AssemblyProduct("Offliner")] [assembly: AssemblyTitle("Offliner")] [assembly: AssemblyVersion("1.0.0.0")] namespace Offliner { internal abstract class CheatCommand : ConsoleCommand { public sealed override bool IsCheat => true; public sealed override void Run(string[] args) { RunCheat(args); } protected abstract void RunCheat(string[] args); } internal class DebugCommand : CheatCommand { public override string Name => "offliner_debug"; public override string Help => "offliner_debug - report effect state, writes BepInEx/offliner_debug.txt"; protected override void RunCheat(string[] args) { //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_012e: 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_0150: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_02b9: Unknown result type (might be due to invalid IL or missing references) //IL_037f: Unknown result type (might be due to invalid IL or missing references) //IL_038a: Unknown result type (might be due to invalid IL or missing references) //IL_038f: Unknown result type (might be due to invalid IL or missing references) //IL_039e: Unknown result type (might be due to invalid IL or missing references) //IL_03e3: Unknown result type (might be due to invalid IL or missing references) //IL_03e8: Unknown result type (might be due to invalid IL or missing references) //IL_0448: Unknown result type (might be due to invalid IL or missing references) //IL_0454: Unknown result type (might be due to invalid IL or missing references) //IL_0460: Unknown result type (might be due to invalid IL or missing references) //IL_0465: Unknown result type (might be due to invalid IL or missing references) //IL_0479: Unknown result type (might be due to invalid IL or missing references) //IL_047e: Unknown result type (might be due to invalid IL or missing references) //IL_0482: Unknown result type (might be due to invalid IL or missing references) //IL_0487: Unknown result type (might be due to invalid IL or missing references) //IL_049d: Unknown result type (might be due to invalid IL or missing references) //IL_04a2: Unknown result type (might be due to invalid IL or missing references) //IL_04bc: Unknown result type (might be due to invalid IL or missing references) //IL_04c1: Unknown result type (might be due to invalid IL or missing references) //IL_04e0: Unknown result type (might be due to invalid IL or missing references) //IL_04e5: Unknown result type (might be due to invalid IL or missing references) //IL_04f5: Unknown result type (might be due to invalid IL or missing references) //IL_04fa: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; OfflinerAvatar offlinerAvatar = (((Object)(object)localPlayer != (Object)null) ? ((Component)localPlayer).GetComponent<OfflinerAvatar>() : null); if ((Object)(object)offlinerAvatar == (Object)null) { Console.instance.Print("offliner_debug: no local player."); return; } StringBuilder stringBuilder = new StringBuilder(); Camera main = Camera.main; Stage stage = offlinerAvatar.Stage; stringBuilder.AppendLine($"level {offlinerAvatar.Level:F2} | tint {stage.Tint:F2} groans {stage.Groans} eyes {stage.Eyes} mist {stage.Mist} draugr {stage.Draugr}"); stringBuilder.AppendLine(string.Format("camera '{0}' cullingMask {1:X8} pos {2}", ((Object)(object)main != (Object)null) ? ((Object)main).name : "none", ((Object)(object)main != (Object)null) ? main.cullingMask : 0, ((Object)(object)main != (Object)null) ? ((Component)main).transform.position : Vector3.zero)); Transform val = Priv.Head.Invoke((Character)(object)localPlayer); object arg = ((Component)localPlayer).transform.position; object arg2; Vector3 val2; if (!((Object)(object)val != (Object)null)) { arg2 = "null"; } else { val2 = val.position; arg2 = ((Vector3)(ref val2)).ToString("F3"); } stringBuilder.AppendLine($"player pos {arg} head {arg2}"); Transform val3 = ((IEnumerable<Transform>)((Component)localPlayer).GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "Offliner_HeadGlow")); stringBuilder.AppendLine(); object value; if (!((Object)(object)val3 == (Object)null)) { object[] obj = new object[4] { val3.position, null, null, null }; object obj2; if (!((Object)(object)val != (Object)null)) { obj2 = "?"; } else { val2 = val3.position - val.position; obj2 = ((Vector3)(ref val2)).ToString("F3"); } obj[1] = obj2; obj[2] = val3.lossyScale; obj[3] = ((Component)val3).gameObject.activeInHierarchy; value = string.Format("HEAD GLOW: pos {0:F3} (from head {1}) lossyScale {2:F4} active {3}", obj); } else { value = "HEAD GLOW: none"; } stringBuilder.AppendLine((string?)value); if ((Object)(object)val3 != (Object)null) { Renderer[] componentsInChildren = ((Component)val3).GetComponentsInChildren<Renderer>(true); foreach (Renderer r in componentsInChildren) { Describe(stringBuilder, r, main); } Light[] componentsInChildren2 = ((Component)val3).GetComponentsInChildren<Light>(true); foreach (Light val4 in componentsInChildren2) { stringBuilder.AppendLine($" light range {val4.range} intensity {val4.intensity} enabled {((Behaviour)val4).enabled} renderMode {val4.renderMode}"); } } Transform[] array = (from t in ((Component)localPlayer).GetComponentsInChildren<Transform>(true) where ((Object)t).name.StartsWith("Offliner_Aura_") select t).ToArray(); stringBuilder.AppendLine(); stringBuilder.AppendLine((array.Length == 0) ? "AURA: none" : $"AURA: {array.Length} effect(s)"); Transform[] array2 = array; foreach (Transform val5 in array2) { object[] obj3 = new object[5] { ((Object)val5).name, null, null, null, null }; Transform parent = val5.parent; obj3[1] = ((parent != null) ? ((Object)parent).name : null); obj3[2] = val5.position - ((Component)localPlayer).transform.position; obj3[3] = val5.lossyScale; obj3[4] = ((Component)val5).gameObject.activeInHierarchy; stringBuilder.AppendLine(string.Format(" '{0}' on '{1}' pos from player {2:F3} lossyScale {3:F3} active {4}", obj3)); ParticleSystem[] componentsInChildren3 = ((Component)val5).GetComponentsInChildren<ParticleSystem>(true); foreach (ParticleSystem val6 in componentsInChildren3) { MainModule main2 = val6.main; string text = $" ps '{((Object)val6).name}' playing {val6.isPlaying} count {val6.particleCount} maxParticles {((MainModule)(ref main2)).maxParticles} loop {((MainModule)(ref main2)).loop} "; object arg3 = ((MainModule)(ref main2)).simulationSpace; object arg4 = ((MainModule)(ref main2)).scalingMode; ShapeModule shape = val6.shape; object arg5; if (!((ShapeModule)(ref shape)).enabled) { arg5 = "off"; } else { shape = val6.shape; string? text2 = ((object)((ShapeModule)(ref shape)).shapeType/*cast due to .constrained prefix*/).ToString(); shape = val6.shape; object obj4; if (!((Object)(object)((ShapeModule)(ref shape)).skinnedMeshRenderer != (Object)null)) { obj4 = "-"; } else { shape = val6.shape; obj4 = ((Object)((ShapeModule)(ref shape)).skinnedMeshRenderer).name; } arg5 = text2 + " mesh " + (string?)obj4; } string text3 = $"space {arg3} scaling {arg4} shape {arg5} "; MinMaxCurve val7 = ((MainModule)(ref main2)).startSize; object arg6 = ((MinMaxCurve)(ref val7)).constant; val7 = ((MainModule)(ref main2)).startLifetime; stringBuilder.AppendLine(text + text3 + $"startSize {arg6:F2} startLifetime {((MinMaxCurve)(ref val7)).constant:F2}"); } Renderer[] componentsInChildren = ((Component)val5).GetComponentsInChildren<Renderer>(true); foreach (Renderer r2 in componentsInChildren) { Describe(stringBuilder, r2, main); } } string text4 = Path.Combine(Paths.BepInExRootPath, "offliner_debug.txt"); File.WriteAllText(text4, stringBuilder.ToString()); Console.instance.Print(stringBuilder.ToString().Split(new char[1] { '\n' })[0]); Console.instance.Print("Details written to " + text4); } private static void Describe(StringBuilder sb, Renderer r, Camera cam) { //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: 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_011f: Unknown result type (might be due to invalid IL or missing references) Material sharedMaterial = r.sharedMaterial; bool flag = (Object)(object)cam != (Object)null && (cam.cullingMask & (1 << ((Component)r).gameObject.layer)) != 0; string text = $" renderer '{((Object)r).name}' {((object)r).GetType().Name} enabled {r.enabled} visible {r.isVisible} layer {((Component)r).gameObject.layer}({LayerMask.LayerToName(((Component)r).gameObject.layer)}) "; object arg = flag; Bounds bounds = r.bounds; object arg2 = ((Bounds)(ref bounds)).center; bounds = r.bounds; sb.AppendLine(text + $"cameraSeesLayer {arg} bounds {arg2:F2} size {((Bounds)(ref bounds)).size:F3} " + string.Format("shader '{0}' color {1} queue {2}", ((Object)(object)sharedMaterial != (Object)null && (Object)(object)sharedMaterial.shader != (Object)null) ? ((Object)sharedMaterial.shader).name : "none", ((Object)(object)sharedMaterial != (Object)null && sharedMaterial.HasProperty("_Color")) ? ((object)sharedMaterial.color/*cast due to .constrained prefix*/).ToString() : "-", ((Object)(object)sharedMaterial != (Object)null) ? sharedMaterial.renderQueue : 0)); } } internal static class DraugrAssets { public static string PrefabName = "Draugr"; private static readonly HashSet<string> Warned = new HashSet<string>(); public static GameObject Prefab { get { if ((Object)(object)ZNetScene.instance == (Object)null) { return null; } GameObject prefab = ZNetScene.instance.GetPrefab(PrefabName); if ((Object)(object)prefab == (Object)null) { WarnOnce("prefab", "Prefab '" + PrefabName + "' not found; draugr effects disabled."); } return prefab; } } public static EffectList IdleSound { get { GameObject prefab = Prefab; if ((Object)(object)prefab == (Object)null) { return null; } BaseAI component = prefab.GetComponent<BaseAI>(); if ((Object)(object)component == (Object)null || component.m_idleSound == null || component.m_idleSound.m_effectPrefabs.Length == 0) { WarnOnce("idle", "'" + PrefabName + "' has no idle sound; groans disabled."); return null; } return component.m_idleSound; } } public static GameObject Visual { get { GameObject prefab = Prefab; Transform val = (((Object)(object)prefab != (Object)null) ? prefab.transform.Find("Visual") : null); GameObject val2 = (((Object)(object)val != (Object)null) ? ((Component)val).gameObject : null); if ((Object)(object)prefab != (Object)null && (Object)(object)val2 == (Object)null) { WarnOnce("visual", "'" + PrefabName + "' has no visual; draugr form disabled."); } return val2; } } public static void InfoOnce(string key, string message) { if (Warned.Add("info:" + key)) { Plugin.Log.LogInfo((object)message); } } public static void WarnOnce(string key, string message) { if (Warned.Add(key)) { Plugin.Log.LogWarning((object)message); } } } internal class FindFxCommand : CheatCommand { public override string Name => "offliner_findfx"; public override string Help => "offliner_findfx <text> - list particle effect prefabs by name"; protected override void RunCheat(string[] args) { string text = ((args.Length != 0) ? args[0].ToLowerInvariant() : "mist"); foreach (string item in from n in (from go in MistEffect.ParticlePrefabs() select ((Object)go).name into n where n.ToLowerInvariant().Contains(text) select n).Distinct() orderby n select n) { Console.instance.Print(item); } } } internal static class LevelSync { public const string ZdoKey = "Offliner_Level"; public static float Read(ZNetView nview) { if ((Object)(object)nview == (Object)null || !nview.IsValid()) { return 0f; } return nview.GetZDO().GetFloat("Offliner_Level", 0f); } public static void Write(ZNetView nview, float level) { if (!((Object)(object)nview == (Object)null) && nview.IsValid() && nview.IsOwner()) { ZDO zDO = nview.GetZDO(); if (Mathf.Abs(zDO.GetFloat("Offliner_Level", 0f) - level) > 0.01f) { zDO.Set("Offliner_Level", level); } } } } [DefaultExecutionOrder(-10)] internal class OfflinerAvatar : MonoBehaviour { public Player Player { get; private set; } public ZNetView NView { get; private set; } public float Level { get; private set; } public Stage Stage { get; private set; } public bool IsValid { get { if ((Object)(object)NView != (Object)null) { return NView.IsValid(); } return false; } } private void Awake() { Player = ((Component)this).GetComponent<Player>(); NView = ((Component)this).GetComponent<ZNetView>(); } private void LateUpdate() { if (!IsValid) { Level = 0f; Stage = default(Stage); return; } if ((Object)(object)Player == (Object)(object)Player.m_localPlayer) { LevelSync.Write(NView, OffliningSkill.EffectiveLevel(Player)); } Level = LevelSync.Read(NView); Stage = Progression.For(Level); } } internal class OffliningCommand : CheatCommand { public override string Name => "offlining"; public override string Help => "offlining <0-100> - set your Offlining level (testing)"; protected override void RunCheat(string[] args) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || args.Length != 1 || !float.TryParse(args[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { Console.instance.Print(((ConsoleCommand)this).Help); return; } result = Mathf.Clamp(result, 0f, 100f); Skills skills = ((Character)localPlayer).GetSkills(); if (OffliningSkill.Find(localPlayer) == null) { skills.RaiseSkill(OffliningSkill.Type, 0f); } Skill obj = OffliningSkill.Find(localPlayer); obj.m_level = result; obj.m_accumulator = 0f; Console.instance.Print($"Offlining set to {result}"); } } internal static class OffliningSkill { public const string Identifier = "wannie.offliner.offlining"; public static SkillType Type { get; private set; } public static void Register(string pluginDir) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown //IL_0042: Unknown result type (might be due to invalid IL or missing references) Type = SkillManager.Instance.AddSkill(new SkillConfig { Identifier = "wannie.offliner.offlining", Name = "Offlining", Description = "Time spent alone on the server. Nobody knows what it's doing to you.", IncreaseStep = 15f, Icon = LoadIcon(pluginDir) }); } private static Sprite LoadIcon(string pluginDir) { string text = IconPath.Find(pluginDir); if (text == null) { Plugin.Log.LogWarning((object)"Offlining icon 'offlining_icon.png' not found next to the mod; the skill has no icon."); return null; } return AssetUtils.LoadSpriteFromFile(text); } public static Skill Find(Player player) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) foreach (Skill skill in ((Character)player).GetSkills().GetSkillList()) { if (skill.m_info.m_skill == Type) { return skill; } } return null; } public static float EffectiveLevel(Player player) { Skill val = Find(player); if (val != null) { return XpTuning.EffectiveLevel(val.m_level, val.m_accumulator); } return 0f; } } [BepInPlugin("wannie.offliner", "Offliner", "1.0.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] internal class Plugin : BaseUnityPlugin { public const string Guid = "wannie.offliner"; public const string Version = "1.0.2"; internal static ManualLogSource Log; private void Awake() { //IL_006d: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; OffliningSkill.Register(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location)); CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new OffliningCommand()); CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new FindFxCommand()); CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new TuneCommand()); CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new DebugCommand()); ((Component)this).gameObject.AddComponent<SoloXpTicker>(); new Harmony("wannie.offliner").PatchAll(); } } internal static class Priv { public static readonly int SkinColorId = (int)AccessTools.Field(typeof(VisEquipment), "s_skinColorID").GetValue(null); public static readonly FieldRef<Character, Transform> Head = AccessTools.FieldRefAccess<Character, Transform>("m_head"); public static readonly FieldRef<Character, GameObject> Visual = AccessTools.FieldRefAccess<Character, GameObject>("m_visual"); public static readonly FieldRef<Character, Animator> CharAnimator = AccessTools.FieldRefAccess<Character, Animator>("m_animator"); public static readonly FieldRef<VisEquipment, GameObject> RightItemInstance = AccessTools.FieldRefAccess<VisEquipment, GameObject>("m_rightItemInstance"); public static readonly FieldRef<VisEquipment, GameObject> LeftItemInstance = AccessTools.FieldRefAccess<VisEquipment, GameObject>("m_leftItemInstance"); public static readonly FieldRef<VisEquipment, GameObject> RightBackItemInstance = AccessTools.FieldRefAccess<VisEquipment, GameObject>("m_rightBackItemInstance"); public static readonly FieldRef<VisEquipment, GameObject> LeftBackItemInstance = AccessTools.FieldRefAccess<VisEquipment, GameObject>("m_leftBackItemInstance"); public static readonly FieldRef<Humanoid, VisEquipment> VisEquip = AccessTools.FieldRefAccess<Humanoid, VisEquipment>("m_visEquipment"); } internal static class SoloCheck { public static bool IsAloneOnServer() { ZNet instance = ZNet.instance; if ((Object)(object)instance == (Object)null) { return false; } return SoloRules.CountsAsAlone(instance.IsServer(), instance.GetPlayerList().Count); } } internal class SoloXpTicker : MonoBehaviour { private float _elapsed; private void Update() { //IL_005a: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || !SoloCheck.IsAloneOnServer()) { _elapsed = 0f; return; } _elapsed += Time.deltaTime; if (!(_elapsed < 60f)) { _elapsed -= 60f; ((Character)localPlayer).GetSkills().RaiseSkill(OffliningSkill.Type, 1f); } } } internal class TuneCommand : CheatCommand { public override string Name => "offliner_tune"; public override string Help => "offliner_tune [skin r g b | glow r g b | glowlight range intensity up]"; protected override void RunCheat(string[] args) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) float[] values2; float[] values3; if (args.Length == 4 && args[0] == "skin" && TryFloats(args, out var values)) { SkinTintPatch.DraugrSkin = new Color(values[0], values[1], values[2]); } else if (args.Length == 4 && args[0] == "glow" && TryFloats(args, out values2)) { HeadGlow.Color = new Color(values2[0], values2[1], values2[2]); HeadGlow.Version++; } else if (args.Length == 4 && args[0] == "glowlight" && TryFloats(args, out values3)) { HeadGlow.Range = values3[0]; HeadGlow.Intensity = values3[1]; HeadGlow.UpOffset = values3[2]; HeadGlow.Version++; } else if (args.Length != 0) { Console.instance.Print(((ConsoleCommand)this).Help); return; } Color draugrSkin = SkinTintPatch.DraugrSkin; Color color = HeadGlow.Color; Console.instance.Print(string.Format(CultureInfo.InvariantCulture, "skin {0:F2} {1:F2} {2:F2} | glow {3:F2} {4:F2} {5:F2} | glowlight {6:F2} {7:F2} {8:F2}", draugrSkin.r, draugrSkin.g, draugrSkin.b, color.r, color.g, color.b, HeadGlow.Range, HeadGlow.Intensity, HeadGlow.UpOffset)); } private static bool TryFloats(string[] args, out float[] values) { values = new float[args.Length - 1]; for (int i = 1; i < args.Length; i++) { if (!float.TryParse(args[i], NumberStyles.Float, CultureInfo.InvariantCulture, out values[i - 1])) { return false; } } return true; } } internal static class VisualClone { public static GameObject Create(GameObject source, Transform parent) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_00ae: 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) GameObject val = new GameObject("Offliner_CloneHolder"); val.SetActive(false); GameObject val2 = Object.Instantiate<GameObject>(source, val.transform, false); for (int i = 0; i < 3; i++) { MonoBehaviour[] componentsInChildren = val2.GetComponentsInChildren<MonoBehaviour>(true); for (int j = 0; j < componentsInChildren.Length; j++) { Object.DestroyImmediate((Object)(object)componentsInChildren[j]); } Collider[] componentsInChildren2 = val2.GetComponentsInChildren<Collider>(true); for (int j = 0; j < componentsInChildren2.Length; j++) { Object.DestroyImmediate((Object)(object)componentsInChildren2[j]); } Rigidbody[] componentsInChildren3 = val2.GetComponentsInChildren<Rigidbody>(true); for (int j = 0; j < componentsInChildren3.Length; j++) { Object.DestroyImmediate((Object)(object)componentsInChildren3[j]); } } val2.transform.SetParent(parent, false); val2.transform.localPosition = Vector3.zero; val2.transform.localRotation = Quaternion.identity; Object.Destroy((Object)(object)val); val2.SetActive(true); return val2; } } } namespace Offliner.Core { public static class BoneMap { private static readonly Dictionary<string, string> Aliases = new Dictionary<string, string> { { "Spine0", "Spine" }, { "LeftHip", "Hips" }, { "RightHip", "Hips" } }; public static string Resolve(IEnumerable<string> chainToRoot, ISet<string> playerBones) { foreach (string item in chainToRoot) { if (playerBones.Contains(item)) { return item; } if (Aliases.TryGetValue(item, out var value) && playerBones.Contains(value)) { return value; } } return null; } } public static class IconPath { public const string FileName = "offlining_icon.png"; public static string Find(string pluginDir) { string text = Path.Combine(pluginDir, "offlining_icon.png"); if (File.Exists(text)) { return text; } string text2 = Path.Combine(pluginDir, "Assets", "offlining_icon.png"); if (!File.Exists(text2)) { return null; } return text2; } } public enum GroanRate { None, Occasional, Frequent } public readonly struct Stage { public float Tint { get; } public GroanRate Groans { get; } public bool Eyes { get; } public bool Mist { get; } public bool Draugr { get; } public Stage(float tint, GroanRate groans, bool eyes, bool mist, bool draugr) { Tint = tint; Groans = groans; Eyes = eyes; Mist = mist; Draugr = draugr; } } public static class Progression { public const float EffectsStart = 30f; public const float FrequentGroansAt = 45f; public const float EyesAt = 65f; public const float MistAt = 75f; public const float DraugrAt = 100f; public static Stage For(float level) { if (float.IsNaN(level) || level < 30f) { return default(Stage); } return new Stage(TintFor(level), (!(level >= 45f)) ? GroanRate.Occasional : GroanRate.Frequent, level >= 65f, level >= 75f, level >= 100f); } public static float TintFor(float level) { if (float.IsNaN(level) || level <= 30f) { return 0f; } float num = (level - 30f) / 70f; if (!(num > 1f)) { return num; } return 1f; } public static float NextGroanDelaySeconds(GroanRate rate, float random01) { return rate switch { GroanRate.Occasional => 300f + 300f * random01, GroanRate.Frequent => 60f + 120f * random01, _ => float.PositiveInfinity, }; } } public static class SoloRules { public static bool CountsAsAlone(bool isServer, int playersOnServer) { if (!isServer) { return playersOnServer == 1; } return false; } } public static class XpTuning { public const float XpPerTick = 15f; public const float TickSeconds = 60f; public const float MaxLevel = 100f; public const float FinalLevelMinutes = 420f; public static float NextLevelRequirement(float level) { float num = (float)Math.Floor(level + 1f); if (num >= 100f) { return 6300f; } return (float)Math.Pow(num, 1.5) * 0.5f + 0.5f; } public static int TicksToReach(float targetLevel) { float num = 0f; float num2 = 0f; int num3 = 0; while (num < targetLevel && num < 100f) { num2 += 15f; num3++; if (num2 >= NextLevelRequirement(num)) { num = Math.Min(num + 1f, 100f); num2 = 0f; } } return num3; } public static float EffectiveLevel(float level, float accumulator) { if (level >= 100f) { return 100f; } float num = accumulator / NextLevelRequirement(level); if (num < 0f) { num = 0f; } if (num > 1f) { num = 1f; } return level + num; } } } namespace Offliner.Patches { [HarmonyPatch(typeof(Skill), "GetNextLevelRequirement")] internal static class FinalLevelPatch { private static void Postfix(Skill __instance, ref float __result) { //IL_000e: 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) if (__instance.m_info != null && __instance.m_info.m_skill == OffliningSkill.Type) { __result = XpTuning.NextLevelRequirement(__instance.m_level); } } } [HarmonyPatch(typeof(Player), "Awake")] internal static class PlayerAwakePatch { private static void Postfix(Player __instance) { ((Component)__instance).gameObject.AddComponent<OfflinerAvatar>(); ((Component)__instance).gameObject.AddComponent<GroanEffect>(); ((Component)__instance).gameObject.AddComponent<MistEffect>(); ((Component)__instance).gameObject.AddComponent<HeadGlow>(); ((Component)__instance).gameObject.AddComponent<DraugrForm>(); } } [HarmonyPatch(typeof(VisEquipment), "UpdateColors")] internal static class SkinTintPatch { public static Color DraugrSkin = new Color(0.55f, 0.95f, 1.2f); private static void Postfix(VisEquipment __instance) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) if (!__instance.m_isPlayer || (Object)(object)__instance.m_bodyModel == (Object)null) { return; } OfflinerAvatar componentInParent = ((Component)__instance).GetComponentInParent<OfflinerAvatar>(); if (!((Object)(object)componentInParent == (Object)null)) { float tint = componentInParent.Stage.Tint; if (!(tint <= 0f)) { Material val = ((Renderer)__instance.m_bodyModel).materials[0]; val.SetColor(Priv.SkinColorId, Color.Lerp(val.GetColor(Priv.SkinColorId), DraugrSkin, tint)); } } } } } namespace Offliner.Effects { internal class DraugrForm : MonoBehaviour { private OfflinerAvatar _avatar; private GameObject _skin; private Animator _playerAnimator; private AnimatorCullingMode _playerCulling; private readonly List<Renderer> _hidden = new List<Renderer>(); private void Awake() { _avatar = ((Component)this).GetComponent<OfflinerAvatar>(); } private void LateUpdate() { bool flag = _avatar.IsValid && _avatar.Stage.Draugr && !((Character)_avatar.Player).IsDead(); if (flag && (Object)(object)_skin == (Object)null) { Create(); } else if (!flag && (Object)(object)_skin != (Object)null) { Remove(); } if ((Object)(object)_skin != (Object)null) { HidePlayerRenderers(); } } private void Create() { //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Expected O, but got Unknown //IL_010a: 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_0140: 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_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0291: Unknown result type (might be due to invalid IL or missing references) //IL_0296: Unknown result type (might be due to invalid IL or missing references) GameObject visual = DraugrAssets.Visual; VisEquipment val = Priv.VisEquip.Invoke((Humanoid)(object)_avatar.Player); if ((Object)(object)visual == (Object)null || (Object)(object)val == (Object)null || (Object)(object)val.m_bodyModel == (Object)null || (Object)(object)val.m_bodyModel.rootBone == (Object)null) { return; } SkinnedMeshRenderer bodyModel = val.m_bodyModel; Transform rootBone = bodyModel.rootBone; Dictionary<string, Transform> dictionary = new Dictionary<string, Transform>(); Transform[] componentsInChildren = ((Component)rootBone).GetComponentsInChildren<Transform>(true); foreach (Transform val2 in componentsInChildren) { if (!dictionary.ContainsKey(((Object)val2).name)) { dictionary[((Object)val2).name] = val2; } } HashSet<string> playerBones = new HashSet<string>(dictionary.Keys); _skin = new GameObject("Offliner_Draugr"); _skin.layer = ((Component)bodyModel).gameObject.layer; _skin.transform.SetParent(((Component)bodyModel).transform.parent, false); _skin.transform.localPosition = ((Component)bodyModel).transform.localPosition; _skin.transform.localRotation = ((Component)bodyModel).transform.localRotation; _skin.transform.localScale = ((Component)bodyModel).transform.localScale; int num = 0; SkinnedMeshRenderer[] componentsInChildren2 = visual.GetComponentsInChildren<SkinnedMeshRenderer>(true); foreach (SkinnedMeshRenderer val3 in componentsInChildren2) { GameObject val4 = new GameObject(((Object)val3).name) { layer = _skin.layer }; val4.transform.SetParent(_skin.transform, false); SkinnedMeshRenderer val5 = val4.AddComponent<SkinnedMeshRenderer>(); val5.sharedMesh = val3.sharedMesh; ((Renderer)val5).sharedMaterials = ((Renderer)val3).sharedMaterials; val5.rootBone = rootBone; val5.updateWhenOffscreen = true; Transform[] array = (Transform[])(object)new Transform[val3.bones.Length]; for (int j = 0; j < array.Length; j++) { string text = BoneMap.Resolve(ChainToRoot(val3.bones[j]), playerBones); if (text == null) { num++; } array[j] = ((text != null) ? dictionary[text] : rootBone); } val5.bones = array; } if (num > 0) { DraugrAssets.WarnOnce("bones", $"{num} draugr bone(s) had no player match; they follow the hips."); } _playerAnimator = Priv.CharAnimator.Invoke((Character)(object)_avatar.Player); if ((Object)(object)_playerAnimator != (Object)null) { _playerCulling = _playerAnimator.cullingMode; _playerAnimator.cullingMode = (AnimatorCullingMode)0; } } private static bool IsAura(Transform t) { while ((Object)(object)t != (Object)null) { if (((Object)t).name.StartsWith("Offliner_Aura_")) { return true; } t = t.parent; } return false; } private static IEnumerable<string> ChainToRoot(Transform bone) { Transform t = bone; while ((Object)(object)t != (Object)null) { yield return ((Object)t).name; t = t.parent; } } private void Remove() { //IL_005f: Unknown result type (might be due to invalid IL or missing references) foreach (Renderer item in _hidden) { if ((Object)(object)item != (Object)null) { item.enabled = true; } } _hidden.Clear(); if ((Object)(object)_playerAnimator != (Object)null) { _playerAnimator.cullingMode = _playerCulling; } _playerAnimator = null; Object.Destroy((Object)(object)_skin); _skin = null; } private void HidePlayerRenderers() { GameObject val = Priv.Visual.Invoke((Character)(object)_avatar.Player); if ((Object)(object)val == (Object)null) { return; } VisEquipment val2 = Priv.VisEquip.Invoke((Humanoid)(object)_avatar.Player); GameObject[] source = (GameObject[])(((Object)(object)val2 == (Object)null) ? ((Array)new GameObject[0]) : ((Array)((IEnumerable<GameObject>)(object)new GameObject[4] { Priv.RightItemInstance.Invoke(val2), Priv.LeftItemInstance.Invoke(val2), Priv.RightBackItemInstance.Invoke(val2), Priv.LeftBackItemInstance.Invoke(val2) }).Where((GameObject go) => (Object)(object)go != (Object)null).ToArray())); Renderer[] componentsInChildren = val.GetComponentsInChildren<Renderer>(true); foreach (Renderer r in componentsInChildren) { if (r.enabled && !((Component)r).transform.IsChildOf(_skin.transform) && !IsAura(((Component)r).transform) && !source.Any((GameObject item) => ((Component)r).transform.IsChildOf(item.transform))) { r.enabled = false; _hidden.Add(r); } } } private void OnDestroy() { if ((Object)(object)_skin != (Object)null) { Object.Destroy((Object)(object)_skin); } } } internal class GroanEffect : MonoBehaviour { public const string RpcName = "Offliner_Groan"; private OfflinerAvatar _avatar; private GroanRate _rate; private float _timer; private void Awake() { _avatar = ((Component)this).GetComponent<OfflinerAvatar>(); ZNetView component = ((Component)this).GetComponent<ZNetView>(); if ((Object)(object)component != (Object)null) { component.Register("Offliner_Groan", (Action<long>)RPC_Groan); } } private void Update() { if (!_avatar.IsValid || !_avatar.NView.IsOwner()) { return; } GroanRate groans = _avatar.Stage.Groans; if (groans != _rate) { _rate = groans; _timer = Progression.NextGroanDelaySeconds(groans, Random.value); } if (groans != GroanRate.None) { _timer -= Time.deltaTime; if (!(_timer > 0f)) { _timer = Progression.NextGroanDelaySeconds(groans, Random.value); _avatar.NView.InvokeRPC(ZNetView.Everybody, "Offliner_Groan", Array.Empty<object>()); } } } private void RPC_Groan(long sender) { //IL_0011: 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_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) EffectList idleSound = DraugrAssets.IdleSound; if (idleSound != null) { idleSound.Create(((Component)this).transform.position, ((Component)this).transform.rotation, ((Component)this).transform, 1f, -1, default(ZDOID)); } } } internal class HeadGlow : MonoBehaviour { public static Color Color = new Color(0.45f, 1f, 0.35f); public static float Range = 0.6f; public static float Intensity = 3f; public static float UpOffset = 0.1f; public static int Version; private OfflinerAvatar _avatar; private GameObject _glow; private int _builtVersion; private void Awake() { _avatar = ((Component)this).GetComponent<OfflinerAvatar>(); } private void LateUpdate() { bool flag = _avatar.IsValid && _avatar.Stage.Eyes && !_avatar.Stage.Draugr; if ((Object)(object)_glow != (Object)null && (!flag || _builtVersion != Version)) { Object.Destroy((Object)(object)_glow); _glow = null; } if (flag && (Object)(object)_glow == (Object)null) { _glow = Build(); _builtVersion = Version; } } private GameObject Build() { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Expected O, but got Unknown Transform val = Priv.Head.Invoke((Character)(object)_avatar.Player); if ((Object)(object)val == (Object)null) { DraugrAssets.WarnOnce("glow", "Player head bone not found; head glow disabled."); return null; } GameObject val2 = new GameObject("Offliner_HeadGlow"); val2.transform.SetParent(val, false); val2.transform.position = val.position + ((Component)_avatar.Player).transform.up * UpOffset; Light obj = val2.AddComponent<Light>(); obj.type = (LightType)2; obj.color = Color; obj.range = Range; obj.intensity = Intensity; obj.renderMode = (LightRenderMode)1; return val2; } private void OnDestroy() { if ((Object)(object)_glow != (Object)null) { Object.Destroy((Object)(object)_glow); } } } internal class MistEffect : MonoBehaviour { public const string AuraPrefix = "Offliner_Aura_"; private OfflinerAvatar _avatar; private readonly List<GameObject> _aura = new List<GameObject>(); private SkinnedMeshRenderer _emitter; private bool _built; public static IEnumerable<GameObject> ParticlePrefabs() { return (from ps in Resources.FindObjectsOfTypeAll<ParticleSystem>() select ((Component)((Component)ps).transform.root).gameObject).Where(delegate(GameObject go) { //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) Scene scene = go.scene; return !((Scene)(ref scene)).IsValid(); }).Distinct(); } private void Awake() { _avatar = ((Component)this).GetComponent<OfflinerAvatar>(); } private void LateUpdate() { if (!_avatar.IsValid || !_avatar.Stage.Mist || ((Character)_avatar.Player).IsDead()) { if (_built) { Clear(); } return; } SkinnedMeshRenderer val = ShownBody(); if (!((Object)(object)val == (Object)null) && (!_built || (Object)(object)val != (Object)(object)_emitter)) { Clear(); Build(val); } } private SkinnedMeshRenderer ShownBody() { VisEquipment val = Priv.VisEquip.Invoke((Humanoid)(object)_avatar.Player); if ((Object)(object)val == (Object)null || (Object)(object)val.m_bodyModel == (Object)null) { return null; } Transform val2 = (((Object)(object)((Component)val.m_bodyModel).transform.parent != (Object)null) ? ((Component)val.m_bodyModel).transform.parent.Find("Offliner_Draugr") : null); SkinnedMeshRenderer val3 = (((Object)(object)val2 != (Object)null) ? ((Component)val2).GetComponentInChildren<SkinnedMeshRenderer>(true) : null); if (!((Object)(object)val3 != (Object)null)) { return val.m_bodyModel; } return val3; } private void Build(SkinnedMeshRenderer body) { //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_0218: 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_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: 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) //IL_023c: Unknown result type (might be due to invalid IL or missing references) _built = true; _emitter = body; GameObject prefab = DraugrAssets.Prefab; GameObject visual = DraugrAssets.Visual; VisEquipment val = Priv.VisEquip.Invoke((Humanoid)(object)_avatar.Player); GameObject val2 = Priv.Visual.Invoke((Character)(object)_avatar.Player); if ((Object)(object)prefab == (Object)null || (Object)(object)visual == (Object)null || (Object)(object)val == (Object)null || (Object)(object)val.m_bodyModel.rootBone == (Object)null || (Object)(object)val2 == (Object)null) { return; } Dictionary<string, Transform> dictionary = new Dictionary<string, Transform>(); Transform[] componentsInChildren = ((Component)val.m_bodyModel.rootBone).GetComponentsInChildren<Transform>(true); foreach (Transform val3 in componentsInChildren) { if (!dictionary.ContainsKey(((Object)val3).name)) { dictionary[((Object)val3).name] = val3; } } HashSet<string> playerBones = new HashSet<string>(dictionary.Keys); List<string> list = new List<string>(); ParticleSystem[] componentsInChildren2 = prefab.GetComponentsInChildren<ParticleSystem>(true); foreach (ParticleSystem val4 in componentsInChildren2) { Transform parent = ((Component)val4).transform.parent; if ((Object)(object)parent != (Object)null && (Object)(object)((Component)parent).GetComponentInParent<ParticleSystem>(true) != (Object)null) { continue; } string text = (((Object)(object)parent != (Object)null) ? BoneMap.Resolve(ChainToRoot(parent), playerBones) : null); GameObject val5 = VisualClone.Create(((Component)val4).gameObject, (text != null) ? dictionary[text] : val2.transform); ((Object)val5).name = "Offliner_Aura_" + ((Object)val4).name; if (text != null) { val5.transform.localPosition = ((Component)val4).transform.localPosition; val5.transform.localRotation = ((Component)val4).transform.localRotation; val5.transform.localScale = ((Component)val4).transform.localScale; } else { val5.transform.localPosition = visual.transform.InverseTransformPoint(((Component)val4).transform.position); val5.transform.localRotation = Quaternion.Inverse(visual.transform.rotation) * ((Component)val4).transform.rotation; } ParticleSystem[] componentsInChildren3 = val5.GetComponentsInChildren<ParticleSystem>(true); foreach (ParticleSystem obj in componentsInChildren3) { ShapeModule shape = obj.shape; if (((ShapeModule)(ref shape)).enabled && (Object)(object)((ShapeModule)(ref shape)).skinnedMeshRenderer != (Object)null) { ((ShapeModule)(ref shape)).skinnedMeshRenderer = body; } obj.Play(true); } _aura.Add(val5); list.Add(((Object)val4).name + " on " + (text ?? "body")); } DraugrAssets.InfoOnce("aura", (list.Count == 0) ? ("'" + DraugrAssets.PrefabName + "' has no particle effects; no aura.") : string.Format("Draugr aura: {0} effect(s): {1}.", list.Count, string.Join(", ", list))); } private static IEnumerable<string> ChainToRoot(Transform bone) { Transform t = bone; while ((Object)(object)t != (Object)null) { yield return ((Object)t).name; t = t.parent; } } private void Clear() { foreach (GameObject item in _aura) { if ((Object)(object)item != (Object)null) { Object.Destroy((Object)(object)item); } } _aura.Clear(); _emitter = null; _built = false; } private void OnDestroy() { Clear(); } } }