Files
SMScripts/scripting/include/fartsy/ass_bosshandler.inc

601 lines
26 KiB
PHP
Raw Normal View History

2025-04-15 22:27:20 -04:00
// 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;
2025-04-15 22:27:20 -04:00
bool tickBuster;
bool tickBusterNuclear;
2025-04-15 22:27:20 -04:00
float fAng[3];
float fPos[3];
int bustTarget;
int bustNukeTarget;
2025-04-15 22:27:20 -04:00
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);
GlobalAudio.Stop();
GlobalAudio.setBGM(20, true);
2025-04-15 22:27:20 -04:00
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);
2025-04-15 22:27:20 -04:00
}
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);
2025-04-23 07:50:24 -04:00
FastFire2("FB.MetalFace", "Enable", "", 0.0, false);
2025-04-15 22:27:20 -04:00
}
case 2:{
//PrintToChatAll("Recognized 1 -> 2, things are heating up!");
GlobalAudio.setBGM(22, false);
2025-04-15 22:27:20 -04:00
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");
GlobalAudio.setBGM(24, false);
2025-04-15 22:27:20 -04:00
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");
GlobalAudio.setBGM(26, true);
2025-04-15 22:27:20 -04:00
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);
}
}
}
}
2025-04-15 22:27:20 -04:00
}
}
//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);
}
}
GlobalAudio.setBGM(iBGM0, false);
2025-04-15 22:27:20 -04:00
}
}
//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);
}
2025-04-15 22:27:20 -04:00
//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;
}
2025-04-15 22:27:20 -04:00
//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){
GlobalAudio.setBGM(20, true);
2025-04-15 22:27:20 -04:00
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;
}