Welcome Guest ( Log In | Register )

欢迎访问本站。游客仅能浏览首页新闻、版块主题、维基条目与资源信息,需登录后方可获得内容发布、话题讨论、维基编辑与资源下载等权限。若无账号请先完成注册流程。
2 Pages V  1 2   
Reply to this topicStart new topic
> WeiDU不完全说明, 深坑待填
Baldur's Gate
四是而非
2017-12-04, 16:52
Post #1


特珞骑士
Group Icon
 478
   10

Group: Avatar
Posts: 307
Joined: 2012-04-17
Member No.: 48323


WeiDU不完全说明

作者:四是而非 即 c4_angel
一个半吊子modder


前言
  • 本文内容为原创,但也会引用其他国内外优秀mod的内容。转载请注明出处(自我感觉良好ing)!
  • 这不是一个mod制作教程,初学者、浅入门者请先食用Machohy版主 博德之门完全索引Mod制作相关内容 部分。点击进入
  • 本文仅着重于WeiDU结构与语法的讲解(部分直接翻译自WeiDu说明文档),旨在帮助modders借用WeiDU的强大功能,更省时、省力的进行mod开发。但本文仅基于若干年来自己的mod制作经验,显然无法涵盖WeiDU所有功能,敬请谅解。
  • WeiDU基本支持所有无限引擎的游戏,无论原版还是增强版,但笔者只有过博德之门mod的开发经验,本文的内容是否在冰风谷或异域镇魂曲中也可使用须先进行测试。
  • 笔者写作能力不佳,细心不足,耐性有限,而这偏偏是个深坑。因此:
    • 前期恐怕难有很严谨的顺序可言(其实WeiDU自己的说明文档也够乱的),楼层顺序与目录顺序不一致的问题尽情谅解。
    • 内容错漏与typo极可能出现,敬请指出。
    • 更新间隔未知,完成时间未知……
  • 推荐shohy猫爪大人的技术群:260237108,对本文或是其他Mod有问题应该都能在群里得到解答。
  • 每个命令的具体英文解释参阅:WeiDU官方说明文档
  • 注意:本文以WeiDU版本243及其在线说明文档为基础,低版本的WeiDU可能无法实现某些部分。最新版本WeiDU下载地址
    文中的超链接的地址可能随WeiDU的版本更新出现变动,请善用CTRL+F进行搜索。
  • 文中对mod名的举例均为MyMod,请自动替换为你的mod的名字,不再重复说明。

快速链接与目录

This post has been edited by 四是而非: 2018-01-18, 01:48
TOP
四是而非
2017-12-04, 19:53
Post #2


特珞骑士
Group Icon
 478
   10

Group: Avatar
Posts: 307
Joined: 2012-04-17
Member No.: 48323


TP2文件概述

一个WeiDU mod的安装文件,除了如物品、法术等资源文件之外,至少包含一个MyMod.tp2 或 Setup-MyMod.tp2文件。如果你打算发布和共享你的mod,TP2文件也许是工作的最后一步,可能也是最重要的一步。
TP2文件名可以是MyMod.tp2或Setup-MyMod.tp2,位置可以是在MyMod文件夹下,也可以在游戏根目录下。无论怎样命名和放在什么地方,均可以被Setup-MyMod.exe正常引用。

TP2文件可以分为 声明部分组件部分

TP2文件:声明部分
WeiDU说明文档中将此部分称为TP2 File。

总的来说,TP2文件包含(也是必不可少的,list表示可以是多个):
QUOTE

BACKUP directoryName
AUTHOR emailAddress

TP2 Flag list
Language list
Component list

BACKUP
指定mod组件安装之后,被编辑过的文件的备份以及卸载信息的文件夹。directoryName通常格式是“MyMod\backup”,当然也可以是其他。注意:和游戏安装目录名一样,mod文件夹的名字必须使用英文。

AUTHOR
作者的标识,而如果Mod安装失败,这部分会显示在命令窗口,提示玩家联系作者。所以WeiDU的建议是留下邮箱地址,但不是必须,甚至可以留空:AUTHOR ~~,但此条目必须存在。

Language
理论上本段应该位于TP2 FLAG之后,但方便之后的说明,先提前这部分。
格式:
QUOTE
LANGUAGE languageName languageDirectory defaultLanguageTRA list
其中:
languageName:显示在安装界面语言选择的部分
languageDirectory:既是该语言的子目录名,同时也是常量LANGUAGE的值,对于EE下使用HANDLE_CHARSETS转码时还是WeiDU判断codepage时的标签。
defaultLanguageTRA:在语言一经选择之后自动加载。注意:可以是其他语言的tra文件。例如在新版英文mod上使用旧版汉化包时,因为tra条目可能有缺漏,可以同时载入英文文本以防万一。

当你的mod支持多个语言时可以重复该段落以包含全部语言。

