* Almost everything except players and badniks get removed on deathpit collision, as requested by Nev (very useful for the Bridge). May need serious checking for mobjtypes this is safe to do for.

* Flames fall with flameholders.
* New modification to teleport cheat: -sp <val> <val> allows instantaneous jump to any starpost in the map, including spawnpoints as starpost index 0!
* Also, -ang <val> and -aim <val>, which can be combined with -nop to pivot on the spot.
This commit is contained in:
toaster 2018-06-05 20:47:30 +01:00
parent 3725203bcd
commit 9c2d30ce35
4 changed files with 240 additions and 68 deletions

View File

@ -6740,7 +6740,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
4, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOGRAVITY|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
MF_NOBLOCKMAP|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate
},

View File

@ -499,56 +499,211 @@ void Command_Teleport_f(void)
REQUIRE_INLEVEL;
REQUIRE_SINGLEPLAYER;
if (COM_Argc() < 3 || COM_Argc() > 7)
if (COM_Argc() < 3 || COM_Argc() > 11)
{
CONS_Printf(M_GetText("teleport -x <value> -y <value> -z <value>: teleport to a location\n"));
CONS_Printf(M_GetText("teleport -x <value> -y <value> -z <value> -ang <value> -aim <value>: teleport to a location\nteleport -sp <sequence> <placement>: teleport to specified checkpoint\n"));
return;
}
if (!p->mo)
return;
i = COM_CheckParm("-x");
if (i)
intx = atoi(COM_Argv(i + 1));
else
{
CONS_Alert(CONS_NOTICE, M_GetText("%s value not specified\n"), "X");
return;
}
i = COM_CheckParm("-y");
if (i)
inty = atoi(COM_Argv(i + 1));
else
{
CONS_Alert(CONS_NOTICE, M_GetText("%s value not specified\n"), "Y");
return;
}
ss = R_PointInSubsector(intx*FRACUNIT, inty*FRACUNIT);
if (!ss || ss->sector->ceilingheight - ss->sector->floorheight < p->mo->height)
{
CONS_Alert(CONS_NOTICE, M_GetText("Not a valid location.\n"));
return;
}
i = COM_CheckParm("-z");
i = COM_CheckParm("-sp");
if (i)
{
intz = atoi(COM_Argv(i + 1));
intz <<= FRACBITS;
if (intz < ss->sector->floorheight)
intz = ss->sector->floorheight;
if (intz > ss->sector->ceilingheight - p->mo->height)
intz = ss->sector->ceilingheight - p->mo->height;
INT32 starpostnum = atoi(COM_Argv(i + 1)); // starpost number
INT32 starpostpath = atoi(COM_Argv(i + 2)); // quick, dirty way to distinguish between paths
if (starpostnum < 0 || starpostpath < 0)
{
CONS_Alert(CONS_NOTICE, M_GetText("Negative starpost indexing is not valid.\n"));
return;
}
if (!starpostnum) // spawnpoints...
{
mapthing_t *mt;
if (starpostpath >= numcoopstarts)
{
CONS_Alert(CONS_NOTICE, M_GetText("Player %d spawnpoint not found (%d max).\n"), starpostpath+1, numcoopstarts-1);
return;
}
mt = playerstarts[starpostpath]; // Given above check, should never be NULL.
intx = mt->x<<FRACBITS;
inty = mt->y<<FRACBITS;
ss = R_IsPointInSubsector(intx, inty);
if (!ss || ss->sector->ceilingheight - ss->sector->floorheight < p->mo->height)
{
CONS_Alert(CONS_NOTICE, M_GetText("Spawnpoint not in a valid location.\n"));
return;
}
// Flagging a player's ambush will make them start on the ceiling
// Objectflip inverts
if (!!(mt->options & MTF_AMBUSH) ^ !!(mt->options & MTF_OBJECTFLIP))
{
intz = ss->sector->ceilingheight - p->mo->height;
if (mt->options >> ZSHIFT)
intz -= ((mt->options >> ZSHIFT) << FRACBITS);
}
else
{
intz = ss->sector->floorheight;
if (mt->options >> ZSHIFT)
intz += ((mt->options >> ZSHIFT) << FRACBITS);
}
if (mt->options & MTF_OBJECTFLIP) // flip the player!
{
p->mo->eflags |= MFE_VERTICALFLIP;
p->mo->flags2 |= MF2_OBJECTFLIP;
}
else
{
p->mo->eflags &= ~MFE_VERTICALFLIP;
p->mo->flags2 &= ~MF2_OBJECTFLIP;
}
localangle = p->mo->angle = p->drawangle = FixedAngle(mt->angle<<FRACBITS);
}
else // scan the thinkers to find starposts...
{
mobj_t *mo2;
thinker_t *th;
INT32 starpostmax = 0;
intz = starpostpath; // variable reuse - counting down for selection purposes
for (th = thinkercap.next; th != &thinkercap; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2->type != MT_STARPOST)
continue;
if (mo2->health != starpostnum)
{
if (mo2->health > starpostmax)
starpostmax = mo2->health;
continue;
}
if (intz--)
continue;
break;
}
if (th == &thinkercap)
{
if (intz == starpostpath)
CONS_Alert(CONS_NOTICE, M_GetText("No starpost of position %d found (%d max).\n"), starpostnum, starpostmax);
else
CONS_Alert(CONS_NOTICE, M_GetText("Starpost of position %d, %d not found (%d, %d max).\n"), starpostnum, starpostpath, starpostmax, (starpostpath-intz)-1);
return;
}
ss = R_IsPointInSubsector(mo2->x, mo2->y);
if (!ss || ss->sector->ceilingheight - ss->sector->floorheight < p->mo->height)
{
CONS_Alert(CONS_NOTICE, M_GetText("Starpost not in a valid location.\n"));
return;
}
intx = mo2->x;
inty = mo2->y;
intz = mo2->z;
if (mo2->flags2 & MF2_OBJECTFLIP) // flip the player!
{
p->mo->eflags |= MFE_VERTICALFLIP;
p->mo->flags2 |= MF2_OBJECTFLIP;
}
else
{
p->mo->eflags &= ~MFE_VERTICALFLIP;
p->mo->flags2 &= ~MF2_OBJECTFLIP;
}
localangle = p->mo->angle = p->drawangle = mo2->angle;
}
CONS_Printf(M_GetText("Teleporting to checkpoint %d, %d...\n"), starpostnum, starpostpath);
}
else
intz = ss->sector->floorheight;
{
i = COM_CheckParm("-nop"); // undocumented stupid addition to allow pivoting on the spot with -ang and -aim
if (i)
{
intx = p->mo->x;
inty = p->mo->y;
}
else
{
i = COM_CheckParm("-x");
if (i)
intx = atoi(COM_Argv(i + 1))<<FRACBITS;
else
{
CONS_Alert(CONS_NOTICE, M_GetText("%s value not specified.\n"), "X");
return;
}
CONS_Printf(M_GetText("Teleporting to %d, %d, %d...\n"), intx, inty, FixedInt(intz));
i = COM_CheckParm("-y");
if (i)
inty = atoi(COM_Argv(i + 1))<<FRACBITS;
else
{
CONS_Alert(CONS_NOTICE, M_GetText("%s value not specified.\n"), "Y");
return;
}
}
ss = R_IsPointInSubsector(intx, inty);
if (!ss || ss->sector->ceilingheight - ss->sector->floorheight < p->mo->height)
{
CONS_Alert(CONS_NOTICE, M_GetText("Not a valid location.\n"));
return;
}
i = COM_CheckParm("-z");
if (i)
{
intz = atoi(COM_Argv(i + 1))<<FRACBITS;
if (intz < ss->sector->floorheight)
intz = ss->sector->floorheight;
if (intz > ss->sector->ceilingheight - p->mo->height)
intz = ss->sector->ceilingheight - p->mo->height;
}
else
intz = ((p->mo->eflags & MFE_VERTICALFLIP) ? ss->sector->ceilingheight : ss->sector->floorheight);
i = COM_CheckParm("-ang");
if (i)
localangle = p->drawangle = p->mo->angle = FixedAngle(atoi(COM_Argv(i + 1))<<FRACBITS);
i = COM_CheckParm("-aim");
if (i)
{
angle_t aim = FixedAngle(atoi(COM_Argv(i + 1))<<FRACBITS);
if (aim >= ANGLE_90 && aim <= ANGLE_270)
{
CONS_Alert(CONS_NOTICE, M_GetText("Not a valid aiming angle (between +/-90).\n"));
return;
}
localaiming = p->aiming = aim;
}
CONS_Printf(M_GetText("Teleporting to %d, %d, %d...\n"), FixedInt(intx), FixedInt(inty), FixedInt(intz));
}
P_MapStart();
if (!P_TeleportMove(p->mo, intx*FRACUNIT, inty*FRACUNIT, intz))
if (!P_TeleportMove(p->mo, intx, inty, intz))
CONS_Alert(CONS_WARNING, M_GetText("Unable to teleport to that spot!\n"));
else
S_StartSound(p->mo, sfx_mixup);

