Wiz Programming Tutorials

Here we'll show you how to award quest points to a player.

Right now there's no way for a player to see what quests they've solved. We don't actually keep enough information, unfortunately, and we'll have to do a "backfill" to fix it. (A backfill is a script that modifies every player in the player base). In this tutorial, we'll make sure you set up your quests so that when we implement the command for seeing what quests you've solved, you'll have enough info for us already.

Some terms:

  • mini-quest — a simple quest, usually only one quest point, that typically involves running an errand for an NPC.

  • main quest — a bigger quest, possibly composed of multiple mini-quests.

A very general rule of thumb, which you shouldn't take as the law, is that a quest point roughly corresponds to a few hours of work. It can be an hour or two of monster-killing, or several hours of hunting around, or some combination of the two. It's a fairly loose system, though, so you should talk to an Arch Wizard if you're not sure how many to award.

Map Editor Support

It's possible to set up an NPC to award quest points when a quest is solved using the Quest tab in the Monster Editor. You fill out the dialog, and it puts a QuestSolver property on your NPC that automatically solves the quest when the NPC is activated.

This is how you'll do 90% of your quests, including most mini-quests.

Rolling Your Own

Sometimes you'll need to award quest points when the player has solved a puzzle or performed some other action that doesn't involve interacting with an NPC. We'll cover how to do this here.

Ingredients

You'll need:

  • a (unique) short name for your quest, such as legolas-oldmage. This is used to uniquely identify your quest, and only needs to be set when the quest is completely solved.

  • a unique long name for the quest, such as Kiz's Side Scroller Quest, or "Cult of the Aquator". This is what the game driver shouts when the quest is solved, and will eventually be what the player sees when they type the "quests" command. It's also how the quest is listed in the Adventurers Guild and on the website.

  • a number of quest points to give out for the quest.

Recipe

Here's some example code that solves a quest for you:

