Recent Posts

Pages: 1 [2] 3 4 ... 10
Scripting Board / Re: Trading Scripts
« Last post by erwin on January 06, 2017, 07:22:55 am »
Trading script v3, uses real examples. Imms only need to edit the first part, and can add as many or as few items as wanted. Script takes care of the rest.

Wishlist: Can we hardcode this somehow? Something like medit / oedit / sedit. tradeedit?

Note: We're setting a flag for this, so we can also track how many items players have traded, for that vendor.
Code: [Select]

if !%actor.is_pc%
* Molly, Kvetch, whoever wants to add MORE trading stuff here, follow the
* comments
* If you want to reduce the number of items traded, it's a bit more complex.
* Send me a note, or any of the coders.
* Ideally, we should probably write this in C instead of DG scripts.
* Flag: trade_winter
* Currently, can trade SIX items, and mob rejects FOUR items
*** The Edit Place
* Edit the below if you want to change the number of items traded
set max_items 6
* na_flag is basically SIX nas (or however max_items nas)
set na_flag na na na na na na

* thinrope
set item1 52615
set speecha1 Bob says, 'OK, most of the mountaneers buy a thin rope from me.'

* thickrope
set item2 52616
set speecha2 Bob says, 'Right, thinropes are in most demand of course.
set speechb2 But there are situations when the mountaineers need thicker ropes too.
set speechc2 I've seen ten of them dangle over a precipice from the same rope.'

* longrope
set item3 52617
set speecha3 Bob says, 'Thanks! Just what I wanted.
set speechb3 I need a longrope in reserve in case some of them mountaneers falls into a deep ravine.'

* ropeladder
set item4 52618
set speecha4 Bob says, 'Great! I was just out of ropeladders!'

* wool yarn
set item5 52619 52620
set speecha5 Bob says, 'Yup, wool yarn is popular around here.'

* wool cloth
set item6 52624 52625
set speecha6 Bob says, 'Mmm, wool cloth is just what we need.
set speechb6 None of the other kinds keep you warm enough.'

* TP and EXP for each item
set tp_reward_vec 5 13 28 0 3 7
set brass_reward_vec 0 0 0 1 0 0
set exp_reward_vec 3000 6000 8000 10000 1000 1000

* rejected items

set rej_max_items 3

* cotton thread
set rej1 3266 30957
set rejspeecha1 Bob says, 'No thanks, I'm really just interested in wool yarn and cloth.
set rejspeechb1 It's too cold for other materials here.'

* silk
set rej2 52651 52661
set rejspeecha2 Bob says wistfully, 'I wish I could afford it.
set rejspeechb2 But nobody around here would buy silk, And it's too cold for it anyway.'

* cloth
set rej3 3267 30958 44653
set rejspeecha3 Bob says, 'Sorry, I cannot afford silk, and neither can my customers.'

* Can stop here for most cases. Below is generic stuff.
set trade_winter %na_flag%
if !%actor.varexists(trade_winter)%
  remote trade_winter
elseif %actor.varexists(trade_winter)%
  * Check to see if we have any changes in the length if this var exists
  set findnumwords %actor.trade_winter%
  function 21625
  * Check to see if variable max_items (set above) is equal
  * to number of words in trade_winter, eg if you modified above
  * flag to trade NINE items instead of SIX.
  if %max_items% != %num%
    * someone added more items so that's fine
    set ub 0
    while %ub% < %num%
      eval ub %ub% + 1
      *%echo% Replacing...
      replace_word %findnumwords.wordat(%ub%)% %ub% trade_winter
    remote trade_winter

set trade_winter %actor.trade_winter%

* Make sure you have defined a prefix for the items traded
* Above it's item1, item2, item3, item4, item5, item6, so prefix is item
* Also make sure you've set max_items, which ought to be ABOVE

* For the purists: function 21627 takes in an input prefix, and max_items,
* gives an output item_in_list

