Register forum user name Search FAQ

Gammon Forum

Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to verify your details, confirm your email, resolve issues, making threats, or asking for money, are spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the password reset link.

Due to spam on this forum, all posts now need moderator approval.

 Entire forum ➜ SMAUG ➜ SMAUG coding ➜ Suggestion's on timers

Suggestion's on timers

It is now over 60 days since the last post. This thread is closed.     Refresh page


Posted by Nick Cash   USA  (626 posts)  Bio
Date Mon 28 Apr 2003 02:12 AM (UTC)
Message
I'm not very good with coding timers, so I was wondering if someone could help me out with them. I need a timer that goes through several phases, like the login switch statements, except I need timers. So to be specific on the phases, I'll list them in order they need to appear:
Note: I'm working with a modified SWR 1.0 codebase..

1. Sends in order for ship upgrade
2. Order Recieved (after timer)
3. Money Transfer
4. Money Revieved (after timer)
5. Upgrading Metal
6. Upgrade Complete (after timer)

I know the code to put in each of these, such as subtracting the money from the character, displaying the messages, etc., but I don't know how to do a timer that goes from one thing to the next in the same statement or that triggers another timer. Anyways, if you have questions on my question then just post them.

As always, thanks for any and all help!

~Nick Cash
http://www.nick-cash.com
Top

Posted by Nick Gammon   Australia  (23,165 posts)  Bio   Forum Administrator
Date Reply #1 on Mon 28 Apr 2003 02:30 AM (UTC)
Message
The simple thing would be to have whatever-it-is that start this process off (an alias) set up a few timers, like this:

world.DoAfter 5, "order ship"
world.DoAfter 30, "transfer money"
world.DoAfter 60, "upgrade metal"


However if you are waiting for something to tell you these things have happened then you really want a trigger that matches on the text that says "X has happened" and then make the next event happen.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Cash   USA  (626 posts)  Bio
Date Reply #2 on Mon 28 Apr 2003 10:49 PM (UTC)
Message
I think I stated that wrong. I'm not looking for timers in scripts, I'm looking for timers to add into the code. If that was acually what you were talking about then could you put it in a mini snippet type style so I can model it into the code.

~Nick Cash
http://www.nick-cash.com
Top

Posted by Nick Gammon   Australia  (23,165 posts)  Bio   Forum Administrator
Date Reply #3 on Tue 29 Apr 2003 01:33 AM (UTC)
Message
Sorry, misunderstood the question.

I'm not a big expert on timers in SMAUG, but I gather you would want to add a timer type to:


typedef enum    
{
  TIMER_NONE, TIMER_RECENTFIGHT, TIMER_SHOVEDRAG, TIMER_DO_FUN,
  TIMER_APPLIED, TIMER_PKILLED, TIMER_ASUPRESSED, TIMER_NUISANCE
} timer_types;


Then add a timer to the player's timer list - I haven't looked into it more than that.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Gammon   Australia  (23,165 posts)  Bio   Forum Administrator
Date Reply #4 on Tue 29 Apr 2003 01:35 AM (UTC)
Message
Something like this, from magic.c:


        add_timer( ch, TIMER_DO_FUN, UMIN(skill->beats / 10, 3),
                do_cast, 1 );


- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Boborak   USA  (228 posts)  Bio
Date Reply #5 on Tue 29 Apr 2003 08:08 PM (UTC)
Message
Let me see if I can explain timers a little bit for ya.
First off, I don't think add_timer is what you really want, because 'during' the timer, the player will be unable to do anything else. However, understanding what a timer does and how it works can help in the long run.

