From 208395214a4e75852f5dcc53baafc4d64fdc81b0 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 31 Dec 2021 11:39:34 +0100 Subject: [PATCH] Implement sector fields for linedef executor triggering --- extras/conf/udb/Includes/SRB222_misc.cfg | 20 ++ src/deh_lua.c | 10 + src/deh_tables.c | 10 + src/deh_tables.h | 1 + src/lua_maplib.c | 16 ++ src/p_floor.c | 5 +- src/p_mobj.c | 6 +- src/p_saveg.c | 16 +- src/p_setup.c | 58 ++++++ src/p_spec.c | 240 ++++++++++++++--------- src/p_spec.h | 3 +- src/r_defs.h | 25 ++- 12 files changed, 299 insertions(+), 111 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_misc.cfg b/extras/conf/udb/Includes/SRB222_misc.cfg index d6210e9f1..537214b58 100644 --- a/extras/conf/udb/Includes/SRB222_misc.cfg +++ b/extras/conf/udb/Includes/SRB222_misc.cfg @@ -78,6 +78,8 @@ sectorflags flipspecial_ceiling = "Trigger on Ceiling Touch"; triggerspecial_touch = "Trigger on Edge Touch"; triggerspecial_headbump = "Trigger on Headbump"; + triggerline_plane = "Linedef Trigger Requires Plane Touch"; + triggerline_mobj = "Non-Pushables Can Trigger Linedef"; invertprecip = "Invert Precipitation"; gravityflip = "Flip Objects in Reverse Gravity"; heatwave = "Heat Wave"; @@ -253,6 +255,24 @@ universalfields type = 0; default = 0; } + + triggertag + { + type = 15; + default = 0; + } + + triggerer + { + type = 0; + default = 0; + enum + { + 0 = "Player"; + 1 = "All players"; + 2 = "Object"; + } + } } linedef diff --git a/src/deh_lua.c b/src/deh_lua.c index e313c5888..9472c1e7b 100644 --- a/src/deh_lua.c +++ b/src/deh_lua.c @@ -373,6 +373,16 @@ static inline int lib_getenum(lua_State *L) if (mathlib) return luaL_error(L, "sector damagetype '%s' could not be found.\n", word); return 0; } + else if (fastncmp("TO_", word, 3)) { + p = word + 3; + for (i = 0; TO_LIST[i]; i++) + if (fastcmp(p, TO_LIST[i])) { + lua_pushinteger(L, i); + return 1; + } + if (mathlib) return luaL_error(L, "sector triggerer '%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 1409fae58..bc3368e06 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -4478,6 +4478,8 @@ const char *const MSF_LIST[] = { "FLIPSPECIAL_CEILING", "TRIGGERSPECIAL_TOUCH", "TRIGGERSPECIAL_HEADBUMP", + "TRIGGERLINE_PLANE", + "TRIGGERLINE_MOBJ", "GRAVITYFLIP", "HEATWAVE", "NOCLIPCAMERA", @@ -4522,6 +4524,14 @@ const char *const SD_LIST[] = { NULL }; +// Sector triggerer +const char *const TO_LIST[] = { + "PLAYER", + "ALLPLAYERS", + "MOBJ", + NULL +}; + const char *COLOR_ENUMS[] = { "NONE", // SKINCOLOR_NONE, diff --git a/src/deh_tables.h b/src/deh_tables.h index 3fbc6357b..dccf98252 100644 --- a/src/deh_tables.h +++ b/src/deh_tables.h @@ -68,6 +68,7 @@ extern const char *const ML_LIST[]; // Linedef flags extern const char *const MSF_LIST[]; // Sector flags extern const char *const SSF_LIST[]; // Sector special flags extern const char *const SD_LIST[]; // Sector damagetype +extern const char *const TO_LIST[]; // Sector triggerer extern const char *COLOR_ENUMS[]; extern const char *const POWERS_LIST[]; extern const char *const HUDITEMS_LIST[]; diff --git a/src/lua_maplib.c b/src/lua_maplib.c index b18f4a44f..4bbd826ef 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -52,6 +52,8 @@ enum sector_e { sector_flags, sector_specialflags, sector_damagetype, + sector_triggertag, + sector_triggerer, sector_friction, sector_gravity, }; @@ -80,6 +82,8 @@ static const char *const sector_opt[] = { "flags", "specialflags", "damagetype", + "triggertag", + "triggerer", "friction", "gravity", NULL}; @@ -668,6 +672,12 @@ static int sector_get(lua_State *L) case sector_damagetype: // damagetype lua_pushinteger(L, (UINT8)sector->damagetype); return 1; + case sector_triggertag: // triggertag + lua_pushinteger(L, (INT16)sector->triggertag); + return 1; + case sector_triggerer: // triggerer + lua_pushinteger(L, (UINT8)sector->triggerer); + return 1; case sector_friction: // friction lua_pushinteger(L, sector->friction); return 1; @@ -771,6 +781,12 @@ static int sector_set(lua_State *L) case sector_damagetype: sector->damagetype = (UINT8)luaL_checkinteger(L, 3); break; + case sector_triggertag: + sector->triggertag = (INT16)luaL_checkinteger(L, 3); + break; + case sector_triggerer: + sector->triggerer = (UINT8)luaL_checkinteger(L, 3); + break; case sector_gravity: sector->gravity = luaL_checkfixed(L, 3); break; diff --git a/src/p_floor.c b/src/p_floor.c index 85a1f54a8..5f71a1fbe 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -1276,7 +1276,6 @@ void T_EachTimeThinker(eachtime_t *eachtime) sector_t *caller[MAXPLAYERS]; boolean allPlayersChecked = false; boolean allPlayersTrigger = false; - mtag_t tag = Tag_FGet(&eachtime->sourceline->tags); for (i = 0; i < MAXPLAYERS; i++) { @@ -1300,7 +1299,7 @@ void T_EachTimeThinker(eachtime_t *eachtime) continue; // If sector has an "all players" trigger type, all players need to be in area - if (caller[i] && (GETSECSPECIAL(caller[i]->special, 2) == 2 || GETSECSPECIAL(caller[i]->special, 2) == 3)) + if (caller[i] && caller[i]->triggerer == TO_ALLPLAYERS) { if (!allPlayersChecked) { @@ -1312,7 +1311,7 @@ void T_EachTimeThinker(eachtime_t *eachtime) continue; } - CONS_Debug(DBG_GAMELOGIC, "Trying to activate each time executor with tag %d\n", tag); + CONS_Debug(DBG_GAMELOGIC, "Trying to activate each time executor with tag %d\n", Tag_FGet(&eachtime->sourceline->tags)); // 03/08/14 -Monster Iestyn // No more stupid hacks involving changing eachtime->sourceline's tag or special or whatever! diff --git a/src/p_mobj.c b/src/p_mobj.c index 004575a79..57ff8d4f1 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10161,8 +10161,8 @@ void P_MobjThinker(mobj_t *mobj) tmfloorthing = tmhitthing = NULL; - // Sector special (2,8) allows ANY mobj to trigger a linedef exec - P_CheckMobjTrigger(mobj); + // Sector flag MSF_TRIGGERLINE_MOBJ allows ANY mobj to trigger a linedef exec + P_CheckMobjTrigger(mobj, false); if (mobj->scale != mobj->destscale) P_MobjScaleThink(mobj); // Slowly scale up/down to reach your destscale. @@ -10382,7 +10382,7 @@ void P_PushableThinker(mobj_t *mobj) I_Assert(mobj != NULL); I_Assert(!P_MobjWasRemoved(mobj)); - P_CheckPushableTrigger(mobj, mobj->subsector->sector); + P_CheckMobjTrigger(mobj, true); // it has to be pushable RIGHT NOW for this part to happen if (mobj->flags & MF_PUSHABLE && !(mobj->momx || mobj->momy)) diff --git a/src/p_saveg.c b/src/p_saveg.c index 1baa34582..50608ad7a 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -858,7 +858,9 @@ static void P_NetUnArchiveWaypoints(void) //diff4 flags #define SD_DAMAGETYPE 0x01 -#define SD_GRAVITY 0x02 +#define SD_TRIGGERTAG 0x02 +#define SD_TRIGGERER 0x04 +#define SD_GRAVITY 0x08 #define LD_FLAG 0x01 #define LD_SPECIAL 0x02 @@ -1050,6 +1052,10 @@ static void ArchiveSectors(void) diff3 |= SD_SPECIALFLAG; if (ss->damagetype != spawnss->damagetype) diff4 |= SD_DAMAGETYPE; + if (ss->triggertag != spawnss->triggertag) + diff4 |= SD_TRIGGERTAG; + if (ss->triggerer != spawnss->triggerer) + diff4 |= SD_TRIGGERER; if (ss->gravity != spawnss->gravity) diff4 |= SD_GRAVITY; @@ -1127,6 +1133,10 @@ static void ArchiveSectors(void) WRITEUINT32(save_p, ss->specialflags); if (diff4 & SD_DAMAGETYPE) WRITEUINT8(save_p, ss->damagetype); + if (diff4 & SD_TRIGGERTAG) + WRITEINT16(save_p, ss->triggertag); + if (diff4 & SD_TRIGGERER) + WRITEUINT8(save_p, ss->triggerer); if (diff4 & SD_GRAVITY) WRITEFIXED(save_p, ss->gravity); if (diff & SD_FFLOORS) @@ -1243,6 +1253,10 @@ static void UnArchiveSectors(void) sectors[i].specialflags = READUINT32(save_p); if (diff4 & SD_DAMAGETYPE) sectors[i].damagetype = READUINT8(save_p); + if (diff4 & SD_TRIGGERTAG) + sectors[i].triggertag = READINT16(save_p); + if (diff4 & SD_TRIGGERER) + sectors[i].triggerer = READUINT8(save_p); if (diff4 & SD_GRAVITY) sectors[i].gravity = READFIXED(save_p); diff --git a/src/p_setup.c b/src/p_setup.c index 4efbc4e4b..f64bd842c 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1051,6 +1051,8 @@ static void P_LoadSectors(UINT8 *data) ss->flags = MSF_FLIPSPECIAL_FLOOR; ss->specialflags = 0; ss->damagetype = SD_NONE; + ss->triggertag = 0; + ss->triggerer = TO_PLAYER; P_InitializeSector(ss); } @@ -1673,6 +1675,10 @@ static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val) sectors[i].flags |= MSF_TRIGGERSPECIAL_TOUCH; else if (fastcmp(param, "triggerspecial_headbump") && fastcmp("true", val)) sectors[i].flags |= MSF_TRIGGERSPECIAL_HEADBUMP; + else if (fastcmp(param, "triggerline_plane") && fastcmp("true", val)) + sectors[i].flags |= MSF_TRIGGERLINE_PLANE; + else if (fastcmp(param, "triggerline_mobj") && fastcmp("true", val)) + sectors[i].flags |= MSF_TRIGGERLINE_MOBJ; else if (fastcmp(param, "invertprecip") && fastcmp("true", val)) sectors[i].flags |= MSF_INVERTPRECIP; else if (fastcmp(param, "gravityflip") && fastcmp("true", val)) @@ -1744,6 +1750,10 @@ static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val) if (fastcmp(val, "SpecialStage")) sectors[i].damagetype = SD_SPECIALSTAGE; } + else if (fastcmp(param, "triggertag")) + sectors[i].triggertag = atol(val); + else if (fastcmp(param, "triggerer")) + sectors[i].triggerer = atol(val); } static void ParseTextmapSidedefParameter(UINT32 i, char *param, char *val) @@ -2025,6 +2035,8 @@ static void P_LoadTextmap(void) sc->flags = MSF_FLIPSPECIAL_FLOOR; sc->specialflags = 0; sc->damagetype = SD_NONE; + sc->triggertag = 0; + sc->triggerer = TO_PLAYER; textmap_colormap.used = false; textmap_colormap.lightcolor = 0; @@ -5084,6 +5096,8 @@ static void P_ConvertBinaryMap(void) for (i = 0; i < numsectors; i++) { + mtag_t tag = Tag_FGet(§ors[i].tags); + switch(GETSECSPECIAL(sectors[i].special, 1)) { case 1: //Damage @@ -5126,6 +5140,50 @@ static void P_ConvertBinaryMap(void) break; } + switch(GETSECSPECIAL(sectors[i].special, 2)) + { + case 1: //Trigger linedef executor (pushable objects) + sectors[i].triggertag = tag; + sectors[i].flags |= MSF_TRIGGERLINE_PLANE; + sectors[i].triggerer = TO_MOBJ; + break; + case 2: //Trigger linedef executor (Anywhere in sector, all players) + sectors[i].triggertag = tag; + sectors[i].flags &= ~MSF_TRIGGERLINE_PLANE; + sectors[i].triggerer = TO_ALLPLAYERS; + break; + case 3: //Trigger linedef executor (Floor touch, all players) + sectors[i].triggertag = tag; + sectors[i].flags |= MSF_TRIGGERLINE_PLANE; + sectors[i].triggerer = TO_ALLPLAYERS; + break; + case 4: //Trigger linedef executor (Anywhere in sector) + sectors[i].triggertag = tag; + sectors[i].flags &= ~MSF_TRIGGERLINE_PLANE; + sectors[i].triggerer = TO_PLAYER; + break; + case 5: //Trigger linedef executor (Floor touch) + sectors[i].triggertag = tag; + sectors[i].flags |= MSF_TRIGGERLINE_PLANE; + sectors[i].triggerer = TO_PLAYER; + break; + case 6: //Trigger linedef executor (Emerald check) + sectors[i].triggertag = tag; + sectors[i].flags &= ~MSF_TRIGGERLINE_PLANE; + sectors[i].triggerer = TO_PLAYEREMERALDS; + break; + case 7: //Trigger linedef executor (NiGHTS mare) + sectors[i].triggertag = tag; + sectors[i].flags &= ~MSF_TRIGGERLINE_PLANE; + sectors[i].triggerer = TO_PLAYERNIGHTS; + break; + case 8: //Check for linedef executor on FOFs + sectors[i].flags |= MSF_TRIGGERLINE_MOBJ; + break; + default: + break; + } + switch(GETSECSPECIAL(sectors[i].special, 3)) { case 2: //Wind/Current diff --git a/src/p_spec.c b/src/p_spec.c index 95c3a5118..973c6ee3c 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1755,15 +1755,15 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller // Trigger conditions // //////////////////////// - if (caller) + if (caller && !udmf) { - if (GETSECSPECIAL(caller->special, 2) == 6) + if (caller->triggerer == TO_PLAYEREMERALDS) { CONS_Alert(CONS_WARNING, M_GetText("Deprecated emerald check sector type detected. Please use linedef types 337-339 instead.\n")); if (!(ALL7EMERALDS(emeralds))) return false; } - else if (GETSECSPECIAL(caller->special, 2) == 7) + else if (caller->triggerer == TO_PLAYERNIGHTS) { CONS_Alert(CONS_WARNING, M_GetText("Deprecated NiGHTS mare sector type detected. Please use linedef types 340-342 instead.\n")); if (!P_CheckPlayerMareOld(triggerline)) @@ -4226,20 +4226,23 @@ sector_t *P_PlayerTouchingSectorSpecialFlag(player_t *player, sectorspecialflags return P_MobjTouchingSectorSpecialFlag(player->mo, flag); } -static sector_t *P_Check3DFloorTriggers(player_t *player, sector_t *sector, line_t *sourceline) +static sector_t *P_CheckPlayer3DFloorTrigger(player_t *player, sector_t *sector, line_t *sourceline) { ffloor_t *rover; for (rover = sector->ffloors; rover; rover = rover->next) { - if (GETSECSPECIAL(rover->master->frontsector->special, 2) < 2 || GETSECSPECIAL(rover->master->frontsector->special, 2) > 7) + if (!rover->master->frontsector->triggertag) + continue; + + if (rover->master->frontsector->triggerer == TO_MOBJ) continue; if (!(rover->flags & FF_EXISTS)) continue; - if (!Tag_Find(&sourceline->tags, Tag_FGet(&rover->master->frontsector->tags))) - return false; + if (!Tag_Find(&sourceline->tags, rover->master->frontsector->triggertag)) + continue; if (!P_IsMobjTouching3DFloor(player->mo, rover, sector)) continue; @@ -4253,25 +4256,28 @@ static sector_t *P_Check3DFloorTriggers(player_t *player, sector_t *sector, line return NULL; } -static sector_t *P_CheckPolyobjTriggers(player_t *player, line_t *sourceline) +static sector_t *P_CheckPlayerPolyobjTrigger(player_t *player, line_t *sourceline) { polyobj_t *po; sector_t *polysec; boolean touching = false; boolean inside = false; - for (po = player->mo->subsector->polyList; po; po = (polyobj_t *)(po->link.next)) //TODO + for (po = player->mo->subsector->polyList; po; po = (polyobj_t *)(po->link.next)) { if (po->flags & POF_NOSPECIALS) continue; polysec = po->lines[0]->backsector; - if (GETSECSPECIAL(polysec->special, 2) < 2 || GETSECSPECIAL(polysec->special, 2) > 7) + if (!polysec->triggertag) continue; - if (!Tag_Find(&sourceline->tags, Tag_FGet(&polysec->tags))) - return false; + if (polysec->triggerer == TO_MOBJ) + continue; + + if (!Tag_Find(&sourceline->tags, polysec->triggertag)) + continue; touching = (polysec->flags & MSF_TRIGGERSPECIAL_TOUCH) && P_MobjTouchingPolyobj(po, player->mo); inside = P_MobjInsidePolyobj(po, player->mo); @@ -4288,16 +4294,19 @@ static sector_t *P_CheckPolyobjTriggers(player_t *player, line_t *sourceline) return NULL; } -static boolean P_CheckSectorTriggers(player_t *player, sector_t *sector, line_t *sourceline) +static boolean P_CheckPlayerSectorTrigger(player_t *player, sector_t *sector, line_t *sourceline) { - if (GETSECSPECIAL(sector->special, 2) < 2 || GETSECSPECIAL(sector->special, 2) > 7) + if (!sector->triggertag) return false; - if (!Tag_Find(&sourceline->tags, Tag_FGet(§or->tags))) + if (sector->triggerer == TO_MOBJ) return false; - if (GETSECSPECIAL(sector->special, 2) != 3 && GETSECSPECIAL(sector->special, 2) != 5) - return true; // "Anywhere in sector" types + if (!Tag_Find(&sourceline->tags, sector->triggertag)) + return false; + + if (!(sector->flags & MSF_TRIGGERLINE_PLANE)) + return true; // Don't require plane touch return P_IsMobjTouchingSectorPlane(player->mo, sector); @@ -4315,18 +4324,18 @@ sector_t *P_FindPlayerTrigger(player_t *player, line_t *sourceline) originalsector = player->mo->subsector->sector; - caller = P_Check3DFloorTriggers(player, originalsector, sourceline); // Handle FOFs first. + caller = P_CheckPlayer3DFloorTrigger(player, originalsector, sourceline); // Handle FOFs first. if (caller) return caller; // Allow sector specials to be applied to polyobjects! - caller = P_CheckPolyobjTriggers(player, sourceline); + caller = P_CheckPlayerPolyobjTrigger(player, sourceline); if (caller) return caller; - if (P_CheckSectorTriggers(player, originalsector, sourceline)) + if (P_CheckPlayerSectorTrigger(player, originalsector, sourceline)) return originalsector; // Iterate through touching_sectorlist for SF_TRIGGERSPECIAL_TOUCH @@ -4338,7 +4347,7 @@ sector_t *P_FindPlayerTrigger(player_t *player, line_t *sourceline) continue; // Check 3D floors... - caller = P_Check3DFloorTriggers(player, loopsector, sourceline); // Handle FOFs first. + caller = P_CheckPlayer3DFloorTrigger(player, loopsector, sourceline); // Handle FOFs first. if (caller) return caller; @@ -4346,7 +4355,7 @@ sector_t *P_FindPlayerTrigger(player_t *player, line_t *sourceline) if (!(loopsector->flags & MSF_TRIGGERSPECIAL_TOUCH)) continue; - if (P_CheckSectorTriggers(player, loopsector, sourceline)) + if (P_CheckPlayerSectorTrigger(player, loopsector, sourceline)) return loopsector; } @@ -4376,12 +4385,12 @@ boolean P_CanPlayerTrigger(size_t playernum) } /// \todo check continues for proper splitscreen support? -static boolean P_DoAllPlayersTrigger(mtag_t sectag) +static boolean P_DoAllPlayersTrigger(mtag_t triggertag) { INT32 i; line_t dummyline; dummyline.tags.count = 1; - dummyline.tags.tags = §ag; + dummyline.tags.tags = &triggertag; for (i = 0; i < MAXPLAYERS; i++) { @@ -4903,34 +4912,26 @@ static void P_ProcessRopeHang(player_t *player, mtag_t sectag) P_SetPlayerMobjState(player->mo, S_PLAY_RIDE); } -/** Applies a sector special to a player. - * - * \param player Player in the sector. - * \param sector Sector with the special. - * \param roversector If !NULL, sector is actually an FOF; otherwise, sector - * is being physically contacted by the player. - * \sa P_PlayerInSpecialSector, P_PlayerOnSpecial3DFloor - */ -void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *roversector) +static boolean P_SectorHasSpecial(sector_t *sec) +{ + if (sec->specialflags) + return true; + + if (sec->damagetype != SD_NONE) + return true; + + if (sec->triggertag) + return true; + + if (sec->special) + return true; + + return false; +} + +static void P_EvaluateSpecialFlags(player_t *player, sector_t *sector, sector_t *roversector, boolean isTouching) { - INT32 section1, section2; mtag_t sectag = Tag_FGet(§or->tags); - boolean isTouching; - - if (!sector->special && sector->specialflags == 0 && sector->damagetype == SD_NONE) - return; - - // Ignore spectators - if (player->spectator) - return; - - // Ignore dead players. - // If this strange phenomenon could be potentially used in levels, - // TODO: modify this to accommodate for it. - if (player->playerstate != PST_LIVE) - return; - - isTouching = roversector || P_IsMobjTouchingSectorPlane(player->mo, sector); if (sector->specialflags & SSF_OUTERSPACE) { @@ -4994,7 +4995,10 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers P_ProcessFinishLine(player); if ((sector->specialflags & SSF_ROPEHANG) && isTouching) P_ProcessRopeHang(player, sectag); +} +static void P_EvaluateDamageType(player_t *player, sector_t *sector, boolean isTouching) +{ switch (sector->damagetype) { case SD_GENERIC: @@ -5047,19 +5051,36 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers default: break; } +} - section1 = GETSECSPECIAL(sector->special, 1); - section2 = GETSECSPECIAL(sector->special, 2); +static void P_EvaluateLinedefExecutorTrigger(player_t *player, sector_t *sector, boolean isTouching) +{ + if (player->bot) + return; - switch (section1) + if (!sector->triggertag) + return; + + if (sector->triggerer == TO_MOBJ) + return; + else if (sector->triggerer == TO_ALLPLAYERS && !P_DoAllPlayersTrigger(sector->triggertag)) + return; + + if ((sector->flags & MSF_TRIGGERLINE_PLANE) && !isTouching) + return; + + P_LinedefExecute(sector->triggertag, player->mo, sector); +} + +static void P_EvaluateOldSectorSpecial(player_t *player, sector_t *sector, sector_t *roversector, boolean isTouching) +{ + switch (GETSECSPECIAL(sector->special, 1)) { case 9: // Ring Drainer (Floor Touch) if (!isTouching) break; /* FALLTHRU */ case 10: // Ring Drainer (No Floor Touch) - if (udmf) - break; if (leveltime % (TICRATE/2) == 0 && player->rings > 0) { player->rings--; @@ -5068,29 +5089,50 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers break; } - switch (section2) + switch (GETSECSPECIAL(sector->special, 2)) { - 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)) - break; - /* FALLTHRU */ - case 4: // Linedef executor that doesn't require touching floor - case 5: // Linedef executor - case 6: // Linedef executor (7 Emeralds) - case 7: // Linedef executor (NiGHTS Mare) - if ((section2 == 3 || section2 == 5) && !isTouching) - break; - if (!player->bot) - P_LinedefExecute(sectag, player->mo, sector); - break; case 9: // Egg trap capsule - if (!udmf && roversector) + if (roversector) P_ProcessEggCapsule(player, sector); break; } } +/** Applies a sector special to a player. + * + * \param player Player in the sector. + * \param sector Sector with the special. + * \param roversector If !NULL, sector is actually an FOF; otherwise, sector + * is being physically contacted by the player. + * \sa P_PlayerInSpecialSector, P_PlayerOnSpecial3DFloor + */ +void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *roversector) +{ + boolean isTouching; + + if (!P_SectorHasSpecial(sector)) + return; + + // Ignore spectators + if (player->spectator) + return; + + // Ignore dead players. + // If this strange phenomenon could be potentially used in levels, + // TODO: modify this to accommodate for it. + if (player->playerstate != PST_LIVE) + return; + + isTouching = roversector || P_IsMobjTouchingSectorPlane(player->mo, sector); + + P_EvaluateSpecialFlags(player, sector, roversector, isTouching); + P_EvaluateDamageType(player, sector, isTouching); + P_EvaluateLinedefExecutorTrigger(player, sector, isTouching); + + if (!udmf) + P_EvaluateOldSectorSpecial(player, sector, roversector, isTouching); +} + #define TELEPORTED(mo) (mo->subsector->sector != originalsector) /** Checks if a player is standing on or is inside a 3D floor (e.g. water) and @@ -5106,7 +5148,7 @@ static void P_PlayerOnSpecial3DFloor(player_t *player, sector_t *sector) for (rover = sector->ffloors; rover; rover = rover->next) { - if (!rover->master->frontsector->special && rover->master->frontsector->specialflags == 0 && rover->master->frontsector->damagetype == SD_NONE) + if (!P_SectorHasSpecial(rover->master->frontsector)) continue; if (!(rover->flags & FF_EXISTS)) @@ -5140,7 +5182,7 @@ static void P_PlayerOnSpecialPolyobj(player_t *player) polysec = po->lines[0]->backsector; - if (!polysec->special && polysec->specialflags == 0 && polysec->damagetype == SD_NONE) + if (!P_SectorHasSpecial(polysec)) continue; touching = (polysec->flags & MSF_TRIGGERSPECIAL_TOUCH) && P_MobjTouchingPolyobj(po, player->mo); @@ -5203,25 +5245,26 @@ void P_PlayerInSpecialSector(player_t *player) } } -static void P_CheckMobj3DFloorTrigger(mobj_t *mo) +static void P_CheckMobj3DFloorTrigger(mobj_t *mo, sector_t *sec) { sector_t *originalsector = mo->subsector->sector; ffloor_t *rover; - mtag_t tag; - for (rover = mo->subsector->sector->ffloors; rover; rover = rover->next) + for (rover = sec->ffloors; rover; rover = rover->next) { - if (GETSECSPECIAL(rover->master->frontsector->special, 2) != 1) + if (!rover->master->frontsector->triggertag) + continue; + + if (rover->master->frontsector->triggerer != TO_MOBJ) continue; if (!(rover->flags & FF_EXISTS)) continue; - if (!P_IsMobjTouching3DFloor(mo, rover, mo->subsector->sector)) + if (!P_IsMobjTouching3DFloor(mo, rover, sec)) continue; - tag = Tag_FGet(&rover->master->frontsector->tags); - P_LinedefExecute(tag, mo, rover->master->frontsector); + P_LinedefExecute(rover->master->frontsector->triggertag, mo, rover->master->frontsector); if TELEPORTED(mo) return; } } @@ -5233,7 +5276,6 @@ static void P_CheckMobjPolyobjTrigger(mobj_t *mo) sector_t *polysec; boolean touching = false; boolean inside = false; - mtag_t tag; for (po = mo->subsector->polyList; po; po = (polyobj_t *)(po->link.next)) { @@ -5242,7 +5284,10 @@ static void P_CheckMobjPolyobjTrigger(mobj_t *mo) polysec = po->lines[0]->backsector; - if (!polysec->special) + if (!polysec->triggertag) + continue; + + if (polysec->triggerer != TO_MOBJ) continue; touching = (polysec->flags & MSF_TRIGGERSPECIAL_TOUCH) && P_MobjTouchingPolyobj(po, mo); @@ -5254,30 +5299,26 @@ static void P_CheckMobjPolyobjTrigger(mobj_t *mo) if (!P_IsMobjTouchingPolyobj(mo, po, polysec)) continue; - tag = Tag_FGet(&polysec->tags); - P_LinedefExecute(tag, mo, polysec); + P_LinedefExecute(polysec->triggertag, mo, polysec); if TELEPORTED(mo) return; } } -void P_CheckPushableTrigger(mobj_t *mobj, sector_t *sec) +static void P_CheckMobjSectorTrigger(mobj_t *mo, sector_t *sec) { - sector_t *originalsector = mobj->subsector->sector; + if (!sec->triggertag) + return; - P_CheckMobj3DFloorTrigger(mobj); - if TELEPORTED(mobj) return; + if (sec->triggerer != TO_MOBJ) + return; - P_CheckMobjPolyobjTrigger(mobj); - if TELEPORTED(mobj) return; + if ((sec->flags & MSF_TRIGGERLINE_PLANE) && !P_IsMobjTouchingSectorPlane(mo, sec)) + return; - if (GETSECSPECIAL(sec->special, 2) == 1 && P_IsMobjTouchingSectorPlane(mobj, sec)) - { - mtag_t tag = Tag_FGet(&sec->tags); - P_LinedefExecute(tag, mobj, sec); - } + P_LinedefExecute(sec->triggertag, mo, sec); } -void P_CheckMobjTrigger(mobj_t *mobj) +void P_CheckMobjTrigger(mobj_t *mobj, boolean pushable) { sector_t *originalsector; @@ -5286,13 +5327,16 @@ void P_CheckMobjTrigger(mobj_t *mobj) originalsector = mobj->subsector->sector; - if (GETSECSPECIAL(originalsector->special, 2) != 8) + if (!pushable && !(originalsector->flags & MSF_TRIGGERLINE_MOBJ)) return; - P_CheckMobj3DFloorTrigger(mobj); + P_CheckMobj3DFloorTrigger(mobj, originalsector); if TELEPORTED(mobj) return; P_CheckMobjPolyobjTrigger(mobj); + if TELEPORTED(mobj) return; + + P_CheckMobjSectorTrigger(mobj, originalsector); } #undef TELEPORTED diff --git a/src/p_spec.h b/src/p_spec.h index 19d3bd103..d02b5989f 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -484,8 +484,7 @@ 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); +void P_CheckMobjTrigger(mobj_t *mobj, boolean pushable); sector_t *P_FindPlayerTrigger(player_t *player, line_t *sourceline); boolean P_IsPlayerValid(size_t playernum); boolean P_CanPlayerTrigger(size_t playernum); diff --git a/src/r_defs.h b/src/r_defs.h index 4180af800..cd632aeca 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -282,11 +282,14 @@ typedef enum // triggerspecial - conditions under which plane touch causes effect MSF_TRIGGERSPECIAL_TOUCH = 1<<2, MSF_TRIGGERSPECIAL_HEADBUMP = 1<<3, + // triggerline - conditions for linedef executor triggering + MSF_TRIGGERLINE_PLANE = 1<<4, // require plane touch + MSF_TRIGGERLINE_MOBJ = 1<<5, // allow non-pushable mobjs to trigger // invertprecip - inverts presence of precipitation - MSF_INVERTPRECIP = 1<<4, - MSF_GRAVITYFLIP = 1<<5, - MSF_HEATWAVE = 1<<6, - MSF_NOCLIPCAMERA = 1<<7, + MSF_INVERTPRECIP = 1<<6, + MSF_GRAVITYFLIP = 1<<7, + MSF_HEATWAVE = 1<<8, + MSF_NOCLIPCAMERA = 1<<9, } sectorflags_t; typedef enum @@ -326,6 +329,15 @@ typedef enum SD_SPECIALSTAGE = 9, } sectordamage_t; +typedef enum +{ + TO_PLAYER = 0, + TO_ALLPLAYERS = 1, + TO_MOBJ = 2, + TO_PLAYEREMERALDS = 3, // only for binary backwards compatibility: check player emeralds + TO_PLAYERNIGHTS = 4, // only for binary backwards compatibility: check NiGHTS mare +} triggerobject_t; + typedef enum { CRUMBLE_NONE, // No crumble thinker @@ -406,10 +418,15 @@ 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; UINT8 damagetype; + // Linedef executor triggering + mtag_t triggertag; // tag to call upon triggering + UINT8 triggerer; // who can trigger? + INT32 friction; // Sprite culling feature