模组:触发动作
← 目录
此页面解释了触发动作,后者负责在某些事情发生时让内容包完成特定动作。(C#模组则通常应当使用SMAPI Events API。)
概览
简介
一个触发动作包括两个主要部分:
- 触发条件是导致此动作发生的条件。它可以是一个Data/TriggerActions列表项、一条事件命令之类的东西。参见内建触发条件。
- 动作是由空格分隔的字符串,它定义了触发后执行的动作。例如,
AddMail Current Robin
会在第二天将标识为Robin的信件添加到玩家的邮箱中。参见参数格式和内建动作。
参数格式
参数之间使用空格分隔。例如,AddMail Current Abigail_LeoMoved Now
调用samp>AddMail动作并传入如下三个参数:Current(玩家)、Abigail_LeoMoved(信件ID)、Now(信件类型)。
若某个参数内部需要包括空格,则需使用半角双引号括起来。例如AddFriendshipPoints "Mister Qi" 10
有两个参数(Mister Qi和10)。如需在双引号内部使用空格,则应使用反斜杠 \ 转义,例如AddFriendshipPoints "Mister \"Qi\"" 10
。
请记住,JSON字符串内部的引号和反斜杠也需要转义。例如 "AddFriendshipPoints \"Mister Qi\" 10"
会向游戏代码发送。您也可以使用单引号表示JSON字符串,例如 'AddFriendshipPoints "Mister Qi" 10'
。
动作
内建动作
如下是任何触发条件都能使用的内建动作(其他自定义动作可以通过C#添加)。
动作 | 效果 | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
AddBuff <buff ID> [milliseconds duration] RemoveBuff <buff ID>
|
为当前玩家赋予或清除指定ID的效果。对于AddBuff,持续时间默认为此效果的默认持续时间;该值可以是 -2,以使效果持续一整天。 | ||||||||||
AddConversationTopic <topic ID> <day duration>
|
启动一个持续指定天数的对话主题。若已激活,则重置其持续时间为给定的天数。 | ||||||||||
RemoveConversationTopic <topic ID>
|
结束一个进行中的对话主题。 | ||||||||||
AddFriendshipPoints <NPC name> <count>
|
count}点友谊值。<count> 可以为负数,以减少友谊值。
| ||||||||||
AddItem <item ID> [count] [quality]
|
根据限定性或非限定性物品ID将物品添加到当前玩家的背包中,还可以选择数量(默认为 1)和[模组:物品数据#品质|品质]](默认为 0)。 | ||||||||||
RemoveItem <item ID> [count]
|
根据限定性或非限定性物品ID从玩家背包中删除物品,最大数量为 [count] (默认为 1)。
| ||||||||||
AddMail <player> <mail ID> [type] RemoveMail <player> <mail ID> [type]
|
添加或移除指定玩家的信件标识或信件。
其中
若省略,则AddMail的 | ||||||||||
AddMoney <amount>
|
为当前玩家增加指定的 <amount> 金钱。<amount> 可以为负数,用于扣除金钱。
| ||||||||||
AddQuest <quest ID> RemoveQuest <quest ID>
|
添加/移除当前玩家的任务。 | ||||||||||
AddSpecialOrder <order ID> RemoveSpecialOrder <order ID>
|
添加/移除当前玩家的特别任务。 | ||||||||||
If <query> ## <action if true> If <query> ## <action if true> ## <action if false>
|
检查给定游戏状态查询,并根据返回值执行特定动作。
下面的例子会送给玩家一封信,如果玩家未收到过此信、邮箱暂无此信且明日没有此信: "ActionsOnPurchase": [
"If !PLAYER_HAS_MAIL Current SomeFlag ## AddMail Current SomeFlag"
]
| ||||||||||
IncrementStat <stat key> [amount]
|
将当前玩家的指定统计值增加指定值(默认为 1)。<stat key> 可以为原版统计量(参见 PLAYER_STAT 游戏状态查询 以获取列表),也可以是一个自定义统计量。数值可以是负数,表示减少。
| ||||||||||
MarkActionApplied <player> <answer ID> [applied]
|
根据 [applied] (默认true),将相应触发事件标记为已触发或未触发。<player> 指定了此命令的目标玩家 。这可以用来跳过或重新运行一个触发事件(注意Data/TriggerActions中的触发事件默认只能触发一次。)
需要注意的是,一个触发事件不能以此标记“‘自身’”未应用;如果要这样做,参见使Data/TriggerActions重复发生。 | ||||||||||
MarkCookingRecipeKnown <player> <recipe ID> [known] MarkCraftingRecipeKnown <player> <recipe key> [known]
|
根据[known] (默认为true),设置目标玩家是否已学会烹饪或打造配方 。(默认为true)。
请注意,忘记配方也会将其烹饪/打造次数计数器重置为零。 | ||||||||||
MarkEventSeen <player> <event ID> [seen]
|
根据[seen] (默认true),设置目标玩家是否已看过指定事件。
| ||||||||||
MarkQuestionAnswered <player> <answer ID> [answered]
|
根据[answered] (默认true),设置目标玩家是否已选择过<answer ID> 对应的对话回答。
| ||||||||||
MarkSongHeard <player> <song ID> [heard]
|
根据 [heard] (默认true),设置目标玩家是否已听过指定的音乐提示。这将影响歌曲是否出现在迷你点唱机歌单中。
| ||||||||||
Null | (专用) 什么也不做。主要用于内部;一般情况下对您没有什么用。 | ||||||||||
RemoveTemporaryAnimatedSprites | 移除当前位置的所有临时动画贴图。例如,这可以在setSkipActions事件中使用,以清理事件的临时贴图。 | ||||||||||
SetNpcInvisible <NPC name> <day duration>
|
隐藏某个村民,使之消失且持续<day duration> 多天不能交互。这用于村民离开一段事件的场景(例如艾利欧特的14心事件)。
TODO: 是否可以对农场帮手使用?Atra不这样认为。 | ||||||||||
SetNpcVisible <NPC name>
|
解除村民的隐藏状态(若可用)。
TODO: 是否可以对农场帮手使用?可能会解除NPC的隐藏状态,但daysUntilNotInvisible 不会 同步。 |
目标玩家
某些触发条件具有<player>
参数。可以有下列取值:
值 | 结果 |
---|---|
All | 用于所有玩家(无论是否在线)。 |
Current | 用于本地玩家。 |
Host | 用于房主。 |
触发条件
Data/TriggerActions
Data/TriggerActions 是一种数据素材,可让您在条件满足时动态执行操作。
例如,请参见如下Content Patcher补丁(patch):
{
"Format": "2.3.0",
"Changes": [
{
"Action": "EditData",
"Target": "Data/TriggerActions",
"Entries": {
"{{ModId}}_OnLeoMoved": {
"Id": "{{ModId}}_OnLeoMoved",
"Trigger": "DayEnding",
"Condition": "PLAYER_HAS_MAIL Host leoMoved",
"Actions": [
"AddMail Current {{ModId}}_Abigail_LeoMoved",
"AddConversationTopic {{ModId}}_LeoMoved 5"
]
}
}
}
]
}
上述代码大意为:“当玩家准备睡觉时,若雷欧搬到了星露谷,则发送一封信件并开启一个对话主题。”
默认情况下Data/TriggerActions的每个触发事件仅能触发以此,尽管您可以使用MarkActionApplied动作来重复触发。
Data/TriggerActions为包含如下字段的数据模型所组成的列表。
字段 | 效果 | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
Id | 此触发动作的唯一字符串ID。 | ||||||||||
Trigger | 触发条件。此字段必须为如下取值中的一到多个(若有多个,则使用空格分隔):
| ||||||||||
Actions | (可选) 欲执行的动作,为合乎动作格式的字符串列表。 | ||||||||||
Action | (可选) 欲执行的单个动作,须合乎动作格式。
此命令为Actions只有单个动作的简写。技术上而言您可以同时使用这两个字段,但实际上您应当仅使用其中一个。 | ||||||||||
HostOnly | (可选) 触发动作是否仅适用于房主。若为true,则合作模式下此动作不会对农场帮手执行。 | ||||||||||
MarkActionApplied | (可选) 当事件触发时,是否将其标记为已触发。默认为true。 | ||||||||||
Condition | (可选) 一个游戏状态查询,表示当前是否可以应用此动作。默认为始终为 “true”。 | ||||||||||
CustomFields | (可选) 此条目的自定义字段。 |
其他位置
您也可以直接从如下位置加载动作:
- 使用$action命令的对话字符串。例如:
"Mon": "Hi there! Here's 10g and a parsnip, don't spend it all at once.#$action AddMoney 10#$action AddItem (O)24"
- 使用action命令的事件脚本。例如:
"{{ModId}}_Event": "continue/64 15/farmer 64 16 2 Abigail 64 18 0/pause 1500/speak Abigail \"Hi. Here's 10g and a parsnip.\"/action AddMoney 10/action AddItem (O)24/pause 500/end"
另请参阅setSkipActions命令。
- 使用%action命令的信件数据。例如:
"{{ModId}}_Letter": "Hey there!^Here's 10g and a parsnip. Take care!^ -Abigail%action AddMoney 10%% %action Additem (O)24%%[#]A gift from Abigail"
- 使用debug action控制台命令的SMAPI 控制台窗口。例如:
> debug action "AddMoney 10" Applied action 'AddMoney 10'.
针对C#模组作者
在C#中使用触发事件
触发动作主要用于Content Patcher内容包。C# mod 可以使用SMAPI的Events API代替,这样会更加灵活和高效(除非您希望内容包编辑您的触发动作)。
扩展性
C# mods 可以使用 StardewValley.Triggers.TriggerActionManager 类与触发动作进行交互。
例如,您可以...
- 注册/调用自定义动作
// register custom trigger type TriggerActionManager.RegisterTrigger("Some.ModId_OnItemReceived"); // run actions in Data/TriggerActions for the custom trigger TriggerActionManager.Raise("Some.ModId_OnItemReceived", new[] { item, index }); // trigger can pass optional trigger arguments
- 添加新动作
TriggerActionManager.RegisterAction("Some.ModId_PlaySound", this.PlaySound); ... /// <inheritdoc cref="TriggerActionDelegate" /> public static bool PlaySound(string[] args, TriggerActionContext context, out string error) { // get args if (!ArgUtility.TryGet(args, 1, out string soundId, out error, allowBlank: false)) return false; // apply Game1.playSound(soundId); return true; }
- 或运行动作字符串:
// NOTE: this is just an example of how to run an action. This is meant to support actions specified in data or content // packs. If you want to send mail (or perform other actions) in C#, it's better to call the C# APIs directly instead. string action = "AddMail Current Robin Now"; if (!TriggerActionManager.TryRunAction(action, out string error, out Exception ex)) Game1.log.Error($"Failed running action '{action}': {error}", ex);
为避免冲突,自定义触发条件的名称应当为唯一字符串ID。
常见问题
触发动作 vs 地图动作
动作可能指如下两个不同的概念:
- 触发的动作(本页)可让您执行随时可行的一般背景任务,如发送信件或开始任务。这些操作可以根据条件自动触发,也可以通过对话、事件等中的命令触发。
- 地图动作指的是 Action 和 TouchAction 地图属性,当您在地图上行走或与地图地块互动时,这些属性会执行某些操作。这些属性可以执行一系列特定于地图和交互的操作,如显示消息框、更改地图、打开商店菜单等。这些功能只在地图中起作用,在其他情况下一般没有意义。
除了名称相似外,这两个概念完全不同。
使Data/TriggerActions重复发生
默认情况下,Data/TriggerActions 中的每个触发动作对每个玩家只触发一次。 重复触发有两种主要方式:
- 立即使其能够重复触发,为此,需要为Data/TriggerActions中的列表项设置"MarkActionApplied": false。
- 稍后使其能够重复触发,可以使用MarkActionApplied动作来忘记此事件已触发。
在下面的例子中,Content Patcher补丁(patch)会根据一周的不同日期交替设置"work"或"weekend"信件标识:
{ "Format": "2.3.0", "Changes": [ { "Action": "EditData", "Target": "Data/TriggerActions", "Entries": { // set 'work' flag on weekdays, and reset weekend action "{{ModId}}_Work": { "Id": "{{ModId}}_Work", "Trigger": "DayStarted", "Condition": "!DAY_OF_WEEK Saturday Sunday", "Actions": [ "AddMail Current {{ModId}}_Work Received", "RemoveMail Current {{ModId}}_Weekend", "MarkActionApplied Current {{ModId}}_Weekend false" ] }, // set 'weekend' flag on weekends, and reset work action "{{ModId}}_Weekend": { "Id": "{{ModId}}_Weekend", "Trigger": "DayStarted", "Condition": "DAY_OF_WEEK Saturday Sunday", "Actions": [ "AddMail Current {{ModId}}_Weekend Received", "RemoveMail Current {{ModId}}_Work", "MarkActionApplied Current {{ModId}}_Work false" ] }, } } ] }