d5155e3d83411be7e71953e2f8e8fdc52818b36d

This commit is contained in:
NepDisk 2024-09-03 16:39:02 -04:00
parent 5dac959ccc
commit 3aab5834fc
11 changed files with 509 additions and 870 deletions

View file

@ -1,719 +0,0 @@
linedefflags
{
1 = "[0] Impassable";
2 = "[1] Block Players";
4 = "[2] Double-Sided";
8 = "[3] Upper Unpegged";
16 = "[4] Lower Unpegged";
32 = "[5] Slope Skew";
64 = "[6] Not Climbable";
128 = "[7] No Midtexture Skew";
256 = "[8] Peg Midtexture";
512 = "[9] Solid Midtexture";
1024 = "[10] Repeat Midtexture";
2048 = "[11] Netgame Only";
4096 = "[12] No Netgame";
8192 = "[13] Block Enemies";
16384 = "[14] Don't Bounce";
32768 = "[15] FOF Transfer";
}
// Linedef flags UDMF translation table
// This is needed for copy/paste and prefabs to work properly
// When the UDMF field name is prefixed with ! it is inverted
linedefflagstranslation
{
1 = "blocking";
2 = "blockplayers";
4 = "twosided";
8 = "dontpegtop";
16 = "dontpegbottom";
32 = "skewtd";
64 = "noclimb";
128 = "noskew";
256 = "midpeg";
512 = "midsolid";
1024 = "wrapmidtex";
2048 = "netonly";
4096 = "nonet";
8192 = "blockmonsters";
16384 = "notbouncy";
32768 = "transfer";
}
linedefflags_udmf
{
blocking = "Impassable";
blockplayers = "Block Players";
twosided = "Double-Sided";
dontpegtop = "Upper Unpegged";
dontpegbottom = "Lower Unpegged";
skewtd = "Slope Skew";
noclimb = "Not Climbable";
noskew = "No Midtexture Skew";
midpeg = "Peg Midtexture";
midsolid = "Solid Midtexture";
wrapmidtex = "Repeat Midtexture";
netonly = "Netgame Only";
nonet = "No Netgame";
blockmonsters = "Block Enemies";
bouncy = "Don't Bump";
transfer = "FOF Transfer";
}
linedefrenderstyles
{
translucent = "Translucent";
add = "Add";
subtract = "Subtract";
reversesubtract = "Reverse subtract";
modulate = "Modulate";
fog = "Fog";
}
sectorflags
{
colormapfog = "Fog Planes in Colormap";
colormapfadesprites = "Fade Fullbright in Colormap";
colormapprotected = "Protected Colormap";
flipspecial_nofloor = "No Trigger on Floor Touch";
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";
noclipcamera = "Intangible to the Camera";
ripple_floor = "Water Ripple Floor";
ripple_ceiling = "Water Ripple Ceiling";
invertencore = "Encore Remap Invert";
nostepup = "Wall Sector (no step-up)";
doublestepup = "Ramp Sector (double step-up/down)";
nostepdown = "Non-Ramp Sector (no step-down)";
starpostactivator = "Star Post Activator";
exit = "Exit";
fan = "Fan Sector";
deleteitems = "Delete Items";
zoomtubestart = "Zoom Tube Start";
zoomtubeend = "Zoom Tube End";
}
thingflags
{
1 = "[1] Extra";
2 = "[2] Flip";
4 = "[4] Special";
8 = "[8] Ambush";
}
// THING FLAGS
thingflags_udmf
{
flip = "Flip";
}
// Thing flags UDMF translation table
// This is needed for copy/paste and prefabs to work properly
// When the UDMF field name is prefixed with ! it is inverted
thingflagstranslation
{
2 = "flip";
}
// DEFAULT SECTOR BRIGHTNESS LEVELS
sectorbrightness
{
255;
248;
240;
232;
224;
216;
208;
200;
192;
184;
176;
168;
160;
152;
144;
136;
128;
120;
112;
104;
96;
88;
80;
72;
64;
56;
48;
40;
32;
24;
16;
8;
0;
}
numbrightnesslevels = 32;
/*
TEXTURES AND FLAT SOURCES
This tells Doom Builder where to find the information for textures
and flats in the IWAD file, Addition WAD file and Map WAD file.
Start and end lumps must be given in a structure (of which the
key name doesnt matter) and any textures or flats in between them
are loaded in either the textures category or flats category.
For textures: PNAMES, TEXTURE1 and TEXTURE2 are loaded by default.
*/
textures
{
zdoom1
{
start = "TX_START";
end = "TX_END";
}
}
/*
ADDITIONAL UNIVERSAL DOOM MAP FORMAT FIELD DEFINITIONS
Only add fields here that Doom Builder does not edit with its own user-interface!
The "default" field must match the UDMF specifications!
Field data types:
0 = integer *
1 = float
2 = string
3 = bool
4 = linedef action (integer) *
5 = sector effect (integer) *
6 = texture (string)
7 = flat (string)
8 = angle in degrees (integer)
9 = angle in radians (float)
10 = XXRRGGBB color (integer)
11 = enum option (integer) *
12 = enum bits (integer) *
13 = sector tag (integer) *
14 = thing tag (integer) *
15 = linedef tag (integer) *
16 = enum option (string)
17 = angle in degrees (float)
22 = byte angle (integer)
*/
universalfields
{
sector
{
}
linedef
{
}
sidedef
{
}
thing
{
}
}
/*
MAP LUMP NAMES
Map lumps are loaded with the map as long as they are right after each other. When the editor
meets a lump which is not defined in this list it will ignore the map if not satisfied.
The order of items defines the order in which lumps will be written to WAD file on save.
To indicate the map header lump, use ~MAP
Legenda:
required = Lump is required to exist.
blindcopy = Lump will be copied along with the map blindly. (useful for lumps Doom Builder doesn't use)
nodebuild = The nodebuilder generates this lump.
allowempty = The nodebuilder is allowed to leave this lump empty.
scriptbuild = This lump is a text-based script, which should be compiled using current script compiler;
script = This lump is a text-based script. Specify the filename of the script configuration to use.
*/
doommaplumpnames
{
~MAP
{
required = true;
blindcopy = true;
nodebuild = false;
}
THINGS
{
required = true;
nodebuild = true;
allowempty = true;
}
LINEDEFS
{
required = true;
nodebuild = true;
allowempty = false;
}
SIDEDEFS
{
required = true;
nodebuild = true;
allowempty = false;
}
VERTEXES
{
required = true;
nodebuild = true;
allowempty = false;
}
SEGS
{
required = false;
nodebuild = true;
allowempty = false;
}
SSECTORS
{
required = false;
nodebuild = true;
allowempty = false;
}
NODES
{
required = false;
nodebuild = true;
allowempty = false;
}
SECTORS
{
required = true;
nodebuild = true;
allowempty = false;
}
REJECT
{
required = false;
nodebuild = true;
allowempty = false;
}
BLOCKMAP
{
required = false;
nodebuild = true;
allowempty = true;
}
}
udmfmaplumpnames
{
ZNODES
{
required = false;
nodebuild = true;
allowempty = false;
}
REJECT
{
required = false;
nodebuild = true;
allowempty = false;
}
BLOCKMAP
{
required = false;
nodebuild = true;
allowempty = true;
}
}
// ENUMERATIONS
// These are enumerated lists for linedef types and UDMF fields.
// Reserved names are: angledeg, anglerad, color, texture, flat
enums
{
falsetrue
{
0 = "False";
1 = "True";
}
yesno
{
0 = "Yes";
1 = "No";
}
noyes
{
0 = "No";
1 = "Yes";
}
setadd
{
0 = "Set";
1 = "Add";
}
onoff
{
0 = "On";
1 = "Off";
}
offon
{
0 = "Off";
1 = "On";
}
updown
{
0 = "Up";
1 = "Down";
}
downup
{
0 = "Down";
1 = "Up";
}
frontback
{
0 = "None";
1 = "Front";
2 = "Back";
}
frontbackboth
{
0 = "Front";
1 = "Back";
2 = "Front and back";
}
tangibility
{
1 = "Intangible from top";
2 = "Intangible from bottom";
4 = "Don't block players";
8 = "Don't block non-players";
}
floorceiling
{
0 = "Floor";
1 = "Ceiling";
2 = "Both";
}
scrollcarry
{
0 = "Scroll and carry";
1 = "Scroll";
2 = "Carry";
}
scrolltype
{
0 = "Regular";
1 = "Accelerative";
2 = "Displacement";
}
comparison
{
0 = "Equal";
1 = "Less than or equal";
2 = "Greater than or equal";
}
triggertype
{
0 = "Continuous";
1 = "Once";
2 = "Each time on entry";
3 = "Each time on entry/exit";
}
xtriggertype
{
0 = "Continuous";
1 = "Each time on entry";
2 = "Each time on entry/exit";
}
team
{
0 = "Red";
1 = "Blue";
}
flagcheck
{
0 = "Has all";
1 = "Has any";
2 = "Has exactly";
3 = "Doesn't have all";
4 = "Doesn't have any";
}
maceflags
{
1 = "Double size";
2 = "No sounds";
4 = "Player-turnable chain";
8 = "Swing instead of spin";
16 = "Make chain from end item";
32 = "Spawn link at origin";
64 = "Clip inside ground";
128 = "No distance check";
}
pushablebehavior
{
0 = "Normal";
1 = "Slide";
2 = "Immovable";
3 = "Classic";
}
monitorrespawn
{
0 = "Same item";
1 = "Random (Weak)";
2 = "Random (Strong)";
}
blendmodes
{
0 = "Translucent";
1 = "Add";
2 = "Subtract";
3 = "Reverse subtract";
4 = "Modulate";
}
rritems
{
0 = "Rings";
1 = "Sneaker";
2 = "Rocket Sneaker";
3 = "Invincibility";
4 = "Banana";
5 = "Eggman Mark";
6 = "Orbinaut";
7 = "Jawz";
8 = "Proximity Mine";
9 = "Land Mine";
10 = "Ballhog";
11 = "SPB";
12 = "Grow";
13 = "Shrink";
14 = "Lightning Shield";
15 = "Bubble Shield";
16 = "Flame Shield";
17 = "Hyudoro";
18 = "Pogo Spring";
19 = "Super Ring";
20 = "Kitchen Sink";
21 = "Drop Target";
22 = "Garden Top";
}
}
//Default things filters
thingsfilters
{
filter0
{
name = "Player starts";
category = "starts";
type = -1;
}
filter1
{
name = "Normal Gravity";
category = "";
type = -1;
fields
{
2 = false;
}
}
filter2
{
name = "Reverse Gravity";
category = "";
type = -1;
fields
{
2 = true;
}
}
filter3
{
name = "Rings";
category = "";
type = 300;
}
filter4
{
name = "Waypoints";
category = "waypoints";
}
}
// Special linedefs
speciallinedefs
{
soundlinedefflag = 64; // See linedefflags
singlesidedflag = 1; // See linedefflags
doublesidedflag = 4; // See linedefflags
impassableflag = 1;
upperunpeggedflag = 8;
lowerunpeggedflag = 16;
repeatmidtextureflag = 1024;
pegmidtextureflag = 256;
}
speciallinedefs_udmf
{
soundlinedefflag = "noclimb";
singlesidedflag = "blocking";
doublesidedflag = "twosided";
impassableflag = "blocking";
upperunpeggedflag = "dontpegtop";
lowerunpeggedflag = "dontpegbottom";
repeatmidtextureflag = "wrapmidtex";
pegmidtextureflag = "midpeg";
}
scriptlumpnames
{
MAINCFG
{
script = "SOC.cfg";
}
OBJCTCFG
{
script = "SOC.cfg";
}
SOC_
{
script = "SOC.cfg";
isprefix = true;
}
LUA_
{
script = "Lua.cfg";
isprefix = true;
}
}
// Texture sources
textures
{
zdoom1
{
start = "TX_START";
end = "TX_END";
}
}
// Patch sources
patches
{
standard1
{
start = "P_START";
end = "P_END";
}
standard2
{
start = "PP_START";
end = "PP_END";
}
}
// Sprite sources
sprites
{
standard1
{
start = "S_START";
end = "S_END";
}
standard2
{
start = "SS_START";
end = "SS_END";
}
}
// Flat sources
flats
{
standard1
{
start = "F_START";
end = "F_END";
}
standard2
{
start = "FF_START";
end = "FF_END";
}
standard3
{
start = "FF_START";
end = "F_END";
}
standard4
{
start = "F_START";
end = "FF_END";
}
}

