Thursday, April 24, 2008

改变游戏中的字体

游戏里面用的字体文件有两个:font3.e16和font3.c16。第一个是128个ASCII字符,点阵大小为16*8;后一个为BIG5码的汉字,点阵大小为16*16。

使用工具可以将系统中的字体转为游戏可用的格式,但并不是所有字体都合适。一般字体在9pt时如果仍能够保持锐利,那么在游戏中就会有比较好的效果。最常见的这类字体就是细明体和宋体(楷体GB2312也可以,但是繁体字库不全),如果你知道其他适合的字体或者好的建议,欢迎告诉我们知道。

这个是更换了英文字体,英文字体最好是等宽的:

z_048

这个是把原来的细明体改小了一号:

z_050

这个是标楷体,效果很模糊:

z_043

这个是微软正黑,也不怎么样:

z_042

这里是我生成字库使用的工具和一个教程。

使用ts2.exe,选择字体,要选择台湾中文(Big5)。

clip_image002

调整好汉字的位置,然后高度改成32,把“上下”加上16。

clip_image004

点“生成”,即可生成点阵字库。

因软件是未注册版,所以每个字都会多出一个斜线,而使用32*16的尺寸可以使汉字刚好避开斜线。

clip_image006

使用这个程序会将字体上半部分去掉,生成font3.c16文件,可以直接用在游戏中。

这类工具的算法都很清楚,但这个软件注册费的性价比实在不怎么高,何况我只需要其中的一小部分,而不注册的话生成的字会有删除线,所以我想了一个办法避开删除线。

google的审查好严,居然禁止这个文件,可能是文件中含有木马。

Tuesday, April 22, 2008

多重循环的代码



像弯月一样。要是连续写几个,就像苏州的锦带桥。


Sunday, April 20, 2008

有关“插入事件改写系统”的碎语


这个post不是什么技术相关的,大概算是一个无聊碎语的集合。

我以前编写过一个新的伤害公式,那时是完全用十六进制代码写的,首先将汇编代码译成十六进制代码,call和jmp指令的地址还都要自己计算出来,非常麻烦也容易出错。

使用物品直接触发事件是谁最早提出来的已经搞不清楚了,最早跟我提这个的是Guest。战斗中调用事件其实也不知最早是谁的主意,总之用事件修改伤害公式也是很早之前就有人想过(但那时想怎么改,直接改汇编代码么?那样还是有很大限制的)。

用物品调用事件,就可以任意增加大地图事件了。那么自然就会想到,战斗中能不能调用事件?如果能的话,需要什么样的事件?

我看反汇编的代码时,发现有一个子程似乎是控制选择攻击目标的,这就是有了战斗指令的最早构思。最开始是想有一个选择目标的也许就够了,但后来越想越复杂。

最初只构思了法宝,后来发现也许只有法宝还是不够的,于是又增加了武功调用事件,这样有些功能就必须直接操作内存才能用,但是这时已经是战斗指令搞出来一个多月了。所以从0.10到0.20,指令没有增加,却有了非常大的变化。

后来所想的就是找许多适当的位置插入事件了,这样系统许多功能就完全可以自定,随作者的想法了。

不过我自己倒是没开放太多地方,z.dat文件里面的空间其实还有很多,插几十个事件还不成问题,但插在哪却要好好想一想。如果选的地方好可以事半功倍,选的地方糟糕就有可能没有效果甚至导致游戏功能出错。

无论如何,“插入事件”总算开了个花,希望能看到结果的那天。

Thursday, April 17, 2008

Vista SP1



看来不错。


Monday, April 14, 2008

扩展战斗指令0.20

因为目前对战斗的了解已经比刚开始计划战斗指令时深入得多,所以此次对战斗指令进行了大规模改写。

战斗指令的变化非常大:

