diff --git a/extras/conf/udb/Includes/RingRacers_misc.cfg b/extras/conf/udb/Includes/RingRacers_misc.cfg deleted file mode 100644 index 95e782a8e..000000000 --- a/extras/conf/udb/Includes/RingRacers_misc.cfg +++ /dev/null @@ -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"; - } -} diff --git a/src/doomdata.h b/src/doomdata.h index 597c84dd4..268fce1ac 100644 --- a/src/doomdata.h +++ b/src/doomdata.h @@ -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. diff --git a/src/lua_maplib.c b/src/lua_maplib.c index df69334ff..75252f2f4 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -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; diff --git a/src/p_map.c b/src/p_map.c index d4f4c40aa..c8715f820 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -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; diff --git a/src/p_mobj.c b/src/p_mobj.c index 8dfa5f4b8..9a1a3888a 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -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 diff --git a/src/p_mobj.h b/src/p_mobj.h index eda76132a..a60675226 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -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); diff --git a/src/p_saveg.c b/src/p_saveg.c index 6eb7a5cf3..543773120 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -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); } } diff --git a/src/p_setup.c b/src/p_setup.c index b21f9b4b8..c4690d95c 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -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; diff --git a/src/p_spec.c b/src/p_spec.c index eb4266993..14b8df6ff 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -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 = §ors[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 = §ors[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 = §ors[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 = §ors[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; } // diff --git a/src/p_spec.h b/src/p_spec.h index 771c6df8f..9bbdd4acd 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -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); diff --git a/src/r_defs.h b/src/r_defs.h index 03a7617ea..38f0e7ed6 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -530,6 +530,7 @@ typedef struct line_s // Animation related. UINT32 flags; + UINT32 activation; INT16 special; taglist_t tags; INT32 args[NUMLINEARGS];