From 9c2d30ce3521ccab3661c2ea96f3266638d895ae Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 5 Jun 2018 20:47:30 +0100 Subject: [PATCH] * 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 allows instantaneous jump to any starpost in the map, including spawnpoints as starpost index 0! * Also, -ang and -aim , which can be combined with -nop to pivot on the spot. --- src/info.c | 2 +- src/m_cheat.c | 227 ++++++++++++++++++++++++++++++++++++++++++-------- src/p_inter.c | 25 +++--- src/p_mobj.c | 54 +++++++----- 4 files changed, 240 insertions(+), 68 deletions(-) diff --git a/src/info.c b/src/info.c index dbbe54de9..d2bd1dab5 100644 --- a/src/info.c +++ b/src/info.c @@ -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 }, diff --git a/src/m_cheat.c b/src/m_cheat.c index 81a8702fd..15a3353c4 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -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 -y -z : teleport to a location\n")); + CONS_Printf(M_GetText("teleport -x -y -z -ang -aim : teleport to a location\nteleport -sp : 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<y<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<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))<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))<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))<= 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); diff --git a/src/p_inter.c b/src/p_inter.c index f3fb5f6e1..8f8c1f4fa 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -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: diff --git a/src/p_mobj.c b/src/p_mobj.c index cc28fb5a0..5a8729df2 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -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)