/* 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 "config.h"
#include "ScriptMgr.h"
#include "../../shared/WorldPacket.h"
#include "../../game/Player.h"
#include "../../game/GameObject.h"
#include "../../game/GossipDef.h"
#include "../../game/QuestDef.h"
#include "../../game/TargetedMovementGenerator.h"
#include "../../game/Spell.h"
#include "../../shared/Database/DBCStores.h"
uint8 loglevel = 0;
int nrscripts;
Script *m_scripts[MAX_SCRIPTS];
// Spell summary for ScriptedAI::SelectSpell
struct TSpellSummary {
uint8 Targets; // set of enum SelectTarget
uint8 Effects; // set of enum SelectEffect
} *SpellSummary;
void FillSpellSummary();
// -- Scripts to be added --
// -- Area --
// -- Boss --
extern void AddSC_boss_emeriss();
extern void AddSC_boss_taerar();
extern void AddSC_boss_ysondre();
// -- Creature --
extern void AddSC_kobold();
extern void AddSC_generic_creature();
extern void AddSC_defias();
// -- Custom --
extern void AddSC_custom_example();
extern void AddSC_test();
// -- GO --
extern void AddSC_go_teleporter();
extern void AddSC_go_orb_of_command();
// -- Guard --
extern void AddSC_guards();
// -- Honor --
extern void AddSC_Honor_Vendor();
// -- Item --
extern void AddSC_item_test();
extern void AddSC_area_52_special();
extern void AddSC_draenei_fishing_net();
extern void AddSC_nether_wraith_beacon();
extern void AddSC_purification_mixture();
extern void AddSC_vorenthals_presence();
// -- NPC --
extern void AddSC_not_selectable();
extern void AddSC_npc_guardian();
// -- Servers --
//--------------------
//------ ZONE --------
//Alterac Mountains
//Arathi Highlands
//Ashenvale Forest
//Aunchindoun
//--Auchenai Crypts
extern void AddSC_boss_shirrak_the_dead_watcher();
//--Mana Tombs
extern void AddSC_boss_nexusprince_shaffar();
extern void AddSC_boss_pandemonius();
extern void AddSC_boss_tavarok();
//--Sekketh Halls
extern void AddSC_boss_darkweaver_syth();
extern void AddSC_boss_tailonking_ikiss();
//--Shadow Labyrinth
extern void AddSC_boss_ambassador_hellmaw();
extern void AddSC_boss_blackheart_the_inciter();
extern void AddSC_boss_grandmaster_vorpil();
extern void AddSC_boss_murmur();
extern void AddSC_instance_shadow_labyrinth();
//Azshara
extern void AddSC_boss_azuregos();
extern void AddSC_mobs_spitelashes();
//Azuremyst Isle
extern void AddSC_injured_draenei();
extern void AddSC_draenei_survivor();
//Badlands
//Barrens
extern void AddSC_npc_beaten_corpse();
//Black Temple
extern void AddSC_mob_blacktemple();
extern void AddSC_boss_illidan();
extern void AddSC_boss_shade_of_akama();
extern void AddSC_boss_supremus();
extern void AddSC_boss_gurtogg_bloodboil();
extern void AddSC_boss_mother_shahraz();
extern void AddSC_boss_reliquary_of_souls();
extern void AddSC_boss_teron_gorefiend();
extern void AddSC_boss_najentus();
extern void AddSC_boss_illidari_council();
extern void AddSC_instance_black_temple();
//Blackfathom Depths
//Blackrock Depths
extern void AddSC_boss_ambassador_flamelash();
extern void AddSC_boss_angerrel();
extern void AddSC_boss_anubshiah();
extern void AddSC_boss_baelgar();
extern void AddSC_boss_doomrel();
extern void AddSC_boss_doperel();
extern void AddSC_boss_draganthaurissan();
extern void AddSC_boss_fineous_darkvire();
extern void AddSC_boss_general_angerforge();
extern void AddSC_boss_gloomrel();
extern void AddSC_boss_golemlordargelmach();
extern void AddSC_boss_gorosh_the_dervish();
extern void AddSC_boss_grizzle();
extern void AddSC_boss_haterel();
extern void AddSC_boss_high_interrogator_gerstahn();
extern void AddSC_boss_lord_incendius();
extern void AddSC_boss_lord_roccor();
extern void AddSC_boss_magmus();
extern void AddSC_boss_moira_bronzebeard();
extern void AddSC_boss_pyromancer_loregrain();
extern void AddSC_boss_seethrel();
extern void AddSC_boss_verek();
extern void AddSC_boss_vilerel();
extern void AddSC_boss_warder_stilgiss();
extern void AddSC_overmaster_pyron();
extern void AddSC_phalanx();
extern void AddSC_npc_lokhtos_darkbargainer();
//Blackrock Spire
extern void AddSC_boss_drakkisath();
extern void AddSC_boss_halycon();
extern void AddSC_boss_highlordomokk();
extern void AddSC_boss_mothersmolderweb();
extern void AddSC_boss_overlordwyrmthalak();
extern void AddSC_boss_shadowvosh();
extern void AddSC_boss_thebeast();
extern void AddSC_boss_warmastervoone();
extern void AddSC_boss_quatermasterzigris();
extern void AddSC_boss_pyroguard_emberseer();
extern void AddSC_boss_gyth();
extern void AddSC_boss_rend_blackhand();
extern void AddSC_mob_chromatic_elite_guard();
//Blackwing lair
extern void AddSC_boss_razorgore();
extern void AddSC_boss_vael();
extern void AddSC_boss_broodlord();
extern void AddSC_boss_firemaw();
extern void AddSC_boss_ebonroc();
extern void AddSC_boss_flamegor();
extern void AddSC_boss_chromaggus();
extern void AddSC_boss_nefarian();
extern void AddSC_boss_victor_nefarius();
//Blasted lands
extern void AddSC_boss_kruul();
extern void AddSC_boss_teremusthedevourer();
//Burning steppes
//Caverns of Time
//--Battle for Mt. Hyjal
//--Old Hillsbrad
extern void AddSC_boss_captain_skarloc();
extern void AddSC_boss_epoch_hunter();
extern void AddSC_boss_lieutenant_drake();
//--The Dark Portal
extern void AddSC_boss_aeonus();
extern void AddSC_boss_chrono_lord_deja();
extern void AddSC_boss_temporus();
//Coilfang Resevoir
//--Serpent Shrine Cavern
extern void AddSC_boss_fathomlord_karathress();
extern void AddSC_boss_hydross_the_unstable();
extern void AddSC_boss_leotheras_the_blind();
extern void AddSC_boss_morogrim_tidewalker();
extern void AddSC_instance_serpentshrine_cavern();
extern void AddSC_mob_serpentshrine_cavern();
//--Slave Pens
extern void AddSC_boss_rokmar_the_crackler();
//--Steam Vault
extern void AddSC_boss_warlord_kalithresh();
extern void AddSC_boss_hydromancer_thespia();
//--Underbog
extern void AddSC_boss_ghazan();
extern void AddSC_boss_hungarfen();
//Darkshore
extern void AddSC_mobs_darkshore();
//Darnassus
//Deadmines
extern void AddSC_boss_deadmines();
//Deadwind pass
//Desolace
//Dire Maul
//Dun Morogh
extern void AddSC_npc_narm_faulk();
//Durotar
//Duskwood
//Duskwallow marsh
extern void AddSC_npc_lady_jaina_proudmoore();
//Eversong Woods
extern void AddSC_mobs_mana_tapped();
//Exodar
//Eastern Plaguelands
extern void AddSC_mobs_ghoul_flayer();
extern void AddSC_npc_darrowshire_spirit();
//Elwynn Forest
extern void AddSC_npc_henze_faulk();
//Felwood
//Feralas
//Ghostlands
//Gnomeregan
//Gruul's Lair
extern void AddSC_boss_gruul();
extern void AddSC_boss_high_king_maulgar();
extern void AddSC_instance_gruuls_lair();
extern void AddSC_mob_gruuls_lair();
//Hellfire Citadel
//--Blood Furnace
extern void AddSC_boss_broggok();
extern void AddSC_boss_kelidan_the_breaker();
extern void AddSC_boss_the_maker();
//--Magtheridon's Lair
extern void AddSC_boss_magtheridon();
//--Shattered Halls
extern void AddSC_boss_grand_warlock_nethekurse();
//--Ramparts
extern void AddSC_boss_watchkeeper_gargolmar();
extern void AddSC_boss_omor_the_unscarred();
//Hellfire Peninsula
extern void AddSC_boss_doomlordkazzak();
extern void AddSC_mobs_bonechewer_orc();
//Hillsbrad Foothills
//Hinterlands
//Ironforge
//Karazhan
extern void AddSC_boss_attumen();
extern void AddSC_boss_curator();
extern void AddSC_boss_maiden_of_virtue();
extern void AddSC_boss_shade_of_aran();
extern void AddSC_boss_malchezaar();
extern void AddSC_boss_terestian_illhoof();
extern void AddSC_mob_homunculus();
extern void AddSC_mob_kilrek();
extern void AddSC_netherspite_infernal();
//Loch Modan
//Lower Blackrock Spire
//Magtheridon's Lair
//Maraudon
extern void AddSC_boss_landslide();
extern void AddSC_boss_lord_vyletongue();
extern void AddSC_boss_noxxion();
extern void AddSC_boss_ptheradras();
extern void AddSC_boss_rotgrip();
extern void AddSC_boss_tinkerergizlock();
extern void AddSC_celebras_the_cursed();
extern void AddSC_meshlok_the_harvester();
extern void AddSC_razorlash();
//Molten core
extern void AddSC_boss_lucifron();
extern void AddSC_boss_magmadar();
extern void AddSC_boss_gehennas();
extern void AddSC_boss_garr();
extern void AddSC_boss_baron_geddon();
extern void AddSC_boss_shazzrah();
extern void AddSC_boss_golemagg();
extern void AddSC_boss_sulfuron();
extern void AddSC_boss_majordomo();
extern void AddSC_boss_ragnaros();
extern void AddSC_mob_firelord();
extern void AddSC_mob_molten_giant();
extern void AddSC_mob_ancient_core_hound();
extern void AddSC_mob_molten_destroyer();
extern void AddSC_mob_firewalker();
extern void AddSC_mob_flame_guard();
extern void AddSC_mob_flamewaker();
extern void AddSC_mob_flamewaker_elite();
extern void AddSC_mob_flamewaker_healer();
extern void AddSC_mob_flamewaker_protector();
extern void AddSC_mob_core_rager();
extern void AddSC_mob_lavaspawn();
//Moonglade
extern void AddSC_silva_filnaveth();
extern void AddSC_bunthen_plainswind();
extern void AddSC_npc_great_bear_spirit();
//Mulgore
extern void AddSC_skorn_whitecloud();
//Nagrand
extern void AddSC_mobs_nagrand();
extern void AddSC_npcs_nagrand();
//Naxxramas
extern void AddSC_boss_anubrekhan();
extern void AddSC_boss_maexxna();
extern void AddSC_boss_patchwerk();
extern void AddSC_boss_razuvious();
extern void AddSC_boss_highlord_mograine();
extern void AddSC_boss_lady_blaumeux();
extern void AddSC_boss_sir_zeliek();
extern void AddSC_boss_thane_korthazz();
extern void AddSC_boss_kelthuzad();
extern void AddSC_boss_faerlina();
extern void AddSC_boss_loatheb();
extern void AddSC_boss_noth();
extern void AddSC_boss_gluth();
//Netherstorm
//Onyxia's Lair
extern void AddSC_boss_onyxia();
//Orgrimmar
//Ragefire Chasm
//Razorfen Downs
extern void AddSC_boss_amnennar_the_coldbringer();
//Redridge Mountains
//Ruins of Ahn'Qiraj
//Scarlet Monastery
extern void AddSC_boss_arcanist_doan();
extern void AddSC_boss_azshir_the_sleepless();
extern void AddSC_boss_bloodmage_thalnos();
extern void AddSC_boss_herod();
extern void AddSC_boss_high_inquisitor_fairbanks();
extern void AddSC_boss_high_inquisitor_whitemane();
extern void AddSC_boss_houndmaster_loksey();
extern void AddSC_boss_interrogator_vishas();
extern void AddSC_boss_scarlet_commander_mograine();
extern void AddSC_boss_scorn();
extern void AddSC_scarlet_torturer();
//Scholomance
extern void AddSC_boss_death_knight_darkreaver();
extern void AddSC_boss_theolenkrastinov();
extern void AddSC_boss_illuciabarov();
extern void AddSC_boss_instructormalicia();
extern void AddSC_boss_jandicebarov();
extern void AddSC_boss_kormok();
extern void AddSC_boss_lordalexeibarov();
extern void AddSC_boss_lorekeeperpolkelt();
extern void AddSC_boss_rasfrost();
extern void AddSC_boss_theravenian();
extern void AddSC_boss_vectus();
//Searing gorge
extern void AddSC_npc_lothos_riftwalker();
//Shadowfang keep
//Shadowmoon Valley
extern void AddSC_neltharaku();
//Shattrath
extern void AddSC_npc_shattrathflaskvendors();
//Silithus
extern void AddSC_npcs_captains_blackanvil_and_skullsplit();
extern void AddSC_npcs_rutgar_and_frankal();
//Silvermoon
extern void AddSC_npc_blood_knight_stillblade();
//Silverpine forest
//Stockade
//Stonetalon mountains
//Stormwind City
extern void AddSC_npc_bartleby();
extern void AddSC_npc_dashel_stonefist();
//Stranglethorn Vale
extern void AddSC_mobs_stranglethorn_vale();
//Stratholme
extern void AddSC_boss_fras_siabi();
extern void AddSC_boss_hearthsinger_forresten();
extern void AddSC_boss_magistrate_barthilas();
extern void AddSC_boss_maleki_the_pallid();
extern void AddSC_boss_skul();
extern void AddSC_boss_nerubenkan();
extern void AddSC_boss_the_unforgiven();
extern void AddSC_boss_cannon_master_willey();
extern void AddSC_boss_baroness_anastari();
extern void AddSC_boss_archivist_galford();
extern void AddSC_boss_crimson_hammersmith();
extern void AddSC_boss_ramstein_the_gorger();
extern void AddSC_boss_malor_the_zealous();
extern void AddSC_boss_black_guard_swordsmith();
extern void AddSC_boss_timmy_the_cruel();
extern void AddSC_boss_stonespine();
extern void AddSC_boss_postmaster_malown();
extern void AddSC_boss_baron_rivendare();
extern void AddSC_mobs_stratholme();
//Sunken Temple
//Tanaris
extern void AddSC_npcs_tanaris();
//Teldrassil
//Tempest Keep
//--Arcatraz
//--Botanica
//--The Eye
extern void AddSC_boss_kaelthas();
extern void AddSC_boss_void_reaver();
extern void AddSC_instance_the_eye();
extern void AddSC_mob_crystalcore_devastator();
extern void AddSC_mob_the_eye();
//--The Mechanar
//Temple of ahn'qiraj
extern void AddSC_Yauj();
extern void AddSC_Kri();
extern void AddSC_Vem();
extern void AddSC_boss_cthun();
//Terokkar Forest
extern void AddSC_mobs_terokkar_forest();
//Thousand Needles
//Thunder Bluff
extern void AddSC_npc_cairne_bloodhoof();
//Tirisfal Glades
//Uldaman
extern void AddSC_boss_ironaya();
extern void AddSC_mob_jadespine_basilisk();
extern void AddSC_mob_uldaman();
//Undercity
//Un'Goro Crater
//Upper blackrock spire
//Wailing caverns
extern void AddSC_boss_wailing_caverns();
//Western plaguelands
//Westfall
//Wetlands
//Winterspring
//Zangramarsh
extern void AddSC_npcs_zangarmarsh();
//Zul'Farrak
//Zul'Gurub
// -------------------
MANGOS_DLL_EXPORT
void ScriptsFree()
{
// Free Spell Summary
delete []SpellSummary;
// Free resources before library unload
for(int i=0;iName == Name )
return m_scripts[i];
}
return NULL;
}
//********************************
//*** Functions to be Exported ***
MANGOS_DLL_EXPORT
bool GossipHello ( Player * player, Creature *_Creature )
{
Script *tmpscript = NULL;
tmpscript = GetScriptByName(_Creature->GetCreatureInfo()->ScriptName);
if(!tmpscript || !tmpscript->pGossipHello) return false;
player->PlayerTalkClass->ClearMenus();
return tmpscript->pGossipHello(player,_Creature);
}
MANGOS_DLL_EXPORT
bool GossipSelect( Player *player, Creature *_Creature,uint32 sender, uint32 action )
{
Script *tmpscript = NULL;
printf("action: %d\n",action);
tmpscript = GetScriptByName(_Creature->GetCreatureInfo()->ScriptName);
if(!tmpscript || !tmpscript->pGossipSelect) return false;
player->PlayerTalkClass->ClearMenus();
return tmpscript->pGossipSelect(player,_Creature,sender,action);
}
MANGOS_DLL_EXPORT
bool GossipSelectWithCode( Player *player, Creature *_Creature, uint32 sender, uint32 action, char* sCode )
{
Script *tmpscript = NULL;
tmpscript = GetScriptByName(_Creature->GetCreatureInfo()->ScriptName);
if(!tmpscript || !tmpscript->pGossipSelectWithCode) return false;
player->PlayerTalkClass->ClearMenus();
return tmpscript->pGossipSelectWithCode(player,_Creature,sender,action,sCode);
}
MANGOS_DLL_EXPORT
bool QuestAccept( Player *player, Creature *_Creature, Quest const *_Quest )
{
Script *tmpscript = NULL;
tmpscript = GetScriptByName(_Creature->GetCreatureInfo()->ScriptName);
if(!tmpscript || !tmpscript->pQuestAccept) return false;
player->PlayerTalkClass->ClearMenus();
return tmpscript->pQuestAccept(player,_Creature,_Quest);
}
MANGOS_DLL_EXPORT
bool QuestSelect( Player *player, Creature *_Creature, Quest const *_Quest )
{
Script *tmpscript = NULL;
tmpscript = GetScriptByName(_Creature->GetCreatureInfo()->ScriptName);
if(!tmpscript || !tmpscript->pQuestSelect) return false;
player->PlayerTalkClass->ClearMenus();
return tmpscript->pQuestSelect(player,_Creature,_Quest);
}
MANGOS_DLL_EXPORT
bool QuestComplete( Player *player, Creature *_Creature, Quest const *_Quest )
{
Script *tmpscript = NULL;
tmpscript = GetScriptByName(_Creature->GetCreatureInfo()->ScriptName);
if(!tmpscript || !tmpscript->pQuestComplete) return false;
player->PlayerTalkClass->ClearMenus();
return tmpscript->pQuestComplete(player,_Creature,_Quest);
}
MANGOS_DLL_EXPORT
bool ChooseReward( Player *player, Creature *_Creature, Quest const *_Quest, uint32 opt )
{
Script *tmpscript = NULL;
tmpscript = GetScriptByName(_Creature->GetCreatureInfo()->ScriptName);
if(!tmpscript || !tmpscript->pChooseReward) return false;
player->PlayerTalkClass->ClearMenus();
return tmpscript->pChooseReward(player,_Creature,_Quest,opt);
}
MANGOS_DLL_EXPORT
uint32 NPCDialogStatus( Player *player, Creature *_Creature )
{
Script *tmpscript = NULL;
tmpscript = GetScriptByName(_Creature->GetCreatureInfo()->ScriptName);
if(!tmpscript || !tmpscript->pNPCDialogStatus) return 100;
player->PlayerTalkClass->ClearMenus();
return tmpscript->pNPCDialogStatus(player,_Creature);
}
MANGOS_DLL_EXPORT
bool ItemHello( Player *player, Item *_Item, Quest const *_Quest )
{
Script *tmpscript = NULL;
tmpscript = GetScriptByName(_Item->GetProto()->ScriptName);
if(!tmpscript || !tmpscript->pItemHello) return false;
player->PlayerTalkClass->ClearMenus();
return tmpscript->pItemHello(player,_Item,_Quest);
}
MANGOS_DLL_EXPORT
bool ItemQuestAccept( Player *player, Item *_Item, Quest const *_Quest )
{
Script *tmpscript = NULL;
tmpscript = GetScriptByName(_Item->GetProto()->ScriptName);
if(!tmpscript || !tmpscript->pItemQuestAccept) return false;
player->PlayerTalkClass->ClearMenus();
return tmpscript->pItemQuestAccept(player,_Item,_Quest);
}
MANGOS_DLL_EXPORT
bool GOHello( Player *player, GameObject *_GO )
{
Script *tmpscript = NULL;
tmpscript = GetScriptByName(_GO->GetGOInfo()->ScriptName);
if(!tmpscript || !tmpscript->pGOHello) return false;
player->PlayerTalkClass->ClearMenus();
return tmpscript->pGOHello(player,_GO);
}
MANGOS_DLL_EXPORT
bool GOQuestAccept( Player *player, GameObject *_GO, Quest const *_Quest )
{
Script *tmpscript = NULL;
tmpscript = GetScriptByName(_GO->GetGOInfo()->ScriptName);
if(!tmpscript || !tmpscript->pGOQuestAccept) return false;
player->PlayerTalkClass->ClearMenus();
return tmpscript->pGOQuestAccept(player,_GO,_Quest);
}
MANGOS_DLL_EXPORT
bool GOChooseReward( Player *player, GameObject *_GO, Quest const *_Quest, uint32 opt )
{
Script *tmpscript = NULL;
tmpscript = GetScriptByName(_GO->GetGOInfo()->ScriptName);
if(!tmpscript || !tmpscript->pGOChooseReward) return false;
player->PlayerTalkClass->ClearMenus();
return tmpscript->pGOChooseReward(player,_GO,_Quest,opt);
}
MANGOS_DLL_EXPORT
bool AreaTrigger ( Player *player, Quest const *_Quest, uint32 triggerID )
{
Script *tmpscript = NULL;
// TODO: load a script name for the areatriggers
//tmpscript = GetScriptByName();
if(!tmpscript || !tmpscript->pAreaTrigger) return false;
player->PlayerTalkClass->ClearMenus();
return tmpscript->pAreaTrigger(player,_Quest,triggerID);
}
MANGOS_DLL_EXPORT
CreatureAI* GetAI(Creature *_Creature)
{
Script *tmpscript = GetScriptByName(_Creature->GetCreatureInfo()->ScriptName);
if(!tmpscript || !tmpscript->GetAI) return NULL;
return tmpscript->GetAI(_Creature);
}
MANGOS_DLL_EXPORT
bool ItemUse( Player *player, Item* _Item, SpellCastTargets const& targets)
{
Script *tmpscript = NULL;
tmpscript = GetScriptByName(_Item->GetProto()->ScriptName);
if(!tmpscript || !tmpscript->pItemUse) return false;
return tmpscript->pItemUse(player,_Item,targets);
}
MANGOS_DLL_EXPORT
bool ReceiveEmote( Player *player, Creature *_Creature, uint32 emote )
{
Script *tmpscript = NULL;
tmpscript = GetScriptByName(_Creature->GetCreatureInfo()->ScriptName);
if(!tmpscript || !tmpscript->pReceiveEmote) return false;
return tmpscript->pReceiveEmote(player, _Creature, emote);
}
MANGOS_DLL_EXPORT
InstanceData* CreateInstanceData(Map *map)
{
Script *tmpscript = NULL;
tmpscript = GetScriptByName(map->GetScript());
if(!tmpscript || !tmpscript->GetInstanceData) return false;
return tmpscript->GetInstanceData(map);
}
bool ScriptedAI::IsVisible(Unit* who) const
{
if (!who)
return false;
return m_creature->IsWithinDistInMap(who, VISIBLE_RANGE) && who->isVisibleForOrDetect(m_creature,true);
}
void ScriptedAI::AttackStart(Unit* who)
{
if (!who)
return;
if (who->isTargetableForAttack())
{
//Begin attack
DoStartMeleeAttack(who);
}
}
void ScriptedAI::UpdateAI(const uint32 diff)
{
//Check if we have a current target
if( m_creature->isAlive() && m_creature->SelectHostilTarget() && m_creature->getVictim())
{
//If we are within range melee the target
if( m_creature->IsWithinDistInMap(m_creature->getVictim(), ATTACK_DISTANCE))
{
if( m_creature->isAttackReady() )
{
m_creature->AttackerStateUpdate(m_creature->getVictim());
m_creature->resetAttackTimer();
}
}
}
}
void ScriptedAI::EnterEvadeMode()
{
m_creature->RemoveAllAuras();
m_creature->DeleteThreatList();
m_creature->CombatStop();
DoGoHome();
}
void ScriptedAI::DoStartMeleeAttack(Unit* victim)
{
if (!victim)
return;
if ( m_creature->Attack(victim) )
{
m_creature->GetMotionMaster()->Mutate(new TargetedMovementGenerator(*victim));
m_creature->AddThreat(victim, 0.0f);
m_creature->resetAttackTimer();
if (victim->GetTypeId() == TYPEID_PLAYER)
m_creature->SetLootRecipient((Player*)victim);
}
}
void ScriptedAI::DoMeleeAttackIfReady()
{
//If we are within range melee the target
if( m_creature->IsWithinDistInMap(m_creature->getVictim(), ATTACK_DISTANCE))
{
//Make sure our attack is ready and we arn't currently casting
if( m_creature->isAttackReady() && !m_creature->IsNonMeleeSpellCasted(false))
{
m_creature->AttackerStateUpdate(m_creature->getVictim());
m_creature->resetAttackTimer();
}
}
}
void ScriptedAI::DoStartRangedAttack(Unit* victim)
{
if (!victim)
return;
if (m_creature->Attack(victim))
{
m_creature->AddThreat(victim, 0.0f);
m_creature->resetAttackTimer();
if (victim->GetTypeId() == TYPEID_PLAYER)
m_creature->SetLootRecipient((Player*)victim);
}
}
void ScriptedAI::DoStopAttack()
{
if( m_creature->getVictim() != NULL )
{
m_creature->AttackStop();
}
}
void ScriptedAI::DoCast(Unit* victim, uint32 spelId, bool triggered)
{
if (!victim || m_creature->IsNonMeleeSpellCasted(false))
return;
m_creature->StopMoving();
m_creature->CastSpell(victim, spelId, triggered);
}
void ScriptedAI::DoCastSpell(Unit* who,SpellEntry const *spellInfo, bool triggered)
{
if (!who || m_creature->IsNonMeleeSpellCasted(false))
return;
m_creature->StopMoving();
m_creature->CastSpell(who, spellInfo, triggered);
}
void ScriptedAI::DoSay(const char* text, uint32 language, Unit* target)
{
if (target)m_creature->Say(text, language, target->GetGUID());
else m_creature->Say(text, language, 0);
}
void ScriptedAI::DoYell(const char* text, uint32 language, Unit* target)
{
if (target)m_creature->Yell(text, language, target->GetGUID());
else m_creature->Yell(text, language, 0);
}
void ScriptedAI::DoTextEmote(const char* text, Unit* target)
{
if (target)m_creature->TextEmote(text, target->GetGUID());
else m_creature->TextEmote(text, 0);
}
void ScriptedAI::DoGoHome()
{
if( !m_creature->getVictim() && m_creature->isAlive() )
{
if( (*m_creature).GetMotionMaster()->top()->GetMovementGeneratorType() == TARGETED_MOTION_TYPE )
m_creature->GetMotionMaster()->TargetedHome();
}
}
void ScriptedAI::DoPlaySoundToSet(Unit* unit, uint32 sound)
{
if (!unit)
return;
WorldPacket data(4);
data.SetOpcode(SMSG_PLAY_SOUND);
data << uint32(sound);
unit->SendMessageToSet(&data,false);
}
void ScriptedAI::DoFaceTarget(Unit *unit)
{
if (!unit)
return;
//Face target
m_creature->SetInFront(unit);
}
Creature* ScriptedAI::DoSpawnCreature(uint32 id, float x, float y, float z, float angle, uint32 type, uint32 despawntime)
{
return m_creature->SummonCreature(id,m_creature->GetPositionX() + x,m_creature->GetPositionY() + y,m_creature->GetPositionZ() + z, angle, (TempSummonType)type, despawntime);
}
Unit* ScriptedAI::SelectUnit(SelectAggroTarget target, uint32 position)
{
//ThreatList m_threatlist;
std::list& m_threatlist = m_creature->getThreatManager().getThreatList();
std::list::iterator i = m_threatlist.begin();
std::list::reverse_iterator r = m_threatlist.rbegin();
if (position >= m_threatlist.size() || !m_threatlist.size())
return NULL;
switch (target)
{
case SELECT_TARGET_RANDOM:
advance ( i , position + (rand() % (m_threatlist.size() - position ) ));
return Unit::GetUnit((*m_creature),(*i)->getUnitGuid());
break;
case SELECT_TARGET_TOPAGGRO:
advance ( i , position);
return Unit::GetUnit((*m_creature),(*i)->getUnitGuid());
break;
case SELECT_TARGET_BOTTOMAGGRO:
advance ( r , position);
return Unit::GetUnit((*m_creature),(*r)->getUnitGuid());
break;
}
return NULL;
}
SpellEntry const* ScriptedAI::SelectSpell(Unit* Target, int32 School, int32 Mechanic, SelectTarget Targets, uint32 PowerCostMin, uint32 PowerCostMax, float RangeMin, float RangeMax, SelectEffect Effects)
{
//No target so we can't cast
if (!Target)
return false;
//Silenced so we can't cast
if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED))
return false;
//Using the extended script system we first create a list of viable spells
SpellEntry const* Spell[4];
Spell[0] = 0;
Spell[1] = 0;
Spell[2] = 0;
Spell[3] = 0;
uint32 SpellCount = 0;
SpellEntry const* TempSpell;
SpellRangeEntry const* TempRange;
//Check if each spell is viable(set it to null if not)
for (uint32 i = 0; i < 4; i++)
{
TempSpell = GetSpellStore()->LookupEntry(m_creature->m_spells[i]);
//This spell doesn't exist
if (!TempSpell)
continue;
// Targets and Effects checked first as most used restrictions
//Check the spell targets if specified
if ( Targets && !(SpellSummary[m_creature->m_spells[i]].Targets & (1 << (Targets-1))) )
continue;
//Check the type of spell if we are looking for a specific spell type
if ( Effects && !(SpellSummary[m_creature->m_spells[i]].Effects & (1 << (Effects-1))) )
continue;
//Check for school if specified
if (School >= 0 && TempSpell->School != School)
continue;
//Check for spell mechanic if specified
if (Mechanic >= 0 && TempSpell->Mechanic != Mechanic)
continue;
//Make sure that the spell uses the requested amount of power
if (PowerCostMin && TempSpell->manaCost < PowerCostMin)
continue;
if (PowerCostMax && TempSpell->manaCost > PowerCostMax)
continue;
//Continue if we don't have the mana to actually cast this spell
if (TempSpell->manaCost > m_creature->GetPower((Powers)TempSpell->powerType))
continue;
//Get the Range
TempRange = GetSpellRangeStore()->LookupEntry(TempSpell->rangeIndex);
//Spell has invalid range store so we can't use it
if (!TempRange)
continue;
//Check if the spell meets our range requirements
if (RangeMin && TempRange->maxRange < RangeMin)
continue;
if (RangeMax && TempRange->maxRange > RangeMax)
continue;
//Check if our target is in range
if (m_creature->IsWithinDistInMap(Target, TempRange->minRange) || !m_creature->IsWithinDistInMap(Target, TempRange->maxRange))
continue;
//All good so lets add it to the spell list
Spell[SpellCount] = TempSpell;
SpellCount++;
}
//We got our usable spells so now lets randomly pick one
if (!SpellCount)
return NULL;
return Spell[rand()%SpellCount];
}
bool ScriptedAI::CanCast(Unit* Target, SpellEntry const *Spell)
{
//No target so we can't cast
if (!Target)
return false;
//Silenced so we can't cast
if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED))
return false;
//Check for power
if (m_creature->GetPower((Powers)Spell->powerType) < Spell->manaCost)
return false;
SpellRangeEntry const *TempRange = NULL;
TempRange = GetSpellRangeStore()->LookupEntry(Spell->rangeIndex);
//Spell has invalid range store so we can't use it
if (!TempRange)
return false;
//Unit is out of range of this spell
if (m_creature->GetDistanceSq(Target) > TempRange->maxRange*TempRange->maxRange || m_creature->GetDistanceSq(Target) < TempRange->minRange*TempRange->minRange)
return false;
return true;
}
void FillSpellSummary()
{
SpellSummary = new TSpellSummary[GetSpellStore()->GetNumRows()];
SpellEntry const* TempSpell;
for (int i=0; i < GetSpellStore()->GetNumRows(); i++ )
{
SpellSummary[i].Effects = 0;
SpellSummary[i].Targets = 0;
TempSpell = GetSpellStore()->LookupEntry(i);
//This spell doesn't exist
if (!TempSpell)
continue;
for (int j=0; j<3; j++)
{
//Spell targets self
if ( TempSpell->EffectImplicitTargetA[j] == TARGET_SELF )
SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SELF-1);
//Spell targets a single enemy
if ( TempSpell->EffectImplicitTargetA[j] == TARGET_CHAIN_DAMAGE ||
TempSpell->EffectImplicitTargetA[j] == TARGET_CURRENT_SELECTED_ENEMY )
SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SINGLE_ENEMY-1);
//Spell targets AoE at enemy
if ( TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA ||
TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA_INSTANT ||
TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_AROUND_CASTER ||
TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA_CHANNELED )
SpellSummary[i].Targets |= 1 << (SELECT_TARGET_AOE_ENEMY-1);
//Spell targets an enemy
if ( TempSpell->EffectImplicitTargetA[j] == TARGET_CHAIN_DAMAGE ||
TempSpell->EffectImplicitTargetA[j] == TARGET_CURRENT_SELECTED_ENEMY ||
TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA ||
TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA_INSTANT ||
TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_AROUND_CASTER ||
TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA_CHANNELED )
SpellSummary[i].Targets |= 1 << (SELECT_TARGET_ANY_ENEMY-1);
//Spell targets a single friend(or self)
if ( TempSpell->EffectImplicitTargetA[j] == TARGET_SELF ||
TempSpell->EffectImplicitTargetA[j] == TARGET_SINGLE_FRIEND ||
TempSpell->EffectImplicitTargetA[j] == TARGET_SINGLE_PARTY )
SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SINGLE_FRIEND-1);
//Spell targets aoe friends
if ( TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_PARTY_AROUND_CASTER ||
TempSpell->EffectImplicitTargetA[j] == TARGET_AREAEFFECT_PARTY ||
TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_AROUND_CASTER)
SpellSummary[i].Targets |= 1 << (SELECT_TARGET_AOE_FRIEND-1);
//Spell targets any friend(or self)
if ( TempSpell->EffectImplicitTargetA[j] == TARGET_SELF ||
TempSpell->EffectImplicitTargetA[j] == TARGET_SINGLE_FRIEND ||
TempSpell->EffectImplicitTargetA[j] == TARGET_SINGLE_PARTY ||
TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_PARTY_AROUND_CASTER ||
TempSpell->EffectImplicitTargetA[j] == TARGET_AREAEFFECT_PARTY ||
TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_AROUND_CASTER)
SpellSummary[i].Targets |= 1 << (SELECT_TARGET_ANY_FRIEND-1);
//Make sure that this spell includes a damage effect
if ( TempSpell->Effect[j] == SPELL_EFFECT_SCHOOL_DAMAGE ||
TempSpell->Effect[j] == SPELL_EFFECT_INSTAKILL ||
TempSpell->Effect[j] == SPELL_EFFECT_ENVIRONMENTAL_DAMAGE ||
TempSpell->Effect[j] == SPELL_EFFECT_HEALTH_LEECH )
SpellSummary[i].Effects |= 1 << (SELECT_EFFECT_DAMAGE-1);
//Make sure that this spell includes a healing effect (or an apply aura with a periodic heal)
if ( TempSpell->Effect[j] == SPELL_EFFECT_HEAL ||
TempSpell->Effect[j] == SPELL_EFFECT_HEAL_MAX_HEALTH ||
TempSpell->Effect[j] == SPELL_EFFECT_HEAL_MECHANICAL ||
(TempSpell->Effect[j] == SPELL_EFFECT_APPLY_AURA && TempSpell->EffectApplyAuraName[j]== 8 ))
SpellSummary[i].Effects |= 1 << (SELECT_EFFECT_HEALING-1);
//Make sure that this spell applies an aura
if ( TempSpell->Effect[j] == SPELL_EFFECT_APPLY_AURA )
SpellSummary[i].Effects |= 1 << (SELECT_EFFECT_AURA-1);
}
}
}