Welcome!

Join our community of MMO enthusiasts and game developers! By registering, you'll gain access to discussions on the latest developments in MMO server files and collaborate with like-minded individuals. Join us today and unlock the potential of MMO server development!

Join Today!

3DSMAX Script - Map Viewer [Unfinished]

Joined
Aug 27, 2013
Messages
800
Reaction score
1,956
After discussing with a friend, who made this and getting hit permission, I've decided to share this unfinished 3DSMAX script to view any Cabal Online Map.

This is ONLY a VIEWER! It cannot edit maps!

What it CAN DO:
  • View Maps in all angles.
  • Zoom in/out.

What it CANNOT DO:
  • Edit Maps
  • Add objects
  • Move Objects from their locations
  • Change anything!

PROBLEMS and UNFINISHED BITS (IMPORTANT!)
  • Messed up shaders, that's why maps are not displayed as they should be.
  • Object importer doesn't work - so no need Yamachi's Scripts to launch this one.

This script might give a head-start for some sort of a viewer launcher, and, although code is far from perfect, it's still better than nothing :8: If someone wants to finish it - go ahead!
If someone would be willing to fix it / if even worth it, hopefully, it will be shared with the community, not leeched away and/or sold behind the scenes.
:junglejane:​



Instructions [a.k.a. Quick Instalation]:
  • Launch 3DS Max, run script.
  • Or, place script into %LOCALAPPDATA%\Autodesk\3dsMax\3DS_MAX_VERSION\ENU\scripts\startup
  • Usage - SELF EXPLANATORY.
  • Enjoy using script

Copyright (c) The Leviathan Team 2016 and penetrator9000

\\=\\=\\ //=//=//

Image Preview​

