Decompiled source of ForgeVisual v0.1.0
ForgeVisual.dll
Decompiled 2 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Numerics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text; using System.Text.Json; using Agents; using BepInEx; using BepInEx.Configuration; using BepInEx.Unity.IL2CPP; using CharacterDestruction; using Enemies; using FX_EffectSystem; using ForgeCore; using HarmonyLib; using Il2CppInterop.Runtime; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSystem; using Il2CppSystem.Reflection; using Microsoft.CodeAnalysis; using Player; using RootMotion.FinalIK; using SNetwork; using TMPro; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("ForgeVisual")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.0.0")] [assembly: AssemblyInformationalVersion("0.1.0+66ec6b43e1a1603bac84a4b9a226674300b2fc7d")] [assembly: AssemblyProduct("ForgeVisual")] [assembly: AssemblyTitle("ForgeVisual")] [assembly: AssemblyVersion("0.1.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ForgeVisual { public enum BodyBone { Hips = 0, LeftUpperLeg = 1, RightUpperLeg = 2, LeftLowerLeg = 3, RightLowerLeg = 4, LeftFoot = 5, RightFoot = 6, Spine = 7, Chest = 8, Neck = 9, Head = 10, LeftShoulder = 11, RightShoulder = 12, LeftUpperArm = 13, RightUpperArm = 14, LeftLowerArm = 15, RightLowerArm = 16, LeftHand = 17, RightHand = 18, LeftToes = 19, RightToes = 20, UpperChest = 54 } public enum BodyMeasure { ShoulderSpan, LeftLeg, RightLeg, LeftArm, RightArm } public readonly struct WearBone { public string Model { get; } public BodyBone Body { get; } public bool Worn { get; } public BodyMeasure Scale { get; } public WearBone(string model, BodyBone body, bool worn = true, BodyMeasure scale = BodyMeasure.ShoulderSpan) { Model = model ?? throw new ArgumentNullException("model"); Body = body; Worn = worn; Scale = scale; } } public readonly struct PoseLink { public string Model { get; } public BodyBone Body { get; } public BodyBone? BodyAlt { get; } public int Toward { get; } public int From { get; } public BodyBone? TowardBody { get; } public BodyBone? TowardBodyAlt { get; } public PoseLink(string model, BodyBone body, int toward = -1, int from = -1, BodyBone? bodyAlt = null, BodyBone? towardBody = null, BodyBone? towardBodyAlt = null) { Model = model ?? throw new ArgumentNullException("model"); Body = body; Toward = toward; From = from; BodyAlt = bodyAlt; TowardBody = towardBody; TowardBodyAlt = towardBodyAlt; } } public readonly struct PoseReach { public int Upper { get; } public int Lower { get; } public int End { get; } public int Anchor { get; } public PoseReach(int upper, int lower, int end, int anchor) { Upper = upper; Lower = lower; End = end; Anchor = anchor; } } internal readonly struct RestPose { internal Vector3 Position { get; } internal Quaternion Rotation { get; } internal float Scale { get; } internal RestPose(Vector3 position, Quaternion rotation, float scale = 1f) { Position = position; Rotation = rotation; Scale = scale; } } internal struct Weights4 { internal int I0 { get; set; } internal int I1 { get; set; } internal int I2 { get; set; } internal int I3 { get; set; } internal float W0 { get; set; } internal float W1 { get; set; } internal float W2 { get; set; } internal float W3 { get; set; } } internal static class BodyMath { internal static Quaternion LookRotation(Vector3 forward, Vector3 up) { if (forward.LengthSquared() < 1E-12f) { return Quaternion.Identity; } Vector3 vector = Vector3.Normalize(forward); Vector3 value = Vector3.Cross(up, vector); if (value.LengthSquared() < 1E-12f) { value = Vector3.Cross((Math.Abs(vector.Y) < 0.99f) ? Vector3.UnitY : Vector3.UnitX, vector); } value = Vector3.Normalize(value); Vector3 vector2 = Vector3.Cross(vector, value); return Quaternion.Normalize(Quaternion.CreateFromRotationMatrix(new Matrix4x4(value.X, value.Y, value.Z, 0f, vector2.X, vector2.Y, vector2.Z, 0f, vector.X, vector.Y, vector.Z, 0f, 0f, 0f, 0f, 1f))); } internal static Quaternion FromTo(Vector3 from, Vector3 to) { if (from.LengthSquared() < 1E-12f || to.LengthSquared() < 1E-12f) { return Quaternion.Identity; } Vector3 vector = Vector3.Normalize(from); Vector3 vector2 = Vector3.Normalize(to); float num = Vector3.Dot(vector, vector2); if (num >= 0.999999f) { return Quaternion.Identity; } if (num <= -0.999999f) { Vector3 value = Vector3.Cross(Vector3.UnitX, vector); if (value.LengthSquared() < 1E-06f) { value = Vector3.Cross(Vector3.UnitY, vector); } return Quaternion.CreateFromAxisAngle(Vector3.Normalize(value), (float)Math.PI); } return Quaternion.Normalize(new Quaternion(Vector3.Cross(vector, vector2), 1f + num)); } internal static Vector3 Rotate(Quaternion q, Vector3 v) { return Vector3.Transform(v, q); } internal static Quaternion SkeletonFrame(Vector3 leftArm, Vector3 rightArm, Vector3 hips) { Vector3 vector = Vector3.Normalize(rightArm - leftArm); Vector3 vector2 = (leftArm + rightArm) * 0.5f - hips; Vector3 vector3 = Vector3.Normalize(Vector3.Cross(vector, vector2)); vector2 = Vector3.Cross(vector3, vector); return LookRotation(vector3, vector2); } internal static Quaternion BoneFrame(Vector3 along) { if (along.LengthSquared() < 1E-08f) { return Quaternion.Identity; } along = Vector3.Normalize(along); return LookRotation(along, (Math.Abs(Vector3.Dot(along, Vector3.UnitZ)) > 0.8f) ? Vector3.UnitY : Vector3.UnitZ); } } internal static class WearSolver { internal static int[] Children(int[] parents) { int[] array = new int[parents.Length]; for (int i = 0; i < array.Length; i++) { array[i] = -1; } for (int j = 0; j < parents.Length; j++) { int num = parents[j]; if (num >= 0) { array[num] = ((array[num] == -1) ? j : (-2)); } } for (int k = 0; k < array.Length; k++) { if (array[k] == -2) { array[k] = -1; } } return array; } internal static string? Solve(IReadOnlyList<WearBone> bones, int[] parents, RestPose[] model, RestPose?[] game, out Quaternion[] offset, out float[] scale) { int count = bones.Count; offset = new Quaternion[count]; scale = new float[count]; for (int i = 0; i < count; i++) { offset[i] = Quaternion.Identity; scale[i] = 1f; } int num = IndexOf(bones, BodyBone.LeftUpperArm); int num2 = IndexOf(bones, BodyBone.RightUpperArm); int num3 = IndexOf(bones, BodyBone.Hips); if (num < 0 || num2 < 0 || num3 < 0 || !game[num].HasValue || !game[num2].HasValue || !game[num3].HasValue) { return "the bones must list LeftUpperArm, RightUpperArm and Hips, each on the game's body, to match the skeletons"; } Quaternion value = BodyMath.SkeletonFrame(model[num].Position, model[num2].Position, model[num3].Position); Quaternion quaternion = BodyMath.SkeletonFrame(game[num].Value.Position, game[num2].Value.Position, game[num3].Value.Position) * Quaternion.Inverse(value); float span = (game[num2].Value.Position - game[num].Value.Position).Length() / Math.Max(0.0001f, (model[num2].Position - model[num].Position).Length()); int[] array = Children(parents); for (int j = 0; j < count; j++) { RestPose? restPose = game[j]; if (!restPose.HasValue) { continue; } RestPose valueOrDefault = restPose.GetValueOrDefault(); if (!bones[j].Worn) { continue; } scale[j] = Measure(bones, model, game, bones[j].Scale, span); Vector3 v = Vector3.Zero; Vector3 to = Vector3.Zero; if (array[j] >= 0) { restPose = game[array[j]]; if (restPose.HasValue) { RestPose valueOrDefault2 = restPose.GetValueOrDefault(); v = model[array[j]].Position - model[j].Position; to = valueOrDefault2.Position - valueOrDefault.Position; goto IL_02b4; } } if (parents[j] >= 0) { restPose = game[parents[j]]; if (restPose.HasValue) { RestPose valueOrDefault3 = restPose.GetValueOrDefault(); v = model[j].Position - model[parents[j]].Position; to = valueOrDefault.Position - valueOrDefault3.Position; } } goto IL_02b4; IL_02b4: Quaternion quaternion2 = quaternion * model[j].Rotation; if (v.LengthSquared() > 1E-08f && to.LengthSquared() > 1E-08f) { quaternion2 = BodyMath.FromTo(BodyMath.Rotate(quaternion, v), to) * quaternion2; } offset[j] = Quaternion.Inverse(valueOrDefault.Rotation) * quaternion2; } return null; } internal static float Measure(IReadOnlyList<WearBone> bones, RestPose[] model, RestPose?[] game, BodyMeasure measure, float span) { return measure switch { BodyMeasure.LeftLeg => Chain(bones, model, game, span, BodyBone.LeftUpperLeg, BodyBone.LeftLowerLeg, BodyBone.LeftFoot), BodyMeasure.RightLeg => Chain(bones, model, game, span, BodyBone.RightUpperLeg, BodyBone.RightLowerLeg, BodyBone.RightFoot), BodyMeasure.LeftArm => Chain(bones, model, game, span, BodyBone.LeftUpperArm, BodyBone.LeftLowerArm, BodyBone.LeftHand), BodyMeasure.RightArm => Chain(bones, model, game, span, BodyBone.RightUpperArm, BodyBone.RightLowerArm, BodyBone.RightHand), _ => span, }; } private static float Chain(IReadOnlyList<WearBone> bones, RestPose[] model, RestPose?[] game, float fallback, BodyBone a, BodyBone b, BodyBone c) { int num = IndexOf(bones, a); int num2 = IndexOf(bones, b); int num3 = IndexOf(bones, c); if (num >= 0 && num2 >= 0 && num3 >= 0) { RestPose? restPose = game[num]; if (restPose.HasValue) { RestPose valueOrDefault = restPose.GetValueOrDefault(); restPose = game[num2]; if (restPose.HasValue) { RestPose valueOrDefault2 = restPose.GetValueOrDefault(); restPose = game[num3]; if (restPose.HasValue) { RestPose valueOrDefault3 = restPose.GetValueOrDefault(); float num4 = (model[num2].Position - model[num].Position).Length() + (model[num3].Position - model[num2].Position).Length(); float num5 = (valueOrDefault2.Position - valueOrDefault.Position).Length() + (valueOrDefault3.Position - valueOrDefault2.Position).Length(); if (!(num4 > 0.0001f)) { return fallback; } return num5 / num4; } } } } return fallback; } internal static float LocalScale(float scale, float bodyScale, float modelRestScale, float gameBoneScale) { return scale * bodyScale * modelRestScale / ((Math.Abs(gameBoneScale) > 1E-06f) ? gameBoneScale : 1f); } internal static int IndexOf(IReadOnlyList<WearBone> bones, BodyBone body) { for (int i = 0; i < bones.Count; i++) { if (bones[i].Body == body) { return i; } } return -1; } } internal static class PoseSolver { internal static string? Validate(IReadOnlyList<PoseLink> links) { if (links == null || links.Count == 0) { return "no links"; } for (int i = 0; i < links.Count; i++) { PoseLink poseLink = links[i]; if (string.IsNullOrEmpty(poseLink.Model)) { return "link " + i + " names no model bone"; } if (poseLink.Toward >= 0 && poseLink.From >= 0) { return "link " + i + " (" + poseLink.Model + ") has both a toward and a from"; } if (poseLink.Toward == i || poseLink.From == i) { return "link " + i + " (" + poseLink.Model + ") points at itself"; } if (poseLink.Toward >= links.Count || poseLink.From >= links.Count || poseLink.Toward < -1 || poseLink.From < -1) { return "link " + i + " (" + poseLink.Model + ") points outside the " + links.Count + " links"; } for (int j = 0; j < i; j++) { if (links[j].Model == poseLink.Model) { return "model bone " + poseLink.Model + " is listed twice"; } } } return null; } internal static Quaternion[] Unframe(IReadOnlyList<PoseLink> links, Vector3[] position, Quaternion[] rotation) { Quaternion[] array = new Quaternion[links.Count]; for (int i = 0; i < links.Count; i++) { PoseLink poseLink = links[i]; Vector3 along = ((poseLink.Toward >= 0) ? (position[poseLink.Toward] - position[i]) : ((poseLink.From >= 0) ? (position[i] - position[poseLink.From]) : Vector3.Zero)); array[i] = Quaternion.Inverse(BodyMath.BoneFrame(along)) * rotation[i]; } return array; } internal static Quaternion[] Correct(IReadOnlyList<PoseLink> links, Vector3[] position, Quaternion[] rotation, Vector3?[] toward, Quaternion[] unframe) { Quaternion[] array = new Quaternion[links.Count]; for (int i = 0; i < links.Count; i++) { PoseLink poseLink = links[i]; Vector3 along = Vector3.Zero; if (poseLink.Toward >= 0) { along = (toward[i] ?? position[poseLink.Toward]) - position[i]; } else if (poseLink.From >= 0) { along = position[i] - position[poseLink.From]; } array[i] = Quaternion.Inverse(rotation[i]) * BodyMath.BoneFrame(along) * unframe[i]; } return array; } internal static string? Ratio(float modelRootHeight, float bodyRootHeight, out float ratio) { ratio = 1f; if (bodyRootHeight < 0.1f || modelRootHeight < 0.1f) { return "the root (hips) stands at " + bodyRootHeight.ToString("0.###") + " m on the body and " + modelRootHeight.ToString("0.###") + " m on the model"; } ratio = modelRootHeight / bodyRootHeight; return null; } internal static string? ValidateReach(IReadOnlyList<PoseReach> reaches, int count) { for (int i = 0; i < reaches.Count; i++) { PoseReach poseReach = reaches[i]; if (poseReach.Upper < 0 || poseReach.Lower < 0 || poseReach.End < 0 || poseReach.Anchor < 0 || poseReach.Upper >= count || poseReach.Lower >= count || poseReach.End >= count || poseReach.Anchor >= count) { return "reach " + i + " points outside the " + count + " links"; } if (poseReach.Upper == poseReach.Lower || poseReach.Lower == poseReach.End || poseReach.Upper == poseReach.End) { return "reach " + i + " needs three different links"; } } return null; } internal static Vector3 Elbow(Vector3 root, Vector3 target, float upper, float lower, Vector3 bend, out Vector3 end) { Vector3 vector = target - root; float num = vector.Length(); Vector3 vector2 = ((num > 1E-05f) ? (vector / num) : Vector3.UnitY); float num2 = Math.Clamp(num, Math.Abs(upper - lower) + 0.0001f, upper + lower - 0.0001f); end = root + vector2 * num2; Vector3 value = bend - vector2 * Vector3.Dot(bend, vector2); if (value.LengthSquared() < 1E-10f) { value = Vector3.Cross(vector2, (Math.Abs(vector2.Y) < 0.99f) ? Vector3.UnitY : Vector3.UnitX); } float num3 = (upper * upper + num2 * num2 - lower * lower) / (2f * num2); float num4 = MathF.Sqrt(Math.Max(0f, upper * upper - num3 * num3)); return root + vector2 * num3 + Vector3.Normalize(value) * num4; } internal static Vector3 Root(Vector3 modelRootRest, Vector3 bodyRoot, Vector3 bodyRootRest, float ratio) { return modelRootRest + (bodyRoot - bodyRootRest) * ratio; } } internal static class HeldPlacement { internal static Vector3 Position(Quaternion turn, Vector3 source, Vector3 bodyHand, Vector3 modelHand, float scale) { return modelHand + BodyMath.Rotate(turn, source - bodyHand) * scale; } } internal static class MeshCut { internal static bool[] KeepVertices(Weights4[] weights, bool[] kept) { bool[] array = new bool[weights.Length]; for (int i = 0; i < weights.Length; i++) { Weights4 weights2 = weights[i]; float num = K(weights2.I0, weights2.W0); float num2 = K(weights2.I1, weights2.W1); float num3 = K(weights2.I2, weights2.W2); float num4 = K(weights2.I3, weights2.W3); float num5 = num + num2 + num3 + num4; if (!(num5 < 0.5f)) { array[i] = true; weights2.W0 = num / num5; weights2.W1 = num2 / num5; weights2.W2 = num3 / num5; weights2.W3 = num4 / num5; weights[i] = weights2; } } return array; float K(int index, float weight) { if (index < 0 || index >= kept.Length || !kept[index]) { return 0f; } return weight; } } internal static int[] KeepTriangles(int[] triangles, bool[] keep) { List<int> list = new List<int>(triangles.Length / 4); for (int i = 0; i + 2 < triangles.Length; i += 3) { int num = triangles[i]; int num2 = triangles[i + 1]; int num3 = triangles[i + 2]; if (keep[num] && keep[num2] && keep[num3]) { list.Add(num); list.Add(num2); list.Add(num3); } } return list.ToArray(); } } internal static class Overdraw { internal const float ScreenBudget = 5f; internal const float MaxShed = 0.85f; private const float MinDistance = 0.3f; private const float Aspect = 1.7777778f; private const float FadeBand = 0.15f; internal static float Coverage(float size, float distance, float tanHalfFov) { float num = 2f * Math.Max(distance, 0.3f) * Math.Max(tanHalfFov, 0.01f); float num2 = size * size / (num * num * 1.7777778f); if (!(num2 > 1f)) { return num2; } return 1f; } internal static float Shed(float total, float sheddable, float budget) { if (total <= budget || sheddable <= 0f) { return 0f; } return Math.Min(0.85f, (total - budget) / sheddable); } internal static float Fade(float cut, float shed) { if (shed <= 0f) { return 1f; } float num = (cut - shed) / 0.15f; if (!(num <= 0f)) { if (!(num >= 1f)) { return num; } return 1f; } return 0f; } } internal sealed class FxRandom { private uint _state; internal FxRandom(uint seed) { _state = ((seed == 0) ? 2654435769u : seed); } internal float Next() { _state ^= _state << 13; _state ^= _state >> 17; _state ^= _state << 5; return (float)(_state >> 8) * 5.9604645E-08f; } internal float Range(float low, float high) { return low + (high - low) * Next(); } } internal struct RateDebt { private float _debt; internal int Take(float perSecond, float seconds) { if (perSecond <= 0f || seconds <= 0f) { return 0; } _debt += perSecond * seconds; int num = (int)_debt; _debt -= num; return num; } internal void Reset() { _debt = 0f; } } internal static class ForgeCatalog { internal const string SoftDot = "soft-dot"; internal const string SoftLine = "soft-line"; internal static readonly (string Item, string Summary)[] Sprites = new(string, string)[2] { ("soft-dot", "A round soft-edged dot: glows, sparks, smoke puffs and light spots; tinted and sized per use."), ("soft-line", "A soft-edged streak across its length: tracers, beams and trails; tinted and sized per use.") }; } internal readonly record struct ForgeEffectSpec(string Item, bool Line, float DefaultSize, float HoldSeconds, float HoldReach); internal static class ForgeEffects { internal static readonly IReadOnlyList<ForgeEffectSpec> All = new ForgeEffectSpec[11] { new ForgeEffectSpec("forge_energy_beam", Line: true, float.NaN, 0.12f, 1.5f), new ForgeEffectSpec("forge_lightning_arc", Line: true, float.NaN, 0f, 0f), new ForgeEffectSpec("forge_blast_tracer", Line: true, float.NaN, 0f, 0f), new ForgeEffectSpec("forge_plasma_discharge", Line: true, float.NaN, 0f, 0f), new ForgeEffectSpec("forge_plasma_orb", Line: false, 0.3f, 0.25f, 1.5f), new ForgeEffectSpec("forge_plasma_explosion", Line: false, 3f, 0f, 0f), new ForgeEffectSpec("forge_explosion", Line: false, 2.2f, 0f, 0f), new ForgeEffectSpec("forge_flame", Line: false, 8f, 0.12f, 1.5f), new ForgeEffectSpec("forge_flame_impact", Line: false, float.NaN, 0f, 0f), new ForgeEffectSpec("forge_sparks", Line: false, float.NaN, 0f, 0f), new ForgeEffectSpec("forge_black_hole", Line: false, 8f, 0.5f, 2f) }; } internal enum GameSource : byte { PreloadedPool, ResourcePrefab, MuzzleFlash } internal sealed record GameEffect(string Item, GameSource Source, string Native, string? AssetPath, bool Line) { internal string Name => VisualNames.Join("Game", Item); [CompilerGenerated] private bool PrintMembers(StringBuilder builder) { RuntimeHelpers.EnsureSufficientExecutionStack(); builder.Append("Item = "); builder.Append((object?)Item); builder.Append(", Source = "); builder.Append(Source.ToString()); builder.Append(", Native = "); builder.Append((object?)Native); builder.Append(", AssetPath = "); builder.Append((object?)AssetPath); builder.Append(", Line = "); builder.Append(Line.ToString()); return true; } } internal static class GameCatalog { private const string FxEffects = "Assets/AssetPrefabs/FX_Effects/"; private const string Muzzle = "Assets/AssetPrefabs/Effects/Weapon/MuzzleFlash/"; internal static readonly IReadOnlyList<GameEffect> All = new GameEffect[28] { Pooled("FX_Tripmine", "Assets/AssetPrefabs/FX_Effects/FX_Tripmine.prefab"), Pooled("FX_TripmineGlue", "Assets/AssetPrefabs/FX_Effects/FX_TripmineGlue.prefab"), Pooled("FX_Tracer", "Assets/AssetPrefabs/FX_Effects/FX_Tracer.prefab")with { Line = true }, Pooled("FX_BulletImpact_Concrete"), Pooled("FX_BulletImpact_Metal"), Pooled("FX_BulletImpact_SheetMetal"), Pooled("FX_BulletImpact_Glass"), Pooled("FX_BulletImpact_Wood"), Pooled("FX_BulletImpact_Plastic"), Pooled("FX_BulletImpact_Mud"), Pooled("FX_BulletImpact_Gravel"), Pooled("FX_3D Blood Impact"), Pooled("FXC_MeshBloodBomb"), Pooled("FX_TorchCutting"), Pooled("FX_ElevatorSparks"), Pooled("FX_LockMelter"), Pooled("FX_InfectionSpit"), Resource("fxc_flyerdeath"), Resource("fxc_flyerbigdeath"), Resource("fx_flyer_teleport"), Resource("fx_flyer_big_teleport"), Resource("fxc_fleshbulb_pop"), Resource("fxc_fleshbulb_pop_boss"), Flash("AssaultRifle_MuzzleFlash_3RD"), Flash("Pistol_MuzzleFlash_3RD"), Flash("Shotgun_MuzzleFlash_3RD"), Flash("SubMachine_MuzzleFlash_3RD"), Flash("Sentrygun_MuzzleFlash_3RD") }; private static readonly Dictionary<string, GameEffect> ByName = Index(); internal static bool TryGet(string? name, out GameEffect effect) { effect = null; if (name != null) { return ByName.TryGetValue(name, out effect); } return false; } private static Dictionary<string, GameEffect> Index() { Dictionary<string, GameEffect> dictionary = new Dictionary<string, GameEffect>(StringComparer.Ordinal); foreach (GameEffect item in All) { string text = VisualNames.CheckItem(item.Item); if (text != null) { throw new InvalidOperationException("Game catalog entry " + item.Native + ": " + text); } if (!dictionary.TryAdd(item.Name, item)) { throw new InvalidOperationException("Game catalog lists " + item.Name + " twice."); } } return dictionary; } private static string Item(string native) { return native.Replace(' ', '_'); } private static GameEffect Pooled(string prefab, string? path = null) { return new GameEffect(Item(prefab), GameSource.PreloadedPool, prefab, path, Line: false); } private static GameEffect Resource(string path) { return new GameEffect(Item(path), GameSource.ResourcePrefab, path, null, Line: false); } private static GameEffect Flash(string stem) { return new GameEffect(Item(stem), GameSource.MuzzleFlash, "Assets/AssetPrefabs/Effects/Weapon/MuzzleFlash/" + stem + ".prefab", "Assets/AssetPrefabs/Effects/Weapon/MuzzleFlash/" + stem + ".prefab", Line: false); } } internal static class GunFit { internal const float MinSpan = 0.05f; internal static (float Scale, Vector3 Move)? Solve(Vector3 nativeRight, Vector3 nativeLeft, Vector3? nativeMuzzle, Vector3 modelRight, Vector3 modelLeft, Vector3? modelMuzzle, float minScale, float maxScale, Vector3? nativeSight = null, Vector3? modelSight = null) { float num3; float z; float num4; if (Finite(nativeRight) && Finite(nativeLeft) && Finite(modelRight) && Finite(modelLeft)) { if (nativeMuzzle.HasValue) { Vector3 valueOrDefault = nativeMuzzle.GetValueOrDefault(); if (!Finite(valueOrDefault)) { goto IL_009a; } } if (modelMuzzle.HasValue) { Vector3 valueOrDefault2 = modelMuzzle.GetValueOrDefault(); if (!Finite(valueOrDefault2)) { goto IL_009a; } } if (nativeSight.HasValue) { Vector3 valueOrDefault3 = nativeSight.GetValueOrDefault(); if (!Finite(valueOrDefault3)) { goto IL_009a; } } if (modelSight.HasValue) { Vector3 valueOrDefault4 = modelSight.GetValueOrDefault(); if (!Finite(valueOrDefault4)) { goto IL_009a; } } if (minScale > 0f && maxScale >= minScale) { float num = nativeLeft.Z - nativeRight.Z; float num2 = modelLeft.Z - modelRight.Z; num3 = ((num >= 0.05f && num2 >= 0.05f) ? Math.Clamp(num / num2, minScale, maxScale) : 1f); z = nativeRight.Z - num3 * modelRight.Z; if (nativeSight.HasValue) { Vector3 valueOrDefault5 = nativeSight.GetValueOrDefault(); if (modelSight.HasValue) { Vector3 valueOrDefault6 = modelSight.GetValueOrDefault(); num4 = valueOrDefault5.Y - num3 * valueOrDefault6.Y; goto IL_0161; } } num4 = (nativeRight.Y - num3 * modelRight.Y + (nativeLeft.Y - num3 * modelLeft.Y)) * 0.5f; goto IL_0161; } } goto IL_009a; IL_0161: float y = num4; float num5; if (nativeMuzzle.HasValue) { Vector3 valueOrDefault7 = nativeMuzzle.GetValueOrDefault(); if (modelMuzzle.HasValue) { Vector3 valueOrDefault8 = modelMuzzle.GetValueOrDefault(); num5 = valueOrDefault7.X - num3 * valueOrDefault8.X; goto IL_01ad; } } num5 = nativeRight.X - num3 * modelRight.X; goto IL_01ad; IL_009a: return null; IL_01ad: float x = num5; return (num3, new Vector3(x, y, z)); } private static bool Finite(Vector3 v) { if (float.IsFinite(v.X) && float.IsFinite(v.Y)) { return float.IsFinite(v.Z); } return false; } } internal sealed class ModelProfile { internal sealed class Surface { public string key { get; set; } = ""; public string albedo { get; set; } = ""; public string metallic { get; set; } = ""; public string normal { get; set; } = ""; public string emission { get; set; } = ""; public float[] emissionColor { get; set; } = Array.Empty<float>(); internal bool Emissive { get { if (emission.Length != 0) { return emissionColor.Length == 3; } return false; } } } internal sealed class RendererEntry { public string name { get; set; } = ""; public string[] surfaces { get; set; } = Array.Empty<string>(); } internal sealed class Prefab { public string name { get; set; } = ""; public RendererEntry[] renderers { get; set; } = Array.Empty<RendererEntry>(); public string[] anchors { get; set; } = Array.Empty<string>(); } private sealed class Document { public int format { get; set; } public Prefab[] prefabs { get; set; } = Array.Empty<Prefab>(); public Surface[] surfaces { get; set; } = Array.Empty<Surface>(); public string[] textures { get; set; } = Array.Empty<string>(); } internal const string AssetName = "ordnance-profile"; internal const int Format = 1; internal IReadOnlyList<Prefab> Prefabs { get; } internal IReadOnlyList<Surface> Surfaces { get; } internal IReadOnlyList<string> Textures { get; } private ModelProfile(Document d) { Prefabs = d.prefabs; Surfaces = d.surfaces; Textures = d.textures; } internal static ModelProfile? Read(string json, out string? why) { why = null; Document document; try { document = JsonSerializer.Deserialize<Document>(json); } catch (JsonException ex) { why = "the profile is not valid JSON: " + ex.Message; return null; } if (document == null) { why = "the profile is empty"; return null; } if (document.format != 1) { why = "profile format " + document.format + " is not " + 1 + "; rebuild the bundle"; return null; } HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal); Surface[] surfaces = document.surfaces; foreach (Surface surface in surfaces) { if (surface == null || surface.key.Length == 0) { why = "a surface has no key"; return null; } if (!hashSet.Add(surface.key)) { why = "surface " + surface.key + " is listed twice"; return null; } if (surface.albedo.Length == 0 || surface.metallic.Length == 0) { why = "surface " + surface.key + " lacks its albedo or metallic map"; return null; } } HashSet<string> hashSet2 = new HashSet<string>(StringComparer.Ordinal); Prefab[] prefabs = document.prefabs; string[] surfaces2; foreach (Prefab prefab in prefabs) { if (prefab == null || prefab.name.Length == 0) { why = "a prefab has no name"; return null; } string text = VisualNames.CheckItem(prefab.name); if (text != null) { why = text; return null; } if (!hashSet2.Add(prefab.name)) { why = "prefab " + prefab.name + " is listed twice"; return null; } RendererEntry[] renderers = prefab.renderers; foreach (RendererEntry rendererEntry in renderers) { surfaces2 = rendererEntry.surfaces; foreach (string text2 in surfaces2) { if (!hashSet.Contains(text2)) { why = "prefab " + prefab.name + " renderer " + rendererEntry.name + " names the unknown surface " + text2; return null; } } } } HashSet<string> hashSet3 = new HashSet<string>(StringComparer.Ordinal); surfaces2 = document.textures; foreach (string text3 in surfaces2) { string text4 = VisualNames.CheckItem(text3); if (text4 != null) { why = text4; return null; } if (!hashSet3.Add(text3)) { why = "texture " + text3 + " is listed twice"; return null; } } return new ModelProfile(document); } } internal static class VisualNames { internal const string Game = "Game"; internal const string Forge = "Forge"; internal static string? CheckPack(string? pack, bool builtIn = false) { if (string.IsNullOrEmpty(pack)) { return "the pack name is empty"; } foreach (char c in pack) { if (!IsNameChar(c) || c == '.') { return "the pack name '" + pack + "' may only hold letters, digits, '_' and '-'"; } } if (string.Equals(pack, "Game", StringComparison.OrdinalIgnoreCase)) { return "'Game' is the game's own catalog"; } if (!builtIn && string.Equals(pack, "Forge", StringComparison.OrdinalIgnoreCase)) { return "'Forge' is this library's own namespace"; } return null; } internal static string? CheckItem(string? item) { if (string.IsNullOrEmpty(item)) { return "the item name is empty"; } for (int i = 0; i < item.Length; i++) { if (!IsNameChar(item[i])) { return "the item name '" + item + "' may only hold letters, digits, '_', '-' and '.'"; } } return null; } internal static string Join(string pack, string item) { return pack + ":" + item; } internal static bool TrySplit(string? name, out string pack, out string item, out string? why) { pack = (item = ""); why = null; if (string.IsNullOrEmpty(name)) { why = "the name is empty"; return false; } int num = name.IndexOf(':'); if (num <= 0 || num == name.Length - 1 || name.IndexOf(':', num + 1) >= 0) { why = "'" + name + "' is not Pack:item"; return false; } pack = name.Substring(0, num); item = name.Substring(num + 1); why = CheckItem(item); string text = pack; foreach (char c in text) { if ((!IsNameChar(c) || c == '.') && why == null) { why = "the pack name '" + pack + "' may only hold letters, digits, '_' and '-'"; } } return why == null; } private static bool IsNameChar(char c) { switch (c) { case '-': case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': case '_': case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': return true; default: return false; } } } internal sealed class NameTable<T> where T : class { private readonly Dictionary<string, T> _byName = new Dictionary<string, T>(StringComparer.Ordinal); private readonly List<string> _names = new List<string>(); internal int Count => _byName.Count; internal IReadOnlyList<string> Names => _names; internal string? Add(string name, T value) { if (!VisualNames.TrySplit(name, out string _, out string _, out string why)) { return why; } if (_byName.ContainsKey(name)) { return "'" + name + "' is already registered"; } _byName.Add(name, value); _names.Add(name); return null; } internal bool TryGet(string? name, out T value) { value = null; if (name != null) { return _byName.TryGetValue(name, out value); } return false; } internal bool Remove(string name) { if (!_byName.Remove(name)) { return false; } _names.Remove(name); return true; } } internal static class Missing { internal static string Why(string? name, Func<string, bool> packKnown, string kind) { if (!VisualNames.TrySplit(name, out string pack, out string _, out string why)) { return why; } if (!packKnown(pack)) { return "no pack " + pack + " is registered (is the mod that owns it installed?)"; } return "pack " + pack + " has no " + kind + " '" + name + "'"; } } public readonly struct OutlineColor : IEquatable<OutlineColor> { public float R { get; } public float G { get; } public float B { get; } public float A { get; } internal bool Valid { get { if (float.IsFinite(R) && float.IsFinite(G) && float.IsFinite(B) && R >= 0f && G >= 0f && B >= 0f) { float a = A; if (a >= 0f) { return a <= 1f; } return false; } return false; } } public OutlineColor(float r, float g, float b, float a = 1f) { R = r; G = g; B = b; A = a; } public bool Equals(OutlineColor other) { if (R == other.R && G == other.G && B == other.B) { return A == other.A; } return false; } public override bool Equals(object? obj) { if (obj is OutlineColor other) { return Equals(other); } return false; } public override int GetHashCode() { return HashCode.Combine(R, G, B, A); } } public sealed class EnemyOutlineStyle { public const int MaxEnemiesLimit = 128; public const float RangeLimit = 500f; public const float WidthLimit = 16f; public float Range { get; init; } = 35f; public float FadeDistance { get; init; } = 5f; public int MaxEnemies { get; init; } = 24; public float Width { get; init; } = 1.6f; public OutlineColor Sleeping { get; init; } = new OutlineColor(0.23f, 0.4f, 0.44f, 0.4f); public OutlineColor Awake { get; init; } = new OutlineColor(0.8f, 0.56f, 0.22f, 0.65f); public OutlineColor Hunting { get; init; } = new OutlineColor(0.8f, 0.18f, 0.18f, 0.8f); public bool XRay { get; init; } public int Priority { get; init; } public OutlineColor ColorOf(EnemyAlert state) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected I4, but got Unknown return (state - 1) switch { 0 => Sleeping, 1 => Awake, 2 => Hunting, _ => default(OutlineColor), }; } public string? Problem() { if (!float.IsFinite(Range) || Range <= 0f || Range > 500f) { return "Range must be above 0 and at most " + 500f + " metres"; } if (!float.IsFinite(FadeDistance) || FadeDistance < 0f || FadeDistance > Range) { return "FadeDistance must be between 0 and Range"; } if (MaxEnemies < 1 || MaxEnemies > 128) { return "MaxEnemies must be between 1 and " + 128; } if (!float.IsFinite(Width) || Width <= 0f || Width > 16f) { return "Width must be above 0 and at most " + 16f + " pixels"; } if (!Sleeping.Valid || !Awake.Valid || !Hunting.Valid) { return "colours must be finite, not negative, with alpha 0..1"; } return null; } } public static class OutlineRules { public const float DefaultWidth = 1.6f; public const float NearAlways = 3f; public const float ViewCosine = -0.1f; public const int RefreshPerFrame = 24; public const int LimbSettleFrames = 45; public const float WakeSeconds = 6f; public const float WakeScanSeconds = 0.25f; public const float Unlimited = 1000000f; public static float PixelWidth(float width1080, int screenHeight) { return width1080 * (float)Math.Max(1, screenHeight) / 1080f; } public static bool WakeScanDue(float now, float wakeUntil, float nextScan) { if (now < wakeUntil) { return now >= nextScan; } return false; } public static float Until(float now, float seconds) { if (!(seconds > 0f)) { return float.PositiveInfinity; } return now + seconds; } public static string? Problem(OutlineColor color, float seconds) { if (!color.Valid) { return "the colour must be finite, not negative, with alpha 0..1"; } if (!float.IsFinite(seconds) || seconds < 0f) { return "seconds must be 0 (until removed) or more"; } return null; } } public static class OutlineCuts { public const int Max = 4; public static bool Removes(ReadOnlySpan<float> matrices, ReadOnlySpan<float> inverts, int count, float x, float y, float z) { float num = 0f; for (int i = 0; i < Math.Min(count, 4); i++) { ReadOnlySpan<float> readOnlySpan = matrices.Slice(16 * i, 16); float num2 = readOnlySpan[0] * x + readOnlySpan[1] * y + readOnlySpan[2] * z + readOnlySpan[3]; float num3 = readOnlySpan[4] * x + readOnlySpan[5] * y + readOnlySpan[6] * z + readOnlySpan[7]; float num4 = readOnlySpan[8] * x + readOnlySpan[9] * y + readOnlySpan[10] * z + readOnlySpan[11]; float num5 = Math.Min(MathF.Sqrt(num2 * num2 + num3 * num3 + num4 * num4), 1f); num = Math.Max(num, (inverts[i] != 0f) ? num5 : (1f - num5)); } return num > 0.5f; } } public static class OutlineDrawSet { public static int Collect<T>(IEnumerable<T> candidates, Func<T, bool> drawn, int max, List<T> into) { into.Clear(); int num = 0; foreach (T candidate in candidates) { if (!drawn(candidate)) { num++; } else if (into.Count < max) { into.Add(candidate); } } return num; } } public sealed class OutlineClaims { private long[] _key = new long[16]; private long[] _stamp = new long[16]; private int[] _priority = new int[16]; private int[] _generation = new int[16]; private float[] _until = new float[16]; private bool[] _used = new bool[16]; private int _high; private int _live; private long _clock; public int Capacity => _high; public int Count => _live; public bool Live(int slot) { if (slot >= 0 && slot < _high) { return _used[slot]; } return false; } public long Key(int slot) { return _key[slot]; } public int Priority(int slot) { return _priority[slot]; } public int Generation(int slot) { if (slot < 0 || slot >= _high) { return 0; } return _generation[slot]; } public int Add(long key, int priority, float until) { int num = -1; for (int i = 0; i < _high; i++) { if (!_used[i]) { num = i; break; } } if (num < 0) { if (_high == _used.Length) { Grow(); } num = _high++; } _used[num] = true; _key[num] = key; _priority[num] = priority; _until[num] = until; _stamp[num] = ++_clock; _live++; return num; } public bool Remove(int slot, int generation) { if (!Live(slot) || _generation[slot] != generation) { return false; } Free(slot); return true; } public bool Expire(float now) { bool result = false; for (int i = 0; i < _high; i++) { if (_used[i] && now >= _until[i]) { Free(i); result = true; } } return result; } public int Winner(long key) { int num = -1; for (int i = 0; i < _high; i++) { if (_used[i] && _key[i] == key && (num < 0 || _priority[i] > _priority[num] || (_priority[i] == _priority[num] && _stamp[i] > _stamp[num]))) { num = i; } } return num; } public bool Overrides(long key, int priority) { int num = Winner(key); if (num >= 0) { return _priority[num] >= priority; } return false; } public void Clear() { for (int i = 0; i < _high; i++) { if (_used[i]) { Free(i); } } } private void Free(int slot) { _used[slot] = false; _generation[slot]++; _live--; } private void Grow() { int newSize = _used.Length * 2; Array.Resize(ref _key, newSize); Array.Resize(ref _stamp, newSize); Array.Resize(ref _priority, newSize); Array.Resize(ref _generation, newSize); Array.Resize(ref _until, newSize); Array.Resize(ref _used, newSize); } } public sealed class EnemyOutlineTracker { private bool[] _used = new bool[64]; private int[] _generation = new int[64]; private float[] _x = new float[64]; private float[] _y = new float[64]; private float[] _z = new float[64]; private EnemyAlert[] _state = (EnemyAlert[])(object)new EnemyAlert[64]; private int _high; private int _cursor; private int[] _selSlot = new int[128]; private int[] _selGen = new int[128]; private EnemyAlert[] _selState = (EnemyAlert[])(object)new EnemyAlert[128]; private readonly int[] _newSlot = new int[128]; private readonly float[] _newDist = new float[128]; private int[] _nextSlot = new int[128]; private int[] _nextGen = new int[128]; private EnemyAlert[] _nextState = (EnemyAlert[])(object)new EnemyAlert[128]; public int Capacity => _high; public int SelectedCount { get; private set; } public bool Used(int slot) { if (slot >= 0 && slot < _high) { return _used[slot]; } return false; } public int Generation(int slot) { if (!Used(slot)) { return 0; } return _generation[slot]; } public EnemyAlert State(int slot) { if (Used(slot)) { return _state[slot]; } return (EnemyAlert)0; } public int NextSlot(int slotCount) { if (slotCount <= 0) { return -1; } if (_cursor >= slotCount) { _cursor = 0; } return _cursor++; } public void Set(int slot, int generation, float x, float y, float z, EnemyAlert state) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected I4, but got Unknown if (slot >= 0) { if (slot >= _used.Length) { Grow(slot + 1); } if (slot >= _high) { _high = slot + 1; } _used[slot] = true; _generation[slot] = generation; _x[slot] = x; _y[slot] = y; _z[slot] = z; _state[slot] = (EnemyAlert)(int)state; } } public bool Release(int slot) { if (!Used(slot)) { return false; } _used[slot] = false; _state[slot] = (EnemyAlert)0; return IsSelected(slot); } public bool IsSelected(int slot) { for (int i = 0; i < SelectedCount; i++) { if (_selSlot[i] == slot) { return true; } } return false; } public int SelectedSlot(int index) { return _selSlot[index]; } public EnemyAlert SelectedState(int index) { return _selState[index]; } public void ClearSelection() { SelectedCount = 0; } public bool Select(EnemyOutlineStyle style, float cx, float cy, float cz, float fx, float fy, float fz) { int num = Math.Clamp(style.MaxEnemies, 1, 128); float num2 = style.Range * style.Range; float num3 = 9f; int num4 = 0; for (int i = 0; i < _high; i++) { if (!_used[i] || (int)_state[i] == 0) { continue; } float num5 = _x[i] - cx; float num6 = _y[i] - cy; float num7 = _z[i] - cz; float num8 = num5 * num5 + num6 * num6 + num7 * num7; if (!(num8 > num2) && (!(num8 > num3) || !(num5 * fx + num6 * fy + num7 * fz < -0.1f * MathF.Sqrt(num8))) && (num4 != num || !(num8 >= _newDist[num4 - 1]))) { int num9 = ((num4 < num) ? num4++ : (num4 - 1)); while (num9 > 0 && _newDist[num9 - 1] > num8) { _newDist[num9] = _newDist[num9 - 1]; _newSlot[num9] = _newSlot[num9 - 1]; num9--; } _newDist[num9] = num8; _newSlot[num9] = i; } } for (int j = 0; j < num4; j++) { int num10 = _newSlot[j]; int num11 = j; while (num11 > 0 && _nextSlot[num11 - 1] > num10) { _nextSlot[num11] = _nextSlot[num11 - 1]; num11--; } _nextSlot[num11] = num10; } bool flag = num4 != SelectedCount; for (int k = 0; k < num4; k++) { int num12 = _nextSlot[k]; _nextGen[k] = _generation[num12]; _nextState[k] = _state[num12]; if (!flag && (_selSlot[k] != num12 || _selGen[k] != _nextGen[k] || (int)_selState[k] != (int)_nextState[k])) { flag = true; } } if (!flag) { return false; } int[] nextSlot = _nextSlot; int[] selSlot = _selSlot; _selSlot = nextSlot; _nextSlot = selSlot; selSlot = _nextGen; nextSlot = _selGen; _selGen = selSlot; _nextGen = nextSlot; EnemyAlert[] nextState = _nextState; EnemyAlert[] selState = _selState; _selState = nextState; _nextState = selState; SelectedCount = num4; return true; } private void Grow(int needed) { int num; for (num = _used.Length; num < needed; num *= 2) { } Array.Resize(ref _used, num); Array.Resize(ref _generation, num); Array.Resize(ref _x, num); Array.Resize(ref _y, num); Array.Resize(ref _z, num); Array.Resize(ref _state, num); } } public sealed class OutlineScopes<T> where T : class { private readonly List<(T Scope, long Stamp)> _on = new List<(T, long)>(); private long _clock; public T? Current { get; private set; } public bool Set(T scope, bool on) { int num = -1; for (int i = 0; i < _on.Count; i++) { if (_on[i].Scope == scope) { num = i; break; } } if (on && num < 0) { _on.Add((scope, ++_clock)); } else { if (on || num < 0) { return false; } _on.RemoveAt(num); } T current = Current; Current = null; long num2 = long.MinValue; foreach (var (current2, num3) in _on) { if (num3 > num2) { num2 = num3; Current = current2; } } return current != Current; } public bool IsOn(T scope) { foreach (var item in _on) { if (item.Scope == scope) { return true; } } return false; } } internal static class ParticleBudget { internal static bool Admits(int live, int capacity, int priority) { if (capacity > 0 && live >= capacity) { return priority > 0; } return true; } } internal sealed class PooledBodies<T> where T : class { private readonly List<T> _live = new List<T>(); private readonly Stack<T> _free = new Stack<T>(); internal int LiveCount => _live.Count; internal int FreeCount => _free.Count; internal T this[int index] => _live[index]; internal T? Reuse(Func<T, bool> usable) { while (_free.Count > 0) { T val = _free.Pop(); if (usable(val)) { return val; } } return null; } internal void Add(T item) { _live.Add(item); } internal void RemoveAt(int index) { _live.RemoveAt(index); } internal bool Release(T item, Action<T> hide, bool usable) { if (!_live.Contains(item)) { return false; } hide(item); _live.Remove(item); if (usable) { _free.Push(item); } return true; } } internal static class ShakeMath { internal static float Setting(float configured) { if (!float.IsNaN(configured)) { if (!(configured < 0f)) { if (!(configured > 1f)) { return configured; } return 1f; } return 0f; } return 1f; } internal static float Falloff(float distance, float inner, float range) { if (!(range > 0f) || !(distance < range)) { return 0f; } if (distance <= inner) { return 1f; } return 1f - (distance - inner) / (range - inner); } } internal sealed class ShakeStack { private readonly float[] _start; private readonly float[] _seconds; private readonly float[] _amplitude; internal ShakeStack(int capacity) { if (capacity <= 0) { throw new ArgumentOutOfRangeException("capacity", "A stack holds at least one shake."); } _start = new float[capacity]; _seconds = new float[capacity]; _amplitude = new float[capacity]; } internal float Live(float now) { float num = 0f; for (int i = 0; i < _amplitude.Length; i++) { num += Share(i, now); } return num; } internal float Admit(float now, float amplitude, float seconds, float cap) { if (!(amplitude > 0f) || !(seconds > 0f) || !(cap > 0f)) { return 0f; } float num = cap - Live(now); if (num <= 0f) { return 0f; } float num2 = Math.Min(amplitude, num); int num3 = 0; float num4 = float.MaxValue; for (int i = 0; i < _amplitude.Length; i++) { float num5 = Share(i, now); if (num5 < num4) { num4 = num5; num3 = i; } } _start[num3] = now; _seconds[num3] = seconds; _amplitude[num3] = num2; return num2; } internal void Clear() { Array.Clear(_amplitude, 0, _amplitude.Length); } private float Share(int i, float now) { if (_amplitude[i] <= 0f) { return 0f; } float num = now - _start[i]; if (num < 0f) { num = 0f; } if (!(num >= _seconds[i])) { return _amplitude[i] * (1f - num / _seconds[i]); } return 0f; } } internal sealed class SlotBook { private readonly bool[] _live; private readonly bool[] _pinned; private readonly int[] _priority; private readonly int[] _generation; private readonly long[] _started; private long _sequence; private int _scan; internal int Capacity => _live.Length; internal int LiveCount { get; private set; } internal SlotBook(int capacity) { if (capacity <= 0) { throw new ArgumentOutOfRangeException("capacity", "A pool holds at least one item."); } _live = new bool[capacity]; _pinned = new bool[capacity]; _priority = new int[capacity]; _generation = new int[capacity]; _started = new long[capacity]; } internal bool Live(int slot) { return _live[slot]; } internal int Generation(int slot) { return _generation[slot]; } internal int Take(int priority, bool pinned, out bool replaced) { replaced = false; int num = _live.Length; for (int i = 0; i < num; i++) { int num2 = (_scan + i) % num; if (!_live[num2]) { _scan = (num2 + 1) % num; Start(num2, priority, pinned); LiveCount++; return num2; } } int num3 = -1; for (int j = 0; j < num; j++) { if (!_pinned[j] && _priority[j] < priority && (num3 < 0 || _priority[j] < _priority[num3] || (_priority[j] == _priority[num3] && _started[j] < _started[num3]))) { num3 = j; } } if (num3 < 0) { return -1; } replaced = true; Start(num3, priority, pinned); return num3; } internal void Free(int slot) { if (_live[slot]) { _live[slot] = false; _pinned[slot] = false; _generation[slot]++; LiveCount--; } } internal void Unpin(int slot) { _pinned[slot] = false; } internal void Clear() { for (int i = 0; i < _live.Length; i++) { Free(i); } } private void Start(int slot, int priority, bool pinned) { _live[slot] = true; _pinned[slot] = pinned; _priority[slot] = priority; _generation[slot]++; _started[slot] = ++_sequence; } } internal sealed class DecalSlots { private readonly bool[] _live; private readonly int[] _generation; private readonly long[] _started; private long _sequence; internal int Capacity => _live.Length; internal int LiveCount { get; private set; } internal DecalSlots(int capacity) { if (capacity <= 0) { throw new ArgumentOutOfRangeException("capacity", "A set of marks holds at least one."); } _live = new bool[capacity]; _generation = new int[capacity]; _started = new long[capacity]; } internal bool Live(int slot) { return _live[slot]; } internal int Generation(int slot) { return _generation[slot]; } internal int Take() { int num = -1; for (int i = 0; i < _live.Length; i++) { if (!_live[i]) { num = i; break; } if (num < 0 || _started[i] < _started[num]) { num = i; } } if (!_live[num]) { LiveCount++; } _live[num] = true; _generation[num]++; _started[num] = ++_sequence; return num; } internal bool Current(int slot, int generation) { if (slot >= 0 && slot < _live.Length && _live[slot]) { return _generation[slot] == generation; } return false; } internal void End(int slot) { if (_live[slot]) { _live[slot] = false; _generation[slot]++; LiveCount--; } } internal void Clear() { for (int i = 0; i < _live.Length; i++) { End(i); } } } internal static class DecalMath { internal static float Hold(float life, float fade) { if (!(life > 0f)) { return 0f; } if (!(fade > 0f)) { return 1f; } float num = 1f - fade / life; if (!(num < 0f)) { return num; } return 0f; } } internal static class LightSlots { internal static int Pick(bool[] used, bool[] held, float[] ends, float now) { for (int i = 0; i < used.Length; i++) { if (!used[i]) { return i; } } int result = -1; float num = float.MaxValue; for (int j = 0; j < used.Length; j++) { if (!held[j]) { float num2 = ends[j] - now; if (num2 < num) { num = num2; result = j; } } } return result; } internal static float Blink(float age, float rate) { if (!(rate > 0f)) { return 1f; } float num = age * rate; if (!(num - (float)Math.Floor(num) < 0.5f)) { return 0f; } return 1f; } } internal sealed class HoldBook { private readonly bool[] _playing; private readonly bool[] _emitting; private readonly float[] _until; private readonly float[] _x; private readonly float[] _y; private readonly float[] _z; private readonly long[] _started; private long _sequence; internal int Copies => _playing.Length; internal HoldBook(int copies) { if (copies <= 0) { throw new ArgumentOutOfRangeException("copies", "An effect keeps at least one copy."); } _playing = new bool[copies]; _emitting = new bool[copies]; _until = new float[copies]; _x = new float[copies]; _y = new float[copies]; _z = new float[copies]; _started = new long[copies]; } internal bool Playing(int copy) { return _playing[copy]; } internal bool Emitting(int copy) { return _emitting[copy]; } internal int Near(float x, float y, float z, float reach) { int result = -1; float num = reach * reach; for (int i = 0; i < _playing.Length; i++) { if (_playing[i] && _emitting[i]) { float num2 = _x[i] - x; float num3 = _y[i] - y; float num4 = _z[i] - z; float num5 = num2 * num2 + num3 * num3 + num4 * num4; if (num5 <= num) { num = num5; result = i; } } } return result; } internal int Take() { int num = 0; for (int i = 0; i < _playing.Length; i++) { if (!_playing[i]) { return i; } if (_started[i] < _started[num]) { num = i; } } return num; } internal void Start(int copy, float x, float y, float z, float now, float window) { _playing[copy] = true; _emitting[copy] = window > 0f; _until[copy] = ((window > 0f) ? (now + window) : 0f); _started[copy] = ++_sequence; Place(copy, x, y, z); } internal void Extend(int copy, float x, float y, float z, float now, float window) { _until[copy] = now + window; Place(copy, x, y, z); } internal bool Expired(int copy, float now) { if (!_playing[copy] || !_emitting[copy] || now < _until[copy]) { return false; } _emitting[copy] = false; return true; } internal void Stop(int copy) { _emitting[copy] = false; } internal void Finished(int copy) { _playing[copy] = false; _emitting[copy] = false; } private void Place(int copy, float x, float y, float z) { _x[copy] = x; _y[copy] = y; _z[copy] = z; } } internal sealed class RibbonRing<T> where T : struct { private readonly T[] _ring; private int _head; private float _next; internal int Count => _ring.Length; internal float Step { get; } internal T this[int i] => _ring[(_head - i + _ring.Length * 2) % _ring.Length]; internal RibbonRing(int points, float step) { if (points < 2) { throw new ArgumentOutOfRangeException("points", "A ribbon has at least two points."); } if (!(step > 0f)) { throw new ArgumentOutOfRangeException("step", "The sample step must be positive."); } _ring = new T[points]; Step = step; } internal void Reset(T start, float now) { for (int i = 0; i < _ring.Length; i++) { _ring[i] = start; } _head = 0; _next = now + Step; } internal void Sample(T position, float now) { while (now >= _next) { _head = (_head + 1) % _ring.Length; _ring[_head] = position; _next += Step; if (now - _next > 0.1f) { _next = now + Step; } } _ring[_head] = position; } } internal static class MarkerMath { internal const float RevealMargin = 3f; internal const float RevealHeight = 2.5f; internal static float Reveal(float across, float up, float reach) { return Clamp01(reach + 3f - across) * Clamp01(2.5f - Math.Abs(up)); } internal static float Sweep(float age, float seconds) { if (!(seconds <= 0f)) { return Clamp01(age / seconds); } return 1f; } internal static float Advance(float phase, float perSecond, float seconds) { float num = phase + Math.Max(0f, perSecond) * Math.Max(0f, seconds); return num - (float)Math.Floor(num); } internal static float Blink(float sinceTick) { if (!(sinceTick < 0f)) { return (float)Math.Exp((0f - sinceTick) * 7f); } return 0f; } internal static float Clamp01(float v) { if (!(v < 0f)) { if (!(v > 1f)) { return v; } return 1f; } return 0f; } } public sealed class BeamStyle { public float CoreWidth { get; set; } = 0.03f; public float CorePerMetre { get; set; } = 0.0014f; public float GlowWidth { get; set; } = 0.34f; public float CoreSharpness { get; set; } = 1.1f; public float GlowSharpness { get; set; } = 3.2f; public float CoreOpacity { get; set; } = 0.9f; public float GlowOpacity { get; set; } = 0.45f; public bool Column { get; set; } = true; public float FlareSize { get; set; } public bool FlareAtEnd { get; set; } public float FlareOpacity { get; set; } = 0.6f; public float FlareLift { get; set; } } public sealed class Beam { private static readonly int ColorId = Shader.PropertyToID("_Color"); private static readonly int HotId = Shader.PropertyToID("_Hot"); private static readonly int StateId = Shader.PropertyToID("_State"); private static readonly int ShapeId = Shader.PropertyToID("_Shape"); private static readonly int RevealId = Shader.PropertyToID("_Reveal"); private static readonly MaterialPropertyBlock Block = new MaterialPropertyBlock(); private readonly GameObject _object; private readonly LineRenderer _core; private readonly LineRenderer _glow; private readonly MeshRenderer _flare; private Vector3 _from; private Vector3 _to; private float _born; internal bool Live; public BeamStyle Style { get; internal set; } public Color Colour { get; set; } public Color Hot { get; set; } public float Opacity { get; set; } = 1f; public float Width { get; set; } = 1f; public float CoreScale { get; set; } = 1f; public float FlareScale { get; set; } = 1f; public float CoreLevel { get; set; } = 1f; public float GlowLevel { get; set; } = 1f; public float FlareLevel { get; set; } = 1f; public float GlowWidthScale { get; set; } = 1f; public bool Visible { get; private set; } public bool Alive { get { if (Live && (Object)(object)_object != (Object)null) { return !((Il2CppObjectBase)_object).WasCollected; } return false; } } internal GameObject Object => _object; internal Beam(GameObject o, LineRenderer core, LineRenderer glow, MeshRenderer flare) { _object = o; _core = core; _glow = glow; _flare = flare; } public void Show(Vector3 from, Vector3 to) { //IL_000a: 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) //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) //IL_001e: 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_0038: 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) if (Alive) { _from = from; _to = to; _core.SetPosition(0, from); _core.SetPosition(1, to); _glow.SetPosition(0, from); _glow.SetPosition(1, to); if (!Visible) { Visible = true; _object.SetActive(true); } Draw(Scene.Now); } } public void Hide() { Visible = false; if ((Object)(object)_object != (Object)null && !((Il2CppObjectBase)_object).WasCollected) { _object.SetActive(false); } } public void Release() { Beams.Release(this); } internal void Begin(BeamStyle style, Color colour) { //IL_0008: 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_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) Style = style; Colour = colour; Hot = Color.Lerp(colour, Color.white, 0.65f); float num = (CoreScale = 1f); float num3 = (GlowWidthScale = num); float num5 = (FlareLevel = num3); float num7 = (GlowLevel = num5); float num9 = (CoreLevel = num7); float num11 = (FlareScale = num9); float opacity = (Width = num11); Opacity = opacity; _born = Scene.Now; Visible = false; Live = true; _object.SetActive(false); } internal void Draw(float now) { //IL_0013: 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_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: 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) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: 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_022b: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Unknown result type (might be due to invalid IL or missing references) //IL_0299: Unknown result type (might be due to invalid IL or missing references) //IL_02b0: Unknown result type (might be due to invalid IL or missing references) //IL_02e8: Unknown result type (might be due to invalid IL or missing references) //IL_0310: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_0274: Unknown result type (might be due to invalid IL or missing references) //IL_0279: Unknown result type (might be due to invalid IL or missing references) //IL_028b: Unknown result type (might be due to invalid IL or missing references) //IL_028d: Unknown result type (might be due to invalid IL or missing references) if (!Visible) { return; } float num = now - _born; Vector3 val = _to - _from; float magnitude = ((Vector3)(ref val)).magnitude; float num2 = (Style.Column ? 0f : 1f); float num3 = (Scene.HasEye ? DistanceToSegment(Scene.Eye, _from, _to) : 10f); _core.widthMultiplier = Math.Max(Style.CoreWidth, num3 * Style.CorePerMetre) * Width * CoreScale; _glow.widthMultiplier = Style.GlowWidth * Width * GlowWidthScale; Block.SetFloat(RevealId, 0f); Block.SetColor(ColorId, Colour); Block.SetColor(HotId, Hot); Block.SetVector(StateId, new Vector4(num, 0f, 0f, Style.CoreOpacity * Opacity * CoreLevel)); Block.SetVector(ShapeId, new Vector4(magnitude, 0f, Style.CoreSharpness, num2)); ((Renderer)_core).SetPropertyBlock(Block); Block.SetVector(StateId, new Vector4(num, 0f, 0f, Style.GlowOpacity * Opacity * GlowLevel)); Block.SetVector(ShapeId, new Vector4(magnitude, 0f, Style.GlowSharpness, num2)); ((Renderer)_glow).SetPropertyBlock(Block); bool flag = Style.FlareSize > 0f; if (((Renderer)_flare).enabled != flag) { ((Renderer)_flare).enabled = flag; } if (!flag) { return; } Vector3 val2 = (Style.FlareAtEnd ? _to : _from); Transform transform = ((Component)_flare).transform; val2 = (transform.position = val2 + Vector3.up * Style.FlareLift); if (Scene.HasEye) { Vector3 val4 = val2 - Scene.Eye; if (((Vector3)(ref val4)).sqrMagnitude > 0.0001f) { transform.rotation = Quaternion.LookRotation(val4); } } transform.localScale = Vector3.one * (Style.FlareSize * FlareScale); Block.SetVector(StateId, new Vector4(num, 0f, 0f, Style.FlareOpacity * Opacity * FlareLevel)); Block.SetVector(ShapeId, new Vector4(0f, 2f, 0f, 0f)); ((Renderer)_flare).SetPropertyBlock(Block); } private static float DistanceToSegment(Vector3 p, Vector3 a, Vector3 b) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: 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_001d: 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_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0046: 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) Vector3 val = b - a; float num = ((((Vector3)(ref val)).sqrMagnitude > 1E-06f) ? Mathf.Clamp01(Vector3.Dot(p - a, val) / ((Vector3)(ref val)).sqrMagnitude) : 0f); Vector3 val2 = a + val * num - p; return ((Vector3)(ref val2)).magnitude; } } public static class Beams { private static readonly PooledBodies<Beam> Pool = new PooledBodies<Beam>(); public static Beam? Create(Color colour, BeamStyle style) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) Material val = Shaders.Marker(); if ((Object)(object)val == (Object)null) { return null; } Beam beam = Pool.Reuse(Usable) ?? Make(val); beam.Begin(style ?? new BeamStyle(), colour); Pool.Add(beam); return beam; } private static Beam Make(Material material) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //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_002d: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("ForgeVisual.Beam"); Object.DontDestroyOnLoad((Object)(object)val); GameObject val2 = new GameObject("flare"); val2.transform.SetParent(val.transform, false); val2.AddComponent<MeshFilter>().sharedMesh = Shaders.Quad(); MeshRenderer val3 = val2.AddComponent<MeshRenderer>(); ((Renderer)val3).sharedMaterial = material; ((Renderer)val3).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)val3).receiveShadows = false; LineRenderer glow = Line(val, "glow", material); LineRenderer core = Line(val, "core", material); return new Beam(val, core, glow, val3); } internal static LineRenderer Line(GameObject parent, string name, Material material) { //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) GameObject val = new GameObject(name); val.transform.SetParent(parent.transform, false); LineRenderer obj = val.AddComponent<LineRenderer>(); ((Renderer)obj).sharedMaterial = material; obj.useWorldSpace = true; obj.textureMode = (LineTextureMode)0; ((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)obj).receiveShadows = false; obj.numCapVertices = 0; obj.positionCount = 2; return obj; } internal static void Release(Beam beam) { if (Pool.Release(beam, delegate(Beam b) { b.Hide(); }, Usable(beam))) { beam.Live = false; } } private static bool Usable(Beam beam) { if ((Object)(object)beam.Object != (Object)null) { return !((Il2CppObjectBase)beam.Object).WasCollected; } return false; } internal static void TickAll(float now) { for (int num = Pool.LiveCount - 1; num >= 0; num--) { Beam beam = Pool[num]; if (!Usable(beam)) { beam.Live = false; Pool.RemoveAt(num); } else { beam.Draw(now); } } } internal static void ClearAll() { for (int num = Pool.LiveCount - 1; num >= 0; num--) { Release(Pool[num]); } } } public sealed class WorldBackdrop { private readonly GameObject _object; private readonly Material _material; public GameObject Root => _object; private WorldBackdrop(GameObject target, Material material) { _object = target; _material = material; } public static WorldBackdrop? TryCreate(Transform parent, string name, Color color) { //IL_0017: 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_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown Shader val = Shader.Find("Sprites/Default"); if ((Object)(object)val == (Object)null) { return null; } Material val2 = new Material(val) { color = color }; GameObject val3 = new GameObject(name); try { val3.transform.SetParent(parent, false); val3.AddComponent<MeshFilter>().sharedMesh = Shaders.Quad(); MeshRenderer obj = val3.AddComponent<MeshRenderer>(); ((Renderer)obj).sharedMaterial = val2; ((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0; } catch { Object.Destroy((Object)(object)val3); Object.Destroy((Object)(object)val2); throw; } return new WorldBackdrop(val3, val2); } public void SetColor(Color color) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) _material.color = color; } public void Place(Vector2 size, Vector2 center, float depth = 0.01f) { //IL_000b: 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_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) _object.transform.localScale = new Vector3(size.x, size.y, 1f); _object.transform.localPosition = new Vector3(center.x, center.y, depth); } public void Destroy() { if ((Object)(object)_object != (Object)null && !((Il2CppObjectBase)_object).WasCollected) { Object.Destroy((Object)(object)_object); } if ((Object)(object)_material != (Object)null && !((Il2CppObjectBase)_material).WasCollected) { Object.Destroy((Object)(object)_material); } } } public sealed class ImageBoard { private readonly GameObject _object; private readonly Material _material; public GameObject Root => _object; private ImageBoard(GameObject target, Material material) { _object = target; _material = material; } public static ImageBoard? TryCreate(Transform parent, string name, int layer, Texture2D texture, float width, float height) { //IL_0017: 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_001d: 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_002f: Expected O, but got Unknown //IL_0030: 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) //IL_003d: Expected O, but got Unknown //IL_0050: 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) //IL_0079: Unknown result type (might be due to invalid IL or missing references) Shader val = Shader.Find("Sprites/Default"); if ((Object)(object)val == (Object)null) { return null; } Material val2 = new Material(val) { color = Color.white, mainTexture = (Texture)(object)texture }; GameObject val3 = new GameObject(name) { layer = layer }; try { val3.transform.SetParent(parent, false); val3.transform.localPosition = Vector3.zero; val3.transform.localRotation = Quaternion.identity; val3.transform.localScale = new Vector3(width, height, 1f); val3.AddComponent<MeshFilter>().sharedMesh = Shaders.Quad(); MeshRenderer obj = val3.AddComponent<MeshRenderer>(); ((Renderer)obj).sharedMaterial = val2; ((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0; } catch { Object.Destroy((Object)(object)val3); Object.Destroy((Object)(object)val2); throw; } return new ImageBoard(val3, val2); } public void Destroy() { if ((Object)(object)_object != (Object)null && !((Il2CppObjectBase)_object).WasCollected) { Object.Destroy((Object)(object)_object); } if ((Object)(object)_material != (Object)null && !((Il2CppObjectBase)_material).WasCollected) { Object.Destroy((Object)(object)_material); } } } public sealed class SignBoard { private readonly Transform _face; private readonly float _width; private readonly float _height; private readonly float _padding; private WorldText? _text; public WorldBackdrop? Backdrop { get; } public WorldText? Text => _text; private SignBoard(Transform face, float width, float height, float padding, WorldBackdrop? backdrop) { _face = face; _width = width; _height = height; _padding = padding; Backdrop = backdrop; } public static SignBoard? TryCreate(Transform face, string backdropName, float width, float height, float padding, Color? backdrop) { //IL_000d: 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) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) WorldBackdrop worldBackdrop = null; if (backdrop.HasValue) { Color valueOrDefault = backdrop.GetValueOrDefault(); worldBackdrop = WorldBackdrop.TryCreate(face, backdropName, valueOrDefault); if (worldBackdrop == null) { return null; } worldBackdrop.Place(new Vector2(padding * 2f, padding * 2f), default(Vector2)); } return new SignBoard(face, width, height, padding, worldBackdrop); } public WorldText ShowText(string textName, WorldTextStyle style, string content, float? lineWidth = null) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: 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_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: 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_00e5: Unknown result type (might be due to invalid IL or missing references) if (_text == null) { _text = WorldText.Create(_face, textName, style with { Alignment = (TextAlignmentOptions)514, Pivot = new Vector2(0.5f, 0.5f) }); _text.SetLocalPosition(new Vector3(0f, 0f, -0.02f)); } _text.SetShown(shown: true); float num = lineWidth ?? _width; Vector2 val = _text.SetContent(content, num, _height); Backdrop?.Place(new Vector2(Mathf.Min(num, val.x) + _padding * 2f, val.y + _padding * 2f), default(Vector2)); return _text; } public void DestroyText() { _text?.Destroy(); _text = null; } public void Destroy() { DestroyText(); Backdrop?.Destroy(); } } public sealed class BodyClipRig { public Transform Root { get; } public GameObject Animated { get; } public IReadOnlyList<Transform> Bones { get; } private BodyClipRig(Transform root, GameObject animated, Transform[] bones) { Root = root; Animated = animated; Bones = bones; } public Transform? Bone(string name) { for (int i = 0; i < Bones.Count; i++) { if (((Object)Bones[i]).name == name) { return Bones[i]; } } return null; } internal static BodyClipRig? Create(Transform root, GameObject animated, string rootBone, string label) { Transform val = Models.Find(animated.transform, rootBone); if ((Object)(object)val == (Object)null) { Plugin.Logger.ErrorOnce("ForgeVisual body clip rig " + label + " has no bone " + rootBone + "; it plays nothing."); return null; } List<Transform> list = new List<Transform> { val }; foreach (Transform componentsInChild in ((Component)val).GetComponentsInChildren<Transform>(true)) { if ((Object)(object)componentsInChild != (Object)(object)val) { list.Add(componentsInChild); } } return new BodyClipRig(root, animated, list.ToArray()); } } public sealed class BodyClipOptions { public bool PauseIk { get; set; } = true; public bool FirstPersonHead { get; set; } public IReadOnlyList<string>? FirstPersonSkip { get; set; } public string? Label { get; set; } } public sealed class BodyClip { private readonly PlayerAgent _agent; private readonly BodyClipRig _rig; private readonly bool _local; private readonly Transform?[] _game; private readonly Behaviour[] _solvers; private readonly bool[] _solversWere; private readonly Renderer[] _drawn; private readonly ShadowCastingMode[] _drawnMode; private readonly int[] _drawnLayer; private readonly Renderer[] _arms; private readonly bool[] _armsWere; private bool _posing; private bool _firstPerson; public int Matched { get; } public bool Posing => _posing; private BodyClip(PlayerAgent agent, BodyClipRig rig, bool local, Transform?[] game, Behaviour[] solvers, Renderer[] drawn, Renderer[] arms) { _agent = agent; _rig = rig; _local = local; _game = game; _solvers = solvers; _solversWere = new bool[solvers.Length]; _drawn = drawn; _drawnMode = (ShadowCastingMode[])(object)new ShadowCastingMode[drawn.Length]; _drawnLayer = new int[drawn.Length]; _arms = arms; _armsWere = new bool[arms.Length]; Matched = 0; for (int i = 0; i < game.Length; i++) { if ((Object)(object)game[i] != (Object)null) { int matched = Matched; Matched = matched + 1; } } } internal static BodyClip? Bind(PlayerAgent agent, BodyClipRig rig, BodyClipOptions options) { string text = options.Label; if (text == null) { SNet_Player owner = agent.Owner; text = "player " + ((owner != null) ? new ulong?(owner.Lookup) : ((ulong?)null)); } string text2 = text; Animator animatorBody = agent.AnimatorBody; Transform val = (((Object)(object)animatorBody != (Object)null) ? animatorBody.GetBoneTransform((HumanBodyBones)0) : null); if ((Object)(object)val == (Object)null) { Plugin.Logger.ErrorOnce("ForgeVisual body clip " + text2 + ": the player's body has no hips; no clip plays on it."); return null; } Dictionary<string, Transform> dictionary = new Dictionary<string, Transform>(StringComparer.Ordinal); foreach (Transform componentsInChild in ((Component)val).GetComponentsInChildren<Transform>(true)) { dictionary.TryAdd(((Object)componentsInChild).name, componentsInChild); } IReadOnlyList<Transform> bones = rig.Bones; Transform[] array = (Transform[])(object)new Transform[bones.Count]; for (int i = 0; i < bones.Count; i++) { if (dictionary.TryGetValue(((Object)bones[i]).name, out var value)) { array[i] = value; } } array[0] = val; List<Behaviour> list = new List<Behaviour>(); if (options.PauseIk) { foreach (MonoBehaviour componentsInChild2 in ((Component)agent).GetComponentsInChildren<MonoBehaviour>(true)) { Type il2CppType = ((Object)componentsInChild2).GetIl2CppType(); if ((il2CppType.Namespace ?? "").StartsWith("RootMotion.FinalIK", StringComparison.Ordinal) || ((MemberInfo)il2CppType).Name == "PlayerSyncIK") { list.Add((Behaviour)(object)componentsInChild2); } } } bool flag = BodyConvert.IsLocal(agent); List<Renderer> list2 = new List<Renderer>(); List<Renderer> list3 = new List<Renderer>(); if (flag) { PlayerSyncModelData playerSyncModel = agent.PlayerSyncModel; if ((Object)(object)playerSyncModel != (Object)null) { HashSet<IntPtr> hashSet = new HashSet<IntPtr>(); if (!options.FirstPersonHead && playerSyncModel.m_gfxHead != null) { foreach (GameObject item in (Il2CppArrayBase<GameObject>)(object)playerSyncModel.m_gfxHead) { if (!((Object)(object)item != (Object)null)) { continue; } foreach (Renderer componentsInChild3 in item.GetComponentsInChildren<Renderer>(true)) { hashSet.Add(((Il2CppObjectBase)componentsInChild3).Pointer); } } } foreach (Renderer componentsInChild4 in ((Component)playerSyncModel).GetComponentsInChildren<Renderer>(true)) { if (!hashSet.Contains(((Il2CppObjectBase)componentsInChild4).Pointer) && !Skipped(((Object)componentsInChild4).name, options.FirstPersonSkip)) { list2.Add(componentsInChild4); } } } FirstPersonItemHolder fPItemHolder = agent.FPItemHolder; if ((Object)(object)fPItemHolder != (Object)null) { list3.AddRange((IEnumerable<Renderer>)((Component)fPItemHolder).GetComponentsInChildren<Renderer>(true)); } } return new BodyClip(agent, rig, flag, array, list.ToArray(), list2.ToArray(), list3.ToArray()); } private static bool Skipped(string name, IReadOnlyList<string>? skip) { if (skip == null) { return false; } for (int i = 0; i < skip.Count; i++) { if (name.IndexOf(skip[i], StringComparison.OrdinalIgnoreCase) >= 0) { return true; } } return false; } public bool Pose(AnimationClip clip, float time, Vector3 position, Quaternion rotation) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0095: 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_00c9: Unknown result type (might be due to invalid IL or missing references) if (((Il2CppObjectBase)_agent).WasCollected || (Object)(object)_rig.Root == (Object)null || ((Il2CppObjectBase)_rig.Root).WasCollected) { return false; } if (!_posing) { Pause(); } _rig.Root.SetPositionAndRotation(position, rotation); clip.SampleAnimation(_rig.Animated, time); IReadOnlyList<Transform> bones = _rig.Bones; Transform val = _game[0]; if ((Object)(object)val != (Object)null && !((Il2CppObjectBase)val).WasCollected) { val.SetPositionAndRotation(bones[0].position, bones[0].rotation); } for (int i = 1; i < bones.Count; i++) { Transform val2 = _game[i]; if ((Object)(object)val2 != (Object)null) { val2.localRotation = bones[i].localRotation; } } return true; } public void Stop() { FirstPerson(on: false); if (!_posing) { return; } _posing = false; for (int i = 0; i < _solvers.Length; i++) { if ((Object)(object)_solvers[i] != (Object)null && !((Il2CppObjectBase)_solvers[i]).WasCollected && _solversWere[i]) { _solvers[i].enabled = true; } } } private void Pause() { _posing = true; for (int i = 0; i < _solvers.Length; i++) { Behaviour val = _solvers[i]; _solversWere[i] = (Object)(object)val != (Object)null && !((Il2CppObjectBase)val).WasCollected && val.enabled; if (_solversWere[i]) { val.enabled = false; } } } public void FirstPerson(bool on, Camera? camera = null) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected I4, but got Unknown if (!_local || on == _firstPerson) { return; } _firstPerson = on; int num = (((Object)(object)camera != (Object)null && !((Il2CppObjectBase)camera).WasCollected) ? camera.cullingMask : (-1)); for (int i = 0; i < _drawn.Length; i++) { Renderer val = _drawn[i]; if ((Object)(object)val == (Object)null || ((Il2CppObjectBase)val).WasCollected) { continue; } if (on) { _drawnMode[i] = (ShadowCastingMode)(int)val.shadowCastingMode; _drawnLayer[i] = ((Component)val).gameObject.layer; val.shadowCastingMode = (ShadowCastingMode)1; if ((num & (1 << ((Component)val).gameObject.layer)) == 0) { ((Component)val).gameObject.layer = 0; } } else { val.shadowCastingMode = _drawnMode[i]; ((Component)val).gameObject.layer = _drawnLayer[i]; } } for (int j = 0; j < _arms.Length; j++) { Renderer val2 = _arms[j]; if (!((Object)(object)val2 == (Object)null) && !((Il2CppObjectBase)val2).WasCollected) { if (on) { _armsWere[j] = val2.forceRenderingOff; val2.forceRenderingOff = true; } else { val2.forceRenderingOff = _armsWere[j]; } } } } } [Flags] public enum BodyParts { None = 0, Head = 1, Torso = 2, Legs = 4, Arms = 8 } public sealed class FirstPersonWearOptions { public IReadOnlyList<WearBone> Bones { get; set; } = Array.Empty<WearBone>(); public BodyParts Hide { get; set; } = BodyParts.Head | BodyParts.Torso | BodyParts.Legs; public IReadOnlyCollection<string>? FollowParent { get; set; } public string? Label { get; set; } } internal static class BodyConvert { internal static Vector3 N(Vector3 v) { //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_000c: Unknown result type (might be due to invalid IL or missing references) return new Vector3(v.x, v.y, v.z); } internal static Quaternion N(Quaternion q) { //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_000c: 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) return new Quaternion(q.x, q.y, q.z, q.w); } internal static Quaternion U(Quaternion q) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) return new Quaternion(q.X, q.Y, q.Z, q.W); } internal static Vector3 U(Vector3 v) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) return new Vector3(v.X, v.Y, v.Z); } internal static Dictionary<IntPtr, Matrix4x4> BindRest(Component root, Transform frame) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0076: 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_0087: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: 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_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) Dictionary<IntPtr, Matrix4x4> dictionary = new Dictionary<IntPtr, Matrix4x4>(); Matrix4x4 worldToLocalMatrix = frame.worldToLocalMatrix; foreach (SkinnedMeshRenderer componentsInChild in root.GetComponentsInChildren<SkinnedMeshRenderer>(true)) { Mesh val = (((Object)(object)componentsInChild == (Object)null) ? null : componentsInChild.sharedMesh); if ((Object)(object)val == (Object)null) { continue; } Il2CppReferenceArray<Transform> bones = componentsInChild.bones; Il2CppStructArray<Matrix4x4> bindposes = val.bindposes; if (bones == null || bindposes == null || ((Il2CppArrayBase<Matrix4x4>)(object)bindposes).Length != ((Il2CppArrayBase<Transform>)(object)bones).Length) { continue; } Matrix4x4 val2 = worldToLocalMatrix * ((Component)componentsInChild).transform.localToWorldMatrix; for (int i = 0; i < ((Il2CppArrayBase<Transform>)(object)bones).Length; i++) { if ((Object)(object)((Il2CppArrayBase<Transform>)(object)bones)[i] != (Object)null && !dictionary.ContainsKey(((Il2CppObjectBase)((Il2CppArrayBase<Transform>)(object)bones)[i]).Pointer)) { IntPtr pointer = ((Il2CppObjectBase)((Il2CppArrayBase<Transform>)(object)bones)[i]).Pointer; Matrix4x4 val3 = ((Il2CppArrayBase<Matrix4x4>)(object)bindposes)[i]; dictionary[pointer] = val2 * ((Matrix4x4)(ref val3)).inverse; } } } return dictionary; } internal static bool IsLocal(PlayerAgent agent) { if (((Agent)agent).IsLocallyOwned && (Object)(object)agent.Owner != (Object)null && (Object)(object)SNet.LocalPlayer != (Object)null) { return agent.Owner.Lookup == SNet.LocalPlayer.Lookup; } return false; } } public sealed class FirstPersonWear { private readonly GameObject _root; private readonly Transform[] _worn; private readonly Transform?[] _on; private readonly PlayerFPSBody _body; private readonly SkinnedMeshRenderer _renderer; private readonly Mesh _mesh; private readonly List<Material> _materials = new List<Material>(); private readonly List<Renderer> _hidden = new List<Renderer>(); private readonly bool[] _wasOff; private readonly GameObject[] _arms; private bool _active; private bool _shown; private bool _held; private bool RootAlive { get { if ((Object)(object)_root != (Object)null) { return !((Il2CppObjectBase)_root).WasCollected; } return false; } } public bool Alive { get { if (RootAlive && (Object)(object)_body != (Object)null) { return !((Il2CppObjectBase)_body).WasCollected; } return false; } } public bool Active => _active; public int Hidden => _hidden.Count; private FirstPersonWear(GameObject root, Transform[] worn, Transform?[] on, PlayerFPSBody body, SkinnedMeshRenderer renderer, Mesh mesh, GameObject[] arms, BodyParts hide) { _root = root; _worn = worn; _on = on; _body = body; _renderer = renderer; _mesh = mesh; _arms = arms; foreach (Material item in (Il2CppArrayBase<Material>)(object)((Renderer)renderer).materials) { _materials.Add(item); } if ((hide & BodyParts.Torso) != BodyParts.None) { Collect(body.m_gfxTorso); } if ((hide & BodyParts.Legs) != BodyParts.None) { Collect(body.m_gfxLegs); } if ((hide & BodyParts.Head) != BodyParts.None) { Collect(body.m_gfxHead); } if ((hide & BodyParts.Arms) != BodyParts.None) { Collect(body.m_gfxArms); } _wasOff = new bool[_hidden.Count]; } internal static FirstPersonWear? Build(PlayerAgent agent, ModelHandle look, FirstPersonWearOptions options) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) string label = options.Label ?? look.Name; IReadOnlyList<WearBone> bones = options.Bones; if (bones.Count == 0) { Error(label, "lists no bones"); return null; } PlayerFPSBody val = (((Object)(object)agent.FPItemHolder == (Object)null) ? null : agent.FPItemHolder.FPSArms); if ((Object)(object)val == (Object)null || ((Il2CppObjectBase)val).WasCollected) { Error(label, "the player has no first-person body"); return null; } GameObject val2 = look.Spawn(Vector3.zero, Quaternion.identity); if ((Object)(object)val2 == (Object)null) { return null; } ((Object)val2).name = "ForgeVisual.Wear." + look.Name; val2.SetActive(false); foreach (Animation componentsInChild in val2.GetComponentsInChildren<Animation>(true)) { ((Behaviour)componentsInChild).enabled = false; } FirstPersonWear firstPersonWear = null; try { firstPersonWear = Bind(agent, val, val2, bones, options, label); } catch (Exception ex) { Error(label, "building failed: " + ex); } if (firstPersonWear == null && (Object)(object)val2 != (Object)null && !((Il2CppObjectBase)val2).WasCollected) { Object.Destroy((Object)(object)val2); } return firstPersonWear; } private static FirstPersonWear? Bind(PlayerAgent agent, PlayerFPSBody body, GameObject root, IReadOnlyList<WearBone> bones, FirstPersonWearOptions options, string label) { //IL_0297: Unknown result type (might be due to invalid IL or missing references) //IL_02a3: Unknown result type (might be due to invalid IL or missing references) //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Unknown result type (might be due to invalid IL or missing references) //IL_033c: Unknown result type (might be due to invalid IL or missing references) //IL_0342: Unknown result type (might be due to invalid IL or missing references) //IL_0347: Unknown result type (might be due to invalid IL or missing references) //IL_034b: Unknown result type (might be due to invalid IL or missing references) //IL_0350: Unknown result type (might be due to invalid IL or missing references) //IL_0355: Unknown result type (might be due to invalid IL or missing references) //IL_035e: Unknown result ty