Merge branch 'master' into newmenus

This commit is contained in:
Steel Titanium 2019-08-01 18:36:42 -04:00
parent 147815b87c
commit e8caa8538d
No known key found for this signature in database
GPG Key ID: 924BA411F18DFDBE
37 changed files with 1066 additions and 567 deletions

View File

@ -4270,13 +4270,11 @@ static INT16 Consistancy(void)
ret += P_GetRandSeed(); ret += P_GetRandSeed();
#ifdef MOBJCONSISTANCY #ifdef MOBJCONSISTANCY
if (!thlist[THINK_MOBJ].next)
{
DEBFILE(va("Consistancy = %u\n", ret));
return ret;
}
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo = (mobj_t *)th; mo = (mobj_t *)th;
if (mo->flags & (MF_SPECIAL | MF_SOLID | MF_PUSHABLE | MF_BOSS | MF_MISSILE | MF_SPRING | MF_MONITOR | MF_FIRE | MF_ENEMY | MF_PAIN | MF_STICKY)) if (mo->flags & (MF_SPECIAL | MF_SOLID | MF_PUSHABLE | MF_BOSS | MF_MISSILE | MF_SPRING | MF_MONITOR | MF_FIRE | MF_ENEMY | MF_PAIN | MF_STICKY))

View File

@ -4261,7 +4261,8 @@ static void Command_Archivetest_f(void)
// assign mobjnum // assign mobjnum
i = 1; i = 1;
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
((mobj_t *)th)->mobjnum = i++; if (th->function.acp1 != (actionf_p1)P_RemoveThinkerDelayed)
((mobj_t *)th)->mobjnum = i++;
// allocate buffer // allocate buffer
buf = save_p = ZZ_Alloc(1024); buf = save_p = ZZ_Alloc(1024);

View File

@ -5699,7 +5699,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_CEZFLOWER", "S_CEZFLOWER",
"S_CEZPOLE", "S_CEZPOLE",
"S_CEZBANNER", "S_CEZBANNER1",
"S_CEZBANNER2",
"S_PINETREE", "S_PINETREE",
"S_CEZBUSH1", "S_CEZBUSH1",
"S_CEZBUSH2", "S_CEZBUSH2",
@ -5708,7 +5709,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_FLAMEHOLDER", "S_FLAMEHOLDER",
"S_FIRETORCH", "S_FIRETORCH",
"S_WAVINGFLAG", "S_WAVINGFLAG",
"S_WAVINGFLAGSEG", "S_WAVINGFLAGSEG1",
"S_WAVINGFLAGSEG2",
"S_CRAWLASTATUE", "S_CRAWLASTATUE",
"S_FACESTABBERSTATUE", "S_FACESTABBERSTATUE",
"S_SUSPICIOUSFACESTABBERSTATUE_WAIT", "S_SUSPICIOUSFACESTABBERSTATUE_WAIT",
@ -7514,8 +7516,10 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_SMALLFIREBAR", // Small Firebar "MT_SMALLFIREBAR", // Small Firebar
"MT_BIGFIREBAR", // Big Firebar "MT_BIGFIREBAR", // Big Firebar
"MT_CEZFLOWER", // Flower "MT_CEZFLOWER", // Flower
"MT_CEZPOLE", // Pole "MT_CEZPOLE1", // Pole (with red banner)
"MT_CEZBANNER", // Banner "MT_CEZPOLE2", // Pole (with blue banner)
"MT_CEZBANNER1", // Banner (red)
"MT_CEZBANNER2", // Banner (blue)
"MT_PINETREE", // Pine Tree "MT_PINETREE", // Pine Tree
"MT_CEZBUSH1", // Bush 1 "MT_CEZBUSH1", // Bush 1
"MT_CEZBUSH2", // Bush 2 "MT_CEZBUSH2", // Bush 2
@ -7523,8 +7527,10 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_CANDLEPRICKET", // Candle pricket "MT_CANDLEPRICKET", // Candle pricket
"MT_FLAMEHOLDER", // Flame holder "MT_FLAMEHOLDER", // Flame holder
"MT_FIRETORCH", // Fire torch "MT_FIRETORCH", // Fire torch
"MT_WAVINGFLAG", // Waving flag "MT_WAVINGFLAG1", // Waving flag (red)
"MT_WAVINGFLAGSEG", // Waving flag segment "MT_WAVINGFLAG2", // Waving flag (blue)
"MT_WAVINGFLAGSEG1", // Waving flag segment (red)
"MT_WAVINGFLAGSEG2", // Waving flag segment (blue)
"MT_CRAWLASTATUE", // Crawla statue "MT_CRAWLASTATUE", // Crawla statue
"MT_FACESTABBERSTATUE", // Facestabber statue "MT_FACESTABBERSTATUE", // Facestabber statue
"MT_SUSPICIOUSFACESTABBERSTATUE", // :eggthinking: "MT_SUSPICIOUSFACESTABBERSTATUE", // :eggthinking:

View File

@ -1695,6 +1695,9 @@ void F_TitleScreenTicker(boolean run)
{ {
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (!mo2) if (!mo2)

View File

@ -2567,6 +2567,9 @@ void G_ChangePlayerReferences(mobj_t *oldmo, mobj_t *newmo)
// scan all thinkers // scan all thinkers
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (!(mo2->flags & MF_MISSILE)) if (!(mo2->flags & MF_MISSILE))
@ -4466,12 +4469,13 @@ void G_ConsGhostTic(void)
mobj = NULL; mobj = NULL;
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mobj = (mobj_t *)th; mobj = (mobj_t *)th;
if (mobj->type == (mobjtype_t)type && mobj->x == x && mobj->y == y && mobj->z == z) if (mobj->type == (mobjtype_t)type && mobj->x == x && mobj->y == y && mobj->z == z)
break; break;
mobj = NULL; // wasn't this one, keep searching.
} }
if (mobj && mobj->health != health) // Wasn't damaged?! This is desync! Fix it! if (th != &thlist[THINK_MOBJ] && mobj->health != health) // Wasn't damaged?! This is desync! Fix it!
{ {
if (demosynced) if (demosynced)
CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n")); CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n"));
@ -5860,13 +5864,16 @@ void G_DoPlayMetal(void)
// find metal sonic // find metal sonic
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo = (mobj_t *)th; mo = (mobj_t *)th;
if (mo->type != MT_METALSONIC_RACE) if (mo->type != MT_METALSONIC_RACE)
continue; continue;
break; break;
} }
if (!mo) if (th == &thlist[THINK_MOBJ])
{ {
CONS_Alert(CONS_ERROR, M_GetText("Failed to find bot entity.\n")); CONS_Alert(CONS_ERROR, M_GetText("Failed to find bot entity.\n"));
Z_Free(metalbuffer); Z_Free(metalbuffer);

View File

@ -804,6 +804,14 @@ void HWR_WallLighting(FOutVector *wlVerts)
FSurfaceInfo Surf; FSurfaceInfo Surf;
float dist_p2d, d[4], s; float dist_p2d, d[4], s;
if (!dynlights->mo[j])
continue;
if (P_MobjWasRemoved(dynlights->mo[j]))
{
P_SetTarget(&dynlights->mo[j], NULL);
continue;
}
// check bounding box first // check bounding box first
if (SphereTouchBBox3D(&wlVerts[2], &wlVerts[0], &LIGHT_POS(j), DL_RADIUS(j))==false) if (SphereTouchBBox3D(&wlVerts[2], &wlVerts[0], &LIGHT_POS(j), DL_RADIUS(j))==false)
continue; continue;
@ -854,8 +862,6 @@ void HWR_WallLighting(FOutVector *wlVerts)
#ifdef DL_HIGH_QUALITY #ifdef DL_HIGH_QUALITY
Surf.FlatColor.s.alpha = (UINT8)((1-dist_p2d/DL_SQRRADIUS(j))*Surf.FlatColor.s.alpha); Surf.FlatColor.s.alpha = (UINT8)((1-dist_p2d/DL_SQRRADIUS(j))*Surf.FlatColor.s.alpha);
#endif #endif
if (!dynlights->mo[j]->state)
return;
// next state is null so fade out with alpha // next state is null so fade out with alpha
if (dynlights->mo[j]->state->nextstate == S_NULL) if (dynlights->mo[j]->state->nextstate == S_NULL)
Surf.FlatColor.s.alpha = (UINT8)(((float)dynlights->mo[j]->tics/(float)dynlights->mo[j]->state->tics)*Surf.FlatColor.s.alpha); Surf.FlatColor.s.alpha = (UINT8)(((float)dynlights->mo[j]->tics/(float)dynlights->mo[j]->state->tics)*Surf.FlatColor.s.alpha);
@ -886,6 +892,14 @@ void HWR_PlaneLighting(FOutVector *clVerts, int nrClipVerts)
FSurfaceInfo Surf; FSurfaceInfo Surf;
float dist_p2d, s; float dist_p2d, s;
if (!dynlights->mo[j])
continue;
if (P_MobjWasRemoved(dynlights->mo[j]))
{
P_SetTarget(&dynlights->mo[j], NULL);
continue;
}
// BP: The kickass Optimization: check if light touch bounding box // BP: The kickass Optimization: check if light touch bounding box
if (SphereTouchBBox3D(&p1, &p2, &dynlights->position[j], DL_RADIUS(j))==false) if (SphereTouchBBox3D(&p1, &p2, &dynlights->position[j], DL_RADIUS(j))==false)
continue; continue;
@ -917,8 +931,6 @@ void HWR_PlaneLighting(FOutVector *clVerts, int nrClipVerts)
#ifdef DL_HIGH_QUALITY #ifdef DL_HIGH_QUALITY
Surf.FlatColor.s.alpha = (unsigned char)((1 - dist_p2d/DL_SQRRADIUS(j))*Surf.FlatColor.s.alpha); Surf.FlatColor.s.alpha = (unsigned char)((1 - dist_p2d/DL_SQRRADIUS(j))*Surf.FlatColor.s.alpha);
#endif #endif
if (!dynlights->mo[j]->state)
return;
// next state is null so fade out with alpha // next state is null so fade out with alpha
if ((dynlights->mo[j]->state->nextstate == S_NULL)) if ((dynlights->mo[j]->state->nextstate == S_NULL))
Surf.FlatColor.s.alpha = (unsigned char)(((float)dynlights->mo[j]->tics/(float)dynlights->mo[j]->state->tics)*Surf.FlatColor.s.alpha); Surf.FlatColor.s.alpha = (unsigned char)(((float)dynlights->mo[j]->tics/(float)dynlights->mo[j]->state->tics)*Surf.FlatColor.s.alpha);
@ -1049,6 +1061,14 @@ void HWR_DrawCoronas(void)
if (!(p_lspr->type & CORONA_SPR)) if (!(p_lspr->type & CORONA_SPR))
continue; continue;
if (!dynlights->mo[j])
continue;
if (P_MobjWasRemoved(dynlights->mo[j]))
{
P_SetTarget(&dynlights->mo[j], NULL);
continue;
}
transform(&cx,&cy,&cz); transform(&cx,&cy,&cz);
// more realistique corona ! // more realistique corona !
@ -1110,7 +1130,8 @@ void HWR_DrawCoronas(void)
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
void HWR_ResetLights(void) void HWR_ResetLights(void)
{ {
dynlights->nb = 0; while (dynlights->nb)
P_SetTarget(&dynlights->mo[--dynlights->nb], NULL);
} }
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
@ -1141,24 +1162,25 @@ void HWR_DL_AddLight(gr_vissprite_t *spr, GLPatch_t *patch)
return; return;
#endif #endif
if (dynlights->nb >= DL_MAX_LIGHT)
return;
// check if sprite contain dynamic light // check if sprite contain dynamic light
p_lspr = t_lspr[spr->mobj->sprite]; p_lspr = t_lspr[spr->mobj->sprite];
if ((p_lspr->type&DYNLIGHT_SPR) if (!(p_lspr->type & DYNLIGHT_SPR))
&& ((p_lspr->type != LIGHT_SPR) || cv_grstaticlighting.value) return;
&& (dynlights->nb < DL_MAX_LIGHT) if ((p_lspr->type != LIGHT_SPR) || cv_grstaticlighting.value)
return;
&& spr->mobj->state) LIGHT_POS(dynlights->nb).x = FIXED_TO_FLOAT(spr->mobj->x);
{ LIGHT_POS(dynlights->nb).y = FIXED_TO_FLOAT(spr->mobj->z)+FIXED_TO_FLOAT(spr->mobj->height>>1)+p_lspr->light_yoffset;
LIGHT_POS(dynlights->nb).x = FIXED_TO_FLOAT(spr->mobj->x); LIGHT_POS(dynlights->nb).z = FIXED_TO_FLOAT(spr->mobj->y);
LIGHT_POS(dynlights->nb).y = FIXED_TO_FLOAT(spr->mobj->z)+FIXED_TO_FLOAT(spr->mobj->height>>1)+p_lspr->light_yoffset;
LIGHT_POS(dynlights->nb).z = FIXED_TO_FLOAT(spr->mobj->y);
P_SetTarget(&dynlights->mo[dynlights->nb], spr->mobj); P_SetTarget(&dynlights->mo[dynlights->nb], spr->mobj);
dynlights->p_lspr[dynlights->nb] = p_lspr; dynlights->p_lspr[dynlights->nb] = p_lspr;
dynlights->nb++; dynlights->nb++;
}
} }
static GLPatch_t lightmappatch; static GLPatch_t lightmappatch;
@ -1312,6 +1334,14 @@ static void HWR_CheckSubsector(size_t num, fixed_t *bbox)
// if (CircleTouchBBox(&p1, &p2, &LIGHT_POS(lightnum), DL_RADIUS(lightnum))==false) // if (CircleTouchBBox(&p1, &p2, &LIGHT_POS(lightnum), DL_RADIUS(lightnum))==false)
// continue; // continue;
if (!dynlights->mo[lightnum])
continue;
if (P_MobjWasRemoved(dynlights->mo[lightnum]))
{
P_SetTarget(&dynlights->mo[lightnum], NULL);
continue;
}
count = sub->numlines; // how many linedefs count = sub->numlines; // how many linedefs
line = &segs[sub->firstline]; // first line seg line = &segs[sub->firstline]; // first line seg
while (count--) while (count--)
@ -1329,18 +1359,20 @@ static void HWR_CheckSubsector(size_t num, fixed_t *bbox)
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
static void HWR_AddMobjLights(mobj_t *thing) static void HWR_AddMobjLights(mobj_t *thing)
{ {
if (t_lspr[thing->sprite]->type & CORONA_SPR) if (dynlights->nb >= DL_MAX_LIGHT)
{ return;
LIGHT_POS(dynlights->nb).x = FIXED_TO_FLOAT(thing->x); if (!(t_lspr[thing->sprite]->type & CORONA_SPR))
LIGHT_POS(dynlights->nb).y = FIXED_TO_FLOAT(thing->z) + t_lspr[thing->sprite]->light_yoffset; return;
LIGHT_POS(dynlights->nb).z = FIXED_TO_FLOAT(thing->y);
dynlights->p_lspr[dynlights->nb] = t_lspr[thing->sprite]; LIGHT_POS(dynlights->nb).x = FIXED_TO_FLOAT(thing->x);
LIGHT_POS(dynlights->nb).y = FIXED_TO_FLOAT(thing->z) + t_lspr[thing->sprite]->light_yoffset;
LIGHT_POS(dynlights->nb).z = FIXED_TO_FLOAT(thing->y);
dynlights->nb++; P_SetTarget(&dynlights->mo[dynlights->nb], thing);
if (dynlights->nb > DL_MAX_LIGHT)
dynlights->nb = DL_MAX_LIGHT; dynlights->p_lspr[dynlights->nb] = t_lspr[thing->sprite];
}
dynlights->nb++;
} }
//Hurdler: The goal of this function is to walk through all the bsp starting //Hurdler: The goal of this function is to walk through all the bsp starting
@ -1367,7 +1399,8 @@ static void HWR_SearchLightsInMobjs(void)
// search in the list of thinkers // search in the list of thinkers
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
HWR_AddMobjLights((mobj_t *)th); if (th->function.acp1 != (actionf_p1)P_RemoveThinkerDelayed)
HWR_AddMobjLights((mobj_t *)th);
} }
#endif #endif
@ -1379,7 +1412,7 @@ void HWR_CreateStaticLightmaps(int bspnum)
#ifdef STATICLIGHT #ifdef STATICLIGHT
CONS_Debug(DBG_RENDER, "HWR_CreateStaticLightmaps\n"); CONS_Debug(DBG_RENDER, "HWR_CreateStaticLightmaps\n");
dynlights->nb = 0; HWR_ResetLights();
// First: Searching for lights // First: Searching for lights
// BP: if i was you, I will make it in create mobj since mobj can be create // BP: if i was you, I will make it in create mobj since mobj can be create
@ -1390,8 +1423,6 @@ void HWR_CreateStaticLightmaps(int bspnum)
// Second: Build all lightmap for walls covered by lights // Second: Build all lightmap for walls covered by lights
validcount++; // to be sure validcount++; // to be sure
HWR_ComputeLightMapsInBSPNode(bspnum, NULL); HWR_ComputeLightMapsInBSPNode(bspnum, NULL);
dynlights->nb = 0;
#else #else
(void)bspnum; (void)bspnum;
#endif #endif

