diff --git a/zone/client.h b/zone/client.h index ac505ecdb..73bde1a69 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1130,6 +1130,7 @@ public: inline bool IsDraggingCorpse() { return (DraggedCorpses.size() > 0); } void DragCorpses(); inline void ClearDraggedCorpses() { DraggedCorpses.clear(); } + inline void ResetPositionTimer() { position_timer_counter = 0; } void SendAltCurrencies(); void SetAlternateCurrencyValue(uint32 currency_id, uint32 new_amount); void AddAlternateCurrencyValue(uint32 currency_id, int32 amount, int8 method = 0); diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index b3aaad1dc..650ba350c 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -1653,76 +1653,17 @@ void NPC::AI_DoMovement() { if (gridno > 0 || cur_wp==-2) { if (movetimercompleted==true) { // time to pause at wp is over - - int32 spawn_id = this->GetSpawnPointID(); - LinkedListIterator iterator(zone->spawn2_list); - iterator.Reset(); - Spawn2 *found_spawn = nullptr; - - while(iterator.MoreElements()) - { - Spawn2* cur = iterator.GetData(); - iterator.Advance(); - if(cur->GetID() == spawn_id) - { - found_spawn = cur; - break; - } - } - - if (wandertype == 4 && cur_wp == CastToNPC()->GetMaxWp()) { - CastToNPC()->Depop(true); //depop and resart spawn timer - if(found_spawn) - found_spawn->SetNPCPointerNull(); - } - else if (wandertype == 6 && cur_wp == CastToNPC()->GetMaxWp()) { - CastToNPC()->Depop(false);//depop without spawn timer - if(found_spawn) - found_spawn->SetNPCPointerNull(); - } - else { - movetimercompleted=false; - - Log.Out(Logs::Detail, Logs::Pathing, "We are departing waypoint %d.", cur_wp); - - //if we were under quest control (with no grid), we are done now.. - if(cur_wp == -2) { - Log.Out(Logs::Detail, Logs::Pathing, "Non-grid quest mob has reached its quest ordered waypoint. Leaving pathing mode."); - roamer = false; - cur_wp = 0; - } - - if(GetAppearance() != eaStanding) - SetAppearance(eaStanding, false); - - entity_list.OpenDoorsNear(CastToNPC()); - - if(!DistractedFromGrid) { - //kick off event_waypoint depart - char temp[16]; - sprintf(temp, "%d", cur_wp); - parse->EventNPC(EVENT_WAYPOINT_DEPART, CastToNPC(), nullptr, temp, 0); - - //setup our next waypoint, if we are still on our normal grid - //remember that the quest event above could have done anything it wanted with our grid - if(gridno > 0) { - CastToNPC()->CalculateNewWaypoint(); - } - } - else { - DistractedFromGrid = false; - } - } + AI_SetupNextWaypoint(); } // endif (movetimercompleted==true) else if (!(AIwalking_timer->Enabled())) { // currently moving + bool doMove = true; if (m_CurrentWayPoint.x == GetX() && m_CurrentWayPoint.y == GetY()) { // are we there yet? then stop Log.Out(Logs::Detail, Logs::AI, "We have reached waypoint %d (%.3f,%.3f,%.3f) on grid %d", cur_wp, GetX(), GetY(), GetZ(), GetGrid()); if (cur_wp_pause != 0) { SetWaypointPause(); - if(GetAppearance() != eaStanding) - SetAppearance(eaStanding, false); + SetAppearance(eaStanding, false); SetMoving(false); if (m_CurrentWayPoint.w >= 0.0) { SetHeading(m_CurrentWayPoint.w); @@ -1734,13 +1675,17 @@ void NPC::AI_DoMovement() { char temp[16]; sprintf(temp, "%d", cur_wp); parse->EventNPC(EVENT_WAYPOINT_ARRIVE, CastToNPC(), nullptr, temp, 0); - + // start moving directly to next waypoint if we're at a 0 pause waypoint and we didn't get quest halted. + if (!AIwalking_timer->Enabled()) + AI_SetupNextWaypoint(); + else + doMove = false; // wipe feign memory since we reached our first waypoint if(cur_wp == 1) ClearFeignMemory(); } - else - { // not at waypoint yet, so keep moving + if (doMove) + { // not at waypoint yet or at 0 pause WP, so keep moving if(!RuleB(Pathing, AggroReturnToGrid) || !zone->pathing || (DistractedFromGrid == 0)) CalculateNewPosition2(m_CurrentWayPoint.x, m_CurrentWayPoint.y, m_CurrentWayPoint.z, walksp, true); else @@ -1768,8 +1713,7 @@ void NPC::AI_DoMovement() { SetGrid( 0 - GetGrid()); // revert to AI control Log.Out(Logs::Detail, Logs::Pathing, "Quest pathing is finished. Resuming on grid %d", GetGrid()); - if(GetAppearance() != eaStanding) - SetAppearance(eaStanding, false); + SetAppearance(eaStanding, false); CalculateNewWaypoint(); } @@ -1818,15 +1762,73 @@ void NPC::AI_DoMovement() { } } +void NPC::AI_SetupNextWaypoint() { + int32 spawn_id = this->GetSpawnPointID(); + LinkedListIterator iterator(zone->spawn2_list); + iterator.Reset(); + Spawn2 *found_spawn = nullptr; + + while (iterator.MoreElements()) + { + Spawn2* cur = iterator.GetData(); + iterator.Advance(); + if (cur->GetID() == spawn_id) + { + found_spawn = cur; + break; + } + } + + if (wandertype == 4 && cur_wp == CastToNPC()->GetMaxWp()) { + CastToNPC()->Depop(true); //depop and restart spawn timer + if (found_spawn) + found_spawn->SetNPCPointerNull(); + } + else if (wandertype == 6 && cur_wp == CastToNPC()->GetMaxWp()) { + CastToNPC()->Depop(false);//depop without spawn timer + if (found_spawn) + found_spawn->SetNPCPointerNull(); + } + else { + movetimercompleted = false; + + Log.Out(Logs::Detail, Logs::Pathing, "We are departing waypoint %d.", cur_wp); + + //if we were under quest control (with no grid), we are done now.. + if (cur_wp == -2) { + Log.Out(Logs::Detail, Logs::Pathing, "Non-grid quest mob has reached its quest ordered waypoint. Leaving pathing mode."); + roamer = false; + cur_wp = 0; + } + + SetAppearance(eaStanding, false); + + entity_list.OpenDoorsNear(CastToNPC()); + + if (!DistractedFromGrid) { + //kick off event_waypoint depart + char temp[16]; + sprintf(temp, "%d", cur_wp); + parse->EventNPC(EVENT_WAYPOINT_DEPART, CastToNPC(), nullptr, temp, 0); + + //setup our next waypoint, if we are still on our normal grid + //remember that the quest event above could have done anything it wanted with our grid + if (GetGrid() > 0) { + CastToNPC()->CalculateNewWaypoint(); + } + } + else { + DistractedFromGrid = false; + } + } +} + // Note: Mob that caused this may not get added to the hate list until after this function call completes void Mob::AI_Event_Engaged(Mob* attacker, bool iYellForHelp) { if (!IsAIControlled()) return; - if(GetAppearance() != eaStanding) - { - SetAppearance(eaStanding); - } + SetAppearance(eaStanding); if (iYellForHelp) { if(IsPet()) { diff --git a/zone/npc.h b/zone/npc.h index 95a857460..f960c736e 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -119,6 +119,7 @@ public: virtual void AI_Start(uint32 iMoveDelay = 0); virtual void AI_Stop(); void AI_DoMovement(); + void AI_SetupNextWaypoint(); bool AI_AddNPCSpells(uint32 iDBSpellsID); bool AI_AddNPCSpellsEffects(uint32 iDBSpellsEffectsID); virtual bool AI_EngagedCastCheck(); diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index c4f37864d..7570165a3 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -394,6 +394,7 @@ void NPC::SetWaypointPause() if (cur_wp_pause == 0) { AIwalking_timer->Start(100); + AIwalking_timer->Trigger(); } else { @@ -519,6 +520,7 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo return true; } + bool send_update = false; int compare_steps = IsBoat() ? 1 : 20; if(tar_ndx < compare_steps && m_TargetLocation.x==x && m_TargetLocation.y==y) { @@ -709,11 +711,18 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo m_Delta = glm::vec4(m_Position.x - nx, m_Position.y - ny, m_Position.z - nz, 0.0f); if (IsClient()) + { SendPosUpdate(1); + CastToClient()->ResetPositionTimer(); + } else + { + // force an update now + move_tic_count = RuleI(Zone, NPCPositonUpdateTicCount); SendPosUpdate(); + SetAppearance(eaStanding, false); + } - SetAppearance(eaStanding, false); pLastChange = Timer::GetCurrentTime(); return true; }