set prefix item
function 21627
set traded_item %item_in_list%

** The reward for great trading items
** Can mostly ignore this part
if %traded_item% != 0
  *Great, no rejected items. Now to find which one
  wait 1
  mjunk %object%
  * evals the correct speech corresponding to the traded item
  eval tosaypartone %%speecha%traded_item%%%
  eval tosayparttwo %%speechb%traded_item%%%
  eval tosaypartthree %%speechc%traded_item%%%

  %send% %actor% %tosaypartone%
  if %tosayparttwo%
    %send% %actor% %tosayparttwo%
  if %tosaypartthree%
    %send% %actor% %tosaypartthree%
  wait 1
  * Reward goes here, corresponding to the traded_item
  set tp_reward %tp_reward_vec.wordat(%traded_item%)%
  if %tp_reward% == 1
    emote hands over %tp_reward% tradepoint.
  elseif %tp_reward% > 1
    emote hands over %tp_reward% tradepoints.
  eval d %actor.level% * %exp_reward_vec.wordat(%traded_item%)%
  nop %actor.exp(%d%)%
  * tokens
  set bronze_reward %brass_reward_vec.wordat(%traded_item%)%
  set counter 0
  while %counter% < %bronze_reward
    eval counter %counter% + 1
    emote hands over a brass token.
    %load% obj 3300 %actor%
  set trade_winter %actor.trade_winter%
  set curr_item %trade_winter.wordat(%traded_item%)%
  if %curr_item% == na
    set curr_item 1
    eval curr_item %curr_item% + 1
  replace_word %curr_item% %traded_item% trade_winter
  remote trade_winter
  * Halt this script if we have successfully traded! 

* Let's do the same for rejected items for special messages
* We are calling the same function 21627 again, but with
* rejected items as input
* So max_items is now rej_max_items, and prefix is rej

set max_items %rej_max_items%
set prefix rej
function 21627
set rej_traded_item %item_in_list%

if %rej_traded_item% != 0 
  eval tosay1 %%rejspeecha%rej_traded_item%%%
  eval tosay2 %%rejspeechb%rej_traded_item%%%
  %send% %actor% %tosay1%
  if %tosay2%
    %send% %actor% %tosay2%
  emote says, 'Sorry, I don't trade in that kind of stuff.'
Suggestions & Ideas / Questjournal - Understanding and Debugging Quests
« Last post by erwin on January 05, 2017, 08:29:52 pm »
Hi all,

This post is meant to illustrate how to debug quest scripts with the questjournal. Writing triggers for the questjournal itself (and debugging them)will be in another post.

PS (sorry Roland, Thotter in advance) - feel free to add on to this post, clarify it if I skip some points.

questflags now look like this: questcardx_questname, for example, there's:

Code: [Select]

To find all quest related triggers pertaining to that questcard, you can simply do
Code: [Select]
tsearch all questcardxx, example:
Code: [Select]
*find triggers related to questcard 19
tsearch all questcard19

All flags related to this quest will be in this flag. Sometimes, there may be subflags, eg
Code: [Select]

Most flags follow the below style. Here, we have a fake flag (questcard200_myquest), and show how it might look like, when you search for this flag on a player.

Code: [Select]
questcard200_myquest: noprog 0 notdone inprog 2 notdone inprog 3 done noprog 0 done
How do you read this? You can think of this in "groups of 3", so in this zone, there are four quests.

For the first quest, the player is not on the quest, is at step 0, and hasn't completed it.
For the second quest, the player is on the quest, is at step 2, and hasn't completed it.
For the third quest, the player is on the quest, is at step 3, and has completed the quest at least once.
For the fourth quest, the player has completed the quest, and hasn't restarted it again.

Think of noprog / inprog as noprogress and inprogress, notdone and done as whether the player has completed the quest at least once.

