示例#1
0
        public static void Prefix(ref GameData.LGBOMGHJELL EAFLJGMBLCH, bool EMBDDLIPBME)
        {
            // Shifter shift
            if (Shifter.shifter != null && AmongUsClient.Instance.HHBLOCGKFAB && Shifter.futureShift != null)   // We need to send the RPC from the host here, to make sure that the order of shifting and erasing is correct (for that reason the futureShifted and futureErased are being synced)
            {
                MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.ShifterShift, Hazel.SendOption.Reliable, -1);
                writer.Write(Shifter.futureShift.PlayerId);
                AmongUsClient.Instance.FinishRpcImmediately(writer);
                RPCProcedure.shifterShift(Shifter.futureShift.PlayerId);
            }
            Shifter.futureShift = null;

            // Eraser erase
            if (Eraser.eraser != null && AmongUsClient.Instance.HHBLOCGKFAB && Eraser.futureErased != null)    // We need to send the RPC from the host here, to make sure that the order of shifting and erasing is correct (for that reason the futureShifted and futureErased are being synced)
            {
                foreach (PlayerControl target in Eraser.futureErased)
                {
                    if (target != null)
                    {
                        MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.ErasePlayerRole, Hazel.SendOption.Reliable, -1);
                        writer.Write(target.PlayerId);
                        AmongUsClient.Instance.FinishRpcImmediately(writer);
                        RPCProcedure.erasePlayerRole(target.PlayerId);
                    }
                }
            }
            Eraser.futureErased = new List <PlayerControl>();

            // Trickster boxes
            if (Trickster.trickster != null && JackInTheBox.hasJackInTheBoxLimitReached())
            {
                JackInTheBox.convertToVents();
            }
        }
示例#2
0
 public static void clearAndReload()
 {
     trickster         = null;
     lightsOutTimer    = 0f;
     placeBoxCooldown  = CustomOptionHolder.tricksterPlaceBoxCooldown.getFloat();
     lightsOutCooldown = CustomOptionHolder.tricksterLightsOutCooldown.getFloat();
     lightsOutDuration = CustomOptionHolder.tricksterLightsOutDuration.getFloat();
     JackInTheBox.UpdateStates(); // if the role is erased, we might have to update the state of the created objects
 }
示例#3
0
        public static void Prefix(ExileController __instance, [HarmonyArgument(0)] ref GameData.PlayerInfo exiled, [HarmonyArgument(1)] bool tie)
        {
            // Shifter shift
            if (Shifter.shifter != null && AmongUsClient.Instance.AmHost && Shifter.futureShift != null)   // We need to send the RPC from the host here, to make sure that the order of shifting and erasing is correct (for that reason the futureShifted and futureErased are being synced)
            {
                MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.ShifterShift, Hazel.SendOption.Reliable, -1);
                writer.Write(Shifter.futureShift.PlayerId);
                AmongUsClient.Instance.FinishRpcImmediately(writer);
                RPCProcedure.shifterShift(Shifter.futureShift.PlayerId);
            }
            Shifter.futureShift = null;

            // Eraser erase
            if (Eraser.eraser != null && AmongUsClient.Instance.AmHost && Eraser.futureErased != null)    // We need to send the RPC from the host here, to make sure that the order of shifting and erasing is correct (for that reason the futureShifted and futureErased are being synced)
            {
                foreach (PlayerControl target in Eraser.futureErased)
                {
                    if (target != null)
                    {
                        MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.ErasePlayerRole, Hazel.SendOption.Reliable, -1);
                        writer.Write(target.PlayerId);
                        AmongUsClient.Instance.FinishRpcImmediately(writer);
                        RPCProcedure.erasePlayerRole(target.PlayerId);
                    }
                }
            }
            Eraser.futureErased = new List <PlayerControl>();

            // Trickster boxes
            if (Trickster.trickster != null && JackInTheBox.hasJackInTheBoxLimitReached())
            {
                JackInTheBox.convertToVents();
            }

            // SecurityGuard vents and cameras
            var allCameras = ShipStatus.Instance.AllCameras.ToList();

            MapOptions.camerasToAdd.ForEach(camera => {
                camera.gameObject.SetActive(true);
                camera.gameObject.GetComponent <SpriteRenderer>().color = Color.white;
                allCameras.Add(camera);
            });
            ShipStatus.Instance.AllCameras = allCameras.ToArray();
            MapOptions.camerasToAdd        = new List <SurvCamera>();

            foreach (Vent vent in MapOptions.ventsToSeal)
            {
                PowerTools.SpriteAnim animator = vent.GetComponent <PowerTools.SpriteAnim>();
                animator?.Stop();
                vent.EnterVentAnim = vent.ExitVentAnim = null;
                vent.myRend.sprite = animator == null?SecurityGuard.getStaticVentSealedSprite() : SecurityGuard.getAnimatedVentSealedSprite();

                vent.myRend.color = Color.white;
                vent.name         = "SealedVent_" + vent.name;
            }
            MapOptions.ventsToSeal = new List <Vent>();
        }
