Add sector action

Linedef actions, but on sectors. Including args, stringargs, and unique activator flags.
This commit is contained in:
Sally Coolatta 2023-01-06 05:31:53 -05:00
parent 75658fd469
commit 5b147f59ed
10 changed files with 597 additions and 26 deletions

View file

@ -153,30 +153,30 @@ enum
// Transfers FOF properties.
ML_TFERLINE = 0x00008000,
// Special action is repeatable.
ML_REPEATSPECIAL = 0x00010000,
};
enum
{
// Special action is repeatable.
SPAC_REPEATSPECIAL = 0x00000001,
// Activates when crossed by a player.
SPAC_CROSS = 0x00000001,
SPAC_CROSS = 0x00000002,
// Activates when crossed by an enemy.
SPAC_CROSSMONSTER = 0x00000002,
SPAC_CROSSMONSTER = 0x00000004,
// Activates when crossed by a projectile.
SPAC_CROSSMISSILE = 0x00000004,
SPAC_CROSSMISSILE = 0x00000008,
// Activates when bumped by a player.
SPAC_PUSH = 0x00000008,
SPAC_PUSH = 0x00000010,
// Activates when bumped by an enemy.
SPAC_PUSHMONSTER = 0x00000010,
SPAC_PUSHMONSTER = 0x00000020,
// Activates when bumped by a missile.
SPAC_IMPACT = 0x00000020,
SPAC_IMPACT = 0x00000040,
};
// Sector definition, from editing.

View file

@ -204,6 +204,9 @@ static const struct {
{META_LINEARGS, "line_t.args"},
{META_LINESTRINGARGS, "line_t.stringargs"},
{META_SECTORARGS, "sector_t.args"},
{META_SECTORSTRINGARGS, "sector_t.stringargs"},
{META_THINGARGS, "mapthing.args"},
{META_THINGSTRINGARGS, "mapthing.stringargs"},
#ifdef HAVE_LUA_SEGS

View file

@ -77,6 +77,8 @@ extern lua_State *gL;
#define META_SIDENUM "LINE_T*SIDENUM"
#define META_LINEARGS "LINE_T*ARGS"
#define META_LINESTRINGARGS "LINE_T*STRINGARGS"
#define META_SECTORARGS "SECTOR_T*ARGS"
#define META_SECTORSTRINGARGS "SECTOR_T*STRINGARGS"
#define META_THINGARGS "MAPTHING_T*ARGS"
#define META_THINGSTRINGARGS "MAPTHING_T*STRINGARGS"
#define META_POLYOBJVERTICES "POLYOBJ_T*VERTICES"

View file

@ -56,6 +56,10 @@ enum sector_e {
sector_triggerer,
sector_friction,
sector_gravity,
sector_action,
sector_args,
sector_stringargs,
sector_activation,
};
static const char *const sector_opt[] = {
@ -86,6 +90,10 @@ static const char *const sector_opt[] = {
"triggerer",
"friction",
"gravity",
"action",
"args"
"stringargs",
"activation",
NULL};
enum subsector_e {
@ -592,6 +600,42 @@ static int sectorlines_num(lua_State *L)
// sector_t //
//////////////
// args, i -> args[i]
static int sectorargs_get(lua_State *L)
{
INT32 *args = *((INT32**)luaL_checkudata(L, 1, META_SECTORARGS));
int i = luaL_checkinteger(L, 2);
if (i < 0 || i >= NUMSECTORARGS)
return luaL_error(L, LUA_QL("sector_t.args") " index cannot be %d", i);
lua_pushinteger(L, args[i]);
return 1;
}
// #args -> NUMSECTORARGS
static int sectorargs_len(lua_State* L)
{
lua_pushinteger(L, NUMSECTORARGS);
return 1;
}
// stringargs, i -> stringargs[i]
static int sectorstringargs_get(lua_State *L)
{
char **stringargs = *((char***)luaL_checkudata(L, 1, META_SECTORSTRINGARGS));
int i = luaL_checkinteger(L, 2);
if (i < 0 || i >= NUMSECTORSTRINGARGS)
return luaL_error(L, LUA_QL("line_t.stringargs") " index cannot be %d", i);
lua_pushstring(L, stringargs[i]);
return 1;
}
// #stringargs -> NUMLINESTRINGARGS
static int sectorstringargs_len(lua_State *L)
{
lua_pushinteger(L, NUMSECTORSTRINGARGS);
return 1;
}
static int sector_get(lua_State *L)
{
sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR));
@ -710,6 +754,18 @@ static int sector_get(lua_State *L)
case sector_gravity: // gravity
lua_pushfixed(L, sector->gravity);
return 1;
case sector_action: // action
lua_pushinteger(L, (INT16)sector->action);
return 1;
case sector_args:
LUA_PushUserdata(L, sector->args, META_SECTORARGS);
return 1;
case sector_stringargs:
LUA_PushUserdata(L, sector->stringargs, META_SECTORSTRINGARGS);
return 1;
case sector_activation: // activation
lua_pushinteger(L, sector->activation);
return 1;
}
return 0;
}
@ -738,6 +794,8 @@ static int sector_set(lua_State *L)
case sector_fslope: // f_slope
case sector_cslope: // c_slope
case sector_friction: // friction
case sector_args: // args
case sector_stringargs: // stringargs
default:
return luaL_error(L, "sector_t field " LUA_QS " cannot be set.", sector_opt[field]);
case sector_floorheight: { // floorheight
@ -816,6 +874,12 @@ static int sector_set(lua_State *L)
case sector_gravity:
sector->gravity = luaL_checkfixed(L, 3);
break;
case sector_action:
sector->action = (INT16)luaL_checkinteger(L, 3);
break;
case sector_activation:
sector->activation = luaL_checkinteger(L, 3);
break;
}
return 0;
}
@ -2570,6 +2634,22 @@ int LUA_MapLib(lua_State *L)
lua_setfield(L, -2, "__len");
lua_pop(L, 1);
luaL_newmetatable(L, META_SECTORARGS);
lua_pushcfunction(L, sectorargs_get);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, sectorargs_len);
lua_setfield(L, -2, "__len");
lua_pop(L, 1);
luaL_newmetatable(L, META_SECTORSTRINGARGS);
lua_pushcfunction(L, sectorstringargs_get);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, sectorstringargs_len);
lua_setfield(L, -2, "__len");
lua_pop(L, 1);
luaL_newmetatable(L, META_SUBSECTOR);
lua_pushcfunction(L, subsector_get);
lua_setfield(L, -2, "__index");

