objectplace stability fix

Objectplace reallocates the mapthings list to add one more mapthing. By itself there's no problem with this.
But, mobj->spawnpoint is a pointer to the mapthing's location in the mapthings list.
So by reallocating the mapthings list, all references to mobj->spawnpoints point to freed memory.

... Oops.

Now when objectplace reallocates the mapthings list it actually corrects the locations of all mobj's spawnpoints to point to the new list.

Hooray, you can use NiGHTS objectplace again if you really want to.
This commit is contained in:
Inuyasha 2016-01-20 01:13:21 -08:00
parent 6fd3036112
commit 55f0e5cab5

View file

@ -880,12 +880,33 @@ static boolean OP_HeightOkay(player_t *player, UINT8 ceiling)
static mapthing_t *OP_CreateNewMapThing(player_t *player, UINT16 type, boolean ceiling) static mapthing_t *OP_CreateNewMapThing(player_t *player, UINT16 type, boolean ceiling)
{ {
mapthing_t *mt; mapthing_t *mt = mapthings;
#ifdef HAVE_BLUA #ifdef HAVE_BLUA
LUA_InvalidateMapthings(); LUA_InvalidateMapthings();
#endif #endif
mapthings = Z_Realloc(mapthings, ++nummapthings * sizeof (*mapthings), PU_LEVEL, NULL); mapthings = Z_Realloc(mapthings, ++nummapthings * sizeof (*mapthings), PU_LEVEL, NULL);
// as Z_Realloc can relocate mapthings, quickly go through thinker list and correct
// the spawnpoints of any objects that have them to the new location
if (mt != mapthings)
{
thinker_t *th;
mobj_t *mo;
for (th = thinkercap.next; th != &thinkercap; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo = (mobj_t *)th;
// get offset from mt, which points to old mapthings, then add new location
if (mo->spawnpoint)
mo->spawnpoint = (mo->spawnpoint - mt) + mapthings;
}
}
mt = (mapthings+nummapthings-1); mt = (mapthings+nummapthings-1);
mt->type = type; mt->type = type;