示例#4
0
        // Main Controls

        public static void resetVariables()
        {
            Garlic.clearGarlics();
            JackInTheBox.clearJackInTheBoxes();
            clearAndReloadMapOptions();
            clearAndReloadRoles();
            clearGameHistory();
            setCustomButtonCooldowns();
        }
        public static void startAnimation(int ventId)
        {
            JackInTheBox box = AllJackInTheBoxes.FirstOrDefault((x) => x?.vent != null && x.vent.Id == ventId);

            if (box == null)
            {
                return;
            }
            Vent vent = box.vent;

            HudManager.Instance.StartCoroutine(Effects.Lerp(0.6f, new Action <float>((p) => {
                if (vent != null && vent.myRend != null)
                {
                    vent.myRend.sprite = getBoxAnimationSprite((int)(p * boxAnimationSprites.Length));
                    if (p == 1f)
                    {
                        vent.myRend.sprite = getBoxAnimationSprite(0);
                    }
                }
            })));
        }
示例#6
0
        public static void useUncheckedVent(int ventId, byte playerId, byte isEnter)
        {
            PlayerControl player = Helpers.playerById(playerId);

            if (player == null)
            {
                return;
            }
            // Fill dummy MessageReader and call MyPhysics.HandleRpc as the corountines cannot be accessed
            MessageReader reader = new MessageReader();

            byte[] bytes = BitConverter.GetBytes(ventId);
            if (!BitConverter.IsLittleEndian)
            {
                Array.Reverse(bytes);
            }
            reader.Buffer = bytes;
            reader.Length = bytes.Length;

            JackInTheBox.startAnimation(ventId);
            player.MyPhysics.HandleRpc(isEnter != 0 ? (byte)19 : (byte)20, reader);
        }
示例#7
0
        public static void startAnimation(int ventId)
        {
            JackInTheBox box = AllJackInTheBoxes.FirstOrDefault((x) => x?.vent != null && x.vent.Id == ventId);

            if (box == null)
            {
                return;
            }
            Vent vent = box.vent;

            HudManager.Instance.StartCoroutine(Effects.Lerp(0.6f, new Action <float>((p) => {
                var sprites = getBoxAnimationSprites();
                if (vent != null && vent.myRend != null && sprites != null && sprites.Count > 0)
                {
                    int index          = (int)(p * sprites.Count);
                    vent.myRend.sprite = sprites[Mathf.Clamp(index, 0, sprites.Count - 1)];
                    if (p == 1f)
                    {
                        vent.myRend.sprite = getBoxSprite();
                    }
                }
            })));
        }