View file

@ -9810,6 +9810,9 @@ void P_MobjThinker(mobj_t *mobj)
P_SetTarget(&tm.floorthing, NULL);
P_SetTarget(&tm.hitthing, NULL);
// Check for sector special actions
P_CheckMobjTouchingSectorActions(mobj);
// Sector flag MSF_TRIGGERLINE_MOBJ allows ANY mobj to trigger a linedef exec
P_CheckMobjTrigger(mobj, false);

View file

@ -1101,6 +1101,38 @@ static void P_NetUnArchiveColormaps(savebuffer_t *save)
#define SD_TRIGGERTAG 0x02
#define SD_TRIGGERER 0x04
#define SD_GRAVITY 0x08
#define SD_ACTION 0x10
#define SD_ARGS 0x20
#define SD_STRINGARGS 0x40
#define SD_DIFF5 0x80
//diff5 flags
#define SD_ACTIVATION 0x01
static boolean P_SectorArgsEqual(const sector_t *sc, const sector_t *spawnsc)
{
UINT8 i;
for (i = 0; i < NUMSECTORARGS; i++)
if (sc->args[i] != spawnsc->args[i])
return false;
return true;
}
static boolean P_SectorStringArgsEqual(const sector_t *sc, const sector_t *spawnsc)
{
UINT8 i;
for (i = 0; i < NUMSECTORSTRINGARGS; i++)
{
if (!sc->stringargs[i])
return !spawnsc->stringargs[i];
if (strcmp(sc->stringargs[i], spawnsc->stringargs[i]))
return false;
}
return true;
}
#define LD_FLAG 0x01
#define LD_SPECIAL 0x02
@ -1124,7 +1156,7 @@ static void P_NetUnArchiveColormaps(savebuffer_t *save)
// diff3 flags
#define LD_ACTIVATION 0x01
static boolean P_AreArgsEqual(const line_t *li, const line_t *spawnli)
static boolean P_LineArgsEqual(const line_t *li, const line_t *spawnli)
{
UINT8 i;
for (i = 0; i < NUMLINEARGS; i++)
@ -1134,7 +1166,7 @@ static boolean P_AreArgsEqual(const line_t *li, const line_t *spawnli)
return true;
}
static boolean P_AreStringArgsEqual(const line_t *li, const line_t *spawnli)
static boolean P_LineStringArgsEqual(const line_t *li, const line_t *spawnli)
{
UINT8 i;
for (i = 0; i < NUMLINESTRINGARGS; i++)
@ -1243,11 +1275,11 @@ static void ArchiveSectors(savebuffer_t *save)
size_t i, j;
const sector_t *ss = sectors;
const sector_t *spawnss = spawnsectors;
UINT8 diff, diff2, diff3, diff4;
UINT8 diff, diff2, diff3, diff4, diff5;
for (i = 0; i < numsectors; i++, ss++, spawnss++)
{
diff = diff2 = diff3 = diff4 = 0;
diff = diff2 = diff3 = diff4 = diff5 = 0;
if (ss->floorheight != spawnss->floorheight)
diff |= SD_FLOORHT;
if (ss->ceilingheight != spawnss->ceilingheight)
@ -1303,9 +1335,21 @@ static void ArchiveSectors(savebuffer_t *save)
if (ss->gravity != spawnss->gravity)
diff4 |= SD_GRAVITY;
if (ss->action != spawnss->action)
diff4 |= SD_ACTION;
if (!P_SectorArgsEqual(ss, spawnss))
diff4 |= SD_ARGS;
if (!P_SectorStringArgsEqual(ss, spawnss))
diff4 |= SD_STRINGARGS;
if (ss->activation != spawnss->activation)
diff5 |= SD_ACTIVATION;
if (ss->ffloors && CheckFFloorDiff(ss))
diff |= SD_FFLOORS;
if (diff5)
diff4 |= SD_DIFF5;
if (diff4)
diff3 |= SD_DIFF4;
@ -1383,6 +1427,35 @@ static void ArchiveSectors(savebuffer_t *save)
WRITEUINT8(save->p, ss->triggerer);
if (diff4 & SD_GRAVITY)
WRITEFIXED(save->p, ss->gravity);
if (diff4 & SD_ACTION)
WRITEINT16(save->p, ss->action);
if (diff4 & SD_ARGS)
{
for (j = 0; j < NUMSECTORARGS; j++)
WRITEINT32(save->p, ss->args[j]);
}
if (diff4 & SD_STRINGARGS)
{
for (j = 0; j < NUMSECTORSTRINGARGS; j++)
{
size_t len, k;
if (!ss->stringargs[j])
{
WRITEINT32(save->p, 0);
continue;
}
len = strlen(ss->stringargs[j]);
WRITEINT32(save->p, len);
for (k = 0; k < len; k++)
WRITECHAR(save->p, ss->stringargs[j][k]);
}
}
if (diff5 & SD_ACTIVATION)
WRITEUINT32(save->p, ss->activation);
if (diff & SD_FFLOORS)
ArchiveFFloors(save, ss);
}
@ -1394,7 +1467,7 @@ static void ArchiveSectors(savebuffer_t *save)
static void UnArchiveSectors(savebuffer_t *save)
{
UINT16 i, j;
UINT8 diff, diff2, diff3, diff4;
UINT8 diff, diff2, diff3, diff4, diff5;
for (;;)
{
i = READUINT16(save->p);
@ -1419,6 +1492,11 @@ static void UnArchiveSectors(savebuffer_t *save)
else
diff4 = 0;
if (diff4 & SD_DIFF5)
diff5 = READUINT8(save->p);
else
diff5 = 0;
if (diff & SD_FLOORHT)
sectors[i].floorheight = READFIXED(save->p);
if (diff & SD_CEILHT)
@ -1504,6 +1582,36 @@ static void UnArchiveSectors(savebuffer_t *save)
if (diff4 & SD_GRAVITY)
sectors[i].gravity = READFIXED(save->p);
if (diff4 & SD_ACTION)
sectors[i].action = READINT16(save->p);
if (diff4 & SD_ARGS)
{
for (j = 0; j < NUMSECTORARGS; j++)
sectors[i].args[j] = READINT32(save->p);
}
if (diff4 & SD_STRINGARGS)
{
for (j = 0; j < NUMLINESTRINGARGS; j++)
{
size_t len = READINT32(save->p);
size_t k;
if (!len)
{
Z_Free(sectors[i].stringargs[j]);
sectors[i].stringargs[j] = NULL;
continue;
}
sectors[i].stringargs[j] = Z_Realloc(sectors[i].stringargs[j], len + 1, PU_LEVEL, NULL);
for (k = 0; k < len; k++)
sectors[i].stringargs[j][k] = READCHAR(save->p);
sectors[i].stringargs[j][len] = '\0';
}
}
if (diff5 & SD_ACTIVATION)
sectors[i].activation = READUINT32(save->p);
if (diff & SD_FFLOORS)
UnArchiveFFloors(save, &sectors[i]);
}
@ -1531,10 +1639,10 @@ static void ArchiveLines(savebuffer_t *save)
if (spawnli->special == 321 || spawnli->special == 322) // only reason li->callcount would be non-zero is if either of these are involved
diff |= LD_CLLCOUNT;
if (!P_AreArgsEqual(li, spawnli))
if (!P_LineArgsEqual(li, spawnli))
diff2 |= LD_ARGS;
if (!P_AreStringArgsEqual(li, spawnli))
if (!P_LineStringArgsEqual(li, spawnli))
diff2 |= LD_STRINGARGS;
if (li->executordelay != spawnli->executordelay)

View file

@ -870,6 +870,11 @@ static void P_LoadSectors(UINT8 *data)
ss->friction = ORIG_FRICTION;
ss->action = 0;
memset(ss->args, 0, NUMLINEARGS*sizeof(*ss->args));
memset(ss->stringargs, 0x00, NUMLINESTRINGARGS*sizeof(*ss->stringargs));
ss->activation = 0;
P_InitializeSector(ss);
}
}
@ -980,6 +985,7 @@ static void P_LoadLinedefs(UINT8 *data)
memset(ld->stringargs, 0x00, NUMLINESTRINGARGS*sizeof(*ld->stringargs));
ld->alpha = FRACUNIT;
ld->executordelay = 0;
ld->activation = 0;
P_SetLinedefV1(i, SHORT(mld->v1));
P_SetLinedefV2(i, SHORT(mld->v2));
@ -1216,6 +1222,7 @@ static void P_LoadThings(UINT8 *data)
mt->scale = mapobjectscale;
memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args));
memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs));
mt->special = 0;
mt->pitch = mt->roll = 0;
mt->type &= 4095;
@ -1530,6 +1537,43 @@ static void ParseTextmapSectorParameter(UINT32 i, const char *param, const char
sectors[i].triggertag = atol(val);
else if (fastcmp(param, "triggerer"))
sectors[i].triggerer = atol(val);
else if (fastcmp(param, "action"))
sectors[i].action = atol(val);
else if (fastncmp(param, "stringarg", 9) && strlen(param) > 9)
{
size_t argnum = atol(param + 9);
if (argnum >= NUMSECTORSTRINGARGS)
return;
sectors[i].stringargs[argnum] = Z_Malloc(strlen(val) + 1, PU_LEVEL, NULL);
M_Memcpy(sectors[i].stringargs[argnum], val, strlen(val) + 1);
}
else if (fastncmp(param, "arg", 3) && strlen(param) > 3)
{
size_t argnum = atol(param + 3);
if (argnum >= NUMSECTORARGS)
return;
sectors[i].args[argnum] = atol(val);
}
else if (fastcmp(param, "repeatspecial") && fastcmp("true", val))
sectors[i].activation |= SECSPAC_REPEATSPECIAL;
else if (fastcmp(param, "playerenter") && fastcmp("true", val))
sectors[i].activation |= SECSPAC_ENTER;
else if (fastcmp(param, "playerfloor") && fastcmp("true", val))
sectors[i].activation |= SECSPAC_FLOOR;
else if (fastcmp(param, "playerceiling") && fastcmp("true", val))
sectors[i].activation |= SECSPAC_CEILING;
else if (fastcmp(param, "monsterenter") && fastcmp("true", val))
sectors[i].activation |= SECSPAC_ENTERMONSTER;
else if (fastcmp(param, "monsterfloor") && fastcmp("true", val))
sectors[i].activation |= SECSPAC_FLOORMONSTER;
else if (fastcmp(param, "monsterceiling") && fastcmp("true", val))
sectors[i].activation |= SECSPAC_CEILINGMONSTER;
else if (fastcmp(param, "missileenter") && fastcmp("true", val))
sectors[i].activation |= SECSPAC_ENTERMISSILE;
else if (fastcmp(param, "missilefloor") && fastcmp("true", val))
sectors[i].activation |= SECSPAC_FLOORMISSILE;
else if (fastcmp(param, "missileceiling") && fastcmp("true", val))
sectors[i].activation |= SECSPAC_CEILINGMISSILE;
}
static void ParseTextmapSidedefParameter(UINT32 i, const char *param, const char *val)
@ -1642,9 +1686,9 @@ static void ParseTextmapLinedefParameter(UINT32 i, const char *param, const char
lines[i].flags |= ML_NOTBOUNCY;
else if (fastcmp(param, "transfer") && fastcmp("true", val))
lines[i].flags |= ML_TFERLINE;
else if (fastcmp(param, "repeatspecial") && fastcmp("true", val))
lines[i].flags |= ML_REPEATSPECIAL;
// Activation flags
else if (fastcmp(param, "repeatspecial") && fastcmp("true", val))
lines[i].activation |= SPAC_REPEATSPECIAL;
else if (fastcmp(param, "playercross") && fastcmp("true", val))
lines[i].activation |= SPAC_CROSS;
else if (fastcmp(param, "monstercross") && fastcmp("true", val))
@ -2219,7 +2263,7 @@ static void P_WriteTextmap(void)
fprintf(f, "notbouncy = true;\n");
if (wlines[i].flags & ML_TFERLINE)
fprintf(f, "transfer = true;\n");
if (wlines[i].flags & ML_REPEATSPECIAL)
if (wlines[i].activation & SPAC_REPEATSPECIAL)
fprintf(f, "repeatspecial = true;\n");
if (wlines[i].activation & SPAC_CROSS)
fprintf(f, "playercross = true;\n");
@ -2403,6 +2447,34 @@ static void P_WriteTextmap(void)
fprintf(f, "triggertag = %d;\n", wsectors[i].triggertag);
if (wsectors[i].triggerer != 0)
fprintf(f, "triggerer = %d;\n", wsectors[i].triggerer);
if (wsectors[i].action != 0)
fprintf(f, "action = %d;\n", wsectors[i].action);
for (j = 0; j < NUMSECTORARGS; j++)
if (wsectors[i].args[j] != 0)
fprintf(f, "arg%s = %d;\n", sizeu1(j), wsectors[i].args[j]);
for (j = 0; j < NUMSECTORSTRINGARGS; j++)
if (wsectors[i].stringargs[j])
fprintf(f, "stringarg%s = \"%s\";\n", sizeu1(j), wsectors[i].stringargs[j]);
if (wsectors[i].activation & SECSPAC_REPEATSPECIAL)
fprintf(f, "repeatspecial = true;\n");
if (wsectors[i].activation & SECSPAC_ENTER)
fprintf(f, "playerenter = true;\n");
if (wsectors[i].activation & SECSPAC_FLOOR)
fprintf(f, "playerfloor = true;\n");
if (wsectors[i].activation & SECSPAC_CEILING)
fprintf(f, "playerceiling = true;\n");
if (wsectors[i].activation & SECSPAC_ENTERMONSTER)
fprintf(f, "monsterenter = true;\n");
if (wsectors[i].activation & SECSPAC_FLOORMONSTER)
fprintf(f, "monsterfloor = true;\n");
if (wsectors[i].activation & SECSPAC_CEILINGMONSTER)
fprintf(f, "monsterceiling = true;\n");
if (wsectors[i].activation & SECSPAC_ENTERMISSILE)
fprintf(f, "missileenter = true;\n");
if (wsectors[i].activation & SECSPAC_FLOORMISSILE)
fprintf(f, "missilefloor = true;\n");
if (wsectors[i].activation & SECSPAC_CEILINGMISSILE)
fprintf(f, "missileceiling = true;\n");
fprintf(f, "}\n");
fprintf(f, "\n");
}
@ -2497,6 +2569,11 @@ static void P_LoadTextmap(void)
sc->friction = ORIG_FRICTION;
sc->action = 0;
memset(sc->args, 0, NUMSECTORARGS*sizeof(*sc->args));
memset(sc->stringargs, 0x00, NUMSECTORSTRINGARGS*sizeof(*sc->stringargs));
sc->activation = 0;
textmap_colormap.used = false;
textmap_colormap.lightcolor = 0;
textmap_colormap.lightalpha = 25;
@ -2549,6 +2626,8 @@ static void P_LoadTextmap(void)
ld->sidenum[0] = 0xffff;
ld->sidenum[1] = 0xffff;
ld->activation = 0;
TextmapParse(linesPos[i], i, ParseTextmapLinedefParameter);
if (!ld->v1)
@ -2593,6 +2672,7 @@ static void P_LoadTextmap(void)
mt->scale = mapobjectscale;
memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args));
memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs));
mt->special = 0;
mt->mobj = NULL;
TextmapParse(mapthingsPos[i], i, ParseTextmapThingParameter);
@ -5843,14 +5923,12 @@ static void P_ConvertBinaryLinedefTypes(void)
lines[i].blendmode = AST_FOG;
break;
case 2001: //Finish line
lines[i].activation |= SPAC_CROSS;
lines[i].flags |= ML_REPEATSPECIAL;
lines[i].activation |= (SPAC_CROSS|SPAC_REPEATSPECIAL);
if (lines[i].flags & ML_NOCLIMB)
lines[i].args[0] |= TMCFF_FLIP;
break;
case 2003: //Respawn line
lines[i].activation |= SPAC_CROSS;
lines[i].flags |= ML_REPEATSPECIAL;
lines[i].activation |= (SPAC_CROSS|SPAC_REPEATSPECIAL);
if (lines[i].flags & ML_NOCLIMB)
lines[i].args[0] |= TMCRF_FRONTONLY;
break;

