Announcement

Collapse
No announcement yet.

[Medivia] Discover Battlelist Structure

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • [Medivia] Discover Battlelist Structure

    Finding battle list address

    1. Open CheatEngine -> Open Medivia client -> Attached. -> Login to game and go where are some creatures. May be monsters, npc's or players but depot with many players is bad place to start I think.

    2. Select value: String and in text write name of creature. If Case sensitive is checked you need to remember that must by big letter 'K' and 'M' -> King Medivus


    3. Now we need to find right address. I start from second address cuz first is located in other memory region and next 5's are closer. Right click on this address and Browse this memory region.


    4. Next step is looking changing values in memory(CE will mark in on red square). If nothing happen even if creature move/change direction you need to browse memory for next address from list. When you find right address add it to your list -> Right click and Pointer scan for this address.


    5. Make sure that your settings are equal this here.


    6. Pointer scan should find finally a few addresses. Select this with the lower offset but remember that last offsets must be [0xC, 0x20]. Add this addres into your list(double mouse clicking)


    7. Click mouse on pointerscan in your list and look in stack. Finally we got address of battle list.

    Code:
    Local $addrBattleStart = 0x545F48
    Local $offset_node = 0x0    ;==> Why 0x0 not 0x20? We will see after
    Local $offset_value = 0xC
    Local $offset_name = 0x20

    8. On picture below we can see how looks steps in CE to get next creatures.


    Std String method

    It's method to store most of string informations on Medivia client like a 'name', 'text messages' etc.
    What's an idea of this method?
    If creature name length < 16 then name is store in memory as you can see on picture in point 4.
    But if creature name length > 15 then medivia write address to creature name instead of orginal creature name.

    Code:
    ;==============================================================================================================================
    ; Function:         _MemoryReadStdString($address, $handle, [, $offset=False])
    ;
    ; Description:      Read memory for string. If str_length > 15 read pointer else read str.
    ;
    ; Parameter(s):     $address - Address in memory to read.
    ;			$handle - An array containing the Dll handle and the handle of the open
    ;                       process as returned by _MemoryOpen().
    ;			$offset - If we wanna read pointer put offset in hex value example:
    ;			$offset[2] = [0x20, 0x264]
    ;
    ; Return Value(s):  On Success - Returns string value
    ;                   On Failure - Returns empty string ''
    ;
    ; Author(s):        Ascer
    ;===============================================================================================================================
    Func _MemoryReadStdString ($address, $handle, $offset)
            
            ; read memory for address of our name and return address to this name. 
    	Local $addr_start = '0x' & Hex(_MemoryPointerRead($address, $handle, $offset)[0], 8)    ;==> example 0x8A16308
    
            ; read memory for name length, just one byte
    	Local $str_length = _MemoryRead($addr_start + 0x10, $handle, 'byte')    ;==> 0x8A16308 + 0x10 = 0x8A16318
    
            ; check if string < 16 then read name from $addr_start
    	If $str_length < 16 Then
    		Return BinaryToString(_MemoryRead($addr_start, $handle, 'char[15]'))    ;==> 'King Medivius'
    	
            ; string length is > 15 then we must read memory($addr_start) for new address
            Else
    		$str_pointer = '0x' & Hex(_MemoryRead($addr_start, $handle), 8)    ;==> example 0x8C95320
    		Return BinaryToString(_MemoryRead($str_pointer, $handle, 'char[32]'))   ;==> read memory in $str_pointer region to get true name
    	EndIf
    
            ; return empty string if nothing found
    	Return ""
    
    EndFunc
    Someone enter to my screen when i writing this tutorial so it's will good visual example for Std method.

    Code:
    Strange value 'H?' is our address to real name:
    10 17 C8 03 its value of address lets convert into address (reverse hex) -> 0x03C81710
    Color: Yellow   ;==> creature name length (0x19) = 25 in dec
    Color: Green    ;==> creature name max length (0x1F) = 31 in dec
    Finally we see creature name 'Cigano Mirabolt Explodesz'


    Geting $offset_node. Why not 0x20?

    Sometimes when we stay in game long time, example in depot where many players join and leave our battle list, offsets 0x0 will adding many times. Also Medivia client dont remove creatures from memory too fast. We have to find $offset_node who will store all creatures, not only part of them.

    Function below is a little strange but i dont found other way to get this offset. (Im sure that is some easy way but anyone cant share so...)
    In big shortcut we must increasing $offset_node starting from 0x0 and adding +0x4 until find last who draws creature name.

    Code:
    ;===============================================================================================================
    ; Function:         _Get_Node_Offset ()
    ;
    ; Description:      Get node offset to battle list reading.
    ;
    ; Parameter(s):     None
    ;
    ; Return Value(s):  On Success - Returns true offset in Hex value
    ;                   On Failure - Returns 0x0
    ;
    ; Author(s):        Ascer
    ;===============================================================================================================
    Func _Get_Node_Offset ()
    
            ; set default values for offsets
    	Local $last_node = 0x0
    	Local $offset_node = 0x0
    
            ; why 200? It means that we will incresing our $offset_node 200*0x4 (most time we will use offsets 0x44, 0xD4, 0x184, 0x304) but its good range if will more creatures on screen.
    	For $i = 0 To 200 
    
                    ; [0] - increasing offset node, [1] - $offset value, [2] - offset to creature name
    		Local $offset[3] = [$offset_node, 0xC, 0x20]
                    ; read memory for character name
    		Local $name =_MemoryReadStdString($BASE_ADDRESS + 0x545F48, $handle, $offset)
    
                    ; If length of our character name > 2 and < 32 then we save here last readable node
    		If StringLen($name) > 2 and StringLen($name) < 32 Then
    			Local $last_node = $offset_node
    		EndIf
    
                    ; increase offset_node by 0x4 to find next creature name
    		$offset_node += 0x4
    	Next
    
            ; return last node with readable character name
    	Return $last_node
    
    EndFunc
    Let's relogin in game now to reset our battle list(remove non-avaiable creatures). After that go to find last offset node manually in CE to make sure that our function works fine.

    Code:
    Local $offset_node = _Get_Node_Offset()
    ConsoleWrite('Current offset node = ' & $offset_node & @CRLF)
    
    >> Current offset node = 0x44


    Building a Get_Cratures function

    So we have a right node pointer now, go to create a function.

    Code:
    ;base addresses and battle list offsets:
    Local $BASE_ADDRESS = _MemoryModuleGetBaseAddress('Medivia_D3D.exe')
    Local $addrBattleStart = 0x545F48
    Local $offset_posx = 0xC
    Local $offset_posy = 0x10
    Local $offset_posz = 0x14
    Local $offset_id = 0x1C
    Local $offset_name = 0x20
    Local $offset_hpperc = 0x38
    Local $offset_direction = 0x3C
    
    
    Func _Get_Creatures ()
    
    	Local $offset_node = _Get_Node_Offset ()    ;==> last node offset we found it in function above
    	Local $offset[3] = [$offset_node, 0xC, $offset_name] ;==> offsets to first creature name [ 0x44, 0xC, 0x20]
    
            ; read memory for first creature name
    	Local $name = _MemoryReadStdString($BASE_ADDRESS + $addrBattleStart, $handle, $offset)
    
            ; In this loop we will increasing array with offset by 0x0 until $name of creature will equal empty string "" -> end of battle list. 
    	While StringLen($name) > 2 and StringLen($name) < 3
    
                    ; Ok here we must set start address of each creature to make easier later memory reading. Just read memory for character name
                    ; get this address and subtract [- 0x20] to get start creature address.
    		Local $addrStart = '0x' & StringRight(Hex(_MemoryPointerRead($BASE_ADDRESS + $addrBattleStart, $ah_Handle, $offset)[0]-$offset_name),8)
    
                    ; read memory for each information
    		Local $posx = _MemoryRead($addrStart+$offset_posx, $handle)
    		Local $posy = _MemoryRead($addrStart+$offset_posy, $handle)
    		Local $posz = _MemoryRead($addrStart+$offset_posz, $handle, 'byte')   ;==> only 1 byte
    		Local $id = _MemoryRead($addrStart+$offset_id, $handle)
                    Local $hpperc = _MemoryRead($addrStart+$offset_hpperc, $handle, 'byte')   ;==> only 1 byte
                    Local $dir = _MemoryRead($addrStart+$offset_direction, $handle)
    
                    ; Here we check if creature in battle list is available. What is mean? When creature died/logout/step out of our screen(x=9, y=7) then 
                    ; this creature is still in battle list but they positions x, y, z are filing with 0xFF( x = 65535, y = 65535, z = 255)
    		If $posx < 60000 and $posy < 60000 and $posz < 20 Then
    
    			ConsoleWrite('$id = ' & $id & ', $posx = ' & $posx& ', $posy = ' & $posy & ', $posz = ' & $posz &  ', $hpperc = ' & $hpperc & ', dir = ' & $dir & ', $name = ' & $name & @CRLF)
    		
                    EndIf
    
                    ; at end we must add to array next creature offset 0x0 at index nr 1. [0x44, 0xC, 0x20] + 0x0 -> [0x44, 0x0, 0xC, 0x20]
    		_ArrayInsert($offset, 1, 0x0)
    		$name =_MemoryReadStdString($BASE_ADDRESS + $addrBattleStart, $handle, $offset)   ;==> read memory for name of new creature
    	WEnd
    EndFunc
    This is visual example of function above in CheatEngine



    Let's test out our function in practice:

    Code:
    ConsoleWrite('START SEARCHING...' & CRLF)
    _Get_Creatures()
    ConsoleWrite('END SEARCHING' & CRLF)

    Thanks for read and feel free to ask!
    Ascer
    Last edited by Ascer; 31-03-2017, 05:36 AM.

  • #2
    Ascer, I can say only one sentence. Great work. I figured out before PM'ing you the battle list start address (and a little knowledge about it's structure) but now, you provide me the missing knowledge. Thank you so much

    Comment


    • #3
      amazing tutorial. Can you show us in next tutorial something like: if im on floor -1 i can see names of all creatures and players under me anyway, i waiting for any your new tut greetings

      Comment


      • #4
        Originally posted by LuisPro View Post
        amazing tutorial. Can you show us in next tutorial something like: if im on floor -1 i can see names of all creatures and players under me :
        It's pretty easy with tut above. Just select only creatures with posz different than your character.


        Originally posted by LuisPro View Post
        i waiting for any your new tut
        I've discovered Container & Items structure so next Tutorial coming soon. It's much easier than Battle list struct(maybe little masked).

        Comment


        • #5
          Originally posted by Ascer View Post
          It's pretty easy with tut above. Just select only creatures with posz different than your character.
          i mean name spy :P no idea how to search adress for it :P

          Comment


          • #6
            Awesome dude. Will try to implement this in my macro. I'll make sure to credit you for it. Thanks buddy!

            Comment


            • #7
              I just tried this in C# and it works fine but not really :P Not sure what is wrong, but I can read battle, but some are missing sometimes.
              Current offsetnode: D4
              D4 0 C 20
              Name: Gatter King x: 32911 y: 32072, z: 7
              D4 0 0 C 20
              Name: Boozer x: 32921 y: 32068, z: 5
              D4 0 0 0 C 20
              D4 0 0 0 0 C 20
              D4 0 0 0 0 0 C 20
              Name: Baob x: 32916 y: 32076, z: 4
              D4 0 0 0 0 0 0 C 20
              D4 0 0 0 0 0 0 0 C 20
              D4 0 0 0 0 0 0 0 0 C 20
              Name: Beka Chasac Man x: 32910 y: 32076, z: 6
              D4 0 0 0 0 0 0 0 0 0 C 20
              Name: Frenkie x: 32920 y: 32069, z: 7
              D4 0 0 0 0 0 0 0 0 0 0 C 20
              Name: Dove x: 32919 y: 32075, z: 7
              D4 0 0 0 0 0 0 0 0 0 0 0 C 20
              D4 0 0 0 0 0 0 0 0 0 0 0 0 C 20
              Name: Night Huntress x: 32915 y: 32069, z: 7
              D4 0 0 0 0 0 0 0 0 0 0 0 0 0 C 20
              Total in battle: 7
              ------------------------------------------
              Seems like not all people are contained in the last offset_node that the get node offset function finds.

              Also
              ; In this loop we will increasing array with offset by 0x0 until $name of creature will equal empty string "" -> end of battle list.
              While StringLen($name) > 2 and StringLen($name) < 3
              Is this a typo? name length to be > 2 and less than 3. I guess you mean > 2 & < 32?

              Still, People are missing in my battlelist. Strange.

              EDIT
              Hmm. I think it works now. Had an issue with the names longer than 15. Also got confused as it shows everyone below you as well as above on certain floors.
              Also changed the find offset node function to break when it finds the first one instead of last. I had issues if I used the last one.

              So far so good. Gonna need more testing.
              Thank you so much for this awesome infromation <3
              Last edited by Tony32; 17-07-2017, 04:46 PM. Reason: Fixed? :P

              Comment

              Working...
              X