紧急!《赤壁》GM重金寻求高人保镖
三国乱世之中,镖局作为护送物资的唯一途径,每天都可接受到押镖任务,而在每日完成押镖任务之后,玩家不仅可以获得特殊的活动奖励,更可以获得海量的历练值。而今天GM化身镖局丫鬟现身《赤壁》,重金寻找高人保镖,你是她要寻找的最得力的高人吗?
【押镖介绍】
就在12月9日16:00,GM将现身桃园村,而整个活动将从此地展开,届时,GM将以系统公告形式公布活动细则,想参加此次活动的玩家需前往桃园村参加活动。现场GM将从众多玩家中寻找高人保镖,而此时,欲参与活动的玩家请用密语频道与GM交流,GM会随机选择玩家并发送相依相偎请求,此时玩家需抱着GM前往下一站。但是没有成功成为押镖人也没关系,只要玩家参与到押镖队伍中来,也是有机会获得奖励的哦。
活动保镖的路线为桃园村→落雨滩→清凉驿→邓家庄→白马津→泛水关→长安南门,每站将更换一次保镖人,也就是说将有6名玩家进行保镖。参加押镖的玩家如果掉线,则押镖失败,奖励会发放给现场的其他参与玩家,此时每人能获得30金币的奖励。最后只有将GM顺利送到长安南门方可成功,每人将奖励60金币,此时没有得到奖励的玩家也不要着急,活动最后会在现场所有参与的玩家中选出四名幸运玩家发放30金币的幸运奖励哦。
温馨小提示:
1、押镖活动在15线举行,起点为桃园村口,因此参与活动的玩家可提前换到指定线路和位置等待参加活动;
2、保镖路线桃园村→落雨滩→清凉驿→邓家庄→白马津→泛水关→长安南门;
3、每一站若能将GM成功送到站点的玩家可获得60金币奖励,若失败,奖励则发放给现场参与活动的任意两名玩家,每人30金币;
4、到达终点站以后,GM将在现场参与活动的玩家中随机抽取4名幸运玩家发放每人30金币的奖励;
5、奖励将以交易的形式由GM直接发放。
还没有人评论
2013年末最大跨服竞技,完美首款3D移动格斗三国巨制《赤壁-斗群英》全国争霸赛进入倒计时5天!各方军团蓄势待发,最后5天的备战,你,为自己,为团队准备好了吗?《赤壁-斗群英》群英...曾经,3天狂飙80级让无数玩家激动不已,今日,如果告诉你完美首款3D移动格斗三国巨制----《赤壁-斗群英》升级又要加速了,你岂不是可以叫上更多的小伙伴一起来征战?万万没想到,就在下周...在完美首款3D移动格斗三国巨制《赤壁-斗群英》群英公测后,新增的野外群杀BOSS抢宝活动,为小伙伴们带来了不少的游戏乐趣。《赤壁-斗群英》火爆公测精彩活动百万豪礼等你领《赤壁-斗群...英雄一怒为红颜,风转云变拔剑向天!完美首款3D移动格斗三国巨制《赤壁-斗群英》群英公测,主打玩法新国战宣传片首映,为你呈现如此豪气干云的战争,带来那个沧海横流时代的三国千人争霸。而...完美首款3D移动格斗三国巨制----《赤壁-斗群英》将于11月11日12:00正式开启群英公测。凭借四大全新玩法,新版将为玩家带来无限炫斗激情体验。双线新服【斗群英】一触即发,新手入驻...完美首款3D移动格斗三国巨制《赤壁-斗群英》11.11群英公测!在魏蜀吴三足鼎立的时代背景下,大型多人互动PVP新国战震撼来袭,世界地图千人戮战,演绎激情斗战夺城。新国战畅享360...完美首款3D移动格斗三国巨制《赤壁-斗群英》11月11日群英公测,研发团队潜心制作,以独立新颖的开发视角,向广大玩家诚意推出第20大职业***。继承前19大兵种霸气精巧的形象气质,开辟...有兄弟就有阵营,有阵营就有搏杀!完美首款3D移动格斗三国巨制《赤壁-斗群英》11月11日公测!深化阵营玩法,增加阵营官职、阵营方针,届时,一些高端玩家不仅对阵营拥有管理权限和职能,...百兵武斗争锋,打造格斗战争巨制,完美首款3D移动格斗三国巨制《赤壁-斗群英》11月11日精英公测,第20大职业兵种***将劲爆登场。强劲火力爆发,酷炫特技光效,让你***射天下!持***形象【...今日,完美首款3D移动格斗三国巨制《赤壁》正式揭开新版神秘面纱----新版定名“斗群英”,并将于11月11日光棍节上线!全新PVP国战、新***兵、新系统等诸多更新,在光棍节当天让你乐斗群...
if (_url.indexOf("culture") > 0) {
document.write("");
} else if (_url.indexOf("game") > 0 || _url.indexOf("news") > 0 || _url.indexOf("flash") > 0 || _url.indexOf("zq") > 0) {
document.write("");
} else if (_url.indexOf("vote") > 0) {
document.write("");
//} else if (_url.indexOf("audio") > 0) {
//document.write("");
} else if (_url.replace(_url_i, "") == "" || _url.replace(_url_i, "") == "/" || _url.replace(_url_i, "") == "/index.html") {
document.write("");
} else if (_url.indexOf("portrait") > 0) {
document.write("");
} else if (_url.indexOf("biography") > 0) {
document.write("");
} else if (_url.indexOf("library") > 0) {
document.write("");
//} else if (_url.indexOf("download") > 0) {
//document.write("");
//} else if (_url.indexOf("magazine") > 0) {
//document.write("");
//} else if (_url.indexOf("video") > 0) {
//document.write("");
} else if (_url.indexOf("picture") > 0) {
document.write("");
//} else if (_url.indexOf("search") > 0 || (location.search).indexOf("k=")>0) {
//document.write("");
} else if (_url.indexOf("cartoon") > 0) {
document.write("");
} else if (_url.indexOf("bbs") > 0 && _url.indexOf("forum") > 0 ||
_url.indexOf("thread") > 0 && _url.indexOf("html") > 0) {
document.write("");
} else if (_url.indexOf("bbs") > 0 && _url.indexOf("forum") == -1 || _url.indexOf("bbs") > 0 && _url.indexOf("thread") ==-1) {
document.write("");
function ad(){
baidu_inc.innerHTML=baidu_view.innerHTML;
google_inc.innerHTML=google_view.innerHTML;后使用快捷导航没有帐号?
查看: 23072|回复: 59
新人欢迎积分1 阅读权限40积分327精华0UID帖子金钱2992 威望0
Lv.4, 积分 327, 距离下一级还需 673 积分
UID帖子威望0 多玩草50 草
----其实是一个失败的输入法候选框&&{: M( `3 K2 M2 @&&`3 X7 e
: w+ y* ]. z9 {& G- g- A" w
最近在学python语言,但是一直没有什么实践的机会。正好我唯一在玩的网络游戏坦克世界就是用python做脚本语言的,便一拍脑门,便决定把那个蛋疼的输入法问题(打字杀永远的痛)解决掉,于是一发不可收拾。事先透露一下,原本的方案可以说算是流产了……. k! p$ ~8 \/ Q! o) W! M' b
但是我这么有节操的人怎么能做无用功呢。自己研究期间搜到多玩坦克世界插件版的帖子基本都是在涂装和图标、语音等方向徘徊,觉得总是比毛服欧服论坛差点什么。为了改善这种状况,我决定拿这次案例来做个脚本方面的教程,权当抛砖引玉,引诱大神们出来打脸,打脸之余顺便提高坛子里关于脚本方面的教程帖子的质量。
0 o8 ~/ }- Z: }0 S
&纯技术贴啊,楼主乃真大神也!&
&点赞~~友情提示:二楼正文开始~~&
&好好好好好好&
&快来我的群!这种人才我才不会放过!!!!&
你的贴子很不错。推荐一下! O(∩_∩)O.
感谢你帮助玩友O(∩_∩)O
总评分:&金钱 + 323&
多玩草 + 50&
3年单野路过
新人欢迎积分1 阅读权限40积分327精华0UID帖子金钱2992 威望0
Lv.4, 积分 327, 距离下一级还需 673 积分
UID帖子威望0 多玩草50 草
配置篇:python环境& & 这个是必须的啦,诸君看到的所谓pyc后缀名的文件便是py脚本编译后的东西。Windows上的***方法也是超级简单,设置一下***路径,一路下一步就ok。实在不明白的可以网上搜一下,很多教程。我这里贴一个图文并茂的:/article/1a62e53e5707e0.html。要注意的是python有两个阵营----python2和python3,坦克世界以前是2.6版本的python,最近好像是换成了2.7.3,大家网上下***包的时候不要下python3的版本,安全起见,我贴一个下载地址(大部分下载地址都是我的百度网盘,比较容易得到的软件我就不上传了):/s/1eQw3Ssi。至今还在用xp系统的筒子们可以去官网下32位版本的,我就不吐槽了。呃还有一点是python的***路径不要有中文,虽然不是必须的,但毕竟是开源的东西,一些个人写的包可能会有不识别中文的问题,会出现一些费解的小bug。***好之后打开控制台(快捷键Windows键+R,然后输入cmd),输入python,出现python的版本、许可信息等,说明你的python已经成功***上了。9 T/ ?# ^: q2 Z5 p
17:30:22 上传
+ F5 J' a( A+ C
1 A$ Q- j' j6 L( m&&p
还有一步就是把咱的***路径填到系统变量中,至于环境变量是个啥,简单来说就是默认路径啦,计算机搜索可执行程序或是bat文件、dll文件之类文件时,优先搜索这些用“;”隔开的一个个路径。我们再编写一个小文件【compile27.py】,来方便我们将以后编写的py文件编译成pyc文件。在***路径下新建一个Scripts文件夹,1 ~) E9 [7 ~2 B6 ?8 d+ d/ l. h
17:33:05 上传
将这个Scripts文件夹也添加到环境变量中,注意路径之间用分号隔开“;”,把这个compile27.py文件放进去。具体代码如下:% |4 r& R6 c, K) T+ c' S&&x8 g) E
#!usr/bin/env python270 x8 j7 E2 O5 {0 _* f" L$ {
# -*- coding: UTF-8 -*-
&&L# }/ Y. @& o" \9 b
import sys, py_compile#导入所需要的包
if len(sys.argv) & 1:#如果输入的参数个数大于1。说明一下,第一个参数是这个文件的文件名,所以如果输入有效的话,系统参数应该是2个以上的,第二个以后就是要编译的py文件了。
& & for argv_i in sys.argv[1:]:#对每个参数,除去第一个本文件名
& && &&&try:#尝试
& && && && &pile(argv_i)#编译py文件为pyc文件3 V&&[2 @7 X2 k
& && &&&except:#出错的处理
& && && && &print argv_i, &can't be compiled在控制台上打印错误消息$ }+ R- D6 |7 w7 x" Q
else:#如果输入的参数只有一个) N" o3 ?( p+ @1 s- e( e
& & print &please input the file to be compiled在控制台上打印消息,提示输入正确的格式 复制代码& & 没错,这便是筒子们的第一个py脚本了。如果出错的话,删掉#连同后边的中文注释……4 }, M7 W6 ^1 `9 x' S( p
【EasyPythonDecompiler】反编译pyc为py文件的工具& & 这个用法也很简单,打开exe后,两个大的选项,
17:37:23 上传
【Decompile a File】是反编译单个pyc文件,【Decompile a Directory】是反编译一个文件夹内的所有pyc文件。有了它之后,咱就可以把坦克世界的整个客户端翻个底朝天。当然大家也可以像我一样用一些用来反编译pyc的脚本,如【uncompyle2】等等,毕竟生命在于折腾。不过配置起来比较麻烦了就是,我们目的不在于此,怎么简单怎么来,python的精神也是提倡这样的。下载地址/s/1eQy5JwQ,解压即可。至此,python这端的配置算是完成了。python的编辑器& & 虽然说脚本文件很多情况下是不用IDE(开发环境)的,记事本就可以,但是像大型的程序最好还是挑选一个智能一点的编辑器比较好。推荐SublimeText,自带python补全,小巧而强大,网上汉化版也很多,/html/24343.html。Notepad++也不错,不过我因为某些政治上的问题弃用了,现在vim用的不亦乐乎,顺便向外插usb脚踏板的emacs用户们宣战,哈哈玩笑了。python的手册& & 新手们大都要先接触python的语法啊、运算符啊、数据结构啊等看起来很高端的问题。但python作为一门相对来说简单到爆的语言,其实是非常容易上手的,计算机二级过了的筒子们基本上可以驾驭(怎么过的我就不去揣测了)。唯一不习惯的大概就是python是以缩进来代表语句块的格式了,我在此提醒一下,建议用4个空格来缩进,而不是tab键。贴上两本pdf书籍地址:《可爱的python》/s/1bndDjkj,《python核心编程》/s/1ntMEalr。Adobe Flash& & 这个大家都熟,坛子里介绍如何替换准心啥的帖子大都提到过,不多赘述。Scaleform Gfx在flash里的插件& & WG现如今的框架大概就是逐渐褪去的BigWorld引擎和Scaleform的UI系统再加上WG尚算是良心的游戏方式了。这个是我从UDK里边摘出来的。Scaleform是个商业的UI接口,售价是很高的。但UDK里有免费的授权,Epic公司实在是良心大大的好,可惜UDK被棒子的泡菜游戏搞得名声狼藉。& & 话不多说上攻略。压缩包下载地址/s/1jG0z2lC,我大概介绍一下压缩包里的内容:
17:33:01 上传
【AMP/GFxAmpClient.exe】是一个profile分析工具,大体上就是去测试一下咱开发出来的swf性能如何,占CPU多少,占内存多少等等,没多大用,但也可以显示一些调试信息,哪里出错了之类的,但仍然像我说的,没多大用。【CLIK Tools/Scaleform Extensions.mxp】这个是重点了,mxp是Adobe的插件格式,需要用【AdobeExtension Manager】这个坑爹东西去***……
17:33:01 上传
所以用精简版的Flash的筒子们哭去吧哈哈。当然你可以单独下一个Extension Manager,但要注意几点,一是版本要对,Flash CS3的就要对应CS3的版本,CS5要对应CS5版本,二是精简版的Flash大都是不被Extension Manager识别的,所以最好用官方版本然后输入序列号,或者什么龙卷风版本啊等完整的***版本,正版的壕请无视我,顺便求交友。& & 解压文件,准备好了之后就要打开Extension Manager,***这个mxp格式的插件了。
17:33:01 上传
我用的是CS3版本,这个EM也比较简陋,高版本方法是一样的。& & ***好之后进入Flash,新建一个Flash项目,照着下边截图方式操作一次就算是配置好了。
17:33:02 上传
& u8 x' I/ g5 h
17:33:02 上传
17:33:03 上传
+ |" M+ e$ P8 ~9 Z$ Y+ d, F: K
# b1 D& w/ Y1 |+ T# m) T
17:33:03 上传
3 k( Y/ c$ }# f1 n% H
& & 【Flash/AS2/CLIK】文件夹下的都是Scaleform 在Flash这一端的一些类。按照截图方式将CLIK文件夹添加到AS2的类路径中。. p6 o1 g. [. U0 x8 t
17:33:04 上传
5 q. z( H1 X8 Q5 |/ F' N* a
到此,Flash这边就算是完事了。【硕思闪客精灵】反编译swf文件的工具& & 这个也不必多说,换准心的教程里都有介绍。我这个算是最新版本的吧,从国外扒过来的,热乎乎的英文版……地址/s/1kT2ztkF。***好后用crack包里的exe文件覆盖原始文件,不过这个好像跟阿里巴巴反钓鱼软件有冲突……不要在意这些细节,→△→。
乌拉,经过一番作死般的折腾,我们终于配置好了所有的开发环境,下一步就是开工啦。【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】哎呀忘了一个极其重要的东东,这玩意是我千辛万苦从一个大洋洲某小岛国上的服务器里整过来的。此时小马哥专属音乐请奏起来!!!原始地址我就不放了,怕被人找上门来……英文版,不多说,地址/s/1i3KKsfF。用浏览器打开index文件即可。这份文件我估计存活时间长不了,虽然我不明白为啥它们不做保护。
本帖最后由 狩土_默 于
02:38 编辑
&documentation真取消共享啦……&
3年单野路过
新人欢迎积分1 阅读权限40积分327精华0UID帖子金钱2992 威望0
Lv.4, 积分 327, 距离下一级还需 673 积分
UID帖子威望0 多玩草50 草
探索篇: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】:
#Embedded file name: CameraNode.py#文件名import BigWorld#导入BigWorld包
class CameraNode(BigWorld.UserDataObject):#定义CameraNode类,继承自BigWorld.UserDataObject类; H# J/ k& t" h
& &def __init__(self):#构造函数,实例化CameraNode类时会自动调用& && & BigWorld.UserDataObject.__init__(self)#调用基类的构造函数, s) w6 C1 K&&d7 E* r! c5 ^
def load_mods():#定义加载mod的函数,加载那些凭空出现对应不上的文件& &import ResMgr, os, glob#导入需要的包& &res = ResMgr.openSection('../paths.xml')#读取***路径下的paths.xml文件,大家可以看一下,第一个【Path】节点便是【.res_mods/0.9.3】,倒数第二个才是【./res】,这也印证了我们上边的猜想是正确的。& &sb = res['Paths']& &vals = sb.values()[0:2]& &for vl in vals:& && &&&mp = vl.asString +'/scripts/client/mods/*.pyc'#组合成正确的加载路径& && & print '& & GF47_Console: currentpath is', mp#这是我自己debug时加的,功能是在游戏***目录下的【python.log】文件中写一行log信息。& && & for fp in glob.iglob(mp):对于【mp】中每一条& && && &&&_, hn = os.path.split(fp)#将【fp】这个相对路径拆分成两段,一段是所在文件夹,丢弃,一段是带后缀的mod文件名,存储在【hn】中& && && &&&zn, _ = hn.split('.')#将带后缀的文件名拆分成两段,一段是不带后缀的文件名,存在zn中,一段是“pyc”这个后缀字符串,丢弃& && && &&&if zn != '__init__':& && && && && & print 'Load mods: ' + zn#在【python.log】中写一行log信息,显示当前加载的mod& && && && && & try:& && && && && && &&&exec 'import mods.' + zn#执行“importmods.zn”这段语句,zn是刚才筛选出来的mod名字。注意这句是动态执行的,脚本语言的特点……& && && && && & except Exception as err:& && && && && && &&&print 'Load mods Error:' +err#打印错误信息' @. W$ S3 V, ~& t
) F7 n# h% u$ ]$ ^5 g3 E
import sysprint '& &GF47_Console: python version is', sys.version[:5]#这也是我debug时加的,显示当前坦克世界所使用的python版本load_mods()#执行load_mods函数" ]" I% n) Z/ j7 ^* o
我们编译一下这个【CameraNode.py】文件,方法是:打开控制台,转到当前py文件所在的文件夹,输入【compile27.py CameraNode.py】,回车后会在当前文件夹中生成CameraNode.pyc文件。呦,少年,你已经编译出了第一份pyc文件了!把这个文件拷贝到【res_mods/0.9.3/scripts/client】下。&&`" f" \6 }6 n5 y
我们可以在游戏***目录的【python.log】文件内读取脚本文件中使用【print】语句所输出的log信息。删掉这个文件是没问题的,它会在游戏开始时再次生成。播放一次战斗回放,我们看一下它的内容:BigWorld Release Client (compiled at 15:29:52 Sep&&3 2014) starting on Sun Oct 19 21:52:49 2014
& &Content Type: content
Checking ./res_mods/0.9.3: mods found
& & GF47_Console: python version is 2.7.3
& & GF47_Console: current path is ./res_mods/0.9.3/scripts/client/mods/*.pyc" m5 m3 ~&&V# L&&e; f. r" r
Load mods: GunConstraints9 U; [3 ~$ X- S" ~" e
Load mods: MS
Load mods: DamagePanel
& && &&&[ Damage Panel by GambitER 0.8.11 v.2 ]( f- c- X. ]9 c% J
& & GF47_Console: current path is ./res/packages/shared_content.pkg/scripts/client/mods/*.pyc- }* c+ P' P" Y: r) y3 q/ k# U
[NOTE] (scripts/common/fortified_regions.py, 188): fortified_regions.init()
[WARNING] (scripts/common/DestructiblesCache.py, 478): Failed to read fractureEffect name in content/Environment/env414_Pole/normal/lod0/env414_Pole.model6 H' W# u. W* Y% \&&K
[WARNING] (scripts/common/DestructiblesCache.py, 478): Failed to read touchdownEffect name in content/Environment/env414_Pole/normal/lod0/env414_Pole.model
[WARNING] (scripts/common/DestructiblesCache.py, 478): Failed to read fractureEffect name in content/Environment/env414_Pole/normal/lod0/env414_Pole10.model! ~' n, p4 b( f" i! I4 B/ E
[WARNING] (scripts/common/DestructiblesCache.py, 478): Failed to read touchdownEffect name in content/Environment/env414_Pole/normal/lod0/env414_Pole10.model. q1 Q$ B, P! T+ \2 D+ Q! k$ |
[NOTE] (scripts/client/post_processing/__init__.py, 267): The quality = 4 was selected.
[NOTE] (scripts/client/post_processing/__init__.py, 267): The quality = 3 was selected./ C7 _# b- K9 o1 y
[SPACE] Loading space: spaces/28_desert
PostProcessing.Phases.fini()复制代码
以GF47开头的行便是我刚才添加的debug信息了,第一个说明了当前python版本为2.7.3,第二个说明了先加载【res_mods/0.9.3/scripts/client/mods】下的所有pyc文件,Load mods开头的行显示了所加载的mod,我只***了几个,所以只有3行,有些筒子们估计要一屏以上……8 z7 J! G- o* C&&n& ]7 ?
摸清了mod运行的原理,接下来就简单了,若想添加新的功能,只需把编译好的pyc文件放在【res_mods/0.9.3/scripts/client/mods】里,游戏就可以正常加载了。若想修改原始的功能,只需和【res/scripts/client】文件夹中的文件路径匹配就可以啦。8 A% ~. k3 F* Q' `2 j
我这里只介绍原理,就不多做赘述了。贴一个喊话的mod源码,/s/1sjyPqR7,可以看一下里边的【SpotMessanger.py】文件,里边有如何加载xml配置文件的方法,还有调用聊天功能接口的函数。这个小mod还是很条理清晰的。分析已有的战斗面板接下来加快速度。我是想在战斗中显示一个独立面板的,而不是DamagePanel或debugPanel那种默认就有的面板,然后我就开始在【res】文件夹中翻找。既然是战斗中显示,那当然要优先看battle有关的脚本,果然,在【res/scripts/client/gui/Scaleform】文件夹中找到了【Battle.pyc】文件,我有一种预感,就是这个玩意了。- g&&w: [8 @+ @. }6 M4 _
反编译后,哇哦,光是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文件位置的参数,那就先用它咯。; Z- Z&&v& v) f0 e! w" E, x
其实选用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函数也是有必要的。8 Y5 ?4 u2 D' r&&Y4 g
这样,我们就确定了一个面板的生命旅程,首先是实例化,然后是start,然后是destroy,至于中间干什么,那肯定是update啦。1 X7 w) n* b! Q; d# K6 c' u- q
啊……如何update呢?这可是个难题,我详细看了【Battle.py】文件,发现了这个_TimeInterval类,懂英文的筒子们从名字上就知道啥意思了,时间间隔。它的功能就是每隔一段时间执行一次特定的函数,具体原理我们先不深究,大家有兴趣可以折腾一下,反正就是callback那一套了,举个栗子,我很困,于是让闹钟每隔5分钟叫醒我一次,我就可以写一段这个教程,然后又困到睡觉,再叫醒,再写一段,再睡觉……* C$ D& B) x' |
好啦,python脚本这边我们算是分析完毕了,接下来就是Flash端了,毕竟UI面板是要交互的。Flash & swf可惜Flash我是不太熟悉的,只能慢慢摸索着来。那些package我先用硕思闪客精灵反编译了【debugPanel.swf】文件,这个算是最简单的swf文件了。
17:57:16 上传
解释一下图中的Actions:MainMovie是直接F9然后输入的代码,不需要选择任何元件,它的作用是全局的。sprite9中的代码是选中元件9后输入的,它作用于元件9(其实里边一个字也没有)。sprite后边有括号的,是Flash中设置过外部链接的。__packages就是外部导入的类了,其中__packages.gfx.xxxxxx格式的类我们如果正确***了【scaleform】插件的话可以无视,不然我们费那么大劲安它干什么。而__packages.net.wargaming.ingame.xxxxxx是我们自定义的类,要按照固定路径放置,在fla工程文件同目录下建立net文件夹,在net里边建立wargaming文件夹,以此类推。
17:58:25 上传
8 T6 E, a7 d1 o. q5 J
交互方法我最开始没有明白debugPanel.swf文件是如何与Battle.pyc中定义的DebugPanel类互相响应的。而在VehiclemarkerManager.swf中我找到了这个addCallBack函数,它向客户端注册了一个swf里的函数,然后python脚本便可以根据注册时传入的函数名字“call”这个函数了。哇哦,总算搞明白了python中Flash类里的call函数(其实是invoke函数调用的swf里的函数,call函数只是对invoke进行了封装)。相应的respond也是一样,区别就是,call是python调用swf里的函数,而respond是swf文件调用python脚本里的函数。后来我看了Scaleform Gfx的《Getting Started》/s/1mgyt5qw,里边标准的交互方法也确实是这样的。还有一本《Technical Appendix》/s/1dDjEH01,这两个doc便详细介绍了交互方法,英文,真是残念……! _$ x* y: n* O# ^+ J. t5 @5 X
# J6 W- ^' F, s' @
. N% d, L* I& o- A
. [9 t2 K8 H9 S$ V$ l
以上,我们便掌握了python脚本、flash制作swf文件、两者之间交互方式。我又一不小心找到了BigWorld的A_P_I,详细一切都准备好啦!!!
本帖最后由 狩土_默 于
18:52 编辑
3年单野路过
新人欢迎积分1 阅读权限40积分327精华0UID帖子金钱2992 威望0
Lv.4, 积分 327, 距离下一级还需 673 积分
UID帖子威望0 多玩草50 草
实战篇终于到了上手的阶段,经过了前几篇的折腾,头已经开始嗡嗡嗡了……
- S5 H1 v9 s! x6 G: ]1 e
新面板的python类还是先从python这边入手。在反编译后的【Battle.py】文件最后添加我们自己的内容。class GF47TextPanel(Flash):& F! V7 Q&&W7 B/ o1 `5 x- T
& & __SWF_FIEL_NAME__ = &GF47TextPanel.swf&
& & def __init__(self):+ f0 g: n2 @8 v: \8 D% `$ j
& && &&&Flash.__init__(self, self.__SWF_FIEL_NAME__)
& && &&&self.__msg = &&
& && &&&self.__timeInterval = None复制代码1 F2 P1 `. `&&M
首先建立一个名为GF47TextPanel(名字你们就无视好了)的继承自Flash基类的类,然后定义一个存储了所要加载的swf名字的字符串__SWF_FIEL__NAME__,再后定义构造函数(__init__,这是每个类都必须的东西,而__del__析构函数不是必须的)。然后继续输入以下代码:
& & def start(self):& && & self.active(True)#将自身是否显示设为“显示”& && & self.__setCandidate(&测试是否可以显示文字&)#下文会提到,更改面板上的信息& && & GUI.ponent)#必须要有的,向GUI root注册自身的UIcomponent,当然也可以像其他的UI面板一样将自身注册到Battle类上,但我们先把这个框架搭起来,以后再优化。& && & ponent.wg_inputKeyMode = 2#A_P_I里没有,wg自己添加的东西,大概是设置键盘事件的接收优先模式吧。反正不设置这个的话,默认是1,然后你的键盘就不管用了……& && & ponent.drawWithRestrictedViewPort = False#暂时不知道啥作用& && & self.movie.backgroundAlpha = 0#看名知意,设置背景透明度,你可以设置为1……& && & self.__timeInterval = _TimeInterval(0.1, '_GF47TextPanel__update',weakref.proxy(self))#实例化一个“时间间隔”,作用是每隔0.1秒激活一次“_GF47TextPanel”里的“__update”函数。后边那个weakref.proxy(self)是建立一个自身的弱引用,大概意思就是比如一个上战场的老兵临行前把老婆托付给了自己隔壁的二狗,假如自己挂了,老婆也不至于晒床单没有帮手,老兵就是这个self,隔壁的二狗就是weakref.proxy(self)……突然感觉好悲伤……& && & self.__timeInterval.start()#启动“时间间隔”,开始每0.1秒执行一次“__update”& && & self.__update()#可以加上,也可以去掉& B9 s/ w# \1 |/ m
我上文分析过,这个类是需要一个启动的阀门的----start,我们不可能在构造函数里做这些工作,因为那时候Battle类的初始化还没完成呢。
然后是destroy():&&w% p: d7 D" F" W6 s/ U0 u4 J5 A
& & def destroy(self):$ [2 M$ n3 y! p9 \( d* a* I( J
& && &&&self.__timeInterval.stop()
& && &&&GUI.ponent)
& && &&&self.close()& V6 B9 F1 R* O* d* y# {&&B
2 Q" z3 j2 [8 F! n- ]
, R/ K" _" f* W# U" T
当战斗结束后,销毁战斗面板时触发的事件。再后是__update():& & def __update(self):
& && &&&pass#先跳过,这里的东西战斗中每隔一段时间便执行一次,以后筒子们添加东西大都要在这里做文章。复制代码, M. u* M0 O/ \7 l6 ?- J
最后是与swf文件交互的函数:& & def __setCandidate(self, msg):
& && &&&self.call(&GF47TextPanel.setAndShowCandidate&, [msg])#记得这个“call”不,它呼叫swf文件中注册的那个“GF47TextPanel.setAndShowCandidate”函数,并将参数“msg”封装成一个列表一并传递过去。“msg”在本例中就是一串字符串了。复制代码7 Q' F' X, H. U3 B* J
OK,这个“GF47TextPanel”类我们就完成了。
7 o0 h. l8 C$ ?5 ?( `' u
将“GF47TextPanel”添加到战斗中但貌似我们创建的类目前为止没有和Battle类产生任何关联,我们接下来将模仿那些debugPanel、DamagePanel等,将start与destroy添加到Battle类中。在【Battle.py】文件中找到之前分析的Battle类,在afterCreate函数中照葫芦画瓢,在那一列“self.__xxx = xxx(self.proxy)”后添加:self.__GF47TextPanel = GF47TextPanel()复制代码在那列“self.__xxx.start()”后添加:self.__GF47TextPanel.start()复制代码在Battle类的beforeDelete函数中,找到那一列“self.__xxx.destroy()”,在后边添加:self.__GF47TextPanel.destroy()复制代码如此这般,我们的新面板就可以在战斗中显示啦。但光这样其实是不够的,假如现在就完事的话,我们会发现,当战斗中使用快捷键“v”,就是那个隐藏所有面板的键时,我们的新面板仍然固执地停留在屏幕上,于是我们可以找到Battle类中的showAll函数,在它最后添加一句:self.__GF47TextPanel.active(isShow)复制代码这样一来,快捷键“v”也对我们的新面板起作用了。- |0 F) o/ M; x
好了,编译这个【Battle.py】文件,如果有错误就把“#”号和注释删掉。在【res_mods/0.9.3/scripts/client】文件夹(就是CameraNode.pyc所在的文件夹)中新建【gui/Scaleform】,还记得为什么不?要保持路径相同。将编译好的【Battle.pyc】文件拷贝到里边。&&O&&d! Y$ D! J
制作swf文件接下来开始制作与GF47TextPanel类相交互的swf文件。+ y! U, k- H( _
工程设置新建一个AS2工程,大小为750x32像素,你们随便。帧率选30,好像那些原有的面板就是30的帧率。没必要发布HTML版本的,所以去掉勾勾。Flash版本其实没多大关系,我选的flash8。
18:09:01 上传
7 G: R7 {7 y! f- n* o# J
添加动态文本和背景在合适的位置上添加一个动态文本。给动态文本起一个合适的实例名称,这样它就可以在ActionScript里被直接访问了,我的是GF47Text。为了安全起见,我给swf嵌入了中文字库,和必要的拉丁字母。
18:10:07 上传
我新建了一个层,作为背景,就是简单地画了个框框,然后转换成了元件,也起了个实例名。/ e6 ]- V&&L, l2 a
添加AS2脚本按下“F9”,打开脚本编辑界面,输入以下代码:import gfx.io.GameD//导入GameDelegate包* a. K* V* b# V+ Q) o/ w
Stage.scaleMode = &noScale&;//设置缩放方式为不缩放) t+ [# c# [: \$ N
Stage.align = &BL&;//设置对齐方式为左下角对其. g8 l7 ?6 D0 e4 u) B9 p
GF47Text.text = &Made by GF47&;//设置动态文本的text属性值为“Made by GF47”
GameDelegate.addCallBack(&GF47TextPanel.setAndShowCandidate&, this, &setAndShowCandidate&);//将“setAndShowCandidate”函数注册到游戏中,函数名为“GF47TextPanel.setAndShowCandidate”,与python脚本中的“call”相交互
GameDelegate.addCallBack(&GF47TextPanel.showCandidate&, this, &showCandidate&);//与上句差不多意思7 A. D7 U! M. X( L0 O
function setAndShowCandidate(msg:String):Void//定义“setAndShowCandidate”函数
& & GF47TextBackground._visible =
& & GF47Text._visible =# F) V" I% `1 a0 q
& & GF47Text.text =//改变动态文本的text属性值,显示“msg”内容2 {0 N! r% w4 G" H
function showCandidate(isShow:Boolean):Void//显示或隐藏
& & GF47TextBackground._visible = isS: i. _* Y/ J% d
& & GF47Text._visible = isS
GameDelegate.addCallBack这个函数便是交互的关键了,上文已经说过了,不明白可以查看那两个文档。总之以后我们就用这种方式来交互。本例中没有设置respond。% r7 g- s' @1 N# ~- d
发布swf文档完成上边的操作后,我们就可以发布啦。点击那个scaleform插件的发布按钮,我们的swf就发布出来了。发布的swf名称要与python脚本中设置的那个“__SWF_FILE_NAME__”相吻合。
18:12:46 上传
5 q: p. v% \( d% j: T
18:24:37 上传
* c$ t$ x3 K! y( r
将发布出来的swf拷贝到【res_mods/0.9.3/gui/scaleform】中,大功告成。
测试打开一个战斗回放,呦,已经有了啊,并且它的文本已经改变了。在脚本中的“__update”函数中我们并没有设置什么,我们只是在“start”中改变了一下文本的值。如果想在战斗中更新文本,比如显示200米范围内敌军数量,友军数量等(这只是一个例子,我可能会以后把它实现,毕竟ime的问题失败了),可以在update函数中添相应代码,最后将处理好的文本传给swf文件。
本帖最后由 狩土_默 于
02:37 编辑 &&\2 z$ [, M: Y+ G1 b&&C
(322.65 KB, 下载次数: 1)
18:26:02 上传
下载次数: 1
&牛!字太多!慢慢看!&
3年单野路过
新人欢迎积分1 阅读权限40积分327精华0UID帖子金钱2992 威望0
Lv.4, 积分 327, 距离下一级还需 673 积分
UID帖子威望0 多玩草50 草
我本来是想解决战斗中输入法候选框不显示的问题的,找到的BW_A_P_I里也有PyIME类,脚本中也可以引用BigWorld.ime. candidatesVisible,但偏偏它一直是False状态。后来我看Scaleform文档,发现新的Scaleform好像已经有了对东亚IME的支持,也就是说,WG大概是用了Scaleform的方法,而屏蔽了BigWorld的默认方式……4 |, s5 Z: W3 F6 ^! p6 x4 j2 [* o
0 t4 F: r2 J& A- h2 \
(?°Д°)?? ┻━┻ 特么的你玩我啊!!!
1 ~$ W; `! x( a7 b, l
之后我看到【res/gui/flash】文件夹里有【ime.swf】文件,反编译了一下,果然,虽然这是个AS3版本的文件,但还是很明了。Scaleform的方式是在swf文件中处理东亚字符的所有问题,传给游戏的只是最终选择的那个词组,也就是说,所有问题都处在这个swf文件上。这个问题找个会AS3的人,比如做网页的,解决起来是很简单的……但是我是不太懂Flash……不知道二雷连这么个错误都能拖n个版本为啥……好吧我这几天去补一下AS3……说点题外话,其实说起来flash技术已经有些过时了,这年头google苹果大微软基本都要把flash这玩意撇开自己单干,简单来说就是不带你玩了,这就是没有像格力那样掌握核心科技的后果,被人掐着脖子走。所以华为那种方式才是正道啊,有实力,敢说话,不用看别人脸色,哪像二雷这种坑货,连个swf都不敢改……哎不说了,有打广告的嫌疑……7 |4 C. S0 g' Y0 J% K% ?0 u/ o
好啦,这篇教程就到这里了。我仅仅是搭了一个mod的基本框架,筒子们可以用它来实现各种功能。希望大家发挥想象,折腾的愉快……2 T1 u1 `: |% a2 B: {& K
最后附上一张截图,我大多炮塔神教万岁!!!
18:46:19 上传
本帖最后由 狩土_默 于
18:57 编辑 ; A&&_8 L. |& t&&^! Z1 R&&\3 `
3年单野路过
新人欢迎积分1 阅读权限60积分3175精华0UID帖子金钱24553 威望-2
Lv.6, 积分 3175, 距离下一级还需 1825 积分
UID帖子威望-2 多玩草386 草
牛!字太多!慢慢看!
新人欢迎积分0 阅读权限70积分9014精华0UID帖子金钱56478 威望0
Lv.7, 积分 9014, 距离下一级还需 986 积分
UID帖子威望0 多玩草483 草
这技术帖很不错啊,多谢楼主!!
新人欢迎积分0 阅读权限50积分1469精华0UID帖子金钱746 威望0
Lv.5, 积分 1469, 距离下一级还需 1031 积分
UID帖子威望0 多玩草0 草
能不能给来个现成的
秋山S优花里
新人欢迎积分0 阅读权限50积分2251精华0UID帖子金钱19285 威望0
Lv.5, 积分 2251, 距离下一级还需 249 积分
UID帖子威望0 多玩草0 草
谢谢楼主的教程~~~' V7 k: r0 q5 N$ L. A# C* T: _: |
吾辈是学渣,所以纯支持了~~~
傲?重巡加藤惠
新人欢迎积分0 阅读权限60积分3406精华0UID帖子金钱25479 威望0
Lv.6, 积分 3406, 距离下一级还需 1594 积分
UID帖子威望0 多玩草638 草
一个只会点涂装和稍微改点模型的支持一下撸主这种技术宅
专注各种风格的涂装30年
新人欢迎积分0 阅读权限40积分972精华0UID帖子金钱3316 威望0
Lv.4, 积分 972, 距离下一级还需 28 积分
UID帖子威望0 多玩草35 草
天降-小裤裤
新人欢迎积分0 阅读权限80积分13122精华0UID帖子金钱315060 威望4
【小心被屏蔽】
Lv.8, 积分 13122, 距离下一级还需 6878 积分
UID帖子威望4 多玩草1189 草
新人欢迎积分1 阅读权限90积分29455精华0UID145100帖子金钱377766 威望1
注册时间:号17点05分
Lv.9, 积分 29455, 距离下一级还需 5545 积分
UID145100帖子威望1 多玩草2068 草
新人欢迎积分1 阅读权限50积分1288精华0UID帖子金钱27317 威望-2
Lv.5, 积分 1288, 距离下一级还需 1212 积分
UID帖子威望-2 多玩草115 草
新人欢迎积分1 阅读权限70积分9760精华0UID帖子金钱54298 威望4
Lv.7, 积分 9760, 距离下一级还需 240 积分
UID帖子威望4 多玩草1953 草
技术贴赞一个!
SerB wrote:
Do not play on the German tanks.
Do not play on Soviet tanks.
Do not play on American tanks.
Do not play on Chinese tanks.
Do not play on the French tanks.
Do not play on British tanks!
Do not play team games.
马年新春勋章
手机APP马年迎春,马上有钱!
元宝专属一阶勋章。已绝版
365天!天天有你
连续签到1年即可获得
YY论坛外管
YY论坛外管
手机论坛勋章
APP发帖双倍积分,登陆即送勋章!
需要金钱:1100
手机盒子客户端点击或扫描下载
Powered by