Jump to content
  • Announcements

    • Xmat

      Pravidlo pro postování v TTT

      Do sekce Tipy, triky, tutoriály nepatří žádné dotazy.   Postujte sem vaše návody, tipy a různé další věci jež uznáte za vhodné sdělit zdejšímu osazenstvu, ale veškeré dotazy směřujte do sekce Všeobecná diskuse.
    • Replik

      Seznam návodů a důležitých témat v této sekci

      Pro lepší přehlednost jsem vytvořil tento seznam, který vás, méně zkušené, lépe provede touto sekcí. Věřím, že zde najdete, co hledáte. Vypsané jsou návody, které jsou oficiálně uznané jako návody. Běžné diskuze, které neposkytují postupy a rady zvěřejněny nejsou.   Instalace vlastního MaNGOS Serveru Díky těmto návodům budete (měli by jste být) schopni vytvořit a následně spustit váš vlastní server. Nastavení je pro verze s i bez datadisku.   Instalace MaNGOS Serveru (bez datadisku TBC) - Autor Benny Instalace MaNGOS Serveru (s datadiskem TBC) - Autor Malfik Instalace MaNGOS Serveru v prostředí Linux - Autor charlie Instalace MaNGOS Serveru v prostředí Linux - Autor kupkoid   Chyby a jejich řešení při přihlašování k serveru - Autor Cybe   Zálohování uživatelských dat   Dávkový soubor (BAT soubor) pro vytvoření SQL záloh - Autor Replik   Kompilování - tvoření vlastních release (revizí)   Tvorba kompilací pro Win32 (MangoScript) - Autor bLuma   Ostatní - těžko zařaditelné, ale neznamená to, že nejsou dobré   VIP Systém - Autor charlie Tvorba Webových stránek pro MaNGOS - Autor zahuba Tvorba teleportačních NPC (MangoScript) - Autor Replik Registrační web (původně předělaná SPORA) Funkční pro Antrix i MaNGOS - Autor Replik Nastavení a spuštění Minimanager pro MaNGOS - Autor BlackMartin Nastavení MaNGOS Website - Autor Artorius   Samozřejmě jsou zde i jiné návody, ale tyto jsou nejvíce používané, proto věřím, že vám budou nápomocné. Tuto sekci budeme upravovat podle potřeby. Pokud by jste něco nenašli nebo si nevěděli rady, hledejte na fóru a teprve potom založte vlastní topik. Pokud nějaký autor vytvoří kvalitní návod a chtěl by ho zveřejnit i v tomto seznamu, doporučuji, aby mi napsal zprávu skrze PM.   Díky a přeji hezký den na WoWResource   Replik
    • Aristo

      Příspěvky tam, kde nemají co dělat

      Dodržujte zákaz přispívání do topiků s repaky pokud si to zakladatelé nepřejí!! Opakované psaní příspěvků bude trestáno warnem.
    • Aristo

      Používání spoilerů

      Poslední dobou má většina uživatelů fora zvláštní nutkání postovat extrémně dlouhé texty nebo kódy, které zabírají v nejedenom případu i 80% obsahu celé stránky a hodně tak zvedají nepřehlednost v topiku. Chtěl bych všechny uživatele požádat, aby při postování citací, jakýchkoliv kódů, errorů, atp... delších než 30 řádků používali funkci spoileru.   Funkci vyvoláte příkazem [spoiler] text [/spoiler]   Ukázka:  
Sign in to follow this  
Tort

Scripty

Recommended Posts

Prosím vás nemá tu niekdo z váš funkčné scripty bosov v BT ? Konkrétne ide o bosov -> Shade of Akama a Bloodboil. Reviziu mám 1223+. Ďakujem.

Share this post


Link to post
Share on other sites

Shade of akama

 

#include "ScriptPCH.h"
#include "black_temple.h"

#define SAY_DEATH                   -1564013
#define SAY_LOW_HEALTH              -1564014
// Ending cinematic text
#define SAY_FREE                    -1564015
#define SAY_BROKEN_FREE_01          -1564016
#define SAY_BROKEN_FREE_02          -1564017

#define GOSSIP_ITEM                 "We are ready to fight alongside you, Akama"

struct Location
{
   float x, y, o, z;
};

/* Not used
static Location ChannelerLocations[]=
{
   {463.161285f, 401.219757f, 3.141592f, 0.0f},
   {457.377625f, 391.227661f, 2.106461f, 0.0f},
   {446.012421f, 391.227661f, 1.071904f, 0.0f},
   {439.533783f, 401.219757f, 0.000000f, 0.0f},
   {446.012421f, 411.211853f, 5.210546f, 0.0f},
   {457.377625f, 411.211853f, 4.177494f, 0.0f}
};
*/

static Location SpawnLocations[]=
{
   {498.652740f, 461.728119f, 0.0f, 0.0f},
   {498.505003f, 339.619324f, 0.0f, 0.0f}
};

static Location AkamaWP[]=
{
   {482.352448f, 401.162720f, 0.0f, 112.783928f},
   {469.597443f, 402.264404f, 0.0f, 118.537910f}
};

static Location BrokenCoords[]=
{
   {541.375916f, 401.439575f, M_PI, 112.783997f},             // The place where Akama channels
   {534.130005f, 352.394531f, 2.164150f, 112.783737f},         // Behind a 'pillar' which is behind the east alcove
   {499.621185f, 341.534729f, 1.652856f, 112.783730f},         // East Alcove
   {499.151093f, 461.036438f, 4.770888f, 112.78370f},          // West Alcove
};

