《魔女:终末旅途》的脚本语法速通

前言

教程目的

本教程系魔女:终末旅途游戏的脚本语法速通及知识速查,不对您进行任何知识完备性的保证,旨在以最快速度上手脚本以及Mod编写。

在开始之前:熟悉Google Sheet表格

在在线文档上,表格被划分为DataText两个表。

其中Text表由于只包含文本及其本地化信息,不在本文讨论范围内。

接下来我们重点关注Data

观察以下卡牌表格范例:

Id Rarity Expend Tag InitScript DrawScript UseScript DropScript Icon Effects Action
唯一的标识 稀有度 消耗的费用 标签 卡牌初始化脚本(可以简单理解成,每时每刻都在执行,用于更新卡面信息) 卡牌抽到后执行 卡牌使用后执行 卡牌进入弃牌堆后执行 图标资源的路径 特效(填入名称) 动作(填入名称)
*1 1 1 Vars["BaseScript"]="AttackCardItem";Vars["DesVal1"]=Self!=null?Self.DamageCalculate(5+int.Parse(Vars["CorAtk"])).ToString():(5+int.Parse(Vars["CorAtk"])).ToString(); SetStatus("Target");Damage("5"); Icon/buff/治愈光环 slash Attack

命名规范:凡是列标题的后缀为Script,即为脚本,也即为我们本文将要讨论的内容。

特别地:物品的游戏内Id由两部分组成,表名+表内id。例如这张表的名字为card.csv,所列出卡牌的Id为*1,那么其游戏内Id为card_*1。对于Mod物品,Id规则为:Mod名+表名+Id名,例如TestMod_card_1

C#语法速通(基础篇)

变量与赋值

在脚本中,变量就像游戏中的背包格子,用于存储各种数据。使用=符号进行赋值操作:

// 基本格式:变量名 = 表达式;
DamageValue = 5;      // 数字
CardName = "火球术";   // 文字(必须用双引号包裹)
IsActive = true;      // 布尔值(true/false)
DrawCount = 1+2+3;   // 表达式(等同于DrawCount = 6)

在脚本中,变量分为两种。内建变量自定义变量

其中自定义变量若是第一次出现,需要声明其类型进行定义。如int(整数), float(实数), string(字符串,即文本)。 如定义一个整数int DamageValue = 5;

内建变量则不能声明类型,直接调用即可。

游戏中常用内建变量:

  1. Vars (字典),采用键值对的方法存储,其中键为查找索引,值为结果,访问方法为Vars["这里输入你要找的值"],其结果返回一个字符串(string),存着一切需要永久保存的变量。
  2. Self (StatusManager),是自定义类,一种包含了若干自定义类与基础类型的复合类型,用于指向效果执行者自己。
  3. Target (StatusManager),是自定义类,类型同Self,用于指向效果对象自己。(单选目标卡特供)

基础运算符

就像数学一样,运算符用于计算数值:

运算符 示例 说明
+ 3 + 2 → 5 加法
- 5 - 1 → 4 减法
* 2 * 3 → 6 乘法
/ 11 / 2 → 5, 11 / 2.0 → 5.5 除法(若两边为整数,则是整除)
% 10 % 3 → 1 取余数(模运算)
++ x++ → x+1 自增1,等同于x=x+1
> 5 > 3 → true 大于
! !(5 > 3) → false 逻辑非
== 1 == 1 -> true 逻辑等于
>= 1 >= 1 -> true 大于等于

运算符可以在表达式中使用,即在赋值的=后,或条件判断
例子:

  1. x = 1 + 1; (1 + 1为表达式)
  2. x = x + 1; (x + 1为表达式)
  3. if (a > 1) (a > 1为表达式)

条件判断(if)

就像游戏中的分支剧情,根据条件执行不同操作:

if (魔力值 > 10) {
    释放大招(); 
} 
else if (魔力值 > 5) {
    释放普通技能();
} 
else {
    使用药剂();
}

特别地,分支还可以通过三目运算符实现,其格式为:

条件表达式 ? 真时表达式 : 假时表达式

例如将x的值设为a与b的较大值

x = a > b ? a : b

注意,不要使用嵌套三目!此时请用if语句代替。

方法调用

程序提供了一些现成功能,直接调用即可实现预设功能:

// 基础格式:方法名(参数);
Damage("15");                   // 造成15点伤害
DrawCount("20");             // 抽20张牌
AddBuff("buff_burn", "-10", "3");           // 添加3层无限时间的燃烧状态(附:-10被规定为 BUFF的无限时长)

常见游戏方法:

  • Damage(数值):造成伤害
  • ChangeHp(数值):数值 >0 时治疗目标, < 0 时造成真实伤害
  • AddBuff(状态名, 持续时间, 层数):添加Buff
  • DrawCount(数量):抽卡

