// Fartsy's Boss Handler v1.0.0
enum struct BOSSHANDLER {
    int bossID;
    bool bTargetInRange[MAXPLAYERS+1];
    bool bDoTankBuster;
    bool isAlive;
    bool shouldTick;
    bool shouldTickBGM;
    bool sOverflow;
    bool tickBuster;
    bool tickBusterNuclear;
    float fAng[3];
    float fPos[3];
    int bustTarget;
    int bustNukeTarget;
    int iBossEnt;
    int iBossEntHealth;
    int iBossEntMaxHealth;
    int iBossEntTarget;
    int iBossPhase;
    int iBossPhaseTmp;
    void EmitSpawnSound(int boss){
        switch(boss){
            //Onslaughter
            case 0:{
                //Onslaughter has no spawn sound for now.... maybe when brute justice happens c:
            }
            //Sephiroth (wip)
            case 1:{

            }
            //Metallizer (wip) To Do: Only change to Inferno if we're in boss attack range. Use a trigger_multiple for this. To Do, delay this by like 1 second so the DJMM sound can play properly.
            case 2:{
                sudo(1001);
                AudioManager.Stop();
                AudioManager.indexBGM = 20;
                CustomSoundEmitter(SFXArray[106].realPath, 65, false, 0, 1.0, 100); //DJMM SFX
                CreateTimer(1.5, DelayedMetalFace);
            }
        }
    }
    //For tracking model and skipping player ready check if boss is alive
    void Tick(){
        //PrintToServer("Boss %i, hp %i/%i", this.bossID, this.iBossEntHealth, this.iBossEntMaxHealth);
        if (this.shouldTickBGM) (this.TickBGM());
        if(this.isAlive && !core.isWave){
            PrintToChatAll("PLACEHOLDER -- FORCE PLAYERS TO BE READY IF NOT IN WAVE.");
        }
        if(this.tickBuster) this.TickBuster();
        switch(this.bossID){
            case 0:{
                float pos[3], ang[3], vel[3], newPos[3];
                vel[0] = 0.0;
                vel[1] = 0.0;
                vel[2] = 0.0;
                int BossEnt = FindEntityByTargetname("FB.BruteJusticeTrain", "func_tracktrain");
                int BossTP = FindEntityByTargetname("FB.OnslaughterBase", "base_boss");
                GetEntPropVector(BossEnt, Prop_Send, "m_vecOrigin", pos);
                GetEntPropVector(BossEnt, Prop_Data, "m_angRotation", ang);
                newPos[0] = pos[0];
                newPos[1] = pos[1];
                newPos[2] = pos[2] + 0.0;
                TeleportEntity(BossTP, newPos, ang, vel);
            }
            case 1:{

            }
            case 2:{
                this.iBossEnt = FindEntityByTargetname("FB.MetalBase", "base_boss");
                if (!IsValidEntity(this.iBossEnt)) this.iBossPhase = 4;
                else {
                    this.iBossEntHealth = GetEntProp(this.iBossEnt, Prop_Data, "m_iHealth");
                    this.iBossEntMaxHealth = GetEntProp(this.iBossEnt, Prop_Data, "m_iMaxHealth");
                    this.iBossEntTarget = FindEntityByTargetname("FB.MetalFace.Train", "func_tracktrain");
                    GetEntPropVector(this.iBossEntTarget, Prop_Send, "m_vecOrigin", this.fPos);
                    GetEntPropVector(this.iBossEntTarget, Prop_Data, "m_angRotation", this.fAng);
                    float vel[3];
                    float newPos[3];
                    vel[0] = 0.0;
                    vel[1] = 0.0;
                    vel[2] = 0.0;
                    newPos[0] = this.fPos[0];
                    newPos[1] = this.fPos[1];
                    newPos[2] = this.fPos[2] - 50.0;
                    TeleportEntity(this.iBossEnt, newPos, this.fAng, vel);
                }
                //Also need to set entity angles to its target... we can use this.bustTarget for the index of the client to get the angles...
                //Do phase changes
                switch(RoundToFloor((this.iBossEntHealth * 1.0/this.iBossEntMaxHealth * 1.0) * 10.0)){
                    case 10:{
                        this.iBossPhase = 1;
                    }
                    case 7:{
                        this.iBossPhase = 2;
                    }
                    case 4:{
                        this.iBossPhase = 3;
                    }
                    case 1:{
                        this.iBossPhase = 4;
                    }
                }
                if(this.iBossPhase != this.iBossPhaseTmp){
                    PrintToChatAll("PHASE CHANGED, %i to %i", this.iBossPhaseTmp, this.iBossPhase);
                    this.iBossPhaseTmp = this.iBossPhase;
                    if(this.iBossPhase > 1){
                        FastFire2("mfTelefect", "Start", "", 0.0, false);
                        FastFire2("FB.MetalFace.ReturnSND", "PlaySound", "", 0.0, false);
                        FastFire2("FB.MetalFace.Train", "TeleportToPathTrack", "MFTHOME", 0.25, false);
                        FastFire2("FB.MetalFace.Invuln", "Enable", "", 3.0, false);
                    }
                    //Phase changing, these only ever happen once per phase.
                    switch(this.iBossPhase){
                        case 0:{
                            PrintToChatAll("Phase 0 happened, boss must must be dead /shrug");
                        }
                        case 1:{
                            //PrintToChatAll("Recognized 0 -> 1, the boss must have just spawned!");
                            FastFire2("FB.MetalBase", "SetHealth", "320000", 0.0, false);
                            FastFire2("FB.MetalBase", "SetMaxHealth", "320000", 0.0, false);
                            FastFire2("FB.MetalBase", "AddOutput", "health 320000", 0.0, false);
                            FastFire2("FB.MetalFace", "Enable", "", 0.0, false);
                        }
                        case 2:{
                            //PrintToChatAll("Recognized 1 -> 2, things are heating up!");
                            AudioManager.ChangeBGM(22, false);
                            FastFire2("FB.MetalFace.Train", "TeleportToPathTrack", "MFT1x0", 3.00, false);
                            FastFire2("FB.MetalFace.SkeleSpawner", "Enable", "", 0.0, false);
                            FastFire2("FB.MetalFace.SkeleSpawner", "Disable", "", 120.0, false);
                            FastFire2("mfTelefect", "Start", "", 120.0, false);
                            FastFire2("FB.MetalFace.ReturnSND", "PlaySound", "", 120.0, false);
                            FastFire2("FB.MetalFace.Train", "TeleportToPathTrack", "MFTHOME", 120.25, false);
                            FastFire2("FB.MetalFace.Invuln", "Disable", "", 123.0, false);
                            FastFire2("FB.MetalFace.Train", "TeleportToPathTrack", "tank_path_a_100", 126.85, false);
                            FastFire2("mfTelefect", "Start", "", 127.0, false);
                            FastFire2("FB.MetalFace.ReturnSND", "PlaySound", "", 127.0, false);
                        }
                        case 3:{
                            //PrintToChatAll("Recognized 2 -> 3, oh boi");
                            AudioManager.ChangeBGM(24, false);
                            FastFire2("FB.MetalFace.Train", "TeleportToPathTrack", "MFT2x0", 3.00, false);
                            FastFire2("FB.MetalFace.MerasmusSpawner", "ForceSpawn", "", 5.0, false); //Spawn halloween bosses at MetalFace's location
                            FastFire2("FB.MetalFace.MonoculusSpawner", "ForceSpawn", "", 7.0, false); //Spawn halloween bosses at MetalFace's location
                            FastFire2("FB.MetalFace.HHHSpawner", "ForceSpawn", "", 9.0, false); //Spawn halloween bosses at MetalFace's location
                            FastFire2("FB.MetalFace.Invuln", "Disable", "", 123.0, false);
                            FastFire2("FB.MetalFace.Train", "TeleportToPathTrack", "tank_path_a_250", 126.85, false);
                            FastFire2("mfTelefect", "Start", "", 127.0, false);
                            FastFire2("FB.MetalFace.ReturnSND", "PlaySound", "", 127.0, false);
                        }
                        case 4:{
                            //PrintToChatAll("Recognized 3 -> 4, OHSHITOHFUCKOHNO");
                            AudioManager.ChangeBGM(26, true);
                            FastFire2("FB.MetalFace.Train", "TeleportToPathTrack", "MFT3x0", 3.00, false);
                            FastFire2("FB.MetalFace.GigaBuster", "ForceSpawn", "", 10.0, false);
                        }
                    }
                }
            }
            case 69:{
                int eCount = 0;
                for (int i = 1; i <= MaxClients; i++) {
                  if (!IsClientInGame(i)) continue;
                  if (GetClientTeam(i) == 2 && TF2_GetPlayerClass(i) == TFClass_Engineer) eCount++;
                }
                int sCount = 0;
                int ent = -1
                while ((ent = FindEntityByClassname(ent, "obj_sentrygun")) != -1) {
                    if (!IsValidEntity(ent)) continue;
                    if (this.sOverflow) {
                        SetEntProp(ent, Prop_Send, "m_iTeamNum", TFTeam_Blue);
                        SetEntPropEnt(ent, Prop_Data, "m_hOwnerEntity", 0);
                    }
                    if (GetEntProp(ent, Prop_Send, "m_iTeamNum") == 2) {
                        sCount++;
                        PrintToChatAll("Found %i sentry guns. I'm watching your ass...", sCount);
                        if (sCount > eCount * 7){
                            PrintToChatAll("[FARTSY.DLL] TOO MANY SENTRIES DETECTED. PREPARE TO DIE. WOLOLOOOOOOO!");
                            this.sOverflow = true;
                            ent = -1;
                            sCount = 0;
                            CreateTimer(3.0, TimedOperator, 42690);
                        }
                    }
                }
            }
        }
    }
    //For tracking bgm and updating bgm based on player emnity
    void TickBGM(){
        if (this.shouldTickBGM){
            int iBGM0;
            int iBGM1;
            switch(this.iBossPhase){
                case 1:{
                    iBGM0 = 20;
                    iBGM1 = 21;
                }
                case 2:{
                    iBGM0 = 22;
                    iBGM1 = 23;
                }
                case 3:{
                    iBGM0 = 24;
                    iBGM1 = 25;
                }
                case 4:{
                    iBGM0 = 26;
                    iBGM1 = 27;
                }
            }
            for (int i = 0; i < MaxClients; i++){
                if (EmnityManager[i].IsAboveEmnityThreshold(SuggestEmnityThreshold())) {
                    CSEClient(i, BGMArray[iBGM1].realPath, BGMArray[iBGM1].SNDLVL, true, 1, 1.0, 100);
                    CSEClient(i, BGMArray[iBGM0].realPath, BGMArray[iBGM0].SNDLVL, true, 1, 0.05, 100);
                }
                else {
                    CSEClient(i, BGMArray[iBGM1].realPath, BGMArray[iBGM1].SNDLVL, true, 1, 0.05, 100);
                    CSEClient(i, BGMArray[iBGM0].realPath, BGMArray[iBGM0].SNDLVL, true, 1, 1.0, 100);
                }
            }
            AudioManager.indexBGM = iBGM0;
        }
    }
    //Tank buster thing
    void TickBuster(){
        float cPos[3]; //Client's Position
        float pPos[3]; //Ground Particle Target Position
        float sPos[3]; //Sign/Arrow's Target Position
        float rPos[3];
        float fVelocity[3]; //Velocity for teleporting entities, used for angles as well so we don't need two vectors.
        int iAirParticle = FindEntityByTargetname("FB.TankBuster.AirParticle", "func_brush");
        int iBuster = FindEntityByTargetname("FB.TankBuster", "trigger_hurt");
        int iExploParticle = FindEntityByTargetname("FB.TankBuster.ExplodeParticle", "info_particle_system");
        int iParticle = FindEntityByTargetname("FB.TankBuster.GroundParticle", "info_particle_system");
        int iSign = FindEntityByTargetname("FB.TankBuster.Sign", "func_rotating");
        int iSpin = FindEntityByTargetname("FB.TankBuster.Spinner", "func_rotating");
        GetClientAbsOrigin(this.bustTarget, cPos);
        rPos[0] = cPos[0];
        rPos[1] = cPos[1];
        rPos[2] = cPos[2] + 50.0;
        pPos[0] = cPos[0];
        pPos[1] = cPos[1];
        pPos[2] = cPos[2] + 25.0;
        sPos[0] = cPos[0];
        sPos[1] = cPos[1];
        sPos[2] = cPos[2] + 150.0;
        TeleportEntity(iAirParticle, rPos, fVelocity, fVelocity);
        TeleportEntity(iParticle, pPos, fVelocity, fVelocity);
        TeleportEntity(iExploParticle, pPos, fVelocity, fVelocity);
        TeleportEntity(iBuster, cPos, fVelocity, fVelocity);
        TeleportEntity(iSign, sPos, fVelocity, fVelocity); 
        TeleportEntity(iSpin, pPos, fVelocity, fVelocity);
    }
    //Tick client post
    void TickForClient(int client){
        float cPos[3];
        GetClientAbsOrigin(client, cPos);
        if(GetVectorDistance(cPos, this.fPos) < 500 && client == GetEmnityMax() && this.bDoTankBuster){
            char sDamage[32];
            this.bustTarget = client;
            this.bDoTankBuster = false;
            int iHealth = GetClientHealth(this.bustTarget);
            Format(sDamage, sizeof(sDamage), "damage %i", RoundToFloor(iHealth * 0.65));
            FastFire2("FB.TankBuster", "AddOutput", sDamage, 0.0, false);
            FastFire2("FB.TankBusterSND", "PlaySound", "", 1.25, false);
            FastFire2("FB.TankBuster.GroundParticle", "Start", "", 0.0, false);
            FastFire2("FB.TankBuster.ExplodeSND", "PlaySound", "", 5.50, false);
            FastFire2("FB.TankBuster.ExplodeParticle", "Start", "", 5.75, false);
            FastFire2("FB.TankBuster.ExplodeParticle", "Stop", "", 9.0, false);
            FastFire2("FB.TankBuster", "Enable", "", 5.75, false);
            FastFire2("FB.TankBuster", "Disable", "", 6.0, false);
            CreateTimer(1.0, StartTickBuster);
            PrintToServer("Dropping a tank buster on %N, they have %i HP, the tank buster will do %s.", this.bustTarget, iHealth, sDamage);
            CreateTimer(7.0, ResetTickBuster);
        }
    }
    // Tank buster - Potato cannon edition!
    void TickBusterNuclear(){
        float cPos[3]; //Client's Position
        float pPos[3]; //Ground Particle Target Position
        float sPos[3]; //Sign/Arrow's Target Position
        float rPos[3];
        float nPos[3];
        float fVelocity[3]; //Velocity for teleporting entities, used for angles as well so we don't need two vectors.
        int iAirParticle = FindEntityByTargetname("FB.TankBuster.AirParticle", "func_brush");
        int iBuster = FindEntityByTargetname("FB.TankBuster", "trigger_hurt");
        int iExploParticle = FindEntityByTargetname("FB.TankBuster.ExplodeParticle", "info_particle_system");
        int iParticle = FindEntityByTargetname("FB.TankBuster.GroundParticle", "info_particle_system");
        int iSign = FindEntityByTargetname("FB.TankBuster.Sign", "func_rotating");
        int iSpin = FindEntityByTargetname("FB.TankBuster.Spinner", "func_rotating");
        int iNukeTemplate = FindEntityByTargetname("PL.NukeCart", "env_entity_maker");
        GetClientAbsOrigin(this.bustNukeTarget, cPos);
        rPos[0] = cPos[0];
        rPos[1] = cPos[1];
        rPos[2] = cPos[2] + 50.0;
        pPos[0] = cPos[0];
        pPos[1] = cPos[1];
        pPos[2] = cPos[2] + 25.0;
        sPos[0] = cPos[0];
        sPos[1] = cPos[1];
        sPos[2] = cPos[2] + 150.0;
        nPos[0] = cPos[0];
        nPos[1] = cPos[1];
        nPos[2] = cPos[2] + 750.0;
        TeleportEntity(iAirParticle, rPos, fVelocity, fVelocity);
        TeleportEntity(iParticle, pPos, fVelocity, fVelocity);
        TeleportEntity(iExploParticle, pPos, fVelocity, fVelocity);
        TeleportEntity(iBuster, cPos, fVelocity, fVelocity);
        TeleportEntity(iSign, sPos, fVelocity, fVelocity); 
        TeleportEntity(iSpin, pPos, fVelocity, fVelocity);
        TeleportEntity(iNukeTemplate, nPos, fVelocity, fVelocity);
    }
    //Boss was slain
    void TriggerDeath(){
        this.shouldTick = false;
        this.tickBuster = false;
        this.iBossPhase = 0;
        switch(this.bossID){
            //Onslaughter lost
            case 0: {

            }
            //Sephiroth lost
            case 1:{

            }
            //Metal Face lost
            case 2:{
                FastFire2("FB.MetalFace.Train", "TeleportToPathTrack", "MFTHOME", 0.0, false);
            }
        }
    }
    //Boss reached bomb hatch
    void TriggerVictory(){
        this.shouldTick = false;
        this.tickBuster = false;
        float bossOrigin[3];
        float targetOrigin[3];
        int targetEnt = FindEntityByTargetname("capturezone_blue", "func_capturezone");
        GetEntPropVector(targetEnt, Prop_Send, "m_vecOrigin", targetOrigin);
        switch(this.bossID){
            //Onslaughter Won
            case 0:{
                int bossEnt = FindEntityByTargetname("FB.MetalBase", "base_boss");
                if(bossEnt == -1) return;
                GetEntPropVector(bossEnt, Prop_Send, "m_vecOrigin", bossOrigin);
                if (GetVectorDistance(bossOrigin, targetOrigin) < 2200){
                    //Do something here because Onslaughter is at the pit, victory for boss.
                }
            }
            //Sephiroth Won
            case 1:{

            }
            //Metallizer Won
            case 2:{
                int bossEnt = FindEntityByTargetname("FB.MetalBase", "base_boss");
                if(bossEnt == -1) return;
                GetEntPropVector(bossEnt, Prop_Send, "m_vecOrigin", bossOrigin);
                if (GetVectorDistance(bossOrigin, targetOrigin) < 2200){
                    //Do something here because Metal Face is at the pit, victory for boss.
                }
            }
        }
    }
    //Spawn the boi
    void TriggerSpawn(int boss){
        this.bossID = boss;
        this.shouldTick = true;
        switch(boss){
            case 0:{

            }
            case 1:{

            }
            case 2:{
                this.EmitSpawnSound(2);
                FastFire2("FB.MetalFace.Train", "TeleportToPathTrack", "MFT0x0", 1.0, false);
                FastFire2("FB.MetalFace.SpawnParticle", "Start", "", 1.0, false);
                FastFire2("FB.MetalFace.Train", "SetSpeedReal", "1024", 1.0, false);
                //switch(GetClientCount(true))
                FastFire2("FB.MetalBase", "AddOutput", "health 320000", 0.0, false);
            }
        }
    }
}
BOSSHANDLER BossHandler;
BOSSHANDLER Get_Boss_Handler() {
  return BossHandler;
}
//Player specific async tick process
public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3], float angles[3], int &weapon){
  if (BossHandler.shouldTick) BossHandler.TickForClient(client);
  return Plugin_Continue;
}

