Skip to content

Commit

Permalink
Queue blood splats to avoid crash
Browse files Browse the repository at this point in the history
When spawning blood splats, add them to a queue. Once the maximum has
been reached (BLOODSPLATQUEUESIZE = 512), remove the oldest blood splat
before adding a new one. Also, instead of crashing once MAXVISSPRITES is
reached, try to remove the oldest blood splat first. Failing that, exit
cleanly with with an error rather than crashing. MAXVISSPRITES has been
increased from 1024 to 2048.
  • Loading branch information
bradharding committed Feb 1, 2014
1 parent f049045 commit 5b61310
Show file tree
Hide file tree
Showing 8 changed files with 62 additions and 29 deletions.
2 changes: 1 addition & 1 deletion src/d_main.c
Expand Up @@ -706,7 +706,7 @@ void D_DoomMain(void)
}
else
{
sprintf (file,"%s.lmp", myargv[p + 1]);
sprintf(file,"%s.lmp", myargv[p + 1]);
}

if (D_AddFile(file))
Expand Down
5 changes: 4 additions & 1 deletion src/g_game.c
Expand Up @@ -1591,6 +1591,9 @@ void G_DoLoadGame(void)

leveltime = savedleveltime;

bloodSplatQueueSlot = 0;
memset(bloodSplatQueue, 0, sizeof(mobj_t *) * BLOODSPLATQUEUESIZE);

// dearchive all the modifications
P_UnArchivePlayers();
P_UnArchiveWorld();
Expand Down Expand Up @@ -2126,7 +2129,7 @@ void G_DoPlayDemo(void)
int demoversion;

gameaction = ga_nothing;
demobuffer = demo_p = (byte *)W_CacheLumpName (defdemoname, PU_STATIC);
demobuffer = demo_p = (byte *)W_CacheLumpName(defdemoname, PU_STATIC);

demoversion = *demo_p++;

Expand Down
2 changes: 1 addition & 1 deletion src/info.c
Expand Up @@ -51,7 +51,7 @@ char *sprnames[] = {
"POL3", "POL1", "POL6", "GOR2", "GOR3", "GOR4", "GOR5", "SMIT", "COL1", "COL2",
"COL3", "COL4", "CAND", "CBRA", "COL6", "TRE1", "TRE2", "ELEC", "CEYE", "FSKU",
"COL5", "TBLU", "TGRN", "TRED", "SMBT", "SMGT", "SMRT", "HDB1", "HDB2", "HDB3",
"HDB4", "HDB5", "HDB6", "POB1", "POB2", "BRS1", "TLMP", "TLP2", "BLD2", NULL // [BH] "BLD2"
"HDB4", "HDB5", "HDB6", "POB1", "POB2", "BRS1", "TLMP", "TLP2", "BLD2", NULL
};


Expand Down
14 changes: 9 additions & 5 deletions src/p_local.h
Expand Up @@ -102,13 +102,17 @@ void P_PlayerThink(player_t *player);
#define ONCEILINGZ INT_MAX

// Time interval for item respawning.
#define ITEMQUESIZE 128
#define ITEMQUEUESIZE 128

extern mapthing_t itemrespawnque[ITEMQUESIZE];
extern int itemrespawntime[ITEMQUESIZE];
extern int iquehead;
extern int iquetail;
extern mapthing_t itemrespawnqueue[ITEMQUEUESIZE];
extern int itemrespawntime[ITEMQUEUESIZE];
extern int iqueuehead;
extern int iqueuetail;

#define BLOODSPLATQUEUESIZE 512

extern mobj_t *bloodSplatQueue[BLOODSPLATQUEUESIZE];
extern int bloodSplatQueueSlot;

void P_RespawnSpecials(void);

Expand Down
51 changes: 33 additions & 18 deletions src/p_mobj.c
Expand Up @@ -45,6 +45,10 @@ along with DOOM RETRO. If not, see http://www.gnu.org/licenses/.
void G_PlayerReborn(int player);


mobj_t *bloodSplatQueue[BLOODSPLATQUEUESIZE];
int bloodSplatQueueSlot;


//
// P_SetMobjState
// Returns true if the mobj is still present.
Expand Down Expand Up @@ -585,10 +589,10 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
//
// P_RemoveMobj
//
mapthing_t itemrespawnque[ITEMQUESIZE];
int itemrespawntime[ITEMQUESIZE];
int iquehead;
int iquetail;
mapthing_t itemrespawnqueue[ITEMQUEUESIZE];
int itemrespawntime[ITEMQUEUESIZE];
int iqueuehead;
int iqueuetail;

void P_RemoveMobj(mobj_t *mobj)
{
Expand All @@ -597,17 +601,17 @@ void P_RemoveMobj(mobj_t *mobj)
&& (mobj->type != MT_INV)
&& (mobj->type != MT_INS))
{
itemrespawnque[iquehead] = mobj->spawnpoint;
itemrespawntime[iquehead] = leveltime;
iquehead = (iquehead + 1) & (ITEMQUESIZE - 1);
itemrespawnqueue[iqueuehead] = mobj->spawnpoint;
itemrespawntime[iqueuehead] = leveltime;
iqueuehead = (iqueuehead + 1) & (ITEMQUEUESIZE - 1);

// lose one off the end?
if (iquehead == iquetail)
iquetail = (iquetail + 1) & (ITEMQUESIZE - 1);
if (iqueuehead == iqueuetail)
iqueuetail = (iqueuetail + 1) & (ITEMQUEUESIZE - 1);
}