So we have two benefits already: First, flags are consolidated into one flag (less spam when you vstat a player's flags). Secondly, you can tsearch questflags easily by tsearch questcardxx.

However, because there are "multiple flags" on one flag (multiple variables in one array), things are a bit trickier.

Previously, you could do something like:
Code: [Select]
if !%actor.varexists(hanna)%
  * Player doesn't have this flag
  %send% %actor% You are not on this quest!
  %send% %actor% I will put you on this quest!
  set hanna 1
  remote hanna
  * Player has this flag
  set hanna %actor.hanna%
  if %hanna% == 1
    %send% %actor% You are on step 1. Let me progress you to step 2
    set hanna 2
    remote hanna
  elseif %hanna% == 2
    %send% %actor% You are on step 2. Let me progress you to step 3
    set hanna 2
    remote hanna

How can you do this now? Let's imagine Hanna is the third quest for this zone, so we need to look at the third group, i.e. the group in bold here.

questcard200_myquest: noprog 0 notdone inprog 2 notdone inprog 3 done noprog 0 done

Let's look at a WRONG way to do this first.

Code: [Select]
* A wrong way
if !%actor.varexists(questcard200_myquest)%
  %send% %actor% You are not on this quest!
  %send% %actor% I will put you on this quest!
  set questcard200_myquest noprog 0 notdone noprog 0 notdone inprog 1 notdone noprog 0 notdone
  remote questcard200_myquest

You might think the above code makes sense, since you're setting just the variables for the third quest. But, what if the player was on the other quests? You'd be resetting his or her progress.

Thus, every questcard now has up to three FUNCTIONS. A room function, a obj function, and a mob function. You can tsearch to find these functions, which look like this, and each have identical code (only the type - room, obj, mob differs).

Code: [Select]
* Example of an object function
Name: 'Questcard200 obj function',  VNum: [12345], RNum: [----]
Trigger Intended Assignment: Objects
Trigger Type: FUNCTION , Numeric Arg: 100, Arg list: None
* Create this questflag if it doesn't exist
if !%actor.varexists(questcard200_quest)%
  set questcard200_quest noprog 0 notdone noprog 0 notdone noprog 0 notdone noprog 0 notdone
  remote questcard200_quest

  * To reassure people that their old flags aren't deleted
  * suppose they completed quest 1 before
  if %actor.varexists(oldflag1)%
    replace_word done 3 questcard200_quest
    rdelete oldflag1 
  remote questcard200_quest

Now, this is what you can do:
Code: [Select]
* Need to check if is PC before calling any functions.
if %actor.is_pc%
  *For any trigger which deals with questflags 
  *Call the appropriate function (room, mob or obj?)
  *Pretend it's an object so call the function above

  * This function sets the questflag ONCE, if it doesn't exist.
  function 12345
  * The below line can't bug, because we've created the flag if it didn't exist.
  set questcard200_quest %actor.questcard200_quest%

  * Now, proceed as normal, eg:

  if %questcard200_quest.wordat(7)% == noprog
    %send% %actor% You are not on this quest.
    %send% %actor% I will put you on this quest
    %send% %actor% I will replace the 7th word in your flag to show you are now in progress
    replace_word inprog 7 questcard200_quest
    %send% %actor% I will replace the 8th word by 1 to show you are now on step 1 for this quest
    replace_word 1 8 questcard200_quest
    remote questcard200_quest
    if %questcard200_quest.wordat(8)% == 1
      %send% %actor% You are on step 1
      replace_word 2 8 questcard200_quest
      remote questcard200_quest
      %send% %actor% Now you are on step 2
    elseif %questcard200_quest.wordat(8)% == 2
      %send% %actor perfect, let's give you a reward
      if %questcard200_quest.wordat(9)% == notdone
        %send% %actor% You haven't done this quest before, so I'll give you a big reward!
        replace_word done 9 questcard200_quest
        %send% %actor% You've done this quest before, so a smaller reward!
      * Reset all other questflags for this quest so
      replace_word 7 noprog questcard200_quest
      replace_word 8 0 questcard200_quest
      remote questcard200_quest

So this is how the code would look like. Finally - how can we debug?

Here's some common errors.

Firstly, the trigger is not enclosed within:
Code: [Select]
if %actor.is_pc%

Previously, you didn't need to have this check. Now you always need to have it.

Secondly, the WRONG type of function is called. We called function 12345, which was an Object function. If the trigger was a Mobile trigger, then you must call an Mobile function. If the trigger was a Room trigger, then you must call a Room function. Again, these three functions would have identical code, just different types.

Thirdly, logic wise. In this case, this is usually a problem with the old quest. As you can see, quests have the same logic. However, we have just used replace_word and wordat to work with arrays.

Finally, you may have a question. Hold on: How do I know if this player's quest is the THIRD quest or the FOURTH quest? Good question! Imms have a command (note me if you can't get this to work): questcheck card<num> debug <playername>, which actually goes into way more detail what each variable represents.