<span class='keyword'></span>from<span class='keyword'></span> <span class='keyword'></span>java<span class='keyword'></span>.<span class='keyword'></span>lang<span class='keyword'></span> <span class='keyword'></span>import<span class='keyword'></span> <span class='keyword'></span>Boolean<span class='keyword'></span>, <span class='keyword'></span>String<span class='keyword'></span><br><span class='keyword'></span>from<span class='keyword'></span> <span class='keyword'></span>wyvern<span class='keyword'></span>.<span class='keyword'></span>lib<span class='keyword'></span> <span class='keyword'></span>import<span class='keyword'></span> <span class='keyword'></span>Predicate<span class='keyword'></span>, <span class='keyword'></span>Kernel<span class='keyword'></span><br><span class='keyword'></span>from<span class='keyword'></span> <span class='keyword'></span>wyvern<span class='keyword'></span>.<span class='keyword'></span>lib<span class='keyword'></span>.<span class='keyword'></span>properties<span class='keyword'></span> <span class='keyword'></span>import<span class='keyword'></span> <span class='keyword'></span>GiveInterest<span class='keyword'></span><br><span class='keyword'></span>from<span class='keyword'></span> <span class='keyword'></span>wyvern<span class='keyword'></span>.<span class='keyword'></span>kernel<span class='keyword'></span>.<span class='keyword'></span>monsters<span class='keyword'></span> <span class='keyword'></span>import<span class='keyword'></span> <span class='keyword'></span>MonsterImpl<span class='keyword'></span><br><span class='keyword'></span>from<span class='keyword'></span> <span class='keyword'></span>wyvern<span class='keyword'></span>.<span class='keyword'></span>kernel<span class='keyword'></span>.<span class='keyword'></span>kernel<span class='keyword'></span> <span class='keyword'></span>import<span class='keyword'></span> <span class='keyword'></span>Logging<span class='keyword'></span><br><span class='keyword'></span>from<span class='keyword'></span> <span class='keyword'></span>wyvern<span class='keyword'></span>.<span class='keyword'></span>world<span class='keyword'></span> <span class='keyword'></span>import<span class='keyword'></span> <span class='keyword'></span>World<span class='keyword'></span><br><br><span class='keyword'>class</span> <span class='function'>questdude</span>(MonsterImpl, GiveInterest):<br><br>    <span class='keyword'>def</span> <span class='function'>initialize</span>(self):<br>        <span class='keyword'></span><span class='instance'>self</span><span class='keyword'></span>.<span class='keyword'></span>super__initialize<span class='keyword'></span>()<br>        <span class='keyword'></span><span class='instance'>self</span><span class='keyword'></span>.<span class='keyword'></span>setImage<span class='keyword'></span>('<span class='keyword'></span>npc<span class='keyword'></span>/<span class='keyword'></span>old_sage<span class='keyword'></span>')<br>        <span class='keyword'></span><span class='instance'>self</span><span class='keyword'></span>.<span class='keyword'></span>setLayer<span class='keyword'></span>(<span class='keyword'></span>1000<span class='keyword'></span>)<br><br>    <span class='keyword'>def</span> <span class='function'>__repr__</span>(self):<br>        <span class='keyword'></span>return<span class='keyword'></span> '<span class='keyword'></span>Quest<span class='keyword'></span> <span class='keyword'></span>Dude<span class='keyword'></span>'<br><br>    <span class='keyword'>def</span> <span class='function'>toString</span>(self):<br>        <span class='keyword'></span>return<span class='keyword'></span> <span class='keyword'></span><span class='instance'>self</span><span class='keyword'></span>.<span class='keyword'></span>__repr__<span class='keyword'></span>()<br><br>    <span class='keyword'>def</span> <span class='function'>receivedGift</span>(self, agent, gift):<br>        <span class='keyword'></span>if<span class='keyword'></span> <span class='keyword'></span>gift<span class='keyword'></span>.<span class='keyword'></span>hasProperty<span class='keyword'></span>('<span class='keyword'></span>myquest<span class='keyword'></span>-<span class='keyword'></span>603<span class='keyword'></span>'):<br>            <span class='keyword'></span><span class='instance'>self</span><span class='keyword'></span>.<span class='keyword'></span>gift<span class='keyword'></span> = <span class='keyword'></span>gift<span class='keyword'></span><br>            <span class='keyword'></span><span class='instance'>self</span><span class='keyword'></span>.<span class='keyword'></span>solveQuest<span class='keyword'></span>(<span class='keyword'></span>agent<span class='keyword'></span>)<br>        <span class='keyword'></span>else<span class='keyword'></span>:<br>            <span class='keyword'></span>agent<span class='keyword'></span>.<span class='keyword'></span>message<span class='keyword'></span>('<span class='keyword'></span>Quest<span class='keyword'></span> <span class='keyword'></span>Dude<span class='keyword'></span> <span class='keyword'></span>says<span class='keyword'></span>:  <span class='keyword'></span>Thank<span class='keyword'></span> <span class='keyword'></span>you<span class='keyword'></span>!')<br>            <span class='keyword'></span>return<span class='keyword'></span><br><br>    <span class='keyword'>def</span> <span class='function'>solveQuest</span>(self, agent):<br><br>        <span class='keyword'></span>agent<span class='keyword'></span>.<span class='keyword'></span>message<span class='keyword'></span>(<span class='string'>"<span class='keyword'></span>Quest<span class='keyword'></span> <span class='keyword'></span>Dude<span class='keyword'></span> <span class='keyword'></span>says<span class='keyword'></span>:  <span class='keyword'></span>It<span class='keyword'></span>'<span class='keyword'></span>s<span class='keyword'></span> <span class='keyword'></span>the<span class='keyword'></span> <span class='keyword'></span>Pilfer<span class='keyword'></span> <span class='keyword'></span>Grommet<span class='keyword'></span> <span class='keyword'></span>of<span class='keyword'></span> <span class='keyword'></span>Myo<span class='keyword'></span>-<span class='keyword'></span>Bar<span class='keyword'></span>!"</span>)<br>        <span class='keyword'></span>agent<span class='keyword'></span>.<span class='keyword'></span>message<span class='keyword'></span>(<span class='string'>"<span class='keyword'></span>Quest<span class='keyword'></span> <span class='keyword'></span>Dude<span class='keyword'></span> <span class='keyword'></span>says<span class='keyword'></span>:  <span class='keyword'></span>Congratulations<span class='keyword'></span>, <span class='keyword'></span>you<span class='keyword'></span>'<span class='keyword'></span>ve<span class='keyword'></span> <span class='keyword'></span>solved<span class='keyword'></span> <span class='keyword'></span>the<span class='keyword'></span> <span class='keyword'></span>quest<span class='keyword'></span>!"</span>)<br><br><span class='comment'>        # see if they've done it already; if so, no quest points</span><br>        <span class='keyword'></span>if<span class='keyword'></span> <span class='keyword'></span>agent<span class='keyword'></span>.<span class='keyword'></span>solvedQuest<span class='keyword'></span>('<span class='keyword'></span>pilfer<span class='keyword'></span>-<span class='keyword'></span>grommet<span class='keyword'></span>'):<br>            <span class='keyword'></span>return<span class='keyword'></span><br><br><span class='comment'>        # give them the quests points and mark them as having solved it</span><br>        <span class='keyword'></span>agent<span class='keyword'></span>.<span class='keyword'></span>adjustIntProperty<span class='keyword'></span>('<span class='keyword'></span>qp<span class='keyword'></span>', <span class='keyword'></span>10<span class='keyword'></span>)<br>        <span class='keyword'></span>numquests<span class='keyword'></span> = <span class='keyword'></span>agent<span class='keyword'></span>.<span class='keyword'></span>adjustIntProperty<span class='keyword'></span>('<span class='keyword'></span>quests<span class='keyword'></span>-<span class='keyword'></span>solved<span class='keyword'></span>', <span class='keyword'></span>1<span class='keyword'></span>)<br>        <span class='keyword'></span>agent<span class='keyword'></span>.<span class='keyword'></span>setProperty<span class='keyword'></span>('<span class='keyword'></span>quest<span class='keyword'></span>-' + <span class='keyword'></span>str<span class='keyword'></span>(<span class='keyword'></span>numquests<span class='keyword'></span>), '<span class='keyword'></span>pilfer<span class='keyword'></span>-<span class='keyword'></span>grommet<span class='keyword'></span>')<br>        <span class='keyword'></span>agent<span class='keyword'></span>.<span class='keyword'></span>setProperty<span class='keyword'></span>('<span class='keyword'></span>quest<span class='keyword'></span>-' + <span class='keyword'></span>str<span class='keyword'></span>(<span class='keyword'></span>numquests<span class='keyword'></span>) + '-<span class='keyword'></span>long<span class='keyword'></span>',                             '<span class='keyword'></span>Pilfer<span class='keyword'></span> <span class='keyword'></span>Grommet<span class='keyword'></span> <span class='keyword'></span>of<span class='keyword'></span> <span class='keyword'></span>Myo<span class='keyword'></span>-<span class='keyword'></span>Bar<span class='keyword'></span>')<br>        <span class='keyword'></span>agent<span class='keyword'></span>.<span class='keyword'></span>autosave<span class='keyword'></span>()<br><br><br><span class='comment'>        # log the fact that they solved it (logger will add date stamp)</span><br><span class='comment'>        # assume the wizard's name is foobar</span><br>        <span class='keyword'></span>logmsg<span class='keyword'></span> = <span class='keyword'></span>agent<span class='keyword'></span>.<span class='keyword'></span>getName<span class='keyword'></span>() + ': <span class='keyword'></span>Pilfer<span class='keyword'></span> <span class='keyword'></span>Grommet<span class='keyword'></span>'<br>        <span class='keyword'></span>log<span class='keyword'></span> = <span class='keyword'></span>Kernel<span class='keyword'></span>.<span class='keyword'></span>writeWizLog<span class='keyword'></span>('<span class='keyword'></span>foobar<span class='keyword'></span>', '<span class='keyword'></span>quest<span class='keyword'></span>.<span class='keyword'></span>log<span class='keyword'></span>', <span class='keyword'></span>logmsg<span class='keyword'></span>)<br><br><span class='comment'>        # put in main quest log as well, if you want</span><br>        <span class='keyword'></span>logger<span class='keyword'></span> = <span class='keyword'></span>Logging<span class='keyword'></span>.<span class='keyword'></span>getLog<span class='keyword'></span>('<span class='keyword'></span>quest<span class='keyword'></span>.<span class='keyword'></span>log<span class='keyword'></span>')<br>        <span class='keyword'></span>logger<span class='keyword'></span>.<span class='keyword'></span>info<span class='keyword'></span>(<span class='keyword'></span>logmsg<span class='keyword'></span>)<br><br><span class='comment'>        # let everyone know (optional)</span><br>        <span class='keyword'></span>World<span class='keyword'></span>.<span class='keyword'></span>shout<span class='keyword'></span>('<span class='keyword'></span>Game<span class='keyword'></span> <span class='keyword'></span>Driver<span class='keyword'></span> <span class='keyword'></span>shouts<span class='keyword'></span>: ' + <span class='keyword'></span>agent<span class='keyword'></span>.<span class='keyword'></span>getName<span class='keyword'></span>() +                     ' <span class='keyword'></span>just<span class='keyword'></span> <span class='keyword'></span>solved<span class='keyword'></span> <span class='keyword'></span>the<span class='keyword'></span> <span class='keyword'></span>Pilfer<span class='keyword'></span> <span class='keyword'></span>Grommet<span class='keyword'></span> <span class='keyword'></span>Quest<span class='keyword'></span>!')<br><br><span class='comment'>        # destroy the real grommet so they can't kill us, take it</span><br><span class='comment'>        # back, and have someone else solve the quest again.</span><br>        <span class='keyword'></span>inv<span class='keyword'></span> = <span class='keyword'></span><span class='instance'>self</span><span class='keyword'></span>.<span class='keyword'></span>getInventory<span class='keyword'></span>()<br>        <span class='keyword'></span>inv<span class='keyword'></span>.<span class='keyword'></span>removeAll<span class='keyword'></span>()