View File

@ -2322,9 +2322,10 @@ state_t states[NUMSTATES] =
{SPR_BFBR, FF_FULLBRIGHT|15, 1, {NULL}, 0, 0, S_BIGFIREBAR1}, // S_BIGFIREBAR16 {SPR_BFBR, FF_FULLBRIGHT|15, 1, {NULL}, 0, 0, S_BIGFIREBAR1}, // S_BIGFIREBAR16
{SPR_FWR4, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CEZFLOWER {SPR_FWR4, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CEZFLOWER
{SPR_BANR, 1, -1, {NULL}, 0, 0, S_NULL}, // S_CEZPOLE {SPR_BANR, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CEZPOLE
{SPR_BANR, FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_CEZBANNER {SPR_BANR, FF_PAPERSPRITE|1, -1, {NULL}, 0, 0, S_NULL}, // S_CEZBANNER1
{SPR_BANR, FF_PAPERSPRITE|2, -1, {NULL}, 0, 0, S_NULL}, // S_CEZBANNER2
{SPR_PINE, 0, -1, {NULL}, 0, 0, S_NULL}, // S_PINETREE {SPR_PINE, 0, -1, {NULL}, 0, 0, S_NULL}, // S_PINETREE
{SPR_CEZB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CEZBUSH1 {SPR_CEZB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CEZBUSH1
@ -2338,7 +2339,8 @@ state_t states[NUMSTATES] =
{SPR_CTRC, FF_FULLBRIGHT|FF_ANIMATE, 8*3, {A_FlameParticle}, 3, 3, S_FIRETORCH}, // S_FIRETORCH {SPR_CTRC, FF_FULLBRIGHT|FF_ANIMATE, 8*3, {A_FlameParticle}, 3, 3, S_FIRETORCH}, // S_FIRETORCH
{SPR_CFLG, 0, -1, {NULL}, 0, 0, S_NULL}, // S_WAVINGFLAG {SPR_CFLG, 0, -1, {NULL}, 0, 0, S_NULL}, // S_WAVINGFLAG
{SPR_CFLG, FF_PAPERSPRITE|1, -1, {NULL}, 0, 0, S_NULL}, // S_WAVINGFLAGSEG {SPR_CFLG, FF_PAPERSPRITE|1, -1, {NULL}, 0, 0, S_NULL}, // S_WAVINGFLAGSEG1
{SPR_CFLG, FF_PAPERSPRITE|2, -1, {NULL}, 0, 0, S_NULL}, // S_WAVINGFLAGSEG2
{SPR_CSTA, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CRAWLASTATUE {SPR_CSTA, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CRAWLASTATUE
@ -7492,7 +7494,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // painstate S_NULL, // painstate
0, // painchance 0, // painchance
sfx_s3k64, // painsound sfx_s3k64, // painsound
S_NULL, // meleestate S_WALLSPIKE4, // meleestate
S_NULL, // missilestate S_NULL, // missilestate
S_WALLSPIKED1, // deathstate S_WALLSPIKED1, // deathstate
S_WALLSPIKED2, // xdeathstate S_WALLSPIKED2, // xdeathstate
@ -11018,7 +11020,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate S_NULL // raisestate
}, },
{ // MT_CEZPOLE { // MT_CEZPOLE1
1117, // doomednum 1117, // doomednum
S_CEZPOLE, // spawnstate S_CEZPOLE, // spawnstate
1000, // spawnhealth 1000, // spawnhealth
@ -11045,9 +11047,63 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate S_NULL // raisestate
}, },
{ // MT_CEZBANNER { // MT_CEZPOLE2
1118, // doomednum
S_CEZPOLE, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
40*FRACUNIT, // radius
224*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags
S_NULL // raisestate
},
{ // MT_CEZBANNER1
-1, // doomednum -1, // doomednum
S_CEZBANNER, // spawnstate S_CEZBANNER1, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
40*FRACUNIT, // radius
224*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags
S_NULL // raisestate
},
{ // MT_CEZBANNER2
-1, // doomednum
S_CEZBANNER2, // spawnstate
1000, // spawnhealth 1000, // spawnhealth
S_NULL, // seestate S_NULL, // seestate
sfx_None, // seesound sfx_None, // seesound
@ -11261,8 +11317,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate S_NULL // raisestate
}, },
{ // MT_WAVINGFLAG { // MT_WAVINGFLAG1
1118, // doomednum 1128, // doomednum
S_WAVINGFLAG, // spawnstate S_WAVINGFLAG, // spawnstate
1000, // spawnhealth 1000, // spawnhealth
S_NULL, // seestate S_NULL, // seestate
@ -11278,8 +11334,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate S_NULL, // xdeathstate
sfx_None, // deathsound sfx_None, // deathsound
0, // speed 0, // speed
4*FRACUNIT, // radius 8*FRACUNIT, // radius
104*FRACUNIT, // height 208*FRACUNIT, // height
0, // display offset 0, // display offset
100, // mass 100, // mass
0, // damage 0, // damage
@ -11288,9 +11344,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate S_NULL // raisestate
}, },
{ // MT_WAVINGFLAGSEG { // MT_WAVINGFLAG2
-1, // doomednum 1129, // doomednum
S_WAVINGFLAGSEG, // spawnstate S_WAVINGFLAG, // spawnstate
1000, // spawnhealth 1000, // spawnhealth
S_NULL, // seestate S_NULL, // seestate
sfx_None, // seesound sfx_None, // seesound
@ -11305,7 +11361,61 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate S_NULL, // xdeathstate
sfx_None, // deathsound sfx_None, // deathsound
0, // speed 0, // speed
4*FRACUNIT, // radius 8*FRACUNIT, // radius
208*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_SOLID, // flags
S_NULL // raisestate
},
{ // MT_WAVINGFLAGSEG1
-1, // doomednum
S_WAVINGFLAGSEG1, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
8*FRACUNIT, // radius
1, // height -- this is not a typo
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags
S_NULL // raisestate
},
{ // MT_WAVINGFLAGSEG2
-1, // doomednum
S_WAVINGFLAGSEG2, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
8*FRACUNIT, // radius
1, // height -- this is not a typo 1, // height -- this is not a typo
0, // display offset 0, // display offset
100, // mass 100, // mass
@ -19642,7 +19752,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // display offset 0, // display offset
100, // mass 100, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_wbreak, // activesound
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_RUNSPAWNFUNC|MF_NOCLIPHEIGHT|MF_SCENERY, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_RUNSPAWNFUNC|MF_NOCLIPHEIGHT|MF_SCENERY, // flags
S_NULL // raisestate S_NULL // raisestate
}, },

View File

@ -2458,7 +2458,8 @@ typedef enum state
S_CEZFLOWER, S_CEZFLOWER,
S_CEZPOLE, S_CEZPOLE,
S_CEZBANNER, S_CEZBANNER1,
S_CEZBANNER2,
S_PINETREE, S_PINETREE,
S_CEZBUSH1, S_CEZBUSH1,
S_CEZBUSH2, S_CEZBUSH2,
@ -2467,7 +2468,8 @@ typedef enum state
S_FLAMEHOLDER, S_FLAMEHOLDER,
S_FIRETORCH, S_FIRETORCH,
S_WAVINGFLAG, S_WAVINGFLAG,
S_WAVINGFLAGSEG, S_WAVINGFLAGSEG1,
S_WAVINGFLAGSEG2,
S_CRAWLASTATUE, S_CRAWLASTATUE,
S_FACESTABBERSTATUE, S_FACESTABBERSTATUE,
S_SUSPICIOUSFACESTABBERSTATUE_WAIT, S_SUSPICIOUSFACESTABBERSTATUE_WAIT,
@ -4295,8 +4297,10 @@ typedef enum mobj_type
MT_SMALLFIREBAR, // Small Firebar MT_SMALLFIREBAR, // Small Firebar
MT_BIGFIREBAR, // Big Firebar MT_BIGFIREBAR, // Big Firebar
MT_CEZFLOWER, // Flower MT_CEZFLOWER, // Flower
MT_CEZPOLE, // Pole MT_CEZPOLE1, // Pole (with red banner)
MT_CEZBANNER, // Banner MT_CEZPOLE2, // Pole (with blue banner)
MT_CEZBANNER1, // Banner (red)
MT_CEZBANNER2, // Banner (blue)
MT_PINETREE, // Pine Tree MT_PINETREE, // Pine Tree
MT_CEZBUSH1, // Bush 1 MT_CEZBUSH1, // Bush 1
MT_CEZBUSH2, // Bush 2 MT_CEZBUSH2, // Bush 2
@ -4304,8 +4308,10 @@ typedef enum mobj_type
MT_CANDLEPRICKET, // Candle pricket MT_CANDLEPRICKET, // Candle pricket
MT_FLAMEHOLDER, // Flame holder MT_FLAMEHOLDER, // Flame holder
MT_FIRETORCH, // Fire torch MT_FIRETORCH, // Fire torch
MT_WAVINGFLAG, // Waving flag MT_WAVINGFLAG1, // Waving flag (red)
MT_WAVINGFLAGSEG, // Waving flag segment MT_WAVINGFLAG2, // Waving flag (blue)
MT_WAVINGFLAGSEG1, // Waving flag segment (red)
MT_WAVINGFLAGSEG2, // Waving flag segment (blue)
MT_CRAWLASTATUE, // Crawla statue MT_CRAWLASTATUE, // Crawla statue
MT_FACESTABBERSTATUE, // Facestabber statue MT_FACESTABBERSTATUE, // Facestabber statue
MT_SUSPICIOUSFACESTABBERSTATUE, // :eggthinking: MT_SUSPICIOUSFACESTABBERSTATUE, // :eggthinking:

View File

@ -539,7 +539,7 @@ static int lib_pSpawnLockOn(lua_State *L)
if (P_IsLocalPlayer(player)) // Only display it on your own view. if (P_IsLocalPlayer(player)) // Only display it on your own view.
{ {
mobj_t *visual = P_SpawnMobj(lockon->x, lockon->y, lockon->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker mobj_t *visual = P_SpawnMobj(lockon->x, lockon->y, lockon->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker
visual->target = lockon; P_SetTarget(&visual->target, lockon);
visual->flags2 |= MF2_DONTDRAW; visual->flags2 |= MF2_DONTDRAW;
P_SetMobjStateNF(visual, state); P_SetMobjStateNF(visual, state);
} }

View File

@ -54,10 +54,12 @@ static UINT8 lib_searchBlockmap_Objects(lua_State *L, INT32 x, INT32 y, mobj_t *
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
lua_pop(gL, 1); lua_pop(gL, 1);
blockfuncerror = true; blockfuncerror = true;
P_SetTarget(&bnext, NULL);
return 0; // *shrugs* return 0; // *shrugs*
} }
if (!lua_isnil(gL, -1)) if (!lua_isnil(gL, -1))
{ // if nil, continue { // if nil, continue
P_SetTarget(&bnext, NULL);
if (lua_toboolean(gL, -1)) if (lua_toboolean(gL, -1))
return 2; // stop whole search return 2; // stop whole search
else else

View File

@ -274,10 +274,19 @@ static int mobj_get(lua_State *L)
// bprev -- same deal as sprev above, but for the blockmap. // bprev -- same deal as sprev above, but for the blockmap.
return UNIMPLEMENTED; return UNIMPLEMENTED;
case mobj_hnext: case mobj_hnext:
if (mo->hnext && P_MobjWasRemoved(mo->hnext))
{ // don't put invalid mobj back into Lua.
P_SetTarget(&mo->hnext, NULL);
return 0;
}
LUA_PushUserdata(L, mo->hnext, META_MOBJ); LUA_PushUserdata(L, mo->hnext, META_MOBJ);
break; break;
case mobj_hprev: case mobj_hprev:
// implimented differently from sprev and bprev because SSNTails. if (mo->hprev && P_MobjWasRemoved(mo->hprev))
{ // don't put invalid mobj back into Lua.
P_SetTarget(&mo->hprev, NULL);
return 0;
}
LUA_PushUserdata(L, mo->hprev, META_MOBJ); LUA_PushUserdata(L, mo->hprev, META_MOBJ);
break; break;
case mobj_type: case mobj_type:

View File

@ -476,7 +476,12 @@ static int player_set(lua_State *L)
else if (fastcmp(field,"followitem")) else if (fastcmp(field,"followitem"))
plr->followitem = luaL_checkinteger(L, 3); plr->followitem = luaL_checkinteger(L, 3);
else if (fastcmp(field,"followmobj")) else if (fastcmp(field,"followmobj"))
P_SetTarget(&plr->followmobj, *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ))); {
mobj_t *mo = NULL;
if (!lua_isnil(L, 3))
mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
P_SetTarget(&plr->followmobj, mo);
}
else if (fastcmp(field,"actionspd")) else if (fastcmp(field,"actionspd"))
plr->actionspd = (INT32)luaL_checkinteger(L, 3); plr->actionspd = (INT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"mindash")) else if (fastcmp(field,"mindash"))
@ -560,9 +565,19 @@ static int player_set(lua_State *L)
else if (fastcmp(field,"old_angle_pos")) else if (fastcmp(field,"old_angle_pos"))
plr->old_angle_pos = luaL_checkangle(L, 3); plr->old_angle_pos = luaL_checkangle(L, 3);
else if (fastcmp(field,"axis1")) else if (fastcmp(field,"axis1"))
P_SetTarget(&plr->axis1, *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ))); {
mobj_t *mo = NULL;
if (!lua_isnil(L, 3))
mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
P_SetTarget(&plr->axis1, mo);
}
else if (fastcmp(field,"axis2")) else if (fastcmp(field,"axis2"))
P_SetTarget(&plr->axis2, *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ))); {
mobj_t *mo = NULL;
if (!lua_isnil(L, 3))
mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
P_SetTarget(&plr->axis2, mo);
}
else if (fastcmp(field,"bumpertime")) else if (fastcmp(field,"bumpertime"))
plr->bumpertime = (tic_t)luaL_checkinteger(L, 3); plr->bumpertime = (tic_t)luaL_checkinteger(L, 3);
else if (fastcmp(field,"flyangle")) else if (fastcmp(field,"flyangle"))

View File