28:这条指令用处不大,但暂时保留。
29:判定人物回合是否结束的方式有所改变。为简化武功事件增加可以跳过选择目标画面的选项(4.15)。
30:取人物R序号改为取人物战斗属性,可以获取更多的战斗属性。与原指令不兼容。
31:取人物敌友信息改为写人物战斗属性。原功能用30指令(偏移2)代替。此指令实际上在以前的版本中是错误的。

44:播放效果增强功能。
45:闪烁改为显示数字。
46:显示人物属性改为设定效果层。原功能需用49指令代替。
47:改变人物改为回复人物静止贴图。原功能用31指令(偏移0)代替。

49:不变。

此外对上个版本中插入事件导致战斗跳出的错误作了修正。添加了几个新的插入事件。
说明文档中的示例有些是较早时编写,所以某些位置可能并没使用新指令,而是直接写内存。在说明文档中附带了一个反噬效果的实现方案,可以作为增加状态效果的参考。

如果您已经开始利用原来的指令编写一些事件,那么我为此次更新对您造成的不便表示歉意。

此版本仍是测试版,主要是某些事件插入的最佳时机尚不完全确定。


4.16,增添载入进度预处理事件,测试时使用KG的改调色版指令基本成功。版本号未更改。

BattleKDEF0.20.zip

Friday, April 11, 2008

扩大队伍人数?

理论上可以把队伍的人数扩大一倍,就是把以前读字的语句改成读字节。

问题是人的名字可能没处放,战斗需要改得多些,不一定真的有用。

z_032

Sunday, April 06, 2008

反汇编z文件


我以前找到的反汇编结果可能是游泳的鱼最早注释的。

画面引擎,声音的部分基本是不可能修改的。文件后段有一大堆子程根本不知是什么鬼东西,有可能是编译器自己加上去的。

比较清晰的几个地方是:

  • 系统菜单;
  • 进入场景;
  • 事件系统;
  • 战斗系统。

这些其实也是大家最关心的几个地方,还有比较重要的是主角在大地图上行走的部分,但这个似乎没什么好改的。

Saturday, April 05, 2008

49号指令应用:“从队伍中选择一个队员”选单


下面的指令片段可以生成一个选择队员的选单,在制作新型装备的时候可以用到。


;Kdefnum=1023
50 0 0 2 0 0 0 0 ; 50(32):变量赋值 [X0]=2
数字2改成所需选单的样式,含义见下面
50 49 8336 2 0 1 0 0 ; 50(32):调用任意子程
50 48 0 1 0 0 0 0 ; 50(32):调试指令,显示变量 [X0] -- [X0]
0 ; 0(0)::空语句(清屏)
-1 ; -1(FFFF):事件结束

 

此事件直接调用游戏中22090子程,该子程有一个自变量,表示选单的样式:

0-医疗,1-解毒,2-状态,3-装备,4-修炼,5-使用,6-离队。

返回值为队伍内序号,范围是0~5,如按了esc键,返回值为-1。

如果需要一个通用的选单,建议将原版中“要谁离队”4个字改为“选择队友”,需要选择队友时即调用6号样式的选单。尽管真实的离队选单也会有相同变化,但不会产生误解。

49号指令应用:任意转换场景


目前转换场景多是用动态改写跳转口的方法。经测试,以下指令可以比较方便地改变场景,工作量小了许多。
这里没有改写大地图坐标和场景内坐标。


;Kdefnum=1022
  1 0 0 0                        ;  1(1):[xxx]说: 小兄弟,我们现在去桃花岛。
这句是对话指令,无关紧要。
  50 25 0 0 10590 29 75 0        ;  50(32):保存给定地址数据 [1D-295E+0]=75(Int)
75为桃花岛的编号,根据实际需求修改。
  50 25 0 1 -27969 2 195 0       ;  50(32):保存给定地址数据 [2-92BF+0]=195(Byte)
  50 49 -28218 2 0 1 0 0         ;  50(32):新指令,暂时没有解释
  50 25 0 1 -27969 2 233 0       ;  50(32):保存给定地址数据 [2-92BF+0]=233(Byte)
  0                              ;  0(0)::空语句(清屏)
  -1                             ;  -1(FFFF):事件结束

