Okay, if you noticed SMAUG's timers are very, very useful. Except there is one flaw: creating timers in code which a timer executes when it finishes. The psuedo-code for this goes like this: void do_squaredance(...) { switch(ch->substate) { default: // Get ready to dance! add_timer(...); // Timer returns 1 return; case 1: // Time to do a new dance move! add_timer(...); // Timer returns 2 return; case 2: ... } } Case 2 will never happen, you may go, "But Gatz! It should!?!" Well, SMAUG has a boo-boo, which is why you are reading this snippet! Okay, let's get to it. for ( timer = ch->first_timer; timer; timer = timer_next ) { timer_next = timer->next; if ( --timer->count <= 0 ) { if ( timer->type == TIMER_DO_FUN ) { int tempsub; tempsub = ch->substate; ch->substate = timer->value; (timer->do_fun)( ch, "" ); if ( char_died(ch) ) break; ch->substate = tempsub; } extract_timer( ch, timer ); } } That is the devious code which executes the whole dealie. It should be in fight.c for SMAUGers or SWRers or update.c for you AFKMUDers. Here is how we shall tweak it. for ( timer = ch->first_timer; timer; timer = timer_next ) { timer_next = timer->next; if ( --timer->count <= 0 ) { if ( timer->type == TIMER_DO_FUN ) { int tempsub; // Slight fix to timers - Gatz DO_FUN *fun; tempsub = ch->substate; fun = timer->do_fun; ch->substate = timer->value; extract_timer( ch, timer ); // Seems redundent but, why not? timer = NULL; (fun)( ch, "" ); if ( char_died(ch) ) break; ch->substate = tempsub; } if(timer) extract_timer( ch, timer ); } } Now, there is another bug with timers in SMAUG. (Not bad for how cool the SMAUG Timer system is) but before I go on, I will give an explanation for why I did what I did. You can skip this if you don't care for that knowledge and just enjoy taking my word for it. -----------Explanation---------------- Okay, we need a tempoary variable to store what we truly want from the Timer, it's function to execute. We need to delete the Timer BEFORE the code executes. It is a very logistical thing really. I believe a timer should be finished when it executes the code, that makes sense to me. When it wouldn't ket you add a timer before, it was because that old worthless timer still was looming. Now, I set timer to NULL, which then lets me check it later on so I don't accidently extract the timer twice. ----------End Explanation-------------- Next bug, timers defaulty are assumed to be used in commands in SMAUG and SWR. Lots of examples this isn't true, so, the fix for this is very, very easy. In interp.c look for: if ( cmd && timer) { int tempsub; tempsub = ch->substate; ch->substate = SUB_TIMER_DO_ABORT; (timer->do_fun)(ch,""); if ( char_died(ch) ) return; if ( ch->substate != SUB_TIMER_CANT_ABORT ) { ch->substate = tempsub; extract_timer( ch, timer ); } else { ch->substate = tempsub; return; } } And now you need to do this: Declare a boolean value of whatever you wish, I called my check. bool check = FALSE; // Make sure we got a default value for no goof-ups! - Gatz if(cmd) check = TRUE; if(!cmd) check = TRUE; if ( check && timer) { int tempsub; tempsub = ch->substate; ch->substate = SUB_TIMER_DO_ABORT; (timer->do_fun)(ch,""); if ( char_died(ch) ) return; if ( ch->substate != SUB_TIMER_CANT_ABORT ) { ch->substate = tempsub; extract_timer( ch, timer ); } else { ch->substate = tempsub; return; } } Note, I have OOC commands to not disrupt timers in my code. If you do to, that first if-check looks like this: if(cmd && cmd->ooc == 0) check = TRUE; Now we have timer's all fixed up! Rocken! Now, you can run around using this to patch up your code base to your hearts content, except I ask you give a line of credit in a comment around where the main timer function is. Like a simple // Timer fix by Gatz (Nicholas Jaross) would do. These coding fixes have been tested on a fairly stock SMAUGFUSS and heavily mod'ed SWR 1.0 and it works perfectly. My e-mail is h_b_k316@hotmail.com if you have any questions pertaining to this.