diff --git a/zone/command.cpp b/zone/command.cpp index 6b38aec28..53b5a2929 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -304,6 +304,7 @@ int command_init(void) #endif command_add("pvp", "[on/off] - Set your or your player target's PVP status", 100, command_pvp) || + command_add("path", "to/from - Checks and reports on a path either from you to your target or from your target to you.", 100, command_path) || command_add("qglobal", "[on/off/view] - Toggles qglobal functionality on an NPC", 100, command_qglobal) || command_add("questerrors", "Shows quest errors.", 100, command_questerrors) || command_add("race", "[racenum] - Change your or your target's race. Use racenum 0 to return to normal", 50, command_race) || @@ -4044,6 +4045,77 @@ void command_unfreeze(Client *c, const Seperator *sep) c->Message(0, "ERROR: Unfreeze requires a target."); } +void command_path(Client *c, const Seperator *sep) +{ + auto target = c->GetTarget(); + if (!target) { + c->Message(0, "Path command requires a target."); + return; + } + + glm::vec3 src; + glm::vec3 dest; + if (strcasecmp(sep->arg[1], "to") == 0) { + src.x = c->GetX(); + src.y = c->GetY(); + src.z = c->GetZ(); + dest.x = target->GetX(); + dest.y = target->GetY(); + dest.z = target->GetZ(); + } + else if (strcasecmp(sep->arg[1], "from") == 0) { + src.x = target->GetX(); + src.y = target->GetY(); + src.z = target->GetZ(); + dest.x = c->GetX(); + dest.y = c->GetY(); + dest.z = c->GetZ(); + } + else { + c->Message(0, "Unknown path argument: '%s'.", sep->arg[1]); + return; + } + + bool first = true; + auto route = zone->pathing.FindRoute(src, dest); + auto &nodes = route.GetNodes(); + auto &last_node = nodes[nodes.size() - 1]; + auto dist = DistanceSquared(glm::vec4(last_node.position, 1.0f), glm::vec4(dest.x, dest.y, dest.z, 0.0f)); + if (dist > 10000.0f) { + c->Message(0, "Path from (%.2f, %.2f, %.2f) to (%.2f, %.2f, %.2f) found with %i nodes, broken path, would need warp.", + src.x, + src.y, + src.z, + dest.x, + dest.y, + dest.z, + (int)nodes.size()); + return; + } + else if (dist > 100.0f) { + c->Message(0, "Path from (%.2f, %.2f, %.2f) to (%.2f, %.2f, %.2f) found with %i nodes, partial path.", + src.x, + src.y, + src.z, + dest.x, + dest.y, + dest.z, + (int)nodes.size()); + return; + } + + c->Message(0, "Path from (%.2f, %.2f, %.2f) to (%.2f, %.2f, %.2f) found with %i nodes, complete path.", + src.x, + src.y, + src.z, + dest.x, + dest.y, + dest.z, + (int)nodes.size()); + + return; +} + void command_pvp(Client *c, const Seperator *sep) { bool state=atobool(sep->arg[1]); diff --git a/zone/command.h b/zone/command.h index 23e514f5f..dc90c247f 100644 --- a/zone/command.h +++ b/zone/command.h @@ -74,7 +74,6 @@ void command_connectworldserver(Client *c, const Seperator *sep); void command_corpse(Client *c, const Seperator *sep); void command_crashtest(Client *c, const Seperator *sep); void command_cvs(Client *c, const Seperator *sep); -void command_d1(Client *c, const Seperator *sep); void command_damage(Client *c, const Seperator *sep); void command_date(Client *c, const Seperator *sep); void command_dbspawn2(Client *c, const Seperator *sep); @@ -118,7 +117,6 @@ void command_gmspeed(Client *c, const Seperator *sep); void command_goto(Client *c, const Seperator *sep); void command_grid(Client *c, const Seperator *sep); void command_guild(Client *c, const Seperator *sep); -bool helper_guild_edit(Client *c, uint32 dbid, uint32 eqid, uint8 rank, const char* what, const char* value); void command_guildapprove(Client *c, const Seperator *sep); void command_guildcreate(Client *c, const Seperator *sep); void command_guildlist(Client *c, const Seperator *sep); @@ -159,7 +157,6 @@ void command_logs(Client *c, const Seperator *sep); void command_logtest(Client *c, const Seperator *sep); void command_makepet(Client *c, const Seperator *sep); void command_mana(Client *c, const Seperator *sep); -void command_manastat(Client *c, const Seperator *sep); void command_max_all_skills(Client *c, const Seperator *sep); void command_memspell(Client *c, const Seperator *sep); void command_merchantcloseshop(Client *c, const Seperator *sep); @@ -186,7 +183,6 @@ void command_npctype_cache(Client *c, const Seperator *sep); void command_npctypespawn(Client *c, const Seperator *sep); void command_nukebuffs(Client *c, const Seperator *sep); void command_nukeitem(Client *c, const Seperator *sep); -void command_numauths(Client *c, const Seperator *sep); void command_object(Client* c, const Seperator *sep); void command_oocmute(Client *c, const Seperator *sep); void command_opcode(Client *c, const Seperator *sep); @@ -209,15 +205,14 @@ void command_profiledump(Client *c, const Seperator *sep); void command_profilereset(Client *c, const Seperator *sep); #endif +void command_path(Client *c, const Seperator *sep); void command_pvp(Client *c, const Seperator *sep); void command_qglobal(Client *c, const Seperator *sep); -void command_qtest(Client *c, const Seperator *sep); void command_questerrors(Client *c, const Seperator *sep); void command_race(Client *c, const Seperator *sep); void command_raidloot(Client* c, const Seperator *sep); void command_randomfeatures(Client *c, const Seperator *sep); void command_refreshgroup(Client *c, const Seperator *sep); -void command_refundaa(Client *c, const Seperator *sep); void command_reloadaa(Client *c, const Seperator *sep); void command_reloadallrules(Client *c, const Seperator *sep); void command_reloademote(Client* c, const Seperator *sep); @@ -238,7 +233,6 @@ void command_rules(Client *c, const Seperator *sep); void command_save(Client *c, const Seperator *sep); void command_scribespell(Client *c, const Seperator *sep); void command_scribespells(Client *c, const Seperator *sep); -void command_sendop(Client *c, const Seperator *sep); void command_sendzonespawns(Client *c, const Seperator *sep); void command_sensetrap(Client *c, const Seperator *sep); void command_serverinfo(Client *c, const Seperator *sep); @@ -263,7 +257,6 @@ void command_setxp(Client *c, const Seperator *sep); void command_showbonusstats(Client *c, const Seperator *sep); void command_showbuffs(Client *c, const Seperator *sep); void command_shownumhits(Client *c, const Seperator *sep); -void command_showpetspell(Client *c, const Seperator *sep); void command_showskills(Client *c, const Seperator *sep); void command_showspellslist(Client *c, const Seperator *sep); void command_showstats(Client *c, const Seperator *sep); @@ -280,12 +273,9 @@ void command_summon(Client *c, const Seperator *sep); void command_summonburiedplayercorpse(Client *c, const Seperator *sep); void command_summonitem(Client *c, const Seperator *sep); void command_suspend(Client *c, const Seperator *sep); -void command_synctod(Client *c, const Seperator *sep); void command_task(Client *c, const Seperator *sep); void command_tattoo(Client *c, const Seperator *sep); void command_tempname(Client *c, const Seperator *sep); -void command_testspawn(Client *c, const Seperator *sep); -void command_testspawnkill(Client *c, const Seperator *sep); void command_texture(Client *c, const Seperator *sep); void command_time(Client *c, const Seperator *sep); void command_timers(Client *c, const Seperator *sep); diff --git a/zone/mob.cpp b/zone/mob.cpp index 30d4f30ce..e8d317d7d 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -109,7 +109,7 @@ Mob::Mob(const char* in_name, m_TargetV(glm::vec3()), flee_timer(FLEE_CHECK_TIMER), m_Position(position), - m_pos_update_timer(3000) + m_pos_update_timer(8000) { targeted = 0; tar_ndx=0; diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index b0173361b..fd67a3569 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -910,7 +910,10 @@ void Client::AI_Process() nspeed *= 2; SetCurrentSpeed(nspeed); - CalculateNewPosition2(owner->GetX(), owner->GetY(), owner->GetZ(), nspeed); + bool WaypointChanged; + glm::vec3 Goal = UpdatePath(owner->GetX(), owner->GetY(), owner->GetZ(), nspeed, WaypointChanged); + + CalculateNewPosition2(Goal.x, Goal.y, Goal.z, nspeed); } } else @@ -1362,7 +1365,11 @@ void Mob::AI_Process() { if (dist >= 5625) speed = GetRunspeed(); - CalculateNewPosition2(owner->GetX(), owner->GetY(), owner->GetZ(), speed); + bool WaypointChanged; + glm::vec3 Goal = UpdatePath(owner->GetX(), owner->GetY(), owner->GetZ(), + speed, WaypointChanged); + + CalculateNewPosition2(Goal.x, Goal.y, Goal.z, speed); } else { @@ -1418,7 +1425,12 @@ void Mob::AI_Process() { int speed = GetWalkspeed(); if (dist2 >= followdist + 150) speed = GetRunspeed(); - CalculateNewPosition2(follow->GetX(), follow->GetY(), follow->GetZ(), speed); + + bool WaypointChanged; + glm::vec3 Goal = UpdatePath(follow->GetX(), follow->GetY(), follow->GetZ(), + speed, WaypointChanged); + + CalculateNewPosition2(Goal.x, Goal.y, Goal.z, speed); } else { @@ -1499,7 +1511,11 @@ void NPC::AI_DoMovement() { Log.Out(Logs::Detail, Logs::AI, "Roam Box: d=%.3f (%.3f->%.3f,%.3f->%.3f): Go To (%.3f,%.3f)", roambox_distance, roambox_min_x, roambox_max_x, roambox_min_y, roambox_max_y, roambox_movingto_x, roambox_movingto_y); - if (!CalculateNewPosition2(roambox_movingto_x, roambox_movingto_y, GetZ(), walksp, true)) + + bool WaypointChanged; + glm::vec3 Goal = UpdatePath(roambox_movingto_x, roambox_movingto_y, GetZ(), walksp, WaypointChanged); + + if (!CalculateNewPosition2(Goal.x, Goal.y, Goal.z, walksp, true)) { roambox_movingto_x = roambox_max_x + 1; // force update pLastFightingDelayMoving = Timer::GetCurrentTime() + RandomTimer(roambox_min_delay, roambox_delay); @@ -1553,8 +1569,17 @@ void NPC::AI_DoMovement() { } if (doMove) { // not at waypoint yet or at 0 pause WP, so keep moving - if(DistractedFromGrid == 0) - CalculateNewPosition2(m_CurrentWayPoint.x, m_CurrentWayPoint.y, m_CurrentWayPoint.z, walksp, true); + if (DistractedFromGrid == 0) { + bool WaypointChanged; + glm::vec3 Goal = UpdatePath(m_CurrentWayPoint.x, m_CurrentWayPoint.y, m_CurrentWayPoint.z, + walksp, WaypointChanged); + + if (WaypointChanged) { + entity_list.OpenDoorsNear(CastToNPC()); + } + + CalculateNewPosition2(Goal.x, Goal.y, Goal.z, walksp, true); + } else { bool WaypointChanged; diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index 5ab46dc1f..5accc3340 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -429,7 +429,10 @@ void NPC::SaveGuardSpot(bool iClearGuardSpot) { } void NPC::NextGuardPosition() { - if (!CalculateNewPosition2(m_GuardPoint.x, m_GuardPoint.y, m_GuardPoint.z, GetMovespeed())) { + bool WaypointChanged; + glm::vec3 Goal = UpdatePath(m_GuardPoint.x, m_GuardPoint.y, m_GuardPoint.z, GetMovespeed(), WaypointChanged); + + if (!CalculateNewPosition2(Goal.x, Goal.y, Goal.z, GetMovespeed())) { SetHeading(m_GuardPoint.w); Log.Out(Logs::Detail, Logs::AI, "Unable to move to next guard position. Probably rooted."); } @@ -739,8 +742,7 @@ bool Mob::CalculateNewPosition(float x, float y, float z, int speed, bool checkZ if (m_TargetV.x == 0 && m_TargetV.y == 0) return false; - SetCurrentSpeed((int8)(speed)); //*NPC_RUNANIM_RATIO); - //speed *= NPC_SPEED_MULTIPLIER; + SetCurrentSpeed((int8)(speed)); Log.Out(Logs::Detail, Logs::AI, "Calculating new position to (%.3f, %.3f, %.3f) vector (%.3f, %.3f, %.3f) rate %.3f RAS %d", x, y, z, m_TargetV.x, m_TargetV.y, m_TargetV.z, speed, pRunAnimSpeed); @@ -782,32 +784,33 @@ bool Mob::CalculateNewPosition(float x, float y, float z, int speed, bool checkZ NPCFlyMode = 1; } - //fix up pathing Z - if(!NPCFlyMode && checkZ && zone->HasMap() && RuleB(Map, FixPathingZWhenMoving)) - { - if(!RuleB(Watermap, CheckForWaterWhenMoving) || !zone->HasWaterMap() || - (zone->HasWaterMap() && !zone->watermap->InWater(glm::vec3(m_Position)))) - { - glm::vec3 dest(m_Position.x, m_Position.y, m_Position.z); - - float newz = zone->zonemap->FindBestZ(dest, nullptr) + 2.0f; - - Log.Out(Logs::Detail, Logs::AI, "BestZ returned %4.3f at %4.3f, %4.3f, %4.3f", newz,m_Position.x,m_Position.y,m_Position.z); - - if ((newz > -2000) && - std::abs(newz - dest.z) < RuleR(Map, FixPathingZMaxDeltaMoving)) // Sanity check. - { - if (std::abs(x - m_Position.x) < 0.5 && std::abs(y - m_Position.y) < 0.5) { - if (std::abs(z - m_Position.z) <= RuleR(Map, FixPathingZMaxDeltaMoving)) - m_Position.z = z; - else - m_Position.z = newz + 1; - } - else - m_Position.z = newz+1; - } - } - } + //TODO: lets_move + ////fix up pathing Z + //if(!NPCFlyMode && checkZ && zone->HasMap() && RuleB(Map, FixPathingZWhenMoving)) + //{ + // if(!RuleB(Watermap, CheckForWaterWhenMoving) || !zone->HasWaterMap() || + // (zone->HasWaterMap() && !zone->watermap->InWater(glm::vec3(m_Position)))) + // { + // glm::vec3 dest(m_Position.x, m_Position.y, m_Position.z); + // + // float newz = zone->zonemap->FindBestZ(dest, nullptr) + 2.0f; + // + // Log.Out(Logs::Detail, Logs::AI, "BestZ returned %4.3f at %4.3f, %4.3f, %4.3f", newz,m_Position.x,m_Position.y,m_Position.z); + // + // if ((newz > -2000) && + // std::abs(newz - dest.z) < RuleR(Map, FixPathingZMaxDeltaMoving)) // Sanity check. + // { + // if (std::abs(x - m_Position.x) < 0.5 && std::abs(y - m_Position.y) < 0.5) { + // if (std::abs(z - m_Position.z) <= RuleR(Map, FixPathingZMaxDeltaMoving)) + // m_Position.z = z; + // else + // m_Position.z = newz + 1; + // } + // else + // m_Position.z = newz+1; + // } + // } + //} //OP_MobUpdate if((old_test_vector!=test_vector) || tar_ndx>20){ //send update