View file

@ -120,35 +120,59 @@ enum
// top and bottom textures (use next to windows).
// upper texture unpegged
ML_DONTPEGTOP = 0x00000008,
ML_DONTPEGTOP = 0x00000008,
// lower texture unpegged
ML_DONTPEGBOTTOM = 0x00000010,
ML_DONTPEGBOTTOM = 0x00000010,
ML_SKEWTD = 0x00000020,
ML_SKEWTD = 0x00000020,
// Don't let Knuckles climb on this line
ML_NOCLIMB = 0x00000040,
ML_NOCLIMB = 0x00000040,
ML_NOSKEW = 0x00000080,
ML_MIDPEG = 0x00000100,
ML_MIDSOLID = 0x00000200,
ML_WRAPMIDTEX = 0x00000400,
ML_NOSKEW = 0x00000080,
ML_MIDPEG = 0x00000100,
ML_MIDSOLID = 0x00000200,
ML_WRAPMIDTEX = 0x00000400,
// Apply effect only in netgames
ML_NETONLY = 0x00000800,
ML_NETONLY = 0x00000800,
// Apply effect only in single player games
ML_NONET = 0x00001000,
ML_NONET = 0x00001000,
// SRB2Kart: Blocks players only; items can be thrown through these.
ML_BLOCKPLAYERS = 0x00002000,
// Don't bounce off this wall!
ML_NOTBOUNCY = 0x00004000,
ML_NOTBOUNCY = 0x00004000,
// Transfers FOF properties.
ML_TFERLINE = 0x00008000,
ML_TFERLINE = 0x00008000,
// Special action is repeatable.
ML_REPEATSPECIAL = 0x00010000,
};
enum
{
// Activates when crossed by a player.
SPAC_CROSS = 0x00000001,
// Activates when crossed by an enemy.
SPAC_CROSSMONSTER = 0x00000002,
// Activates when crossed by a projectile.
SPAC_CROSSMISSILE = 0x00000004,
// Activates when bumped by a player.
SPAC_PUSH = 0x00000008,
// Activates when bumped by an enemy.
SPAC_PUSHMONSTER = 0x00000010,
// Activates when bumped by a missile.
SPAC_IMPACT = 0x00000020,
};
// Sector definition, from editing.

