Author Topic: Questjournal OLC  (Read 8829 times)

0 Members and 1 Guest are viewing this topic.

Offline erwin

  • Sr. Member
  • ****
  • Posts: 314
    • View Profile
Questjournal OLC
« on: February 09, 2017, 08:18:03 pm »
Here's a brief description of what to do (in practice) with the Questjournal OLC. If there are any questions, feel free to shoot Roland, Maco, or me a note.

Current Questcards will be in this post ; New questcards will be in a separate post.

The goal of the questjournal is to:
  • Prevent spam / too many single questflags when you vstat a player
  • Provide some information to any imms when trying to debug a quest. Eg, is it a logic problem in a quest, or typo problem in a quest, or some other issue?
  • Allow players to track their quest status
  • Allow players to track their trading status
  • Allow players to reset questflags

The following post gives design suggestions on how to transfer current questcards to the quest journal.

Essentially, you need to know the zone in and out.

First, you need to know what ALL the flags are, and how they should be replaced with a new flag. The new flag should be something of the form "questcard<num>_<questname>" etc so it's easier to track flags.

Second, you need to plan how many questflags you want to have, and how the variables in the questflag will change based on the player's status in the quest, and which variables to reset. You should do this before editing any triggers, etc.

Third, while planning the questflags, you should also think of constructing a debug mode trigger at the same time. This helps to prevent errors.

Fourth, you want a mechanism that replaces the flags properly. Remember that questflags are checked when a player interacts with any mob, room, or object that is part of the quest. Function triggers are useful here if you don't want to duplicate code, and prevent errors.