特别地,一些方法名会连接在变量后面,例如15.ToString(),返回值为"15"(字符串类型的15),这是因为作为int类型,拥有ToString()作为成员方法。

这时即可调用x.ToString()(即在任意结果为整型的表达式后加.,效果如上的方法调用,可以理解成变量.方法名是其完整方法名。)

实战解析

让我们一起解构初始示例中的复杂脚本:

// InitScript
// 第一部分:设置基础卡牌类型
Vars["BaseScript"] = "AttackCardItem"; 

// 第二部分:动态计算应该显示在卡面上的伤害值
Vars["DesVal1"] = 
    // 如果卡牌存在(非空检查)
    Self != null ? 
        // 计算伤害:5 + CorAtk变量值
        Self.DamageCalculate(5 + int.Parse(Vars["CorAtk"])).ToString() // 调用Self变量中的DamageCalculate方法计算伤害值,调用int.Parse方法转换类型,调用ToString方法转换类型
        : 
        // 备用计算(战斗外时)
        (5 + int.Parse(Vars["CorAtk"])).ToString();

// UseScript
SetStatus("Target");
Damage("5");

要点:

  1. int.Parse():将文本转换为数字(如"3"→3
  2. ToString():将数字转为文本(如8→"8"
  3. 三元运算符条件 ? 真时结果 : 假时结果
  4. 通过键值对访问Vars字典,如访问键为DesVal1的值,将其变更为表达式的值。
  5. Vars["CorAtk"] 所存值为攻击的值增幅,仅接受例如“卡牌的数字+1”等特殊加成。

脚本编写安全指南

结尾分号:每个完整代码结尾必须加;

Damage("5");  // 正确
Damage("5")   // 错误(缺少分号)

如若初始示例中的脚本,因为代码语义未尽,赋值格式:变量名 = 表达式表达式未在一行中写全,则无需添加;

括号匹配:确保{}和()成对出现

if (x > y {} // 错误,缺少 )
if (x > y) { // 错误, 缺少}
if (x > y) 单行语句; // 正确
if (x > y) 
{
  语句1;
  语句2;
} // 正确



实用模板

其中【】需要自填,不保留括号,记得删注释。

攻击卡模板

// InitScript
Vars["BaseScript"]="AttackCardItem";// 注: AttackCardItem为单选目标卡, CommonCardItem为不选目标卡。
AddDescription("1", "Damage", "【基础伤害】")

// UseScript
SetStatus("Target");// 设定接下来的效果对象为所选目标
Damage("【基础伤害】", "【伤害类型】");// 伤害类型不填则默认为Normal 普通伤害。 其余可选True 真实伤害

防御卡模板

// InitScript
Vars["BaseScript"]="CommonCardItem";
AddDescription("1", "Defence", "【基础防御】")

// UseScript
SetStatus("Target");// 设定接下来的效果对象为所选目标
ChangeDefence("【基础防御】");

治疗卡模板

// InitScript
Vars["BaseScript"]="CommonCardItem";
AddDescription("1", "Hp", "【治疗量】")

// UseScript
SetStatus("Self");// 设定接下来的效果对象为自己
ChangeHp("【治疗量】");

状态卡模板

// InitScript
Vars["BaseScript"]="AttackCardItem";
AddDescription("1", "Buff", "【Buff层数】")

// UseScript
SetStatus("Target");// 设定接下来的效果对象为所选目标
AddBuff("【Id】", "【持续时间】", "【层数】");

下一步行动

尝试修改

测试环境中尝试修改示例数值(在/StreamingAssets/Data/Card/card.csv中)

// 将原脚本的5改为8
Damage(5); → Damage(8);

检查修改

打开游戏,等待加载完成。查看初始卡组的卡牌是否已经被修改。(记得新开游戏)

尝试添加卡牌

测试环境中尝试添加卡牌(在/StreamingAssets/Data/Card/card.csv中)

id为testcard,其余配置仿照修改后的card_*1, 并额外添加如下效果:

打出时,抽一张卡。

别忘了修改Text表与其描述!

然后在游戏中使用控制台!输入give card card_testcard,查看是否获取了卡牌!

尝试自己编写效果

结合上述两步以及卡牌模板,编辑出如下效果

对对方造成5点伤害。若对方生命值 > 50%,则抽一张卡

提示:Target.MaxHp 为目标最大生命值,Target.CurHp为对方当前生命值。
TargetSelf类型一样,其可访问的属性也一样!

查阅手册

已经成功?查阅《API速查手册》,开始你的脚本编写之旅!

posted @ 2025-06-25 21:47  DLS童真  阅读(738)  评论(0)    收藏  举报