View file

@ -112,6 +112,7 @@ enum line_e {
line_dy,
line_angle,
line_flags,
line_activation,
line_special,
line_tag,
line_taglist,
@ -138,6 +139,7 @@ static const char *const line_opt[] = {
"dy",
"angle",
"flags",
"activation",
"special",
"tag",
"taglist",
@ -932,6 +934,9 @@ static int line_get(lua_State *L)
case line_flags:
lua_pushinteger(L, line->flags);
return 1;
case line_activation:
lua_pushinteger(L, line->activation);
return 1;
case line_special:
lua_pushinteger(L, line->special);
return 1;

View file

@ -262,20 +262,11 @@ static boolean P_SpecialIsLinedefCrossType(line_t *ld)
{
boolean linedefcrossspecial = false;
switch (ld->special)
// Take anything with any cross type for now,
// we'll have to filter it down later...
if (ld->activation & (SPAC_CROSS | SPAC_CROSSMONSTER | SPAC_CROSSMISSILE))
{
case 2001: // Finish line
case 2003: // Respawn line
{
linedefcrossspecial = true;
}
break;
default:
{
linedefcrossspecial = false;
}
break;
linedefcrossspecial = P_CanActivateSpecial(ld->special);
}
return linedefcrossspecial;

View file

@ -1613,6 +1613,8 @@ void P_XYMovement(mobj_t *mo)
}
else if (P_MobjWasRemoved(mo))
return;
P_PushSpecialLine(blockingline, mo);
//{ SRB2kart - Jawz
if (mo->type == MT_JAWZ || mo->type == MT_JAWZ_DUD)
@ -4985,6 +4987,23 @@ boolean P_IsKartItem(INT32 type)
}
}
boolean K_IsMissileOrKartItem(mobj_t *mo)
{
if (mo->flags & MF_MISSILE)
{
// It's already a missile!
return true;
}
if (mo->type == MT_SPB)
{
// Not considered a field item, so manually include.
return true;
}
return P_IsKartFieldItem(mo->type);
}
// This item can die in death sectors. There may be some
// special conditions for items that don't switch types...
// TODO: just make a general function for things that should

View file

@ -505,6 +505,7 @@ void P_AddCachedAction(mobj_t *mobj, INT32 statenum);
// kartitem stuff: Returns true if the specified 'type' is one of the kart item constants we want in the kitemcap list
boolean P_IsKartFieldItem(INT32 type);
boolean P_IsKartItem(INT32 type);
boolean K_IsMissileOrKartItem(mobj_t *mo);
boolean P_CanDeleteKartItem(INT32 type);
void P_AddKartItem(mobj_t *thing); // needs to be called in k_kart.c
void P_RunKartItems(void);

View file

