updated method as my information was incorrect
This commit is contained in:
parent
04802e3938
commit
35727d0a48
@ -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,48 +11,64 @@
|
|||||||
#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 ===
|
||||||
{
|
static constexpr float TELEPORT_DISTANCE = 200.0f; // yards (search radius)
|
||||||
// === CONFIG ===
|
static constexpr float Z_BUMP = 1.5f; // anti-clip offset on Z
|
||||||
static constexpr float TELEPORT_DISTANCE = 200.0f; // yards
|
static constexpr float MIN_RETELEPORT_DIST = 8.0f; // don't pick nodes closer than this to the player
|
||||||
static constexpr float Z_BUMP = 1.5f; // anti-clip offset
|
|
||||||
|
|
||||||
// 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,
|
||||||
176643,177388,179144,179224,180215,181109,181248,181249,181557,
|
176643, 177388, 179144, 179224, 180215, 181109, 181248, 181249, 181557,
|
||||||
185557,191133,1735,2040,2047,2653,73939,123309,123310,150079,
|
185557, 191133, 1735, 2040, 2047, 2653, 73939, 123309, 123310, 150079,
|
||||||
150081,165658,176645,181108,181555,181556,181569,181570,185877,
|
150081, 165658, 176645, 181108, 181555, 181556, 181569, 181570, 185877,
|
||||||
189978,189979,189980,189981,195036,
|
189978, 189979, 189980, 189981, 195036,
|
||||||
};
|
};
|
||||||
|
|
||||||
static GameObject* FindNearestReadyVein(Player* player, float maxRange, float minDistanceFromPlayer)
|
// 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)
|
||||||
{
|
{
|
||||||
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))
|
||||||
{
|
{
|
||||||
|
// Don’t 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;
|
||||||
|
|
||||||
|
// Don’t pick a node that’s 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;
|
||||||
@ -60,7 +79,7 @@ namespace
|
|||||||
return nearest;
|
return nearest;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool DoTeleNode(Player* player)
|
static bool DoTeleNode(Player* player)
|
||||||
{
|
{
|
||||||
if (!player)
|
if (!player)
|
||||||
return false;
|
return false;
|
||||||
@ -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 won’t bounce back here if it hasn’t 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();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user