diff --git a/src/teleport-to-node.cpp b/src/teleport-to-node.cpp index 356df2c..8984c89 100644 --- a/src/teleport-to-node.cpp +++ b/src/teleport-to-node.cpp @@ -4,9 +4,9 @@ #include "ChatCommand.h" #include "Player.h" #include "GameObject.h" +#include "BasicEvent.h" #include -#include #include #include @@ -15,6 +15,7 @@ using namespace Acore::ChatCommands; static constexpr float TELEPORT_DISTANCE = 250.0f; static constexpr float Z_BUMP = 1.5f; static constexpr float MIN_RETELEPORT_DIST = 1.0f; +static constexpr uint32 RECHECK_DELAY_MS = 3000; static const std::vector kVeinEntries = { 324,1610,1667,1731,1732,1733,1734,2054,2055,3763,3764,19903, @@ -25,33 +26,21 @@ static const std::vector kVeinEntries = { 189978,189979,189980,189981,195036, }; -static std::unordered_map s_lastNodeByPlayer; - -static GameObject* FindNearestReadyVein(Player* player, float maxRange, float minDistanceFromPlayer) +static GameObject* FindNearestReadyVein(Player* player, float maxRange) { 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)) { - 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; @@ -62,6 +51,41 @@ static GameObject* FindNearestReadyVein(Player* player, float maxRange, float mi return nearest; } +class TeleNodeRecheckEvent : public BasicEvent +{ +public: + TeleNodeRecheckEvent(Player* player, uint64 lastNodeGuidRaw) + : _player(player), _lastNodeGuidRaw(lastNodeGuidRaw) { } + + bool Execute(uint64 /*time*/, uint32 /*diff*/) override + { + if (!_player || !_player->IsInWorld()) + return true; + + if (GameObject* node = FindNearestReadyVein(_player, TELEPORT_DISTANCE)) + { + if (node->GetGUID().GetRawValue() != _lastNodeGuidRaw) + { + if (_player->GetDistance(node) >= MIN_RETELEPORT_DIST) + { + _player->TeleportTo( + node->GetMapId(), + node->GetPositionX(), + node->GetPositionY(), + node->GetPositionZ() + Z_BUMP, + node->GetOrientation() + ); + } + } + } + return true; + } + +private: + Player* _player; + uint64 _lastNodeGuidRaw; +}; + static bool DoTeleNode(Player* player) { if (!player) @@ -73,9 +97,10 @@ static bool DoTeleNode(Player* player) return true; } - if (GameObject* node = FindNearestReadyVein(player, TELEPORT_DISTANCE, MIN_RETELEPORT_DIST)) + if (GameObject* node = FindNearestReadyVein(player, TELEPORT_DISTANCE)) { - s_lastNodeByPlayer[player->GetGUID().GetRawValue()] = node->GetGUID().GetRawValue(); + uint64 lastGuid = node->GetGUID().GetRawValue(); + player->TeleportTo( node->GetMapId(), node->GetPositionX(), @@ -83,6 +108,9 @@ static bool DoTeleNode(Player* player) node->GetPositionZ() + Z_BUMP, node->GetOrientation() ); + + player->m_Events.AddEvent(new TeleNodeRecheckEvent(player, lastGuid), + player->m_Events.CalculateTime(RECHECK_DELAY_MS)); } else {