Author Topic: Suggested Practices for Scripting  (Read 10386 times)

0 Members and 1 Guest are viewing this topic.

Offline erwin

  • Sr. Member
  • ****
  • Posts: 314
    • View Profile
Suggested Practices for Scripting
« on: December 05, 2015, 11:42:32 pm »
In the past, we had lots of good practices for scripting.

For example, here's some best practices in the past:

1. The difference between set and eval and when to use them
2. The difference between %actor% versus %actor.name%, and when to use them.
3. mjunk an object (instantly) when the player gives it to a mob so he can't steal it back
4. Setting a flag when the player completes the quest, so the rewards are lesser the second / subsequent time the player completes it

However, I think we can have more "suggested practices for scripting", as well as use the 4D only DG functions which Mordecai / Rynald / others have coded in for future best practices.

These "suggested practices" will be focused on debugging and understanding scripts, in the context of the builder fixing his/her own scripts a few weeks / months after he/she worked on it, as well as someone else fixing the script if the previous builder has retired.

I will first describe what imms face when debugging. For example, Molly made a post here

http://4dimensions.org/forum/index.php/topic,682.msg5045.html#msg5045

which shows the questflags a player has. Here's some potential issues (maybe):

a) The list is quite long
b) Some variable names are not intuitive. For example, the variable zeddletter versus jack versus asking. For the first variable, this depends on how much the person knows about the MUD. He might make a guess that it's from the Midlands zone, and is given to the player when he interacts with Zedd about a letter (giving a letter / receiving a letter / asking him to write a letter?). Having knowledge about the quests in the MUD would give the player the knowledge of what the variable does, so that's fine.

How about the other two variables? Well, a solution would be to tsearch all jack, or tsearch all asking to find the respective scripts, and then try to figure out what they do. That takes effort, but can we do better?

Thus: Suggested Practices for Scripting shall be about intuitive variable names, and intuitive variable values. I'll try to present this in a way of "Problem", and then the "Solution", as suggested best practices.

Problem: Variable names are not intuitive. For example, asking is less intuitive than zeddletter

Solution: Create intuitive variable names

Problem: There are five helper vouchers. Suppose upon picking each one up, we store the value as 1, and we have the five variables

Code: [Select]
helper_voucher_1: 1
helper_voucher_2: 1
helper_voucher_3: 1
helper_voucher_4: 1
helper_voucher_5: 1

on the player. Once goes through the Newbie School, he is convinced he picked up all 5 vouchers, but lost them in a DT. Poor Once. He tells Kvetch: You can vstat me, and search for these 5 variables. Unfortunately, vstat doesn't show the variables in alphabetical order, nor the time the variable was created. Must Kvetch painstakingly look at all his variables and find the 5 of them in 15 pages? What if Once didn't get the 4th voucher, but Kvetch thinks he has, so she tries to find it? Or worse, what if Once did get the 4th voucher, but because of the spam, Kvetch didn't see it?

Solution 1: Ask a coder to fix vstat to show whether the player has the variable or not.
Solution 2: Use an array and store the values in one variable, called helper_voucher

Code: [Select]
helper_voucher: found found not_found found not_foundor
Code: [Select]
helper_voucher: 1 0 1 1 0

Problem: Once goes to the Midlands, and does a quest. He thinks it's bugged, and he wants to know the variables relating to the zone, so he can fix it himself in the BP. Unfortunately, apart from zeddletter, he doesn't know what other variables on his pfile relate to the Midlands. He wonders if he should search through the "quest actions" done, or the names of the mobs in the Midlands just in case the builder used that as a variable?

Solution: Have the variable name include the zone as well. Even if the builder / imm online doesn't know anything about the quest, he or she can say: "This is the variable / these are the variables related to the zone, I'll send this on to another imm."

In other words, incorporate the zone name in the variable.

Examples of two variables:
Code: [Select]
crete_zone: not_killed_minotaur killed_theseus bullgirl_not_done
and
Code: [Select]
crete_zone: killed_minotaur killed_theseus bullgirl_done

Most imms / players who see that flag would immediately know what the player has done (or not done) in the zone. 

Thus, a suggested practice for scripting is to minimize the number of variables by using arrays, and replace_word.
« Last Edit: December 05, 2015, 11:48:16 pm by erwin »

Offline Fizban

  • Maniacal Scroder!
  • Administrator
  • Full Member
  • *****
  • Posts: 183
  • Fizban, the Mangy Wizard
    • MSN Messenger - Fizban1216@hotmail.com
    • AOL Instant Messenger - Fizban1216
    • View Profile
    • Email
Re: Suggested Practices for Scripting
« Reply #1 on: January 05, 2016, 08:37:40 am »
Not that I think saving variables this way is a bad idea, it's not, but it is more complicated to do for someone with a very limited understanding of trigedit (ie. most builders).

Telling builders to think like coders doesn't tend to work very well in my experience.

That's only an issue for the array related idea though, nothing should prevent builders from properly naming their variables so that they're intuitive and easily distinguished by what zone they relate to.

Offline erwin

  • Sr. Member
  • ****
  • Posts: 314
    • View Profile
Re: Suggested Practices for Scripting
« Reply #2 on: January 05, 2016, 12:41:45 pm »
I've been using a template for the Quest Journal ; an example of a quest variable would be of the form:

Code: [Select]
hat_temple: noprog notdone 2
hat_temple: inprog notdone 1
hat_temple: noprog done 0

where noprog/inprog determines whether the player has activated / started the quest, notdone/done the "final" flag to signal completion, and the numbers to represent the steps in the quest. I'm hoping that (most) quests follow this template ; it's not as hard as it seems to set it up, since we just need a function to create this variable if it doesn't exist, so most scripts would be of the following form

Code: [Select]
* Create this variable if it hasn't existed
function 12345
set hat_temple %actor.hat_temple%

if %hat_temple.wordat(3)% == 2
  %echo% You are at step 2
endif

* Previously it would probably be something like
*if %actor.varexists(hat_temple_quest)%
* if %hat_temple_quest% == 2
*    %echo% You are at step 2
* endif
*endif
* and script errors would occur if you had
* if %actor.varexists(hat_temple_quest)% && %hat_temple_quest% == 2
* if the variable didn't exist

Of course, function 12345 would be

Code: [Select]
if !%actor.varexists(hat_temple)%
  set hat_temple noprog notdone 0
  remote hat_temple %actor.id%
endif

A side effect of this is that it removes errors where the script is something like
Code: [Select]
if %actor.varexists(hat_temple_quest)% && %hat_temple_quest% == 2
  %echo% do this
endif
and the player doesn't have the variable.