Thursday, April 03, 2008

修改对话框每行字数的源码

在对话框调整器里面有这个功能。对话框每行字数并不是由程序自身决定的,而是在对话文件中写的“*”决定换行的位置。

对话文件talk.grp和talk.idx的格式非常简单,talk.grp文件只要把全部内容按位取反就是Big5的明码,星号表示换行而0表示一条结束。talk.idx里面保存的是每条对话的长度,也可以认为是下一条的起始位置。

我在重整对话文件“*”位置时使用的是如下的方法。算法本身很简单,根据读入的第一个字节判断字符是否是Big5码里面的,这时需要把2个字节作为一个字符处理,idx文件就直接生成一个新的。

这个算法是用 Object Pascal 写的,一些不太关键的代码略去了,注意这里并没有先取反,而是直接操作的。

file0:=Fileopen(edit2.text,fmOpenread);
//file0用来打开原始的talk.grp文件

length:=Fileseek(file0,0,2);
filegrp:=filecreate('talk1.grp');
fileidx:=filecreate('talk1.idx');
i:=0;
fileseek(file0,0,0);
while i<length do
begin   
  fileread(file0,ch,1);
  i:=i+1;
  if (c=0) and (ch>=128) and (ch<>213) then
  begin
    filewrite(filegrp,ch,1);
    p:=p+1;
    x:=x+1;
    c:=0;
  end;
  //以上是对字符为标准ASCII字符的处理

if ch=213 then
  begin
  end;
  if (c=0) and (ch<127) and (ch>0) then
  begin
    filewrite(filegrp,ch,1);
    fileread(file0,ch,1);
    i:=i+1;
    filewrite(filegrp,ch,1);
    p:=p+1;
    x:=x+2;
  end;
  //以上是对Big5字符的处理

if (p>=p0) and (ch<>0) then
  begin
    p:=0;
    ch1:=213;
    Filewrite(filegrp,ch1,1);
    x:=x+1;
  end;
  //在适当位置添加星号

if (ch=0) then
  begin
    x:=x+1;
    filewrite(fileidx,x,4);
    Filewrite(filegrp,ch,1);
    p:=0;
  end;
  //重新编制索引

end;

有兴趣的朋友可以据此减少重复工作的时间。

Tuesday, April 01, 2008

物品调用事件


物品调用事件已经比较完美地实现了。除了物品功能本身之外,清屏指令和对话指令也要针对大地图重写。

那么用这个功能可以实现什么呢?来畅想一下!

  • 在罗盘上挂一个事件,可以画出地图缩略图,标出当前的位置。
  • 队友加入或离开时给一个信物,使用这个信物就可以直接呼唤队友加入,从此无需费神去找队友,制作队友加入离开事件时也会简单很多。
  • 在大地图上挖矿,打猎(南宫老师构思)。
  • 某些物品可以调用一段对话,相当于复杂的物品说明。
  • 特殊的秘笈修炼条件,特殊的药品性能。
  • 可以制作重排队伍的指令,相当于《轩辕剑伍》里面一些队友可以在后排休息?

还有什么主意?

在事件中取得当前物品编号似乎可以这样做:

x1=[54B74]*4
x2=[18FE2C+x1]

x2即物品编号,x1是物品在选单中的顺序号。
 

还有一些新的设想,比如在某些地方插一个事件,这样就可以用事件来改写某些系统功能。例如在计算伤害的地方插一个事件,并事先截获几个关键参数,就可以按自己的想法改写伤害公式了;比如截取攻击人物、使用的武功和防守人物,那么为特殊人物,特殊武功和特殊装备编写特殊伤害公式或特殊防守公式都是可能的,甚至能够让某些武功带有特殊攻击效果。

哪些地方值得插入事件需要考虑一番,做到修改器里面就比较困难了。

遥控车



100HK$的遥控车,郁闷和无聊的时候可以拿来消遣。



ykc