diff --git a/zone/command.cpp b/zone/command.cpp index 9c2008afb..dd0bd95bb 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -1264,7 +1264,7 @@ void command_movement(Client *c, const Seperator *sep) auto &mgr = MobMovementManager::Get(); if (sep->arg[1][0] == 0) { - c->Message(0, "Usage: #movement stats/clearstats"); + c->Message(0, "Usage: #movement stats/clearstats/walkto/runto/rotateto/stop"); return; } @@ -1276,8 +1276,48 @@ void command_movement(Client *c, const Seperator *sep) { mgr.ClearStats(); } + else if (strcasecmp(sep->arg[1], "walkto") == 0) + { + auto target = c->GetTarget(); + if (target == nullptr) { + c->Message(0, "No target found."); + return; + } + + target->WalkTo(c->GetX(), c->GetY(), c->GetZ()); + } + else if (strcasecmp(sep->arg[1], "runto") == 0) + { + auto target = c->GetTarget(); + if (target == nullptr) { + c->Message(0, "No target found."); + return; + } + + target->RunTo(c->GetX(), c->GetY(), c->GetZ()); + } + else if (strcasecmp(sep->arg[1], "rotateto") == 0) + { + auto target = c->GetTarget(); + if (target == nullptr) { + c->Message(0, "No target found."); + return; + } + + target->RotateToWalking(target->CalculateHeadingToTarget(c->GetX(), c->GetY())); + } + else if (strcasecmp(sep->arg[1], "stop") == 0) + { + auto target = c->GetTarget(); + if (target == nullptr) { + c->Message(0, "No target found."); + return; + } + + target->StopNavigation(); + } else { - c->Message(0, "Usage: #movement stats/clearstats"); + c->Message(0, "Usage: #movement stats/clearstats/walkto/runto/rotateto/stop"); } } diff --git a/zone/mob.cpp b/zone/mob.cpp index b9c6f1af3..b34b667d7 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -387,7 +387,7 @@ Mob::Mob(const char* in_name, permarooted = (runspeed > 0) ? false : true; - movetimercompleted = false; + pause_timer_complete = false; ForcedMovement = 0; roamer = false; rooted = false; diff --git a/zone/mob.h b/zone/mob.h index d1bd23145..967ab51f5 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -1430,7 +1430,6 @@ protected: std::unique_ptr AI_think_timer; std::unique_ptr AI_movement_timer; std::unique_ptr AI_target_check_timer; - bool movetimercompleted; int8 ForcedMovement; // push bool permarooted; std::unique_ptr AI_scan_area_timer; @@ -1482,6 +1481,7 @@ protected: glm::vec3 m_FearWalkTarget; bool currently_fleeing; + bool pause_timer_complete; bool DistractedFromGrid; uint32 pDontHealMeBefore; uint32 pDontBuffMeBefore; diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 8e2e3e029..d315e0579 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -1686,19 +1686,19 @@ void NPC::AI_DoMovement() { } else if (roamer) { if (AI_walking_timer->Check()) { - movetimercompleted = true; + pause_timer_complete = true; AI_walking_timer->Disable(); } - + int32 gridno = CastToNPC()->GetGrid(); - + if (gridno > 0 || cur_wp == -2) { - if (movetimercompleted == true) { // time to pause at wp is over + if (pause_timer_complete == true) { // time to pause at wp is over AI_SetupNextWaypoint(); - } // endif (movetimercompleted==true) + } // endif (pause_timer_complete==true) else if (!(AI_walking_timer->Enabled())) { // currently moving bool doMove = true; - if (m_CurrentWayPoint.x == GetX() && m_CurrentWayPoint.y == GetY()) { // are we there yet? then stop + if(IsPositionEqual(glm::vec2(m_CurrentWayPoint.x, m_CurrentWayPoint.y), glm::vec2(GetX(), GetY()))) { Log(Logs::Detail, Logs::AI, "We have reached waypoint %d (%.3f,%.3f,%.3f) on grid %d", @@ -1707,13 +1707,13 @@ void NPC::AI_DoMovement() { GetY(), GetZ(), GetGrid()); - + SetWaypointPause(); SetAppearance(eaStanding, false); - if (cur_wp_pause > 0 && m_CurrentWayPoint.w >= 0.0) { + if (cur_wp_pause > 0) { RotateTo(m_CurrentWayPoint.w); } - + //kick off event_waypoint arrive char temp[16]; sprintf(temp, "%d", cur_wp); @@ -1727,29 +1727,36 @@ void NPC::AI_DoMovement() { if (cur_wp == -2) { AI_SetupNextWaypoint(); } - + // wipe feign memory since we reached our first waypoint if (cur_wp == 1) ClearFeignMemory(); + + if (cur_wp_pause == 0) { + pause_timer_complete = true; + AI_SetupNextWaypoint(); + doMove = true; + } } + if (doMove) { // not at waypoint yet or at 0 pause WP, so keep moving NavigateTo( m_CurrentWayPoint.x, m_CurrentWayPoint.y, m_CurrentWayPoint.z ); - + } } } // endif (gridno > 0) // handle new quest grid command processing else if (gridno < 0) { // this mob is under quest control - if (movetimercompleted == true) { // time to pause has ended + if (pause_timer_complete == true) { // time to pause has ended SetGrid(0 - GetGrid()); // revert to AI control Log(Logs::Detail, Logs::Pathing, "Quest pathing is finished. Resuming on grid %d", GetGrid()); - + SetAppearance(eaStanding, false); - + CalculateNewWaypoint(); } } @@ -1813,27 +1820,26 @@ void NPC::AI_SetupNextWaypoint() { found_spawn->SetNPCPointerNull(); } else { - movetimercompleted = false; - + pause_timer_complete = false; Log(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(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(this); - + 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) { diff --git a/zone/mob_movement_manager.cpp b/zone/mob_movement_manager.cpp index 1d97227cc..d73f0fef1 100644 --- a/zone/mob_movement_manager.cpp +++ b/zone/mob_movement_manager.cpp @@ -169,7 +169,6 @@ public: glm::vec2 pos(p.x, p.y); double len = glm::distance(pos, tar); if (len == 0) { - m->SetMoving(false); return true; } @@ -187,7 +186,6 @@ public: } m->TryFixZ(); - m->SetMoving(false); return true; } else { @@ -437,6 +435,10 @@ void MobMovementManager::Teleport(Mob *who, float x, float y, float z, float hea void MobMovementManager::NavigateTo(Mob *who, float x, float y, float z, MobMovementMode mode) { + if (IsPositionEqualWithinCertainZ(glm::vec3(x, y, z), glm::vec3(who->GetX(), who->GetY(), who->GetZ()), 6.0f)) { + return; + } + auto iter = _impl->Entries.find(who); auto &ent = (*iter); auto &nav = ent.second.NavTo; @@ -476,12 +478,8 @@ void MobMovementManager::StopNavigation(Mob *who) { return; } - if (who->IsMoving()) { - who->TryFixZ(); - who->SetMoving(false); - SendCommandToClients(who, 0.0, 0.0, 0.0, 0.0, 0, ClientRangeCloseMedium); - } ent.second.Commands.clear(); + PushStopMoving(ent.second); } void MobMovementManager::SendCommandToClients(Mob *m, float dx, float dy, float dz, float dh, int anim, ClientRange range) @@ -615,6 +613,7 @@ void MobMovementManager::UpdatePath(Mob *who, float x, float y, float z, MobMove auto &ent = (*iter); PushMoveTo(ent.second, x, y, z, mode); + PushStopMoving(ent.second); return; } } @@ -634,17 +633,17 @@ void MobMovementManager::UpdatePath(Mob *who, float x, float y, float z, MobMove auto &last = route.back(); PushMoveTo(ent.second, x, y, z, mode); + PushStopMoving(ent.second); return; } else if(route.size() < 2) { PushMoveTo(ent.second, x, y, z, mode); + PushStopMoving(ent.second); return; } } - - auto &first = route.front(); auto &last = route.back(); diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index c156914c8..e39a40221 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -390,12 +390,8 @@ void NPC::SetWaypointPause() { //Declare time to wait on current WP - if (cur_wp_pause == 0) { - AI_walking_timer->Start(100); - } - else + if(cur_wp_pause > 0) { - switch (pausetype) { case 0: //Random Half