TP2 Flag
TP2标签,不是必须存在。本文不列出部分没有太多实际价值,或是不推荐使用甚至已弃用的标签,有兴趣的可查阅官方说明文档。
  • AUTO_TRA path:当使用COMPILE编译BAF或D文件时,自动检索和加载path下同名的tra文件,好处是不必担心tra中的条目序号存在冲突。path通常定义为~%MOD_FOLDER%/languages/%s~
  • ASK_EVERY_COMPONENT:当mod中包含超过5个组件时默认会询问“是否全部安装,或逐一显示”,这个标签将强制逐一显示。
  • README file list:此条存在将在安装时询问“是否显示说明文档”。
  • VERSION String:版本号,将显示在weidu.log内组件条目的最后
  • SCRIPT_STYLE style:脚本风格,用以区分BG IWD IWD2 PST,详见官方说明文档的 the Scripting Styles tutorial 部分
  • AUTO_EVAL_STRINGS:自动将%变量名%转义为变量的值,在函数等地方使用变量时不再需要添加EVALUATE_BUFFER,但那些注明了需要指定EVALUATE_BUFFER的指令中,这个标签不起作用。
  • ALWAYS TP2 Action list END:指定一些外部命令,在每个组件安装之前运行,省去复制粘贴至每个组件之前的麻烦。


This post has been edited by 四是而非: 2017-12-08, 03:24
TOP
四是而非
2017-12-04, 20:06
Post #3


特珞骑士
Group Icon
 478
   10

Group: Avatar
Posts: 307
Joined: 2012-04-17
Member No.: 48323


TP2文件:组件

Component,即组件,几乎可以说是mod的核心。格式为:
BEGIN ~组件名~ 或 BEGIN @x 读取tra中对应的条目。拥有参数(顺序无所谓):
  • DESIGNATED forcedNumber:强制设定组件编号,如果没有设定,将依照组件在TP2文件中的顺序从0开始自上而下排列。如果下个组件没有指定编号,本来属于本组件的序号将被跳过。例如:第一个组件指定了编号,那么第二个组件如果没有指定,编号将是1。
  • DEPRECATED String:将该组件标记为失效,自动跳过,并且如果游戏中已经安装了该组件,将会自动卸载。安装窗口将显示string的内容。
  • REQUIRE_COMPONENT modToInstall modComponent String: 设置只有安装了modToInstall 的 modComponent 组件才能安装本组件,否则将显示String的内容。
  • FORBID_COMPONENT modToUninstall modComponent String: 设置必须modToInstall 的 modComponent 组件没有安装,才能安装本组件,否则将显示String的内容。
  • REQUIRE_PREDICATE value String:指定只有在value为真时才能安装本组件,否则将显示String的内容。
  • NO_LOG_RECORD:不记录在weidu.log中,也就是不可卸载,同时也无法被其他mod的REQUIRE_COMPONENT 或 FORBID_COMPONENT识别。慎用!
  • INSTALL_BY_DEFAULT:默认安装,即WeiDU不会询问是否安装本组件。不推荐使用。

特殊安装方式
有三个组件部分的参数因为较为特殊,笔者将其独立出来讲解。

1. 组件组Group
以Tweaks Anthology(曾经的BG2Tweaks进化版)为例,所有组件分为了5个组,在安装的一开始会询问,例如“是否显示规则的改变中的内容”,这里“规则的改变”即为组的名字。在属于该组的每个组件都指定了一个相同的参数:
CODE
GROUP @x
而@x在tra中即为“规则的改变”

2. 子组件Subcomponent
涉及2个参数:SUBCOMPONENT String [ value ] 和 FORCED_SUBCOMPONENT String [ value ]
当我们希望玩家在某几个选项中选择其中一个时使用,例如tweaks中的更改经验上限组件:
Attached Image
在tweaks的TP2中可以找到:
CODE
BEGIN @209001 DESIGNATED 2090 // remove xp cap 组件(也就是下方的选项)名:移除经验上限
GROUP @9 //tweaks中的组:规则的改变
SUBCOMPONENT @209000 // change xp cap 子组件所属的类别:更改经验上限

BEGIN @209100 DESIGNATED 2091 // 最高20级
GROUP @9
SUBCOMPONENT @209000 // change xp cap

BEGIN @209200 DESIGNATED 2092 // 最高30级
GROUP @9
SUBCOMPONENT @209000 // change xp cap

参数说明中的[ value ] 代表这个值的判断为非强制项,在WeiDU官方说明中可以看见很多类似的可选项。这里代表值未被指定,或是为真时,该子组件才会显示以供选择。

而紧跟在 组件 部分后面的,则是一系列 外部命令内部命令 的组合,这将是一个mod,也是本文的核心内容。

This post has been edited by 四是而非: 2018-01-10, 07:44
TOP
四是而非
2017-12-04, 20:06
Post #4


特珞骑士
Group Icon
 478
   10

Group: Avatar
Posts: 307
Joined: 2012-04-17
Member No.: 48323


外部命令与内部命令

如果说组件部分是一个TP2文件的核心,那么具体的命令则是核心的核心。
WeiDU命令分为两类:
Action:一类命令可以在Component即组件中直接使用,WeiDU称为Action。为后述方便,笔者将其译为外部命令
Patch:另外一类命令,在使用外部将资源文件调入内存并进行读取、写入等操作。笔者将Patch相对应的译为内部命令