News & Announcements / Re: How many action figures have YOU collected?
« Last post by Mott on January 03, 2017, 07:14:10 am »
lol then i will have to wait till next halloween to collect them all!
News & Announcements / Re: How many action figures have YOU collected?
« Last post by Kvetch on January 02, 2017, 08:15:02 pm »
Those action figures were part of a Halloween thing - not the "real" action figures for whatever quest that is.
News & Announcements / Re: How many action figures have YOU collected?
« Last post by Mott on December 31, 2016, 09:32:28 am »
You are missing

a Shorty collectible action figure

on the list. 

Or is it not supposed to exist in 4D these days?
I've been gone too long, so I have no idea where I got that Shorty action figure from...
Suggestions & Ideas / Re: Questjournal v1
« Last post by rynald on December 19, 2016, 01:42:46 pm »
That's great news, i'm a fan of the journal. You can join gitlab as far as i'm concerned, but it doesn't track triggers (yet), only code.
Suggestions & Ideas / Re: Questjournal v1
« Last post by erwin on December 19, 2016, 03:18:40 am »
*actually you know what - add me to the 4D Github if there's one. I'll also upload my trigger files for each quest. This makes it easy for everyone to debug.
Suggestions & Ideas / Re: Questjournal v1
« Last post by erwin on December 19, 2016, 03:11:41 am »

Here's the new plan - with Vryce, Jubei, and Mott helping.

The idea is to *rigorously* do and complete the quest journal. This also means extensively playtesting old quests.

Cycle will be slow, but this ensures no bugs.
Building Board / Checking to see if a door is open or closed
« Last post by Kvetch on September 18, 2016, 07:25:12 pm »
I'd been whining about this for a while:
When you have an exit that has a door do you:
1) describe the door : like look east - you see a large oak door - since the player wouldn't know what room was beyond it unless they have already visited it, or
2) describe the room that lies beyond the door: like look east - you see the library there - since they should be able to know the neighboring room is a library if the door is open.

If the door is closed, 2 doesn't make sense.  If the door is open, 1 doesn't make sense, but there was always only one exit description.

After whining again yesterday, Roland did a look into it for me and found out this:

room trig:

if %self.east% /= closed
and in a mob trigger:

if /= closed
See in the Rooms section for the details.

So now, if you're really into doing scripts and really want a different description for your exit if there is a door - you can do it. 

Building Board / Re: Day/Night script
« Last post by Kvetch on September 09, 2016, 07:33:51 pm »
Still love you, Parn and I'm redoing the haunted house again.  Could use your amazing ideas and scripting skills on that again.

FYI: I had tried to use that on some global time loading scripts and realized it wouldn't work since there's not a command that anyone would do - so there would be no %actor% in that case.  So.. it became %self.vnum% for that.  These's could probably be changed to %self.vnum% and have it work too.
Pages: 1 [2] 3 4 ... 10