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 CHEF Skin Pack v0.2.0
BepInEx/plugins/ChefCollection/Rodanius.Chef.Collection.dll
Decompiled a week agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Security.Cryptography; using BepInEx; using Eclipse.AdvancedSkins; using EntityStates; using EntityStates.Chef; using HG.Reflection; using On.EntityStates.Chef; using R2API; using R2API.Utils; using RoR2; using RoR2.UI.MainMenu; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.ResourceManagement.AsyncOperations; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: OptIn] [assembly: AssemblyVersion("0.0.0.0")] namespace Rodanius.ChefCollection; [BepInPlugin("rodanius.chef.collection", "CHEF Skin Pack - Collection", "0.2.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class ChefPack : BaseUnityPlugin { [Serializable] public sealed class AssetFile { public string file; public string sha256; } [Serializable] public sealed class AssetManifest { public int schema; public string skinId; public string revision; public string displayName; public AssetFile mesh; public AssetFile motion; public AssetFile albedo; public AssetFile normal; public AssetFile icon; public string[] nativeBoneNames; } public const string Guid = "rodanius.chef.collection"; public const string Version = "0.2.0"; private string SkinId; private readonly List<IDisposable> registrations = new List<IDisposable>(); private static ChefPack instance; private string folder; private float deadline; private bool registered; private readonly Dictionary<string, Mesh> fallbackMeshes = new Dictionary<string, Mesh>(); private GameObject modelPrefab; private GameObject displayModelPrefab; private Mesh nativeMesh; private Material nativeMaterial; private AssetManifest manifest; private readonly List<AsyncOperationHandle> retainedAssets = new List<AsyncOperationHandle>(); private static readonly string[] RendererNames = new string[5] { "meshChef", "meshChefPizzaCutter", "meshlChefCleaver", "meshChefOven", "meshChefIceBox" }; private void Awake() { instance = this; ChefNativeEvents.Install(); folder = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location); SystemInitializerInjector.InjectDependency(typeof(SkinCatalog), typeof(ChefPack)); RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(SyncDisplaySkins)); MainMenuController.OnMainMenuInitialised += SyncDisplaySkins; } [SystemInitializer(new Type[] { typeof(BodyCatalog), typeof(SurvivorCatalog) })] private static IEnumerator InitializeSkin() { if (!Object.op_Implicit((Object)(object)instance)) { yield break; } instance.deadline = Time.realtimeSinceStartup + 45f; IEnumerator routine = instance.Register(); try { while (true) { bool flag; try { flag = routine.MoveNext(); } catch (Exception ex) { ((BaseUnityPlugin)instance).Logger.LogError((object)("CHEF_PACK_REGISTRATION_FAILED " + ex)); break; } if (flag) { yield return routine.Current; continue; } break; } } finally { IDisposable disposable = routine as IDisposable; if (disposable != null) { disposable.Dispose(); } } } private void CheckDeadline() { if (Time.realtimeSinceStartup > deadline) { throw new TimeoutException("Chef asset loading timed out; other startup work continues."); } } private byte[] ReadAsset(AssetFile entry) { if (entry == null || string.IsNullOrWhiteSpace(entry.file) || Path.GetFileName(entry.file) != entry.file || entry.file.Contains("..") || entry.sha256 == null || entry.sha256.Length != 64) { throw new InvalidDataException("Invalid character asset manifest entry"); } string text = Path.Combine(folder, entry.file); if (new FileInfo(text).Length > 67108864) { throw new InvalidDataException("Chef asset too large"); } byte[] array = File.ReadAllBytes(text); using SHA256 sHA = SHA256.Create(); if (BitConverter.ToString(sHA.ComputeHash(array)).Replace("-", "").ToLowerInvariant() != entry.sha256) { throw new InvalidDataException("Chef asset hash mismatch: " + entry.file); } return array; } private static SkinnedMeshRenderer Exact(GameObject model, string name) { Transform val = model.transform.Find(name); if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)((Component)val).GetComponent<SkinnedMeshRenderer>())) { throw new InvalidOperationException("Missing scoped CHEF renderer " + name); } return ((Component)val).GetComponent<SkinnedMeshRenderer>(); } private void PrepareTemplate(GameObject model) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) AdvancedSkinModel component = model.GetComponent<AdvancedSkinModel>(); if (Object.op_Implicit((Object)(object)component) && component.HasNativeSnapshot) { component.Prepare(); return; } SkinnedMeshRenderer val = Exact(model, "meshChef"); Animator component2 = model.GetComponent<Animator>(); Vector3 val2 = ((Component)val).transform.localScale - Vector3.one * 100f; if (!(((Vector3)(ref val2)).sqrMagnitude > 0.01f) && !(Quaternion.Angle(((Component)val).transform.localRotation, Quaternion.Euler(-90f, 0f, 0f)) > 0.1f)) { val2 = ((Component)val).transform.localPosition; if (!(((Vector3)(ref val2)).sqrMagnitude > 0.0001f)) { if (!Object.op_Implicit((Object)(object)component2) || val.bones.Length != manifest.nativeBoneNames.Length) { throw new InvalidOperationException("Chef requires the original CHEF skeleton"); } for (int i = 0; i < val.bones.Length; i++) { if (!Object.op_Implicit((Object)(object)val.bones[i]) || ((Object)val.bones[i]).name != manifest.nativeBoneNames[i]) { throw new InvalidOperationException("Native bone slot mismatch " + i); } } AdvancedSkinModel val3 = model.GetComponent<AdvancedSkinModel>(); if (!Object.op_Implicit((Object)(object)val3)) { val3 = model.AddComponent<AdvancedSkinModel>(); } val3.CaptureNativeTemplate(val, component2, nativeMesh, (Material[])(object)new Material[1] { nativeMaterial }); val3.Prepare(); return; } } throw new InvalidOperationException("CHEF renderer conversion contract changed"); } private IEnumerator Register() { string root = folder; int[] array = new int[7] { 1, 3, 4, 5, 6, 7, 8 }; for (int i = 0; i < array.Length; i++) { int tier = array[i]; folder = Path.Combine(root, "e" + tier); SkinId = "RodaniusChefE" + tier; fallbackMeshes.Clear(); deadline = Time.realtimeSinceStartup + 45f; { IEnumerator routine = RegisterOne(); try { while (true) { bool flag; try { flag = routine.MoveNext(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("CHEF_PACK_SKIN_FAILED tier=" + tier + " " + ex)); break; } if (!flag) { break; } yield return routine.Current; } } finally { IDisposable disposable = routine as IDisposable; if (disposable != null) { disposable.Dispose(); } } } } } private IEnumerator RegisterOne() { manifest = JsonUtility.FromJson<AssetManifest>(File.ReadAllText(Path.Combine(folder, "assets.json"))); if (manifest == null || manifest.schema != 1 || manifest.skinId != SkinId || string.IsNullOrWhiteSpace(manifest.revision) || manifest.nativeBoneNames == null || manifest.nativeBoneNames.Length != 61) { throw new InvalidDataException("Invalid character asset identity"); } MotionBank bank; using (MemoryStream memoryStream = new MemoryStream(ReadAsset(manifest.motion), writable: false)) { bank = MotionBank.Read((Stream)memoryStream); } if (bank.SkinId != SkinId) { throw new InvalidDataException("Motion identity mismatch"); } bank.Find("idle"); bank.Find("scuttle"); bank.Find("claw_grip_proof"); Mesh mesh; using (MemoryStream memoryStream2 = new MemoryStream(ReadAsset(manifest.mesh), writable: false)) { mesh = SkinMesh.Read((Stream)memoryStream2, bank); } Texture2D albedo = new Texture2D(2, 2, (TextureFormat)4, true, false) { name = "ChefPackAlbedo", filterMode = (FilterMode)1, anisoLevel = 4 }; if (!ImageConversion.LoadImage(albedo, ReadAsset(manifest.albedo), false)) { throw new InvalidDataException("Invalid character albedo"); } mesh.RecalculateTangents(); Texture2D normal = new Texture2D(2, 2, (TextureFormat)4, true, true) { name = SkinId + "Normal", filterMode = (FilterMode)2, anisoLevel = 4 }; if (!ImageConversion.LoadImage(normal, ReadAsset(manifest.normal), false)) { throw new InvalidDataException("Invalid CHEF normal texture"); } Texture2D portrait = new Texture2D(2, 2, (TextureFormat)4, false, false) { name = SkinId + "Portrait" }; if (!ImageConversion.LoadImage(portrait, ReadAsset(manifest.icon), false)) { throw new InvalidDataException("Invalid CHEF portrait"); } GameObject body = BodyCatalog.FindBodyPrefab("ChefBody"); if (!Object.op_Implicit((Object)(object)body) || !Object.op_Implicit((Object)(object)body.GetComponent<ModelLocator>())) { throw new InvalidOperationException("CHEF body unavailable"); } modelPrefab = ((Component)body.GetComponent<ModelLocator>().modelTransform).gameObject; ModelSkinController controller = modelPrefab.GetComponent<ModelSkinController>(); if (!Object.op_Implicit((Object)(object)controller) || controller.skins == null || controller.skins.Length == 0) { throw new InvalidOperationException("Native CHEF skins unavailable"); } if (controller.skins.Any((SkinDef s) => Object.op_Implicit((Object)(object)s) && ((Object)s).name == SkinId)) { yield break; } SkinDef baseSkin = controller.skins[0]; SkinDefParams parameters = baseSkin.skinDefParams; if (!Object.op_Implicit((Object)(object)parameters) && baseSkin.skinDefParamsAddress != null && ((AssetReference)baseSkin.skinDefParamsAddress).RuntimeKeyIsValid()) { AsyncOperationHandle<SkinDefParams> op = Addressables.LoadAssetAsync<SkinDefParams>(((AssetReference)baseSkin.skinDefParamsAddress).RuntimeKey); retainedAssets.Add(AsyncOperationHandle<SkinDefParams>.op_Implicit(op)); while (!op.IsDone) { CheckDeadline(); yield return null; } parameters = op.Result; } if (!Object.op_Implicit((Object)(object)parameters)) { throw new InvalidOperationException("Native skin parameters unavailable"); } SkinnedMeshRenderer[] componentsInChildren = modelPrefab.GetComponentsInChildren<SkinnedMeshRenderer>(true); SkinnedMeshRenderer target = componentsInChildren.Single((SkinnedMeshRenderer r) => ((Object)r).name == "meshChef"); MeshReplacement val = ((IEnumerable<MeshReplacement>)parameters.meshReplacements).FirstOrDefault((Func<MeshReplacement, bool>)((MeshReplacement r) => (Object)(object)r.renderer == (Object)(object)target)); nativeMesh = val.mesh; if (!Object.op_Implicit((Object)(object)nativeMesh) && val.meshAddress != null && ((AssetReference)val.meshAddress).RuntimeKeyIsValid()) { AsyncOperationHandle<Mesh> op2 = Addressables.LoadAssetAsync<Mesh>(((AssetReference)val.meshAddress).RuntimeKey); retainedAssets.Add(AsyncOperationHandle<Mesh>.op_Implicit(op2)); while (!op2.IsDone) { CheckDeadline(); yield return null; } nativeMesh = op2.Result; } if (!Object.op_Implicit((Object)(object)nativeMesh)) { nativeMesh = target.sharedMesh; } if (!Object.op_Implicit((Object)(object)nativeMesh) || nativeMesh.bindposes.Length != 61) { throw new InvalidOperationException("Native fallback mesh invalid"); } RendererInfo info = parameters.rendererInfos.First((RendererInfo r) => (Object)(object)r.renderer == (Object)(object)target); nativeMaterial = info.defaultMaterial; if (!Object.op_Implicit((Object)(object)nativeMaterial) && info.defaultMaterialAddress != null && ((AssetReference)info.defaultMaterialAddress).RuntimeKeyIsValid()) { AsyncOperationHandle<Material> op3 = Addressables.LoadAssetAsync<Material>(((AssetReference)info.defaultMaterialAddress).RuntimeKey); retainedAssets.Add(AsyncOperationHandle<Material>.op_Implicit(op3)); while (!op3.IsDone) { CheckDeadline(); yield return null; } nativeMaterial = op3.Result; } if (!Object.op_Implicit((Object)(object)nativeMaterial) || !Object.op_Implicit((Object)(object)nativeMaterial.shader)) { throw new InvalidOperationException("Native fallback material invalid"); } string[] rendererNames = RendererNames; foreach (string name in rendererNames) { SkinnedMeshRenderer nativeRenderer = Exact(modelPrefab, name); MeshReplacement val2 = parameters.meshReplacements.First((MeshReplacement r) => (Object)(object)r.renderer == (Object)(object)nativeRenderer); Mesh val3 = val2.mesh; if (!Object.op_Implicit((Object)(object)val3) && val2.meshAddress != null && ((AssetReference)val2.meshAddress).RuntimeKeyIsValid()) { AsyncOperationHandle<Mesh> op2 = Addressables.LoadAssetAsync<Mesh>(((AssetReference)val2.meshAddress).RuntimeKey); retainedAssets.Add(AsyncOperationHandle<Mesh>.op_Implicit(op2)); while (!op2.IsDone) { CheckDeadline(); yield return null; } val3 = op2.Result; } if (!Object.op_Implicit((Object)(object)val3)) { val3 = nativeRenderer.sharedMesh; } if (!Object.op_Implicit((Object)(object)val3) || val3.bindposes.Length != 61) { throw new InvalidOperationException("Missing fallback mesh " + name); } fallbackMeshes.Add(name, val3); } SurvivorDef val4 = SurvivorCatalog.FindSurvivorDefFromBody(body); if (!Object.op_Implicit((Object)(object)val4) || !Object.op_Implicit((Object)(object)val4.displayPrefab)) { throw new InvalidOperationException("CHEF display unavailable"); } CharacterModel componentInChildren = val4.displayPrefab.GetComponentInChildren<CharacterModel>(true); if (!Object.op_Implicit((Object)(object)componentInChildren)) { throw new InvalidOperationException("CHEF display model unavailable"); } displayModelPrefab = ((Component)componentInChildren).gameObject; PrepareTemplate(modelPrefab); PrepareTemplate(displayModelPrefab); ModelSkinController val5 = ((Component)componentInChildren).GetComponent<ModelSkinController>() ?? ((Component)componentInChildren).gameObject.AddComponent<ModelSkinController>(); Material val6 = new Material(nativeMaterial) { name = "mat" + SkinId }; val6.SetTexture("_MainTex", (Texture)(object)albedo); val6.SetColor("_Color", Color.white); if (val6.HasProperty("_Cull")) { val6.SetInt("_Cull", 0); } val6.SetTexture("_NormalTex", (Texture)(object)normal); val6.SetFloat("_NormalStrength", 0.7f); val6.SetFloat("_Smoothness", 0.16f); val6.SetFloat("_SpecularStrength", 0.15f); val6.SetFloat("_SpecularExponent", 8f); val6.SetFloat("_EmPower", 0f); val6.SetTexture("_EmTex", (Texture)(object)Texture2D.blackTexture); val6.DisableKeyword("FLOWMAP"); val6.SetFloat("_FlowmapOn", 0f); val6.SetFloat("_FlowEmissionStrength", 0f); val6.DisableKeyword("FORCE_SPEC"); val6.SetFloat("_ForceSpecOn", 0f); val6.DisableKeyword("LIMBREMOVAL"); val6.SetFloat("_LimbRemovalOn", 0f); AdvancedSkinRegistry.Register(new AdvancedSkinDefinition { Mesh = mesh, Motion = bank, FallbackClip = "idle", AirTransitionSeconds = 0f, CreateEffects = (SkinnedMeshRenderer renderer) => (ISkinEffectDriver)(object)new ChefEffects(renderer), CreateMotionSource = (Animator animator, MotionBank motion) => (ISkinMotionSource)(object)new ChefMotion(animator, motion) }); Mesh empty = new Mesh { name = SkinId + "EmptyNativeVisuals" }; empty.vertices = Array.Empty<Vector3>(); empty.triangles = Array.Empty<int>(); GameObject[] array = (GameObject[])(object)new GameObject[2] { modelPrefab, displayModelPrefab }; foreach (GameObject model in array) { model.AddComponent<ChefNativeVisuals>().Configure(Exact(model, "meshChef"), mesh, empty, (from n in RendererNames.Skip(1) select Exact(model, n)).ToArray(), (from n in RendererNames.Skip(1) select fallbackMeshes[n]).ToArray()); } info.defaultMaterial = val6; info.defaultMaterialAddress = new AssetReferenceT<Material>(""); SkinDefParams val7 = ScriptableObject.CreateInstance<SkinDefParams>(); val7.rendererInfos = (RendererInfo[])(object)new RendererInfo[1] { info }; val7.meshReplacements = ((IEnumerable<string>)RendererNames).Select((Func<string, MeshReplacement>)((string n) => new MeshReplacement { renderer = (Renderer)(object)Exact(modelPrefab, n), mesh = ((n == "meshChef") ? mesh : empty), meshAddress = new AssetReferenceT<Mesh>("") })).ToArray(); SkinDef val8 = ScriptableObject.CreateInstance<SkinDef>(); ((Object)val8).name = SkinId; val8.nameToken = SkinId.ToUpperInvariant() + "_NAME"; LanguageAPI.Add(val8.nameToken, manifest.displayName); val8.unlockableDef = null; val8.rootObject = modelPrefab; val8.baseSkins = (SkinDef[])(object)new SkinDef[1] { baseSkin }; val8.skinDefParams = val7; val8.icon = Sprite.Create(portrait, new Rect(0f, 0f, (float)((Texture)portrait).width, (float)((Texture)portrait).height), new Vector2(0.5f, 0.5f)); registrations.Add(AdvancedSkinApplications.Register(val8, mesh)); val5.skins = (SkinDef[])(controller.skins = controller.skins.Concat((IEnumerable<SkinDef>)(object)new SkinDef[1] { val8 }).ToArray()).Clone(); registered = true; ((BaseUnityPlugin)this).Logger.LogInfo((object)("CHEF_PACK_REGISTERED skin=" + SkinId + " revision=" + manifest.revision + " customBones=" + bank.Bones.Length + " unlocked=true audio=not_integrated items=uncalibrated gameplay=untested skills=authored_motion_native_effects_playtest")); } private void SyncDisplaySkins() { if (!registered) { return; } try { if (!Object.op_Implicit((Object)(object)displayModelPrefab)) { throw new InvalidOperationException("Prepared character display was destroyed"); } PrepareTemplate(displayModelPrefab); ModelSkinController component = displayModelPrefab.GetComponent<ModelSkinController>(); if (!Object.op_Implicit((Object)(object)component)) { throw new InvalidOperationException("Prepared character display controller was removed"); } component.skins = (SkinDef[])modelPrefab.GetComponent<ModelSkinController>().skins.Clone(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("CHEF_PACK_DISPLAY_FAILED " + ex)); } } private void OnDestroy() { ChefNativeEvents.Uninstall(); RoR2Application.onLoad = (Action)Delegate.Remove(RoR2Application.onLoad, new Action(SyncDisplaySkins)); MainMenuController.OnMainMenuInitialised -= SyncDisplaySkins; foreach (IDisposable registration in registrations) { registration.Dispose(); } registrations.Clear(); if ((Object)(object)instance == (Object)(object)this) { instance = null; } } } internal static class ChefActor { internal static CharacterBody Resolve(Component member) { if (!Object.op_Implicit((Object)(object)member)) { return null; } CharacterModel componentInParent = member.GetComponentInParent<CharacterModel>(); if (Object.op_Implicit((Object)(object)componentInParent) && Object.op_Implicit((Object)(object)componentInParent.body) && Object.op_Implicit((Object)(object)componentInParent.body.modelLocator) && (Object)(object)componentInParent.body.modelLocator.modelTransform == (Object)(object)((Component)componentInParent).transform) { return componentInParent.body; } AdvancedSkinModel componentInParent2 = member.GetComponentInParent<AdvancedSkinModel>(); if (!Object.op_Implicit((Object)(object)componentInParent2)) { return null; } return componentInParent2.AssociatedBody; } internal static bool Boosted(CharacterBody body) { if (Object.op_Implicit((Object)(object)body)) { if ((!Object.op_Implicit((Object)(object)Buffs.Boosted) || !body.HasBuff(Buffs.Boosted)) && (!Object.op_Implicit((Object)(object)Buffs.boostedFireEffect) || !body.HasBuff(Buffs.boostedFireEffect))) { if (Object.op_Implicit((Object)(object)Buffs.boostedFrostEffect)) { return body.HasBuff(Buffs.boostedFrostEffect); } return false; } return true; } return false; } } public sealed class ChefMotion : ISkinMotionSource, IDisposable { private sealed class Route { public string Clip; public string Group; public int Priority; public int[] Mask; public Route(string c, string g, int p, int[] m = null) { Clip = c; Group = g; Priority = p; Mask = m; } } private readonly Animator animator; private readonly MotionBank bank; private readonly Dictionary<string, MotionClip> clips; private readonly Dictionary<int, LayerMotionClock> clocks = new Dictionary<int, LayerMotionClock>(); private readonly List<AnimatorClipInfo> infos = new List<AnimatorClipInfo>(); private readonly int[] upper; private readonly int[] right; private readonly int[] left; private readonly int[] eyes; private readonly ObservedMotionChannel gaitChannel = new ObservedMotionChannel(); private readonly HashSet<string> floatParameters; private double idlePhase; private double walkPhase; private double deathAt = -1.0; private float movement; private bool disposed; private readonly ChefActionTimeline actionTimeline = new ChefActionTimeline(); private EntityState sustained; private EntityState suppressedState; private string sustainedKind; private float sustainedStart; private CharacterBody trackedBody; private EntityStateMachine[] machines = Array.Empty<EntityStateMachine>(); private readonly HashSet<string> canceledGroups = new HashSet<string>(); private readonly Dictionary<string, Route> routes = new Dictionary<string, Route>(); private CharacterBody BindBody() { CharacterBody val = ChefActor.Resolve((Component)(object)animator); if ((Object)(object)val != (Object)(object)trackedBody) { trackedBody = val; machines = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponents<EntityStateMachine>() : Array.Empty<EntityStateMachine>()); actionTimeline.Clear(); sustained = null; suppressedState = null; canceledGroups.Clear(); } return val; } private EntityState ActiveSecondary() { return (from m in machines where Object.op_Implicit((Object)(object)m) && m.state != null select m.state).FirstOrDefault((Func<EntityState, bool>)((EntityState s) => s is Sear || s is IceBox)); } private void OnNativeAction(ChefNativeEvents.Signal signal) { if (disposed || !Object.op_Implicit((Object)(object)animator) || signal.State == null) { return; } CharacterBody val = BindBody(); if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)signal.State.outer) || (Object)(object)((Component)signal.State.outer).GetComponent<CharacterBody>() != (Object)(object)val) { return; } string kind = signal.Kind; double now = Time.time; string item = ((kind.StartsWith("fire") || kind.StartsWith("ice")) ? "secondary" : (kind.StartsWith("glaze") ? "glaze" : ((kind == "throw") ? "primary" : "transformation"))); canceledGroups.Remove(item); switch (kind) { case "fire-start": case "ice-start": actionTimeline.Remove("secondary"); suppressedState = null; sustained = signal.State; sustainedKind = ((kind == "fire-start") ? "sear" : "icebox"); sustainedStart = Time.time; break; case "fire-end": case "ice-end": if (sustained == signal.State) { sustained = null; sustainedKind = null; } if (ChefActionTimeline.PlayExit(kind, signal.Boosted, signal.Duration)) { actionTimeline.Trigger("secondary", (kind == "fire-end") ? "sear_end" : "icebox_end", now, signal.Duration); } break; case "throw": actionTimeline.Trigger("primary", signal.Boosted ? "throw_boost" : "throw", now, signal.Duration); break; case "fire-burst": actionTimeline.Trigger("secondary", "sear_burst", now, signal.Duration); break; case "ice-burst": actionTimeline.Trigger("secondary", "icebox_burst", now, signal.Duration); break; case "glaze": actionTimeline.Trigger("glaze", "glaze_prep", now, signal.Duration); break; case "glaze-shot": actionTimeline.Trigger("glaze", "glaze", now, signal.Duration, 0.18); break; case "yes-chef": actionTimeline.Trigger("transformation", "yes_chef", now, signal.Duration); break; } } private void CollectNativeActions(List<NativeMotionCandidate> observed) { EntityState val = ActiveSecondary(); if (observed.Any((NativeMotionCandidate c) => c.Motion.Group == "roll" && c.Motion.Samples.Any((WeightedMotion x) => x.Weight > 0f))) { actionTimeline.Clear(); suppressedState = val; sustained = null; string[] array = new string[4] { "primary", "secondary", "glaze", "transformation" }; foreach (string item in array) { canceledGroups.Add(item); } return; } if (val != null && val != suppressedState && val != sustained) { actionTimeline.Remove("secondary"); sustained = val; sustainedKind = ((val is IceBox) ? "icebox" : "sear"); sustainedStart = Time.time - ChefNativeEvents.Number(val, (val is IceBox) ? "fixedAge" : "stopwatch", 0f); canceledGroups.Remove("secondary"); } else if (val == null) { sustained = null; } if (sustained != null) { float num2 = Mathf.Max(0.01f, ChefNativeEvents.Number(sustained, "entryDuration", 0.3f)); float num3 = ((sustainedKind == "sear") ? ChefNativeEvents.Number(sustained, "stopwatch", Time.time - sustainedStart) : (Time.time - sustainedStart)); double num4; string id; if (sustainedKind == "sear") { num4 = ChefActionTimeline.FirePhase(num3, num2, ChefNativeEvents.Number(sustained, "flamethrowerDuration", 1f), ChefNativeEvents.Number(sustained, "exitDuration", 0.3f), ChefNativeEvents.Flag(sustained, "flamethrowerStarted"), ChefNativeEvents.Flag(sustained, "flamethrowerEnded"), ChefNativeEvents.Flag(sustained, "hasBoost") && !ChefNativeEvents.Flag(sustained, "allBoostProjectilesFired"), out id); if (id == "sear_loop") { num4 /= (double)clips[id].Duration; } } else { bool flag = num3 < num2; id = "icebox" + (flag ? "_start" : "_loop"); num4 = (flag ? (num3 / num2) : ((num3 - num2) / clips[id].Duration)); } observed.Add(Candidate(id, "secondary", 30, -60000, Math.Max(0.0, num4), 1f, upper, "sustained:" + sustainedStart, 1500)); } foreach (ChefActionTimeline.Sample item2 in actionTimeline.Samples(Time.time)) { int num5 = ((item2.Group == "primary") ? 20 : ((item2.Group == "glaze") ? 25 : ((item2.Group == "transformation") ? 60 : 30))); int[] mask = ((item2.Group == "primary") ? ((item2.Clip == "throw_boost") ? upper : right) : ((item2.Group == "glaze") ? left : upper)); observed.Add(Candidate(item2.Clip, item2.Group, num5, -61000 - num5, item2.Phase, item2.Weight, mask, item2.Token, 2000)); } } private int[] Mask(Func<string, bool> predicate) { return (from x in bank.Bones.Select((Bone b, int i) => new { b.Name, i }) where predicate(x.Name) select x.i).ToArray(); } private void Map(string native, string clip, string group, int priority, int[] mask = null) { routes.Add(native, new Route(clip, group, priority, mask)); } public ChefMotion(Animator animator, MotionBank bank) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown this.animator = animator; this.bank = bank; clips = bank.Clips.ToDictionary((MotionClip c) => c.Id); floatParameters = new HashSet<string>(from p in animator.parameters where (int)p.type == 1 select p.name); upper = Mask(delegate(string n) { switch (n) { default: if (!n.StartsWith("Arm_") && !n.StartsWith("Forearm_") && !n.StartsWith("Tool_") && !n.StartsWith("Wing_")) { return n.StartsWith("Tail_"); } break; case "Body": case "Head": case "Jaw": break; } return true; }); right = Mask(delegate(string n) { switch (n) { default: return n.StartsWith("Tail_"); case "Body": case "Head": case "Arm_R": case "Forearm_R": case "Tool_R": return true; } }); left = Mask(delegate(string n) { switch (n) { default: return n.StartsWith("Tail_"); case "Body": case "Head": case "Arm_L": case "Forearm_L": case "Tool_L": return true; } }); eyes = Mask((string n) => n == "Head" || n.StartsWith("Wing_")); Map("Chef_SliceAndDice", "throw", "primary", 20, right); Map("PrimaryDice1_Return_Start", "recall", "primary", 20, right); Map("PrimaryDice1_Return_Hold", "cleaver_hold", "primary", 20, right); Map("PrimaryDice1_Return_Catch", "catch", "primary", 20, right); Map("PrimaryDice1_Return_All", "catch", "primary", 20, right); Map("root|PrimaryDice1_Oops", "flinch", "primary", 20, right); Map("ChefGlazeStart", "glaze_prep", "glaze", 25, left); Map("Chef_Glaze3Shots", "glaze_boost", "glaze", 25, left); Map("Glaze_Glaze3Shot_Exit", "glaze_end", "glaze", 25, left); Map("SearBlaze_Prep", "sear_start", "secondary", 30, upper); Map("SearBlaze_Loop", "sear_loop", "secondary", 30, upper); Map("SearBlaze_Exit", "sear_end", "secondary", 30, upper); Map("YesChef", "yes_chef", "transformation", 60, upper); string[][] array = new string[3][] { new string[2] { "Chef_JumpStartTweaked", "jump_start" }, new string[2] { "Chef_JumpUp", "jump_up" }, new string[2] { "Chef_JumpDown", "fall" } }; foreach (string[] array2 in array) { Map(array2[0], array2[1], "airborne", 10); } array = new string[10][] { new string[2] { "Rolypoly_Enter", "roll_enter" }, new string[2] { "Rolypoly_ChargeLoop", "roll_charge" }, new string[2] { "Chef_RolyPolyStart", "roll_enter" }, new string[2] { "Chef_RolyPoly", "roll_loop" }, new string[2] { "ExitRolyPoly", "roll_exit" }, new string[2] { "Boosted_Rolypoly_Start", "roll_enter" }, new string[2] { "Boosted_Rolypoly_Loop", "roll_boost" }, new string[2] { "Chef_RolyPoly_JumpStart", "roll_enter" }, new string[2] { "Chef_RolyPoly_JumpUp", "roll_charge" }, new string[2] { "Chef_RolyPoly_JumpDown", "roll_charge" } }; foreach (string[] array3 in array) { Map(array3[0], array3[1], "roll", 40); } Map("Chef_JumpLand", "land", "landing", 11); Map("Chef_RolyPoly_JumpLand", "roll_exit", "roll-landing", 41); string[] array4 = new string[2] { ",Additive", ",Override" }; foreach (string text in array4) { Map("OilSpillJump" + text, "oil_jump", "oil", 45); Map("OilSpillLoop" + text, "oil_loop", "oil", 45); Map("OilSpillLand" + text, "oil_land", "oil", 45); } Map("Chef_Flinch1", "flinch", "flinch", 70, upper); Map("Chef_Flinch2", "flinch", "flinch", 70, upper); Map("LobbyIntro", "lobby_intro", "display", 10); array4 = new string[3] { "Chef_LobbyIdle", "Chef_LobbyIdleAlternate", "Chef_LobbyIdleAlternate2" }; foreach (string native in array4) { Map(native, "lobby_idle", "display", 10); } foreach (Route value in routes.Values) { if (!clips.ContainsKey(value.Clip)) { throw new InvalidOperationException("Missing CHEF action " + value.Clip); } if (value.Mask != null && value.Mask.Length == 0) { throw new InvalidOperationException("Empty CHEF action mask"); } } array4 = new string[16] { "idle", "scuttle", "sprint", "backpedal", "strafe_left", "strafe_right", "death", "throw_boost", "empowered", "aim_yaw", "aim_pitch", "icebox_start", "icebox_loop", "icebox_end", "sear_burst", "icebox_burst" }; foreach (string text2 in array4) { if (!clips.ContainsKey(text2)) { throw new InvalidOperationException("Missing CHEF motion " + text2); } } ChefNativeEvents.Observed += OnNativeAction; } private NativeMotionCandidate Candidate(string id, string group, int priority, int layer, double time, float weight, int[] mask = null, string token = null, int rank = 1000) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_005a: 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) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Expected O, but got Unknown NativeMotionCandidate val = new NativeMotionCandidate(); val.SourceLayer = layer; val.SourceRank = rank; MotionLayer val2 = new MotionLayer(); val2.Group = group; val2.Priority = priority; val2.Blend = (MotionBlend)0; val2.BoneMask = mask; val2.Samples = (WeightedMotion[])(object)new WeightedMotion[1] { new WeightedMotion { Clip = clips[id], Time = Math.Max(0.0, time), Weight = Mathf.Clamp01(weight), Token = (token ?? group) } }; val.Motion = val2; return val; } private void Collect(int layer, AnimatorStateInfo state, MotionOccurrence occurrence, float transition, List<NativeMotionCandidate> result, bool boosted) { //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) string layerName = animator.GetLayerName(layer); float num = ((layer == 0) ? 1f : Mathf.Clamp01(animator.GetLayerWeight(layer))); float num2 = infos.Sum((AnimatorClipInfo x) => Mathf.Max(0f, ((AnimatorClipInfo)(ref x)).weight)); if (num <= 0f) { return; } string text = ((((AnimatorStateInfo)(ref state)).fullPathHash == Animator.StringToHash(layerName + ".FireDice")) ? "throw" : ((((AnimatorStateInfo)(ref state)).fullPathHash == Animator.StringToHash(layerName + ".FireSliceAndDice")) ? "throw_boost" : null)); if (text != null) { if (!canceledGroups.Contains("primary")) { result.Add(Candidate(text, "primary", 20, -1000 - layer, ((AnimatorStateInfo)(ref state)).normalizedTime, transition * num, (text == "throw_boost") ? upper : right, layer + ":" + occurrence.Serial + ":" + text, layerName.Contains("Override") ? 30 : 20)); } } else { if (num2 <= 1E-06f) { return; } foreach (AnimatorClipInfo info in infos) { AnimatorClipInfo current = info; if (Object.op_Implicit((Object)(object)((AnimatorClipInfo)(ref current)).clip) && routes.TryGetValue(((Object)((AnimatorClipInfo)(ref current)).clip).name, out var value) && !canceledGroups.Contains(value.Group)) { string text2 = value.Clip; if (((AnimatorStateInfo)(ref state)).fullPathHash == Animator.StringToHash(layerName + ".FireDice")) { text2 = "throw"; value = new Route(text2, "primary", 20, right); } else if (((AnimatorStateInfo)(ref state)).fullPathHash == Animator.StringToHash(layerName + ".FireSliceAndDice")) { text2 = "throw_boost"; value = new Route(text2, "primary", 20, right); } int rank = (layerName.Contains("Override") ? 30 : (layerName.Contains("Additive") ? 20 : 10)); int layer2 = -1000 - layer; result.Add(Candidate(text2, value.Group, value.Priority, layer2, ((AnimatorStateInfo)(ref state)).normalizedTime, ((AnimatorClipInfo)(ref current)).weight / num2 * transition * num, value.Mask, layer + ":" + occurrence.Serial + ":" + text2, rank)); } } } } public void Observe(List<NativeMotionCandidate> candidates, HashSet<string> replaced) { //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_02dc: Unknown result type (might be due to invalid IL or missing references) //IL_02e1: 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_02f3: Unknown result type (might be due to invalid IL or missing references) //IL_02f4: Unknown result type (might be due to invalid IL or missing references) //IL_02f9: Unknown result type (might be due to invalid IL or missing references) //IL_0304: Unknown result type (might be due to invalid IL or missing references) //IL_030b: Unknown result type (might be due to invalid IL or missing references) //IL_030d: Unknown result type (might be due to invalid IL or missing references) //IL_0312: Unknown result type (might be due to invalid IL or missing references) //IL_031f: Expected O, but got Unknown //IL_0324: Expected O, but got Unknown //IL_0355: Unknown result type (might be due to invalid IL or missing references) //IL_035a: Unknown result type (might be due to invalid IL or missing references) //IL_0372: Unknown result type (might be due to invalid IL or missing references) //IL_0377: Unknown result type (might be due to invalid IL or missing references) //IL_0391: 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_0385: Unknown result type (might be due to invalid IL or missing references) //IL_0396: Unknown result type (might be due to invalid IL or missing references) //IL_040c: Unknown result type (might be due to invalid IL or missing references) //IL_03b1: Unknown result type (might be due to invalid IL or missing references) //IL_03b6: Unknown result type (might be due to invalid IL or missing references) //IL_03b9: Expected O, but got Unknown //IL_03be: Expected O, but got Unknown //IL_053f: Unknown result type (might be due to invalid IL or missing references) //IL_0544: Unknown result type (might be due to invalid IL or missing references) //IL_044a: Unknown result type (might be due to invalid IL or missing references) //IL_0588: Unknown result type (might be due to invalid IL or missing references) //IL_058d: Unknown result type (might be due to invalid IL or missing references) //IL_05b5: Unknown result type (might be due to invalid IL or missing references) //IL_05ba: Unknown result type (might be due to invalid IL or missing references) //IL_0638: Unknown result type (might be due to invalid IL or missing references) if (disposed || !Object.op_Implicit((Object)(object)animator)) { return; } MotionBinding[] bindings = bank.Bindings; foreach (MotionBinding val in bindings) { replaced.Add(val.Clip); } CharacterBody val2 = BindBody(); bool num = Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)val2.healthComponent) && !val2.healthComponent.alive; bool flag = ChefActor.Boosted(val2); float num2 = Mathf.Min(Time.deltaTime, 0.1f); idlePhase += num2 / clips["idle"].Duration; if (num) { actionTimeline.Clear(); sustained = null; if (deathAt < 0.0) { deathAt = Time.time; } candidates.Add(Candidate("death", "death", 1000, -90000, ((double)Time.time - deathAt) / (double)clips["death"].Duration, 1f)); return; } deathAt = -1.0; Vector3 val3 = Vector3.zero; if (Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)val2.characterMotor) && val2.characterMotor.isGrounded) { val3 = val2.characterMotor.velocity; val3.y = 0f; val3 = ((Component)animator).transform.InverseTransformDirection(val3); } float magnitude = ((Vector3)(ref val3)).magnitude; movement = Mathf.MoveTowards(movement, (float)((magnitude > 0.15f) ? 1 : 0), num2 * 6f); walkPhase += num2 * Mathf.Min(magnitude / 0.65f, 3.5f); string text = ((!(Mathf.Abs(val3.x) > Mathf.Abs(val3.z))) ? ((val3.z < -0.1f) ? "backpedal" : ((Object.op_Implicit((Object)(object)val2) && val2.isSprinting) ? "sprint" : "scuttle")) : ((val3.x < 0f) ? "strafe_left" : "strafe_right")); candidates.Add(Candidate("idle", "base-idle", 1, -1, idlePhase, 1f - movement)); WeightedMotion[] array = gaitChannel.Sample(clips[text], text, walkPhase, (double)Time.time, 0.12f, (string)null, 0, false); WeightedMotion[] array2 = array; foreach (WeightedMotion obj in array2) { obj.Weight *= movement; } candidates.Add(new NativeMotionCandidate { SourceLayer = -1, SourceRank = 1000, Motion = new MotionLayer { Group = "base-gait", Priority = 1, Blend = (MotionBlend)0, Samples = array } }); List<NativeMotionCandidate> list = new List<NativeMotionCandidate>(); AnimatorTransitionInfo animatorTransitionInfo; AnimatorStateInfo val4; for (int j = 0; j < animator.layerCount; j++) { bool flag2 = animator.IsInTransition(j); float num3; if (!flag2) { num3 = 0f; } else { animatorTransitionInfo = animator.GetAnimatorTransitionInfo(j); num3 = Mathf.Clamp01(((AnimatorTransitionInfo)(ref animatorTransitionInfo)).normalizedTime); } float num4 = num3; AnimatorStateInfo currentAnimatorStateInfo = animator.GetCurrentAnimatorStateInfo(j); AnimatorStateInfo val5; if (!flag2) { val4 = default(AnimatorStateInfo); val5 = val4; } else { val5 = animator.GetNextAnimatorStateInfo(j); } AnimatorStateInfo state = val5; if (!clocks.TryGetValue(j, out var value)) { Dictionary<int, LayerMotionClock> dictionary = clocks; int key = j; LayerMotionClock val6 = new LayerMotionClock(); value = val6; dictionary[key] = val6; } value.Observe(((AnimatorStateInfo)(ref currentAnimatorStateInfo)).fullPathHash, (double)((AnimatorStateInfo)(ref currentAnimatorStateInfo)).normalizedTime, flag2, ((AnimatorStateInfo)(ref state)).fullPathHash, (double)((AnimatorStateInfo)(ref state)).normalizedTime, (double)Time.time); infos.Clear(); animator.GetCurrentAnimatorClipInfo(j, infos); Collect(j, currentAnimatorStateInfo, value.Current, 1f - num4, list, flag); if (flag2) { infos.Clear(); animator.GetNextAnimatorClipInfo(j, infos); Collect(j, state, value.Next, num4, list, flag); } } CollectNativeActions(list); ChefActionTimeline.FilterCanceled(list, canceledGroups); candidates.AddRange(NativeMotionComposition.ResolveSources((IEnumerable<NativeMotionCandidate>)list)); string[][] array3 = new string[2][] { new string[3] { "AimYaw", "aimYawCycle", "aim_yaw" }, new string[3] { "AimPitch", "aimPitchCycle", "aim_pitch" } }; foreach (string[] array4 in array3) { int layerIndex = animator.GetLayerIndex(array4[0]); if (layerIndex < 0 || !floatParameters.Contains(array4[1])) { continue; } bool flag3 = animator.IsInTransition(layerIndex); float num5; if (!flag3) { num5 = 0f; } else { animatorTransitionInfo = animator.GetAnimatorTransitionInfo(layerIndex); num5 = Mathf.Clamp01(((AnimatorTransitionInfo)(ref animatorTransitionInfo)).normalizedTime); } float num6 = num5; int num7 = Animator.StringToHash(array4[0] + ((array4[0] == "AimYaw") ? ".YawControl" : ".PitchControl")); val4 = animator.GetCurrentAnimatorStateInfo(layerIndex); float num8 = ((((AnimatorStateInfo)(ref val4)).fullPathHash == num7) ? (1f - num6) : 0f); float num9; if (flag3) { val4 = animator.GetNextAnimatorStateInfo(layerIndex); if (((AnimatorStateInfo)(ref val4)).fullPathHash == num7) { num9 = num6; goto IL_05d0; } } num9 = 0f; goto IL_05d0; IL_05d0: float num10 = num8 + num9; float num11 = Mathf.Clamp01(animator.GetLayerWeight(layerIndex)) * num10; if (!(num11 <= 0f)) { NativeMotionCandidate val7 = Candidate(array4[2], array4[0], 80, -70000 - layerIndex, Mathf.Clamp01(animator.GetFloat(array4[1])), num11, upper); val7.Motion.Blend = (MotionBlend)1; candidates.Add(val7); } } if (flag) { candidates.Add(Candidate("empowered", "boost-eyes", 5, -80000, Time.time / clips["empowered"].Duration, 1f, eyes)); } } public void Dispose() { disposed = true; ChefNativeEvents.Observed -= OnNativeAction; actionTimeline.Clear(); sustained = null; trackedBody = null; machines = Array.Empty<EntityStateMachine>(); canceledGroups.Clear(); clocks.Clear(); infos.Clear(); } } public sealed class ChefEffects : ISkinEffectDriver, IDisposable { private readonly SkinnedMeshRenderer renderer; private Transform tool; private Vector3 visibleScale; private bool masked; private bool disposed; private readonly Material original; private readonly Material accent; private readonly Color originalColor; private float boostBlend; public ChefEffects(SkinnedMeshRenderer renderer) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //IL_0072: 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_0077: Unknown result type (might be due to invalid IL or missing references) this.renderer = renderer; original = ((Renderer)renderer).sharedMaterial; if (!Object.op_Implicit((Object)(object)original)) { throw new InvalidOperationException("Chef material unavailable"); } accent = new Material(original) { name = "ChefActorAccent" }; originalColor = (original.HasProperty("_Color") ? original.GetColor("_Color") : Color.white); ((Renderer)renderer).sharedMaterial = accent; } public void Update() { //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) if (disposed || !Object.op_Implicit((Object)(object)renderer)) { return; } if (!Object.op_Implicit((Object)(object)tool)) { tool = ((IEnumerable<Transform>)renderer.bones).FirstOrDefault((Func<Transform, bool>)((Transform b) => Object.op_Implicit((Object)(object)b) && ((Object)b).name == "Tool_R")); } CharacterBody val = ChefActor.Resolve((Component)(object)renderer); ChefController val2 = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<ChefController>() : null); if (Object.op_Implicit((Object)(object)tool)) { visibleScale = tool.localScale; masked = false; if (Object.op_Implicit((Object)(object)val2) && val2.cleaversAway) { tool.localScale = Vector3.zero; masked = true; } } bool flag = ChefActor.Boosted(val) && (!Object.op_Implicit((Object)(object)val.healthComponent) || val.healthComponent.alive); boostBlend = Mathf.MoveTowards(boostBlend, (float)(flag ? 1 : 0), Time.deltaTime * 5f); if (Object.op_Implicit((Object)(object)accent) && (Object)(object)((Renderer)renderer).sharedMaterial == (Object)(object)accent) { bool flag2 = Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)Buffs.boostedFrostEffect) && val.HasBuff(Buffs.boostedFrostEffect); accent.SetColor("_Color", Color.Lerp(originalColor, flag2 ? new Color(0.7f, 0.92f, 1f) : new Color(1f, 0.83f, 0.6f), boostBlend * 0.65f)); } } public void Dispose() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) if (!disposed) { disposed = true; if (masked && Object.op_Implicit((Object)(object)tool)) { tool.localScale = visibleScale; } if (Object.op_Implicit((Object)(object)renderer) && (Object)(object)((Renderer)renderer).sharedMaterial == (Object)(object)accent) { ((Renderer)renderer).sharedMaterial = original; } if (Object.op_Implicit((Object)(object)accent)) { Object.Destroy((Object)(object)accent); } masked = false; } } } [DefaultExecutionOrder(32001)] public sealed class ChefNativeVisuals : MonoBehaviour { [SerializeField] private SkinnedMeshRenderer target; [SerializeField] private Mesh custom; [SerializeField] private Mesh empty; [SerializeField] private SkinnedMeshRenderer[] companions; [SerializeField] private Mesh[] originals; public void Configure(SkinnedMeshRenderer target, Mesh custom, Mesh empty, SkinnedMeshRenderer[] companions, Mesh[] originals) { this.target = target; this.custom = custom; this.empty = empty; this.companions = companions; this.originals = originals; } private void LateUpdate() { if (Object.op_Implicit((Object)(object)target) && companions != null && !((Object)(object)target.sharedMesh == (Object)(object)custom)) { Restore(); } } private void Restore() { if (companions == null) { return; } for (int i = 0; i < companions.Length; i++) { if (Object.op_Implicit((Object)(object)companions[i]) && (Object)(object)companions[i].sharedMesh == (Object)(object)empty) { companions[i].sharedMesh = originals[i]; } } } private void OnDestroy() { Restore(); } } internal static class ChefNativeEvents { internal sealed class Signal { public EntityState State; public string Kind; public float Duration; public bool Boosted; } private static bool installed; private static readonly Dictionary<string, FieldInfo> fields = new Dictionary<string, FieldInfo>(); private static bool warned; internal static event Action<Signal> Observed; internal static float Number(EntityState s, string n, float fallback) { if (!(Read(s, n) is float num) || float.IsNaN(num) || float.IsInfinity(num)) { return fallback; } return num; } internal static bool Flag(EntityState s, string n) { object obj = Read(s, n); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } private static object Read(EntityState s, string n) { try { if (s == null) { return null; } string key = ((object)s).GetType().FullName + ":" + n; if (!fields.TryGetValue(key, out var value)) { value = ((object)s).GetType().GetField(n, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); fields[key] = value; } return (value != null) ? value.GetValue(s) : ((object)s).GetType().GetProperty(n, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(s); } catch (Exception) { if (!warned) { warned = true; Debug.LogWarning((object)"CHEF CHEF presentation observation unavailable; native gameplay preserved."); } return null; } } private static void Emit(EntityState s, string kind, float duration = 0f, bool boost = false) { Action<Signal> observed = ChefNativeEvents.Observed; if (observed == null) { return; } Signal obj = new Signal { State = s, Kind = kind, Duration = duration, Boosted = boost }; Delegate[] invocationList = observed.GetInvocationList(); for (int i = 0; i < invocationList.Length; i++) { Action<Signal> action = (Action<Signal>)invocationList[i]; try { action(obj); } catch (Exception ex) { Debug.LogException(ex); } } } internal static void Install() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Expected O, but got Unknown if (!installed) { installed = true; Dice.PlayThrowAnims += new hook_PlayThrowAnims(Throw); Sear.OnEnter += new hook_OnEnter(FireEnter); Sear.OnExit += new hook_OnExit(FireExit); Sear.FireBoostedFireball += new hook_FireBoostedFireball(FireBurst); IceBox.OnEnter += new hook_OnEnter(IceEnter); IceBox.OnExit += new hook_OnExit(IceExit); IceBox.FireBoostedIceCube += new hook_FireBoostedIceCube(IceBurst); Glaze.OnEnter += new hook_OnEnter(Glaze); Glaze.FireGrenade += new hook_FireGrenade(GlazeShot); YesChef.OnEnter += new hook_OnEnter(YesChef); } } internal static void Uninstall() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Expected O, but got Unknown if (installed) { installed = false; Dice.PlayThrowAnims -= new hook_PlayThrowAnims(Throw); Sear.OnEnter -= new hook_OnEnter(FireEnter); Sear.OnExit -= new hook_OnExit(FireExit); Sear.FireBoostedFireball -= new hook_FireBoostedFireball(FireBurst); IceBox.OnEnter -= new hook_OnEnter(IceEnter); IceBox.OnExit -= new hook_OnExit(IceExit); IceBox.FireBoostedIceCube -= new hook_FireBoostedIceCube(IceBurst); Glaze.OnEnter -= new hook_OnEnter(Glaze); Glaze.FireGrenade -= new hook_FireGrenade(GlazeShot); YesChef.OnEnter -= new hook_OnEnter(YesChef); ChefNativeEvents.Observed = null; fields.Clear(); } } private static void Throw(orig_PlayThrowAnims orig, Dice self, float duration) { orig.Invoke(self, duration); Emit((EntityState)(object)self, "throw", duration, Flag((EntityState)(object)self, "hasBoost")); } private static void FireEnter(orig_OnEnter orig, Sear self) { orig.Invoke(self); Emit((EntityState)(object)self, "fire-start"); } private static void FireExit(orig_OnExit orig, Sear self) { bool flag = Flag((EntityState)(object)self, "flamethrowerEnded"); orig.Invoke(self); Emit((EntityState)(object)self, "fire-end", flag ? 0f : Number((EntityState)(object)self, "exitDuration", 0.3f)); } private static void FireBurst(orig_FireBoostedFireball orig, Sear self, string muzzle) { orig.Invoke(self, muzzle); Emit((EntityState)(object)self, "fire-burst", 0.32f); } private static void IceEnter(orig_OnEnter orig, IceBox self) { orig.Invoke(self); Emit((EntityState)(object)self, "ice-start"); } private static void IceExit(orig_OnExit orig, IceBox self) { bool boost = Flag((EntityState)(object)self, "hasBoost"); orig.Invoke(self); Emit((EntityState)(object)self, "ice-end", Number((EntityState)(object)self, "exitDuration", 0.3f), boost); } private static void IceBurst(orig_FireBoostedIceCube orig, IceBox self) { orig.Invoke(self); Emit((EntityState)(object)self, "ice-burst", 0.65f, boost: true); } private static void Glaze(orig_OnEnter orig, Glaze self) { orig.Invoke(self); Emit((EntityState)(object)self, "glaze", Number((EntityState)(object)self, "duration", 1f)); } private static void GlazeShot(orig_FireGrenade orig, Glaze self, string muzzle) { orig.Invoke(self, muzzle); Emit((EntityState)(object)self, "glaze-shot", 0.3f); } private static void YesChef(orig_OnEnter orig, YesChef self) { orig.Invoke(self); Emit((EntityState)(object)self, "yes-chef", Number((EntityState)(object)self, "duration", 1f)); } } internal sealed class ChefActionTimeline { internal sealed class Sample { public string Group; public string Clip; public string Token; public double Phase; public float Weight; } private sealed class Pulse { public string Clip; public double Start; public double Duration; public double StartPhase; public long Serial; } private readonly Dictionary<string, Pulse> pulses = new Dictionary<string, Pulse>(); private long serial; internal void Trigger(string group, string clip, double now, double duration, double startPhase = 0.0) { if (!double.IsNaN(now) && !double.IsInfinity(now) && !double.IsNaN(duration) && !double.IsInfinity(duration) && !(duration <= 0.0)) { pulses[group] = new Pulse { Clip = clip, Start = now, Duration = Math.Max(0.06, duration), StartPhase = Math.Max(0.0, Math.Min(1.0, startPhase)), Serial = ++serial }; } } internal IEnumerable<Sample> Samples(double now) { List<string> list = new List<string>(); List<Sample> list2 = new List<Sample>(); foreach (KeyValuePair<string, Pulse> pulse in pulses) { Pulse value = pulse.Value; double num = now - value.Start; if (num < 0.0 || num >= value.Duration) { list.Add(pulse.Key); continue; } list2.Add(new Sample { Group = pulse.Key, Clip = value.Clip, Phase = value.StartPhase + (1.0 - value.StartPhase) * num / value.Duration, Weight = (float)Math.Min(1.0, (value.Duration - num) / Math.Min(0.08, value.Duration * 0.2)), Token = pulse.Key + ":" + value.Serial }); } foreach (string item in list) { pulses.Remove(item); } return list2; } internal static bool PlayExit(string kind, bool boosted, double duration) { if (duration > 0.0) { return !(kind == "ice-end" && boosted); } return false; } internal static double FirePhase(double elapsed, double entry, double flame, double exit, bool started, bool ended, bool boostWaiting, out string id) { entry = Math.Max(0.01, entry); exit = Math.Max(0.01, exit); if (ended) { id = "sear_end"; return Math.Max(0.0, (elapsed - entry - flame) / exit); } if (elapsed < entry || !started || boostWaiting) { id = "sear_start"; return Math.Max(0.0, Math.Min(1.0, elapsed / entry)); } id = "sear_loop"; return Math.Max(0.0, elapsed - entry); } internal static void FilterCanceled(List<NativeMotionCandidate> observed, HashSet<string> canceled) { observed.RemoveAll((NativeMotionCandidate c) => canceled.Contains(c.Motion.Group)); } internal void Remove(string group) { pulses.Remove(group); } internal void Clear() { pulses.Clear(); } }
BepInEx/plugins/ChefCrabRangoon/Eclipse.Chef.E2.CrabRangoon.dll
Decompiled a week agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Security.Cryptography; using BepInEx; using Eclipse.AdvancedSkins; using EclipseSkinRuntimeFix; using EntityStates; using EntityStates.Chef; using HG.Reflection; using On.EntityStates.Chef; using R2API; using R2API.Utils; using RoR2; using RoR2.UI.MainMenu; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.ResourceManagement.AsyncOperations; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: OptIn] [assembly: AssemblyVersion("0.0.0.0")] namespace EclipseSkinRuntimeFix { internal static class NativeRenderers { private static readonly HashSet<string> NativePaths = new HashSet<string>(StringComparer.Ordinal) { "mdlLoader/PilotFemaleMesh", "mdlLoader/LoaderMechMesh", "mdlLoader/PilotFemaleFoldedOverJumpsuit", "mdlFalseSon/FalseSon_Body", "mdlFalseSon/FalseSon_Cloth", "mdlFalseSon/L_FalseSon_Weapon", "mdlSeeker/meshSeekerBody", "mdlSeeker/meshSeekerCloth", "mdlSeeker/meshSeekerGlass", "mdlChef/meshChef", "mdlChef/meshChefPizzaCutter", "mdlChef/meshlChefCleaver", "mdlChef/meshChefOven", "mdlChef/meshChefIceBox", "mdlCroco/CrocoMesh", "mdlCroco/CrocoSpineMesh", "mdlHuntress/HuntressMesh", "mdlHuntress/BowMesh", "mdlHuntress/HuntressScarfMesh", "mdlHuntress (1)/HuntressMesh", "mdlHuntress (1)/BowMesh", "mdlHuntress (1)/HuntressScarfMesh", "mdlMerc/MercMesh", "mdlMerc/MercSwordMesh", "mdlTreebot/TreebotBotMesh", "mdlTreebot/TreebotRootMesh", "mdlTreebot/TreebotLeafletMesh", "mdlTreebot/TreebotFlowerMesh", "mdlVoidSurvivor/mdlVoidSurvivorBody", "mdlVoidSurvivor/mdlVoidSurvivorHead", "mdlVoidSurvivor/mdlVoidSurvivorMetal", "mdlVoidSurvivor/metalcollar.001", "mdlBandit2/BanditArmature/ROOT/base/MainWeapon/BanditShotgunMesh", "mdlBandit2/BanditArmature/SideWeapon/SideWeaponSpinner/BanditPistolMesh", "mdlBandit2/Bandit2AccessoriesMesh" }; public static T[] GetSkinRenderers<T>(this Component owner, bool inactive = false, SkinDefParams parameters = null) where T : Renderer { return owner.gameObject.GetSkinRenderers<T>(inactive, parameters); } public static T[] GetSkinRenderers<T>(this GameObject owner, bool inactive = false, SkinDefParams parameters = null) where T : Renderer { //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) T[] componentsInChildren = owner.GetComponentsInChildren<T>(inactive); CharacterModel val = owner.GetComponent<CharacterModel>() ?? owner.GetComponentInParent<CharacterModel>(); ModelSkinController val2 = owner.GetComponent<ModelSkinController>() ?? (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<ModelSkinController>() : null); HashSet<Renderer> skinRefs = new HashSet<Renderer>(); SkinDefParams val3 = parameters; if (!Object.op_Implicit((Object)(object)val3) && Object.op_Implicit((Object)(object)val2) && val2.skins != null && val2.skins.Length != 0 && Object.op_Implicit((Object)(object)val2.skins[0])) { val3 = val2.skins[0].skinDefParams; } if (Object.op_Implicit((Object)(object)val3)) { if (val3.rendererInfos != null) { RendererInfo[] rendererInfos = val3.rendererInfos; foreach (RendererInfo val4 in rendererInfos) { if (Object.op_Implicit((Object)(object)val4.renderer)) { skinRefs.Add(val4.renderer); } } } if (val3.meshReplacements != null) { MeshReplacement[] meshReplacements = val3.meshReplacements; foreach (MeshReplacement val5 in meshReplacements) { if (Object.op_Implicit((Object)(object)val5.renderer)) { skinRefs.Add(val5.renderer); } } } } HashSet<Renderer> modelRefs = new HashSet<Renderer>(); if (Object.op_Implicit((Object)(object)val) && val.baseRendererInfos != null) { RendererInfo[] rendererInfos = val.baseRendererInfos; foreach (RendererInfo val6 in rendererInfos) { if (Object.op_Implicit((Object)(object)val6.renderer)) { modelRefs.Add(val6.renderer); } } } return Select(componentsInChildren, (T x) => ((Object)(object)x).name, (T x) => skinRefs.Contains((Renderer)(object)x), (T x) => modelRefs.Contains((Renderer)(object)x), (T x) => Path(((Component)(object)x).transform, owner.transform), (T x) => IsKnownNativePath(Path(((Component)(object)x).transform, owner.transform))); } internal static T[] Select<T>(T[] found, Func<T, string> name, Func<T, bool> skin, Func<T, bool> model, Func<T, string> path, Func<T, bool> contract = null) { HashSet<T> hashSet = new HashSet<T>(); if (contract == null) { contract = (T x) => false; } bool flag = found.Any(skin) || found.Any(model) || found.Any(contract); foreach (IGrouping<string, T> item in found.GroupBy(name)) { T[] array = item.ToArray(); if (array.Length == 1) { if (!flag || skin(array[0]) || model(array[0]) || contract(array[0])) { hashSet.Add(array[0]); } continue; } T[] array2 = array.Where(skin).ToArray(); T[] array3 = array.Where(model).ToArray(); T[] array4 = ((array2.Length == 1) ? ((array3.Length == 0 || array3.Contains(array2[0])) ? array2 : new T[0]) : ((array2.Length <= 1) ? array3 : array2.Where(((IEnumerable<T>)array3).Contains<T>).ToArray())); if (array2.Length == 0 && array3.Length == 0) { T[] array5 = array.Where(contract).ToArray(); if (array5.Length != 0) { if (array5.Length != 1) { throw new InvalidOperationException("ECLIPSE_RENDERER_PATH_AMBIGUOUS " + string.Join(";", array.Select(path))); } hashSet.Add(array5[0]); Debug.Log((object)("ECLIPSE_RENDERER_NATIVE_PATH name=" + item.Key + " native=" + path(array5[0]))); continue; } } if (array2.Length == 0 && array3.Length == 0 && flag) { Debug.Log((object)("ECLIPSE_RENDERER_FOREIGN_DUPLICATES name=" + item.Key + " ignored=" + array.Length)); continue; } if (array4.Length != 1) { throw new InvalidOperationException("ECLIPSE_RENDERER_AMBIGUOUS name=" + item.Key + " candidates=" + string.Join(";", array.Select(path)) + " skinRefs=" + array2.Length + " modelRefs=" + array3.Length); } hashSet.Add(array4[0]); Debug.Log((object)("ECLIPSE_RENDERER_RESOLVED name=" + item.Key + " native=" + path(array4[0]) + " ignoredDuplicates=" + (array.Length - 1))); } return found.Where(hashSet.Contains).ToArray(); } internal static bool IsKnownNativePath(string path) { if (path == null) { return false; } int num = path.IndexOf('/'); if (num < 0) { return false; } string text = path.Substring(0, num); if (text.EndsWith("(Clone)", StringComparison.Ordinal)) { text = text.Substring(0, text.Length - 7); } return NativePaths.Contains(text + path.Substring(num)); } private static string Path(Transform t, Transform root) { List<string> list = new List<string>(); Transform val = t; while (Object.op_Implicit((Object)(object)val)) { list.Add(((Object)val).name); if ((Object)(object)val == (Object)(object)root) { break; } val = val.parent; } list.Reverse(); return string.Join("/", list); } } } namespace EclipsePlaytestChefE2 { internal sealed class CrabActionTimeline { internal sealed class Sample { public string Group; public string Clip; public string Token; public double Phase; public float Weight; } private sealed class Pulse { public string Clip; public double Start; public double Duration; public double StartPhase; public long Serial; } private readonly Dictionary<string, Pulse> pulses = new Dictionary<string, Pulse>(); private long serial; internal void Trigger(string group, string clip, double now, double duration, double startPhase = 0.0) { if (!double.IsNaN(now) && !double.IsInfinity(now) && !double.IsNaN(duration) && !double.IsInfinity(duration) && !(duration <= 0.0)) { pulses[group] = new Pulse { Clip = clip, Start = now, Duration = Math.Max(0.06, duration), StartPhase = Math.Max(0.0, Math.Min(1.0, startPhase)), Serial = ++serial }; } } internal IEnumerable<Sample> Samples(double now) { List<string> list = new List<string>(); List<Sample> list2 = new List<Sample>(); foreach (KeyValuePair<string, Pulse> pulse in pulses) { Pulse value = pulse.Value; double num = now - value.Start; if (num < 0.0 || num >= value.Duration) { list.Add(pulse.Key); continue; } list2.Add(new Sample { Group = pulse.Key, Clip = value.Clip, Phase = value.StartPhase + (1.0 - value.StartPhase) * num / value.Duration, Weight = (float)Math.Min(1.0, (value.Duration - num) / Math.Min(0.08, value.Duration * 0.2)), Token = pulse.Key + ":" + value.Serial }); } foreach (string item in list) { pulses.Remove(item); } return list2; } internal static bool PlayExit(string kind, bool boosted, double duration) { if (duration > 0.0) { return !(kind == "ice-end" && boosted); } return false; } internal static double FirePhase(double elapsed, double entry, double flame, double exit, bool started, bool ended, bool boostWaiting, out string id) { entry = Math.Max(0.01, entry); exit = Math.Max(0.01, exit); if (ended) { id = "sear_end"; return Math.Max(0.0, (elapsed - entry - flame) / exit); } if (elapsed < entry || !started || boostWaiting) { id = "sear_start"; return Math.Max(0.0, Math.Min(1.0, elapsed / entry)); } id = "sear_loop"; return Math.Max(0.0, elapsed - entry); } internal static void FilterCanceled(List<NativeMotionCandidate> observed, HashSet<string> canceled) { observed.RemoveAll((NativeMotionCandidate c) => canceled.Contains(c.Motion.Group)); } internal void Remove(string group) { pulses.Remove(group); } internal void Clear() { pulses.Clear(); } } internal static class CrabNativeEvents { internal sealed class Signal { public EntityState State; public string Kind; public float Duration; public bool Boosted; } private static bool installed; private static readonly Dictionary<string, FieldInfo> fields = new Dictionary<string, FieldInfo>(); private static bool warned; internal static event Action<Signal> Observed; internal static float Number(EntityState s, string n, float fallback) { if (!(Read(s, n) is float num) || float.IsNaN(num) || float.IsInfinity(num)) { return fallback; } return num; } internal static bool Flag(EntityState s, string n) { object obj = Read(s, n); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } private static object Read(EntityState s, string n) { try { if (s == null) { return null; } string key = ((object)s).GetType().FullName + ":" + n; if (!fields.TryGetValue(key, out var value)) { value = ((object)s).GetType().GetField(n, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); fields[key] = value; } return (value != null) ? value.GetValue(s) : ((object)s).GetType().GetProperty(n, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(s); } catch (Exception) { if (!warned) { warned = true; Debug.LogWarning((object)"CHEF crab presentation observation unavailable; native gameplay preserved."); } return null; } } private static void Emit(EntityState s, string kind, float duration = 0f, bool boost = false) { Action<Signal> observed = CrabNativeEvents.Observed; if (observed == null) { return; } Signal obj = new Signal { State = s, Kind = kind, Duration = duration, Boosted = boost }; Delegate[] invocationList = observed.GetInvocationList(); for (int i = 0; i < invocationList.Length; i++) { Action<Signal> action = (Action<Signal>)invocationList[i]; try { action(obj); } catch (Exception ex) { Debug.LogException(ex); } } } internal static void Install() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Expected O, but got Unknown if (!installed) { installed = true; Dice.PlayThrowAnims += new hook_PlayThrowAnims(Throw); Sear.OnEnter += new hook_OnEnter(FireEnter); Sear.OnExit += new hook_OnExit(FireExit); Sear.FireBoostedFireball += new hook_FireBoostedFireball(FireBurst); IceBox.OnEnter += new hook_OnEnter(IceEnter); IceBox.OnExit += new hook_OnExit(IceExit); IceBox.FireBoostedIceCube += new hook_FireBoostedIceCube(IceBurst); Glaze.OnEnter += new hook_OnEnter(Glaze); Glaze.FireGrenade += new hook_FireGrenade(GlazeShot); YesChef.OnEnter += new hook_OnEnter(YesChef); } } internal static void Uninstall() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Expected O, but got Unknown if (installed) { installed = false; Dice.PlayThrowAnims -= new hook_PlayThrowAnims(Throw); Sear.OnEnter -= new hook_OnEnter(FireEnter); Sear.OnExit -= new hook_OnExit(FireExit); Sear.FireBoostedFireball -= new hook_FireBoostedFireball(FireBurst); IceBox.OnEnter -= new hook_OnEnter(IceEnter); IceBox.OnExit -= new hook_OnExit(IceExit); IceBox.FireBoostedIceCube -= new hook_FireBoostedIceCube(IceBurst); Glaze.OnEnter -= new hook_OnEnter(Glaze); Glaze.FireGrenade -= new hook_FireGrenade(GlazeShot); YesChef.OnEnter -= new hook_OnEnter(YesChef); CrabNativeEvents.Observed = null; fields.Clear(); } } private static void Throw(orig_PlayThrowAnims orig, Dice self, float duration) { orig.Invoke(self, duration); Emit((EntityState)(object)self, "throw", duration, Flag((EntityState)(object)self, "hasBoost")); } private static void FireEnter(orig_OnEnter orig, Sear self) { orig.Invoke(self); Emit((EntityState)(object)self, "fire-start"); } private static void FireExit(orig_OnExit orig, Sear self) { bool flag = Flag((EntityState)(object)self, "flamethrowerEnded"); orig.Invoke(self); Emit((EntityState)(object)self, "fire-end", flag ? 0f : Number((EntityState)(object)self, "exitDuration", 0.3f)); } private static void FireBurst(orig_FireBoostedFireball orig, Sear self, string muzzle) { orig.Invoke(self, muzzle); Emit((EntityState)(object)self, "fire-burst", 0.32f); } private static void IceEnter(orig_OnEnter orig, IceBox self) { orig.Invoke(self); Emit((EntityState)(object)self, "ice-start"); } private static void IceExit(orig_OnExit orig, IceBox self) { bool boost = Flag((EntityState)(object)self, "hasBoost"); orig.Invoke(self); Emit((EntityState)(object)self, "ice-end", Number((EntityState)(object)self, "exitDuration", 0.3f), boost); } private static void IceBurst(orig_FireBoostedIceCube orig, IceBox self) { orig.Invoke(self); Emit((EntityState)(object)self, "ice-burst", 0.65f, boost: true); } private static void Glaze(orig_OnEnter orig, Glaze self) { orig.Invoke(self); Emit((EntityState)(object)self, "glaze", Number((EntityState)(object)self, "duration", 1f)); } private static void GlazeShot(orig_FireGrenade orig, Glaze self, string muzzle) { orig.Invoke(self, muzzle); Emit((EntityState)(object)self, "glaze-shot", 0.3f); } private static void YesChef(orig_OnEnter orig, YesChef self) { orig.Invoke(self); Emit((EntityState)(object)self, "yes-chef", Number((EntityState)(object)self, "duration", 1f)); } } internal static class CrabActor { internal static CharacterBody Resolve(Component member) { if (!Object.op_Implicit((Object)(object)member)) { return null; } CharacterModel componentInParent = member.GetComponentInParent<CharacterModel>(); if (Object.op_Implicit((Object)(object)componentInParent) && Object.op_Implicit((Object)(object)componentInParent.body) && Object.op_Implicit((Object)(object)componentInParent.body.modelLocator) && (Object)(object)componentInParent.body.modelLocator.modelTransform == (Object)(object)((Component)componentInParent).transform) { return componentInParent.body; } AdvancedSkinModel componentInParent2 = member.GetComponentInParent<AdvancedSkinModel>(); if (!Object.op_Implicit((Object)(object)componentInParent2)) { return null; } return componentInParent2.AssociatedBody; } internal static bool Boosted(CharacterBody body) { if (Object.op_Implicit((Object)(object)body)) { if ((!Object.op_Implicit((Object)(object)Buffs.Boosted) || !body.HasBuff(Buffs.Boosted)) && (!Object.op_Implicit((Object)(object)Buffs.boostedFireEffect) || !body.HasBuff(Buffs.boostedFireEffect))) { if (Object.op_Implicit((Object)(object)Buffs.boostedFrostEffect)) { return body.HasBuff(Buffs.boostedFrostEffect); } return false; } return true; } return false; } } public sealed class CrabMotion : ISkinMotionSource, IDisposable { private sealed class Route { public string Clip; public string Group; public int Priority; public int[] Mask; public Route(string c, string g, int p, int[] m = null) { Clip = c; Group = g; Priority = p; Mask = m; } } private readonly Animator animator; private readonly MotionBank bank; private readonly Dictionary<string, MotionClip> clips; private readonly Dictionary<int, LayerMotionClock> clocks = new Dictionary<int, LayerMotionClock>(); private readonly List<AnimatorClipInfo> infos = new List<AnimatorClipInfo>(); private readonly int[] upper; private readonly int[] right; private readonly int[] left; private readonly int[] eyes; private readonly ObservedMotionChannel gaitChannel = new ObservedMotionChannel(); private readonly HashSet<string> floatParameters; private double idlePhase; private double walkPhase; private double deathAt = -1.0; private float movement; private bool disposed; private readonly CrabActionTimeline actionTimeline = new CrabActionTimeline(); private EntityState sustained; private EntityState suppressedState; private string sustainedKind; private float sustainedStart; private CharacterBody trackedBody; private EntityStateMachine[] machines = Array.Empty<EntityStateMachine>(); private readonly HashSet<string> canceledGroups = new HashSet<string>(); private readonly Dictionary<string, Route> routes = new Dictionary<string, Route>(); private CharacterBody BindBody() { CharacterBody val = CrabActor.Resolve((Component)(object)animator); if ((Object)(object)val != (Object)(object)trackedBody) { trackedBody = val; machines = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponents<EntityStateMachine>() : Array.Empty<EntityStateMachine>()); actionTimeline.Clear(); sustained = null; suppressedState = null; canceledGroups.Clear(); } return val; } private EntityState ActiveSecondary() { return (from m in machines where Object.op_Implicit((Object)(object)m) && m.state != null select m.state).FirstOrDefault((Func<EntityState, bool>)((EntityState s) => s is Sear || s is IceBox)); } private void OnNativeAction(CrabNativeEvents.Signal signal) { if (disposed || !Object.op_Implicit((Object)(object)animator) || signal.State == null) { return; } CharacterBody val = BindBody(); if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)signal.State.outer) || (Object)(object)((Component)signal.State.outer).GetComponent<CharacterBody>() != (Object)(object)val) { return; } string kind = signal.Kind; double now = Time.time; string item = ((kind.StartsWith("fire") || kind.StartsWith("ice")) ? "secondary" : (kind.StartsWith("glaze") ? "glaze" : ((kind == "throw") ? "primary" : "transformation"))); canceledGroups.Remove(item); switch (kind) { case "fire-start": case "ice-start": actionTimeline.Remove("secondary"); suppressedState = null; sustained = signal.State; sustainedKind = ((kind == "fire-start") ? "sear" : "icebox"); sustainedStart = Time.time; break; case "fire-end": case "ice-end": if (sustained == signal.State) { sustained = null; sustainedKind = null; } if (CrabActionTimeline.PlayExit(kind, signal.Boosted, signal.Duration)) { actionTimeline.Trigger("secondary", (kind == "fire-end") ? "sear_end" : "icebox_end", now, signal.Duration); } break; case "throw": actionTimeline.Trigger("primary", signal.Boosted ? "throw_boost" : "throw", now, signal.Duration); break; case "fire-burst": actionTimeline.Trigger("secondary", "sear_burst", now, signal.Duration); break; case "ice-burst": actionTimeline.Trigger("secondary", "icebox_burst", now, signal.Duration); break; case "glaze": actionTimeline.Trigger("glaze", "glaze_prep", now, signal.Duration); break; case "glaze-shot": actionTimeline.Trigger("glaze", "glaze", now, signal.Duration, 0.18); break; case "yes-chef": actionTimeline.Trigger("transformation", "yes_chef", now, signal.Duration); break; } } private void CollectNativeActions(List<NativeMotionCandidate> observed) { EntityState val = ActiveSecondary(); if (observed.Any((NativeMotionCandidate c) => c.Motion.Group == "roll" && c.Motion.Samples.Any((WeightedMotion x) => x.Weight > 0f))) { actionTimeline.Clear(); suppressedState = val; sustained = null; string[] array = new string[4] { "primary", "secondary", "glaze", "transformation" }; foreach (string item in array) { canceledGroups.Add(item); } return; } if (val != null && val != suppressedState && val != sustained) { actionTimeline.Remove("secondary"); sustained = val; sustainedKind = ((val is IceBox) ? "icebox" : "sear"); sustainedStart = Time.time - CrabNativeEvents.Number(val, (val is IceBox) ? "fixedAge" : "stopwatch", 0f); canceledGroups.Remove("secondary"); } else if (val == null) { sustained = null; } if (sustained != null) { float num2 = Mathf.Max(0.01f, CrabNativeEvents.Number(sustained, "entryDuration", 0.3f)); float num3 = ((sustainedKind == "sear") ? CrabNativeEvents.Number(sustained, "stopwatch", Time.time - sustainedStart) : (Time.time - sustainedStart)); double num4; string id; if (sustainedKind == "sear") { num4 = CrabActionTimeline.FirePhase(num3, num2, CrabNativeEvents.Number(sustained, "flamethrowerDuration", 1f), CrabNativeEvents.Number(sustained, "exitDuration", 0.3f), CrabNativeEvents.Flag(sustained, "flamethrowerStarted"), CrabNativeEvents.Flag(sustained, "flamethrowerEnded"), CrabNativeEvents.Flag(sustained, "hasBoost") && !CrabNativeEvents.Flag(sustained, "allBoostProjectilesFired"), out id); if (id == "sear_loop") { num4 /= (double)clips[id].Duration; } } else { bool flag = num3 < num2; id = "icebox" + (flag ? "_start" : "_loop"); num4 = (flag ? (num3 / num2) : ((num3 - num2) / clips[id].Duration)); } observed.Add(Candidate(id, "secondary", 30, -60000, Math.Max(0.0, num4), 1f, upper, "sustained:" + sustainedStart, 1500)); } foreach (CrabActionTimeline.Sample item2 in actionTimeline.Samples(Time.time)) { int num5 = ((item2.Group == "primary") ? 20 : ((item2.Group == "glaze") ? 25 : ((item2.Group == "transformation") ? 60 : 30))); int[] mask = ((item2.Group == "primary") ? ((item2.Clip == "throw_boost") ? upper : right) : ((item2.Group == "glaze") ? left : upper)); observed.Add(Candidate(item2.Clip, item2.Group, num5, -61000 - num5, item2.Phase, item2.Weight, mask, item2.Token, 2000)); } } private int[] Mask(Func<string, bool> predicate) { return (from x in bank.Bones.Select((Bone b, int i) => new { b.Name, i }) where predicate(x.Name) select x.i).ToArray(); } private void Map(string native, string clip, string group, int priority, int[] mask = null) { routes.Add(native, new Route(clip, group, priority, mask)); } public CrabMotion(Animator animator, MotionBank bank) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown this.animator = animator; this.bank = bank; clips = bank.Clips.ToDictionary((MotionClip c) => c.Id); floatParameters = new HashSet<string>(from p in animator.parameters where (int)p.type == 1 select p.name); upper = Mask((string n) => n == "Mouth" || n.StartsWith("Claw_") || n.StartsWith("Tool_") || n.StartsWith("Eye_")); right = Mask((string n) => n == "Eye_R" || n.StartsWith("Claw_R") || n == "Tool_R"); left = Mask((string n) => n == "Eye_L" || n.StartsWith("Claw_L") || n == "Tool_L"); eyes = Mask((string n) => n.StartsWith("Eye_")); Map("Chef_SliceAndDice", "throw", "primary", 20, right); Map("PrimaryDice1_Return_Start", "recall", "primary", 20, right); Map("PrimaryDice1_Return_Hold", "cleaver_hold", "primary", 20, right); Map("PrimaryDice1_Return_Catch", "catch", "primary", 20, right); Map("PrimaryDice1_Return_All", "catch", "primary", 20, right); Map("root|PrimaryDice1_Oops", "flinch", "primary", 20, right); Map("ChefGlazeStart", "glaze_prep", "glaze", 25, left); Map("Chef_Glaze3Shots", "glaze_boost", "glaze", 25, left); Map("Glaze_Glaze3Shot_Exit", "glaze_end", "glaze", 25, left); Map("SearBlaze_Prep", "sear_start", "secondary", 30, upper); Map("SearBlaze_Loop", "sear_loop", "secondary", 30, upper); Map("SearBlaze_Exit", "sear_end", "secondary", 30, upper); Map("YesChef", "yes_chef", "transformation", 60, upper); string[][] array = new string[3][] { new string[2] { "Chef_JumpStartTweaked", "jump_start" }, new string[2] { "Chef_JumpUp", "jump_up" }, new string[2] { "Chef_JumpDown", "fall" } }; foreach (string[] array2 in array) { Map(array2[0], array2[1], "airborne", 10); } array = new string[10][] { new string[2] { "Rolypoly_Enter", "roll_enter" }, new string[2] { "Rolypoly_ChargeLoop", "roll_charge" }, new string[2] { "Chef_RolyPolyStart", "roll_enter" }, new string[2] { "Chef_RolyPoly", "roll_loop" }, new string[2] { "ExitRolyPoly", "roll_exit" }, new string[2] { "Boosted_Rolypoly_Start", "roll_enter" }, new string[2] { "Boosted_Rolypoly_Loop", "roll_boost" }, new string[2] { "Chef_RolyPoly_JumpStart", "roll_enter" }, new string[2] { "Chef_RolyPoly_JumpUp", "roll_charge" }, new string[2] { "Chef_RolyPoly_JumpDown", "roll_charge" } }; foreach (string[] array3 in array) { Map(array3[0], array3[1], "roll", 40); } Map("Chef_JumpLand", "land", "landing", 11); Map("Chef_RolyPoly_JumpLand", "roll_exit", "roll-landing", 41); string[] array4 = new string[2] { ",Additive", ",Override" }; foreach (string text in array4) { Map("OilSpillJump" + text, "oil_jump", "oil", 45); Map("OilSpillLoop" + text, "oil_loop", "oil", 45); Map("OilSpillLand" + text, "oil_land", "oil", 45); } Map("Chef_Flinch1", "flinch", "flinch", 70, upper); Map("Chef_Flinch2", "flinch", "flinch", 70, upper); Map("LobbyIntro", "lobby_intro", "display", 10); array4 = new string[3] { "Chef_LobbyIdle", "Chef_LobbyIdleAlternate", "Chef_LobbyIdleAlternate2" }; foreach (string native in array4) { Map(native, "lobby_idle", "display", 10); } foreach (Route value in routes.Values) { if (!clips.ContainsKey(value.Clip)) { throw new InvalidOperationException("Missing crab action " + value.Clip); } if (value.Mask != null && value.Mask.Length == 0) { throw new InvalidOperationException("Empty crab action mask"); } } array4 = new string[16] { "idle", "scuttle", "sprint", "backpedal", "strafe_left", "strafe_right", "death", "throw_boost", "empowered", "aim_yaw", "aim_pitch", "icebox_start", "icebox_loop", "icebox_end", "sear_burst", "icebox_burst" }; foreach (string text2 in array4) { if (!clips.ContainsKey(text2)) { throw new InvalidOperationException("Missing crab motion " + text2); } } CrabNativeEvents.Observed += OnNativeAction; } private NativeMotionCandidate Candidate(string id, string group, int priority, int layer, double time, float weight, int[] mask = null, string token = null, int rank = 1000) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_005a: 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) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Expected O, but got Unknown NativeMotionCandidate val = new NativeMotionCandidate(); val.SourceLayer = layer; val.SourceRank = rank; MotionLayer val2 = new MotionLayer(); val2.Group = group; val2.Priority = priority; val2.Blend = (MotionBlend)0; val2.BoneMask = mask; val2.Samples = (WeightedMotion[])(object)new WeightedMotion[1] { new WeightedMotion { Clip = clips[id], Time = Math.Max(0.0, time), Weight = Mathf.Clamp01(weight), Token = (token ?? group) } }; val.Motion = val2; return val; } private void Collect(int layer, AnimatorStateInfo state, MotionOccurrence occurrence, float transition, List<NativeMotionCandidate> result, bool boosted) { //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) string layerName = animator.GetLayerName(layer); float num = ((layer == 0) ? 1f : Mathf.Clamp01(animator.GetLayerWeight(layer))); float num2 = infos.Sum((AnimatorClipInfo x) => Mathf.Max(0f, ((AnimatorClipInfo)(ref x)).weight)); if (num <= 0f) { return; } string text = ((((AnimatorStateInfo)(ref state)).fullPathHash == Animator.StringToHash(layerName + ".FireDice")) ? "throw" : ((((AnimatorStateInfo)(ref state)).fullPathHash == Animator.StringToHash(layerName + ".FireSliceAndDice")) ? "throw_boost" : null)); if (text != null) { if (!canceledGroups.Contains("primary")) { result.Add(Candidate(text, "primary", 20, -1000 - layer, ((AnimatorStateInfo)(ref state)).normalizedTime, transition * num, (text == "throw_boost") ? upper : right, layer + ":" + occurrence.Serial + ":" + text, layerName.Contains("Override") ? 30 : 20)); } } else { if (num2 <= 1E-06f) { return; } foreach (AnimatorClipInfo info in infos) { AnimatorClipInfo current = info; if (Object.op_Implicit((Object)(object)((AnimatorClipInfo)(ref current)).clip) && routes.TryGetValue(((Object)((AnimatorClipInfo)(ref current)).clip).name, out var value) && !canceledGroups.Contains(value.Group)) { string text2 = value.Clip; if (((AnimatorStateInfo)(ref state)).fullPathHash == Animator.StringToHash(layerName + ".FireDice")) { text2 = "throw"; value = new Route(text2, "primary", 20, right); } else if (((AnimatorStateInfo)(ref state)).fullPathHash == Animator.StringToHash(layerName + ".FireSliceAndDice")) { text2 = "throw_boost"; value = new Route(text2, "primary", 20, right); } int rank = (layerName.Contains("Override") ? 30 : (layerName.Contains("Additive") ? 20 : 10)); int layer2 = -1000 - layer; result.Add(Candidate(text2, value.Group, value.Priority, layer2, ((AnimatorStateInfo)(ref state)).normalizedTime, ((AnimatorClipInfo)(ref current)).weight / num2 * transition * num, value.Mask, layer + ":" + occurrence.Serial + ":" + text2, rank)); } } } } public void Observe(List<NativeMotionCandidate> candidates, HashSet<string> replaced) { //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_02dc: Unknown result type (might be due to invalid IL or missing references) //IL_02e1: 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_02f3: Unknown result type (might be due to invalid IL or missing references) //IL_02f4: Unknown result type (might be due to invalid IL or missing references) //IL_02f9: Unknown result type (might be due to invalid IL or missing references) //IL_0304: Unknown result type (might be due to invalid IL or missing references) //IL_030b: Unknown result type (might be due to invalid IL or missing references) //IL_030d: Unknown result type (might be due to invalid IL or missing references) //IL_0312: Unknown result type (might be due to invalid IL or missing references) //IL_031f: Expected O, but got Unknown //IL_0324: Expected O, but got Unknown //IL_0355: Unknown result type (might be due to invalid IL or missing references) //IL_035a: Unknown result type (might be due to invalid IL or missing references) //IL_0372: Unknown result type (might be due to invalid IL or missing references) //IL_0377: Unknown result type (might be due to invalid IL or missing references) //IL_0391: 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_0385: Unknown result type (might be due to invalid IL or missing references) //IL_0396: Unknown result type (might be due to invalid IL or missing references) //IL_040c: Unknown result type (might be due to invalid IL or missing references) //IL_03b1: Unknown result type (might be due to invalid IL or missing references) //IL_03b6: Unknown result type (might be due to invalid IL or missing references) //IL_03b9: Expected O, but got Unknown //IL_03be: Expected O, but got Unknown //IL_053f: Unknown result type (might be due to invalid IL or missing references) //IL_0544: Unknown result type (might be due to invalid IL or missing references) //IL_044a: Unknown result type (might be due to invalid IL or missing references) //IL_0588: Unknown result type (might be due to invalid IL or missing references) //IL_058d: Unknown result type (might be due to invalid IL or missing references) //IL_05b5: Unknown result type (might be due to invalid IL or missing references) //IL_05ba: Unknown result type (might be due to invalid IL or missing references) //IL_0638: Unknown result type (might be due to invalid IL or missing references) if (disposed || !Object.op_Implicit((Object)(object)animator)) { return; } MotionBinding[] bindings = bank.Bindings; foreach (MotionBinding val in bindings) { replaced.Add(val.Clip); } CharacterBody val2 = BindBody(); bool num = Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)val2.healthComponent) && !val2.healthComponent.alive; bool flag = CrabActor.Boosted(val2); float num2 = Mathf.Min(Time.deltaTime, 0.1f); idlePhase += num2 / clips["idle"].Duration; if (num) { actionTimeline.Clear(); sustained = null; if (deathAt < 0.0) { deathAt = Time.time; } candidates.Add(Candidate("death", "death", 1000, -90000, ((double)Time.time - deathAt) / (double)clips["death"].Duration, 1f)); return; } deathAt = -1.0; Vector3 val3 = Vector3.zero; if (Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)val2.characterMotor) && val2.characterMotor.isGrounded) { val3 = val2.characterMotor.velocity; val3.y = 0f; val3 = ((Component)animator).transform.InverseTransformDirection(val3); } float magnitude = ((Vector3)(ref val3)).magnitude; movement = Mathf.MoveTowards(movement, (float)((magnitude > 0.15f) ? 1 : 0), num2 * 6f); walkPhase += num2 * Mathf.Min(magnitude / 0.65f, 3.5f); string text = ((!(Mathf.Abs(val3.x) > Mathf.Abs(val3.z))) ? ((val3.z < -0.1f) ? "backpedal" : ((Object.op_Implicit((Object)(object)val2) && val2.isSprinting) ? "sprint" : "scuttle")) : ((val3.x < 0f) ? "strafe_left" : "strafe_right")); candidates.Add(Candidate("idle", "base-idle", 1, -1, idlePhase, 1f - movement)); WeightedMotion[] array = gaitChannel.Sample(clips[text], text, walkPhase, (double)Time.time, 0.12f, (string)null, 0, false); WeightedMotion[] array2 = array; foreach (WeightedMotion obj in array2) { obj.Weight *= movement; } candidates.Add(new NativeMotionCandidate { SourceLayer = -1, SourceRank = 1000, Motion = new MotionLayer { Group = "base-gait", Priority = 1, Blend = (MotionBlend)0, Samples = array } }); List<NativeMotionCandidate> list = new List<NativeMotionCandidate>(); AnimatorTransitionInfo animatorTransitionInfo; AnimatorStateInfo val4; for (int j = 0; j < animator.layerCount; j++) { bool flag2 = animator.IsInTransition(j); float num3; if (!flag2) { num3 = 0f; } else { animatorTransitionInfo = animator.GetAnimatorTransitionInfo(j); num3 = Mathf.Clamp01(((AnimatorTransitionInfo)(ref animatorTransitionInfo)).normalizedTime); } float num4 = num3; AnimatorStateInfo currentAnimatorStateInfo = animator.GetCurrentAnimatorStateInfo(j); AnimatorStateInfo val5; if (!flag2) { val4 = default(AnimatorStateInfo); val5 = val4; } else { val5 = animator.GetNextAnimatorStateInfo(j); } AnimatorStateInfo state = val5; if (!clocks.TryGetValue(j, out var value)) { Dictionary<int, LayerMotionClock> dictionary = clocks; int key = j; LayerMotionClock val6 = new LayerMotionClock(); value = val6; dictionary[key] = val6; } value.Observe(((AnimatorStateInfo)(ref currentAnimatorStateInfo)).fullPathHash, (double)((AnimatorStateInfo)(ref currentAnimatorStateInfo)).normalizedTime, flag2, ((AnimatorStateInfo)(ref state)).fullPathHash, (double)((AnimatorStateInfo)(ref state)).normalizedTime, (double)Time.time); infos.Clear(); animator.GetCurrentAnimatorClipInfo(j, infos); Collect(j, currentAnimatorStateInfo, value.Current, 1f - num4, list, flag); if (flag2) { infos.Clear(); animator.GetNextAnimatorClipInfo(j, infos); Collect(j, state, value.Next, num4, list, flag); } } CollectNativeActions(list); CrabActionTimeline.FilterCanceled(list, canceledGroups); candidates.AddRange(NativeMotionComposition.ResolveSources((IEnumerable<NativeMotionCandidate>)list)); string[][] array3 = new string[2][] { new string[3] { "AimYaw", "aimYawCycle", "aim_yaw" }, new string[3] { "AimPitch", "aimPitchCycle", "aim_pitch" } }; foreach (string[] array4 in array3) { int layerIndex = animator.GetLayerIndex(array4[0]); if (layerIndex < 0 || !floatParameters.Contains(array4[1])) { continue; } bool flag3 = animator.IsInTransition(layerIndex); float num5; if (!flag3) { num5 = 0f; } else { animatorTransitionInfo = animator.GetAnimatorTransitionInfo(layerIndex); num5 = Mathf.Clamp01(((AnimatorTransitionInfo)(ref animatorTransitionInfo)).normalizedTime); } float num6 = num5; int num7 = Animator.StringToHash(array4[0] + ((array4[0] == "AimYaw") ? ".YawControl" : ".PitchControl")); val4 = animator.GetCurrentAnimatorStateInfo(layerIndex); float num8 = ((((AnimatorStateInfo)(ref val4)).fullPathHash == num7) ? (1f - num6) : 0f); float num9; if (flag3) { val4 = animator.GetNextAnimatorStateInfo(layerIndex); if (((AnimatorStateInfo)(ref val4)).fullPathHash == num7) { num9 = num6; goto IL_05d0; } } num9 = 0f; goto IL_05d0; IL_05d0: float num10 = num8 + num9; float num11 = Mathf.Clamp01(animator.GetLayerWeight(layerIndex)) * num10; if (!(num11 <= 0f)) { NativeMotionCandidate val7 = Candidate(array4[2], array4[0], 80, -70000 - layerIndex, Mathf.Clamp01(animator.GetFloat(array4[1])), num11, upper); val7.Motion.Blend = (MotionBlend)1; candidates.Add(val7); } } if (flag) { candidates.Add(Candidate("empowered", "boost-eyes", 5, -80000, Time.time / clips["empowered"].Duration, 1f, eyes)); } } public void Dispose() { disposed = true; CrabNativeEvents.Observed -= OnNativeAction; actionTimeline.Clear(); sustained = null; trackedBody = null; machines = Array.Empty<EntityStateMachine>(); canceledGroups.Clear(); clocks.Clear(); infos.Clear(); } } public sealed class CrabEffects : ISkinEffectDriver, IDisposable { private readonly SkinnedMeshRenderer renderer; private Transform tool; private Vector3 visibleScale; private bool masked; private bool disposed; private readonly Material original; private readonly Material accent; private readonly Color originalColor; private float boostBlend; public CrabEffects(SkinnedMeshRenderer renderer) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //IL_0072: 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_0077: Unknown result type (might be due to invalid IL or missing references) this.renderer = renderer; original = ((Renderer)renderer).sharedMaterial; if (!Object.op_Implicit((Object)(object)original)) { throw new InvalidOperationException("Crab material unavailable"); } accent = new Material(original) { name = "CrabActorAccent" }; originalColor = (original.HasProperty("_Color") ? original.GetColor("_Color") : Color.white); ((Renderer)renderer).sharedMaterial = accent; } public void Update() { //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) if (disposed || !Object.op_Implicit((Object)(object)renderer)) { return; } if (!Object.op_Implicit((Object)(object)tool)) { tool = ((IEnumerable<Transform>)renderer.bones).FirstOrDefault((Func<Transform, bool>)((Transform b) => Object.op_Implicit((Object)(object)b) && ((Object)b).name == "Tool_R")); } CharacterBody val = CrabActor.Resolve((Component)(object)renderer); ChefController val2 = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<ChefController>() : null); if (Object.op_Implicit((Object)(object)tool)) { visibleScale = tool.localScale; masked = false; if (Object.op_Implicit((Object)(object)val2) && val2.cleaversAway) { tool.localScale = Vector3.zero; masked = true; } } bool flag = CrabActor.Boosted(val) && (!Object.op_Implicit((Object)(object)val.healthComponent) || val.healthComponent.alive); boostBlend = Mathf.MoveTowards(boostBlend, (float)(flag ? 1 : 0), Time.deltaTime * 5f); if (Object.op_Implicit((Object)(object)accent) && (Object)(object)((Renderer)renderer).sharedMaterial == (Object)(object)accent) { bool flag2 = Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)Buffs.boostedFrostEffect) && val.HasBuff(Buffs.boostedFrostEffect); accent.SetColor("_Color", Color.Lerp(originalColor, flag2 ? new Color(0.7f, 0.92f, 1f) : new Color(1f, 0.83f, 0.6f), boostBlend * 0.65f)); } } public void Dispose() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) if (!disposed) { disposed = true; if (masked && Object.op_Implicit((Object)(object)tool)) { tool.localScale = visibleScale; } if (Object.op_Implicit((Object)(object)renderer) && (Object)(object)((Renderer)renderer).sharedMaterial == (Object)(object)accent) { ((Renderer)renderer).sharedMaterial = original; } if (Object.op_Implicit((Object)(object)accent)) { Object.Destroy((Object)(object)accent); } masked = false; } } } [DefaultExecutionOrder(32001)] public sealed class CrabNativeVisuals : MonoBehaviour { [SerializeField] private SkinnedMeshRenderer target; [SerializeField] private Mesh custom; [SerializeField] private Mesh empty; [SerializeField] private SkinnedMeshRenderer[] companions; [SerializeField] private Mesh[] originals; public void Configure(SkinnedMeshRenderer target, Mesh custom, Mesh empty, SkinnedMeshRenderer[] companions, Mesh[] originals) { this.target = target; this.custom = custom; this.empty = empty; this.companions = companions; this.originals = originals; } private void LateUpdate() { if (Object.op_Implicit((Object)(object)target) && companions != null && !((Object)(object)target.sharedMesh == (Object)(object)custom)) { Restore(); } } private void Restore() { if (companions == null) { return; } for (int i = 0; i < companions.Length; i++) { if (Object.op_Implicit((Object)(object)companions[i]) && (Object)(object)companions[i].sharedMesh == (Object)(object)empty) { companions[i].sharedMesh = originals[i]; } } } private void OnDestroy() { Restore(); } } [BepInPlugin("eclipseplaytest.chef.e2", "CHEF - Crab Rangoon (Playtest)", "0.1.4")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class CrabRangoon : BaseUnityPlugin { [Serializable] public sealed class AssetFile { public string file; public string sha256; } [Serializable] public sealed class AssetManifest { public int schema; public string skinId; public string revision; public AssetFile mesh; public AssetFile motion; public AssetFile albedo; public string[] nativeBoneNames; } public const string Guid = "eclipseplaytest.chef.e2"; public const string Version = "0.1.4"; public const string SkinId = "EclipsePlaytestChefE2CrabRangoon"; private static CrabRangoon instance; private string folder; private float deadline; private bool registered; private readonly Dictionary<string, Mesh> fallbackMeshes = new Dictionary<string, Mesh>(); private GameObject modelPrefab; private GameObject displayModelPrefab; private Mesh nativeMesh; private Material nativeMaterial; private AssetManifest manifest; private IDisposable registration; private readonly List<AsyncOperationHandle> retainedAssets = new List<AsyncOperationHandle>(); private static readonly string[] RendererNames = new string[5] { "meshChef", "meshChefPizzaCutter", "meshlChefCleaver", "meshChefOven", "meshChefIceBox" }; private void Awake() { instance = this; CrabNativeEvents.Install(); folder = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location); SystemInitializerInjector.InjectDependency(typeof(SkinCatalog), typeof(CrabRangoon)); RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(SyncDisplaySkins)); MainMenuController.OnMainMenuInitialised += SyncDisplaySkins; } [SystemInitializer(new Type[] { typeof(BodyCatalog), typeof(SurvivorCatalog) })] private static IEnumerator InitializeSkin() { if (!Object.op_Implicit((Object)(object)instance)) { yield break; } instance.deadline = Time.realtimeSinceStartup + 45f; IEnumerator routine = instance.Register(); try { while (true) { bool flag; try { flag = routine.MoveNext(); } catch (Exception ex) { ((BaseUnityPlugin)instance).Logger.LogError((object)("CHEF_E2_REGISTRATION_FAILED " + ex)); break; } if (flag) { yield return routine.Current; continue; } break; } } finally { IDisposable disposable = routine as IDisposable; if (disposable != null) { disposable.Dispose(); } } } private void CheckDeadline() { if (Time.realtimeSinceStartup > deadline) { throw new TimeoutException("Crab asset loading timed out; other startup work continues."); } } private byte[] ReadAsset(AssetFile entry) { if (entry == null || string.IsNullOrWhiteSpace(entry.file) || Path.GetFileName(entry.file) != entry.file || entry.file.Contains("..") || entry.sha256 == null || entry.sha256.Length != 64) { throw new InvalidDataException("Invalid crab asset manifest entry"); } string text = Path.Combine(folder, entry.file); if (new FileInfo(text).Length > 67108864) { throw new InvalidDataException("Crab asset too large"); } byte[] array = File.ReadAllBytes(text); using SHA256 sHA = SHA256.Create(); if (BitConverter.ToString(sHA.ComputeHash(array)).Replace("-", "").ToLowerInvariant() != entry.sha256) { throw new InvalidDataException("Crab asset hash mismatch: " + entry.file); } return array; } private static SkinnedMeshRenderer Exact(GameObject model, string name) { Transform val = model.transform.Find(name); if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)((Component)val).GetComponent<SkinnedMeshRenderer>())) { throw new InvalidOperationException("Missing scoped CHEF renderer " + name); } return ((Component)val).GetComponent<SkinnedMeshRenderer>(); } private void PrepareTemplate(GameObject model) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) AdvancedSkinModel component = model.GetComponent<AdvancedSkinModel>(); if (Object.op_Implicit((Object)(object)component) && component.HasNativeSnapshot) { component.Prepare(); return; } SkinnedMeshRenderer val = Exact(model, "meshChef"); Animator component2 = model.GetComponent<Animator>(); Vector3 val2 = ((Component)val).transform.localScale - Vector3.one * 100f; if (!(((Vector3)(ref val2)).sqrMagnitude > 0.01f) && !(Quaternion.Angle(((Component)val).transform.localRotation, Quaternion.Euler(-90f, 0f, 0f)) > 0.1f)) { val2 = ((Component)val).transform.localPosition; if (!(((Vector3)(ref val2)).sqrMagnitude > 0.0001f)) { if (!Object.op_Implicit((Object)(object)component2) || val.bones.Length != manifest.nativeBoneNames.Length) { throw new InvalidOperationException("Crab requires the original CHEF skeleton"); } for (int i = 0; i < val.bones.Length; i++) { if (!Object.op_Implicit((Object)(object)val.bones[i]) || ((Object)val.bones[i]).name != manifest.nativeBoneNames[i]) { throw new InvalidOperationException("Native bone slot mismatch " + i); } } AdvancedSkinModel val3 = model.GetComponent<AdvancedSkinModel>(); if (!Object.op_Implicit((Object)(object)val3)) { val3 = model.AddComponent<AdvancedSkinModel>(); } val3.CaptureNativeTemplate(val, component2, nativeMesh, (Material[])(object)new Material[1] { nativeMaterial }); val3.Prepare(); return; } } throw new InvalidOperationException("CHEF renderer conversion contract changed"); } private IEnumerator Register() { manifest = JsonUtility.FromJson<AssetManifest>(File.ReadAllText(Path.Combine(folder, "crab-assets.json"))); if (manifest == null || manifest.schema != 1 || manifest.skinId != "EclipsePlaytestChefE2CrabRangoon" || string.IsNullOrWhiteSpace(manifest.revision) || manifest.nativeBoneNames == null || manifest.nativeBoneNames.Length != 61) { throw new InvalidDataException("Invalid crab asset identity"); } MotionBank bank; using (MemoryStream memoryStream = new MemoryStream(ReadAsset(manifest.motion), writable: false)) { bank = MotionBank.Read((Stream)memoryStream); } if (bank.SkinId != "EclipsePlaytestChefE2CrabRangoon") { throw new InvalidDataException("Motion identity mismatch"); } bank.Find("idle"); bank.Find("scuttle"); bank.Find("claw_grip_proof"); Mesh mesh; using (MemoryStream memoryStream2 = new MemoryStream(ReadAsset(manifest.mesh), writable: false)) { mesh = SkinMesh.Read((Stream)memoryStream2, bank); } Texture2D albedo = new Texture2D(2, 2, (TextureFormat)4, false, false) { name = "CrabRangoonAlbedo", filterMode = (FilterMode)1, anisoLevel = 1 }; if (!ImageConversion.LoadImage(albedo, ReadAsset(manifest.albedo), false)) { throw new InvalidDataException("Invalid crab albedo"); } GameObject body = BodyCatalog.FindBodyPrefab("ChefBody"); if (!Object.op_Implicit((Object)(object)body) || !Object.op_Implicit((Object)(object)body.GetComponent<ModelLocator>())) { throw new InvalidOperationException("CHEF body unavailable"); } modelPrefab = ((Component)body.GetComponent<ModelLocator>().modelTransform).gameObject; ModelSkinController controller = modelPrefab.GetComponent<ModelSkinController>(); if (!Object.op_Implicit((Object)(object)controller) || controller.skins == null || controller.skins.Length == 0) { throw new InvalidOperationException("Native CHEF skins unavailable"); } if (controller.skins.Any((SkinDef s) => Object.op_Implicit((Object)(object)s) && ((Object)s).name == "EclipsePlaytestChefE2CrabRangoon")) { yield break; } SkinDef baseSkin = controller.skins[0]; SkinDefParams parameters = baseSkin.skinDefParams; if (!Object.op_Implicit((Object)(object)parameters) && baseSkin.skinDefParamsAddress != null && ((AssetReference)baseSkin.skinDefParamsAddress).RuntimeKeyIsValid()) { AsyncOperationHandle<SkinDefParams> op = Addressables.LoadAssetAsync<SkinDefParams>(((AssetReference)baseSkin.skinDefParamsAddress).RuntimeKey); retainedAssets.Add(AsyncOperationHandle<SkinDefParams>.op_Implicit(op)); while (!op.IsDone) { CheckDeadline(); yield return null; } parameters = op.Result; } if (!Object.op_Implicit((Object)(object)parameters)) { throw new InvalidOperationException("Native skin parameters unavailable"); } SkinnedMeshRenderer[] skinRenderers = modelPrefab.GetSkinRenderers<SkinnedMeshRenderer>(inactive: true, parameters); SkinnedMeshRenderer target = skinRenderers.Single((SkinnedMeshRenderer r) => ((Object)r).name == "meshChef"); MeshReplacement val = ((IEnumerable<MeshReplacement>)parameters.meshReplacements).FirstOrDefault((Func<MeshReplacement, bool>)((MeshReplacement r) => (Object)(object)r.renderer == (Object)(object)target)); nativeMesh = val.mesh; if (!Object.op_Implicit((Object)(object)nativeMesh) && val.meshAddress != null && ((AssetReference)val.meshAddress).RuntimeKeyIsValid()) { AsyncOperationHandle<Mesh> op2 = Addressables.LoadAssetAsync<Mesh>(((AssetReference)val.meshAddress).RuntimeKey); retainedAssets.Add(AsyncOperationHandle<Mesh>.op_Implicit(op2)); while (!op2.IsDone) { CheckDeadline(); yield return null; } nativeMesh = op2.Result; } if (!Object.op_Implicit((Object)(object)nativeMesh)) { nativeMesh = target.sharedMesh; } if (!Object.op_Implicit((Object)(object)nativeMesh) || nativeMesh.bindposes.Length != 61) { throw new InvalidOperationException("Native fallback mesh invalid"); } RendererInfo info = parameters.rendererInfos.First((RendererInfo r) => (Object)(object)r.renderer == (Object)(object)target); nativeMaterial = info.defaultMaterial; if (!Object.op_Implicit((Object)(object)nativeMaterial) && info.defaultMaterialAddress != null && ((AssetReference)info.defaultMaterialAddress).RuntimeKeyIsValid()) { AsyncOperationHandle<Material> op3 = Addressables.LoadAssetAsync<Material>(((AssetReference)info.defaultMaterialAddress).RuntimeKey); retainedAssets.Add(AsyncOperationHandle<Material>.op_Implicit(op3)); while (!op3.IsDone) { CheckDeadline(); yield return null; } nativeMaterial = op3.Result; } if (!Object.op_Implicit((Object)(object)nativeMaterial) || !Object.op_Implicit((Object)(object)nativeMaterial.shader)) { throw new InvalidOperationException("Native fallback material invalid"); } string[] rendererNames = RendererNames; foreach (string name in rendererNames) { SkinnedMeshRenderer nativeRenderer = Exact(modelPrefab, name); MeshReplacement val2 = parameters.meshReplacements.First((MeshReplacement r) => (Object)(object)r.renderer == (Object)(object)nativeRenderer); Mesh val3 = val2.mesh; if (!Object.op_Implicit((Object)(object)val3) && val2.meshAddress != null && ((AssetReference)val2.meshAddress).RuntimeKeyIsValid()) { AsyncOperationHandle<Mesh> op2 = Addressables.LoadAssetAsync<Mesh>(((AssetReference)val2.meshAddress).RuntimeKey); retainedAssets.Add(AsyncOperationHandle<Mesh>.op_Implicit(op2)); while (!op2.IsDone) { CheckDeadline(); yield return null; } val3 = op2.Result; } if (!Object.op_Implicit((Object)(object)val3)) { val3 = nativeRenderer.sharedMesh; } if (!Object.op_Implicit((Object)(object)val3) || val3.bindposes.Length != 61) { throw new InvalidOperationException("Missing fallback mesh " + name); } fallbackMeshes.Add(name, val3); } SurvivorDef val4 = SurvivorCatalog.FindSurvivorDefFromBody(body); if (!Object.op_Implicit((Object)(object)val4) || !Object.op_Implicit((Object)(object)val4.displayPrefab)) { throw new InvalidOperationException("CHEF display unavailable"); } CharacterModel componentInChildren = val4.displayPrefab.GetComponentInChildren<CharacterModel>(true); if (!Object.op_Implicit((Object)(object)componentInChildren)) { throw new InvalidOperationException("CHEF display model unavailable"); } displayModelPrefab = ((Component)componentInChildren).gameObject; PrepareTemplate(modelPrefab); PrepareTemplate(displayModelPrefab); ModelSkinController val5 = ((Component)componentInChildren).GetComponent<ModelSkinController>() ?? ((Component)componentInChildren).gameObject.AddComponent<ModelSkinController>(); Material val6 = new Material(nativeMaterial) { name = "matEclipseChefE2Crab" }; val6.SetTexture("_MainTex", (Texture)(object)albedo); val6.SetColor("_Color", Color.white); val6.SetFloat("_NormalStrength", 0f); val6.SetFloat("_Smoothness", 0.16f); val6.SetFloat("_SpecularStrength", 0.15f); val6.SetFloat("_SpecularExponent", 8f); val6.SetFloat("_EmPower", 0f); val6.SetTexture("_EmTex", (Texture)(object)Texture2D.blackTexture); val6.DisableKeyword("FLOWMAP"); val6.SetFloat("_FlowmapOn", 0f); val6.SetFloat("_FlowEmissionStrength", 0f); val6.DisableKeyword("FORCE_SPEC"); val6.SetFloat("_ForceSpecOn", 0f); val6.DisableKeyword("LIMBREMOVAL"); val6.SetFloat("_LimbRemovalOn", 0f); AdvancedSkinRegistry.Register(new AdvancedSkinDefinition { Mesh = mesh, Motion = bank, FallbackClip = "idle", AirTransitionSeconds = 0f, CreateEffects = (SkinnedMeshRenderer renderer) => (ISkinEffectDriver)(object)new CrabEffects(renderer), CreateMotionSource = (Animator animator, MotionBank motion) => (ISkinMotionSource)(object)new CrabMotion(animator, motion) }); Mesh empty = new Mesh { name = "EclipseChefE2EmptyNativeVisuals" }; empty.vertices = Array.Empty<Vector3>(); empty.triangles = Array.Empty<int>(); GameObject[] array = (GameObject[])(object)new GameObject[2] { modelPrefab, displayModelPrefab }; foreach (GameObject model in array) { model.AddComponent<CrabNativeVisuals>().Configure(Exact(model, "meshChef"), mesh, empty, (from n in RendererNames.Skip(1) select Exact(model, n)).ToArray(), (from n in RendererNames.Skip(1) select fallbackMeshes[n]).ToArray()); } info.defaultMaterial = val6; info.defaultMaterialAddress = new AssetReferenceT<Material>(""); SkinDefParams val7 = ScriptableObject.CreateInstance<SkinDefParams>(); val7.rendererInfos = (RendererInfo[])(object)new RendererInfo[1] { info }; val7.meshReplacements = ((IEnumerable<string>)RendererNames).Select((Func<string, MeshReplacement>)((string n) => new MeshReplacement { renderer = (Renderer)(object)Exact(modelPrefab, n), mesh = ((n == "meshChef") ? mesh : empty), meshAddress = new AssetReferenceT<Mesh>("") })).ToArray(); SkinDef val8 = ScriptableObject.CreateInstance<SkinDef>(); ((Object)val8).name = "EclipsePlaytestChefE2CrabRangoon"; val8.nameToken = "ECLIPSE_PLAYTEST_CHEF_E2_CRAB_RANGOON"; LanguageAPI.Add(val8.nameToken, "Crab Rangoon (Playtest)"); val8.unlockableDef = null; val8.rootObject = modelPrefab; val8.baseSkins = (SkinDef[])(object)new SkinDef[1] { baseSkin }; val8.skinDefParams = val7; val8.icon = baseSkin.icon; registration = AdvancedSkinApplications.Register(val8, mesh); val5.skins = (SkinDef[])(controller.skins = controller.skins.Concat((IEnumerable<SkinDef>)(object)new SkinDef[1] { val8 }).ToArray()).Clone(); registered = true; ((BaseUnityPlugin)this).Logger.LogInfo((object)("CHEF_E2_REGISTERED revision=" + manifest.revision + " customBones=" + bank.Bones.Length + " unlocked=true audio=not_integrated items=uncalibrated gameplay=untested skills=authored_motion_native_effects_playtest")); } private void SyncDisplaySkins() { if (!registered) { return; } try { if (!Object.op_Implicit((Object)(object)displayModelPrefab)) { throw new InvalidOperationException("Prepared crab display was destroyed"); } PrepareTemplate(displayModelPrefab); ModelSkinController component = displayModelPrefab.GetComponent<ModelSkinController>(); if (!Object.op_Implicit((Object)(object)component)) { throw new InvalidOperationException("Prepared crab display controller was removed"); } component.skins = (SkinDef[])modelPrefab.GetComponent<ModelSkinController>().skins.Clone(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("CHEF_E2_DISPLAY_FAILED " + ex)); } } private void OnDestroy() { CrabNativeEvents.Uninstall(); RoR2Application.onLoad = (Action)Delegate.Remove(RoR2Application.onLoad, new Action(SyncDisplaySkins)); MainMenuController.OnMainMenuInitialised -= SyncDisplaySkins; registration?.Dispose(); if ((Object)(object)instance == (Object)(object)this) { instance = null; } } } }