bool npc_escortAI::IsPlayerOrGroupInRange() { if (Player* pPlayer = GetPlayerForEscort()) { if (Group* pGroup = pPlayer->GetGroup()) { for (GroupReference* pRef = pGroup->GetFirstMember(); pRef != NULL; pRef = pRef->next()) { Player* pMember = pRef->getSource(); if (pMember && m_creature->IsWithinDistInMap(pMember, GetMaxPlayerDistance())) { return true; break; } } } else { if (m_creature->IsWithinDistInMap(pPlayer, GetMaxPlayerDistance())) return true; } } return false; }
//see followerAI bool npc_escortAI::AssistPlayerInCombat(Unit* pWho) { if (!pWho || !pWho->getVictim()) return false; //experimental (unknown) flag not present if (!(me->GetCreatureInfo()->type_flags & CREATURE_TYPEFLAGS_AID_PLAYERS)) return false; //not a player if (!pWho->getVictim()->GetCharmerOrOwnerPlayerOrPlayerItself()) return false; //never attack friendly if (me->IsFriendlyTo(pWho)) return false; //too far away and no free sight? if (me->IsWithinDistInMap(pWho, GetMaxPlayerDistance()) && me->IsWithinLOSInMap(pWho)) { //already fighting someone? if (!me->getVictim()) { AttackStart(pWho); return true; } else { pWho->SetInCombatWith(me); me->AddThreat(pWho, 0.0f); return true; } } return false; }
void WaypointReached(uint32 waypointId) { switch (waypointId) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: if (Player* player = GetPlayerForEscort()) { // If player is out of range or has lost his aura, evade! if (!player->IsInRange(me, 0.0f, GetMaxPlayerDistance()) || (!player->HasAura(SPELL_SCARLET_RAVEN_PRIEST_IMAGE_MALE) && !player->HasAura(SPELL_SCARLET_RAVEN_PRIEST_IMAGE_FEMALE))) { EnterEvadeMode(); } } else EnterEvadeMode(); // Should not happen regularly, but... break; case 9: // 0-8 are irrelevant, 10 is a dummy. SetEscortPaused(true); if(Player* player = GetPlayerForEscort()) me->SetFacingToObject(player); else EnterEvadeMode(); // Should not happen regularly, but... events.ScheduleEvent(EVENT_SPEECH_DISGUISE, 1000); break; } }
bool npc_escortAI::IsPlayerOrGroupInRange() { if (Player* player = GetPlayerForEscort()) { if (Group* group = player->GetGroup()) { for (GroupReference* groupRef = group->GetFirstMember(); groupRef != NULL; groupRef = groupRef->next()) if (Player* member = groupRef->GetSource()) if (me->IsWithinDistInMap(member, GetMaxPlayerDistance())) return true; } else if (me->IsWithinDistInMap(player, GetMaxPlayerDistance())) return true; } return false; }
//see followerAI bool npc_escortAI::AssistPlayerInCombatAgainst(Unit* who) { if (!who || !who->GetVictim()) return false; //experimental (unknown) flag not present if (!(me->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_CAN_ASSIST)) return false; //not a player if (!who->EnsureVictim()->GetCharmerOrOwnerPlayerOrPlayerItself()) return false; //never attack friendly if (me->IsFriendlyTo(who)) return false; //too far away and no free sight? if (me->IsWithinDistInMap(who, GetMaxPlayerDistance()) && me->IsWithinLOSInMap(who)) { //already fighting someone? if (!me->GetVictim()) { AttackStart(who); return true; } else { who->SetInCombatWith(me); me->AddThreat(who, 0.0f); return true; } } return false; }
void npc_escortAI::UpdateAI(const uint32 diff) { //Waypoint Updating if (IsBeingEscorted && !m_creature->isInCombat() && WaitTimer && !Returning) { if (WaitTimer <= diff) { if (ReconnectWP) { //Correct movement speed if (bIsRunning && m_creature->HasUnitMovementFlag(MOVEMENTFLAG_WALK_MODE)) m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); else if (!bIsRunning && !m_creature->HasUnitMovementFlag(MOVEMENTFLAG_WALK_MODE)) m_creature->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); //Continue with waypoints if( !IsOnHold ) { if (CurrentWP != WaypointList.end()) { m_creature->GetMotionMaster()->MovePoint(CurrentWP->id, CurrentWP->x, CurrentWP->y, CurrentWP->z ); debug_log("RSCR: EscortAI Reconnect WP is: %u, %f, %f, %f", CurrentWP->id, CurrentWP->x, CurrentWP->y, CurrentWP->z); WaitTimer = 0; ReconnectWP = false; return; } else debug_log("RSCR: EscortAI Reconnected to end of WP list"); } } //End of the line, Despawn self then immediatly respawn if (CurrentWP == WaypointList.end()) { if(DespawnAtEnd) { debug_log("RSCR: EscortAI reached end of waypoints"); m_creature->setDeathState(JUST_DIED); m_creature->Respawn(); m_creature->GetMotionMaster()->Clear(true); //Restore original NpcFlags m_creature->SetUInt32Value(UNIT_NPC_FLAGS, m_uiNpcFlags); IsBeingEscorted = false; WaitTimer = 0; return; } else { debug_log("RSCR: EscortAI reached end of waypoints with Despawn off"); IsBeingEscorted = false; WaitTimer = 0; return; } } if( !IsOnHold ) { m_creature->GetMotionMaster()->MovePoint(CurrentWP->id, CurrentWP->x, CurrentWP->y, CurrentWP->z ); debug_log("RSCR: EscortAI Next WP is: %u, %f, %f, %f", CurrentWP->id, CurrentWP->x, CurrentWP->y, CurrentWP->z); WaitTimer = 0; } }else WaitTimer -= diff; } //Check if player is within range if (IsBeingEscorted && !m_creature->isInCombat() && PlayerGUID) { if (PlayerTimer < diff) { Unit* p = Unit::GetUnit(*m_creature, PlayerGUID); if (DespawnAtFar && (!p || !m_creature->IsWithinDist(p,GetMaxPlayerDistance()))) { JustDied(m_creature); IsBeingEscorted = false; debug_log("RSCR: EscortAI Evaded back to spawn point because player was to far away or not found"); m_creature->setDeathState(JUST_DIED); m_creature->SetHealth(0); m_creature->CombatStop(true); m_creature->DeleteThreatList(); m_creature->Respawn(); m_creature->GetMotionMaster()->Clear(true); //Restore original NpcFlags m_creature->SetUInt32Value(UNIT_NPC_FLAGS, m_uiNpcFlags); } PlayerTimer = 1000; }else PlayerTimer -= diff; } if(CanMelee && UpdateVictim()) DoMeleeAttackIfReady(); }
void npc_escortAI::UpdateAI(const uint32 diff) { //Waypoint Updating if (IsBeingEscorted && !InCombat && WaitTimer && !Returning) { if (WaitTimer <= diff) { if (ReconnectWP) { //Correct movement speed if (Run) m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); else m_creature->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); //Continue with waypoints if( !IsOnHold ) { m_creature->GetMotionMaster()->MovePoint(CurrentWP->id, CurrentWP->x, CurrentWP->y, CurrentWP->z ); debug_log("TSCR: EscortAI Reconnect WP is: %u, %f, %f, %f", CurrentWP->id, CurrentWP->x, CurrentWP->y, CurrentWP->z); WaitTimer = 0; ReconnectWP = false; return; } } //End of the line, Despawn self then immediatly respawn if (CurrentWP == WaypointList.end()) { if(DespawnAtEnd) { debug_log("TSCR: EscortAI reached end of waypoints"); m_creature->setDeathState(JUST_DIED); m_creature->SetHealth(0); m_creature->CombatStop(); m_creature->DeleteThreatList(); m_creature->Respawn(); m_creature->GetMotionMaster()->Clear(true); //Re-Enable gossip m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); IsBeingEscorted = false; WaitTimer = 0; return; }else{ debug_log("TSCR: EscortAI reached end of waypoints with Despawn off"); IsBeingEscorted = false; WaitTimer = 0; return; } } if( !IsOnHold ) { m_creature->GetMotionMaster()->MovePoint(CurrentWP->id, CurrentWP->x, CurrentWP->y, CurrentWP->z ); debug_log("TSCR: EscortAI Next WP is: %u, %f, %f, %f", CurrentWP->id, CurrentWP->x, CurrentWP->y, CurrentWP->z); WaitTimer = 0; } }else WaitTimer -= diff; } //Check if player is within range if (IsBeingEscorted && !InCombat && PlayerGUID) { if (PlayerTimer < diff) { Unit* p = Unit::GetUnit(*m_creature, PlayerGUID); if (DespawnAtFar && (!p || m_creature->GetDistance(p) > GetMaxPlayerDistance())) { JustDied(m_creature); IsBeingEscorted = false; debug_log("TSCR: EscortAI Evaded back to spawn point because player was to far away or not found"); m_creature->setDeathState(JUST_DIED); m_creature->SetHealth(0); m_creature->CombatStop(); m_creature->DeleteThreatList(); m_creature->Respawn(); m_creature->GetMotionMaster()->Clear(true); //Re-Enable gossip m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); } PlayerTimer = 1000; }else PlayerTimer -= diff; } if(CanMelee) { //Check if we have a current target if( m_creature->isAlive() && UpdateVictim() && m_creature->canMelee() ) { //If we are within range melee the target if( m_creature->IsWithinMeleeRange(m_creature->getVictim())) { if( m_creature->isAttackReady() ) { m_creature->AttackerStateUpdate(m_creature->getVictim()); m_creature->resetAttackTimer(); } } } } }