仙五前MOD增强工具

下载地址

目前工具的最新版为2.0。打开mod.xml可查看version,如果小于此值可以选择更新!

下载地址

此工具用于对主程序进行Patch,从而开放更加强大的MOD功能!除说明文件Readme.txt外,压缩包内有一个主文件夹和一个demo文件夹,下面分别进行介绍。

主文件夹Pal5Q-MOD

请把此文件夹放在游戏主目录下。

Pal5Q.exe

此为原版v1.04游戏主程序,可用作备份。卸载MOD时,请将该文件覆盖修改后的Pal5Q.exe,以达到还原主程序的目的。

Pal5Q-MOD.exe

此程序将此目录下原版Pal5Q.exe读入内存,解析mod.xml文件后修改相应内容,然后输出覆盖游戏主程序。每次mod.xml修改后,如果想要测试效果,都要运行一次此程序以应用修改。
程序运行需要.NET 4.0,win7及以上windows系统都有包含。如果无法运行,需要下载.NET Framework

mod.xml

这是MOD的核心文件,需要和Pal5Q-MOD.exe在同一个文件夹下。MOD制作者通过对此文件内容进行修改来控制游戏数据。下面对文件中的一些标签作简要说明。

dest

1
<dest 描述="修改后主程序文件位置">../Pal5Q.exe</dest>

输出的游戏主程序位置。假定游戏目录为D:\Pal5Q,MOD工具的目录为D:\Pal5Q\Pal5Q-MOD,那么该条应填写../Pal5Q.exe(表示MOD工具目录的上一级目录下的Pal5Q.exe)。

source

1
<source 描述="原版主程序文件位置">Pal5Q.exe</source>

原版游戏主程序位置。假定原版文件放在了MOD工具目录D:\Pal5Q\Pal5Q-MOD下,那么该条应填写Pal5Q.exe(表示MOD工具同目录的下的Pal5Q.exe)。

data

有很多row作为子元素。每一行都是一条记录,其中属性有效可供修改。当有效设置为0时,Pal5Q-MOD.exe会忽略此条记录,即保持原游戏默认值;否则将修改为指定值,即将描述中的x换成。例如:

1
<row id="118" 有效="0" 偏移="2146296" 类型="sbyte" 值="1" 描述="贴有编号469(聚气)的角色扣血时,气增加x。"/>

若将有效设置为1,而设置为2,则聚气的效果变成:

贴有编号469(聚气)的角色扣血时,气增加2。

请注意:值的取值集合受类型限定! 如下表:

类型取值范围备注
sbyte-128到127之间的整数包含两端
byte0到255之间的整数包含两端
int-2147483648到2147483647之间的整数包含两端
uint0到4294967295之间的整数包含两端
float不太大即可,可保证6位有效数字
double保证15位有效数字
map:n参见map标签其中n表示map的id
bytesbyte的数组base64,不需要管

如果不在需求范围内,条目会被忽略,控制台会输出错误信息。

也有的记录条目不允许修改,例如:

1
<row id="200" 有效="1" 偏移="1866349" 类型="byte" 值="0xC4" 描述="是否修复状态消失BUG。“有效”设置为0则不修复,设置为1则修复。请勿修改其他选项!"/>

对于每个条目,只要理解描述即不难判断是否允许修改值。

部分条目效果介绍

1
<row id="0" 有效="0" 偏移="2986396" 类型="bytes" 值="PZinTAKQdQXoB/v//4vN" 描述="打开控制台" />

此项设置有效为1可打开游戏内控制台,具体可见此帖11楼及以后

1
2
<!--扩展MOD相关 下一行的“有效”设置为1则打开MOD扩展,设置为0则关闭MOD扩展。请勿修改其他选项!-->
<row id="1" 有效="0" 偏移="2873606" 类型="bytes" 值="(略)"/>

此项设置有效为1可打开MOD扩展功能,详情在后面的章节中介绍。此外还使回合开始时调用脚本,见ref中id="643"的行,以及demo/script/begin_round.lua

1
<row id="3" 有效="0" 偏移="0x1C1969" 类型="bytes" 值="6NJB5P+JwYnKaIQ8AADoFK8PAItN7IsB/5CMAAAAUInR6FGoDwCDfQgKD5TAD7bAUOhBqA8AidHo+qgPAIsV4EVNAoPiAZA=" 描述="接管普攻伤害。普攻时调用15492号脚本。"/>

此项设置有效为1可接管游戏内的普攻伤害计算函数,在Lua中自行编写伤害计算函数。详细使用方法请参考demo/script/atk_script.lua

1
<row id="200" 有效="1" 偏移="1866349" 类型="byte" 值="0xC4" 描述="是否修复状态消失BUG。“有效”设置为0则不修复,设置为1则修复。请勿修改其他选项!"/>

此项设置有效为1可修复仙五前的状态消失BUG,具体见仙五前资料百科

