diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/bindings/scripts/ScriptMgr.cpp | 2 | ||||
| -rw-r--r-- | src/bindings/scripts/scripts/zone/karazhan/boss_netherspite.cpp | 338 | ||||
| -rw-r--r-- | src/game/SpellMgr.cpp | 3 |
3 files changed, 330 insertions, 13 deletions
diff --git a/src/bindings/scripts/ScriptMgr.cpp b/src/bindings/scripts/ScriptMgr.cpp index 09c1605f866..50a502e98ed 100644 --- a/src/bindings/scripts/ScriptMgr.cpp +++ b/src/bindings/scripts/ScriptMgr.cpp @@ -350,6 +350,7 @@ extern void AddSC_boss_malchezaar(); extern void AddSC_boss_terestian_illhoof(); extern void AddSC_boss_moroes(); extern void AddSC_bosses_opera(); +extern void AddSC_boss_netherspite(); extern void AddSC_instance_karazhan(); extern void AddSC_karazhan(); extern void AddSC_boss_nightbane(); @@ -1285,6 +1286,7 @@ void ScriptsInit(char const* cfg_file = "trinitycore.conf") AddSC_boss_terestian_illhoof(); AddSC_boss_moroes(); AddSC_bosses_opera(); + AddSC_boss_netherspite(); AddSC_instance_karazhan(); AddSC_karazhan(); AddSC_boss_nightbane(); diff --git a/src/bindings/scripts/scripts/zone/karazhan/boss_netherspite.cpp b/src/bindings/scripts/scripts/zone/karazhan/boss_netherspite.cpp index 6db1b193234..34a4e25d73c 100644 --- a/src/bindings/scripts/scripts/zone/karazhan/boss_netherspite.cpp +++ b/src/bindings/scripts/scripts/zone/karazhan/boss_netherspite.cpp @@ -16,26 +16,338 @@ /* ScriptData SDName: Boss_Netherspite -SD%Complete: 0 -SDComment: Place Holder +SD%Complete: 90 +SDComment: Not sure about timing and portals placing SDCategory: Karazhan EndScriptData */ #include "precompiled.h" +#include "def_karazhan.h" #define EMOTE_PHASE_PORTAL -1532089 #define EMOTE_PHASE_BANISH -1532090 #define SPELL_NETHERBURN_AURA 30522 -#define SPELL_VOIDZONE 37014 //Probably won't work -#define SPELL_BERSERK 26662 -#define SPELL_NETHERBREATH 36631 - -//Beams (no idea how these are going to work in Trinity) -#define SPELL_DOMINANCE_ENEMY 30423 -#define SPELL_DOMINANCE_SELF 30468 -#define SPELL_PERSEVERANCE_ENEMY 30421 -#define SPELL_PERSEVERANCE_SELF 30466 -#define SPELL_SERENITY_ENEMY 30422 -#define SPELL_SERENITY_SELF 30467 +#define SPELL_VOIDZONE 37063 +#define SPELL_NETHER_INFUSION 38688 +#define SPELL_NETHERBREATH 38523 +#define SPELL_BANISH_VISUAL 39833 +#define SPELL_BANISH_ROOT 42716 +#define SPELL_EMPOWERMENT 38549 +#define SPELL_NETHERSPITE_ROAR 38684 +const float PortalCoord[3][3] = +{ + {-11195.353516, -1613.237183, 278.237258}, // Left side + {-11137.846680, -1685.607422, 278.239258}, // Right side + {-11094.493164, -1591.969238, 279.949188} // Back side +}; + +enum Netherspite_Portal{ + RED_PORTAL = 0, // Perseverence + GREEN_PORTAL = 1, // Serenity + BLUE_PORTAL = 2 // Dominance +}; + +const uint32 PortalID[3] = {17369, 17367, 17368}; +const uint32 PortalVisual[3] = {30487,30490,30491}; +const uint32 PortalBeam[3] = {30465,30464,30463}; +const uint32 PlayerBuff[3] = {30421,30422,30423}; +const uint32 NetherBuff[3] = {30466,30467,30468}; +const uint32 PlayerDebuff[3] = {38637,38638,38639}; + +struct TRINITY_DLL_DECL boss_netherspiteAI : public ScriptedAI +{ + boss_netherspiteAI(Creature* c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + + for(int i=0; i<3; ++i) + { + PortalGUID[i] = 0; + BeamTarget[i] = 0; + BeamerGUID[i] = 0; + } + // need core fix + for(int i=0; i<3; ++i) + { + if(SpellEntry *spell = (SpellEntry*)GetSpellStore()->LookupEntry(PlayerBuff[i])) + spell->AttributesEx |= SPELL_ATTR_EX_NEGATIVE; + } + } + + ScriptedInstance* pInstance; + + bool PortalPhase; + bool Berserk; + uint32 PhaseTimer; // timer for phase switching + uint32 VoidZoneTimer; + uint32 NetherInfusionTimer; // berserking timer + uint32 NetherbreathTimer; + uint32 EmpowermentTimer; + uint32 PortalTimer; // timer for beam checking + uint64 PortalGUID[3]; // guid's of portals + uint64 BeamerGUID[3]; // guid's of auxiliary beaming portals + uint64 BeamTarget[3]; // guid's of portals' current targets + + bool IsBetween(WorldObject* u1, WorldObject* target, WorldObject* u2) // the in-line checker + { + if(!u1 || !u2 || !target) + return false; + + float xn, yn, xp, yp, xh, yh; + xn = u1->GetPositionX(); + yn = u1->GetPositionY(); + xp = u2->GetPositionX(); + yp = u2->GetPositionY(); + xh = target->GetPositionX(); + yh = target->GetPositionY(); + + // check if target is between (not checking distance from the beam yet) + if(dist(xn,yn,xh,yh)>=dist(xn,yn,xp,yp) || dist(xp,yp,xh,yh)>=dist(xn,yn,xp,yp)) + return false; + // check distance from the beam + return (abs((xn-xp)*yh+(yp-yn)*xh-xn*yp+xp*yn)/dist(xn,yn,xp,yp) < 1.5f); + } + + float dist(float xa, float ya, float xb, float yb) // auxiliary method for distance + { + return sqrt((xa-xb)*(xa-xb) + (ya-yb)*(ya-yb)); + } + + void Reset() + { + Berserk = false; + NetherInfusionTimer = 540000; + VoidZoneTimer = 15000; + NetherbreathTimer = 3000; + + HandleDoors(true); + DestroyPortals(); + } + + void SummonPortals() + { + uint8 r = rand()%4; + uint8 pos[3]; + pos[RED_PORTAL] = (r%2 ? (r>1 ? 2: 1): 0); + pos[GREEN_PORTAL] = (r%2 ? 0: (r>1 ? 2: 1)); + pos[BLUE_PORTAL] = (r>1 ? 1: 2); // Blue Portal not on the left side (0) + + for(int i=0; i<3; ++i) + if(Creature *portal = m_creature->SummonCreature(PortalID[i],PortalCoord[pos[i]][0],PortalCoord[pos[i]][1],PortalCoord[pos[i]][2],0,TEMPSUMMON_TIMED_DESPAWN,60000)) + { + PortalGUID[i] = portal->GetGUID(); + portal->AddAura(PortalVisual[i], portal); + } + } + + void DestroyPortals() + { + for(int i=0; i<3; ++i) + { + if(Creature *portal = Unit::GetCreature(*m_creature, PortalGUID[i])) + { + portal->SetVisibility(VISIBILITY_OFF); + portal->DealDamage(portal, portal->GetMaxHealth()); + portal->RemoveFromWorld(); + } + if(Creature *portal = Unit::GetCreature(*m_creature, BeamerGUID[i])) + { + portal->SetVisibility(VISIBILITY_OFF); + portal->DealDamage(portal, portal->GetMaxHealth()); + portal->RemoveFromWorld(); + } + PortalGUID[i] = 0; + BeamTarget[i] = 0; + } + } + + void UpdatePortals() // Here we handle the beams' behavior + { + for(int j=0; j<3; ++j) // j = color + if(Creature *portal = Unit::GetCreature(*m_creature, PortalGUID[j])) + { + // the one who's been casted upon before + Unit *current = Unit::GetUnit(*portal, BeamTarget[j]); + // temporary store for the best suitable beam reciever + Unit *target = m_creature; + + if(Map* map = m_creature->GetMap()) + { + Map::PlayerList const& players = map->GetPlayers(); + + // get the best suitable target + for(Map::PlayerList::const_iterator i = players.begin(); i!=players.end(); ++i) + { + Player* p = i->getSource(); + if(p && p->isAlive() // alive + && (!target || target->GetDistance2d(portal)>p->GetDistance2d(portal)) // closer than current best + && !p->HasAura(PlayerDebuff[j],0) // not exhausted + && !p->HasAura(PlayerBuff[(j+1)%3],0) // not on another beam + && !p->HasAura(PlayerBuff[(j+2)%3],0) + && IsBetween(m_creature, p, portal)) // on the beam + target = p; + } + } + // buff the target + if(target->GetTypeId() == TYPEID_PLAYER) + target->AddAura(PlayerBuff[j], target); + else + target->AddAura(NetherBuff[j], target); + // cast visual beam on the chosen target if switched + // simple target switching isn't working -> using BeamerGUID to cast (workaround) + if(!current || target != current) + { + BeamTarget[j] = target->GetGUID(); + // remove currently beaming portal + if(Creature *beamer = Unit::GetCreature(*portal, BeamerGUID[j])) + { + beamer->CastSpell(target, PortalBeam[j], false); + beamer->SetVisibility(VISIBILITY_OFF); + beamer->DealDamage(beamer, beamer->GetMaxHealth()); + beamer->RemoveFromWorld(); + BeamerGUID[j] = 0; + } + // create new one and start beaming on the target + if(Creature *beamer = portal->SummonCreature(PortalID[j],portal->GetPositionX(),portal->GetPositionY(),portal->GetPositionZ(),portal->GetOrientation(),TEMPSUMMON_TIMED_DESPAWN,60000)) + { + beamer->CastSpell(target, PortalBeam[j], false); + BeamerGUID[j] = beamer->GetGUID(); + } + } + // aggro target if Red Beam + if(j==RED_PORTAL && m_creature->getVictim() != target && target->GetTypeId() == TYPEID_PLAYER) + m_creature->getThreatManager().addThreat(target, 100000.0f+DoGetThreat(m_creature->getVictim())); + } + } + + void SwitchToPortalPhase() + { + m_creature->RemoveAurasDueToSpell(SPELL_BANISH_ROOT); + m_creature->RemoveAurasDueToSpell(SPELL_BANISH_VISUAL); + SummonPortals(); + PhaseTimer = 60000; + PortalPhase = true; + PortalTimer = 10000; + EmpowermentTimer = 10000; + DoScriptText(EMOTE_PHASE_PORTAL,m_creature); + } + + void SwitchToBanishPhase() + { + m_creature->RemoveAurasDueToSpell(SPELL_EMPOWERMENT); + m_creature->RemoveAurasDueToSpell(SPELL_NETHERBURN_AURA); + DoCast(m_creature,SPELL_BANISH_VISUAL,true); + DoCast(m_creature,SPELL_BANISH_ROOT,true); + DestroyPortals(); + PhaseTimer = 30000; + PortalPhase = false; + DoScriptText(EMOTE_PHASE_BANISH,m_creature); + + for(int i=0; i<3; ++i) + m_creature->RemoveAurasDueToSpell(NetherBuff[i]); + } + + void HandleDoors(bool open) // Massive Door switcher + { + if(GameObject *Door = GameObject::GetGameObject((*m_creature),pInstance->GetData64(DATA_GO_MASSIVE_DOOR))) + Door->SetGoState(open ? GO_STATE_ACTIVE : GO_STATE_READY); + } + + void Aggro(Unit *who) + { + HandleDoors(false); + SwitchToPortalPhase(); + } + + void JustDied(Unit* killer) + { + HandleDoors(true); + DestroyPortals(); + } + + void UpdateAI(const uint32 diff) + { + if(!UpdateVictim()) + return; + + // Void Zone + if(VoidZoneTimer < diff) + { + DoCast(SelectTarget(SELECT_TARGET_RANDOM,1,45,true),SPELL_VOIDZONE,true); + VoidZoneTimer = 15000; + }else VoidZoneTimer -= diff; + + // NetherInfusion Berserk + if(!Berserk && NetherInfusionTimer < diff) + { + m_creature->AddAura(SPELL_NETHER_INFUSION, m_creature); + DoCast(m_creature, SPELL_NETHERSPITE_ROAR); + Berserk = true; + }else NetherInfusionTimer -= diff; + + if(PortalPhase) // PORTAL PHASE + { + // Distribute beams and buffs + if(PortalTimer < diff) + { + UpdatePortals(); + PortalTimer = 1000; + }else PortalTimer -= diff; + + // Empowerment & Nether Burn + if(EmpowermentTimer < diff) + { + DoCast(m_creature, SPELL_EMPOWERMENT); + m_creature->AddAura(SPELL_NETHERBURN_AURA, m_creature); + EmpowermentTimer = 90000; + }else EmpowermentTimer -= diff; + + if(PhaseTimer < diff) + { + if(!m_creature->IsNonMeleeSpellCasted(false)) + { + SwitchToBanishPhase(); + return; + } + }else PhaseTimer -= diff; + } + else // BANISH PHASE + { + // Netherbreath + if(NetherbreathTimer < diff) + { + if(Unit* target = SelectTarget(SELECT_TARGET_RANDOM,0,40,true)) + DoCast(target,SPELL_NETHERBREATH); + NetherbreathTimer = 5000+rand()%2000; + }else NetherbreathTimer -= diff; + + if(PhaseTimer < diff) + { + if(!m_creature->IsNonMeleeSpellCasted(false)) + { + SwitchToPortalPhase(); + return; + } + }else PhaseTimer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_netherspite(Creature *_Creature) +{ + return new boss_netherspiteAI(_Creature); +} + +void AddSC_boss_netherspite() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="boss_netherspite"; + newscript->GetAI = GetAI_boss_netherspite; + newscript->RegisterSelf(); +} diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index e0b49b8406b..9db16df7281 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -3727,6 +3727,9 @@ void SpellMgr::LoadSpellCustomAttr() case 48422: spellInfo->Stances = 1 << (FORM_TREE - 1); break; + case 30421: // Nether Portal - Perseverence + spellInfo->EffectBasePoints[2] += 30000; + break; default: break; } |
