魔兽3地图文件解析(inside&w3m&)
译者原帖:
前面翻译了一篇关于MPQ的文章,也许是能看懂的人太少,也许是文章已经被翻译过了,
关注的人很少,心里有种淡淡的失落感。好在一位同学的提醒下,决定去翻译这篇文章。上次的翻译太急功近利,仅仅熬夜两晚就完成了,语句上没有太多的推敲,造成阅读上有许多障碍,这次的文章比较长,所以打算慢慢打磨推敲一下,也许翻译速度上会慢点,有兴趣的同学们就稍微等待一会吧。
如有转贴,请注明本网站:
本文档包括了所有的WAR3地图文件(*.W3M和*.W3X)的详细说明。不过并没有暴雪的任何官方帮助说明,也不涉及WAR3引擎的"逆向工程"。
这里所介绍的文件版本是WAR3的最初版本,请注意您真在查看和修改的文件版本。
最后,使用这个文件需要承担一定风险,如果您改动了文件遭成任何后果,我不负任何责任。
1.1 必要预装
您需要***好WAR3,在"C:\Program
Files\Warcraft
III"。我们将在这里谈论的是WAR3文件的最初版本,所以可以基于一切您使用的版本文件格式。您必须意识到在不同版本文件中是有所差异的,不过只要是***了完整的魔兽争霸3,那么您应该会看到这些文件的(当然还有一些其他的文件,而且我会用为例子):
在"C:\Program Files\Warcraft III":
和在"C:\Program Files\Warcraft III\Maps":
&(4)Lost Temple.w3m
当然还有其他的W3M文件。
"W3M"地图文件可以用任何支持WAR3的MPQ编辑器,那么我建议您使用(WinMPQ
(ShadowFlare));
您也可以使用MPQview, 不过会麻烦些。
最后,您还需要一个十六进制编辑器,我推荐的是hexworkshop.
1.2 WAR3文件
1.2.1)关于MPQ文件
MPQ文件就像是"RAR"或"ZIP"文件,包含了被压缩文件的目录结构。
在这里并不详细说明,具体的说明请看:
1.2.2)WAR3文件结构
当查找一个文件时,WAR3会最先在“真正的”目录中查找(就像网页浏览器的一样)。
假如您设置一个特殊的注册表键:
路径:HKEY_CURRENT_USER\Software\Blizzard Entertainment\Warcraft
键名称:"Allow Local Files"
键类型: dword
如果注册表键并没有设置,或者文件没有在目录中找到,那么会继续在您的地图文件中(W3M)中查找,然后是在最新的MPQ补丁(WAR3PATCH.MPQ)中查找,最后才是主要MPQ(WAR3.MPQ).
这就以为着您不需要对官方MPQs变址(不要更改您的WAR3.MPQ地址),您只需要使用
与"C:\Program Files\Warcraft III"相同的 目录/文件结构
。然后添加*.W3M文件和其他大部分文件,不过不是全部。
Units\unitUI.slk
Units\UnitMetadata.slk
Units\HumanUnitFunc.txt
Units\HumanUnitStrings.txt
Units\HumanAbilityFunc.txt
Units\HumanAbilityStrings.txt
Units\HumanUpgradeFunc.txt
Units\HumanUpgradeStrings.txt
Units\Abilitata.slk
Units\MiscData.txt
当您真的需要去改变文件,让文件不在地图装载前被装载
或者根本不被装载。
我的建议是先备份您的
"war3patch.mpq",然后创建个新文件,把原来的war3patch.mpq
和您修改后的文件添加到您刚创建的新"war3patch.mpq"。
请不要忘了备份您原本的war3patch.mpq,当您与别人对战时遇到版本冲突或者需要升级WAR3版本的时候,请还原备份的文件。
例如:
您有个叫"UI\MiscData.txt"
的文件同时存在于"War3Patch.mpq"和"War3.mpq"中。
魔兽程序默认使用在"War3Patch.mpq"中的文件。如果您要修改它,只需要在"C:\Program
Files\Warcraft
III"中创建一个"UI"目录,然后提取"War3Patch.mpq"中的"MiscData.txt"文件并放入上面的目录中(即"C:\Program
Files\Warcraft III\UI\MiscData.txt")。
注册表键就用上面的路径来修改。
现在,当您再次运行魔兽3的时候,就会用新的文件代替旧的文件了。
注意:
在某些情况下,假如您与别人对战,那么所有人都需要有同样有您修改过的文件,否
则会出现像"netsyns eror"之类的错误。
某一些文件需要一种“特殊”的格式,假如您修改了它们,您需要“伪造”这种格式
,而且并不是什么时候都有效。假如无效,WAR3会试图找到一个“标准文件”进行代
在WAR3.MPQ和WAR3PATCH.MPQ以外的文件,WAR3是不会使用的。
1.2.3)
地图文件(W3M)
去编辑一个地图,您必须解压W3M中的某个档案,然后编辑档案,最后再把档案放回W3M文件。
不过W3M文件和MPQs文件是有不同的。我会在“W3M文件格式一节”和以下各节对W3M内其他档案做更多的介绍。
1.3 WAR3数据格式
暴雪在档案中使用了多种方式储存数据。不过还是经常使用到了通用类型。
__Integers整数
整数使用了4bytes(高高低低原则)储存。
就是说读取的第一个字节是最后一个字节。
就像C++中的"int"(signed)。
大小:4 bytes
例子(十进制)=[00 00 04 D2]h 储存后是[D2 04 00
Integers数值稍小的整数
数值稍小的整数使用了2bytes(高高低低原则)储存。
与C++中的signed short相近,不过Short
Integers的范围是-1.
就是说可以随意用来做flag。
大小:2bytes
__Floats小数
小数使用标准IEEE
32位浮点数格式。使用4bytes(高高低低原则)储存。
就像C++中的"float"。
大小:4bytes
例子.32(小数)
这个数字不能直接使用此格式储存,所以系统将会使用最最接近的值,而且能够用二进制数储存的数字代替。最接近的是.319824(小数)=[45
EF 32 8H]h 储存后是[8F 32 EF 45]h
__Chars and Array of
Chars字符和字符数组
字符使用标准chars(1char=1byte)储存,字符数组不得使用空字符
大小(chars):1byte
(array of chars):通常4bytes
__Trigger Strings and
Strings触发字符串和字符串
字符串只是用一个空字符(C++
"\0")结束的字符数组。只不过暴雪有时使用特殊的控制代码来改变现实颜色。就像"|c00BBGGRR","BB","GG","RR"是用十六进制值(每个使用2位数)来代表蓝色,绿色和红色的值。
如果一个字符串使用 "TRIGSTR_"
做开头(区分大小写),则被视为触发字符串。一个触发字符串在记忆体中以("TRIGSTR_***")
开头,并且在WAR3需要显示它的时候会改变。所以在用户屏幕上出现的不是"TRIGSTR_000",WAR3会在加载地图时查看触发字符串表,然后用对应的触发字符串代替后显示。除了WTS通常自己定义触发字符串表外,触发字符串只对W3M内部文件有用(Jass,w3i)。如果在"TRIGSTR_"
下的数字为负,触发字符串将会指为一个NULL(空)字串;如果"TRIGSTR_"
下是文本,它将被视为触发字符串#0(=
"TRIGSTR_000")。
"TRIGSTR_7", "TRIGSTR_07",
"TRIGSTR_007"和"TRIGSTR_7abc"全部指向触发字符串#7;
"TRIGSTR_ab7",
"TRIGSTR_abc"和"TRIGSTR_"全部指向触发字符串#0."TRIGSTR_-7"是负的,将不会指向任何触发字符串,显示"
"。按照惯例。"TRIGSTR_"
后为三位数,以空字串结束。
例1:
您设置字符串"blah |c000080FFblah", WAR3将显示"blah
blah",但是第二个blah将显示为橙***(blue=00 +
green=80 + red=FF ==&orange)
例2:
您设置"TRIGSTR_025"
,字符串25在.WTS文件中被定义为"blah|c000080FFblah",
那么显示的结果和例1一样。
大小(字符串):变化的。字符串长度+1(空终止符)
(触发字符串):12 bytes
flags就是布尔值(TURE或FALSE,1或0),被储存为4
每位都是一个flag(4 bytes = 32 bit = 32 flags)。
暴雪在储存flags使用整数。
大小:通常4 bytes
__ Custom Types
有时候,字节会被整数和flags共用。
在W3E文件格式中,水平线和2
Flags使用着相同的4字节组。
最高2位为flags,后两位为水平线。更有时一个字节包含两个或更多的数据。
__ Structures 结构
WAR4也使用各种大小的构造类型。
2.0 w3m文件格式
W3M文件就是WAR3地图文件,就是有一个512
bytes为header的MPQ文件(新压缩格式)。
官方W3M文件常常还为了认证地图,使用了260
bytes的footer。
header格式(固定大小=512bytes):
char[4]: 文件ID (应该是"HM3W")
int: unknown
string:地图名称
int:地图flags (和W3I文件一样)
0x0001: 1=隐藏预览屏的小地图
0x0002: 1=变更结盟优先权
0x0004: 1=混战
0x0008: 1=可用地图大小为大,从未减小
0x0010: 1=阴影区域部分可见
0x0020: 1=对固定玩家设置默认属性
0x0040: 1=使用默认属性
0x0080: 1=使用默认技能树
0x0100: 1=使用默认技能
0x0200: 1=使用默认升级设置
0x0400: 1=地图创建后至少打开一次地图道具菜单
0x0800: 1=在cliff shores显示水波
0x1000: 1=在rolling shores显示水波
int:最高玩家数量
从00 bytes到512 bytes(header are filled).
foot格式:
char[4]: footer sign ID (应该是"NGIS" ==相反的 'sign')
byte[256]: 256 data bytes (认证用).
MPQ包含的文件:
(listfile)
(signature)
(attributes)
war3map.w3e
war3map.w3i
war3map.wtg
war3map.wct
war3map.wts
war3map.shd
war3mapMap.blp
war3mapMap.b00
war3mapMap.tga
war3mapPreview.tga
war3map.mmp
war3mapPath.tga
war3map.wpm
war3map.doo
war3mapUnits.doo
war3map.w3r
war3map.w3c
war3map.w3u
war3map.w3s
war3map.imp
war3mapImported\*.* (wave
files,和其他用魔兽编辑器保存的文件)
下面我们会看到这些文件代表了什么。
"war3map.j"The JASS2 Script
这是最主要的地图脚本文件。使用的是文本格式,您可以使用记事本打开查看。
编写的语言是暴雪研发的JASS2(区分大小写)。
当您在进行游戏之前,JASS脚本会被加载然后被执行。
下面就是JASS里的几个关键词:
只存在“nothing”和”handle”两个”native
types”。
其他所有类型都能从”handle”导出(关键词”extends”)
从WAR3.MPQ中的"Scripts\Common.j"您可以看到完整的类型表和本地函数。
您还可以对句柄类型设定常数值:
“null”,整型数值,浮点型数值,字符串,触发字符串,”ture”,”false”。
下面是一些JASS里的运算符:
parenthesis for
priorities
(concatenation for strings)
substraction
multiplication
assignation
comparison
(equal, lighter, lighter or equal, greater, greater or equal,
different)
boolean value
在编辑器里的函数在”Scripts\Blizzard.j”中被定义。
下面是一个函数定义的例子:
function myfunction
nothing returns
str = "blah blah
blah" local
i // comments line set i = 0
loop set i = i + 1 if (i == 27) then call
DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, str) endif
exitwhen i == 30 endloop return i endfunction
“war3map.w3e”The
environment
这是”tiles”文件,包含了地图中所有地形设定的数据。
实际上地图被分为许多的矩形区域,这个矩形区域就叫”tiles”。
在3D,我们用点来定义面,但是在这里是用它们的转角来定义”tiles”。
我称之为”tilepoint”。
因此,假如您做了一张256&256的地图,那么就会有257&257个tilepoints。
例如,1/2块土地,1/4块草地,1/4块岩石 ,都只是一个tile。
在文件中,第一个tilepoint代表了地图的左下角,然后连成一条条水平线。
Tilesets就是用于地面的纹理组。
下面就是war3map.w3e文件的格式:
char[4]: 文件ID =
int: w3e format version [0B 00 00 00]h = version 11
char: main tileset [TS]
Underground
int: custom tilesets flag (1 = using cutom,
0 = not using custom tilesets)
int: tilesets组的编号 (高高低低原则) (注意: 不能大于16 ,因为tilesets 标注在tilepoints 的定义中)
char[4][a]: 地表 tilesets IDs (tilesets目录)
& 例如: "Ldrt" 代表了 "洛丹伦的夏天"地表
& (想要了解更多,请参阅war3.mpq中"TerrainArt\Terrain.slk"文件)
int: cliff tilesets的编号(高高低低原则) (注意: 不能大于16,原因同上)
char[4][b]: cliff tilesets IDs (悬崖tilesets 目录)
& 例如: "CLdi"代表了洛丹伦悬崖泥土
& (想要了解更多,请参阅war3,mpq中"TerrainArt\CliffTypes.slk"文件)
int: 地图宽度+ 1 = Mx
int: 地图高度
& 例如: 您的地图大小是160x128, Mx=A1h and My=81h
float: 地图X坐标中心偏移
float: 地图Y坐标中心偏移
这两个偏移用于脚本文件,小装饰物,还有其他一些地方。
原始坐标(0,0)位于地图左下角,比传统在地图正中间做(0,0)更易于使用。
下面是偏移的算法:
-1*(Mx-1)*128/2 and -1*(My-1)*128/2
(Mx-1) 和 (My-1)
是地图的宽度和高度
128是地图里tile的大小
& /2 是取长度的中间值
& -1* 因为我们是"translating"
地图区域,而不是定义新坐标
一个 tilepoint
用一个7bytes的块来定义。
block的数量=
short: 地面高度
C000h: 最低高度(-16384)
2000h: 正常高度(零地水准平面)
3FFFh: 最高高度(+16383)
short: 水面 +
标记*(地图边缘的阴影范围)
4bit: 标记*
4bit: 地面构造类型
(草地,泥土,岩石,...)
1byte: 细节纹理
(石头, 洞, 骨头,...).
4bit: 悬崖构造类型
4bit: 层的高度
flags*(标记):
标记值(低低高高原则):
& 0x4000 --& 范围标记1 (地图边缘的阴影范围)
& 0x0010 --& 斜坡标记 (两个地表层之间的斜坡)
& 0x0020 --& blight flag (ground
will look like Undead's ground)
& 0x0040 --& 水面标记 (可用水面)
& 0x0080 --&范围标记2 (镜头区域范围.)
水平面和地面高度的储存一样.
最高位 (bit 15)
是范围标记1
Tilepoint 数据的例子:
51 21 00 62 56 84 13
51 21 --(高高低低原则)--&
0x2151 --(十六进制--&十二进制)--&
高度 = 8529
00 62 --(高高低低原则)--&
& (提取范围标记)--&
(0x6200 & 0xC000) = 0x4000 范围标记设置
& (提取水面数据)--&
(0x6200 & 0x3FFF) = 0x2200 --(十六进制-&十二进制)--&
水平面 = 8704
56 --& 5代表了水面标记和斜坡标记,
6 代表tilesets
表里的地表类型#6
的tilepoint
84 --& 代表了细节纹理#132的 tilepoint (=0x084)
13 --& 1 代表了悬崖类型 #1 (悬崖tilesets表), 3代表了在"3"层的tilepoint
在WE中tilepoint的 "final height"算法是:
(ground_height - 0x2000 + (layer - 2)*0x0200)/4
"0x2000"代表了零地水准平面,
2代表了零层面,
"0x0200" 也是层高
& = (0x2151 - 0x2000 + 1*0x0200)/4
& = (8529 - 8192 + 512)/4
& = 212,25
在WE中水平面的tilepoint算法是:
(水平面- 0x2000)/4 -
"0x2000"代表了零地水准平面,
-89.6代表了零水平面(water.slk
文件 高度 = -0,7 --&
零水平面 =
-0,7*128):
& = 8704/4 - 89,6
既然这样, 水面标记已经设置,水平面低于地水准平面,所以我们不会看到水面。
这只是个例子,您不可能在地图中看到这样的tilepoint
。这只是为了示例。
“war3map.shd”The Shadow Map
这个文件没有header,,全部都是原始数据。
文件大小 =
16*地图宽度*地图高度
1byte 可以有两个值:
00h =无阴影
FFh =有阴影
Each byte set the shadow status of 1/16 of a tileset.
也就是说每个tileset
(4*4)个部分。
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。