To cut down on flag spam, here's how you can build quests using arrays, and a suggested method of doing so.
First - decide on the logic of the quest, as well as the variables needed for the quest. All this goes in one array.
Second - create a function (or three functions - a mob function, a room function, and a obj function) with the same script, which sets up the array. Here's an example (for a quest that wants you to kill the captain, find one helper's voucher, and to rescue a dog). Create the "basic" quest array which is when nothing is done for the quest.
if !%actor.varexists(my_quest)%
set my_quest no_captain no_voucher no_rescue no_prog not_done
remote my_quest %actor.id%
endif
The array (when someone vstats a player) will look like this:
my_quest: no_captain no_voucher no_rescue no_prog not_done
All such quest arrays should have two extra variables at the end, namely no_prog, and not_done, to signify the quest has not been started (no progress), and the quest has not been completed at least once (not_done). Obviously, you can re-name these variables to be anything you like, but it makes it easier for future people to debug your quest logic if you are not around on the MUD.
Now, suppose:
function 1 - corresponded to a ROOM function
function 2 - corresponded to a MOB function
function 3 - corresponded to an OBJ function
To start the quest, suppose it was a ROOM trigger that started the quest.
function 1
%echo% The room says: I will give you a quest.
set my_quest %actor.my_quest%
replace_word in_prog 4 my_quest
Equivalently:
function 1
%echo% The room says: I will give you a quest.
set my_quest %actor.my_quest%
if %my_quest.wordat(4)% != in_prog
replace_word in_prog 4 my_quest
remote my_quest %actor.id%
endif
To kill the captain, suppose it was a death script on the mob. This means that we are going to use the function corresponding to a mob function. Code would just be:
function 2
* If the actor did not have the variable, he has it now
set my_quest %actor.my_quest%
* replaces killed_captain with the first word in my_quest
replace_word killed_captain 1 my_quest
remote my_quest %actor.id%
See - no messy if statements needed. Or, to be a bit more efficient,
function 2
* If the actor did not have the variable, he has it now
set my_quest %actor.my_quest%
if %my_quest.wordat(1)% != killed_captain
* replaces killed_captain with the first word in my_quest
replace_word killed_captain 1 my_quest
remote my_quest %actor.id%
endif
Or better still:
function 2
* If the actor did not have the variable, he has it now
set my_quest %actor.my_quest%
* Only sets the flag if actor started the quest - else killing the captain won't register, muahahahaha
if %my_quest.wordat(4)% == in_prog
* replaces killed_captain with the first word in my_quest
replace_word killed_captain 1 my_quest
remote my_quest %actor.id%
endif
Note that the the snippets of code above for giving the quest / killing the captain are the same. One snippet doesn't do an if-check and updates the variables regardless of the value, but the other does an if-check. So for builders who doesn't understand if-checks, they can choose the first option for both and no bugs!
You do the same for other scripts. In fact, for any script which checks for that quest variable, calling the appropriate function (function 1 if it's a room script, function 2 if it is a mob script, and function 3 which is an obj script) and checking for the quest variables and replacing them works.
Then finally (suppose this script was on a mob):
function 2
set my_quest %actor.my_quest%
if %my_quest.wordat(1)% == killed_captain && %my_quest.wordat(2)% == got_voucher && %my_quest.wordat(3)% == rescued_dog
* yay, let's check
if %my_quest.wordat(5)% != done
* first time doing this quest
* %echo% great job, have this big reward
replace_word done 5 my_quest
else
%echo% You have done this before, so here's this small reward
endif
* now, reset all questflags (in practice, good to have this as a function as well)
replace_word 1 no_captain my_quest
replace_word 2 no_voucher my_quest
replace_word 3 no_rescue my_quest
replace_word 4 no_prog my_quest
remote my_quest %actor.id%
endif
Equivalently, instead of replacing all 4 words, you can just do
set my_quest no_captain no_voucher no_rescue no_prog done
remote my_quest %actor.id%
but - be careful if you store other variables on this flag (eg, maybe whether a person has a zoneflag or not. Then it gets messy - so replace_word is the better option)
What is the in_prog / no_prog variable for? Well, the quest journal shows active quests. So to check if a quest is in progress, the quest journal just checks for a in_prog / no_prog flag. in_prog flag means the player is doing this quest, else the player isn't. Basically, when the player starts off the quest, but hasn't completed anything yet.