add_timer is called with a few variables. Using Nick's example, we'll break those down. (for simplicity I removed the UMIN() call.

add_timer( ch, TIMER_DO_FUN, 5, do_cast, 1 );

First, lemme explain what a timer does. Basically it starts a countdown, and after the countdown is complete it makes a call to a specified spec_fun (normally the same function that created the timer) with the ch->substate set to a specified value. That value is then (normally) used by a case statement to do a specified action. I'll explain more when I'm done with the vars.

The first var, is obviously the player to be affected. In this case the 'current' char.

The second is the 'type'. The 'enumerated' list Nick posted, is an example list of types. Under almost ALL circumstances, you'd want to use TIMER_DO_FUN, because of the way it utilizes the variables. This 'tutorial' assumes you will be using TIMER_DO_FUN.

The third var is an important one, it's the actual 'count' of pulses the timer will exist, before calling the specified spec_fun. Each timer pulse is one pulse of PULSE_VIOLENCE, which is roughly 3 seconds (even though it appears to be more like 2 seconds or even 1). So in this example, the timer will last for 15 seconds.

Next, is the spec_fun to be called (or re-called as I tend to think of it). This function CAN be different then the function that started the timer, but in most cases it's more efficiant to use the same function.

Finally, you have the 'return' SUBSTATE. This is normally set to '1' simply because most timers are simple timers to 'wait' for an action to finish. This 'substate' is then used to perform specified actions.

One thing of note, is that when a timer is created, you normally see this:

ch->dest_buf = str_dup(arg);

What that is doing, is storing the arguments given to the command. This is necessary, because when the command is recalled at the end of the timer, the arguments have been lost and must be recalled. The first thing you will normally see in the 'case 1' statement is the setting of 'argument' to that of ch->dest_buf.

Here's a pseudo explanation of what do_target (in SWR) does:

The first thing that happens is a check of the char's substate. If there's no substate the command assumes the 'default case'. Everything in the default case will ONLY be done if the substate is null. This is very important to consider.

After all of the checks done in the default case, a timer is added and teh arguments saved:

add_timer ( ch , TIMER_DO_FUN , 1 , do_target , 1 );
ch->dest_buf = str_dup(arg);

This timer should last roughly 3 seconds, recall do_target and return a value of 1 as a substate.

The function now returns.

After the timer expires, the function do_target is recalled (with no arguments) and the substate checked. It now equals 1, so the '1' case is implied.

case 1:
if ( !ch->dest_buf )
return;
strcpy(arg, ch->dest_buf);
DISPOSE( ch->dest_buf);
break;

The original arguments are recalled at this point. Since this function REQUIRES areguments, if they don't exist, the function returns.

The function then breaks out of the case statement and continues. Firstly, the ch-substate is returned to normal (SUB_NONE). Then, the arguments are used to once again accuire the necesary variables to finish the function. In this case the current ship and target ship are accuired. From here the function completes as normal.

Hope this is useful (at least to someone). ;-)
Top

Posted by Boborak   USA  (228 posts)  Bio
Date Reply #6 on Tue 29 Apr 2003 11:59 PM (UTC)
Message
As for a suggestion on your particular case. I was going to write the only real idea I had. But, I started looking at some thigns, and I think a small mod to the TIMER_DATA stuff may allow you to do what you want to do. I'll let you know if I figure something out.
Top

Posted by Boborak   USA  (228 posts)  Bio
Date Reply #7 on Sat 03 May 2003 04:50 AM (UTC)
Message
Sorry for the delay. But, I was playing around with the timers when it donned on me I was wasting my time. Timers don't carry over after reboots/crashes. The problem with that is that the functions the timers were suppose to call, would never be called. Simply put, a mort would order their upgrade and never get it. so, it's back to my original idea. Here's what I think you should do:

Create a variable in the pcdata struct that you tend to save and load with the players pfile.

When the player calls the function that starts the whole process going (orders the ship upgrade), then set that variable to a certain number.

Then create a function that checks for the value of that variable on every char and depending on what the variable is calls another function (money received and upgrade complete). Have this function get called every tick or so. Look in update.c and search for the pulse checks, adding your function to the list.

That should do it. Of course you could only allow one upgrade at a time (unless you got creative with arrays), but the tick count would be saved if the player quit or if the mud rebooted, leaving off where it was. So lets see if some psueudo-code helps.

void do_upgradeship(CHAR_DATA *ch, char *argument)
{
  ch->upgradetimer = 10;
  "Your upgrade has been made and will take 10 ticks"
}

void update_upgradetimers( void )
{
  for first_char to last_char
  {
    if ch->upgradetimer <= 0
      continue;
    else if ch->upgradetimer == 5
      upgradeship(ch, 1);
    else if ch->upgradetimer == 1
      upgradeship(ch, 2);

    ch->upgradetimer--;
  }
}

the above function would be called each tick

void upgradeship(CHAR_DATA *ch, int action)
{
   switch (action)
   {
      default:
        return;
      case 1:
        "your funds have been transfered"
        break;
      case 2:
        "your upgrade is complete!"
        break;
   }
}

Hope this made some sense, I was just trying to illustrate my idea a bit. Your code for subtracting the money and displaying the messages and such would go in the case statement. You could even create another function that used the 'ch->upgradetimer' variable to allow a player to check the status of their upgrade.
Top

Posted by Nick Cash   USA  (626 posts)  Bio
Date Reply #8 on Fri 11 Jul 2003 02:47 AM (UTC)
Message
I know this is actually an old subject, but I finally got around to coding it in, and I was wondering. How should I go about knowing which ship to upgrade in upgradeship? I mean, should I have it save to the character, or what?

~Nick Cash
http://www.nick-cash.com
Top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


26,262 views.

It is now over 60 days since the last post. This thread is closed.     Refresh page

Go to topic:           Search the forum


[Go to top] top

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.