1
<row id="201" 有效="1" 偏移="1861656" 类型="byte" 值="1" 描述="施加已有状态时,回合取代还是回合叠加。“有效”设置为0则取代,设置为1则叠加。请勿修改其他选项!"/>

此项设置有效为1可以将回合取代修改为回合叠加。举例:

夏侯瑾轩使用灵砚绘虎为我方全体加10回合强袭,接着又因为仙福的效果而获得了3回合强袭,原游戏回合取代的结果是强袭回合数变为3,若此项有效则强袭回合数变为13。

1
<row id="202" 有效="1" 偏移="0x20BEF8" 类型="bytes" 值="gH0QAHVCkA==" 描述="即死的扣血是否可因玄甲而减半。“有效”设置为1则不能,从而修复BUG。请勿修改其他选项!"/>

若满足玄甲触发条件的角色被施加了即死状态,原游戏将扣除一半精,结果人物精不为0但失去行动能力,从而出现BUG。将此条设置有效可以避免此BUG。

ref

有的条目不止一处偏移需要修改,但有部分属性需维持一致,故使用参照值。总而言之,此项可直接忽略。

map

当data条目的类型为map:n时,其只能取于id为n的map诸条目中的key值。例如:

1
2
<row id="100" 有效="0" 偏移="2146011" 类型="map:1" 值="精" 描述="对于贴有编号457(玄甲)的角色,当x小于……"/>
<row id="101" 有效="0" 偏移="2146036" 类型="map:1" 值="精上限" 描述="……x的1/4时,受伤减半。"/>

此处两条的类型为map:1,于是查看id=1的map:

1
2
3
4
5
6
<map id="1" 描述="角色的成员函数">
<row type="int" key="精" value="0xAC"/>
<row type="int" key="精上限" value="0xB0"/>
<row type="int" key="神" value="0xB4"/>
<row type="int" key="神上限" value="0xB8"/>
</map>

从而只能填以下四者之一:精、精上限、神、神上限。MOD工具在解析时,向主程序写入的值从key转换为对应value

实际在处理map:2或map:3时,请选择map表中有的、最接近需要的一项浮点数填写。

macro.lua

此文件原存于游戏目录script\mainline下,用于自定义lua函数以供使用。如果前述mod.xml中开启了MOD扩展功能并要使用Pal5Q-MOD来载入游戏,请先将此文件放置到script\mainline下覆盖原版macro.lua;否则请不要放置到script\mainline,否则无论哪种情况都会引起BUG。

开启扩展功能后,以下函数被新增,可供lua使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
battle.AtkToNpc(id)     --玩家攻击指定id的npc(此函数不在macro中定义,可以直接使用)
battle.GetRndNpc() --和游戏一样,但此函数被我覆盖,所以需要重新定义
player.GetHP(id, flag) --和游戏一样,但此函数被我覆盖,所以需要重新定义
npc.GetHP(id, flag) --和游戏一样,但此函数被我覆盖,所以需要重新定义
player.GetMaxHP(id) --玩家精上限
npc.GetMaxHP(id) --npc精上限
player.GetMP(id, flag) --和游戏一样,但此函数被我覆盖,所以需要重新定义
player.GetMaxMP(id) --玩家神上限
player.GetQuickness(id) --玩家身法
player.GetLuckyness(id) --玩家运势
npc.GetAtk(id) --npc攻击
player.GetDef(id) --玩家防御
npc.GetDef(id) --npc防御
npc.GetMagicAtk(id) --npc仙攻
player.GetMagicDef(id) --玩家仙防
npc.GetMagicDef(id) --npc仙防
player.GetHit(id) --玩家命中
npc.GetHit(id) --npc命中
player.GetMiss(id) --玩家闪避
npc.GetMiss(id) --npc闪避
player.GetBlock(id) --玩家招架
player.GetCrtical(id) --玩家暴击
npc.GetCrtical(id) --npc暴击
player.GetCombo(id) --玩家连击
player.GetMagicBonus(id, attr) --玩家某系加成(比如夏侯、火返回0.3)
player.GetMagicResistance(id, attr) --玩家某系抗性(比如夏侯、火返回0.3)
npc.GetMagicResistance(id, attr) --npc某系抗性
player.GetStateResistance(id, attr) --玩家状态抗性(仅0-9和29号)(比如瑕、中毒返回30)
npc.GetStateResistance(id, attr) --npc状态抗性
player.CheckClothesFuZhou(id, fuzhouID) --玩家衣服上是否有指定符咒(1有0无)
player.CheckWeaponFuZhou(id, fuzhouID) --玩家武器上是否有指定符咒
player.CheckFuZhou(id, fuzhouID) --玩家是否有指定符咒。一般用这个就好了
player.GetDP(id) --玩家气
player.GetStrength(id) --玩家力
player.GetStamina(id) --玩家体
player.GetSpeed(id) --玩家速。注意原游戏里面有SetSpeed,和速属性无关
player.GetMagic(id) --玩家术
player.GetLuck(id) --玩家运
player.GetXiuWei(id, attr) --玩家某系修为
player.GetWeapon(id) --玩家武器编号(无返回0)
player.GetClothes(id) --玩家衣服编号
player.GetShoe(id) --玩家鞋子编号
player.GetAccouters(id) --返回两个值,分别为两个首饰的编号