示例#8
0
        public static void Postfix(HudManager __instance)
        {
            // Engineer Repair
            engineerRepairButton = new CustomButton(
                () => {
                engineerRepairButton.Timer = 0f;

                MessageWriter usedRepairWriter = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.EngineerUsedRepair, Hazel.SendOption.Reliable, -1);
                AmongUsClient.Instance.FinishRpcImmediately(usedRepairWriter);
                RPCProcedure.engineerUsedRepair();

                foreach (PlayerTask task in PlayerControl.LocalPlayer.myTasks)
                {
                    if (task.TaskType == TaskTypes.FixLights)
                    {
                        MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.EngineerFixLights, Hazel.SendOption.Reliable, -1);
                        AmongUsClient.Instance.FinishRpcImmediately(writer);
                        RPCProcedure.engineerFixLights();
                    }
                    else if (task.TaskType == TaskTypes.RestoreOxy)
                    {
                        ShipStatus.Instance.RpcRepairSystem(SystemTypes.LifeSupp, 0 | 64);
                        ShipStatus.Instance.RpcRepairSystem(SystemTypes.LifeSupp, 1 | 64);
                    }
                    else if (task.TaskType == TaskTypes.ResetReactor)
                    {
                        ShipStatus.Instance.RpcRepairSystem(SystemTypes.Reactor, 16);
                    }
                    else if (task.TaskType == TaskTypes.ResetSeismic)
                    {
                        ShipStatus.Instance.RpcRepairSystem(SystemTypes.Laboratory, 16);
                    }
                    else if (task.TaskType == TaskTypes.FixComms)
                    {
                        ShipStatus.Instance.RpcRepairSystem(SystemTypes.Comms, 16 | 0);
                        ShipStatus.Instance.RpcRepairSystem(SystemTypes.Comms, 16 | 1);
                    }
                    else if (task.TaskType == TaskTypes.StopCharles)
                    {
                        ShipStatus.Instance.RpcRepairSystem(SystemTypes.Reactor, 0 | 16);
                        ShipStatus.Instance.RpcRepairSystem(SystemTypes.Reactor, 1 | 16);
                    }
                }
            },
                () => { return(Engineer.engineer != null && Engineer.engineer == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead); },
                () => {
                bool sabotageActive = false;
                foreach (PlayerTask task in PlayerControl.LocalPlayer.myTasks)
                {
                    if (task.TaskType == TaskTypes.FixLights || task.TaskType == TaskTypes.RestoreOxy || task.TaskType == TaskTypes.ResetReactor || task.TaskType == TaskTypes.ResetSeismic || task.TaskType == TaskTypes.FixComms || task.TaskType == TaskTypes.StopCharles)
                    {
                        sabotageActive = true;
                    }
                }
                return(sabotageActive && !Engineer.usedRepair && PlayerControl.LocalPlayer.CanMove);
            },
                () => {},
                Engineer.getButtonSprite(),
                new Vector3(-1.3f, 0, 0),
                __instance,
                KeyCode.Q
                );

            // Janitor Clean
            janitorCleanButton = new CustomButton(
                () => {
                foreach (Collider2D collider2D in Physics2D.OverlapCircleAll(PlayerControl.LocalPlayer.GetTruePosition(), PlayerControl.LocalPlayer.MaxReportDistance, Constants.PlayersOnlyMask))
                {
                    if (collider2D.tag == "DeadBody")
                    {
                        DeadBody component = collider2D.GetComponent <DeadBody>();
                        if (component && !component.Reported)
                        {
                            Vector2 truePosition  = PlayerControl.LocalPlayer.GetTruePosition();
                            Vector2 truePosition2 = component.TruePosition;
                            if (Vector2.Distance(truePosition2, truePosition) <= PlayerControl.LocalPlayer.MaxReportDistance && PlayerControl.LocalPlayer.CanMove && !PhysicsHelpers.AnythingBetween(truePosition, truePosition2, Constants.ShipAndObjectsMask, false))
                            {
                                GameData.PlayerInfo playerInfo = GameData.Instance.GetPlayerById(component.ParentId);

                                MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.CleanBody, Hazel.SendOption.Reliable, -1);
                                writer.Write(playerInfo.PlayerId);
                                AmongUsClient.Instance.FinishRpcImmediately(writer);
                                RPCProcedure.cleanBody(playerInfo.PlayerId);
                                janitorCleanButton.Timer = janitorCleanButton.MaxTimer;

                                break;
                            }
                        }
                    }
                }
            },
                () => { return(Janitor.janitor != null && Janitor.janitor == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead); },
                () => { return(__instance.ReportButton.renderer.color == Palette.EnabledColor && PlayerControl.LocalPlayer.CanMove); },
                () => { janitorCleanButton.Timer = janitorCleanButton.MaxTimer; },
                Janitor.getButtonSprite(),
                new Vector3(-1.3f, 0, 0),
                __instance,
                KeyCode.Q
                );

            // Sheriff Kill
            sheriffKillButton = new CustomButton(
                () => {
                if (Medic.shielded != null && Medic.shielded == Sheriff.currentTarget)
                {
                    MessageWriter attemptWriter = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.ShieldedMurderAttempt, Hazel.SendOption.Reliable, -1);
                    AmongUsClient.Instance.FinishRpcImmediately(attemptWriter);
                    RPCProcedure.shieldedMurderAttempt();
                    return;
                }

                byte targetId = 0;
                if ((Sheriff.currentTarget.Data.IsImpostor && (Sheriff.currentTarget != Child.child || Child.isGrownUp())) ||
                    Sheriff.currentTarget == Jackal.jackal ||
                    Sheriff.currentTarget == Sidekick.sidekick ||
                    (Sheriff.spyCanDieToSheriff && Spy.spy != null && Spy.spy == Sheriff.currentTarget) ||
                    (Sheriff.jesterCanDieToSheriff && Jester.jester != null && Jester.jester == Sheriff.currentTarget))
                {
                    targetId = Sheriff.currentTarget.PlayerId;
                }
                else
                {
                    targetId = PlayerControl.LocalPlayer.PlayerId;
                }
                MessageWriter killWriter = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.SheriffKill, Hazel.SendOption.Reliable, -1);
                killWriter.Write(targetId);
                AmongUsClient.Instance.FinishRpcImmediately(killWriter);
                RPCProcedure.sheriffKill(targetId);

                sheriffKillButton.Timer = sheriffKillButton.MaxTimer;
                Sheriff.currentTarget   = null;
            },
                () => { return(Sheriff.sheriff != null && Sheriff.sheriff == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead); },
                () => { return(Sheriff.currentTarget && PlayerControl.LocalPlayer.CanMove); },
                () => { sheriffKillButton.Timer = sheriffKillButton.MaxTimer; },
                __instance.KillButton.renderer.sprite,
                new Vector3(-1.3f, 0, 0),
                __instance,
                KeyCode.Q
                );

            // Time Master Rewind Time
            timeMasterShieldButton = new CustomButton(
                () => {
                MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.TimeMasterShield, Hazel.SendOption.Reliable, -1);
                AmongUsClient.Instance.FinishRpcImmediately(writer);
                RPCProcedure.timeMasterShield();
            },
                () => { return(TimeMaster.timeMaster != null && TimeMaster.timeMaster == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead); },
                () => { return(PlayerControl.LocalPlayer.CanMove); },
                () => {
                timeMasterShieldButton.Timer          = timeMasterShieldButton.MaxTimer;
                timeMasterShieldButton.isEffectActive = false;
                timeMasterShieldButton.killButtonManager.TimerText.color = Palette.EnabledColor;
            },
                TimeMaster.getButtonSprite(),
                new Vector3(-1.3f, 0, 0),
                __instance,
                KeyCode.Q,
                true,
                TimeMaster.shieldDuration,
                () => { timeMasterShieldButton.Timer = timeMasterShieldButton.MaxTimer; }
                );

            // Medic Shield
            medicShieldButton = new CustomButton(
                () => {
                medicShieldButton.Timer = 0f;

                MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.MedicSetShielded, Hazel.SendOption.Reliable, -1);
                writer.Write(Medic.currentTarget.PlayerId);
                AmongUsClient.Instance.FinishRpcImmediately(writer);
                RPCProcedure.medicSetShielded(Medic.currentTarget.PlayerId);
            },
                () => { return(Medic.medic != null && Medic.medic == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead); },
                () => { return(!Medic.usedShield && Medic.currentTarget && PlayerControl.LocalPlayer.CanMove); },
                () => {},
                Medic.getButtonSprite(),
                new Vector3(-1.3f, 0, 0),
                __instance,
                KeyCode.Q
                );


            // Shifter shift
            shifterShiftButton = new CustomButton(
                () => {
                MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.SetFutureShifted, Hazel.SendOption.Reliable, -1);
                writer.Write(Shifter.currentTarget.PlayerId);
                AmongUsClient.Instance.FinishRpcImmediately(writer);
                RPCProcedure.setFutureShifted(Shifter.currentTarget.PlayerId);
            },
                () => { return(Shifter.shifter != null && Shifter.shifter == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead); },
                () => { return(Shifter.currentTarget && Shifter.futureShift == null && PlayerControl.LocalPlayer.CanMove); },
                () => { },
                Shifter.getButtonSprite(),
                new Vector3(-1.3f, 0, 0),
                __instance,
                KeyCode.Q
                );

            // Morphling morph
            morphlingButton = new CustomButton(
                () => {
                if (Morphling.sampledTarget != null)
                {
                    MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.MorphlingMorph, Hazel.SendOption.Reliable, -1);
                    writer.Write(Morphling.sampledTarget.PlayerId);
                    AmongUsClient.Instance.FinishRpcImmediately(writer);
                    RPCProcedure.morphlingMorph(Morphling.sampledTarget.PlayerId);
                    Morphling.sampledTarget        = null;
                    morphlingButton.EffectDuration = Morphling.duration;
                }
                else if (Morphling.currentTarget != null)
                {
                    Morphling.sampledTarget        = Morphling.currentTarget;
                    morphlingButton.Sprite         = Morphling.getMorphSprite();
                    morphlingButton.EffectDuration = 1f;
                }
            },
                () => { return(Morphling.morphling != null && Morphling.morphling == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead); },
                () => { return((Morphling.currentTarget || Morphling.sampledTarget) && PlayerControl.LocalPlayer.CanMove); },
                () => {
                morphlingButton.Timer          = morphlingButton.MaxTimer;
                morphlingButton.Sprite         = Morphling.getSampleSprite();
                morphlingButton.isEffectActive = false;
                morphlingButton.killButtonManager.TimerText.color = Palette.EnabledColor;
                Morphling.sampledTarget = null;
            },
                Morphling.getSampleSprite(),
                new Vector3(-1.3f, 1.3f, 0f),
                __instance,
                KeyCode.F,
                true,
                Morphling.duration,
                () => {
                if (Morphling.sampledTarget == null)
                {
                    morphlingButton.Timer  = morphlingButton.MaxTimer;
                    morphlingButton.Sprite = Morphling.getSampleSprite();
                }
            }
                );

            // Camouflager camouflage
            camouflagerButton = new CustomButton(
                () => {
                MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.CamouflagerCamouflage, Hazel.SendOption.Reliable, -1);
                AmongUsClient.Instance.FinishRpcImmediately(writer);
                RPCProcedure.camouflagerCamouflage();
            },
                () => { return(Camouflager.camouflager != null && Camouflager.camouflager == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead); },
                () => { return(PlayerControl.LocalPlayer.CanMove); },
                () => {
                camouflagerButton.Timer          = camouflagerButton.MaxTimer;
                camouflagerButton.isEffectActive = false;
                camouflagerButton.killButtonManager.TimerText.color = Palette.EnabledColor;
            },
                Camouflager.getButtonSprite(),
                new Vector3(-1.3f, 1.3f, 0f),
                __instance,
                KeyCode.F,
                true,
                Camouflager.duration,
                () => { camouflagerButton.Timer = camouflagerButton.MaxTimer; }
                );

            // Hacker button
            hackerButton = new CustomButton(
                () => {
                Hacker.hackerTimer = Hacker.duration;
            },
                () => { return(Hacker.hacker != null && Hacker.hacker == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead); },
                () => { return(PlayerControl.LocalPlayer.CanMove); },
                () => {
                hackerButton.Timer          = hackerButton.MaxTimer;
                hackerButton.isEffectActive = false;
                hackerButton.killButtonManager.TimerText.color = Palette.EnabledColor;
            },
                Hacker.getButtonSprite(),
                new Vector3(-1.3f, 0, 0),
                __instance,
                KeyCode.Q,
                true,
                0f,
                () => {
                hackerButton.Timer = hackerButton.MaxTimer;
            }
                );

            // Tracker button
            trackerButton = new CustomButton(
                () => {
                MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.TrackerUsedTracker, Hazel.SendOption.Reliable, -1);
                writer.Write(Tracker.currentTarget.PlayerId);
                AmongUsClient.Instance.FinishRpcImmediately(writer);
                RPCProcedure.trackerUsedTracker(Tracker.currentTarget.PlayerId);
            },
                () => { return(Tracker.tracker != null && Tracker.tracker == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead); },
                () => { return(PlayerControl.LocalPlayer.CanMove && Tracker.currentTarget != null && !Tracker.usedTracker); },
                () => { },
                Tracker.getButtonSprite(),
                new Vector3(-1.3f, 0, 0),
                __instance,
                KeyCode.Q
                );

            vampireKillButton = new CustomButton(
                () => {
                if (Helpers.handleMurderAttempt(Vampire.currentTarget))
                {
                    if (Vampire.targetNearGarlic)
                    {
                        PlayerControl.LocalPlayer.RpcMurderPlayer(Vampire.currentTarget);
                        vampireKillButton.HasEffect = false;     // Block effect on this click
                        vampireKillButton.Timer     = vampireKillButton.MaxTimer;
                    }
                    else
                    {
                        Vampire.bitten = Vampire.currentTarget;
                        // Notify players about bitten
                        MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.VampireSetBitten, Hazel.SendOption.Reliable, -1);
                        writer.Write(Vampire.bitten.PlayerId);
                        writer.Write(0);
                        AmongUsClient.Instance.FinishRpcImmediately(writer);
                        RPCProcedure.vampireSetBitten(Vampire.bitten.PlayerId, 0);

                        HudManager.Instance.StartCoroutine(Effects.Lerp(Vampire.delay, new Action <float>((p) => {    // Delayed action
                            if (p == 1f)
                            {
                                if (Vampire.bitten != null && !Vampire.bitten.Data.IsDead && Helpers.handleMurderAttempt(Vampire.bitten))
                                {
                                    // Perform kill
                                    MessageWriter killWriter = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.VampireTryKill, Hazel.SendOption.Reliable, -1);
                                    AmongUsClient.Instance.FinishRpcImmediately(killWriter);
                                    RPCProcedure.vampireTryKill();
                                }
                                else
                                {
                                    // Notify players about clearing bitten
                                    MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.VampireSetBitten, Hazel.SendOption.Reliable, -1);
                                    writer.Write(byte.MaxValue);
                                    writer.Write(byte.MaxValue);
                                    AmongUsClient.Instance.FinishRpcImmediately(writer);
                                    RPCProcedure.vampireSetBitten(byte.MaxValue, byte.MaxValue);
                                }
                            }
                        })));

                        vampireKillButton.HasEffect = true;     // Trigger effect on this click
                    }
                }
                else
                {
                    vampireKillButton.HasEffect = false;     // Block effect if no action was fired
                }
            },
                () => { return(Vampire.vampire != null && Vampire.vampire == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead); },
                () => {
                if (Vampire.targetNearGarlic && Vampire.canKillNearGarlics)
                {
                    vampireKillButton.killButtonManager.renderer.sprite = __instance.KillButton.renderer.sprite;
                }
                else
                {
                    vampireKillButton.killButtonManager.renderer.sprite = Vampire.getButtonSprite();
                }
                return(Vampire.currentTarget != null && PlayerControl.LocalPlayer.CanMove && (!Vampire.targetNearGarlic || Vampire.canKillNearGarlics));
            },
                () => {
                vampireKillButton.Timer          = vampireKillButton.MaxTimer;
                vampireKillButton.isEffectActive = false;
                vampireKillButton.killButtonManager.TimerText.color = Palette.EnabledColor;
            },
                Vampire.getButtonSprite(),
                new Vector3(-1.3f, 0, 0),
                __instance,
                KeyCode.Q,
                false,
                0f,
                () => {
                vampireKillButton.Timer = vampireKillButton.MaxTimer;
            }
                );

            garlicButton = new CustomButton(
                () => {
                Vampire.localPlacedGarlic = true;
                var pos     = PlayerControl.LocalPlayer.transform.position;
                byte[] buff = new byte[sizeof(float) * 2];
                Buffer.BlockCopy(BitConverter.GetBytes(pos.x), 0, buff, 0 * sizeof(float), sizeof(float));
                Buffer.BlockCopy(BitConverter.GetBytes(pos.y), 0, buff, 1 * sizeof(float), sizeof(float));

                MessageWriter writer = AmongUsClient.Instance.StartRpc(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.PlaceGarlic, Hazel.SendOption.Reliable);
                writer.WriteBytesAndSize(buff);
                writer.EndMessage();
                RPCProcedure.placeGarlic(buff);
            },
                () => { return(!Vampire.localPlacedGarlic && !PlayerControl.LocalPlayer.Data.IsDead && Vampire.garlicsActive); },
                () => { return(PlayerControl.LocalPlayer.CanMove && !Vampire.localPlacedGarlic); },
                () => { },
                Vampire.getGarlicButtonSprite(),
                Vector3.zero,
                __instance,
                null,
                true
                );


            // Jackal Sidekick Button
            jackalSidekickButton = new CustomButton(
                () => {
                MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.JackalCreatesSidekick, Hazel.SendOption.Reliable, -1);
                writer.Write(Jackal.currentTarget.PlayerId);
                AmongUsClient.Instance.FinishRpcImmediately(writer);
                RPCProcedure.jackalCreatesSidekick(Jackal.currentTarget.PlayerId);
            },
                () => { return(Jackal.canCreateSidekick && Sidekick.sidekick == null && Jackal.fakeSidekick == null && Jackal.jackal != null && Jackal.jackal == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead); },
                () => { return(Sidekick.sidekick == null && Jackal.fakeSidekick == null && Jackal.currentTarget != null && PlayerControl.LocalPlayer.CanMove); },
                () => { jackalSidekickButton.Timer = jackalSidekickButton.MaxTimer; },
                Jackal.getSidekickButtonSprite(),
                new Vector3(-1.3f, 1.3f, 0f),
                __instance,
                KeyCode.F
                );

            // Jackal Kill
            jackalKillButton = new CustomButton(
                () => {
                if (!Helpers.handleMurderAttempt(Jackal.currentTarget))
                {
                    return;
                }
                byte targetId            = Jackal.currentTarget.PlayerId;
                MessageWriter killWriter = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.JackalKill, Hazel.SendOption.Reliable, -1);
                killWriter.Write(targetId);
                AmongUsClient.Instance.FinishRpcImmediately(killWriter);
                RPCProcedure.jackalKill(targetId);
                jackalKillButton.Timer = jackalKillButton.MaxTimer;
                Jackal.currentTarget   = null;
            },
                () => { return(Jackal.jackal != null && Jackal.jackal == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead); },
                () => { return(Jackal.currentTarget && PlayerControl.LocalPlayer.CanMove); },
                () => { jackalKillButton.Timer = jackalKillButton.MaxTimer; },
                __instance.KillButton.renderer.sprite,
                new Vector3(-1.3f, 0, 0),
                __instance,
                KeyCode.Q
                );

            // Sidekick Kill
            sidekickKillButton = new CustomButton(
                () => {
                if (!Helpers.handleMurderAttempt(Sidekick.currentTarget))
                {
                    return;
                }
                byte targetId            = Sidekick.currentTarget.PlayerId;
                MessageWriter killWriter = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.SidekickKill, Hazel.SendOption.Reliable, -1);
                killWriter.Write(targetId);
                AmongUsClient.Instance.FinishRpcImmediately(killWriter);
                RPCProcedure.sidekickKill(targetId);

                sidekickKillButton.Timer = sidekickKillButton.MaxTimer;
                Sidekick.currentTarget   = null;
            },
                () => { return(Sidekick.canKill && Sidekick.sidekick != null && Sidekick.sidekick == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead); },
                () => { return(Sidekick.currentTarget && PlayerControl.LocalPlayer.CanMove); },
                () => { sidekickKillButton.Timer = sidekickKillButton.MaxTimer; },
                __instance.KillButton.renderer.sprite,
                new Vector3(-1.3f, 0, 0),
                __instance,
                KeyCode.Q
                );

            // Lighter light
            lighterButton = new CustomButton(
                () => {
                Lighter.lighterTimer = Lighter.duration;
            },
                () => { return(Lighter.lighter != null && Lighter.lighter == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead); },
                () => { return(PlayerControl.LocalPlayer.CanMove); },
                () => {
                lighterButton.Timer          = lighterButton.MaxTimer;
                lighterButton.isEffectActive = false;
                lighterButton.killButtonManager.TimerText.color = Palette.EnabledColor;
            },
                Lighter.getButtonSprite(),
                new Vector3(-1.3f, 0f, 0f),
                __instance,
                KeyCode.Q,
                true,
                Lighter.duration,
                () => { lighterButton.Timer = lighterButton.MaxTimer; }
                );

            // Eraser erase button
            eraserButton = new CustomButton(
                () => {
                eraserButton.MaxTimer += 10;
                eraserButton.Timer     = eraserButton.MaxTimer;

                MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.SetFutureErased, Hazel.SendOption.Reliable, -1);
                writer.Write(Eraser.currentTarget.PlayerId);
                AmongUsClient.Instance.FinishRpcImmediately(writer);
                RPCProcedure.setFutureErased(Eraser.currentTarget.PlayerId);
            },
                () => { return(Eraser.eraser != null && Eraser.eraser == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead); },
                () => { return(PlayerControl.LocalPlayer.CanMove && Eraser.currentTarget != null); },
                () => { eraserButton.Timer = eraserButton.MaxTimer; },
                Eraser.getButtonSprite(),
                new Vector3(-1.3f, 1.3f, 0f),
                __instance,
                KeyCode.F
                );

            placeJackInTheBoxButton = new CustomButton(
                () => {
                placeJackInTheBoxButton.Timer = placeJackInTheBoxButton.MaxTimer;

                var pos     = PlayerControl.LocalPlayer.transform.position;
                byte[] buff = new byte[sizeof(float) * 2];
                Buffer.BlockCopy(BitConverter.GetBytes(pos.x), 0, buff, 0 * sizeof(float), sizeof(float));
                Buffer.BlockCopy(BitConverter.GetBytes(pos.y), 0, buff, 1 * sizeof(float), sizeof(float));

                MessageWriter writer = AmongUsClient.Instance.StartRpc(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.PlaceJackInTheBox, Hazel.SendOption.Reliable);
                writer.WriteBytesAndSize(buff);
                writer.EndMessage();
                RPCProcedure.placeJackInTheBox(buff);
            },
                () => { return(Trickster.trickster != null && Trickster.trickster == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead && !JackInTheBox.hasJackInTheBoxLimitReached()); },
                () => { return(PlayerControl.LocalPlayer.CanMove && !JackInTheBox.hasJackInTheBoxLimitReached()); },
                () => { placeJackInTheBoxButton.Timer = placeJackInTheBoxButton.MaxTimer; },
                Trickster.getPlaceBoxButtonSprite(),
                new Vector3(-1.3f, 1.3f, 0f),
                __instance,
                KeyCode.F
                );

            lightsOutButton = new CustomButton(
                () => {
                MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.LightsOut, Hazel.SendOption.Reliable, -1);
                AmongUsClient.Instance.FinishRpcImmediately(writer);
                RPCProcedure.lightsOut();
            },
                () => { return(Trickster.trickster != null && Trickster.trickster == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead && JackInTheBox.hasJackInTheBoxLimitReached() && JackInTheBox.boxesConvertedToVents); },
                () => { return(PlayerControl.LocalPlayer.CanMove && JackInTheBox.hasJackInTheBoxLimitReached() && JackInTheBox.boxesConvertedToVents); },
                () => {
                lightsOutButton.Timer          = lightsOutButton.MaxTimer;
                lightsOutButton.isEffectActive = false;
                lightsOutButton.killButtonManager.TimerText.color = Palette.EnabledColor;
            },
                Trickster.getLightsOutButtonSprite(),
                new Vector3(-1.3f, 1.3f, 0f),
                __instance,
                KeyCode.F,
                true,
                Trickster.lightsOutDuration,
                () => { lightsOutButton.Timer = lightsOutButton.MaxTimer; }
                );
            // Cleaner Clean
            cleanerCleanButton = new CustomButton(
                () => {
                foreach (Collider2D collider2D in Physics2D.OverlapCircleAll(PlayerControl.LocalPlayer.GetTruePosition(), PlayerControl.LocalPlayer.MaxReportDistance, Constants.PlayersOnlyMask))
                {
                    if (collider2D.tag == "DeadBody")
                    {
                        DeadBody component = collider2D.GetComponent <DeadBody>();
                        if (component && !component.Reported)
                        {
                            Vector2 truePosition  = PlayerControl.LocalPlayer.GetTruePosition();
                            Vector2 truePosition2 = component.TruePosition;
                            if (Vector2.Distance(truePosition2, truePosition) <= PlayerControl.LocalPlayer.MaxReportDistance && PlayerControl.LocalPlayer.CanMove && !PhysicsHelpers.AnythingBetween(truePosition, truePosition2, Constants.ShipAndObjectsMask, false))
                            {
                                GameData.PlayerInfo playerInfo = GameData.Instance.GetPlayerById(component.ParentId);

                                MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.CleanBody, Hazel.SendOption.Reliable, -1);
                                writer.Write(playerInfo.PlayerId);
                                AmongUsClient.Instance.FinishRpcImmediately(writer);
                                RPCProcedure.cleanBody(playerInfo.PlayerId);

                                Cleaner.cleaner.killTimer = cleanerCleanButton.Timer = cleanerCleanButton.MaxTimer;
                                break;
                            }
                        }
                    }
                }
            },
                () => { return(Cleaner.cleaner != null && Cleaner.cleaner == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead); },
                () => { return(__instance.ReportButton.renderer.color == Palette.EnabledColor && PlayerControl.LocalPlayer.CanMove); },
                () => { cleanerCleanButton.Timer = cleanerCleanButton.MaxTimer; },
                Cleaner.getButtonSprite(),
                new Vector3(-1.3f, 1.3f, 0f),
                __instance,
                KeyCode.F
                );
            // Warlock curse
            warlockCurseButton = new CustomButton(
                () => {
                if (Warlock.curseVictim == null)
                {
                    // Apply Curse
                    Warlock.curseVictim       = Warlock.currentTarget;
                    warlockCurseButton.Sprite = Warlock.getCurseKillButtonSprite();
                    warlockCurseButton.Timer  = 1f;
                }
                else if (Warlock.curseVictim != null && Warlock.curseVictimTarget != null && Helpers.handleMurderAttempt(Warlock.curseVictimTarget))
                {
                    // Curse Kill
                    Warlock.curseKillTarget = Warlock.curseVictimTarget;

                    MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.WarlockCurseKill, Hazel.SendOption.Reliable, -1);
                    writer.Write(Warlock.curseKillTarget.PlayerId);
                    AmongUsClient.Instance.FinishRpcImmediately(writer);
                    RPCProcedure.warlockCurseKill(Warlock.curseKillTarget.PlayerId);

                    Warlock.curseVictim       = null;
                    Warlock.curseVictimTarget = null;
                    warlockCurseButton.Sprite = Warlock.getCurseButtonSprite();
                    Warlock.warlock.killTimer = warlockCurseButton.Timer = warlockCurseButton.MaxTimer;

                    if (Warlock.rootTime > 0)
                    {
                        PlayerControl.LocalPlayer.moveable = false;
                        PlayerControl.LocalPlayer.NetTransform.Halt();                                                // Stop current movement so the warlock is not just running straight into the next object
                        HudManager.Instance.StartCoroutine(Effects.Lerp(Warlock.rootTime, new Action <float>((p) => { // Delayed action
                            if (p == 1f)
                            {
                                PlayerControl.LocalPlayer.moveable = true;
                            }
                        })));
                    }
                }
            },
                () => { return(Warlock.warlock != null && Warlock.warlock == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead); },
                () => { return(((Warlock.curseVictim == null && Warlock.currentTarget != null) || (Warlock.curseVictim != null && Warlock.curseVictimTarget != null)) && PlayerControl.LocalPlayer.CanMove); },
                () => {
                warlockCurseButton.Timer  = warlockCurseButton.MaxTimer;
                warlockCurseButton.Sprite = Warlock.getCurseButtonSprite();
                Warlock.curseVictim       = null;
                Warlock.curseVictimTarget = null;
            },
                Warlock.getCurseButtonSprite(),
                new Vector3(-1.3f, 1.3f, 0f),
                __instance,
                KeyCode.F
                );


            // Set the default (or settings from the previous game) timers/durations when spawning the buttons
            setCustomButtonCooldowns();
        }