Object Traversal Guide menu

User Tag List

Results 1 to 4 of 4
  1. #1
    GlittPrizes's Avatar Active Member CoreCoins Purchaser Authenticator enabled
    Reputation
    58
    Join Date
    Nov 2019
    Posts
    104
    Thanks G/R
    53/33
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Object Traversal Guide

    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;
    }
    Last edited by GlittPrizes; 07-18-2021 at 11:13 AM. Reason: edit: might want a bitwise for "All" instead of non zero objects

    Object Traversal Guide
  2. Thanks wang666, Neer, aeo, Reghero, thateuler (5 members gave Thanks to GlittPrizes for this useful post)
  3. #2
    GlittPrizes's Avatar Active Member CoreCoins Purchaser Authenticator enabled
    Reputation
    58
    Join Date
    Nov 2019
    Posts
    104
    Thanks G/R
    53/33
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    On second thought flushing and repopulating might not be the best way about this. I'm still trying to find a proper way to cycle the objects. My issue is with old garbage objects that go out of the object manager and I crash when I call a vtable function on them. Any ideas how to check if an object is still valid on the module side of things? Like what will change that can be determined without causing a null or access violation?

  4. #3
    Weekday's Avatar Contributor

    Reputation
    144
    Join Date
    Sep 2007
    Posts
    350
    Thanks G/R
    1/2
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    On every update set all the object pointers to zero, then enumerate and go through objects, if an object is already in your list then set back the pointer, if it is not then create a new object and add it. At some interval clear out objects with zeroed pointers.

  5. Thanks GlittPrizes, Creepwalker (2 members gave Thanks to Weekday for this useful post)
  6. #4
    GlittPrizes's Avatar Active Member CoreCoins Purchaser Authenticator enabled
    Reputation
    58
    Join Date
    Nov 2019
    Posts
    104
    Thanks G/R
    53/33
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Weekday View Post
    On every update set all the object pointers to zero, then enumerate and go through objects, if an object is already in your list then set back the pointer, if it is not then create a new object and add it. At some interval clear out objects with zeroed pointers.
    I think I have found what was causing so many issues with my object management. In my lua_CFunctions it would call things like the Object Manager or another function that has a return value. The return happening in the middle of the CFunc would interfere with the lua stack.

    I'm now very rarely ever clearing the object map and just do <guidString, WowObject*> which is easier and more performant to fetch objects in the CFuncs.

Similar Threads

  1. object manager, guid
    By asdcxy in forum Diablo 3 Memory Editing
    Replies: 2
    Last Post: 10-09-2012, 03:33 PM
  2. [Release] [snippet]Get Object By GUID
    By J0llyGr33n in forum WoW Memory Editing
    Replies: 4
    Last Post: 03-24-2012, 12:02 PM
  3. Guide: How to use/create your own Game Objects
    By Arthas117 in forum WoW EMU Guides & Tutorials
    Replies: 12
    Last Post: 01-22-2008, 12:22 PM
  4. Obstacle Course Guide+ Game Objects
    By LJN in forum World of Warcraft Emulator Servers
    Replies: 13
    Last Post: 12-14-2007, 07:47 PM
  5. [Guide] Finding Display IDs and Item/Object IDs,
    By iccy in forum World of Warcraft Guides
    Replies: 2
    Last Post: 10-02-2007, 11:37 PM
All times are GMT -5. The time now is 08:32 PM. Powered by vBulletin® Version 4.2.3
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2024 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search