if (mobj->type == MT_BLOOD)
P_SpawnBloodSplat(mobj->x, mobj->y, mobj->flags2);
P_SpawnBloodSplat(mobj->x, mobj->y, (mobjflag2_t)mobj->flags2);

// unlink from sector and block lists
P_UnsetThingPosition(mobj);
Expand Down Expand Up @@ -654,14 +658,14 @@ void P_RespawnSpecials(void)
return;

// nothing left to respawn?
if (iquehead == iquetail)
if (iqueuehead == iqueuetail)
return;

// wait at least 30 seconds
if (leveltime - itemrespawntime[iquetail] < 30 * TICRATE)
if (leveltime - itemrespawntime[iqueuetail] < 30 * TICRATE)
return;

mthing = &itemrespawnque[iquetail];
mthing = &itemrespawnqueue[iqueuetail];

x = mthing->x << FRACBITS;
y = mthing->y << FRACBITS;
Expand Down Expand Up @@ -690,7 +694,7 @@ void P_RespawnSpecials(void)
mo->angle = ANG45 * (mthing->angle / 45);

// pull it from the queue
iquetail = (iquetail + 1) & (ITEMQUESIZE - 1);
iqueuetail = (iqueuetail + 1) & (ITEMQUEUESIZE - 1);
}


Expand Down Expand Up @@ -955,14 +959,25 @@ void P_SpawnBlood(fixed_t x, fixed_t y, fixed_t z, angle_t angle, int damage, mo


//
// P_SpawnBlood
// P_SpawnBloodSplat
//
void P_SpawnBloodSplat(fixed_t x, fixed_t y, mobjflag2_t flag)
{
mobj_t *th = P_SpawnMobj(x, y, ONFLOORZ, MT_BLOODSPLAT);
mobj_t *newmobj = P_SpawnMobj(x, y, ONFLOORZ, MT_BLOODSPLAT);

newmobj->flags2 |= flag;
P_SetMobjState(newmobj, (statenum_t)(S_BLOODSPLAT + M_RandomInt(0, 7)));

th->flags2 |= flag;
P_SetMobjState(th, (statenum_t)(S_BLOODSPLAT + M_RandomInt(0, 7)));
if (bloodSplatQueueSlot >= BLOODSPLATQUEUESIZE)
{
// Too many blood splats - remove an old one
mobj_t *old = bloodSplatQueue[bloodSplatQueueSlot % BLOODSPLATQUEUESIZE];

if (old)
P_RemoveMobj(old);
}
bloodSplatQueue[bloodSplatQueueSlot % BLOODSPLATQUEUESIZE] = newmobj;
bloodSplatQueueSlot++;
}


Expand Down
4 changes: 3 additions & 1 deletion src/p_setup.c
Expand Up @@ -1031,6 +1031,8 @@ void P_SetupLevel(int episode, int map, int playermask, skill_t skill)

bodyqueslot = 0;
deathmatch_p = deathmatchstarts;
bloodSplatQueueSlot = 0;
memset(bloodSplatQueue, 0, sizeof(mobj_t *) * BLOODSPLATQUEUESIZE);
P_LoadThings(lumpnum + ML_THINGS);

// if deathmatch, randomly spawn the active players
Expand All @@ -1046,7 +1048,7 @@ void P_SetupLevel(int episode, int map, int playermask, skill_t skill)
}

// clear special respawning queue
iquehead = iquetail = 0;
iqueuehead = iqueuetail = 0;

// set up world state
P_SpawnSpecials();
Expand Down
11 changes: 10 additions & 1 deletion src/r_things.c
Expand Up @@ -42,6 +42,7 @@ along with DOOM RETRO. If not, see http://www.gnu.org/licenses/.
#include "doomstat.h"

#include "v_video.h"
#include "p_local.h"



Expand Down Expand Up @@ -307,7 +308,15 @@ vissprite_t overflowsprite;
vissprite_t *R_NewVisSprite(void)
{
if (vissprite_p == &vissprites[MAXVISSPRITES])
return &overflowsprite;
{
// Try to remove an old blood splat
mobj_t *old = bloodSplatQueue[bloodSplatQueueSlot % BLOODSPLATQUEUESIZE];

if (old)
P_RemoveMobj(old);
else
I_Error("R_NewVisSprite: MAXVISSPRITES reached");
}

vissprite_p++;
return vissprite_p - 1;
Expand Down
2 changes: 1 addition & 1 deletion src/r_things.h
Expand Up @@ -31,7 +31,7 @@ along with DOOM RETRO. If not, see http://www.gnu.org/licenses/.



#define MAXVISSPRITES 1024
#define MAXVISSPRITES 2048

extern vissprite_t vissprites[MAXVISSPRITES];
extern vissprite_t *vissprite_p;
Expand Down

0 comments on commit 5b61310

Please sign in to comment.