We did a few things in this example:

  1. issued some sort of message to the agent (player) letting them know they solved it.

  2. checked if they've already solved it, and bail if so. The solvedQuest function checks all the quest-N properties to see if your short name is one of the values. More on this below.

  3. gave them 10 quest points.

  4. incremented their 'quests-solved' counter

  5. set a property called 'quest-N' to the quest shortname. This is for the solvedQuest function. The 'N' in this case is one higher than the highest quest number they've solved so far, which is in the 'quests-solved' property.

  6. set a property called 'quest-N-long' to the quest's long name. This is the part we forgot to do for all existing quests. We'll have to add it in for all the quests (Moon Quest, Samhoc, etc.) so can show up in the "quests" command.

  7. wrote a log message to two separate logs: one for the wizard, and also to the main Wyvern quest log. You should avoid writing to the Wyvern log until you've tested your quest and it's ready for people to start solving it, since we don't want a bunch of test messages in there.

  8. shouted to everyone that the agent solved the quest.

  9. (optionally) removed the inventory of the quest NPC, which may or may not apply to you.

A few miscellaneous notes:

  • we weren't super consistent about the long name, which is OK. As long as the player gets the general idea of which quest he or she solved, it's good enough. The long name is really only for display purposes.

  • adjustIntProperty(prop, 1) increments the property and returns the new value.

  • we autosaved the player after solving the quest, to make sure they still get credit if the game crashes right afterwards.

  • we wrote lots of comments. All your code should be just as well commented, and should use lots of whitespace. You should rarely ever have blocks of code longer than 8 lines or so without a blank line to separate it from the next logical step.

  • we also broke all our lines before 80 columns, so no line is longer than 80 columns. This makes the code much more readable, and you should get into the habit of doing it.

That's pretty much all there is to it! Please send us questions if we've missed anything.

<< Previous Chapter Next Chapter >>