#define QUEST_ID xxxxxx // related quest, 0 if no quest #define ESCORT_TIMER xxxxxx // set quest time limit in seconds 0 if NO TIME LIMIT #define MAX_FOLLOW_DISTANCE xxx // max distance before escort fails /************************* Generic Follower AI *************************/ struct MANGOS_DLL_DECL generic_followerAI : public ScriptedAI { npc_fluff_escortAI(Creature *c) : ScriptedAI(c) {Reset();} uint64 pGUID; uint32 EscortTimer; bool TimeLimit; float FollowDistance; void Reset() { pGUID = 0; EscortTimer = ESCORT_TIMER; if(!EscortTimer) TimeLimit = false; else TimeLimit = true; FollowDistance = 30.0f; if (MAX_FOLLOW_DISTANCE) FollowDistance = MAX_FOLLOW_DISTANCE; } void Aggro(Unit *who) { } void MoveInLineOfSight(Unit* who) { if (!who) return; /* Add LOS check for attack start here if you want it to attack enemies */ /* THIS PART ALLOWS THE NPC TO PICK AN OWNER, BASED ON HAVING 'QUEST_ID' INCOMPLETE */ if (!QUEST_ID) return; if (!pGUID) { if (m_creature->IsWithinDistInMap(who, 10.0f) && (who->GetTypeId() == TYPEID_PLAYER) && ((Player*)who)->GetQuestStatus(QUEST_ID) == QUEST_STATUS_INCOMPLETE) { pGUID = who->GetGUID(); EscortPhase = 0; if(pGUID) { Player* pEscort = NULL; pEscort = (Player*)Unit::GetUnit((*m_creature), pGUID); if (pEscort) { m_creature->GetMotionMaster()->MoveFollow(pEscort, 2.0, 0.0); } } } } } /* CALL THROUGH GOSSIP OPTION OR THROUGH QUEST ACCEPT SCRIPT */ void InitiateFollow(uint64 owner) { pGUID = owner; Player* pEscort = NULL; pEscort = (Player*)Unit::GetUnit((*m_creature), pGUID); if (pEscort) { m_creature->GetMotionMaster()->MoveFollow(pEscort, 2.0, 0.0); } } void ActionSequence(uint32 action) { } void UpdateAI(const uint32 diff) { if (pGUID) { Player* pEscort = NULL; pEscort = (Player*)Unit::GetUnit((*m_creature), pGUID); if (!pEscort) return; if (pEscort->isDead()) { if (QUEST_ID) pEscort->FailQuest(QUEST_ID); m_creature->GetMotionMaster()->Clear(false); m_creature->SetVisibility(VISIBILITY_OFF); m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); pGUID = 0; return; } if (m_creature->isDead()) { if (QUEST_ID) pEscort->FailQuest(QUEST_ID); m_creature->SetVisibility(VISIBILITY_OFF); pGUID = 0; return; } if (!m_creature->IsWithinDistInMap(pEscort, FollowDistance)) { if (QUEST_ID) pEscort->FailQuest(QUEST_ID); m_creature->GetMotionMaster()->Clear(false); m_creature->SetVisibility(VISIBILITY_OFF); m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); pGUID = 0; return; } if (TimeLimit) { if (EscortTimer < diff) { if (QUEST_ID) pEscort->FailQuest(QUEST_ID); m_creature->GetMotionMaster()->Clear(false); m_creature->SetVisibility(VISIBILITY_OFF); m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); pGUID = 0; return; } else { EscortTimer -= diff; } } } } };