The EnumVisibleObjects function takes a pointer to the collection of objects and you pass to it a callback for each object as well as a filter for specific object types. Because I don't like to have competing threads, I like to just do everything from the main one and clear the objects before each query.
Implementation: (You can make your last argument ie lua_gettop be the filter for calls that use the object manager)
Code:
-- COUNTING
local units = GetObjCount(5)
local players = GetObjCount(6)
local player = GetObjCount(7)
print(units, players, player)
-- FILTER EXAMPLE
local onlyTraverseCreatureType = GetObjGUID("target", 5)
-- HELPERS
local unitID = "focus mouseover pet player target vehicle" ..
"arena1 arena2 arena3 arena4 arena5 " ..
"boss1 boss2 boss3 boss4 " ..
"party1 party2 party3 party4 " ..
"partytype1 partytype2 partytype3 partytype4 " ..
"raid1 raid2 raid3 raid4 raid5 raid6 raid7 raid8 raid9 raid10 " ..
"raid11 raid12 raid13 raid14 raid15 raid16 raid17 raid18 raid19 raid20 " ..
"raid21 raid22 raid23 raid24 raid25 raid26 raid27 raid28 raid29 raid30 " ..
"raid31 raid32 raid33 raid34 raid35 raid36 raid37 raid38 raid39 raid40 " ..
"raidpet1 raidpet2 raidpet3 raidpet4 raidpet5 raidpet6 raidpet7 raidpet8 raidpet9 raidpet10 " ..
"raidpet11 raidpet12 raidpet13 raidpet14 raidpet15 raidpet16 raidpet17 raidpet18 raidpet19 raidpet20 " ..
"raidpet21 raidpet22 raidpet23 raidpet24 raidpet25 raidpet26 raidpet27 raidpet28 raidpet29 raidpet30 " ..
"raidpet31 raidpet32 raidpet33 raidpet34 raidpet35 raidpet36 raidpet37 raidpet38 raidpet39 raidpet40 " ..
"npc"
local unitIDs = {}
for s in unitID:gmatch("%S+") do table.insert(unitIDs, s) end
function GetObjGUID(unit)
if not CPlus then return end
for k, v in pairs(unitIDs) do
if unit == v then
return UnitGUID(v) -- use WoW api for known relations ("player", "pet, "mouseover", etc)
end
end
return GetGUID(unit) -- link to your module call (your name would be different)
end
Module Setup:
Code:
void addToGlobal(unsigned int type, WowObject* obj)
{
Globals::Objects[type].push_back(obj);
}
unsigned int ObjMgr::EnumVisibleObjectsCb(int64_t objectPtr, int64_t filter)
{
if (objectPtr && filter < Invalid)
{
auto object = reinterpret_cast<WowObject*>(objectPtr);
auto type = object->GetType();
switch (type)
{
case Object:
addToGlobal(Object, object);
break;
case Item:
addToGlobal(Item, object);
break;
case Container:
addToGlobal(Container, object);
break;
// ... for all types
}
}
return 1;
}
Explicit Traversal (All Object Types):
Code:
auto filter = TypeId::Object;
filter = (TypeId)GMethod::Invoke<int64_t>(Offsets::lua_tointeger, L, 3); -- may not be 3 in your case
for (auto i = 0; i < TypeId::Invalid; i++) // clear and work with a clean list avoid freed object (nullptr)
Globals::Objects[i].clear();
GMethod::Invoke<char>(Offsets::EnumVisibleObjects, ObjMgr::EnumVisibleObjectsCb, (int)filter); // Invoke the object traversal
if (filter) // non-zero object (not TypeId::Object)
{
for (auto o : Globals::Objects[filter])
{
if (o->GetGuid() == guid)
{
// o->Interact(); // do work here
return 1;
}
else
continue;
}
}
else
{
for (auto j = 0; j < TypeId::Invalid; j++) // TypId::Invalid == 17 ie make it the last member of the object type enum
{
for (auto o : Globals::Objects[j])
{
if (o->GetGuid() == guid)
{
o->Interact();
return 1;
}
else
continue;
}
}
}
GetGUID:
Code:
int LMethod::GetObjectGuid(int64_t L)
{
auto objectName = GMethod::Invoke<char*>(Offsets::lua_tolstring, L, 2, nullptr);
auto filter = TypeId::Object;
filter = (TypeId)GMethod::Invoke<int64_t>(Offsets::lua_tointeger, L, 3);
for (auto i = 0; i < TypeId::Invalid; i++)
Globals::Objects[i].clear();
GMethod::Invoke<char>(Offsets::EnumVisibleObjects, ObjMgr::EnumVisibleObjectsCb, (int)filter);
for (auto o : Globals::Objects[filter])
{
if (string(o->GetObjectName()) == objectName)
{
GMethod::Invoke<int64_t>(Offsets::lua_pushguid, L, o->GetGuid());
return 1;
}
else
continue;
}
GMethod::Invoke<int64_t>(Offsets::lua_pushnil, L);
return 1;
}
As a side note I also experimented with using a modded external lua 5.1. There is a guid to string function in WoW that can be used in this case because regular non-WoW lua has no guid things.
External GUID Conversion:
Code:
string GString(WGuid* guid)
{
char guidStr[136];
GMethod::Invoke<int64_t>(Offsets::GuidToString, (int64_t)guid, guidStr, 128); // not sure why 128 ??? todo investigate
return guidStr;
}