static Location BrokenWP[]=
{
   {492.491638f, 400.744690f, 3.122336f, 112.783737f},
   {494.335724f, 382.221771f, 2.676230f, 112.783737f},
   {489.555939f, 373.507202f, 2.416263f, 112.783737f},
   {491.136353f, 427.868774f, 3.519748f, 112.783737f},
};

// Locations
#define Z1              118.543144f
#define Z2              120.783768f
#define Z_SPAWN         113.537949f
#define AGGRO_X         482.793182f
#define AGGRO_Y         401.270172f
#define AGGRO_Z         112.783928f
#define AKAMA_X         514.583984f
#define AKAMA_Y         400.601013f
#define AKAMA_Z         112.783997f

// Spells
#define SPELL_VERTEX_SHADE_BLACK    39833
#define SPELL_SHADE_SOUL_CHANNEL    40401
#define SPELL_DESTRUCTIVE_POISON    40874
#define SPELL_LIGHTNING_BOLT        42024
#define SPELL_AKAMA_SOUL_CHANNEL    40447
#define SPELL_AKAMA_SOUL_RETRIEVE   40902
#define AKAMA_SOUL_EXPEL            40855
#define SPELL_SHADE_SOUL_CHANNEL_2  40520

// Channeler entry
#define CREATURE_CHANNELER          23421
#define CREATURE_SORCERER           23215
#define CREATURE_DEFENDER           23216
#define CREATURE_BROKEN             23319

const uint32 spawnEntries[4]= { 23523, 23318, 23524 };

class mob_ashtongue_channeler : public CreatureScript
{
public:
   mob_ashtongue_channeler() : CreatureScript("mob_ashtongue_channeler") { }

   CreatureAI* GetAI(Creature* pCreature) const
   {
       return new mob_ashtongue_channelerAI (pCreature);
   }

   struct mob_ashtongue_channelerAI : public ScriptedAI
   {
       mob_ashtongue_channelerAI(Creature* c) : ScriptedAI(c) {ShadeGUID = 0;}

       uint64 ShadeGUID;

       void Reset() {}
       void JustDied(Unit* /*killer*/);
       void EnterCombat(Unit* /*who*/) {}
       void AttackStart(Unit* /*who*/) {}
       void MoveInLineOfSight(Unit* /*who*/) {}
       void UpdateAI(const uint32 /*diff*/) {}
   };

};

class mob_ashtongue_sorcerer : public CreatureScript
{
public:
   mob_ashtongue_sorcerer() : CreatureScript("mob_ashtongue_sorcerer") { }

   CreatureAI* GetAI(Creature* pCreature) const
   {
       return new mob_ashtongue_sorcererAI (pCreature);
   }

   struct mob_ashtongue_sorcererAI : public ScriptedAI
   {
       mob_ashtongue_sorcererAI(Creature* c) : ScriptedAI(c) {ShadeGUID = 0;}

       uint64 ShadeGUID;
       uint32 CheckTimer;
       bool StartBanishing;

       void Reset()
       {
           StartBanishing = false;
           CheckTimer = 5000;
       }

       void JustDied(Unit* /*killer*/);
       void EnterCombat(Unit* /*who*/) {}
       void AttackStart(Unit* /*who*/) {}
       void MoveInLineOfSight(Unit* /*who*/) {}
       void UpdateAI(const uint32 diff)
       {
           if (StartBanishing)
               return;

           if (CheckTimer <= diff)
           {
               Creature* Shade = Unit::GetCreature((*me), ShadeGUID);
               if (Shade && Shade->isAlive() && me->isAlive())
               {
                   if (me->IsWithinDist(Shade, 20,false))
                   {
                       me->GetMotionMaster()->Clear(false);
                       me->GetMotionMaster()->MoveIdle();
                       DoCast(Shade, SPELL_SHADE_SOUL_CHANNEL, true);
                       DoCast(Shade, SPELL_SHADE_SOUL_CHANNEL_2, true);

                       StartBanishing = true;
                   }
               }
               CheckTimer = 2000;
           } else CheckTimer -= diff;
       }
   };

};

class boss_shade_of_akama : public CreatureScript
{
public:
   boss_shade_of_akama() : CreatureScript("boss_shade_of_akama") { }

   CreatureAI* GetAI(Creature* pCreature) const
   {
       return new boss_shade_of_akamaAI (pCreature);
   }

