高级技巧 Tips and Tricks
(版本:2018-10-16 翻译:kjiang 原文链接)
(为便于理解,本文和原文有所出入)
Handling death in your quests
Sometimes, while writing a dangerous quest you will want something specific to happen when the player dies. If it's a boss battle you may want to fail the quest, if it's a dungeon you may want to respawn the player at the beginning of a level etc. You can do that with die
objective - simply start it for the player at the beginning of the quest and make it fire events that will do the thing you want (like teleporting the player to desired respawn point, removing tags set during the quest etc). You can add persistent
argument to the objective instruction string to make it active even after completing it. Remember to delete
it after the quest is done!
Creating regions for one player at the time
Imagine you have a room to which the player is teleported. Then suddenly mobs start to spawn and the player must kill them (because it's a trap or something). The player has killed all the mobs, he got a tag and wants to proceed but all of the sudden another player teleports into the room and all the mobs start to spawn again. The first player is quickly killed and the second one easily kills all mobs. You can prevent such situations by using party
condition. Just check with it if the party consisting of “players inside the room” has greater amount of players that 1. Set the range to something big enough so it covers the room and the party condition can be tag or location.
Racing with folder event
Since folder
event can run tag
events even for offline players you can create races. Create location
objective where you want the finish line to be and condition it with negated “race_failed” tag (or similar). It will mean that “if the player has not failed the race, he can win it by reaching the location”. Now when the race starts fire folder
event with the amount of time you want to give your players to complete the race. This event should set “race_failed” tag. If the player reaches the location before this tag is set, he will fire all events in that location
objective, but if the time has passed, the objective will not be completed. You can figure the rest out for yourself.
Random daily quests
Starting the random quest must be blocked with a special tag. If there is no such tag, the conversation option should appear. Create a few quests, each of them started with single folder
event (they must be started by single event!). Now add those events to another folder
event and make it random:1
. At the end of every quest add delay
which will reset the special blocking tag. Now add that folder
event to the conversation option. When the player chooses it he will start one random quest, and the conversation option will become available after defined in delay
objective time after completing the quest.
每日固定随机任务
(所有人都是同一个随机任务)
通过设置静态事件,配合事件包folder就可以创建一个每天都固定的随机任务。思路是让BetonQuest每天在固定的时刻随机更改某个座标上的方块,然后在玩家和NPC对话中,判断这个座标上的方块种类,展示相对应的对话内容。
具体实现步骤如下:
- 首先编辑你的main.yml,在static新增加一个静态事件(如果没有static就创建一个。):
- main.yml
static: '23:59': 刷新随机任务
这会在每天的23:59刷新这个随机任务。
- 然后在events.yml创建一个叫“刷新随机任务”的事件:
- events.yml
刷新随机任务: folder 改成紫色羊毛,改成黄色羊毛,改成黑色羊毛 random:1
这里的“改成紫色羊毛”是另一个事件,它会修改某个座标的方块种类,例如:
- events.yml
刷新随机任务: folder 改成紫色羊毛,改成黄色羊毛,改成黑色羊毛 random:1 改成紫色羊毛: setblock PURPLE_WOOL 123;64;456;world 改成黄色羊毛: setblock YELLOW_WOOL 123;64;456;world 改成黑色羊毛: setblock BLACK_WOOL 123;64;456;world
(你可以查看设置方块setblock的用法和参数格式)例子中123;64;456;world座标是随便举的例子,你应该把这个座标设置在碰不到的地方,比如搜保护的领地内。
- 在任务NPC的各个初始对话中各插入一个方块检测testforblock条件conditions,比如:
- conversations/工会NPC.yml
quester: 工会NPC start: 任务A,任务B,任务C NPC_options: 任务A: text: '今天工会提供任务A哦,你要接受吗?' conditions: 是紫色羊毛 任务B: text: '今天工会提供任务B哦,你要接受吗?' conditions: 是黄色羊毛 任务C: text: '今天工会提供任务C哦,你要接受吗?' conditions: 是黑色羊毛
- 别忘了你的conditions.yml:
- conditions.yml
是紫色羊毛: testforblock 123;64;456;world PURPLE_WOOL 是黄色羊毛: testforblock 123;64;456;world YELLOW_WOOL 是黑色羊毛: testforblock 123;64;456;world BLACK_WOOL
让NPC表现得更随机一些
假设你需要某个NPC有15%的机率玩家相信玩家、35%的机率怀疑、剩下50%的机率完全不相信玩家,那么怎么设计呢?
基本思路是,设计出一段对话conversation,让NPC有15%的概率显示对话a、35%概率显示对话b、50%概率显示对话c。我们可以借助随机/概率random这个condition实现。那么我们先制作出三段对话:
- conversations/怀疑者.yml
- quester: 怀疑者
- start: 初始对话
- NPC_options:
- 初始对话:
- text: "我要怎么相信你?"
- pointer: "相信我"
- 我相信: # 有15%的概率会显示这段对话
- text: "行吧,我相信你。"
- conditions: 相信的概率
- 我怀疑: # 有35%的概率会显示
- text: "我没空,下次再说吧。"
- conditions: 怀疑的概率
- 我不信: # 有50%的概率会显示
- text: "我不信,除非你证明给我看。"
- conditions: 不信的概率
- player_optoins:
- 相信我:
- text: "相信我, 我是认真的!"
- pointer: 我相信,我怀疑,我不信
然后是相信的概率
、怀疑的概率
、怀疑的概率
:
- conditions.yml
- 相信的概率: random 15-100 # =15%
- 怀疑的概率: random 35-85 # =(35%)/{1-15%}=35%/85%=46.6666%
- 不信的概率: random 50-50 # =(50%)/{(1-15%)(1-35%/85%)}=50/50=100%
注意这里怀疑的概率
填的并不是“35-100”,不信的概率
也不是“50-100”,为什么?
因为BetonQuest在判断conditions的时候是按顺序逐个计算的,注意对话文件的第20行:
pointer: 我相信,我怀疑,我不信
在这里,NPC有三个选项,BetonQuest在决定NPC的下一段对话的时候,会按照如下顺序计算conditions:
- 先计算
我相信
对话里的conditions条件(相信的概率
)是否满足,如果满足则显示“我相信你。” - 如果“我相信”里的conditions不满足,则计算
我怀疑
里的conditions条件(怀疑的概率
),满足则显示“我没空,下次再说吧。” - 如果“我怀疑”也不满足,最后则计算
我不信
的conditions条件(不信的概率
)
我们逐个分析:
- 首先第一个选项“我相信”很好理解,BetonQuest开始计算“我相信”中的conditions
相信的概率
,因为“相信的概率”是random 15-100
,也就是说第一段对话有15/100的概率“满足”,也就是15%的概率会显示出来。但如果不满足, - 然后BetonQuest就会开始计算“我怀疑”的conditinos
怀疑的概率
,注意,因为BetonQuest是按顺序计算conditions条件,所以这个计算是在上一个条件“相信的概率”不满足的大前提下计算的。上一个选项不满足条件的概率是100%-15%=85%,如果你“怀疑的概率”填写的是“35-100”,那么玩家实际触发这个“我怀疑”对话的概率是=(85%)x(35%)=29.75%,并不是你所想的35%。所以我们应该填35-85
,因为{第一个选项不满足条件的概率}x{第二个选项不满足条件的概率}={85%}x{35/85}刚好等于你想要的35% - 如果“我怀疑”也不满足,现在BetonQuest需要计算最后一个选项“我不信”,同样它的conditions条件需要在之前两个选项都不满足的大前提下计算。我们知道第一个选项不满足条件的概率是85%,而第二个选项不满足条件的概率是100%-(35/85)%=(50/85)%(注意这里我们用“35-85”计算不满足率),那么第三个需要填写的概率应该是
50-50
,因为{第一个选项不满足条件的概率}x{第二个选项不满足条件的概率}x{第三个选项满足条件的概率}={85%}x{50/85}x{50/50}=50/100刚好等于50%
因为计算的概率和pointer(pointer: 我相信,我怀疑,我不信
)的排序有强烈关系,所以pointer里填写的(“我相信”、“我怀疑”和“我不信”)顺序不能打乱,否则实际概率会变!
这里有一个快速计算公式,假设你有a%、b%、c%、d%、e%…种概率:
- 第一个填写的概率 -
a-100
- 第二个填写的概率 -
b-{100-a}
- 第三个填写的概率 -
c-{100-a-b}
- 第四个填写的概率 -
d-{100-a-b-c}
- 第五个填写的概率 -
e-{100-a-b-c-d}
- …
- 最后一个填写的概率 -
100-100
其实不用填,因为一定等于100%
例如,a=3、b=7、c=15、d=31…:
- 第一个 -
a满足: random 3-100
- 第二个 - 7-{100-3}=7-97
b满足: random 7-97
- 第三个 - 15-{100-3-7}=15-90
c满足: random 15-90
- 第四个 - 31-{100-3-7-15}=31-75
d满足: random 31-75
- …
- 最后一个 - (不用写conditions)
Quest GUI
If you want your players to be able to choose a quest everywhere, every time, then you can create a conversation which can be started with an item. This one is a little hacky but it shows flexibility of BetonQuest. First you need a conversation which behaves as a quest choosing GUI. Name the NPC “Quester”, add one option for each quest etc. Now you need an objective which will start this conversation using conversation
event. It should be action
objective, set to right click on any block. Add hand
condition to make it accept only clicks with a specific item and make the objective persistent
(so players can use it multiple times). The item used here should be marked as Quest Item so players can't drop it. Now define new global location covering your whole map and using it start the objective and give players the item. This way all players (existing and new) will get the quest item, which opens a GUI with quests when right clicked.