/* Copyright (C) 2006,2007 ScriptDev2
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../../sc_defines.h"
#include "../../../../../game/Player.h"
#define SPELL_WEBTRAP 28622 //Spell is normally used by the webtrap on the wall NOT by Maexxna
#define SPELL_WEBSPRAY 29484
#define SPELL_POISONSHOCK 28741
#define SPELL_NECROTICPOISON 28776
#define SPELL_ENRAGE 28747
#define SPELL_SUMMON_SPIDERLING 29434
#define LOC_X1 3546.796
#define LOC_Y1 -3869.082
#define LOC_Z1 296.450
#define LOC_X2 3531.271
#define LOC_Y2 -3847.424
#define LOC_Z2 299.450
#define LOC_X3 3497.067
#define LOC_Y3 -3843.384
#define LOC_Z3 302.384
struct MANGOS_DLL_DECL mob_webwrapAI : public ScriptedAI
{
mob_webwrapAI(Creature *c) : ScriptedAI(c) {SetVariables();}
uint64 victimGUID;
void SetVariables()
{
victimGUID = 0;
}
void SetVictim(Unit* victim)
{
if(victim)
{
victimGUID = victim->GetGUID();
victim->CastSpell(victim, SPELL_WEBTRAP, true);
}
}
void DamageTaken(Unit *done_by, uint32 &damage)
{
if(damage > m_creature->GetHealth())
{
if(victimGUID)
{
Unit* victim = NULL;
victim = Unit::GetUnit((*m_creature), victimGUID);
victim->RemoveAurasDueToSpell(SPELL_WEBTRAP);
}
}
}
void AttackStart(Unit *who)
{
}
void MoveInLineOfSight(Unit *who)
{
}
void UpdateAI(const uint32 diff)
{
}
};
struct MANGOS_DLL_DECL boss_maexxnaAI : public ScriptedAI
{
boss_maexxnaAI(Creature *c) : ScriptedAI(c) {SetVariables();}
uint32 WebTrap_Timer;
uint32 WebSpray_Timer;
uint32 PoisonShock_Timer;
uint32 NecroticPoison_Timer;
uint32 SummonSpiderling_Timer;
bool Enraged;
bool InCombat;
void SetVariables()
{
WebTrap_Timer = 20000; //20 sec init, 40 sec normal
WebSpray_Timer = 40000; //40 seconds
PoisonShock_Timer = 20000; //20 seconds
NecroticPoison_Timer = 30000; //30 seconds
SummonSpiderling_Timer = 30000; //30 sec init, 40 sec normal
Enraged = false;
}
void EnterEvadeMode()
{
InCombat = false;
m_creature->RemoveAllAuras();
m_creature->DeleteThreatList();
m_creature->CombatStop();
DoGoHome();
}
void AttackStart(Unit *who)
{
if (!who)
return;
if (who->isTargetableForAttack() && who!= m_creature)
{
//Begin melee attack if we are within range
DoStartMeleeAttack(who);
InCombat = true;
}
}
void MoveInLineOfSight(Unit *who)
{
if (!who || m_creature->getVictim())
return;
if (who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who))
{
float attackRadius = m_creature->GetAttackDistance(who);
if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who))
{
if(who->HasStealthAura())
who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
//Begin melee attack if we are within range
DoStartMeleeAttack(who);
InCombat = true;
}
}
}
void DoCastWebWrap()
{
std::list t_list = m_creature->getThreatManager().getThreatList();
std::vector targets;
if(!t_list.size())
return;
//begin + 1 , so we don't target the one with the highest threat
std::list::iterator itr = t_list.begin();
std::advance(itr, 1);
for( ; itr!= t_list.end(); ++itr) //store the threat list in a different container
{
Unit *target = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid());
if(target && target->isAlive() && target->GetTypeId() == TYPEID_PLAYER ) //only on alive players
targets.push_back( target);
}
while(targets.size() > 3)
targets.erase(targets.begin()+rand()%targets.size()); //cut down to size if we have more than 3 targets
int i = 0;
for(std::vector::iterator itr = targets.begin(); itr!= targets.end(); ++itr, ++i)
{
// Teleport the 3 targets to a location on the wall and summon a Web Wrap on them
Unit *target = *itr;
Creature* Wrap = NULL;
if(target)
{
switch(i)
{
case 0:
((Player*)target)->TeleportTo(target->GetMapId(), LOC_X1, LOC_Y1, LOC_Z1, target->GetOrientation());
Wrap = DoSpawnCreature(16486, LOC_X1, LOC_Y1, LOC_Z1, 0, TEMPSUMMON_DEAD_DESPAWN, 0);
break;
case 1:
((Player*)target)->TeleportTo(target->GetMapId(), LOC_X2, LOC_Y2, LOC_Z2, target->GetOrientation());
Wrap = DoSpawnCreature(16486, LOC_X2, LOC_Y2, LOC_Z2, 0, TEMPSUMMON_DEAD_DESPAWN, 0);
break;
case 2:
((Player*)target)->TeleportTo(target->GetMapId(), LOC_X3, LOC_Y3, LOC_Z3, target->GetOrientation());
Wrap = DoSpawnCreature(16486, LOC_X3, LOC_Y3, LOC_Z3, 0, TEMPSUMMON_DEAD_DESPAWN, 0);
break;
}
if(Wrap)
{
Wrap->setFaction(m_creature->getFaction());
((mob_webwrapAI*)Wrap->AI())->SetVictim(target);
Wrap->CastSpell(Wrap, 42716, true); // Root self w/o visual
}
}
}
}
void UpdateAI(const uint32 diff)
{
//Return since we have no target
if (!m_creature->SelectHostilTarget() || !m_creature->getVictim())
return;
//WebTrap_Timer
if (WebTrap_Timer < diff)
{
DoCastWebWrap();
WebTrap_Timer = 40000; //40 seconds until we should cast this again
}else WebTrap_Timer -= diff;
//WebSpray_Timer
if (WebSpray_Timer < diff)
{
//Cast
DoCast(m_creature->getVictim(), SPELL_WEBSPRAY);
//40 seconds until we should cast this agian
WebSpray_Timer = 40000;
}else WebSpray_Timer -= diff;
//PoisonShock_Timer
if (PoisonShock_Timer < diff)
{
//Cast
DoCast(m_creature->getVictim(), SPELL_POISONSHOCK);
//20 seconds until we should cast this agian
PoisonShock_Timer = 20000;
}else PoisonShock_Timer -= diff;
//NecroticPoison_Timer
if (NecroticPoison_Timer < diff)
{
//Cast
DoCast(m_creature->getVictim(), SPELL_NECROTICPOISON);
//30 seconds until we should cast this agian
NecroticPoison_Timer = 30000;
}else NecroticPoison_Timer -= diff;
//SummonSpiderling_Timer
if (SummonSpiderling_Timer < diff)
{
//Cast
DoCast(m_creature, SPELL_SUMMON_SPIDERLING);
//40 seconds until we should cast this agian
SummonSpiderling_Timer = 40000;
}else SummonSpiderling_Timer -= diff;
//Enrage if not already enraged and below 30%
if (!Enraged && (m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 30)
{
DoCast(m_creature,SPELL_ENRAGE);
Enraged = true;
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI_mob_webwrap(Creature* _Creature)
{
return new mob_webwrapAI (_Creature);
}
CreatureAI* GetAI_boss_maexxna(Creature *_Creature)
{
return new boss_maexxnaAI (_Creature);
}
void AddSC_boss_maexxna()
{
Script *newscript;
newscript = new Script;
newscript->Name="boss_maexxna";
newscript->GetAI = GetAI_boss_maexxna;
m_scripts[nrscripts++] = newscript;
newscript = new Script;
newscript->Name="mob_webwrap";
newscript->GetAI = GetAI_mob_webwrap;
m_scripts[nrscripts++] = newscript;
}