updated method as my information was incorrect

This commit is contained in:
Flerp 2025-10-31 06:23:18 -07:00
parent 04802e3938
commit 35727d0a48

View File

@ -1,5 +1,8 @@
/* /*
* Teleport to nearest mining node (.telenode) AzerothCore ChatCommandTable style * Teleport to nearest mining node (.telenode)
* - AzerothCore ChatCommandTable style (matches si_commandscript)
* - Skips depleted/in-use nodes using loot/go state
* - Avoids "sticky" re-teleport by skipping the last-node GUID and a min distance
*/ */
#include "ScriptMgr.h" #include "ScriptMgr.h"
@ -8,20 +11,20 @@
#include "ChatCommand.h" #include "ChatCommand.h"
#include "Player.h" #include "Player.h"
#include "GameObject.h" #include "GameObject.h"
#include "GameTime.h" #include "ObjectGuid.h"
#include <vector> #include <vector>
#include <unordered_map>
#include <limits> #include <limits>
using namespace Acore::ChatCommands; using namespace Acore::ChatCommands;
namespace
{
// === CONFIG === // === CONFIG ===
static constexpr float TELEPORT_DISTANCE = 200.0f; // yards static constexpr float TELEPORT_DISTANCE = 200.0f; // yards (search radius)
static constexpr float Z_BUMP = 1.5f; // anti-clip offset static constexpr float Z_BUMP = 1.5f; // anti-clip offset on Z
static constexpr float MIN_RETELEPORT_DIST = 8.0f; // don't pick nodes closer than this to the player
// Mining node entries (trim as needed) // Mining node entries (trim to the entries you actually want)
static const std::vector<uint32> kVeinEntries = { static const std::vector<uint32> kVeinEntries = {
324, 1610, 1667, 1731, 1732, 1733, 1734, 2054, 2055, 3763, 3764, 19903, 324, 1610, 1667, 1731, 1732, 1733, 1734, 2054, 2055, 3763, 3764, 19903,
73940, 73941, 103711, 103713, 105569, 123848, 150080, 150082, 175404, 73940, 73941, 103711, 103713, 105569, 123848, 150080, 150082, 175404,
@ -31,25 +34,41 @@ namespace
189978, 189979, 189980, 189981, 195036, 189978, 189979, 189980, 189981, 195036,
}; };
// Remember the last teleported-to node for each player (prevents “sticky” coords)
static std::unordered_map<ObjectGuid, ObjectGuid, ObjectGuid::Hash> s_lastNodeByPlayer;
static GameObject* FindNearestReadyVein(Player* player, float maxRange, float minDistanceFromPlayer) static GameObject* FindNearestReadyVein(Player* player, float maxRange, float minDistanceFromPlayer)
{ {
GameObject* nearest = nullptr; GameObject* nearest = nullptr;
float nearestDist = std::numeric_limits<float>::infinity(); float nearestDist = std::numeric_limits<float>::infinity();
// Skip the last node we teleported to (if any)
ObjectGuid lastNodeGuid;
if (auto it = s_lastNodeByPlayer.find(player->GetGUID()); it != s_lastNodeByPlayer.end())
lastNodeGuid = it->second;
for (uint32 entry : kVeinEntries) for (uint32 entry : kVeinEntries)
{ {
// Fast query: nearest object of this entry (we still validate it)
if (GameObject* go = player->FindNearestGameObject(entry, maxRange)) if (GameObject* go = player->FindNearestGameObject(entry, maxRange))
{ {
// Dont pick the node we just used
if (go->GetGUID() == lastNodeGuid)
continue;
// Ignore nodes not in the default/usable state or not loot-ready
// (common depleted states are GO_ACTIVATED/GO_JUST_DEACTIVATED)
if (go->GetLootState() != GO_READY)
continue;
if (go->GetGoState() != GO_STATE_READY)
continue;
// Dont pick a node thats basically under the player
float d = player->GetDistance(go); float d = player->GetDistance(go);
if (d < minDistanceFromPlayer) if (d < minDistanceFromPlayer)
continue; continue;
if (go->IsInUse())
continue;
if (go->GetLootState() != GO_READY)
continue;
if (d <= maxRange && d < nearestDist) if (d <= maxRange && d < nearestDist)
{ {
nearest = go; nearest = go;
@ -68,14 +87,14 @@ namespace
if (player->IsInCombat()) if (player->IsInCombat())
{ {
ChatHandler(player->GetSession()).PSendSysMessage("You can't use this while in combat."); ChatHandler(player->GetSession()).PSendSysMessage("You can't use this while in combat.");
return true; return true; // handled
} }
// Skip anything within ~8 yards so we don't pick the node we just mined if (GameObject* node = FindNearestReadyVein(player, TELEPORT_DISTANCE, MIN_RETELEPORT_DIST))
constexpr float kMinReTeleportDist = 8.0f;
if (GameObject* node = FindNearestReadyVein(player, TELEPORT_DISTANCE, kMinReTeleportDist))
{ {
// Remember this node so the next call wont bounce back here if it hasnt despawned yet
s_lastNodeByPlayer[player->GetGUID()] = node->GetGUID();
player->TeleportTo( player->TeleportTo(
node->GetMapId(), node->GetMapId(),
node->GetPositionX(), node->GetPositionX(),
@ -88,6 +107,7 @@ namespace
{ {
ChatHandler(player->GetSession()).PSendSysMessage("No mining nodes found within range."); ChatHandler(player->GetSession()).PSendSysMessage("No mining nodes found within range.");
} }
return true; return true;
} }
@ -96,7 +116,7 @@ class telenode_commandscript : public CommandScript
public: public:
telenode_commandscript() : CommandScript("telenode_commandscript") { } telenode_commandscript() : CommandScript("telenode_commandscript") { }
// Match your si_commandscript style: ChatCommandTable and { name, handler, SEC, Console } // Matches your si_commandscript style: ChatCommandTable with { name, handler, SEC, Console }
ChatCommandTable GetCommands() const override ChatCommandTable GetCommands() const override
{ {
static ChatCommandTable commandTable = static ChatCommandTable commandTable =
@ -107,7 +127,6 @@ public:
} }
private: private:
// No-arg handler (Acore parser will pass only ChatHandler*)
static bool HandleTeleNode(ChatHandler* handler) static bool HandleTeleNode(ChatHandler* handler)
{ {
if (!handler) if (!handler)
@ -125,7 +144,7 @@ private:
} }
}; };
// Export symbol called by your loader.cpp // Export symbol; call this from your module loader (e.g., Addmod_teleport_to_nodeScripts)
void AddSC_telenode_commandscript() void AddSC_telenode_commandscript()
{ {
new telenode_commandscript(); new telenode_commandscript();