   struct boss_shade_of_akamaAI : public ScriptedAI
   {
       boss_shade_of_akamaAI(Creature* c) : ScriptedAI(c), summons(me)
       {
           pInstance = c->GetInstanceScript();
           AkamaGUID = pInstance ? pInstance->GetData64(DATA_AKAMA_SHADE) : 0;
           me->setActive(true);//if view distance is too low
           me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true);
           me->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, true);
       }

       InstanceScript* pInstance;

       std::list<uint64> Channelers;
       std::list<uint64> Sorcerers;
       uint64 AkamaGUID;

       uint32 SorcererCount;
       uint32 DeathCount;

       uint32 ReduceHealthTimer;
       uint32 SummonTimer;
       uint32 ResetTimer;
       uint32 DefenderTimer;                                   // They are on a flat 15 second timer, independant of the other summon Creature timer.

       bool IsBanished;
       bool HasKilledAkama;
       bool reseting;
       bool GridSearcherSucceeded;
       bool HasKilledAkamaAndReseting;
       SummonList summons;

       void Reset()
       {
           reseting = true;
           HasKilledAkamaAndReseting = false;

           GridSearcherSucceeded = false;

           Sorcerers.clear();
           summons.DespawnAll();//despawn all adds

           if (Creature* Akama = Unit::GetCreature(*me, AkamaGUID))
           {
               Akama->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);//turn gossip on so players can restart the event
               if (Akama->isDead())
               {
                   Akama->Respawn();//respawn akama if dead
                   Akama->AI()->EnterEvadeMode();
               }
           }
           SorcererCount = 0;
           DeathCount = 0;

           SummonTimer = 10000;
           ReduceHealthTimer = 0;
           ResetTimer = 60000;
           DefenderTimer = 15000;

           IsBanished = true;
           HasKilledAkama = false;

           me->SetVisible(true);
           me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
           me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
           //me->GetMotionMaster()->Clear();
           //me->GetMotionMaster()->MoveIdle();
           me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_STUN);

           if (pInstance)
               pInstance->SetData(DATA_SHADEOFAKAMAEVENT, NOT_STARTED);

           reseting = false;
       }
       void JustDied(Unit* /*killer*/)
       {
           summons.DespawnAll();
       }
       void JustSummoned(Creature *summon)
       {
           if (summon->GetEntry() == CREATURE_DEFENDER || summon->GetEntry() == 23523 || summon->GetEntry() == 23318 || summon->GetEntry() == 23524)
               summons.Summon(summon);
       }
       void SummonedCreatureDespawn(Creature *summon)
       {
           if (summon->GetEntry() == CREATURE_DEFENDER || summon->GetEntry() == 23523 || summon->GetEntry() == 23318 || summon->GetEntry() == 23524)
               summons.Despawn(summon);
       }

       void MoveInLineOfSight(Unit * /*who*/)
       {
           if (!GridSearcherSucceeded)
           {
               FindChannelers();

               if (!Channelers.empty())
               {
                   for (std::list<uint64>::const_iterator itr = Channelers.begin(); itr != Channelers.end(); ++itr)
                   {
                       Creature* Channeler = (Unit::GetCreature(*me, *itr));
                       if (Channeler)
                       {
                           if (Channeler->isDead())
                           {
                               Channeler->RemoveCorpse();
                               Channeler->Respawn();
                           }

                           Channeler->CastSpell(me, SPELL_SHADE_SOUL_CHANNEL, true);
                           Channeler->CastSpell(me, SPELL_SHADE_SOUL_CHANNEL_2, true);
                           Channeler->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
                           GridSearcherSucceeded = true;
                       }
                   }
               } else sLog->outError("SD2 ERROR: No Channelers are stored in the list. This encounter will not work properly");
           }
       }

       void AttackStart(Unit* who)
       {
           if (!who || IsBanished) return;

           if (who->isTargetableForAttack() && who != me)
               DoStartMovement(who);
       }

       void IncrementDeathCount(uint64 guid = 0)               // If guid is set, will remove it from list of sorcerer
       {
           if (reseting)
               return;

           sLog->outDebug(LOG_FILTER_TSCR, "TSCR: Increasing Death Count for Shade of Akama encounter");
           ++DeathCount;
           me->RemoveAuraFromStack(SPELL_SHADE_SOUL_CHANNEL_2);
           if (guid)
           {
               if (Sorcerers.empty())
                   sLog->outError("SD2 ERROR: Shade of Akama - attempt to remove guid " UI64FMTD " from Sorcerers list but list is already empty", guid);
               else  Sorcerers.remove(guid);
           }
       }

       void SummonCreature()
       {
           uint32 random = rand()%2;
           float X = SpawnLocations[random].x;
           float Y = SpawnLocations[random].y;
           // max of 6 sorcerers can be summoned
           if ((rand()%3 == 0) && (DeathCount > 0) && (SorcererCount < 7))
           {
               Creature* Sorcerer = me->SummonCreature(CREATURE_SORCERER, X, Y, Z_SPAWN, 0, TEMPSUMMON_DEAD_DESPAWN, 0);
               if (Sorcerer)
               {
                   CAST_AI(mob_ashtongue_sorcerer::mob_ashtongue_sorcererAI, Sorcerer->AI())->ShadeGUID = me->GetGUID();
                   Sorcerer->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
                   Sorcerer->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ());
                   Sorcerer->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID());
                   Sorcerers.push_back(Sorcerer->GetGUID());
                   --DeathCount;
                   ++SorcererCount;
               }
           }
           else
           {
               for (uint8 i = 0; i < 3; ++i)
               {
                   Creature* Spawn = me->SummonCreature(spawnEntries[i], X, Y, Z_SPAWN, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 25000);
                   if (Spawn)
                   {
                       Spawn->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
                       Spawn->GetMotionMaster()->MovePoint(0, AGGRO_X, AGGRO_Y, AGGRO_Z);
                       Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1);
                       Spawn->AI()->AttackStart(pTarget);
                   }
               }
           }
       }

       void FindChannelers()
       {
           std::list<Creature*> ChannelerList;
           me->GetCreatureListWithEntryInGrid(ChannelerList,CREATURE_CHANNELER,50.0f);

           if (!ChannelerList.empty())
           {
               for (std::list<Creature*>::const_iterator itr = ChannelerList.begin(); itr != ChannelerList.end(); ++itr)
               {
                   CAST_AI(mob_ashtongue_channeler::mob_ashtongue_channelerAI, (*itr)->AI())->ShadeGUID = me->GetGUID();
                   Channelers.push_back((*itr)->GetGUID());
                   sLog->outDebug(LOG_FILTER_TSCR, "TSCR: Shade of Akama Grid Search found channeler " UI64FMTD ". Adding to list", (*itr)->GetGUID());
               }
           }
           else sLog->outError("SD2 ERROR: Grid Search was unable to find any channelers. Shade of Akama encounter will be buggy");
       }

       void SetSelectableChannelers()
       {
           if (Channelers.empty())
           {
               sLog->outError("SD2 ERROR: Channeler List is empty, Shade of Akama encounter will be buggy");
               return;
           }

           for (std::list<uint64>::const_iterator itr = Channelers.begin(); itr != Channelers.end(); ++itr)
               if (Creature* Channeler = (Unit::GetCreature(*me, *itr)))
                   Channeler->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
       }

       void SetAkamaGUID(uint64 guid) { AkamaGUID = guid; }

       void UpdateAI(const uint32 diff)
       {
           if (!me->isInCombat())
               return;

           if (IsBanished)
           {
               // Akama is set in the threatlist so when we reset, we make sure that he is not included in our check
               if (me->getThreatManager().getThreatList().size() < 2)
               {
                   EnterEvadeMode();
                   return;
               }

               if (DefenderTimer <= diff)
               {
                   uint32 ran = rand()%2;
                   Creature* Defender = me->SummonCreature(CREATURE_DEFENDER, SpawnLocations[ran].x, SpawnLocations[ran].y, Z_SPAWN, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 25000);
                   if (Defender)
                   {
                       Defender->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
                       bool move = true;
                       if (AkamaGUID)
                       {
                           if (Creature* Akama = Unit::GetCreature(*me, AkamaGUID))
                           {
                               float x, y, z;
                               Akama->GetPosition(x,y,z);
                               // They move towards AKama
                               Defender->GetMotionMaster()->MovePoint(0, x, y, z);
                               Defender->AI()->AttackStart(Akama);
                           } else move = false;
                       } else move = false;
                       if (!move)
                           Defender->GetMotionMaster()->MovePoint(0, AKAMA_X, AKAMA_Y, AKAMA_Z);
                   }
                   DefenderTimer = 15000;
               } else DefenderTimer -= diff;

               if (SummonTimer <= diff)
               {
                   SummonCreature();
                   SummonTimer = 35000;
               } else SummonTimer -= diff;

               if (DeathCount >= 6)
               {
                   if (AkamaGUID)
                   {
                       Creature* Akama = Unit::GetCreature((*me), AkamaGUID);
                       if (Akama && Akama->isAlive())
                       {
                           IsBanished = false;
                           me->GetMotionMaster()->Clear(false);
                           me->GetMotionMaster()->MoveChase(Akama);
                           Akama->GetMotionMaster()->Clear();
                           // Shade should move to Akama, not the other way around
                           Akama->GetMotionMaster()->MoveIdle();
                           me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
                           // Crazy amount of threat
                           me->AddThreat(Akama, 10000000.0f);
                           Akama->AddThreat(me, 10000000.0f);
                           me->Attack(Akama, true);
                           Akama->Attack(me, true);
                       }
                   }
               }
           }
           else                                                // No longer banished, let's fight Akama now
           {
               if (ReduceHealthTimer <= diff)
               {
                   if (AkamaGUID)
                   {
                       Creature* Akama = Unit::GetCreature((*me), AkamaGUID);
                       if (Akama && Akama->isAlive())
                       {
                           //10 % less health every few seconds.
                           me->DealDamage(Akama, Akama->GetMaxHealth()/10, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
                           ReduceHealthTimer = 12000;
                       }
                   }
               } else ReduceHealthTimer -= diff;

               if (HasKilledAkama)
               {
                   if (!HasKilledAkamaAndReseting)//do not let players kill Shade if Akama is dead and Shade is waiting for ResetTimer!! event would bug
                   {
                       HasKilledAkamaAndReseting = true;
                       me->RemoveAllAuras();
                       me->DeleteThreatList();
                       me->CombatStop();
                       //me->SetFullHealth();
                       me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
                       me->GetMotionMaster()->MoveTargetedHome();
                   }
                   if (ResetTimer <= diff)
                   {
                       EnterEvadeMode();// Reset a little while after killing Akama, evade and respawn Akama
                       return;
                   } else ResetTimer -= diff;
               }

               DoMeleeAttackIfReady();
           }
       }
   };

};