绝大多数外部与内部命令都需要加上参数才能正确执行,分别是:
  1. when条件控制,字面意思,当满足条件时命令才会被执行。
  2. option特殊选项,包括optNoBackup optGlob等,在特殊命令中控制相应的行为。
  3. variables变量,被赋予了含义(值)的代号,值可以是整数或字符串,以及队列。需要注意的是:
    • 变量名不仅可以用任意拉丁字符(区分大小写且必须是半角),特殊符号(注意不能是regexp中使用的特殊符号),也可以是包括中文字符在内的任意系统支持的字符(需要用一对~或"包含),但为了通用性,通常不建议使用。
    • 有一些在变量(通常是大写)是内置在WeiDU中,或是由某些命令直接定义,可以直接调用的。为方便区分,本文中将这类变量称作常量,虽然也是可自定义的(但不推荐这么做)。
    • 对于值为字符串的变量,有些字符会在regular expression(regexp)中使用,例如?+*等等使用时需要注意。下文中将对REGEXP进行详细解释。
  4. value。除了直接写出的整数、字符串和队列之外,在%变量名%之前添加EVALUATE_BUFFER(可简写为EVAL),可直接读取变量的值进行处理。
  5. array队列,由若干个变量构成的一种特殊的变量,将在后续章节详细说明。
  6. Function & Macro函数和宏,见详细说明

双胞胎命令
WeiDU中的一些命令无论用途还是使用的参数都完全一样,但分别属于外部命令和内部命令。为了区分是action还是patch,WeiDU中通常使用以下一些方式:
  1. 外部命令加上前缀ACTION_,内部命令加上前缀PATCH_,例如ACTION_IF和PATCH_IF。
  2. 外部命令加上前缀OUTER_,内部命令不加前缀。例如OUTER_SET和SET。
  3. 外部命令不加前缀,内部命令加上前缀PATCH_。如PRINT和PATCH_PRINT。
  4. 有一些指令的INNER_并非前缀,例如INNER_PATCH,他的外部命令形态是OUTER_INNER_PATCH,但为了看起来不那么奇怪,WeiDU提供了一个同义的命令OUTER_PATCH,但OUTER_INNER_PATCH依然可用。
  5. 特殊:INNER_ACTION,用途是在一段内部指令中插入一段外部指令,因此没有OUTER_ACTION这种奇怪的东西。

This post has been edited by 四是而非: 2018-01-15, 21:32
TOP
四是而非
2017-12-04, 22:15
Post #5


特珞骑士
Group Icon
 478
   10

Group: Avatar
Posts: 307
Joined: 2012-04-17
Member No.: 48323


通用表达式 Regular Expression(REGEXP)

WeiDU的regexp与GNU EMACS中的语法相同,算是简化版的正则表达式,相信对后者有一定了解的话理解起来应该很容易,但如果从未接触,下面的例子应该能够让你有所了解。

regexp在WeiDU中有着非常重要的作用,熟练应用可以让不少繁杂的手动工作变得容易起来。

regexp使用的特殊字符包括:$^.*+?[]\,如果你希望使用这些字符的本来状态须在前面加上反斜杠\。
具体格式及含义:
CODE
.      代表除了新行之外的一个任意字符
*      后缀,代表在此之前的字符不存在,存在1个,或是重复若干次
+      后缀,代表在此之前的字符至少存在1个,或是重复若干次
?      后缀,代表在此之前的字符不存在或者只有1个
[..]   字符组,代表组中字符任意一个,可使用连接符(减号)表示范围,例如[a-e]表示abcde中任何一个。
       在开始加上^表示否定,例如[^0-9]表示该字符不可以是0到9中的任意数字。
       另外字符组中的字母区分大小写,也支持中文和空格。
^      代表一行的开头
$      代表一行的结尾
\|     分隔符,出现于两组表达式中间,连同下面的表达组使用
\(..\) 表达组,配合下面的转义符使用
\1     将之前表达式中的组进行转义,\1表示第一个组,\2表示第二个,以此类推
\b     代表完整匹配两个\b之间的字符
\      使用特殊字符的本意,例如\?代表真的是一个问号,而非代表反斜杠\的0个或1个

举例:
例1:将原版所有单手剑、双手剑、斧头复制到MyMod\itm文件夹下,并在物品名的最后加上下划线
CODE
//字符组、表达组及转义的用法
COPY_EXISTING_REGEXP GLOB ~\(SW\|AX\)\([12].+\)\.itm~ ~MyMod/itm/\1\2_.itm~

例2:将游戏文本中所有的“铠甲+1”改成“板甲+1”
CODE
//使用特殊字符的本意
ALTER_TLK BEGIN
  REPLACE_TEXTUALLY ~铠甲\+1~ ~板甲+1~
END

This post has been edited by 四是而非: 2018-01-16, 00:20
TOP
四是而非
2017-12-06, 00:16
Post #6


特珞骑士
Group Icon
 478
   10

Group: Avatar
Posts: 307
Joined: 2012-04-17
Member No.: 48323


建议和注意事项

以下是一些个人在mod制作中得出的心得,或是来自国内外优秀modder的经验分享,仅供参考。

1. 注册一个你独有的前缀,并在所有mod中统一使用
一个新mod很多时候都会用到新的文件名、宗派代号、变量名等等,随心所欲的使用不仅给自己在维护时带来不必要的麻烦,最重要的有可能与其他mod存在兼容性问题。此时,一个独有的前缀也许能够避免很多问题出现。

前缀注册方式:
» Click to show Spoiler - click again to hide... «

2. 选择一个优秀的文本编辑工具
Windows自带的记事本虽然也可以用来编写你的TP2 BAF等文件,但功能实在过于简陋。
笔者推荐Notepad++,不仅因为其本身开源(即免费),以及其他例如备份等强大功能,还因为有国外优秀modder Argent77制作的语法模板:WeiDU Highlighter for Notepad++,在编写TP2 BAF TRA等文本模式的WeiDU文件时十分方便。

3. 添加注释
养成添加注释的习惯不仅在于编写WeiDU,在所有代码编辑中都是十分重要的好习惯,无需多言。
与很多程序语言类似,在WeiDU文件中(无论是TP2 BAF等等)添加注释的方法为:
单行注释:双斜杠 //
段落注释:/* 注释内容 */
需要注意的是(笔者未验证):IWD/IWD2的BAF文件中不支持 // 的注释方式

4. 非必要时不要更改组件编号(DESIGNATED后面的数字)
一个mod可以用REQUIRE_COMPONENT或FORBID_COMPONENT来检测其他mod的安装情况,如果你修改了组件编号则会造成其他mod的判断失效。详见:TP2文件概述:组件

5. 给组件和版本号添加独立标识
有时候确实有更改组件编号的需要甚至必要,另一个避免问题出现的方式,则是给组件(及其版本)添加一个在游戏中没有实际用处的文件。最好是从mod发布的一开始就添加,或是在你更新某个版本之后,知会(你所知道的)其他有关联的mod的作者,请他们改变对你的mod的判断方式。
例如在组件中添加:
CODE
<<<<<<<< .../inlined/mymod/blank.baf
>>>>>>>>

COPY ~.../inlined/mymod/blank.baf~ ~override/mymod_c1_v1.mymod~
此时mymod_c1_v1.mymod即可用作为mymod的组件1,版本v1的标识。切忌与游戏使用的数据文件同名!

6. 时常参考知名mod的代码,尤其是Library库和WeiDU内置的函数与宏
毕加索说过:“模仿是人类一切学习的开端,然后才是创新,最后是你的自主”,对modder也一样。所有WeiDU mod(包括WeiDU本身)都是开源的,所有的借鉴、模仿乃至直接引用都是被允许的。当然,全盘照搬冠以自己的名号依然是抄袭。
从个人经验来说,也许一个WeiDU内置或是别人写好的函数能够帮我们节省大量的时间和精力,并降低bug出现的概率,也许别人一段代码能拓宽思路甚至产生新的灵感,或是能大幅优化自己的代码。保持学习,在任何事情上都是大有裨益的,做mod也是如此。

在此推荐一些经常可用于参考的mod:
Gibberlings3的Git站:众多G3mod的源代码
G3论坛上一些知名modder共享的函数

This post has been edited by 四是而非: 2018-01-10, 11:04
TOP
四是而非
2017-12-06, 00:22
Post #7


特珞骑士
Group Icon
 478
   10

Group: Avatar
Posts: 307
Joined: 2012-04-17
Member No.: 48323


Function & Macro:函数与宏

对于熟悉编程的modder来说这两个应该再熟悉不过。简单的说就是一系列提前编辑好的命令的集合,让modder能够通过简单的命令调用,大量省去重复的工作。仅WeiDU内置的函数与宏数量就相当多,此处仅作简要介绍,在实际应用中再作详细说明。

WeiDU本身内置的函数和宏可阅读WeiDU说明文档的 Macros Listing 部分获取详细说明。
注意标注为INT_VAR所填入的变量应为整数,STR_VAR应填入字符串,而RET部分为该函数的返回值。

本文的后续介绍中将还会使用到若干自己编写,或是从国外优秀mod、论坛中借鉴的函数和宏,均放置在GitHub。不再赘述。

一. 调用
在调用函数或宏之前首先需要明确你准备调用的,是属于外部命令的函数或宏,还是属于内部命令。例如在WeiDU说明文档中对于某一个函数或宏的说明中都会有:
» Click to show Spoiler - click again to hide... «

在明确了之后再选择对应的WeiDU命令(点击命令查看完整格式):
QUOTE
LAUNCH_ACTION_MACRO:调用外部宏,可简写为LAM
LAUNCH_ACTION_FUNCTION:调用外部函数,可简写为LAF
LAUNCH_PATCH_MACRO:调用内部宏,可简写为LPM
LAUNCH_PATCH_FUNCTION:调用内部函数,可简写为LPF

举例:
» Click to show Spoiler - click again to hide... «

二. 自定义宏和函数
WeiDU虽然提供了大量函数和宏,但有时候并不够用,需要创建一些适合我们自己mod的东西。
命令(点击命令查看完整格式):
创建宏:
DEFINE_ACTION_MACRODEFINE_PATCH_MACRO
创建函数:
DEFINE_ACTION_FUNCTIONDEFINE_PATCH_FUNCTION

三. 加载外部库
为了方便管理和维护,以及TP2文件的美观,直接将(可能会很长)的自定义宏/函数的段落放在TP2文件中不是一个好主意。笔者推荐将这些段落(无论是mod自定义的,或是借用其他mod)单独放置在一些新的文件中,并在TP2中将其引用。

与TP2文件一样,这些新文件都是一个文本文件。一般来说定义外部函数的段落会存放在后缀为TPA的文件中,内部函数存放在后缀为TPP的文件,而将宏放进后缀为TPH的文件。这只是一种约定俗成(WeiDU Highlighter for Notepad++插件也能够自动识别)而非WeiDU的规定,只要你愿意,随便选择三种之一甚至可以随意更改文件后缀。只要该文件是文本格式,WeiDU都能够正常加载。

加载外部库所使用的命令为:
INCLUDE String listPATCH_INCLUDE String list
其中String list是外部库的路径和文件名,例如:MyMod/lib/MyMacro.tph,作用与将库文件的全部内容直接写进TP2相同。

有时候可能会根据玩家的选择,在mod安装的过程中对库文件进行修改,此时需要重新加载外部库。所使用的命令为:
REINCLUDE String listPATCH_REINCLUDE String list

This post has been edited by 四是而非: 2018-01-20, 06:09
TOP
四是而非
2017-12-06, 01:16
Post #8


特珞骑士
Group Icon
 478
   10

Group: Avatar
Posts: 307
Joined: 2012-04-17
Member No.: 48323


内联文件

外部命令的一种,由于比较特殊,独立出来进行说明。
例如:
CODE
<<<<<<<< .../inlined/MyMod/temp.baf
IF
  See(NearestEnemyOf())
THEN
  RESPONSE #100
    Attack(LastSeenBy())
END
>>>>>>>>

并添加到明斯克的脚本顶部

CODE
EXTEND_TOP ~Minsc.bcs~ ~.../inlined/MyMod/temp.baf~

此指令的作用是在内存中临时建立一个包含纯文本内容的内联文件,例如BAF(通常内容很简单),随后进行例如EXTEND_TOP的操作。这样做的好处是无须繁琐的建立真实文件即可进行操作,自然也方便了进行测试。
例子中的路径使用了.../inlined/MyMod的目的是能够避免与现有真实文件重复,当然也可写作其他。

This post has been edited by 四是而非: 2018-01-16, 00:13
TOP
四是而非
2017-12-06, 03:48
Post #9


特珞骑士
Group Icon
 478
   10

Group: Avatar
Posts: 307
Joined: 2012-04-17
Member No.: 48323


常量
前面介绍过,本文将一系列由WeiDU自动指定的变量称为常量。包括以下类型:

内置常量
WeiDU将一些资源文件的偏移地址,特殊的符号等储存进一些变量之中,方便modder直接使用,笔者称之为内置常量。内容比较多,可在:WeiDU说明文档的相关部分查询具体信息。

系统常量
由玩家电脑的CPU、操作系统,以及模组安装方式决定的常量,笔者称之为系统常量。包括:
  • WEIDU_ARCH:CPU架构类型,在安装程序一开始即判断和指定,x86,amd64或是mac
  • WEIDU_OS:系统类型,在安装程序一开始即判断和指定,可以是win32,osx或是unix
  • INTERACTIVE:交互状态,当玩家使用Setup-MyMod.exe安装时值设为1,否则为0,例如重新安装/卸载此组件须先卸载别的mod/组件时,别的组件TP2中的这个值为0

模组常量
在声明部分完成的同时,有相当数量的常量将被指定。包括:
  • MOD_FOLDER:BACKUP中directoryName的根目录,即MyMod。无论BACKUP中指定的是~MyMod/backup~还是~MyMod/123/234~,这里的值都是MyMod,不区分大小写
  • TP2_AUTHOR:AUTHOR指定的值值,即emailAddress
  • TP2_FILE_NAME:TP2文件的名字,即Setup-MyMod或MyMod
  • TP2_BASE_NAME:TP2文件去掉Setup-前缀之后的名字
  • LANGUAGE:Language段落中的languageDirectory
  • COMPONENT_NUMBER:当前组件编号

动态常量
也许你会觉得这个名称很奇怪,这里指的是由某些外部或内部命令在执行时自动赋值的常量。
例如COPY命令在执行时自动给SOURCE_RES赋值为源文件的主文件名,给SOURCE_EXT赋值为源文件的扩展名。
动态常量的数量非常多,笔者将在介绍具体的命令时,对相关的动态常量进行说明。

This post has been edited by 四是而非: 2018-01-14, 07:04
TOP
四是而非
2017-12-06, 03:48
Post #10


特珞骑士
Group Icon
 478
   10

Group: Avatar
Posts: 307
Joined: 2012-04-17
Member No.: 48323


变量

变量的概念无须赘述,只需注意变量名只能是A到Z的拉丁字符(区分大小写),0到9的数字,以及下划线_、连字符号-、井号#、感叹号!。所有字符必须使用半角

在WeiDU中变量根据值的类型的不同,分为整数与字符串。

整数型变量
整数型可以是十进制、八进制(以0o开头表示)、十六进制(以0x开头表示)和二进制(以0b开头表示),最大长度为4字节,即0xFFFFFFFF,十进制的4294967295。

此外还有布尔型变量,在WeiDU中视为值只有0和非0两种情况的整数型变量,将在之后对条件控制的介绍中详细说明。

字符串型变量
字符串的值可以是任意拉丁字母,数字,特殊符号:~!@#$%^&*()_+-=\[\]{}\\|;:'",\<.\>/?,乃至其他任何可以在游戏内正常显示的字符,当然也包括简体中文和正体中文,但需要注意REGEXP中使用的特殊字符的使用方式。见 REGEXP的说明

声明字符串:
WeiDU本身无法判断一段字符究竟是字符串,还是命令或者其他一些意图,因此需要进行声明,告诉WeiDU这是一个字符串。
声明的格式包括:
  1. 将字符串嵌套在一对半角双引号 "之内,例如"abcde"
  2. 将字符串嵌套在一对半角波浪符号 ~之内,例如~abcde~
  3. 将字符串嵌套在一对半角百分号 %之内,例如%abcde%,BiG5码中使用
  4. 将字符串嵌套在一对连续5个半角波浪符号 ~~~~~之内,例如~~~~~abcde~~~~~

变量的转义
在具体应用变量时,通常需要将变量进行转义,使用其所代表的值,最常见的形式是将变量放在一对百分号%中,并配合(不一定是必需的)EVALUATE_BUFFER(或简写为EVAL)使用。

This post has been edited by 四是而非: 2018-01-14, 06:39
TOP
四是而非
2017-12-08, 02:07
Post #11


特珞骑士
Group Icon
 478
   10

Group: Avatar
Posts: 307
Joined: 2012-04-17
Member No.: 48323


整数型变量的赋值

整数型变量的赋值有若干种,WeiDU中为了操作方便,很多命令会将赋值与简单运算融合在一条命令中。

第一类:直接将具体的值赋给变量。
QUOTE
  • [ SET ] variable = value:将value的值赋给variable。value可以是一个给定的值,也可以是另一个变量。
  • [ SET ] variable += value:等价于 SET variable = variable + value
  • [ SET ] variable -= value:等价于 SET variable = variable - value
  • [ SET ] variable *= value:等价于 SET variable = variable * value
  • [ SET ] variable /= value:等价于 SET variable = variable / value
  • [ SET ] variable &= value:等价于 SET variable = variable BAND value
  • [ SET ] variable |= value:等价于 SET variable = variable BOR value
  • [ SET ] variable <<= value:等价于 SET variable = variable BLSL value
  • [ SET ] variable >>= value:等价于 SET variable = variable BLSR value
说明中[ SET ]被放进方括号中,如之前所述,表示该部分在WeiDU中可以省略不写,即
SET variable = value 和 variable = value有相同作用。
相对应的外部命令为OUTER_SET,但须注意:OUTER_SET不可省略

第二类:从指定的偏移量中提取指定长度的字节,赋给指定的变量,一般是内部命令。
QUOTE
  • READ_BYTE offset variable [ ELSE value ]:从偏移量offset开始读取长度为1个字节的值并以10进制的格式赋给variable。
  • READ_SBYTE offset variable [ ELSE value ]:类似READ_BYTE,只是读取的值保留符号。例如读取的值是0xFF,READ_BYTE得到的结果是255,而READ_SBYTE的结果是-1
  • READ_SHORT offset variable [ ELSE value ]:类似READ_BYTE,只是读取的长度为2个字节
  • READ_SSHORT offset variable [ ELSE value ]:类似READ_SBYTE,只是读取的长度为2个字节
  • READ_LONG offset variable [ ELSE value ]:类似READ_BYTE,只是读取的长度为4个字节
  • READ_SLONG offset variable [ ELSE value ]:类似READ_SBYTE,只是读取的长度为4个字节
显然,该类操作没有对应的外部命令。
注意:当指定的偏移量和长度超出当前加载的资源文件的大小,如果指定了 [ ELSE value ] 则将value赋给variable,否则WeiDU将提示OUT OF BOUNDS并且安装失败。

第三类:返回值。某些命令在执行之后会返回一个变量,作为该命令执行之后的结果。
例如读取2DA文件列数的命令:
CODE
COUNT_2DA_COLS variable
此类命令将在具体介绍资源文件编辑时具体说明。

第四类:TLK相关,此类将在TLK操作介绍中具体说明。

除此之外还有很多涉及到具体资源文件或操作的变量,本文将在涉及时进行介绍。

This post has been edited by 四是而非: 2018-01-14, 07:30
TOP
四是而非
2017-12-08, 03:53
Post #12


特珞骑士
Group Icon
 478
   10

Group: Avatar
Posts: 307
Joined: 2012-04-17
Member No.: 48323


整数型变量的计算

赋值部分提到过一些计算,但在WeiDU中不仅于此。在此仅说明普通计算,布尔值部分会在条件判断部分进行说明。
WeiDU可以有的普通计算包括:
QUOTE

  • value + value:加法
  • value - value:减法
  • value * value:乘法
  • value / value:除法,由于无限引擎只支持整数,小数点后的部分被舍弃,即向下取整。
  • value MODULO value:求模
  • value ** value:求幂,如SET x = 100 ** 2,则x=10000
  • value ** ( value value ):求分数幂,如SET x = 100 ** (1 2),则x=10
  • ABS value:求绝对值
  • value BAND value:按位与,如 0b101 BAND 0b110 = 0b100。可用&代替。
  • value BOR value:按位或,如 0b101 BOR 0b110 = 0b111。可用|代替。
  • value BXOR value:按位异或,如 0b101 BXOR 0b110 = 0b011。可用^^代替。
  • BNOT value:按位取反,如 BNOT 0b111 = 0b1111111111111111111111111111000。可用`代替。
  • value BLSL value:位逻辑左移,如 0b101 BLSL 2 = 0b10100。可用<<代替。
  • value BLSR value:位逻辑右移,如 0b101 BLSR 2 = 0b1。可用>>代替。
  • value BASR value:位算术右移,如 0b101 BASR 2 = 0b1。
  • value1 ? value2 : value3:基于条件的选择。当value1不为0时结果为value2,value1为0时结果为value3。

This post has been edited by 四是而非: 2018-01-10, 07:54
TOP
四是而非
2017-12-10, 02:44
Post #13


特珞骑士
Group Icon
 478
   10

Group: Avatar
Posts: 307
Joined: 2012-04-17
Member No.: 48323


字符串型变量的赋值

第一类:直接将具体的字符串赋给变量。
QUOTE
  • TEXT_SPRINT variable stringWithVars:将 stringWithVars 赋给变量 variable。如果stringWithVars中包含了嵌套在一对%中的变量名,则使用该变量的值,赋给variable。外部命令为OUTER_TEXT_SPRINT。
  • SPRINT variable stringWithVars:与TEXT_SPRINT类似,但stringWithVars可以是@xxx的格式,直接调取TRA文件中的对应条目。外部命令为OUTER_SPRINT。
  • TO_UPPER variable:将variable的值中的字符全部转为大写,重新赋给variable。外部命令为ACTION_TO_UPPER。
  • TO_LOWER variable:将variable的值中的字符全部转为小写,重新赋给variable。外部命令为ACTION_TO_LOWER。
  • SNPRINT value variable stringWithVars:与SPRINT相似,但只读取stringWithVars中前value个字符。
    例如:
    CODE
    SPRINT "author" "Jason"
    SNPRINT 3 "myvar" "1:%author%"
    则myvar的值是1:J,即1:Jason的前3个字符。
    当value为负值时则从stringWithVars的最末一个字符开始读取。例如:
    CODE
    SPRINT "author" "Jason"
    SNPRINT "-3" "myvar" "1:%author%"
    则myvar的值是son,即1:Jason的最后3个字符。
    外部命令为:OUTER_SNPRINT。
  • SPACES variable stringWithVars:将stringWithVars中所有字符用空格代替,赋给variable。没有外部命令形式。
  • QUOTE variable stringWithVars:将stringWithVars中包含的REGEXP特殊字符用\标记,赋给variable。
    例如:QUOTE var ~some\thing^~,得到的var的值将是:some\\thing\^。没有外部命令形式。

第二类:从指定的偏移量中提取指定长度的字节,赋给指定的变量,一般是内部命令。
与整数型变量相似,只是将读取的值以字符串的形式保存。
QUOTE

  • READ_ASCII offset variable [ ELSE string ] [ ( value ) [ NULL ] ]:从偏移量offset开始读取长度为8个字节(以空字符nul为结束), 并以字符串形式赋给variable. 如果指定了value, 则读取的字节长度为value, 即使出现空字符. 但当NULL指定时不包含空字符在内. 如果指定的偏移量和长度超出当前加载的资源文件的大小,如果指定了 [ ELSE value ] 则将value赋给variable,否则WeiDU将提示OUT OF BOUNDS并且安装失败。

第三类:截取子字符串。
SNPRINT只能指定开头或最后几个字符,但有时候需要的是中间的一个或几个字符,WeiDU提供了一个函数来帮我们简单的实现目的:SUBSTRING。同时拥有内部和外部形式。
格式:
LAF/LPF SUBSTRING INT_VAR start length STR_VAR string RET substring END
其中
start:起始位置(目标字符串的第一个字符为0),整数
length:截取长度,整数
string:目标字符串
substring:返回的子字符串。
例如
CODE
LAF SUBSTRING INT_VAR start=1 length=2 STR_VAR string=trow RET sub=substring END
则变量sub的值为ro。注意RET部分使用的形式,可以是自定义变量 sub=substring, 也可以直接将substring为后续直接使用的变量名。

This post has been edited by 四是而非: 2018-01-10, 08:33
TOP
四是而非
2018-01-10, 11:54
Post #14


特珞骑士
Group Icon
 478
   10

Group: Avatar
Posts: 307
Joined: 2012-04-17
Member No.: 48323


条件控制
在mod的安装过程中,经常会需要在某些条件满足的基础上才进行某些操作,笔者将这种判断称为条件控制。WeiDU中分为命令辅助条件、独立条件两种。

命令辅助条件
指必须配合对应命令使用的条件,对应的判断通常与正在操作的资源文件相关。包含:
QUOTE
  • IF_SIZE_IS filesize:当前文件的大小与filesize相等时返回真。可简写为I_S_I
  • IF regexp:当前文件包含指定regexp表达式时返回真。
  • UNLESS regexp:当前文件未包含指定regexp表达式时返回真。
  • BUT_ONLY_IF_IT_CHANGES:仅在当前文件经过一系列内部命令处理后有所改动,才将当期文件复制到硬盘。一般只在COPY、COPY_EXISTING、COPY_EXISTING_REGEXP等命令后使用。
  • IF_EXISTS :当文件存在时返回真. 对COPY命令相当于 FILE_EXISTS,对COPY_EXISTING, COPY_EXISTING_REGEXP, COPY_RANDOM, APPEND 和 APPEND_COL等命令相当于 FILE_EXISTS_IN_GAME

This post has been edited by 四是而非: 2018-01-14, 07:01
TOP
四是而非
2018-01-14, 08:02
Post #15


特珞骑士
Group Icon
 478
   10

Group: Avatar
Posts: 307
Joined: 2012-04-17
Member No.: 48323


布尔型变量

在变量环节曾经提到过,整数型变量中有一类特殊的整数型变量,称为布尔型变量。此类变量几乎唯一的作用是配合独立条件使用。

布尔型变量大致包括
QUOTE

  • 普通整数型变量:值为非0整数时返回真(1),值为0时返回假(0)
  • NOT value:否定。当value为真(1)时返回假(0),当value为假(0)时返回真(1)
  • value1 = value2:当value1与value2相等时返回真(1),否则返回假(0)。可用 == 代替
  • value1 != value2:当value1与value2不相等时返回真
  • value1 > value2:当value1大于value2不相等时返回真
  • value1 < value2:当value1小于value2不相等时返回真
  • value1 >= value2:当value1大于或等于value2不相等时返回真
  • value1 <= value2:当value1小于或等于value2不相等时返回真
  • String1 STRING_EQUAL String2:当String1和String2两个字符串完全一致时返回真,区分大小写
  • String1 STRING_EQUAL_CASE String2:与STRING_EQUAL相似,但不区分大小写。可简写为STR_EQ
  • String1 STRING_COMPARE String2:与STRING_EQUAL完全相反,区分大小写。可简写为STR_CMP
  • String1 STRING_COMPARE_CASE String2:与STRING_COMPARE相似,但不区分大小写
  • String1 STRING_MATCHES_REGEXP String2:与STRING_COMPARE相似,但String2可以是REGEXP表达式。也可写作STRING_COMPARE_REGEXP
    例如:AR1005 STRING_MATCHES_REGEXP “AR[0-9]+”将返回假(0),即没有区别
    注意此变量的“结果”与字面意思是完全相反的
  • String1 STRING_CONTAINS_REGEXP String2:当String1的内容未能完整包含String2(可以是REGEXP表达式)时返回真
    例如:AR1005 STRING_CONTAINS_REGEXP “[X-Z]”将返回真(1),即没有完整包含
    注意此变量的“结果”与字面意思是完全相反的
  • GAME_IS String:当前游戏环境属于String中列举的游戏时返回真
    String可以是以下的一项或多项(多项时使用空格隔开,不区分大小写):
    bg2=soa, tob, iwd2, pst, bg1, totsc, iwd=iwd1, how, totlm, tutu, tutu_totsc, bgt, ca, iwd_in_bg2, bgee, bg2ee, eet, iwdee, pstee。其中:bg2=soa表示bg2与soa同义,可任意选择使用
    各项之间一般是互相冲突的,例如bg2(soa)表示没有安装tob或tutu的纯soa环境,但tob可以是单独的soa+tob环境,也可以是安装了tob的bgt
    GAME_IS相似的还有ENGINE_ISGAME_INCLUDES,但使用起来不如GAME_IS方便和准确,推荐使用GAME_IS或配合使用
  • VARIABLE_IS_SET String:当名为String的变量已被定义时返回真
  • IS_AN_INT String:当名为String的变量是一个整数型变量时返回真
  • MOD_IS_INSTALLED modTp2Name modComponent:当modTp2Name的modComponent组件已经被安装时返回真
  • INSTALL_ORDER modTp2Name1 modComponent1 BEFORE modTp2Name2 modComponent2:安装顺序判断,当modTp2Name1的modComponent1组件在modTp2Name2的modComponent2之前安装时返回真
  • INSTALL_ORDER modTp2Name1 modComponent1 AFTER modTp2Name2 modComponent2:安装顺序判断,当modTp2Name1的modComponent1组件在modTp2Name2的modComponent2之后安装时返回真
  • FILE_EXISTS fileName:当文件fileName(包含路径)存在于硬盘上(因此内联文件无法通过本变量判断),或是一个.BIF文件当前已被chitin.key文件引用时返回真。如果fileName是一个文件夹则该变量不会被赋值
  • FILE_EXISTS_IN_GAME fileName:当文件fileName存在于override文件夹中,或是包含于某个bif文件,且大小不为0时返回真
  • DIRECTORY_EXISTS dirName:文件夹dirName(包含路径)存在时返回真
  • FILE_CONTAINS fileName regexp:当文件fileName中包含regexp表达式时返回真
  • FILE_CONTAINS_EVALUATED ( fileName varsRegexp ):当文件fileName中包含了varsRegexp(可以为regexp表达式的变量)时返回真。
    fileName和varsRegexp中如果含有被一对%围住的变量名时使用变量的值。例子和详细解释见WeiDU说明的相关部分
  • FILE_SIZE fileName fileSize:当文件fileName(包含路径)的大小(以字节计)等于fileSize时返回真
  • FILE_MD5 fileName md5sum:当文件fileName(包含路径)的md5值等于md5sum时返回真,如果不等于或文件不存在时返回假。无论如何,该文件的md5值会写入log文件(除非不存在)

布尔型变量的嵌套
使用连接符号 ANDOR 可将多个布尔型变量整合为一个变量,称为嵌套。
  • value1 AND value2:当value1和value2同时为真时返回真。可用&&代替
  • value1 OR value2:当value1和value2中任一一项为真时返回真。可用||代替
例如:
QUOTE

  • (x=y) AND (x != z)
    假如x=1,y=1,z=2,此时返回真,但如果z=1,虽然x=y返回真但x != z返回假,整个式子将返回假(0)
  • (x=y) OR (x != z)
    假如x=1,y=1,z=1,虽然x != z返回假,但x=y返回真,整个式子将返回真
  • (x=y) AND ((x != z) OR (z=1))
    假如x=1,y=1,z=1,虽然x != z返回假,但z=1返回真,(x != z) OR (z=1)将返回真,同时x=y返回真,整个式子返回真。注意括号的使用

This post has been edited by 四是而非: 2018-01-16, 02:09
TOP
2 Pages V  1 2 
Fast ReplyReply to this topicStart new topic
 


360网站安全检测平台
Time is now: 2018-07-16, 14:32