@ -931,6 +931,10 @@ static void P_NetUnArchiveColormaps(void)
#define LD_ARGS 0x10
#define LD_STRINGARGS 0x20
#define LD_EXECUTORDELAY 0x40
#define LD_DIFF3 0x80
// diff3 flags
#define LD_ACTIVATION 0x01
static boolean P_AreArgsEqual(const line_t *li, const line_t *spawnli)
{
@ -1324,11 +1328,14 @@ static void ArchiveLines(void)
const line_t *spawnli = spawnlines;
const side_t *si;
const side_t *spawnsi;
UINT8 diff, diff2; // no diff3
UINT8 diff, diff2, diff3;
for (i = 0; i < numlines; i++, spawnli++, li++)
{
diff = diff2 = 0;
diff = diff2 = diff3 = 0;
if (li->flags != spawnli->flags)
diff |= LD_FLAG;
if (li->special != spawnli->special)
diff |= LD_SPECIAL;
@ -1345,6 +1352,9 @@ static void ArchiveLines(void)
if (li->executordelay != spawnli->executordelay)
diff2 |= LD_EXECUTORDELAY;
if (li->activation != spawnli->activation)
diff3 |= LD_ACTIVATION;
if (li->sidenum[0] != 0xffff)
{
si = &sides[li->sidenum[0]];
@ -1373,6 +1383,9 @@ static void ArchiveLines(void)
diff2 |= LD_S2MIDTEX;
}
if (diff3)
diff2 |= LD_DIFF3;
if (diff2)
diff |= LD_DIFF2;
@ -1382,6 +1395,8 @@ static void ArchiveLines(void)
WRITEUINT8(save_p, diff);
if (diff & LD_DIFF2)
WRITEUINT8(save_p, diff2);
if (diff2 & LD_DIFF3)
WRITEUINT8(save_p, diff3);
if (diff & LD_FLAG)
WRITEUINT32(save_p, li->flags);
if (diff & LD_SPECIAL)
@ -1435,6 +1450,8 @@ static void ArchiveLines(void)
}
if (diff2 & LD_EXECUTORDELAY)
WRITEINT32(save_p, li->executordelay);
if (diff3 & LD_ACTIVATION)
WRITEUINT32(save_p, li->activation);
}
}
WRITEUINT16(save_p, 0xffff);
@ -1445,7 +1462,7 @@ static void UnArchiveLines(void)
UINT16 i;
line_t *li;
side_t *si;
UINT8 diff, diff2; // no diff3
UINT8 diff, diff2, diff3;
for (;;)
{
@ -1464,6 +1481,11 @@ static void UnArchiveLines(void)
else
diff2 = 0;
if (diff2 & LD_DIFF3)
diff3 = READUINT8(save_p);
else
diff3 = 0;
if (diff & LD_FLAG)
li->flags = READUINT32(save_p);
if (diff & LD_SPECIAL)
@ -1519,6 +1541,8 @@ static void UnArchiveLines(void)
}
if (diff2 & LD_EXECUTORDELAY)
li->executordelay = READINT32(save_p);
if (diff3 & LD_ACTIVATION)
li->activation = READUINT32(save_p);
}
}

View file

@ -1853,6 +1853,21 @@ 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, "playercross") && fastcmp("true", val))
lines[i].activation |= SPAC_CROSS;
else if (fastcmp(param, "monstercross") && fastcmp("true", val))
lines[i].activation |= SPAC_CROSSMONSTER;
else if (fastcmp(param, "missilecross") && fastcmp("true", val))
lines[i].activation |= SPAC_CROSSMISSILE;
else if (fastcmp(param, "playerpush") && fastcmp("true", val))
lines[i].activation |= SPAC_PUSH;
else if (fastcmp(param, "monsterpush") && fastcmp("true", val))
lines[i].activation |= SPAC_PUSHMONSTER;
else if (fastcmp(param, "impact") && fastcmp("true", val))
lines[i].activation |= SPAC_IMPACT;
}
static void ParseTextmapThingParameter(UINT32 i, const char *param, const char *val)
@ -6054,10 +6069,14 @@ 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;
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;
if (lines[i].flags & ML_NOCLIMB)
lines[i].args[0] |= TMCRF_FRONTONLY;
break;

View file