View File

@ -104,8 +104,13 @@ void P_ClearStarPost(INT32 postnum)
mo2 = (mobj_t *)th;
if (mo2->type == MT_STARPOST && mo2->health <= postnum)
P_SetMobjState(mo2, mo2->info->seestate);
if (mo2->type != MT_STARPOST)
return;
if (mo2->health > postnum)
return;
P_SetMobjState(mo2, mo2->info->seestate);
}
return;
}
@ -1364,7 +1369,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
P_ClearStarPost(special->health);
// Find all starposts in the level with this value.
// Find all starposts in the level with this value - INCLUDING this one!
if (!(netgame && circuitmap && player != &players[consoleplayer]))
{
thinker_t *th;
mobj_t *mo2;
@ -1376,21 +1382,16 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
mo2 = (mobj_t *)th;
if (mo2 == special)
if (mo2->type != MT_STARPOST)
continue;
if (mo2->health != special->health)
continue;
if (mo2->type == MT_STARPOST && mo2->health == special->health)
{
if (!(netgame && circuitmap && player != &players[consoleplayer]))
P_SetMobjState(mo2, mo2->info->painstate);
}
P_SetMobjState(mo2, mo2->info->painstate);
}
}
S_StartSound(toucher, special->info->painsound);
if (!(netgame && circuitmap && player != &players[consoleplayer]))
P_SetMobjState(special, special->info->painstate);
return;
case MT_FAKEMOBILE:

