mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-03-20 01:43:50 +00:00
Implement sector fields for linedef executor triggering
This commit is contained in:
parent
b3be8d1f44
commit
208395214a
12 changed files with 299 additions and 111 deletions
|
@ -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
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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,
|
||||
|
||||
|
|
|
@ -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[];
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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!
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
240
src/p_spec.c
240
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
|
||||
|
|
|
@ -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);
|
||||
|
|
25
src/r_defs.h
25
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
|
||||
|
|
Loading…
Reference in a new issue