aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bindings/scripts/scripts/npc/npcs_special.cpp1823
-rw-r--r--src/game/Creature.cpp11
-rw-r--r--src/game/Creature.h2
-rw-r--r--src/game/PetHandler.cpp7
-rw-r--r--src/game/Player.cpp132
-rw-r--r--src/game/PossessedAI.cpp4
-rw-r--r--src/game/SharedDefines.h2
-rw-r--r--src/game/Spell.cpp2
-rw-r--r--src/game/SpellAuras.cpp8
-rw-r--r--src/game/SpellEffects.cpp24
-rw-r--r--src/game/SpellHandler.cpp9
-rw-r--r--src/game/Unit.cpp37
-rw-r--r--src/game/Unit.h5
13 files changed, 1086 insertions, 980 deletions
diff --git a/src/bindings/scripts/scripts/npc/npcs_special.cpp b/src/bindings/scripts/scripts/npc/npcs_special.cpp
index 00116746a68..61091ab54e2 100644
--- a/src/bindings/scripts/scripts/npc/npcs_special.cpp
+++ b/src/bindings/scripts/scripts/npc/npcs_special.cpp
@@ -1,878 +1,945 @@
-/* Copyright (C) 2006 - 2008 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
- */
-
-/* ScriptData
-SDName: Npcs_Special
-SD%Complete: 100
-SDComment: To be used for special NPCs that are located globally. Support for quest 3861 (Cluck!), 6622 and 6624 (Triage)
-SDCategory: NPCs
-EndScriptData
-*/
-
-/* ContentData
-npc_chicken_cluck 100% support for quest 3861 (Cluck!)
-npc_dancing_flames 100% midsummer event NPC
-npc_guardian 100% guardianAI used to prevent players from accessing off-limits areas. Not in use by SD2
-npc_injured_patient 100% patients for triage-quests (6622 and 6624)
-npc_doctor 100% Gustaf Vanhowzen and Gregory Victor, quest 6622 and 6624 (Triage)
-npc_mount_vendor 100% Regular mount vendors all over the world. Display gossip if player doesn't meet the requirements to buy
-npc_rogue_trainer 80% Scripted trainers, so they are able to offer item 17126 for class quest 6681
-npc_sayge 100% Darkmoon event fortune teller, buff player based on answers given
-EndContentData */
-
-#include "precompiled.h"
-
-/*########
-# npc_chicken_cluck
-#########*/
-
-#define QUEST_CLUCK 3861
-#define EMOTE_A_HELLO "looks up at you quizzically. Maybe you should inspect it?"
-#define EMOTE_H_HELLO "looks at you unexpectadly."
-#define CLUCK_TEXT2 "starts pecking at the feed."
-#define FACTION_FRIENDLY 84
-#define FACTION_CHICKEN 31
-
-struct TRINITY_DLL_DECL npc_chicken_cluckAI : public ScriptedAI
-{
- npc_chicken_cluckAI(Creature *c) : ScriptedAI(c) {Reset();}
-
- uint32 ResetFlagTimer;
-
- void Reset()
- {
- ResetFlagTimer = 120000;
-
- m_creature->setFaction(FACTION_CHICKEN);
- m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER);
- }
-
- void Aggro(Unit *who) {}
-
- void UpdateAI(const uint32 diff)
- {
- // Reset flags after a certain time has passed so that the next player has to start the 'event' again
- if(m_creature->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER))
- {
- if(ResetFlagTimer < diff)
- EnterEvadeMode();
- else ResetFlagTimer -= diff;
- }
-
- if(m_creature->SelectHostilTarget() && m_creature->getVictim())
- DoMeleeAttackIfReady();
- }
-};
-
-CreatureAI* GetAI_npc_chicken_cluck(Creature *_Creature)
-{
- return new npc_chicken_cluckAI(_Creature);
-}
-
-bool ReceiveEmote_npc_chicken_cluck( Player *player, Creature *_Creature, uint32 emote )
-{
- if( emote == TEXTEMOTE_CHICKEN )
- {
- if( player->GetTeam() == ALLIANCE )
- {
- if( rand()%30 == 1 )
- {
- if( player->GetQuestStatus(QUEST_CLUCK) == QUEST_STATUS_NONE )
- {
- _Creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER);
- _Creature->setFaction(FACTION_FRIENDLY);
- _Creature->MonsterTextEmote(EMOTE_A_HELLO, 0);
- }
- }
- } else
- _Creature->MonsterTextEmote(EMOTE_H_HELLO,0);
- }
- if( emote == TEXTEMOTE_CHEER && player->GetTeam() == ALLIANCE )
- if( player->GetQuestStatus(QUEST_CLUCK) == QUEST_STATUS_COMPLETE )
- {
- _Creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER);
- _Creature->setFaction(FACTION_FRIENDLY);
- _Creature->MonsterTextEmote(CLUCK_TEXT2, 0);
- }
-
- return true;
-}
-
-bool QuestAccept_npc_chicken_cluck(Player *player, Creature *_Creature, const Quest *_Quest )
-{
- if(_Quest->GetQuestId() == QUEST_CLUCK)
- ((npc_chicken_cluckAI*)_Creature->AI())->Reset();
-
- return true;
-}
-
-bool QuestComplete_npc_chicken_cluck(Player *player, Creature *_Creature, const Quest *_Quest)
-{
- if(_Quest->GetQuestId() == QUEST_CLUCK)
- ((npc_chicken_cluckAI*)_Creature->AI())->Reset();
-
- return true;
-}
-
-/*######
-## npc_dancing_flames
-######*/
-
-bool ReceiveEmote_npc_dancing_flames( Player *player, Creature *_Creature, uint32 emote )
-{
- if( emote == TEXTEMOTE_DANCE )
- _Creature->CastSpell(player,47057,false);
-
- return true;
-}
-
-/*######
-## Triage quest
-######*/
-
-#define SAY_DOC1 "I'm saved! Thank you, doctor!"
-#define SAY_DOC2 "HOORAY! I AM SAVED!"
-#define SAY_DOC3 "Sweet, sweet embrace... take me..."
-
-struct Location
-{
- float x, y, z, o;
-};
-
-#define DOCTOR_ALLIANCE 12939
-
-static Location AllianceCoords[]=
-{
- { // Top-far-right bunk as seen from entrance
- -3757.38, -4533.05, 14.16, 3.62
- },
- { // Top-far-left bunk
- -3754.36, -4539.13, 14.16, 5.13
- },
- { // Far-right bunk
- -3749.54, -4540.25, 14.28, 3.34
- },
- { // Right bunk near entrance
- -3742.10, -4536.85, 14.28, 3.64
- },
- { // Far-left bunk
- -3755.89, -4529.07, 14.05, 0.57
- },
- { // Mid-left bunk
- -3749.51, -4527.08, 14.07, 5.26
- },
- { // Left bunk near entrance
- -3746.37, -4525.35, 14.16, 5.22
- },
-};
-
-#define ALLIANCE_COORDS 7
-
-//alliance run to where
-#define A_RUNTOX -3742.96
-#define A_RUNTOY -4531.52
-#define A_RUNTOZ 11.91
-
-#define DOCTOR_HORDE 12920
-
-static Location HordeCoords[]=
-{
- { // Left, Behind
- -1013.75, -3492.59, 62.62, 4.34
- },
- { // Right, Behind
- -1017.72, -3490.92, 62.62, 4.34
- },
- { // Left, Mid
- -1015.77, -3497.15, 62.82, 4.34
- },
- { // Right, Mid
- -1019.51, -3495.49, 62.82, 4.34
- },
- { // Left, front
- -1017.25, -3500.85, 62.98, 4.34
- },
- { // Right, Front
- -1020.95, -3499.21, 62.98, 4.34
- }
-};
-
-#define HORDE_COORDS 6
-
-//horde run to where
-#define H_RUNTOX -1016.44
-#define H_RUNTOY -3508.48
-#define H_RUNTOZ 62.96
-
-const uint32 AllianceSoldierId[3] =
-{
- 12938, // 12938 Injured Alliance Soldier
- 12936, // 12936 Badly injured Alliance Soldier
- 12937 // 12937 Critically injured Alliance Soldier
-};
-
-const uint32 HordeSoldierId[3] =
-{
- 12923, //12923 Injured Soldier
- 12924, //12924 Badly injured Soldier
- 12925 //12925 Critically injured Soldier
-};
-
-/*######
-## npc_doctor (handles both Gustaf Vanhowzen and Gregory Victor)
-######*/
-
-struct TRINITY_DLL_DECL npc_doctorAI : public ScriptedAI
-{
- uint64 Playerguid;
-
- uint32 SummonPatient_Timer;
- uint32 SummonPatientCount;
- uint32 PatientDiedCount;
- uint32 PatientSavedCount;
-
- bool Event;
-
- std::list<uint64> Patients;
- std::vector<Location*> Coordinates;
-
- npc_doctorAI(Creature *c) : ScriptedAI(c) {Reset();}
-
- void Reset(){}
-
- void BeginEvent(Player* player);
- void PatientDied(Location* Point);
- void PatientSaved(Creature* soldier, Player* player, Location* Point);
- void UpdateAI(const uint32 diff);
-
- void Aggro(Unit* who){}
-};
-
-/*#####
-## npc_injured_patient (handles all the patients, no matter Horde or Alliance)
-#####*/
-
-struct TRINITY_DLL_DECL npc_injured_patientAI : public ScriptedAI
-{
- npc_injured_patientAI(Creature *c) : ScriptedAI(c) {Reset();}
-
- uint64 Doctorguid;
-
- Location* Coord;
-
- void Reset()
- {
- Doctorguid = 0;
-
- Coord = NULL;
- //no select
- m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- //no regen health
- m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT);
- //to make them lay with face down
- m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, PLAYER_STATE_DEAD);
-
- uint32 mobId = m_creature->GetEntry();
-
- switch (mobId)
- { //lower max health
- case 12923:
- case 12938: //Injured Soldier
- m_creature->SetHealth(uint32(m_creature->GetMaxHealth()*.75));
- break;
- case 12924:
- case 12936: //Badly injured Soldier
- m_creature->SetHealth(uint32(m_creature->GetMaxHealth()*.50));
- break;
- case 12925:
- case 12937: //Critically injured Soldier
- m_creature->SetHealth(uint32(m_creature->GetMaxHealth()*.25));
- break;
- }
- }
-
- void Aggro(Unit* who){}
-
- void SpellHit(Unit *caster, const SpellEntry *spell)
- {
- if (caster->GetTypeId() == TYPEID_PLAYER && m_creature->isAlive() && spell->Id == 20804)
- {
- if( (((Player*)caster)->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE) || (((Player*)caster)->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE))
- {
- if(Doctorguid)
- {
- Creature* Doctor = ((Creature*)Unit::GetUnit((*m_creature), Doctorguid));
- if(Doctor)
- ((npc_doctorAI*)Doctor->AI())->PatientSaved(m_creature, ((Player*)caster), Coord);
- }
- }
- //make not selectable
- m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- //regen health
- m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT);
- //stand up
- m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, PLAYER_STATE_NONE);
- DoSay(SAY_DOC1,LANG_UNIVERSAL,NULL);
-
- uint32 mobId = m_creature->GetEntry();
- m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
- switch (mobId)
- {
- case 12923:
- case 12924:
- case 12925:
- m_creature->GetMotionMaster()->MovePoint(0, H_RUNTOX, H_RUNTOY, H_RUNTOZ);
- break;
- case 12936:
- case 12937:
- case 12938:
- m_creature->GetMotionMaster()->MovePoint(0, A_RUNTOX, A_RUNTOY, A_RUNTOZ);
- break;
- }
- }
- return;
- }
-
- void UpdateAI(const uint32 diff)
- {
- if (m_creature->isAlive() && m_creature->GetHealth() > 6)
- { //lower HP on every world tick makes it a useful counter, not officlone though
- m_creature->SetHealth(uint32(m_creature->GetHealth()-5) );
- }
-
- if (m_creature->isAlive() && m_creature->GetHealth() <= 6)
- {
- m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT);
- m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- m_creature->setDeathState(JUST_DIED);
- m_creature->SetFlag(UNIT_DYNAMIC_FLAGS, 32);
-
- if(Doctorguid)
- {
- Creature* Doctor = ((Creature*)Unit::GetUnit((*m_creature), Doctorguid));
- if(Doctor)
- ((npc_doctorAI*)Doctor->AI())->PatientDied(Coord);
- }
- }
- }
-};
-
-CreatureAI* GetAI_npc_injured_patient(Creature *_Creature)
-{
- return new npc_injured_patientAI (_Creature);
-}
-
-/*
-npc_doctor (continue)
-*/
-
-void npc_doctorAI::BeginEvent(Player* player)
-{
- Playerguid = player->GetGUID();
-
- SummonPatient_Timer = 10000;
- SummonPatientCount = 0;
- PatientDiedCount = 0;
- PatientSavedCount = 0;
-
- switch(m_creature->GetEntry())
- {
- case DOCTOR_ALLIANCE:
- for(uint8 i = 0; i < ALLIANCE_COORDS; ++i)
- Coordinates.push_back(&AllianceCoords[i]);
- break;
-
- case DOCTOR_HORDE:
- for(uint8 i = 0; i < HORDE_COORDS; ++i)
- Coordinates.push_back(&HordeCoords[i]);
- break;
- }
-
- Event = true;
-
- m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
-}
-
-void npc_doctorAI::PatientDied(Location* Point)
-{
- Player* player = ((Player*)Unit::GetUnit((*m_creature), Playerguid));
- if(player && ((player->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE) || (player->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE)))
- {
- PatientDiedCount++;
- if (PatientDiedCount > 5 && Event)
- {
- if(player->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE)
- player->FailQuest(6624);
- else if(player->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE)
- player->FailQuest(6622);
-
- Event = false;
- m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- }
-
- Coordinates.push_back(Point);
- }
-}
-
-void npc_doctorAI::PatientSaved(Creature* soldier, Player* player, Location* Point)
-{
- if(player && Playerguid == player->GetGUID())
- {
- if((player->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE) || (player->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE))
- {
- PatientSavedCount++;
- if(PatientSavedCount == 15)
- {
- if(!Patients.empty())
- {
- std::list<uint64>::iterator itr;
- for(itr = Patients.begin(); itr != Patients.end(); ++itr)
- {
- Creature* Patient = ((Creature*)Unit::GetUnit((*m_creature), *itr));
- if( Patient )
- Patient->setDeathState(JUST_DIED);
- }
- }
-
- if(player->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE)
- player->AreaExploredOrEventHappens(6624);
- else if(player->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE)
- player->AreaExploredOrEventHappens(6622);
-
- Event = false;
- m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- }
-
- Coordinates.push_back(Point);
- }
- }
-}
-
-void npc_doctorAI::UpdateAI(const uint32 diff)
-{
- if(Event && SummonPatientCount >= 20)
- {
- Event = false;
- m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- }
-
- if(Event)
- if(SummonPatient_Timer < diff)
- {
- Creature* Patient = NULL;
- Location* Point = NULL;
-
- if(Coordinates.empty())
- return;
-
- std::vector<Location*>::iterator itr = Coordinates.begin()+rand()%Coordinates.size();
- uint32 patientEntry = 0;
-
- switch(m_creature->GetEntry())
- {
- case DOCTOR_ALLIANCE: patientEntry = AllianceSoldierId[rand()%3]; break;
- case DOCTOR_HORDE: patientEntry = HordeSoldierId[rand()%3]; break;
- default:
- error_log("SD2: Invalid entry for Triage doctor. Please check your database");
- return;
- }
-
- Point = *itr;
-
- Patient = m_creature->SummonCreature(patientEntry, Point->x, Point->y, Point->z, Point->o, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
-
- if(Patient)
- {
- Patients.push_back(Patient->GetGUID());
- ((npc_injured_patientAI*)Patient->AI())->Doctorguid = m_creature->GetGUID();
- if(Point)
- ((npc_injured_patientAI*)Patient->AI())->Coord = Point;
- Coordinates.erase(itr);
- }
- SummonPatient_Timer = 10000;
- SummonPatientCount++;
- }else SummonPatient_Timer -= diff;
-}
-
-bool QuestAccept_npc_doctor(Player *player, Creature *creature, Quest const *quest )
-{
- if((quest->GetQuestId() == 6624) || (quest->GetQuestId() == 6622))
- ((npc_doctorAI*)creature->AI())->BeginEvent(player);
-
- return true;
-}
-
-CreatureAI* GetAI_npc_doctor(Creature *_Creature)
-{
- return new npc_doctorAI (_Creature);
-}
-
-/*######
-## npc_guardian
-######*/
-
-#define SPELL_DEATHTOUCH 5
-#define SAY_AGGRO "This area is closed!"
-
-struct TRINITY_DLL_DECL npc_guardianAI : public ScriptedAI
-{
- npc_guardianAI(Creature *c) : ScriptedAI(c) {Reset();}
-
- void Reset()
- {
- m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- }
-
- void Aggro(Unit *who)
- {
- DoYell(SAY_AGGRO,LANG_UNIVERSAL,NULL);
- }
-
- void UpdateAI(const uint32 diff)
- {
- if (!m_creature->SelectHostilTarget() || !m_creature->getVictim())
- return;
-
- if (m_creature->isAttackReady())
- {
- m_creature->CastSpell(m_creature->getVictim(),SPELL_DEATHTOUCH, true);
- m_creature->resetAttackTimer();
- }
- }
-};
-
-CreatureAI* GetAI_npc_guardian(Creature *_Creature)
-{
- return new npc_guardianAI (_Creature);
-}
-
-/*######
-## npc_mount_vendor
-######*/
-
-bool GossipHello_npc_mount_vendor(Player *player, Creature *_Creature)
-{
- if (_Creature->isQuestGiver())
- player->PrepareQuestMenu( _Creature->GetGUID() );
-
- bool canBuy;
- canBuy = false;
- uint32 vendor = _Creature->GetEntry();
- uint8 race = player->getRace();
-
- switch (vendor)
- {
- case 384: //Katie Hunter
- case 1460: //Unger Statforth
- case 2357: //Merideth Carlson
- case 4885: //Gregor MacVince
- if (player->GetReputationRank(72) != REP_EXALTED && race != RACE_HUMAN)
- player->SEND_GOSSIP_MENU(5855, _Creature->GetGUID());
- else canBuy = true;
- break;
- case 1261: //Veron Amberstill
- if (player->GetReputationRank(47) != REP_EXALTED && race != RACE_DWARF)
- player->SEND_GOSSIP_MENU(5856, _Creature->GetGUID());
- else canBuy = true;
- break;
- case 3362: //Ogunaro Wolfrunner
- if (player->GetReputationRank(76) != REP_EXALTED && race != RACE_ORC)
- player->SEND_GOSSIP_MENU(5841, _Creature->GetGUID());
- else canBuy = true;
- break;
- case 3685: //Harb Clawhoof
- if (player->GetReputationRank(81) != REP_EXALTED && race != RACE_TAUREN)
- player->SEND_GOSSIP_MENU(5843, _Creature->GetGUID());
- else canBuy = true;
- break;
- case 4730: //Lelanai
- if (player->GetReputationRank(69) != REP_EXALTED && race != RACE_NIGHTELF)
- player->SEND_GOSSIP_MENU(5844, _Creature->GetGUID());
- else canBuy = true;
- break;
- case 4731: //Zachariah Post
- if (player->GetReputationRank(68) != REP_EXALTED && race != RACE_UNDEAD_PLAYER)
- player->SEND_GOSSIP_MENU(5840, _Creature->GetGUID());
- else canBuy = true;
- break;
- case 7952: //Zjolnir
- if (player->GetReputationRank(530) != REP_EXALTED && race != RACE_TROLL)
- player->SEND_GOSSIP_MENU(5842, _Creature->GetGUID());
- else canBuy = true;
- break;
- case 7955: //Milli Featherwhistle
- if (player->GetReputationRank(54) != REP_EXALTED && race != RACE_GNOME)
- player->SEND_GOSSIP_MENU(5857, _Creature->GetGUID());
- else canBuy = true;
- break;
- case 16264: //Winaestra
- if (player->GetReputationRank(911) != REP_EXALTED && race != RACE_BLOODELF)
- player->SEND_GOSSIP_MENU(10305, _Creature->GetGUID());
- else canBuy = true;
- break;
- case 17584: //Torallius the Pack Handler
- if (player->GetReputationRank(930) != REP_EXALTED && race != RACE_DRAENEI)
- player->SEND_GOSSIP_MENU(10239, _Creature->GetGUID());
- else canBuy = true;
- break;
- }
-
- if (canBuy)
- {
- if (_Creature->isVendor())
- player->ADD_GOSSIP_ITEM( 1, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE);
- player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID());
- }
- return true;
-}
-
-bool GossipSelect_npc_mount_vendor(Player *player, Creature *_Creature, uint32 sender, uint32 action)
-{
- if (action == GOSSIP_ACTION_TRADE)
- player->SEND_VENDORLIST( _Creature->GetGUID() );
-
- return true;
-}
-
-/*######
-## npc_rogue_trainer
-######*/
-
-bool GossipHello_npc_rogue_trainer(Player *player, Creature *_Creature)
-{
- if( _Creature->isQuestGiver() )
- player->PrepareQuestMenu( _Creature->GetGUID() );
-
- if( _Creature->isTrainer() )
- player->ADD_GOSSIP_ITEM(2, GOSSIP_TEXT_TRAIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRAIN);
-
- if( _Creature->isCanTrainingAndResetTalentsOf(player) )
- player->ADD_GOSSIP_ITEM(2, "I wish to unlearn my talents", GOSSIP_SENDER_MAIN, GOSSIP_OPTION_UNLEARNTALENTS);
-
- if( player->getClass() == CLASS_ROGUE && player->getLevel() >= 24 && !player->HasItemCount(17126,1) && !player->GetQuestRewardStatus(6681) )
- {
- player->ADD_GOSSIP_ITEM(0, "<Take the letter>", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
- player->SEND_GOSSIP_MENU(5996, _Creature->GetGUID());
- } else
- player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID());
-
- return true;
-}
-
-bool GossipSelect_npc_rogue_trainer(Player *player, Creature *_Creature, uint32 sender, uint32 action)
-{
- switch( action )
- {
- case GOSSIP_ACTION_INFO_DEF+1:
- player->CLOSE_GOSSIP_MENU();
- player->CastSpell(player,21100,false);
- break;
- case GOSSIP_ACTION_TRAIN:
- player->SEND_TRAINERLIST( _Creature->GetGUID() );
- break;
- case GOSSIP_OPTION_UNLEARNTALENTS:
- player->CLOSE_GOSSIP_MENU();
- player->SendTalentWipeConfirm( _Creature->GetGUID() );
- break;
- }
- return true;
-}
-
-/*######
-## npc_sayge
-######*/
-
-#define SPELL_DMG 23768 //dmg
-#define SPELL_RES 23769 //res
-#define SPELL_ARM 23767 //arm
-#define SPELL_SPI 23738 //spi
-#define SPELL_INT 23766 //int
-#define SPELL_STM 23737 //stm
-#define SPELL_STR 23735 //str
-#define SPELL_AGI 23736 //agi
-#define SPELL_FORTUNE 23765 //faire fortune
-
-bool GossipHello_npc_sayge(Player *player, Creature *_Creature)
-{
- if(_Creature->isQuestGiver())
- player->PrepareQuestMenu( _Creature->GetGUID() );
-
- if( player->HasSpellCooldown(SPELL_INT) ||
- player->HasSpellCooldown(SPELL_ARM) ||
- player->HasSpellCooldown(SPELL_DMG) ||
- player->HasSpellCooldown(SPELL_RES) ||
- player->HasSpellCooldown(SPELL_STR) ||
- player->HasSpellCooldown(SPELL_AGI) ||
- player->HasSpellCooldown(SPELL_STM) ||
- player->HasSpellCooldown(SPELL_SPI) )
- player->SEND_GOSSIP_MENU(7393, _Creature->GetGUID());
- else
- {
- player->ADD_GOSSIP_ITEM(0, "Yes", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
- player->SEND_GOSSIP_MENU(7339, _Creature->GetGUID());
- }
-
- return true;
-}
-
-void SendAction_npc_sayge(Player *player, Creature *_Creature, uint32 action)
-{
- switch(action)
- {
- case GOSSIP_ACTION_INFO_DEF+1:
- player->ADD_GOSSIP_ITEM(0, "Slay the Man", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
- player->ADD_GOSSIP_ITEM(0, "Turn him over to liege", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3);
- player->ADD_GOSSIP_ITEM(0, "Confiscate the corn", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4);
- player->ADD_GOSSIP_ITEM(0, "Let him go and have the corn", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5);
- player->SEND_GOSSIP_MENU(7340, _Creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+2:
- player->ADD_GOSSIP_ITEM(0, "Execute your friend painfully", GOSSIP_SENDER_MAIN+1, GOSSIP_ACTION_INFO_DEF);
- player->ADD_GOSSIP_ITEM(0, "Execute your friend painlessly", GOSSIP_SENDER_MAIN+2, GOSSIP_ACTION_INFO_DEF);
- player->ADD_GOSSIP_ITEM(0, "Let your friend go", GOSSIP_SENDER_MAIN+3, GOSSIP_ACTION_INFO_DEF);
- player->SEND_GOSSIP_MENU(7341, _Creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+3:
- player->ADD_GOSSIP_ITEM(0, "Confront the diplomat", GOSSIP_SENDER_MAIN+4, GOSSIP_ACTION_INFO_DEF);
- player->ADD_GOSSIP_ITEM(0, "Show not so quiet defiance", GOSSIP_SENDER_MAIN+5, GOSSIP_ACTION_INFO_DEF);
- player->ADD_GOSSIP_ITEM(0, "Remain quiet", GOSSIP_SENDER_MAIN+2, GOSSIP_ACTION_INFO_DEF);
- player->SEND_GOSSIP_MENU(7361, _Creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+4:
- player->ADD_GOSSIP_ITEM(0, "Speak against your brother openly", GOSSIP_SENDER_MAIN+6, GOSSIP_ACTION_INFO_DEF);
- player->ADD_GOSSIP_ITEM(0, "Help your brother in", GOSSIP_SENDER_MAIN+7, GOSSIP_ACTION_INFO_DEF);
- player->ADD_GOSSIP_ITEM(0, "Keep your brother out without letting him know", GOSSIP_SENDER_MAIN+8, GOSSIP_ACTION_INFO_DEF);
- player->SEND_GOSSIP_MENU(7362, _Creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+5:
- player->ADD_GOSSIP_ITEM(0, "Take credit, keep gold", GOSSIP_SENDER_MAIN+5, GOSSIP_ACTION_INFO_DEF);
- player->ADD_GOSSIP_ITEM(0, "Take credit, share the gold", GOSSIP_SENDER_MAIN+4, GOSSIP_ACTION_INFO_DEF);
- player->ADD_GOSSIP_ITEM(0, "Let the knight take credit", GOSSIP_SENDER_MAIN+3, GOSSIP_ACTION_INFO_DEF);
- player->SEND_GOSSIP_MENU(7363, _Creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF:
- player->ADD_GOSSIP_ITEM(0, "Thanks", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6);
- player->SEND_GOSSIP_MENU(7364, _Creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+6:
- _Creature->CastSpell(player, SPELL_FORTUNE, false);
- player->SEND_GOSSIP_MENU(7365, _Creature->GetGUID());
- break;
- }
-}
-
-bool GossipSelect_npc_sayge(Player *player, Creature *_Creature, uint32 sender, uint32 action )
-{
- switch(sender)
- {
- case GOSSIP_SENDER_MAIN:
- SendAction_npc_sayge(player, _Creature, action);
- break;
- case GOSSIP_SENDER_MAIN+1:
- _Creature->CastSpell(player, SPELL_DMG, false);
- player->AddSpellCooldown(SPELL_DMG,0,time(NULL) + 7200);
- SendAction_npc_sayge(player, _Creature, action);
- break;
- case GOSSIP_SENDER_MAIN+2:
- _Creature->CastSpell(player, SPELL_RES, false);
- player->AddSpellCooldown(SPELL_RES,0,time(NULL) + 7200);
- SendAction_npc_sayge(player, _Creature, action);
- break;
- case GOSSIP_SENDER_MAIN+3:
- _Creature->CastSpell(player, SPELL_ARM, false);
- player->AddSpellCooldown(SPELL_ARM,0,time(NULL) + 7200);
- SendAction_npc_sayge(player, _Creature, action);
- break;
- case GOSSIP_SENDER_MAIN+4:
- _Creature->CastSpell(player, SPELL_SPI, false);
- player->AddSpellCooldown(SPELL_SPI,0,time(NULL) + 7200);
- SendAction_npc_sayge(player, _Creature, action);
- break;
- case GOSSIP_SENDER_MAIN+5:
- _Creature->CastSpell(player, SPELL_INT, false);
- player->AddSpellCooldown(SPELL_INT,0,time(NULL) + 7200);
- SendAction_npc_sayge(player, _Creature, action);
- break;
- case GOSSIP_SENDER_MAIN+6:
- _Creature->CastSpell(player, SPELL_STM, false);
- player->AddSpellCooldown(SPELL_STM,0,time(NULL) + 7200);
- SendAction_npc_sayge(player, _Creature, action);
- break;
- case GOSSIP_SENDER_MAIN+7:
- _Creature->CastSpell(player, SPELL_STR, false);
- player->AddSpellCooldown(SPELL_STR,0,time(NULL) + 7200);
- SendAction_npc_sayge(player, _Creature, action);
- break;
- case GOSSIP_SENDER_MAIN+8:
- _Creature->CastSpell(player, SPELL_AGI, false);
- player->AddSpellCooldown(SPELL_AGI,0,time(NULL) + 7200);
- SendAction_npc_sayge(player, _Creature, action);
- break;
- }
- return true;
-}
-
-void AddSC_npcs_special()
-{
- Script *newscript;
-
- newscript = new Script;
- newscript->Name="npc_chicken_cluck";
- newscript->GetAI = GetAI_npc_chicken_cluck;
- newscript->pReceiveEmote = &ReceiveEmote_npc_chicken_cluck;
- newscript->pQuestAccept = &QuestAccept_npc_chicken_cluck;
- newscript->pQuestComplete = &QuestComplete_npc_chicken_cluck;
- newscript->RegisterSelf();
-
- newscript = new Script;
- newscript->Name="npc_dancing_flames";
- newscript->pReceiveEmote = &ReceiveEmote_npc_dancing_flames;
- newscript->RegisterSelf();
-
- newscript = new Script;
- newscript->Name="npc_injured_patient";
- newscript->GetAI = GetAI_npc_injured_patient;
- newscript->RegisterSelf();
-
- newscript = new Script;
- newscript->Name="npc_doctor";
- newscript->GetAI = GetAI_npc_doctor;
- newscript->pQuestAccept = &QuestAccept_npc_doctor;
- newscript->RegisterSelf();
-
- newscript = new Script;
- newscript->Name="npc_guardian";
- newscript->GetAI = GetAI_npc_guardian;
- newscript->RegisterSelf();
-
- newscript = new Script;
- newscript->Name="npc_mount_vendor";
- newscript->pGossipHello = &GossipHello_npc_mount_vendor;
- newscript->pGossipSelect = &GossipSelect_npc_mount_vendor;
- newscript->RegisterSelf();
-
- newscript = new Script;
- newscript->Name="npc_rogue_trainer";
- newscript->pGossipHello = &GossipHello_npc_rogue_trainer;
- newscript->pGossipSelect = &GossipSelect_npc_rogue_trainer;
- newscript->RegisterSelf();
-
- newscript = new Script;
- newscript->Name="npc_sayge";
- newscript->pGossipHello = &GossipHello_npc_sayge;
- newscript->pGossipSelect = &GossipSelect_npc_sayge;
- newscript->RegisterSelf();
-}
+/* Copyright (C) 2006 - 2008 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
+ */
+
+/* ScriptData
+SDName: Npcs_Special
+SD%Complete: 100
+SDComment: To be used for special NPCs that are located globally. Support for quest 3861 (Cluck!), 6622 and 6624 (Triage)
+SDCategory: NPCs
+EndScriptData
+*/
+
+/* ContentData
+npc_chicken_cluck 100% support for quest 3861 (Cluck!)
+npc_dancing_flames 100% midsummer event NPC
+npc_guardian 100% guardianAI used to prevent players from accessing off-limits areas. Not in use by SD2
+npc_injured_patient 100% patients for triage-quests (6622 and 6624)
+npc_doctor 100% Gustaf Vanhowzen and Gregory Victor, quest 6622 and 6624 (Triage)
+npc_mount_vendor 100% Regular mount vendors all over the world. Display gossip if player doesn't meet the requirements to buy
+npc_rogue_trainer 80% Scripted trainers, so they are able to offer item 17126 for class quest 6681
+npc_sayge 100% Darkmoon event fortune teller, buff player based on answers given
+EndContentData */
+
+#include "precompiled.h"
+
+/*########
+# npc_chicken_cluck
+#########*/
+
+#define QUEST_CLUCK 3861
+#define EMOTE_A_HELLO "looks up at you quizzically. Maybe you should inspect it?"
+#define EMOTE_H_HELLO "looks at you unexpectadly."
+#define CLUCK_TEXT2 "starts pecking at the feed."
+#define FACTION_FRIENDLY 84
+#define FACTION_CHICKEN 31
+
+struct TRINITY_DLL_DECL npc_chicken_cluckAI : public ScriptedAI
+{
+ npc_chicken_cluckAI(Creature *c) : ScriptedAI(c) {Reset();}
+
+ uint32 ResetFlagTimer;
+
+ void Reset()
+ {
+ ResetFlagTimer = 120000;
+
+ m_creature->setFaction(FACTION_CHICKEN);
+ m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER);
+ }
+
+ void Aggro(Unit *who) {}
+
+ void UpdateAI(const uint32 diff)
+ {
+ // Reset flags after a certain time has passed so that the next player has to start the 'event' again
+ if(m_creature->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER))
+ {
+ if(ResetFlagTimer < diff)
+ EnterEvadeMode();
+ else ResetFlagTimer -= diff;
+ }
+
+ if(m_creature->SelectHostilTarget() && m_creature->getVictim())
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_npc_chicken_cluck(Creature *_Creature)
+{
+ return new npc_chicken_cluckAI(_Creature);
+}
+
+bool ReceiveEmote_npc_chicken_cluck( Player *player, Creature *_Creature, uint32 emote )
+{
+ if( emote == TEXTEMOTE_CHICKEN )
+ {
+ if( player->GetTeam() == ALLIANCE )
+ {
+ if( rand()%30 == 1 )
+ {
+ if( player->GetQuestStatus(QUEST_CLUCK) == QUEST_STATUS_NONE )
+ {
+ _Creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER);
+ _Creature->setFaction(FACTION_FRIENDLY);
+ _Creature->MonsterTextEmote(EMOTE_A_HELLO, 0);
+ }
+ }
+ } else
+ _Creature->MonsterTextEmote(EMOTE_H_HELLO,0);
+ }
+ if( emote == TEXTEMOTE_CHEER && player->GetTeam() == ALLIANCE )
+ if( player->GetQuestStatus(QUEST_CLUCK) == QUEST_STATUS_COMPLETE )
+ {
+ _Creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER);
+ _Creature->setFaction(FACTION_FRIENDLY);
+ _Creature->MonsterTextEmote(CLUCK_TEXT2, 0);
+ }
+
+ return true;
+}
+
+bool QuestAccept_npc_chicken_cluck(Player *player, Creature *_Creature, const Quest *_Quest )
+{
+ if(_Quest->GetQuestId() == QUEST_CLUCK)
+ ((npc_chicken_cluckAI*)_Creature->AI())->Reset();
+
+ return true;
+}
+
+bool QuestComplete_npc_chicken_cluck(Player *player, Creature *_Creature, const Quest *_Quest)
+{
+ if(_Quest->GetQuestId() == QUEST_CLUCK)
+ ((npc_chicken_cluckAI*)_Creature->AI())->Reset();
+
+ return true;
+}
+
+/*######
+## npc_dancing_flames
+######*/
+
+bool ReceiveEmote_npc_dancing_flames( Player *player, Creature *_Creature, uint32 emote )
+{
+ if( emote == TEXTEMOTE_DANCE )
+ _Creature->CastSpell(player,47057,false);
+
+ return true;
+}
+
+/*######
+## Triage quest
+######*/
+
+#define SAY_DOC1 "I'm saved! Thank you, doctor!"
+#define SAY_DOC2 "HOORAY! I AM SAVED!"
+#define SAY_DOC3 "Sweet, sweet embrace... take me..."
+
+struct Location
+{
+ float x, y, z, o;
+};
+
+#define DOCTOR_ALLIANCE 12939
+
+static Location AllianceCoords[]=
+{
+ { // Top-far-right bunk as seen from entrance
+ -3757.38, -4533.05, 14.16, 3.62
+ },
+ { // Top-far-left bunk
+ -3754.36, -4539.13, 14.16, 5.13
+ },
+ { // Far-right bunk
+ -3749.54, -4540.25, 14.28, 3.34
+ },
+ { // Right bunk near entrance
+ -3742.10, -4536.85, 14.28, 3.64
+ },
+ { // Far-left bunk
+ -3755.89, -4529.07, 14.05, 0.57
+ },
+ { // Mid-left bunk
+ -3749.51, -4527.08, 14.07, 5.26
+ },
+ { // Left bunk near entrance
+ -3746.37, -4525.35, 14.16, 5.22
+ },
+};
+
+#define ALLIANCE_COORDS 7
+
+//alliance run to where
+#define A_RUNTOX -3742.96
+#define A_RUNTOY -4531.52
+#define A_RUNTOZ 11.91
+
+#define DOCTOR_HORDE 12920
+
+static Location HordeCoords[]=
+{
+ { // Left, Behind
+ -1013.75, -3492.59, 62.62, 4.34
+ },
+ { // Right, Behind
+ -1017.72, -3490.92, 62.62, 4.34
+ },
+ { // Left, Mid
+ -1015.77, -3497.15, 62.82, 4.34
+ },
+ { // Right, Mid
+ -1019.51, -3495.49, 62.82, 4.34
+ },
+ { // Left, front
+ -1017.25, -3500.85, 62.98, 4.34
+ },
+ { // Right, Front
+ -1020.95, -3499.21, 62.98, 4.34
+ }
+};
+
+#define HORDE_COORDS 6
+
+//horde run to where
+#define H_RUNTOX -1016.44
+#define H_RUNTOY -3508.48
+#define H_RUNTOZ 62.96
+
+const uint32 AllianceSoldierId[3] =
+{
+ 12938, // 12938 Injured Alliance Soldier
+ 12936, // 12936 Badly injured Alliance Soldier
+ 12937 // 12937 Critically injured Alliance Soldier
+};
+
+const uint32 HordeSoldierId[3] =
+{
+ 12923, //12923 Injured Soldier
+ 12924, //12924 Badly injured Soldier
+ 12925 //12925 Critically injured Soldier
+};
+
+/*######
+## npc_doctor (handles both Gustaf Vanhowzen and Gregory Victor)
+######*/
+
+struct TRINITY_DLL_DECL npc_doctorAI : public ScriptedAI
+{
+ uint64 Playerguid;
+
+ uint32 SummonPatient_Timer;
+ uint32 SummonPatientCount;
+ uint32 PatientDiedCount;
+ uint32 PatientSavedCount;
+
+ bool Event;
+
+ std::list<uint64> Patients;
+ std::vector<Location*> Coordinates;
+
+ npc_doctorAI(Creature *c) : ScriptedAI(c) {Reset();}
+
+ void Reset(){}
+
+ void BeginEvent(Player* player);
+ void PatientDied(Location* Point);
+ void PatientSaved(Creature* soldier, Player* player, Location* Point);
+ void UpdateAI(const uint32 diff);
+
+ void Aggro(Unit* who){}
+};
+
+/*#####
+## npc_injured_patient (handles all the patients, no matter Horde or Alliance)
+#####*/
+
+struct TRINITY_DLL_DECL npc_injured_patientAI : public ScriptedAI
+{
+ npc_injured_patientAI(Creature *c) : ScriptedAI(c) {Reset();}
+
+ uint64 Doctorguid;
+
+ Location* Coord;
+
+ void Reset()
+ {
+ Doctorguid = 0;
+
+ Coord = NULL;
+ //no select
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ //no regen health
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT);
+ //to make them lay with face down
+ m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, PLAYER_STATE_DEAD);
+
+ uint32 mobId = m_creature->GetEntry();
+
+ switch (mobId)
+ { //lower max health
+ case 12923:
+ case 12938: //Injured Soldier
+ m_creature->SetHealth(uint32(m_creature->GetMaxHealth()*.75));
+ break;
+ case 12924:
+ case 12936: //Badly injured Soldier
+ m_creature->SetHealth(uint32(m_creature->GetMaxHealth()*.50));
+ break;
+ case 12925:
+ case 12937: //Critically injured Soldier
+ m_creature->SetHealth(uint32(m_creature->GetMaxHealth()*.25));
+ break;
+ }
+ }
+
+ void Aggro(Unit* who){}
+
+ void SpellHit(Unit *caster, const SpellEntry *spell)
+ {
+ if (caster->GetTypeId() == TYPEID_PLAYER && m_creature->isAlive() && spell->Id == 20804)
+ {
+ if( (((Player*)caster)->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE) || (((Player*)caster)->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE))
+ {
+ if(Doctorguid)
+ {
+ Creature* Doctor = ((Creature*)Unit::GetUnit((*m_creature), Doctorguid));
+ if(Doctor)
+ ((npc_doctorAI*)Doctor->AI())->PatientSaved(m_creature, ((Player*)caster), Coord);
+ }
+ }
+ //make not selectable
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ //regen health
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT);
+ //stand up
+ m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, PLAYER_STATE_NONE);
+ DoSay(SAY_DOC1,LANG_UNIVERSAL,NULL);
+
+ uint32 mobId = m_creature->GetEntry();
+ m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
+ switch (mobId)
+ {
+ case 12923:
+ case 12924:
+ case 12925:
+ m_creature->GetMotionMaster()->MovePoint(0, H_RUNTOX, H_RUNTOY, H_RUNTOZ);
+ break;
+ case 12936:
+ case 12937:
+ case 12938:
+ m_creature->GetMotionMaster()->MovePoint(0, A_RUNTOX, A_RUNTOY, A_RUNTOZ);
+ break;
+ }
+ }
+ return;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (m_creature->isAlive() && m_creature->GetHealth() > 6)
+ { //lower HP on every world tick makes it a useful counter, not officlone though
+ m_creature->SetHealth(uint32(m_creature->GetHealth()-5) );
+ }
+
+ if (m_creature->isAlive() && m_creature->GetHealth() <= 6)
+ {
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT);
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ m_creature->setDeathState(JUST_DIED);
+ m_creature->SetFlag(UNIT_DYNAMIC_FLAGS, 32);
+
+ if(Doctorguid)
+ {
+ Creature* Doctor = ((Creature*)Unit::GetUnit((*m_creature), Doctorguid));
+ if(Doctor)
+ ((npc_doctorAI*)Doctor->AI())->PatientDied(Coord);
+ }
+ }
+ }
+};
+
+CreatureAI* GetAI_npc_injured_patient(Creature *_Creature)
+{
+ return new npc_injured_patientAI (_Creature);
+}
+
+/*
+npc_doctor (continue)
+*/
+
+void npc_doctorAI::BeginEvent(Player* player)
+{
+ Playerguid = player->GetGUID();
+
+ SummonPatient_Timer = 10000;
+ SummonPatientCount = 0;
+ PatientDiedCount = 0;
+ PatientSavedCount = 0;
+
+ switch(m_creature->GetEntry())
+ {
+ case DOCTOR_ALLIANCE:
+ for(uint8 i = 0; i < ALLIANCE_COORDS; ++i)
+ Coordinates.push_back(&AllianceCoords[i]);
+ break;
+
+ case DOCTOR_HORDE:
+ for(uint8 i = 0; i < HORDE_COORDS; ++i)
+ Coordinates.push_back(&HordeCoords[i]);
+ break;
+ }
+
+ Event = true;
+
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+}
+
+void npc_doctorAI::PatientDied(Location* Point)
+{
+ Player* player = ((Player*)Unit::GetUnit((*m_creature), Playerguid));
+ if(player && ((player->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE) || (player->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE)))
+ {
+ PatientDiedCount++;
+ if (PatientDiedCount > 5 && Event)
+ {
+ if(player->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE)
+ player->FailQuest(6624);
+ else if(player->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE)
+ player->FailQuest(6622);
+
+ Event = false;
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ }
+
+ Coordinates.push_back(Point);
+ }
+}
+
+void npc_doctorAI::PatientSaved(Creature* soldier, Player* player, Location* Point)
+{
+ if(player && Playerguid == player->GetGUID())
+ {
+ if((player->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE) || (player->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE))
+ {
+ PatientSavedCount++;
+ if(PatientSavedCount == 15)
+ {
+ if(!Patients.empty())
+ {
+ std::list<uint64>::iterator itr;
+ for(itr = Patients.begin(); itr != Patients.end(); ++itr)
+ {
+ Creature* Patient = ((Creature*)Unit::GetUnit((*m_creature), *itr));
+ if( Patient )
+ Patient->setDeathState(JUST_DIED);
+ }
+ }
+
+ if(player->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE)
+ player->AreaExploredOrEventHappens(6624);
+ else if(player->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE)
+ player->AreaExploredOrEventHappens(6622);
+
+ Event = false;
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ }
+
+ Coordinates.push_back(Point);
+ }
+ }
+}
+
+void npc_doctorAI::UpdateAI(const uint32 diff)
+{
+ if(Event && SummonPatientCount >= 20)
+ {
+ Event = false;
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ }
+
+ if(Event)
+ if(SummonPatient_Timer < diff)
+ {
+ Creature* Patient = NULL;
+ Location* Point = NULL;
+
+ if(Coordinates.empty())
+ return;
+
+ std::vector<Location*>::iterator itr = Coordinates.begin()+rand()%Coordinates.size();
+ uint32 patientEntry = 0;
+
+ switch(m_creature->GetEntry())
+ {
+ case DOCTOR_ALLIANCE: patientEntry = AllianceSoldierId[rand()%3]; break;
+ case DOCTOR_HORDE: patientEntry = HordeSoldierId[rand()%3]; break;
+ default:
+ error_log("SD2: Invalid entry for Triage doctor. Please check your database");
+ return;
+ }
+
+ Point = *itr;
+
+ Patient = m_creature->SummonCreature(patientEntry, Point->x, Point->y, Point->z, Point->o, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
+
+ if(Patient)
+ {
+ Patients.push_back(Patient->GetGUID());
+ ((npc_injured_patientAI*)Patient->AI())->Doctorguid = m_creature->GetGUID();
+ if(Point)
+ ((npc_injured_patientAI*)Patient->AI())->Coord = Point;
+ Coordinates.erase(itr);
+ }
+ SummonPatient_Timer = 10000;
+ SummonPatientCount++;
+ }else SummonPatient_Timer -= diff;
+}
+
+bool QuestAccept_npc_doctor(Player *player, Creature *creature, Quest const *quest )
+{
+ if((quest->GetQuestId() == 6624) || (quest->GetQuestId() == 6622))
+ ((npc_doctorAI*)creature->AI())->BeginEvent(player);
+
+ return true;
+}
+
+CreatureAI* GetAI_npc_doctor(Creature *_Creature)
+{
+ return new npc_doctorAI (_Creature);
+}
+
+/*######
+## npc_guardian
+######*/
+
+#define SPELL_DEATHTOUCH 5
+#define SAY_AGGRO "This area is closed!"
+
+struct TRINITY_DLL_DECL npc_guardianAI : public ScriptedAI
+{
+ npc_guardianAI(Creature *c) : ScriptedAI(c) {Reset();}
+
+ void Reset()
+ {
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ }
+
+ void Aggro(Unit *who)
+ {
+ DoYell(SAY_AGGRO,LANG_UNIVERSAL,NULL);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostilTarget() || !m_creature->getVictim())
+ return;
+
+ if (m_creature->isAttackReady())
+ {
+ m_creature->CastSpell(m_creature->getVictim(),SPELL_DEATHTOUCH, true);
+ m_creature->resetAttackTimer();
+ }
+ }
+};
+
+CreatureAI* GetAI_npc_guardian(Creature *_Creature)
+{
+ return new npc_guardianAI (_Creature);
+}
+
+/*######
+## npc_mount_vendor
+######*/
+
+bool GossipHello_npc_mount_vendor(Player *player, Creature *_Creature)
+{
+ if (_Creature->isQuestGiver())
+ player->PrepareQuestMenu( _Creature->GetGUID() );
+
+ bool canBuy;
+ canBuy = false;
+ uint32 vendor = _Creature->GetEntry();
+ uint8 race = player->getRace();
+
+ switch (vendor)
+ {
+ case 384: //Katie Hunter
+ case 1460: //Unger Statforth
+ case 2357: //Merideth Carlson
+ case 4885: //Gregor MacVince
+ if (player->GetReputationRank(72) != REP_EXALTED && race != RACE_HUMAN)
+ player->SEND_GOSSIP_MENU(5855, _Creature->GetGUID());
+ else canBuy = true;
+ break;
+ case 1261: //Veron Amberstill
+ if (player->GetReputationRank(47) != REP_EXALTED && race != RACE_DWARF)
+ player->SEND_GOSSIP_MENU(5856, _Creature->GetGUID());
+ else canBuy = true;
+ break;
+ case 3362: //Ogunaro Wolfrunner
+ if (player->GetReputationRank(76) != REP_EXALTED && race != RACE_ORC)
+ player->SEND_GOSSIP_MENU(5841, _Creature->GetGUID());
+ else canBuy = true;
+ break;
+ case 3685: //Harb Clawhoof
+ if (player->GetReputationRank(81) != REP_EXALTED && race != RACE_TAUREN)
+ player->SEND_GOSSIP_MENU(5843, _Creature->GetGUID());
+ else canBuy = true;
+ break;
+ case 4730: //Lelanai
+ if (player->GetReputationRank(69) != REP_EXALTED && race != RACE_NIGHTELF)
+ player->SEND_GOSSIP_MENU(5844, _Creature->GetGUID());
+ else canBuy = true;
+ break;
+ case 4731: //Zachariah Post
+ if (player->GetReputationRank(68) != REP_EXALTED && race != RACE_UNDEAD_PLAYER)
+ player->SEND_GOSSIP_MENU(5840, _Creature->GetGUID());
+ else canBuy = true;
+ break;
+ case 7952: //Zjolnir
+ if (player->GetReputationRank(530) != REP_EXALTED && race != RACE_TROLL)
+ player->SEND_GOSSIP_MENU(5842, _Creature->GetGUID());
+ else canBuy = true;
+ break;
+ case 7955: //Milli Featherwhistle
+ if (player->GetReputationRank(54) != REP_EXALTED && race != RACE_GNOME)
+ player->SEND_GOSSIP_MENU(5857, _Creature->GetGUID());
+ else canBuy = true;
+ break;
+ case 16264: //Winaestra
+ if (player->GetReputationRank(911) != REP_EXALTED && race != RACE_BLOODELF)
+ player->SEND_GOSSIP_MENU(10305, _Creature->GetGUID());
+ else canBuy = true;
+ break;
+ case 17584: //Torallius the Pack Handler
+ if (player->GetReputationRank(930) != REP_EXALTED && race != RACE_DRAENEI)
+ player->SEND_GOSSIP_MENU(10239, _Creature->GetGUID());
+ else canBuy = true;
+ break;
+ }
+
+ if (canBuy)
+ {
+ if (_Creature->isVendor())
+ player->ADD_GOSSIP_ITEM( 1, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE);
+ player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID());
+ }
+ return true;
+}
+
+bool GossipSelect_npc_mount_vendor(Player *player, Creature *_Creature, uint32 sender, uint32 action)
+{
+ if (action == GOSSIP_ACTION_TRADE)
+ player->SEND_VENDORLIST( _Creature->GetGUID() );
+
+ return true;
+}
+
+/*######
+## npc_rogue_trainer
+######*/
+
+bool GossipHello_npc_rogue_trainer(Player *player, Creature *_Creature)
+{
+ if( _Creature->isQuestGiver() )
+ player->PrepareQuestMenu( _Creature->GetGUID() );
+
+ if( _Creature->isTrainer() )
+ player->ADD_GOSSIP_ITEM(2, GOSSIP_TEXT_TRAIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRAIN);
+
+ if( _Creature->isCanTrainingAndResetTalentsOf(player) )
+ player->ADD_GOSSIP_ITEM(2, "I wish to unlearn my talents", GOSSIP_SENDER_MAIN, GOSSIP_OPTION_UNLEARNTALENTS);
+
+ if( player->getClass() == CLASS_ROGUE && player->getLevel() >= 24 && !player->HasItemCount(17126,1) && !player->GetQuestRewardStatus(6681) )
+ {
+ player->ADD_GOSSIP_ITEM(0, "<Take the letter>", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+ player->SEND_GOSSIP_MENU(5996, _Creature->GetGUID());
+ } else
+ player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID());
+
+ return true;
+}
+
+bool GossipSelect_npc_rogue_trainer(Player *player, Creature *_Creature, uint32 sender, uint32 action)
+{
+ switch( action )
+ {
+ case GOSSIP_ACTION_INFO_DEF+1:
+ player->CLOSE_GOSSIP_MENU();
+ player->CastSpell(player,21100,false);
+ break;
+ case GOSSIP_ACTION_TRAIN:
+ player->SEND_TRAINERLIST( _Creature->GetGUID() );
+ break;
+ case GOSSIP_OPTION_UNLEARNTALENTS:
+ player->CLOSE_GOSSIP_MENU();
+ player->SendTalentWipeConfirm( _Creature->GetGUID() );
+ break;
+ }
+ return true;
+}
+
+/*######
+## npc_sayge
+######*/
+
+#define SPELL_DMG 23768 //dmg
+#define SPELL_RES 23769 //res
+#define SPELL_ARM 23767 //arm
+#define SPELL_SPI 23738 //spi
+#define SPELL_INT 23766 //int
+#define SPELL_STM 23737 //stm
+#define SPELL_STR 23735 //str
+#define SPELL_AGI 23736 //agi
+#define SPELL_FORTUNE 23765 //faire fortune
+
+bool GossipHello_npc_sayge(Player *player, Creature *_Creature)
+{
+ if(_Creature->isQuestGiver())
+ player->PrepareQuestMenu( _Creature->GetGUID() );
+
+ if( player->HasSpellCooldown(SPELL_INT) ||
+ player->HasSpellCooldown(SPELL_ARM) ||
+ player->HasSpellCooldown(SPELL_DMG) ||
+ player->HasSpellCooldown(SPELL_RES) ||
+ player->HasSpellCooldown(SPELL_STR) ||
+ player->HasSpellCooldown(SPELL_AGI) ||
+ player->HasSpellCooldown(SPELL_STM) ||
+ player->HasSpellCooldown(SPELL_SPI) )
+ player->SEND_GOSSIP_MENU(7393, _Creature->GetGUID());
+ else
+ {
+ player->ADD_GOSSIP_ITEM(0, "Yes", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+ player->SEND_GOSSIP_MENU(7339, _Creature->GetGUID());
+ }
+
+ return true;
+}
+
+void SendAction_npc_sayge(Player *player, Creature *_Creature, uint32 action)
+{
+ switch(action)
+ {
+ case GOSSIP_ACTION_INFO_DEF+1:
+ player->ADD_GOSSIP_ITEM(0, "Slay the Man", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
+ player->ADD_GOSSIP_ITEM(0, "Turn him over to liege", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3);
+ player->ADD_GOSSIP_ITEM(0, "Confiscate the corn", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4);
+ player->ADD_GOSSIP_ITEM(0, "Let him go and have the corn", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5);
+ player->SEND_GOSSIP_MENU(7340, _Creature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+2:
+ player->ADD_GOSSIP_ITEM(0, "Execute your friend painfully", GOSSIP_SENDER_MAIN+1, GOSSIP_ACTION_INFO_DEF);
+ player->ADD_GOSSIP_ITEM(0, "Execute your friend painlessly", GOSSIP_SENDER_MAIN+2, GOSSIP_ACTION_INFO_DEF);
+ player->ADD_GOSSIP_ITEM(0, "Let your friend go", GOSSIP_SENDER_MAIN+3, GOSSIP_ACTION_INFO_DEF);
+ player->SEND_GOSSIP_MENU(7341, _Creature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+3:
+ player->ADD_GOSSIP_ITEM(0, "Confront the diplomat", GOSSIP_SENDER_MAIN+4, GOSSIP_ACTION_INFO_DEF);
+ player->ADD_GOSSIP_ITEM(0, "Show not so quiet defiance", GOSSIP_SENDER_MAIN+5, GOSSIP_ACTION_INFO_DEF);
+ player->ADD_GOSSIP_ITEM(0, "Remain quiet", GOSSIP_SENDER_MAIN+2, GOSSIP_ACTION_INFO_DEF);
+ player->SEND_GOSSIP_MENU(7361, _Creature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+4:
+ player->ADD_GOSSIP_ITEM(0, "Speak against your brother openly", GOSSIP_SENDER_MAIN+6, GOSSIP_ACTION_INFO_DEF);
+ player->ADD_GOSSIP_ITEM(0, "Help your brother in", GOSSIP_SENDER_MAIN+7, GOSSIP_ACTION_INFO_DEF);
+ player->ADD_GOSSIP_ITEM(0, "Keep your brother out without letting him know", GOSSIP_SENDER_MAIN+8, GOSSIP_ACTION_INFO_DEF);
+ player->SEND_GOSSIP_MENU(7362, _Creature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+5:
+ player->ADD_GOSSIP_ITEM(0, "Take credit, keep gold", GOSSIP_SENDER_MAIN+5, GOSSIP_ACTION_INFO_DEF);
+ player->ADD_GOSSIP_ITEM(0, "Take credit, share the gold", GOSSIP_SENDER_MAIN+4, GOSSIP_ACTION_INFO_DEF);
+ player->ADD_GOSSIP_ITEM(0, "Let the knight take credit", GOSSIP_SENDER_MAIN+3, GOSSIP_ACTION_INFO_DEF);
+ player->SEND_GOSSIP_MENU(7363, _Creature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF:
+ player->ADD_GOSSIP_ITEM(0, "Thanks", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6);
+ player->SEND_GOSSIP_MENU(7364, _Creature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+6:
+ _Creature->CastSpell(player, SPELL_FORTUNE, false);
+ player->SEND_GOSSIP_MENU(7365, _Creature->GetGUID());
+ break;
+ }
+}
+
+bool GossipSelect_npc_sayge(Player *player, Creature *_Creature, uint32 sender, uint32 action )
+{
+ switch(sender)
+ {
+ case GOSSIP_SENDER_MAIN:
+ SendAction_npc_sayge(player, _Creature, action);
+ break;
+ case GOSSIP_SENDER_MAIN+1:
+ _Creature->CastSpell(player, SPELL_DMG, false);
+ player->AddSpellCooldown(SPELL_DMG,0,time(NULL) + 7200);
+ SendAction_npc_sayge(player, _Creature, action);
+ break;
+ case GOSSIP_SENDER_MAIN+2:
+ _Creature->CastSpell(player, SPELL_RES, false);
+ player->AddSpellCooldown(SPELL_RES,0,time(NULL) + 7200);
+ SendAction_npc_sayge(player, _Creature, action);
+ break;
+ case GOSSIP_SENDER_MAIN+3:
+ _Creature->CastSpell(player, SPELL_ARM, false);
+ player->AddSpellCooldown(SPELL_ARM,0,time(NULL) + 7200);
+ SendAction_npc_sayge(player, _Creature, action);
+ break;
+ case GOSSIP_SENDER_MAIN+4:
+ _Creature->CastSpell(player, SPELL_SPI, false);
+ player->AddSpellCooldown(SPELL_SPI,0,time(NULL) + 7200);
+ SendAction_npc_sayge(player, _Creature, action);
+ break;
+ case GOSSIP_SENDER_MAIN+5:
+ _Creature->CastSpell(player, SPELL_INT, false);
+ player->AddSpellCooldown(SPELL_INT,0,time(NULL) + 7200);
+ SendAction_npc_sayge(player, _Creature, action);
+ break;
+ case GOSSIP_SENDER_MAIN+6:
+ _Creature->CastSpell(player, SPELL_STM, false);
+ player->AddSpellCooldown(SPELL_STM,0,time(NULL) + 7200);
+ SendAction_npc_sayge(player, _Creature, action);
+ break;
+ case GOSSIP_SENDER_MAIN+7:
+ _Creature->CastSpell(player, SPELL_STR, false);
+ player->AddSpellCooldown(SPELL_STR,0,time(NULL) + 7200);
+ SendAction_npc_sayge(player, _Creature, action);
+ break;
+ case GOSSIP_SENDER_MAIN+8:
+ _Creature->CastSpell(player, SPELL_AGI, false);
+ player->AddSpellCooldown(SPELL_AGI,0,time(NULL) + 7200);
+ SendAction_npc_sayge(player, _Creature, action);
+ break;
+ }
+ return true;
+}
+
+struct TRINITY_DLL_DECL npc_steam_tonkAI : public ScriptedAI
+{
+ npc_steam_tonkAI(Creature *c) : ScriptedAI(c) {Reset();}
+
+ void Reset() {}
+ void Aggro(Unit *who) {}
+
+ void OnPossess(bool apply)
+ {
+ if (apply)
+ {
+ // Initialize the action bar without the melee attack command
+ m_creature->InitCharmInfo(m_creature);
+ m_creature->GetCharmInfo()->InitEmptyActionBar(false);
+ }
+ }
+
+};
+
+CreatureAI* GetAI_npc_steam_tonk(Creature *_Creature)
+{
+ return new npc_steam_tonkAI(_Creature);
+}
+
+#define SPELL_TONK_MINE_DETONATE 25099
+
+struct TRINITY_DLL_DECL npc_tonk_mineAI : public ScriptedAI
+{
+ npc_tonk_mineAI(Creature *c) : ScriptedAI(c) {Reset();}
+
+ uint32 ExplosionTimer;
+
+ void Reset()
+ {
+ ExplosionTimer = 3000;
+ }
+
+ void Aggro(Unit *who) {}
+ void AttackStart(Unit *who) {}
+ void MoveInLineOfSight(Unit *who) {}
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (ExplosionTimer < diff)
+ {
+ m_creature->CastSpell(m_creature, SPELL_TONK_MINE_DETONATE, true);
+ m_creature->setDeathState(DEAD); // unsummon it
+ } else
+ ExplosionTimer -= diff;
+ }
+};
+
+CreatureAI* GetAI_npc_tonk_mine(Creature *_Creature)
+{
+ return new npc_tonk_mineAI(_Creature);
+}
+
+void AddSC_npcs_special()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name="npc_chicken_cluck";
+ newscript->GetAI = GetAI_npc_chicken_cluck;
+ newscript->pReceiveEmote = &ReceiveEmote_npc_chicken_cluck;
+ newscript->pQuestAccept = &QuestAccept_npc_chicken_cluck;
+ newscript->pQuestComplete = &QuestComplete_npc_chicken_cluck;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name="npc_dancing_flames";
+ newscript->pReceiveEmote = &ReceiveEmote_npc_dancing_flames;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name="npc_injured_patient";
+ newscript->GetAI = GetAI_npc_injured_patient;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name="npc_doctor";
+ newscript->GetAI = GetAI_npc_doctor;
+ newscript->pQuestAccept = &QuestAccept_npc_doctor;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name="npc_guardian";
+ newscript->GetAI = GetAI_npc_guardian;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name="npc_mount_vendor";
+ newscript->pGossipHello = &GossipHello_npc_mount_vendor;
+ newscript->pGossipSelect = &GossipSelect_npc_mount_vendor;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name="npc_rogue_trainer";
+ newscript->pGossipHello = &GossipHello_npc_rogue_trainer;
+ newscript->pGossipSelect = &GossipSelect_npc_rogue_trainer;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name="npc_sayge";
+ newscript->pGossipHello = &GossipHello_npc_sayge;
+ newscript->pGossipSelect = &GossipSelect_npc_sayge;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name="npc_steam_tonk";
+ newscript->GetAI = &GetAI_npc_steam_tonk;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name="npc_tonk_mine";
+ newscript->GetAI = &GetAI_npc_tonk_mine;
+ newscript->RegisterSelf();
+}
diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp
index 91eb04b07f5..cb6a7640d16 100644
--- a/src/game/Creature.cpp
+++ b/src/game/Creature.cpp
@@ -147,7 +147,11 @@ Creature::~Creature()
delete i_AI;
i_AI = NULL;
- DeletePossessedAI();
+ if (i_AI_possessed)
+ {
+ delete i_AI_possessed;
+ i_AI_possessed = NULL;
+ }
}
void Creature::AddToWorld()
@@ -562,13 +566,10 @@ void Creature::InitPossessedAI()
i_AI->OnPossess(true);
}
-void Creature::DeletePossessedAI()
+void Creature::DisablePossessedAI()
{
if (!i_AI_possessed) return;
- delete i_AI_possessed;
- i_AI_possessed = NULL;
-
// Signal the old AI that it's been re-enabled
i_AI->OnPossess(false);
}
diff --git a/src/game/Creature.h b/src/game/Creature.h
index 5d0ca5b5946..da62a9834ca 100644
--- a/src/game/Creature.h
+++ b/src/game/Creature.h
@@ -460,7 +460,7 @@ class TRINITY_DLL_SPEC Creature : public Unit
bool AIM_Initialize();
void InitPossessedAI();
- void DeletePossessedAI();
+ void DisablePossessedAI();
void AI_SendMoveToPacket(float x, float y, float z, uint32 time, uint32 MovementFlags, uint8 type);
CreatureAI* AI() { return isPossessed() && i_AI_possessed ? i_AI_possessed : i_AI; }
diff --git a/src/game/PetHandler.cpp b/src/game/PetHandler.cpp
index f95be3a9352..d912f42c22b 100644
--- a/src/game/PetHandler.cpp
+++ b/src/game/PetHandler.cpp
@@ -97,6 +97,13 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data )
break;
case COMMAND_ATTACK: //spellid=1792 //ATTACK
{
+ // Can't attack if owner is pacified
+ if (_player->HasAuraType(SPELL_AURA_MOD_PACIFY))
+ {
+ //pet->SendPetCastFail(spellid, SPELL_FAILED_PACIFIED);
+ //TODO: Send proper error message to client
+ return;
+ }
// only place where pet can be player
pet->clearUnitState(UNIT_STAT_FOLLOW);
uint64 selguid = _player->GetSelection();
diff --git a/src/game/Player.cpp b/src/game/Player.cpp
index 11ffba972a3..5b63b87bc6f 100644
--- a/src/game/Player.cpp
+++ b/src/game/Player.cpp
@@ -18700,70 +18700,70 @@ bool ItemPosCount::isContainedIn(ItemPosCountVec const& vec) const
//-------------TRINITY---------------
//***********************************
-void Player::HandleFallDamage(MovementInfo& movementInfo)
-{
- //Players with Feather Fall or low fall time, or physical immunity (charges used) are ignored
- if (!isInFlight() && movementInfo.fallTime > 1100 && !isDead() && !isGameMaster() &&
- !HasAuraType(SPELL_AURA_HOVER) && !HasAuraType(SPELL_AURA_FEATHER_FALL) &&
- !HasAuraType(SPELL_AURA_FLY) && !IsImmunedToDamage(SPELL_SCHOOL_MASK_NORMAL,true) )
- {
- //Safe fall, fall time reduction
- int32 safe_fall = GetTotalAuraModifier(SPELL_AURA_SAFE_FALL);
- uint32 fall_time = (movementInfo.fallTime > (safe_fall*10)) ? movementInfo.fallTime - (safe_fall*10) : 0;
-
- if(fall_time > 1100) //Prevent damage if fall time < 1100
- {
- //Fall Damage calculation
- float fallperc = float(fall_time)/1100;
- uint32 damage = (uint32)(((fallperc*fallperc -1) / 9 * GetMaxHealth())*sWorld.getRate(RATE_DAMAGE_FALL));
-
- float height = movementInfo.z;
- UpdateGroundPositionZ(movementInfo.x,movementInfo.y,height);
-
- if (damage > 0)
- {
- //Prevent fall damage from being more than the player maximum health
- if (damage > GetMaxHealth())
- damage = GetMaxHealth();
-
- // Gust of Wind
- if (GetDummyAura(43621))
- damage = GetMaxHealth()/2;
-
- EnvironmentalDamage(GetGUID(), DAMAGE_FALL, damage);
- }
-
- //Z given by moveinfo, LastZ, FallTime, WaterZ, MapZ, Damage, Safefall reduction
- DEBUG_LOG("FALLDAMAGE z=%f sz=%f pZ=%f FallTime=%d mZ=%f damage=%d SF=%d" , movementInfo.z, height, GetPositionZ(), movementInfo.fallTime, height, damage, safe_fall);
- }
- }
-}
-
-void Player::HandleFallUnderMap()
-{
- if(InBattleGround() && GetBattleGround()
- && GetBattleGround()->HandlePlayerUnderMap(this))
- {
- // do nothing, the handle already did if returned true
- }
- else
- {
- // NOTE: this is actually called many times while falling
- // even after the player has been teleported away
- // TODO: discard movement packets after the player is rooted
- if(isAlive())
- {
- EnvironmentalDamage(GetGUID(),DAMAGE_FALL_TO_VOID, GetMaxHealth());
- // change the death state to CORPSE to prevent the death timer from
- // starting in the next player update
- KillPlayer();
- BuildPlayerRepop();
- }
-
- // cancel the death timer here if started
- RepopAtGraveyard();
- }
-}
+void Player::HandleFallDamage(MovementInfo& movementInfo)
+{
+ //Players with Feather Fall or low fall time, or physical immunity (charges used) are ignored
+ if (!isInFlight() && movementInfo.fallTime > 1100 && !isDead() && !isGameMaster() &&
+ !HasAuraType(SPELL_AURA_HOVER) && !HasAuraType(SPELL_AURA_FEATHER_FALL) &&
+ !HasAuraType(SPELL_AURA_FLY) && !IsImmunedToDamage(SPELL_SCHOOL_MASK_NORMAL,true) )
+ {
+ //Safe fall, fall time reduction
+ int32 safe_fall = GetTotalAuraModifier(SPELL_AURA_SAFE_FALL);
+ uint32 fall_time = (movementInfo.fallTime > (safe_fall*10)) ? movementInfo.fallTime - (safe_fall*10) : 0;
+
+ if(fall_time > 1100) //Prevent damage if fall time < 1100
+ {
+ //Fall Damage calculation
+ float fallperc = float(fall_time)/1100;
+ uint32 damage = (uint32)(((fallperc*fallperc -1) / 9 * GetMaxHealth())*sWorld.getRate(RATE_DAMAGE_FALL));
+
+ float height = movementInfo.z;
+ UpdateGroundPositionZ(movementInfo.x,movementInfo.y,height);
+
+ if (damage > 0)
+ {
+ //Prevent fall damage from being more than the player maximum health
+ if (damage > GetMaxHealth())
+ damage = GetMaxHealth();
+
+ // Gust of Wind
+ if (GetDummyAura(43621))
+ damage = GetMaxHealth()/2;
+
+ EnvironmentalDamage(GetGUID(), DAMAGE_FALL, damage);
+ }
+
+ //Z given by moveinfo, LastZ, FallTime, WaterZ, MapZ, Damage, Safefall reduction
+ DEBUG_LOG("FALLDAMAGE z=%f sz=%f pZ=%f FallTime=%d mZ=%f damage=%d SF=%d" , movementInfo.z, height, GetPositionZ(), movementInfo.fallTime, height, damage, safe_fall);
+ }
+ }
+}
+
+void Player::HandleFallUnderMap()
+{
+ if(InBattleGround() && GetBattleGround()
+ && GetBattleGround()->HandlePlayerUnderMap(this))
+ {
+ // do nothing, the handle already did if returned true
+ }
+ else
+ {
+ // NOTE: this is actually called many times while falling
+ // even after the player has been teleported away
+ // TODO: discard movement packets after the player is rooted
+ if(isAlive())
+ {
+ EnvironmentalDamage(GetGUID(),DAMAGE_FALL_TO_VOID, GetMaxHealth());
+ // change the death state to CORPSE to prevent the death timer from
+ // starting in the next player update
+ KillPlayer();
+ BuildPlayerRepop();
+ }
+
+ // cancel the death timer here if started
+ RepopAtGraveyard();
+ }
+}
void Player::Possess(Unit *target)
{
@@ -18936,8 +18936,8 @@ void Player::RemovePossess(bool attack)
if(attack)
target->AddThreat(this, 1000000.0f);
}
- // Delete the assigned possessed AI
- ((Creature*)target)->DeletePossessedAI();
+ // Disable the assigned possessed AI
+ ((Creature*)target)->DisablePossessedAI();
}
}
diff --git a/src/game/PossessedAI.cpp b/src/game/PossessedAI.cpp
index 6b803303185..8abbb7f2603 100644
--- a/src/game/PossessedAI.cpp
+++ b/src/game/PossessedAI.cpp
@@ -24,7 +24,7 @@
void PossessedAI::AttackStart(Unit *u)
{
- if( !u )
+ if( !u || i_pet.GetCharmer()->HasAuraType(SPELL_AURA_MOD_PACIFY))
return;
if (i_pet.getVictim() && u != i_pet.getVictim())
@@ -95,7 +95,7 @@ void PossessedAI::UpdateAI(const uint32 diff)
_stopAttack(); // i_victimGuid == 0 && i_pet.getVictim() == NULL now
return;
}
- else if(i_pet.IsWithinCombatDist(i_pet.getVictim(), ATTACK_DISTANCE) && i_pet.isAttackReady())
+ else if(i_pet.IsWithinCombatDist(i_pet.getVictim(), ATTACK_DISTANCE) && i_pet.isAttackReady() && !i_pet.GetCharmer()->HasAuraType(SPELL_AURA_MOD_PACIFY))
{
i_pet.AttackerStateUpdate(i_pet.getVictim());
diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h
index 37dca1aa656..dc22b3affbc 100644
--- a/src/game/SharedDefines.h
+++ b/src/game/SharedDefines.h
@@ -2069,7 +2069,7 @@ enum SummonType
SUMMON_TYPE_CRITTER2 = 407,
SUMMON_TYPE_CRITTER3 = 307,
SUMMON_TYPE_UNKNOWN5 = 409,
- SUMMON_TYPE_UNKNOWN2 = 427,
+ SUMMON_TYPE_POSESSED3 = 427,
SUMMON_TYPE_POSESSED2 = 428
};
diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp
index da6d67a3c6c..59d019800ed 100644
--- a/src/game/Spell.cpp
+++ b/src/game/Spell.cpp
@@ -1533,6 +1533,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
}break;
case TARGET_SCRIPT:
case TARGET_SCRIPT_COORDINATES:
+ case TARGET_UNIT_AREA_SCRIPT:
{
SpellScriptTarget::const_iterator lower = spellmgr.GetBeginSpellScriptTarget(m_spellInfo->Id);
SpellScriptTarget::const_iterator upper = spellmgr.GetEndSpellScriptTarget(m_spellInfo->Id);
@@ -3865,6 +3866,7 @@ uint8 Spell::CanCast(bool strict)
{
case SUMMON_TYPE_POSESSED:
case SUMMON_TYPE_POSESSED2:
+ case SUMMON_TYPE_POSESSED3:
case SUMMON_TYPE_DEMON:
case SUMMON_TYPE_SUMMON:
{
diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp
index 55203554665..35d39a22b27 100644
--- a/src/game/SpellAuras.cpp
+++ b/src/game/SpellAuras.cpp
@@ -49,7 +49,6 @@
#include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
#include "CellImpl.h"
-#include "TemporarySummon.h"
#define NULL_AURA_SLOT 0xFF
@@ -2024,13 +2023,6 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
m_target->CastSpell(m_target,47287,true,NULL,this);
return;
}
-
- // Eye of Kilrogg, unsummon eye when aura is gone
- if(GetId() == 126 && caster->GetTypeId() == TYPEID_PLAYER && caster->GetCharm())
- {
- ((TemporarySummon*)caster->GetCharm())->UnSummon();
- return;
- }
}
// AT APPLY & REMOVE
diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp
index a492e06f5b1..b3dcc2c5069 100644
--- a/src/game/SpellEffects.cpp
+++ b/src/game/SpellEffects.cpp
@@ -341,17 +341,17 @@ void Spell::EffectSchoolDMG(uint32 effect_idx)
return;
break;
}
- // gruul's shatter
- case 33671:
- {
- // don't damage self and only players
- if(unitTarget->GetGUID() == m_caster->GetGUID() || unitTarget->GetTypeId() != TYPEID_PLAYER)
- return;
-
- float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[0]));
- if(!radius) return;
- float distance = m_caster->GetDistance2d(unitTarget);
- damage = (distance > radius ) ? 0 : (int32)(m_spellInfo->EffectBasePoints[0]*((radius - distance)/radius));
+ // gruul's shatter
+ case 33671:
+ {
+ // don't damage self and only players
+ if(unitTarget->GetGUID() == m_caster->GetGUID() || unitTarget->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[0]));
+ if(!radius) return;
+ float distance = m_caster->GetDistance2d(unitTarget);
+ damage = (distance > radius ) ? 0 : (int32)(m_spellInfo->EffectBasePoints[0]*((radius - distance)/radius));
}break;
}
break;
@@ -3150,6 +3150,7 @@ void Spell::EffectSummonType(uint32 i)
break;
case SUMMON_TYPE_POSESSED:
case SUMMON_TYPE_POSESSED2:
+ case SUMMON_TYPE_POSESSED3:
EffectSummonPossessed(i);
break;
case SUMMON_TYPE_WILD:
@@ -3174,7 +3175,6 @@ void Spell::EffectSummonType(uint32 i)
EffectSummonTotem(i);
break;
case SUMMON_TYPE_UNKNOWN1:
- case SUMMON_TYPE_UNKNOWN2:
case SUMMON_TYPE_UNKNOWN3:
case SUMMON_TYPE_UNKNOWN4:
case SUMMON_TYPE_UNKNOWN5:
diff --git a/src/game/SpellHandler.cpp b/src/game/SpellHandler.cpp
index 07d8b18b543..6caab76e061 100644
--- a/src/game/SpellHandler.cpp
+++ b/src/game/SpellHandler.cpp
@@ -33,6 +33,7 @@
#include "MapManager.h"
#include "ScriptCalls.h"
#include "Totem.h"
+#include "TemporarySummon.h"
void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket)
{
@@ -376,6 +377,14 @@ void WorldSession::HandleCancelAuraOpcode( WorldPacket& recvPacket)
((Unit*)_player->GetFarsightTarget())->RemoveAurasDueToSpellByCancel(spellId);
return;
}
+ else if (spellInfo->Effect[i] == SPELL_EFFECT_SUMMON &&
+ (spellInfo->EffectMiscValueB[i] == SUMMON_TYPE_POSESSED ||
+ spellInfo->EffectMiscValueB[i] == SUMMON_TYPE_POSESSED2 ||
+ spellInfo->EffectMiscValueB[i] == SUMMON_TYPE_POSESSED3))
+ {
+ // Possession is removed in the UnSummon function
+ ((TemporarySummon*)_player->GetCharm())->UnSummon();
+ }
}
}
diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp
index 94f647cdd46..bcdd771bcea 100644
--- a/src/game/Unit.cpp
+++ b/src/game/Unit.cpp
@@ -46,6 +46,7 @@
#include "GridNotifiersImpl.h"
#include "CellImpl.h"
#include "Path.h"
+#include "TemporarySummon.h"
#include <math.h>
@@ -3418,6 +3419,21 @@ void Unit::InterruptNonMeleeSpells(bool withDelayed, uint32 spell_id)
// channeled spells are interrupted if they are not finished, even if they are delayed
if (m_currentSpells[CURRENT_CHANNELED_SPELL] && (!spell_id || m_currentSpells[CURRENT_CHANNELED_SPELL]->m_spellInfo->Id==spell_id))
{
+ // Unsummon any summoned as possessed creatures on channel interrupt
+ SpellEntry const *spellInfo = m_currentSpells[CURRENT_CHANNELED_SPELL]->m_spellInfo;
+ for (int i = 0; i < 3; i++)
+ {
+ if (spellInfo->Effect[i] == SPELL_EFFECT_SUMMON &&
+ (spellInfo->EffectMiscValueB[i] == SUMMON_TYPE_POSESSED ||
+ spellInfo->EffectMiscValueB[i] == SUMMON_TYPE_POSESSED2 ||
+ spellInfo->EffectMiscValueB[i] == SUMMON_TYPE_POSESSED3))
+ {
+ // Possession is removed in the UnSummon function
+ if (GetCharm())
+ ((TemporarySummon*)GetCharm())->UnSummon();
+ }
+ }
+
if (m_currentSpells[CURRENT_CHANNELED_SPELL]->getState() != SPELL_STATE_FINISHED)
m_currentSpells[CURRENT_CHANNELED_SPELL]->cancel();
m_currentSpells[CURRENT_CHANNELED_SPELL]->SetReferencedFromCurrent(false);
@@ -9797,7 +9813,7 @@ CharmInfo* Unit::InitCharmInfo(Unit *charm)
}
CharmInfo::CharmInfo(Unit* unit)
-: m_unit(unit), m_CommandState(COMMAND_FOLLOW), m_reactState(REACT_PASSIVE), m_petnumber(0)
+: m_unit(unit), m_CommandState(COMMAND_FOLLOW), m_reactState(REACT_PASSIVE), m_petnumber(0), m_barInit(false)
{
for(int i =0; i<4; ++i)
{
@@ -9808,6 +9824,9 @@ CharmInfo::CharmInfo(Unit* unit)
void CharmInfo::InitPetActionBar()
{
+ if (m_barInit)
+ return;
+
// the first 3 SpellOrActions are attack, follow and stay
for(uint32 i = 0; i < 3; i++)
{
@@ -9822,17 +9841,25 @@ void CharmInfo::InitPetActionBar()
PetActionBar[i + 3].Type = ACT_DISABLED;
PetActionBar[i + 3].SpellOrAction = 0;
}
+ m_barInit = true;
}
-void CharmInfo::InitEmptyActionBar()
+void CharmInfo::InitEmptyActionBar(bool withAttack)
{
- for(uint32 x = 1; x < 10; ++x)
+ if (m_barInit)
+ return;
+
+ for(uint32 x = 0; x < 10; ++x)
{
PetActionBar[x].Type = ACT_CAST;
PetActionBar[x].SpellOrAction = 0;
}
- PetActionBar[0].Type = ACT_COMMAND;
- PetActionBar[0].SpellOrAction = COMMAND_ATTACK;
+ if (withAttack)
+ {
+ PetActionBar[0].Type = ACT_COMMAND;
+ PetActionBar[0].SpellOrAction = COMMAND_ATTACK;
+ }
+ m_barInit = true;
}
void CharmInfo::InitPossessCreateSpells()
diff --git a/src/game/Unit.h b/src/game/Unit.h
index cd5770cccd6..5ae34624c96 100644
--- a/src/game/Unit.h
+++ b/src/game/Unit.h
@@ -640,7 +640,7 @@ struct CharmSpellEntry
typedef std::list<Player*> SharedVisionList;
-struct CharmInfo
+struct TRINITY_DLL_SPEC CharmInfo
{
public:
explicit CharmInfo(Unit* unit);
@@ -657,7 +657,7 @@ struct CharmInfo
void InitPossessCreateSpells();
void InitCharmCreateSpells();
void InitPetActionBar();
- void InitEmptyActionBar();
+ void InitEmptyActionBar(bool withAttack = true);
//return true if successful
bool AddSpellToAB(uint32 oldid, uint32 newid, ActiveStates newstate = ACT_DECIDE);
void ToggleCreatureAutocast(uint32 spellid, bool apply);
@@ -671,6 +671,7 @@ struct CharmInfo
CommandStates m_CommandState;
ReactStates m_reactState;
uint32 m_petnumber;
+ bool m_barInit;
};
// for clearing special attacks