mirror of
https://github.com/ornfelt/azerothcore_lua_scripts
synced 2026-08-22 06:26:03 -04:00
448 lines
No EOL
15 KiB
C++
448 lines
No EOL
15 KiB
C++
#include <math.h>
|
|
#include "Cell.h"
|
|
#include "Chat.h"
|
|
#include "ChatTextBuilder.h"
|
|
#include "GameObject.h"
|
|
#include "GoMove.h"
|
|
#include "GridNotifiers.h"
|
|
#include "Map.h"
|
|
#include "MapManager.h"
|
|
#include "Object.h"
|
|
#include "ObjectMgr.h"
|
|
#include "Player.h"
|
|
#include "ScriptMgr.h"
|
|
#include "ChatPackets.h"
|
|
#include <G3D/Quat.h>
|
|
|
|
GameObjectStore GOMove::Store;
|
|
|
|
void GOMove::SendAddonMessage(Player* player, char const* msg)
|
|
{
|
|
if (!player || !msg)
|
|
return;
|
|
|
|
WorldPackets::Chat::Chat packet;
|
|
packet.Initialize(CHAT_MSG_ADDON, LANG_ADDON, player, player, msg, 0, "", DEFAULT_LOCALE, "GOMOVE\t%s");
|
|
player->SendDirectMessage(packet.Write());
|
|
}
|
|
|
|
GameObject * GOMove::GetGameObject(Player * player, ObjectGuid::LowType lowguid)
|
|
{
|
|
if (GameObjectData const* data = sObjectMgr->GetGOData(lowguid))
|
|
return ChatHandler(player->GetSession()).GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid, data->id);
|
|
return nullptr;
|
|
}
|
|
|
|
void GOMove::SendAdd(Player * player, GameObject* go)
|
|
{
|
|
if (!go)
|
|
return;
|
|
char msg[256];
|
|
snprintf(msg, 256, "ADD|%u|%s|%u", go->GetGUIDLow(), go->GetName(), go->GetEntry());
|
|
SendAddonMessage(player, msg);
|
|
}
|
|
|
|
void GOMove::SendRemove(Player * player, ObjectGuid::LowType lowguid)
|
|
{
|
|
char msg[256];
|
|
snprintf(msg, 256, "REMOVE|%llu||0", lowguid);
|
|
|
|
SendAddonMessage(player, msg);
|
|
}
|
|
|
|
void GOMove::DeleteGameObject(GameObject * object)
|
|
{
|
|
if (!object)
|
|
return;
|
|
|
|
// copy paste .gob del command
|
|
ObjectGuid ownerGuid = object->GetOwnerGUID();
|
|
if (ownerGuid)
|
|
{
|
|
Unit* owner = ObjectAccessor::GetUnit(*object, ownerGuid);
|
|
if (owner && owner->GetTypeId() == TYPEID_PLAYER)
|
|
owner->RemoveGameObject(object, false);
|
|
}
|
|
object->SetRespawnTime(0);
|
|
object->Delete();
|
|
object->DeleteFromDB();
|
|
}
|
|
|
|
GameObject * GOMove::SpawnGameObject(Player* player, float x, float y, float z, float o, uint32 p, uint32 entry)
|
|
{
|
|
if (!player || !entry)
|
|
return nullptr;
|
|
|
|
if (!MapManager::IsValidMapCoord(player->GetMapId(), x, y, z))
|
|
return nullptr;
|
|
|
|
Position pos;
|
|
pos.Relocate(x, y, z, o);
|
|
|
|
// copy paste .gob add command
|
|
GameObjectTemplate const* objectInfo = sObjectMgr->GetGameObjectTemplate(entry);
|
|
if (!objectInfo)
|
|
return nullptr;
|
|
|
|
if (objectInfo->displayId && !sGameObjectDisplayInfoStore.LookupEntry(objectInfo->displayId))
|
|
return nullptr;
|
|
|
|
Map* map = player->GetMap();
|
|
|
|
GameObject* object = new GameObject();
|
|
ObjectGuid::LowType guidLow = sObjectMgr->GetGenerator<HighGuid::GameObject>()->Generate();
|
|
|
|
if (!object->Create(guidLow, objectInfo->entry, map, player->GetPhaseMgr().GetPhaseMaskForSpawn(), pos, G3D::Quat(), 255, GO_STATE_READY))
|
|
{
|
|
delete object;
|
|
return nullptr;
|
|
}
|
|
|
|
// fill the gameobject data and save to the db
|
|
object->SaveToDB(map->GetId(), (UI64LIT(1) << map->GetSpawnMode()), p);
|
|
// guidLow = object->GetSpawnId();
|
|
|
|
// delete the old object and do a clean load from DB with a fresh new GameObject instance.
|
|
// this is required to avoid weird behavior and memory leaks
|
|
delete object;
|
|
|
|
object = new GameObject();
|
|
// this will generate a new guid if the object is in an instance
|
|
if (!object->LoadGameObjectFromDB(guidLow, map))
|
|
{
|
|
delete object;
|
|
return nullptr;
|
|
}
|
|
|
|
sObjectMgr->AddGameobjectToGrid(guidLow, sObjectMgr->GetGOData(guidLow));
|
|
|
|
if (object)
|
|
SendAdd(player, object);
|
|
return object;
|
|
}
|
|
|
|
GameObject * GOMove::MoveGameObject(Player* player, float x, float y, float z, float o, uint32 p, ObjectGuid::LowType lowguid)
|
|
{
|
|
if (!player)
|
|
return nullptr;
|
|
GameObject* object = nullptr;
|
|
if (GameObjectData const* data = sObjectMgr->GetGOData(lowguid))
|
|
object = ChatHandler(player->GetSession()).GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid, data->id);
|
|
if (!object)
|
|
{
|
|
SendRemove(player, lowguid);
|
|
return nullptr;
|
|
}
|
|
|
|
if (!MapManager::IsValidMapCoord(object->GetMapId(), x, y, z))
|
|
return nullptr;
|
|
|
|
// copy paste .gob move command
|
|
// copy paste .gob turn command
|
|
// object->Relocate(x, y, z, o);
|
|
// object->SetWorldRotationAngles(o, 0, 0);
|
|
// object->SaveToDB();
|
|
SpawnGameObject(player, x, y, z, o, p, object->GetEntry());
|
|
DeleteGameObject(object);
|
|
|
|
SendRemove(player, lowguid);
|
|
|
|
|
|
return object;
|
|
}
|
|
|
|
void GameObjectStore::SpawnQueAdd(ObjectGuid const& guid, uint32 entry)
|
|
{
|
|
WriteGuard lock(_objectsToSpawnLock);
|
|
objectsToSpawn[guid] = entry;
|
|
}
|
|
|
|
void GameObjectStore::SpawnQueRem(ObjectGuid const& guid)
|
|
{
|
|
WriteGuard lock(_objectsToSpawnLock);
|
|
objectsToSpawn.erase(guid);
|
|
}
|
|
|
|
uint32 GameObjectStore::SpawnQueGet(ObjectGuid const& guid)
|
|
{
|
|
WriteGuard lock(_objectsToSpawnLock);
|
|
auto it = objectsToSpawn.find(guid);
|
|
if (it != objectsToSpawn.end())
|
|
return it->second;
|
|
return 0;
|
|
}
|
|
|
|
std::list<GameObject*> GOMove::GetNearbyGameObjects(Player* player, float range)
|
|
{
|
|
float x, y, z;
|
|
player->GetPosition(x, y, z);
|
|
|
|
std::list<GameObject*> objects;
|
|
Trinity::GameObjectInRangeCheck check(x, y, z, range);
|
|
Trinity::GameObjectListSearcher<Trinity::GameObjectInRangeCheck> searcher(player, objects, check);
|
|
player->GetMap()->VisitGrid(player->GetPositionX(), player->GetPositionY(), SIZE_OF_GRIDS, searcher);
|
|
return objects;
|
|
};
|
|
|
|
class GOMove_commandscript : public CommandScript
|
|
{
|
|
public:
|
|
GOMove_commandscript() : CommandScript("GOMove_commandscript")
|
|
{
|
|
}
|
|
|
|
enum commandIDs
|
|
{
|
|
TEST,
|
|
SELECTNEAR,
|
|
DELET,
|
|
X,
|
|
Y,
|
|
Z,
|
|
O,
|
|
GROUND,
|
|
FLOOR,
|
|
RESPAWN,
|
|
GOTO,
|
|
FACE,
|
|
|
|
SPAWN,
|
|
NORTH,
|
|
EAST,
|
|
SOUTH,
|
|
WEST,
|
|
NORTHEAST,
|
|
NORTHWEST,
|
|
SOUTHEAST,
|
|
SOUTHWEST,
|
|
UP,
|
|
DOWN,
|
|
LEFT,
|
|
RIGHT,
|
|
PHASE,
|
|
SELECTALLNEAR,
|
|
SPAWNSPELL,
|
|
};
|
|
|
|
ChatCommand* GetCommands() const override
|
|
{
|
|
static ChatCommand GOMoveCommandTable[] =
|
|
{
|
|
{ "gomove", SEC_ADMINISTRATOR, false, &GOMove_Command, "", NULL},
|
|
{ NULL, 0, false, NULL, "", NULL }
|
|
};
|
|
return GOMoveCommandTable;
|
|
}
|
|
|
|
static bool GOMove_Command(ChatHandler* handler, const char* args)
|
|
{
|
|
if (!args)
|
|
return false;
|
|
|
|
char* ID_t = strtok(const_cast<char*>(args), " ");
|
|
if (!ID_t)
|
|
return false;
|
|
uint32 ID = static_cast<uint32>(atoi(ID_t));
|
|
|
|
ObjectGuid::LowType lowguid = 0;
|
|
if (char* cLowguid = strtok(nullptr, " "))
|
|
lowguid = static_cast<uint64>(atoi(cLowguid));
|
|
|
|
char* ARG_t = strtok(nullptr, " ");
|
|
uint32 ARG = 0;
|
|
if (ARG_t)
|
|
ARG = static_cast<uint32>(atoi(ARG_t));
|
|
|
|
WorldSession* session = handler->GetSession();
|
|
if (!session)
|
|
return false;
|
|
Player* player = session->GetPlayer();
|
|
|
|
if (ID < SPAWN) // no args
|
|
{
|
|
if (ID >= DELET && ID <= GOTO) // has target (needs retrieve gameobject)
|
|
{
|
|
GameObject* target = GOMove::GetGameObject(player, lowguid);
|
|
if (!target)
|
|
ChatHandler(player->GetSession()).PSendSysMessage("Object GUID: %u not found.", lowguid);
|
|
else
|
|
{
|
|
float x, y, z, o;
|
|
target->GetPosition(x, y, z, o);
|
|
uint32 p = target->GetPhaseMask();
|
|
switch (ID)
|
|
{
|
|
case DELET: GOMove::DeleteGameObject(target); GOMove::SendRemove(player, lowguid); break;
|
|
case X: GOMove::MoveGameObject(player, player->GetPositionX(), y, z, o, p, lowguid); break;
|
|
case Y: GOMove::MoveGameObject(player, x, player->GetPositionY(), z, o, p, lowguid); break;
|
|
case Z: GOMove::MoveGameObject(player, x, y, player->GetPositionZ(), o, p, lowguid); break;
|
|
case O: GOMove::MoveGameObject(player, x, y, z, player->GetOrientation(), p, lowguid); break;
|
|
case RESPAWN: GOMove::SpawnGameObject(player, x, y, z, o, p, target->GetEntry()); break;
|
|
case GOTO:
|
|
{
|
|
// stop flight if need
|
|
if (player->isInFlight())
|
|
{
|
|
player->GetMotionMaster()->MovementExpired();
|
|
player->CleanupAfterTaxiFlight();
|
|
}
|
|
// save only in non-flight case
|
|
else
|
|
player->SaveRecallPosition();
|
|
player->TeleportTo(target->GetMapId(), x, y, z, o);
|
|
} break;
|
|
case GROUND:
|
|
{
|
|
float ground = target->GetMap()->GetHeight(target->GetPhases(), x, y, MAX_HEIGHT);
|
|
if (ground != INVALID_HEIGHT)
|
|
GOMove::MoveGameObject(player, x, y, ground, o, p, lowguid);
|
|
} break;
|
|
case FLOOR:
|
|
{
|
|
float floor = target->GetMap()->GetHeight(target->GetPhases(), x, y, z);
|
|
if (floor != INVALID_HEIGHT)
|
|
GOMove::MoveGameObject(player, x, y, floor, o, p, lowguid);
|
|
} break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (ID)
|
|
{
|
|
case TEST:
|
|
session->SendNotification("%s", player->GetName());
|
|
break;
|
|
case FACE:
|
|
{
|
|
float const piper2 = float(M_PI) / 2.0f;
|
|
float const multi = player->GetOrientation() / piper2;
|
|
float const multi_int = floor(multi);
|
|
float const new_ori = (multi - multi_int > 0.5f) ? (multi_int + 1)*piper2 : multi_int*piper2;
|
|
player->SetFacingTo(new_ori);
|
|
} break;
|
|
case SELECTNEAR:
|
|
{
|
|
GameObject* object = handler->GetNearbyGameObject();
|
|
if (!object)
|
|
ChatHandler(player->GetSession()).PSendSysMessage("No objects found");
|
|
else
|
|
{
|
|
GOMove::SendAdd(player, object);
|
|
session->SendNotification("Selected %s", object->GetName());
|
|
}
|
|
} break;
|
|
}
|
|
}
|
|
}
|
|
else if (ARG && ID >= SPAWN)
|
|
{
|
|
if (ID >= NORTH && ID <= PHASE)
|
|
{
|
|
GameObject* target = GOMove::GetGameObject(player, lowguid);
|
|
if (!target)
|
|
ChatHandler(player->GetSession()).PSendSysMessage("Object GUID: %u not found", lowguid);
|
|
else
|
|
{
|
|
float x, y, z, o;
|
|
target->GetPosition(x, y, z, o);
|
|
uint32 p = target->GetPhaseMask();
|
|
switch (ID)
|
|
{
|
|
case NORTH: GOMove::MoveGameObject(player, x + ((float)ARG / 100), y, z, o, p, lowguid); break;
|
|
case EAST: GOMove::MoveGameObject(player, x, y - ((float)ARG / 100), z, o, p, lowguid); break;
|
|
case SOUTH: GOMove::MoveGameObject(player, x - ((float)ARG / 100), y, z, o, p, lowguid); break;
|
|
case WEST: GOMove::MoveGameObject(player, x, y + ((float)ARG / 100), z, o, p, lowguid); break;
|
|
case NORTHEAST: GOMove::MoveGameObject(player, x + ((float)ARG / 100), y - ((float)ARG / 100), z, o, p, lowguid); break;
|
|
case SOUTHEAST: GOMove::MoveGameObject(player, x - ((float)ARG / 100), y - ((float)ARG / 100), z, o, p, lowguid); break;
|
|
case SOUTHWEST: GOMove::MoveGameObject(player, x - ((float)ARG / 100), y + ((float)ARG / 100), z, o, p, lowguid); break;
|
|
case NORTHWEST: GOMove::MoveGameObject(player, x + ((float)ARG / 100), y + ((float)ARG / 100), z, o, p, lowguid); break;
|
|
case UP: GOMove::MoveGameObject(player, x, y, z + ((float)ARG / 100), o, p, lowguid); break;
|
|
case DOWN: GOMove::MoveGameObject(player, x, y, z - ((float)ARG / 100), o, p, lowguid); break;
|
|
case RIGHT: GOMove::MoveGameObject(player, x, y, z, o - ((float)ARG / 100), p, lowguid); break;
|
|
case LEFT: GOMove::MoveGameObject(player, x, y, z, o + ((float)ARG / 100), p, lowguid); break;
|
|
case PHASE: GOMove::MoveGameObject(player, x, y, z, o, ARG, lowguid); break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (ID)
|
|
{
|
|
case SPAWN:
|
|
{
|
|
if (GOMove::SpawnGameObject(player, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), player->GetPhaseMgr().GetPhaseMaskForSpawn(), ARG))
|
|
GOMove::Store.SpawnQueAdd(player->GetGUID(), ARG);
|
|
} break;
|
|
case SPAWNSPELL:
|
|
{
|
|
GOMove::Store.SpawnQueAdd(player->GetGUID(), ARG);
|
|
} break;
|
|
case SELECTALLNEAR:
|
|
{
|
|
for (GameObject * go : GOMove::GetNearbyGameObjects(player, static_cast<float>(ARG)))
|
|
GOMove::SendAdd(player, go);
|
|
} break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
return false;
|
|
return true;
|
|
}
|
|
};
|
|
|
|
// possible spells:
|
|
// 27651, 897
|
|
|
|
class GOMove_spell_place : public SpellScriptLoader
|
|
{
|
|
public:
|
|
GOMove_spell_place() : SpellScriptLoader("GOMove_spell_place") { }
|
|
|
|
class GOMove_spellscript : public SpellScript
|
|
{
|
|
PrepareSpellScript(GOMove_spellscript);
|
|
|
|
void HandleAfterCast()
|
|
{
|
|
if (!GetCaster())
|
|
return;
|
|
Player* player = GetCaster()->ToPlayer();
|
|
if (!player)
|
|
return;
|
|
const WorldLocation* summonPos = GetExplTargetDest();
|
|
if (!summonPos)
|
|
return;
|
|
if (uint32 entry = GOMove::Store.SpawnQueGet(player->GetGUID()))
|
|
GOMove::SpawnGameObject(player, summonPos->GetPositionX(), summonPos->GetPositionY(), summonPos->GetPositionZ(), player->GetOrientation(), player->GetPhaseMgr().GetPhaseMaskForSpawn(), entry);
|
|
}
|
|
|
|
void Register() override
|
|
{
|
|
AfterCast += SpellCastFn(GOMove_spellscript::HandleAfterCast);
|
|
}
|
|
};
|
|
|
|
SpellScript* GetSpellScript() const override
|
|
{
|
|
return new GOMove_spellscript();
|
|
}
|
|
};
|
|
|
|
class GOMove_player_track : public PlayerScript
|
|
{
|
|
public:
|
|
GOMove_player_track() : PlayerScript("GOMove_player_track") { }
|
|
|
|
void OnLogout(Player* player) override
|
|
{
|
|
GOMove::Store.SpawnQueRem(player->GetGUID());
|
|
}
|
|
};
|
|
|
|
void AddSC_GOMove_commandscript()
|
|
{
|
|
new GOMove_commandscript();
|
|
new GOMove_spell_place();
|
|
} |