[URL="
MrSensei - 3DSMAX Script - Map Viewer [Unfinished] - RaGEZONE Forums



Script code in spoiler

Code:
/*
 *            _ __      _________ 
 *           | |\ \    / /__   __|
 *           | | \ \  / /   | |   
 *           | |  \ \/ /    | |   
 *           | |___\  /     | |   
 *           |______\/      |_|   
 *           
 ---------------------------------------- 
 *         MCL Importer For 3DS Max
 *  Copyright (c) The Leviathan Team 2016
 *
 */
 
global import_flag = false
global CabalMCLTools
global hmap_bin
global tmap_bin

callbacks.removeScripts id:#resetImport

function readHeader pFile =
(
    print "(|) Loading..."
    readLong pFile #unsigned                                                         -- magic key 
    readFloat pFile; readFloat pFile; readFloat pFile                            -- unkv0
    readLong pFile #unsigned                                                        -- unkui0
    readFloat pFile; readFloat pFile; readFloat pFile                            -- unkv1
    readFloat pFile; readFloat pFile; readFloat pFile; readFloat pFile    -- unkq0
    readLong pFile #unsigned                                                        -- unkui1
    readFloat pFile; readFloat pFile; readFloat pFile; readFloat pFile    -- unkq1
    readLong pFile #unsigned                                                        -- unkui2
    readLong pFile #unsigned                                                        -- unkui3
    readLong pFile #unsigned                                                        -- unkui4    
    readFloat pFile; readFloat pFile; readFloat pFile                            -- unkv2
    readLong pFile #unsigned                                                        -- unkui5    
    readLong pFile #unsigned                                                        -- unkui6    
    readLong pFile #unsigned                                                        -- unkui7    
    readLong pFile #unsigned                                                        -- unkui8    
    readLong pFile #unsigned                                                        -- unkui9    
    readLong pFile #unsigned                                                        -- unkuiA    
    readLong pFile #unsigned                                                        -- unkuiB    
    readLong pFile #unsigned                                                        -- unkuiC
    readLong pFile #unsigned                                                        -- unkuiD
    readLong pFile                                                                     -- unki0
    print "(/) Loading..."
)

function readEffects pFile =
(
    print "(-) Loading..."
    effectCount = readLong pFile #unsigned
    
    for i = 1 to effectCount do
    (
        effectTextLen = readShort pFile #unsigned    -- text len
        fseek pFile effectTextLen #seek_cur            -- text
        readFloat pFile                                            -- unkf0
        readFloat pFile                                            -- unkf1
        readLong pFile #unsigned                            -- unkui0
        readLong pFile #unsigned                            -- unkui1
    )
    
    print "(\) Loading..."
)

function readTextures pFile =
(
    print "(|) Loading..."
    textureCount = readLong pFile #unsigned
    
    if import_flag == true then
        global in_materials = #()
    
    for i = 1 to textureCount do
    (
        size = readLong pFile #unsigned
        
        if size == 0
            do continue;
        
        texName = stringstream ""
        format "texture_%.dds" (i - 1) to:texName
        aout = (pathconfig.getdir #import) + "/" + texName
        pTexFile = fopen aout "wb"

        for j = 1 to size do
        (
            byte = readByte pFile
            writeByte pTexFile byte
        )
        
        fclose pTexFile
        
        if import_flag == true then
        (
            tex = openbitmap aout
            tex_bmp = bitmaptexture bitmap:tex
            
            local new_mat = standard name:texName
            new_mat.adlock = false
            new_mat.diffusemap = tex_bmp
            new_mat.showinviewport = true
            append in_materials new_mat
        )
    )
    
    print "(/) Loading..."
)

function readTileTextures pFile =
(
    print "(-) Loading..."
        
    for i = 1 to 64 do
    (
        size = readLong pFile #unsigned
        
        texName = stringstream ""
        format "tile_texture_%.dds" (i - 1) to:texName
        aout = (pathconfig.getdir #import) + "/" + texName
        pTexFile = fopen aout "wb"

        for j = 1 to size do
        (
            byte = readByte pFile
            writeByte pTexFile byte
        )
        
        fclose pTexFile
    )

    print "(\) Loading..."    
)

function readLayer pFile first symbol = 
(
    print symbol
    face_count = readLong pFile #unsigned
    vertex_count = readLong pFile #unsigned
    
    vertex = #()
    face = #()
    uv = #()
    vcolor = #()
    
    vertex.count = vertex_count
    face.count = face_count
    uv.count = vertex_count
    vcolor.count = vertex_count
    
    for i = 1 to vertex_count do
    (
        -- position
        x = readFloat pFile;
        y = readFloat pFile;
        z = readFloat pFile;
                
        if first then
        (
            -- vertex color
            r = readByte pFile #unsigned -- r
            g = readByte pFile #unsigned -- g
            b = readByte pFile #unsigned -- b
            a = readByte pFile #unsigned -- a
            vcolor[i] = [r, g, b, a]
        )

        -- uv
        uv_x = readFloat pFile;
        uv_y = readFloat pFile;
        
        vertex[i] = [x, y, z]
        uv[i] = [uv_x, uv_y, 0]
    )

    for i = 1 to face_count do
    (
        f1 = readshort pFile 
        f2 = readshort pFile
        f3 = readshort pFile
            
        face[i] = [f1 + 1, f2 + 1, f3 + 1]
    )
    
    local sbTextureId = #()
    local sbTextureIndex = #()
    
    sbTextureIndex.count = face_count
    sbTextureId.count = face_count
    
    prevTextureId = -1
    k = 1;
    
    for i = 1 to face_count do
    (
        texId = readLong pFile -- face texture id
        if prevTextureId != texId then
        (
            sbTextureIndex[k] = i - 1
            sbTextureId[k] = texId
            prevTextureId = texId
            k += 1
        )
    )

    usedTextures = readLong pFile

    for i = 1 to usedTextures do
    (
        readLong pFile    -- used texture id
    )
    
    if import_flag == false then
    (
        mapMesh = mesh vertices:vertex faces:face tverts:uv
                    
        if vertex_count > 0 then
            buildtvfaces mapMesh
        
        for j = 1 to mapMesh.numfaces do
            setTVFace mapMesh j (getFace mapMesh j)
        
        m = mirror()
        addModifier mapMesh m
        m.mirror_axis = 0
        rotate mapMesh (angleaxis 90 [1,0,0])
    )
    else
    (
        startIndex = 1
        endIndex = 1

        if k > 2 then
            endIndex = sbTextureIndex[2];
        else
            endIndex = k
            
        for i = 1 to k - 1 do
        (
            tmpFaces = #()
            tmpFaces.count = endIndex - startIndex

            tmpI = 1
            for j = startIndex to endIndex do
            (
                tmpFaces[tmpI] = face[j]
                tmpI = tmpI + 1    
            )
            
            mapMesh = mesh vertices:vertex faces:tmpFaces tverts:uv
                    
            if vertex_count > 0 then
                buildtvfaces mapMesh
        
            for j = 1 to mapMesh.numfaces do
                setTVFace mapMesh j (getFace mapMesh j)
            
            if first then
            (
                setNumCPVVerts mapMesh mapMesh.numverts
                defaultVCFaces mapMesh
                
                for j = 1 to vertex_count do
                    setVertColor mapMesh j vcolor[j]
            )

            mapMesh.material = in_materials[sbTextureId[i]]
            
            m = mirror()
            addModifier mapMesh m
            m.mirror_axis = 0
            
            rotate mapMesh (angleaxis 90 [1,0,0])
            
            startIndex = endIndex
            
            if i + 2 >= k then
                endIndex = face_count
            else
                endIndex = sbTextureIndex[i + 2]
        )
    )
)

function readTile pFile =
(
    print "(|) Loading..."
    symbolChange = 1
    
    for i = 1 to 64 do
    (
        if symbolChange == 1 then
        (
            symbol = "(-) Loading..."
            symbolChange = 2
        )
        else if symbolChange == 2 then
        (
            symbol = "(\) Loading..."
            symbolChange = 3
        )
        else if symbolChange == 3 then
        (
            symbol = "(|) Loading..."
            symbolChange = 4
        )
        else
        (
            symbol = "(/) Loading..."
            symbolChange = 1
        )
        
        readFloat pFile; readFloat pFile; readFloat pFile    -- bound min
        readFloat pFile; readFloat pFile; readFloat pFile    -- bound max        
        has1stLayer = readLong pFile
                
        if has1stLayer != 0 then
            readLayer pFile true symbol
        
        has2ndLayer = readLong pFile
        
        if has2ndLayer != 0 then
            readLayer pFile false symbol
    )    
    
    print "(/) Loading..."
)

function resetImportValue =
(
    if CabalMCLTools != undefined then
        CabalMCLTools.imported = false
)

function export_hmap pFile =
(
    if pFile == undefined then
        return messagebox "Please select a file to export!" title:"Error"
    
    hmapFile = fopen pFile "wb"
    
    for i = 1 to 264196 do
    (
        writeByte hmapFile hmap_bin[i]
    )
    
    fclose hmapFile    
    
    messagebox "Height Map exporting process is done!" title:"Done"
)

function export_tmap pFile =
(
    if pFile == undefined then
        return messagebox "Please select a file to export!" title:"Error"
        
    tmapFile = fopen pFile "wb"
    
    for i = 1 to 262144 do
    (
        writeByte tmapFile tmap_bin[i]
    )
    
    fclose tmapFile    
    
    messagebox "Thread Map exporting process is done!" title:"Done"
)

function readText pFile tLength =
(
    local result = ""
    
    -- Read each byte, convert it to a character, and append it to our string
    for i = 1 to tLength do
    (
        next_byte = readbyte pFile
        result += bit.intaschar(next_byte)
    )
    
    -- Return the resulting string
    result
)

function readFirstData pFile =
(
    modelCount = readLong pFile #unsigned        -- model count
    
    for i = 1 to modelCount do
    (
        textLength = readShort pFile #unsigned    -- text length
        fseek pFile textLength #seek_cur            -- text
        
        -- position
        posX = readFloat pFile; posY = readFloat pFile; posZ = readFloat pFile
        
        -- rotation
        rotX = readFloat pFile; rotY = readFloat pFile; rotZ = readFloat pFile; rotW = readFloat pFile
        
        -- scale
        scaleX = readFloat pFile; scaleY = readFloat pFile; scaleZ = readFloat pFile
        
        modelId = readLong pFile #unsigned        -- model id
        readLong pFile                                     -- type
        readLong pFile #unsigned                        -- flags
        readLong pFile #unsigned                        -- npc id
        
        mybox = box length:20 width:20 height:20
        mybox.pos = [posX, posZ, posY]
        --mybox.rotation = [rotX, rotY, rotZ, rotW]
        mybox.scale = [100 * scaleX, 100 * scaleY, 100 * scaleZ]
        mybox.name = modelList[modelId - 1]
    )
)

function readSecondData pFile =
(
    modelCount = readLong pFile #unsigned        -- model count
    
    for i = 1 to modelCount do
    (    
        -- position
        posX = readFloat pFile; posY = readFloat pFile; posZ = readFloat pFile
        
        -- rotation
        rotX = readFloat pFile; rotY = readFloat pFile; rotZ = readFloat pFile; rotW = readFloat pFile
        
        -- scale
        scaleX = readFloat pFile; scaleY = readFloat pFile; scaleZ = readFloat pFile
        
        modelId = readLong pFile #unsigned        -- model id
        
        mybox = box length:20 width:20 height:20
        mybox.pos = [posX, posZ, posY]
        --mybox.rotation = [rotX, rotY, rotZ, rotW]
        mybox.scale = [100 * scaleX, 100 * scaleY, 100 * scaleZ]
        mybox.name = modelList[modelId - 1]
    )
)

function readThirdData pFile =
(
    readLong pFile #unsigned                            -- unk_count
    modelCount = readLong pFile #unsigned        -- model count
    
    for i = 1 to modelCount do
    (    
        -- position
        posX = readFloat pFile; posY = readFloat pFile; posZ = readFloat pFile
        
        -- rotation
        rotX = readFloat pFile; rotY = readFloat pFile; rotZ = readFloat pFile; rotW = readFloat pFile
        
        -- scale
        scaleX = readFloat pFile; scaleY = readFloat pFile; scaleZ = readFloat pFile
        
        modelId = readLong pFile #unsigned        -- model id
        
        mybox = box length:20 width:20 height:20
        mybox.pos = [posX, posZ, posY]
        --mybox.rotation = [rotX, rotY, rotZ, rotW]
        mybox.scale = [100 * scaleX, 100 * scaleY, 100 * scaleZ]
        mybox.name = modelList[modelId]
    )
)

function importModels pFile =
(
    global modelList = #()
    
    modelCount = readLong pFile #unsigned
    modelList.count = modelCount                            -- model count
    
    for i = 1 to modelCount do
    (
        mNameLength = readShort pFile #unsigned        -- name length
        mName = readText pFile mNameLength            -- name
        readFloat pFile; readFloat pFile; readFloat pFile    -- bound min
        readFloat pFile; readFloat pFile; readFloat pFile    -- bound max
        modelList[i] = mName;
    )
            
    readFirstData pFile                                            -- reading first data; "interactive models"
    --readSecondData pFile                                        -- reading second data
    --readThirdData pFile                                            -- reading third data
)

function import_mcl file_name =
(
    if file_name == undefined then
        return messagebox "Please select a map to import!" title:"Error"
        
    import_msg = "Import Map with materials? It might take more time to load.";
    import_msg += "(Use only if you need materials!)\n\n";
    import_msg += "Press yes to import with materials.\n";
    import_msg += "Press no to import without materials.\n\n";
    import_msg += "NOTICE: Import process might take some time, please be patient!";
        
    import_flag = queryBox import_msg title:"Map Import"
    
    import_msg = "Import Map with models? It might take more time to load.\n\n";
    import_msg += "Press yes to import with models. You will be asked to select Objects folder.\n";
    import_msg += "Press no to import without models.\n\n";
    import_msg += "NOTICE: You will need to have ebm importer in your 3DS scripts folder!";
    import_models = queryBox import_msg title:"Models Import"  
    
    if import_models  == true then
    (
        import_script = (pathconfig.getdir #userScripts) + "/import_ebm_cabal.ms" 
        exist = (getfiles import_script).count
        if exist == 0 then
        (
            import_models = false
            messagebox "EBM import script: import_ebm_cabal.ms was not found!\nSkipping models import..." title:"Error"
        )
    )
    
    mapFile = fopen file_name "rb"

    print "(/) Loading..."
    readHeader mapFile                    -- header
        
    print "(-) Loading..."
    readEffects mapFile                    -- effects
        
    print "(\) Loading..."
    readTextures mapFile                -- textures
        
    print "(|) Loading..."
    readLong mapFile #unsigned        -- unkui0
    readLong mapFile #unsigned        -- unkui1
    readLong mapFile #unsigned        -- unkui2

    print "(/) Loading..."
    -- height map
    global hmap_bin = #()
    hmap_bin.count = 264196
        
    for i = 1 to 264196 do
    (
        hmap_bin[i] = readByte mapFile
    )
        
    print "(-) Loading..."
    -- thread map
    global tmap_bin = #()
    tmap_bin.count = 262144
        
    for i = 1 to 262144 do
    (
        tmap_bin[i] = readByte mapFile
    )
        
    print "(\) Loading..."
    readTileTextures mapFile            -- tile textures
        
    print "(|) Loading..."
    readTile mapFile                        -- tile
    
    --if import_models  == true then
        --importModels mapFile
        
    fclose mapFile
            
    if CabalMCLTools != undefined then
        CabalMCLTools.imported = true
        
    print "DONE!"
    messagebox "Importing process is done!" title:"Done"
)        

rollout CabalMCLTools "Cabal MCL Tools"
(
    local imported = false
    
    group "Import:"
    (
        button btn_import_mcl "Open..." width:68 height:18 pos:[45, 20]
    )
    
    group "Export binary:"
    (
        button btn_export_hmap "Height Map" width:68 height:18 pos:[10, 65]
        button btn_export_tmap "Thread Map" width:68 height:18 pos:[85, 65]
    )
    
    group "Export list:"
    (
        button btn_export_models "Map Models" width:68 height:18 pos:[45, 110]
    )
    
    group "Export textures:"
    (
        button btn_export_tiletex "Tile Textures" width:68 height:18 pos:[45, 155]
        button btn_export_maptex "Map Textures" width:68 height:18 pos:[45, 180]
    )
    
    on btn_import_mcl pressed do
    (
        file_name = getopenfilename caption:"Select a world to import..." types:"Cabal Map File(*.mcl)|*.mcl"
        import_mcl(file_name)
    )
    
    on btn_export_hmap pressed do
    (
        if imported == true then
        (
            file_name = getsavefilename caption:"Select a file name to export..." types:"Binary(*.bin)|*.bin"
            export_hmap(file_name)
        )
        else
            messagebox "Please import map first!" title:"Height Map"
    )
    
    on btn_export_tmap pressed do
    (
        if imported == true then
        (
            file_name = getsavefilename caption:"Select a file name to export..." types:"Binary(*.bin)|*.bin"
            export_tmap(file_name)
        )
        else
            messagebox "Please import map first!" title:"Thread Map"
    )
    
    on btn_export_models pressed do
    (
        if imported == true then
        (

        )
        else
            messagebox "Please import map first!" title:"Map Models"
    )
    
    on btn_export_tiletex pressed do
    (
        if imported == true then
        (
            map_textures_msg = "Tile Textures are already exported in ";
            map_textures_msg += (pathconfig.getdir #import) 
            messagebox map_textures_msg title:"Tile Textures"
        )
        else
            messagebox "Please import map first!" title:"Tile Textures"
    )
    
    on btn_export_maptex pressed do
    (
        if imported == true then
        (
            map_textures_msg = "Map Textures are already exported in ";
            map_textures_msg += (pathconfig.getdir #import) 
            messagebox map_textures_msg title:"Map Textures"
        )
        else
            messagebox "Please import map first!" title:"Map Textures"
    )
)

createdialog CabalMCLTools
--cui.registerdialogbar CabalMCLTools style:#(#cui_dock_right, #cui_floatable) minsize:#(272, 160) maxsize:#(272, 160)
--cui.dockdialogbar CabalMCLTools #cui_dock_right

callbacks.addScript #systemPreNew" resetImportValue()" id:#resetImport
 
Last edited:
Newbie Spellweaver
Joined
Jan 3, 2015
Messages
17
Reaction score
1
I've been waiting for this. Thanks :eek:tt:
 
Back
Top