void mob_ashtongue_channeler::mob_ashtongue_channelerAI::JustDied(Unit* /*killer*/)
{
   Creature* Shade = (Unit::GetCreature((*me), ShadeGUID));
   if (Shade && Shade->isAlive())
       CAST_AI(boss_shade_of_akama::boss_shade_of_akamaAI, Shade->AI())->IncrementDeathCount();
   else sLog->outError("SD2 ERROR: Channeler dead but unable to increment DeathCount for Shade of Akama.");
}

void mob_ashtongue_sorcerer::mob_ashtongue_sorcererAI::JustDied(Unit* /*killer*/)
{
   Creature* Shade = (Unit::GetCreature((*me), ShadeGUID));
   if (Shade && Shade->isAlive())
       CAST_AI(boss_shade_of_akama::boss_shade_of_akamaAI, Shade->AI())->IncrementDeathCount(me->GetGUID());
   else sLog->outError("SD2 ERROR: Sorcerer dead but unable to increment DeathCount for Shade of Akama.");
}

class npc_akama_shade : public CreatureScript
{
public:
   npc_akama_shade() : CreatureScript("npc_akama_shade") { }

   bool OnGossipSelect(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction)
   {
       pPlayer->PlayerTalkClass->ClearMenus();
       if (uiAction == GOSSIP_ACTION_INFO_DEF + 1)               //Fight time
       {
           pPlayer->CLOSE_GOSSIP_MENU();
           CAST_AI(npc_akama_shade::npc_akamaAI, pCreature->AI())->BeginEvent(pPlayer);
       }

       return true;
   }

