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

View file

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

View file

@ -77,6 +77,8 @@ extern lua_State *gL;
#define META_SIDENUM "LINE_T*SIDENUM" #define META_SIDENUM "LINE_T*SIDENUM"
#define META_LINEARGS "LINE_T*ARGS" #define META_LINEARGS "LINE_T*ARGS"
#define META_LINESTRINGARGS "LINE_T*STRINGARGS" #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_THINGARGS "MAPTHING_T*ARGS"
#define META_THINGSTRINGARGS "MAPTHING_T*STRINGARGS" #define META_THINGSTRINGARGS "MAPTHING_T*STRINGARGS"
#define META_POLYOBJVERTICES "POLYOBJ_T*VERTICES" #define META_POLYOBJVERTICES "POLYOBJ_T*VERTICES"

View file

@ -56,6 +56,10 @@ enum sector_e {
sector_triggerer, sector_triggerer,
sector_friction, sector_friction,
sector_gravity, sector_gravity,
sector_action,
sector_args,
sector_stringargs,
sector_activation,
}; };
static const char *const sector_opt[] = { static const char *const sector_opt[] = {
@ -86,6 +90,10 @@ static const char *const sector_opt[] = {
"triggerer", "triggerer",
"friction", "friction",
"gravity", "gravity",
"action",
"args"
"stringargs",
"activation",
NULL}; NULL};
enum subsector_e { enum subsector_e {
@ -592,6 +600,42 @@ static int sectorlines_num(lua_State *L)
// sector_t // // 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) static int sector_get(lua_State *L)
{ {
sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR)); 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 case sector_gravity: // gravity
lua_pushfixed(L, sector->gravity); lua_pushfixed(L, sector->gravity);
return 1; 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; return 0;
} }
@ -738,6 +794,8 @@ static int sector_set(lua_State *L)
case sector_fslope: // f_slope case sector_fslope: // f_slope
case sector_cslope: // c_slope case sector_cslope: // c_slope
case sector_friction: // friction case sector_friction: // friction
case sector_args: // args
case sector_stringargs: // stringargs
default: default:
return luaL_error(L, "sector_t field " LUA_QS " cannot be set.", sector_opt[field]); return luaL_error(L, "sector_t field " LUA_QS " cannot be set.", sector_opt[field]);
case sector_floorheight: { // floorheight case sector_floorheight: { // floorheight
@ -816,6 +874,12 @@ static int sector_set(lua_State *L)
case sector_gravity: case sector_gravity:
sector->gravity = luaL_checkfixed(L, 3); sector->gravity = luaL_checkfixed(L, 3);
break; break;
case sector_action:
sector->action = (INT16)luaL_checkinteger(L, 3);
break;
case sector_activation:
sector->activation = luaL_checkinteger(L, 3);
break;
} }
return 0; return 0;
} }
@ -2570,6 +2634,22 @@ int LUA_MapLib(lua_State *L)
lua_setfield(L, -2, "__len"); lua_setfield(L, -2, "__len");
lua_pop(L, 1); 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); luaL_newmetatable(L, META_SUBSECTOR);
lua_pushcfunction(L, subsector_get); lua_pushcfunction(L, subsector_get);
lua_setfield(L, -2, "__index"); 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.floorthing, NULL);
P_SetTarget(&tm.hitthing, 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 // Sector flag MSF_TRIGGERLINE_MOBJ allows ANY mobj to trigger a linedef exec
P_CheckMobjTrigger(mobj, false); P_CheckMobjTrigger(mobj, false);

View file

@ -1099,8 +1099,40 @@ static void P_NetUnArchiveColormaps(savebuffer_t *save)
//diff4 flags //diff4 flags
#define SD_DAMAGETYPE 0x01 #define SD_DAMAGETYPE 0x01
#define SD_TRIGGERTAG 0x02 #define SD_TRIGGERTAG 0x02
#define SD_TRIGGERER 0x04 #define SD_TRIGGERER 0x04
#define SD_GRAVITY 0x08 #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_FLAG 0x01
#define LD_SPECIAL 0x02 #define LD_SPECIAL 0x02
@ -1124,7 +1156,7 @@ static void P_NetUnArchiveColormaps(savebuffer_t *save)
// diff3 flags // diff3 flags
#define LD_ACTIVATION 0x01 #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; UINT8 i;
for (i = 0; i < NUMLINEARGS; 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; 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; UINT8 i;
for (i = 0; i < NUMLINESTRINGARGS; i++) for (i = 0; i < NUMLINESTRINGARGS; i++)
@ -1243,11 +1275,11 @@ static void ArchiveSectors(savebuffer_t *save)
size_t i, j; size_t i, j;
const sector_t *ss = sectors; const sector_t *ss = sectors;
const sector_t *spawnss = spawnsectors; const sector_t *spawnss = spawnsectors;
UINT8 diff, diff2, diff3, diff4; UINT8 diff, diff2, diff3, diff4, diff5;
for (i = 0; i < numsectors; i++, ss++, spawnss++) for (i = 0; i < numsectors; i++, ss++, spawnss++)
{ {
diff = diff2 = diff3 = diff4 = 0; diff = diff2 = diff3 = diff4 = diff5 = 0;
if (ss->floorheight != spawnss->floorheight) if (ss->floorheight != spawnss->floorheight)
diff |= SD_FLOORHT; diff |= SD_FLOORHT;
if (ss->ceilingheight != spawnss->ceilingheight) if (ss->ceilingheight != spawnss->ceilingheight)
@ -1303,9 +1335,21 @@ static void ArchiveSectors(savebuffer_t *save)
if (ss->gravity != spawnss->gravity) if (ss->gravity != spawnss->gravity)
diff4 |= SD_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)) if (ss->ffloors && CheckFFloorDiff(ss))
diff |= SD_FFLOORS; diff |= SD_FFLOORS;
if (diff5)
diff4 |= SD_DIFF5;
if (diff4) if (diff4)
diff3 |= SD_DIFF4; diff3 |= SD_DIFF4;
@ -1383,6 +1427,35 @@ static void ArchiveSectors(savebuffer_t *save)
WRITEUINT8(save->p, ss->triggerer); WRITEUINT8(save->p, ss->triggerer);
if (diff4 & SD_GRAVITY) if (diff4 & SD_GRAVITY)
WRITEFIXED(save->p, ss->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) if (diff & SD_FFLOORS)
ArchiveFFloors(save, ss); ArchiveFFloors(save, ss);
} }
@ -1394,7 +1467,7 @@ static void ArchiveSectors(savebuffer_t *save)
static void UnArchiveSectors(savebuffer_t *save) static void UnArchiveSectors(savebuffer_t *save)
{ {
UINT16 i, j; UINT16 i, j;
UINT8 diff, diff2, diff3, diff4; UINT8 diff, diff2, diff3, diff4, diff5;
for (;;) for (;;)
{ {
i = READUINT16(save->p); i = READUINT16(save->p);
@ -1419,6 +1492,11 @@ static void UnArchiveSectors(savebuffer_t *save)
else else
diff4 = 0; diff4 = 0;
if (diff4 & SD_DIFF5)
diff5 = READUINT8(save->p);
else
diff5 = 0;
if (diff & SD_FLOORHT) if (diff & SD_FLOORHT)
sectors[i].floorheight = READFIXED(save->p); sectors[i].floorheight = READFIXED(save->p);
if (diff & SD_CEILHT) if (diff & SD_CEILHT)
@ -1504,6 +1582,36 @@ static void UnArchiveSectors(savebuffer_t *save)
if (diff4 & SD_GRAVITY) if (diff4 & SD_GRAVITY)
sectors[i].gravity = READFIXED(save->p); 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) if (diff & SD_FFLOORS)
UnArchiveFFloors(save, &sectors[i]); 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 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; diff |= LD_CLLCOUNT;
if (!P_AreArgsEqual(li, spawnli)) if (!P_LineArgsEqual(li, spawnli))
diff2 |= LD_ARGS; diff2 |= LD_ARGS;
if (!P_AreStringArgsEqual(li, spawnli)) if (!P_LineStringArgsEqual(li, spawnli))
diff2 |= LD_STRINGARGS; diff2 |= LD_STRINGARGS;
if (li->executordelay != spawnli->executordelay) if (li->executordelay != spawnli->executordelay)

View file

@ -870,6 +870,11 @@ static void P_LoadSectors(UINT8 *data)
ss->friction = ORIG_FRICTION; 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); P_InitializeSector(ss);
} }
} }
@ -980,6 +985,7 @@ static void P_LoadLinedefs(UINT8 *data)
memset(ld->stringargs, 0x00, NUMLINESTRINGARGS*sizeof(*ld->stringargs)); memset(ld->stringargs, 0x00, NUMLINESTRINGARGS*sizeof(*ld->stringargs));
ld->alpha = FRACUNIT; ld->alpha = FRACUNIT;
ld->executordelay = 0; ld->executordelay = 0;
ld->activation = 0;
P_SetLinedefV1(i, SHORT(mld->v1)); P_SetLinedefV1(i, SHORT(mld->v1));
P_SetLinedefV2(i, SHORT(mld->v2)); P_SetLinedefV2(i, SHORT(mld->v2));
@ -1216,6 +1222,7 @@ static void P_LoadThings(UINT8 *data)
mt->scale = mapobjectscale; mt->scale = mapobjectscale;
memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args)); memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args));
memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs)); memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs));
mt->special = 0;
mt->pitch = mt->roll = 0; mt->pitch = mt->roll = 0;
mt->type &= 4095; mt->type &= 4095;
@ -1530,6 +1537,43 @@ static void ParseTextmapSectorParameter(UINT32 i, const char *param, const char
sectors[i].triggertag = atol(val); sectors[i].triggertag = atol(val);
else if (fastcmp(param, "triggerer")) else if (fastcmp(param, "triggerer"))
sectors[i].triggerer = atol(val); 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) 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; lines[i].flags |= ML_NOTBOUNCY;
else if (fastcmp(param, "transfer") && fastcmp("true", val)) else if (fastcmp(param, "transfer") && fastcmp("true", val))
lines[i].flags |= ML_TFERLINE; lines[i].flags |= ML_TFERLINE;
else if (fastcmp(param, "repeatspecial") && fastcmp("true", val))
lines[i].flags |= ML_REPEATSPECIAL;
// Activation flags // Activation flags
else if (fastcmp(param, "repeatspecial") && fastcmp("true", val))
lines[i].activation |= SPAC_REPEATSPECIAL;
else if (fastcmp(param, "playercross") && fastcmp("true", val)) else if (fastcmp(param, "playercross") && fastcmp("true", val))
lines[i].activation |= SPAC_CROSS; lines[i].activation |= SPAC_CROSS;
else if (fastcmp(param, "monstercross") && fastcmp("true", val)) else if (fastcmp(param, "monstercross") && fastcmp("true", val))
@ -2219,7 +2263,7 @@ static void P_WriteTextmap(void)
fprintf(f, "notbouncy = true;\n"); fprintf(f, "notbouncy = true;\n");
if (wlines[i].flags & ML_TFERLINE) if (wlines[i].flags & ML_TFERLINE)
fprintf(f, "transfer = true;\n"); fprintf(f, "transfer = true;\n");
if (wlines[i].flags & ML_REPEATSPECIAL) if (wlines[i].activation & SPAC_REPEATSPECIAL)
fprintf(f, "repeatspecial = true;\n"); fprintf(f, "repeatspecial = true;\n");
if (wlines[i].activation & SPAC_CROSS) if (wlines[i].activation & SPAC_CROSS)
fprintf(f, "playercross = true;\n"); fprintf(f, "playercross = true;\n");
@ -2403,6 +2447,34 @@ static void P_WriteTextmap(void)
fprintf(f, "triggertag = %d;\n", wsectors[i].triggertag); fprintf(f, "triggertag = %d;\n", wsectors[i].triggertag);
if (wsectors[i].triggerer != 0) if (wsectors[i].triggerer != 0)
fprintf(f, "triggerer = %d;\n", wsectors[i].triggerer); 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");
fprintf(f, "\n"); fprintf(f, "\n");
} }
@ -2497,6 +2569,11 @@ static void P_LoadTextmap(void)
sc->friction = ORIG_FRICTION; 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.used = false;
textmap_colormap.lightcolor = 0; textmap_colormap.lightcolor = 0;
textmap_colormap.lightalpha = 25; textmap_colormap.lightalpha = 25;
@ -2549,6 +2626,8 @@ static void P_LoadTextmap(void)
ld->sidenum[0] = 0xffff; ld->sidenum[0] = 0xffff;
ld->sidenum[1] = 0xffff; ld->sidenum[1] = 0xffff;
ld->activation = 0;
TextmapParse(linesPos[i], i, ParseTextmapLinedefParameter); TextmapParse(linesPos[i], i, ParseTextmapLinedefParameter);
if (!ld->v1) if (!ld->v1)
@ -2593,6 +2672,7 @@ static void P_LoadTextmap(void)
mt->scale = mapobjectscale; mt->scale = mapobjectscale;
memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args)); memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args));
memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs)); memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs));
mt->special = 0;
mt->mobj = NULL; mt->mobj = NULL;
TextmapParse(mapthingsPos[i], i, ParseTextmapThingParameter); TextmapParse(mapthingsPos[i], i, ParseTextmapThingParameter);
@ -5843,14 +5923,12 @@ static void P_ConvertBinaryLinedefTypes(void)
lines[i].blendmode = AST_FOG; lines[i].blendmode = AST_FOG;
break; break;
case 2001: //Finish line case 2001: //Finish line
lines[i].activation |= SPAC_CROSS; lines[i].activation |= (SPAC_CROSS|SPAC_REPEATSPECIAL);
lines[i].flags |= ML_REPEATSPECIAL;
if (lines[i].flags & ML_NOCLIMB) if (lines[i].flags & ML_NOCLIMB)
lines[i].args[0] |= TMCFF_FLIP; lines[i].args[0] |= TMCFF_FLIP;
break; break;
case 2003: //Respawn line case 2003: //Respawn line
lines[i].activation |= SPAC_CROSS; lines[i].activation |= (SPAC_CROSS|SPAC_REPEATSPECIAL);
lines[i].flags |= ML_REPEATSPECIAL;
if (lines[i].flags & ML_NOCLIMB) if (lines[i].flags & ML_NOCLIMB)
lines[i].args[0] |= TMCRF_FRONTONLY; lines[i].args[0] |= TMCRF_FRONTONLY;
break; break;

