Implement sector fields for linedef executor triggering

This commit is contained in:
MascaraSnake 2021-12-31 11:39:34 +01:00
parent b3be8d1f44
commit 208395214a
12 changed files with 299 additions and 111 deletions

View file

@ -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

View file

@ -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++) {

View file

@ -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,

View file

@ -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[];

View file

@ -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;

View file

@ -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!

View file

@ -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))

View file

@ -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);

View file

@ -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(&sectors[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

View file

@ -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(&sector->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 = &sectag;
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(&sector->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

View file

@ -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);

View file

@ -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