From 2d50dd1fd1ad65923acb271717027316c802d4bd Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Mon, 31 Oct 2016 00:02:38 +0000 Subject: [PATCH 01/11] A bunch of fixes that allow for proper handling of triggerspecial_touch. Not perfect, but I don't have any more time to spend tonight. --- src/p_floor.c | 39 +++++++++++++++++++++++++++++--- src/p_spec.c | 61 +++++++++++++++++++++++++++++---------------------- 2 files changed, 71 insertions(+), 29 deletions(-) diff --git a/src/p_floor.c b/src/p_floor.c index 91121301..1f3873d9 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -2073,6 +2073,7 @@ void T_EachTimeThinker(levelspecthink_t *eachtime) boolean inAndOut = false; boolean floortouch = false; fixed_t bottomheight, topheight; + msecnode_t *node; for (i = 0; i < MAXPLAYERS; i++) { @@ -2134,8 +2135,22 @@ void T_EachTimeThinker(levelspecthink_t *eachtime) if ((netgame || multiplayer) && players[j].spectator) continue; - if (players[j].mo->subsector->sector != targetsec) - continue; + if (players[j].mo->subsector->sector == targetsec) + ; + else if (sec->flags & SF_TRIGGERSPECIAL_TOUCH) + { + boolean insector = false; + for (node = players[j].mo->touching_sectorlist; node; node = node->m_sectorlist_next) + { + if (node->m_sector == targetsec) + { + insector = true; + break; + } + } + if (!insector) + continue; + } topheight = P_GetSpecialTopZ(players[j].mo, sec, targetsec); bottomheight = P_GetSpecialBottomZ(players[j].mo, sec, targetsec); @@ -2184,7 +2199,25 @@ void T_EachTimeThinker(levelspecthink_t *eachtime) if ((netgame || multiplayer) && players[i].spectator) continue; - if (players[i].mo->subsector->sector != sec) + if (players[i].mo->subsector->sector == targetsec) + ; + else if (sec->flags & SF_TRIGGERSPECIAL_TOUCH) + { + boolean insector = false; + for (node = players[i].mo->touching_sectorlist; node; node = node->m_sectorlist_next) + { + if (node->m_sector == targetsec) + { + insector = true; + break; + } + } + if (!insector) + continue; + } + + if (!(players[i].mo->subsector->sector == sec + || P_PlayerTouchingSectorSpecial(&players[i], 2, (GETSECSPECIAL(sec->special, 2))) == sec)) continue; if (floortouch == true && P_IsObjectOnGroundIn(players[i].mo, sec)) diff --git a/src/p_spec.c b/src/p_spec.c index b04c5588..10a8f731 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3606,14 +3606,16 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers { if (roversector) { - if (players[i].mo->subsector->sector != roversector) + if (!(players[i].mo->subsector->sector == roversector + || sector->flags & SF_TRIGGERSPECIAL_TOUCH)) goto DoneSection2; if (!P_ThingIsOnThe3DFloor(players[i].mo, sector, roversector)) goto DoneSection2; } else { - if (players[i].mo->subsector->sector != sector) + if (!(players[i].mo->subsector->sector == sector + || sector->flags & SF_TRIGGERSPECIAL_TOUCH)) goto DoneSection2; if (special == 3 && !P_MobjReadyToTrigger(players[i].mo, sector)) @@ -4364,6 +4366,7 @@ sector_t *P_ThingOnSpecial3DFloor(mobj_t *mo) { sector_t *sector; ffloor_t *rover; + fixed_t topheight, bottomheight; sector = mo->subsector->sector; if (!sector->ffloors) @@ -4371,8 +4374,6 @@ sector_t *P_ThingOnSpecial3DFloor(mobj_t *mo) for (rover = sector->ffloors; rover; rover = rover->next) { - fixed_t topheight, bottomheight; - if (!rover->master->frontsector->special) continue; @@ -4420,20 +4421,21 @@ sector_t *P_ThingOnSpecial3DFloor(mobj_t *mo) return NULL; } +#define TELEPORTED (player->mo->subsector->sector != originalsector) + /** Checks if a player is standing on or is inside a 3D floor (e.g. water) and * applies any specials. * * \param player Player to check. * \sa P_ThingOnSpecial3DFloor, P_PlayerInSpecialSector */ -static void P_PlayerOnSpecial3DFloor(player_t *player, sector_t *sector) +static void P_PlayerOnSpecial3DFloor(player_t *player, sector_t *sector, sector_t *originalsector) { ffloor_t *rover; + fixed_t topheight, bottomheight; for (rover = sector->ffloors; rover; rover = rover->next) { - fixed_t topheight, bottomheight; - if (!rover->master->frontsector->special) continue; @@ -4477,7 +4479,10 @@ static void P_PlayerOnSpecial3DFloor(player_t *player, sector_t *sector) // This FOF has the special we're looking for, but are we allowed to touch it? if (sector == player->mo->subsector->sector || (rover->master->frontsector->flags & SF_TRIGGERSPECIAL_TOUCH)) + { P_ProcessSpecialSector(player, rover->master->frontsector, sector); + if TELEPORTED return; + } } // Allow sector specials to be applied to polyobjects! @@ -4488,7 +4493,7 @@ static void P_PlayerOnSpecial3DFloor(player_t *player, sector_t *sector) boolean touching = false; boolean inside = false; - while(po) + while (po) { if (po->flags & POF_NOSPECIALS) { @@ -4564,6 +4569,7 @@ static void P_PlayerOnSpecial3DFloor(player_t *player, sector_t *sector) } P_ProcessSpecialSector(player, polysec, sector); + if TELEPORTED return; po = (polyobj_t *)(po->link.next); } @@ -4668,40 +4674,43 @@ static void P_RunSpecialSectorCheck(player_t *player, sector_t *sector) */ void P_PlayerInSpecialSector(player_t *player) { - sector_t *sector; + sector_t *originalsector; + sector_t *loopsector; msecnode_t *node; if (!player->mo) return; - // Do your ->subsector->sector first - sector = player->mo->subsector->sector; - P_PlayerOnSpecial3DFloor(player, sector); - // After P_PlayerOnSpecial3DFloor, recheck if the player is in that sector, - // because the player can be teleported in between these times. - if (sector == player->mo->subsector->sector) - P_RunSpecialSectorCheck(player, sector); + originalsector = player->mo->subsector->sector; - // Iterate through touching_sectorlist + P_PlayerOnSpecial3DFloor(player, originalsector, originalsector); // Handle FOFs first. + if TELEPORTED return; + + P_RunSpecialSectorCheck(player, originalsector); + if TELEPORTED return; + + // Iterate through touching_sectorlist for SF_TRIGGERSPECIAL_TOUCH for (node = player->mo->touching_sectorlist; node; node = node->m_sectorlist_next) { - sector = node->m_sector; + loopsector = node->m_sector; - if (sector == player->mo->subsector->sector) // Don't duplicate + if (loopsector == originalsector) // Don't duplicate continue; // Check 3D floors... - P_PlayerOnSpecial3DFloor(player, sector); + P_PlayerOnSpecial3DFloor(player, loopsector, originalsector); + if TELEPORTED return; - if (!(sector->flags & SF_TRIGGERSPECIAL_TOUCH)) - return; - // After P_PlayerOnSpecial3DFloor, recheck if the player is in that sector, - // because the player can be teleported in between these times. - if (sector == player->mo->subsector->sector) - P_RunSpecialSectorCheck(player, sector); + if (!(loopsector->flags & SF_TRIGGERSPECIAL_TOUCH)) + continue; + + P_RunSpecialSectorCheck(player, loopsector); + if TELEPORTED return; } } +#undef TELEPORTED + /** Animate planes, scroll walls, etc. and keeps track of level timelimit and exits if time is up. * * \sa P_CheckTimeLimit, P_CheckPointLimit From 6a2e101ebe0589c228ba0bdf990d8169250fd4ec Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Mon, 31 Oct 2016 00:03:07 +0000 Subject: [PATCH 02/11] Forcing on triggerspecial_touch for slopes, because pain slopes and it would be a pain to handle this manually. --- src/p_slopes.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/p_slopes.c b/src/p_slopes.c index d939fee9..c127001c 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -281,6 +281,7 @@ void P_SpawnSlope_Line(int linenum) if(frontfloor || frontceil) { line->frontsector->hasslope = true; // Tell the software renderer that we're sloped + line->frontsector->flags |= SF_TRIGGERSPECIAL_TOUCH; // you're gonna want to get specials on contact origin.z = line->backsector->floorheight; direction.x = nx; @@ -407,6 +408,7 @@ void P_SpawnSlope_Line(int linenum) if(backfloor || backceil) { line->backsector->hasslope = true; // Tell the software renderer that we're sloped + line->backsector->flags |= SF_TRIGGERSPECIAL_TOUCH; // you're gonna want to get specials on contact origin.z = line->frontsector->floorheight; // Backsector @@ -599,6 +601,7 @@ void P_CopySectorSlope(line_t *line) } fsec->hasslope = true; + fsec->flags |= SF_TRIGGERSPECIAL_TOUCH; // you're gonna want to get specials on contact line->special = 0; // Linedef was use to set slopes, it finished its job, so now make it a normal linedef } @@ -718,6 +721,7 @@ void P_ResetDynamicSlopes(void) { *slopetoset = P_NewVertexSlope(lines[i].tag, lines[i].tag, lines[i].tag, flags); sides[lines[i].sidenum[which]].sector->hasslope = true; + sides[lines[i].sidenum[which]].sector->flags |= SF_TRIGGERSPECIAL_TOUCH; // you're gonna want to get specials on contact } break; From 1e1a6c32f0b8c0ee0d93b4f1008fe6ae0e956cf8 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Mon, 31 Oct 2016 09:34:24 +0000 Subject: [PATCH 03/11] Corrected non-complete set of cases. --- src/p_floor.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/p_floor.c b/src/p_floor.c index 1f3873d9..b2c07bce 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -2151,6 +2151,8 @@ void T_EachTimeThinker(levelspecthink_t *eachtime) if (!insector) continue; } + else + continue; topheight = P_GetSpecialTopZ(players[j].mo, sec, targetsec); bottomheight = P_GetSpecialBottomZ(players[j].mo, sec, targetsec); @@ -2215,6 +2217,8 @@ void T_EachTimeThinker(levelspecthink_t *eachtime) if (!insector) continue; } + else + continue; if (!(players[i].mo->subsector->sector == sec || P_PlayerTouchingSectorSpecial(&players[i], 2, (GETSECSPECIAL(sec->special, 2))) == sec)) From 1bbbe15ee52600b1404cd65bb9b95591a0728938 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Mon, 31 Oct 2016 13:53:52 +0000 Subject: [PATCH 04/11] Fixed a bug with being able to go under the lava because P_CheckSolidLava doesn't take slopes into account. (neither does P_CanRunOnWater, but I don't think it's necessary to make that check more complicated as you probably shouldn't be able to waterrun up steep surfaces anyways) --- src/lua_baselib.c | 5 ++++- src/p_local.h | 2 +- src/p_map.c | 2 +- src/p_maputl.c | 4 ++-- src/p_mobj.c | 6 +++--- src/p_user.c | 2 +- 6 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index e8e8fd02..00a51927 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -560,12 +560,15 @@ static int lib_pCheckSolidLava(lua_State *L) { mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR)); + sector_t *bound = *((sector_t **)luaL_checkudata(L, 3, META_SECTOR)); //HUDSAFE if (!mo) return LUA_ErrInvalid(L, "mobj_t"); if (!rover) return LUA_ErrInvalid(L, "ffloor_t"); - lua_pushboolean(L, P_CheckSolidLava(mo, rover)); + if (!bound) + return LUA_ErrInvalid(L, "sector_t"); + lua_pushboolean(L, P_CheckSolidLava(mo, rover, bound)); return 1; } diff --git a/src/p_local.h b/src/p_local.h index 1fd7ada0..ce6aed02 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -238,7 +238,7 @@ fixed_t P_CameraCeilingZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, f boolean P_InsideANonSolidFFloor(mobj_t *mobj, ffloor_t *rover); boolean P_CheckDeathPitCollide(mobj_t *mo); -boolean P_CheckSolidLava(mobj_t *mo, ffloor_t *rover); +boolean P_CheckSolidLava(mobj_t *mo, ffloor_t *rover, sector_t *bound); mobj_t *P_SpawnMissile(mobj_t *source, mobj_t *dest, mobjtype_t type); mobj_t *P_SpawnXYZMissile(mobj_t *source, mobj_t *dest, mobjtype_t type, fixed_t x, fixed_t y, fixed_t z); diff --git a/src/p_map.c b/src/p_map.c index 6a555953..7b542660 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -1323,7 +1323,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) continue; } - if (thing->player && (P_CheckSolidLava(thing, rover) || P_CanRunOnWater(thing->player, rover))) + if (thing->player && (P_CheckSolidLava(thing, rover, newsubsec->sector) || P_CanRunOnWater(thing->player, rover))) ; else if (thing->type == MT_SKIM && (rover->flags & FF_SWIMMABLE)) ; diff --git a/src/p_maputl.c b/src/p_maputl.c index fea8530a..3aa9a994 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -646,7 +646,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (!(rover->flags & FF_EXISTS)) continue; - if (mobj->player && (P_CheckSolidLava(mobj, rover) || P_CanRunOnWater(mobj->player, rover))) + if (mobj->player && (P_CheckSolidLava(mobj, rover, front) || P_CanRunOnWater(mobj->player, rover))) ; else if (!((rover->flags & FF_BLOCKPLAYER && mobj->player) || (rover->flags & FF_BLOCKOTHERS && !mobj->player))) @@ -690,7 +690,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (!(rover->flags & FF_EXISTS)) continue; - if (mobj->player && (P_CheckSolidLava(mobj, rover) || P_CanRunOnWater(mobj->player, rover))) + if (mobj->player && (P_CheckSolidLava(mobj, rover, back) || P_CanRunOnWater(mobj->player, rover))) ; else if (!((rover->flags & FF_BLOCKPLAYER && mobj->player) || (rover->flags & FF_BLOCKOTHERS && !mobj->player))) diff --git a/src/p_mobj.c b/src/p_mobj.c index e7ec2f8b..4f0c8403 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1983,7 +1983,7 @@ static void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motyp topheight = P_GetFOFTopZ(mo, sector, rover, mo->x, mo->y, NULL); bottomheight = P_GetFOFBottomZ(mo, sector, rover, mo->x, mo->y, NULL); - if (mo->player && (P_CheckSolidLava(mo, rover) || P_CanRunOnWater(mo->player, rover))) // only the player should be affected + if (mo->player && (P_CheckSolidLava(mo, rover, sector) || P_CanRunOnWater(mo->player, rover))) // only the player should be affected ; else if (motype != 0 && rover->flags & FF_SWIMMABLE) // "scenery" only continue; @@ -2133,14 +2133,14 @@ boolean P_CheckDeathPitCollide(mobj_t *mo) return false; } -boolean P_CheckSolidLava(mobj_t *mo, ffloor_t *rover) +boolean P_CheckSolidLava(mobj_t *mo, ffloor_t *rover, sector_t *bound) { I_Assert(mo != NULL); I_Assert(!P_MobjWasRemoved(mo)); if (rover->flags & FF_SWIMMABLE && GETSECSPECIAL(rover->master->frontsector->special, 1) == 3 && !(rover->master->flags & ML_BLOCKMONSTERS) - && ((rover->master->flags & ML_EFFECT3) || mo->z-mo->momz > *rover->topheight - FixedMul(16*FRACUNIT, mo->scale))) + && ((rover->master->flags & ML_EFFECT3) || mo->z-mo->momz > P_GetSpecialTopZ(mo, rover->master->frontsector, bound) - FixedMul(16*FRACUNIT, mo->scale))) return true; return false; diff --git a/src/p_user.c b/src/p_user.c index f8dc942c..801eb595 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2908,7 +2908,7 @@ static void P_DoTeeter(player_t *player) bottomheight = P_GetZAt(*rover->b_slope, player->mo->x, player->mo->y); #endif - if (P_CheckSolidLava(player->mo, rover)) + if (P_CheckSolidLava(player->mo, rover, sec)) ; else if (!(rover->flags & FF_BLOCKPLAYER || rover->flags & FF_QUICKSAND)) continue; // intangible 3d floor From a2dabd70413ab9085d9b3af113e8aa0d86d1d27c Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Mon, 31 Oct 2016 14:03:53 +0000 Subject: [PATCH 05/11] Fixed a bunch of things MI pointed out. --- src/p_floor.c | 4 ++-- src/p_spec.c | 48 +++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/src/p_floor.c b/src/p_floor.c index b2c07bce..0af81efe 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -2201,14 +2201,14 @@ void T_EachTimeThinker(levelspecthink_t *eachtime) if ((netgame || multiplayer) && players[i].spectator) continue; - if (players[i].mo->subsector->sector == targetsec) + if (players[i].mo->subsector->sector == sec) ; else if (sec->flags & SF_TRIGGERSPECIAL_TOUCH) { boolean insector = false; for (node = players[i].mo->touching_sectorlist; node; node = node->m_sectorlist_next) { - if (node->m_sector == targetsec) + if (node->m_sector == sec) { insector = true; break; diff --git a/src/p_spec.c b/src/p_spec.c index 10a8f731..1fd94b2e 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3606,16 +3606,49 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers { if (roversector) { - if (!(players[i].mo->subsector->sector == roversector - || sector->flags & SF_TRIGGERSPECIAL_TOUCH)) + if (players[i].mo->subsector->sector == roversector) + ; + else if (sector->flags & SF_TRIGGERSPECIAL_TOUCH) + { + boolean insector = false; + msecnode_t *node; + for (node = players[i].mo->touching_sectorlist; node; node = node->m_sectorlist_next) + { + if (node->m_sector == roversector) + { + insector = true; + break; + } + } + if (!insector) + goto DoneSection2; + } + else goto DoneSection2; + if (!P_ThingIsOnThe3DFloor(players[i].mo, sector, roversector)) goto DoneSection2; } else { - if (!(players[i].mo->subsector->sector == sector - || sector->flags & SF_TRIGGERSPECIAL_TOUCH)) + if (players[i].mo->subsector->sector == sector) + ; + else if (sector->flags & SF_TRIGGERSPECIAL_TOUCH) + { + boolean insector = false; + msecnode_t *node; + for (node = players[i].mo->touching_sectorlist; node; node = node->m_sectorlist_next) + { + if (node->m_sector == sector) + { + insector = true; + break; + } + } + if (!insector) + goto DoneSection2; + } + else goto DoneSection2; if (special == 3 && !P_MobjReadyToTrigger(players[i].mo, sector)) @@ -4429,8 +4462,9 @@ sector_t *P_ThingOnSpecial3DFloor(mobj_t *mo) * \param player Player to check. * \sa P_ThingOnSpecial3DFloor, P_PlayerInSpecialSector */ -static void P_PlayerOnSpecial3DFloor(player_t *player, sector_t *sector, sector_t *originalsector) +static void P_PlayerOnSpecial3DFloor(player_t *player, sector_t *sector) { + sector_t *originalsector = player->mo->subsector->sector; ffloor_t *rover; fixed_t topheight, bottomheight; @@ -4683,7 +4717,7 @@ void P_PlayerInSpecialSector(player_t *player) originalsector = player->mo->subsector->sector; - P_PlayerOnSpecial3DFloor(player, originalsector, originalsector); // Handle FOFs first. + P_PlayerOnSpecial3DFloor(player, originalsector); // Handle FOFs first. if TELEPORTED return; P_RunSpecialSectorCheck(player, originalsector); @@ -4698,7 +4732,7 @@ void P_PlayerInSpecialSector(player_t *player) continue; // Check 3D floors... - P_PlayerOnSpecial3DFloor(player, loopsector, originalsector); + P_PlayerOnSpecial3DFloor(player, loopsector); if TELEPORTED return; if (!(loopsector->flags & SF_TRIGGERSPECIAL_TOUCH)) From 04a38a683bc436ad2e00ebebcc223b1acc059a28 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Mon, 31 Oct 2016 20:15:11 +0000 Subject: [PATCH 06/11] Okay, this is a biggun. Pay attention, everyone. Moved the handling of P_PlayerInSpecialSector to P_PlayerAfterThink from P_PlayerThink. * This allows the player to get hurt on sloped lava surfaces that are moving downwards. * Also prevents the player from standing on death pits for 1 tic. * Prevents the player moving 1 extra tic's worth of movement of pain when hit by sector. * Thankfully, no consequences re conveyors. * Like, the only consequences I've found have been positive. However, this DOES need to be thoroughly investigated before it can be allowed anywhere near Next itself. --- src/doomdef.h | 4 ++++ src/p_user.c | 13 +++++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/doomdef.h b/src/doomdef.h index fb8ab1ca..7d883849 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -495,4 +495,8 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; /// \note You should leave this enabled unless you're working with a future SRB2 version. #define MUSICSLOT_COMPATIBILITY +/// Handle touching sector specials in P_PlayerAfterThink instead of P_PlayerThink. +/// \note Required for proper collision with moving sloped surfaces that have sector specials on them. +#define SECTORSPECIALSAFTERTHINK + #endif // __DOOMDEF__ diff --git a/src/p_user.c b/src/p_user.c index 801eb595..921f1240 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8779,6 +8779,7 @@ void P_PlayerThink(player_t *player) // check water content, set stuff in mobj P_MobjCheckWater(player->mo); +#ifndef SECTORSPECIALSAFTERTHINK #ifdef POLYOBJECTS if (player->onconveyor != 1 || !P_IsObjectOnGround(player->mo)) #endif @@ -8787,6 +8788,7 @@ void P_PlayerThink(player_t *player) if (!player->spectator) P_PlayerInSpecialSector(player); +#endif if (player->playerstate == PST_DEAD) { @@ -9148,6 +9150,17 @@ void P_PlayerAfterThink(player_t *player) cmd = &player->cmd; +#ifdef SECTORSPECIALSAFTERTHINK +#ifdef POLYOBJECTS + if (player->onconveyor != 1 || !P_IsObjectOnGround(player->mo)) +#endif + player->onconveyor = 0; + // check special sectors : damage & secrets + + if (!player->spectator) + P_PlayerInSpecialSector(player); +#endif + if (splitscreen && player == &players[secondarydisplayplayer]) thiscam = &camera2; else if (player == &players[displayplayer]) From d13ca362d66360c87dc6f53a08b68f3d6501cb01 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Mon, 31 Oct 2016 21:34:43 +0000 Subject: [PATCH 07/11] Quicksand now supports slopes and also reverse gravity. --- src/p_user.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index 921f1240..f2f0cb77 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1940,6 +1940,7 @@ static void P_CheckQuicksand(player_t *player) { ffloor_t *rover; fixed_t sinkspeed, friction; + fixed_t topheight, bottomheight; if (!(player->mo->subsector->sector->ffloors && player->mo->momz <= 0)) return; @@ -1951,16 +1952,33 @@ static void P_CheckQuicksand(player_t *player) if (!(rover->flags & FF_QUICKSAND)) continue; - if (*rover->topheight >= player->mo->z && *rover->bottomheight < player->mo->z + player->mo->height) + topheight = P_GetSpecialTopZ(player->mo, sectors + rover->secnum, player->mo->subsector->sector); + bottomheight = P_GetSpecialBottomZ(player->mo, sectors + rover->secnum, player->mo->subsector->sector); + + if (topheight >= player->mo->z && bottomheight < player->mo->z + player->mo->height) { sinkspeed = abs(rover->master->v1->x - rover->master->v2->x)>>1; sinkspeed = FixedDiv(sinkspeed,TICRATE*FRACUNIT); - player->mo->z -= sinkspeed; + if (player->mo->eflags & MFE_VERTICALFLIP) + { + fixed_t ceilingheight = P_GetCeilingZ(player->mo, player->mo->subsector->sector, player->mo->x, player->mo->y, NULL); - if (player->mo->z <= player->mo->subsector->sector->floorheight) - player->mo->z = player->mo->subsector->sector->floorheight; + player->mo->z += sinkspeed; + + if (player->mo->z + player->mo->height >= ceilingheight) + player->mo->z = ceilingheight - player->mo->height; + } + else + { + fixed_t floorheight = P_GetFloorZ(player->mo, player->mo->subsector->sector, player->mo->x, player->mo->y, NULL); + + player->mo->z -= sinkspeed; + + if (player->mo->z <= floorheight) + player->mo->z = floorheight; + } friction = abs(rover->master->v1->y - rover->master->v2->y)>>6; From d21b091b967d2d76d259347e8f6da6dab620fc03 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Mon, 31 Oct 2016 22:14:34 +0000 Subject: [PATCH 08/11] * Slope/gravity support for quicksand complete. * Space sector support complete, bounds of drowning now altered slightly. * Knuckles climb now has symmetrical slope support for both normal and reverse gravity. * All slope-determining topheight and bottomheight code is now identical in form. * Camera postimages now support slopes properly. --- src/p_user.c | 89 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 67 insertions(+), 22 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index f2f0cb77..621122e2 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1607,9 +1607,8 @@ void P_DoPlayerExit(player_t *player) #define SPACESPECIAL 12 boolean P_InSpaceSector(mobj_t *mo) // Returns true if you are in space { - sector_t *sector; - - sector = mo->subsector->sector; + sector_t *sector = mo->subsector->sector; + fixed_t topheight, bottomheight; if (GETSECSPECIAL(sector->special, 1) == SPACESPECIAL) return true; @@ -1622,11 +1621,18 @@ boolean P_InSpaceSector(mobj_t *mo) // Returns true if you are in space { if (GETSECSPECIAL(rover->master->frontsector->special, 1) != SPACESPECIAL) continue; +#ifdef ESLOPE + topheight = *rover->t_slope ? P_GetZAt(*rover->t_slope, mo->x, mo->y) : *rover->topheight; + bottomheight = *rover->b_slope ? P_GetZAt(*rover->b_slope, mo->x, mo->y) : *rover->bottomheight; +#else + topheight = *rover->topheight; + bottomheight = *rover->bottomheight; +#endif - if (mo->z > *rover->topheight) + if (mo->z + (mo->height/2) > topheight) continue; - if (mo->z + (mo->height/2) < *rover->bottomheight) + if (mo->z + (mo->height/2) < bottomheight) continue; return true; @@ -1638,9 +1644,10 @@ boolean P_InSpaceSector(mobj_t *mo) // Returns true if you are in space boolean P_InQuicksand(mobj_t *mo) // Returns true if you are in quicksand { - sector_t *sector; + sector_t *sector = mo->subsector->sector; + fixed_t topheight, bottomheight; - sector = mo->subsector->sector; + fixed_t flipoffset = ((mo->eflags & MFE_VERTICALFLIP) ? (mo->height/2) : 0); if (sector->ffloors) { @@ -1654,10 +1661,18 @@ boolean P_InQuicksand(mobj_t *mo) // Returns true if you are in quicksand if (!(rover->flags & FF_QUICKSAND)) continue; - if (mo->z > *rover->topheight) +#ifdef ESLOPE + topheight = *rover->t_slope ? P_GetZAt(*rover->t_slope, mo->x, mo->y) : *rover->topheight; + bottomheight = *rover->b_slope ? P_GetZAt(*rover->b_slope, mo->x, mo->y) : *rover->bottomheight; +#else + topheight = *rover->topheight; + bottomheight = *rover->bottomheight; +#endif + + if (mo->z + flipoffset > topheight) continue; - if (mo->z + (mo->height/2) < *rover->bottomheight) + if (mo->z + (mo->height/2) + flipoffset < bottomheight) continue; return true; @@ -1952,8 +1967,13 @@ static void P_CheckQuicksand(player_t *player) if (!(rover->flags & FF_QUICKSAND)) continue; - topheight = P_GetSpecialTopZ(player->mo, sectors + rover->secnum, player->mo->subsector->sector); - bottomheight = P_GetSpecialBottomZ(player->mo, sectors + rover->secnum, player->mo->subsector->sector); +#ifdef ESLOPE + topheight = *rover->t_slope ? P_GetZAt(*rover->t_slope, player->mo->x, player->mo->y) : *rover->topheight; + bottomheight = *rover->b_slope ? P_GetZAt(*rover->b_slope, player->mo->x, player->mo->y) : *rover->bottomheight; +#else + topheight = *rover->topheight; + bottomheight = *rover->bottomheight; +#endif if (topheight >= player->mo->z && bottomheight < player->mo->z + player->mo->height) { @@ -2339,11 +2359,11 @@ static void P_DoClimbing(player_t *player) floorclimb = true; #ifdef ESLOPE - bottomheight = *rover->b_slope ? P_GetZAt(*rover->b_slope, player->mo->x, player->mo->y) : *rover->bottomheight; topheight = *rover->t_slope ? P_GetZAt(*rover->t_slope, player->mo->x, player->mo->y) : *rover->topheight; + bottomheight = *rover->b_slope ? P_GetZAt(*rover->b_slope, player->mo->x, player->mo->y) : *rover->bottomheight; #else - bottomheight = *rover->bottomheight; topheight = *rover->topheight; + bottomheight = *rover->bottomheight; #endif // Only supports rovers that are moving like an 'elevator', not just the top or bottom. @@ -2532,13 +2552,20 @@ static void P_DoClimbing(player_t *player) // Is there a FOF directly below that we can move onto? if (glidesector->sector->ffloors) { + fixed_t topheight; ffloor_t *rover; for (rover = glidesector->sector->ffloors; rover; rover = rover->next) { if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER) || (rover->flags & FF_BUSTUP)) continue; - if (*rover->topheight > ceilingheight - FixedMul(16*FRACUNIT, player->mo->scale)) +#ifdef ESLOPE + topheight = *rover->t_slope ? P_GetZAt(*rover->t_slope, player->mo->x, player->mo->y) : *rover->topheight; +#else + topheight = *rover->topheight; +#endif + + if (topheight > ceilingheight - FixedMul(16*FRACUNIT, player->mo->scale)) { foundfof = true; break; @@ -2916,14 +2943,12 @@ static void P_DoTeeter(player_t *player) { if (!(rover->flags & FF_EXISTS)) continue; +#ifdef ESLOPE + topheight = *rover->t_slope ? P_GetZAt(*rover->t_slope, player->mo->x, player->mo->y) : *rover->topheight; + bottomheight = *rover->b_slope ? P_GetZAt(*rover->b_slope, player->mo->x, player->mo->y) : *rover->bottomheight; +#else topheight = *rover->topheight; bottomheight = *rover->bottomheight; - -#ifdef ESLOPE - if (*rover->t_slope) - topheight = P_GetZAt(*rover->t_slope, player->mo->x, player->mo->y); - if (*rover->b_slope) - bottomheight = P_GetZAt(*rover->b_slope, player->mo->x, player->mo->y); #endif if (P_CheckSolidLava(player->mo, rover, sec)) @@ -8549,13 +8574,23 @@ static void P_CalcPostImg(player_t *player) else if (sector->ffloors) { ffloor_t *rover; + fixed_t topheight; + fixed_t bottomheight; for (rover = sector->ffloors; rover; rover = rover->next) { if (!(rover->flags & FF_EXISTS)) continue; - if (pviewheight >= *rover->topheight || pviewheight <= *rover->bottomheight) +#ifdef ESLOPE + topheight = *rover->t_slope ? P_GetZAt(*rover->t_slope, player->mo->x, player->mo->y) : *rover->topheight; + bottomheight = *rover->b_slope ? P_GetZAt(*rover->b_slope, player->mo->x, player->mo->y) : *rover->bottomheight; +#else + topheight = *rover->topheight; + bottomheight = *rover->bottomheight; +#endif + + if (pviewheight >= topheight || pviewheight <= bottomheight) continue; if (P_FindSpecialLineFromTag(13, rover->master->frontsector->tag, -1) != -1) @@ -8567,13 +8602,23 @@ static void P_CalcPostImg(player_t *player) if (sector->ffloors) { ffloor_t *rover; + fixed_t topheight; + fixed_t bottomheight; for (rover = sector->ffloors; rover; rover = rover->next) { if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_SWIMMABLE) || rover->flags & FF_BLOCKPLAYER) continue; - if (pviewheight >= *rover->topheight || pviewheight <= *rover->bottomheight) +#ifdef ESLOPE + topheight = *rover->t_slope ? P_GetZAt(*rover->t_slope, player->mo->x, player->mo->y) : *rover->topheight; + bottomheight = *rover->b_slope ? P_GetZAt(*rover->b_slope, player->mo->x, player->mo->y) : *rover->bottomheight; +#else + topheight = *rover->topheight; + bottomheight = *rover->bottomheight; +#endif + + if (pviewheight >= topheight || pviewheight <= bottomheight) continue; *type = postimg_water; From 7b12820c8298a2abfeb11e3c3f7c3e09839e5840 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Wed, 2 Nov 2016 20:32:36 +0000 Subject: [PATCH 09/11] Tweaked P_CheckSolidLava to avoid changing its function signature, and P_CanRunOnWater now supports slopes too. --- src/lua_baselib.c | 5 +---- src/p_local.h | 2 +- src/p_mobj.c | 30 ++++++++++++++++++++++-------- 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 00a51927..e8e8fd02 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -560,15 +560,12 @@ static int lib_pCheckSolidLava(lua_State *L) { mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR)); - sector_t *bound = *((sector_t **)luaL_checkudata(L, 3, META_SECTOR)); //HUDSAFE if (!mo) return LUA_ErrInvalid(L, "mobj_t"); if (!rover) return LUA_ErrInvalid(L, "ffloor_t"); - if (!bound) - return LUA_ErrInvalid(L, "sector_t"); - lua_pushboolean(L, P_CheckSolidLava(mo, rover, bound)); + lua_pushboolean(L, P_CheckSolidLava(mo, rover)); return 1; } diff --git a/src/p_local.h b/src/p_local.h index ce6aed02..1fd7ada0 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -238,7 +238,7 @@ fixed_t P_CameraCeilingZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, f boolean P_InsideANonSolidFFloor(mobj_t *mobj, ffloor_t *rover); boolean P_CheckDeathPitCollide(mobj_t *mo); -boolean P_CheckSolidLava(mobj_t *mo, ffloor_t *rover, sector_t *bound); +boolean P_CheckSolidLava(mobj_t *mo, ffloor_t *rover); mobj_t *P_SpawnMissile(mobj_t *source, mobj_t *dest, mobjtype_t type); mobj_t *P_SpawnXYZMissile(mobj_t *source, mobj_t *dest, mobjtype_t type, fixed_t x, fixed_t y, fixed_t z); diff --git a/src/p_mobj.c b/src/p_mobj.c index 4f0c8403..6ad84de3 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1983,7 +1983,7 @@ static void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motyp topheight = P_GetFOFTopZ(mo, sector, rover, mo->x, mo->y, NULL); bottomheight = P_GetFOFBottomZ(mo, sector, rover, mo->x, mo->y, NULL); - if (mo->player && (P_CheckSolidLava(mo, rover, sector) || P_CanRunOnWater(mo->player, rover))) // only the player should be affected + if (mo->player && (P_CheckSolidLava(mo, rover) || P_CanRunOnWater(mo->player, rover))) // only the player should be affected ; else if (motype != 0 && rover->flags & FF_SWIMMABLE) // "scenery" only continue; @@ -2133,15 +2133,23 @@ boolean P_CheckDeathPitCollide(mobj_t *mo) return false; } -boolean P_CheckSolidLava(mobj_t *mo, ffloor_t *rover, sector_t *bound) +boolean P_CheckSolidLava(mobj_t *mo, ffloor_t *rover) { I_Assert(mo != NULL); I_Assert(!P_MobjWasRemoved(mo)); - if (rover->flags & FF_SWIMMABLE && GETSECSPECIAL(rover->master->frontsector->special, 1) == 3 - && !(rover->master->flags & ML_BLOCKMONSTERS) - && ((rover->master->flags & ML_EFFECT3) || mo->z-mo->momz > P_GetSpecialTopZ(mo, rover->master->frontsector, bound) - FixedMul(16*FRACUNIT, mo->scale))) - return true; + { + fixed_t topheight = + #ifdef ESLOPE + *rover->t_slope ? P_GetZAt(*rover->t_slope, mo->x, mo->y) : + #endif + *rover->topheight; + + if (rover->flags & FF_SWIMMABLE && GETSECSPECIAL(rover->master->frontsector->special, 1) == 3 + && !(rover->master->flags & ML_BLOCKMONSTERS) + && ((rover->master->flags & ML_EFFECT3) || mo->z-mo->momz > topheight - FixedMul(16*FRACUNIT, mo->scale))) + return true; + } return false; } @@ -3076,11 +3084,17 @@ static boolean P_SceneryZMovement(mobj_t *mo) // boolean P_CanRunOnWater(player_t *player, ffloor_t *rover) { + fixed_t topheight = +#ifdef ESLOPE + *rover->t_slope ? P_GetZAt(*rover->t_slope, player->mo->x, player->mo->y) : +#endif + *rover->topheight; + if (!(player->pflags & PF_NIGHTSMODE) && !player->homing - && (((player->charability == CA_SWIM) || player->powers[pw_super] || player->charflags & SF_RUNONWATER) && player->mo->ceilingz-*rover->topheight >= player->mo->height) + && (((player->charability == CA_SWIM) || player->powers[pw_super] || player->charflags & SF_RUNONWATER) && player->mo->ceilingz-topheight >= player->mo->height) && (rover->flags & FF_SWIMMABLE) && !(player->pflags & PF_SPINNING) && player->speed > FixedMul(player->runspeed, player->mo->scale) && !(player->pflags & PF_SLIDING) - && abs(player->mo->z - *rover->topheight) < FixedMul(30*FRACUNIT, player->mo->scale)) + && abs(player->mo->z - topheight) < FixedMul(30*FRACUNIT, player->mo->scale)) return true; return false; From e67f48df83cd82bc67a0d24fc00333e5d2bba62f Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Wed, 2 Nov 2016 20:35:53 +0000 Subject: [PATCH 10/11] Forgot to revert the other files. --- src/p_map.c | 2 +- src/p_maputl.c | 4 ++-- src/p_user.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index 7b542660..6a555953 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -1323,7 +1323,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) continue; } - if (thing->player && (P_CheckSolidLava(thing, rover, newsubsec->sector) || P_CanRunOnWater(thing->player, rover))) + if (thing->player && (P_CheckSolidLava(thing, rover) || P_CanRunOnWater(thing->player, rover))) ; else if (thing->type == MT_SKIM && (rover->flags & FF_SWIMMABLE)) ; diff --git a/src/p_maputl.c b/src/p_maputl.c index 3aa9a994..fea8530a 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -646,7 +646,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (!(rover->flags & FF_EXISTS)) continue; - if (mobj->player && (P_CheckSolidLava(mobj, rover, front) || P_CanRunOnWater(mobj->player, rover))) + if (mobj->player && (P_CheckSolidLava(mobj, rover) || P_CanRunOnWater(mobj->player, rover))) ; else if (!((rover->flags & FF_BLOCKPLAYER && mobj->player) || (rover->flags & FF_BLOCKOTHERS && !mobj->player))) @@ -690,7 +690,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (!(rover->flags & FF_EXISTS)) continue; - if (mobj->player && (P_CheckSolidLava(mobj, rover, back) || P_CanRunOnWater(mobj->player, rover))) + if (mobj->player && (P_CheckSolidLava(mobj, rover) || P_CanRunOnWater(mobj->player, rover))) ; else if (!((rover->flags & FF_BLOCKPLAYER && mobj->player) || (rover->flags & FF_BLOCKOTHERS && !mobj->player))) diff --git a/src/p_user.c b/src/p_user.c index 621122e2..56ecdf80 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2951,7 +2951,7 @@ static void P_DoTeeter(player_t *player) bottomheight = *rover->bottomheight; #endif - if (P_CheckSolidLava(player->mo, rover, sec)) + if (P_CheckSolidLava(player->mo, rover)) ; else if (!(rover->flags & FF_BLOCKPLAYER || rover->flags & FF_QUICKSAND)) continue; // intangible 3d floor From 77399b8fb97711ca9fce68a093a247e9834a5579 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Tue, 6 Dec 2016 21:49:59 +0000 Subject: [PATCH 11/11] * Disabled #define SECTORSPECIALSAFTERTHINK. This did not need to be done in next, since it could have subtle consequences which we'd rather not deal with in the hyperextended patch cycle as-is. * Removed the adding of SF_TRIGGERSPECIAL_TOUCH for sectors with slopes in them. Too many undesired consequences, I'll handle them another way. --- src/doomdef.h | 2 +- src/p_slopes.c | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/doomdef.h b/src/doomdef.h index f993dadf..bccf433b 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -500,6 +500,6 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; /// Handle touching sector specials in P_PlayerAfterThink instead of P_PlayerThink. /// \note Required for proper collision with moving sloped surfaces that have sector specials on them. -#define SECTORSPECIALSAFTERTHINK +//#define SECTORSPECIALSAFTERTHINK #endif // __DOOMDEF__ diff --git a/src/p_slopes.c b/src/p_slopes.c index c127001c..d939fee9 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -281,7 +281,6 @@ void P_SpawnSlope_Line(int linenum) if(frontfloor || frontceil) { line->frontsector->hasslope = true; // Tell the software renderer that we're sloped - line->frontsector->flags |= SF_TRIGGERSPECIAL_TOUCH; // you're gonna want to get specials on contact origin.z = line->backsector->floorheight; direction.x = nx; @@ -408,7 +407,6 @@ void P_SpawnSlope_Line(int linenum) if(backfloor || backceil) { line->backsector->hasslope = true; // Tell the software renderer that we're sloped - line->backsector->flags |= SF_TRIGGERSPECIAL_TOUCH; // you're gonna want to get specials on contact origin.z = line->frontsector->floorheight; // Backsector @@ -601,7 +599,6 @@ void P_CopySectorSlope(line_t *line) } fsec->hasslope = true; - fsec->flags |= SF_TRIGGERSPECIAL_TOUCH; // you're gonna want to get specials on contact line->special = 0; // Linedef was use to set slopes, it finished its job, so now make it a normal linedef } @@ -721,7 +718,6 @@ void P_ResetDynamicSlopes(void) { *slopetoset = P_NewVertexSlope(lines[i].tag, lines[i].tag, lines[i].tag, flags); sides[lines[i].sidenum[which]].sector->hasslope = true; - sides[lines[i].sidenum[which]].sector->flags |= SF_TRIGGERSPECIAL_TOUCH; // you're gonna want to get specials on contact } break;