View File

@ -2404,6 +2404,7 @@ boolean P_CheckSolidLava(mobj_t *mo, ffloor_t *rover)
static boolean P_ZMovement(mobj_t *mo)
{
fixed_t dist, delta;
boolean onground;
I_Assert(mo != NULL);
I_Assert(!P_MobjWasRemoved(mo));
@ -2421,13 +2422,14 @@ static boolean P_ZMovement(mobj_t *mo)
mo->eflags &= ~MFE_APPLYPMOMZ;
}
mo->z += mo->momz;
onground = P_IsObjectOnGround(mo);
#ifdef ESLOPE
if (mo->standingslope)
{
if (mo->flags & MF_NOCLIPHEIGHT)
mo->standingslope = NULL;
else if (!P_IsObjectOnGround(mo))
else if (!onground)
P_SlopeLaunch(mo);
}
#endif
@ -2571,15 +2573,9 @@ static boolean P_ZMovement(mobj_t *mo)
break;
}
if (P_CheckDeathPitCollide(mo))
if (!mo->player && P_CheckDeathPitCollide(mo))
{
if (mo->flags & MF_PUSHABLE)
{
// Remove other pushable items from death pits.
P_RemoveMobj(mo);
return false;
}
else if (mo->flags & MF_ENEMY || mo->flags & MF_BOSS)
if (mo->flags & MF_ENEMY || mo->flags & MF_BOSS)
{
// Kill enemies and bosses that fall into death pits.
if (mo->health)
@ -2588,6 +2584,11 @@ static boolean P_ZMovement(mobj_t *mo)
return false;
}
}
else
{
P_RemoveMobj(mo);
return false;
}
}
if (P_MobjFlip(mo)*mo->momz < 0
@ -2870,6 +2871,8 @@ static boolean P_ZMovement(mobj_t *mo)
static void P_PlayerZMovement(mobj_t *mo)
{
boolean onground;
I_Assert(mo != NULL);
I_Assert(!P_MobjWasRemoved(mo));
@ -2903,6 +2906,7 @@ static void P_PlayerZMovement(mobj_t *mo)
}
mo->z += mo->momz;
onground = P_IsObjectOnGround(mo);
// Have player fall through floor?
if (mo->player->playerstate == PST_DEAD
@ -2914,13 +2918,13 @@ static void P_PlayerZMovement(mobj_t *mo)
{
if (mo->flags & MF_NOCLIPHEIGHT)
mo->standingslope = NULL;
else if (!P_IsObjectOnGround(mo))
else if (!onground)
P_SlopeLaunch(mo);
}
#endif
// clip movement
if (P_IsObjectOnGround(mo) && !(mo->flags & MF_NOCLIPHEIGHT))
if (onground && !(mo->flags & MF_NOCLIPHEIGHT))
{
if (mo->eflags & MFE_VERTICALFLIP)
mo->z = mo->ceilingz - mo->height;
@ -3222,19 +3226,14 @@ static boolean P_SceneryZMovement(mobj_t *mo)
P_RemoveMobj(mo);
return false;
}
default:
break;
}
// Fix for any silly pushables like the egg statues that are also scenery for some reason -- Monster Iestyn
if (P_CheckDeathPitCollide(mo))
{
if (mo->flags & MF_PUSHABLE)
{
P_RemoveMobj(mo);
return false;
}
P_RemoveMobj(mo);
return false;
}
// clip movement
@ -7483,6 +7482,19 @@ void P_MobjThinker(mobj_t *mobj)
mobj->z += FINESINE(mobj->extravalue1*(FINEMASK+1)/360);
P_SetThingPosition(mobj);
break;
case MT_FLAME:
if (mobj->flags2 & MF2_BOSSNOTRAP)
{
if (!mobj->target || P_MobjWasRemoved(mobj->target))
{
P_RemoveMobj(mobj);
return;
}
mobj->z = mobj->target->z + mobj->target->momz;
if (!(mobj->eflags & MFE_VERTICALFLIP))
mobj->z += mobj->target->height;
}
break;
case MT_WAVINGFLAG:
{
fixed_t base = (leveltime<<(FRACBITS+1));
@ -10474,7 +10486,11 @@ ML_EFFECT4 : Don't clip inside the ground
break;
case MT_FLAMEHOLDER:
if (!(mthing->options & MTF_OBJECTSPECIAL)) // Spawn the fire
P_SpawnMobjFromMobj(mobj, 0, 0, mobj->height, MT_FLAME);
{
mobj_t *flame = P_SpawnMobjFromMobj(mobj, 0, 0, mobj->height, MT_FLAME);
P_SetTarget(&flame->target, mobj);
flame->flags2 |= MF2_BOSSNOTRAP;
}
break;
case MT_SMASHINGSPIKEBALL:
if (mthing->angle > 0)