@ -1127,14 +1127,15 @@ void LUA_Archive(void)
ArchiveExtVars(&players[i], "player"); ArchiveExtVars(&players[i], "player");
} }
for (i = 0; i < NUM_THINKERLISTS; i++) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
for (th = thlist[i].next; th != &thlist[i]; th = th->next) {
if (th->function.acp1 == (actionf_p1)P_MobjThinker) if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
{ continue;
// archive function will determine when to skip mobjs,
// and write mobjnum in otherwise. // archive function will determine when to skip mobjs,
ArchiveExtVars(th, "mobj"); // and write mobjnum in otherwise.
} ArchiveExtVars(th, "mobj");
}
WRITEUINT32(save_p, UINT32_MAX); // end of mobjs marker, replaces mobjnum. WRITEUINT32(save_p, UINT32_MAX); // end of mobjs marker, replaces mobjnum.
@ -1163,11 +1164,14 @@ void LUA_UnArchive(void)
do { do {
mobjnum = READUINT32(save_p); // read a mobjnum mobjnum = READUINT32(save_p); // read a mobjnum
for (i = 0; i < NUM_THINKERLISTS; i++) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
for (th = thlist[i].next; th != &thlist[i]; th = th->next) {
if (th->function.acp1 == (actionf_p1)P_MobjThinker if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
&& ((mobj_t *)th)->mobjnum == mobjnum) // find matching mobj continue;
UnArchiveExtVars(th); // apply variables if (((mobj_t *)th)->mobjnum != mobjnum) // find matching mobj
continue;
UnArchiveExtVars(th); // apply variables
}
} while(mobjnum != UINT32_MAX); // repeat until end of mobjs marker. } while(mobjnum != UINT32_MAX); // repeat until end of mobjs marker.
LUAh_NetArchiveHook(NetUnArchive); // call the NetArchive hook in unarchive mode LUAh_NetArchiveHook(NetUnArchive); // call the NetArchive hook in unarchive mode

View File

@ -579,6 +579,9 @@ void Command_Teleport_f(void)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2->type != MT_STARPOST) if (mo2->type != MT_STARPOST)
@ -1068,10 +1071,14 @@ static mapthing_t *OP_CreateNewMapThing(player_t *player, UINT16 type, boolean c
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo = (mobj_t *)th; mo = (mobj_t *)th;
// get offset from mt, which points to old mapthings, then add new location // get offset from mt, which points to old mapthings, then add new location
if (mo->spawnpoint) if (!mo->spawnpoint)
mo->spawnpoint = (mo->spawnpoint - mt) + mapthings; continue;
mo->spawnpoint = (mo->spawnpoint - mt) + mapthings;
} }
} }

View File

@ -2289,23 +2289,26 @@ static boolean MIT_SetCurBackground(UINT32 menutype, INT32 level, INT32 *retval,
(void)retval; (void)retval;
(void)fromoldest; (void)fromoldest;
if (!menutype) // if there's nothing in this level, do nothing
return false;
if (menupres[menutype].bgcolor >= 0) if (menupres[menutype].bgcolor >= 0)
{ {
curbgcolor = menupres[menutype].bgcolor; curbgcolor = menupres[menutype].bgcolor;
return true; return true;
} }
else if (menupres[menutype].bgname[0] && (!menupres[menutype].bghide || !titlemapinaction)) else if (menupres[menutype].bghide && titlemapinaction) // hide the background
{
curbghide = true;
return true;
}
else if (menupres[menutype].bgname[0])
{ {
strncpy(curbgname, menupres[menutype].bgname, 8); strncpy(curbgname, menupres[menutype].bgname, 8);
curbgxspeed = menupres[menutype].titlescrollxspeed != INT32_MAX ? menupres[menutype].titlescrollxspeed : titlescrollxspeed; curbgxspeed = menupres[menutype].titlescrollxspeed != INT32_MAX ? menupres[menutype].titlescrollxspeed : titlescrollxspeed;
curbgyspeed = menupres[menutype].titlescrollyspeed != INT32_MAX ? menupres[menutype].titlescrollyspeed : titlescrollyspeed; curbgyspeed = menupres[menutype].titlescrollyspeed != INT32_MAX ? menupres[menutype].titlescrollyspeed : titlescrollyspeed;
return true; return true;
} }
else if (menupres[menutype].bghide && titlemapinaction) // hide the background
{
curbghide = true;
return true;
}
else if (!level) else if (!level)
{ {
if (M_GetYoungestChildMenu() == MN_SP_PLAYER || !defaultname || !defaultname[0]) if (M_GetYoungestChildMenu() == MN_SP_PLAYER || !defaultname || !defaultname[0])
@ -2329,6 +2332,9 @@ static boolean MIT_ChangeMusic(UINT32 menutype, INT32 level, INT32 *retval, void
(void)retval; (void)retval;
(void)fromoldest; (void)fromoldest;
if (!menutype) // if there's nothing in this level, do nothing
return false;
if (menupres[menutype].musname[0]) if (menupres[menutype].musname[0])
{ {
S_ChangeMusic(menupres[menutype].musname, menupres[menutype].mustrack, menupres[menutype].muslooping); S_ChangeMusic(menupres[menutype].musname, menupres[menutype].mustrack, menupres[menutype].muslooping);
@ -2353,6 +2359,9 @@ static boolean MIT_SetCurFadeValue(UINT32 menutype, INT32 level, INT32 *retval,
(void)retval; (void)retval;
(void)fromoldest; (void)fromoldest;
if (!menutype) // if there's nothing in this level, do nothing
return false;
if (menupres[menutype].fadestrength >= 0) if (menupres[menutype].fadestrength >= 0)
{ {
curfadevalue = (menupres[menutype].fadestrength % 32); curfadevalue = (menupres[menutype].fadestrength % 32);
@ -2369,6 +2378,9 @@ static boolean MIT_SetCurHideTitlePics(UINT32 menutype, INT32 level, INT32 *retv
(void)retval; (void)retval;
(void)fromoldest; (void)fromoldest;
if (!menutype) // if there's nothing in this level, do nothing
return false;
if (menupres[menutype].hidetitlepics >= 0) if (menupres[menutype].hidetitlepics >= 0)
{ {
curhidepics = menupres[menutype].hidetitlepics; curhidepics = menupres[menutype].hidetitlepics;
@ -2470,7 +2482,7 @@ static void M_HandleMenuPresState(menu_t *newMenu)
curbgcolor = -1; curbgcolor = -1;
curbgxspeed = (gamestate == GS_TIMEATTACK) ? 0 : titlescrollxspeed; curbgxspeed = (gamestate == GS_TIMEATTACK) ? 0 : titlescrollxspeed;
curbgyspeed = (gamestate == GS_TIMEATTACK) ? 18 : titlescrollyspeed; curbgyspeed = (gamestate == GS_TIMEATTACK) ? 18 : titlescrollyspeed;
curbghide = (gamestate == GS_TIMEATTACK) ? false : true; curbghide = (gamestate != GS_TIMEATTACK); // show in time attack, hide in other menus
// don't do the below during the in-game menus // don't do the below during the in-game menus
if (gamestate != GS_TITLESCREEN && gamestate != GS_TIMEATTACK) if (gamestate != GS_TITLESCREEN && gamestate != GS_TIMEATTACK)
@ -5054,6 +5066,14 @@ static void M_DrawLevelPlatterMenu(void)
F_SkyScroll(curbgxspeed, curbgyspeed, curbgname); F_SkyScroll(curbgxspeed, curbgyspeed, curbgname);
if (curfadevalue) if (curfadevalue)
V_DrawFadeScreen(0xFF00, curfadevalue); V_DrawFadeScreen(0xFF00, curfadevalue);
// Draw and animate foreground
if (!curbghide || !titlemapinaction)
{
V_DrawSciencePatch(0, -(130<<FRACBITS) + FixedMul(130<<FRACBITS, FixedDiv(recfgtimer%70, 70)), V_SNAPTOTOP|V_SNAPTOLEFT, W_CachePatchName("RECATFG", PU_CACHE), FRACUNIT);
V_DrawSciencePatch(320<<FRACBITS, -(130<<FRACBITS) + FixedMul(130<<FRACBITS, FixedDiv(recfgtimer%70, 70)), V_SNAPTOTOP|V_SNAPTORIGHT|V_FLIP, W_CachePatchName("RECATFG", PU_CACHE), FRACUNIT);
recfgtimer++;
}
} }
// finds row at top of the screen // finds row at top of the screen
@ -8061,7 +8081,6 @@ void M_DrawTimeAttackMenu(void)
INT32 i, x, y, cursory = 0; INT32 i, x, y, cursory = 0;
UINT16 dispstatus; UINT16 dispstatus;
patch_t *PictureOfUrFace; patch_t *PictureOfUrFace;
patch_t *menufg;
curbgxspeed = 0; curbgxspeed = 0;
curbgyspeed = 18; curbgyspeed = 18;
@ -8069,7 +8088,6 @@ void M_DrawTimeAttackMenu(void)
strncpy(curbgname, "RECATTBG", 8); strncpy(curbgname, "RECATTBG", 8);
M_ChangeMenuMusic("_inter", true); // Eww, but needed for when user hits escape during demo playback M_ChangeMenuMusic("_inter", true); // Eww, but needed for when user hits escape during demo playback
menufg = W_CachePatchName("RECATFG", PU_CACHE);
if (curbgcolor >= 0) if (curbgcolor >= 0)
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor); V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor);
@ -8079,11 +8097,12 @@ void M_DrawTimeAttackMenu(void)
V_DrawFadeScreen(0xFF00, curfadevalue); V_DrawFadeScreen(0xFF00, curfadevalue);
// Draw and animate foreground // Draw and animate foreground
V_DrawSciencePatch(0, -(130<<FRACBITS) + FixedMul(130<<FRACBITS, FixedDiv(recfgtimer%70, 70)), V_SNAPTOTOP|V_SNAPTOLEFT, menufg, FRACUNIT); if (!curbghide || !titlemapinaction)
V_DrawSciencePatch(320<<FRACBITS, -(130<<FRACBITS) + FixedMul(130<<FRACBITS, FixedDiv(recfgtimer%70, 70)), V_SNAPTOTOP|V_SNAPTORIGHT|V_FLIP, menufg, FRACUNIT); {
recfgtimer++; V_DrawSciencePatch(0, -(130<<FRACBITS) + FixedMul(130<<FRACBITS, FixedDiv(recfgtimer%70, 70)), V_SNAPTOTOP|V_SNAPTOLEFT, W_CachePatchName("RECATFG", PU_CACHE), FRACUNIT);
CONS_Printf("%d\n", recfgtimer); V_DrawSciencePatch(320<<FRACBITS, -(130<<FRACBITS) + FixedMul(130<<FRACBITS, FixedDiv(recfgtimer%70, 70)), V_SNAPTOTOP|V_SNAPTORIGHT|V_FLIP, W_CachePatchName("RECATFG", PU_CACHE), FRACUNIT);
recfgtimer++;
}
M_DrawMenuTitle(); M_DrawMenuTitle();
// draw menu (everything else goes on top of it) // draw menu (everything else goes on top of it)
@ -8256,6 +8275,7 @@ static void M_TimeAttack(INT32 choice)
M_PatchSkinNameTable(); M_PatchSkinNameTable();
G_SetGamestate(GS_TIMEATTACK); // do this before M_SetupNextMenu so that menu meta state knows that we're switching G_SetGamestate(GS_TIMEATTACK); // do this before M_SetupNextMenu so that menu meta state knows that we're switching
titlemapinaction = TITLEMAP_OFF; // Nope don't give us HOMs please
M_SetupNextMenu(&SP_TimeAttackDef); M_SetupNextMenu(&SP_TimeAttackDef);
if (!M_CanShowLevelInList(cv_nextmap.value-1, -1) && levelselect.rows[0].maplist[0]) if (!M_CanShowLevelInList(cv_nextmap.value-1, -1) && levelselect.rows[0].maplist[0])
CV_SetValue(&cv_nextmap, levelselect.rows[0].maplist[0]); CV_SetValue(&cv_nextmap, levelselect.rows[0].maplist[0]);
@ -8437,6 +8457,7 @@ static void M_NightsAttack(INT32 choice)
G_SetGamestate(GS_TIMEATTACK); // do this before M_SetupNextMenu so that menu meta state knows that we're switching G_SetGamestate(GS_TIMEATTACK); // do this before M_SetupNextMenu so that menu meta state knows that we're switching
M_SetupNextMenu(&SP_NightsAttackDef); M_SetupNextMenu(&SP_NightsAttackDef);
titlemapinaction = TITLEMAP_OFF; // Nope don't give us HOMs please
if (!M_CanShowLevelInList(cv_nextmap.value-1, -1) && levelselect.rows[0].maplist[0]) if (!M_CanShowLevelInList(cv_nextmap.value-1, -1) && levelselect.rows[0].maplist[0])
CV_SetValue(&cv_nextmap, levelselect.rows[0].maplist[0]); CV_SetValue(&cv_nextmap, levelselect.rows[0].maplist[0]);
else else

View File

@ -1391,7 +1391,7 @@ void A_StatueBurst(mobj_t *actor)
return; return;
new->angle = actor->angle; new->angle = actor->angle;
new->target = actor->target; P_SetTarget(&new->target, actor->target);
if (locvar2) if (locvar2)
P_SetMobjState(new, (statenum_t)locvar2); P_SetMobjState(new, (statenum_t)locvar2);
S_StartSound(new, new->info->attacksound); S_StartSound(new, new->info->attacksound);
@ -2155,7 +2155,7 @@ void A_CrushclawLaunch(mobj_t *actor)
for (i = 0; (i < CSEGS); i++) for (i = 0; (i < CSEGS); i++)
{ {
mobj_t *newchain = P_SpawnMobjFromMobj(actor, 0, 0, 0, actor->info->raisestate); mobj_t *newchain = P_SpawnMobjFromMobj(actor, 0, 0, 0, actor->info->raisestate);
prevchain->target = newchain; P_SetTarget(&prevchain->target, newchain);
prevchain = newchain; prevchain = newchain;
} }
actor->target->angle = R_PointToAngle2(actor->target->x, actor->target->y, crab->target->x, crab->target->y); actor->target->angle = R_PointToAngle2(actor->target->x, actor->target->y, crab->target->x, crab->target->y);
@ -3088,7 +3088,7 @@ void A_Boss1Laser(mobj_t *actor)
if (z - floorz < mobjinfo[MT_EGGMOBILE_FIRE].height>>1) if (z - floorz < mobjinfo[MT_EGGMOBILE_FIRE].height>>1)
{ {
point = P_SpawnMobj(x, y, floorz+1, MT_EGGMOBILE_FIRE); point = P_SpawnMobj(x, y, floorz+1, MT_EGGMOBILE_FIRE);
point->target = actor; P_SetTarget(&point->target, actor);
point->destscale = 3*FRACUNIT; point->destscale = 3*FRACUNIT;
point->scalespeed = FRACUNIT>>2; point->scalespeed = FRACUNIT>>2;
point->fuse = TICRATE; point->fuse = TICRATE;
@ -3488,9 +3488,11 @@ void A_1upThinker(mobj_t *actor)
if (closestplayer == -1 || skins[players[closestplayer].skin].sprites[SPR2_LIFE].numframes == 0) if (closestplayer == -1 || skins[players[closestplayer].skin].sprites[SPR2_LIFE].numframes == 0)
{ // Closest player not found (no players in game?? may be empty dedicated server!), or does not have correct sprite. { // Closest player not found (no players in game?? may be empty dedicated server!), or does not have correct sprite.
if (actor->tracer) { if (actor->tracer)
P_RemoveMobj(actor->tracer); {
actor->tracer = NULL; mobj_t *tracer = actor->tracer;
P_SetTarget(&actor->tracer, NULL);
P_RemoveMobj(tracer);
} }
return; return;
} }
@ -3786,6 +3788,9 @@ void A_BossDeath(mobj_t *mo)
// if all bosses are dead // if all bosses are dead
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2 != mo && (mo2->flags & MF_BOSS) && mo2->health > 0) if (mo2 != mo && (mo2->flags & MF_BOSS) && mo2->health > 0)
goto bossjustdie; // other boss not dead - just go straight to dying! goto bossjustdie; // other boss not dead - just go straight to dying!
@ -3884,6 +3889,9 @@ bossjustdie:
// scan the thinkers to find the runaway point // scan the thinkers to find the runaway point
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2->type != MT_BOSSFLYPOINT) if (mo2->type != MT_BOSSFLYPOINT)
@ -6137,6 +6145,9 @@ void A_RingExplode(mobj_t *actor)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2 == actor) // Don't explode yourself! Endless loop! if (mo2 == actor) // Don't explode yourself! Endless loop!
@ -7263,7 +7274,7 @@ void A_Boss2PogoTarget(mobj_t *actor)
if (actor->info->missilestate) // spawn the pogo stick collision box if (actor->info->missilestate) // spawn the pogo stick collision box
{ {
mobj_t *pogo = P_SpawnMobj(actor->x, actor->y, actor->z - mobjinfo[actor->info->missilestate].height, (mobjtype_t)actor->info->missilestate); mobj_t *pogo = P_SpawnMobj(actor->x, actor->y, actor->z - mobjinfo[actor->info->missilestate].height, (mobjtype_t)actor->info->missilestate);
pogo->target = actor; P_SetTarget(&pogo->target, actor);
} }
actor->reactiontime = 1; actor->reactiontime = 1;
@ -7835,6 +7846,9 @@ void A_Boss3Path(mobj_t *actor)
// the number // the number
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2->type != MT_BOSS3WAYPOINT) if (mo2->type != MT_BOSS3WAYPOINT)
continue; continue;
@ -8227,6 +8241,9 @@ void A_FindTarget(mobj_t *actor)
// scan the thinkers // scan the thinkers
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2->type == (mobjtype_t)locvar1) if (mo2->type == (mobjtype_t)locvar1)
@ -8289,6 +8306,9 @@ void A_FindTracer(mobj_t *actor)
// scan the thinkers // scan the thinkers
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2->type == (mobjtype_t)locvar1) if (mo2->type == (mobjtype_t)locvar1)
@ -8873,6 +8893,9 @@ void A_RemoteAction(mobj_t *actor)
// scan the thinkers // scan the thinkers
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2->type == (mobjtype_t)locvar1) if (mo2->type == (mobjtype_t)locvar1)
@ -9136,6 +9159,9 @@ void A_SetObjectTypeState(mobj_t *actor)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2->type == (mobjtype_t)loc2lw) if (mo2->type == (mobjtype_t)loc2lw)
@ -9771,6 +9797,9 @@ void A_CheckThingCount(mobj_t *actor)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2->type == (mobjtype_t)loc1up) if (mo2->type == (mobjtype_t)loc1up)
@ -13061,9 +13090,10 @@ static boolean PIT_TNTExplode(mobj_t *nearby)
if (barrel->target == nearby) if (barrel->target == nearby)
{ {
mobj_t *tar = barrel->target; // temporarily store barrel's target mobj_t *tar = barrel->target; // temporarily store barrel's target
barrel->target = NULL; P_SetTarget(&barrel->target, NULL);
P_DamageMobj(nearby, barrel, NULL, 1, 0); P_DamageMobj(nearby, barrel, NULL, 1, 0);
barrel->target = tar; if (!P_MobjWasRemoved(barrel))
P_SetTarget(&barrel->target, tar);
} }
else else
{ {
@ -13565,7 +13595,7 @@ void A_SaloonDoorSpawn(mobj_t *actor)
door->extravalue2 = 0; door->extravalue2 = 0;
// Origin door // Origin door
door->tracer = actor; P_SetTarget(&door->tracer, actor);
//Back //Back
door = P_SpawnMobj(x - c*d, y - s*d, z, MT_SALOONDOOR); door = P_SpawnMobj(x - c*d, y - s*d, z, MT_SALOONDOOR);
@ -13578,7 +13608,7 @@ void A_SaloonDoorSpawn(mobj_t *actor)
door->extravalue2 = 0; door->extravalue2 = 0;
// Origin door // Origin door
door->tracer = actor; P_SetTarget(&door->tracer, actor);
} }
// Function: A_MinecartSparkThink // Function: A_MinecartSparkThink

