坦克世界MOD制作教程Word下载.docx
《坦克世界MOD制作教程Word下载.docx》由会员分享,可在线阅读,更多相关《坦克世界MOD制作教程Word下载.docx(25页珍藏版)》请在冰豆网上搜索。
说明一下,第一个参数是这个文件的文件名,所以如果输入有效的话,系统参数应该是2个以上的,第二个以后就是要编译的py文件了。
6.
forargv_iinsys.argv[1:
]:
#对每个参数,除去第一个本文件名
7.
try:
#尝试
8.
py_pile(argv_i)#编译py文件为pyc文件
9.
except:
#出错的处理
10.
printargv_i,"
can'
tbecompiled"
#在控制台上打印错误消息
11.else:
#如果输入的参数只有一个
12.
print"
pleaseinputthefiletobecompiled"
#在控制台上打印消息,提示输入正确的格式
复制代码
没错,这便是筒子们的第一个py脚本了。
如果出错的话,删掉#连同后边的中文注释……
【EasyPythonDecompiler】反编译pyc为py文件的工具
这个用法也很简单,打开exe后,两个大的选项,
【DecompileaFile】是反编译单个pyc文件,【DecompileaDirectory】是反编译一个文件夹内的所有pyc文件。
有了它之后,咱就可以把坦克世界的整个客户端翻个底朝天。
当然大家也可以像我一样用一些用来反编译pyc的脚本,如【uncompyle2】等等,毕竟生命在于折腾。
不过配置起来比较麻烦了就是,我们目的不在于此,怎么简单怎么来,python的精神也是提倡这样的。
下载地址
python的编辑器
虽然说脚本文件很多情况下是不用IDE(开发环境)的,记事本就可以,但是像大型的程序最好还是挑选一个智能一点的编辑器比较好。
推荐SublimeText,自带python补全,小巧而强大,网上汉化版也很多,
python的手册
新手们大都要先接触python的语法啊、运算符啊、数据结构啊等看起来很高端的问题。
但python作为一门相对来说简单到爆的语言,其实是非常容易上手的,计算机二级过了的筒子们基本上可以驾驭(怎么过的我就不去揣测了)。
唯一不习惯的大概就是python是以缩进来代表语句块的格式了,我在此提醒一下,建议用4个空格来缩进,而不是tab键。
贴上两本pdf书籍地址:
《可爱的python》
AdobeFlash
这个大家都熟,坛子里介绍如何替换准心啥的帖子大都提到过,不多赘述。
ScaleformGfx在flash里的插件
WG现如今的框架大概就是逐渐褪去的BigWorld引擎和Scaleform的UI系统再加上WG尚算是良心的游戏方式了。
这个是我从UDK里边摘出来的。
Scaleform是个商业的UI接口,售价是很高的。
但UDK里有免费的授权,Epic公司实在是良心大大的好,可惜UDK被棒子的泡菜游戏搞得名声狼藉。
话不多说上攻略。
压缩包下载地址
【AMP/GFxAmpClient.exe】是一个profile分析工具,大体上就是去测试一下咱开发出来的swf性能如何,占CPU多少,占内存多少等等,没多大用,但也可以显示一些调试信息,哪里出错了之类的,但仍然像我说的,没多大用。
【CLIKTools/ScaleformExtensions.mxp】这个是重点了,mxp是Adobe的插件格式,需要用【AdobeExtensionManager】这个坑爹东西去安装……
所以用精简版的Flash的筒子们哭去吧哈哈。
当然你可以单独下一个ExtensionManager,但要注意几点,一是版本要对,FlashCS3的就要对应CS3的版本,CS5要对应CS5版本,二是精简版的Flash大都是不被ExtensionManager识别的,所以最好用官方版本然后输入序列号,或者什么龙卷风版本啊等完整的安装版本,正版的壕请无视我,顺便求交友。
解压文件,准备好了之后就要打开ExtensionManager,安装这个mxp格式的插件了。
我用的是CS3版本,这个EM也比较简陋,高版本方法是一样的。
安装好之后进入Flash,新建一个Flash项目,照着下边截图方式操作一次就算是配置好了。
【Flash/AS2/CLIK】文件夹下的都是Scaleform
在Flash这一端的一些类。
按照截图方式将CLIK文件夹添加到AS2的类路径中。
到此,Flash这边就算是完事了。
【硕思闪客精灵】反编译swf文件的工具
这个也不必多说,换准心的教程里都有介绍。
我这个算是最新版本的吧,从国外扒过来的,热乎乎的英文版……地址
乌拉,经过一番作死般的折腾,我们终于配置好了所有的开发环境,下一步就是开工啦。
【B_i_g_W_o_r_l_d
P_y_t_h_o_n
D_o_c_u_m_e_n_t_a_t_i_o_n】哎呀忘了一个极其重要的东东,这玩意是我千辛万苦从一个大洋洲某小岛国上的服务器里整过来的。
此时小马哥专属音乐请奏起来
原始地址我就不放了,怕被人找上门来……英文版,不多说,地址
探索篇:
python脚本
凡事都是慢慢探索出来的,做mod尤其如此。
mod是如何加载的
我先找到一个毛服的喊话mod,国内的“前方高能……”估计就是从那个mod改的,至于为什么选择这个,原因很简单,它有源码,有xml配置文件,这是很重要的。
首先分析一下这个mod的结构,【res_mods/0.9.3/scripts/client】文件夹下便是一系列的脚本文件了,它对应了坦克世界安装目录中【res/scripts/client】文件夹,经过一番测试,我大概了解了mod的工作原理,客户端程序首先加载【res_mods】里对应版本的文件,然后再加载【res】里的,如果【res】中的同名文件已经被加载了,便跳过这个文件。
如此一来便完成了客户端文件的安全替换。
但是筒子们有时候发现,下载的mod里经常有一些【res】文件夹中没有的文件,如果以上推论正确的话,照理来说这些文件是不会被加载的啊?
细心的筒子会发现,一般情况下,mod的【res_mods/0.9.3/scripts/client】里会有一个【mods】文件夹,还会有一个【CameraNode.pyc】文件,反编译这个文件后,呦,一切了然。
我们来逐句分析这个【CameraNode.py】:
#Embeddedfilename:
CameraNode.py#文件名
importBigWorld#导入BigWorld包
classCameraNode(BigWorld.UserDataObject):
#定义CameraNode类,继承自BigWorld.UserDataObject类
def__init__(self):
#构造函数,实例化CameraNode类时会自动调用
BigWorld.UserDataObject.__init__(self)#调用基类的构造函数
defload_mods():
#定义加载mod的函数,加载那些凭空出现对应不上的文件
importResMgr,os,glob#导入需要的包
res=ResMgr.openSection('
../paths.xml'
)#读取安装路径下的paths.xml文件,大家可以看一下,第一个【Path】节点便是【.res_mods/0.9.3】,倒数第二个才是【./res】,这也印证了我们上边的猜想是正确的。
sb=res['
Paths'
]
vals=sb.values()[0:
2]
forvlinvals:
mp=vl.asString+'
/scripts/client/mods/*.pyc'
#组合成正确的加载路径
print'
GF47_Console:
currentpathis'
mp#这是我自己debug时加的,功能是在游戏安装目录下的【python.log】文件中写一行log信息。
forfpinglob.iglob(mp):
对于【mp】中每一条
_,hn=os.path.split(fp)#将【fp】这个相对路径拆分成两段,一段是所在文件夹,丢弃,一段是带后缀的mod文件名,存储在【hn】中
zn,_=hn.split('
.'
)#将带后缀的文件名拆分成两段,一段是不带后缀的文件名,存在zn中,一段是“pyc”这个后缀字符串,丢弃
ifzn!
='
__init__'
:
Loadmods:
'
+zn#在【python.log】中写一行log信息,显示当前加载的mod
try:
exec'
importmods.'
+zn#执行“importmods.zn”这段语句,zn是刚才筛选出来的mod名字。
注意这句是动态执行的,脚本语言的特点……
exceptExceptionaserr:
print'
LoadmodsError:
'
+err#打印错误信息
importsys
GF47_Console:
pythonversionis'
sys.version[:
5]#这也是我debug时加的,显示当前坦克世界所使用的python版本
load_mods()#执行load_mods函数
我们编译一下这个【CameraNode.py】文件,方法是:
打开控制台,转到当前py文件所在的文件夹,输入【compile27.pyCameraNode.py】,回车后会在当前文件夹中生成CameraNode.pyc文件。
呦,少年,你已经编译出了第一份pyc文件了!
把这个文件拷贝到【res_mods/0.9.3/scripts/client】下。
我们可以在游戏安装目录的【python.log】文件内读取脚本文件中使用【print】语句所输出的log信息。
删掉这个文件是没问题的,它会在游戏开始时再次生成。
播放一次战斗回放,我们看一下它的内容:
1.BigWorldReleaseClient(compiledat15:
29:
52Sep
32014)startingonSunOct1921:
52:
492014
2.
ContentType:
content
4.Checking./res_mods/0.9.3:
modsfound
5.
pythonversionis2.7.30
currentpathis./res_mods/0.9.3/scripts/client/mods/*.pyc
7.Loadmods:
GunConstraints
8.Loadmods:
MS
9.Loadmods:
DamagePanel
[DamagePanelbyGambitER0.8.11v.2]
11.
currentpathis./res/packages/shared_content.pkg/scripts/client/mods/*.pyc
12.[NOTE](scripts/common/fortified_regions.py,188):
fortified_regions.init()
13.[WARNING](scripts/common/DestructiblesCache.py,478):
FailedtoreadfractureEffectnameincontent/Environment/env414_Pole/normal/lod0/env414_Pole.model
14.[WARNING](scripts/common/DestructiblesCache.py,478):
FailedtoreadtouchdownEffectnameincontent/Environment/env414_Pole/normal/lod0/env414_Pole.model
15.[WARNING](scripts/common/DestructiblesCache.py,478):
FailedtoreadfractureEffectnameincontent/Environment/env414_Pole/normal/lod0/env414_Pole10.model
16.[WARNING](scripts/common/DestructiblesCache.py,478):
FailedtoreadtouchdownEffectnameincontent/Environment/env414_Pole/normal/lod0/env414_Pole10.model
17.[NOTE](scripts/client/post_processing/__init__.py,267):
Thequality=4wasselected.
18.[NOTE](scripts/client/post_processing/__init__.py,267):
Thequality=3wasselected.
19.[SPACE]Loadingspace:
spaces/28_desert
20.PostProcessing.Phases.fini()
以GF47开头的行便是我刚才添加的debug信息了,第一个说明了当前python版本为2.7.3,第二个说明了先加载【res_mods/0.9.3/scripts/client/mods】下的所有pyc文件,Loadmods开头的行显示了所加载的mod,我只安装了几个,所以只有3行,有些筒子们估计要一屏以上……
摸清了mod运行的原理,接下来就简单了,若想添加新的功能,只需把编译好的pyc文件放在【res_mods/0.9.3/scripts/client/mods】里,游戏就可以正常加载了。
若想修改原始的功能,只需和【res/scripts/client】文件夹中的文件路径匹配就可以啦。
我这里只介绍原理,就不多做赘述了。
贴一个喊话的mod源码,
分析已有的战斗面板
接下来加快速度。
我是想在战斗中显示一个独立面板的,而不是DamagePanel或debugPanel那种默认就有的面板,然后我就开始在【res】文件夹中翻找。
既然是战斗中显示,那当然要优先看battle有关的脚本,果然,在【res/scripts/client/gui/Scaleform】文件夹中找到了【Battle.pyc】文件,我有一种预感,就是这个玩意了。
反编译后,哇哦,光是import包就有40多行代码……镇定镇定。
看看它定义的类吧,Battle、TeamBasesPanel、VehicleDamageInfoPanel、DebugPanel、DamagePanel……是不是心花怒放了?
乌拉!
我在这里先提一下另外两个重要的脚本文件:
flash.pyc、windows.pyc。
其中flash.pyc文件定义了一个Flash类,它的功能是加载一个swf文件(泪流满面,终于找到跟swf交互的类了),而windows.pyc文件中定义了ModalWindow、BattleWindow、GUIWindow、UIInterface这几个类,除去BattleWindow这个至关重要的类外,另外三个都是与界面相关的。
像是【debugPanel】,就是那个显示帧率延迟丢包的左上角的小面板,它就是继承自UIInterface的。
但最开始我没有找到它是如何加载并调用swf文件的,只有Flash类里有一个直观的可以输入swf文件位置的参数,那就先用它咯。
其实选用Flash类作为基类也不是空穴来风,因为我发现安装坦克世界盒子后,这个【Battle.pyc】文件会被替换,新的文件中会多出来一个VehicleMarkersManager类,这个玩意其实是战斗统计面板,就是统计筒子们每炮输出的那个面板。
这个类就是继承自Flash类的。
毫无疑问,这个统计输出的面板是个新的面板,而不是客户端自带的那些,so,我就先模仿它来编写我的面板喽。
我们先摸清这些面板是如何被创建的,毫无疑问Battle类是最重要的,在它的构造函数__init__中,有一些初始化设置,但我最开始是肯定一头雾水的……这特么的什么玩意啊
耐心耐心,继续往下看。
我找到了一个afterCreate函数,呦,感觉应该就是它了。
一排self.__xxx=xxx(self.proxy),这当然是对xxx类的实例化,比如那个self.__debugPanel=DebugPanel(self.proxy)……再往下看,又是一堆self.__xxx.start(),看来这个start函数也是必要的了。
有创建当然就要有销毁,就像开机一定对应关机一样,我找到了一个beforeDelete函数,里边又是一堆self.__xxx.destroy(),这个destroy函数也是有必要的。
这样,我们就确定了一个面板的生命旅程,首先是实例化,然后是start,然后是destroy,至于中间干什么,那肯定是update啦。
啊……如何update呢?
这可是个难题,我详细看了【Battle.py】文件,发现了这个_TimeInterval类,懂英文的筒子们从名字上就知道啥意思了,时间间隔。
它的功能就是每隔一段时间执行一次特定的函数,具体原理我们先不深究,大家有兴趣可以折腾一下,反正就是callback那一套了,举个栗子,我很困,于是让闹钟每隔5分钟叫醒我一次,我就可以写一段这个教程,然后又困到睡觉,再叫醒,再写一段,再睡觉……
好啦,python脚本这边我们算是分析完毕了,接下来就是Flash端了,毕竟UI面板是要交互的。
Flash&
swf
可惜Flash我是不太熟悉的,只能慢慢摸索着来。
那些package
我先用硕思闪客精灵反编译了【debugPanel.swf】文件,这个算是最简单的swf文件了。
解释一下图中的Actions:
MainMovie是直接F9然后输入的代码,不需要选择任何元件,它的作用是全局的。
sprite9中的代码是选中元件9后输入的,它作用于元件9(其实里边一个字也没有)。
sprite后边有括号的,是Flash中设置过外部链接的。
__packages就是外部导入的类了,其中__packages.gfx.xxxxxx格式的类我们如果正确安装了【scaleform】插件的话可以无视,不然我们费那么大劲安它干什么。
而__.wargaming.ingame.xxxxxx是我们自定义的类,要按照固定路径放置,在fla工程文件同目录下建立net文件夹,在net里边建立wargaming文件夹,以此类推。
交互方法
我最开始没有明白debugPanel.swf文件是如何与Battle.pyc中定义的DebugPanel类互相响应的。
而在VehiclemarkerManager.swf中我找到了这个addCallBack函数,它向客户端注册了一