codemp/game/g_timer.c

Go to the documentation of this file.
00001 //rww - rewrite from C++ SP version.
00002 //This is here only to make porting from SP easier, it's really sort of nasty (being static
00003 //now). Basically it's slower and takes more memory.
00004 
00005 #include "g_local.h"
00006 //typedef map           < string, int > timer_m;
00007 
00008 #define MAX_GTIMERS     16384
00009 
00010 typedef struct gtimer_s
00011 {
00012         const char *name;
00013         int time;
00014         struct gtimer_s *next;  // In either free list or current list
00015 } gtimer_t;
00016 
00017 gtimer_t g_timerPool[ MAX_GTIMERS ];
00018 gtimer_t *g_timers[ MAX_GENTITIES ];
00019 gtimer_t *g_timerFreeList;
00020 
00021 /*
00022 -------------------------
00023 TIMER_Clear
00024 -------------------------
00025 */
00026 
00027 void TIMER_Clear( void )
00028 {
00029         int i;
00030         for (i = 0; i < MAX_GENTITIES; i++)
00031         {
00032                 g_timers[i] = NULL;
00033         }
00034 
00035         for (i = 0; i < MAX_GTIMERS - 1; i++)
00036         {
00037                 g_timerPool[i].next = &g_timerPool[i+1];
00038         }
00039         g_timerPool[MAX_GTIMERS-1].next = NULL;
00040         g_timerFreeList = &g_timerPool[0];
00041 }
00042 
00043 /*
00044 -------------------------
00045 TIMER_Clear
00046 -------------------------
00047 */
00048 
00049 void TIMER_Clear2( gentity_t *ent )
00050 {
00051         // rudimentary safety checks, might be other things to check?
00052         if ( ent && ent->s.number > 0 && ent->s.number < MAX_GENTITIES )
00053         {
00054                 gtimer_t *p = g_timers[ent->s.number];
00055 
00056                 // No timers at all -> do nothing
00057                 if (!p)
00058                 {
00059                         return;
00060                 }
00061 
00062                 // Find the end of this ents timer list
00063                 while (p->next)
00064                 {
00065                         p = p->next;
00066                 }
00067 
00068                 // Splice the lists
00069                 p->next = g_timerFreeList;
00070                 g_timerFreeList = g_timers[ent->s.number];
00071                 g_timers[ent->s.number] = NULL;
00072                 return;
00073         }
00074 }
00075 
00076 
00077 //New C "lookup" func.
00078 //Returns existing timer in array if 
00079 gtimer_t *TIMER_GetNew(int num, const char *identifier)
00080 {
00081         gtimer_t *p = g_timers[num];
00082 
00083         // Search for an existing timer with this name
00084         while (p)
00085         {
00086                 if (!Q_stricmp(p->name, identifier))
00087                 { // Found it
00088                         return p;
00089                 }
00090 
00091                 p = p->next;
00092         }
00093 
00094         // No existing timer with this name was found, so grab one from the free list
00095         if (!g_timerFreeList)
00096                 return NULL;
00097 
00098         p = g_timerFreeList;
00099         g_timerFreeList = g_timerFreeList->next;
00100         p->next = g_timers[num];
00101         g_timers[num] = p;
00102         return p;
00103 }
00104 
00105 //don't return the first free if it doesn't already exist, return null.
00106 gtimer_t *TIMER_GetExisting(int num, const char *identifier)
00107 {
00108         gtimer_t *p = g_timers[num];
00109 
00110         while (p)
00111         {
00112                 if (!Q_stricmp(p->name, identifier))
00113                 { // Found it
00114                         return p;
00115                 }
00116 
00117                 p = p->next;
00118         }
00119         
00120         return NULL;
00121 }       
00122 
00123 /*
00124 -------------------------
00125 TIMER_Set
00126 -------------------------
00127 */
00128 
00129 void TIMER_Set( gentity_t *ent, const char *identifier, int duration )
00130 {
00131         gtimer_t *timer = TIMER_GetNew(ent->s.number, identifier);
00132 
00133         if (!timer)
00134         {
00135                 return;
00136         }
00137         timer->name = identifier;
00138         timer->time = level.time + duration;
00139 }
00140 
00141 /*
00142 -------------------------
00143 TIMER_Get
00144 -------------------------
00145 */
00146 
00147 int     TIMER_Get( gentity_t *ent, const char *identifier )
00148 {
00149         gtimer_t *timer = TIMER_GetExisting(ent->s.number, identifier);
00150 
00151         if (!timer)
00152         {
00153                 return -1;
00154         }
00155 
00156         return timer->time;
00157 }
00158 
00159 /*
00160 -------------------------
00161 TIMER_Done
00162 -------------------------
00163 */
00164 
00165 qboolean TIMER_Done( gentity_t *ent, const char *identifier )
00166 {
00167         gtimer_t *timer = TIMER_GetExisting(ent->s.number, identifier);
00168 
00169         if (!timer)
00170         {
00171                 return qtrue;
00172         }
00173 
00174         return (timer->time < level.time);
00175 }
00176 
00177 /*
00178 -------------------------
00179 TIMER_RemoveHelper
00180 
00181 Scans an entities timer list to remove a given
00182 timer from the list and put it on the free list
00183 
00184 Doesn't do much error checking, only called below
00185 -------------------------
00186 */
00187 void TIMER_RemoveHelper( int num, gtimer_t *timer )
00188 {
00189         gtimer_t *p = g_timers[num];
00190 
00191         // Special case: first timer in list
00192         if (p == timer)
00193         {
00194                 g_timers[num] = g_timers[num]->next;
00195                 p->next = g_timerFreeList;
00196                 g_timerFreeList = p;
00197                 return;
00198         }
00199 
00200         // Find the predecessor
00201         while (p->next != timer)
00202         {
00203                 p = p->next;
00204         }
00205 
00206         // Rewire
00207         p->next = p->next->next;
00208         timer->next = g_timerFreeList;
00209         g_timerFreeList = timer;
00210         return;
00211 }
00212 
00213 /*
00214 -------------------------
00215 TIMER_Done2
00216 
00217 Returns false if timer has been 
00218 started but is not done...or if 
00219 timer was never started
00220 -------------------------
00221 */
00222 
00223 qboolean TIMER_Done2( gentity_t *ent, const char *identifier, qboolean remove )
00224 {
00225         gtimer_t *timer = TIMER_GetExisting(ent->s.number, identifier);
00226         qboolean res;
00227 
00228         if (!timer)
00229         {
00230                 return qfalse;
00231         }
00232 
00233         res = (timer->time < level.time);
00234 
00235         if (res && remove)
00236         {
00237                 // Put it back on the free list
00238                 TIMER_RemoveHelper(ent->s.number, timer);
00239         }
00240 
00241         return res;
00242 }
00243 
00244 /*
00245 -------------------------
00246 TIMER_Exists
00247 -------------------------
00248 */
00249 qboolean TIMER_Exists( gentity_t *ent, const char *identifier )
00250 {
00251         gtimer_t *timer = TIMER_GetExisting(ent->s.number, identifier);
00252 
00253         if (!timer)
00254         {
00255                 return qfalse;
00256         }
00257 
00258         return qtrue;
00259 }
00260 
00261 /*
00262 -------------------------
00263 TIMER_Remove
00264 Utility to get rid of any timer
00265 -------------------------
00266 */
00267 void TIMER_Remove( gentity_t *ent, const char *identifier )
00268 {
00269         gtimer_t *timer = TIMER_GetExisting(ent->s.number, identifier);
00270 
00271         if (!timer)
00272         {
00273                 return;
00274         }
00275 
00276         // Put it back on the free list
00277         TIMER_RemoveHelper(ent->s.number, timer);
00278 }
00279 
00280 /*
00281 -------------------------
00282 TIMER_Start
00283 -------------------------
00284 */
00285 
00286 qboolean TIMER_Start( gentity_t *self, const char *identifier, int duration )
00287 {
00288         if ( TIMER_Done( self, identifier ) )
00289         {
00290                 TIMER_Set( self, identifier, duration );
00291                 return qtrue;
00292         }
00293         return qfalse;
00294 }