stock int SuggestEmnityThreshold(){
    switch(GetClientCount(true)){
        case 1:{
            return 75;
        }
        case 2:{
            return 60;
        }
        case 3:{
            return 50;
        }
        case 4:{
            return 35;
        }
        case 5:{
            return 25;
        }
        case 6:{
            return 20;
        }
        case 7:{
            return 15;
        }
        case 8,9,10:{
            return 10;
        }
    }
    return -1;
}
//Used for emitting boss sounds
public Action QueueBossSound(Handle timer, int sound){
    AssLogger(LOGLVL_DEBUG, "QueueBossSound played %i", sound);
    switch(sound){
        case 2:{ 
        }
        case 10:{
            CustomSoundEmitter(SFXArray[71].realPath, 65, false, 0, 1.0, 100); //Interrupting
            CreateTimer(3.1, QueueBossSound, GetRandomInt(16,22));
        }
        case 11:{
            CustomSoundEmitter(SFXArray[69].realPath, 65, false, 0, 1.0, 100); //FunnyLooking
            CreateTimer(3.0, QueueBossSound, GetRandomInt(18, 21));
        }
        case 12:{
            CustomSoundEmitter(SFXArray[75].realPath, 65, false, 0, 1.0, 100); //Racket
            CreateTimer(3.2, QueueBossSound, GetRandomInt(16, 22));
        }
        case 13:{
            CustomSoundEmitter(SFXArray[78].realPath, 65, false, 0, 1.0, 100); //WhatDoing
        }
        case 14:{
            CustomSoundEmitter(SFXArray[79].realPath, 65, false, 0, 1.0, 100); //WhateverDoing
            CreateTimer(4.3, QueueBossSound, GetRandomInt(16,17));
        }
        case 15:{
            CustomSoundEmitter(SFXArray[72].realPath, 65, false, 0, 1.0, 100); //Join In
            CreateTimer(3.2, QueueBossSound, 16);
        }
        //pt 2
        case 16:{
            CustomSoundEmitter(SFXArray[70].realPath, 65, false, 0, 1.0, 100); //Good show
        }
        case 17:{
            CustomSoundEmitter(SFXArray[67].realPath, 65, false, 0, 1.0, 100); //Carryon
        }
        case 18:{
            CustomSoundEmitter(SFXArray[66].realPath, 65, false, 0, 1.0, 100); //Carnage
        }
        case 19:{
            CustomSoundEmitter(SFXArray[73].realPath, 65, false, 0, 1.0, 100); //Lets Start
        }
        case 20:{
            CustomSoundEmitter(SFXArray[74].realPath, 65, false, 0, 1.0, 100); //Make Way
        }
        //Attack sounds, but also shared with spawn sounds
        case 21:{
            CustomSoundEmitter(SFXArray[76].realPath, 65, false, 0, 1.0, 100); //SliceYou
        }
        case 22:{
            CustomSoundEmitter(SFXArray[77].realPath, 65, false, 0, 1.0, 100); //Stroll
        }
        //Attack sounds, used for random grunts
        case 23:{
            CustomSoundEmitter(SFXArray[80].realPath, 65, false, 0, 1.0, 100); //gah
        }
        case 24:{
            CustomSoundEmitter(SFXArray[81].realPath, 65, false, 0, 1.0, 100); //guh
        }
        case 25:{
            CustomSoundEmitter(SFXArray[82].realPath, 65, false, 0, 1.0, 100); //hah
        }
        //Defeats
        case 26:{
            CustomSoundEmitter(SFXArray[83].realPath, 65, false, 0, 1.0, 100); //BadSide
        }
        case 27:{
            CustomSoundEmitter(SFXArray[84].realPath, 65, false, 0, 1.0, 100); //NotFair
        }
        case 28:{
            CustomSoundEmitter(SFXArray[85].realPath, 65, false, 0, 1.0, 100); //Nothing
        }
        case 29:{
            CustomSoundEmitter(SFXArray[86].realPath, 65, false, 0, 1.0, 100); //Scream
        }
        case 30:{
            CustomSoundEmitter(SFXArray[87].realPath, 65, false, 0, 1.0, 100); //ToGo
        }
        //Special attack sounds like phase changes
        case 31:{
            CustomSoundEmitter(SFXArray[88].realPath, 65, false, 0, 1.0, 100); //Clever
        }
        case 32:{
            CustomSoundEmitter(SFXArray[89].realPath, 65, false, 0, 1.0, 100); //Cmon
        }
        case 33:{
            CustomSoundEmitter(SFXArray[90].realPath, 65, false, 0, 1.0, 100); //Die
        }
        case 34:{
            CustomSoundEmitter(SFXArray[91].realPath, 65, false, 0, 1.0, 100); //GetOff
        }
        case 35:{
            CustomSoundEmitter(SFXArray[92].realPath, 65, false, 0, 1.0, 100); //HearYouScream
        }
        case 36:{
            CustomSoundEmitter(SFXArray[93].realPath, 65, false, 0, 1.0, 100); //IsntOver
        }
        case 37:{
            CustomSoundEmitter(SFXArray[94].realPath, 65, false, 0, 1.0, 100); //Like
        }
        case 38:{
            CustomSoundEmitter(SFXArray[95].realPath, 65, false, 0, 1.0, 100); //Little
        }
        case 39:{
            CustomSoundEmitter(SFXArray[96].realPath, 65, false, 0, 1.0, 100); //Pay
        }
        case 40:{
            CustomSoundEmitter(SFXArray[97].realPath, 65, false, 0, 1.0, 100); //Pointers
        }
        case 41:{
            CustomSoundEmitter(SFXArray[98].realPath, 65, false, 0, 1.0, 100); //Seat
        }
        case 42:{
            CustomSoundEmitter(SFXArray[99].realPath, 65, false, 0, 1.0, 100); //Size
        }
        case 43:{
            CustomSoundEmitter(SFXArray[100].realPath, 65, false, 0, 1.0, 100); //There
        }
        case 44:{
            CustomSoundEmitter(SFXArray[101].realPath, 65, false, 0, 1.0, 100); //TimeToDie
        }
        case 45:{
            CustomSoundEmitter(SFXArray[102].realPath, 65, false, 0, 1.0, 100); //Way
        }
        //Ultimates
        case 46:{
            CustomSoundEmitter(SFXArray[103].realPath, 65, false, 0, 1.0, 100); //FinalWords
        }
        case 47:{
            CustomSoundEmitter(SFXArray[104].realPath, 65, false, 0, 1.0, 100); //PartingGift
        }
        case 48:{
            CustomSoundEmitter(SFXArray[105].realPath, 65, false, 0, 1.0, 100); //WatchAndLearn
        }
    }
    return Plugin_Stop;
}
//Teleport all entities to the client every frame
public Action StartTickBuster(Handle timer){
    BossHandler.tickBuster = true;
    return Plugin_Stop;
}
//Used for stopping tank busters from ticking
public Action ResetTickBuster(Handle time){
    BossHandler.tickBuster = false;
    float fAirPart[3] = {
        -1437.270019,
        -3906.739990,
        -1334.989990
    };
    float fVelocity[3];
    int iAirParticle = FindEntityByTargetname("FB.TankBuster.AirParticle", "func_brush");
    int iBuster = FindEntityByTargetname("FB.TankBuster", "trigger_hurt");
    int iExploParticle = FindEntityByTargetname("FB.TankBuster.ExplodeParticle", "info_particle_system");
    int iParticle = FindEntityByTargetname("FB.TankBuster.GroundParticle", "info_particle_system");
    int iSign = FindEntityByTargetname("FB.TankBuster.Sign", "func_rotating");
    int iSpin = FindEntityByTargetname("FB.TankBuster.Spinner", "func_rotating");
    TeleportEntity(iAirParticle, fAirPart, fVelocity, fVelocity);
    TeleportEntity(iParticle, fAirPart, fVelocity, fVelocity);
    TeleportEntity(iExploParticle, fAirPart, fVelocity, fVelocity);
    TeleportEntity(iBuster, fAirPart, fVelocity, fVelocity);
    TeleportEntity(iSign, fAirPart, fVelocity, fVelocity); 
    TeleportEntity(iSpin, fAirPart, fVelocity, fVelocity);
    return Plugin_Stop;
}

//Spawn metal face
public Action DelayedMetalFace(Handle timer){
    AudioManager.indexBGM = 20;
    AudioManager.stopBGM = true;
    CustomSoundEmitter(SFXArray[68].realPath, 65, false, 0, 1.0, 100); //Evil Laugh
    CreateTimer(3.2, QueueBossSound, GetRandomInt(10,14));
    sudo(1000);
    BossHandler.shouldTickBGM = true;
    return Plugin_Stop;
}