   bool OnGossipHello(Player* pPlayer, Creature* pCreature)
   {
       if (pPlayer->isAlive())
       {
           pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
           pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID());
       }

       return true;
   }

   CreatureAI* GetAI(Creature* pCreature) const
   {
       return new npc_akamaAI (pCreature);
   }

   struct npc_akamaAI : public ScriptedAI
   {
       npc_akamaAI(Creature* c) : ScriptedAI(c), summons(me)
       {
           ShadeHasDied = false;
           StartCombat = false;
           pInstance = c->GetInstanceScript();
           if (pInstance)
               ShadeGUID = pInstance->GetData64(DATA_SHADEOFAKAMA);
           else
               ShadeGUID = NOT_STARTED;
           me->setActive(true);
           EventBegun = false;
           CastSoulRetrieveTimer = 0;
           SoulRetrieveTimer = 0;
           SummonBrokenTimer = 0;
           EndingTalkCount = 0;
           WayPointId = 0;
           BrokenSummonIndex = 0;
           BrokenList.clear();
           HasYelledOnce = false;
       }

       InstanceScript* pInstance;

       uint64 ShadeGUID;

       uint32 DestructivePoisonTimer;
       uint32 LightningBoltTimer;
       uint32 CheckTimer;
       uint32 CastSoulRetrieveTimer;
       uint32 SoulRetrieveTimer;
       uint32 SummonBrokenTimer;
       uint32 EndingTalkCount;
       uint32 WayPointId;
       uint32 BrokenSummonIndex;

       std::list<uint64> BrokenList;

       bool EventBegun;
       bool ShadeHasDied;
       bool StartCombat;
       bool HasYelledOnce;
       SummonList summons;

       void Reset()
       {
           DestructivePoisonTimer = 15000;
           LightningBoltTimer = 10000;
           CheckTimer = 2000;

           if (!EventBegun)
           {
               me->SetUInt32Value(UNIT_NPC_FLAGS, 0);      // Database sometimes has very very strange values
               me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
           }
           summons.DespawnAll();
       }

       void JustSummoned(Creature *summon)
       {
           if (summon->GetEntry() == CREATURE_BROKEN)
               summons.Summon(summon);
       }
       void SummonedCreatureDespawn(Creature *summon)
       {
           if (summon->GetEntry() == CREATURE_BROKEN)
               summons.Despawn(summon);
       }

       void EnterCombat(Unit* /*who*/) {}

       void BeginEvent(Player* pl)
       {
           if (!pInstance)
               return;

           ShadeGUID = pInstance->GetData64(DATA_SHADEOFAKAMA);
           if (!ShadeGUID)
               return;

           Creature* Shade = (Unit::GetCreature((*me), ShadeGUID));
           if (Shade)
           {
               pInstance->SetData(DATA_SHADEOFAKAMAEVENT, IN_PROGRESS);
               // Prevent players from trying to restart event
               me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
               CAST_AI(boss_shade_of_akama::boss_shade_of_akamaAI, Shade->AI())->SetAkamaGUID(me->GetGUID());
               CAST_AI(boss_shade_of_akama::boss_shade_of_akamaAI, Shade->AI())->SetSelectableChannelers();
               Shade->AddThreat(me, 1000000.0f);
               me->CombatStart(Shade);
               Shade->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE);
               Shade->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID());
               if (pl) Shade->AddThreat(pl, 1.0f);
               DoZoneInCombat(Shade);
               EventBegun = true;
           }
       }

       void MovementInform(uint32 type, uint32 id)
       {
           if (type != POINT_MOTION_TYPE)
               return;

           switch(id)
           {
           case 0: ++WayPointId; break;

           case 1:
               if (Creature* Shade = Unit::GetCreature(*me, ShadeGUID))
               {
                   me->SetUInt64Value(UNIT_FIELD_TARGET, ShadeGUID);
                   DoCast(Shade, SPELL_AKAMA_SOUL_RETRIEVE);
                   EndingTalkCount = 0;
                   SoulRetrieveTimer = 16000;
               }
               break;
           }
       }

       void JustDied(Unit* /*killer*/)
       {
           DoScriptText(SAY_DEATH, me);
           EventBegun = false;
           ShadeHasDied = false;
           StartCombat = false;
           CastSoulRetrieveTimer = 0;
           SoulRetrieveTimer = 0;
           SummonBrokenTimer = 0;
           EndingTalkCount = 0;
           WayPointId = 0;
           BrokenSummonIndex = 0;
           BrokenList.clear();
           HasYelledOnce = false;
           Creature* Shade = Unit::GetCreature((*me), ShadeGUID);
           if (Shade && Shade->isAlive())
               CAST_AI(boss_shade_of_akama::boss_shade_of_akamaAI, Shade->AI())->HasKilledAkama = true;
           summons.DespawnAll();
       }

       void UpdateAI(const uint32 diff)
       {
           if (!EventBegun)
               return;

           if (HealthBelowPct(15) && !HasYelledOnce)
           {
               DoScriptText(SAY_LOW_HEALTH, me);
               HasYelledOnce = true;
           }

           if (ShadeGUID && !StartCombat)
           {
               Creature* Shade = (Unit::GetCreature((*me), ShadeGUID));
               if (Shade && Shade->isAlive())
               {
                   if (CAST_AI(boss_shade_of_akama::boss_shade_of_akamaAI, Shade->AI())->IsBanished)
                   {
                       if (CastSoulRetrieveTimer <= diff)
                       {
                           DoCast(Shade, SPELL_AKAMA_SOUL_CHANNEL);
                           CastSoulRetrieveTimer = 500;
                       } else CastSoulRetrieveTimer -= diff;
                   }
                   else
                   {
                       me->InterruptNonMeleeSpells(false);
                       StartCombat = true;
                   }
               }
           }

           if (ShadeHasDied && (WayPointId == 1))
           {
               if (pInstance)
                   pInstance->SetData(DATA_SHADEOFAKAMAEVENT, DONE);
               me->GetMotionMaster()->MovePoint(WayPointId, AkamaWP[1].x, AkamaWP[1].y, AkamaWP[1].z);
               ++WayPointId;
           }

           if (!ShadeHasDied && StartCombat)
           {
               if (CheckTimer <= diff)
               {
                   if (ShadeGUID)
                   {
                       Creature* Shade = Unit::GetCreature((*me), ShadeGUID);
                       if (Shade && !Shade->isAlive())
                       {
                           ShadeHasDied = true;
                           WayPointId = 0;
                           me->AddUnitMovementFlag(MOVEMENTFLAG_WALKING);
                           me->GetMotionMaster()->MovePoint(WayPointId, AkamaWP[0].x, AkamaWP[0].y, AkamaWP[0].z);
                       }
                       if (Shade && Shade->isAlive())
                       {
                           if (Shade->getThreatManager().getThreatList().size() < 2)
                               Shade->AI()->EnterEvadeMode();
                       }
                   }
                   CheckTimer = 5000;
               } else CheckTimer -= diff;
           }

           if (SummonBrokenTimer && BrokenSummonIndex < 4)
           {
               if (SummonBrokenTimer <= diff)
               {
                   for (uint8 i = 0; i < 4; ++i)
                   {
                       float x = BrokenCoords[brokenSummonIndex].x + (i*5);
                       float y = BrokenCoords[brokenSummonIndex].y + (1*5);
                       float z = BrokenCoords[brokenSummonIndex].z;
                       float o = BrokenCoords[brokenSummonIndex].o;
                       Creature* Broken = me->SummonCreature(CREATURE_BROKEN, x, y, z, o, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 360000);
                       if (Broken)
                       {
                           float wx = BrokenWP[brokenSummonIndex].x + (i*5);
                           float wy = BrokenWP[brokenSummonIndex].y + (i*5);
                           float wz = BrokenWP[brokenSummonIndex].z;
                           Broken->GetMotionMaster()->MovePoint(0, wx, wy, wz);
                           Broken->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
                           BrokenList.push_back(Broken->GetGUID());
                       }
                   }
                   ++BrokenSummonIndex;
                   SummonBrokenTimer = 1000;
               } else SummonBrokenTimer -= diff;
           }

           if (SoulRetrieveTimer)
           {
               if (SoulRetrieveTimer <= diff)
               {
                   switch(EndingTalkCount)
                   {
                   case 0:
                       me->HandleEmoteCommand(EMOTE_ONESHOT_ROAR);
                       ++EndingTalkCount;
                       SoulRetrieveTimer = 2000;
                       SummonBrokenTimer = 1;
                       break;
                   case 1:
                       DoScriptText(SAY_FREE, me);
                       ++EndingTalkCount;
                       SoulRetrieveTimer = 25000;
                       break;
                   case 2:
                       if (!BrokenList.empty())
                       {
                           bool Yelled = false;
                           for (std::list<uint64>::const_iterator itr = BrokenList.begin(); itr != BrokenList.end(); ++itr)
                               if (Creature* pUnit = Unit::GetCreature(*me, *itr))
                               {
                                   if (!Yelled)
                                   {
                                       DoScriptText(SAY_BROKEN_FREE_01, pUnit);
                                       Yelled = true;
                                   }
                                   pUnit->HandleEmoteCommand(EMOTE_ONESHOT_KNEEL);
                               }
                       }
                       ++EndingTalkCount;
                       SoulRetrieveTimer = 1500;
                       break;
                   case 3:
                       if (!BrokenList.empty())
                       {
                           for (std::list<uint64>::const_iterator itr = BrokenList.begin(); itr != BrokenList.end(); ++itr)
                               if (Creature* pUnit = Unit::GetCreature(*me, *itr))
                                   // This is the incorrect spell, but can't seem to find the right one.
                                   pUnit->CastSpell(pUnit, 39656, true);
                       }
                       ++EndingTalkCount;
                       SoulRetrieveTimer = 5000;
                       break;
                   case 4:
                       if (!BrokenList.empty())
                       {
                           for (std::list<uint64>::const_iterator itr = BrokenList.begin(); itr != BrokenList.end(); ++itr)
                               if (Creature* pUnit = Unit::GetCreature((*me), *itr))
                                   pUnit->MonsterYell(SAY_BROKEN_FREE_02, LANG_UNIVERSAL, 0);
                       }
                       SoulRetrieveTimer = 0;
                       break;
                   }
               } else SoulRetrieveTimer -= diff;
           }

           if (!UpdateVictim())
               return;

           if (DestructivePoisonTimer <= diff)
           {
               Creature* Shade = Unit::GetCreature((*me), ShadeGUID);
               if (Shade && Shade->isAlive())
                   DoCast(Shade, SPELL_DESTRUCTIVE_POISON);
               DestructivePoisonTimer = 15000;
           } else DestructivePoisonTimer -= diff;

           if (LightningBoltTimer <= diff)
           {
               DoCast(me->getVictim(), SPELL_LIGHTNING_BOLT);
               LightningBoltTimer = 10000;
           } else LightningBoltTimer -= diff;

           DoMeleeAttackIfReady();
       }
   };

};

