From a96616d85fb69e26c1eb4654a288d6666d35cbb7 Mon Sep 17 00:00:00 2001 From: Yamagi Burmeister Date: Sat, 5 Jan 2013 16:56:44 +0100 Subject: [PATCH] Cleanup g_utils.c and add sanity checks --- src/g_utils.c | 597 ++++++++++++++++++++++++++++---------------------- 1 file changed, 337 insertions(+), 260 deletions(-) diff --git a/src/g_utils.c b/src/g_utils.c index 0c562ef..b0de50f 100644 --- a/src/g_utils.c +++ b/src/g_utils.c @@ -1,106 +1,127 @@ -// g_utils.c -- misc utility functions for game module +/* ======================================================================= + * + * Misc. utility functions for the game logic. + * + * ======================================================================= + */ #include "header/local.h" +#define MAXCHOICES 8 -void G_ProjectSource (vec3_t point, vec3_t distance, vec3_t forward, vec3_t right, vec3_t result) +void +G_ProjectSource(vec3_t point, vec3_t distance, vec3_t forward, + vec3_t right, vec3_t result) { result[0] = point[0] + forward[0] * distance[0] + right[0] * distance[1]; result[1] = point[1] + forward[1] * distance[0] + right[1] * distance[1]; result[2] = point[2] + forward[2] * distance[0] + right[2] * distance[1] + distance[2]; } - /* -============= -G_Find - -Searches all active entities for the next one that holds -the matching string at fieldofs (use the FOFS() macro) in the structure. - -Searches beginning at the edict after from, or the beginning if NULL -NULL will be returned if the end of the list is reached. - -============= -*/ -edict_t *G_Find (edict_t *from, int fieldofs, char *match) + * Searches all active entities for the next one that holds + * the matching string at fieldofs (use the FOFS() macro) in the structure. + * + * Searches beginning at the edict after from, or the beginning if NULL + * NULL will be returned if the end of the list is reached. + */ +edict_t * +G_Find(edict_t *from, int fieldofs, char *match) { - char *s; + char *s; if (!from) + { from = g_edicts; + } else + { from++; + } - for ( ; from < &g_edicts[globals.num_edicts] ; from++) + for ( ; from < &g_edicts[globals.num_edicts]; from++) { if (!from->inuse) + { continue; - s = *(char **) ((byte *)from + fieldofs); + } + + s = *(char **)((byte *)from + fieldofs); + if (!s) + { continue; - if (!Q_stricmp (s, match)) + } + + if (!Q_stricmp(s, match)) + { return from; + } } return NULL; } - /* -================= -findradius - -Returns entities that have origins within a spherical area - -findradius (origin, radius) -================= -*/ -edict_t *findradius (edict_t *from, vec3_t org, float rad) + * Returns entities that have origins within a spherical area + */ +edict_t * +findradius(edict_t *from, vec3_t org, float rad) { - vec3_t eorg; - int j; + vec3_t eorg; + int j; if (!from) + { from = g_edicts; + } else + { from++; + } + for ( ; from < &g_edicts[globals.num_edicts]; from++) { if (!from->inuse) + { continue; + } + if (from->solid == SOLID_NOT) + { continue; - for (j=0 ; j<3 ; j++) - eorg[j] = org[j] - (from->s.origin[j] + (from->mins[j] + from->maxs[j])*0.5); + } + + for (j = 0; j < 3; j++) + { + eorg[j] = org[j] - (from->s.origin[j] + + (from->mins[j] + from->maxs[j]) * 0.5); + } + if (VectorLength(eorg) > rad) + { continue; + } + return from; } return NULL; } - /* -============= -G_PickTarget - -Searches all active entities for the next one that holds -the matching string at fieldofs (use the FOFS() macro) in the structure. - -Searches beginning at the edict after from, or the beginning if NULL -NULL will be returned if the end of the list is reached. - -============= -*/ -#define MAXCHOICES 8 - -edict_t *G_PickTarget (char *targetname) + * Searches all active entities for the next one that holds + * the matching string at fieldofs (use the FOFS() macro) in the structure. + * + * Searches beginning at the edict after from, or the beginning if NULL + * NULL will be returned if the end of the list is reached. + */ +edict_t * +G_PickTarget(char *targetname) { - edict_t *ent = NULL; - int num_choices = 0; - edict_t *choice[MAXCHOICES]; + edict_t *ent = NULL; + int num_choices = 0; + edict_t *choice[MAXCHOICES]; if (!targetname) { @@ -108,14 +129,21 @@ edict_t *G_PickTarget (char *targetname) return NULL; } - while(1) + while (1) { - ent = G_Find (ent, FOFS(targetname), targetname); + ent = G_Find(ent, FOFS(targetname), targetname); + if (!ent) + { break; + } + choice[num_choices++] = ent; + if (num_choices == MAXCHOICES) + { break; + } } if (!num_choices) @@ -127,75 +155,85 @@ edict_t *G_PickTarget (char *targetname) return choice[rand() % num_choices]; } - - -void Think_Delay (edict_t *ent) +void +Think_Delay(edict_t *ent) { - G_UseTargets (ent, ent->activator); - G_FreeEdict (ent); + if (!ent) + { + return; + } + + G_UseTargets(ent, ent->activator); + G_FreeEdict(ent); } /* -============================== -G_UseTargets - -the global "activator" should be set to the entity that initiated the firing. - -If self.delay is set, a DelayedUse entity will be created that will actually -do the SUB_UseTargets after that many seconds have passed. - -Centerprints any self.message to the activator. - -Search for (string)targetname in all entities that -match (string)self.target and call their .use function - -============================== -*/ -void G_UseTargets (edict_t *ent, edict_t *activator) + * the global "activator" should be set to the entity that initiated the firing. + * + * If self.delay is set, a DelayedUse entity will be created that will actually + * do the SUB_UseTargets after that many seconds have passed. + * + * Centerprints any self.message to the activator. + * + * Search for (string)targetname in all entities that + * match (string)self.target and call their .use function + */ +void +G_UseTargets(edict_t *ent, edict_t *activator) { - edict_t *t; + edict_t *t; - // - // check for a delay - // + if (!ent || !activator) + { + return; + } + + /* check for a delay */ if (ent->delay) { - // create a temp object to fire at a later time + /* create a temp object to fire at a later time */ t = G_Spawn(); t->classname = "DelayedUse"; t->nextthink = level.time + ent->delay; t->think = Think_Delay; t->activator = activator; + if (!activator) - gi.dprintf ("Think_Delay with no activator\n"); + { + gi.dprintf("Think_Delay with no activator\n"); + } + t->message = ent->message; t->target = ent->target; t->killtarget = ent->killtarget; return; } - - - // - // print the message - // + + /* print the message */ if ((ent->message) && !(activator->svflags & SVF_MONSTER)) { - gi.centerprintf (activator, "%s", ent->message); + gi.centerprintf(activator, "%s", ent->message); + if (ent->noise_index) - gi.sound (activator, CHAN_AUTO, ent->noise_index, 1, ATTN_NORM, 0); + { + gi.sound(activator, CHAN_AUTO, ent->noise_index, 1, ATTN_NORM, 0); + } else - gi.sound (activator, CHAN_AUTO, gi.soundindex ("misc/talk1.wav"), 1, ATTN_NORM, 0); + { + gi.sound(activator, CHAN_AUTO, gi.soundindex("misc/talk1.wav"), + 1, ATTN_NORM, 0); + } } - // - // kill killtargets - // + /* kill killtargets */ if (ent->killtarget) { t = NULL; - while ((t = G_Find (t, FOFS(targetname), ent->killtarget))) + + while ((t = G_Find(t, FOFS(targetname), ent->killtarget))) { - G_FreeEdict (t); + G_FreeEdict(t); + if (!ent->inuse) { gi.dprintf("entity was removed while using killtargets\n"); @@ -204,28 +242,33 @@ void G_UseTargets (edict_t *ent, edict_t *activator) } } - // - // fire targets - // + /* fire targets */ if (ent->target) { t = NULL; - while ((t = G_Find (t, FOFS(targetname), ent->target))) + + while ((t = G_Find(t, FOFS(targetname), ent->target))) { - // doors fire area portals in a specific way + /* doors fire area portals in a specific way */ if (!Q_stricmp(t->classname, "func_areaportal") && - (!Q_stricmp(ent->classname, "func_door") || !Q_stricmp(ent->classname, "func_door_rotating"))) + (!Q_stricmp(ent->classname, "func_door") || + !Q_stricmp(ent->classname, "func_door_rotating"))) + { continue; + } if (t == ent) { - gi.dprintf ("WARNING: Entity used itself.\n"); + gi.dprintf("WARNING: Entity used itself.\n"); } else { if (t->use) - t->use (t, ent, activator); + { + t->use(t, ent, activator); + } } + if (!ent->inuse) { gi.dprintf("entity was removed while using targets\n"); @@ -235,25 +278,21 @@ void G_UseTargets (edict_t *ent, edict_t *activator) } } - /* -============= -TempVector - -This is just a convenience function -for making temporary vectors for function calls -============= -*/ -float *tv (float x, float y, float z) + * This is just a convenience function + * for making temporary vectors for function calls + */ +float * +tv(float x, float y, float z) { - static int index; - static vec3_t vecs[8]; - float *v; + static int index; + static vec3_t vecs[8]; + float *v; - // use an array so that multiple tempvectors won't collide - // for a while + /* use an array so that multiple tempvectors + won't collide for a while */ v = vecs[index]; - index = (index + 1)&7; + index = (index + 1) & 7; v[0] = x; v[1] = y; @@ -262,106 +301,127 @@ float *tv (float x, float y, float z) return v; } - /* -============= -VectorToString - -This is just a convenience function -for printing vectors -============= -*/ -char *vtos (vec3_t v) + * This is just a convenience function + * for printing vectors + */ +char * +vtos(vec3_t v) { - static int index; - static char str[8][32]; - char *s; + static int index; + static char str[8][32]; + char *s; - // use an array so that multiple vtos won't collide + /* use an array so that multiple vtos won't collide */ s = str[index]; - index = (index + 1)&7; + index = (index + 1) & 7; - Com_sprintf (s, 32, "(%i %i %i)", (int)v[0], (int)v[1], (int)v[2]); + Com_sprintf(s, 32, "(%i %i %i)", (int)v[0], (int)v[1], (int)v[2]); return s; } +vec3_t VEC_UP = {0, -1, 0}; +vec3_t MOVEDIR_UP = {0, 0, 1}; +vec3_t VEC_DOWN = {0, -2, 0}; +vec3_t MOVEDIR_DOWN = {0, 0, -1}; -vec3_t VEC_UP = {0, -1, 0}; -vec3_t MOVEDIR_UP = {0, 0, 1}; -vec3_t VEC_DOWN = {0, -2, 0}; -vec3_t MOVEDIR_DOWN = {0, 0, -1}; - -void G_SetMovedir (vec3_t angles, vec3_t movedir) +void +G_SetMovedir(vec3_t angles, vec3_t movedir) { - if (VectorCompare (angles, VEC_UP)) + if (VectorCompare(angles, VEC_UP)) { - VectorCopy (MOVEDIR_UP, movedir); + VectorCopy(MOVEDIR_UP, movedir); } - else if (VectorCompare (angles, VEC_DOWN)) + else if (VectorCompare(angles, VEC_DOWN)) { - VectorCopy (MOVEDIR_DOWN, movedir); + VectorCopy(MOVEDIR_DOWN, movedir); } else { - AngleVectors (angles, movedir, NULL, NULL); + AngleVectors(angles, movedir, NULL, NULL); } - VectorClear (angles); + VectorClear(angles); } - -float vectoyaw (vec3_t vec) +float +vectoyaw(vec3_t vec) { - float yaw; - - if (/*vec[YAW] == 0 &&*/ vec[PITCH] == 0) + float yaw; + + if (vec[PITCH] == 0) { yaw = 0; + if (vec[YAW] > 0) + { yaw = 90; + } else if (vec[YAW] < 0) + { yaw = -90; - } + } + } else { - yaw = (int) (atan2(vec[YAW], vec[PITCH]) * 180 / M_PI); + yaw = (int)(atan2(vec[YAW], vec[PITCH]) * 180 / M_PI); + if (yaw < 0) + { yaw += 360; + } } return yaw; } - -void vectoangles (vec3_t value1, vec3_t angles) +void +vectoangles(vec3_t value1, vec3_t angles) { - float forward; - float yaw, pitch; - - if (value1[1] == 0 && value1[0] == 0) + float forward; + float yaw, pitch; + + if ((value1[1] == 0) && (value1[0] == 0)) { yaw = 0; + if (value1[2] > 0) + { pitch = 90; + } else + { pitch = 270; + } } else { if (value1[0]) - yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI); + { + yaw = (int)(atan2(value1[1], value1[0]) * 180 / M_PI); + } else if (value1[1] > 0) + { yaw = 90; + } else + { yaw = -90; - if (yaw < 0) - yaw += 360; + } + + if (yaw < 0) + { + yaw += 360; + } + + forward = sqrt(value1[0] * value1[0] + value1[1] * value1[1]); + pitch = (int)(atan2(value1[2], forward) * 180 / M_PI); - forward = sqrt (value1[0]*value1[0] + value1[1]*value1[1]); - pitch = (int) (atan2(value1[2], forward) * 180 / M_PI); if (pitch < 0) + { pitch += 360; + } } angles[PITCH] = -pitch; @@ -369,17 +429,18 @@ void vectoangles (vec3_t value1, vec3_t angles) angles[ROLL] = 0; } -char *G_CopyString (char *in) +char * +G_CopyString(char *in) { - char *out; - - out = gi.TagMalloc (strlen(in)+1, TAG_LEVEL); - strcpy (out, in); + char *out; + + out = gi.TagMalloc(strlen(in) + 1, TAG_LEVEL); + strcpy(out, in); return out; } - -void G_InitEdict (edict_t *e) +void +G_InitEdict(edict_t *e) { e->inuse = true; e->classname = "noclass"; @@ -388,159 +449,175 @@ void G_InitEdict (edict_t *e) } /* -================= -G_Spawn - -Either finds a free edict, or allocates a new one. -Try to avoid reusing an entity that was recently freed, because it -can cause the client to think the entity morphed into something else -instead of being removed and recreated, which can cause interpolated -angles and bad trails. -================= -*/ -edict_t *G_Spawn (void) + * Either finds a free edict, or allocates a new one. + * Try to avoid reusing an entity that was recently freed, because it + * can cause the client to think the entity morphed into something else + * instead of being removed and recreated, which can cause interpolated + * angles and bad trails. + */ +edict_t * +G_Spawn(void) { - int i; - edict_t *e; + int i; + edict_t *e; - e = &g_edicts[(int)maxclients->value+1]; - for ( i=maxclients->value+1 ; ivalue + 1]; + + for (i = maxclients->value + 1; i < globals.num_edicts; i++, e++) { - // the first couple seconds of server time can involve a lot of - // freeing and allocating, so relax the replacement policy - if (!e->inuse && ( e->freetime < 2 || level.time - e->freetime > 0.5 ) ) + /* the first couple seconds of server time can involve a lot of + freeing and allocating, so relax the replacement policy */ + if (!e->inuse && ((e->freetime < 2) || (level.time - e->freetime > 0.5))) { - G_InitEdict (e); + G_InitEdict(e); return e; } } - + if (i == game.maxentities) - gi.error ("ED_Alloc: no free edicts"); - + { + gi.error("ED_Alloc: no free edicts"); + } + globals.num_edicts++; - G_InitEdict (e); + G_InitEdict(e); return e; } /* -================= -G_FreeEdict - -Marks the edict as free -================= -*/ -void G_FreeEdict (edict_t *ed) + * Marks the edict as free + */ +void +G_FreeEdict(edict_t *ed) { - gi.unlinkentity (ed); // unlink from world + gi.unlinkentity(ed); /* unlink from world */ if ((ed - g_edicts) <= (maxclients->value + BODY_QUEUE_SIZE)) { return; } - memset (ed, 0, sizeof(*ed)); + memset(ed, 0, sizeof(*ed)); ed->classname = "freed"; ed->freetime = level.time; ed->inuse = false; } - -/* -============ -G_TouchTriggers - -============ -*/ -void G_TouchTriggers (edict_t *ent) +void +G_TouchTriggers(edict_t *ent) { - int i, num; - edict_t *touch[MAX_EDICTS], *hit; - - // dead things don't activate triggers! - if ((ent->client || (ent->svflags & SVF_MONSTER)) && (ent->health <= 0)) + int i, num; + edict_t *touch[MAX_EDICTS], *hit; + + if (!ent) + { return; + } + + /* dead things don't activate triggers! */ + if ((ent->client || (ent->svflags & SVF_MONSTER)) && (ent->health <= 0)) + { + return; + } - num = gi.BoxEdicts (ent->absmin, ent->absmax, touch - , MAX_EDICTS, AREA_TRIGGERS); + num = gi.BoxEdicts(ent->absmin, ent->absmax, touch, + MAX_EDICTS, AREA_TRIGGERS); - // be careful, it is possible to have an entity in this - // list removed before we get to it (killtriggered) - for (i=0 ; iinuse) + { continue; + } + if (!hit->touch) + { continue; - hit->touch (hit, ent, NULL, NULL); + } + + hit->touch(hit, ent, NULL, NULL); } } /* -============ -G_TouchSolids - -Call after linking a new trigger in during gameplay -to force all entities it covers to immediately touch it -============ -*/ -void G_TouchSolids (edict_t *ent) + * Call after linking a new trigger in during gameplay + * to force all entities it covers to immediately touch it + */ +void +G_TouchSolids(edict_t *ent) { - int i, num; - edict_t *touch[MAX_EDICTS], *hit; + int i, num; + edict_t *touch[MAX_EDICTS], *hit; + + if (!ent) + { + return; + } + + num = gi.BoxEdicts(ent->absmin, ent->absmax, touch, + MAX_EDICTS, AREA_SOLID); - num = gi.BoxEdicts (ent->absmin, ent->absmax, touch - , MAX_EDICTS, AREA_SOLID); - - // be careful, it is possible to have an entity in this - // list removed before we get to it (killtriggered) - for (i=0 ; iinuse) + { continue; + } + if (ent->touch) - ent->touch (hit, ent, NULL, NULL); + { + ent->touch(hit, ent, NULL, NULL); + } + if (!ent->inuse) + { break; + } } } /* -============================================================================== - -Kill box - -============================================================================== -*/ - -/* -================= -KillBox - -Kills all entities that would touch the proposed new positioning -of ent. Ent should be unlinked before calling this! -================= -*/ -qboolean KillBox (edict_t *ent) + * Kills all entities that would touch the proposed new positioning + * of ent. Ent should be unlinked before calling this! + */ +qboolean +KillBox(edict_t *ent) { - trace_t tr; - + trace_t tr; + + if (!ent) + { + return false; + } + while (1) { - tr = gi.trace (ent->s.origin, ent->mins, ent->maxs, ent->s.origin, NULL, MASK_PLAYERSOLID); + tr = gi.trace(ent->s.origin, ent->mins, ent->maxs, ent->s.origin, + NULL, MASK_PLAYERSOLID); + if (!tr.ent) + { break; + } - // nail it - T_Damage (tr.ent, ent, ent, vec3_origin, ent->s.origin, vec3_origin, 100000, 0, DAMAGE_NO_PROTECTION, MOD_TELEFRAG); + /* nail it */ + T_Damage(tr.ent, ent, ent, vec3_origin, ent->s.origin, vec3_origin, + 100000, 0, DAMAGE_NO_PROTECTION, MOD_TELEFRAG); - // if we didn't kill it, fail + /* if we didn't kill it, fail */ if (tr.ent->solid) + { return false; + } } - return true; // all clear + return true; /* all clear */ } -