From c3b57bc81de59b3b47ed5acb813ecef1e8b64a29 Mon Sep 17 00:00:00 2001 From: BjossiAlfreds Date: Fri, 29 Oct 2021 17:25:03 +0000 Subject: [PATCH] Made the game able to handle entity overload better --- src/game/g_ai.c | 9 ++++++- src/game/g_misc.c | 27 ++++++++++++++------ src/game/g_utils.c | 56 +++++++++++++++++++++++++++++------------ src/game/header/local.h | 1 + 4 files changed, 68 insertions(+), 25 deletions(-) diff --git a/src/game/g_ai.c b/src/game/g_ai.c index 7c70d582..f2cb07d8 100644 --- a/src/game/g_ai.c +++ b/src/game/g_ai.c @@ -1196,8 +1196,15 @@ ai_run(edict_t *self, float dist) return; } + tempgoal = G_SpawnOptional(); + + if (!tempgoal) + { + M_MoveToGoal(self, dist); + return; + } + save = self->goalentity; - tempgoal = G_Spawn(); self->goalentity = tempgoal; new = false; diff --git a/src/game/g_misc.c b/src/game/g_misc.c index 664c09f3..29dcff32 100644 --- a/src/game/g_misc.c +++ b/src/game/g_misc.c @@ -196,14 +196,19 @@ ThrowGib(edict_t *self, char *gibname, int damage, int type) return; } - gibsthisframe++; - - if (gibsthisframe > MAX_GIBS) + if (gibsthisframe >= MAX_GIBS) { return; } - gib = G_Spawn(); + gib = G_SpawnOptional(); + + if (!gib) + { + return; + } + + gibsthisframe++; VectorScale(self->size, 0.5, size); VectorAdd(self->absmin, size, origin); @@ -373,14 +378,20 @@ ThrowDebris(edict_t *self, char *modelname, float speed, vec3_t origin) return; } - debristhisframe++; - - if (debristhisframe > MAX_DEBRIS) + if (debristhisframe >= MAX_DEBRIS) { return; } - chunk = G_Spawn(); + chunk = G_SpawnOptional(); + + if (!chunk) + { + return; + } + + debristhisframe++; + VectorCopy(origin, chunk->s.origin); gi.setmodel(chunk, modelname); v[0] = 100 * crandom(); diff --git a/src/game/g_utils.c b/src/game/g_utils.c index beb4753f..7a80210e 100644 --- a/src/game/g_utils.c +++ b/src/game/g_utils.c @@ -512,34 +512,58 @@ G_InitEdict(edict_t *e) * being removed and recreated, which can * cause interpolated angles and bad trails. */ -edict_t * -G_Spawn(void) +#define POLICY_DEFAULT 0 +#define POLICY_DESPERATE 1 + +static edict_t * +G_FindFreeEdict(int policy) { - int i; edict_t *e; - e = &g_edicts[(int)maxclients->value + 1]; - - for (i = maxclients->value + 1; i < globals.num_edicts; i++, e++) + for (e = g_edicts + game.maxclients + 1 ; e < &g_edicts[globals.num_edicts] ; 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 && (policy == POLICY_DESPERATE || e->freetime < 2.0f || (level.time - e->freetime) > 0.5f)) { - G_InitEdict(e); + G_InitEdict (e); return e; } } - if (i == game.maxentities) + return NULL; +} + +edict_t * +G_SpawnOptional(void) +{ + edict_t *e = G_FindFreeEdict (POLICY_DEFAULT); + + if (e) { - gi.error("ED_Alloc: no free edicts"); + return e; } - globals.num_edicts++; - G_InitEdict(e); + if (globals.num_edicts >= game.maxentities) + { + return G_FindFreeEdict (POLICY_DESPERATE); + } + + e = &g_edicts[globals.num_edicts++]; + G_InitEdict (e); + + return e; +} + +edict_t * +G_Spawn(void) +{ + edict_t *e = G_SpawnOptional(); + + if (!e) + gi.error ("ED_Alloc: no free edicts"); + return e; } diff --git a/src/game/header/local.h b/src/game/header/local.h index a96683c5..a1558b2d 100644 --- a/src/game/header/local.h +++ b/src/game/header/local.h @@ -629,6 +629,7 @@ void G_UseTargets(edict_t *ent, edict_t *activator); void G_SetMovedir(vec3_t angles, vec3_t movedir); void G_InitEdict(edict_t *e); +edict_t *G_SpawnOptional(void); edict_t *G_Spawn(void); void G_FreeEdict(edict_t *e);