void AddSC_boss_shade_of_akama()
{
   new boss_shade_of_akama();
   new mob_ashtongue_channeler();
   new mob_ashtongue_sorcerer();
   new npc_akama_shade();
}

 

 

Bloodboil:

 

#include "ScriptPCH.h"
#include "black_temple.h"

//Speech'n'Sound
#define SAY_AGGRO               -1564029
#define SAY_SLAY1               -1564030
#define SAY_SLAY2               -1564031
#define SAY_SPECIAL1            -1564032
#define SAY_SPECIAL2            -1564033
#define SAY_ENRAGE1             -1564034
#define SAY_ENRAGE2             -1564035
#define SAY_DEATH               -1564036

//Spells
#define SPELL_ACID_GEYSER        40630
#define SPELL_ACIDIC_WOUND       40481
#define SPELL_ARCING_SMASH       40599
#define SPELL_BLOODBOIL          42005                      // This spell is AoE whereas it shouldn't be
#define SPELL_FEL_ACID           40508
#define SPELL_FEL_RAGE_SELF      40594
#define SPELL_FEL_RAGE_TARGET    40604
#define SPELL_FEL_RAGE_2         40616
#define SPELL_FEL_RAGE_3         41625
#define SPELL_BEWILDERING_STRIKE 40491
#define SPELL_EJECT1             40486                      // 1000 Physical damage + knockback + script effect (should handle threat reduction I think)
#define SPELL_EJECT2             40597                      // 1000 Physical damage + Stun (used in phase 2?)
#define SPELL_TAUNT_GURTOGG      40603
#define SPELL_INSIGNIFIGANCE     40618
#define SPELL_BERSERK            45078

