Ingame WMO Management menu

Shout-Out

User Tag List

Results 1 to 6 of 6
  1. #1
    UnknOwned's Avatar Legendary
    Reputation
    713
    Join Date
    Nov 2006
    Posts
    583
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)

    Ingame WMO Management

    Ingame WMO Management.

    Updated, not elite anymore.

    One could say that it is easier to manage WMO's directly from the MPQ files, and I would agree to a certain extend. However you can also easily manage the WMO's currently loaded into the memory and still maintaining the structure that is so well documented at the WoW Wiki(s)

    In the regard of ingame WMO editing there are serval things you need to understand. When a WMO is loaded serval data sections are loaded into other sections of the memory where they are handeld seperately from the WMO file itself. This means that some parts of the strucutre are present you will see no effect changing these. Generally speaking the Position and Flag related data is stored in a seperate structure.
    The mesh is loaded into the 3D buffer so you usually need to put the model "out of sight and back in" if you want to edit the geometry of the model ingame.

    The M-WMO Structure

    I know my documentation of the M-WMO structure is limited but since i have not played around with WMO's quite often i havent taken the time to discover more than just the basic flags, position and render offset.

    Hence: http://www.madx.dk/wowdev/wiki/index.php?title=M-WMO


    The Main WMO Structure


    But lets talk about the main WMO structure.
    WMO's are loaded into wow.exe's memory space as a whole file with a few execptions, some of the headers are stripped and used for the general memory indexing of all the WMO files.
    But there is no need to worry. As WoW will put all the models up in a lovely structure, easy to manage.

    -The Index Structure


    I have not yet reversed all parts of the index strucutre but i guess if you really need it you can easily guess the rest.
    There is a static pointer leading to the first object in the list. And like all other lists, a pointer to the next and previous object.


    0x0 = Linked To
    0x8 = Linked To
    0x14 = Link To Next Object
    0x1C = Text (Wmo file + full path)
    0x128 = Link to MOGN (names) chunk
    0x130 = Link to the MOGI chunk
    0x1C0 = Link to the Actual WMO


    Around 0x128 there are links to all the chunks as documented at WMO - WoW.Dev Wiki and they are all in correct order (update, Wrong.. they are not all in correct order, 2 of them are misplaced). So as you may have guessed 0x134 should link to the MOSB chunk.



    Now here is a sample written in AutoIT.
    Its written for version 3.1.3

    It will spit out All models loaded, their file path, the number of sub wmos, index of all sub wmo's and sub wmo names in the console.
    The code is made so that it is easy to extend it with any data from the WMO structure (was to lazy to add it all).
    The code is super easy to keep up to date every time a new version of wow is released as you only need to change 1 offset (0x010E9F1


    Code:
    ;;================================================================================
    ;;INCLUDE DEFINITION
    ;;================================================================================
    #include <NomadMemory.au3>
    
    $detailMOGI = 0 ;Output Flag Data
    $detailMODN = 1 ;Output M2 file names
    
    dim $WMOsetname_M2[1]
    ;;================================================================================
    ;;PRE PREPERATION
    ;;================================================================================
    SetPrivilege("SeDebugPrivilege", 1)
    $list = ProcessList("wow.exe")
    if $list[0][0] = 0 Then
    MsgBox(0,0,"Error 01")
    exit
    EndIf
    $wow = _memoryopen($list[1][1])
    if FileExists("WMO_Output.txt") then FileDelete("WMO_Output.txt")
    WMOINDEX()
    ;;================================================================================
    ;;WMO Indexing
    ;;================================================================================
    Func WMOINDEX() 
        WriteOutput("---INGAME WMO INDEXER By MALU05---" & @CRLF)
        $mainWMOindex = _MemoryRead(0x010E9F18, $wow, 'ptr')
        WriteOutput(@crlf)
        for $i = 0 to 30 step +1
            if $mainWMOindex <> 0x00000000 Then
        $_WSMainOffs = $mainWMOindex
        $_WSName = _MemoryRead($mainWMOindex + 0x1C, $wow, 'char[700]')
        ;find number of names
        $_WSLinkToWmoMOHD = _MemoryRead($mainWMOindex + 0x120, $wow, 'ptr')
        $_WSLinkToWmoMOTX = _MemoryRead($mainWMOindex + 0x120, $wow, 'ptr') ;!!this one is wrong...
        $_WSLinkToWmoMOMT = _MemoryRead($mainWMOindex + 0x124, $wow, 'ptr')
        $_WSLinkToMOGN = _MemoryRead($mainWMOindex + 0x128, $wow, 'ptr') 
        $_WSLinkToWmoMOSB = _MemoryRead($mainWMOindex + 0x12C, $wow, 'ptr') ;lol? 
        $_WSLinkToWmoMOGI = _MemoryRead($mainWMOindex + 0x130, $wow, 'ptr') ;lol?
        $_WSLinkToWmoMOPV = _MemoryRead($mainWMOindex + 0x134, $wow, 'ptr')
        $_WSLinkToWmoMOPT = _MemoryRead($mainWMOindex + 0x138, $wow, 'ptr')
        $_WSLinkToWmoMOPR = _MemoryRead($mainWMOindex + 0x13C, $wow, 'ptr')
        $_WSLinkToWmoMOVV = _MemoryRead($mainWMOindex + 0x140, $wow, 'ptr')
        $_WSLinkToWmoMOVB = _MemoryRead($mainWMOindex + 0x144, $wow, 'ptr')
        $_WSLinkToWmoMOLT = _MemoryRead($mainWMOindex + 0x148, $wow, 'ptr')
        $_WSLinkToWmoMODS = _MemoryRead($mainWMOindex + 0x14C, $wow, 'ptr')
        $_WSLinkToWmoMODN = _MemoryRead($mainWMOindex + 0x150, $wow, 'ptr')
        $_WSLinkToWmoMODD = _MemoryRead($mainWMOindex + 0x154, $wow, 'ptr')
        $_WSLinkToWmoMFOG = _MemoryRead($mainWMOindex + 0x158, $wow, 'ptr')
        $_WSLinkToWmoMCVP = _MemoryRead($mainWMOindex + 0x15C, $wow, 'ptr')
        $_WSLinkToWmo = _MemoryRead($mainWMOindex + 0x1C8, $wow, 'ptr')
        $_WSNoOfNames = _MemoryRead($_WSLinkToWmo + 0x18, $wow, 'int')
        ;find each subgroup
        $WMOm2setname = _MemoryRead($_WSLinkToWmoMODS + 0x0, $wow, 'char[20]')
        $WMOm2setindex = _MemoryRead($_WSLinkToWmoMODS + 0x14, $wow, 'int')
        $WMOm2setnr = _MemoryRead($_WSLinkToWmoMODS + 0x18, $wow, 'int')    
        $WMOm2Nnr = _MemoryRead($_WSLinkToWmoMOHD + 0x10, $wow, 'int')
        ;MsgBox(0,0,$_WSLinkToWmoMOHD)
            WriteOutput("#######################################################################################################" &@crlf)
            WriteOutput("Loading WMO Nr. " & $i & @crlf)
            WriteOutput("Located at: " & $mainWMOindex & @crlf)
            WriteOutput("FileName: " & $_WSName & @crlf)
            WriteOutput("Number Of SUB WMO's: " & $_WSNoOfNames &@crlf)
            WriteOutput("Number of Models: " & $WMOm2Nnr &@crlf)
            WriteOutput("Model Set Name: " & $WMOm2setname &@crlf)
            WriteOutput("Number of set models: "  & $WMOm2setnr &@crlf) ;Flags from MOGI
            WriteOutput("-------------------------------------------------------------------------------------------------------" &@crlf)
            
    
    
    ;//==================================================
    ;// Look through the MODN list and index filenames.
    ;//==================================================
            redim $WMOsetname_M2[$WMOm2Nnr+1]
            writeoutput("________________________________________________________________________________________________________" &@crlf)
            writeoutput("List of filenames for M2 models that appear in this WMO." &@crlf)
            writeoutput(@crlf)
            for $i2 = 1 to $WMOm2Nnr step + 1
                $plaus = 1
                $WMOsetname = _MemoryRead($_WSLinkToWmoMODN + 0x0, $wow, 'char[700]')
                if $WMOsetname = "" or $WMOsetname = " "Then
                    $WMOsetname = _MemoryRead($_WSLinkToWmoMODN + 0x1, $wow, 'char[700]')
                    if $WMOsetname = "" or $WMOsetname = " "Then
                        $WMOsetname = _MemoryRead($_WSLinkToWmoMODN + 0x2, $wow, 'char[700]')
                        $plaus = 2
                        if $WMOsetname = "" or $WMOsetname = " "Then
                            $WMOsetname = _MemoryRead($_WSLinkToWmoMODN + 0x3, $wow, 'char[700]')
                            $plaus = 3
                            if $WMOsetname = "" or $WMOsetname = " "Then
                                $WMOsetname = _MemoryRead($_WSLinkToWmoMODN + 0x4, $wow, 'char[700]')
                                $plaus = 4
                            EndIf
                        EndIf
                    EndIf
                EndIf
                
            $WMOsetname_M2[$i2] = StringReplace($WMOsetname,"MDX","M2")    
            if $detailMODN = 1 Then writeoutput($_WSLinkToWmoMODN & @TAB & $WMOsetname_M2[$i2]  &@crlf)
            $_WSLinkToWmoMODN = $_WSLinkToWmoMODN + stringlen($WMOsetname) +$plaus
        Next
        writeoutput(@crlf &@crlf)
    
    
    ;//==================================================
    ;// Look through the MOGN list and index filenames.
    ;//==================================================
            writeoutput("________________________________________________________________________________________________________" &@crlf)
            writeoutput("Data for SUB WMO's." &@crlf)
            writeoutput(@crlf)
            for $i2 = 1 to $_WSNoOfNames step + 1
                $flag = _MemoryRead($_WSLinkToWmoMOGI, $wow, 'int')
                
                $valueFlags = _MemoryRead($_WSLinkToWmoMOGI, $wow, 'ushort')
                $valueFlagName = _MemoryRead($_WSLinkToWmo, $wow, 'int')
                
                $plaus = 1
                $WMOeditorname = _MemoryRead($_WSLinkToMOGN + 0x0, $wow, 'char[700]')
                if $WMOeditorname = "" or $WMOeditorname = " "Then
                    $WMOeditorname = _MemoryRead($_WSLinkToMOGN + 0x1, $wow, 'char[700]')
                    if $WMOeditorname = "" or $WMOeditorname = " "Then
                        $WMOeditorname = _MemoryRead($_WSLinkToMOGN + 0x2, $wow, 'char[700]')
                        $plaus = 2
                        if $WMOeditorname = "" or $WMOeditorname = " "Then
                            $WMOeditorname = _MemoryRead($_WSLinkToMOGN + 0x3, $wow, 'char[700]')
                        EndIf
                    EndIf
                EndIf
                $_WSLinkToMOGN = $_WSLinkToMOGN + stringlen($WMOeditorname) +$plaus
                
                
                
                ;MODS
                
    
                ;//Announce Data
                WriteOutput("SubWMO Located at: " & $_WSLinkToWmoMOGI & " " & @tab & " IndexName: " &$WMOeditorname &@crlf)
                    if $detailMOGI = 1 Then WriteOutput(@TAB & "*Flags: " & " " & @tab & $valueFlags &@crlf) ;Flags from MOGI
                    
                $_WSLinkToWmoMOGI = $_WSLinkToWmoMOGI + 0x20
            Next
            WriteOutput("=======================================================================================================" &@crlf)
            WriteOutput(@crlf)
        
        $mainWMOindex =    _MemoryRead($mainWMOindex + 0x14, $wow, 'ptr')
    Else
    EndIf
    Next
        
    EndFunc   ;==>Action_RenderOPT
    
    func WriteOutput($_input)
        ConsoleWrite($_input)
        FileWriteLine("WMO_Output.txt",$_input)
        
    EndFunc



    I ran this in stormwind and got this data:

    pastebin - collaborative debugging tool





    End of story...
    Last edited by UnknOwned; 07-22-2009 at 11:37 AM.

    Ingame WMO Management
  2. #2
    barthen's Avatar Contributor Authenticator enabled
    Reputation
    94
    Join Date
    Apr 2007
    Posts
    112
    Thanks G/R
    4/4
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks for sharing. Quite instructive

  3. #3
    Sel3n's Avatar Member
    Reputation
    10
    Join Date
    Jul 2009
    Posts
    115
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Very interresting, thanks!

  4. #4
    zenteoxero's Avatar Member
    Reputation
    1
    Join Date
    Dec 2008
    Posts
    8
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thank you very much for sharing tis information to us
    This is perfect for my pather, by putting this info into a
    octree and run a A* trough it!

    Rep+

  5. #5
    schlumpf's Avatar Retired Noggit Developer

    Reputation
    755
    Join Date
    Nov 2006
    Posts
    2,759
    Thanks G/R
    0/3
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Code:
    struct WMO
    {
    
    /* 0000001C */ char[256] Filename
    
    /* 00000120 */ void* MOHD
    /* 00000124 */ void* MOTX
    /* 00000128 */ void* MOGN
    /* 0000012C */ void* MOSB
    /* 00000130 */ void* MOGI
    /* 00000134 */ void* MOPV
    /* 00000138 */ void* MOPT
    /* 0000013C */ void* MOPR
    /* 00000140 */ void* MOVV
    /* 00000144 */ void* MOVB
    /* 00000148 */ void* MOLT
    /* 0000014C */ void* MODS
    /* 00000150 */ void* MODN
    /* 00000154 */ void* MODD
    /* 00000158 */ void* MFOG
    /* 0000015C */ void* MCVP
    /* 00000160 */ int MOTX_size
    /* 00000164 */ int MOGN_size
    /* 00000168 */ int MOGI_entries
    /* 0000016C */ int MOPV_entries
    /* 00000170 */ int MOPT_entries
    /* 00000174 */ int MOPR_entries
    /* 00000178 */ int MOVV_entries
    /* 0000017C */ int MOVB_entries
    /* 00000180 */ int MOLT_entries
    /* 00000184 */ int MODS_entries
    /* 00000188 */ int MODN_size
    /* 0000018C */ int MODD_entries
    /* 00000190 */ int MFOG_entries
    /* 00000194 */ int MCVP_entries
    /* 00000198 */ color Header_color
    
    /* 000001A0 */ Vec3f boundingbox_1
    /* 000001AC */ Vec3f boundingbox_2
    
    /* 000001C0 */ void* FullFile
    /* 000001C4 */ int FileSize
    
    /* 000001CC */ float float_1CC
    /* 000001D0 */ void* AsyncObject
    /* 000001D4 */ int AsyncObject_isfinished
    /* 000001D8 */ void* MOMT
    /* 000001DC */ int MOMT_entries
    
    /* 000001F0 */ int nGroupWMOs
    /* 000001F4 */ GroupWMO[] GroupWMOs
    /* 000001F8 */
    }
    
    struct GroupWMO
    {
    
    /* 00000030 */ int header_flags
    /* 00000034 */ Vec3f boundingbox_1
    /* 00000040 */ Vec3f boundingbox_2
    /* 0000004C */ int header_indexintoMOPR
    /* 00000050 */ int header_MOPR_itemsused
    /* 00000054 */ int header_fogs
    /* 00000058 */ short header_batches_a
    /* 0000005A */ short header_batches_b
    /* 0000005C */ short header_batches_c
    
    /* 000000D4 */ byte field_D4
    
    /* 000000DC */ void* MOPY
    /* 000000E0 */ void* MOVI
    /* 000000E4 */ void* UnknownChunk
    /* 000000E8 */ void* MOVT
    /* 000000EC */ void* MONR
    /* 000000F0 */ void* MOTV
    /* 000000F4 */ void* MOBA
    /* 000000F8 */ void* UnknownChunk2
    /* 000000FC */ void* MOLR
    /* 00000100 */ void* MODR
    /* 00000104 */ void* VerticesData
    /* 00000108 */ void* VerticesIndexData
    /* 0000010C */ void* MOCV
    /* 00000114 */ int Water_xverts
    /* 00000118 */ int Water_yverts
    /* 0000011C */ int Water_xtiles
    /* 00000120 */ int Water_ytiles
    /* 00000124 */ Vec3f Water_float_base
    /* 00000130 */ short Water_materialId
    /* 00000134 */ int Water_vertices
    /* 00000138 */ int Water_field_138
    /* 0000013C */ int Water_field_13C
    /* 00000140 */ int Water_field_140
    /* 00000144 */ int Water_Something
    
    /* 00000150 */ int MOPY_entries
    /* 00000154 */ int MOVI_entries
    /* 00000158 */ int UnknownChunk_entries
    /* 0000015C */ int MOVT_entries
    /* 00000160 */ int MONR_entries
    /* 00000164 */ int MOTV_entries
    /* 00000168 */ int MOBA_entries
    /* 0000016C */ int MOLR_entries
    /* 00000170 */ int MODR_entries
    /* 00000174 */ int MOCV_entries
    /* 00000178 */ int WMOGroupID
    /* 0000017C */ void* File
    /* 00000180 */ int FileSize
    /* 00000184 */ void* SOMESUBCLASS
    /* 0000018C */ void* AsyncObject
    /* 00000190 */ byte field_190
    
    /* 0000019C */ 
    }

  6. #6
    karliky's Avatar Contributor Authenticator enabled
    Reputation
    112
    Join Date
    Jun 2007
    Posts
    69
    Thanks G/R
    6/27
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    could you update these offsets for 3.2??

Similar Threads

  1. Malu05's Terrain Management UDF (For ingame Terrain Editing)
    By UnknOwned in forum WoW Memory Editing
    Replies: 37
    Last Post: 03-10-2014, 10:38 PM
  2. [APP] - Malu05's Ingame Object Manager.
    By UnknOwned in forum WoW ME Tools & Guides
    Replies: 16
    Last Post: 05-30-2009, 01:42 PM
  3. [Question]WMO's Not Visible Ingame
    By gregzoid2 in forum WoW ME Questions and Requests
    Replies: 4
    Last Post: 08-28-2008, 12:04 PM
  4. [Question] .WMO's added in Noggit dont appear ingame
    By MooseBoi in forum WoW ME Questions and Requests
    Replies: 3
    Last Post: 05-14-2008, 02:03 AM
All times are GMT -5. The time now is 07:14 PM. 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