如果觉得函数名字不合适,可以自行于macro.lua中修改,但请勿修改函数定义

demo文件夹

这是一份demo,是寻仙往事2.0的未完工产物的一部分,用来展示回合开始脚本以及普攻接管脚本的使用方法。原计划是MOD做完之后再和MOD工具一起放出来,但是做MOD时极其缺乏灵感,估计无法完成,因此先将工具整理发布了。注意这里的demo展示文件中有些函数是没有定义的(因为这些文件只是MOD的一部分),因此关键是要阅读和理解其使用方法。在MOD制作过程中我已经多次通过了一场战斗的完整测试,不过没有经过其他人检验,不能确保功能完全有效,如发现BUG希望予以反馈!

回合开始脚本

mod.xml中开启MOD扩展后,战斗系统中每个人物回合开始时(状态清算后)会调用编号15491的脚本,因此需要在scriptlist.ini中定义15491=begin_round,然后begin_round.lua即可生效。在该脚本中,可以通过battle.GetActingPlayerID()来获取当前回合行动者的ID,包括敌人ID也可以如此获得。
有了这样一个脚本后,一个很明显的好处就是我们可以很容易自定义状态了,比如写个回合开始扣多少血的状态都是很简单的。需要注意的是,由于该脚本是状态回合数清算后执行,如果某个自定义的状态该回合刚好消失,那么在这个脚本中会探测不到此状态。

普攻接管脚本

mod.xml中开启普攻接管后,战斗系统中每个人物普通攻击时会调用编号15492的脚本,并且绕过原有的伤害计算,因此需要在scriptlist.ini中定义15492=atk_script,然后atk_script.lua即可生效。为了拿到Lua脚本的值,我将PushParam改成即时执行,在Atk脚本里将传递的值PushParam上去。主程序在调用脚本后,手动拿到传上来的值,并且进行解析。
虽然我们可以获取当前行动者ID,也就是攻击者ID,但无法获取被攻击者ID,因此主程序会将这个ID传入Lua,作为函数atk_script的第一个参数。此外还会传入一个布尔变量表示这次攻击是否是连击。为了能将本次攻击的伤害值、是否触发暴击、闪避、招架等传给主程序,开发者需要在最后调用一次ReturnAtkArgs函数。因此MOD开发者如果要接管普攻,注意别忘了将我的atk_script.luaReturnAtkArgs函数定义原样拷贝过去使用。

macro2

如果你仔细阅读了我demo中的脚本接管函数,会发现有很多函数来源于自定义宏macro2.lua。这是我的一个示例,或者说推崇的解决方案,可以减少代码量和记忆量。特别是在自定义宏中对主程序的一些函数经过“继承”后,如果有什么改动需求都很容易实现。
举个例子,自定义宏中有一个获取防御的函数:

1
2
3
4
5
6
7
8
9
10
11
12
function GetDef(tid)
local def
if IsPlayer(tid) then
def = player.GetDef(tid)
else
def = npc.GetDef(tid)
end
if CheckStat(tid, 11) then --坚盾
def = def * 1.25
end
return def
end

在这里我就直接判断了角色是否有坚盾状态,如果有那么防御力提升25%。在非宏脚本里,每次我们需要获取防御时,就应该直接调用GetDef。这样后期如果我们觉得这个25%不合适,或者想要加一个类似破甲的状态,只需要改动此处函数即可。

2.0更新说明

这次是一个较大的更新,如果之前使用1.x版本,更新后请注意可能会有不兼容之处,因此需要仔细阅读更新说明来酌情修改。

  • MOD工具的结构和使用方法发生变化。现在我们不通过创建和运行临时主程序文件达到目的,而是将原版文件备份下来,直接将修改应用到主程序上。现在的使用流程为:修改mod.xml,然后运行Pal5Q-MOD.exe,最后运行游戏目录下Pal5Q.exe验证效果。发布时需提供安装和卸载,安装不必提供mod.xmlPal5Q-MOD.exe,只需提供修改后的Pal5Q.exe并备份原版的即可。卸载时需用原版的主程序覆盖修改后的主程序。
  • macro.luaGetMagicBonusGetMagicResistance的定义发生变化。出于某些一致性考虑,原来的30现在会返回0.3。
  • 增加普攻接管功能,为此占用编号15492。同时将1.1版本提供的回合开始脚本编号15491由可修改变为不可修改。

作者:风靡义磊
有任何问题或建议,请于此处交流,或直接在下方的评论区评论。