Due to update 2.4.3, some mods may no longer function. FixedConfig may be necessary.
Decompiled source of InvisibilityDecoy v1.0.0
InvisibilityDecoy.dll
Decompiled 20 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Logging; using BoplFixedMath; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyVersion("0.0.0.0")] namespace InvisibilityDecoy; public sealed class DecoyActor : MonoBehaviour { internal Player State; internal int OwnerId; internal SlimeController Controller; internal PlayerBody Body; internal PlayerPhysics Physics; internal PlayerCollision Collision; internal IPhysicsCollider Hurtbox; internal bool Removed; private DecoySnapshot appearance; private Material bodyMaterial; private readonly List<DecoyCooldown> cooldowns = new List<DecoyCooldown>(); private static readonly string[] palette = new string[3] { "_MainColor", "_ShadowColor", "_ReflectionColour" }; private readonly Dictionary<string, Color> normalColors = new Dictionary<string, Color>(); private bool frozenPalette; private readonly List<AbilityReadyIndicator> indicators = new List<AbilityReadyIndicator>(); private readonly List<Material> iconMaterials = new List<Material>(); internal void SetAppearanceMaterial(Material source) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0058: Unknown result type (might be due to invalid IL or missing references) bodyMaterial = new Material(source); ((Renderer)Controller.GetPlayerSprite()).sharedMaterial = bodyMaterial; State.Color = bodyMaterial; string[] array = palette; foreach (string text in array) { if (bodyMaterial.HasProperty(text)) { normalColors[text] = source.GetColor(text); } } UpdateTimeStopAppearance(); } private void LateUpdate() { UpdateTimeStopAppearance(); } private void UpdateTimeStopAppearance() { //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_0077: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) if (Removed || (Object)(object)bodyMaterial == (Object)null) { return; } bool flag = GameTime.IsTimeStopped(); if (flag == frozenPalette) { return; } foreach (KeyValuePair<string, Color> normalColor in normalColors) { Color value = normalColor.Value; if (flag) { ((Color)(ref value))..ctor(((Color)(ref value)).grayscale, ((Color)(ref value)).grayscale, ((Color)(ref value)).grayscale, value.a); } bodyMaterial.SetColor(normalColor.Key, value); } frozenPalette = flag; } private void ChargeIndicators(Fix deltaTime) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_002f: 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_0041: 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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0059: 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_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: 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_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0072: 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) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: 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_0094: 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_009b: 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_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_010f: 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_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0133: 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_013e: Unknown result type (might be due to invalid IL or missing references) if (GameSessionHandler.GameIsPaused) { return; } Fix val = GameTime.FixedDeltaTime(State.Id, deltaTime); for (int i = 0; i < cooldowns.Count; i++) { DecoyCooldown value = cooldowns[i]; bool flag = value.Delay <= Fix.Zero && value.Elapsed >= value.Duration; Fix val2 = val; if (value.Delay > Fix.Zero) { Fix val3 = Fix.Min(value.Delay, val2); ref Fix delay = ref value.Delay; delay -= val3; val2 -= val3; } value.Elapsed = Fix.Min(value.Duration, value.Elapsed + val2); cooldowns[i] = value; AbilityReadyIndicator val4 = indicators[i]; if (!((Object)(object)val4 == (Object)null)) { bool flag2 = value.Delay <= Fix.Zero && value.Elapsed >= value.Duration; val4.SetCooldownProgress((value.Delay > Fix.Zero) ? 0f : ((value.Duration <= Fix.Zero) ? 1f : ((float)(value.Elapsed / value.Duration)))); if (!flag && flag2) { val4.ResetAnimation(); } } } } internal void Configure(Player state, DecoySnapshot snapshot, SlimeController controller) { State = state; OwnerId = snapshot.OwnerId; appearance = snapshot; Controller = controller; Body = ((Component)this).GetComponent<PlayerBody>(); Physics = ((Component)this).GetComponent<PlayerPhysics>(); Collision = ((Component)this).GetComponent<PlayerCollision>(); Hurtbox = ((Component)this).GetComponent<IPhysicsCollider>(); if ((Object)(object)controller == (Object)null || (Object)(object)Body == (Object)null || (Object)(object)Physics == (Object)null || (Object)(object)Collision == (Object)null || Hurtbox == null) { throw new InvalidOperationException("The native empty-player prefab is missing a required component."); } RefreshTimeProtection(); } internal DecoySnapshot SnapshotForCopy() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: 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_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) PlayerInfo pose = appearance.Pose; pose.position = Body.position; pose.rotation = Body.rotation; pose.isGrounded = false; pose.currentlyAttachedGround = null; return new DecoySnapshot { OwnerId = OwnerId, Team = State.Team, Scale = Hurtbox.Scale, Pose = pose, Prefab = appearance.Prefab, Animation = appearance.Animation, Material = appearance.Material, Tint = Controller.GetPlayerSprite().color, SortingLayer = ((Renderer)Controller.GetPlayerSprite()).sortingLayerID, SortingOrder = ((Renderer)Controller.GetPlayerSprite()).sortingOrder, Indicators = indicators.ToArray(), Cooldowns = cooldowns.ToArray() }; } internal void RefreshTimeProtection() { State.isProtectedFromTimeStop = false; } internal void Simulate(Fix deltaTime) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: 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_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) if (Removed) { return; } RefreshTimeProtection(); State.GetRawInputProfile().Reset(); State.isInvisible = false; State.Position = Body.position; Hurtbox.Scale = State.Scale; ChargeIndicators(deltaTime); if (GameTime.IsTimeStoppedFor(State.Id) || GameSessionHandler.GameIsPaused || !Physics.IsGrounded()) { return; } StickyRoundedRectangle attachedGround = Physics.getAttachedGround(); if ((Object)(object)attachedGround == (Object)null || ((MonoUpdatable)attachedGround).IsDestroyed || !((Component)attachedGround).gameObject.activeInHierarchy) { Physics.UnGround(true, false); return; } Vec2 val = attachedGround.currentNormal(Body); if (Vec2.Dot(Body.externalVelocity, val) > (Fix)2L) { Physics.UnGround(true, false); return; } Physics.groundedSpeed = Fix.Zero; Physics.Move(Vec2.zero, deltaTime, true); } internal bool Remove(bool effect, bool ignoreInvulnerability) { //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) if (Removed || ((Object)(object)Collision != (Object)null && Collision.IsInvulnerable && !ignoreInvulnerability)) { return false; } Removed = true; State.playersAndClonesStillAlive = 0; if ((Object)(object)Body != (Object)null && Body.ropeBody != null) { Body.AttachRope((RopeBody)null, Body.topAttachment); } if (Hurtbox != null) { Hurtbox.enabled = false; } if (effect && (Object)(object)Collision != (Object)null && (Object)(object)Collision.deathEffect != (Object)null) { GameObject obj = FixTransform.InstantiateFixed(Collision.deathEffect, Body.position); Transform transform = obj.transform; transform.localScale *= (float)Body.fixtrans.Scale; SpriteRenderer component = obj.GetComponent<SpriteRenderer>(); if ((Object)(object)component != (Object)null) { ((Renderer)component).sharedMaterial = appearance.Material; } } DestroyIndicators(); DecoyRegistry.Forget(this); Updater.DestroyFix(((Component)this).gameObject); return true; } internal void CopyIndicators(AbilityReadyIndicator[] source) { //IL_01a4: 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_008a: Expected O, but got Unknown //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_010d: 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_012c: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) if (source == null) { return; } for (int i = 0; i < source.Length; i++) { AbilityReadyIndicator val = source[i]; if (!((Object)(object)val == (Object)null)) { AbilityReadyIndicator val2 = Object.Instantiate<AbilityReadyIndicator>(val); indicators.Add(val2); cooldowns.Add((appearance.Cooldowns != null && i < appearance.Cooldowns.Length) ? appearance.Cooldowns[i] : default(DecoyCooldown)); SpriteRenderer component = ((Component)val2).GetComponent<SpriteRenderer>(); Material val3 = new Material(((Renderer)val.GetSpriteRen()).material); iconMaterials.Add(val3); ((Renderer)component).material = val3; Color color = component.color; color.a = 1f; component.color = color; FollowTransform component2 = ((Component)val2).GetComponent<FollowTransform>(); if ((Object)(object)component2 != (Object)null) { Transform val4 = ((Component)val).GetComponent<FollowTransform>()?.Leader; ((Component)val2).transform.position = (((Object)(object)val4 == (Object)null) ? (((Component)val).transform.position - ((Component)appearance.Pose.slimeController).transform.position) : (((Component)val).transform.position - val4.position)); component2.Leader = ((Component)this).transform; } val2.Init(); Sprite primarySprite = val.GetPrimarySprite(); if ((Object)(object)primarySprite != (Object)null) { val2.SetSprite(primarySprite, true); } ((Component)val2).gameObject.SetActive(((Component)val).gameObject.activeSelf); val2.InstantlySyncTransform(); } } Controller.AbilityReadyIndicators = indicators.ToArray(); ChargeIndicators(Fix.Zero); } private void DestroyIndicators() { foreach (AbilityReadyIndicator indicator in indicators) { if ((Object)(object)indicator != (Object)null) { Object.Destroy((Object)(object)((Component)indicator).gameObject); } } indicators.Clear(); cooldowns.Clear(); foreach (Material iconMaterial in iconMaterials) { if ((Object)(object)iconMaterial != (Object)null) { Object.Destroy((Object)(object)iconMaterial); } } iconMaterials.Clear(); } private void OnDestroy() { Removed = true; DestroyIndicators(); if ((Object)(object)bodyMaterial != (Object)null) { Object.Destroy((Object)(object)bodyMaterial); } if (State != null) { DecoyRegistry.Forget(this); } } } internal struct DecoyCooldown { internal Fix Elapsed; internal Fix Duration; internal Fix Delay; } internal sealed class DecoySnapshot { internal int OwnerId; internal int Team; internal Fix Scale; internal PlayerInfo Pose; internal SlimeController Prefab; internal AnimationData Animation; internal Material Material; internal Color Tint; internal int SortingLayer; internal int SortingOrder; internal AbilityReadyIndicator[] Indicators; internal DecoyCooldown[] Cooldowns; } internal static class DecoyFactory { internal static DecoySnapshot Capture(InstantAbility ability) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0112: 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_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_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_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_017f: 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) if ((Object)(object)ability == (Object)null) { return null; } PlayerInfo playerInfo = ability.playerInfo; SlimeController slimeController = playerInfo.slimeController; if ((Object)(object)slimeController == (Object)null || ((MonoUpdatable)slimeController).IsDestroyed || (Object)(object)((Component)slimeController).GetComponent<DecoyActor>() != (Object)null) { return null; } Player player = PlayerHandler.Get().GetPlayer(playerInfo.playerId); PlayerCollision playerCollision = slimeController.GetPlayerCollision(); SpriteRenderer playerSprite = slimeController.GetPlayerSprite(); if (player == null || !player.IsAlive || (Object)(object)playerCollision == (Object)null || (Object)(object)playerSprite == (Object)null || (Object)(object)playerCollision.reviveEffectPrefab == (Object)null || (Object)(object)playerCollision.reviveEffectPrefab.emptyPlayerPrefab == (Object)null) { return null; } Fix[] value = Traverse.Create((object)slimeController).Field("abilityCooldownTimers").GetValue<Fix[]>(); DecoyCooldown[] array = new DecoyCooldown[slimeController.AbilityReadyIndicators.Length]; for (int i = 0; i < array.Length; i++) { if (i < slimeController.abilities.Count && !((Object)(object)slimeController.abilities[i] == (Object)null)) { AbilityMonoBehaviour val = slimeController.abilities[i]; array[i].Duration = val.GetCooldown(); array[i].Elapsed = ((value != null && i < value.Length) ? value[i] : Fix.Zero); if ((Object)(object)((Component)val).GetComponent<Invisibility>() != (Object)null) { array[i].Duration = Fix.One; array[i].Elapsed = Fix.One; array[i].Delay = Fix.Zero; } } } return new DecoySnapshot { OwnerId = player.Id, Team = player.Team, Scale = slimeController.body.fixtrans.Scale, Pose = playerInfo, Prefab = playerCollision.reviveEffectPrefab.emptyPlayerPrefab, Animation = slimeController.animData, Material = ((Renderer)playerSprite).sharedMaterial, Tint = playerSprite.color, SortingLayer = ((Renderer)playerSprite).sortingLayerID, SortingOrder = ((Renderer)playerSprite).sortingOrder, Indicators = slimeController.AbilityReadyIndicators, Cooldowns = array }; } internal static DecoyActor Spawn(DecoySnapshot snapshot, Vec2 position, bool activation) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_005e: 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_012a: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_018d: 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_0195: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: 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_01ad: 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_01c2: 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_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_0250: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) if (snapshot == null || !DecoyRegistry.MakeRoom(snapshot.OwnerId, activation)) { return null; } Player val = null; GameObject val2 = null; try { SpriteFrame[] animation = snapshot.Animation.GetAnimation("idle"); if (animation == null || animation.Length == 0) { throw new InvalidOperationException("The source slime has no idle animation."); } val = DecoyRegistry.Allocate(snapshot.Team, snapshot.Scale, snapshot.Material, position); val2 = FixTransform.InstantiateFixed(((Component)snapshot.Prefab).gameObject, position, snapshot.Pose.rotation); DecoyActor decoyActor = val2.AddComponent<DecoyActor>(); SlimeController component = val2.GetComponent<SlimeController>(); decoyActor.Configure(val, snapshot, component); DecoyRegistry.Attach(decoyActor); ((Object)val2).name = "InvisibilityDecoy"; component.playerNumber = val.Id; component.suppressInput = true; component.isAbilitylessClone = true; component.abilities = new List<AbilityMonoBehaviour>(); component.AbilityReadyIndicators = Array.Empty<AbilityReadyIndicator>(); component.animData = snapshot.Animation; Traverse.Create((object)component).Field("currentState").SetValue((object)(State)0); Traverse.Create((object)component).Field("hasSpawned").SetValue((object)true); decoyActor.Collision.SetInvulnerable(false, uint.MaxValue); decoyActor.Hurtbox.Scale = val.Scale; decoyActor.Hurtbox.enabled = true; ((Behaviour)decoyActor.Physics).enabled = true; Traverse.Create((object)decoyActor.Physics).Field("ApplyGravity").SetValue((object)true); PlayerInfo pose = snapshot.Pose; pose.playerId = val.Id; pose.slimeController = component; pose.position = position; pose.externalVelocity = Vec2.zero; pose.selfImposedVelocity = Vec2.zero; pose.groundedSpeed = Fix.Zero; pose.ropeBody = null; if (!activation || (Object)(object)pose.currentlyAttachedGround == (Object)null || ((MonoUpdatable)pose.currentlyAttachedGround).IsDestroyed) { pose.isGrounded = false; pose.currentlyAttachedGround = null; } decoyActor.Physics.SyncPhysicsTo(pose); decoyActor.Body.simulated = true; decoyActor.Body.selfImposedVelocity = Vec2.zero; decoyActor.Body.externalVelocity = Vec2.zero; SpriteRenderer playerSprite = component.GetPlayerSprite(); decoyActor.SetAppearanceMaterial(snapshot.Material); Color tint = snapshot.Tint; tint.a = 1f; playerSprite.color = tint; ((Renderer)playerSprite).enabled = true; ((Renderer)playerSprite).sortingLayerID = snapshot.SortingLayer; ((Renderer)playerSprite).sortingOrder = snapshot.SortingOrder; FlippingTransform componentInChildren = ((Component)component).GetComponentInChildren<FlippingTransform>(true); if ((Object)(object)componentInChildren != (Object)null) { componentInChildren.alignTransform(snapshot.Pose.isFacingRight); } SpriteAnimator component2 = ((Component)playerSprite).GetComponent<SpriteAnimator>(); if ((Object)(object)component2 == (Object)null) { throw new InvalidOperationException("The native slime sprite has no SpriteAnimator."); } component2.AlwaysStopDuringTimeStop = true; component2.beginAnimation(animation); val2.SetActive(true); decoyActor.CopyIndicators(snapshot.Indicators); return decoyActor; } catch (Exception ex) { if (val != null) { val.playersAndClonesStillAlive = 0; } if ((Object)(object)val2 != (Object)null) { DecoyActor component3 = val2.GetComponent<DecoyActor>(); if ((Object)(object)component3 != (Object)null && component3.State != null) { component3.Remove(effect: false, ignoreInvulnerability: true); } else { Updater.DestroyFix(val2); } } Plugin.Log.LogError((object)("Invisibility Decoy: spawning failed; native invisibility remains active. " + ex)); return null; } } } internal static class DecoyRegistry { private sealed class Entry { internal Player State; internal DecoyActor Body; } private static readonly Dictionary<int, Entry> entries = new Dictionary<int, Entry>(); private static readonly List<DecoyActor> active = new List<DecoyActor>(); private static int nextId = -10000; internal static bool TryGetPlayer(int id, out Player player) { Entry value; bool flag = entries.TryGetValue(id, out value); player = (flag ? value.State : null); return flag; } internal static DecoyActor Find(int id) { if (!entries.TryGetValue(id, out var value)) { return null; } return value.Body; } internal static Player Allocate(int team, Fix scale, Material material, Vec2 position) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0040: 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_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: 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_005c: 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_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown while (PlayerHandler.Get().GetPlayer(nextId) != null) { nextId--; } Player val = new Player(nextId--, team) { Scale = scale, Color = material, Position = position, SpawnPosition = position, IsLocalPlayer = false, CanUseAbilities = false, ignoreAllInputs = true, isInvisible = false, ExtraLife = (ReviveStatus)0, playersAndClonesStillAlive = 1 }; entries.Add(val.Id, new Entry { State = val }); return val; } internal static void Attach(DecoyActor actor) { entries[actor.State.Id].Body = actor; active.Add(actor); } internal static void Forget(DecoyActor actor) { active.Remove(actor); if (actor.State != null && entries.TryGetValue(actor.State.Id, out var value) && value.State == actor.State) { value.State.playersAndClonesStillAlive = 0; value.Body = null; } } internal static bool MakeRoom(int ownerId, bool activation) { active.RemoveAll((DecoyActor actor) => (Object)(object)actor == (Object)null || actor.Removed); int num = 0; DecoyActor decoyActor = null; foreach (DecoyActor item in active) { if (item.OwnerId == ownerId) { num++; if ((Object)(object)decoyActor == (Object)null) { decoyActor = item; } } } if (num < 16) { return true; } if (!activation) { return false; } decoyActor?.Remove(effect: false, ignoreInvulnerability: true); return true; } internal static void Clear() { DecoyActor[] array = active.ToArray(); foreach (DecoyActor decoyActor in array) { if ((Object)(object)decoyActor != (Object)null) { decoyActor.Remove(effect: false, ignoreInvulnerability: true); } } active.Clear(); entries.Clear(); nextId = -10000; } } [HarmonyPatch(typeof(ShootDuplicator), "ApplyDuplicationEffect")] internal static class DuplicateDecoyPatch { private static bool Prefix(ShootDuplicator __instance, GameObject obj, Vec2 objPos, Vec2 dir, ref bool hasFired) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0059: 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_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0068: 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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0089: 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) DecoyActor decoyActor = (((Object)(object)obj == (Object)null) ? null : obj.GetComponent<DecoyActor>()); if ((Object)(object)decoyActor == (Object)null) { return true; } hasFired = true; if (decoyActor.Removed) { return false; } DecoyActor decoyActor2 = DecoyFactory.Spawn(decoyActor.SnapshotForCopy(), objPos, activation: false); if ((Object)(object)decoyActor2 != (Object)null) { Vec2 val = decoyActor.Controller.CurrentNormal(); Vec2 val2 = ((dir == val) ? dir : Vec2.Slerp(dir, val, __instance.f03)); decoyActor2.Body.selfImposedVelocity = val2 * (Fix)1.3 * decoyActor2.Physics.jumpStrength; } return false; } } [HarmonyPatch] internal static class CloneDecoyPatch { private static IEnumerable<MethodBase> TargetMethods() { yield return AccessTools.Method(typeof(PlayerCollision), "SpawnClone", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(PlayerCollision), "SpawnAbilityLessClone", (Type[])null, (Type[])null); } private static bool Prefix(SlimeController slimeContToRevive, Vec2 targetPosition, ref SlimeController __result) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) DecoyActor decoyActor = (((Object)(object)slimeContToRevive == (Object)null) ? null : ((Component)slimeContToRevive).GetComponent<DecoyActor>()); if ((Object)(object)decoyActor == (Object)null) { return true; } DecoyActor decoyActor2 = (decoyActor.Removed ? null : DecoyFactory.Spawn(decoyActor.SnapshotForCopy(), targetPosition, activation: false)); __result = (((Object)(object)decoyActor2 == (Object)null) ? null : decoyActor2.Controller); return false; } } [HarmonyPatch(typeof(Invisibility), "CastInvisibility")] internal static class CastInvisibilityPatch { private static void Prefix(InstantAbility ___ia, out DecoySnapshot __state) { __state = null; try { __state = DecoyFactory.Capture(___ia); } catch (Exception ex) { Plugin.Log.LogError((object)("Could not capture decoy appearance: " + ex)); } } private static void Postfix(DecoySnapshot __state) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) if (__state != null) { Player player = PlayerHandler.Get().GetPlayer(__state.OwnerId); if (player != null && player.IsAlive && player.isInvisible) { DecoyFactory.Spawn(__state, __state.Pose.position, activation: true); InstantInvisibilityPatch.RegisterInitialCast(player.Id); } } } } [HarmonyPatch(typeof(PlayerHandler), "GetPlayer")] internal static class ResolveDecoyPatch { private static bool Prefix(int playerId, ref Player __result) { if (!DecoyRegistry.TryGetPlayer(playerId, out var player)) { return true; } __result = player; return false; } } [HarmonyPatch(typeof(PlayerCollision), "killPlayer")] internal static class DecoyHitPatch { [HarmonyPriority(800)] private static bool Prefix(PlayerCollision __instance, bool spawnEffect, bool ignoreInvulnerability, ref bool __result) { DecoyActor component = ((Component)__instance).GetComponent<DecoyActor>(); if ((Object)(object)component == (Object)null) { return true; } __result = component.Remove(spawnEffect, ignoreInvulnerability); return false; } } [HarmonyPatch(typeof(Player), "Kill")] internal static class DecoyPlayerDeathPatch { private static bool Prefix(Player __instance) { if (!DecoyRegistry.TryGetPlayer(__instance.Id, out var player) || player != __instance) { return true; } DecoyRegistry.Find(__instance.Id)?.Remove(effect: false, ignoreInvulnerability: true); return false; } } [HarmonyPatch(typeof(SlimeController), "UpdateSim")] internal static class PassiveSlimePatch { private static bool Prefix(SlimeController __instance, Fix __0) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) DecoyActor component = ((Component)__instance).GetComponent<DecoyActor>(); if ((Object)(object)component == (Object)null) { return true; } component.Simulate(__0); return false; } } [HarmonyPatch] internal static class PassiveLifecyclePatch { private static IEnumerable<MethodBase> TargetMethods() { string[] names = new string[8] { "Init", "Spawn", "ReSpawn", "PrepareToRevive", "EnterAbility", "Bite", "OnNoLongerGrounded", "attachToGround" }; return from method in typeof(SlimeController).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) where names.Contains(method.Name) select method; } private static bool Prefix(SlimeController __instance) { return (Object)(object)((Component)__instance).GetComponent<DecoyActor>() == (Object)null; } } [HarmonyPatch(typeof(SlimeController), "OnCollide")] internal static class PassiveContactPatch { private static bool Prefix(SlimeController __instance, CollisionInformation collision) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)((Component)__instance).GetComponent<DecoyActor>() != (Object)null) { return false; } FixTransform fixTrans = collision.colliderPP.fixTrans; DecoyActor decoyActor = (((Object)(object)fixTrans == (Object)null) ? null : ((Component)fixTrans).GetComponent<DecoyActor>()); if (!((Object)(object)decoyActor == (Object)null)) { return decoyActor.OwnerId != __instance.playerNumber; } return true; } } [HarmonyPatch(typeof(SlimeController), "ApplyRagDoll")] internal static class PassiveImpulsePatch { private static bool Prefix(SlimeController __instance, Vec2 speed) { //IL_002d: 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) DecoyActor component = ((Component)__instance).GetComponent<DecoyActor>(); if ((Object)(object)component == (Object)null) { return true; } if (!component.Removed) { component.Physics.UnGround(true, false); component.Body.selfImposedVelocity = speed; } return false; } } [HarmonyPatch(typeof(PlayerPhysics), "UnGround")] internal static class DecoyJumpSoundPatch { private static void Prefix(PlayerPhysics __instance, ref bool playSoundEffect) { if ((Object)(object)((Component)__instance).GetComponent<DecoyActor>() != (Object)null) { playSoundEffect = false; } } } [HarmonyPatch(typeof(PlayerPhysics), "UpdateSim")] internal static class DecoyTimeStopPatch { private static bool Prefix(PlayerPhysics __instance) { DecoyActor component = ((Component)__instance).GetComponent<DecoyActor>(); if ((Object)(object)component == (Object)null) { return true; } component.RefreshTimeProtection(); if (!component.Removed && !GameSessionHandler.GameIsPaused) { return !GameTime.IsTimeStoppedFor(component.State.Id); } return false; } } [HarmonyPatch(typeof(DynamicAbilityPickup), "OnCollide")] internal static class DecoyPickupPatch { private static bool Prefix(CollisionInformation collision) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) FixTransform fixTrans = collision.colliderPP.fixTrans; if (!((Object)(object)fixTrans == (Object)null)) { return (Object)(object)((Component)fixTrans).GetComponent<DecoyActor>() == (Object)null; } return true; } } [HarmonyPatch(typeof(PlayerHandler), "ResetForNextStage")] internal static class DecoyRoundCleanupPatch { private static void Prefix() { DecoyRegistry.Clear(); } } [HarmonyPatch(typeof(Updater), "PreLevelLoad")] internal static class DecoyLevelCleanupPatch { private static void Prefix() { DecoyRegistry.Clear(); } } [HarmonyPatch] internal static class FrozenDecoyBodyPatch { private static IEnumerable<MethodBase> TargetMethods() { yield return AccessTools.Method(typeof(PlayerBody), "UpdateSim", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(PlayerBody), "LateUpdateSim", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(PlayerPhysics), "LateUpdateSim", (Type[])null, (Type[])null); } private static bool Prefix(Component __instance) { DecoyActor component = __instance.GetComponent<DecoyActor>(); if (!((Object)(object)component == (Object)null)) { if (!component.Removed && !GameTime.IsTimeStopped()) { return !GameSessionHandler.GameIsPaused; } return false; } return true; } } [HarmonyPatch(typeof(Invisibility), "SetAlphaBasedOnPlayerInvisibiltyTime")] internal static class InstantInvisibilityPatch { private static readonly HashSet<int> _initialCasts = new HashSet<int>(); public static void RegisterInitialCast(int playerId) { _initialCasts.Add(playerId); } private static void Postfix(Player player, SpriteRenderer spriteRen) { //IL_003a: 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_0063: 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_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) if (player == null || (Object)(object)spriteRen == (Object)null) { return; } if (!player.isInvisible) { _initialCasts.Remove(player.Id); } else if (_initialCasts.Contains(player.Id)) { if (player.timeSpentInvisible >= (Fix)1f) { _initialCasts.Remove(player.Id); } else if (spriteRen.color.a < 1f) { Color color = spriteRen.color; color.a = 0f; spriteRen.color = color; } } } } [BepInPlugin("com.maha.boplbattle.invisibilitydecoy", "Invisibility Decoy", "1.0.2")] public sealed class Plugin : BaseUnityPlugin { public const string Guid = "com.maha.boplbattle.invisibilitydecoy"; internal static ManualLogSource Log; internal const int MaxDecoysPerOwner = 16; private void Awake() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; new Harmony("com.maha.boplbattle.invisibilitydecoy").PatchAll(); Log.LogInfo((object)"Invisibility Decoy: native invisibility now leaves a passive, independent slime decoy."); } }