Reading Memory - Bag slots available? menu

Shout-Out

User Tag List

Results 1 to 8 of 8
  1. #1
    Tanaris4's Avatar Contributor Authenticator enabled
    Reputation
    148
    Join Date
    Oct 2008
    Posts
    646
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Reading Memory - Bag slots available?

    So, currently to determine how many bag spots are available I have to do a few things:
    1. Find the bag GUIDs from playerbase
    2. Increment the total spaces used by the GUIDs found in the backpack
    3. Loops through ALL objects that are of type item, compare the container ID to the GUIDs we found from playerbase, then increment total spaces used
    4. Find out the TOTAL bag spots possible by adding the size of the bags + 16 (for the backpack)


    This isn't uber-complicated, but it's a decent amount of memory reading just to get to one number. Does anyone do this a different way that is more efficient? (And I'm not thinking create an addon that stores the bag slots used/available next to some text I could scan for )

    Thanks :-)
    https://tanaris4.com

    Reading Memory - Bag slots available?
  2. #2
    Apoc's Avatar Angry Penguin
    Reputation
    1388
    Join Date
    Jan 2008
    Posts
    2,750
    Thanks G/R
    0/13
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Loop through your currently equipped bags.

    Loop through each slot in each bag, grabbing just the GUID of the item in that slot. If it's 0, the slot is empty.

    Pretty simple actually.

    Code:
            public int EmptySlots
            {
                get
                {
                    int freeSlots = Slots;
    
                    for (int i = 0; i < Slots; ++i)
                    {
                        if (GetItem(i).IsValid)
                        {
                            --freeSlots;
                        }
                    }
    
                    return freeSlots;
                }
            }
    Code:
    int freeSots = 0;
    for(int i = 0; i < 5; i++)
    {
    var bag = GetBag(i);
    if (bag.IsValid)
    {
    freeSlots+=bag.EmptySlots;
    }
    }
    return freeSlots;
    Excuse the shitty formatting. Wrote it in the browser.

    Edit; since I know some of you are going to go all batty about 'I CAN'T DO THAT!', you can do it out of process easily.

    The GetBagPtr vfunc (9th vfunc this patch) returns a pointer to a CGBag_C object. It's basically a WoWContainer, without all the WoWObject stuff.

    It provides the slot count, the slots, bag GUID, and whether or not the bag is 'inventory'. (Inventory meaning; the bag is 'you'. The first 16 slot bag you have.)

    Code:
            struct CGBag
            {
                public int SlotCount;
                public ulong[] Slots;
                public ulong GUID;
                public byte IsInventory;
            }
    That's the layout. The Slots array is SlotCount long (so no 'nifty' marshaling allowed. ) Whatever the GetBagPtr vfunc uses in the method body (it's different for containers, and players!!) just read the above struct from that pointer, and viola. You have all you need to know about the bag.

    There are also 2 nifty funcs you can use, GetBagAtIndex, and GetBagItem (check the info dump, not sure it'll be any use to you since you're on a Mac, but you can trace it back from Lua calls fairly easily.). They'll give you the addrs of your available CGBag_C instances.
    Last edited by Apoc; 01-13-2010 at 01:58 PM. Reason: GetBagPtr is the 9th vfunc!

  3. #3
    Tanaris4's Avatar Contributor Authenticator enabled
    Reputation
    148
    Join Date
    Oct 2008
    Posts
    646
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks Apoc, that will save a shit ton of reads I'm doing, I'll start searching for those funcs

    Also, I may PM you a question on maintaining a mac PDB file throughout patches. I'd like to do it myself, I can find functions given enough time, but I obviously lose them (unless I manually find them the same way). I'm hoping there is potentially something in elite, or some script I'm missing that allows me to do a type of diff and easily update through functions.
    https://tanaris4.com

  4. #4
    Apoc's Avatar Angry Penguin
    Reputation
    1388
    Join Date
    Jan 2008
    Posts
    2,750
    Thanks G/R
    0/13
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Nope, nothing in elite. I've suggested a few times to use PatchDiff2 to do the diffing, then just 'parse' the dump into something you can run through an IDC script to automatically rename things.

  5. #5
    bolototo's Avatar Banned
    Reputation
    0
    Join Date
    May 2009
    Posts
    30
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    look this
    Code:
    include <ButtonConstants.au3>
    #include <GUIConstantsEx.au3>
    #include <WindowsConstants.au3>
    #include <NomadMemory.au3>
    
    
    $Form1 = GUICreate("Form1", 172, 109, 308, 197)
    $Go = GUICtrlCreateButton("Go", 40, 40, 75, 25, $WS_GROUP)
    GUISetState(@SW_SHOW)
    
    Global $StaticPlayer=0x00A7B434,$ClienConec=0xC923C0 , $Pbdec1=0x0c , $Pbdec2=0x24 ,$PlayerBase  
    Global $ObjManag=0x2e04,$firstObject = 0xAC,$nextObject = 0x3C ,$TypeObj = 0x14 ,$WowPid,$WowProcess
    Global $SLOT_1=0x5c8,$guidbag=0xC3BD70
    
    SetPrivilege("SeDebugPrivilege", 1)
    
    $WowPid=ProcessExists("wow.exe")
    
    	If $WowPid=0 Then
    		MsgBox(0, "Infos", "World of warcraft n est pas lancer")
    		exit
    	EndIf
    
    $WowProcess = _MEMORYOPEN($WowPid)
    
    
    
    While 1
    	$nMsg = GUIGetMsg()
    	Switch $nMsg
    		Case $GUI_EVENT_CLOSE
    			Exit
    		Case $Go
    			InfosSacs()
    	EndSwitch
    WEnd
    
    Func InfosSacs()
    	Local $AdrSo1,$AdrSo2,$Type,$Firstob,$Curobj
    	Local  $FreeSac0=0,$FreeSac1=0,$FreeSac2=0,$FreeSac3=0,$FreeSac4=0,$FreeSac5=0
    
    	$AdrPb1 = _MEMORYREAD($StaticPlayer,$WowProcess,"dword")
    	$AdrPb2 = _MEMORYREAD($AdrPb1+$Pbdec1,$WowProcess,"dword")
    	$PlayerBase = _MEMORYREAD($AdrPb2+$Pbdec2,$WowProcess,"dword")
    
    	$AdrSo1=_MEMORYREAD($ClienConec,$WowProcess,"dword")
    	$AdrSo2=_MEMORYREAD($AdrSo1+$ObjManag,$WowProcess,"dword")
    	$Firstob=_MEMORYREAD($AdrSo2+$firstObject,$WowProcess,"dword")
    	$Curobj=$Firstob
    	$Type=_MEMORYREAD($Curobj+$TypeObj,$WowProcess,"dword")
    
    
    
    	$TotalPlace=16
    	$firstSlot01=_MEMORYREAD($PlayerBase+0x8,$WowProcess,"dword")
    	$firstSlot=$firstSlot01+0x5c8
    
    	$nbsac=1
    	$baguid1=_MEMORYREAD($guidbag,$WowProcess,"uint64")
    	If $baguid1>0 Then $nbsac +=1
    	$baguid2=_MEMORYREAD($guidbag+8,$WowProcess,"uint64")
    	If $baguid2>0 Then $nbsac +=1
    	$baguid3=_MEMORYREAD($guidbag+16,$WowProcess,"uint64")
    	If $baguid3>0 Then $nbsac +=1
    	$baguid4=_MEMORYREAD($guidbag+24,$WowProcess,"uint64")
    	If $baguid4>0 Then $nbsac +=1
    
    	$FreeSac0=0
    		For $xx=0 To 15
    				$calfree=_MEMORYREAD($firstSlot+($xx*8),$WowProcess,"uint64")
    					If $calfree=0 Then $FreeSac0 +=1
    		Next
    
    	While $Type < 8
    
    
    			If $Type=2 Then
    
    					$descript=_MEMORYREAD($Curobj+8,$WowProcess,"dword")
    					$guid=_MEMORYREAD($descript,$WowProcess,"int64")
    					$Datasac=$descript+0x20
    					$taillesac=_MEMORYREAD($Datasac+0xe0,$WowProcess,"dword")
    					$firstSlot=$Datasac+0xE8
    
    					Switch $guid
    
    						Case $baguid1
    							$FreeSac1=0
    							For $xx=0 To $taillesac-1
    								$calfree=_MEMORYREAD($firstSlot+($xx*8),$WowProcess,"uint64")
    								If $calfree=0 Then $FreeSac1 +=1
    							Next
    							$TotalPlace +=$taillesac
    
    						Case $baguid2
    							$FreeSac2=0
    							For $xx=0 To $taillesac-1
    								$calfree=_MEMORYREAD($firstSlot+($xx*8),$WowProcess,"uint64")
    								If $calfree=0 Then $FreeSac2 +=1
    							Next
    							$TotalPlace +=$taillesac
    
    						Case $baguid3
    							$FreeSac3=0
    							For $xx=0 To $taillesac-1
    								$calfree=_MEMORYREAD($firstSlot+($xx*8),$WowProcess,"uint64")
    								If $calfree=0 Then $FreeSac3 +=1
    							Next
    							$TotalPlace +=$taillesac
    
    						Case $baguid4
    							$FreeSac4=0
    							For $xx=0 To $taillesac-1
    								$calfree=_MEMORYREAD($firstSlot+($xx*8),$WowProcess,"uint64")
    								If $calfree=0 Then $FreeSac4 +=1
    							Next
    							$TotalPlace +=$taillesac
    
    					EndSwitch
    
    			EndIf
    			$Curobj=_MEMORYREAD($Curobj+$nextObject,$WowProcess,"dword")
    			$Type=_MEMORYREAD($Curobj+$TypeObj,$WowProcess,"dword")
    
    	WEnd
    	MsgBox(0,"Infos sac","J ai "&$nbsac&" sac(s) et "& $FreeSac0+$FreeSac1+$FreeSac2+$FreeSac3+$FreeSac4 & " places de dispo sur " & $TotalPlace)
    
    EndFunc

  6. #6
    Mr.Sergey's Avatar Contributor
    Reputation
    117
    Join Date
    Apr 2009
    Posts
    201
    Thanks G/R
    6/23
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I think that everything is much easier. This game has a function "Filled bags" - displays the number of free slots. In memory this value stored in string form. Thus to determine the number of free slots is enough to read a string value and convert it to int. The only thing that I could not yet determine the starting point and shifts to determine the address location of the text with a value of empty cells.

    If anyone knows please write.

  7. #7
    TOM_RUS's Avatar Legendary
    Reputation
    914
    Join Date
    May 2008
    Posts
    699
    Thanks G/R
    0/52
    Trade Feedback
    0 (0%)
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)
    That's how client doing that with lua:

    File: FrameXML\MainMenuBarBagButtons.lua
    Code:
    local BACKPACK_FREESLOTS_FORMAT = "(%s)";
    BACKPACK_CONTAINER = 0;
    NUM_BAG_SLOTS = 4;
    
    function MainMenuBarBackpackButton_UpdateFreeSlots()
    	local totalFree, freeSlots, bagFamily = 0;
    	for i = BACKPACK_CONTAINER, NUM_BAG_SLOTS do
    		freeSlots, bagFamily = GetContainerNumFreeSlots(i);
    		if ( bagFamily == 0 ) then
    			totalFree = totalFree + freeSlots;
    		end
    	end
    	
    	if ( totalFree == 3) then
    		TriggerTutorial(59);
    	end
    	if ( totalFree == 0) then
    		TriggerTutorial(58);
    	end
    
    	MainMenuBarBackpackButton.freeSlots = totalFree;
    	
    	MainMenuBarBackpackButtonCount:SetText(string.format(BACKPACK_FREESLOTS_FORMAT, totalFree));
    end
    May be you can just call MainMenuBarBackpackButtonCount:GetText() and convert it to int or whatever you want...
    Last edited by TOM_RUS; 04-10-2010 at 05:32 AM.

  8. #8
    deCutter's Avatar Member
    Reputation
    5
    Join Date
    Apr 2009
    Posts
    17
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Well, for those who are still out of process and want know free slots in bags - here you go. C#, 3.3.3a working code.
    Code:
    public class LocalPlayer : Player
    {
        ...
        public ulong GetBackpackItemGUID(uint slot)
        {
            if (slot > 15)
                return 0;
            return Read<ulong>(DescriptorFields + (uint)WowPlayerFields.PLAYER_FIELD_PACK_SLOT_1 * 4 + 8 * slot);
        }
    
        public uint bagsFreeSlots
        {
            get { 
                uint result = 0;
                Container bag = null;
                for (uint i = 0; i < 16; i++)
                    if (GetBackpackItemGUID(i) == 0)
                        result++;
                for (uint i = 0; i < 4; i++)
                {
                    ulong bagGuid = 0;
                    bagGuid = Read<ulong>(Offsets.BagFirstGUID + i * 8);
                    if (bagGuid == 0)
                        continue;
                    bag = new Container(objectManager.GetBaseAdressByGuid(bagGuid));
                    for (uint k = 0; k < bag.numberOfSlots; k++)
                        if (bag.GetItemBySlot(k) == 0)
                            result++;
                }
                return result;
            }
        }
    }
    CONTAINER_FIELD_NUM_SLOT, CONTAINER_FIELD_SLOT_1 doesn`t work for me, so here is my Container class members you want. Sorry for hardcoded offsets - that`s still a draft copy of my project, but all the posted code working.
    Code:
    public class Container : GenericWowObject
    {
        ...
        public uint numberOfSlots {
            get { return Read<uint>(BaseAddress + 0x760); }
        }
    
        public ulong GetItemBySlot(uint slot)
        {
            return Read<ulong>(Read<uint>(BaseAddress + 0x3E0) + 8 + 8 * slot);
        }
    }
    Code:
    public static uint BagFirstGUID = 0xC542A8;

Similar Threads

  1. Reading players inventory / available bag slots left
    By Envoke in forum WoW Memory Editing
    Replies: 7
    Last Post: 05-26-2012, 05:14 PM
  2. [Help]Reading bag slots used/remaining slots, gold
    By weber7655 in forum WoW Memory Editing
    Replies: 0
    Last Post: 09-21-2009, 06:09 PM
  3. Witch util are you using to read memory ?
    By guillaume76290 in forum WoW Memory Editing
    Replies: 3
    Last Post: 07-19-2009, 07:52 PM
  4. Read Memory Return 0
    By marko002 in forum WoW Memory Editing
    Replies: 3
    Last Post: 12-12-2008, 09:13 PM
  5. [c++] problem with reading memory
    By Lucani in forum WoW Memory Editing
    Replies: 3
    Last Post: 05-08-2008, 03:41 AM
All times are GMT -5. The time now is 10:32 AM. Powered by vBulletin® Version 4.2.3
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Google Authenticator verification provided by Two-Factor Authentication (Free) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search