Merge branch 'fix-segfault-removemobj-spawn' into 'next'

Fix segfaults when P_RemoveMobj is called from MobjSpawn hook

See merge request STJr/SRB2!1973
This commit is contained in:
Logan Aerl Arias 2023-12-25 23:58:26 +00:00
commit b5a4f227f6
10 changed files with 1671 additions and 951 deletions

View file

@ -614,6 +614,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

@ -798,32 +798,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)
@ -847,6 +855,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;
@ -892,19 +902,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)
{
@ -1097,28 +1110,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)
@ -1140,19 +1160,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)
{
@ -2535,7 +2558,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

@ -256,6 +256,9 @@ void P_DoNightsScore(player_t *player)
player->linktimer = nightslinktics;
}
if (P_MobjWasRemoved(dummymo))
return;
// Award 10-100 score, doubled if bonus time is active
P_AddPlayerScore(player, min(player->linkcount,10)*(player->bonustime ? 20 : 10));
P_SetMobjState(dummymo, (player->bonustime ? dummymo->info->xdeathstate : dummymo->info->spawnstate) + min(player->linkcount,10)-1);
@ -1301,7 +1304,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;
}
@ -1312,7 +1316,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);
@ -1821,9 +1826,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;
@ -2593,7 +2601,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;
}
@ -2754,6 +2763,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);
@ -2832,8 +2843,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;
@ -2932,7 +2946,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;\
@ -2942,7 +2959,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);
@ -2955,20 +2973,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;
@ -2977,7 +2998,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;
@ -3000,21 +3024,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;
@ -3026,21 +3054,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;
@ -3921,6 +3951,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);
@ -4054,6 +4086,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);
@ -4087,13 +4122,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])
{
@ -4138,6 +4173,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);
@ -4163,8 +4200,6 @@ void P_PlayerWeaponAmmoBurst(player_t *player)
if (i & 1)
P_SetObjectMomZ(mo, 3*FRACUNIT, true);
i++;
}
}
@ -4189,45 +4224,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);
@ -4351,23 +4391,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)
@ -4395,6 +4438,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

@ -288,7 +288,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

@ -2865,6 +2865,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