View File

@ -1975,22 +1975,27 @@ void T_ThwompSector(levelspecthink_t *thwomp)
} }
else // Not going anywhere, so look for players. else // Not going anywhere, so look for players.
{ {
thinker_t *th;
mobj_t *mo;
if (!rover || (rover->flags & FF_EXISTS)) if (!rover || (rover->flags & FF_EXISTS))
{ {
// scan the thinkers to find players! UINT8 i;
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) // scan the players to find victims!
for (i = 0; i < MAXPLAYERS; i++)
{ {
mo = (mobj_t *)th; if (!playeringame[i])
if (mo->type == MT_PLAYER && mo->health && mo->player && !mo->player->spectator continue;
&& mo->z <= thwomp->sector->ceilingheight if (players[i].spectator)
&& P_AproxDistance(thwompx - mo->x, thwompy - mo->y) <= 96*FRACUNIT) continue;
{ if (!players[i].mo)
thwomp->direction = -1; continue;
break; if (!players[i].mo->health)
} continue;
if (players[i].mo->z > thwomp->sector->ceilingheight)
continue;
if (P_AproxDistance(thwompx - players[i].mo->x, thwompy - players[i].mo->y) > 96 * FRACUNIT)
continue;
thwomp->direction = -1;
break;
} }
} }

View File

@ -99,6 +99,9 @@ void P_ClearStarPost(INT32 postnum)
// scan the thinkers // scan the thinkers
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2->type != MT_STARPOST) if (mo2->type != MT_STARPOST)
@ -125,10 +128,15 @@ void P_ResetStarposts(void)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
post = (mobj_t *)th; post = (mobj_t *)th;
if (post->type == MT_STARPOST) if (post->type != MT_STARPOST)
P_SetMobjState(post, post->info->spawnstate); continue;
P_SetMobjState(post, post->info->spawnstate);
} }
} }
@ -828,19 +836,22 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
// scan the thinkers to find the corresponding anchorpoint // scan the thinkers to find the corresponding anchorpoint
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2->type == MT_IDEYAANCHOR) if (mo2->type != MT_IDEYAANCHOR)
{ continue;
if (mo2->health == toucher->tracer->health) // do ideya numberes match?
anchorpoint = mo2;
else if (toucher->tracer->hnext && mo2->health == toucher->tracer->hnext->health)
anchorpoint2 = mo2;
if ((!toucher->tracer->hnext && anchorpoint) if (mo2->health == toucher->tracer->health) // do ideya numberes match?
|| (toucher->tracer->hnext && anchorpoint && anchorpoint2)) anchorpoint = mo2;
break; else if (toucher->tracer->hnext && mo2->health == toucher->tracer->hnext->health)
} anchorpoint2 = mo2;
if ((!toucher->tracer->hnext && anchorpoint)
|| (toucher->tracer->hnext && anchorpoint && anchorpoint2))
break;
} }
if (anchorpoint) if (anchorpoint)
@ -919,6 +930,9 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
// scan the remaining thinkers // scan the remaining thinkers
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2 == special) if (mo2 == special)
@ -966,6 +980,9 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
// in from the paraloop. Isn't this just so efficient? // in from the paraloop. Isn't this just so efficient?
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (P_AproxDistance(P_AproxDistance(mo2->x - x, mo2->y - y), mo2->z - z) > gatherradius) if (P_AproxDistance(P_AproxDistance(mo2->x - x, mo2->y - y), mo2->z - z) > gatherradius)
@ -1337,6 +1354,9 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
// scan the remaining thinkers to find koopa // scan the remaining thinkers to find koopa
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2->type != MT_KOOPA) if (mo2->type != MT_KOOPA)
@ -1434,6 +1454,9 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2->type != MT_STARPOST) if (mo2->type != MT_STARPOST)
@ -2572,9 +2595,11 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
UINT32 i = 0; // to check how many clones we've removed UINT32 i = 0; // to check how many clones we've removed
// scan the thinkers to make sure all the old pinch dummies are gone on death // scan the thinkers to make sure all the old pinch dummies are gone on death
// this can happen if the boss was hurt earlier than expected
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo = (mobj_t *)th; mo = (mobj_t *)th;
if (mo->type != (mobjtype_t)target->info->mass) if (mo->type != (mobjtype_t)target->info->mass)
continue; continue;

View File

@ -61,8 +61,8 @@
#define P_GetPlayerHeight(player) FixedMul(player->height, player->mo->scale) #define P_GetPlayerHeight(player) FixedMul(player->height, player->mo->scale)
#define P_GetPlayerSpinHeight(player) FixedMul(player->spinheight, player->mo->scale) #define P_GetPlayerSpinHeight(player) FixedMul(player->spinheight, player->mo->scale)
typedef enum{ typedef enum
THINK_LIMBO, {
THINK_POLYOBJ, THINK_POLYOBJ,
THINK_MAIN, THINK_MAIN,
THINK_MOBJ, THINK_MOBJ,

View File

@ -1093,7 +1093,10 @@ boolean P_BlockThingsIterator(INT32 x, INT32 y, boolean (*func)(mobj_t *))
{ {
P_SetTarget(&bnext, mobj->bnext); // We want to note our reference to bnext here incase it is MF_NOTHINK and gets removed! P_SetTarget(&bnext, mobj->bnext); // We want to note our reference to bnext here incase it is MF_NOTHINK and gets removed!
if (!func(mobj)) if (!func(mobj))
{
P_SetTarget(&bnext, NULL);
return false; return false;
}
if (P_MobjWasRemoved(tmthing) // func just popped our tmthing, cannot continue. if (P_MobjWasRemoved(tmthing) // func just popped our tmthing, cannot continue.
|| (bnext && P_MobjWasRemoved(bnext))) // func just broke blockmap chain, cannot continue. || (bnext && P_MobjWasRemoved(bnext))) // func just broke blockmap chain, cannot continue.
{ {

View File

@ -716,6 +716,9 @@ void P_EmeraldManager(void)
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next)
{ {
if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo = (mobj_t *)think; mo = (mobj_t *)think;
if (mo->type == MT_EMERALDSPAWN) if (mo->type == MT_EMERALDSPAWN)
@ -3694,6 +3697,9 @@ void P_DestroyRobots(void)
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next)
{ {
if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo = (mobj_t *)think; mo = (mobj_t *)think;
if (mo->health <= 0 || !(mo->flags & (MF_ENEMY|MF_BOSS))) if (mo->health <= 0 || !(mo->flags & (MF_ENEMY|MF_BOSS)))
continue; // not a valid enemy continue; // not a valid enemy
@ -4426,6 +4432,9 @@ static void P_Boss3Thinker(mobj_t *mobj)
// this can happen if the boss was hurt earlier than expected // this can happen if the boss was hurt earlier than expected
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2->type != (mobjtype_t)mobj->info->mass) if (mo2->type != (mobjtype_t)mobj->info->mass)
continue; continue;
@ -4524,6 +4533,9 @@ static void P_Boss3Thinker(mobj_t *mobj)
// the number // the number
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2->type != MT_BOSS3WAYPOINT) if (mo2->type != MT_BOSS3WAYPOINT)
continue; continue;
@ -4662,7 +4674,7 @@ static void P_Boss4PinchSpikeballs(mobj_t *mobj, angle_t angle, fixed_t dz)
} }
dz /= 9; dz /= 9;
while ((base = base->tracer)) // there are 10 per spoke, remember that while ((base = base->tracer)) // there are 10 per spoke, remember that
{ {
dx = (originx + P_ReturnThrustX(mobj, angle, (9*132)<<FRACBITS) - mobj->x)/9; dx = (originx + P_ReturnThrustX(mobj, angle, (9*132)<<FRACBITS) - mobj->x)/9;
@ -4832,8 +4844,8 @@ static void P_Boss4Thinker(mobj_t *mobj)
P_SetTarget(&seg->target, mobj); P_SetTarget(&seg->target, mobj);
for (i = 0; i < 9; i++) for (i = 0; i < 9; i++)
{ {
seg->hnext = P_SpawnMobj(mobj->x, mobj->y, z, MT_EGGMOBILE4_MACE); P_SetTarget(&seg->hnext, P_SpawnMobj(mobj->x, mobj->y, z, MT_EGGMOBILE4_MACE));
seg->hnext->hprev = seg; P_SetTarget(&seg->hnext->hprev, seg);
seg = seg->hnext; seg = seg->hnext;
} }
} }
@ -5245,6 +5257,9 @@ static void P_Boss7Thinker(mobj_t *mobj)
// Find waypoint he is closest to // Find waypoint he is closest to
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2->type == MT_BOSS3WAYPOINT && mo2->spawnpoint) if (mo2->type == MT_BOSS3WAYPOINT && mo2->spawnpoint)
{ {
@ -5297,6 +5312,9 @@ static void P_Boss7Thinker(mobj_t *mobj)
// the waypoint to use // the waypoint to use
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2->type == MT_BOSS3WAYPOINT && mo2->spawnpoint && (mo2->spawnpoint->options & 7) == waypointNum) if (mo2->type == MT_BOSS3WAYPOINT && mo2->spawnpoint && (mo2->spawnpoint->options & 7) == waypointNum)
{ {
@ -5427,14 +5445,17 @@ static void P_Boss9Thinker(mobj_t *mobj)
// Build a hoop linked list of 'em! // Build a hoop linked list of 'em!
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2->type == MT_BOSS9GATHERPOINT) if (mo2->type == MT_BOSS9GATHERPOINT)
{ {
if (last) if (last)
last->hnext = mo2; P_SetTarget(&last->hnext, mo2);
else else
mobj->hnext = mo2; P_SetTarget(&mobj->hnext, mo2);
mo2->hprev = last; P_SetTarget(&mo2->hprev, last);
last = mo2; last = mo2;
} }
} }
@ -6072,6 +6093,9 @@ mobj_t *P_GetClosestAxis(mobj_t *source)
// scan the thinkers to find the closest axis point // scan the thinkers to find the closest axis point
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2->type == MT_AXIS) if (mo2->type == MT_AXIS)
@ -6841,12 +6865,14 @@ static void P_RemoveOverlay(mobj_t *thing)
{ {
mobj_t *mo; mobj_t *mo;
for (mo = overlaycap; mo; mo = mo->hnext) for (mo = overlaycap; mo; mo = mo->hnext)
if (mo->hnext == thing) {
{ if (mo->hnext != thing)
P_SetTarget(&mo->hnext, thing->hnext); continue;
P_SetTarget(&thing->hnext, NULL);
return; P_SetTarget(&mo->hnext, thing->hnext);
} P_SetTarget(&thing->hnext, NULL);
return;
}
} }
void A_BossDeath(mobj_t *mo); void A_BossDeath(mobj_t *mo);
@ -8046,7 +8072,8 @@ void P_MobjThinker(mobj_t *mobj)
mobj->tracer->z += mobj->height; mobj->tracer->z += mobj->height;
} }
break; break;
case MT_WAVINGFLAG: case MT_WAVINGFLAG1:
case MT_WAVINGFLAG2:
{ {
fixed_t base = (leveltime<<(FRACBITS+1)); fixed_t base = (leveltime<<(FRACBITS+1));
mobj_t *seg = mobj->tracer, *prev = mobj; mobj_t *seg = mobj->tracer, *prev = mobj;
@ -9649,15 +9676,14 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
case MT_BIGMINE: case MT_BIGMINE:
mobj->extravalue1 = FixedHypot(mobj->x, mobj->y)>>FRACBITS; mobj->extravalue1 = FixedHypot(mobj->x, mobj->y)>>FRACBITS;
break; break;
case MT_WAVINGFLAG: case MT_WAVINGFLAG1:
case MT_WAVINGFLAG2:
{ {
mobj_t *prev = mobj, *cur; mobj_t *prev = mobj, *cur;
UINT8 i; UINT8 i;
mobj->destscale <<= 2;
P_SetScale(mobj, mobj->destscale);
for (i = 0; i <= 16; i++) // probably should be < but staying authentic to the Lua version for (i = 0; i <= 16; i++) // probably should be < but staying authentic to the Lua version
{ {
cur = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_WAVINGFLAGSEG); cur = P_SpawnMobjFromMobj(mobj, 0, 0, 0, ((mobj->type == MT_WAVINGFLAG1) ? MT_WAVINGFLAGSEG1 : MT_WAVINGFLAGSEG2));;
P_SetTarget(&prev->tracer, cur); P_SetTarget(&prev->tracer, cur);
cur->extravalue1 = i; cur->extravalue1 = i;
prev = cur; prev = cur;
@ -9751,7 +9777,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
mobj->momx = 1; //stack hack mobj->momx = 1; //stack hack
break; break;
case MT_MINECARTEND: case MT_MINECARTEND:
mobj->tracer = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_MINECARTENDSOLID); P_SetTarget(&mobj->tracer, P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_MINECARTENDSOLID));
mobj->tracer->angle = mobj->angle + ANGLE_90; mobj->tracer->angle = mobj->angle + ANGLE_90;
break; break;
default: default:
@ -9960,37 +9986,28 @@ void P_RemoveMobj(mobj_t *mobj)
P_SetTarget(&mobj->hnext, P_SetTarget(&mobj->hprev, NULL)); P_SetTarget(&mobj->hnext, P_SetTarget(&mobj->hprev, NULL));
// free block
// DBG: set everything in mobj_t to 0xFF instead of leaving it. debug memory error. // DBG: set everything in mobj_t to 0xFF instead of leaving it. debug memory error.
if (mobj->flags & MF_NOTHINK && !mobj->thinker.next) #ifdef SCRAMBLE_REMOVED
// Invalidate mobj_t data to cause crashes if accessed!
memset((UINT8 *)mobj + sizeof(thinker_t), 0xff, sizeof(mobj_t) - sizeof(thinker_t));
#endif
// free block
if (!mobj->thinker.next)
{ // Uh-oh, the mobj doesn't think, P_RemoveThinker would never go through! { // Uh-oh, the mobj doesn't think, P_RemoveThinker would never go through!
INT32 prevreferences;
if (!mobj->thinker.references) if (!mobj->thinker.references)
{ {
#ifdef SCRAMBLE_REMOVED Z_Free(mobj); // No refrrences? Can be removed immediately! :D
// Invalidate mobj_t data to cause crashes if accessed! return;
memset(mobj, 0xff, sizeof(mobj_t));
#endif
Z_Free(mobj); // No refrences? Can be removed immediately! :D
}
else
{ // Add thinker just to delay removing it until refrences are gone.
mobj->flags &= ~MF_NOTHINK;
P_AddThinker(THINK_MOBJ, (thinker_t *)mobj);
#ifdef SCRAMBLE_REMOVED
// Invalidate mobj_t data to cause crashes if accessed!
memset((UINT8 *)mobj + sizeof(thinker_t), 0xff, sizeof(mobj_t) - sizeof(thinker_t));
#endif
P_RemoveThinker((thinker_t *)mobj);
} }
prevreferences = mobj->thinker.references;
P_AddThinker(THINK_MOBJ, (thinker_t *)mobj);
mobj->thinker.references = prevreferences;
} }
else
{ P_RemoveThinker((thinker_t *)mobj);
#ifdef SCRAMBLE_REMOVED
// Invalidate mobj_t data to cause crashes if accessed!
memset((UINT8 *)mobj + sizeof(thinker_t), 0xff, sizeof(mobj_t) - sizeof(thinker_t));
#endif
P_RemoveThinker((thinker_t *)mobj);
}
} }
// This does not need to be added to Lua. // This does not need to be added to Lua.
@ -11737,13 +11754,14 @@ ML_EFFECT5 : Don't stop thinking when too far away
P_SpawnMobjFromMobj(mobj, -1*FRACUNIT, 0, 0, MT_THZTREEBRANCH)->angle = mobjangle + ANGLE_270; P_SpawnMobjFromMobj(mobj, -1*FRACUNIT, 0, 0, MT_THZTREEBRANCH)->angle = mobjangle + ANGLE_270;
} }
break; break;
case MT_CEZPOLE: case MT_CEZPOLE1:
case MT_CEZPOLE2:
{ // Spawn the banner { // Spawn the banner
angle_t mobjangle = FixedAngle(mthing->angle<<FRACBITS); angle_t mobjangle = FixedAngle(mthing->angle<<FRACBITS);
P_SpawnMobjFromMobj(mobj, P_SpawnMobjFromMobj(mobj,
P_ReturnThrustX(mobj, mobjangle, 4<<FRACBITS), P_ReturnThrustX(mobj, mobjangle, 4<<FRACBITS),
P_ReturnThrustY(mobj, mobjangle, 4<<FRACBITS), P_ReturnThrustY(mobj, mobjangle, 4<<FRACBITS),
0, MT_CEZBANNER)->angle = mobjangle + ANGLE_90; 0, ((mobj->type == MT_CEZPOLE1) ? MT_CEZBANNER1 : MT_CEZBANNER2))->angle = mobjangle + ANGLE_90;
} }
break; break;
case MT_HHZTREE_TOP: case MT_HHZTREE_TOP:
@ -11821,6 +11839,9 @@ ML_EFFECT5 : Don't stop thinking when too far away
// See if other starposts exist in this level that have the same value. // See if other starposts exist in this level that have the same value.
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2 == mobj) if (mo2 == mobj)
@ -12124,11 +12145,11 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime)
// Link all the sprites in the hoop together // Link all the sprites in the hoop together
if (nextmobj) if (nextmobj)
{ {
mobj->hprev = nextmobj; P_SetTarget(&mobj->hprev, nextmobj);
mobj->hprev->hnext = mobj; P_SetTarget(&mobj->hprev->hnext, mobj);
} }
else else
mobj->hprev = mobj->hnext = NULL; P_SetTarget(&mobj->hprev, P_SetTarget(&mobj->hnext, NULL));
nextmobj = mobj; nextmobj = mobj;
} }
@ -12154,9 +12175,9 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime)
mobj->z -= mobj->height/2; mobj->z -= mobj->height/2;
// Link all the collision sprites together. // Link all the collision sprites together.
mobj->hnext = NULL; P_SetTarget(&mobj->hnext, NULL);
mobj->hprev = nextmobj; P_SetTarget(&mobj->hprev, nextmobj);
mobj->hprev->hnext = mobj; P_SetTarget(&mobj->hprev->hnext, mobj);
nextmobj = mobj; nextmobj = mobj;
} }
@ -12181,9 +12202,9 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime)
mobj->z -= mobj->height/2; mobj->z -= mobj->height/2;
// Link all the collision sprites together. // Link all the collision sprites together.
mobj->hnext = NULL; P_SetTarget(&mobj->hnext, NULL);
mobj->hprev = nextmobj; P_SetTarget(&mobj->hprev, nextmobj);
mobj->hprev->hnext = mobj; P_SetTarget(&mobj->hprev->hnext, mobj);
nextmobj = mobj; nextmobj = mobj;
} }
@ -12266,11 +12287,11 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime)
// Link all the sprites in the hoop together // Link all the sprites in the hoop together
if (nextmobj) if (nextmobj)
{ {
mobj->hprev = nextmobj; P_SetTarget(&mobj->hprev, nextmobj);
mobj->hprev->hnext = mobj; P_SetTarget(&mobj->hprev->hnext, mobj);
} }
else else
mobj->hprev = mobj->hnext = NULL; P_SetTarget(&mobj->hprev, P_SetTarget(&mobj->hnext, NULL));
nextmobj = mobj; nextmobj = mobj;
} }
@ -12307,9 +12328,9 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime)
mobj->z -= mobj->height/2; mobj->z -= mobj->height/2;
// Link all the collision sprites together. // Link all the collision sprites together.
mobj->hnext = NULL; P_SetTarget(&mobj->hnext, NULL);
mobj->hprev = nextmobj; P_SetTarget(&mobj->hprev, nextmobj);
mobj->hprev->hnext = mobj; P_SetTarget(&mobj->hprev->hnext, mobj);
nextmobj = mobj; nextmobj = mobj;
} }

