diff --git a/appveyor.yml b/appveyor.yml index cc073ff0..23b9b628 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -47,7 +47,7 @@ before_build: - upx -V - ccache -V - ccache -s -- set SRB2_MFLAGS=-C src MINGW=1 WARNINGMODE=1 GCC63=1 CCACHE=1 +- set SRB2_MFLAGS=-C src MINGW=1 WARNINGMODE=1 GCC63=1 CCACHE=1 NOOBJDUMP=1 build_script: - cmd: mingw32-make.exe %SRB2_MFLAGS% %CONFIGURATION%=1 clean diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 70631262..b8c6ee69 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2525,12 +2525,18 @@ static void Command_Nodes(void) static void Command_Ban(void) { - if (COM_Argc() == 1) + if (COM_Argc() < 2) { CONS_Printf(M_GetText("Ban : ban and kick a player\n")); return; } + if (!netgame) // Don't kick Tails in splitscreen! + { + CONS_Printf(M_GetText("This only works in a netgame.\n")); + return; + } + if (server || adminplayer == consoleplayer) { XBOXSTATIC UINT8 buf[3 + MAX_REASONLENGTH]; @@ -2540,8 +2546,9 @@ static void Command_Ban(void) if (pn == -1 || pn == 0) return; - else - WRITEUINT8(p, pn); + + WRITEUINT8(p, pn); + if (server && I_Ban && !I_Ban(node)) // only the server is allowed to do this right now { CONS_Alert(CONS_WARNING, M_GetText("Too many bans! Geez, that's a lot of people you're excluding...\n")); @@ -2584,21 +2591,27 @@ static void Command_Ban(void) static void Command_Kick(void) { - XBOXSTATIC UINT8 buf[3 + MAX_REASONLENGTH]; - UINT8 *p = buf; - - if (COM_Argc() == 1) + if (COM_Argc() < 2) { CONS_Printf(M_GetText("kick : kick a player\n")); return; } + if (!netgame) // Don't kick Tails in splitscreen! + { + CONS_Printf(M_GetText("This only works in a netgame.\n")); + return; + } + if (server || adminplayer == consoleplayer) { + XBOXSTATIC UINT8 buf[3 + MAX_REASONLENGTH]; + UINT8 *p = buf; const SINT8 pn = nametonum(COM_Argv(1)); - WRITESINT8(p, pn); + if (pn == -1 || pn == 0) return; + // Special case if we are trying to kick a player who is downloading the game state: // trigger a timeout instead of kicking them, because a kick would only // take effect after they have finished downloading @@ -2607,6 +2620,9 @@ static void Command_Kick(void) Net_ConnectionTimeout(playernode[pn]); return; } + + WRITESINT8(p, pn); + if (COM_Argc() == 2) { WRITEUINT8(p, KICK_MSG_GO_AWAY); @@ -3971,7 +3987,7 @@ FILESTAMP if (client) { INT32 i; - for (i = 0; i < MAXNETNODES; i++) + for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i]) playerpingtable[i] = (tic_t)netbuffer->u.pingtable[i]; } @@ -4534,8 +4550,8 @@ static inline void PingUpdate(void) } //send out our ping packets - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i]) + for (i = 0; i < MAXNETNODES; i++) + if (nodeingame[i]) HSendPacket(i, true, 0, sizeof(INT32) * MAXPLAYERS); pingmeasurecount = 1; //Reset count @@ -4565,20 +4581,15 @@ void NetUpdate(void) gametime = nowtime; - if (!(gametime % 255) && netgame && server) - { -#ifdef NEWPING - PingUpdate(); -#endif - } - #ifdef NEWPING if (server) { + if (netgame && !(gametime % 255)) + PingUpdate(); // update node latency values so we can take an average later. - for (i = 0; i < MAXNETNODES; i++) + for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i]) - realpingtable[i] += G_TicsToMilliseconds(GetLag(i)); + realpingtable[i] += G_TicsToMilliseconds(GetLag(playernode[i])); pingmeasurecount++; } #endif diff --git a/src/doomdef.h b/src/doomdef.h index cdb1a7db..1eca59d5 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -498,4 +498,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/g_game.c b/src/g_game.c index 7499fe7a..e3d4ac85 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2288,6 +2288,9 @@ void G_SpawnPlayer(INT32 playernum, boolean starpost) if (starpost) //Don't even bother with looking for a place to spawn. { P_MovePlayerToStarpost(playernum); +#ifdef HAVE_BLUA + LUAh_PlayerSpawn(&players[playernum]); // Lua hook for player spawning :) +#endif return; } @@ -3872,7 +3875,7 @@ void G_GhostAddColor(ghostcolor_t color) ghostext.color = (UINT8)color; } -void G_GhostAddScale(UINT16 scale) +void G_GhostAddScale(fixed_t scale) { if (!demorecording || !(demoflags & DF_GHOST)) return; diff --git a/src/g_game.h b/src/g_game.h index 6d412551..ada82404 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -139,7 +139,7 @@ void G_GhostAddSpin(void); void G_GhostAddRev(void); void G_GhostAddColor(ghostcolor_t color); void G_GhostAddFlip(void); -void G_GhostAddScale(UINT16 scale); +void G_GhostAddScale(fixed_t scale); void G_GhostAddHit(mobj_t *victim); void G_WriteGhostTic(mobj_t *ghost); void G_ConsGhostTic(void); diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 45b59f9b..05391f4d 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1084,9 +1084,9 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, float endheight = 0.0f, endbheight = 0.0f; fixed_t v1x = FLOAT_TO_FIXED(wallVerts[0].x); - fixed_t v1y = FLOAT_TO_FIXED(wallVerts[0].y); + fixed_t v1y = FLOAT_TO_FIXED(wallVerts[0].z); // not a typo fixed_t v2x = FLOAT_TO_FIXED(wallVerts[1].x); - fixed_t v2y = FLOAT_TO_FIXED(wallVerts[1].y); + fixed_t v2y = FLOAT_TO_FIXED(wallVerts[1].z); // not a typo // compiler complains when P_GetZAt is used in FLOAT_TO_FIXED directly // use this as a temp var to store P_GetZAt's return value each time fixed_t temp; @@ -3722,6 +3722,9 @@ static void HWR_Subsector(size_t num) while (count--) { +#ifdef POLYOBJECTS + if (!line->polyseg) // ignore segs that belong to polyobjects +#endif HWR_AddLine(line); line++; } diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index 28cc9176..566e7374 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -391,12 +391,21 @@ static int lib_cvRegisterVar(lua_State *L) // stack: cvar table, cvar userdata lua_getfield(L, LUA_REGISTRYINDEX, "CV_Vars"); I_Assert(lua_istable(L, 3)); + + lua_getfield(L, 3, cvar->name); + if (lua_type(L, -1) != LUA_TNIL) + return luaL_error(L, M_GetText("Variable %s is already defined\n"), cvar->name); + lua_pop(L, 1); + lua_pushvalue(L, 2); lua_setfield(L, 3, cvar->name); lua_pop(L, 1); // actually time to register it to the console now! Finally! + cvar->flags |= CV_MODIFIED; CV_RegisterVar(cvar); + if (cvar->flags & CV_MODIFIED) + return luaL_error(L, "failed to register cvar (probable conflict with internal variable/command names)"); // return cvar userdata return 1; diff --git a/src/lua_script.c b/src/lua_script.c index acb30682..991b8fcf 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -566,14 +566,14 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) { mobjinfo_t *info = *((mobjinfo_t **)lua_touserdata(gL, myindex)); WRITEUINT8(save_p, ARCH_MOBJINFO); - WRITEUINT8(save_p, info - mobjinfo); + WRITEUINT16(save_p, info - mobjinfo); break; } case ARCH_STATE: { state_t *state = *((state_t **)lua_touserdata(gL, myindex)); WRITEUINT8(save_p, ARCH_STATE); - WRITEUINT8(save_p, state - states); + WRITEUINT16(save_p, state - states); break; } case ARCH_MOBJ: diff --git a/src/p_floor.c b/src/p_floor.c index 91121301..ce35ca12 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -2021,6 +2021,33 @@ foundenemy: P_RemoveThinker(&nobaddies->thinker); } +// +// P_IsObjectOnRealGround +// +// Helper function for T_EachTimeThinker +// Like P_IsObjectOnGroundIn, except ONLY THE REAL GROUND IS CONSIDERED, NOT FOFS +// I'll consider whether to make this a more globally accessible function or whatever in future +// -- Monster Iestyn +// +static boolean P_IsObjectOnRealGround(mobj_t *mo, sector_t *sec) +{ + // Is the object in reverse gravity? + if (mo->eflags & MFE_VERTICALFLIP) + { + // Detect if the player is on the ceiling. + if (mo->z+mo->height >= P_GetSpecialTopZ(mo, sec, sec)) + return true; + } + // Nope! + else + { + // Detect if the player is on the floor. + if (mo->z <= P_GetSpecialBottomZ(mo, sec, sec)) + return true; + } + return false; +} + // // P_HavePlayersEnteredArea // @@ -2073,6 +2100,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,7 +2162,23 @@ void T_EachTimeThinker(levelspecthink_t *eachtime) if ((netgame || multiplayer) && players[j].spectator) continue; - if (players[j].mo->subsector->sector != targetsec) + 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; + } + else continue; topheight = P_GetSpecialTopZ(players[j].mo, sec, targetsec); @@ -2184,10 +2228,30 @@ 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 == 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 == sec) + { + insector = true; + break; + } + } + if (!insector) + continue; + } + else continue; - if (floortouch == true && P_IsObjectOnGroundIn(players[i].mo, sec)) + if (!(players[i].mo->subsector->sector == sec + || P_PlayerTouchingSectorSpecial(&players[i], 2, (GETSECSPECIAL(sec->special, 2))) == sec)) + continue; + + if (floortouch == true && P_IsObjectOnRealGround(players[i].mo, sec)) { if (i & 1) eachtime->var2s[i/2] |= 1; diff --git a/src/p_map.c b/src/p_map.c index 86776f8d..81bf9ebe 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -956,6 +956,8 @@ static boolean PIT_CheckThing(mobj_t *thing) if (iwassprung) // this spring caused you to gain MFE_SPRUNG just now... return false; // "cancel" P_TryMove via blocking so you keep your current position } + else if (tmthing->flags & MF_SPRING && (thing->player || thing->flags & MF_PUSHABLE)) + ; // Fix a few nasty spring-jumping bugs that happen sometimes. // Monitors are not treated as solid to players who are jumping, spinning or gliding, // unless it's a CTF team monitor and you're on the wrong team else if (thing->flags & MF_MONITOR && tmthing->player && tmthing->player->pflags & (PF_JUMPED|PF_SPINNING|PF_GLIDING) @@ -987,11 +989,13 @@ static boolean PIT_CheckThing(mobj_t *thing) topz = thing->z - thing->scale; // FixedMul(FRACUNIT, thing->scale), but thing->scale == FRACUNIT in base scale anyways + if (thing->flags & MF_SPRING) + ; // block only when jumping not high enough, // (dont climb max. 24units while already in air) // since return false doesn't handle momentum properly, // we lie to P_TryMove() so it's always too high - if (tmthing->player && tmthing->z + tmthing->height > topz + else if (tmthing->player && tmthing->z + tmthing->height > topz && tmthing->z + tmthing->height < tmthing->ceilingz) { tmfloorz = tmceilingz = topz; // block while in air @@ -1000,8 +1004,6 @@ static boolean PIT_CheckThing(mobj_t *thing) #endif tmfloorthing = thing; // needed for side collision } - else if (thing->flags & MF_SPRING) - ; else if (topz < tmceilingz && tmthing->z <= thing->z+thing->height) { tmceilingz = topz; @@ -1030,11 +1032,13 @@ static boolean PIT_CheckThing(mobj_t *thing) topz = thing->z + thing->height + thing->scale; // FixedMul(FRACUNIT, thing->scale), but thing->scale == FRACUNIT in base scale anyways + if (thing->flags & MF_SPRING) + ; // block only when jumping not high enough, // (dont climb max. 24units while already in air) // since return false doesn't handle momentum properly, // we lie to P_TryMove() so it's always too high - if (tmthing->player && tmthing->z < topz + else if (tmthing->player && tmthing->z < topz && tmthing->z > tmthing->floorz) { tmfloorz = tmceilingz = topz; // block while in air @@ -1043,8 +1047,6 @@ static boolean PIT_CheckThing(mobj_t *thing) #endif tmfloorthing = thing; // needed for side collision } - else if (thing->flags & MF_SPRING) - ; else if (topz > tmfloorz && tmthing->z+tmthing->height >= thing->z) { tmfloorz = topz; diff --git a/src/p_mobj.c b/src/p_mobj.c index 9fdbc37f..f0ff4f21 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2138,10 +2138,18 @@ 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 > *rover->topheight - 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; diff --git a/src/p_spec.c b/src/p_spec.c index 48c0f58b..4ddb90b0 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1742,7 +1742,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller case 305: // continuous case 306: // each time case 307: // once - if (!(actor && actor->player && actor->player->charability != dist/10)) + if (!(actor && actor->player && actor->player->charability == dist/10)) return false; break; case 309: // continuous @@ -2437,73 +2437,81 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 414: // Play SFX { - fixed_t sfxnum; + INT32 sfxnum; sfxnum = sides[line->sidenum[0]].toptexture; //P_AproxDistance(line->dx, line->dy)>>FRACBITS; - if (line->tag != 0 && line->flags & ML_EFFECT5) + if (sfxnum == sfx_None) + return; // Do nothing! + if (sfxnum < sfx_None || sfxnum >= NUMSFX) { - sector_t *sec; - - while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0) + CONS_Debug(DBG_GAMELOGIC, "Line type 414 Executor: sfx number %d is invalid!\n", sfxnum); + return; + } + if (line->tag != 0) // Do special stuff only if a non-zero linedef tag is set + { + if (line->flags & ML_EFFECT5) // Repeat Midtexture { - sec = §ors[secnum]; - S_StartSound(&sec->soundorg, sfxnum); + // Additionally play the sound from tagged sectors' soundorgs + sector_t *sec; + + while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0) + { + sec = §ors[secnum]; + S_StartSound(&sec->soundorg, sfxnum); + } + } + else if (mo) // A mobj must have triggered the executor + { + // Only trigger if mobj is touching the tag + ffloor_t *rover; + boolean foundit = false; + + for(rover = mo->subsector->sector->ffloors; rover; rover = rover->next) + { + if (rover->master->frontsector->tag != line->tag) + continue; + + if (mo->z > P_GetSpecialTopZ(mo, sectors + rover->secnum, mo->subsector->sector)) + continue; + + if (mo->z + mo->height < P_GetSpecialBottomZ(mo, sectors + rover->secnum, mo->subsector->sector)) + continue; + + foundit = true; + } + + if (mo->subsector->sector->tag == line->tag) + foundit = true; + + if (!foundit) + return; } } - else if (line->tag != 0 && mo) + + if (line->flags & ML_NOCLIMB) { - // Only trigger if mobj is touching the tag - ffloor_t *rover; - boolean foundit = false; - - for(rover = mo->subsector->sector->ffloors; rover; rover = rover->next) - { - if (rover->master->frontsector->tag != line->tag) - continue; - - if (mo->z > P_GetSpecialTopZ(mo, sectors + rover->secnum, mo->subsector->sector)) - continue; - - if (mo->z + mo->height < P_GetSpecialBottomZ(mo, sectors + rover->secnum, mo->subsector->sector)) - continue; - - foundit = true; - } - - if (mo->subsector->sector->tag == line->tag) - foundit = true; - - if (!foundit) - return; - } - - if (sfxnum < NUMSFX && sfxnum > sfx_None) - { - if (line->flags & ML_NOCLIMB) - { - // play the sound from nowhere, but only if display player triggered it - if (mo && mo->player && (mo->player == &players[displayplayer] || mo->player == &players[secondarydisplayplayer])) - S_StartSound(NULL, sfxnum); - } - else if (line->flags & ML_EFFECT4) - { - // play the sound from nowhere + // play the sound from nowhere, but only if display player triggered it + if (mo && mo->player && (mo->player == &players[displayplayer] || mo->player == &players[secondarydisplayplayer])) S_StartSound(NULL, sfxnum); - } - else if (line->flags & ML_BLOCKMONSTERS) - { - // play the sound from calling sector's soundorg - if (callsec) - S_StartSound(&callsec->soundorg, sfxnum); - else if (mo) - S_StartSound(&mo->subsector->sector->soundorg, sfxnum); - } + } + else if (line->flags & ML_EFFECT4) + { + // play the sound from nowhere + S_StartSound(NULL, sfxnum); + } + else if (line->flags & ML_BLOCKMONSTERS) + { + // play the sound from calling sector's soundorg + if (callsec) + S_StartSound(&callsec->soundorg, sfxnum); else if (mo) - { - // play the sound from mobj that triggered it - S_StartSound(mo, sfxnum); - } + S_StartSound(&mo->subsector->sector->soundorg, sfxnum); + } + else if (mo) + { + // play the sound from mobj that triggered it + S_StartSound(mo, sfxnum); } } break; @@ -3476,7 +3484,7 @@ static boolean P_ThingIsOnThe3DFloor(mobj_t *mo, sector_t *sector, sector_t *tar // // Is player standing on the sector's "ground"? // -static inline boolean P_MobjReadyToTrigger(mobj_t *mo, sector_t *sec) +static boolean P_MobjReadyToTrigger(mobj_t *mo, sector_t *sec) { if (mo->eflags & MFE_VERTICALFLIP) return (mo->z+mo->height == P_GetSpecialTopZ(mo, sec, sec) && sec->flags & SF_FLIPSPECIAL_CEILING); @@ -3611,14 +3619,49 @@ 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) + ; + 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) + 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)) @@ -4369,6 +4412,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) @@ -4376,8 +4420,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; @@ -4425,6 +4467,8 @@ 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. * @@ -4433,12 +4477,12 @@ sector_t *P_ThingOnSpecial3DFloor(mobj_t *mo) */ static void P_PlayerOnSpecial3DFloor(player_t *player, sector_t *sector) { + sector_t *originalsector = player->mo->subsector->sector; 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; @@ -4482,7 +4526,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! @@ -4493,7 +4540,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) { @@ -4569,6 +4616,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); } @@ -4673,40 +4721,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); // 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); + 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 diff --git a/src/p_user.c b/src/p_user.c index cb523585..7abf8534 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1221,11 +1221,12 @@ boolean P_IsObjectOnGroundIn(mobj_t *mo, sector_t *sec) if (!(rover->flags & FF_EXISTS)) continue; - // If the FOF is configured to let players through, continue. - if (!(rover->flags & FF_BLOCKPLAYER) && (rover->flags & FF_BLOCKOTHERS)) + // If the FOF is configured to let the object through, continue. + if (!((rover->flags & FF_BLOCKPLAYER && mo->player) + || (rover->flags & FF_BLOCKOTHERS && !mo->player))) continue; - // If the the platform is intangile from below, continue. + // If the the platform is intangible from below, continue. if (rover->flags & FF_PLATFORM) continue; @@ -1254,11 +1255,12 @@ boolean P_IsObjectOnGroundIn(mobj_t *mo, sector_t *sec) if (!(rover->flags & FF_EXISTS)) continue; - // If the FOF is configured to let players through, continue. - if (!(rover->flags & FF_BLOCKPLAYER) && (rover->flags & FF_BLOCKOTHERS)) + // If the FOF is configured to let the object through, continue. + if (!((rover->flags & FF_BLOCKPLAYER && mo->player) + || (rover->flags & FF_BLOCKOTHERS && !mo->player))) continue; - // If the the platform is intangile from above, continue. + // If the the platform is intangible from above, continue. if (rover->flags & FF_REVERSEPLATFORM) continue; @@ -1607,9 +1609,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 +1623,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 +1646,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 +1663,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; @@ -1940,6 +1957,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 +1969,38 @@ 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) +#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) { 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; @@ -2321,11 +2361,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. @@ -2514,13 +2554,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; @@ -2898,14 +2945,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)) @@ -8511,13 +8556,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) @@ -8529,13 +8584,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; @@ -8759,6 +8824,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 @@ -8767,6 +8833,7 @@ void P_PlayerThink(player_t *player) if (!player->spectator) P_PlayerInSpecialSector(player); +#endif if (player->playerstate == PST_DEAD) { @@ -9128,6 +9195,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]) diff --git a/src/r_bsp.c b/src/r_bsp.c index 44cb991a..abb11204 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -1222,6 +1222,9 @@ static void R_Subsector(size_t num) while (count--) { // CONS_Debug(DBG_GAMELOGIC, "Adding normal line %d...(%d)\n", line->linedef-lines, leveltime); +#ifdef POLYOBJECTS + if (!line->polyseg) // ignore segs that belong to polyobjects +#endif R_AddLine(line); line++; curline = NULL; /* cph 2001/11/18 - must clear curline now we're done with it, so stuff doesn't try using it for other things */ diff --git a/src/y_inter.c b/src/y_inter.c index 2fd37ff3..42f1e223 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -159,6 +159,20 @@ static void Y_CalculateMatchWinners(void); static void Y_FollowIntermission(void); static void Y_UnloadData(void); +// Stuff copy+pasted from st_stuff.c +static INT32 SCX(INT32 x) +{ + return FixedInt(FixedMul(x<