@ -1359,9 +1359,26 @@ static boolean P_CheckPushables(line_t *triggerline, sector_t *caller)
}
}
boolean P_CanActivateSpecial(INT16 special)
{
switch (special)
{
case 2001: // Finish line
case 2003: // Respawn line
{
return true;
}
default:
{
// Linedef executors
return (special >= 400 && special < 500);
}
}
}
static void P_ActivateLinedefExecutor(line_t *line, mobj_t *actor, sector_t *caller)
{
if (line->special < 400 || line->special >= 500)
if (P_CanActivateSpecial(line->special) == false)
return;
if (line->executordelay)
@ -2035,66 +2052,183 @@ static void K_HandleLapDecrement(player_t *player)
}
}
static void P_LineSpecialWasActivated(line_t *line)
{
if (!(line->flags & ML_REPEATSPECIAL))
{
line->special = 0;
}
}
static boolean P_AllowSpecialCross(line_t *line, mobj_t *thing)
{
if (P_CanActivateSpecial(line->special) == false)
{
// No special to even activate.
return false;
}
if (thing->player != NULL)
{
return !!(line->activation & SPAC_CROSS);
}
else if ((thing->flags & (MF_ENEMY|MF_BOSS)) != 0)
{
return !!(line->activation & SPAC_CROSSMONSTER);
}
else if (K_IsMissileOrKartItem(thing) == true)
{
return !!(line->activation & SPAC_CROSSMISSILE);
}
// No activation flags for you.
return false;
}
//
// P_CrossSpecialLine - TRIGGER
// Called every time a thing origin is about
// to cross a line with specific specials
// Kart - Only used for the finish line currently
//
void P_CrossSpecialLine(line_t *line, INT32 side, mobj_t *thing)
{
// only used for the players currently
if (!(thing && thing->player && !thing->player->spectator && !(thing->player->pflags & PF_NOCONTEST)))
return;
{
player_t *player = thing->player;
player_t *player = NULL;
activator_t *activator = NULL;
boolean result = false;
if (thing == NULL || P_MobjWasRemoved(thing) == true || thing->health <= 0)
{
// Invalid mobj.
return;
}
player = thing->player;
if (player != NULL)
{
if (player->spectator == true)
{
// Ignore spectators.
return;
}
if (player->pflags & PF_NOCONTEST)
{
// Ignore NO CONTEST.
return;
}
// Tripwire effect
if (P_IsLineTripWire(line))
{
K_ApplyTripWire(player, TRIPSTATE_PASSED);
}
}
switch (line->special)
if (P_AllowSpecialCross(line, thing) == false)
{
// This special can't be activated this way.
return;
}
activator = Z_Calloc(sizeof(activator_t), PU_LEVEL, NULL);
I_Assert(activator != NULL);
P_SetTarget(&activator->mo, thing);
activator->line = line;
activator->side = side;
activator->sector = (side != 0) ? line->backsector : line->frontsector;
activator->fromLineSpecial = true;
result = P_ProcessSpecial(activator, line->special, line->args, line->stringargs);
Z_Free(activator);
if (result == true)
{
P_LineSpecialWasActivated(line);
}
}
static boolean P_AllowSpecialPush(line_t *line, mobj_t *thing)
{
if (P_CanActivateSpecial(line->special) == false)
{
// No special to even activate.
return false;
}
if (thing->player != NULL)
{
return !!(line->activation & SPAC_PUSH);
}
else if ((thing->flags & (MF_ENEMY|MF_BOSS)) != 0)
{
return !!(line->activation & SPAC_PUSHMONSTER);
}
else if (K_IsMissileOrKartItem(thing) == true)
{
return !!(line->activation & SPAC_IMPACT);
}
// No activation flags for you.
return false;
}
//
// P_PushSpecialLine - TRIGGER
// Called every time a thing origin is blocked
// by a line with specific specials
//
void P_PushSpecialLine(line_t *line, mobj_t *thing)
{
player_t *player = NULL;
activator_t *activator = NULL;
boolean result = false;
if (thing == NULL || P_MobjWasRemoved(thing) == true || thing->health <= 0)
{
// Invalid mobj.
return;
}
player = thing->player;
if (player != NULL)
{
if (player->spectator == true)
{
case 2001: // Finish Line
{
if ((gametyperules & GTR_CIRCUIT) && !(player->exiting) && !(player->pflags & PF_HITFINISHLINE))
{
if (((line->args[0] & TMCFF_FLIP) && (side == 0))
|| (!(line->args[0] & TMCFF_FLIP) && (side == 1))) // crossed from behind to infront
{
K_HandleLapIncrement(player);
}
else
{
K_HandleLapDecrement(player);
}
player->pflags |= PF_HITFINISHLINE;
}
}
break;
case 2003: // Respawn Line
{
/* No Climb: only trigger from front side */
if
(
!player->respawn &&
(!(line->args[0] & TMCRF_FRONTONLY) || side == 0)
)
{
P_DamageMobj(player->mo, NULL, NULL, 1, DMG_DEATHPIT);
}
}
break;
default:
{
// Do nothing
}
break;
// Ignore spectators.
return;
}
if (player->pflags & PF_NOCONTEST)
{
// Ignore NO CONTEST.
return;
}
}
if (P_AllowSpecialPush(line, thing) == false)
{
// This special can't be activated this way.
return;
}
activator = Z_Calloc(sizeof(activator_t), PU_LEVEL, NULL);
I_Assert(activator != NULL);
P_SetTarget(&activator->mo, thing);
activator->line = line;
activator->side = P_PointOnLineSide(thing->x, thing->y, line);
activator->sector = (activator->side != 0) ? line->backsector : line->frontsector;
activator->fromLineSpecial = true;
result = P_ProcessSpecial(activator, line->special, line->args, line->stringargs);
Z_Free(activator);
if (result == true)
{
P_LineSpecialWasActivated(line);
}
}
@ -2181,11 +2315,45 @@ static mobj_t* P_FindObjectTypeFromTag(mobjtype_t type, mtag_t tag)
*/
static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
{
INT32 secnum = -1;
mobj_t *bot = NULL;
// This is an old function purely for linedef executor
// backwards compatibility.
// note: only commands with linedef types >= 400 && < 500 can be used
switch (line->special)
activator_t *activator = NULL;
if (line == NULL)
{
// No line to activate
return;
}
activator = Z_Calloc(sizeof(activator_t), PU_LEVEL, NULL);
I_Assert(activator != NULL);
P_SetTarget(&activator->mo, mo);
activator->line = line;
activator->sector = callsec;
activator->fromLineSpecial = true;
P_ProcessSpecial(activator, line->special, line->args, line->stringargs);
Z_Free(activator);
// Intentionally no P_LineSpecialWasActivated call.
}
boolean P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char **stringargs)
{
line_t *const line = activator->line; // If called from a linedef executor, this is the control sector linedef. If from a script, then it's the actual activator.
UINT8 const side = activator->side;
mobj_t *const mo = activator->mo;
sector_t *const callsec = activator->sector;
// All of these conditions being met means this is a binary map using a linedef executor.
boolean const backwardsCompat = (!udmf && activator->fromLineSpecial && line != NULL);
INT32 secnum = -1;
// note: only specials that P_CanActivateSpecial returns true on can be used
switch (special)
{
case 400: // Copy tagged sector's heights/flats
{
@ -2196,7 +2364,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
if (line == NULL)
{
CONS_Debug(DBG_GAMELOGIC, "Special type 400 Executor: No frontsector to copy planes from!\n");
return;
return false;
}
copySector = line->frontsector;
}
@ -2205,8 +2373,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
INT32 destsec = Tag_Iterate_Sectors(line->args[0], 0);
if (destsec == -1)
{
CONS_Debug(DBG_GAMELOGIC, "Special type 400 Executor: No sector to copy planes from (tag %d)!\n", line->args[0]);
return;
CONS_Debug(DBG_GAMELOGIC, "Special type 400 Executor: No sector to copy planes from (tag %d)!\n", args[0]);
return false;
}
copySector = &sectors[destsec];
}
@ -2240,22 +2408,22 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
boolean newfloorlightabsolute, newceilinglightabsolute;
INT32 newfloorlightsec, newceilinglightsec;
if (line->args[0] == 0)
if (args[0] == 0)
{
if (line == NULL)
{
CONS_Debug(DBG_GAMELOGIC, "Special type 402 Executor: No frontsector to copy light level from!\n");
return;
return false;
}
copySector = line->frontsector;
}
else
{
INT32 destsec = Tag_Iterate_Sectors(line->args[0], 0);
INT32 destsec = Tag_Iterate_Sectors(args[0], 0);
if (destsec == -1)
{
CONS_Debug(DBG_GAMELOGIC, "Special type 402 Executor: No sector to copy light level from (tag %d)!\n", line->args[0]);
return;
CONS_Debug(DBG_GAMELOGIC, "Special type 402 Executor: No sector to copy light level from (tag %d)!\n", args[0]);
return false;
}
copySector = &sectors[destsec];
}
@ -2306,7 +2474,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
if (line == NULL)
{
CONS_Debug(DBG_GAMELOGIC, "Special type 403 Executor: No frontsector to copy planes from!\n");
return;
return false;
}
copySector = line->frontsector;
}
@ -2315,8 +2483,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
INT32 destsec = Tag_Iterate_Sectors(line->args[0], 0);
if (destsec == -1)
{
CONS_Debug(DBG_GAMELOGIC, "Special type 403 Executor: No sector to copy planes from (tag %d)!\n", line->args[0]);
return;
CONS_Debug(DBG_GAMELOGIC, "Special type 403 Executor: No sector to copy planes from (tag %d)!\n", args[0]);
return false;
}
copySector = &sectors[destsec];
}
@ -2371,31 +2539,31 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
{
sector_t *copySector = NULL;
if (line->args[0] == 0)
if (args[0] == 0)
{
if (line == NULL)
{
CONS_Debug(DBG_GAMELOGIC, "Special type 408 Executor: No frontsector to copy flats from!\n");
return;
return false;
}
copySector = line->frontsector;
}
else
{
INT32 destsec = Tag_Iterate_Sectors(line->args[0], 0);
INT32 destsec = Tag_Iterate_Sectors(args[0], 0);
if (destsec == -1)
{
CONS_Debug(DBG_GAMELOGIC, "Special type 408 Executor: No sector to copy flats from (tag %d)!\n", line->args[0]);
return;
CONS_Debug(DBG_GAMELOGIC, "Special type 408 Executor: No sector to copy flats from (tag %d)!\n", args[0]);
return false;
}
copySector = &sectors[destsec];
}
TAG_ITER_SECTORS(line->args[1], secnum)
TAG_ITER_SECTORS(args[1], secnum)
{
if (line->args[2] != TMP_CEILING)
if (args[2] != TMP_CEILING)
sectors[secnum].floorpic = copySector->floorpic;
if (line->args[2] != TMP_FLOOR)
if (args[2] != TMP_FLOOR)
sectors[secnum].ceilingpic = copySector->ceilingpic;
}
break;
@ -2435,7 +2603,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
if (line == NULL)
{
CONS_Debug(DBG_GAMELOGIC, "Special type 410 Executor: No linedef to change frontsector tag of!\n");
return;
return false;
}
editLine = line;
}
@ -2445,7 +2613,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
if (destline == -1)
{
CONS_Debug(DBG_GAMELOGIC, "Special type 408 Executor: No linedef to change frontsector tag of (tag %d)!\n", line->args[0]);
return;
return false;
}
editLine = &lines[destline];
}
@ -2453,7 +2621,30 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
newtag = line->args[1];
secnum = (UINT32)(editLine->frontsector - sectors);
switch (line->args[2])
if (args[0] == 0)
{
if (line == NULL)
{
CONS_Debug(DBG_GAMELOGIC, "Special type 410 Executor: No linedef to change frontsector tag of!\n");
return false;
}
editLine = line;
}
else
{
INT32 destline = Tag_Iterate_Sectors(args[0], 0);
if (destline == -1)
{
CONS_Debug(DBG_GAMELOGIC, "Special type 408 Executor: No linedef to change frontsector tag of (tag %d)!\n", args[0]);
return false;
}
editLine = &lines[destline];
}
newtag = args[1];
secnum = (UINT32)(editLine->frontsector - sectors);
switch (args[2])
{
case TMT_ADD:
Tag_SectorAdd(secnum, newtag);
@ -2502,7 +2693,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
mobj_t *dest;
if (!mo) // nothing to teleport
return;
return false;
if (line->args[1] & TMT_RELATIVE) // Relative silent teleport
{
@ -2542,14 +2733,14 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
dest = P_FindObjectTypeFromTag(MT_TELEPORTMAN, line->args[0]);
if (!dest)
return;
return false;
angle = (line->args[1] & TMT_KEEPANGLE) ? mo->angle : dest->angle;
silent = !!(line->args[1] & TMT_SILENT);
keepmomentum = !!(line->args[1] & TMT_KEEPMOMENTUM);
if (bot)
P_Teleport(bot, dest->x, dest->y, dest->z, angle, !silent, keepmomentum);
//if (bot)
//P_Teleport(bot, dest->x, dest->y, dest->z, angle, !silent, keepmomentum);
P_Teleport(mo, dest->x, dest->y, dest->z, angle, !silent, keepmomentum);
if (!silent)
S_StartSound(dest, sfx_mixup); // Play the 'bowrwoosh!' sound
@ -2691,11 +2882,11 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
INT32 aim;
if ((!mo || !mo->player) && !titlemapinaction) // only players have views, and title screens
return;
return false;
altview = P_FindObjectTypeFromTag(MT_ALTVIEWMAN, line->args[0]);
if (!altview || !altview->spawnpoint)
return;
return false;
// If titlemap, set the camera ref for title's thinker
// This is not revoked until overwritten; awayviewtics is ignored
@ -2745,7 +2936,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
case 426: // Moves the mobj to its sector's soundorg and on the floor, and stops it
if (!mo)
return;
return false;
if (line->args[0])
{
@ -2802,12 +2993,15 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
break;
case 433: // Flip/flop gravity. Works on pushables, too!
if (line->args[0])
if (!mo)
return false;
if (args[0])
mo->flags2 &= ~MF2_OBJECTFLIP;
else
mo->flags2 |= MF2_OBJECTFLIP;
if (bot)
bot->flags2 = (bot->flags2 & ~MF2_OBJECTFLIP) | (mo->flags2 & MF2_OBJECTFLIP);
//if (bot)
//bot->flags2 = (bot->flags2 & ~MF2_OBJECTFLIP) | (mo->flags2 & MF2_OBJECTFLIP);
break;
case 435: // Change scroller direction
@ -2849,8 +3043,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
if (!sec->ffloors)
{
CONS_Debug(DBG_GAMELOGIC, "Line type 436 Executor: Target sector #%d has no FOFs.\n", secnum);
return;
CONS_Debug(DBG_GAMELOGIC, "Special type 436: Target sector #%d has no FOFs.\n", secnum);
return false;
}
for (rover = sec->ffloors; rover; rover = rover->next)
@ -2865,8 +3059,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
if (!foundrover)
{
CONS_Debug(DBG_GAMELOGIC, "Line type 436 Executor: Can't find a FOF control sector with tag %d\n", foftag);
return;
CONS_Debug(DBG_GAMELOGIC, "Special type 436: Can't find a FOF control sector with tag %d\n", foftag);
return false;
}
}
}
@ -2900,28 +3094,28 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
side_t *set, *this;
boolean always;
if (line->args[0] == 0)
if (args[0] == 0)
{
if (line == NULL)
{
CONS_Debug(DBG_GAMELOGIC, "Special type 439 Executor: No activating line to copy textures from!\n");
return;
return false;
}
copyLine = line;
}
else
{
INT32 origline = Tag_Iterate_Lines(line->args[0], 0);
INT32 origline = Tag_Iterate_Lines(args[0], 0);
if (origline == -1)
{
CONS_Debug(DBG_GAMELOGIC, "Special type 439 Executor: No tagged line to copy textures from (tag %d)!\n", line->args[0]);
return;
CONS_Debug(DBG_GAMELOGIC, "Special type 439 Executor: No tagged line to copy textures from (tag %d)!\n", args[0]);
return false;
}
copyLine = &lines[origline];
}
set = &sides[copyLine->sidenum[0]];
always = !(line->args[3]); // If args[3] is set: Only change mid texture if mid texture already exists on tagged lines, etc.
always = !(args[3]); // If args[3] is set: Only change mid texture if mid texture already exists on tagged lines, etc.
for (linenum = 0; linenum < numlines; linenum++)
{
@ -3057,8 +3251,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
if (!sec->ffloors)
{
CONS_Debug(DBG_GAMELOGIC, "Line type 445 Executor: Target sector #%d has no FOFs.\n", secnum);
return;
CONS_Debug(DBG_GAMELOGIC, "Special type 445 Executor: Target sector #%d has no FOFs.\n", secnum);
return false;
}
for (rover = sec->ffloors; rover; rover = rover->next)
@ -3086,8 +3280,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
if (!foundrover)
{
CONS_Debug(DBG_GAMELOGIC, "Line type 445 Executor: Can't find a FOF control sector with tag %d\n", foftag);
return;
CONS_Debug(DBG_GAMELOGIC, "Special type 445 Executor: Can't find a FOF control sector with tag %d\n", foftag);
return false;
}
}
}
@ -3115,8 +3309,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
if (!sec->ffloors)
{
CONS_Debug(DBG_GAMELOGIC, "Line type 446 Executor: Target sector #%d has no FOFs.\n", secnum);
return;
CONS_Debug(DBG_GAMELOGIC, "Special type 446 Executor: Target sector #%d has no FOFs.\n", secnum);
return false;
}
for (rover = sec->ffloors; rover; rover = rover->next)
@ -3134,8 +3328,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
if (!foundrover)
{
CONS_Debug(DBG_GAMELOGIC, "Line type 446 Executor: Can't find a FOF control sector with tag %d\n", foftag);
return;
CONS_Debug(DBG_GAMELOGIC, "Special type 446 Executor: Can't find a FOF control sector with tag %d\n", foftag);
return false;
}
}
}
@ -3152,15 +3346,22 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
source = sides[line->sidenum[0]].colormap_data;
else
{
if (!line->args[1])
if (!args[1])
{
if (line == NULL)
{
CONS_Debug(DBG_GAMELOGIC, "Special type 447 Executor: Can't find frontsector with source colormap!\n");
return false;
}
source = line->frontsector->extra_colormap;
}
else
{
INT32 sourcesec = Tag_Iterate_Sectors(line->args[1], 0);
if (sourcesec == -1)
{
CONS_Debug(DBG_GAMELOGIC, "Line type 447 Executor: Can't find sector with source colormap (tag %d)!\n", line->args[1]);
return;
CONS_Debug(DBG_GAMELOGIC, "Special type 447 Executor: Can't find sector with source colormap (tag %d)!\n", args[1]);
return false;
}
source = sectors[sourcesec].extra_colormap;
}
@ -3313,7 +3514,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
if (!sec->ffloors)
{
CONS_Debug(DBG_GAMELOGIC, "Line type 452 Executor: Target sector #%d has no FOFs.\n", secnum);
return;
return false;
}
for (rover = sec->ffloors; rover; rover = rover->next)
@ -3350,8 +3551,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
if (!foundrover)
{
CONS_Debug(DBG_GAMELOGIC, "Line type 452 Executor: Can't find a FOF control sector with tag %d\n", foftag);
return;
CONS_Debug(DBG_GAMELOGIC, "Special type 452 Executor: Can't find a FOF control sector with tag %d\n", foftag);
return false;
}
}
break;
@ -3374,8 +3575,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
if (!sec->ffloors)
{
CONS_Debug(DBG_GAMELOGIC, "Line type 453 Executor: Target sector #%d has no FOFs.\n", secnum);
return;
CONS_Debug(DBG_GAMELOGIC, "Special type 453 Executor: Target sector #%d has no FOFs.\n", secnum);
return false;
}
for (rover = sec->ffloors; rover; rover = rover->next)
@ -3438,8 +3639,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
if (!foundrover)
{
CONS_Debug(DBG_GAMELOGIC, "Line type 453 Executor: Can't find a FOF control sector with tag %d\n", foftag);
return;
CONS_Debug(DBG_GAMELOGIC, "Special type 453 Executor: Can't find a FOF control sector with tag %d\n", foftag);
return false;
}
}
break;
@ -3459,8 +3660,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
if (!sec->ffloors)
{
CONS_Debug(DBG_GAMELOGIC, "Line type 454 Executor: Target sector #%d has no FOFs.\n", secnum);
return;
CONS_Debug(DBG_GAMELOGIC, "Special type 454 Executor: Target sector #%d has no FOFs.\n", secnum);
return false;
}
for (rover = sec->ffloors; rover; rover = rover->next)
@ -3476,8 +3677,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
if (!foundrover)
{
CONS_Debug(DBG_GAMELOGIC, "Line type 454 Executor: Can't find a FOF control sector with tag %d\n", foftag);
return;
CONS_Debug(DBG_GAMELOGIC, "Special type 454 Executor: Can't find a FOF control sector with tag %d\n", foftag);
return false;
}
}
break;
@ -3490,15 +3691,22 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
dest = sides[line->sidenum[0]].colormap_data;
else
{
if (!line->args[1])
if (!args[1])
{
if (line == NULL)
{
CONS_Debug(DBG_GAMELOGIC, "Special type 455 Executor: Can't find frontsector with destination colormap!\n");
return false;
}
dest = line->frontsector->extra_colormap;
}
else
{
INT32 destsec = Tag_Iterate_Sectors(line->args[1], 0);
if (destsec == -1)
{
CONS_Debug(DBG_GAMELOGIC, "Line type 455 Executor: Can't find sector with destination colormap (tag %d)!\n", line->args[1]);
return;
CONS_Debug(DBG_GAMELOGIC, "Special type 455 Executor: Can't find sector with destination colormap (tag %d)!\n", args[1]);
return false;
}
dest = sectors[destsec].extra_colormap;
}
@ -3599,7 +3807,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
anchormo = P_FindObjectTypeFromTag(MT_ANGLEMAN, line->args[0]);
if (!anchormo)
return;
return false;
mo->eflags |= MFE_TRACERANGLE;
P_SetTarget(&mo->tracer, anchormo);
@ -3656,11 +3864,15 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
&& (delay <= 0 || !(leveltime % delay)) // Timing
)
{
if (rings > 0)
// Don't award rings while SPB is targetting you
if (mo->player->pflags & PF_RINGLOCK)
return false;
if (delay <= 0 || !(leveltime % delay))
{
// Don't award rings while SPB is targetting you
if (mo->player->pflags & PF_RINGLOCK)
return;
return false;
// args[2]: don't cap rings to 20
K_AwardPlayerRings(mo->player, rings, line->args[2]);
@ -3669,7 +3881,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
{
// Don't push you below baseline
if (mo->player->rings < 0)
return;
return false;
mo->player->rings--;
S_StartSound(mo, sfx_antiri);
@ -3731,7 +3943,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
INT32 color = line->stringargs[0] ? get_number(line->stringargs[0]) : SKINCOLOR_NONE;
if (color < 0 || color >= numskincolors)
return;
return false;
var1 = 0;
var2 = color;
@ -3952,9 +4164,54 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
}
break;
case 2001: // Finish Line
{
if (mo->player == NULL)
{
return false;
}
if ((gametyperules & GTR_CIRCUIT) && (mo->player->exiting == 0) && !(mo->player->pflags & PF_HITFINISHLINE))
{
if (((line->args[0] & TMCFF_FLIP) && (side == 0))
|| (!(line->args[0] & TMCFF_FLIP) && (side == 1))) // crossed from behind to infront
{
K_HandleLapIncrement(mo->player);
}
else
{
K_HandleLapDecrement(mo->player);
}
mo->player->pflags |= PF_HITFINISHLINE;
}
}
break;
case 2003: // Respawn Line
{
if (mo->player == NULL)
{
return false;
}
/* No Climb: only trigger from front side */
if
(
!mo->player->respawn &&
(!(line->args[0] & TMCRF_FRONTONLY) || side == 0)
)
{
P_DamageMobj(mo, NULL, NULL, 1, DMG_DEATHPIT);
}
}
break;
default:
break;
}
return true;
}
//

View file

@ -559,7 +559,24 @@ fixed_t P_FindHighestCeilingSurrounding(sector_t *sec);
INT32 P_FindMinSurroundingLight(sector_t *sector, INT32 max);
void P_CrossSpecialLine(line_t *ld, INT32 side, mobj_t *thing);
void P_CrossSpecialLine(line_t *line, INT32 side, mobj_t *thing);
void P_PushSpecialLine(line_t *line, mobj_t *thing);
//
// Special activation info
//
typedef struct
{
mobj_t *mo;
line_t *line;
UINT8 side;
sector_t *sector;
polyobj_t *po;
boolean fromLineSpecial; // Backwards compat for ACS
} activator_t;
boolean P_CanActivateSpecial(INT16 special);
boolean P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char **stringargs);
void P_SetupSignExit(player_t *player);

View file

@ -530,6 +530,7 @@ typedef struct line_s
// Animation related.
UINT32 flags;
UINT32 activation;
INT16 special;
taglist_t tags;
INT32 args[NUMLINEARGS];