View File

@ -1495,6 +1495,7 @@ void Polyobj_InitLevel(void)
mqueue_t anchorqueue; mqueue_t anchorqueue;
mobjqitem_t *qitem; mobjqitem_t *qitem;
INT32 i, numAnchors = 0; INT32 i, numAnchors = 0;
mobj_t *mo;
M_QueueInit(&spawnqueue); M_QueueInit(&spawnqueue);
M_QueueInit(&anchorqueue); M_QueueInit(&anchorqueue);
@ -1510,7 +1511,10 @@ void Polyobj_InitLevel(void)
// the mobj_t pointers on a queue for use below. // the mobj_t pointers on a queue for use below.
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
mobj_t *mo = (mobj_t *)th; if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo = (mobj_t *)th;
if (mo->info->doomednum == POLYOBJ_SPAWN_DOOMEDNUM || if (mo->info->doomednum == POLYOBJ_SPAWN_DOOMEDNUM ||
mo->info->doomednum == POLYOBJ_SPAWNCRUSH_DOOMEDNUM) mo->info->doomednum == POLYOBJ_SPAWNCRUSH_DOOMEDNUM)
@ -1815,6 +1819,9 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
// We redo this each tic to make savegame compatibility easier. // We redo this each tic to make savegame compatibility easier.
for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next) for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next)
{ {
if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)wp; mo2 = (mobj_t *)wp;
if (mo2->type != MT_TUBEWAYPOINT) if (mo2->type != MT_TUBEWAYPOINT)
@ -1893,28 +1900,31 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
// Find next waypoint // Find next waypoint
for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next) for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next)
{ {
if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)wp; mo2 = (mobj_t *)wp;
if (mo2->type != MT_TUBEWAYPOINT) if (mo2->type != MT_TUBEWAYPOINT)
continue; continue;
if (mo2->threshold == th->sequence) if (mo2->threshold != th->sequence)
continue;
if (th->direction == -1)
{ {
if (th->direction == -1) if (mo2->health == target->health - 1)
{ {
if (mo2->health == target->health - 1) waypoint = mo2;
{ break;
waypoint = mo2;
break;
}
} }
else }
else
{
if (mo2->health == target->health + 1)
{ {
if (mo2->health == target->health + 1) waypoint = mo2;
{ break;
waypoint = mo2;
break;
}
} }
} }
} }
@ -1929,27 +1939,30 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next) for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next)
{ {
if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)wp; mo2 = (mobj_t *)wp;
if (mo2->type != MT_TUBEWAYPOINT) if (mo2->type != MT_TUBEWAYPOINT)
continue; continue;
if (mo2->threshold == th->sequence) if (mo2->threshold != th->sequence)
continue;
if (th->direction == -1)
{ {
if (th->direction == -1) if (waypoint == NULL)
waypoint = mo2;
else if (mo2->health > waypoint->health)
waypoint = mo2;
}
else
{
if (mo2->health == 0)
{ {
if (waypoint == NULL) waypoint = mo2;
waypoint = mo2; break;
else if (mo2->health > waypoint->health)
waypoint = mo2;
}
else
{
if (mo2->health == 0)
{
waypoint = mo2;
break;
}
} }
} }
} }
@ -1963,28 +1976,31 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next) for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next)
{ {
if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)wp; mo2 = (mobj_t *)wp;
if (mo2->type != MT_TUBEWAYPOINT) if (mo2->type != MT_TUBEWAYPOINT)
continue; continue;
if (mo2->threshold == th->sequence) if (mo2->threshold != th->sequence)
continue;
if (th->direction == -1)
{ {
if (th->direction == -1) if (mo2->health == target->health - 1)
{ {
if (mo2->health == target->health - 1) waypoint = mo2;
{ break;
waypoint = mo2;
break;
}
} }
else }
else
{
if (mo2->health == target->health + 1)
{ {
if (mo2->health == target->health + 1) waypoint = mo2;
{ break;
waypoint = mo2;
break;
}
} }
} }
} }
@ -2511,36 +2527,39 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
// Find the first waypoint we need to use // Find the first waypoint we need to use
for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next) for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next)
{ {
if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)wp; mo2 = (mobj_t *)wp;
if (mo2->type != MT_TUBEWAYPOINT) if (mo2->type != MT_TUBEWAYPOINT)
continue; continue;
if (mo2->threshold == th->sequence) if (mo2->threshold != th->sequence)
continue;
if (th->direction == -1) // highest waypoint #
{ {
if (th->direction == -1) // highest waypoint # if (mo2->health == 0)
last = mo2;
else
{ {
if (mo2->health == 0) if (first == NULL)
last = mo2;
else
{
if (first == NULL)
first = mo2;
else if (mo2->health > first->health)
first = mo2;
}
}
else // waypoint 0
{
if (mo2->health == 0)
first = mo2; first = mo2;
else else if (mo2->health > first->health)
{ first = mo2;
if (last == NULL) }
last = mo2; }
else if (mo2->health > last->health) else // waypoint 0
last = mo2; {
} if (mo2->health == 0)
first = mo2;
else
{
if (last == NULL)
last = mo2;
else if (mo2->health > last->health)
last = mo2;
} }
} }
} }
@ -2579,28 +2598,31 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
target = first; target = first;
/*for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next) /*for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next)
{ {
if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)wp; mo2 = (mobj_t *)wp;
if (mo2->type != MT_TUBEWAYPOINT) if (mo2->type != MT_TUBEWAYPOINT)
continue; continue;
if (mo2->threshold == th->sequence) if (mo2->threshold != th->sequence)
continue;
if (th->direction == -1) // highest waypoint #
{ {
if (th->direction == -1) // highest waypoint # if (mo2->health == first->health - 1)
{ {
if (mo2->health == first->health - 1) target = mo2;
{ break;
target = mo2;
break;
}
} }
else // waypoint 0 }
else // waypoint 0
{
if (mo2->health == first->health + 1)
{ {
if (mo2->health == first->health + 1) target = mo2;
{ break;
target = mo2;
break;
}
} }
} }
}*/ }*/

View File

