diff --git a/extras/conf/udb/Includes/SRB222_misc.cfg b/extras/conf/udb/Includes/SRB222_misc.cfg index 709514df8..d6210e9f1 100644 --- a/extras/conf/udb/Includes/SRB222_misc.cfg +++ b/extras/conf/udb/Includes/SRB222_misc.cfg @@ -82,6 +82,25 @@ sectorflags gravityflip = "Flip Objects in Reverse Gravity"; heatwave = "Heat Wave"; noclipcamera = "Intangible to the Camera"; + outerspace = "Space Countdown"; + doublestepup = "Ramp Sector (double step-up/down)"; + nostepdown = "Non-Ramp Sector (No step-down)"; + windcurrent = "Wind/Current"; + conveyor = "Conveyor Belt"; + speedpad = "Speed Pad"; + starpostactivator = "Star Post Activator"; + exit = "Exit"; + specialstagepit = "Special Stage Pit"; + returnflag = "Return Flag"; + redteambase = "Red Team Base"; + blueteambase = "Blue Team Base"; + fan = "Fan Sector"; + supertransform = "Super Sonic Transform"; + forcespin = "Force Spin"; + zoomtubestart = "Zoom Tube Start"; + zoomtubeend = "Zoom Tube End"; + finishline = "Circuit Finish Line"; + ropehang = "Rope Hang"; } thingflags diff --git a/src/deh_lua.c b/src/deh_lua.c index 10f5eb46d..56d2ec1e9 100644 --- a/src/deh_lua.c +++ b/src/deh_lua.c @@ -353,6 +353,16 @@ static inline int lib_getenum(lua_State *L) if (mathlib) return luaL_error(L, "sector flag '%s' could not be found.\n", word); return 0; } + else if (fastncmp("SSF_", word, 3)) { + p = word + 4; + for (i = 0; i < 19; i++) + if (SSF_LIST[i] && fastcmp(p, SSF_LIST[i])) { + lua_pushinteger(L, ((lua_Integer)1 << i)); + return 1; + } + if (mathlib) return luaL_error(L, "sector special flag '%s' could not be found.\n", word); + return 0; + } else if (fastncmp("S_",word,2)) { p = word+2; for (i = 0; i < NUMSTATEFREESLOTS; i++) { diff --git a/src/deh_tables.c b/src/deh_tables.c index 276bfce18..26fa74c90 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -4482,6 +4482,28 @@ const char *const MSF_LIST[7] = { "NOCLIPCAMERA", }; +// Sector special flags +const char* const SSF_LIST[19] = { + "OUTERSPACE", + "DOUBLESTEPUP", + "WINDCURRENT", + "CONVEYOR", + "SPEEDPAD", + "STARPOSTACTIVATOR", + "EXIT", + "SPECIALSTAGEPIT", + "RETURNFLAG", + "REDTEAMBASE", + "BLUETEAMBASE", + "FAN", + "SUPERTRANSFORM", + "FORCESPIN", + "ZOOMTUBESTART", + "ZOOMTUBEEND", + "FINISHLINE", + "ROPEHANG", +}; + const char *COLOR_ENUMS[] = { "NONE", // SKINCOLOR_NONE, diff --git a/src/deh_tables.h b/src/deh_tables.h index 8cabb2063..35f58c882 100644 --- a/src/deh_tables.h +++ b/src/deh_tables.h @@ -66,6 +66,7 @@ extern const char *const PLAYERFLAG_LIST[]; extern const char *const GAMETYPERULE_LIST[]; extern const char *const ML_LIST[16]; // Linedef flags extern const char* const MSF_LIST[7]; // Sector flags +extern const char* const SSF_LIST[19]; // Sector special flags extern const char *COLOR_ENUMS[]; extern const char *const POWERS_LIST[]; extern const char *const HUDITEMS_LIST[]; diff --git a/src/lua_baselib.c b/src/lua_baselib.c index d64f8abd2..27af76ed8 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -2215,6 +2215,18 @@ static int lib_pMobjTouchingSectorSpecial(lua_State *L) return 1; } +static int lib_pMobjTouchingSectorSpecialFlag(lua_State *L) +{ + mobj_t *mo = *((mobj_t**)luaL_checkudata(L, 1, META_MOBJ)); + sectorspecialflags_t flag = (INT32)luaL_checkinteger(L, 2); + //HUDSAFE + INLEVEL + if (!mo) + return LUA_ErrInvalid(L, "mobj_t"); + LUA_PushUserdata(L, P_MobjTouchingSectorSpecialFlag(mo, flag), META_SECTOR); + return 1; +} + static int lib_pPlayerTouchingSectorSpecial(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); @@ -2228,6 +2240,18 @@ static int lib_pPlayerTouchingSectorSpecial(lua_State *L) return 1; } +static int lib_pPlayerTouchingSectorSpecialFlag(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + sectorspecialflags_t flag = (INT32)luaL_checkinteger(L, 2); + //HUDSAFE + INLEVEL + if (!player) + return LUA_ErrInvalid(L, "player_t"); + LUA_PushUserdata(L, P_PlayerTouchingSectorSpecialFlag(player, flag), META_SECTOR); + return 1; +} + static int lib_pFindLowestFloorSurrounding(lua_State *L) { sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR)); @@ -4059,7 +4083,9 @@ static luaL_Reg lib[] = { {"P_DoSuperTransformation",lib_pDoSuperTransformation}, {"P_ExplodeMissile",lib_pExplodeMissile}, {"P_MobjTouchingSectorSpecial",lib_pMobjTouchingSectorSpecial}, + {"P_MobjTouchingSectorSpecialFlag",lib_pMobjTouchingSectorSpecialFlag}, {"P_PlayerTouchingSectorSpecial",lib_pPlayerTouchingSectorSpecial}, + {"P_PlayerTouchingSectorSpecialFlag",lib_pPlayerTouchingSectorSpecialFlag}, {"P_FindLowestFloorSurrounding",lib_pFindLowestFloorSurrounding}, {"P_FindHighestFloorSurrounding",lib_pFindHighestFloorSurrounding}, {"P_FindNextHighestFloor",lib_pFindNextHighestFloor}, diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 74f45535f..8ab8c7e83 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -50,6 +50,7 @@ enum sector_e { sector_fslope, sector_cslope, sector_flags, + sector_specialflags, sector_friction, sector_gravity, }; @@ -76,6 +77,7 @@ static const char *const sector_opt[] = { "f_slope", "c_slope", "flags", + "specialflags", "friction", "gravity", NULL}; @@ -658,6 +660,9 @@ static int sector_get(lua_State *L) case sector_flags: // flags lua_pushinteger(L, sector->flags); return 1; + case sector_specialflags: // specialflags + lua_pushinteger(L, sector->specialflags); + return 1; case sector_friction: // friction lua_pushinteger(L, sector->friction); return 1; @@ -755,6 +760,9 @@ static int sector_set(lua_State *L) sector->flags = luaL_checkinteger(L, 3); CheckForReverseGravity |= (sector->flags & MSF_GRAVITYFLIP); break; + case sector_specialflags: + sector->specialflags = luaL_checkinteger(L, 3); + break; case sector_gravity: sector->gravity = luaL_checkfixed(L, 3); break; diff --git a/src/p_inter.c b/src/p_inter.c index 028ac0ef3..caf247f96 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -763,6 +763,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // return; { UINT8 flagteam = (special->type == MT_REDFLAG) ? 1 : 2; + sectorspecialflags_t specialflag = (special->type == MT_REDFLAG) ? SSF_REDTEAMBASE : SSF_BLUETEAMBASE; const char *flagtext; char flagcolor; char plname[MAXPLAYERNAME+4]; @@ -792,7 +793,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) special->fuse = 1; special->flags2 |= MF2_JUSTATTACKED; - if (!P_PlayerTouchingSectorSpecial(player, 4, 2 + flagteam)) + if (!P_PlayerTouchingSectorSpecialFlag(player, specialflag)) { CONS_Printf(M_GetText("%s returned the %c%s%c to base.\n"), plname, flagcolor, flagtext, 0x80); diff --git a/src/p_map.c b/src/p_map.c index 8b236c7c3..beae1a8ea 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2699,14 +2699,14 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) if (thing->player) { - // If using type Section1:13, double the maxstep. - if (P_PlayerTouchingSectorSpecial(thing->player, 1, 13) - || GETSECSPECIAL(R_PointInSubsector(x, y)->sector->special, 1) == 13) + // If using SSF_DOUBLESTEPUP, double the maxstep. + if (P_PlayerTouchingSectorSpecialFlag(thing->player, SSF_DOUBLESTEPUP) + || (R_PointInSubsector(x, y)->sector->specialflags & SSF_DOUBLESTEPUP)) maxstep <<= 1; - // If using type Section1:14, no maxstep. - if (P_PlayerTouchingSectorSpecial(thing->player, 1, 14) - || GETSECSPECIAL(R_PointInSubsector(x, y)->sector->special, 1) == 14) + // If using SSF_NOSTEPDOWN, no maxstep. + if (P_PlayerTouchingSectorSpecialFlag(thing->player, SSF_NOSTEPDOWN) + || (R_PointInSubsector(x, y)->sector->specialflags & SSF_NOSTEPDOWN)) maxstep = 0; // Don't 'step up' while springing, @@ -2717,12 +2717,12 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) } else if (thing->flags & MF_PUSHABLE) { - // If using type Section1:13, double the maxstep. - if (GETSECSPECIAL(R_PointInSubsector(x, y)->sector->special, 1) == 13) + // If using SSF_DOUBLESTEPUP, double the maxstep. + if (R_PointInSubsector(x, y)->sector->specialflags & SSF_DOUBLESTEPUP) maxstep <<= 1; - // If using type Section1:14, no maxstep. - if (GETSECSPECIAL(R_PointInSubsector(x, y)->sector->special, 1) == 14) + // If using SSF_NOSTEPDOWN, no maxstep. + if (R_PointInSubsector(x, y)->sector->specialflags & SSF_NOSTEPDOWN) maxstep = 0; } diff --git a/src/p_mobj.c b/src/p_mobj.c index bdfee2616..4b31307ef 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -9738,7 +9738,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) break; case MT_BLUEFLAG: case MT_REDFLAG: - if (P_MobjTouchingSectorSpecial(mobj, 4, 2)) + if (P_MobjTouchingSectorSpecialFlag(mobj, SSF_RETURNFLAG)) mobj->fuse = 1; // Return to base. break; case MT_SPINDUST: // Spindash dust diff --git a/src/p_saveg.c b/src/p_saveg.c index d7a9750b7..1923fa576 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -853,7 +853,8 @@ static void P_NetUnArchiveWaypoints(void) #define SD_FLOORLIGHT 0x08 #define SD_CEILLIGHT 0x10 #define SD_FLAG 0x20 -#define SD_GRAVITY 0x40 +#define SD_SPECIALFLAG 0x40 +#define SD_GRAVITY 0x80 #define LD_FLAG 0x01 #define LD_SPECIAL 0x02 @@ -1041,6 +1042,8 @@ static void ArchiveSectors(void) diff3 |= SD_CEILLIGHT; if (ss->flags != spawnss->flags) diff3 |= SD_FLAG; + if (ss->specialflags != spawnss->specialflags) + diff3 |= SD_SPECIALFLAG; if (ss->gravity != spawnss->gravity) diff3 |= SD_GRAVITY; @@ -1109,6 +1112,8 @@ static void ArchiveSectors(void) } if (diff3 & SD_FLAG) WRITEUINT32(save_p, ss->flags); + if (diff3 & SD_SPECIALFLAG) + WRITEUINT32(save_p, ss->specialflags); if (diff3 & SD_GRAVITY) WRITEFIXED(save_p, ss->gravity); if (diff & SD_FFLOORS) @@ -1217,6 +1222,8 @@ static void UnArchiveSectors(void) sectors[i].flags = READUINT32(save_p); CheckForReverseGravity |= (sectors[i].flags & MSF_GRAVITYFLIP); } + if (diff3 & SD_SPECIALFLAG) + sectors[i].specialflags = READUINT32(save_p); if (diff3 & SD_GRAVITY) sectors[i].gravity = READFIXED(save_p); diff --git a/src/p_setup.c b/src/p_setup.c index 0f398c5bc..17fd5bb63 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1679,6 +1679,44 @@ static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val) sectors[i].flags |= MSF_HEATWAVE; else if (fastcmp(param, "noclipcamera") && fastcmp("true", val)) sectors[i].flags |= MSF_NOCLIPCAMERA; + else if (fastcmp(param, "outerspace") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_OUTERSPACE; + else if (fastcmp(param, "doublestepup") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_DOUBLESTEPUP; + else if (fastcmp(param, "nostepdown") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_NOSTEPDOWN; + else if (fastcmp(param, "windcurrent") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_WINDCURRENT; + else if (fastcmp(param, "conveyor") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_CONVEYOR; + else if (fastcmp(param, "speedpad") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_SPEEDPAD; + else if (fastcmp(param, "starpostactivator") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_STARPOSTACTIVATOR; + else if (fastcmp(param, "exit") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_EXIT; + else if (fastcmp(param, "specialstagepit") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_SPECIALSTAGEPIT; + else if (fastcmp(param, "returnflag") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_RETURNFLAG; + else if (fastcmp(param, "redteambase") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_REDTEAMBASE; + else if (fastcmp(param, "blueteambase") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_BLUETEAMBASE; + else if (fastcmp(param, "fan") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_FAN; + else if (fastcmp(param, "supertransform") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_SUPERTRANSFORM; + else if (fastcmp(param, "forcespin") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_FORCESPIN; + else if (fastcmp(param, "zoomtubestart") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_ZOOMTUBESTART; + else if (fastcmp(param, "zoomtubeend") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_ZOOMTUBEEND; + else if (fastcmp(param, "finishline") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_FINISHLINE; + else if (fastcmp(param, "ropehang") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_ROPEHANG; else if (fastcmp(param, "friction")) sectors[i].friction = atol(val); else if (fastcmp(param, "gravity")) @@ -5021,8 +5059,72 @@ static void P_ConvertBinaryMap(void) for (i = 0; i < numsectors; i++) { + + switch(GETSECSPECIAL(sectors[i].special, 1)) + { + case 12: //Space countdown + sectors[i].specialflags |= SSF_OUTERSPACE; + break; + case 13: //Ramp sector + sectors[i].specialflags |= SSF_DOUBLESTEPUP; + break; + case 14: //Non-ramp sector + sectors[i].specialflags |= SSF_NOSTEPDOWN; + break; + default: + break; + } + + switch(GETSECSPECIAL(sectors[i].special, 3)) + { + case 2: //Wind/Current + sectors[i].specialflags |= SSF_WINDCURRENT; + break; + case 4: //Conveyor belt + sectors[i].specialflags |= SSF_CONVEYOR; + break; + case 5: //Speed pad + sectors[i].specialflags |= SSF_SPEEDPAD; + break; + default: + break; + } + switch(GETSECSPECIAL(sectors[i].special, 4)) { + case 1: //Star post activator + sectors[i].specialflags |= SSF_STARPOSTACTIVATOR; + break; + case 2: //Exit/Special Stage pit/Return flag + sectors[i].specialflags |= SSF_EXIT|SSF_SPECIALSTAGEPIT|SSF_RETURNFLAG; + break; + case 3: //Red team base + sectors[i].specialflags |= SSF_REDTEAMBASE; + break; + case 4: //Blue team base + sectors[i].specialflags |= SSF_BLUETEAMBASE; + break; + case 5: //Fan sector + sectors[i].specialflags |= SSF_FAN; + break; + case 6: //Super Sonic transform + sectors[i].specialflags |= SSF_SUPERTRANSFORM; + break; + case 7: //Force spin + sectors[i].specialflags |= SSF_FORCESPIN; + break; + case 8: //Zoom tube start + sectors[i].specialflags |= SSF_ZOOMTUBESTART; + break; + case 9: //Zoom tube end + sectors[i].specialflags |= SSF_ZOOMTUBEEND; + break; + case 10: //Circuit finish line + sectors[i].specialflags |= SSF_FINISHLINE; + break; + case 11: //Rope hang + sectors[i].specialflags |= SSF_ROPEHANG; + break; case 12: //Intangible to the camera sectors[i].flags |= MSF_NOCLIPCAMERA; break; diff --git a/src/p_spec.c b/src/p_spec.c index 388440d75..2e4821972 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3933,7 +3933,7 @@ boolean P_IsFlagAtBase(mobjtype_t flag) { thinker_t *think; mobj_t *mo; - INT32 specialnum = (flag == MT_REDFLAG) ? 3 : 4; + sectorspecialflags_t specialflag = (flag == MT_REDFLAG) ? SSF_REDTEAMBASE : SSF_BLUETEAMBASE; for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { @@ -3945,7 +3945,7 @@ boolean P_IsFlagAtBase(mobjtype_t flag) if (mo->type != flag) continue; - if (GETSECSPECIAL(mo->subsector->sector->special, 4) == specialnum) + if (mo->subsector->sector->specialflags & specialflag) return true; else if (mo->subsector->sector->ffloors) // Check the 3D floors { @@ -3956,7 +3956,7 @@ boolean P_IsFlagAtBase(mobjtype_t flag) if (!(rover->flags & FF_EXISTS)) continue; - if (GETSECSPECIAL(rover->master->frontsector->special, 4) != specialnum) + if (!(rover->master->frontsector->specialflags & specialflag)) continue; if (!(mo->z <= P_GetSpecialTopZ(mo, sectors + rover->secnum, mo->subsector->sector) @@ -4041,6 +4041,30 @@ static sector_t *P_MobjTouching3DFloorSpecial(mobj_t *mo, sector_t *sector, INT3 return NULL; } +static sector_t *P_MobjTouching3DFloorSpecialFlag(mobj_t *mo, sector_t *sector, sectorspecialflags_t flag) +{ + ffloor_t *rover; + + for (rover = sector->ffloors; rover; rover = rover->next) + { + if (!(rover->master->frontsector->specialflags & flag)) + continue; + + if (!(rover->flags & FF_EXISTS)) + continue; + + if (!P_IsMobjTouching3DFloor(mo, rover, sector)) + continue; + + // This FOF has the special we're looking for, but are we allowed to touch it? + if (sector == mo->subsector->sector + || (rover->master->frontsector->flags & MSF_TRIGGERSPECIAL_TOUCH)) + return rover->master->frontsector; + } + + return NULL; +} + static sector_t *P_MobjTouchingPolyobjSpecial(mobj_t *mo, INT32 section, INT32 number) { polyobj_t *po; @@ -4073,6 +4097,38 @@ static sector_t *P_MobjTouchingPolyobjSpecial(mobj_t *mo, INT32 section, INT32 n return NULL; } +static sector_t *P_MobjTouchingPolyobjSpecialFlag(mobj_t *mo, sectorspecialflags_t flag) +{ + polyobj_t *po; + sector_t *polysec; + boolean touching = false; + boolean inside = false; + + for (po = mo->subsector->polyList; po; po = (polyobj_t *)(po->link.next)) + { + if (po->flags & POF_NOSPECIALS) + continue; + + polysec = po->lines[0]->backsector; + + if (!(polysec->specialflags & flag)) + continue; + + touching = (polysec->flags & MSF_TRIGGERSPECIAL_TOUCH) && P_MobjTouchingPolyobj(po, mo); + inside = P_MobjInsidePolyobj(po, mo); + + if (!(inside || touching)) + continue; + + if (!P_IsMobjTouchingPolyobj(mo, po, polysec)) + continue; + + return polysec; + } + + return NULL; +} + sector_t *P_MobjTouchingSectorSpecial(mobj_t *mo, INT32 section, INT32 number) { msecnode_t *node; @@ -4101,7 +4157,42 @@ sector_t *P_MobjTouchingSectorSpecial(mobj_t *mo, INT32 section, INT32 number) if (!(node->m_sector->flags & MSF_TRIGGERSPECIAL_TOUCH)) continue; - if (GETSECSPECIAL(mo->subsector->sector->special, section) == number) + if (GETSECSPECIAL(node->m_sector->special, section) == number) + return node->m_sector; + } + + return NULL; +} + +sector_t *P_MobjTouchingSectorSpecialFlag(mobj_t *mo, sectorspecialflags_t flag) +{ + msecnode_t *node; + sector_t *result; + + result = P_MobjTouching3DFloorSpecialFlag(mo, mo->subsector->sector, flag); + if (result) + return result; + + result = P_MobjTouchingPolyobjSpecialFlag(mo, flag); + if (result) + return result; + + if (mo->subsector->sector->specialflags & flag) + return mo->subsector->sector; + + for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next) + { + if (node->m_sector == mo->subsector->sector) // Don't duplicate + continue; + + result = P_MobjTouching3DFloorSpecialFlag(mo, node->m_sector, flag); + if (result) + return result; + + if (!(node->m_sector->flags & MSF_TRIGGERSPECIAL_TOUCH)) + continue; + + if (node->m_sector->specialflags & flag) return node->m_sector; } @@ -4127,6 +4218,14 @@ sector_t *P_PlayerTouchingSectorSpecial(player_t *player, INT32 section, INT32 n return P_MobjTouchingSectorSpecial(player->mo, section, number); } +sector_t *P_PlayerTouchingSectorSpecialFlag(player_t *player, sectorspecialflags_t flag) +{ + if (!player->mo) + return NULL; + + return P_MobjTouchingSectorSpecialFlag(player->mo, flag); +} + static sector_t *P_Check3DFloorTriggers(player_t *player, sector_t *sector, line_t *sourceline) { ffloor_t *rover; @@ -4371,7 +4470,7 @@ static void P_ProcessSpeedPad(player_t *player, sector_t *sector, sector_t *rove if (lineindex == -1) { - CONS_Debug(DBG_GAMELOGIC, "ERROR: Sector special %d missing line special #4.\n", sector->special); + CONS_Debug(DBG_GAMELOGIC, "ERROR: Speed pad missing line special #4.\n"); return; } @@ -4425,7 +4524,27 @@ static void P_ProcessSpeedPad(player_t *player, sector_t *sector, sector_t *rove S_StartSound(player->mo, sfxnum); } -static void P_ProcessExitSector(player_t *player, boolean isTouching, mtag_t sectag) +static void P_ProcessSpecialStagePit(player_t* player) +{ + if (!(gametyperules & GTR_ALLOWEXIT)) + return; + + if (player->bot) + return; + + if (!G_IsSpecialStage(gamemap)) + return; + + if (maptol & TOL_NIGHTS) + return; + + if (player->nightstime <= 6) + return; + + player->nightstime = 6; // Just let P_Ticker take care of the rest. +} + +static void P_ProcessExitSector(player_t *player, mtag_t sectag) { INT32 lineindex; @@ -4435,13 +4554,6 @@ static void P_ProcessExitSector(player_t *player, boolean isTouching, mtag_t sec if (player->bot) return; - if (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap)) - { - if (player->nightstime > 6 && isTouching) - player->nightstime = 6; // Just let P_Ticker take care of the rest. - return; - } - // Exit (for FOF exits; others are handled in P_PlayerThink in p_user.c) P_DoPlayerFinish(player); @@ -4515,7 +4627,7 @@ static void P_ProcessTeamBase(player_t *player, boolean redteam) P_AddPlayerScore(player, 250); } -static void P_ProcessZoomTube(player_t *player, sector_t *sector, mtag_t sectag, boolean end) +static void P_ProcessZoomTube(player_t *player, mtag_t sectag, boolean end) { INT32 sequence; fixed_t speed; @@ -4534,7 +4646,7 @@ static void P_ProcessZoomTube(player_t *player, sector_t *sector, mtag_t sectag, if (lineindex == -1) { - CONS_Debug(DBG_GAMELOGIC, "ERROR: Sector special %d missing line special #3.\n", sector->special); + CONS_Debug(DBG_GAMELOGIC, "ERROR: Zoom tube missing line special #3.\n"); return; } @@ -4630,7 +4742,7 @@ static void P_ProcessFinishLine(player_t *player) } } -static void P_ProcessRopeHang(player_t *player, sector_t *sector, mtag_t sectag) +static void P_ProcessRopeHang(player_t *player, mtag_t sectag) { INT32 sequence; fixed_t speed; @@ -4668,7 +4780,7 @@ static void P_ProcessRopeHang(player_t *player, sector_t *sector, mtag_t sectag) if (lineindex == -1) { - CONS_Debug(DBG_GAMELOGIC, "ERROR: Sector special %d missing line special #11.\n", sector->special); + CONS_Debug(DBG_GAMELOGIC, "ERROR: Rope hang missing line special #11.\n"); return; } @@ -4801,18 +4913,13 @@ static void P_ProcessRopeHang(player_t *player, sector_t *sector, mtag_t sectag) */ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *roversector) { - INT32 section1, section2, section3, section4; + INT32 section1, section2; mtag_t sectag = Tag_FGet(§or->tags); boolean isTouching; - if (!sector->special) + if (!sector->special && sector->specialflags == 0) return; - section1 = GETSECSPECIAL(sector->special, 1); - section2 = GETSECSPECIAL(sector->special, 2); - section3 = GETSECSPECIAL(sector->special, 3); - section4 = GETSECSPECIAL(sector->special, 4); - // Ignore spectators if (player->spectator) return; @@ -4823,12 +4930,74 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers if (player->playerstate != PST_LIVE) return; - // Conveyor stuff - if (section3 == 2 || section3 == 4) - player->onconveyor = section3; - isTouching = roversector || P_IsMobjTouchingSectorPlane(player->mo, sector); + if (sector->specialflags & SSF_OUTERSPACE) + { + if (!(player->powers[pw_shield] & SH_PROTECTWATER) && !player->powers[pw_spacetime]) + player->powers[pw_spacetime] = spacetimetics + 1; + } + if (sector->specialflags & SSF_WINDCURRENT) + player->onconveyor = 2; + if (sector->specialflags & SSF_CONVEYOR) + player->onconveyor = 4; + if ((sector->specialflags & SSF_SPEEDPAD) && isTouching) + P_ProcessSpeedPad(player, sector, roversector, sectag); + if (sector->specialflags & SSF_STARPOSTACTIVATOR) + { + mobj_t *post = P_GetObjectTypeInSectorNum(MT_STARPOST, sector - sectors); + if (post) + P_TouchStarPost(post, player, false); + } + if (sector->specialflags & SSF_EXIT) + P_ProcessExitSector(player, sectag); + if ((sector->specialflags & SSF_SPECIALSTAGEPIT) && isTouching) + P_ProcessSpecialStagePit(player); + if ((sector->specialflags & SSF_REDTEAMBASE) && isTouching) + P_ProcessTeamBase(player, true); + if ((sector->specialflags & SSF_BLUETEAMBASE) && isTouching) + P_ProcessTeamBase(player, false); + if (sector->specialflags & SSF_FAN) + { + player->mo->momz += mobjinfo[MT_FAN].mass/4; + + if (player->mo->momz > mobjinfo[MT_FAN].mass) + player->mo->momz = mobjinfo[MT_FAN].mass; + + P_ResetPlayer(player); + if (player->panim != PA_FALL) + P_SetPlayerMobjState(player->mo, S_PLAY_FALL); + } + if (sector->specialflags & SSF_SUPERTRANSFORM) + { + if (player->mo->health > 0 && !player->bot && (player->charflags & SF_SUPER) && !player->powers[pw_super] && ALL7EMERALDS(emeralds)) + P_DoSuperTransformation(player, true); + } + if ((sector->specialflags & SSF_FORCESPIN) && isTouching) + { + if (!(player->pflags & PF_SPINNING)) + { + player->pflags |= PF_SPINNING; + P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); + S_StartAttackSound(player->mo, sfx_spin); + + if (abs(player->rmomx) < FixedMul(5*FRACUNIT, player->mo->scale) + && abs(player->rmomy) < FixedMul(5*FRACUNIT, player->mo->scale)) + P_InstaThrust(player->mo, player->mo->angle, FixedMul(10*FRACUNIT, player->mo->scale)); + } + } + if (sector->specialflags & SSF_ZOOMTUBESTART) + P_ProcessZoomTube(player, sectag, false); + if (sector->specialflags & SSF_ZOOMTUBEEND) + P_ProcessZoomTube(player, sectag, true); + if (sector->specialflags & SSF_FINISHLINE) + P_ProcessFinishLine(player); + if ((sector->specialflags & SSF_ROPEHANG) && isTouching) + P_ProcessRopeHang(player, sectag); + + section1 = GETSECSPECIAL(sector->special, 1); + section2 = GETSECSPECIAL(sector->special, 2); + switch (section1) { case 1: // Damage (Generic) @@ -4891,20 +5060,10 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers P_SpecialStageDamage(player, NULL, NULL); break; - case 12: // Space Countdown - if (!(player->powers[pw_shield] & SH_PROTECTWATER) && !player->powers[pw_spacetime]) - player->powers[pw_spacetime] = spacetimetics + 1; - break; - case 13: // Ramp Sector (Increase step-up/down) - case 14: // Non-Ramp Sector (Don't step-down) - case 15: // Bouncy FOF (deprecated) - break; } switch (section2) { - case 1: // Trigger Linedef Exec (Pushable Objects) - break; case 2: // Linedef executor requires all players present+doesn't require touching floor case 3: // Linedef executor requires all players present if (!P_DoAllPlayersTrigger(sectag)) @@ -4919,111 +5078,10 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers if (!player->bot) P_LinedefExecute(sectag, player->mo, sector); break; - case 8: // Tells pushable things to check FOFs - break; case 9: // Egg trap capsule if (!udmf && roversector) P_ProcessEggCapsule(player, sector); break; - case 10: // Special Stage Time/Rings - case 11: // Custom Gravity - case 12: // Lua sector special - break; - } - - switch (section3) - { - case 1: // Unused - case 2: // Wind/Current - case 3: // Unused - case 4: // Conveyor Belt - break; - case 5: // Speed pad - if (isTouching) - P_ProcessSpeedPad(player, sector, roversector, sectag); - break; - case 6: // Unused - case 7: // Unused - case 8: // Unused - case 9: // Unused - case 10: // Unused - case 11: // Unused - case 12: // Unused - case 13: // Unused - case 14: // Unused - case 15: // Unused - break; - } - - switch (section4) - { - case 1: // Starpost Activator - { - mobj_t *post = P_GetObjectTypeInSectorNum(MT_STARPOST, sector - sectors); - - if (!post) - break; - - P_TouchStarPost(post, player, false); - break; - } - case 2: // Special stage GOAL sector / Exit Sector / CTF Flag Return - P_ProcessExitSector(player, isTouching, sectag); - break; - case 3: // Red Team's Base - if (isTouching) - P_ProcessTeamBase(player, true); - break; - case 4: // Blue Team's Base - if (isTouching) - P_ProcessTeamBase(player, false); - break; - case 5: // Fan sector - player->mo->momz += mobjinfo[MT_FAN].mass/4; - - if (player->mo->momz > mobjinfo[MT_FAN].mass) - player->mo->momz = mobjinfo[MT_FAN].mass; - - P_ResetPlayer(player); - if (player->panim != PA_FALL) - P_SetPlayerMobjState(player->mo, S_PLAY_FALL); - break; - case 6: // Super Sonic transformer - if (player->mo->health > 0 && !player->bot && (player->charflags & SF_SUPER) && !player->powers[pw_super] && ALL7EMERALDS(emeralds)) - P_DoSuperTransformation(player, true); - break; - case 7: // Make player spin - if (!isTouching) - break; - if (!(player->pflags & PF_SPINNING)) - { - player->pflags |= PF_SPINNING; - P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); - S_StartAttackSound(player->mo, sfx_spin); - - if (abs(player->rmomx) < FixedMul(5*FRACUNIT, player->mo->scale) - && abs(player->rmomy) < FixedMul(5*FRACUNIT, player->mo->scale)) - P_InstaThrust(player->mo, player->mo->angle, FixedMul(10*FRACUNIT, player->mo->scale)); - } - break; - case 8: // Zoom Tube Start - P_ProcessZoomTube(player, sector, sectag, false); - break; - case 9: // Zoom Tube End - P_ProcessZoomTube(player, sector, sectag, true); - break; - case 10: // Finish Line - P_ProcessFinishLine(player); - break; - case 11: // Rope hang - if (isTouching) - P_ProcessRopeHang(player, sector, sectag); - break; - case 12: // Unused - case 13: // Unused - case 14: // Unused - case 15: // Unused - break; } } @@ -5042,7 +5100,7 @@ static void P_PlayerOnSpecial3DFloor(player_t *player, sector_t *sector) for (rover = sector->ffloors; rover; rover = rover->next) { - if (!rover->master->frontsector->special) + if (!rover->master->frontsector->special && rover->master->frontsector->specialflags == 0) continue; if (!(rover->flags & FF_EXISTS)) @@ -5076,7 +5134,7 @@ static void P_PlayerOnSpecialPolyobj(player_t *player) polysec = po->lines[0]->backsector; - if (!polysec->special) + if (!polysec->special && polysec->specialflags == 0) continue; touching = (polysec->flags & MSF_TRIGGERSPECIAL_TOUCH) && P_MobjTouchingPolyobj(po, player->mo); @@ -6025,6 +6083,12 @@ void P_SpawnSpecials(boolean fromnetsave) { CheckForReverseGravity |= (sector->flags & MSF_GRAVITYFLIP); + if (sector->specialflags & SSF_FINISHLINE) + { + if ((gametyperules & (GTR_RACE|GTR_LIVES)) == GTR_RACE) + circuitmap = true; + } + if (!sector->special) continue; @@ -6063,15 +6127,6 @@ void P_SpawnSpecials(boolean fromnetsave) gravity = sector->floorheight/1000; break; } - - // Process Section 4 - switch(GETSECSPECIAL(sector->special, 4)) - { - case 10: // Circuit finish line - if ((gametyperules & (GTR_RACE|GTR_LIVES)) == GTR_RACE) - circuitmap = true; - break; - } } P_SpawnScrollers(); // Add generalized scrollers @@ -8332,17 +8387,17 @@ void T_Pusher(pusher_t *p) sec = sectors + p->affectee; - // Be sure the special sector type is still turned on. If so, proceed. - // Else, bail out; the sector type has been changed on us. + // Be sure the sector special flag is still turned on. If so, proceed. + // Else, bail out; the flag has been changed on us. if (p->roverpusher) { referrer = §ors[p->referrer]; - if (GETSECSPECIAL(referrer->special, 3) != 2) + if (!(referrer->specialflags & SSF_WINDCURRENT)) return; } - else if (GETSECSPECIAL(sec->special, 3) != 2) + else if (!(sec->specialflags & SSF_WINDCURRENT)) return; // For constant pushers (wind/current) there are 3 situations: diff --git a/src/p_spec.h b/src/p_spec.h index c1f25b3d6..19d3bd103 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -480,7 +480,9 @@ void P_SpawnSpecials(boolean fromnetsave); // every tic void P_UpdateSpecials(void); sector_t *P_MobjTouchingSectorSpecial(mobj_t *mo, INT32 section, INT32 number); +sector_t *P_MobjTouchingSectorSpecialFlag(mobj_t *mo, sectorspecialflags_t flag); sector_t *P_PlayerTouchingSectorSpecial(player_t *player, INT32 section, INT32 number); +sector_t *P_PlayerTouchingSectorSpecialFlag(player_t *player, sectorspecialflags_t flag); void P_PlayerInSpecialSector(player_t *player); void P_CheckPushableTrigger(mobj_t *mobj, sector_t *sec); void P_CheckMobjTrigger(mobj_t *mobj); diff --git a/src/p_user.c b/src/p_user.c index 45c64500f..1006e21ed 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2166,13 +2166,12 @@ void P_DoPlayerExit(player_t *player) P_RestoreMusic(player); } -#define SPACESPECIAL 12 boolean P_InSpaceSector(mobj_t *mo) // Returns true if you are in space { sector_t *sector = mo->subsector->sector; fixed_t topheight, bottomheight; - if (GETSECSPECIAL(sector->special, 1) == SPACESPECIAL) + if (sector->specialflags & SSF_OUTERSPACE) return true; if (sector->ffloors) @@ -2184,7 +2183,7 @@ boolean P_InSpaceSector(mobj_t *mo) // Returns true if you are in space if (!(rover->flags & FF_EXISTS)) continue; - if (GETSECSPECIAL(rover->master->frontsector->special, 1) != SPACESPECIAL) + if (!(rover->master->frontsector->specialflags & SSF_OUTERSPACE)) continue; topheight = P_GetFFloorTopZAt (rover, mo->x, mo->y); bottomheight = P_GetFFloorBottomZAt(rover, mo->x, mo->y); @@ -4678,7 +4677,7 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) if (onground && player->pflags & PF_SPINNING && !(player->pflags & PF_STARTDASH) && player->speed < 5*player->mo->scale && canstand) { - if (GETSECSPECIAL(player->mo->subsector->sector->special, 4) == 7 || (player->mo->ceilingz - player->mo->floorz < P_GetPlayerHeight(player))) + if ((player->mo->subsector->sector->specialflags & SSF_FORCESPIN) || (player->mo->ceilingz - player->mo->floorz < P_GetPlayerHeight(player))) P_InstaThrust(player->mo, player->mo->angle, 10*player->mo->scale); else { diff --git a/src/r_defs.h b/src/r_defs.h index 833958ab1..2b1cbfa58 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -289,6 +289,28 @@ typedef enum MSF_NOCLIPCAMERA = 1<<7, } sectorflags_t; +typedef enum +{ + SSF_OUTERSPACE = 1, + SSF_DOUBLESTEPUP = 1<<1, + SSF_NOSTEPDOWN = 1<<2, + SSF_WINDCURRENT = 1<<3, + SSF_CONVEYOR = 1<<4, + SSF_SPEEDPAD = 1<<5, + SSF_STARPOSTACTIVATOR = 1<<6, + SSF_EXIT = 1<<7, + SSF_SPECIALSTAGEPIT = 1<<8, + SSF_RETURNFLAG = 1<<9, + SSF_REDTEAMBASE = 1<<10, + SSF_BLUETEAMBASE = 1<<11, + SSF_FAN = 1<<12, + SSF_SUPERTRANSFORM = 1<<13, + SSF_FORCESPIN = 1<<14, + SSF_ZOOMTUBESTART = 1<<15, + SSF_ZOOMTUBEEND = 1<<16, + SSF_FINISHLINE = 1<<17, + SSF_ROPEHANG = 1<<18, +} sectorspecialflags_t; typedef enum { @@ -371,6 +393,7 @@ typedef struct sector_s fixed_t gravity; // per-sector gravity factor fixed_t *gravityptr; // For binary format: Read gravity from floor height of master sector sectorflags_t flags; + sectorspecialflags_t specialflags; INT32 friction;