//This is used to sort the players by distance in preparation for the Bloodboil cast.

class boss_gurtogg_bloodboil : public CreatureScript
{
public:
   boss_gurtogg_bloodboil() : CreatureScript("boss_gurtogg_bloodboil") { }

   CreatureAI* GetAI(Creature* pCreature) const
   {
       return new boss_gurtogg_bloodboilAI (pCreature);
   }

   struct boss_gurtogg_bloodboilAI : public ScriptedAI
   {
       boss_gurtogg_bloodboilAI(Creature *c) : ScriptedAI(c)
       {
           pInstance = c->GetInstanceScript();
       }

       InstanceScript* pInstance;

       uint64 TargetGUID;

       float TargetThreat;

       uint32 BloodboilTimer;
       uint32 BloodboilCount;
       uint32 AcidGeyserTimer;
       uint32 AcidicWoundTimer;
       uint32 ArcingSmashTimer;
       uint32 EnrageTimer;
       uint32 FelAcidTimer;
       uint32 EjectTimer;
       uint32 BewilderingStrikeTimer;
       uint32 PhaseChangeTimer;

       bool Phase1;

       void Reset()
       {
           if (pInstance)
               pInstance->SetData(DATA_GURTOGGBLOODBOILEVENT, NOT_STARTED);

           TargetGUID = 0;

           TargetThreat = 0;

           BloodboilTimer = 10000;
           BloodboilCount = 0;
           AcidGeyserTimer = 1000;
           AcidicWoundTimer = 6000;
           ArcingSmashTimer = 19000;
           EnrageTimer = 600000;
           FelAcidTimer = 25000;
           EjectTimer = 10000;
           BewilderingStrikeTimer = 15000;
           PhaseChangeTimer = 60000;

           Phase1 = true;

           me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false);
           me->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, false);
       }

       void EnterCombat(Unit * /*who*/)
       {
           DoZoneInCombat();
           DoScriptText(SAY_AGGRO, me);
           if (pInstance)
               pInstance->SetData(DATA_GURTOGGBLOODBOILEVENT, IN_PROGRESS);
       }

       void KilledUnit(Unit * /*victim*/)
       {
           DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me);
       }

       void JustDied(Unit * /*victim*/)
       {
           if (pInstance)
               pInstance->SetData(DATA_GURTOGGBLOODBOILEVENT, DONE);

           DoScriptText(SAY_DEATH, me);
       }

       // Note: This seems like a very complicated fix. The fix needs to be handled by the core, as implementation of limited-target AoE spells are still not limited.
       void CastBloodboil()
       {
           // Get the Threat List
           std::list<HostileReference *> m_threatlist = me->getThreatManager().getThreatList();

           if (!m_threatlist.size()) // He doesn't have anyone in his threatlist, useless to continue
               return;

           std::list<Unit *> targets;
           std::list<HostileReference *>::const_iterator itr = m_threatlist.begin();
           for (; itr!= m_threatlist.end(); ++itr)             //store the threat list in a different container
           {
               Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid());
                                                               //only on alive players
               if (pTarget && pTarget->isAlive() && pTarget->GetTypeId() == TYPEID_PLAYER)
                   targets.push_back(pTarget);
           }

           //Sort the list of players
           targets.sort(Trinity::ObjectDistanceOrderPred(me, false));
           //Resize so we only get top 5
           targets.resize(5);

           //Aura each player in the targets list with Bloodboil. Aura code copied+pasted from Aura command in Level3.cpp
           /*SpellEntry const *spellInfo = GetSpellStore()->LookupEntry(SPELL_BLOODBOIL);
           if (spellInfo)
           {
               for (std::list<Unit *>::const_iterator itr = targets.begin(); itr != targets.end(); ++itr)
               {
                   Unit *pTarget = *itr;
                   if (!pTarget) return;
                   for (uint32 i = 0; i<3; ++i)
                   {
                       uint8 eff = spellInfo->Effect[i];
                       if (eff >= TOTAL_SPELL_EFFECTS)
                           continue;

                       Aura *Aur = new Aura(spellInfo, i, pTarget, pTarget, pTarget);
                       pTarget->AddAura(Aur);
                   }
               }
           }*/
       }

       void RevertThreatOnTarget(uint64 guid)
       {
           Unit* pUnit = NULL;
           pUnit = Unit::GetUnit((*me), guid);
           if (pUnit)
           {
               if (DoGetThreat(pUnit))
                   DoModifyThreatPercent(pUnit, -100);
               if (TargetThreat)
                   me->AddThreat(pUnit, TargetThreat);
           }
       }

       void UpdateAI(const uint32 diff)
       {
           if (!UpdateVictim())
               return;

           if (ArcingSmashTimer <= diff)
           {
               DoCast(me->getVictim(), SPELL_ARCING_SMASH);
               ArcingSmashTimer = 10000;
           } else ArcingSmashTimer -= diff;

           if (FelAcidTimer <= diff)
           {
               DoCast(me->getVictim(), SPELL_FEL_ACID);
               FelAcidTimer = 25000;
           } else FelAcidTimer -= diff;

           if (!me->HasAura(SPELL_BERSERK))
           {
               if (EnrageTimer <= diff)
               {
                   DoCast(me, SPELL_BERSERK);
                   DoScriptText(RAND(SAY_ENRAGE1,SAY_ENRAGE2), me);
               } else EnrageTimer -= diff;
           }

           if (Phase1)
           {
               if (BewilderingStrikeTimer <= diff)
               {
                   DoCast(me->getVictim(), SPELL_BEWILDERING_STRIKE);
                   float mt_threat = DoGetThreat(me->getVictim());
                   if (Unit *pTarget = SelectTarget(SELECT_TARGET_TOPAGGRO, 1))
                       me->AddThreat(pTarget, mt_threat);
                   BewilderingStrikeTimer = 20000;
               } else BewilderingStrikeTimer -= diff;

               if (EjectTimer <= diff)
               {
                   DoCast(me->getVictim(), SPELL_EJECT1);
                   DoModifyThreatPercent(me->getVictim(), -40);
                   EjectTimer = 15000;
               } else EjectTimer -= diff;

               if (AcidicWoundTimer <= diff)
               {
                   DoCast(me->getVictim(), SPELL_ACIDIC_WOUND);
                   AcidicWoundTimer = 10000;
               } else AcidicWoundTimer -= diff;

               if (BloodboilTimer <= diff)
               {
                   if (BloodboilCount < 5)                      // Only cast it five times.
                   {
                       //CastBloodboil(); // Causes issues on windows, so is commented out.
                       DoCast(me->getVictim(), SPELL_BLOODBOIL);
                       ++BloodboilCount;
                       BloodboilTimer = 10000*BloodboilCount;
                   }
               } else BloodboilTimer -= diff;
           }

           if (!Phase1)
           {
               if (AcidGeyserTimer <= diff)
               {
                   DoCast(me->getVictim(), SPELL_ACID_GEYSER);
                   AcidGeyserTimer = 30000;
               } else AcidGeyserTimer -= diff;

               if (EjectTimer <= diff)
               {
                   DoCast(me->getVictim(), SPELL_EJECT2);
                   EjectTimer = 15000;
               } else EjectTimer -= diff;
           }

           if (PhaseChangeTimer <= diff)
           {
               if (Phase1)
               {
                   Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0);
                   if (pTarget && pTarget->isAlive())
                   {
                       Phase1 = false;

                       TargetThreat = DoGetThreat(pTarget);
                       TargetGUID = pTarget->GetGUID();
                       pTarget->CastSpell(me, SPELL_TAUNT_GURTOGG, true);
                       if (DoGetThreat(pTarget))
                           DoModifyThreatPercent(pTarget, -100);
                       me->AddThreat(pTarget, 50000000.0f);
                       me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true);
                       me->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, true);
                                                               // If VMaps are disabled, this spell can call the whole instance
                       DoCast(me, SPELL_INSIGNIFIGANCE, true);
                       DoCast(pTarget, SPELL_FEL_RAGE_TARGET, true);
                       DoCast(pTarget, SPELL_FEL_RAGE_2, true);
                       /* These spells do not work, comment them out for now.
                       DoCast(pTarget, SPELL_FEL_RAGE_2, true);
                       DoCast(pTarget, SPELL_FEL_RAGE_3, true);*/

                       //Cast this without triggered so that it appears in combat logs and shows visual.
                       DoCast(me, SPELL_FEL_RAGE_SELF);

                       DoScriptText(RAND(SAY_SPECIAL1,SAY_SPECIAL2), me);

                       AcidGeyserTimer = 1000;
                       PhaseChangeTimer = 30000;
                   }
               } else                                           // Encounter is a loop pretty much. Phase 1 -> Phase 2 -> Phase 1 -> Phase 2 till death or enrage
               {
                   if (TargetGUID)
                       RevertThreatOnTarget(TargetGUID);
                   TargetGUID = 0;
                   Phase1 = true;
                   BloodboilTimer = 10000;
                   BloodboilCount = 0;
                   AcidicWoundTimer += 2000;
                   ArcingSmashTimer += 2000;
                   FelAcidTimer += 2000;
                   EjectTimer += 2000;
                   PhaseChangeTimer = 60000;
                   me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false);
                   me->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, false);
               }
           } else PhaseChangeTimer -= diff;

           DoMeleeAttackIfReady();
       }
   };

};

void AddSC_boss_gurtogg_bloodboil()
{
   new boss_gurtogg_bloodboil();
}

 

 

budes si to muset upravit

  • Upvote 1

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

×