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). ;-) |