@ -2174,7 +2174,6 @@ static void P_NetArchiveThinkers(void)
for (i = 0; i < NUM_THINKERLISTS; i++) for (i = 0; i < NUM_THINKERLISTS; i++)
{ {
UINT32 numsaved = 0; UINT32 numsaved = 0;
// save off the current thinkers // save off the current thinkers
for (th = thlist[i].next; th != &thlist[i]; th = th->next) for (th = thlist[i].next; th != &thlist[i]; th = th->next)
{ {
@ -2405,12 +2404,12 @@ static void P_NetArchiveThinkers(void)
} }
#endif // ESLOPE #endif // ESLOPE
#ifdef PARANOIA #ifdef PARANOIA
else if (th->function.acv != P_RemoveThinkerDelayed) // wait garbage collection else if (th->function.acp1 != P_RemoveThinkerDelayed) // wait garbage collection
I_Error("unknown thinker type %p", th->function.acp1); I_Error("unknown thinker type %p", th->function.acp1);
#endif #endif
} }
CONS_Debug(DBG_NETPLAY, "%u thinkers saved\n", numsaved); CONS_Debug(DBG_NETPLAY, "%u thinkers saved in list %d\n", numsaved, i);
WRITEUINT8(save_p, tc_end); WRITEUINT8(save_p, tc_end);
} }
@ -2427,9 +2426,14 @@ mobj_t *P_FindNewPosition(UINT32 oldposition)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mobj = (mobj_t *)th; mobj = (mobj_t *)th;
if (mobj->mobjnum == oldposition) if (mobj->mobjnum != oldposition)
return mobj; continue;
return mobj;
} }
CONS_Debug(DBG_GAMELOGIC, "mobj not found\n"); CONS_Debug(DBG_GAMELOGIC, "mobj not found\n");
return NULL; return NULL;
@ -3404,7 +3408,7 @@ static void P_NetUnArchiveThinkers(void)
{ {
for (;;) for (;;)
{ {
thinker_t* th; thinker_t* th = NULL;
tclass = READUINT8(save_p); tclass = READUINT8(save_p);
if (tclass == tc_end) if (tclass == tc_end)
@ -3597,22 +3601,22 @@ static void P_NetUnArchiveThinkers(void)
P_AddThinker(i, th); P_AddThinker(i, th);
} }
CONS_Debug(DBG_NETPLAY, "%u thinkers loaded\n", numloaded); CONS_Debug(DBG_NETPLAY, "%u thinkers loaded in list %d\n", numloaded, i);
}
if (restoreNum) if (restoreNum)
{
executor_t *delay = NULL;
UINT32 mobjnum;
for (currentthinker = thlist[i].next; currentthinker != &thlist[i];
currentthinker = currentthinker->next)
{ {
executor_t *delay = NULL; if (currentthinker->function.acp1 != (actionf_p1)T_ExecutorDelay)
UINT32 mobjnum; continue;
for (currentthinker = thlist[i].next; currentthinker != &thlist[i]; delay = (void *)currentthinker;
currentthinker = currentthinker->next) if (!(mobjnum = (UINT32)(size_t)delay->caller))
{ continue;
if (currentthinker->function.acp1 == (actionf_p1)T_ExecutorDelay) delay->caller = P_FindNewPosition(mobjnum);
{
delay = (void *)currentthinker;
if ((mobjnum = (UINT32)(size_t)delay->caller))
delay->caller = P_FindNewPosition(mobjnum);
}
}
} }
} }
} }
@ -3723,6 +3727,9 @@ static inline void P_FinishMobjs(void)
for (currentthinker = thlist[THINK_MOBJ].next; currentthinker != &thlist[THINK_MOBJ]; for (currentthinker = thlist[THINK_MOBJ].next; currentthinker != &thlist[THINK_MOBJ];
currentthinker = currentthinker->next) currentthinker = currentthinker->next)
{ {
if (currentthinker->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mobj = (mobj_t *)currentthinker; mobj = (mobj_t *)currentthinker;
mobj->info = &mobjinfo[mobj->type]; mobj->info = &mobjinfo[mobj->type];
} }
@ -3738,6 +3745,9 @@ static void P_RelinkPointers(void)
for (currentthinker = thlist[THINK_MOBJ].next; currentthinker != &thlist[THINK_MOBJ]; for (currentthinker = thlist[THINK_MOBJ].next; currentthinker != &thlist[THINK_MOBJ];
currentthinker = currentthinker->next) currentthinker = currentthinker->next)
{ {
if (currentthinker->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mobj = (mobj_t *)currentthinker; mobj = (mobj_t *)currentthinker;
if (mobj->type == MT_HOOP || mobj->type == MT_HOOPCOLLIDE || mobj->type == MT_HOOPCENTER) if (mobj->type == MT_HOOP || mobj->type == MT_HOOPCOLLIDE || mobj->type == MT_HOOPCENTER)
@ -4115,6 +4125,9 @@ void P_SaveNetGame(void)
// Assign the mobjnumber for pointer tracking // Assign the mobjnumber for pointer tracking
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mobj = (mobj_t *)th; mobj = (mobj_t *)th;
if (mobj->type == MT_HOOP || mobj->type == MT_HOOPCOLLIDE || mobj->type == MT_HOOPCENTER) if (mobj->type == MT_HOOP || mobj->type == MT_HOOPCOLLIDE || mobj->type == MT_HOOPCENTER)
continue; continue;

View File

@ -817,6 +817,9 @@ void P_ReloadRings(void)
// scan the thinkers to find rings/spheres/hoops to unset // scan the thinkers to find rings/spheres/hoops to unset
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo = (mobj_t *)th; mo = (mobj_t *)th;
if (mo->type == MT_HOOPCENTER) if (mo->type == MT_HOOPCENTER)
@ -883,6 +886,9 @@ void P_SwitchSpheresBonusMode(boolean bonustime)
// scan the thinkers to find spheres to switch // scan the thinkers to find spheres to switch
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo = (mobj_t *)th; mo = (mobj_t *)th;
if (mo->type != MT_BLUESPHERE && mo->type != MT_NIGHTSCHIP if (mo->type != MT_BLUESPHERE && mo->type != MT_NIGHTSCHIP
@ -2284,7 +2290,6 @@ static void P_LevelInitStuff(void)
void P_LoadThingsOnly(void) void P_LoadThingsOnly(void)
{ {
// Search through all the thinkers. // Search through all the thinkers.
mobj_t *mo;
thinker_t *think; thinker_t *think;
INT32 i, viewid = -1, centerid = -1; // for skyboxes INT32 i, viewid = -1, centerid = -1; // for skyboxes
@ -2301,10 +2306,9 @@ void P_LoadThingsOnly(void)
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next)
{ {
mo = (mobj_t *)think; if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
if (mo) P_RemoveMobj((mobj_t *)think);
P_RemoveMobj(mo);
} }
P_LevelInitStuff(); P_LevelInitStuff();
@ -2864,7 +2868,10 @@ boolean P_SetupLevel(boolean skipprecip)
// reset the player starts // reset the player starts
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
playerstarts[i] = NULL; playerstarts[i] = bluectfstarts[i] = redctfstarts[i] = NULL;
for (i = 0; i < MAX_DM_STARTS; i++)
deathmatchstarts[i] = NULL;
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
skyboxmo[i] = NULL; skyboxmo[i] = NULL;
@ -2900,7 +2907,10 @@ boolean P_SetupLevel(boolean skipprecip)
// reset the player starts // reset the player starts
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
playerstarts[i] = NULL; playerstarts[i] = bluectfstarts[i] = redctfstarts[i] = NULL;
for (i = 0; i < MAX_DM_STARTS; i++)
deathmatchstarts[i] = NULL;
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
skyboxmo[i] = NULL; skyboxmo[i] = NULL;

View File

@ -2260,7 +2260,7 @@ void P_SwitchWeather(INT32 weathernum)
thinker_t *think; thinker_t *think;
precipmobj_t *precipmobj; precipmobj_t *precipmobj;
for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next) for (think = thlist[THINK_PRECIP].next; think != &thlist[THINK_PRECIP]; think = think->next)
{ {
if (think->function.acp1 != (actionf_p1)P_NullPrecipThinker) if (think->function.acp1 != (actionf_p1)P_NullPrecipThinker)
continue; // not a precipmobj thinker continue; // not a precipmobj thinker
@ -2276,7 +2276,7 @@ void P_SwitchWeather(INT32 weathernum)
precipmobj_t *precipmobj; precipmobj_t *precipmobj;
state_t *st; state_t *st;
for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next) for (think = thlist[THINK_PRECIP].next; think != &thlist[THINK_PRECIP]; think = think->next)
{ {
if (think->function.acp1 != (actionf_p1)P_NullPrecipThinker) if (think->function.acp1 != (actionf_p1)P_NullPrecipThinker)
continue; // not a precipmobj thinker continue; // not a precipmobj thinker
@ -3992,6 +3992,9 @@ void P_SetupSignExit(player_t *player)
// spin all signposts in the level then. // spin all signposts in the level then.
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next)
{ {
if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
thing = (mobj_t *)think; thing = (mobj_t *)think;
if (thing->type != MT_SIGN) if (thing->type != MT_SIGN)
continue; continue;
@ -4017,20 +4020,18 @@ boolean P_IsFlagAtBase(mobjtype_t flag)
{ {
thinker_t *think; thinker_t *think;
mobj_t *mo; mobj_t *mo;
INT32 specialnum = 0; INT32 specialnum = (flag == MT_REDFLAG) ? 3 : 4;
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next)
{ {
if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo = (mobj_t *)think; mo = (mobj_t *)think;
if (mo->type != flag) if (mo->type != flag)
continue; continue;
if (mo->type == MT_REDFLAG)
specialnum = 3;
else if (mo->type == MT_BLUEFLAG)
specialnum = 4;
if (GETSECSPECIAL(mo->subsector->sector->special, 4) == specialnum) if (GETSECSPECIAL(mo->subsector->sector->special, 4) == specialnum)
return true; return true;
else if (mo->subsector->sector->ffloors) // Check the 3D floors else if (mo->subsector->sector->ffloors) // Check the 3D floors
@ -4045,9 +4046,11 @@ boolean P_IsFlagAtBase(mobjtype_t flag)
if (GETSECSPECIAL(rover->master->frontsector->special, 4) != specialnum) if (GETSECSPECIAL(rover->master->frontsector->special, 4) != specialnum)
continue; continue;
if (mo->z <= P_GetSpecialTopZ(mo, sectors + rover->secnum, mo->subsector->sector) if (!(mo->z <= P_GetSpecialTopZ(mo, sectors + rover->secnum, mo->subsector->sector)
&& mo->z >= P_GetSpecialBottomZ(mo, sectors + rover->secnum, mo->subsector->sector)) && mo->z >= P_GetSpecialBottomZ(mo, sectors + rover->secnum, mo->subsector->sector)))
return true; continue;
return true;
} }
} }
} }
@ -4451,9 +4454,12 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers
// The chimps are my friends.. heeheeheheehehee..... - LouisJM // The chimps are my friends.. heeheeheheehehee..... - LouisJM
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2->type == MT_EGGTRAP) if (mo2->type != MT_EGGTRAP)
P_KillMobj(mo2, NULL, player->mo, 0); continue;
P_KillMobj(mo2, NULL, player->mo, 0);
} }
// clear the special so you can't push the button twice. // clear the special so you can't push the button twice.
@ -4754,14 +4760,20 @@ DoneSection2:
// to find the first waypoint // to find the first waypoint
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2->type == MT_TUBEWAYPOINT && mo2->threshold == sequence if (mo2->type != MT_TUBEWAYPOINT)
&& mo2->health == 0) continue;
{ if (mo2->threshold != sequence)
waypoint = mo2; continue;
break; if (mo2->health != 0)
} continue;
waypoint = mo2;
break;
} }
if (!waypoint) if (!waypoint)
@ -4830,15 +4842,20 @@ DoneSection2:
// to find the last waypoint // to find the last waypoint
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2->type == MT_TUBEWAYPOINT && mo2->threshold == sequence) if (mo2->type != MT_TUBEWAYPOINT)
{ continue;
if (!waypoint) if (mo2->threshold != sequence)
waypoint = mo2; continue;
else if (mo2->health > waypoint->health)
waypoint = mo2; if (!waypoint)
} waypoint = mo2;
else if (mo2->health > waypoint->health)
waypoint = mo2;
} }
if (!waypoint) if (!waypoint)
@ -4979,6 +4996,9 @@ DoneSection2:
// to find the first waypoint // to find the first waypoint
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2->type != MT_TUBEWAYPOINT) if (mo2->type != MT_TUBEWAYPOINT)
@ -5014,6 +5034,9 @@ DoneSection2:
// Find waypoint before this one (waypointlow) // Find waypoint before this one (waypointlow)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2->type != MT_TUBEWAYPOINT) if (mo2->type != MT_TUBEWAYPOINT)
@ -5038,6 +5061,9 @@ DoneSection2:
// Find waypoint after this one (waypointhigh) // Find waypoint after this one (waypointhigh)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2->type != MT_TUBEWAYPOINT) if (mo2->type != MT_TUBEWAYPOINT)

View File

@ -44,6 +44,9 @@ void Command_Numthinkers_f(void)
INT32 count = 0; INT32 count = 0;
actionf_p1 action; actionf_p1 action;
thinker_t *think; thinker_t *think;
thinklistnum_t start = 0;
thinklistnum_t end = NUM_THINKERLISTS - 1;
thinklistnum_t i;
if (gamestate != GS_LEVEL) if (gamestate != GS_LEVEL)
{ {
@ -70,6 +73,7 @@ void Command_Numthinkers_f(void)
switch (num) switch (num)
{ {
case 1: case 1:
start = end = THINK_MOBJ;
action = (actionf_p1)P_MobjThinker; action = (actionf_p1)P_MobjThinker;
CONS_Printf(M_GetText("Number of %s: "), "P_MobjThinker"); CONS_Printf(M_GetText("Number of %s: "), "P_MobjThinker");
break; break;
@ -82,14 +86,17 @@ void Command_Numthinkers_f(void)
CONS_Printf(M_GetText("Number of %s: "), "P_SnowThinker"); CONS_Printf(M_GetText("Number of %s: "), "P_SnowThinker");
break;*/ break;*/
case 2: case 2:
start = end = THINK_PRECIP;
action = (actionf_p1)P_NullPrecipThinker; action = (actionf_p1)P_NullPrecipThinker;
CONS_Printf(M_GetText("Number of %s: "), "P_NullPrecipThinker"); CONS_Printf(M_GetText("Number of %s: "), "P_NullPrecipThinker");
break; break;
case 3: case 3:
start = end = THINK_MAIN;
action = (actionf_p1)T_Friction; action = (actionf_p1)T_Friction;
CONS_Printf(M_GetText("Number of %s: "), "T_Friction"); CONS_Printf(M_GetText("Number of %s: "), "T_Friction");
break; break;
case 4: case 4:
start = end = THINK_MAIN;
action = (actionf_p1)T_Pusher; action = (actionf_p1)T_Pusher;
CONS_Printf(M_GetText("Number of %s: "), "T_Pusher"); CONS_Printf(M_GetText("Number of %s: "), "T_Pusher");
break; break;
@ -102,12 +109,15 @@ void Command_Numthinkers_f(void)
return; return;
} }
for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next) for (i = start; i <= end; i++)
{ {
if (think->function.acp1 != action) for (think = thlist[i].next; think != &thlist[i]; think = think->next)
continue; {
if (think->function.acp1 != action)
continue;
count++; count++;
}
} }
CONS_Printf("%d\n", count); CONS_Printf("%d\n", count);
@ -141,6 +151,9 @@ void Command_CountMobjs_f(void)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
if (((mobj_t *)th)->type == i) if (((mobj_t *)th)->type == i)
count++; count++;
} }
@ -158,6 +171,9 @@ void Command_CountMobjs_f(void)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
if (((mobj_t *)th)->type == i) if (((mobj_t *)th)->type == i)
count++; count++;
} }
@ -180,6 +196,10 @@ void P_InitThinkers(void)
// Adds a new thinker at the end of the list. // Adds a new thinker at the end of the list.
void P_AddThinker(const thinklistnum_t n, thinker_t *thinker) void P_AddThinker(const thinklistnum_t n, thinker_t *thinker)
{ {
#ifdef PARANOIA
I_Assert(n >= 0 && n < NUM_THINKERLISTS);
#endif
thlist[n].prev->next = thinker; thlist[n].prev->next = thinker;
thinker->next = &thlist[n]; thinker->next = &thlist[n];
thinker->prev = thlist[n].prev; thinker->prev = thlist[n].prev;
@ -206,22 +226,33 @@ static thinker_t *currentthinker;
// remove it, and set currentthinker to one node preceeding it, so // remove it, and set currentthinker to one node preceeding it, so
// that the next step in P_RunThinkers() will get its successor. // that the next step in P_RunThinkers() will get its successor.
// //
void P_RemoveThinkerDelayed(void *pthinker) void P_RemoveThinkerDelayed(thinker_t *thinker)
{ {
thinker_t *thinker = pthinker; thinker_t *next;
if (!thinker->references) #ifdef PARANOIA
#define BEENAROUNDBIT (0x40000000) // has to be sufficiently high that it's unlikely to happen in regular gameplay. If you change this, pay attention to the bit pattern of INT32_MIN.
if (thinker->references & ~BEENAROUNDBIT)
{ {
{ if (thinker->references & BEENAROUNDBIT) // Usually gets cleared up in one frame; what's going on here, then?
/* Remove from main thinker list */ CONS_Printf("Number of potentially faulty references: %d\n", (thinker->references & ~BEENAROUNDBIT));
thinker_t *next = thinker->next; thinker->references |= BEENAROUNDBIT;
/* Note that currentthinker is guaranteed to point to us, return;
* and since we're freeing our memory, we had better change that. So
* point it to thinker->prev, so the iterator will correctly move on to
* thinker->prev->next = thinker->next */
(next->prev = currentthinker = thinker->prev)->next = next;
}
Z_Free(thinker);
} }
#undef BEENAROUNDBIT
#else
if (thinker->references)
return;
#endif
/* Remove from main thinker list */
next = thinker->next;
/* Note that currentthinker is guaranteed to point to us,
* and since we're freeing our memory, we had better change that. So
* point it to thinker->prev, so the iterator will correctly move on to
* thinker->prev->next = thinker->next */
(next->prev = currentthinker = thinker->prev)->next = next;
Z_Free(thinker);
} }
// //
@ -238,23 +269,10 @@ void P_RemoveThinkerDelayed(void *pthinker)
// //
void P_RemoveThinker(thinker_t *thinker) void P_RemoveThinker(thinker_t *thinker)
{ {
thinker_t *next = thinker->next;
#ifdef HAVE_BLUA #ifdef HAVE_BLUA
LUA_InvalidateUserdata(thinker); LUA_InvalidateUserdata(thinker);
#endif #endif
thinker->function.acp1 = P_RemoveThinkerDelayed; thinker->function.acp1 = (actionf_p1)P_RemoveThinkerDelayed;
if (currentthinker == thinker)
currentthinker = thinker->prev;
// Remove thinker from its current list.
(next->prev = thinker->prev)->next = next;
// Now add it to the limbo list
thlist[THINK_LIMBO].prev->next = thinker;
thinker->next = &thlist[THINK_LIMBO];
thinker->prev = thlist[THINK_LIMBO].prev;
thlist[THINK_LIMBO].prev = thinker;
} }
/* /*
@ -307,8 +325,10 @@ static inline void P_RunThinkers(void)
{ {
for (currentthinker = thlist[i].next; currentthinker != &thlist[i]; currentthinker = currentthinker->next) for (currentthinker = thlist[i].next; currentthinker != &thlist[i]; currentthinker = currentthinker->next)
{ {
if (currentthinker->function.acp1) #ifdef PARANOIA
currentthinker->function.acp1(currentthinker); I_Assert(currentthinker->function.acp1 != NULL)
#endif
currentthinker->function.acp1(currentthinker);
} }
} }

View File

@ -27,7 +27,7 @@ void Command_CountMobjs_f(void);
void P_Ticker(boolean run); void P_Ticker(boolean run);
void P_PreTicker(INT32 frames); void P_PreTicker(INT32 frames);
void P_DoTeamscrambling(void); void P_DoTeamscrambling(void);
void P_RemoveThinkerDelayed(void *pthinker); //killed void P_RemoveThinkerDelayed(thinker_t *thinker); //killed
mobj_t *P_SetTarget(mobj_t **mo, mobj_t *target); // killough 11/98 mobj_t *P_SetTarget(mobj_t **mo, mobj_t *target); // killough 11/98
#endif #endif

View File

@ -345,9 +345,16 @@ UINT8 P_FindLowestMare(void)
// to find the egg capsule with the lowest mare // to find the egg capsule with the lowest mare
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2->type == MT_EGGCAPSULE && mo2->health > 0) if (mo2->type != MT_EGGCAPSULE)
continue;
if (mo2->health <= 0)
continue;
{ {
const UINT8 threshold = (UINT8)mo2->threshold; const UINT8 threshold = (UINT8)mo2->threshold;
if (mare == 255) if (mare == 255)
@ -391,29 +398,32 @@ boolean P_TransferToNextMare(player_t *player)
// to find the closest axis point // to find the closest axis point
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2->type == MT_AXIS) if (mo2->type != MT_AXIS)
{ continue;
if (mo2->threshold == mare)
{
if (closestaxis == NULL)
{
closestaxis = mo2;
lowestaxisnum = mo2->health;
dist2 = R_PointToDist2(player->mo->x, player->mo->y, mo2->x, mo2->y)-mo2->radius;
}
else if (mo2->health < lowestaxisnum)
{
dist1 = R_PointToDist2(player->mo->x, player->mo->y, mo2->x, mo2->y)-mo2->radius;
if (dist1 < dist2) if (mo2->threshold != mare)
{ continue;
closestaxis = mo2;
lowestaxisnum = mo2->health; if (closestaxis == NULL)
dist2 = dist1; {
} closestaxis = mo2;
} lowestaxisnum = mo2->health;
dist2 = R_PointToDist2(player->mo->x, player->mo->y, mo2->x, mo2->y) - mo2->radius;
}
else if (mo2->health < lowestaxisnum)
{
dist1 = R_PointToDist2(player->mo->x, player->mo->y, mo2->x, mo2->y) - mo2->radius;
if (dist1 < dist2)
{
closestaxis = mo2;
lowestaxisnum = mo2->health;
dist2 = dist1;
} }
} }
} }
@ -439,17 +449,22 @@ static mobj_t *P_FindAxis(INT32 mare, INT32 axisnum)
// to find the closest axis point // to find the closest axis point
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
// Axis things are only at beginning of list. // Axis things are only at beginning of list.
if (!(mo2->flags2 & MF2_AXIS)) if (!(mo2->flags2 & MF2_AXIS))
return NULL; return NULL;
if (mo2->type == MT_AXIS) if (mo2->type != MT_AXIS)
{ continue;
if (mo2->health == axisnum && mo2->threshold == mare) if (mo2->health != axisnum)
return mo2; continue;
} if (mo2->threshold != mare)
continue;
return mo2;
} }
return NULL; return NULL;
@ -469,17 +484,22 @@ static mobj_t *P_FindAxisTransfer(INT32 mare, INT32 axisnum, mobjtype_t type)
// to find the closest axis point // to find the closest axis point
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
// Axis things are only at beginning of list. // Axis things are only at beginning of list.
if (!(mo2->flags2 & MF2_AXIS)) if (!(mo2->flags2 & MF2_AXIS))
return NULL; return NULL;
if (mo2->type == type) if (mo2->type != type)
{ continue;
if (mo2->health == axisnum && mo2->threshold == mare) if (mo2->health != axisnum)
return mo2; continue;
} if (mo2->threshold != mare)
continue;
return mo2;
} }
return NULL; return NULL;
@ -505,27 +525,31 @@ void P_TransferToAxis(player_t *player, INT32 axisnum)
// to find the closest axis point // to find the closest axis point
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2->type == MT_AXIS) if (mo2->type != MT_AXIS)
{ continue;
if (mo2->health == axisnum && mo2->threshold == mare) if (mo2->health != axisnum)
{ continue;
if (closestaxis == NULL) if (mo2->threshold != mare)
{ continue;
closestaxis = mo2;
dist2 = R_PointToDist2(player->mo->x, player->mo->y, mo2->x, mo2->y)-mo2->radius;
}
else
{
dist1 = R_PointToDist2(player->mo->x, player->mo->y, mo2->x, mo2->y)-mo2->radius;
if (dist1 < dist2) if (closestaxis == NULL)
{ {
closestaxis = mo2; closestaxis = mo2;
dist2 = dist1; dist2 = R_PointToDist2(player->mo->x, player->mo->y, mo2->x, mo2->y) - mo2->radius;
} }
} else
{
dist1 = R_PointToDist2(player->mo->x, player->mo->y, mo2->x, mo2->y) - mo2->radius;
if (dist1 < dist2)
{
closestaxis = mo2;
dist2 = dist1;
} }
} }
} }
@ -602,6 +626,9 @@ static void P_DeNightserizePlayer(player_t *player)
// Check to see if the player should be killed. // Check to see if the player should be killed.
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (!(mo2->type == MT_NIGHTSDRONE)) if (!(mo2->type == MT_NIGHTSDRONE))
continue; continue;
@ -1617,6 +1644,9 @@ void P_SpawnShieldOrb(player_t *player)
// blaze through the thinkers to see if an orb already exists! // blaze through the thinkers to see if an orb already exists!
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
shieldobj = (mobj_t *)th; shieldobj = (mobj_t *)th;
if (shieldobj->type == orbtype && shieldobj->target == player->mo) if (shieldobj->type == orbtype && shieldobj->target == player->mo)
@ -2019,7 +2049,7 @@ boolean P_PlayerHitFloor(player_t *player)
fixed_t mu = FixedMul(player->maxdash, player->mo->scale); fixed_t mu = FixedMul(player->maxdash, player->mo->scale);
fixed_t mu2 = FixedHypot(player->mo->momx, player->mo->momy); fixed_t mu2 = FixedHypot(player->mo->momx, player->mo->momy);
fixed_t ev; fixed_t ev;
mobj_t *missile; mobj_t *missile = NULL;
if (mu2 < mu) if (mu2 < mu)
mu2 = mu; mu2 = mu;
ev = (50*FRACUNIT - (mu/25))/50; ev = (50*FRACUNIT - (mu/25))/50;
@ -3625,7 +3655,8 @@ static void P_DoTeeter(player_t *player)
if (teeter) // only bother with objects as a last resort if you were already teetering if (teeter) // only bother with objects as a last resort if you were already teetering
{ {
mobj_t *oldtmthing = tmthing; mobj_t *oldtmthing = tmthing;
tmthing = teeterer = player->mo; teeterer = player->mo;
P_SetTarget(&tmthing, teeterer);
teeterxl = teeterxh = player->mo->x; teeterxl = teeterxh = player->mo->x;
teeteryl = teeteryh = player->mo->y; teeteryl = teeteryh = player->mo->y;
couldteeter = false; couldteeter = false;
@ -3639,7 +3670,7 @@ static void P_DoTeeter(player_t *player)
} }
teeterdone: teeterdone:
teeter = solidteeter; teeter = solidteeter;
tmthing = oldtmthing; // restore old tmthing, goodness knows what the game does with this before mobj thinkers P_SetTarget(&tmthing, oldtmthing); // restore old tmthing, goodness knows what the game does with this before mobj thinkers
} }
} }
if (teeter) if (teeter)
@ -4314,7 +4345,7 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd)
if (P_IsLocalPlayer(player)) // Only display it on your own view. if (P_IsLocalPlayer(player)) // Only display it on your own view.
{ {
mobj_t *visual = P_SpawnMobj(lockon->x, lockon->y, lockon->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker mobj_t *visual = P_SpawnMobj(lockon->x, lockon->y, lockon->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker
visual->target = lockon; P_SetTarget(&visual->target, lockon);
} }
} }
if ((cmd->buttons & BT_USE) && !(player->pflags & PF_USEDOWN)) if ((cmd->buttons & BT_USE) && !(player->pflags & PF_USEDOWN))
@ -4589,6 +4620,9 @@ void P_Telekinesis(player_t *player, fixed_t thrust, fixed_t range)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2 == player->mo) if (mo2 == player->mo)
@ -4637,7 +4671,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
if (P_IsLocalPlayer(player)) // Only display it on your own view. if (P_IsLocalPlayer(player)) // Only display it on your own view.
{ {
mobj_t *visual = P_SpawnMobj(lockon->x, lockon->y, lockon->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker mobj_t *visual = P_SpawnMobj(lockon->x, lockon->y, lockon->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker
visual->target = lockon; P_SetTarget(&visual->target, lockon);
} }
} }
@ -5783,29 +5817,32 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad
// Find next waypoint // Find next waypoint
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
// Axis things are only at beginning of list. // Axis things are only at beginning of list.
if (!(mo2->flags2 & MF2_AXIS)) if (!(mo2->flags2 & MF2_AXIS))
break; break;
if (!(mo2->type == MT_AXISTRANSFER || mo2->type == MT_AXISTRANSFERLINE))
continue;
if (mo2->threshold != sequence)
continue;
if ((mo2->type == MT_AXISTRANSFER || mo2->type == MT_AXISTRANSFERLINE) if (player->pflags & PF_TRANSFERTOCLOSEST)
&& mo2->threshold == sequence)
{ {
if (player->pflags & PF_TRANSFERTOCLOSEST) if (mo2->health == player->axis1->health)
{ transfer1 = mo2;
if (mo2->health == player->axis1->health) else if (mo2->health == player->axis2->health)
transfer1 = mo2; transfer2 = mo2;
else if (mo2->health == player->axis2->health) }
transfer2 = mo2; else
} {
else if (mo2->health == player->mo->target->health)
{ transfer1 = mo2;
if (mo2->health == player->mo->target->health) else if (mo2->health == player->mo->target->health + 1)
transfer1 = mo2; transfer2 = mo2;
else if (mo2->health == player->mo->target->health + 1)
transfer2 = mo2;
}
} }
} }
@ -5816,24 +5853,28 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad
{ {
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
// Axis things are only at beginning of list. // Axis things are only at beginning of list.
if (!(mo2->flags2 & MF2_AXIS)) if (!(mo2->flags2 & MF2_AXIS))
break; break;
if (!(mo2->type == MT_AXISTRANSFER || mo2->type == MT_AXISTRANSFERLINE))
continue;
if (mo2->threshold != sequence)
continue;
if (mo2->threshold == sequence && (mo2->type == MT_AXISTRANSFER || mo2->type == MT_AXISTRANSFERLINE)) if (!transfer1)
{ {
if (!transfer1) transfer1 = mo2;
{ transfer1last = true;
transfer1 = mo2; }
transfer1last = true; else if (mo2->health > transfer1->health)
} {
else if (mo2->health > transfer1->health) transfer1 = mo2;
{ transfer1last = true;
transfer1 = mo2;
transfer1last = true;
}
} }
} }
} }
@ -5841,24 +5882,28 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad
{ {
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
// Axis things are only at beginning of list. // Axis things are only at beginning of list.
if (!(mo2->flags2 & MF2_AXIS)) if (!(mo2->flags2 & MF2_AXIS))
break; break;
if (!(mo2->type == MT_AXISTRANSFER || mo2->type == MT_AXISTRANSFERLINE))
continue;
if (mo2->threshold != sequence)
continue;
if (mo2->threshold == sequence && (mo2->type == MT_AXISTRANSFER || mo2->type == MT_AXISTRANSFERLINE)) if (!transfer2)
{ {
if (!transfer2) transfer2 = mo2;
{ transfer2last = true;
transfer2 = mo2; }
transfer2last = true; else if (mo2->health > transfer2->health)
} {
else if (mo2->health > transfer2->health) transfer2 = mo2;
{ transfer2last = true;
transfer2 = mo2;
transfer2last = true;
}
} }
} }
} }
@ -6545,31 +6590,32 @@ static void P_NiGHTSMovement(player_t *player)
// to find the closest axis point // to find the closest axis point
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2->type == MT_AXIS) if (mo2->type != MT_AXIS)
{ continue;
if (mo2->threshold == player->mare) if (mo2->threshold != player->mare)
{ continue;
if (closestaxis == NULL)
{
closestaxis = mo2;
dist2 = R_PointToDist2(newx, newy, mo2->x, mo2->y)-mo2->radius;
}
else
{
dist1 = R_PointToDist2(newx, newy, mo2->x, mo2->y)-mo2->radius;
if (dist1 < dist2) if (closestaxis == NULL)
{ {
closestaxis = mo2; closestaxis = mo2;
dist2 = dist1; dist2 = R_PointToDist2(newx, newy, mo2->x, mo2->y) - mo2->radius;
} }
} else
{
dist1 = R_PointToDist2(newx, newy, mo2->x, mo2->y) - mo2->radius;
if (dist1 < dist2)
{
closestaxis = mo2;
dist2 = dist1;
} }
} }
} }
P_SetTarget(&player->mo->target, closestaxis); P_SetTarget(&player->mo->target, closestaxis);
} }
@ -7352,6 +7398,9 @@ static void P_MovePlayer(player_t *player)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2->type == MT_EGGCAPSULE if (mo2->type == MT_EGGCAPSULE
@ -7855,7 +7904,7 @@ static void P_MovePlayer(player_t *player)
if (P_IsLocalPlayer(player)) // Only display it on your own view. if (P_IsLocalPlayer(player)) // Only display it on your own view.
{ {
mobj_t *visual = P_SpawnMobj(lockon->x, lockon->y, lockon->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker mobj_t *visual = P_SpawnMobj(lockon->x, lockon->y, lockon->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker
visual->target = lockon; P_SetTarget(&visual->target, lockon);
P_SetMobjStateNF(visual, visual->info->spawnstate+1); P_SetMobjStateNF(visual, visual->info->spawnstate+1);
} }
} }
@ -8256,20 +8305,25 @@ static void P_DoZoomTube(player_t *player)
// Find next waypoint // Find next waypoint
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2->type != MT_TUBEWAYPOINT) if (mo2->type != MT_TUBEWAYPOINT)
continue; continue;
if (mo2->threshold == sequence) if (mo2->threshold != sequence)
{ continue;
if ((reverse && mo2->health == player->mo->tracer->health - 1)
|| (!reverse && mo2->health == player->mo->tracer->health + 1)) if (reverse && mo2->health != player->mo->tracer->health - 1)
{ continue;
waypoint = mo2;
break; if (!reverse && mo2->health != player->mo->tracer->health + 1)
} continue;
}
waypoint = mo2;
break;
} }
if (waypoint) if (waypoint)
@ -8387,19 +8441,22 @@ static void P_DoRopeHang(player_t *player)
// Find next waypoint // Find next waypoint
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2->type != MT_TUBEWAYPOINT) if (mo2->type != MT_TUBEWAYPOINT)
continue; continue;
if (mo2->threshold == sequence) if (mo2->threshold != sequence)
{ continue;
if (mo2->health == player->mo->tracer->health + 1)
{ if (mo2->health != player->mo->tracer->health + 1)
waypoint = mo2; continue;
break;
} waypoint = mo2;
} break;
} }
if (!(player->mo->tracer->flags & MF_SLIDEME) && !waypoint) if (!(player->mo->tracer->flags & MF_SLIDEME) && !waypoint)
@ -8409,19 +8466,22 @@ static void P_DoRopeHang(player_t *player)
// Wrap around back to first waypoint // Wrap around back to first waypoint
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2->type != MT_TUBEWAYPOINT) if (mo2->type != MT_TUBEWAYPOINT)
continue; continue;
if (mo2->threshold == sequence) if (mo2->threshold != sequence)
{ continue;
if (mo2->health == 0)
{ if (mo2->health != 0)
waypoint = mo2; continue;
break;
} waypoint = mo2;
} break;
} }
} }
@ -8468,22 +8528,22 @@ static void P_DoRopeHang(player_t *player)
static void P_NukeAllPlayers(player_t *player) static void P_NukeAllPlayers(player_t *player)
{ {
mobj_t *mo; mobj_t *mo;
thinker_t *think; UINT8 i;
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) for (i = 0; i < MAXPLAYERS; i++)
{ {
mo = (mobj_t *)think; if (!playeringame[i])
continue;
if (!mo->player) if (players[i].spectator)
continue;
if (!players[i].mo)
continue;
if (players[i].mo == player->mo)
continue;
if (players[i].mo->health <= 0)
continue; continue;
if (mo->health <= 0) // dead P_DamageMobj(players[i].mo, player->mo, player->mo, 1, 0);
continue;
if (mo == player->mo)
continue;
P_DamageMobj(mo, player->mo, player->mo, 1, 0);
} }
CONS_Printf(M_GetText("%s caused a world of pain.\n"), player_names[player-players]); CONS_Printf(M_GetText("%s caused a world of pain.\n"), player_names[player-players]);
@ -8517,6 +8577,9 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius)
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next)
{ {
if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo = (mobj_t *)think; mo = (mobj_t *)think;
if (!(mo->flags & MF_SHOOTABLE) && !(mo->type == MT_EGGGUARD || mo->type == MT_MINUS)) if (!(mo->flags & MF_SHOOTABLE) && !(mo->type == MT_EGGGUARD || mo->type == MT_MINUS))
@ -8565,6 +8628,9 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet)
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next)
{ {
if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo = (mobj_t *)think; mo = (mobj_t *)think;
if (!((mo->flags & (MF_ENEMY|MF_BOSS|MF_MONITOR) && (mo->flags & MF_SHOOTABLE)) || (mo->flags & MF_SPRING)) == !(mo->flags2 & MF2_INVERTAIMABLE)) // allows if it has the flags desired XOR it has the invert aimable flag if (!((mo->flags & (MF_ENEMY|MF_BOSS|MF_MONITOR) && (mo->flags & MF_SHOOTABLE)) || (mo->flags & MF_SPRING)) == !(mo->flags2 & MF2_INVERTAIMABLE)) // allows if it has the flags desired XOR it has the invert aimable flag
continue; // not a valid target continue; // not a valid target
@ -8706,6 +8772,9 @@ void P_FindEmerald(void)
// to find all emeralds // to find all emeralds
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2->type == MT_EMERHUNT) if (mo2->type == MT_EMERHUNT)
{ {
@ -9931,6 +10000,9 @@ static mobj_t *P_GetAxis(INT32 num)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mobj = (mobj_t *)th; mobj = (mobj_t *)th;
// NiGHTS axes spawn before anything else. If this mobj doesn't have MF2_AXIS, it means we reached the axes' end. // NiGHTS axes spawn before anything else. If this mobj doesn't have MF2_AXIS, it means we reached the axes' end.
@ -9943,6 +10015,7 @@ static mobj_t *P_GetAxis(INT32 num)
return mobj; return mobj;
} }
CONS_Alert(CONS_WARNING, "P_GetAxis: Track segment %d is missing!\n", num); CONS_Alert(CONS_WARNING, "P_GetAxis: Track segment %d is missing!\n", num);
return NULL; return NULL;
} }
@ -10569,6 +10642,9 @@ void P_PlayerThink(player_t *player)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (!(mo2->type == MT_RING || mo2->type == MT_COIN if (!(mo2->type == MT_RING || mo2->type == MT_COIN

View File

@ -2276,7 +2276,8 @@ void R_PrecacheLevel(void)
if (spritepresent == NULL) I_Error("%s: Out of memory looking up sprites", "R_PrecacheLevel"); if (spritepresent == NULL) I_Error("%s: Out of memory looking up sprites", "R_PrecacheLevel");
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
spritepresent[((mobj_t *)th)->sprite] = 1; if (th->function.acp1 != (actionf_p1)P_RemoveThinkerDelayed)
spritepresent[((mobj_t *)th)->sprite] = 1;
spritememory = 0; spritememory = 0;
for (i = 0; i < numsprites; i++) for (i = 0; i < numsprites; i++)

View File

@ -2446,9 +2446,11 @@ static void R_DrawMaskedList (drawnode_t* head)
void R_DrawMasked(maskcount_t* masks, UINT8 nummasks) void R_DrawMasked(maskcount_t* masks, UINT8 nummasks)
{ {
drawnode_t heads[nummasks]; /**< Drawnode lists; as many as number of views/portals. */ drawnode_t *heads; /**< Drawnode lists; as many as number of views/portals. */
SINT8 i; SINT8 i;
heads = calloc(nummasks, sizeof(drawnode_t));
for (i = 0; i < nummasks; i++) for (i = 0; i < nummasks; i++)
{ {
heads[i].next = heads[i].prev = &heads[i]; heads[i].next = heads[i].prev = &heads[i];
@ -2474,6 +2476,8 @@ void R_DrawMasked(maskcount_t* masks, UINT8 nummasks)
R_DrawMaskedList(&heads[nummasks - 1]); R_DrawMaskedList(&heads[nummasks - 1]);
R_ClearDrawNodes(&heads[nummasks - 1]); R_ClearDrawNodes(&heads[nummasks - 1]);
} }
free(heads);
} }
// ========================================================================== // ==========================================================================

