diff --git a/src/teleport-to-node.cpp b/src/teleport-to-node.cpp index 5e62acf..356df2c 100644 --- a/src/teleport-to-node.cpp +++ b/src/teleport-to-node.cpp @@ -4,17 +4,17 @@ #include "ChatCommand.h" #include "Player.h" #include "GameObject.h" -#include "ObjectAccessor.h" -#include "Timer.h" #include +#include #include +#include using namespace Acore::ChatCommands; static constexpr float TELEPORT_DISTANCE = 250.0f; -static constexpr float Z_BUMP = 1.0f; -static constexpr uint32 RECHECK_INTERVAL_MS = 5000; +static constexpr float Z_BUMP = 1.5f; +static constexpr float MIN_RETELEPORT_DIST = 1.0f; static const std::vector kVeinEntries = { 324,1610,1667,1731,1732,1733,1734,2054,2055,3763,3764,19903, @@ -25,49 +25,57 @@ static const std::vector kVeinEntries = { 189978,189979,189980,189981,195036, }; -static GameObject* FindNearestVein(Player* player, float maxRange) +static std::unordered_map s_lastNodeByPlayer; + +static GameObject* FindNearestReadyVein(Player* player, float maxRange, float minDistanceFromPlayer) { GameObject* nearest = nullptr; float nearestDist = std::numeric_limits::infinity(); + uint64 lastNode = 0; + if (auto it = s_lastNodeByPlayer.find(player->GetGUID().GetRawValue()); it != s_lastNodeByPlayer.end()) + lastNode = it->second; for (uint32 entry : kVeinEntries) { if (GameObject* go = player->FindNearestGameObject(entry, maxRange)) { - float dist = player->GetDistance(go); - if (dist <= maxRange && dist < nearestDist) + if (go->GetGUID().GetRawValue() == lastNode) + continue; + + if (go->getLootState() != LootState::GO_READY) + continue; + + if (go->GetGoState() != GOState::GO_STATE_READY) + continue; + + float d = player->GetDistance(go); + if (d < minDistanceFromPlayer) + continue; + + if (d <= maxRange && d < nearestDist) { nearest = go; - nearestDist = dist; + nearestDist = d; } } } return nearest; } -static void DumpNearbyNodes(Player* player) -{ - ChatHandler(player->GetSession()).PSendSysMessage("Nearby node coordinates:"); - for (uint32 entry : kVeinEntries) - { - if (GameObject* go = player->FindNearestGameObject(entry, TELEPORT_DISTANCE)) - { - ChatHandler(player->GetSession()).PSendSysMessage( - "Entry %u -> Map %u X: %.2f Y: %.2f Z: %.2f", - entry, go->GetMapId(), go->GetPositionX(), go->GetPositionY(), go->GetPositionZ() - ); - } - } -} - -static void TeleportToNearest(Player* player) +static bool DoTeleNode(Player* player) { if (!player) - return; + return false; - GameObject* node = FindNearestVein(player, TELEPORT_DISTANCE); - if (node) + if (player->IsInCombat()) { + ChatHandler(player->GetSession()).PSendSysMessage("You can't use this while in combat."); + return true; + } + + if (GameObject* node = FindNearestReadyVein(player, TELEPORT_DISTANCE, MIN_RETELEPORT_DIST)) + { + s_lastNodeByPlayer[player->GetGUID().GetRawValue()] = node->GetGUID().GetRawValue(); player->TeleportTo( node->GetMapId(), node->GetPositionX(), @@ -75,41 +83,12 @@ static void TeleportToNearest(Player* player) node->GetPositionZ() + Z_BUMP, node->GetOrientation() ); - ChatHandler(player->GetSession()).PSendSysMessage("Teleported to nearest node."); } else { - ChatHandler(player->GetSession()).PSendSysMessage("No node found within range."); - } -} - -class TeleNodeRunnable : public BasicEvent -{ -public: - explicit TeleNodeRunnable(Player* player) : _player(player) { } - bool Execute(uint64 /*time*/, uint32 /*diff*/) override - { - if (!_player || !_player->IsInWorld()) - return true; - - DumpNearbyNodes(_player); - TeleportToNearest(_player); - _player->m_Events.AddEvent(new TeleNodeRunnable(_player), _player->m_Events.CalculateTime(RECHECK_INTERVAL_MS)); - return true; + ChatHandler(player->GetSession()).PSendSysMessage("No mining nodes found within range."); } -private: - Player* _player; -}; - -static bool HandleTeleNode(ChatHandler* handler) -{ - Player* player = handler->GetSession()->GetPlayer(); - if (!player) - return false; - - player->m_Events.AddEvent(new TeleNodeRunnable(player), player->m_Events.CalculateTime(0)); - handler->PSendSysMessage("telenode started: re-evaluating every 5 seconds."); return true; } @@ -126,6 +105,23 @@ public: }; return commandTable; } + +private: + static bool HandleTeleNode(ChatHandler* handler) + { + if (!handler) + return false; + + Player* player = handler->GetSession() ? handler->GetSession()->GetPlayer() : nullptr; + if (!player) + { + handler->SendSysMessage("Player only."); + handler->SetSentErrorMessage(true); + return false; + } + + return DoTeleNode(player); + } }; void AddSC_telenode_commandscript()