Index: scripts/zone/dustwallow_marsh/npcs_dustwallow_marsh.cpp =================================================================== --- scripts/zone/dustwallow_marsh/npcs_dustwallow_marsh.cpp (revision 259) +++ scripts/zone/dustwallow_marsh/npcs_dustwallow_marsh.cpp (working copy) @@ -25,6 +25,7 @@ #include "../../../../../game/Player.h" #include "../../../../../game/QuestDef.h" #include "../../../../../game/GossipDef.h" +#include "../../../../../game/RandomMovementGenerator.h" /*###### ## npc_deserter_agitator @@ -407,6 +408,325 @@ } /*###### +npc_private_hendel +######*/ + +#define SAY_ARCHMAGE_1 "Why don't we deal with you now, Hendel? Lady Proudmoore will speak for you back in the tower." +#define SAY_HENDEL "Please... please... Miss Proudmore I didn't mean to..." +#define SAY_ARCHMAGE_2 "I apologize for taking so long to get here. I wanted Lady Proudmoore to be present also." +#define SAY_ARCHMAGE_3 "We can only stay a few moments before returning to the tower. If you wish to speak to us more you may find us there." +#define NPC_PROUDMORE 4968 +#define NPC_ARCHMAGE 4967 +#define NPC_PAINED 4965 +#define NPC_GUARD 5184 +#define QUEST_THE_MISSING_DIPLOMAT 1324 + +static Location GuardLocation[] = +{ + (-2889.18, -3337.46, 32.5128, 3.676120), + (-2890.5, -3344.49, 32.3878, 2.15425) +}; + +static Location ProudmoreLocation = +{ + (-2881.44, -3347.52, 34.18, 2.85) +}; + +static Location ArchmageLocation = +{ +-2882.83, -3345.46, 33.68, 3.21 +}; + +static Location PainedLocation = +{ + (-2880.70, -3343.93, 34.38, 3.36) +}; + + +struct MANGOS_DLL_DECL npc_private_hendelAI : public ScriptedAI +{ + + uint64 ArchmageGUID; + uint64 ProudmoreGUID; //currently unused + uint64 GuardGUID[2]; + bool DoingSpeach; + uint32 SpeachTimer; + uint32 SpeachNum; + uint32 CheckGuardTimer; //currently unused + bool GuardsSummoned; + Unit* PlayerHolder; //currently unused + bool EventStarted; + + npc_private_hendelAI(Creature *c) : ScriptedAI(c) + { + GuardGUID[0]=0; + GuardGUID[1]=0; + CheckGuardTimer=30000; + EnterEvadeMode(); + } + + void EnterEvadeMode() + { + SpeachTimer = 0; + SpeachNum = 0; + DoingSpeach = false; + + ArchmageGUID=0; + ProudmoreGUID=0; + + m_creature->RemoveAllAuras(); + m_creature->DeleteThreatList(); + m_creature->CombatStop(); + DoGoHome(); + m_creature->setFaction(1077); + PlayerHolder = NULL; + StopGuards(); + EventStarted = false; + } + + void AttackStart(Unit *who) + { + if (!who) + return; + + if (who->isTargetableForAttack() && who!= m_creature) + { + DoStartMeleeAttack(who); + } + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || m_creature->getVictim()) + return; + + if (who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who)) + { + float attackRadius = m_creature->GetAttackDistance(who); + if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who)) + { + if(who->HasStealthAura()) + who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + //Begin melee attack if we are within range + DoStartMeleeAttack(who); + } + } + } + + void StartEvent(Player *player) + { + m_creature->setFaction(168); + for (uint8 i = 0; i < 2; i++) //make guards hostil and attacking player + { + Unit *Guard = NULL; + if (GuardGUID[i] != 0) + { + Guard = ((Creature*)Unit::GetUnit((*m_creature), GuardGUID[i])); + Guard->setFaction(168); + ((Creature *)Guard)->AI()->AttackStart(player); + } + } + PlayerHolder = player; + AttackStart(player); + EventStarted = true; + } + + + //implements duell part with private hendel + void DamageTaken(Unit *done_by, uint32 &damage) + { + if ( (m_creature->GetHealth() - damage) *100 / m_creature->GetMaxHealth() < 15 && !DoingSpeach) //capture damage that will reduce HP < 15% + { + + if (done_by->GetTypeId() == TYPEID_PLAYER) + { + damage = 0; //0 damage taken + ((Player*) done_by)->AttackStop(); //stop duell + m_creature->SetCreateHealth(1); + m_creature->setFaction(1077); + m_creature->MonsterTextEmote(", too injured, gives up the chase.", 0); + EnterEvadeMode(); + + //summon npc needed to end quest + m_creature->SummonCreature(NPC_PROUDMORE, ProudmoreLocation.x,ProudmoreLocation.y, ProudmoreLocation.z, ProudmoreLocation.o, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + Creature *Archmage = m_creature->SummonCreature(NPC_ARCHMAGE, ArchmageLocation.x, ArchmageLocation.y, ArchmageLocation.z, ArchmageLocation.o , TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); + if (Archmage) ArchmageGUID = Archmage->GetGUID(); + m_creature->SummonCreature(NPC_PAINED, PainedLocation.x, PainedLocation.y, PainedLocation.z, PainedLocation.o, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + DoingSpeach = true; + SpeachTimer = 5000; + SpeachNum = 0; + } else m_creature->CombatStop(); + } + AttackedBy(done_by); + } + + //complete quest 1324 to player and group + void CompleteQuestTheMissingDiplomat (Unit *victim) + { + if (victim && (victim->GetTypeId() == TYPEID_PLAYER)) + { + Player *killer = (Player *) victim; + + //check if quest need to be rewarded to killer + if ( killer->IsActiveQuest(QUEST_THE_MISSING_DIPLOMAT) && !killer->GetQuestRewardStatus(QUEST_THE_MISSING_DIPLOMAT) ) + killer->CompleteQuest(QUEST_THE_MISSING_DIPLOMAT); + + //check if quest need to be rewarded to member of killers group in LoS. + Group *killerGroup = killer->GetGroup(); + if ( killerGroup ) + { + Player *groupMember; + const Group::MemberSlotList members = killerGroup->GetMemberSlots(); + for (Group::member_citerator itr = members.begin(); itr != members.end(); itr++) + { + groupMember = (Player*)(Unit::GetUnit((*m_creature),itr->guid)); + if ( groupMember && groupMember->IsActiveQuest(QUEST_THE_MISSING_DIPLOMAT) && !groupMember->GetQuestRewardStatus(QUEST_THE_MISSING_DIPLOMAT) && groupMember->IsWithinLOSInMap(m_creature) ) + groupMember->CompleteQuest(QUEST_THE_MISSING_DIPLOMAT); + } + } + } + } + + void SummonGuards() + { + //spawn Guards if they are not present + Unit *Guard ; + for (uint8 i = 0; i < 2; i ++) + { + if (GuardGUID[i] == 0) + { + Guard = NULL; + //Guard = m_creature->SummonCreature(NPC_GUARD, GuardLocation[i].x, GuardLocation[i].y, GuardLocation[i].z, GuardLocation[i].o, TEMPSUMMON_CORPSE_DESPAWN, 0); + Guard = DoSpawnCreature(NPC_GUARD, 0, 0, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + if (Guard) + { + GuardGUID[i] = Guard->GetGUID(); + + ((Creature*)Guard)->SetRespawnDist(5.0f); + Guard->GetMotionMaster()->Clear(false); + Guard->GetMotionMaster()->Mutate(new RandomMovementGenerator(*Guard)); + } + } else if ((Creature*)Unit::GetUnit((*m_creature), GuardGUID[i]) == NULL) GuardGUID[i] = 0; //set guid = 0 if one guard was killed + } + } + + void StopGuards() + { + for (uint8 i = 0; i < 2; i++) //stop guards + { + Unit *Guard = NULL; + if (GuardGUID[i] != 0) + { + Guard = ((Creature*)Unit::GetUnit((*m_creature), GuardGUID[i])); + if (Guard) + { + Guard->setFaction(150); + Guard->CombatStop(); + ((Creature*)Guard)->AI()->EnterEvadeMode(); + } + } + } + } + + void UpdateAI(const uint32 diff) + { + if (m_creature->isAlive() && !EventStarted) //bad coded part, need a better solution here ? + if (CheckGuardTimer < diff) + { + SummonGuards(); + CheckGuardTimer = 30000; + } else CheckGuardTimer -= diff; + + if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + return; //Return since we have no target + + if(DoingSpeach) + { + if (SpeachTimer < diff) + { + switch (SpeachNum) + { + case 0: + if(ArchmageGUID) + { + Creature* Archmage = NULL; + Archmage = ((Creature*)Unit::GetUnit((*m_creature), ArchmageGUID)); + if(Archmage && (Archmage->isAlive())) + { + Archmage->Say(SAY_ARCHMAGE_1, LANG_UNIVERSAL, 0); + SpeachTimer = 6000; + SpeachNum++; + } + } + break; + + case 1: + m_creature->Say(SAY_HENDEL, LANG_UNIVERSAL, 0); + SpeachTimer = 3000; + SpeachNum++; + break; + + case 2: + if(ArchmageGUID) + { + Creature* Archmage = NULL; + Archmage = ((Creature*)Unit::GetUnit((*m_creature), ArchmageGUID)); + if(Archmage && (Archmage->isAlive())) + { + Archmage->Say(SAY_ARCHMAGE_2, LANG_UNIVERSAL, 0); + SpeachTimer = 6000; + SpeachNum++; + } + } + break; + + case 3: + if(ArchmageGUID) + { + Creature* Archmage = NULL; + Archmage = ((Creature*)Unit::GetUnit((*m_creature), ArchmageGUID)); + if(Archmage && (Archmage->isAlive())) + { + CompleteQuestTheMissingDiplomat(m_creature->getVictim()); + Archmage->Say(SAY_ARCHMAGE_3, LANG_UNIVERSAL, 0); + EnterEvadeMode(); + } + } + break; + } + }else SpeachTimer -= diff; + return; + } + + 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->AttackerStateUpdate(m_creature->getVictim()); + m_creature->resetAttackTimer(); + } + } + } +}; + +bool QuestAccept_npc_private_hendel(Player *player, Creature *_Creature, Quest const *_Quest) +{ + if(_Quest->GetQuestId() == QUEST_THE_MISSING_DIPLOMAT) + { + ((npc_private_hendelAI*)_Creature->AI())->StartEvent(player); + } + return true; +} + +CreatureAI* GetAI_npc_private_hendel(Creature *_creature) +{ + return new npc_private_hendelAI(_creature); +} + + +/*###### ## ######*/ @@ -441,4 +761,11 @@ newscript->GetAI = GetAI_npc_doctor; newscript->pQuestAccept = &QuestAccept_npc_doctor; m_scripts[nrscripts++] = newscript; + + newscript = new Script; + newscript->Name = "npc_private_hendel"; + newscript->GetAI = GetAI_npc_private_hendel; + newscript->pQuestAccept = &QuestAccept_npc_private_hendel; + m_scripts[nrscripts++] = newscript; + }