Stendhal Quest Coding - Part 3
Stendhal Quests
You may want to read the first part and second part of the Stendhal Quest Coding tutorial first.
If you have ideas for new quests or are interested in helping to refine quest ideas, please have a look at the Quest Contributor's Guide or the Stendhal Quest Ideas.
Rewarding the player
In the last section of this tutorial we taught Hayunn to only accept one beer per player. We didn't actually take the beer from the player nor did we reward the player. We want to add this functionality now.
We have to do several things at once:
- take the beer from the player
- provide some money as refund
- increase the xp and karma
- and finally remember that the quest was completed
But don't worry, that sounds more complicated than it actually is. There are already actions for all of these tasks that can be combined using a MultipleAction:
<source lang="java">
List<ChatAction> reward = new LinkedList<ChatAction>();
reward.add(new DropItemAction("beer"));
reward.add(new EquipItemAction("money", 20));
reward.add(new IncreaseXPAction(50));
reward.add(new IncreaseKarmaAction(10));
reward.add(new SetQuestAction(QUEST_SLOT, "done"));
npc.add(
ConversationStates.ATTENDING,
"beer",
new PlayerHasItemWithHimCondition("beer"),
ConversationStates.ATTENDING,
"*glug glug* Ah! That hit the spot. Let me know if you need anything, ok?",
new MultipleActions(reward));
</source>
Asking the player for the beer
Let's make it a bit easier for player to remember that they bought a beer in order to give it to Hayunn. Hayunn should notice the beer as soon as the player says "hi" and he actively asks for it.
Therefore we add a new trigger for the GREETING_MESSAGE. There is an internal rule that transitions which have a condition (that is true) are preferred over equal transitions without one. So our greeting transition is used instead of the normal one if the player has the item and the quest is active. Similar to the MultipleAction, there is an AndCondition which combines multiple elementary ones.
<source lang="java">
// player has the quest active and has a beer with him, ask for it
npc.add(
ConversationStates.IDLE,
ConversationPhrases.GREETING_MESSAGES,
new AndCondition(new QuestActiveCondition(QUEST_SLOT), new PlayerHasItemWithHimCondition("beer")),
ConversationStates.QUEST_ITEM_BROUGHT,
"Hey! Is that beer for me?",
null);
// player has accepted the quest but did not bring a beer, remind him
npc.add(
ConversationStates.IDLE,
ConversationPhrases.GREETING_MESSAGES,
new AndCondition(new QuestActiveCondition(QUEST_SLOT), new NotCondition(new PlayerHasItemWithHimCondition("beer"))),
ConversationStates.ATTENDING,
"Hey, I'm still waiting for that beer, remember? Anyway, what can I do for you?",
null);
</source>
As we have learned in the second part of this tutorial, we use a new state for the question. In this case it is named QUEST_ITEM_BROUGHT.
Important note: You need to check again that the player still has the beer when he says yes. Otherwise he could have dropped it to the ground after Hayunn saw it and went to state QUEST_ITEM_BROUGHT.
<source lang="java">
// okay, the player wants to give us a beer :-)
List<ChatAction> reward = new LinkedList<ChatAction>();
reward.add(new DropItemAction("beer"));
reward.add(new EquipItemAction("money", 20));
reward.add(new IncreaseXPAction(50));
reward.add(new IncreaseKarmaAction(10));
reward.add(new SetQuestAction(QUEST_SLOT, "done"));
npc.add(
ConversationStates.QUEST_ITEM_BROUGHT,
ConversationPhrases.YES_MESSAGES,
new PlayerHasItemWithHimCondition("beer"),
ConversationStates.ATTENDING,
"*glug glug* Ah! That hit the spot. Let me know if you need anything, ok?",
new MultipleActions(reward));
// the player has a beer but wants to keep it for himself :-(
npc.add(
ConversationStates.QUEST_ITEM_BROUGHT,
ConversationPhrases.NO_MESSAGES,
null,
ConversationStates.ATTENDING,
"Drat! You remembered that I asked you for one, right? I could really use it right now.",
null);
</source>
Quest Documentation
We are almost done now. Almost? Yes, a very important thing is still missing. And we should have done it as the first thing. But well, better late than never. Here we create the javadoc which summarises our code in a readable form, for other developers and for our future selves!
<source lang="java"> /**
* QUEST: Beer For Hayunn * * PARTICIPANTS:
*
-
*
- Hayunn Naratha (the veteran warrior in Semos) *
- Margaret (the tavern maid) *
* * STEPS:
*
-
*
- Hayunn asks you to buy a beer from Margaret. *
- Margaret sells you a beer. *
- Hayunn sees your beer, asks for it and then thanks you. *
* * REWARD:
*
-
*
- 20 gold coins *
- 50 XP *
- 10 karma *
* * REPETITIONS:
*
-
*
- None *
*/
</source>
This documentation is only a little work in most cases because it is just a reformatted version of the quest description.
Quest Information Methods
These are used for the travel logs and other parts of the game which refer to quests - e.g. the achievement for completing all quests in Semos needs the region to be set for quests in Semos city, to be able to find them.
TODO: fill in description, help and examples on methods below and add missing methods by checking abstract quest
getRegion
getNPCName
getHistory
getQuestInfo
Further Reading and Complete Code
You can have a look at the complete source code for this quest.
The pages might be of interest to you:
- How to add items
- How to add new maps to server
- How to create NPC
- How to test NPC Parser - this can help with trouble shooting