View file

@ -2101,7 +2101,7 @@ static void K_HandleLapDecrement(player_t *player)
static void P_LineSpecialWasActivated(line_t *line) static void P_LineSpecialWasActivated(line_t *line)
{ {
if (!(line->flags & ML_REPEATSPECIAL)) if (!(line->activation & SPAC_REPEATSPECIAL))
{ {
line->special = 0; line->special = 0;
} }
@ -5410,6 +5410,260 @@ void P_CheckMobjTrigger(mobj_t *mobj, boolean pushable)
P_CheckMobjSectorTrigger(mobj, originalsector); 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 #undef TELEPORTED
/** Animate planes, scroll walls, etc. and keeps track of level timelimit and exits if time is up. /** 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); sector_t *P_PlayerTouchingSectorSpecialFlag(player_t *player, sectorspecialflags_t flag);
void P_PlayerInSpecialSector(player_t *player); void P_PlayerInSpecialSector(player_t *player);
void P_CheckMobjTrigger(mobj_t *mobj, boolean pushable); void P_CheckMobjTrigger(mobj_t *mobj, boolean pushable);
void P_CheckMobjTouchingSectorActions(mobj_t *mobj);
sector_t *P_FindPlayerTrigger(player_t *player, line_t *sourceline); sector_t *P_FindPlayerTrigger(player_t *player, line_t *sourceline);
boolean P_IsPlayerValid(size_t playernum); boolean P_IsPlayerValid(size_t playernum);
boolean P_CanPlayerTrigger(size_t playernum); boolean P_CanPlayerTrigger(size_t playernum);

View file

@ -371,6 +371,39 @@ typedef enum
SSF_ZOOMTUBEEND = 1<<16, SSF_ZOOMTUBEEND = 1<<16,
} sectorspecialflags_t; } 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 typedef enum
{ {
SD_NONE = 0, SD_NONE = 0,
@ -396,6 +429,9 @@ typedef enum
CRUMBLE_RESTORE, // Crumble thinker is about to restore to original position CRUMBLE_RESTORE, // Crumble thinker is about to restore to original position
} crumblestate_t; } crumblestate_t;
#define NUMSECTORARGS 10
#define NUMSECTORSTRINGARGS 2
// //
// The SECTORS record, at runtime. // The SECTORS record, at runtime.
// Stores things/mobjs. // Stores things/mobjs.
@ -500,6 +536,12 @@ struct sector_t
// colormap structure // colormap structure
extracolormap_t *spawn_extra_colormap; extracolormap_t *spawn_extra_colormap;
// Action specials
INT16 action;
INT32 args[NUMSECTORARGS];
char *stringargs[NUMSECTORSTRINGARGS];
sectoractionflags_t activation;
}; };
// //