@ -393,6 +393,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);
@ -1889,6 +1891,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);
P_SetTarget(&shieldobj->dontdrawforviewmobj, player->mo); // Hide the shield in first-person
@ -1904,24 +1909,33 @@ 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);
if (!P_MobjWasRemoved(ov))
{
P_SetTarget(&ov->target, shieldobj);
P_SetTarget(&ov->dontdrawforviewmobj, player->mo); // Hide the shield in first-person
P_SetMobjState(ov, shieldobj->info->seestate);
P_SetTarget(&shieldobj->tracer, ov);
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);
if (!P_MobjWasRemoved(ov))
{
P_SetTarget(&ov->target, shieldobj);
P_SetTarget(&ov->dontdrawforviewmobj, player->mo); // Hide the shield in first-person
P_SetMobjState(ov, shieldobj->info->meleestate);
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);
if (!P_MobjWasRemoved(ov))
{
P_SetTarget(&ov->target, shieldobj);
P_SetTarget(&ov->dontdrawforviewmobj, player->mo); // Hide the shield in first-person
P_SetMobjState(ov, shieldobj->info->missilestate);
P_SetMobjState(ov, shieldobj->info->missilestate);
}
}
if (player->powers[pw_shield] & SH_FORCE)
{
@ -2017,6 +2031,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);
P_SetTarget(&ghost->dontdrawforviewmobj, mobj); // Hide the ghost in first-person
@ -2063,10 +2079,13 @@ 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);
if (!P_MobjWasRemoved(ghost2))
{
P_SetTarget(&ghost2->tracer, ghost);
P_SetTarget(&ghost->tracer, ghost2);
P_SetTarget(&ghost2->dontdrawforviewmobj, mobj); // Hide the follow-ghost for the non-follow target
ghost2->flags2 |= (mobj->player->followmobj->flags2 & MF2_LINKDRAW);
ghost2->flags2 |= (mobj->player->followmobj->flags2 & MF2_LINKDRAW);
}
}
// Copy interpolation data :)
@ -2116,6 +2135,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;
@ -2139,7 +2160,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();
}
@ -2177,6 +2199,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;
@ -2201,7 +2225,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.
@ -2426,15 +2451,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;
@ -2989,24 +3017,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)
@ -3065,8 +3098,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.
@ -3121,7 +3157,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
@ -3162,15 +3199,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);
}
}
}
@ -3190,22 +3233,25 @@ static void P_DoPlayerHeadSigns(player_t *player)
if (player->pflags & PF_TAGIT && (!P_IsLocalPlayer(player) || consoleplayer != displayplayer || splitscreen))
{
sign = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_TAG);
sign->x = player->mo->x;
sign->y = player->mo->y;
sign->z = player->mo->z;
sign->old_x = player->mo->old_x;
sign->old_y = player->mo->old_y;
sign->old_z = player->mo->old_z;
if (!P_MobjWasRemoved(sign))
{
sign->x = player->mo->x;
sign->y = player->mo->y;
sign->z = player->mo->z;
sign->old_x = player->mo->old_x;
sign->old_y = player->mo->old_y;
sign->old_z = player->mo->old_z;
if (!(player->mo->eflags & MFE_VERTICALFLIP))
{
sign->z += player->mo->height;
sign->old_z += player->mo->height;
}
else
{
sign->z -= mobjinfo[MT_TAG].height;
sign->old_z -= mobjinfo[MT_TAG].height;
if (!(player->mo->eflags & MFE_VERTICALFLIP))
{
sign->z += player->mo->height;
sign->old_z += player->mo->height;
}
else
{
sign->z -= mobjinfo[MT_TAG].height;
sign->old_z -= mobjinfo[MT_TAG].height;
}
}
}
}
@ -3229,24 +3275,26 @@ 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;
}
}
}
if (!P_MobjWasRemoved(sign) && splitscreen) // Hide the sign from yourself in splitscreen - In single-screen, it wouldn't get spawned if it shouldn't be visible
{
@ -3284,6 +3332,7 @@ static void P_DoPlayerHeadSigns(player_t *player)
}
#endif
}
}
}
//
@ -4371,8 +4420,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!
@ -4613,6 +4665,8 @@ 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);
@ -4760,7 +4814,8 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd)
if (P_IsLocalPlayer(player)) // Only display it on your own view. Don't display it for spectators
{
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);
visual->drawonlyforplayer = player; // Hide it from the other player in splitscreen, and yourself when spectating
}
}
@ -4903,10 +4958,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
@ -5013,14 +5071,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;
}
@ -5118,9 +5179,12 @@ 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);
if (!P_MobjWasRemoved(visual))
{
P_SetTarget(&visual->target, lockonshield);
visual->drawonlyforplayer = player; // Hide it from the other player in splitscreen, and yourself when spectating
P_SetMobjStateNF(visual, visual->info->spawnstate+1);
P_SetMobjStateNF(visual, visual->info->spawnstate+1);
}
}
}
}
@ -5226,7 +5290,8 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
if (P_IsLocalPlayer(player)) // Only display it on your own view. Don't display it for spectators
{
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);
visual->drawonlyforplayer = player; // Hide it from the other player in splitscreen, and yourself when spectating
}
}
@ -6912,10 +6977,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
{
@ -6972,10 +7041,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
@ -6998,19 +7070,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)
@ -7335,19 +7410,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);
}
}
@ -7355,9 +7436,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)
@ -7546,19 +7630,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)
@ -7791,6 +7878,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);
@ -7828,6 +7917,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;
@ -7869,6 +7960,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);
@ -8455,19 +8548,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.
@ -10893,6 +10989,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;
@ -12194,17 +12292,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;
}
}
}
}
@ -12423,9 +12524,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)
@ -13026,15 +13130,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;
}
}
}