Moderator
Staff member
Moderator
- 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.
What it CAN DO:
What it CANNOT DO:
PROBLEMS and UNFINISHED BITS (IMPORTANT!)
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!
Instructions [a.k.a. Quick Instalation]:
Script code in spoiler
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:
: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
\\=\\=\\
You must be registered to see links
//=//=//Image Preview
[URL="
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: