Fix segfaults when P_RemoveMobj is called from MobjSpawn hook

This commit is contained in:
Gustaf Alhäll 2023-04-30 12:43:31 +02:00
parent e5a1fee759
commit 4967c296ab
No known key found for this signature in database
GPG key ID: 6C1F67D690CDEDFD
10 changed files with 1670 additions and 950 deletions

View file

@ -613,6 +613,9 @@ void B_HandleFlightIndicator(player_t *player)
// otherwise, spawn it
P_SetTarget(&tails->hnext, P_SpawnMobjFromMobj(tails, 0, 0, 0, MT_OVERLAY));
if (P_MobjWasRemoved(tails->hnext))
return; // we can't spawn one, so it can't exist
P_SetTarget(&tails->hnext->target, tails);
P_SetTarget(&tails->hnext->hprev, tails);
P_SetMobjState(tails->hnext, S_FLIGHTINDICATOR);

View file

@ -795,32 +795,40 @@ void G_GhostTicker(void)
if (type == MT_GHOST)
{
mobj = P_SpawnGhostMobj(g->mo); // does a large portion of the work for us
mobj->frame = (mobj->frame & ~FF_FRAMEMASK)|tr_trans60<<FF_TRANSSHIFT; // P_SpawnGhostMobj sets trans50, we want trans60
if (!P_MobjWasRemoved(mobj))
mobj->frame = (mobj->frame & ~FF_FRAMEMASK)|tr_trans60<<FF_TRANSSHIFT; // P_SpawnGhostMobj sets trans50, we want trans60
}
else
{
mobj = P_SpawnMobjFromMobj(g->mo, 0, 0, -FixedDiv(FixedMul(g->mo->info->height, g->mo->scale) - g->mo->height,3*FRACUNIT), MT_THOK);
mobj->sprite = states[mobjinfo[type].spawnstate].sprite;
mobj->frame = (states[mobjinfo[type].spawnstate].frame & FF_FRAMEMASK) | tr_trans60<<FF_TRANSSHIFT;
mobj->color = g->mo->color;
mobj->skin = g->mo->skin;
P_SetScale(mobj, (mobj->destscale = g->mo->scale));
if (type == MT_THOK) // spintrail-specific modification for MT_THOK
if (!P_MobjWasRemoved(mobj))
{
mobj->frame = FF_TRANS80;
mobj->fuse = mobj->tics;
mobj->sprite = states[mobjinfo[type].spawnstate].sprite;
mobj->frame = (states[mobjinfo[type].spawnstate].frame & FF_FRAMEMASK) | tr_trans60<<FF_TRANSSHIFT;
mobj->color = g->mo->color;
mobj->skin = g->mo->skin;
P_SetScale(mobj, (mobj->destscale = g->mo->scale));
if (type == MT_THOK) // spintrail-specific modification for MT_THOK
{
mobj->frame = FF_TRANS80;
mobj->fuse = mobj->tics;
}
mobj->tics = -1; // nope.
}
mobj->tics = -1; // nope.
}
mobj->floorz = mobj->z;
mobj->ceilingz = mobj->z+mobj->height;
P_UnsetThingPosition(mobj);
mobj->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; // make an ATTEMPT to curb crazy SOCs fucking stuff up...
P_SetThingPosition(mobj);
if (!mobj->fuse)
mobj->fuse = 8;
P_SetTarget(&mobj->target, g->mo);
if (!P_MobjWasRemoved(mobj))
{
mobj->floorz = mobj->z;
mobj->ceilingz = mobj->z+mobj->height;
P_UnsetThingPosition(mobj);
mobj->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; // make an ATTEMPT to curb crazy SOCs fucking stuff up...
P_SetThingPosition(mobj);
if (!mobj->fuse)
mobj->fuse = 8;
P_SetTarget(&mobj->target, g->mo);
}
}
}
if (xziptic & EZT_HIT)
@ -844,6 +852,8 @@ void G_GhostTicker(void)
|| health != 0 || i >= 4) // only spawn for the first 4 hits per frame, to prevent ghosts from splode-spamming too bad.
continue;
poof = P_SpawnMobj(x, y, z, MT_GHOST);
if (P_MobjWasRemoved(poof))
continue;
poof->angle = angle;
poof->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; // make an ATTEMPT to curb crazy SOCs fucking stuff up...
poof->health = 0;
@ -889,19 +899,22 @@ void G_GhostTicker(void)
if (follow)
P_RemoveMobj(follow);
P_SetTarget(&follow, P_SpawnMobjFromMobj(g->mo, 0, 0, 0, MT_GHOST));
P_SetTarget(&follow->tracer, g->mo);
follow->tics = -1;
temp = READINT16(g->p)<<FRACBITS;
follow->height = FixedMul(follow->scale, temp);
if (!P_MobjWasRemoved(follow))
{
P_SetTarget(&follow->tracer, g->mo);
follow->tics = -1;
temp = READINT16(g->p)<<FRACBITS;
follow->height = FixedMul(follow->scale, temp);
if (followtic & FZT_LINKDRAW)
follow->flags2 |= MF2_LINKDRAW;
if (followtic & FZT_LINKDRAW)
follow->flags2 |= MF2_LINKDRAW;
if (followtic & FZT_COLORIZED)
follow->colorized = true;
if (followtic & FZT_COLORIZED)
follow->colorized = true;
if (followtic & FZT_SKIN)
follow->skin = &skins[READUINT8(g->p)];
if (followtic & FZT_SKIN)
follow->skin = &skins[READUINT8(g->p)];
}
}
if (follow)
{
@ -1094,28 +1107,35 @@ void G_ReadMetalTic(mobj_t *metal)
else
{
mobj = P_SpawnMobjFromMobj(metal, 0, 0, -FixedDiv(FixedMul(metal->info->height, metal->scale) - metal->height,3*FRACUNIT), MT_THOK);
mobj->sprite = states[mobjinfo[type].spawnstate].sprite;
mobj->frame = states[mobjinfo[type].spawnstate].frame;
mobj->angle = metal->angle;
mobj->color = metal->color;
mobj->skin = metal->skin;
P_SetScale(mobj, (mobj->destscale = metal->scale));
if (type == MT_THOK) // spintrail-specific modification for MT_THOK
if (!P_MobjWasRemoved(mobj))
{
mobj->frame = FF_TRANS70;
mobj->fuse = mobj->tics;
mobj->sprite = states[mobjinfo[type].spawnstate].sprite;
mobj->frame = states[mobjinfo[type].spawnstate].frame;
mobj->angle = metal->angle;
mobj->color = metal->color;
mobj->skin = metal->skin;
P_SetScale(mobj, (mobj->destscale = metal->scale));
if (type == MT_THOK) // spintrail-specific modification for MT_THOK
{
mobj->frame = FF_TRANS70;
mobj->fuse = mobj->tics;
}
mobj->tics = -1; // nope.
}
mobj->tics = -1; // nope.
}
mobj->floorz = mobj->z;
mobj->ceilingz = mobj->z+mobj->height;
P_UnsetThingPosition(mobj);
mobj->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; // make an ATTEMPT to curb crazy SOCs fucking stuff up...
P_SetThingPosition(mobj);
if (!mobj->fuse)
mobj->fuse = 8;
P_SetTarget(&mobj->target, metal);
if (!P_MobjWasRemoved(mobj))
{
mobj->floorz = mobj->z;
mobj->ceilingz = mobj->z+mobj->height;
P_UnsetThingPosition(mobj);
mobj->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; // make an ATTEMPT to curb crazy SOCs fucking stuff up...
P_SetThingPosition(mobj);
if (!mobj->fuse)
mobj->fuse = 8;
P_SetTarget(&mobj->target, metal);
}
}
}
if (xziptic & EZT_SPRITE)
@ -1137,19 +1157,22 @@ void G_ReadMetalTic(mobj_t *metal)
if (follow)
P_RemoveMobj(follow);
P_SetTarget(&follow, P_SpawnMobjFromMobj(metal, 0, 0, 0, MT_GHOST));
P_SetTarget(&follow->tracer, metal);
follow->tics = -1;
temp = READINT16(metal_p)<<FRACBITS;
follow->height = FixedMul(follow->scale, temp);
if (!P_MobjWasRemoved(follow))
{
P_SetTarget(&follow->tracer, metal);
follow->tics = -1;
temp = READINT16(metal_p)<<FRACBITS;
follow->height = FixedMul(follow->scale, temp);
if (followtic & FZT_LINKDRAW)
follow->flags2 |= MF2_LINKDRAW;
if (followtic & FZT_LINKDRAW)
follow->flags2 |= MF2_LINKDRAW;
if (followtic & FZT_COLORIZED)
follow->colorized = true;
if (followtic & FZT_COLORIZED)
follow->colorized = true;
if (followtic & FZT_SKIN)
follow->skin = &skins[READUINT8(metal_p)];
if (followtic & FZT_SKIN)
follow->skin = &skins[READUINT8(metal_p)];
}
}
if (follow)
{
@ -2218,7 +2241,9 @@ void G_AddGhost(char *defdemoname)
{ // A bit more complex than P_SpawnPlayer because ghosts aren't solid and won't just push themselves out of the ceiling.
fixed_t z,f,c;
fixed_t offset = mthing->z << FRACBITS;
gh->mo = P_SpawnMobj(mthing->x << FRACBITS, mthing->y << FRACBITS, 0, MT_GHOST);
P_SetTarget(&gh->mo, P_SpawnMobj(mthing->x << FRACBITS, mthing->y << FRACBITS, 0, MT_GHOST));
if (P_MobjWasRemoved(gh->mo))
return;
gh->mo->angle = FixedAngle(mthing->angle << FRACBITS);
f = gh->mo->floorz;
c = gh->mo->ceilingz - mobjinfo[MT_PLAYER].height;

File diff suppressed because it is too large Load diff

View file

@ -1921,6 +1921,9 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover)
for (c = topz; c > bottomz; c -= spacing)
{
spawned = P_SpawnMobj(a, b, c, type);
if (P_MobjWasRemoved(spawned))
continue;
spawned->angle += P_RandomKey(36)*ANG10; // irrelevant for default objects but might make sense for some custom ones
if (fromcenter)

View file

@ -199,6 +199,9 @@ void P_DoNightsScore(player_t *player)
player->linktimer = nightslinktics;
}
if (P_MobjWasRemoved(dummymo))
return;
if (player->linkcount < 10)
{
if (player->bonustime)
@ -1214,7 +1217,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
{
// A flicky orbits us now
mobj_t *flickyobj = P_SpawnMobj(toucher->x, toucher->y, toucher->z + toucher->info->height, MT_NIGHTOPIANHELPER);
P_SetTarget(&flickyobj->target, toucher);
if (!P_MobjWasRemoved(flickyobj))
P_SetTarget(&flickyobj->target, toucher);
player->powers[pw_nights_helper] = (UINT16)special->info->speed;
}
@ -1225,7 +1229,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (playeringame[i] && players[i].mo && players[i].powers[pw_carry] == CR_NIGHTSMODE) {
players[i].powers[pw_nights_helper] = (UINT16)special->info->speed;
flickyobj = P_SpawnMobj(players[i].mo->x, players[i].mo->y, players[i].mo->z + players[i].mo->info->height, MT_NIGHTOPIANHELPER);
P_SetTarget(&flickyobj->target, players[i].mo);
if (!P_MobjWasRemoved(flickyobj))
P_SetTarget(&flickyobj->target, players[i].mo);
}
if (special->info->deathsound != sfx_None)
S_StartSound(NULL, special->info->deathsound);
@ -1734,9 +1739,12 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (!player->bot && player->bot != BOT_MPAI && special->fuse <= TICRATE && player->powers[pw_carry] != CR_MINECART && !(player->powers[pw_ignorelatch] & (1<<15)))
{
mobj_t *mcart = P_SpawnMobj(special->x, special->y, special->z, MT_MINECART);
P_SetTarget(&mcart->target, toucher);
mcart->angle = toucher->angle = player->drawangle = special->angle;
mcart->friction = FRACUNIT;
if (!P_MobjWasRemoved(mcart))
{
P_SetTarget(&mcart->target, toucher);
mcart->angle = toucher->angle = player->drawangle = special->angle;
mcart->friction = FRACUNIT;
}
P_ResetPlayer(player);
player->pflags |= PF_JUMPDOWN;
@ -2506,7 +2514,8 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
break;
}
P_SetMobjState(scoremobj, scorestate);
if (!P_MobjWasRemoved(scoremobj))
P_SetMobjState(scoremobj, scorestate);
source->player->scoreadd = locscoreadd;
}
@ -2667,6 +2676,8 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
mo = P_SpawnMobj(inflictor->x + inflictor->momx, inflictor->y + inflictor->momy, inflictor->z + (inflictor->height / 2) + inflictor->momz, MT_EXTRALARGEBUBBLE);
else
mo = P_SpawnMobj(target->x, target->y, target->z, MT_EXTRALARGEBUBBLE);
if (P_MobjWasRemoved(mo))
break;
mo->destscale = target->scale;
P_SetScale(mo, mo->destscale);
P_SetMobjState(mo, mo->info->raisestate);
@ -2745,8 +2756,11 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
mo->angle = FixedAngle((P_RandomKey(36)*10)<<FRACBITS);
mo2 = P_SpawnMobjFromMobj(mo, 0, 0, 0, MT_BOSSJUNK);
mo2->angle = mo->angle;
P_SetMobjState(mo2, S_BOSSSEBH2);
if (!P_MobjWasRemoved(mo2))
{
mo2->angle = mo->angle;
P_SetMobjState(mo2, S_BOSSSEBH2);
}
if (++i == 2) // we've already removed 2 of these, let's stop now
break;
@ -2845,7 +2859,10 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
if (flip)
momz *= -1;
#define makechunk(angtweak, xmov, ymov) \
do {\
chunk = P_SpawnMobjFromMobj(target, 0, 0, 0, MT_SPIKE);\
if (P_MobjWasRemoved(chunk))\
break;\
P_SetMobjState(chunk, target->info->xdeathstate);\
chunk->health = 0;\
chunk->angle = angtweak;\
@ -2855,7 +2872,8 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
chunk->y += ymov;\
P_SetThingPosition(chunk);\
P_InstaThrust(chunk,chunk->angle, 4*scale);\
chunk->momz = momz
chunk->momz = momz;\
} while (0)
makechunk(ang + ANGLE_180, -xoffs, -yoffs);
makechunk(ang, xoffs, yoffs);
@ -2868,20 +2886,23 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
momz *= -1;
chunk = P_SpawnMobjFromMobj(target, 0, 0, 0, MT_SPIKE);
P_SetMobjState(chunk, target->info->deathstate);
chunk->health = 0;
chunk->angle = ang + ANGLE_180;
P_UnsetThingPosition(chunk);
chunk->flags = MF_NOCLIP;
chunk->x -= xoffs;
chunk->y -= yoffs;
if (flip)
chunk->z -= 12*scale;
else
chunk->z += 12*scale;
P_SetThingPosition(chunk);
P_InstaThrust(chunk, chunk->angle, 2*scale);
chunk->momz = momz;
if (!P_MobjWasRemoved(chunk))
{
P_SetMobjState(chunk, target->info->deathstate);
chunk->health = 0;
chunk->angle = ang + ANGLE_180;
P_UnsetThingPosition(chunk);
chunk->flags = MF_NOCLIP;
chunk->x -= xoffs;
chunk->y -= yoffs;
if (flip)
chunk->z -= 12*scale;
else
chunk->z += 12*scale;
P_SetThingPosition(chunk);
P_InstaThrust(chunk, chunk->angle, 2*scale);
chunk->momz = momz;
}
P_SetMobjState(target, target->info->deathstate);
target->health = 0;
@ -2890,7 +2911,10 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
target->flags = MF_NOCLIP;
target->x += xoffs;
target->y += yoffs;
target->z = chunk->z;
if (flip)
target->z -= 12*scale;
else
target->z += 12*scale;
P_SetThingPosition(target);
P_InstaThrust(target, target->angle, 2*scale);
target->momz = momz;
@ -2913,21 +2937,25 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
sprflip = P_RandomChance(FRACUNIT/2);
#define makechunk(angtweak, xmov, ymov) \
chunk = P_SpawnMobjFromMobj(target, 0, 0, 0, MT_WALLSPIKE);\
P_SetMobjState(chunk, target->info->xdeathstate);\
chunk->health = 0;\
chunk->angle = target->angle;\
P_UnsetThingPosition(chunk);\
chunk->flags = MF_NOCLIP;\
chunk->x += xmov - forwardxoffs;\
chunk->y += ymov - forwardyoffs;\
P_SetThingPosition(chunk);\
P_InstaThrust(chunk, angtweak, 4*scale);\
chunk->momz = P_RandomRange(5, 7)*scale;\
if (flip)\
chunk->momz *= -1;\
if (sprflip)\
chunk->frame |= FF_VERTICALFLIP
do {\
chunk = P_SpawnMobjFromMobj(target, 0, 0, 0, MT_WALLSPIKE);\
if (P_MobjWasRemoved(chunk))\
break;\
P_SetMobjState(chunk, target->info->xdeathstate);\
chunk->health = 0;\
chunk->angle = target->angle;\
P_UnsetThingPosition(chunk);\
chunk->flags = MF_NOCLIP;\
chunk->x += xmov - forwardxoffs;\
chunk->y += ymov - forwardyoffs;\
P_SetThingPosition(chunk);\
P_InstaThrust(chunk, angtweak, 4*scale);\
chunk->momz = P_RandomRange(5, 7)*scale;\
if (flip)\
chunk->momz *= -1;\
if (sprflip)\
chunk->frame |= FF_VERTICALFLIP;\
} while (0)
makechunk(ang + ANGLE_180, -xoffs, -yoffs);
sprflip = !sprflip;
@ -2939,21 +2967,23 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
sprflip = P_RandomChance(FRACUNIT/2);
chunk = P_SpawnMobjFromMobj(target, 0, 0, 0, MT_WALLSPIKE);
P_SetMobjState(chunk, target->info->deathstate);
chunk->health = 0;
chunk->angle = target->angle;
P_UnsetThingPosition(chunk);
chunk->flags = MF_NOCLIP;
chunk->x += forwardxoffs - xoffs;
chunk->y += forwardyoffs - yoffs;
P_SetThingPosition(chunk);
P_InstaThrust(chunk, ang + ANGLE_180, 2*scale);
chunk->momz = P_RandomRange(5, 7)*scale;
if (flip)
chunk->momz *= -1;
if (sprflip)
chunk->frame |= FF_VERTICALFLIP;
if (!P_MobjWasRemoved(chunk))
{
P_SetMobjState(chunk, target->info->deathstate);
chunk->health = 0;
chunk->angle = target->angle;
P_UnsetThingPosition(chunk);
chunk->flags = MF_NOCLIP;
chunk->x += forwardxoffs - xoffs;
chunk->y += forwardyoffs - yoffs;
P_SetThingPosition(chunk);
P_InstaThrust(chunk, ang + ANGLE_180, 2*scale);
chunk->momz = P_RandomRange(5, 7)*scale;
if (flip)
chunk->momz *= -1;
if (sprflip)
chunk->frame |= FF_VERTICALFLIP;
}
P_SetMobjState(target, target->info->deathstate);
target->health = 0;
@ -3829,6 +3859,8 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings)
z += player->mo->height - mobjinfo[objType].height;
mo = P_SpawnMobj(player->mo->x, player->mo->y, z, objType);
if (P_MobjWasRemoved(mo))
continue;
mo->fuse = 8*TICRATE;
P_SetTarget(&mo->target, player->mo);
@ -3962,6 +3994,9 @@ void P_PlayerWeaponPanelBurst(player_t *player)
z += player->mo->height - mobjinfo[weptype].height;
mo = P_SpawnMobj(player->mo->x, player->mo->y, z, weptype);
if (P_MobjWasRemoved(mo))
continue;
mo->reactiontime = ammoamt;
mo->flags2 |= MF2_DONTRESPAWN;
mo->flags &= ~(MF_NOGRAVITY|MF_NOCLIPHEIGHT);
@ -3995,13 +4030,13 @@ void P_PlayerWeaponAmmoBurst(player_t *player)
mobj_t *mo;
angle_t fa;
fixed_t ns;
INT32 i = 0;
INT32 i;
fixed_t z;
mobjtype_t weptype = 0;
powertype_t power = 0;
while (true)
for (i = 0;; i++)
{
if (player->powers[pw_bouncering])
{
@ -4046,6 +4081,8 @@ void P_PlayerWeaponAmmoBurst(player_t *player)
z += player->mo->height - mobjinfo[weptype].height;
mo = P_SpawnMobj(player->mo->x, player->mo->y, z, weptype);
if (P_MobjWasRemoved(mo))
continue;
mo->health = player->powers[power];
mo->flags2 |= MF2_DONTRESPAWN;
mo->flags &= ~(MF_NOGRAVITY|MF_NOCLIPHEIGHT);
@ -4071,8 +4108,6 @@ void P_PlayerWeaponAmmoBurst(player_t *player)
if (i & 1)
P_SetObjectMomZ(mo, 3*FRACUNIT, true);
i++;
}
}
@ -4097,45 +4132,50 @@ void P_PlayerWeaponPanelOrAmmoBurst(player_t *player)
player->ringweapons &= ~rwflag; \
SETUP_DROP(pickup) \
mo = P_SpawnMobj(player->mo->x, player->mo->y, z, pickup); \
mo->reactiontime = 0; \
mo->flags2 |= MF2_DONTRESPAWN; \
mo->flags &= ~(MF_NOGRAVITY|MF_NOCLIPHEIGHT); \
P_SetTarget(&mo->target, player->mo); \
mo->fuse = 12*TICRATE; \
mo->destscale = player->mo->scale; \
P_SetScale(mo, player->mo->scale); \
mo->momx = FixedMul(FINECOSINE(fa),ns); \
if (!(twodlevel || (player->mo->flags2 & MF2_TWOD))) \
mo->momy = FixedMul(FINESINE(fa),ns); \
P_SetObjectMomZ(mo, 4*FRACUNIT, false); \
if (i & 1) \
P_SetObjectMomZ(mo, 4*FRACUNIT, true); \
if (player->mo->eflags & MFE_VERTICALFLIP) \
mo->flags2 |= MF2_OBJECTFLIP; \
++i; \
if (!P_MobjWasRemoved(mo)) \
{ \
mo->reactiontime = 0; \
mo->flags2 |= MF2_DONTRESPAWN; \
mo->flags &= ~(MF_NOGRAVITY|MF_NOCLIPHEIGHT); \
P_SetTarget(&mo->target, player->mo); \
mo->fuse = 12*TICRATE; \
mo->destscale = player->mo->scale; \
P_SetScale(mo, player->mo->scale); \
mo->momx = FixedMul(FINECOSINE(fa),ns); \
if (!(twodlevel || (player->mo->flags2 & MF2_TWOD))) \
mo->momy = FixedMul(FINESINE(fa),ns); \
P_SetObjectMomZ(mo, 4*FRACUNIT, false); \
if (i & 1) \
P_SetObjectMomZ(mo, 4*FRACUNIT, true); \
if (player->mo->eflags & MFE_VERTICALFLIP) \
mo->flags2 |= MF2_OBJECTFLIP; \
} \
} \
else if (player->powers[power] > 0) \
{ \
SETUP_DROP(ammo) \
mo = P_SpawnMobj(player->mo->x, player->mo->y, z, ammo); \
mo->health = player->powers[power]; \
mo->flags2 |= MF2_DONTRESPAWN; \
mo->flags &= ~(MF_NOGRAVITY|MF_NOCLIPHEIGHT); \
P_SetTarget(&mo->target, player->mo); \
mo->fuse = 12*TICRATE; \
mo->destscale = player->mo->scale; \
P_SetScale(mo, player->mo->scale); \
mo->momx = FixedMul(FINECOSINE(fa),ns); \
if (!(twodlevel || (player->mo->flags2 & MF2_TWOD))) \
mo->momy = FixedMul(FINESINE(fa),ns); \
P_SetObjectMomZ(mo, 3*FRACUNIT, false); \
if (i & 1) \
P_SetObjectMomZ(mo, 3*FRACUNIT, true); \
if (player->mo->eflags & MFE_VERTICALFLIP) \
mo->flags2 |= MF2_OBJECTFLIP; \
player->powers[power] = 0; \
++i; \
}
if (!P_MobjWasRemoved(mo)) \
{ \
mo->health = player->powers[power]; \
mo->flags2 |= MF2_DONTRESPAWN; \
mo->flags &= ~(MF_NOGRAVITY|MF_NOCLIPHEIGHT); \
P_SetTarget(&mo->target, player->mo); \
mo->fuse = 12*TICRATE; \
mo->destscale = player->mo->scale; \
P_SetScale(mo, player->mo->scale); \
mo->momx = FixedMul(FINECOSINE(fa),ns); \
if (!(twodlevel || (player->mo->flags2 & MF2_TWOD))) \
mo->momy = FixedMul(FINESINE(fa),ns); \
P_SetObjectMomZ(mo, 3*FRACUNIT, false); \
if (i & 1) \
P_SetObjectMomZ(mo, 3*FRACUNIT, true); \
if (player->mo->eflags & MFE_VERTICALFLIP) \
mo->flags2 |= MF2_OBJECTFLIP; \
player->powers[power] = 0; \
} \
} \
++i
DROP_WEAPON(RW_BOUNCE, MT_BOUNCEPICKUP, MT_BOUNCERING, pw_bouncering);
DROP_WEAPON(RW_RAIL, MT_RAILPICKUP, MT_RAILRING, pw_railring);
@ -4259,23 +4299,26 @@ void P_PlayerEmeraldBurst(player_t *player, boolean toss)
momy = 0;
mo = P_SpawnMobj(player->mo->x, player->mo->y, z, MT_FLINGEMERALD);
mo->health = 1;
mo->threshold = stoneflag;
mo->flags2 |= (MF2_DONTRESPAWN|MF2_SLIDEPUSH);
mo->flags &= ~(MF_NOGRAVITY|MF_NOCLIPHEIGHT);
P_SetTarget(&mo->target, player->mo);
mo->fuse = 12*TICRATE;
P_SetMobjState(mo, statenum);
mo->momx = momx;
mo->momy = momy;
P_SetObjectMomZ(mo, 3*FRACUNIT, false);
if (player->mo->eflags & MFE_VERTICALFLIP)
if (!P_MobjWasRemoved(mo))
{
mo->momz = -mo->momz;
mo->flags2 |= MF2_OBJECTFLIP;
mo->health = 1;
mo->threshold = stoneflag;
mo->flags2 |= (MF2_DONTRESPAWN|MF2_SLIDEPUSH);
mo->flags &= ~(MF_NOGRAVITY|MF_NOCLIPHEIGHT);
P_SetTarget(&mo->target, player->mo);
mo->fuse = 12*TICRATE;
P_SetMobjState(mo, statenum);
mo->momx = momx;
mo->momy = momy;
P_SetObjectMomZ(mo, 3*FRACUNIT, false);
if (player->mo->eflags & MFE_VERTICALFLIP)
{
mo->momz = -mo->momz;
mo->flags2 |= MF2_OBJECTFLIP;
}
}
if (toss)
@ -4303,6 +4346,8 @@ void P_PlayerFlagBurst(player_t *player, boolean toss)
type = MT_BLUEFLAG;
flag = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, type);
if (P_MobjWasRemoved(flag))
return;
if (player->mo->eflags & MFE_VERTICALFLIP)
{

View file

@ -282,7 +282,7 @@ mobjtype_t P_GetMobjtype(UINT16 mthingtype);
void P_RespawnSpecials(void);
mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type);
mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...);
void P_RecalcPrecipInSector(sector_t *sector);
void P_PrecipitationEffects(void);

View file

@ -2861,6 +2861,8 @@ boolean P_CheckMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
{
boolean moveok;
mobj_t *hack = P_SpawnMobjFromMobj(thing, 0, 0, 0, MT_RAY);
if (P_MobjWasRemoved(hack))
return false;
hack->radius = thing->radius;
hack->height = thing->height;

File diff suppressed because it is too large Load diff

View file

@ -1243,6 +1243,8 @@ boolean Polyobj_rotate(polyobj_t *po, angle_t delta, boolean turnplayers, boolea
// Returns NULL if no such polyobject exists.
polyobj_t *Polyobj_GetForNum(INT32 id)
{
if (numPolyObjects == 0)
return NULL;
INT32 curidx = PolyObjects[id % numPolyObjects].first;
while (curidx != numPolyObjects && PolyObjects[curidx].id != id)

View file

@ -394,6 +394,8 @@ void P_GiveFinishFlags(player_t *player)
fixed_t xoffs = FINECOSINE(fa);
fixed_t yoffs = FINESINE(fa);
mobj_t* flag = P_SpawnMobjFromMobj(player->mo, xoffs, yoffs, 0, MT_FINISHFLAG);
if (P_MobjWasRemoved(flag))
continue;
flag->angle = angle;
angle += FixedAngle(120*FRACUNIT);
@ -1826,6 +1828,9 @@ void P_SpawnShieldOrb(player_t *player)
}
shieldobj = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, orbtype);
if (P_MobjWasRemoved(shieldobj))
return;
shieldobj->flags2 |= MF2_SHIELD;
P_SetTarget(&shieldobj->target, player->mo);
if ((player->powers[pw_shield] & SH_NOSTACK) == SH_PINK)
@ -1840,21 +1845,30 @@ void P_SpawnShieldOrb(player_t *player)
if (shieldobj->info->seestate)
{
ov = P_SpawnMobj(shieldobj->x, shieldobj->y, shieldobj->z, MT_OVERLAY);
P_SetTarget(&ov->target, shieldobj);
P_SetMobjState(ov, shieldobj->info->seestate);
P_SetTarget(&shieldobj->tracer, ov);
if (!P_MobjWasRemoved(ov))
{
P_SetTarget(&ov->target, shieldobj);
P_SetMobjState(ov, shieldobj->info->seestate);
P_SetTarget(&shieldobj->tracer, ov);
}
}
if (shieldobj->info->meleestate)
{
ov = P_SpawnMobj(shieldobj->x, shieldobj->y, shieldobj->z, MT_OVERLAY);
P_SetTarget(&ov->target, shieldobj);
P_SetMobjState(ov, shieldobj->info->meleestate);
if (!P_MobjWasRemoved(ov))
{
P_SetTarget(&ov->target, shieldobj);
P_SetMobjState(ov, shieldobj->info->meleestate);
}
}
if (shieldobj->info->missilestate)
{
ov = P_SpawnMobj(shieldobj->x, shieldobj->y, shieldobj->z, MT_OVERLAY);
P_SetTarget(&ov->target, shieldobj);
P_SetMobjState(ov, shieldobj->info->missilestate);
if (!P_MobjWasRemoved(ov))
{
P_SetTarget(&ov->target, shieldobj);
P_SetMobjState(ov, shieldobj->info->missilestate);
}
}
if (player->powers[pw_shield] & SH_FORCE)
{
@ -1950,6 +1964,8 @@ void P_SetPower(player_t *player, powertype_t power, UINT16 value)
mobj_t *P_SpawnGhostMobj(mobj_t *mobj)
{
mobj_t *ghost = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_GHOST);
if (P_MobjWasRemoved(ghost))
return NULL;
P_SetTarget(&ghost->target, mobj);
@ -1992,9 +2008,12 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj)
if (mobj->player && mobj->player->followmobj)
{
mobj_t *ghost2 = P_SpawnGhostMobj(mobj->player->followmobj);
P_SetTarget(&ghost2->tracer, ghost);
P_SetTarget(&ghost->tracer, ghost2);
ghost2->flags2 |= (mobj->player->followmobj->flags2 & MF2_LINKDRAW);
if (!P_MobjWasRemoved(ghost2))
{
P_SetTarget(&ghost2->tracer, ghost);
P_SetTarget(&ghost->tracer, ghost2);
ghost2->flags2 |= (mobj->player->followmobj->flags2 & MF2_LINKDRAW);
}
}
// Copy interpolation data :)
@ -2043,6 +2062,8 @@ void P_SpawnThokMobj(player_t *player)
zheight = player->mo->ceilingz - FixedMul(mobjinfo[type].height, player->mo->scale);
mobj = P_SpawnMobj(player->mo->x, player->mo->y, zheight, type);
if (P_MobjWasRemoved(mobj))
return;
// set to player's angle, just in case
mobj->angle = player->drawangle;
@ -2066,7 +2087,8 @@ void P_SpawnThokMobj(player_t *player)
}
}
P_SetTarget(&mobj->target, player->mo); // the one thing P_SpawnGhostMobj doesn't do
if (!P_MobjWasRemoved(mobj))
P_SetTarget(&mobj->target, player->mo); // the one thing P_SpawnGhostMobj doesn't do
G_GhostAddThok();
}
@ -2104,6 +2126,8 @@ void P_SpawnSpinMobj(player_t *player, mobjtype_t type)
zheight = player->mo->ceilingz - FixedMul(mobjinfo[type].height, player->mo->scale);
mobj = P_SpawnMobj(player->mo->x, player->mo->y, zheight, type);
if (P_MobjWasRemoved(mobj))
return;
// set to player's angle, just in case
mobj->angle = player->drawangle;
@ -2128,7 +2152,8 @@ void P_SpawnSpinMobj(player_t *player, mobjtype_t type)
}
}
P_SetTarget(&mobj->target, player->mo); // the one thing P_SpawnGhostMobj doesn't do
if (!P_MobjWasRemoved(mobj))
P_SetTarget(&mobj->target, player->mo); // the one thing P_SpawnGhostMobj doesn't do
}
/** Called when \p player finishes the level.
@ -2352,15 +2377,18 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff)
while (i < 5)
{
missile = P_SpawnMobjFromMobj(player->mo, xo, yo, zo, type);
P_SetTarget(&missile->target, player->mo);
missile->angle = throwang + player->drawangle;
P_Thrust(missile, player->drawangle + ANGLE_90,
P_ReturnThrustY(missile, throwang, mu)); // side to side component
P_Thrust(missile, player->drawangle, mu2); // forward component
P_SetObjectMomZ(missile, (4 + ((i&1)<<1))*FRACUNIT, true);
missile->momz += player->mo->pmomz;
missile->fuse = TICRATE/2;
missile->extravalue2 = ev;
if (!P_MobjWasRemoved(missile))
{
P_SetTarget(&missile->target, player->mo);
missile->angle = throwang + player->drawangle;
P_Thrust(missile, player->drawangle + ANGLE_90,
P_ReturnThrustY(missile, throwang, mu)); // side to side component
P_Thrust(missile, player->drawangle, mu2); // forward component
P_SetObjectMomZ(missile, (4 + ((i&1)<<1))*FRACUNIT, true);
missile->momz += player->mo->pmomz;
missile->fuse = TICRATE/2;
missile->extravalue2 = ev;
}
i++;
throwang += ANG30;
@ -2912,24 +2940,29 @@ static void P_CheckUnderwaterAndSpaceTimer(player_t *player)
: player->mo->z + player->mo->height + FixedMul(8*FRACUNIT, FixedMul(player->mo->scale, player->shieldscale));
mobj_t *numbermobj = P_SpawnMobj(player->mo->x, player->mo->y, height, MT_DROWNNUMBERS);
timeleft /= (2*TICRATE); // To be strictly accurate it'd need to be ((timeleft/TICRATE) - 1)/2, but integer division rounds down for us
if (player->charflags & SF_MACHINE)
if (!P_MobjWasRemoved(numbermobj))
{
S_StartSound(player->mo, sfx_buzz1);
timeleft += 6;
timeleft /= (2*TICRATE); // To be strictly accurate it'd need to be ((timeleft/TICRATE) - 1)/2, but integer division rounds down for us
if (player->charflags & SF_MACHINE)
{
S_StartSound(player->mo, sfx_buzz1);
timeleft += 6;
}
else
S_StartSound(player->mo, sfx_dwnind);
if (!P_MobjWasRemoved(numbermobj))
{
if (timeleft) // Don't waste time setting the state if the time is 0.
P_SetMobjState(numbermobj, numbermobj->info->spawnstate+timeleft);
P_SetTarget(&numbermobj->target, player->mo);
numbermobj->threshold = 40;
numbermobj->destscale = player->mo->scale;
P_SetScale(numbermobj, player->mo->scale);
}
}
else
S_StartSound(player->mo, sfx_dwnind);
if (timeleft) // Don't waste time setting the state if the time is 0.
P_SetMobjState(numbermobj, numbermobj->info->spawnstate+timeleft);
P_SetTarget(&numbermobj->target, player->mo);
numbermobj->threshold = 40;
numbermobj->destscale = player->mo->scale;
P_SetScale(numbermobj, player->mo->scale);
}
// Underwater timer runs out
else if (timeleft == 1)
@ -2988,8 +3021,11 @@ static void P_CheckInvincibilityTimer(player_t *player)
else if (leveltime % (TICRATE/7) == 0)
{
mobj_t *sparkle = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_IVSP);
sparkle->destscale = player->mo->scale;
P_SetScale(sparkle, player->mo->scale);
if (!P_MobjWasRemoved(sparkle))
{
sparkle->destscale = player->mo->scale;
P_SetScale(sparkle, player->mo->scale);
}
}
// Resume normal music stuff.
@ -3044,7 +3080,8 @@ static void P_DoBubbleBreath(player_t *player)
y += (P_RandomRange(r, -r)<<FRACBITS);
z += (P_RandomKey(player->mo->height>>FRACBITS)<<FRACBITS);
bubble = P_SpawnMobj(x, y, z, MT_WATERZAP);
S_StartSound(bubble, sfx_beelec);
if (!P_MobjWasRemoved(bubble))
S_StartSound(bubble, sfx_beelec);
}
}
else
@ -3085,15 +3122,21 @@ static void P_DoBubbleBreath(player_t *player)
player->mo->x + stirwaterx,
player->mo->y + stirwatery,
stirwaterz, MT_SMALLBUBBLE);
bubble->destscale = player->mo->scale;
P_SetScale(bubble,bubble->destscale);
if (!P_MobjWasRemoved(bubble))
{
bubble->destscale = player->mo->scale;
P_SetScale(bubble,bubble->destscale);
}
bubble = P_SpawnMobj(
player->mo->x - stirwaterx,
player->mo->y - stirwatery,
stirwaterz, MT_SMALLBUBBLE);
bubble->destscale = player->mo->scale;
P_SetScale(bubble,bubble->destscale);
if (!P_MobjWasRemoved(bubble))
{
bubble->destscale = player->mo->scale;
P_SetScale(bubble,bubble->destscale);
}
}
}
@ -3110,22 +3153,25 @@ static void P_DoPlayerHeadSigns(player_t *player)
if (player->pflags & PF_TAGIT && !P_IsLocalPlayer(player))
{
mobj_t* it = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_TAG);
it->x = player->mo->x;
it->y = player->mo->y;
it->z = player->mo->z;
it->old_x = player->mo->old_x;
it->old_y = player->mo->old_y;
it->old_z = player->mo->old_z;
if (!P_MobjWasRemoved(it))
{
it->x = player->mo->x;
it->y = player->mo->y;
it->z = player->mo->z;
it->old_x = player->mo->old_x;
it->old_y = player->mo->old_y;
it->old_z = player->mo->old_z;
if (!(player->mo->eflags & MFE_VERTICALFLIP))
{
it->z += player->mo->height;
it->old_z += player->mo->height;
}
else
{
it->z -= mobjinfo[MT_TAG].height;
it->old_z -= mobjinfo[MT_TAG].height;
if (!(player->mo->eflags & MFE_VERTICALFLIP))
{
it->z += player->mo->height;
it->old_z += player->mo->height;
}
else
{
it->z -= mobjinfo[MT_TAG].height;
it->old_z -= mobjinfo[MT_TAG].height;
}
}
}
}
@ -3150,22 +3196,25 @@ static void P_DoPlayerHeadSigns(player_t *player)
}
sign = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_GOTFLAG);
sign->x = player->mo->x;
sign->y = player->mo->y;
sign->z = player->mo->z + zofs;
sign->old_x = player->mo->old_x;
sign->old_y = player->mo->old_y;
sign->old_z = player->mo->old_z + zofs;
if (player_is_flipped)
if (!P_MobjWasRemoved(sign))
{
sign->eflags |= MFE_VERTICALFLIP;
}
sign->x = player->mo->x;
sign->y = player->mo->y;
sign->z = player->mo->z + zofs;
sign->old_x = player->mo->old_x;
sign->old_y = player->mo->old_y;
sign->old_z = player->mo->old_z + zofs;
if (player->gotflag & GF_REDFLAG)
sign->frame = 1|FF_FULLBRIGHT;
else //if (player->gotflag & GF_BLUEFLAG)
sign->frame = 2|FF_FULLBRIGHT;
if (player_is_flipped)
{
sign->eflags |= MFE_VERTICALFLIP;
}
if (player->gotflag & GF_REDFLAG)
sign->frame = 1|FF_FULLBRIGHT;
else //if (player->gotflag & GF_BLUEFLAG)
sign->frame = 2|FF_FULLBRIGHT;
}
}
}
}
@ -4270,8 +4319,11 @@ static void P_DoSuperStuff(player_t *player)
&& !(leveltime % TICRATE) && (player->mo->momx || player->mo->momy))
{
spark = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_SUPERSPARK);
spark->destscale = player->mo->scale;
P_SetScale(spark, player->mo->scale);
if (!P_MobjWasRemoved(spark))
{
spark->destscale = player->mo->scale;
P_SetScale(spark, player->mo->scale);
}
}
// Ran out of rings while super!
@ -4544,6 +4596,8 @@ static void P_DoSpinDashDust(player_t *player)
INT32 prandom[3];
for (i = 0; i <= (leveltime%7)/2; i++) { // 1, 2, 3 or 4 particles
particle = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_SPINDUST);
if (P_MobjWasRemoved(particle))
return;
if (player->mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER)) // overrides fire version
P_SetMobjState(particle, S_SPINDUST_BUBBLE1);
@ -4691,7 +4745,8 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd)
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
P_SetTarget(&visual->target, lockon);
if (!P_MobjWasRemoved(visual))
P_SetTarget(&visual->target, lockon);
}
}
if ((cmd->buttons & BT_SPIN) && !(player->pflags & PF_SPINDOWN))
@ -4832,10 +4887,13 @@ void P_DoJumpShield(player_t *player)
for (i = 0; i < numangles; i++)
{
spark = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_THUNDERCOIN_SPARK);
P_InstaThrust(spark, travelangle + i*(ANGLE_MAX/numangles), FixedMul(4*FRACUNIT, spark->scale));
if (i % 2)
P_SetObjectMomZ(spark, -4*FRACUNIT, false);
spark->fuse = 18;
if (!P_MobjWasRemoved(spark))
{
P_InstaThrust(spark, travelangle + i*(ANGLE_MAX/numangles), FixedMul(4*FRACUNIT, spark->scale));
if (i % 2)
P_SetObjectMomZ(spark, -4*FRACUNIT, false);
spark->fuse = 18;
}
}
#undef limitangle
#undef numangles
@ -4942,14 +5000,17 @@ void P_TwinSpinRejuvenate(player_t *player, mobjtype_t type)
yo,
player->mo->height/2 + zo,
type);
P_SetTarget(&missile->target, player->mo);
P_SetScale(missile, (missile->destscale >>= 1));
missile->angle = ang + movang;
missile->fuse = TICRATE/2;
missile->extravalue2 = (99*FRACUNIT)/100;
missile->momx = xo;
missile->momy = yo;
missile->momz = zo;
if (!P_MobjWasRemoved(missile))
{
P_SetTarget(&missile->target, player->mo);
P_SetScale(missile, (missile->destscale >>= 1));
missile->angle = ang + movang;
missile->fuse = TICRATE/2;
missile->extravalue2 = (99*FRACUNIT)/100;
missile->momx = xo;
missile->momy = yo;
missile->momz = zo;
}
ang += ANGLE_45;
}
@ -5046,8 +5107,11 @@ static boolean P_PlayerShieldThink(player_t *player, ticcmd_t *cmd, mobj_t *lock
if (dovis)
{
visual = P_SpawnMobj(lockonshield->x, lockonshield->y, lockonshield->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker
P_SetTarget(&visual->target, lockonshield);
P_SetMobjStateNF(visual, visual->info->spawnstate+1);
if (!P_MobjWasRemoved(visual))
{
P_SetTarget(&visual->target, lockonshield);
P_SetMobjStateNF(visual, visual->info->spawnstate+1);
}
}
}
}
@ -5153,7 +5217,8 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
if (P_IsLocalPlayer(player)) // Only display it on your own view.
{
visual = P_SpawnMobj(lockonthok->x, lockonthok->y, lockonthok->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker
P_SetTarget(&visual->target, lockonthok);
if (!P_MobjWasRemoved(visual))
P_SetTarget(&visual->target, lockonthok);
}
}
@ -6848,10 +6913,14 @@ static void P_DoNiGHTSCapsule(player_t *player)
// Spawn a 'pop' for every 2 tics
if (!((tictimer - firstpoptic) % 2))
S_StartSound(P_SpawnMobj(player->capsule->x + ((P_SignedRandom()/2)<<FRACBITS),
player->capsule->y + ((P_SignedRandom()/2)<<FRACBITS),
player->capsule->z + (player->capsule->height/2) + ((P_SignedRandom()/2)<<FRACBITS),
MT_SONIC3KBOSSEXPLODE),sfx_s3kb4);
{
mobj_t *explodemo = P_SpawnMobj(player->capsule->x + ((P_SignedRandom()/2)<<FRACBITS),
player->capsule->y + ((P_SignedRandom()/2)<<FRACBITS),
player->capsule->z + (player->capsule->height/2) + ((P_SignedRandom()/2)<<FRACBITS),
MT_SONIC3KBOSSEXPLODE);
if (!P_MobjWasRemoved(explodemo))
S_StartSound(explodemo,sfx_s3kb4);
}
}
else
{
@ -6908,10 +6977,13 @@ static void P_DoNiGHTSCapsule(player_t *player)
UINT8 em = P_GetNextEmerald();
// Only give it to ONE person, and THAT player has to get to the goal!
mobj_t *emmo = P_SpawnMobjFromMobj(player->mo, 0, 0, player->mo->height, MT_GOTEMERALD);
emmo->health = em; // for identification
P_SetTarget(&emmo->target, player->mo);
P_SetMobjState(emmo, mobjinfo[MT_GOTEMERALD].meleestate + em);
P_SetTarget(&player->mo->tracer, emmo);
if (!P_MobjWasRemoved(emmo))
{
emmo->health = em; // for identification
P_SetTarget(&emmo->target, player->mo);
P_SetMobjState(emmo, mobjinfo[MT_GOTEMERALD].meleestate + em);
P_SetTarget(&player->mo->tracer, emmo);
}
}
// Okay, we're doing this down here because we're handling time weirdly for co-op special stages
@ -6934,19 +7006,22 @@ static void P_DoNiGHTSCapsule(player_t *player)
P_InstaThrust(flicky, flicky->angle, 8*FRACUNIT);
}*/
mobj_t *idya = P_SpawnMobjFromMobj(player->mo, 0, 0, player->mo->height, MT_GOTEMERALD);
idya->extravalue2 = player->mare/5;
idya->health = player->mare + 1; // for identification
P_SetTarget(&idya->target, player->mo);
P_SetMobjState(idya, mobjinfo[MT_GOTEMERALD].missilestate + ((player->mare + 1) % 5));
if (player->mo->tracer)
if (!P_MobjWasRemoved(idya))
{
P_SetTarget(&idya->hnext, player->mo->tracer);
idya->extravalue1 = (angle_t)(player->mo->tracer->extravalue1 - 72*ANG1);
if (idya->extravalue1 > player->mo->tracer->extravalue1)
idya->extravalue1 -= (72*ANG1)/idya->extravalue1;
idya->extravalue2 = player->mare/5;
idya->health = player->mare + 1; // for identification
P_SetTarget(&idya->target, player->mo);
P_SetMobjState(idya, mobjinfo[MT_GOTEMERALD].missilestate + ((player->mare + 1) % 5));
if (player->mo->tracer)
{
P_SetTarget(&idya->hnext, player->mo->tracer);
idya->extravalue1 = (angle_t)(player->mo->tracer->extravalue1 - 72*ANG1);
if (idya->extravalue1 > player->mo->tracer->extravalue1)
idya->extravalue1 -= (72*ANG1)/idya->extravalue1;
}
P_SetTarget(&player->mo->tracer, idya);
}
P_SetTarget(&player->mo->tracer, idya);
}
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].mare == player->mare)
@ -7271,19 +7346,25 @@ static void P_NiGHTSMovement(player_t *player)
z -= FixedMul(mobjinfo[MT_NIGHTSPARKLE].height, player->mo->scale);
firstmobj = P_SpawnMobj(player->mo->x + P_ReturnThrustX(player->mo, player->mo->angle+ANGLE_90, spawndist), player->mo->y + P_ReturnThrustY(player->mo, player->mo->angle+ANGLE_90, spawndist), z, MT_NIGHTSPARKLE);
secondmobj = P_SpawnMobj(player->mo->x + P_ReturnThrustX(player->mo, player->mo->angle-ANGLE_90, spawndist), player->mo->y + P_ReturnThrustY(player->mo, player->mo->angle-ANGLE_90, spawndist), z, MT_NIGHTSPARKLE);
firstmobj->destscale = secondmobj->destscale = player->mo->scale;
P_SetTarget(&firstmobj->target, player->mo);
P_SetScale(firstmobj, player->mo->scale);
P_SetTarget(&secondmobj->target, player->mo);
P_SetScale(secondmobj, player->mo->scale);
// Superloop turns sparkles red
if (player->powers[pw_nights_superloop])
if (!P_MobjWasRemoved(firstmobj))
{
P_SetMobjState(firstmobj, mobjinfo[MT_NIGHTSPARKLE].seestate);
P_SetMobjState(secondmobj, mobjinfo[MT_NIGHTSPARKLE].seestate);
firstmobj->destscale = player->mo->scale;
P_SetTarget(&firstmobj->target, player->mo);
P_SetScale(firstmobj, player->mo->scale);
// Superloop turns sparkles red
if (player->powers[pw_nights_superloop])
P_SetMobjState(firstmobj, mobjinfo[MT_NIGHTSPARKLE].seestate);
}
secondmobj = P_SpawnMobj(player->mo->x + P_ReturnThrustX(player->mo, player->mo->angle-ANGLE_90, spawndist), player->mo->y + P_ReturnThrustY(player->mo, player->mo->angle-ANGLE_90, spawndist), z, MT_NIGHTSPARKLE);
if (!P_MobjWasRemoved(secondmobj))
{
secondmobj->destscale = player->mo->scale;
P_SetTarget(&secondmobj->target, player->mo);
P_SetScale(secondmobj, player->mo->scale);
// Superloop turns sparkles red
if (player->powers[pw_nights_superloop])
P_SetMobjState(secondmobj, mobjinfo[MT_NIGHTSPARKLE].seestate);
}
}
@ -7291,9 +7372,12 @@ static void P_NiGHTSMovement(player_t *player)
// It also spawns every tic to avoid failed paraloops
{
mobj_t *helpermobj = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->height/2, MT_NIGHTSLOOPHELPER);
helpermobj->fuse = player->mo->fuse = leveltime;
P_SetTarget(&helpermobj->target, player->mo);
P_SetScale(helpermobj, player->mo->scale);
if (!P_MobjWasRemoved(helpermobj))
{
helpermobj->fuse = player->mo->fuse = leveltime;
P_SetTarget(&helpermobj->target, player->mo);
P_SetScale(helpermobj, player->mo->scale);
}
}
if (player->bumpertime)
@ -7482,19 +7566,22 @@ static void P_NiGHTSMovement(player_t *player)
mobjtype_t splishtype = (player->mo->eflags & MFE_TOUCHLAVA) ? MT_LAVASPLISH : MT_SPLISH;
mobj_t *water = P_SpawnMobj(player->mo->x, player->mo->y,
((player->mo->eflags & MFE_VERTICALFLIP) ? player->mo->waterbottom - FixedMul(mobjinfo[splishtype].height, player->mo->scale) : player->mo->watertop), splishtype);
if (player->mo->eflags & MFE_GOOWATER)
S_StartSound(water, sfx_ghit);
else if (player->mo->eflags & MFE_TOUCHLAVA)
S_StartSound(water, sfx_splash);
else
S_StartSound(water, sfx_wslap);
if (player->mo->eflags & MFE_VERTICALFLIP)
if (!P_MobjWasRemoved(water))
{
water->flags2 |= MF2_OBJECTFLIP;
water->eflags |= MFE_VERTICALFLIP;
if (player->mo->eflags & MFE_GOOWATER)
S_StartSound(water, sfx_ghit);
else if (player->mo->eflags & MFE_TOUCHLAVA)
S_StartSound(water, sfx_splash);
else
S_StartSound(water, sfx_wslap);
if (player->mo->eflags & MFE_VERTICALFLIP)
{
water->flags2 |= MF2_OBJECTFLIP;
water->eflags |= MFE_VERTICALFLIP;
}
water->destscale = player->mo->scale;
P_SetScale(water, player->mo->scale);
}
water->destscale = player->mo->scale;
P_SetScale(water, player->mo->scale);
}
if (player->mo->momx || player->mo->momy)
@ -7727,6 +7814,8 @@ void P_ElementalFire(player_t *player, boolean cropcircle)
for (i = 0; i < numangles; i++)
{
flame = P_SpawnMobj(player->mo->x, player->mo->y, ground, MT_SPINFIRE);
if (P_MobjWasRemoved(flame))
continue;
flame->flags &= ~MF_NOGRAVITY;
P_SetTarget(&flame->target, player->mo);
flame->angle = travelangle + i*(ANGLE_MAX/numangles);
@ -7764,6 +7853,8 @@ void P_ElementalFire(player_t *player, boolean cropcircle)
}
flame = P_SpawnMobj(newx, newy, ground, MT_SPINFIRE);
if (P_MobjWasRemoved(flame))
continue;
P_SetTarget(&flame->target, player->mo);
flame->angle = travelangle;
flame->fuse = TICRATE*6;
@ -7805,6 +7896,8 @@ void P_SpawnSkidDust(player_t *player, fixed_t radius, boolean sound)
mobj_t *particle;
particle = P_SpawnMobjFromMobj(mo, 0, 0, 0, MT_SPINDUST);
if (P_MobjWasRemoved(particle))
return;
if (radius >>= FRACBITS)
{
P_UnsetThingPosition(particle);
@ -8391,19 +8484,22 @@ void P_MovePlayer(player_t *player)
mobjtype_t splishtype = (player->mo->eflags & MFE_TOUCHLAVA) ? MT_LAVASPLISH : MT_SPLISH;
mobj_t *water = P_SpawnMobj(player->mo->x - P_ReturnThrustX(NULL, player->mo->angle, player->mo->radius), player->mo->y - P_ReturnThrustY(NULL, player->mo->angle, player->mo->radius),
((player->mo->eflags & MFE_VERTICALFLIP) ? player->mo->waterbottom - FixedMul(mobjinfo[splishtype].height, player->mo->scale) : player->mo->watertop), splishtype);
if (player->mo->eflags & MFE_GOOWATER)
S_StartSound(water, sfx_ghit);
else if (player->mo->eflags & MFE_TOUCHLAVA)
S_StartSound(water, sfx_splash);
else
S_StartSound(water, sfx_wslap);
if (player->mo->eflags & MFE_VERTICALFLIP)
if (!P_MobjWasRemoved(water))
{
water->flags2 |= MF2_OBJECTFLIP;
water->eflags |= MFE_VERTICALFLIP;
if (player->mo->eflags & MFE_GOOWATER)
S_StartSound(water, sfx_ghit);
else if (player->mo->eflags & MFE_TOUCHLAVA)
S_StartSound(water, sfx_splash);
else
S_StartSound(water, sfx_wslap);
if (player->mo->eflags & MFE_VERTICALFLIP)
{
water->flags2 |= MF2_OBJECTFLIP;
water->eflags |= MFE_VERTICALFLIP;
}
water->destscale = player->mo->scale;
P_SetScale(water, player->mo->scale);
}
water->destscale = player->mo->scale;
P_SetScale(water, player->mo->scale);
}
// Little water sound while touching water - just a nicety.
@ -10821,6 +10917,8 @@ static void P_SpawnSparks(mobj_t *mo, angle_t maindir)
fixed_t fm = (maindir >> ANGLETOFINESHIFT) & FINEMASK;
spark = P_SpawnMobj(mo->x - b2*s + b1*c, mo->y + b2*c + b1*s, mo->z, MT_MINECARTSPARK);
if (P_MobjWasRemoved(spark))
return;
spark->momx = mo->momx + r1 + 8*FINECOSINE(fm);
spark->momy = mo->momy + r2 + 8*FINESINE(fm);
spark->momz = mo->momz + r3;
@ -12066,17 +12164,20 @@ void P_PlayerThink(player_t *player)
if ((player->powers[pw_super] || player->powers[pw_sneakers]) && (player->speed + abs(player->mo->momz)) > FixedMul(20*FRACUNIT,player->mo->scale))
{
mobj_t *gmobj = P_SpawnGhostMobj(player->mo);
gmobj->fuse = 2;
if (gmobj->tracer)
gmobj->tracer->fuse = 2;
if (leveltime & 1)
if (!P_MobjWasRemoved(gmobj))
{
gmobj->frame &= ~FF_TRANSMASK;
gmobj->frame |= tr_trans70<<FF_TRANSSHIFT;
gmobj->fuse = 2;
if (gmobj->tracer)
gmobj->tracer->fuse = 2;
if (leveltime & 1)
{
gmobj->tracer->frame &= ~FF_TRANSMASK;
gmobj->tracer->frame |= tr_trans70<<FF_TRANSSHIFT;
gmobj->frame &= ~FF_TRANSMASK;
gmobj->frame |= tr_trans70<<FF_TRANSSHIFT;
if (gmobj->tracer)
{
gmobj->tracer->frame &= ~FF_TRANSMASK;
gmobj->tracer->frame |= tr_trans70<<FF_TRANSSHIFT;
}
}
}
@ -12288,9 +12389,12 @@ void P_PlayerThink(player_t *player)
if (player->normalspeed >= skins[player->skin].normalspeed*2)
{
mobj_t *ghost = P_SpawnGhostMobj(player->mo); // Spawns afterimages
ghost->fuse = 2; // Makes the images fade quickly
if (ghost->tracer && !P_MobjWasRemoved(ghost->tracer))
ghost->tracer->fuse = ghost->fuse;
if (!P_MobjWasRemoved(ghost))
{
ghost->fuse = 2; // Makes the images fade quickly
if (ghost->tracer && !P_MobjWasRemoved(ghost->tracer))
ghost->tracer->fuse = ghost->fuse;
}
}
}
else if (dashmode)
@ -12889,15 +12993,18 @@ void P_PlayerAfterThink(player_t *player)
if (!player->followmobj || P_MobjWasRemoved(player->followmobj))
{
P_SetTarget(&player->followmobj, P_SpawnMobjFromMobj(player->mo, 0, 0, 0, player->followitem));
P_SetTarget(&player->followmobj->tracer, player->mo);
switch (player->followmobj->type)
if (!P_MobjWasRemoved(player->followmobj))
{
case MT_METALJETFUME:
player->followmobj->colorized = true;
break;
default:
player->followmobj->flags2 |= MF2_LINKDRAW;
break;
P_SetTarget(&player->followmobj->tracer, player->mo);
switch (player->followmobj->type)
{
case MT_METALJETFUME:
player->followmobj->colorized = true;
break;
default:
player->followmobj->flags2 |= MF2_LINKDRAW;
break;
}
}
}