[Question] Active Player object type hit or miss menu

Shout-Out

User Tag List

Page 1 of 2 12 LastLast
Results 1 to 15 of 27
  1. #1
    wardrive's Avatar Active Member
    Reputation
    15
    Join Date
    Jul 2023
    Posts
    43
    Thanks G/R
    23/8
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    [Question] Active Player object type hit or miss

    WoTLK Classic - 3.4.2.50664

    So I've been building a bot for a few months now, and have grown relatively familiar with navigating the object manager and retrieving data from it. I have not experienced this until recently, but it seems like sometimes entity type 7 (Active Player) does not reside in the entity array. Is this the result of poor code practices, or indeed how the object manager functions on occasion? I'm assuming I can retrieve local player information elsewhere, and if necessary I can handle the active player population via another means. I'd just rather not have to write yet another function to do so unless my observations are correct.

    For context, my bot works flawlessly on several toons. Character class, level, energy type etc, none of that shit matters. It just doesn't work on one particular character. The offsets I'm using are correct, and they provide the correct data for every character, including this one on occasion (the one that isn't working) (object type 7 doesn't exist in the entity array at the time of scanning). It will work randomly on this specific toon as well, particularly after a hearth to another zone. It's just odd behavior. I'm assuming it's my code doing something funky, and can share some relevant code segments for how I handle certain things. Even when it fails to retrieve the active player entity, it still retrieves everything else. Distance values are a little fubar, since they are calculated from the active player object coordinate differential, but other than that they are retrieved and displayed fine.

    I realize this sounds like rambling but it doesn't make any sense to me and I'm the one that wrote it.

    Unless the object manager does indeed occasionally not contain the active player object. Otherwise looks like I'm starting from scratch.

    Screenshot - d916391eeea7c8a4c21559994b41c3cd - Gyazo
    Last edited by wardrive; 09-05-2023 at 02:16 AM.

  2. #2
    wardrive's Avatar Active Member
    Reputation
    15
    Join Date
    Jul 2023
    Posts
    43
    Thanks G/R
    23/8
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Also, while I'm here with an open thread, I've noticed that NPC's may share a GUID, and are differentiated only via a separate smaller, 4 byte ID number (by my observations, I try and retain a unique list of all objects and their pointers, and noticed that filtering them by GUID wasn't working because they share the same value that I was retrieving.

    When displaying NPC's on my ESP for example, they will flicker as they are removed (when another object with the same GUID and different pointer is identified, it cleans the cache) from the local array. It seems to me that this occurs in towns or cities, questing areas most of the time. Selecting one npc for display will display multiple NPCS as their GUID matches the target GUID.

  3. #3
    unsigned's Avatar Member
    Reputation
    2
    Join Date
    Jul 2023
    Posts
    14
    Thanks G/R
    11/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    ActivePlayer is in the objectmanager, might be an issue with how you are iterating it?

    I would recommend this post from @_chase, really good explanation on it. https://www.ownedcore.com/forums/wor...-searches.html.

    https://i.imgur.com/1eCGEp1.jpeg

  4. Thanks wardrive (1 members gave Thanks to unsigned for this useful post)
  5. #4
    wardrive's Avatar Active Member
    Reputation
    15
    Join Date
    Jul 2023
    Posts
    43
    Thanks G/R
    23/8
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by unsigned View Post
    ActivePlayer is in the objectmanager, might be an issue with how you are iterating it?

    I would recommend this post from @_chase, really good explanation on it. https://www.ownedcore.com/forums/wor...-searches.html.

    https://i.imgur.com/1eCGEp1.jpeg
    So I'm in agreement that it's there most of the time, just wasn't sure if this was solely a me problem or something observed by others. I'm ok with my code being fucked and having to fix it, I just don't want to drive myself mad if this is a known issue. I'd readily accept that my implementation of the object manager is flawed if it never worked at all, but thought it an efficient use of time to ask the question here before investing more time troubleshooting than I already have.

  6. #5
    wardrive's Avatar Active Member
    Reputation
    15
    Join Date
    Jul 2023
    Posts
    43
    Thanks G/R
    23/8
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Python implementation:
    Screenshot - bd1b7fa5e90b0f26dc7d87f8c17eb455 - Gyazo

    The piece that I'm somewhat suspect of:

    Code:
                    if pointer != 0:
                        pointer2 = reader.process.read_longlong(pointer + 0x18)
                        entity_temp = reader.process.read_bytes(pointer2 + 0x10, 1)
                        entity_type = int.from_bytes(entity_temp, byteorder='little')
    
                        if entity_type not in [5,6,7,8]:
                            continue
    
                        entity_guid = reader.process.read_long(pointer2 + 0x18)
    
                        if entity_type == 7: #activeplayer 
                            debugmsg = "Triggered entity_type '7'."
                            active_player.timestamp = time.time()
                            active_player.pointer = f"{pointer:X}"
    Is there any reason that 7 would or could be anything more than a 1 byte value at that offset? Like I said, it works on other toons, and even when it doesn't read the player data, it's reading the data from other entity types, so it's iterating and identifying things correctly.

    Are there any other entity types that represent the active player, other than 7?

    wowObjectTypes = {
    [0] = "Object",
    [1] = "Item",
    [2] = "Container",
    [3] = "AzeriteEmpoweredItem",
    [4] = "AzeriteItem" ,
    [5] = "Unit",
    [6] = "Player",
    [7] = "ActivePlayer",
    [8] = "GameObject",
    [9] = "Dynamic",
    [10] = "Corpse",
    [11] = "Areatrigger",
    [12] = "Scene",
    [13] = "Conversation",
    [14] = "AiGroup",
    [15] = "Scenario",
    [16] = "Loot",
    [17] = "Invalid"
    };
    Last edited by wardrive; 09-05-2023 at 03:27 AM.

  7. #6
    wardrive's Avatar Active Member
    Reputation
    15
    Join Date
    Jul 2023
    Posts
    43
    Thanks G/R
    23/8
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Additionally, I tried comparison via localplayer guid and entity guid to match activeplayer and that also failed (only on this one character). It can't be any attributes of the active_player object or definition functions, because it is failing to even detect the active player object for this character.
    Last edited by wardrive; 09-05-2023 at 06:17 AM.

  8. #7
    klumpen's Avatar Active Member
    Reputation
    18
    Join Date
    Apr 2007
    Posts
    67
    Thanks G/R
    29/12
    Trade Feedback
    2 (100%)
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)
    Your object types appear correct. I'd need to see more of the pointer reading loop to tell what is up - the bits you've shown align with what I have, which is the uneducated brute-force loop (as opposed to the sexy TSHashArrayMapList (or whatever the F you guys like to call it. Source?) method). And I always have an ActivePlayer struct present.

    Code:
    let object_types: HashMap<u8, String> = {...5="Unit",6="Player",7="ActivePlayer",...};
    let base: u64 = game.read("ObjectManager::BASE");
    let max: u32 = 256; // ... 
    
    for i in 0..max {
      let ptr = game.read_ptr(base + 0x8 + (0x8 * i));
      if ptr.is_null() { continue }
      while !ptr.is_null() { 
        let addr: u64 = game.read(ptr + 0x18);
        let guid: GUID = game.read(ptr + 0x8);
        if guid != GUID::empty {
          let object_type: u8 = game.read(ptr + 0x10);
          dbg!("entity at {addr} with guid {guid} is of type {object_type}");
        }
        // chase the pointer until null (end of hash bucket chain)
        ptr = game.read(ptr + 0x0);
      }
    }

  9. Thanks wardrive (1 members gave Thanks to klumpen for this useful post)
  10. #8
    wardrive's Avatar Active Member
    Reputation
    15
    Join Date
    Jul 2023
    Posts
    43
    Thanks G/R
    23/8
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    So it's a little sloppy and has a lot of debug code in it at the moment trying to chase this down:

    Code:
    class ObjectManager:
    	def __init__(self, process, base):
    		self.process = process
    		self.base = base
    		self.manager_pointer = self.base + objectmanager_offset
    		self.manager_base = self.process.read_longlong(self.manager_pointer)
    		self.entity_array = self.process.read_longlong(self.manager_base + 0x8)
    		self.objects = []
    		self.players = []
    		self.playernamecache = []
    		self.units = []
    		self.count = self.process.read_int(self.manager_base)
    		self.curCount = self.process.read_int(self.manager_base + 0x10)
    
    	def update(self):
    		self.manager_pointer = self.base + objectmanager_offset
    		self.manager_base = self.process.read_longlong(self.manager_pointer)
    		self.entity_array = self.process.read_longlong(self.manager_base + 0x8)
    		self.count = self.process.read_int(self.manager_base)
    		self.curCount = self.process.read_int(self.manager_base + 0x10)
    
    
    def perform_update_thread(reader, object_manager):
        global gettime, target, active_player, camera, debugmsg#, track_players, track_units, track_objects, active_player
        active_player = object_manager.WowObject()
        camera = reader.CameraObject(reader.process, reader.base)
    
        while True:
            try:
                reader.update()
                gettime = reader.process.read_float(reader.base + gettime_offset)
    
                try:
                    camera.timestamp = time.time()
                    camera.x_pos = reader.process.read_float(camera.offset + 0x10)
                    camera.y_pos = reader.process.read_float(camera.offset + 0x14)
                    camera.z_pos = reader.process.read_float(camera.offset + 0x18)
                    camera.pos_v3 = pygame.math.Vector3(camera.x_pos, camera.y_pos, camera.z_pos)
                except:
                    logger_function("Failed to obtain camera position")
                    print("Failed to obtain camera position")
                    continue
                
                target_guid = reader.process.read_long(reader.base + target_guid_offset)
                localplayer_guid = reader.process.read_long(reader.base + playerguid_offset)
                
                
                if target_guid == 0:
                    target = None
    
                object_manager.update()
                
                object_debug = []
                
                for i in range(0,object_manager.count):
                    pointer = reader.process.read_longlong(object_manager.entity_array + (0x8*i))
    
                    if pointer != 0:
                        pointer2 = reader.process.read_longlong(pointer + 0x18)
                        entity_temp = reader.process.read_bytes(pointer2 + 0x10, 1)
                        entity_type = int.from_bytes(entity_temp, byteorder='little')
    
                        if entity_type not in [5,6,7,8]:
                            continue
    
                        entity_guid = reader.process.read_long(pointer2 + 0x18)
                        
                        entity = {
                            'timestamp' : time.time(),
                            'type' : entity_type,
                            'pointer' : pointer, 
                            'entity_guid' : entity_guid,
                            'reader_base' : reader.base,
                            'obj_manager_base' : object_manager.manager_base
                        }
                        
                        object_debug.append(entity)
                        debugmsg = f"Object Manager  L: {localplayer_guid:X}  E: {entity_guid:X} "
                        
                        if entity_type == 7 or entity_guid == localplayer_guid: #activeplayer 
                            print("Triggered entity_type '7'")
                            debugmsg = "Triggered entity_type '7'."
                            active_player.timestamp = time.time()
                            active_player.pointer = f"{pointer:X}"
                            active_player.name = reader.process.read_string(reader.base + playername_offset, 15)#"Unknown"
                            active_player.base_address = pointer2
                            active_player.entity_type = object_manager.parse_entity_type(entity_type)
                            active_player.level = reader.process.read_long(pointer2 + 0xD7B0)
                            active_player.faction = object_manager.parse_faction_id(reader.process.read_long(pointer2 + 0xD7D4))
                            active_player.race = object_manager.parse_race(reader.process.read_long(pointer2 + 0xD7D4))
                            
                            temp = reader.process.read_bytes(pointer2 + 0xD7A4 + 0x1, 1)
                            temp = int.from_bytes(temp, byteorder='little')
                            active_player.entity_class = object_manager.parse_class(temp)
                            
                            active_player.guid = reader.process.read_long(pointer2 + 0x18)
                            active_player.unitid = reader.process.read_long(pointer2 + 0xD8)
                            active_player.target = reader.process.read_long(pointer2 + 0xD770)
                            #active_player.incombat = str(bool(reader.process.read_int(pointer2 + 0xD680)))#D584
                            active_player.health = reader.process.read_int(pointer2 + 0xD6B0)
                            active_player.healthmax = reader.process.read_int(pointer2 + 0xD6B8)
                            active_player.energy = reader.process.read_int(pointer2 + 0xD9F0) #0xD580 
                            active_player.energymax = reader.process.read_int(pointer2 + 0xDA18)
                            active_player.healthpercentage = round((active_player.health / active_player.healthmax) * 100, 2)
                            active_player.energypercentage = round((active_player.energy / active_player.energymax) * 100, 2)
                            active_player.auras = object_manager.get_auras(pointer2, active_player.guid)
                            active_player.buffs = active_player.auras[0]
                            active_player.debuffs = active_player.auras[1]
                            active_player.misc_auras = active_player.auras[2]
                            active_player.x_pos = reader.process.read_float(pointer2 + 0x148)
                            active_player.y_pos = reader.process.read_float(pointer2 + 0x14C)
                            active_player.z_pos = reader.process.read_float(pointer2 + 0x150)
                            active_player.r_val = reader.process.read_float(pointer2 + 0x158)
                            active_player.pos_v3 = pygame.math.Vector3(active_player.x_pos, active_player.y_pos, active_player.z_pos)
                            active_player.wts = world_to_screen(view_matrix(reader), active_player.pos_v3)
                            active_player.distance = 0
                            active_player.casting_spellid = reader.process.read_int(pointer2 + 0x730)
                            active_player.cooldowns = object_manager.get_cooldowns(object_manager)
    Those are the relevant bits. There's a cleanup function and some exception handling, but it isn't even triggering the conditional for active player on this character unless I hearth (a loading screen seems to fix it, but only when I hearth. /reload does not work. Logging out and back in does not work either) Streaming output to console on each iteration, I can see that the object manager pointer changes between the working and non-working characters, but beyond that nothing is out of the ordinary.

    I'd like to reiterate that even while the active player entity is not functioning on the non-working character, every other entity type populates just fine. Also, I haven't actually had any exceptions thrown for the camera, I was just wrapping sections in try / except that occur before the active_player entity detection statements trying to see if maybe I was getting an error earlier in the iteration that was causing something to fail.

    Everything is working as expected, entity type 7 just never comes across (only while playing this toon). Could this be a threading lock issue or something? I wouldn't think that'd be the case, as each of my threads handles different areas in memory and shouldn't be causing issues. I had assumed it was normal for the object manager pointer to change between character logins (not account logins). Not even closing the game client.

    Any feedback is appreciated. Good to know that the consensus so far is that activeplayer should always be there though. At least I know where to focus my effort.

    it's failing here:

    Code:
    if entity_type == 7
    Output:
    Working character:
    Code:
    Triggered entity_type '7'
    {'timestamp': 1693912119.9532065, 'type': 8, 'pointer': 1729861822560, 'entity_guid': 7208884, 'reader_base': 140702920409088, 'obj_manager_base': 1727293796752}
    {'timestamp': 1693912119.9543283, 'type': 8, 'pointer': 1726732503568, 'entity_guid': 7208883, 'reader_base': 140702920409088, 'obj_manager_base': 1727293796752}
    {'timestamp': 1693912119.9556115, 'type': 5, 'pointer': 1727341702704, 'entity_guid': 82706357, 'reader_base': 140702920409088, 'obj_manager_base': 1727293796752}
    {'timestamp': 1693912119.958603, 'type': 8, 'pointer': 1729861822800, 'entity_guid': 7208884, 'reader_base': 140702920409088, 'obj_manager_base': 1727293796752}
    {'timestamp': 1693912119.9615955, 'type': 8, 'pointer': 1727341254160, 'entity_guid': 7208884, 'reader_base': 140702920409088, 'obj_manager_base': 1727293796752}
    {'timestamp': 1693912119.9641519, 'type': 5, 'pointer': 1726732503376, 'entity_guid': 7654731, 'reader_base': 140702920409088, 'obj_manager_base': 1727293796752}
    {'timestamp': 1693912119.9641519, 'type': 5, 'pointer': 1726732503232, 'entity_guid': 7654543, 'reader_base': 140702920409088, 'obj_manager_base': 1727293796752}
    {'timestamp': 1693912119.9641519, 'type': 5, 'pointer': 1726732503520, 'entity_guid': 7654564, 'reader_base': 140702920409088, 'obj_manager_base': 1727293796752}
    {'timestamp': 1693912119.966611, 'type': 8, 'pointer': 1727341254304, 'entity_guid': 7208884, 'reader_base': 140702920409088, 'obj_manager_base': 1727293796752}
    {'timestamp': 1693912119.9676087, 'type': 8, 'pointer': 1726732503424, 'entity_guid': 7208883, 'reader_base': 140702920409088, 'obj_manager_base': 1727293796752}
    {'timestamp': 1693912119.9686038, 'type': 5, 'pointer': 1727341254112, 'entity_guid': 7654136, 'reader_base': 140702920409088, 'obj_manager_base': 1727293796752}
    {'timestamp': 1693912119.9705987, 'type': 8, 'pointer': 1727341254544, 'entity_guid': 7208884, 'reader_base': 140702920409088, 'obj_manager_base': 1727293796752}
    {'timestamp': 1693912119.9741237, 'type': 8, 'pointer': 1729861822848, 'entity_guid': 7208884, 'reader_base': 140702920409088, 'obj_manager_base': 1727293796752}
    {'timestamp': 1693912119.9773726, 'type': 5, 'pointer': 1729861822752, 'entity_guid': 7654423, 'reader_base': 140702920409088, 'obj_manager_base': 1727293796752}
    {'timestamp': 1693912119.9773726, 'type': 8, 'pointer': 1729861822608, 'entity_guid': 7208884, 'reader_base': 140702920409088, 'obj_manager_base': 1727293796752}
    {'timestamp': 1693912119.978367, 'type': 5, 'pointer': 1729861822464, 'entity_guid': 7654561, 'reader_base': 140702920409088, 'obj_manager_base': 1727293796752}
    {'timestamp': 1693912119.9793663, 'type': 8, 'pointer': 1727341254496, 'entity_guid': 7208884, 'reader_base': 140702920409088, 'obj_manager_base': 1727293796752}
    {'timestamp': 1693912119.9803605, 'type': 6, 'pointer': 1726731870816, 'entity_guid': 84497089, 'reader_base': 140702920409088, 'obj_manager_base': 1727293796752}
    {'timestamp': 1693912119.9833553, 'type': 6, 'pointer': 1726731870720, 'entity_guid': 84357662, 'reader_base': 140702920409088, 'obj_manager_base': 1727293796752}
    {'timestamp': 1693912119.9865954, 'type': 8, 'pointer': 1726732503040, 'entity_guid': 7208884, 'reader_base': 140702920409088, 'obj_manager_base': 1727293796752}
    {'timestamp': 1693912119.9875922, 'type': 5, 'pointer': 1726732503136, 'entity_guid': 7655126, 'reader_base': 140702920409088, 'obj_manager_base': 1727293796752}
    {'timestamp': 1693912119.9885895, 'type': 8, 'pointer': 1729861822896, 'entity_guid': 7208884, 'reader_base': 140702920409088, 'obj_manager_base': 1727293796752}
    {'timestamp': 1693912119.9930837, 'type': 5, 'pointer': 1726731870912, 'entity_guid': 7654491, 'reader_base': 140702920409088, 'obj_manager_base': 1727293796752}
    {'timestamp': 1693912119.9941013, 'type': 8, 'pointer': 1729861822368, 'entity_guid': 7208884, 'reader_base': 140702920409088, 'obj_manager_base': 1727293796752}
    {'timestamp': 1693912119.9965308, 'type': 8, 'pointer': 1726732503616, 'entity_guid': 7208884, 'reader_base': 140702920409088, 'obj_manager_base': 1727293796752}
    {'timestamp': 1693912119.9985266, 'type': 6, 'pointer': 1729861822320, 'entity_guid': 65074276, 'reader_base': 140702920409088, 'obj_manager_base': 1727293796752}
    {'timestamp': 1693912119.9995236, 'type': 8, 'pointer': 1727341254448, 'entity_guid': 7208884, 'reader_base': 140702920409088, 'obj_manager_base': 1727293796752}
    {'timestamp': 1693912120.0060384, 'type': 7, 'pointer': 1729861822176, 'entity_guid': REDACTED, 'reader_base': 140702920409088, 'obj_manager_base': 1727293796752}
    {'timestamp': 1693912120.0090806, 'type': 5, 'pointer': 1726732503760, 'entity_guid': 7654517, 'reader_base': 140702920409088, 'obj_manager_base': 1727293796752}
    Nonworking:
    Code:
    {'timestamp': 1693912200.1197643, 'type': 5, 'pointer': 1726731736016, 'entity_guid': 7742270, 'reader_base': 140702920409088, 'obj_manager_base': 1727292814928}
    {'timestamp': 1693912200.1217656, 'type': 8, 'pointer': 1726731735680, 'entity_guid': 830996489, 'reader_base': 140702920409088, 'obj_manager_base': 1727292814928}
    {'timestamp': 1693912200.1262872, 'type': 5, 'pointer': 1726731736112, 'entity_guid': 7790791, 'reader_base': 140702920409088, 'obj_manager_base': 1727292814928}
    {'timestamp': 1693912200.1272845, 'type': 5, 'pointer': 1726731735872, 'entity_guid': 7736862, 'reader_base': 140702920409088, 'obj_manager_base': 1727292814928}
    {'timestamp': 1693912200.1477525, 'type': 5, 'pointer': 1726731736208, 'entity_guid': 7735901, 'reader_base': 140702920409088, 'obj_manager_base': 1727292814928}
    Object count difference attributed to player location. (Orgrimmar [working character] vs. near spawn [non-working])

    I've also completely killed all threads and relaunched on each toon. It works flawlessly on every character except this one. Has had me scratching my head for several days now.

    I'm poking around in Cheat Engine trying to identify a pointer that contains my player GUID on the non-working character and it seems to confirm my findings and debug output, but I'm not trying to fall victim to my own confirmation bias.
    Last edited by wardrive; 09-05-2023 at 07:00 AM.

  11. #9
    Glitt's Avatar Active Member CoreCoins Purchaser
    Reputation
    30
    Join Date
    Dec 2022
    Posts
    44
    Thanks G/R
    8/13
    Trade Feedback
    0 (0%)
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)
    Go up a layer and look at how the parent function works, and that implies its usage. It takes a callback and returns when it hits the last/first object in the collection or when the callback is zero. That's pretty much all there is to know about the parent "EnumVisibleObjects". If I'm not mistaken classic/wrath also has an enumerator that will iterate through hidden stuff too. There are some extras like the "filter" that is passed along with the returns that can be utilized to take advantage of these functions in a custom way, but that is less relevant to your missing local player.

    Code:
    char __fastcall enum_visible_objects(unsigned int (__fastcall *cb)(_QWORD *, __int64), __int64 filter)
    {
      _QWORD *current; // rbx
      _QWORD *prev; // rcx
    
      current = *(_QWORD **)(cur_mgr + 0x120);
      if ( current == (_QWORD *)(cur_mgr + 0x120) ) // EQUALS LAST
        return 1;
      while ( 1 )
      {
        prev = current - 5;
        current = (_QWORD *)*current;
        if ( !cb(prev, filter) )                    // YOU ARE HERE!!!
          break;
        if ( current == (_QWORD *)(cur_mgr + 0x120) )
          return 1;
      }
      return 0;
    }
    So to reiterate no pun here, you are likely returning 0 before the local player is discovered, you could be causing issues with checking fields on objects that are invalid (usually nullptr), or something else is interfering with the callback. To summarize EVO, the above is:
    Code:
    while forever previous is before current and break if any object (from cb) returns 0. if current is end return 1 (partial of objects) else return 0 (all objects)
    Last edited by Glitt; 09-05-2023 at 10:16 AM. Reason: last or first depending how you look at it

  12. #10
    wardrive's Avatar Active Member
    Reputation
    15
    Join Date
    Jul 2023
    Posts
    43
    Thanks G/R
    23/8
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I don't see that being the case in my implementation though. It's an infinite loop, wrapped in a try / except block with a continue statement handling any errors. In other words, even if it fails, it keeps chugging burning cycles:

    Code:
        while True:
            try:
                gettime = reader.process.read_float(reader.base + gettime_offset)
    
                camera.timestamp = time.time()
                camera.x_pos = reader.process.read_float(camera.offset + 0x10)
                camera.y_pos = reader.process.read_float(camera.offset + 0x14)
                camera.z_pos = reader.process.read_float(camera.offset + 0x18)
                camera.pos_v3 = pygame.math.Vector3(camera.x_pos, camera.y_pos, camera.z_pos)
               
                target_guid = reader.process.read_long(reader.base + target_guid_offset)
                localplayer_guid = reader.process.read_long(reader.base + playerguid_offset)
    
                if target_guid == 0:
                    target = None
    
                object_manager.update()
                
                for i in range(0,object_manager.count):
                    pointer = reader.process.read_longlong(object_manager.entity_array + (0x8*i))
    
                    if pointer != 0:
                        pointer2 = reader.process.read_longlong(pointer + 0x18)
                        entity_temp = reader.process.read_bytes(pointer2 + 0x10, 1)
                        entity_type = int.from_bytes(entity_temp, byteorder='little')
    
                        if entity_type not in [5,6,7,8]:
                            continue
    Pseudocode:
    While true (always, I don't return out of this function, it is managed by a separate thread), for number of entities in the object manager (as reported by the count value at base + objectmanager_offset), do stuff. If the entity type value at offset pointer2 + 0x10 isn't of type 5,6,7, or 8, skip the loop iteration and move onto the next pointer until we have iterated over the entity array n (count) times. Forever.

    After each loop, it updates the count and does it all over again. Typically, count reports 1024. curCount varies depending on where I'm at. I figure if I use the larger (maximum) value, it would find it, no? 1024 reads vs. 120-200 something. Unless I'm missing something. For the sake of argument, and I know it isn't "efficient", even if it fails to read the memory address, the exception handling is a logger function, and a continue statement.

    This thing will burn my CPU out before it stops trying to read pointers.
    Last edited by wardrive; 09-05-2023 at 10:25 AM.

  13. #11
    Glitt's Avatar Active Member CoreCoins Purchaser
    Reputation
    30
    Join Date
    Dec 2022
    Posts
    44
    Thanks G/R
    8/13
    Trade Feedback
    0 (0%)
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)
    When you cycle through do you check for null object or invalid type? I had issues when checking for fields like position, etc when not first checking if the object is valid or zero. That would prevent subsequent objects from being analyzed.

    edit: I see you do check for 0 hmm looking again through this...
    Last edited by Glitt; 09-05-2023 at 10:26 AM. Reason: i see it

  14. Thanks wardrive (1 members gave Thanks to Glitt for this useful post)
  15. #12
    wardrive's Avatar Active Member
    Reputation
    15
    Join Date
    Jul 2023
    Posts
    43
    Thanks G/R
    23/8
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Glitt View Post
    When you cycle through do you check for null object or invalid type? I had issues when checking for fields like position, etc when not first checking if the object is valid or zero. That would prevent subsequent objects from being analyzed.
    Indeed, see below:

    Code:
                object_manager.update()
                
                for i in range(0,object_manager.count):
                    pointer = reader.process.read_longlong(object_manager.entity_array + (0x8*i))
    
                    if pointer != 0:
    If the entity type does not match one of the specified entity types I want to capture, it simply skips the iteration and moves onto the next pointer.

    Code:
                    if pointer != 0:
                        pointer2 = reader.process.read_longlong(pointer + 0x18)
                        entity_temp = reader.process.read_bytes(pointer2 + 0x10, 1)
                        entity_type = int.from_bytes(entity_temp, byteorder='little')
    
                        if entity_type not in [5,6,7,8]:
                            continue
    It does this before retrieving any other data about the object.

    I've tried swapping iteration count definition with both count and curCount. When performing the loop with curCount as the iteration range, I appear to miss some objects when compared to count (1024). I've also tried inflating the range to some absurd number just to keep it chugging along and that didn't work either.

    The bit that's driving me nuts is that it only does this for one of my characters. All other characters I've tested this on work as expected.

    I'm happy to discuss / screenshare if anyone is bored and wants to connect on discord, just shoot me a PM.
    Last edited by wardrive; 09-05-2023 at 10:59 AM.

  16. #13
    Glitt's Avatar Active Member CoreCoins Purchaser
    Reputation
    30
    Join Date
    Dec 2022
    Posts
    44
    Thanks G/R
    8/13
    Trade Feedback
    0 (0%)
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by wardrive View Post
    Indeed, see below:

    Code:
                object_manager.update()
                
                for i in range(0,object_manager.count):
                    pointer = reader.process.read_longlong(object_manager.entity_array + (0x8*i))
    
                    if pointer != 0:
    If the entity type does not match one of the specified entity types I want to capture, it simply skips the iteration and moves onto the next pointer.

    Code:
                    if pointer != 0:
                        pointer2 = reader.process.read_longlong(pointer + 0x18)
                        entity_temp = reader.process.read_bytes(pointer2 + 0x10, 1)
                        entity_type = int.from_bytes(entity_temp, byteorder='little')
    
                        if entity_type not in [5,6,7,8]:
                            continue
    My suggestion would be the simplest way to mimic wow's om either forward (current -> next) or backward like blizz

    PSEUDO:
    Code:
    while current != last, next = current + sz_object; if next.type == 7 print('player found');
    Instead of looping just do it once on that character the above and see if this idea in its simplest form shows the player.
    Last edited by Glitt; 09-05-2023 at 10:36 AM.

  17. #14
    wardrive's Avatar Active Member
    Reputation
    15
    Join Date
    Jul 2023
    Posts
    43
    Thanks G/R
    23/8
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    When my player hearths and teleports a distance that prompts a loading screen (from the barrens crossroads to the valley of trials), the object manager base pointer shifts and everything begins working as intended. Cheat engine reflects the same address that my debug output does for the object manager, so I know it isn't the object manager offset being incorrect. When the pointer changes in game, the value matches cheat engine output.

    WowClassic.exe+0x2EBFD30
    Last edited by wardrive; 09-05-2023 at 01:02 PM.

  18. #15
    aeo's Avatar Contributor
    Reputation
    126
    Join Date
    Apr 2007
    Posts
    268
    Thanks G/R
    84/62
    Trade Feedback
    7 (100%)
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Have you tried just calling EnumVisibleObjects with a callback and seeing if the problem remains?

Page 1 of 2 12 LastLast

Similar Threads

  1. [Question]Custom Game Objects
    By RedFox4 in forum World of Warcraft Emulator Servers
    Replies: 3
    Last Post: 09-12-2010, 08:25 AM
  2. [Question] Make players spawn with an item in thier bag
    By foamysquirl in forum World of Warcraft Emulator Servers
    Replies: 5
    Last Post: 03-01-2008, 05:35 PM
  3. [Question] Invisible Game objects
    By Sonic Waffle in forum World of Warcraft Emulator Servers
    Replies: 6
    Last Post: 02-18-2008, 05:04 PM
  4. Replies: 9
    Last Post: 01-28-2008, 12:35 AM
  5. A way to teleport my players to Horde Mall or to Ally Mall
    By Dajax in forum World of Warcraft Emulator Servers
    Replies: 2
    Last Post: 10-20-2007, 06:56 PM
All times are GMT -5. The time now is 02:25 PM. Powered by vBulletin® Version 4.2.3
Copyright © 2023 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2023 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search