Decompiled source of EscapedTestSubject v0.9.3
WKEscapedSubject.dll
Decompiled 11 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.Audio; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("0.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace WKEscapedSubject { internal static class Assets { private static Dictionary<string, Texture2D>[] overlays; private static int frameCount = -1; private static readonly Dictionary<string, Sprite> spriteCache = new Dictionary<string, Sprite>(); private static readonly Sprite[] counter = (Sprite[])(object)new Sprite[10]; private const int ShootFrames = 9; private static readonly Dictionary<string, Texture2D>[] shootTex = new Dictionary<string, Texture2D>[10]; private static Dictionary<string, float[]> hands; private static HandPose[] shootKeys; public static int FrameCount { get { if (frameCount < 0) { frameCount = 0; while (AssetStore.DirExists("Overlays/stage" + (frameCount + 1))) { frameCount++; } overlays = new Dictionary<string, Texture2D>[frameCount]; Plugin.Log.LogInfo((object)("촉수 덧그림 프레임 " + frameCount + "개")); } return frameCount; } } public static Texture2D LoadTexture(string rel, bool point) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown byte[] array = AssetStore.Read(rel); if (array == null) { return null; } Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); if (!(bool)typeof(ImageConversion).GetMethod("LoadImage", new Type[3] { typeof(Texture2D), typeof(byte[]), typeof(bool) }).Invoke(null, new object[3] { val, array, false })) { return null; } ((Texture)val).filterMode = (FilterMode)(!point); ((Texture)val).wrapMode = (TextureWrapMode)1; ((Object)val).hideFlags = (HideFlags)32; return val; } public static Sprite LoadIcon(string file, WKAssetDatabase db, PerkType type) { //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) Texture2D val = LoadTexture(file, point: true); if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)("아이콘 파일이 없음: " + file)); val = Texture2D.whiteTexture; } List<float> list = new List<float>(); if (db.perkAssets != null) { foreach (Perk perkAsset in db.perkAssets) { if (!((Object)(object)perkAsset == (Object)null) && !((Object)(object)perkAsset.icon == (Object)null) && perkAsset.perkType == type) { Rect rect = perkAsset.icon.rect; float width = ((Rect)(ref rect)).width; rect = perkAsset.icon.rect; list.Add(Mathf.Max(width, ((Rect)(ref rect)).height) / perkAsset.icon.pixelsPerUnit); } } } list.Sort(); float num = ((list.Count > 0) ? list[list.Count / 2] : 1f); Sprite obj = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), (float)Mathf.Max(((Texture)val).width, ((Texture)val).height) / num); ((Object)obj).name = Path.GetFileNameWithoutExtension(file); ((Object)obj).hideFlags = (HideFlags)32; return obj; } public static void PreloadStep() { for (int i = 0; i < FrameCount; i++) { if (overlays[i] == null) { overlays[i] = LoadFrame(i + 1); return; } } for (int j = 2; j <= 9; j++) { if (shootTex[j] == null) { shootTex[j] = LoadShootFrame(j); break; } } } private static Dictionary<string, Texture2D> LoadFrame(int frame) { Dictionary<string, Texture2D> dictionary = new Dictionary<string, Texture2D>(StringComparer.OrdinalIgnoreCase); foreach (string item in AssetStore.List("Overlays/stage" + frame, ".png")) { Texture2D val = LoadTexture(item, point: true); if ((Object)(object)val != (Object)null) { dictionary[Path.GetFileNameWithoutExtension(item)] = val; } } return dictionary; } public static Sprite GetOverlay(int stage, Sprite baseSprite) { if ((Object)(object)baseSprite == (Object)null || stage < 1 || stage > FrameCount) { return null; } if (overlays[stage - 1] == null) { overlays[stage - 1] = LoadFrame(stage); } string text = ((Object)baseSprite).name.Replace("(Clone)", "").Trim(); if (!overlays[stage - 1].TryGetValue(text, out var value)) { return null; } return MakeSprite("Tentacle_" + stage, text, value, baseSprite); } private static void LoadHands() { if (hands != null) { return; } hands = new Dictionary<string, float[]>(StringComparer.OrdinalIgnoreCase); string[] array = AssetStore.ReadLines("Shoot/hands.txt"); if (array == null) { return; } string[] array2 = array; for (int i = 0; i < array2.Length; i++) { string[] array3 = array2[i].Split(new char[1] { ' ' }); if (array3.Length >= 4 && TryF(array3[1], out var v) && TryF(array3[2], out var v2)) { hands[array3[0]] = new float[3] { v, v2, (array3[3] == "1") ? 1f : 0f }; } } } private static bool TryF(string s, out float v) { return float.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out v); } private static string BaseName(Sprite sp) { return ((Object)sp).name.Replace("(Clone)", "").Trim(); } public static Vector2 GetWrist(string spriteName, float width, float height) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) LoadHands(); if (hands.TryGetValue(spriteName.Replace("(Clone)", "").Trim(), out var value)) { return new Vector2(value[0] * width / 128f, value[1] * height / 128f); } return new Vector2(width * 0.4f, height * 0.85f); } public static HandPose ShootKey(int frame) { if (shootKeys == null) { shootKeys = new HandPose[10]; for (int i = 0; i <= 9; i++) { shootKeys[i] = HandPose.Identity; } string[] array = AssetStore.ReadLines("Shoot/keys.txt"); if (array != null) { string[] array2 = array; for (int j = 0; j < array2.Length; j++) { string[] array3 = array2[j].Split(new char[1] { ' ' }); if (array3.Length >= 6 && int.TryParse(array3[0], out var result) && result >= 1 && result <= 9 && TryF(array3[2], out var v) && TryF(array3[3], out var v2) && TryF(array3[4], out var v3) && TryF(array3[5], out var v4)) { shootKeys[result] = new HandPose { scale = v, rot = v2, dx = v3, dy = v4 }; } } } } return shootKeys[Mathf.Clamp(frame, 1, 9)]; } private static Dictionary<string, Texture2D> LoadShootFrame(int frame) { Dictionary<string, Texture2D> dictionary = new Dictionary<string, Texture2D>(StringComparer.OrdinalIgnoreCase); foreach (string item in AssetStore.List("Shoot/frame" + frame, ".png")) { Texture2D val = LoadTexture(item, point: true); if ((Object)(object)val != (Object)null) { dictionary[Path.GetFileNameWithoutExtension(item)] = val; } } return dictionary; } public static Sprite GetShoot(int frame, Sprite baseSprite, out bool full) { full = false; if ((Object)(object)baseSprite == (Object)null || frame < 2 || frame > 9) { return null; } if (shootTex[frame] == null) { shootTex[frame] = LoadShootFrame(frame); } string text = BaseName(baseSprite); if (!shootTex[frame].TryGetValue(text, out var value)) { return null; } LoadHands(); full = hands.TryGetValue(text, out var value2) && value2[2] > 0f; return MakeSprite("Shoot_" + frame, text, value, baseSprite); } private static Sprite MakeSprite(string prefix, string name, Texture2D tex, Sprite baseSprite) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) Rect rect = baseSprite.rect; Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(baseSprite.pivot.x / ((Rect)(ref rect)).width, baseSprite.pivot.y / ((Rect)(ref rect)).height); float num = baseSprite.pixelsPerUnit * ((float)((Texture)tex).width / ((Rect)(ref rect)).width); string key = prefix + "|" + name + "|" + num + "|" + val.x + "," + val.y; if (!spriteCache.TryGetValue(key, out var value) || (Object)(object)value == (Object)null) { value = Sprite.Create(tex, new Rect(0f, 0f, (float)((Texture)tex).width, (float)((Texture)tex).height), val, num); ((Object)value).name = prefix + "_" + name; ((Object)value).hideFlags = (HideFlags)32; spriteCache[key] = value; } return value; } public static Sprite GetCounter(int remaining) { //IL_0068: 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) remaining = Mathf.Clamp(remaining, 0, counter.Length - 1); if ((Object)(object)counter[remaining] == (Object)null) { Texture2D val = LoadTexture("UI/barnacle_counter_" + remaining + ".png", point: true); if ((Object)(object)val == (Object)null) { return null; } counter[remaining] = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(1f, 0f), 1f); ((Object)counter[remaining]).hideFlags = (HideFlags)32; } return counter[remaining]; } } internal static class AssetStore { private const string Prefix = "Assets/"; private static Dictionary<string, string> res; private static void Init() { if (res != null) { return; } res = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); string[] manifestResourceNames = typeof(Plugin).Assembly.GetManifestResourceNames(); foreach (string text in manifestResourceNames) { string text2 = text.Replace('\\', '/'); if (text2.StartsWith("Assets/", StringComparison.OrdinalIgnoreCase)) { res[text2.Substring("Assets/".Length)] = text; } } Plugin.Log.LogInfo((object)("Embedded assets: " + res.Count)); } private static string DiskPath(string rel) { return Path.Combine(Plugin.AssetDir, rel.Replace('/', Path.DirectorySeparatorChar)); } public static byte[] Read(string rel) { Init(); if (res.TryGetValue(rel, out var value)) { using (Stream stream = typeof(Plugin).Assembly.GetManifestResourceStream(value)) { using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); return memoryStream.ToArray(); } } string path = DiskPath(rel); if (!File.Exists(path)) { return null; } return File.ReadAllBytes(path); } public static string[] ReadLines(string rel) { byte[] array = Read(rel); if (array == null) { return null; } return Encoding.UTF8.GetString(array).Replace("\r", "").Split(new char[1] { '\n' }); } public static bool DirExists(string relDir) { Init(); string value = relDir.TrimEnd(new char[1] { '/' }) + "/"; foreach (string key in res.Keys) { if (key.StartsWith(value, StringComparison.OrdinalIgnoreCase)) { return true; } } return Directory.Exists(DiskPath(relDir)); } public static List<string> List(string relDir, string ext) { Init(); string text = relDir.TrimEnd(new char[1] { '/' }) + "/"; List<string> list = new List<string>(); foreach (string key in res.Keys) { if (key.StartsWith(text, StringComparison.OrdinalIgnoreCase) && key.IndexOf('/', text.Length) < 0 && key.EndsWith(ext, StringComparison.OrdinalIgnoreCase)) { list.Add(key); } } if (list.Count == 0 && Directory.Exists(DiskPath(relDir))) { string[] files = Directory.GetFiles(DiskPath(relDir), "*" + ext); foreach (string path in files) { list.Add(text + Path.GetFileName(path)); } } return list; } } internal static class BindingFactory { public const string BindingName = "Trinket_Binding_EscapedSubject"; public const string PerkId = "Perk_Binding_EscapedSubject"; public const string BioTrinketName = "Trinket_BioExperimented"; private const string HotZoneFlag = "session_sacrificed_grub"; private static Trinket binding; private static Perk perk; internal static string Title => Plugin.L("Escaped Test Subject", "탈출한 생체 실험자"); public static void EnsureRegistered() { IList value = Traverse.Create(typeof(CL_AssetManager)).Field("databases").GetValue<IList>(); if (value == null || value.Count == 0) { return; } WKAssetDatabase value2 = Traverse.Create(value[0]).Field("database").GetValue<WKAssetDatabase>(); if ((Object)(object)value2 == (Object)null) { return; } if ((Object)(object)binding == (Object)null) { Build(value2); } if (value2.perkAssets != null && !value2.perkAssets.Contains(perk)) { value2.perkAssets.Add(perk); } if (value2.trinketAssets != null && !value2.trinketAssets.Contains(binding)) { value2.trinketAssets.Add(binding); } if (value2.gamemodeAssets == null) { return; } foreach (M_Gamemode gamemodeAsset in value2.gamemodeAssets) { AddToGamemode(gamemodeAsset); } } public static void AddToGamemode(M_Gamemode gm) { if (!((Object)(object)gm == (Object)null) && !((Object)(object)gm.availableTrinkets == (Object)null) && !((Object)(object)binding == (Object)null)) { List<Trinket> bindings = gm.availableTrinkets.bindings; if (bindings != null && !bindings.Contains(binding)) { bindings.Add(binding); } } } private static string PickerText() { return string.Format(Plugin.L("A test subject mutated while escaping the lab. Weakened, but grotesque mutations awaken. <color=#FFD454>(No leaderboards)</color>\n<color=#7CFF7C>+ Sticky Surface</color>: stay on the ground {0:0}s for the grub effect ({1:0}s once you grab a wall, no stamina drain for the first {2:0}s)\n<color=#7CFF7C>+ Tentacle Mutation</color>: after eating a grub, pill, injector or Lemon Roach, reach with a bare hand for {3:0}s → {4} tentacle shots, stamina +{5:0}%\n<color=#FF6B6B>- Weakness</color>: health {6:0}%, move speed {7:0}%, inventory {8:0}, gravity +{9:0}%, stamina {10:0}% <color=#FFD454>!</color> Hostile Mother, incompatible with 'Biologically Experimented'", "실험실을 탈출하며 변이된 실험체. 몸은 약해졌지만 기괴한 변이 능력이 발현됩니다. <color=#FFD454>(리더보드 제외)</color>\n<color=#7CFF7C>+ 점착성 표면</color>: 지면에 {0:0}초 머무르면 굼벵이 효과 (벽을 짚고 {1:0}초, 처음 {2:0}초는 스태미나 유지)\n<color=#7CFF7C>+ 촉수 변이</color>: 굼벵이·알약·주사기·Lemon 로치 섭취 후 맨손 {3:0}초 → 촉수 사출 {4}회, 스태미나 +{5:0}%\n<color=#FF6B6B>- 약화</color>: 체력 {6:0}%, 이동속도 {7:0}%, 인벤토리 {8:0}, 중력 +{9:0}%, 스태미나 {10:0}% <color=#FFD454>!</color> 둥지의 어머니가 적대, '생체 실험된'과 함께 쓸 수 없음"), Plugin.StickyGroundSeconds.Value, Plugin.StickyDuration.Value, Plugin.StickyNoDrain.Value, Plugin.MutateSeconds.Value, Plugin.Charges.Value, Plugin.TentacleStamina.Value * 100f, Plugin.Health.Value * 100f, Plugin.MoveSpeed.Value * 100f, Plugin.Capacity.Value, Plugin.Gravity.Value * 100f, Plugin.Stamina.Value * 100f); } private static string PerkText() { return string.Format(Plugin.L("A test subject whose body mutated while escaping the lab. Heavier and weaker, but in extreme situations grotesque mutations awaken.\n<color=#7CFF7C>+ Sticky Surface</color>: stay on the ground for {0:0}s to gain the grub effect. It lasts {1:0}s from the moment you grab a wall, and stamina doesn't drain for the first {7:0}s\n<color=#7CFF7C>+ Tentacle Mutation</color>: after eating a grub, pill, injector or Lemon Roach, reach out with a bare hand for {2:0}s to turn both hands into tentacles. {3} tentacle shots (hold the bare-hand button {8:0.##}s, range {10:0}m). The tentacle stays while the button is held, and the shooting hand can grab bare wall near the anchor. Stamina +{11:0}% while in tentacle form\n<color=#FF6B6B>- Weakness</color>: health {9:0}%, move speed {12:0}%, inventory capacity {4:0}, gravity +{5:0}%, stamina {6:0}%\n<color=#FFD454>! Nest</color>: the Mother recognizes the escaped subject and turns hostile\n<color=#FFD454>! Incompatible</color>: trinket 'Biologically Experimented'\n<color=#FFD454>! Leaderboards</color>: runs with this binding are not submitted", "실험실을 탈출하는 과정에서 신체가 변이된 실험체. 몸은 무겁고 약해졌지만, 극한의 상황에서 기괴한 변이 능력이 발현됩니다.\n<color=#7CFF7C>+ 점착성 표면</color>: 지면에 {0:0}초간 머무르면 굼벵이 효과 발현. 벽을 짚는 순간부터 {1:0}초 유지, 처음 {7:0}초는 스태미나가 줄지 않음\n<color=#7CFF7C>+ 촉수 변이</color>: 굼벵이·알약·주사기·Lemon 로치 섭취 후 맨손을 {2:0}초간 뻗고 있으면 양손이 촉수로 변이, 촉수 사출 {3}회 (맨손 버튼 {8:0.##}초 유지, 사거리 {10:0}m). 버튼을 누르고 있는 동안 촉수가 유지되고, 박힌 곳 가까이에서는 쏜 손으로 맨벽도 잡을 수 있음. 촉수 상태 동안 스태미나 +{11:0}%\n<color=#FF6B6B>- 약화</color>: 체력 {9:0}%, 이동속도 {12:0}%, 인벤토리 용량 {4:0}, 중력 +{5:0}%, 스태미나 {6:0}%\n<color=#FFD454>! 둥지</color>: 어머니가 탈출한 실험체를 알아보고 적대합니다\n<color=#FFD454>! 함께 쓸 수 없음</color>: 장신구 '생체 실험된'\n<color=#FFD454>! 리더보드</color>: 이 속박을 낀 판은 기록이 제출되지 않습니다"), Plugin.StickyGroundSeconds.Value, Plugin.StickyDuration.Value, Plugin.MutateSeconds.Value, Plugin.Charges.Value, Plugin.Capacity.Value, Plugin.Gravity.Value * 100f, Plugin.Stamina.Value * 100f, Plugin.StickyNoDrain.Value, Plugin.ShootHold.Value, Plugin.Health.Value * 100f, Plugin.TentacleRange.Value, Plugin.TentacleStamina.Value * 100f, Plugin.MoveSpeed.Value * 100f); } private static void Build(WKAssetDatabase db) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Expected O, but got Unknown //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Expected O, but got Unknown Sprite val = Assets.LoadIcon("binding_icon.png", db, (PerkType)9); string description = PerkText(); perk = ScriptableObject.CreateInstance<Perk>(); ((Object)perk).name = "Perk_Binding_EscapedSubject"; ((Object)perk).hideFlags = (HideFlags)32; perk.id = "Perk_Binding_EscapedSubject"; perk.title = Title; perk.description = description; perk.flavorText = ""; perk.perkType = (PerkType)9; perk.tags = new List<string> { "binding" }; perk.flags = new List<string> { "session_sacrificed_grub" }; perk.playerTag = new List<string>(); perk.spawnPool = (PerkPool)2; perk.spawnInEndless = false; perk.canStack = false; perk.stackMax = 1; perk.multiplierCurve = AnimationCurve.Constant(0f, 1f, 0f); perk.competitive = true; perk.removeOnCleanse = false; perk.unlockProgressionID = ""; perk.icon = val; perk.useBuff = true; perk.buff = new BuffContainer { id = "Perk_Binding_EscapedSubject", desc = "", buffs = new List<Buff> { MakeBuff("addGravity", Plugin.Gravity.Value), MakeBuff("addStamina", Plugin.Stamina.Value), MakeBuff("addCapacity", Plugin.Capacity.Value), MakeBuff("addSpeed", Plugin.MoveSpeed.Value) }, loseOverTime = false, loseRate = 0f, buffTime = 1f, multiplier = 1f }; perk.useBaseBuff = false; perk.baseBuff = new BuffContainer { id = "", desc = "", buffs = new List<Buff>() }; perk.modules = new List<PerkModule>(); binding = ScriptableObject.CreateInstance<Trinket>(); ((Object)binding).name = "Trinket_Binding_EscapedSubject"; ((Object)binding).hideFlags = (HideFlags)32; binding.title = Title; binding.description = PickerText(); binding.flavorText = ""; binding.isBinding = true; binding.icon = val; binding.lockIcon = val; binding.cost = Plugin.Cost.Value; binding.itemsToGrant = new List<Item_Object>(); binding.perksToGrant = new List<Perk> { perk }; binding.pouchesToGrant = 0; binding.progressionUnlock = null; binding.scoreMultiplierBonus = Plugin.ScoreBonus.Value; binding.scoreBonus = 0f; binding.comingSoon = false; binding.settingBlacklist = new List<string>(); binding.activateOrder = 0; Plugin.Log.LogInfo((object)"속박 생성 완료: Trinket_Binding_EscapedSubject"); } private static Buff MakeBuff(string id, float amount) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown return new Buff { id = id, maxAmount = amount, amount = amount }; } public static bool IsActive(ENT_Player p) { if ((Object)(object)p != (Object)null) { return p.HasPerk("Perk_Binding_EscapedSubject"); } return false; } } internal struct HandPose { public float scale; public float rot; public float dx; public float dy; public static readonly HandPose Identity = new HandPose { scale = 1f }; public bool IsIdentity { get { if (scale == 1f && rot == 0f && dx == 0f) { return dy == 0f; } return false; } } public static HandPose Lerp(HandPose a, HandPose b, float t) { return new HandPose { scale = Mathf.Lerp(a.scale, b.scale, t), rot = Mathf.Lerp(a.rot, b.rot, t), dx = Mathf.Lerp(a.dx, b.dx, t), dy = Mathf.Lerp(a.dy, b.dy, t) }; } } internal class HandOverlay : MonoBehaviour { public static readonly int[] Stage = new int[2]; public static readonly int[] ShootFrame = new int[2]; public static readonly HandPose[] Pose = new HandPose[2] { HandPose.Identity, HandPose.Identity }; public static float Pulse; private SpriteRenderer target; private SpriteRenderer bodySprite; private SpriteRenderer overlay; private Material overlayMat; private int hand; private Vector3 restPos; private Vector3 restScale; private Quaternion restRot; private bool moves; private bool hidBase; public static void SetStage(int s) { Stage[0] = (Stage[1] = s); } public static void Attach(SpriteRenderer target, int hand, SpriteRenderer body) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)target == (Object)null) && !((Object)(object)((Component)target).GetComponentInChildren<HandOverlay>(true) != (Object)null)) { GameObject val = new GameObject("WKEscaped_TentacleOverlay"); val.layer = ((Component)target).gameObject.layer; val.transform.SetParent(((Component)target).transform, false); HandOverlay handOverlay = val.AddComponent<HandOverlay>(); handOverlay.target = target; handOverlay.bodySprite = (((Object)(object)body != (Object)null) ? body : target); handOverlay.hand = Mathf.Clamp(hand, 0, 1); handOverlay.overlay = val.AddComponent<SpriteRenderer>(); handOverlay.overlayMat = ((Renderer)handOverlay.overlay).sharedMaterial; Transform transform = ((Component)target).transform; handOverlay.restPos = transform.localPosition; handOverlay.restRot = transform.localRotation; handOverlay.restScale = transform.localScale; handOverlay.moves = (Object)(object)target == (Object)(object)handOverlay.bodySprite || !transform.IsChildOf(((Component)handOverlay.bodySprite).transform); } } private void OnDestroy() { if ((Object)(object)target != (Object)null && hidBase) { ((Renderer)target).forceRenderingOff = false; } } private void LateUpdate() { //IL_0171: 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_01f9: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)target == (Object)null) { Object.Destroy((Object)(object)((Component)this).gameObject); return; } ApplyPose(); bool num = ((Renderer)target).enabled && ((Component)target).gameObject.activeInHierarchy; Sprite val = null; bool full = false; if (num && ShootFrame[hand] >= 2) { val = Assets.GetShoot(ShootFrame[hand], target.sprite, out full); } if (num && (Object)(object)val == (Object)null && Stage[hand] > 0) { val = Assets.GetOverlay(Stage[hand], target.sprite); full = false; } bool flag = (Object)(object)val != (Object)null && full; if (flag != hidBase) { ((Renderer)target).forceRenderingOff = flag; hidBase = flag; } ((Renderer)overlay).enabled = (Object)(object)val != (Object)null; if (!((Object)(object)val == (Object)null)) { overlay.sprite = val; overlay.flipX = target.flipX; overlay.flipY = target.flipY; ((Renderer)overlay).sortingLayerID = ((Renderer)target).sortingLayerID; ((Renderer)overlay).sortingOrder = ((Renderer)target).sortingOrder + 1; overlay.color = new Color(1f, 1f, 1f, target.color.a); ((Renderer)overlay).sharedMaterial = ((full && (Object)(object)((Renderer)target).sharedMaterial != (Object)null) ? ((Renderer)target).sharedMaterial : overlayMat); float num2 = (full ? 1f : (1f + Pulse * 0.025f * Mathf.Sin(Time.time * 16f))); ((Component)this).transform.localScale = new Vector3(num2, 1f / num2, 1f); } } private void ApplyPose() { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006f: 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_0080: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: 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_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0142: 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) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0172: 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_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_0189: 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_0193: 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) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) if (moves) { Transform transform = ((Component)target).transform; HandPose handPose = Pose[hand]; Sprite val = (((Object)(object)bodySprite != (Object)null) ? bodySprite.sprite : null); if (handPose.IsIdentity || (Object)(object)val == (Object)null) { transform.localPosition = restPos; transform.localRotation = restRot; transform.localScale = restScale; return; } Rect rect = val.rect; float pixelsPerUnit = val.pixelsPerUnit; float num = ((Rect)(ref rect)).width / 128f; Vector2 wrist = Assets.GetWrist(((Object)val).name, ((Rect)(ref rect)).width, ((Rect)(ref rect)).height); float num2 = (bodySprite.flipX ? (-1f) : 1f); Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor((wrist.x - val.pivot.x) / pixelsPerUnit * num2, (((Rect)(ref rect)).height - wrist.y - val.pivot.y) / pixelsPerUnit, 0f); Quaternion val3 = Quaternion.Euler(0f, 0f, (0f - handPose.rot) * num2); Vector3 val4 = val2 - val3 * (val2 * handPose.scale) + new Vector3(handPose.dx * num * num2 / pixelsPerUnit, (0f - handPose.dy) * num / pixelsPerUnit, 0f); transform.localPosition = restPos + restRot * Vector3.Scale(restScale, val4); transform.localRotation = restRot * val3; transform.localScale = restScale * handPose.scale; } } } internal static class HandSkin { private const string CosmeticId = "Infested"; private static ENT_Player appliedTo; private static readonly List<Cosmetic_HandItem>[] original = new List<Cosmetic_HandItem>[2]; private static Cosmetic_HandItem infested; private static Cosmetic_HandItem Infested() { if ((Object)(object)infested != (Object)null) { return infested; } Traverse.Create(typeof(CL_CosmeticManager)).Field("cosmeticHandDict").GetValue<Dictionary<string, Cosmetic_HandItem>>()?.TryGetValue("Infested", out infested); if ((Object)(object)infested == (Object)null) { Plugin.Log.LogWarning((object)"Infested 손 코스메틱을 찾지 못함"); } return infested; } public static void Set(ENT_Player player, bool on) { if (on) { if ((Object)(object)appliedTo == (Object)(object)player || (Object)(object)player == (Object)null) { return; } if ((Object)(object)appliedTo != (Object)null) { Restore(); } Cosmetic_HandItem val = Infested(); if ((Object)(object)val == (Object)null) { return; } for (int i = 0; i < player.hands.Length && i < 2; i++) { Hand val2 = player.hands[i]; if (val2.currentCosmetics == null) { val2.currentCosmetics = new List<Cosmetic_HandItem>(); } original[i] = new List<Cosmetic_HandItem>(val2.currentCosmetics); foreach (Cosmetic_HandItem currentCosmetic in val2.currentCosmetics) { currentCosmetic.ClearCosmetic(); } val2.currentCosmetics.Clear(); val2.currentCosmetics.Add(val); } appliedTo = player; } else if ((Object)(object)appliedTo != (Object)null) { Restore(); } } private static void Restore() { ENT_Player val = appliedTo; appliedTo = null; if ((Object)(object)val == (Object)null) { return; } if ((Object)(object)infested != (Object)null) { infested.ClearCosmetic(); } for (int i = 0; i < val.hands.Length && i < 2; i++) { Hand val2 = val.hands[i]; if (val2.currentCosmetics != null) { val2.currentCosmetics.Clear(); if (original[i] != null) { val2.currentCosmetics.AddRange(original[i]); } original[i] = null; } } } } [HarmonyPatch(typeof(M_Gamemode), "Finish")] internal static class Patch_Finish_NoLeaderboard { private static void Prefix(M_Gamemode __instance, out bool __state) { __state = WK_Leaderboard_Core.disableLeaderboards; if (UsedThisRun(__instance)) { WK_Leaderboard_Core.disableLeaderboards = true; Plugin.Log.LogInfo((object)"Escaped Test Subject was used this run: leaderboard submission skipped"); } } private static Exception Finalizer(Exception __exception, bool __state) { WK_Leaderboard_Core.disableLeaderboards = __state; return __exception; } private static bool UsedThisRun(M_Gamemode gm) { try { if (BindingFactory.IsActive(ENT_Player.GetPlayer())) { return true; } } catch (Exception) { } try { List<string> gamemodeTrinkets = StatManager.saveData.GetGamemodeTrinkets(gm.GetGamemodeName(true)); if (gamemodeTrinkets != null && gamemodeTrinkets.Exists((string n) => n?.Contains("Trinket_Binding_EscapedSubject") ?? false)) { return true; } } catch (Exception) { } return false; } } internal class MutationController : MonoBehaviour { private enum State { Idle, Charged, Tentacle, Reverting } private enum Sticky { None, Armed, Counting } private enum Shot { None, Charging, Fired, Retract } private static MutationController instance; private State state; private float progress; private float revertTime; private int charges; private Sticky sticky; private float groundTime; private BuffContainer stickyBuff; private BuffContainer grubTemplate; private bool grubLoaded; private readonly TentacleGrapple grapple = new TentacleGrapple(); private readonly float[] holdTime = new float[2]; private readonly bool[] pending = new bool[2]; private readonly float[] lastGrip = new float[2]; private Image counterImage; private float stickyNoDrainLeft; private Image stickyVignette; private float stickyVignetteAlpha; private ENT_Player healthAppliedTo; private static readonly Color StickyTint = new Color(0.24f, 0.04f, 0.33f, 1f); private const string TentacleStaminaBuffId = "escapedSubject_tentacleStamina"; private readonly Sounds.Player chargeSound = new Sounds.Player("mutation_charge.wav"); private readonly Sounds.Player shootSound = new Sounds.Player("tentacle_shoot.wav"); private readonly Dictionary<int, Camera> layerCamera = new Dictionary<int, Camera>(); private readonly Shot[] shot = new Shot[2]; private readonly float[] shotTime = new float[2]; private float trembleNext; private readonly HandPose[] trembleTarget = new HandPose[2] { HandPose.Identity, HandPose.Identity }; private static readonly float[] ChargeKeyTimes = new float[5] { 0f, 0.1f, 0.35f, 0.6f, 0.75f }; private static readonly float[] FiredKeyTimes = new float[4] { 0f, 0.07f, 0.16f, 0.34f }; private const float RetractSeconds = 0.16f; private void Awake() { instance = this; grapple.OnLatch = delegate { charges = Mathf.Max(0, charges - 1); }; grapple.OnRelease = delegate { if (state == State.Tentacle && charges <= 0) { StartRevert(); } }; grapple.OnShotEnd = delegate(int hand) { if (hand >= 0 && hand < 2) { pending[hand] = false; holdTime[hand] = 0f; } }; grapple.PalmPoint = PalmPoint; } private void OnEnable() { SceneManager.sceneLoaded += OnSceneLoaded; } private void OnDisable() { SceneManager.sceneLoaded -= OnSceneLoaded; } private void OnSceneLoaded(Scene s, LoadSceneMode m) { BindingFactory.EnsureRegistered(); grapple.Reset(); } public static void ResetRun() { if (!((Object)(object)instance == (Object)null)) { instance.state = State.Idle; instance.progress = 0f; instance.charges = 0; instance.groundTime = 0f; instance.sticky = Sticky.None; instance.stickyBuff = null; instance.stickyNoDrainLeft = 0f; instance.grapple.Reset(); instance.chargeSound.Stop(); instance.shootSound.Stop(); instance.RemoveTentacleStamina(ENT_Player.GetPlayer()); } } public static void OnConsume(HandItem_Buff item) { if (!((Object)(object)instance == (Object)null) && BindingFactory.IsActive(ENT_Player.GetPlayer()) && IsChargeItem(item) && instance.state == State.Idle) { instance.state = State.Charged; instance.progress = 0f; Plugin.Log.LogInfo((object)("변이 충전: " + ((Object)((Component)item).gameObject).name)); } } private static bool IsChargeItem(HandItem_Buff h) { if (h is HandItem_Buff_Grub) { return true; } string text = ((Object)((Component)h).gameObject).name; if (((HandItem)h).item != null) { text = text + "|" + ((HandItem)h).item.prefabName + "|" + ((HandItem)h).item.itemName; } string[] array = Plugin.ChargeKeywords.Value.Split(new char[1] { ',' }); for (int i = 0; i < array.Length; i++) { string text2 = array[i].Trim(); if (text2.Length > 0 && text.IndexOf(text2, StringComparison.OrdinalIgnoreCase) >= 0) { return true; } } return false; } private void Update() { ENT_Player val = null; try { val = ENT_Player.GetPlayer(); } catch (Exception) { } if (!((Object)(object)val != (Object)null) || ((GameEntity)val).dead || !BindingFactory.IsActive(val)) { HandOverlay.SetStage(0); HandOverlay.Pulse = 0f; ResetHandMotion(); ShowCounter(0); UpdateStickyVignette(0f); HandSkin.Set(val, on: false); if (grapple.Latched || grapple.Primed) { grapple.Reset(); } chargeSound.Stop(); shootSound.Stop(); return; } ApplyHealth(val); Assets.PreloadStep(); grapple.Tick(val); HandSkin.Set(val, (state == State.Charged && progress > 0f) || state == State.Tentacle || state == State.Reverting); bool flag = (Object)(object)CL_GameManager.gMan != (Object)null && CL_GameManager.gMan.isPaused; for (int i = 0; i < val.hands.Length && i < 2; i++) { Hand val2 = val.hands[i]; HandOverlay.Attach(val2.handSprite, i, val2.handSprite); HandOverlay.Attach(val2.handForegroundSprite, i, val2.handSprite); } grapple.Load(); if (Plugin.DebugKeys.Value) { if (KeyDown((KeyCode)287) && state == State.Idle) { state = State.Charged; } if (KeyDown((KeyCode)288)) { EnterTentacle(); } } if (!flag) { UpdateSticky(val); } switch (state) { case State.Idle: HandOverlay.SetStage(0); HandOverlay.Pulse = 0f; ResetHandMotion(); break; case State.Charged: UpdateMutating(val, flag); break; case State.Tentacle: { HandOverlay.SetStage(Assets.FrameCount); float num = Mathf.Max(holdTime[0], holdTime[1]); HandOverlay.Pulse = 0.6f + 1.6f * Mathf.Clamp01(num / Mathf.Max(0.1f, Plugin.ShootHold.Value)); if (!flag) { UpdateTentacle(val); } UpdateShootMotion(val, flag); break; } case State.Reverting: revertTime += Time.deltaTime; HandOverlay.SetStage(Mathf.Clamp(Mathf.CeilToInt((1f - revertTime / 0.5f) * (float)Assets.FrameCount), 0, Assets.FrameCount)); HandOverlay.Pulse = 0f; UpdateShootMotion(val, flag); if (revertTime >= 0.5f) { state = State.Idle; HandOverlay.SetStage(0); } break; } ShowCounter((state == State.Tentacle) ? charges : 0); } private void LateUpdate() { grapple.LateUpdate(); } private void UpdateMutating(ENT_Player player, bool paused) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) bool flag = true; bool flag2 = false; Hand[] hands = player.hands; foreach (Hand val in hands) { if ((Object)(object)val.GetHandItem() != (Object)null) { flag = false; } if (InputManager.GetButton(val.fireButton).Pressed && (int)val.interactState == 0) { flag2 = true; } } if (flag && flag2 && !paused && !Inventory.IsShowingInventory()) { if (progress <= 0f) { chargeSound.Play(((Component)this).gameObject); } progress += Time.deltaTime; } else { if (progress > 0f) { chargeSound.Stop(); } progress = 0f; } float num = Mathf.Max(0.5f, Plugin.MutateSeconds.Value); float num2 = progress / num; HandOverlay.SetStage((progress > 0f) ? Mathf.Clamp(Mathf.CeilToInt(num2 * (float)Assets.FrameCount), 1, Assets.FrameCount) : 0); HandOverlay.Pulse = Mathf.Clamp01((num2 - 0.6f) / 0.4f); UpdateTremble((progress > 0f && !paused) ? (num2 * 5f) : (-1f)); if (progress >= num) { EnterTentacle(); ResetHandMotion(); } } private void ApplyHealth(ENT_Player player) { if (!((Object)(object)healthAppliedTo == (Object)(object)player)) { healthAppliedTo = player; float num = Mathf.Max(0.05f, 1f + Plugin.Health.Value); ((GameEntity)player).maxHealth = ((GameEntity)player).maxHealth * num; ((GameEntity)player).health = Mathf.Min(((GameEntity)player).health, ((GameEntity)player).maxHealth); Plugin.Log.LogInfo((object)("최대 체력 적용: " + ((GameEntity)player).maxHealth)); } } private void EnterTentacle() { state = State.Tentacle; charges = Plugin.Charges.Value; progress = 0f; pending[0] = (pending[1] = false); ENT_Player player = ENT_Player.GetPlayer(); if ((Object)(object)player != (Object)null) { for (int i = 0; i < player.hands.Length && i < 2; i++) { lastGrip[i] = player.hands[i].gripStrength; } } if ((Object)(object)player != (Object)null) { AddTentacleStamina(player); } Plugin.Log.LogInfo((object)("촉수 변이 완료: " + charges + "회")); } private void StartRevert() { state = State.Reverting; revertTime = 0f; grapple.Reset(); RemoveTentacleStamina(ENT_Player.GetPlayer()); } private void UpdateTentacle(ENT_Player player) { //IL_010d: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < player.hands.Length && i < 2; i++) { Hand val = player.hands[i]; ButtonInput button = InputManager.GetButton(val.fireButton); if (button.Down && (Object)(object)val.GetHandItem() == (Object)null) { holdTime[i] = 0f; pending[i] = true; } if (!button.Pressed) { if (pending[i] && grapple.HandId == i) { grapple.StopPrime(charges <= 0); } if (pending[i] && holdTime[i] < Plugin.ShootHold.Value) { shootSound.Stop(); } pending[i] = false; holdTime[i] = 0f; } else { if (!pending[i]) { continue; } if ((!grapple.Primed && !grapple.Latched) || grapple.HandId != i) { if ((Object)(object)val.GetHandItem() != (Object)null || (int)val.interactState != 0) { if (holdTime[i] > 0f && holdTime[i] < Plugin.ShootHold.Value) { shootSound.Stop(); } pending[i] = false; holdTime[i] = 0f; continue; } if (((grapple.Primed || grapple.Latched) && grapple.HandId != i) || charges <= 0) { continue; } if (holdTime[i] <= 0f) { shootSound.Play(((Component)this).gameObject); } holdTime[i] += Time.deltaTime; } if (holdTime[i] >= Plugin.ShootHold.Value) { grapple.Prime(i); } } } grapple.Update(player, charges <= 0); } private void ResetHandMotion() { for (int i = 0; i < 2; i++) { shot[i] = Shot.None; HandOverlay.Pose[i] = HandPose.Identity; HandOverlay.ShootFrame[i] = 0; } } private void UpdateTremble(float sec) { if (sec < 0f) { HandOverlay.Pose[0] = (HandOverlay.Pose[1] = HandPose.Identity); return; } bool flag = (sec >= 1f && sec < 1.12f) || (sec >= 3.5f && sec < 3.62f); if (Time.time >= trembleNext || flag) { trembleNext = Time.time + 0.06f; float num = 0.4f + 1.8f * sec / 5f; for (int i = 0; i < 2; i++) { trembleTarget[i] = new HandPose { scale = (flag ? 0.95f : (1f + Random.Range(-0.01f, 0.01f))), rot = Random.Range(-1f, 1f) * (0.6f + sec * 0.5f) + (flag ? 4f : 0f), dx = Random.Range(-1f, 1f) * num, dy = Random.Range(-1f, 1f) * num * 0.7f + (flag ? 3f : 0f) }; } } for (int j = 0; j < 2; j++) { HandOverlay.Pose[j] = HandPose.Lerp(HandOverlay.Pose[j], trembleTarget[j], Mathf.Clamp01(Time.deltaTime * 30f)); } } private void UpdateShootMotion(ENT_Player player, bool paused) { if (paused) { return; } float num = Mathf.Max(0.05f, Plugin.ShootHold.Value); for (int i = 0; i < player.hands.Length && i < 2; i++) { bool pressed = InputManager.GetButton(player.hands[i].fireButton).Pressed; bool flag = (grapple.Primed || grapple.Latched) && grapple.HandId == i; switch (shot[i]) { case Shot.None: if (state == State.Tentacle && pending[i] && holdTime[i] > 0f) { shot[i] = Shot.Charging; } break; case Shot.Charging: if (holdTime[i] >= num) { shot[i] = Shot.Fired; shotTime[i] = 0f; } else if (!pending[i] || holdTime[i] <= 0f) { shot[i] = Shot.None; } break; case Shot.Fired: shotTime[i] += Time.deltaTime; if (!(pressed && flag) && shotTime[i] >= FiredKeyTimes[2]) { shot[i] = Shot.Retract; shotTime[i] = 0f; } break; case Shot.Retract: shotTime[i] += Time.deltaTime; if (shotTime[i] >= 0.16f) { shot[i] = Shot.None; } break; } int num2; HandPose handPose; switch (shot[i]) { case Shot.Charging: { float num4 = holdTime[i] / num * 0.75f; int k; for (k = 0; k < ChargeKeyTimes.Length - 2 && num4 >= ChargeKeyTimes[k + 1]; k++) { } float t2 = Mathf.SmoothStep(0f, 1f, (num4 - ChargeKeyTimes[k]) / (ChargeKeyTimes[k + 1] - ChargeKeyTimes[k])); num2 = k + 1; handPose = HandPose.Lerp(Assets.ShootKey(k + 1), Assets.ShootKey(k + 2), t2); if (num2 >= 3) { handPose.dx += Random.Range(-0.6f, 0.6f); handPose.dy += Random.Range(-0.6f, 0.6f); } break; } case Shot.Fired: { float num3 = shotTime[i]; int j; for (j = 0; j < FiredKeyTimes.Length - 1 && num3 >= FiredKeyTimes[j + 1]; j++) { } num2 = 5 + j; if (j < FiredKeyTimes.Length - 1) { float t = Mathf.SmoothStep(0f, 1f, (num3 - FiredKeyTimes[j]) / (FiredKeyTimes[j + 1] - FiredKeyTimes[j])); handPose = HandPose.Lerp(Assets.ShootKey(5 + j), Assets.ShootKey(6 + j), t); } else { handPose = Assets.ShootKey(8); } break; } case Shot.Retract: num2 = 9; handPose = HandPose.Lerp(Assets.ShootKey(9), HandPose.Identity, Mathf.SmoothStep(0f, 1f, shotTime[i] / 0.16f)); break; default: num2 = 0; handPose = HandPose.Identity; break; } HandOverlay.ShootFrame[i] = num2; HandOverlay.Pose[i] = handPose; } } private void AddTentacleStamina(ENT_Player p) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0087: 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_00a2: Expected O, but got Unknown if (!((GameEntity)p).curBuffs.HasBuffContainer("escapedSubject_tentacleStamina")) { ((GameEntity)p).curBuffs.AddBuff(new BuffContainer { id = "escapedSubject_tentacleStamina", desc = "", buffs = new List<Buff> { new Buff { id = "addStamina", maxAmount = Plugin.TentacleStamina.Value, amount = Plugin.TentacleStamina.Value } }, loseOverTime = false, loseRate = 0f, buffTime = 1f, multiplier = 1f }); } } private void RemoveTentacleStamina(ENT_Player p) { if ((Object)(object)p != (Object)null && ((GameEntity)p).curBuffs != null && ((GameEntity)p).curBuffs.HasBuffContainer("escapedSubject_tentacleStamina")) { ((GameEntity)p).curBuffs.RemoveBuffContainer("escapedSubject_tentacleStamina"); } } private Vector3? PalmPoint(int handId, float depth) { //IL_011e: 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_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) try { ENT_Player player = ENT_Player.GetPlayer(); Camera main = Camera.main; if ((Object)(object)player == (Object)null || (Object)(object)main == (Object)null || handId < 0 || handId >= player.hands.Length) { return null; } SpriteRenderer handSprite = player.hands[handId].handSprite; if ((Object)(object)handSprite == (Object)null || (Object)(object)handSprite.sprite == (Object)null || !((Renderer)handSprite).enabled) { return null; } int layer = ((Component)handSprite).gameObject.layer; if (!layerCamera.TryGetValue(layer, out var value) || (Object)(object)value == (Object)null) { value = null; Camera[] allCameras = Camera.allCameras; foreach (Camera val in allCameras) { if ((val.cullingMask & (1 << layer)) != 0 && ((Object)(object)value == (Object)null || val.depth > value.depth)) { value = val; } } layerCamera[layer] = value; } if ((Object)(object)value == (Object)null) { return null; } Bounds bounds = ((Renderer)handSprite).bounds; Vector3 val2 = ((Bounds)(ref bounds)).center - ((Component)handSprite).transform.up * (((Bounds)(ref bounds)).extents.y * 0.2f); Vector3 val3 = value.WorldToScreenPoint(val2); if (val3.z <= 0f) { return null; } return main.ScreenToWorldPoint(new Vector3(val3.x, val3.y, depth)); } catch (Exception) { return null; } } private void UpdateSticky(ENT_Player player) { if (sticky != Sticky.None && (stickyBuff == null || !((GameEntity)player).curBuffs.currentBuffs.Contains(stickyBuff))) { sticky = Sticky.None; stickyBuff = null; groundTime = 0f; stickyNoDrainLeft = 0f; } if (sticky == Sticky.Armed) { UpdateStickyVignette(0.5f); if (player.IsHanging()) { sticky = Sticky.Counting; stickyBuff.buffTime = 1f; stickyBuff.loseOverTime = true; stickyNoDrainLeft = Plugin.StickyNoDrain.Value; for (int i = 0; i < player.hands.Length && i < 2; i++) { lastGrip[i] = player.hands[i].gripStrength; } } return; } if (sticky == Sticky.Counting) { UpdateStickyVignette(0.5f * Mathf.Clamp01(stickyBuff.buffTime)); if (!(stickyNoDrainLeft > 0f)) { return; } stickyNoDrainLeft -= Time.deltaTime; for (int j = 0; j < player.hands.Length && j < 2; j++) { Hand val = player.hands[j]; if (val.gripStrength < lastGrip[j]) { val.SetGripStrength(lastGrip[j]); } lastGrip[j] = val.gripStrength; } return; } UpdateStickyVignette(0f); if (player.IsGrounded(false) && !player.IsHanging()) { groundTime += Time.deltaTime; } else { groundTime = 0f; } if (!(groundTime < Plugin.StickyGroundSeconds.Value)) { groundTime = 0f; stickyBuff = MakeGrubBuff(); if (stickyBuff != null) { ((GameEntity)player).Buff(stickyBuff); stickyBuff = ((GameEntity)player).curBuffs.GetBuffContainer(stickyBuff.id) ?? stickyBuff; stickyBuff.loseOverTime = false; stickyBuff.buffTime = 1f; sticky = Sticky.Armed; } } } private BuffContainer MakeGrubBuff() { //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_017a: 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_0190: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Expected O, but got Unknown //IL_025b: Unknown result type (might be due to invalid IL or missing references) //IL_0260: Unknown result type (might be due to invalid IL or missing references) //IL_026b: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_0286: Expected O, but got Unknown //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Expected O, but got Unknown if (!grubLoaded) { grubLoaded = true; try { GameObject assetGameObject = CL_AssetManager.GetAssetGameObject("Denizen_SlugGrub", ""); Item_Object val = (((Object)(object)assetGameObject != (Object)null) ? assetGameObject.GetComponent<Item_Object>() : null); HandItem_Buff val2 = (HandItem_Buff)(((Object)(object)val != (Object)null && val.itemData != null) ? /*isinst with value type is only supported in some contexts*/: null); if ((Object)(object)val2 != (Object)null && val2.buff != null && val2.buff.buffs != null) { grubTemplate = val2.buff; List<string> list = new List<string>(); foreach (Buff buff in val2.buff.buffs) { list.Add(buff.id + "=" + buff.maxAmount); } Plugin.Log.LogInfo((object)("굼벵이 효과 로드: " + val2.buff.id + " [" + string.Join(", ", list.ToArray()) + "]")); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("굼벵이 효과 로드 실패: " + ex.Message)); } if (grubTemplate == null) { Plugin.Log.LogWarning((object)"굼벵이 효과를 찾지 못해 grabAnything으로 대체"); } } BuffContainer val3 = new BuffContainer { id = "escapedSubject_sticky", desc = "", buffs = new List<Buff>(), loseOverTime = false, loseRateEffectedByPerks = false, loseRate = 1f / Mathf.Max(0.1f, Plugin.StickyDuration.Value) }; if (grubTemplate != null) { foreach (Buff buff2 in grubTemplate.buffs) { if (!(buff2.id == "gooped_screen")) { val3.buffs.Add(new Buff { id = buff2.id, maxAmount = buff2.maxAmount, amount = buff2.maxAmount }); } } } else { val3.buffs.Add(new Buff { id = "grabAnything", maxAmount = 1f, amount = 1f }); } val3.Initialize(); return val3; } private void UpdateStickyVignette(float target) { //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) stickyVignetteAlpha = Mathf.Lerp(stickyVignetteAlpha, target, Time.unscaledDeltaTime * 3f); if ((Object)(object)stickyVignette == (Object)null) { if (stickyVignetteAlpha < 0.01f) { return; } try { CL_UIManager val = CL_UIManager.instance; if ((Object)(object)val == (Object)null || val.vignettes == null) { return; } Vignette val2 = val.vignettes.Find((Vignette v) => v.name == "goop"); if (val2 == null || (Object)(object)val2.image == (Object)null) { return; } GameObject val3 = Object.Instantiate<GameObject>(((Component)val2.image).gameObject, ((Component)val2.image).transform.parent); ((Object)val3).name = "WKEscaped_StickyVignette"; val3.transform.SetSiblingIndex(((Component)val2.image).transform.GetSiblingIndex() + 1); stickyVignette = val3.GetComponent<Image>(); Plugin.Log.LogInfo((object)("보라색 화면 생성 (원본 goop 색: " + ((object)Unsafe.As<Color, Color>(ref val2.color)/*cast due to .constrained prefix*/).ToString() + ")")); } catch (Exception ex) { Plugin.Log.LogWarning((object)("보라색 화면 생성 실패: " + ex.Message)); return; } } Color stickyTint = StickyTint; stickyTint.a = stickyVignetteAlpha; ((Graphic)stickyVignette).color = stickyTint; ((Behaviour)stickyVignette).enabled = stickyVignetteAlpha > 0.005f; } private void ShowCounter(int remaining) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: 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_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) if (remaining <= 0) { if ((Object)(object)counterImage != (Object)null) { ((Behaviour)counterImage).enabled = false; } return; } if ((Object)(object)counterImage == (Object)null) { GameObject val = new GameObject("WKEscaped_BarnacleCounter", new Type[1] { typeof(Canvas) }); Object.DontDestroyOnLoad((Object)(object)val); Canvas component = val.GetComponent<Canvas>(); component.renderMode = (RenderMode)0; component.sortingOrder = 29000; GameObject val2 = new GameObject("Counter", new Type[2] { typeof(RectTransform), typeof(Image) }); val2.transform.SetParent(val.transform, false); RectTransform val3 = (RectTransform)val2.transform; Vector2 val4 = default(Vector2); ((Vector2)(ref val4))..ctor(1f, 0f); val3.anchorMax = val4; val3.anchorMin = val4; val3.pivot = new Vector2(1f, 0f); val3.anchoredPosition = new Vector2(-28f, 28f); counterImage = val2.GetComponent<Image>(); ((Graphic)counterImage).raycastTarget = false; } Sprite counter = Assets.GetCounter(remaining); ((Behaviour)counterImage).enabled = (Object)(object)counter != (Object)null; if (!((Object)(object)counter == (Object)null)) { counterImage.sprite = counter; RectTransform val5 = (RectTransform)((Component)counterImage).transform; Rect rect = counter.rect; float width = ((Rect)(ref rect)).width; rect = counter.rect; val5.sizeDelta = new Vector2(width, ((Rect)(ref rect)).height) * Plugin.CounterScale.Value; } } private static bool KeyDown(KeyCode key) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Invalid comparison between Unknown and I4 //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Invalid comparison between Unknown and I4 //IL_003b: Unknown result type (might be due to invalid IL or missing references) try { Keyboard current = Keyboard.current; if (current != null) { if ((int)key == 287) { return ((ButtonControl)current.f6Key).wasPressedThisFrame; } if ((int)key == 288) { return ((ButtonControl)current.f7Key).wasPressedThisFrame; } } } catch (Exception) { } try { return Input.GetKeyDown(key); } catch (Exception) { return false; } } } [HarmonyPatch(typeof(CL_AssetManager), "InitializeDatabases")] internal static class Patch_InitializeDatabases { private static void Postfix() { BindingFactory.EnsureRegistered(); } } [HarmonyPatch(typeof(UI_TrinketPicker), "ReloadTrinkets")] internal static class Patch_ReloadTrinkets { private static void Prefix(UI_TrinketPicker __instance) { BindingFactory.EnsureRegistered(); BindingFactory.AddToGamemode(Traverse.Create((object)__instance).Field("currentGamemode").GetValue<M_Gamemode>()); } private static void Postfix(UI_TrinketPicker __instance) { PickerLayout.FitBindings(__instance); } } [HarmonyPatch(typeof(UI_TrinketPicker), "ShowTrinketDescription")] internal static class Patch_ShowTrinketDescription { private static void Prefix(UI_TrinketPicker __instance, Trinket t) { PickerLayout.OnShowDescription(__instance, t); } } [HarmonyPatch(typeof(UI_TrinketPicker), "SelectTrinket")] internal static class Patch_SelectTrinket { private static void Prefix(UI_TrinketPicker __instance, Trinket t) { if (!((Object)(object)t == (Object)null) && __instance.selectedTrinkets != null) { string other = ((((Object)t).name == "Trinket_Binding_EscapedSubject") ? "Trinket_BioExperimented" : ((((Object)t).name == "Trinket_BioExperimented") ? "Trinket_Binding_EscapedSubject" : null)); if (other != null && !__instance.selectedTrinkets.Contains(t) && __instance.selectedTrinkets.RemoveAll((Trinket x) => (Object)(object)x != (Object)null && ((Object)x).name == other) > 0) { Plugin.Log.LogInfo((object)("함께 쓸 수 없어 선택 해제: " + other)); } } } } [HarmonyPatch(typeof(M_Gamemode), "StartFreshGamemode")] internal static class Patch_StartFreshGamemode { private static void Prefix(M_Gamemode __instance) { BindingFactory.EnsureRegistered(); MutationController.ResetRun(); try { string gamemodeName = __instance.GetGamemodeName(true); List<string> gamemodeTrinkets = StatManager.saveData.GetGamemodeTrinkets(gamemodeName); if (gamemodeTrinkets != null && gamemodeTrinkets.Exists((string n) => n?.Contains("Trinket_Binding_EscapedSubject") ?? false) && gamemodeTrinkets.RemoveAll((string n) => n?.Contains("Trinket_BioExperimented") ?? false) > 0) { StatManager.saveData.SetGamemodeTrinkets(gamemodeName, gamemodeTrinkets); Plugin.Log.LogInfo((object)"속박과 함께 쓸 수 없어 '생체 실험된'을 이번 판에서 제외"); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("선택 목록 확인 실패: " + ex.Message)); } } } [HarmonyPatch(typeof(ENT_Player), "GrabAnywhere")] internal static class Patch_GrabAnywhere { private static bool Prefix(ENT_Player __instance, Hand curhand, ref InteractHit interactHit, ref bool __result) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) TentacleGrapple active = TentacleGrapple.Active; if (active == null || !active.WallGrabOn || ((GameEntity)__instance).curBuffs.GetBuff("grabAnything") > 0f) { return true; } if (Array.IndexOf(__instance.hands, curhand) == active.WallGrabHand && Vector3.Distance(interactHit.point, active.AnchorPoint) <= Plugin.AnchorGrabRadius.Value) { return true; } ((Component)__instance.grabAnywhereFakeHandholds[curhand.id]).gameObject.SetActive(false); __result = false; return false; } } [HarmonyPatch(typeof(HandItem_Buff), "StartBuff")] internal static class Patch_StartBuff { private static void Prefix(HandItem_Buff __instance) { MutationController.OnConsume(__instance); } } internal static class PickerLayout { private class Saved { public Vector3 scale; public Vector3 position; public Constraint constraint; public int constraintCount; public Vector2 cellSize; public Vector2 spacing; } internal class Fitter : MonoBehaviour { public int dirtyFrame = -1; private void LateUpdate() { if (dirtyFrame < 0 || Time.frameCount <= dirtyFrame) { return; } dirtyFrame = -1; try { Transform transform = ((Component)this).transform; Fit((RectTransform)(object)((transform is RectTransform) ? transform : null)); } catch (Exception ex) { Plugin.Log.LogWarning((object)("속박 칸 배치 조정 실패: " + ex.Message)); } } } private static readonly Dictionary<int, Saved> saved = new Dictionary<int, Saved>(); private static TMP_Text descText; private static bool descSaved; private static bool descAuto; private static float descMin; private static float descMax; public static void FitBindings(UI_TrinketPicker picker) { if (!((Object)(object)picker == (Object)null) && !((Object)(object)picker.bindingIconRoot == (Object)null)) { (((Component)picker.bindingIconRoot).GetComponent<Fitter>() ?? ((Component)picker.bindingIconRoot).gameObject.AddComponent<Fitter>()).dirtyFrame = Time.frameCount; } } private static void Fit(RectTransform root) { //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Expected O, but got Unknown //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Expected O, but got Unknown //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)root == (Object)null) { return; } GridLayoutGroup component = ((Component)root).GetComponent<GridLayoutGroup>(); if (saved.TryGetValue(((Object)root).GetInstanceID(), out var value)) { ((Transform)root).localScale = value.scale; ((Transform)root).position = value.position; if ((Object)(object)component != (Object)null) { component.constraint = value.constraint; component.constraintCount = value.constraintCount; component.cellSize = value.cellSize; component.spacing = value.spacing; } } else { value = new Saved { scale = ((Transform)root).localScale, position = ((Transform)root).position }; if ((Object)(object)component != (Object)null) { value.constraint = component.constraint; value.constraintCount = component.constraintCount; value.cellSize = component.cellSize; value.spacing = component.spacing; } saved[((Object)root).GetInstanceID()] = value; } List<RectTransform> list = new List<RectTransform>(); foreach (Transform item in (Transform)root) { Transform val = item; if (((Component)val).gameObject.activeSelf && val is RectTransform) { list.Add((RectTransform)val); } } if (list.Count <= 9) { return; } if ((Object)(object)component == (Object)null) { Plugin.Log.LogWarning((object)"속박 칸에 GridLayoutGroup이 없어 배치를 맞추지 못함"); return; } LayoutRebuilder.ForceRebuildLayoutImmediate(root); Rect val2 = WorldBounds(list, 9); int num = CountColumns(list); int num2 = Mathf.CeilToInt(9f / (float)num); int constraintCount = num; float num3 = 0f; for (int i = num; i <= num + 3; i++) { int num4 = Mathf.CeilToInt((float)list.Count / (float)i); float num5 = Mathf.Min((float)num / (float)i, (float)num2 / (float)num4); if (num5 > num3 + 0.001f) { num3 = num5; constraintCount = i; } } component.constraint = (Constraint)1; component.constraintCount = constraintCount; ((Transform)root).localScale = value.scale * num3; LayoutRebuilder.ForceRebuildLayoutImmediate(root); Rect val3 = WorldBounds(list, list.Count); ((Transform)root).position = ((Transform)root).position + new Vector3(((Rect)(ref val2)).center.x - ((Rect)(ref val3)).center.x, ((Rect)(ref val2)).yMax - ((Rect)(ref val3)).yMax, 0f); Plugin.Log.LogInfo((object)("속박 칸 배치 조정: " + list.Count + "개, " + num + "열 → " + constraintCount + "열, 크기 ×" + num3.ToString("0.00"))); } private static int CountColumns(List<RectTransform> icons) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) float y = ((Transform)icons[0]).position.y; int num = 0; foreach (RectTransform icon in icons) { float num2 = Mathf.Abs(((Transform)icon).position.y - y); Rect rect = icons[0].rect; if (num2 < 0.01f * Mathf.Max(1f, ((Rect)(ref rect)).height * ((Transform)icons[0]).lossyScale.y)) { num++; } } return Mathf.Max(1, num); } private static Rect WorldBounds(List<RectTransform> icons, int count) { //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: 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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) Vector3[] array = (Vector3[])(object)new Vector3[4]; float num = float.MaxValue; float num2 = float.MaxValue; float num3 = float.MinValue; float num4 = float.MinValue; for (int i = 0; i < count && i < icons.Count; i++) { icons[i].GetWorldCorners(array); Vector3[] array2 = array; foreach (Vector3 val in array2) { num = Mathf.Min(num, val.x); num2 = Mathf.Min(num2, val.y); num3 = Mathf.Max(num3, val.x); num4 = Mathf.Max(num4, val.y); } } return Rect.MinMaxRect(num, num2, num3, num4); } public static void OnShowDescription(UI_TrinketPicker picker, Trinket t) { TMP_Text val = (((Object)(object)picker != (Object)null) ? picker.descriptionText : null); if ((Object)(object)val == (Object)null) { return; } if ((Object)(object)descText != (Object)(object)val) { descText = val; descSaved = false; } if (!descSaved) { descSaved = true; descAuto = val.enableAutoSizing; descMin = val.fontSizeMin; descMax = val.fontSizeMax; if (!descAuto) { descMax = val.fontSize; } } if ((Object)(object)t != (Object)null && (((Object)t).name == "Trinket_Binding_EscapedSubject" || ((Object)t).name == "Trinket_BioExperimented")) { val.fontSizeMax = descMax; val.fontSizeMin = descMax * 0.7f; val.enableAutoSizing = true; } else if (val.enableAutoSizing != descAuto || val.fontSizeMin != descMin) { val.enableAutoSizing = descAuto; val.fontSizeMin = descMin; val.fontSizeMax = descMax; if (!descAuto) { val.fontSize = descMax; } } } } [BepInPlugin("LUNAEGO.EscapedTestSubject", "WK Escaped Test Subject", "0.9.3")] public class Plugin : BaseUnityPlugin { public const string Guid = "LUNAEGO.EscapedTestSubject"; internal static ManualLogSource Log; internal static string AssetDir; internal static ConfigEntry<string> Language; internal static ConfigEntry<int> Cost; internal static ConfigEntry<float> ScoreBonus; internal static ConfigEntry<float> Gravity; internal static ConfigEntry<float> Stamina; internal static ConfigEntry<float> Capacity; internal static ConfigEntry<float> Health; internal static ConfigEntry<float> MoveSpeed; internal static ConfigEntry<float> StickyGroundSeconds; internal static ConfigEntry<float> StickyDuration; internal static ConfigEntry<float> StickyNoDrain; internal static ConfigEntry<float> MutateSeconds; internal static ConfigEntry<float> TentacleStamina; internal static ConfigEntry<float> TentacleRange; internal static ConfigEntry<float> PullForce; internal static ConfigEntry<float> WallGrabDistance; internal static ConfigEntry<float> AnchorGrabRadius; internal static ConfigEntry<int> Charges; internal static ConfigEntry<string> ChargeKeywords; internal static ConfigEntry<float> ShootHold; internal static ConfigEntry<float> CounterScale; internal static ConfigEntry<bool> DebugKeys; internal static bool Korean { get { if (Language != null) { return Language.Value == "Korean"; } return false; } } internal static string L(string en, string ko) { if (!Korean) { return en; } return ko; } private void Awake() { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown //IL_0369: Unknown result type (might be due to invalid IL or missing references) //IL_0387: Unknown result type (might be due to invalid IL or missing references) //IL_038c: Unknown result type (might be due to invalid IL or missing references) //IL_0392: Expected O, but got Unknown //IL_0392: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; AssetDir = Path.Combine(Path.GetDirectoryName(typeof(Plugin).Assembly.Location), "Assets"); Language = ((BaseUnityPlugin)this).Config.Bind<string>("General", "Language", "English", new ConfigDescription("Text language for the binding name and description / 속박 이름·설명 언어", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[2] { "English", "Korean" }), Array.Empty<object>())); Cost = ((BaseUnityPlugin)this).Config.Bind<int>("Binding", "Cost", 1, "Binding cost (a binding adds this much to the trinket budget)"); ScoreBonus = ((BaseUnityPlugin)this).Config.Bind<float>("Binding", "ScoreMultiplierBonus", 0.35f, "Final score multiplier bonus (0.35 = +35%). Runs with this binding are never submitted to leaderboards"); Gravity = ((BaseUnityPlugin)this).Config.Bind<float>("Binding", "Gravity", 0.2f, "Gravity change (0.2 = +20%)"); Stamina = ((BaseUnityPlugin)this).Config.Bind<float>("Binding", "Stamina", -0.2f, "Stamina change (-0.2 = -20%)"); Capacity = ((BaseUnityPlugin)this).Config.Bind<float>("Binding", "InventoryCapacity", -2f, "Inventory capacity change (-2 = 5 slots down to 3)"); Health = ((BaseUnityPlugin)this).Config.Bind<float>("Binding", "MaxHealth", -0.2f, "Max health change (-0.2 = -20%)"); MoveSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Binding", "MoveSpeed", -0.2f, "Move speed change (-0.2 = -20%)"); StickyGroundSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Sticky", "GroundSeconds", 5f, "Seconds on the ground before Sticky Surface triggers"); StickyDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Sticky", "Duration", 7f, "Grub effect duration (seconds), counted from the first wall grab after it triggers"); StickyNoDrain = ((BaseUnityPlugin)this).Config.Bind<float>("Sticky", "NoStaminaDrainSeconds", 5f, "Stamina does not drain for this long after the first wall grab"); MutateSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Mutation", "HoldSeconds", 5f, "Seconds you must reach out with a bare hand to mutate"); Charges = ((BaseUnityPlugin)this).Config.Bind<int>("Mutation", "Charges", 5, "Tentacle shots per mutation"); ChargeKeywords = ((BaseUnityPlugin)this).Config.Bind<string>("Mutation", "ChargeItemKeywords", "Pill,Injector,Inoculator,Syringe,Adrenaline,Grub,Roach_Lemon", "Items whose name contains one of these words charge the mutation (comma separated, case-insensitive)"); TentacleStamina = ((BaseUnityPlugin)this).Config.Bind<float>("Mutation", "TentacleStaminaBonus", 0.35f, "Temporary stamina bonus while in tentacle form (0.35 = +35%). Removed when all shots are used"); TentacleRange = ((BaseUnityPlugin)this).Config.Bind<float>("Mutation", "TentacleRange", 30f, "Tentacle range (m). The Barnacle Hook has 20m"); PullForce = ((BaseUnityPlugin)this).Config.Bind<float>("Mutation", "PullForceMultiplier", 1.1f, "Tentacle pull force multiplier relative to the Barnacle Hook (1.10 = +10%)"); WallGrabDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Mutation", "WallGrabDistance", 2.8f, "Within this distance (m) of the tentacle anchor, the shooting hand can grab bare walls while the button is held"); AnchorGrabRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Mutation", "AnchorGrabRadius", 1.4f, "Bare walls can only be grabbed within this radius (m) of the anchor (walls along the pull path can't be grabbed)"); ShootHold = ((BaseUnityPlugin)this).Config.Bind<float>("Mutation", "ShootHoldSeconds", 0.75f, "In tentacle form, hold the bare-hand button this long to shoot (grabbing something cancels it)"); CounterScale = ((BaseUnityPlugin)this).Config.Bind<float>("Visual", "CounterScale", 3f, "Scale of the remaining-shots counter at the bottom right"); DebugKeys = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "EnableDebugKeys", false, "If true: F6 = charge mutation, F7 = instant tentacle form (for testing)"); new Harmony("LUNAEGO.EscapedTestSubject").PatchAll(typeof(Plugin).Assembly); GameObject val = new GameObject("WKEscapedSubject_Controller"); Object.DontDestroyOnLoad((Object)val); ((Object)val).hideFlags = (HideFlags)61; val.AddComponent<MutationController>(); Log.LogInfo((object)("Escaped Test Subject binding loaded (language: " + Language.Value + ")")); } } internal static class Sounds { public class Player { private readonly string file; private AudioClip clip; private bool loaded; private AudioSource src; public bool IsPlaying { get { if ((Object)(object)src != (Object)null) { return src.isPlaying; } return false; } } public Player(string file) { this.file = file; } public void Play(GameObject host, float volume = 1f) { if (!loaded) { clip = LoadWav(file); loaded = true; } if (!((Object)(object)clip == (Object)null)) { if ((Object)(object)src == (Object)null) { src = host.AddComponent<AudioSource>(); src.playOnAwake = false; src.spatialBlend = 0f; } if ((Object)(object)Mixer != (Object)null) { src.outputAudioMixerGroup = Mixer; } src.clip = clip; src.volume = volume; src.Play(); } } public void Stop() { if ((Object)(object)src != (Object)null && src.isPlaying) { src.Stop(); } } } public static AudioMixerGroup Mixer; public static AudioClip LoadWav(string file) { byte[] array = AssetStore.Read("Sounds/" + file); if (array == null) { Plugin.Log.LogWarning((object)("Sound not found: " + file)); return null; } try { int num = 0; int num2 = 0; int num3 = 0; int num4 = -1; int num5 = 0; int num6; for (int i = 12; i + 8 <= array.Length; i += 8 + num6 + (num6 & 1)) { string text = Encoding.ASCII.GetString(array, i, 4); num6 = BitConverter.ToInt32(array, i + 4); if (text == "fmt ") { num = BitConverter.ToInt16(array, i + 10); num2 = BitConverter.ToInt32(array, i + 12); num3 = BitConverter.ToInt16(array, i + 22); } else if (text == "data") { num4 = i + 8; num5 = Math.Min(num6, array.Length - num4); break; } } if (num4 < 0 || num3 != 16 || num < 1) { Plugin.Log.LogWarning((object)("지원하지 않는 WAV 형식(16bit PCM만): " + file)); return null; } int num7 = num5 / 2; float[] array2 = new float[num7]; for (int j = 0; j < num7; j++) { array2[j] = (float)BitConverter.ToInt16(array, num4 + j * 2) / 32768f; } AudioClip val = AudioClip.Create(Path.GetFileNameWithoutExtension(file), num7 / num, num, num2, false); typeof(AudioClip).GetMethod("SetData", new Type[2] { typeof(float[]), typeof(int) }).Invoke(val, new object[2] { array2, 0 }); ((Object)val).hideFlags = (HideFlags)32; Plugin.Log.LogInfo((object)$"소리 로드: {file} ({val.length:0.00}초)"); return val; } catch (Exception ex) { Plugin.Log.LogWarning((object)("소리 로드 실패 " + file + ": " + ex.Message)); return null; } } } internal static class TentacleFX { private static ParticleSystem ps; private static readonly Color Ink = new Color(0.04f, 0.03f, 0.055f, 1f); private static readonly Color Shade = new Color(0.13f, 0.086f, 0.157f, 1f); private static readonly Color Sheen = new Color(0.275f, 0.157f, 0.353f, 1f); private static ParticleSystem Get() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: 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_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: 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) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ps != (Object)null) { return ps; } GameObject val = new GameObject("WKEscaped_TentacleFX"); Object.DontDestroyOnLoad((Object)val); ps = val.AddComponent<ParticleSystem>(); ps.Stop(true, (ParticleSystemStopBehavior)0); MainModule main = ps.main; ((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)1; ((MainModule)(ref main)).playOnAwake = false; ((MainModule)(ref main)).loop = false; ((MainModule)(ref main)).maxParticles = 600; ((MainModule)(ref main)).gravityModifier = MinMaxCurve.op_Implicit(1.2f); EmissionModule emission = ps.emission; ((EmissionModule)(ref emission)).enabled = false; ShapeModule shape = ps.shape; ((ShapeModule)(ref shape)).enabled = false; SizeOverLifetimeModule sizeOverLifetime = ps.sizeOverLifetime; ((SizeOverLifetimeModule)(ref sizeOverLifetime)).enabled = true; ((SizeOverLifetimeModule)(ref sizeOverLifetime)).size = new MinMaxCurve(1f, AnimationCurve.Linear(0f, 1f, 1f, 0.2f)); LimitVelocityOverLifetimeModule limitVelocityOverLifetime = ps.limitVelocityOverLifetime; ((LimitVelocityOverLifetimeModule)(ref limitVelocityOverLifetime)).enabled = true; ((LimitVelocityOverLifetimeModule)(ref limitVelocityOverLifetime)).dampen = 0.08f; ((LimitVelocityOverLifetimeModule)(ref limitVelocityOverLifetime)).limit = MinMaxCurve.op_Implicit(0f); ParticleSystemRenderer component = val.GetComponent<ParticleSystemRenderer>(); component.renderMode = (ParticleSystemRenderMode)0; ((Renderer)component).material = MakeMaterial(); ps.Play(); return ps; } private static Material MakeMaterial() { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Expected O, but got Unknown //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown //IL_00ac: Expected O, but got Unknown //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(8, 8, (TextureFormat)4, false); ((Texture)val).filterMode = (FilterMode)0; for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { float num = (float)j - 3.5f; float num2 = (float)i - 3.5f; val.SetPixel(j, i, (num * num + num2 * num2 <= 11f) ? Color.white : Color.clear); } } val.Apply(); Shader val2 = Shader.Find("Sprites/Default"); Material val3; if ((Object)(object)val2 != (Object)null) { val3 = new Material(val2); } else { GameObject val4 = new GameObject("tmp"); val3 = new Material(((Renderer)val4.AddComponent<SpriteRenderer>()).sharedMaterial); Object.Destroy((Object)val4); } val3.mainTexture = (Texture)(object)val; return val3; } private static Color RandomInk() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) float value = Random.value; if (!(value < 0.65f)) { if (!(value < 0.9f)) { return Sheen; } return Shade; } return Ink; } public static void Burst(Vector3 start, Vector3 dir) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_015c: 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_016c: Unknown result type (might be due to invalid IL or missing references) ParticleSystem val = Get(); EmitParams val2 = default(EmitParams); dir = ((Vector3)(ref dir)).normalized; for (int i = 0; i < 40; i++) { Vector3 val3 = dir + Random.insideUnitSphere * 0.9f; Vector3 velocity = ((Vector3)(ref val3)).normalized * Random.Range(0.8f, 3.2f); ((EmitParams)(ref val2)).position = start + Random.insideUnitSphere * 0.05f; ((EmitParams)(ref val2)).velocity = velocity; ((EmitParams)(ref val2)).startSize = Random.Range(0.03f, 0.075f); ((EmitParams)(ref val2)).startLifetime = Random.Range(0.3f, 0.6f); ((EmitParams)(ref val2)).startColor = Color32.op_Implicit(RandomInk()); val.Emit(val2, 1); } for (int j = 0; j < 18; j++) { float num = Random.Range(0.1f, 3f); ((EmitParams)(ref val2)).position = start + dir * num + Random.insideUnitSphere * 0.04f; ((EmitParams)(ref val2)).velocity = Random.insideUnitSphere * 0.4f + dir * 0.5f; ((EmitParams)(ref val2)).startSize = Random.Range(0.02f, 0.05f); ((EmitParams)(ref val2)).startLifetime = Random.Range(0.35f, 0.7f); ((EmitParams)(ref val2)).startColor = Color32.op_Implicit(RandomInk()); val.Emit(val2, 1); } } public static void Splat(Vector3 pos, Vector3 normal, float scale = 1f) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //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_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006a: 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_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) ParticleSystem val = Get(); EmitParams val2 = default(EmitParams); int num = Mathf.RoundToInt(30f * scale); for (int i = 0; i < num; i++) { Vector3 val3 = ((Vector3)(ref normal)).normalized + Random.insideUnitSphere * 0.9f; Vector3 velocity = ((Vector3)(ref val3)).normalized * Random.Range(1.2f, 4.5f) * Mathf.Sqrt(scale); ((EmitParams)(ref val2)).position = pos + normal * 0.03f; ((EmitParams)(ref val2)).velocity = velocity; ((EmitParams)(ref val2)).startSize = Random.Range(0.03f, 0.11f) * Mathf.Sqrt(scale); ((EmitParams)(ref val2)).startLifetime = Random.Range(0.45f, 0.9f); ((EmitParams)(ref val2)).startColor = Color32.op_Implicit(RandomInk()); val.Emit(val2, 1); } } } internal class TentacleGrapple { private float distance = 20f; private float force = 1f; private float deadzone = 3f; private float forceTime = 5f; private float whipForce = 5f; private float whipUp = 2f; private float whipTorque = 20f; private Vector3 forceMult = Vector3.one; private AnimationCurve forceCurve = AnimationCurve.Linear(1f, 1f, 1f, 1f); private LayerMask mask = LayerMask.op_Implicit(-1); private string[] foodTags = new string[0]; private string[] lesserFoodTags = new string[0]; private string[] blacklistTags = new string[0]; private GameObject kit; private UT_AudioClipHandler audio; private Transform tentacle; private MeshRenderer tentacleRenderer; priva