目录

快速教程 Quick Start Tutorial

(版本:2018-10-16 翻译:kjiang 原文链接

(为方便理解,本文和原文有出入)

成功安装完BetonQuest之后,你一定想先了解这个插件是怎么运作的吧?不过首先,如果你想修改对话展示方式,比如从文字该城GUI,你可以修改config.yml中的设置,把default_conversation_IO修改成chest,然后输入/q reload重载配置。

BetonQuest在成功安装之后,会默认自带一个叫Innkeeper的简单任务。如果需要在服务器中启用这个任务,你首先需要创建一个NPC,这里有两种创建方法:

如果NPC对话未能显示,你可能需要检查一下BetonQuest是否已被正确安装(使用/bq version指令确认),或NPC创建步骤是否有遗漏。

如果没有问题,你就可以接着体验这个初始任务了。一开始这个NPC会向你提供一项简单任务,当你选择接受之后,你会被要求去砍一些树。在任务过程中你可以使用/journal指令查看任务日志以及一些新的任务提示。如果要完成这个任务,不要往地上拜放原木,否则BetonQuest会相应地增加你需要砍伐的原木。当你砍伐并收集到16个原木之后(你也可以从创造模式直接拿16个原木),返回Innkeeper NPC与之对话,它会把你的木头收走并给予你奖励。

从events和conditions开始

现在你已大概了解一个简单的任务是什么样子的了,那么该怎么设计出一个类似的呢?我们先从events事件conditions条件开始入手:

事件 Events

我们先打开default文件夹中的events.yml文件,然后在后面加入新的一行:

events.yml
foo: message Hello world!

这是一条事件指令。BetonQuest会根据这个指令执行触发相应的事件Events。在这个例子中,foo是你对这个事件的命名(名为foo的事件);message是事件的类型,这个是向玩家发送消息;而Hello world!则是message事件的参数,也就是消息内容。当你执行这个foo事件,BetonQuest就会向你显示Hello world!消息。

现在保存这个文件,并输入/q reload命令重新加载。然后我们可以测试这个事件是否有效了:在游戏中输入/q e {name} foo命令(备注:qquest的缩写,eevent的缩写,{name}填入你的Minecraft名字,foo则表示上面刚刚编写的foo事件。如果成功,那么玩家的聊天框就会显示Hello world!这一段消息。

我们现在来试一试别的事件,就拿传送teleport好了。只要你看过事件列表,就知道这个传送事件需要一个座标作为参数。在游戏里按F3就可以看到你现在的座标(在左边,有三个数字分别代表xyz座标)。现在把这个座标写到events.yml文件的末尾:

events.yml
bar: teleport 100;200;300;world

记得把100改成你的x座标,200改为y,还有300改为zworld改为你现在所在的世界(一般情况下就是world)。然后保存这个文件、重新加载BetonQuest(/q reload)并照葫芦画瓢用上面的/q event {namne} bar命令测试这个事件。如无意外,你会被传送到那个座标。

现在恭喜你!你已经学会了怎么创建事件。你现在可以自己试试事件列表中的其它事件。熟练之后我接着学习条件Conditions

Conditions

Open the _conditions.yml_ file and add there a new line:

  1. foo: location 100;200;300;world;5

Can you see how we named the foo condition in the same way as the foo event? They are not connected in any way. Condition names and event names are separated, so you can give them the same name without any problems. Now let's look at the instruction string. As you can suspect, location is a type of the condition. This one means that we'll be checking if the player is near that location (you should change the location to the place where you're standing right now, so you don't have to run around the world). Note that at the end of location argument there is an additional number, 5. This is the maximum distance you can be away from the location to meet the condition. Alright, save the file and reload the plugin.

Now walk to the location you have defined in the condition. Try to stand on the exact block corresponding to that location. Issue /q c {name} foo command (c is shortcut for condition). It should show you “checking condition blah blah blah: true”. We're focusing on that last word, true. This means that you're meeting the condition: you're standing withing 5 block radius of the location. Now move 2 blocks away and issue that command again. You should still be meeting the condition. Walk 4 more blocks away and try now. It should show false. You are now outside of that 5 block radius. Get it? Great.

Now I'll show you the simplest use of those conditions. Open the _events.yml_ file again, and at the end of foo instruction add conditions:foo argument. By the way, rename foo event to baz, so the names won't get confusing. Now you should have something like

  1. baz: message Hello world! conditions:foo

Now baz event will run only if it meets foo condition. Reload the plugin, walk outside of the 5 block radius and try to run baz event. Puff, nothing happens. It's because you're not meeting foo condition. Walk into the radius again and try to run that event now. It should happily display the Hello world! message.

It's very nice that we can add such conditions, but the problem is: what if you wanted to display the message only if the player is _outside_ the radius? Don't worry, you don't have to specify inverted_location condition or anything like that. You can simply negate the condition. Negation makes the condition behave in the exact opposite way, in this case it foo will be met only if the player is outside of the 5 block radius, and it won't be met if he's inside. Open the _events.yml_ and add an exclamation mark before the foo condition, so it looks like

  1. baz: message Hello world! conditions:!foo

This means “display message Hello world! if the foo condition is _not met_”. Save the file, reload the plugin and run the event inside and outside of the radius to see how it works.

Basic tags

Now that you know how to use events and conditions I'll show you what tags are. Create new events:

  1. add_beton_tag: tag add beton
  2. del_beton_tag: tag del beton

It's a good practice to give your events names that describe what they are doing. Imagine you have 100 events, foo24, bar65, baz12 etc. You would get lost pretty quickly. So, add_beton_tag event here simply adds beton tag to the player, del_beton_tag removes it. Save the file, reload the plugin and run this event. Nothing happens… or does it? Issue /q t {name} command (t is shortcut for tags). It should show you a list with few entries. Right now focus on default.beton, the rest are used by the default quest for Innkeeper. Alright, default is the name of the package in which the tag is, and beton is the name of the tag, as defined in add_beton_tag event. Now run del_beton_tag event. Guess what, default.beton disappeared from the list! And that's it, you know how to add and remove tags. Pretty useless.

Nothing could be more wrong. Tags are one the most powerful things in BetonQuest. They just need to be used with tag condition. Open _conditions.yml_ and add

  1. has_beton_tag: tag beton

line. As you can imagine, tag is the type of a condition (the same as tag event, but these are not the same things - one is an event, the other one is a condition) and beton is the name of the tag. You don't have to specify default.beton, but you can if you want. Now save, reload and check it with a command. It should show false, since you have removed the tag with del_beton_tag event. Add it again with add_beton_tag event and check the has_beton_tag condition again. Now it will show true.

Now you probably understand how powerful this system is. You could for example set a tag on the first time the player talks with an NPC, and if the NPC sees that tag next time they talk, he will tell something different, like “welcome back”.

Creating objectives

Time to write some objectives! Open the _objectives.yml_ file and add a new line:

  1. kill_creepers: mobkill creeper 3 events:bar conditions:has_beton_tag

Now let's analyze it. kill_creepers is a name of the objective. mobkill is a type. In this case, to complete the objective the player will have to kill some mobs. creeper is a type of the mob, so we know that these mobs will have to be Creepers. 3 is the amount. It means that the player has to kill 3 Creepers. events:bar means than once the player kills those Creepers, the bar event will be run (it's the teleportation event). conditions:has_beton_tag tells us that the player will have to have beton tag while killing Creepers to complete the objective. Save it, reload the plugin and issue /q o {name} add kill_creepers command (o is for objective, add tells the plugin to add an objective).

Now you can check if you actually have this objective with /q o {name} command, it will show you all your active objectives. It should show default.kill_creepers. Alright, remove (yes, remove!) the beton tag from you and find some Creepers to kill. Once you killes 3 of them you will notice that nothing happened. It's because has_beton_tag condtion is not met, so the objective does not count your progress. Now add the tag again and kill another Creepers. When the third is dead you should be teleported to the location defined in bar event.

Congratulations, now you know how to use objectives. You should experiment with other types now, since objectives will be used very often in your quests. Once you're done check out the _Writing your first conversation_ chapter to use your knowledge to write your fisrt conversation.

Writing your first conversation

Now that you have seen BetonQuest in action and understood events, conditions and objectives, it's time for writing your first conversation. There's a _conversations_ directory inside the default package. It contains a single file, _innkeeper.yml_. This is the conversation with Innkeeper, the one who asks you to cut some trees. Open it, we'll use that for reference. Now create a new file, let's say _miner.yml_. Now type (don't copy-paste it, you'll learn better while typing) that into the file:

  1. quester: Miner
  2. first: greeting
  3. NPC_options:
  4.   greeting:
  5.   text: Hi there, traveler!

It's the most basic conversation possible. The NPC named Miner upon starting the conversation will use greeting option, which means he will say Hi there, traveler!. Then the conversation will end, because there are no player options defined.

Now you need to link the conversation with an NPC. You do that in the _main.yml_ file. Open it now. As you can see, _inkeeper.yml_ conversation is linked to Innkeeper word. It's the one you have put on the sign, remember? Now, add another line under the Innkeeper: Miner: miner.yml, save the file and reload the server. This will link our new conversation with the NPC named “Miner”. Construct a new NPC on the server, give him a sign with “Miner” name and click on the head.

Guess what, the conversation finished right after it started. The Miner just said Hi there, traveler!, as expected. Now go to the conversation file and edit it (again, manually, no copy-paste!) so the options look like this:

  1. NPC_options:
  2.   greeting:
  3.   text: Hi there, traveler!
  4.   pointers: hello, bye
  5. player_options:
  6.   hello:
  7.   text: Hello!
  8.   bye:
  9.   text: I need to go, sorry.

When you save the file, reload the plugin and start the conversation again you will notice that there are two options for you to choose: Hello! and I need to go, sorry. Choosing any of them will end the conversation, because these options did not specify any pointers.

Now add a new NPC option, for example weather with text Nice weather. and make hello player option point to it. When you save&reload, the Miner should say Nice weather. when you tell him Hello!. I think you get how it works.

  1. NPC_options:
  2.   greeting:
  3.   text: Hi there, traveler!
  4.   pointers: hello, bye
  5.   weather:
  6.   text: Nice weather.
  7. player_options:
  8.   hello:
  9.   text: Hello!
  10.   pointer: weather
  11.   bye:
  12.   text: I need to go, sorry.

Now, every time you talk to the Miner, he will say the same thing. It would be nice if the second time you talk to him he knew your name. We can do that with tags. Define a meet_miner event and has_met_miner condition. When you talk to the Miner for the first time, he will check if you have met him. If not, he will meet you (with that event) and next time you talk, the condition will be passed and he will use your name.

Now, rename greeting NPC option to first_greeting. Add meet_miner event and negated has_met_miner condition (negated because this option should only show if the player has not met the Miner yet). You will need to surround the condition with ' ', because strings cannot start with exclamation marks in YAML. It should look like this:

  1. first: first_greeting
  2. NPC_options:
  3.   first_greeting:
  4.   text: Hi there, traveler!
  5.   condition: '!has_met_miner'
  6.   event: meet_miner
  7.   pointers: hello, bye

This means: first_greeting should be used if the player does not pass has_met_miner condition (meaning he doesn't have a tag because he haven't talked to the NPC yet). When this option is used, it will fire meet_miner event and display hello and bye options. Alright, but what happens if the player met the Miner and now negated has_met_miner condition doesn't work? NPC will try to use next option defined in first setting. There is none yet, so let's add it.

  1. first: first_greeting, regular_greeting
  2. NPC_options:
  3.   regular_greeting:
  4.   text: Hi %player%!
  5.   pointers: hello, bye

This option does not have any conditions, so if the first_greeting fails, the NPC will always choose this one. Now take a look at the %player% thing. It's a variable. In this place it will show your name. There are more than this one, they are described in _Reference_ chapter. Alright, save&reload and start the conversation. If you did everything correctly, the Miner should greet you as a “traveler”, and the second time you talk to him, he should greet you with your Minecraft name.

Here's the whole conversation you created, so you can check if you understood everything correctly:

  1. first: first_greeting, regular_greeting
  2.   NPC_options:
  3.   first_greeting:
  4.   text: Hi there, traveler!
  5.   condition: '!has_met_miner'
  6.   event: meet_miner
  7.   pointers: hello, bye
  8.   regular_greeting:
  9.   text: Hi %player%!
  10.   pointers: hello, bye
  11.   weather:
  12.   text: Nice weather.
  13.   player_options:
  14.   hello:
  15.   text: Hello!
  16.   pointer: weather
  17.   bye:
  18.   text: I need to go, sorry.

Now you should experiment some more with this conversation, you can help yourself by looking at the _innkeeper.yml_ file. Try to understand how that conversation works step by step. As the excercise you should complete the Miner NPC, so he asks you to mine some iron ore, then smelt it in the furnace, next craft an armor with it and return to him wearing this armor.

You might want to check out the _Reference_ chapter to see how to handle items in your quests and how to add entries to the journal. If you want to use Citizens NPCs instead of the ones made with clay you will find information you need in that chapter too. To find out more about events, conditions, objectives and variables, take a look at the appropriate lists (after the Reference chapter).



(下面是早期我们内部人员根据自己的理解编写的简易教程,供大家参考:)

1.启用你的NPC

  1. 上传NPC文件至服务器后台,为了方便维护,建议文件命名方式使用:NPC名称.yml
  2. 通过重新加载的方式使得你上传的NPC文件生效,指令:/q reload
  3. 创建NPC
    1. 放置一块染色粘土
    2. 在它上面放一个头
    3. 在粘土块的一侧放置一个牌子
    4. 写在第一和第二行
      [NPC]
      你上传的NPC名称(如Mycroft.yml就是Mycroft)
  4. NPC已启用

2.为你的NPC添加事件

信息事件

  1. 在默认包中打开events.yml文件
  2. 最后添加一个新行:
    XXX: message 烤麸烤麸考~
    XXX为事件名称
    message为事件类型(此为信息事件)
    烤麸烤麸考~为你所要显示的信息
  3. 重复*1
  4. 使用指令执行事件XXX
    指令:/ qe {name} XXX
    qe:q快捷方式是quest,e是快捷方式event
    {name}是没有括号的用户名

进阶:

message {en} &4You are banned, %player%!

{pl} &4Jestes zbanowany, %player%!

{de}&4Ich weiß nicht.

{}内为语言缩写(如中文cn,英文en)

&4为颜色代码

%player%指代玩家昵称

传送事件

1.在默认包中打开events.yml文件

2.在MC中按F3查看你想设定的坐标位置

3.最后添加一个新行:

XXX: teleport 366;65;290;world

说明:

teleport为事件类型(此为传送事件)

366;65;290;为对应XYZ坐标

world为世界名称

4.重复步骤1.1上传NPC文件、1.2重新加载NPC文件以及步骤2.4通过命令执行事件.(以后统称“进行测试”)

5.倘若正确无误,它应该将你传送到你指定的位置。

进阶:

若想使传送者转身或偏头,应用偏航与俯角

teleport 123;32;-789;world;180;45

180对应偏航(左右偏)

45对应俯角(上下偏)

赋点事件

point XXX XXXX

point为事件类型(此事件为赋点事件)

XXX为赋点对象(可以为玩家或NPC)

XXXX为所赋点值(XXXX为加,-XXXX为减,*XXXX为乘,/XXXX为除)


事件类快速教学到此结束,更多事件教程请查阅事件列表