All pastes #839663 Raw Edit

HyjalAI

public text v1 · immutable
#839663 ·published 2007-12-31 04:01 UTC
rendered paste body
/* Copyright (C) 2006,2007 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
* 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"
#include "../../../../../../game/Group.h"
#include "../../../../../../game/GossipDef.h"

#define GOSSIP_ITEM_BEGIN       "We are ready to defend the Alliance base."
#define GOSSIP_ITEM_ANETHERON   "The defenses are holding up; we can continue."
#define GOSSIP_ITEM_RETREAT     "We can't keep this up. It's time to retreat."

// Trash Mobs summoned in waves
#define NECROMANCER         17899
#define ABOMINATION         17898
#define GHOUL               17895
#define BANSHEE             17905
#define CRYPT_FIEND         17897
#define GARGOYLE            17906
#define FROST_WYRM          17907
#define GIANT_INFERNAL      17908
#define FEL_STALKER         17916

// Bosses summoned after every 8 waves
#define RAGE_WINTERCHILL    17767
#define ANETHERON           17808
#define KAZROGAL            17888
#define AZGALOR             17842
#define ARCHIMONDE          17968

#define HORDEBASE_X         5464.5522
#define HORDEBASE_Y         -2731.5644
#define HORDEBASE_Z         1485.7075

#define SPELL_TELEPORT_VISUAL   41232

struct Wave
{
    uint32 Mob1, Mob2, Mob3, Mob4, Mob5, Mob6, Mob7, Mob8, Mob9, Mob10, Mob11, Mob12, Mob13, Mob14, Mob15, Mob16, Mob17, Mob18;
    uint32 WaveTimer;
    bool IsBoss;
};

static Wave AllianceWaves[]=
{
    {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, 0, 0, 0, 0, 0, 0, 0, 0, 120000, false}, // Wave 1
    {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, 0, 0, 0, 0, 0, 0, 120000, false}, // Wave 2
    {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, 0, 0, 0, 0, 0, 0, 120000, false}, // Wave 3
    {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 120000, false}, // Wave 4
    {GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 120000, false}, // Wave 5
    {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, 0, 0, 0, 0, 0, 120000, false}, // Wave 6
    {GHOUL, GHOUL, GHOUL, GHOUL, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, 0, 0, 0, 0, 0, 0, 120000, false}, // Wave 7
    {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 120000, false}, // Wave 8
    {RAGE_WINTERCHILL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true}, // All 8 Waves are summoned, summon Rage Winterchill, next few waves are for Anetheron
    {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, 0, 0, 0, 0, 0, 0, 0, 0, 120000, false}, // Wave 1
    {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, 0, 0, 0, 0, 0, 0, 120000, false}, // Wave 2
    {GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 120000, false}, // Wave 3
    {GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, BANSHEE, BANSHEE, BANSHEE, BANSHEE, 0, 0, 0, 0, 0, 0, 120000, false}, // Wave 4
    {CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, BANSHEE, BANSHEE, BANSHEE, BANSHEE, 0, 0, 0, 0, 0, 0, 120000, false}, // Wave 5
    {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 120000, false}, // Wave 6
    {CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, BANSHEE, BANSHEE, BANSHEE, BANSHEE, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, 0, 0, 0, 0, 0, 0, 120000, false}, // Wave 7
    {GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, BANSHEE, BANSHEE, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 180000, false}, // Wave 8
    {ANETHERON, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true} // All 8 Waves are summoned, summon Anatheron
};

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

static Location AllianceBase[]=
{
    {4979.010, -1709.134, 1339.674},
    {4969.123, -1705.904, 1341.363},
    {4970.260, -1698.546, 1341.200},
    {4975.262, -1698.239, 1341.427}
};

struct MANGOS_DLL_DECL npc_jaina_proudmooreAI : public ScriptedAI
{
    npc_jaina_proudmooreAI(Creature *c) : ScriptedAI(c)
    {
        pInstance = ((ScriptedInstance*)c->GetInstanceData());
        SetVariables();
    }

    ScriptedInstance* pInstance;

    uint64 PlayerGUID;
    uint64 WinterchillGUID;
    uint64 AnetheronGUID;

    uint32 NextWaveTimer;
    uint32 WaveCount;
    uint32 CheckTimer;

    bool EventBegun;
    bool AllianceOverrun;
    bool InCombat;
    bool RageWinterchillDead;
    bool AnetheronDead;

    void SetVariables()
    {
        PlayerGUID = 0;
        WinterchillGUID = 0;
        AnetheronGUID = 0;

        NextWaveTimer = 30000;
        WaveCount = 0;
        CheckTimer = 0;

        EventBegun = false;
        AllianceOverrun = false;
        InCombat = false;
        RageWinterchillDead = false;
        AnetheronDead = false;
    }

    void EnterEvadeMode()
    {
        SetVariables();

        m_creature->RemoveAllAuras();
        m_creature->DeleteThreatList();
        m_creature->CombatStop();
        DoGoHome();
    }

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

        if(who->isTargetableForAttack() && who!= m_creature)
        {
            DoStartMeleeAttack(who);

            if(!InCombat)
            {
                InCombat = true;
            }
        }

    }

    void MoveInLineOfSight(Unit *who)
    {
        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);

                if(who && who->isAlive())
                    m_creature->AddThreat(who, 1.0f);

                if(!InCombat)
                {
                    InCombat = true;
                }
            }
        }

    }

    void SummonCreature(uint32 entry, bool IsBoss = true)
    {
        uint32 random = rand()%4;
        float X = AllianceBase[random].x;
        float Y = AllianceBase[random].y;
        float Z = AllianceBase[random].z;

        Creature* pCreature = m_creature->SummonCreature(entry, X, Y, Z, 0, TEMPSUMMON_DEAD_DESPAWN, 0);
        if(pCreature)
        {
            if(PlayerGUID)
            {
                Unit* pUnit = Unit::GetUnit((*m_creature), PlayerGUID);
                if(pUnit)
                    pCreature->AddThreat(pUnit, 1.0f);
                else pCreature->AddThreat(m_creature, 1.0f);
            }else pCreature->AddThreat(m_creature, 1.0f);

            if(IsBoss)
            {
                if(!RageWinterchillDead)
                    WinterchillGUID = pCreature->GetGUID();
                else AnetheronGUID = pCreature->GetGUID();
            }
        }
    }

    void SummonNextWave(uint32 Wave)
    {
        if(AllianceWaves[Wave].IsBoss)
            SummonCreature(AllianceWaves[Wave].Mob1, true);
        if(AllianceWaves[Wave].Mob1 && (!AllianceWaves[Wave].IsBoss))
            SummonCreature(AllianceWaves[Wave].Mob1);
         if(AllianceWaves[Wave].Mob2)
             SummonCreature(AllianceWaves[Wave].Mob2);
         if(AllianceWaves[Wave].Mob3)
             SummonCreature(AllianceWaves[Wave].Mob3);
         if(AllianceWaves[Wave].Mob4)
             SummonCreature(AllianceWaves[Wave].Mob4);
         if(AllianceWaves[Wave].Mob5)
             SummonCreature(AllianceWaves[Wave].Mob5);
         if(AllianceWaves[Wave].Mob6)
             SummonCreature(AllianceWaves[Wave].Mob6);
         if(AllianceWaves[Wave].Mob7)
             SummonCreature(AllianceWaves[Wave].Mob7);
         if(AllianceWaves[Wave].Mob8)
             SummonCreature(AllianceWaves[Wave].Mob8);
         if(AllianceWaves[Wave].Mob9)
             SummonCreature(AllianceWaves[Wave].Mob9);
         if(AllianceWaves[Wave].Mob10)
             SummonCreature(AllianceWaves[Wave].Mob10);
         if(AllianceWaves[Wave].Mob11)
             SummonCreature(AllianceWaves[Wave].Mob11);
         if(AllianceWaves[Wave].Mob12)
             SummonCreature(AllianceWaves[Wave].Mob12);
         if(AllianceWaves[Wave].Mob13)
             SummonCreature(AllianceWaves[Wave].Mob13);
         if(AllianceWaves[Wave].Mob14)
             SummonCreature(AllianceWaves[Wave].Mob14);
         if(AllianceWaves[Wave].Mob15)
             SummonCreature(AllianceWaves[Wave].Mob15);
         if(AllianceWaves[Wave].Mob16)
             SummonCreature(AllianceWaves[Wave].Mob16);
         if(AllianceWaves[Wave].Mob17)
             SummonCreature(AllianceWaves[Wave].Mob17);
         if(AllianceWaves[Wave].Mob18)
             SummonCreature(AllianceWaves[Wave].Mob18);

         if(!AllianceWaves[Wave].IsBoss)
             NextWaveTimer = AllianceWaves[Wave].WaveTimer;
         else NextWaveTimer = 0;
    }

    void TeleportRaid(Player* player)
    {
        if(!player)
        {
            if(PlayerGUID)
            {
                player = ((Player*)Unit::GetUnit((*m_creature), PlayerGUID));
                if(!player) return;
            }else return;
        }
        
        Group* Raid = player->GetGroup();
        if(Raid)
        {
            const Group::MemberSlotList list = Raid->GetMemberSlots();
            Group::member_citerator itr = list.begin();
            for( ; itr != list.end(); itr++)
            {
                Player* member = ((Player*)Unit::GetUnit((*m_creature), itr->guid));
                if(member && member->isAlive())
                {
                    member->CastSpell(member, SPELL_TELEPORT_VISUAL, true);
                    member->TeleportTo(m_creature->GetMapId(), HORDEBASE_X, HORDEBASE_Y, HORDEBASE_Z, member->GetOrientation());
                }
            }
        }
    }

    void StartEvent(Player* player)
    {
        if(player)
        {
            EventBegun = true;
            PlayerGUID = player->GetGUID();
            m_creature->SetUInt32Value(UNIT_NPC_FLAGS, 0);
        }
    }

    void StartAnetheronPhase(Player* player)
    {
        if(player)
        {
            EventBegun = true;
            PlayerGUID = player->GetGUID();
            m_creature->SetUInt32Value(UNIT_NPC_FLAGS, 0);
        }
    }

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

        if(NextWaveTimer)
        {
            if(NextWaveTimer < diff)
            {
                SummonNextWave(WaveCount);
                WaveCount++;
            }else NextWaveTimer -= diff;
        }

        if(CheckTimer < diff)
        {
            if(PlayerGUID)
            {
                Player* target = ((Player*)Unit::GetUnit((*m_creature), PlayerGUID));
                if(target)
                {
                    if(!target->isAlive())
                    {
                        Group* Raid = target->GetGroup();
                        if(Raid)
                        {
                            const Group::MemberSlotList list = Raid->GetMemberSlots();
                            Group::member_citerator itr = list.begin();
                            uint32 DeathCount = 0;
                            uint32 RaidCount = Raid->GetMembersCount();
                            for( ; itr != list.end(); itr++)
                            {
                                Player* member = ((Player*)Unit::GetUnit((*m_creature), itr->guid));
                                if(member && member->isAlive())
                                    break;
                                else DeathCount++;
                            }
                            if(DeathCount == RaidCount)
                            {
                                EventBegun = false;
                                SetVariables();
                                EnterEvadeMode();
                            }
                        }
                    }
                }
            }

            if(WinterchillGUID)
            {
                Unit* pUnit = Unit::GetUnit((*m_creature), WinterchillGUID);
                if(pUnit && (!pUnit->isAlive()))
                {
                    RageWinterchillDead = true;
                    m_creature->SetUInt32Value(UNIT_NPC_FLAGS, 1);
                    WinterchillGUID = 0;
                }
            }
            
            if(AnetheronGUID)
            {
                Unit* pUnit = Unit::GetUnit((*m_creature), AnetheronGUID);
                if(pUnit && (!pUnit->isAlive()))
                {
                    AnetheronDead = true;
                    m_creature->SetUInt32Value(UNIT_NPC_FLAGS, 1);
                    AnetheronDead = 0;
                }
            }

            CheckTimer = 15000;
        }else CheckTimer -= diff;
    }
};

bool GossipSelect_npc_jaina_proudmoore(Player *player, Creature *_Creature, uint32 sender, uint32 action )
{
    switch(action)
    {
        case GOSSIP_ACTION_INFO_DEF + 1:
            player->PlayerTalkClass->CloseGossip();
            ((npc_jaina_proudmooreAI*)_Creature->AI())->StartEvent(player);
            break;
        case GOSSIP_ACTION_INFO_DEF + 2:
            player->PlayerTalkClass->CloseGossip();
            ((npc_jaina_proudmooreAI*)_Creature->AI())->StartAnetheronPhase(player);
            break;
        case GOSSIP_ACTION_INFO_DEF + 3:
            player->PlayerTalkClass->CloseGossip();
            ((npc_jaina_proudmooreAI*)_Creature->AI())->TeleportRaid(player);
            break;
    }
    return true;
}

bool GossipHello_npc_jaina_proudmoore(Player *player, Creature *_Creature)
{	
	if(player->isAlive())
	{
        if(!((npc_jaina_proudmooreAI*)_Creature->AI())->EventBegun)
        {
            if(((npc_jaina_proudmooreAI*)_Creature->AI())->RageWinterchillDead)
            {
                player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_ANETHERON, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
                player->PlayerTalkClass->SendGossipMenu(907, _Creature->GetGUID());
            }
            else
            {
                player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_BEGIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
                player->PlayerTalkClass->SendGossipMenu(907, _Creature->GetGUID());
            }
        }
        else
        {            
            if(((npc_jaina_proudmooreAI*)_Creature->AI())->AnetheronDead)
            {
                player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_RETREAT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
                player->PlayerTalkClass->SendGossipMenu(907, _Creature->GetGUID());
            }
        }
	}
    return true;
}

CreatureAI* GetAI_npc_jaina_proudmoore(Creature* _Creature)
{
    return new npc_jaina_proudmooreAI(_Creature);
}


void AddSC_npc_jaina_proudmoore()
{
    Script *newscript;
       
    newscript = new Script;
    newscript->Name="npc_jaina_proudmoore";
    newscript->GetAI = GetAI_npc_jaina_proudmoore;
    newscript->pGossipHello = &GossipHello_npc_jaina_proudmoore;
    newscript->pGossipSelect = &GossipSelect_npc_jaina_proudmoore;
    m_scripts[nrscripts++] = newscript;
}