View file

@ -2101,7 +2101,7 @@ static void K_HandleLapDecrement(player_t *player)
static void P_LineSpecialWasActivated(line_t *line)
{
if (!(line->flags & ML_REPEATSPECIAL))
if (!(line->activation & SPAC_REPEATSPECIAL))
{
line->special = 0;
}
@ -5410,6 +5410,260 @@ void P_CheckMobjTrigger(mobj_t *mobj, boolean pushable)
P_CheckMobjSectorTrigger(mobj, originalsector);
}
static void P_SectorActionWasActivated(sector_t *sec)
{
if ((sec->activation & SECSPAC_REPEATSPECIAL) == 0)
{
sec->action = 0;
}
}
static boolean P_AllowSpecialEnter(sector_t *sec, mobj_t *thing)
{
if (thing->player != NULL)
{
return !!(sec->activation & SECSPAC_ENTER);
}
else if ((thing->flags & (MF_ENEMY|MF_BOSS)) != 0)
{
return !!(sec->activation & SECSPAC_ENTERMONSTER);
}
else if (K_IsMissileOrKartItem(thing) == true)
{
return !!(sec->activation & SECSPAC_ENTERMISSILE);
}
// No activation flags for you.
return false;
}
static boolean P_AllowSpecialFloor(sector_t *sec, mobj_t *thing)
{
if (thing->player != NULL)
{
return !!(sec->activation & SECSPAC_FLOOR);
}
else if ((thing->flags & (MF_ENEMY|MF_BOSS)) != 0)
{
return !!(sec->activation & SECSPAC_FLOORMONSTER);
}
else if (K_IsMissileOrKartItem(thing) == true)
{
return !!(sec->activation & SECSPAC_FLOORMISSILE);
}
// No activation flags for you.
return false;
}
static boolean P_AllowSpecialCeiling(sector_t *sec, mobj_t *thing)
{
if (thing->player != NULL)
{
return !!(sec->activation & SECSPAC_CEILING);
}
else if ((thing->flags & (MF_ENEMY|MF_BOSS)) != 0)
{
return !!(sec->activation & SECSPAC_CEILINGMONSTER);
}
else if (K_IsMissileOrKartItem(thing) == true)
{
return !!(sec->activation & SECSPAC_CEILINGMISSILE);
}
// No activation flags for you.
return false;
}
static void P_CheckMobj3DFloorAction(mobj_t *mo, sector_t *sec)
{
sector_t *originalsector = mo->subsector->sector;
ffloor_t *rover;
sector_t *roversec;
activator_t *activator = NULL;
boolean result = false;
for (rover = sec->ffloors; rover; rover = rover->next)
{
roversec = rover->master->frontsector;
if (P_CanActivateSpecial(roversec->action) == false)
{
// No special to even activate.
continue;
}
if (P_AllowSpecialEnter(roversec, mo) == false)
{
boolean floor = false;
boolean ceiling = false;
if (P_AllowSpecialFloor(roversec, mo) == true)
{
floor = (P_GetMobjFeet(mo) == P_GetSpecialTopZ(mo, roversec, roversec));
}
if (P_AllowSpecialCeiling(roversec, mo) == true)
{
ceiling = (P_GetMobjHead(mo) == P_GetSpecialBottomZ(mo, roversec, roversec));
}
if (floor == false && ceiling == false)
{
continue;
}
}
activator = Z_Calloc(sizeof(activator_t), PU_LEVEL, NULL);
I_Assert(activator != NULL);
P_SetTarget(&activator->mo, mo);
activator->sector = roversec;
result = P_ProcessSpecial(activator, roversec->action, roversec->args, roversec->stringargs);
Z_Free(activator);
if (result == true)
{
P_SectorActionWasActivated(roversec);
}
if TELEPORTED(mo) return;
}
}
static void P_CheckMobjPolyobjAction(mobj_t *mo)
{
sector_t *originalsector = mo->subsector->sector;
polyobj_t *po;
sector_t *polysec;
boolean touching = false;
boolean inside = false;
activator_t *activator = NULL;
boolean result = false;
for (po = mo->subsector->polyList; po; po = (polyobj_t *)(po->link.next))
{
polysec = po->lines[0]->backsector;
touching = P_MobjTouchingPolyobj(po, mo);
inside = P_MobjInsidePolyobj(po, mo);
if (!(inside || touching))
continue;
if (P_CanActivateSpecial(polysec->action) == false)
{
// No special to even activate.
continue;
}
if (P_AllowSpecialEnter(polysec, mo) == false)
{
boolean floor = false;
boolean ceiling = false;
if (P_AllowSpecialFloor(polysec, mo) == true)
{
floor = (P_GetMobjFeet(mo) == P_GetSpecialTopZ(mo, polysec, polysec));
}
if (P_AllowSpecialCeiling(polysec, mo) == true)
{
ceiling = (P_GetMobjHead(mo) == P_GetSpecialBottomZ(mo, polysec, polysec));
}
if (floor == false && ceiling == false)
{
continue;
}
}
activator = Z_Calloc(sizeof(activator_t), PU_LEVEL, NULL);
I_Assert(activator != NULL);
P_SetTarget(&activator->mo, mo);
activator->sector = polysec;
result = P_ProcessSpecial(activator, polysec->action, polysec->args, polysec->stringargs);
Z_Free(activator);
if (result == true)
{
P_SectorActionWasActivated(polysec);
}
if TELEPORTED(mo) return;
}
}
static void P_CheckMobjSectorAction(mobj_t *mo, sector_t *sec)
{
activator_t *activator = NULL;
boolean result = false;
if (P_CanActivateSpecial(sec->action) == false)
{
// No special to even activate.
return;
}
if (P_AllowSpecialEnter(sec, mo) == false)
{
boolean floor = false;
boolean ceiling = false;
if (P_AllowSpecialFloor(sec, mo) == true)
{
floor = (P_GetMobjFeet(mo) == P_GetSpecialBottomZ(mo, sec, sec));
}
if (P_AllowSpecialCeiling(sec, mo) == true)
{
ceiling = (P_GetMobjHead(mo) == P_GetSpecialTopZ(mo, sec, sec));
}
if (floor == false && ceiling == false)
{
return;
}
}
activator = Z_Calloc(sizeof(activator_t), PU_LEVEL, NULL);
I_Assert(activator != NULL);
P_SetTarget(&activator->mo, mo);
activator->sector = sec;
result = P_ProcessSpecial(activator, sec->action, sec->args, sec->stringargs);
Z_Free(activator);
if (result == true)
{
P_SectorActionWasActivated(sec);
}
}
void P_CheckMobjTouchingSectorActions(mobj_t *mobj)
{
sector_t *originalsector;
if (!mobj->subsector)
return;
originalsector = mobj->subsector->sector;
P_CheckMobj3DFloorAction(mobj, originalsector);
if TELEPORTED(mobj) return;
P_CheckMobjPolyobjAction(mobj);
if TELEPORTED(mobj) return;
P_CheckMobjSectorAction(mobj, originalsector);
}
#undef TELEPORTED
/** Animate planes, scroll walls, etc. and keeps track of level timelimit and exits if time is up.

View file

@ -547,6 +547,7 @@ sector_t *P_PlayerTouchingSectorSpecial(player_t *player, INT32 section, INT32 n
sector_t *P_PlayerTouchingSectorSpecialFlag(player_t *player, sectorspecialflags_t flag);
void P_PlayerInSpecialSector(player_t *player);
void P_CheckMobjTrigger(mobj_t *mobj, boolean pushable);
void P_CheckMobjTouchingSectorActions(mobj_t *mobj);
sector_t *P_FindPlayerTrigger(player_t *player, line_t *sourceline);
boolean P_IsPlayerValid(size_t playernum);
boolean P_CanPlayerTrigger(size_t playernum);

View file

@ -371,6 +371,39 @@ typedef enum
SSF_ZOOMTUBEEND = 1<<16,
} sectorspecialflags_t;
typedef enum
{
// Special action is repeatable.
SECSPAC_REPEATSPECIAL = 0x00000001,
// When a player enters this sector.
SECSPAC_ENTER = 0x00000002,
// When a player touches the floor of this sector.
SECSPAC_FLOOR = 0x00000004,
// When a player touches the ceiling of this sector.
SECSPAC_CEILING = 0x00000008,
// When an enemy enters this sector.
SECSPAC_ENTERMONSTER = 0x00000010,
// When an enemy touches the floor of this sector.
SECSPAC_FLOORMONSTER = 0x00000020,
// When an enemy touches the ceiling of this sector.
SECSPAC_CEILINGMONSTER = 0x00000040,
// When a projectile enters this sector.
SECSPAC_ENTERMISSILE = 0x00000080,
// When a projectile touches the floor of this sector.
SECSPAC_FLOORMISSILE = 0x00000100,
// When a projectile touches the ceiling of this sector.
SECSPAC_CEILINGMISSILE = 0x00000200,
} sectoractionflags_t;
typedef enum
{
SD_NONE = 0,
@ -396,6 +429,9 @@ typedef enum
CRUMBLE_RESTORE, // Crumble thinker is about to restore to original position
} crumblestate_t;
#define NUMSECTORARGS 10
#define NUMSECTORSTRINGARGS 2
//
// The SECTORS record, at runtime.
// Stores things/mobjs.
@ -500,6 +536,12 @@ struct sector_t
// colormap structure
extracolormap_t *spawn_extra_colormap;
// Action specials
INT16 action;
INT32 args[NUMSECTORARGS];
char *stringargs[NUMSECTORSTRINGARGS];
sectoractionflags_t activation;
};
//