View File

@ -1988,8 +1988,10 @@ void GameMIDIMusic_OnChange(void)
} }
} }
#ifdef HAVE_OPENMPT
void ModFilter_OnChange(void) void ModFilter_OnChange(void)
{ {
if (openmpt_mhandle) if (openmpt_mhandle)
openmpt_module_set_render_param(openmpt_mhandle, OPENMPT_MODULE_RENDER_INTERPOLATIONFILTER_LENGTH, cv_modfilter.value); openmpt_module_set_render_param(openmpt_mhandle, OPENMPT_MODULE_RENDER_INTERPOLATIONFILTER_LENGTH, cv_modfilter.value);
} }
#endif

View File

@ -277,6 +277,7 @@
<ClInclude Include="..\r_local.h" /> <ClInclude Include="..\r_local.h" />
<ClInclude Include="..\r_main.h" /> <ClInclude Include="..\r_main.h" />
<ClInclude Include="..\r_plane.h" /> <ClInclude Include="..\r_plane.h" />
<ClInclude Include="..\r_portal.h" />
<ClInclude Include="..\r_segs.h" /> <ClInclude Include="..\r_segs.h" />
<ClInclude Include="..\r_sky.h" /> <ClInclude Include="..\r_sky.h" />
<ClInclude Include="..\r_splats.h" /> <ClInclude Include="..\r_splats.h" />
@ -430,6 +431,7 @@
</ClCompile> </ClCompile>
<ClCompile Include="..\r_main.c" /> <ClCompile Include="..\r_main.c" />
<ClCompile Include="..\r_plane.c" /> <ClCompile Include="..\r_plane.c" />
<ClCompile Include="..\r_portal.c" />
<ClCompile Include="..\r_segs.c" /> <ClCompile Include="..\r_segs.c" />
<ClCompile Include="..\r_sky.c" /> <ClCompile Include="..\r_sky.c" />
<ClCompile Include="..\r_splats.c" /> <ClCompile Include="..\r_splats.c" />

View File

@ -453,6 +453,9 @@
<ClInclude Include="..\hardware\hw_clip.h"> <ClInclude Include="..\hardware\hw_clip.h">
<Filter>Hw_Hardware</Filter> <Filter>Hw_Hardware</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\r_portal.h">
<Filter>R_Rend</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<CustomBuild Include="..\tmap.nas"> <CustomBuild Include="..\tmap.nas">
@ -894,6 +897,10 @@
<ClCompile Include="..\hardware\hw_clip.c"> <ClCompile Include="..\hardware\hw_clip.c">
<Filter>Hw_Hardware</Filter> <Filter>Hw_Hardware</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\apng.c" />
<ClCompile Include="..\r_portal.c">
<Filter>R_Rend</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Image Include="Srb2SDL.ico"> <Image Include="Srb2SDL.ico">

View File

@ -108,14 +108,16 @@ static UINT16 current_track;
#endif #endif
#ifdef HAVE_OPENMPT #ifdef HAVE_OPENMPT
int mod_err = OPENMPT_ERROR_OK; static int mod_err = OPENMPT_ERROR_OK;
static const char *mod_err_str; static const char *mod_err_str;
static UINT16 current_subsong; static UINT16 current_subsong;
static size_t probesize;
static int result;
#endif #endif
static void var_cleanup(void) static void var_cleanup(void)
{ {
loop_point = song_length = 0.0f; song_length = loop_point = 0.0f;
music_bytes = fading_source = fading_target =\ music_bytes = fading_source = fading_target =\
fading_timer = fading_duration = 0; fading_timer = fading_duration = 0;
@ -388,7 +390,7 @@ void *I_GetSfx(sfxinfo_t *sfx)
gme_track_info(emu, &info, 0); gme_track_info(emu, &info, 0);
len = (info->play_length * 441 / 10) << 2; len = (info->play_length * 441 / 10) << 2;
mem = malloc(len); mem = Z_Malloc(len, PU_SOUND, 0);
gme_play(emu, len >> 1, mem); gme_play(emu, len >> 1, mem);
gme_free_info(info); gme_free_info(info);
gme_delete(emu); gme_delete(emu);
@ -461,7 +463,7 @@ void *I_GetSfx(sfxinfo_t *sfx)
gme_track_info(emu, &info, 0); gme_track_info(emu, &info, 0);
len = (info->play_length * 441 / 10) << 2; len = (info->play_length * 441 / 10) << 2;
mem = malloc(len); mem = Z_Malloc(len, PU_SOUND, 0);
gme_play(emu, len >> 1, mem); gme_play(emu, len >> 1, mem);
gme_free_info(info); gme_free_info(info);
gme_delete(emu); gme_delete(emu);
@ -1112,6 +1114,36 @@ boolean I_LoadSong(char *data, size_t len)
} }
#endif #endif
#ifdef HAVE_OPENMPT
/*
If the size of the data to be checked is bigger than the recommended size (> 2048)
Let's just set the probe size to the recommended size
Otherwise let's give it the full data size
*/
if (len > openmpt_probe_file_header_get_recommended_size())
probesize = openmpt_probe_file_header_get_recommended_size();
else
probesize = len;
result = openmpt_probe_file_header(OPENMPT_PROBE_FILE_HEADER_FLAGS_DEFAULT, data, probesize, len, NULL, NULL, NULL, NULL, NULL, NULL);
if (result == OPENMPT_PROBE_FILE_HEADER_RESULT_SUCCESS) // We only cared if it succeeded, continue on if not.
{
openmpt_mhandle = openmpt_module_create_from_memory2(data, len, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
if (!openmpt_mhandle) // Failed to create module handle? Show error and return!
{
mod_err = openmpt_module_error_get_last(openmpt_mhandle);
mod_err_str = openmpt_error_string(mod_err);
CONS_Alert(CONS_ERROR, "openmpt_module_create_from_memory2: %s\n", mod_err_str);
return false;
}
else
return true; // All good and we're ready for music playback!
}
#endif
// Let's see if Mixer is able to load this.
rw = SDL_RWFromMem(data, len); rw = SDL_RWFromMem(data, len);
if (rw != NULL) if (rw != NULL)
{ {
@ -1123,40 +1155,6 @@ boolean I_LoadSong(char *data, size_t len)
return false; return false;
} }
#ifdef HAVE_OPENMPT
switch(Mix_GetMusicType(music))
{
case MUS_MODPLUG:
case MUS_MOD:
openmpt_mhandle = openmpt_module_create_from_memory2(data, len, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
if (!openmpt_mhandle)
{
mod_err = openmpt_module_error_get_last(openmpt_mhandle);
mod_err_str = openmpt_error_string(mod_err);
CONS_Alert(CONS_ERROR, "openmpt_module_create_from_memory2: %s\n", mod_err_str);
Mix_FreeMusic(music);
music = NULL;
return false;
}
else
{
Mix_FreeMusic(music);
music = NULL;
return true;
}
break;
case MUS_WAV:
case MUS_MID:
case MUS_OGG:
case MUS_MP3:
case MUS_FLAC:
Mix_HookMusic(NULL, NULL);
break;
default:
break;
}
#endif
// Find the OGG loop point. // Find the OGG loop point.
loop_point = 0.0f; loop_point = 0.0f;
song_length = 0.0f; song_length = 0.0f;

View File

@ -2308,27 +2308,31 @@ static void ST_doItemFinderIconsAndSound(void)
// Scan thinkers to find emblem mobj with these ids // Scan thinkers to find emblem mobj with these ids
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{ {
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2->type == MT_EMBLEM) if (mo2->type != MT_EMBLEM)
continue;
if (!(mo2->flags & MF_SPECIAL))
continue;
for (i = 0; i < stemblems; ++i)
{ {
if (!(mo2->flags & MF_SPECIAL)) if (mo2->health == emblems[i] + 1)
continue;
for (i = 0; i < stemblems; ++i)
{ {
if (mo2->health == emblems[i]+1) soffset = (i * 20) - ((stemblems - 1) * 10);
{
soffset = (i * 20) - ((stemblems-1) * 10);
newinterval = ST_drawEmeraldHuntIcon(mo2, itemhoming, soffset); newinterval = ST_drawEmeraldHuntIcon(mo2, itemhoming, soffset);
if (newinterval && (!interval || newinterval < interval)) if (newinterval && (!interval || newinterval < interval))
interval = newinterval; interval = newinterval;
break; break;
}
} }
} }
} }
if (!(P_AutoPause() || paused) && interval > 0 && leveltime && leveltime % interval == 0) if (!(P_AutoPause() || paused) && interval > 0 && leveltime && leveltime % interval == 0)

View File

@ -293,6 +293,7 @@
</ClCompile> </ClCompile>
<ClCompile Include="..\r_main.c" /> <ClCompile Include="..\r_main.c" />
<ClCompile Include="..\r_plane.c" /> <ClCompile Include="..\r_plane.c" />
<ClCompile Include="..\r_portal.c" />
<ClCompile Include="..\r_segs.c" /> <ClCompile Include="..\r_segs.c" />
<ClCompile Include="..\r_sky.c" /> <ClCompile Include="..\r_sky.c" />
<ClCompile Include="..\r_splats.c" /> <ClCompile Include="..\r_splats.c" />
@ -443,6 +444,7 @@
<ClInclude Include="..\r_local.h" /> <ClInclude Include="..\r_local.h" />
<ClInclude Include="..\r_main.h" /> <ClInclude Include="..\r_main.h" />
<ClInclude Include="..\r_plane.h" /> <ClInclude Include="..\r_plane.h" />
<ClInclude Include="..\r_portal.h" />
<ClInclude Include="..\r_segs.h" /> <ClInclude Include="..\r_segs.h" />
<ClInclude Include="..\r_sky.h" /> <ClInclude Include="..\r_sky.h" />
<ClInclude Include="..\r_splats.h" /> <ClInclude Include="..\r_splats.h" />

View File

@ -456,6 +456,10 @@
<ClCompile Include="..\hardware\hw_clip.c"> <ClCompile Include="..\hardware\hw_clip.c">
<Filter>Hw_Hardware</Filter> <Filter>Hw_Hardware</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\apng.c" />
<ClCompile Include="..\r_portal.c">
<Filter>R_Rend</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="afxres.h"> <ClInclude Include="afxres.h">
@ -857,6 +861,10 @@
<ClInclude Include="..\hardware\hw_clip.h"> <ClInclude Include="..\hardware\hw_clip.h">
<Filter>Hw_Hardware</Filter> <Filter>Hw_Hardware</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\apng.h" />
<ClInclude Include="..\r_portal.h">
<Filter>R_Rend</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Image Include="Srb2win.ico"> <Image Include="Srb2win.ico">