Fifth - extensive testing on 6001 to make sure that every step of the quest / every possible combination works (or doesn't work). Ensure that the debug trigger tells the imm who is debugging where the player is, and what the player needs to do. More information is always better.

A warning for old-> new flag replacing.

Old->New flag replacing

If a player types qcheck <num> <something>, the quest journal will check if the player has the questflags given in the OLC. If not, the quest journal will auto set them. This is great for new quests, but bad for old quests.

Why is this? For example, we will look at Quest 6 (Thetis' Lover). The old quest has 11 questflags, thetis1, thetis2, ... thetis11.

Previously, at a stage, the code would look something like this:

Code: [Select]
if %actor.varexists(thetis2)%
  %echo% You are on stage 2!
else
  %echo% Good day, %actor.name%
endif

Of course, what we really need to do is to create a variable (maybe thetis) - with and set it to different values for each stage, eg
Code: [Select]
set thetis 2
remote thetis %actor.id%
because then we could just do:
Code: [Select]
if %actor.varexists(thetis)%
  if %actor.thetis% == 2
    %echo% You are on stage 2
  endif
endif

So far - this makes sense, right?

In the previous version where we had a quest journal, we put the replacing of flags in a function. Here is how this would have looked like.
Code: [Select]
* Assume this is trigger 12345 as a function

if !%actor.varexists(questcard6_thetis)%
  set questcard6_thetis 0
  if %actor.varexists(thetis1)%
    set questcard6_thetis 1
    rdelete thetis1 %actor.id%
  endif
  if %actor.varexists(thetis2)%
    set questcard6_thetis 2
    rdelete thetis2 %actor.id%
  endif
  if %actor.varexists(thetis3)%
    set questcard6_thetis 3
    rdelete thetis3 %actor.id%
  endif

  * etc etc

  remote questcard6_thetis %actor.id%
endif
etc all the way till thetis11. Note that while the code looks long, and would have eleven if checks (for thetis1 to thetis 11), the first if branch is only ever executed once.

So what would usually be done is this:

Code: [Select]
* Create Thetis flag, and replace questflag
function 12345
if %actor.questcard6_thetis% == 2
  %echo% You are on stage 2
endif

Notice that in the above code, we did not check if the variable questcard6_thetis existed, because our function 12345 would have created this for us automatically if it did not exist. Furthermore, the time taken for the MUD to execute this is almost the same time if we had just replaced function 12345 by
Code: [Select]
if %actor.varexists(questcard6_thetis)%

However: We have a problem when the quest journal auto puts the flags on players. The replacing does not take place. So players may have duplicate flags - both old flags and new flags.

Ahhah, you say. But that is an easy fix - we can move the inner if statements out, eg:
Code: [Select]
* new function

if !%actor.varexists(questcard6_thetis)%
  set questcard6_thetis 0
  remote questcard6_thetis %actor.id%
endif

if %actor.varexists(thetis1)%
  set questcard6_thetis 1
  remote questcard6_thetis %actor.id% 
  rdelete thetis1 %actor.id%
endif

if %actor.varexists(thetis2)%
  set questcard6_thetis 2
  remote questcard6_thetis %actor.id% 
  rdelete thetis2 %actor.id%
endif

if %actor.varexists(thetis3)%
  set questcard6_thetis 3
  remote questcard6_thetis %actor.id% 
  rdelete thetis3 %actor.id%
endif

* etc etc

But in this case - each time the actor is on any part of the quest chain and this function is called, eleven if statements will be checked, potentially adding lag to the MUD.

What's the solution?

We have come up with a nifty way to add all questflags on the player once they: go into Limbo, walk into Recall, die, or use the Time Guardian. Of course, you have to send a note to Pix (or Roland) what the new questflags are, and how the old questflags should be replaced. It's even better if you give us a trigger that does this in the first place.

PS: If you are a player when a current quest is added to the quest journal, we suggest you walk to Recall / use the Time Guardian. Otherwise, you might get the new set of flags which signal that you haven't done a quest, but without the replacing of old flags done. While this might allow you to get more token rewards, it also means if you remove and wear a quest equip, it might purge itself.
« Last Edit: February 09, 2017, 08:20:01 pm by erwin »

Offline erwin

  • Sr. Member
  • ****
  • Posts: 314
    • View Profile
Re: Questjournal OLC
« Reply #1 on: February 12, 2017, 04:13:38 pm »
Questcheck debug mode: What is it, why should it be used?

Every zone these days have quests, and we don't know the intention of the builder when he/she designed the quests. Barring common typos or checking the wrong variables, or not putting a 1s delay before a trigger, we do not know if the quest is functioning as intended.

For example, Questcard11 (Bereaved Woman) could not be solved, because a key involved had a maxload of 1. One of the quests in Questcard17 was also unsolvable because an item did not reload at all.

Playtesting new zones may also not work in getting these bugs out - because we don't know if the player has not done correct steps, or because there really is a "logic bug".

Yesterday, there was a player saying that Marion was "bugged" because she didn't respond - but the actual fact was that the player did not say a certain keyword.

If an imm did not know the quest structure, then fixing any "bugs" might make the quest intentionally "easy", or impossible to complete.

Debug mode in the questjournal tries to resolve the above issues, and also reduces the possibilities of logical errors.

Here is an example of a how it might work.

Suppose we had a questline where the player must do the following.
1. Wait till midnight
2. Eavesdrop on a conversation at Recall behind Buck and Jubei.
3. Say the phrase "hash table". If "splay tree" is said, then the quest cannot be completed (flags are reset, player must start again).
4. Say "yes" to Buck
5. Buck will ask player to get a key, giving the key to Buck will complete the quest.

A good function behind debug mode (when the imm types qcheck <num> debug <playername>) would work like this:

Code: [Select]
* debugger is the imm, player is the player
* pretend the quest variable is questcard200_buck

* Get the player's flag
set questcard200_buck %player.questcard200_buck%

if %questcard200_buck% == 0
  %send% %debugger% %player.name% is not on this quest!
  %send% %debugger% {cx
  %send% %debugger% %player.name% must wait till midnight to start this quest.
elseif %questcard200_buck% == 1
  %send% %debugger% %player.name% has waited till midnight.
  %send% %debugger% {cx
  %send% %debugger% %player.name% must type {cceavesdrop{cx to listen to Buck and Jubei.
elseif %questcard200_buck% == 2
  %send% %debugger% %player.name% has eavesdropped on Buck and Jubei.
  %send% %debugger% {cx
  %send% %debugger% %player.name% must say {cchash table{cx to proceed.
  %send% %debugger% If %player.name% says {ccsplay tree{cx, the flags will be reset and %player.heshe% must start again.
elseif %questcard200_buck% == 3
  %send% %debugger% %player.name% has said {cchash table{cx to Buck.
  %send% %debugger% {cx
  %send% %debugger% %player.name% must say {ccyes{cx to move on.
elseif %questcard200_buck% == 4
  %send% %debugger% %player.name% has been asked by Buck to get a key.
  %send% %debugger% {cx
  %send% %debugger% %player.name% must go to A Dark Mine (14024), and kill the bat there to get the key. Returning the key to Buck completes the quest.
endif

What does this really do? If a player is "stuck" on the quest, then the imm just needs to type qcheck 200 debug <player>. This function will look at the player's flag, and tell the imm where the player is on the quest, and what the player needs to do.

For example, if the flag was at 2, then the imm would see:
Code: [Select]
Lionheart has eavesdropped on Pix and Jubei.

Lionheart must say hash table to proceed.
If Lionheart says splay tree, the flags will be reset and he must start again.

Then, the imm can:
a) Ask Lionheart if he is really at the stage after eavesdropping on Pix and Jubei
b) Asked what Lionheart has tried saying

So: If Lionheart said: "I did everything except say hash table", the imm can say: "This is not a bug, you did not say hash table to proceed."

Similarly, if Lionheart said: "I said hash table, but nothing happened", then the imm can say: "Yup, you are bugged. Let me fix this."

Or perhaps Lionheart might say: "Buck asked me to get a key, but I can't find it." The imm can then type qcheck 200 debug Lionheart, and would get the message:

Code: [Select]
Lionheart has been asked by Buck to get a key.

Lionheart must go to A Dark Mine (14024), and kill the bat there to get the key. Returning the key to Buck completes the quest.

The imm can then check to see if the key exists on the bat, what the maxload is, etc. (This is more common than you think when zones get updated, but quests that may rely on objects / etc on these zones don't update.)

On the builder side when creating such functions, this forces the builder to actually think through the entire quest tree. For example, when I write such functions, I do so step by step, and make sure the debug mode is saying the right thing. This helps to prevent a lot of logic errors, as I ensure every step works for a character on 6001. If you don't do this, you die.

On the other hand, there are some bad ways to write a debug function (please don't do this). Here's another way to write it:

Code: [Select]
* debugger is the imm, player is the player
* pretend the quest variable is questcard200_buck

* Get the player's flag
set questcard200_buck %player.questcard200_buck%

if %questcard200_buck% == 0
  %send% %debugger% %player.name% is not on this quest!
  %send% %debugger% {cx
  %send% %debugger% %player.name% must eavesdrop on Buck at midnight.
elseif %questcard200_buck% == 2
  %send% %debugger% %player.name% must say {cchash table.
elseif %questcard200_buck% == 4
  %send% %debugger% %player.name% must get the key for Buck to complete this quest.
endif

While this function also works, what information does it give the imm? The player actually had to: "Wait till midnight", and then "type eavesdrop" to proceed in the quest. But the phrase: "Lionheart must eavesdrop on Buck at midnight" doesn't convey any meaningful information.

Furthermore, "Lionheart must get the key for Buck to complete this quest." is not very helpful. Note: You can get away with this if it's a unique object, eg, Buck wants a pink colored ski jacket, since an imm can type "where ski jacket", but "where key" isn't helpful :(

If it helps, the way to think about the debug mode is:

For an imm that does not know anything about the zone or nothing about scripting - or both, debug mode should allow the imm to tell the player: "You are right, the quest is bugged!", or "You haven't done something yet."


Fixing the error - send a note to the original builder of the zone, or any of the scripters / coders online.

« Last Edit: February 12, 2017, 04:55:49 pm by erwin »