mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Add Hexen line activation flags
- Lines can be set to activate when crossing or bumping into them, with distinctions for players, enemies, and missiles+items.
- A new flag has been added to determine if a line special can activate more than once.
- Finish Line + Respawn Line are now handled like other specials. This means that:
- They follow the new line activation rules (so you can potentially have a finish line that you have to bump instead of cross)
- More importantly, they can be called as functions in ACS. (Player_FinishLine and Player_Respawn)
- Fixed linedef flags not being saved in save games.
This commit is contained in:
parent
b93ffbef2f
commit
c27139dbcb
13 changed files with 477 additions and 205 deletions
|
|
@ -25,7 +25,7 @@ terminator = ";";
|
|||
extrawordchars = "#"; // Extra characters to be treated as a part of a word by the Script Editor
|
||||
//keywordhelp = "http://www.zdoom.org/wiki/index.php?title=%K";
|
||||
snippetsdir = "acs";
|
||||
scripttype = 1; //0 = unknown script, 1 = acc, 2 = modeldef, 3 = decorate
|
||||
scripttype = "ACS";
|
||||
|
||||
keywords
|
||||
{
|
||||
|
|
@ -71,78 +71,6 @@ keywords
|
|||
Ends a collaspable text region. See also: #region\n
|
||||
Ignored by the compiler.";
|
||||
|
||||
// Keywords
|
||||
if = "if (<expression>)";
|
||||
else = "else";
|
||||
for = "for (<initialize>; <condition>; <iterate>)";
|
||||
do = "do";
|
||||
while = "while (<expression>)";
|
||||
until = "until (<expression>)";
|
||||
break = "break";
|
||||
continue = "continue";
|
||||
switch = "switch (<expression>)";
|
||||
case = "case <expression>:";
|
||||
default = "default:";
|
||||
const = "const";
|
||||
function = "function <return> <identifier> ([arg], [...])";
|
||||
script = "script <identifier> ([arg], [...])";
|
||||
|
||||
return = "return <value>\n
|
||||
Return value for functions.\n
|
||||
Does not work in scripts.";
|
||||
|
||||
restart = "restart\n
|
||||
Restarts the current script from the beginning.\n
|
||||
Does not work in functions.";
|
||||
|
||||
suspend = "suspend\n
|
||||
Pauses the current script. It can be resumed by\n
|
||||
activating the same script again.\n
|
||||
Does not work in functions.";
|
||||
|
||||
terminate = "terminate\n
|
||||
Ends the current script early.\n
|
||||
Does not work in functions.";
|
||||
|
||||
special = "special <expressions>\n
|
||||
Defines special actions for the ACS compiler.\n
|
||||
Serves little to no purpose for level scripts.";
|
||||
|
||||
world = "world <type> <index>:<identifier>\n
|
||||
Sets a wrapper for a hub scope variable.\n
|
||||
Unimplemented in Ring Racers.";
|
||||
|
||||
global = "global <type> <index>:<identifier>\n
|
||||
Sets a wrapper for a global scope variable.\n
|
||||
Unimplemented in Ring Racers.";
|
||||
|
||||
// Types
|
||||
void = "void";
|
||||
bool = "bool";
|
||||
int = "int";
|
||||
str = "str";
|
||||
fixed = "fixed";
|
||||
|
||||
// Script modifiers
|
||||
OPEN = "script <identifier> OPEN\n
|
||||
Makes a script automatically run when the level is initially loaded.";
|
||||
|
||||
ENTER = "script <identifier> ENTER\n
|
||||
Makes a script automatically run when a player enters the game.\n
|
||||
The activator is set to said player for this script.";
|
||||
|
||||
RESPAWN = "script <identifier> RESPAWN\n
|
||||
Makes a script automatically run when a player respawns.\n
|
||||
The activator is set to said player for this script.";
|
||||
|
||||
DEATH = "script <identifier> DEATH\n
|
||||
Makes a script automatically run when a player dies.\n
|
||||
The activator is set to said player for this script.";
|
||||
|
||||
LAP = "script <identifier> LAP\n
|
||||
Makes a script automatically run whenever a player crosses the finish line.\n
|
||||
The activator is set to said player for this script.";
|
||||
|
||||
// Specials
|
||||
Sector_CopyHeights = "void Sector_CopyHeights(int tag1, int tag2, int plane, [bool texture])\n
|
||||
Sets the plane heights of the tagged sectors to match another sector.\n
|
||||
|
|
@ -666,6 +594,17 @@ keywords
|
|||
- tag: The sector tag to search for waypoints in.\n
|
||||
- enable: If true, enable the waypoints. Otherwise, disable the waypoints.";
|
||||
|
||||
Player_FinishLine = "void Player_FinishLine([bool flip])\n
|
||||
Makes the activating player gain or lose a lap, depending on the activating side.\n
|
||||
Runs the LAP script type when incrementing.\n
|
||||
- flip: Flip which side of the activating line is used to increment laps.\n
|
||||
If there was no activating line, then this will increment when false, and decrement when true.";
|
||||
|
||||
Player_Respawn = "void Player_Respawn([bool frontonly])\n
|
||||
Makes the activating player respawn.\n
|
||||
- frontonly: If true, then only respawn when crossing the front side.\n
|
||||
Has no effect if this was not activated from a line.";
|
||||
|
||||
// Functions
|
||||
Delay = "void Delay(int tics)\n
|
||||
Pauses the current script.\n
|
||||
|
|
@ -836,6 +775,46 @@ keywords
|
|||
For logging to only the activator, use Log.";
|
||||
}
|
||||
|
||||
properties
|
||||
{
|
||||
// Keywords
|
||||
if;
|
||||
else;
|
||||
for;
|
||||
do;
|
||||
while;
|
||||
until;
|
||||
break;
|
||||
continue;
|
||||
switch;
|
||||
case;
|
||||
default;
|
||||
const;
|
||||
function;
|
||||
script;
|
||||
return;
|
||||
restart;
|
||||
suspend;
|
||||
terminate;
|
||||
world;
|
||||
global;
|
||||
special;
|
||||
|
||||
// Types
|
||||
void;
|
||||
bool;
|
||||
int;
|
||||
str;
|
||||
fixed;
|
||||
|
||||
// Script modifiers
|
||||
OPEN;
|
||||
ENTER;
|
||||
RESPAWN;
|
||||
DEATH;
|
||||
LAP;
|
||||
}
|
||||
|
||||
constants
|
||||
{
|
||||
TRUE;
|
||||
|
|
|
|||
|
|
@ -63,6 +63,31 @@ linedefflags_udmf
|
|||
transfer = "FOF Transfer";
|
||||
}
|
||||
|
||||
linedefactivations
|
||||
{
|
||||
1 = "When player crosses";
|
||||
2 = "When enemy crosses";
|
||||
4 = "When projectile crosses";
|
||||
8 = "When player bumps";
|
||||
16 = "When enemy bumps";
|
||||
32 = "On projectile impact";
|
||||
}
|
||||
|
||||
linedefactivations_udmf
|
||||
{
|
||||
repeatspecial
|
||||
{
|
||||
name = "Repeatable action";
|
||||
istrigger = false;
|
||||
}
|
||||
playercross = "When player crosses";
|
||||
playerpush = "When player bumps";
|
||||
monstercross = "When enemy crosses";
|
||||
monsterpush = "When enemy bumps";
|
||||
missilecross = "When projectile crosses";
|
||||
impact = "On projectile impact";
|
||||
}
|
||||
|
||||
linedefrenderstyles
|
||||
{
|
||||
translucent = "Translucent";
|
||||
|
|
|
|||
|
|
@ -152,6 +152,9 @@ special
|
|||
|
||||
int 499:Sector_ToggleWaypoints(2),
|
||||
|
||||
int 2001:Player_FinishLine(0, 1),
|
||||
int 2003:Player_RespawnLine(0, 1),
|
||||
|
||||
// Internal functions have negative values
|
||||
// [type] [ID]:[function name]([required args], [type of each arg, including optional ones])
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -149,6 +149,30 @@ enum
|
|||
|
||||
// Transfers FOF properties.
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
@ -950,6 +952,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;
|
||||
|
|
|
|||
17
src/p_map.c
17
src/p_map.c
|
|
@ -249,20 +249,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;
|
||||
|
|
|
|||
19
src/p_mobj.c
19
src/p_mobj.c
|
|
@ -1618,6 +1618,8 @@ void P_XYMovement(mobj_t *mo)
|
|||
else if (P_MobjWasRemoved(mo))
|
||||
return;
|
||||
|
||||
P_PushSpecialLine(tm.blockingline, mo);
|
||||
|
||||
if (mo->flags & MF_MISSILE)
|
||||
{
|
||||
// explode a missile
|
||||
|
|
@ -5215,6 +5217,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
|
||||
|
|
|
|||
|
|
@ -506,6 +506,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);
|
||||
|
|
|
|||
|
|
@ -1147,6 +1147,10 @@ static void P_NetUnArchiveTubeWaypoints(savebuffer_t *save)
|
|||
#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)
|
||||
{
|
||||
|
|
@ -1540,11 +1544,14 @@ static void ArchiveLines(savebuffer_t *save)
|
|||
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;
|
||||
|
|
@ -1561,6 +1568,9 @@ static void ArchiveLines(savebuffer_t *save)
|
|||
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]];
|
||||
|
|
@ -1589,6 +1599,9 @@ static void ArchiveLines(savebuffer_t *save)
|
|||
diff2 |= LD_S2MIDTEX;
|
||||
}
|
||||
|
||||
if (diff3)
|
||||
diff2 |= LD_DIFF3;
|
||||
|
||||
if (diff2)
|
||||
diff |= LD_DIFF2;
|
||||
|
||||
|
|
@ -1598,6 +1611,8 @@ static void ArchiveLines(savebuffer_t *save)
|
|||
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)
|
||||
|
|
@ -1651,6 +1666,8 @@ static void ArchiveLines(savebuffer_t *save)
|
|||
}
|
||||
if (diff2 & LD_EXECUTORDELAY)
|
||||
WRITEINT32(save->p, li->executordelay);
|
||||
if (diff3 & LD_ACTIVATION)
|
||||
WRITEUINT32(save->p, li->activation);
|
||||
}
|
||||
}
|
||||
WRITEUINT16(save->p, 0xffff);
|
||||
|
|
@ -1661,7 +1678,7 @@ static void UnArchiveLines(savebuffer_t *save)
|
|||
UINT16 i;
|
||||
line_t *li;
|
||||
side_t *si;
|
||||
UINT8 diff, diff2; // no diff3
|
||||
UINT8 diff, diff2, diff3;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
|
|
@ -1680,6 +1697,11 @@ static void UnArchiveLines(savebuffer_t *save)
|
|||
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)
|
||||
|
|
@ -1735,6 +1757,8 @@ static void UnArchiveLines(savebuffer_t *save)
|
|||
}
|
||||
if (diff2 & LD_EXECUTORDELAY)
|
||||
li->executordelay = READINT32(save->p);
|
||||
if (diff3 & LD_ACTIVATION)
|
||||
li->activation = READUINT32(save->p);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1646,6 +1646,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)
|
||||
|
|
@ -5814,10 +5829,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;
|
||||
|
|
|
|||
371
src/p_spec.c
371
src/p_spec.c
|
|
@ -1376,9 +1376,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)
|
||||
|
|
@ -2073,68 +2090,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)
|
||||
{
|
||||
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);
|
||||
|
||||
ACS_RunLapScript(thing, line);
|
||||
}
|
||||
else
|
||||
{
|
||||
K_HandleLapDecrement(player);
|
||||
}
|
||||
|
||||
player->pflags |= PF_HITFINISHLINE;
|
||||
if (P_AllowSpecialCross(line, thing) == false)
|
||||
{
|
||||
// This special can't be activated this way.
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 2003: // Respawn Line
|
||||
{
|
||||
/* No Climb: only trigger from front side */
|
||||
if
|
||||
(
|
||||
player->respawn.state == RESPAWNST_NONE &&
|
||||
(!(line->args[0] & TMCRF_FRONTONLY) || side == 0)
|
||||
)
|
||||
{
|
||||
P_DamageMobj(player->mo, NULL, NULL, 1, DMG_DEATHPIT);
|
||||
}
|
||||
}
|
||||
break;
|
||||
activator = Z_Calloc(sizeof(activator_t), PU_LEVEL, NULL);
|
||||
I_Assert(activator != NULL);
|
||||
|
||||
default:
|
||||
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)
|
||||
{
|
||||
// Do nothing
|
||||
P_LineSpecialWasActivated(line);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2221,6 +2353,9 @@ static mobj_t* P_FindObjectTypeFromTag(mobjtype_t type, mtag_t tag)
|
|||
*/
|
||||
static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
|
||||
{
|
||||
// This is an old function purely for linedef executor
|
||||
// backwards compatibility.
|
||||
|
||||
activator_t *activator = NULL;
|
||||
|
||||
if (line == NULL)
|
||||
|
|
@ -2239,26 +2374,23 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
|
|||
|
||||
P_ProcessSpecial(activator, line->special, line->args, line->stringargs);
|
||||
Z_Free(activator);
|
||||
|
||||
// Intentionally no P_LineSpecialWasActivated call.
|
||||
}
|
||||
|
||||
void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char **stringargs)
|
||||
boolean P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char **stringargs)
|
||||
{
|
||||
line_t *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.
|
||||
mobj_t *mo = activator->mo;
|
||||
sector_t *callsec = activator->sector;
|
||||
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.
|
||||
const boolean backwardsCompat = (!udmf && activator->fromLineSpecial && line != NULL);
|
||||
boolean const backwardsCompat = (!udmf && activator->fromLineSpecial && line != NULL);
|
||||
|
||||
INT32 secnum = -1;
|
||||
|
||||
//
|
||||
// TODO: Too many specials are tied to a linedef existing,
|
||||
// even after UDMF cleanups. We'll need to remove all of the
|
||||
// (line == NULL) guards if we want these to be useful for ACS.
|
||||
//
|
||||
|
||||
// note: only commands with linedef types >= 400 && < 500 can be used
|
||||
// note: only specials that P_CanActivateSpecial returns true on can be used
|
||||
switch (special)
|
||||
{
|
||||
case 400: // Copy tagged sector's heights/flats
|
||||
|
|
@ -2270,7 +2402,7 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
if (line == NULL)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Special type 400 Executor: No frontsector to copy planes from!\n");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
copySector = line->frontsector;
|
||||
}
|
||||
|
|
@ -2280,7 +2412,7 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
if (destsec == -1)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Special type 400 Executor: No sector to copy planes from (tag %d)!\n", args[0]);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
copySector = §ors[destsec];
|
||||
}
|
||||
|
|
@ -2319,7 +2451,7 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
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;
|
||||
}
|
||||
|
|
@ -2329,7 +2461,7 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
if (destsec == -1)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Special type 402 Executor: No sector to copy light level from (tag %d)!\n", args[0]);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
copySector = §ors[destsec];
|
||||
}
|
||||
|
|
@ -2380,7 +2512,7 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
if (line == NULL)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Special type 403 Executor: No frontsector to copy planes from!\n");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
copySector = line->frontsector;
|
||||
}
|
||||
|
|
@ -2390,7 +2522,7 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
if (destsec == -1)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Special type 403 Executor: No sector to copy planes from (tag %d)!\n", args[0]);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
copySector = §ors[destsec];
|
||||
}
|
||||
|
|
@ -2450,7 +2582,7 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
if (line == NULL)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Special type 408 Executor: No frontsector to copy flats from!\n");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
copySector = line->frontsector;
|
||||
}
|
||||
|
|
@ -2460,7 +2592,7 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
if (destsec == -1)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Special type 408 Executor: No sector to copy flats from (tag %d)!\n", args[0]);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
copySector = §ors[destsec];
|
||||
}
|
||||
|
|
@ -2509,7 +2641,7 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
if (line == NULL)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Special type 410 Executor: No linedef to change frontsector tag of!\n");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
editLine = line;
|
||||
}
|
||||
|
|
@ -2519,7 +2651,7 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
if (destline == -1)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Special type 408 Executor: No linedef to change frontsector tag of (tag %d)!\n", args[0]);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
editLine = &lines[destline];
|
||||
}
|
||||
|
|
@ -2576,7 +2708,7 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
mobj_t *dest;
|
||||
|
||||
if (!mo) // nothing to teleport
|
||||
return;
|
||||
return false;
|
||||
|
||||
if (args[1] & TMT_RELATIVE) // Relative silent teleport
|
||||
{
|
||||
|
|
@ -2617,7 +2749,7 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
|
||||
dest = P_FindObjectTypeFromTag(MT_TELEPORTMAN, args[0]);
|
||||
if (!dest)
|
||||
return;
|
||||
return false;
|
||||
|
||||
angle = (args[1] & TMT_KEEPANGLE) ? mo->angle : dest->angle;
|
||||
silent = !!(args[1] & TMT_SILENT);
|
||||
|
|
@ -2764,11 +2896,11 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
INT32 aim;
|
||||
|
||||
if ((!mo || !mo->player) && !titlemapinaction) // only players have views, and title screens
|
||||
return;
|
||||
return false;
|
||||
|
||||
altview = P_FindObjectTypeFromTag(MT_ALTVIEWMAN, 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
|
||||
|
|
@ -2818,7 +2950,7 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
|
||||
case 426: // Moves the mobj to its sector's soundorg and on the floor, and stops it
|
||||
if (!mo)
|
||||
return;
|
||||
return false;
|
||||
|
||||
if (args[0])
|
||||
{
|
||||
|
|
@ -2882,7 +3014,7 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
|
||||
case 433: // Flip/flop gravity. Works on pushables, too!
|
||||
if (!mo)
|
||||
return;
|
||||
return false;
|
||||
|
||||
if (args[0])
|
||||
mo->flags2 &= ~MF2_OBJECTFLIP;
|
||||
|
|
@ -2935,7 +3067,7 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
if (!sec->ffloors)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Special type 436: Target sector #%d has no FOFs.\n", secnum);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (rover = sec->ffloors; rover; rover = rover->next)
|
||||
|
|
@ -2951,7 +3083,7 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
if (!foundrover)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Special type 436: Can't find a FOF control sector with tag %d\n", foftag);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2988,7 +3120,7 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
if (line == NULL)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Special type 439 Executor: No activating line to copy textures from!\n");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
copyLine = line;
|
||||
}
|
||||
|
|
@ -2998,7 +3130,7 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
if (origline == -1)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Special type 439 Executor: No tagged line to copy textures from (tag %d)!\n", args[0]);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
copyLine = &lines[origline];
|
||||
}
|
||||
|
|
@ -3149,7 +3281,7 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
if (!sec->ffloors)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Special type 445 Executor: Target sector #%d has no FOFs.\n", secnum);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (rover = sec->ffloors; rover; rover = rover->next)
|
||||
|
|
@ -3178,7 +3310,7 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
if (!foundrover)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Special type 445 Executor: Can't find a FOF control sector with tag %d\n", foftag);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3207,7 +3339,7 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
if (!sec->ffloors)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Special type 446 Executor: Target sector #%d has no FOFs.\n", secnum);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (rover = sec->ffloors; rover; rover = rover->next)
|
||||
|
|
@ -3226,7 +3358,7 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
if (!foundrover)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Special type 446 Executor: Can't find a FOF control sector with tag %d\n", foftag);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3251,7 +3383,7 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
if (line == NULL)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Special type 447 Executor: Can't find frontsector with source colormap!\n");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
source = line->frontsector->extra_colormap;
|
||||
}
|
||||
|
|
@ -3261,7 +3393,7 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
if (sourcesec == -1)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Special type 447 Executor: Can't find sector with source colormap (tag %d)!\n", args[1]);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
source = sectors[sourcesec].extra_colormap;
|
||||
}
|
||||
|
|
@ -3416,7 +3548,7 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
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)
|
||||
|
|
@ -3454,7 +3586,7 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
if (!foundrover)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Special type 452 Executor: Can't find a FOF control sector with tag %d\n", foftag);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -3478,7 +3610,7 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
if (!sec->ffloors)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Special type 453 Executor: Target sector #%d has no FOFs.\n", secnum);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (rover = sec->ffloors; rover; rover = rover->next)
|
||||
|
|
@ -3542,7 +3674,7 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
if (!foundrover)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Special type 453 Executor: Can't find a FOF control sector with tag %d\n", foftag);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -3563,7 +3695,7 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
if (!sec->ffloors)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Special type 454 Executor: Target sector #%d has no FOFs.\n", secnum);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (rover = sec->ffloors; rover; rover = rover->next)
|
||||
|
|
@ -3580,7 +3712,7 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
if (!foundrover)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Special type 454 Executor: Can't find a FOF control sector with tag %d\n", foftag);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -3601,7 +3733,7 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
if (line == NULL)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Special type 455 Executor: Can't find frontsector with destination colormap!\n");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
dest = line->frontsector->extra_colormap;
|
||||
}
|
||||
|
|
@ -3611,7 +3743,7 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
if (destsec == -1)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Special type 455 Executor: Can't find sector with destination colormap (tag %d)!\n", args[1]);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
dest = sectors[destsec].extra_colormap;
|
||||
}
|
||||
|
|
@ -3718,7 +3850,7 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
|
||||
anchormo = P_FindObjectTypeFromTag(MT_ANGLEMAN, args[0]);
|
||||
if (!anchormo)
|
||||
return;
|
||||
return false;
|
||||
|
||||
mo->eflags |= MFE_TRACERANGLE;
|
||||
P_SetTarget(&mo->tracer, anchormo);
|
||||
|
|
@ -3773,7 +3905,7 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
{
|
||||
// Don't award rings while SPB is targetting you
|
||||
if (mo->player->pflags & PF_RINGLOCK)
|
||||
return;
|
||||
return false;
|
||||
|
||||
if (delay <= 0 || !(leveltime % delay))
|
||||
{
|
||||
|
|
@ -3837,7 +3969,7 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
INT32 color = stringargs[0] ? get_number(stringargs[0]) : SKINCOLOR_NONE;
|
||||
|
||||
if (color < 0 || color >= numskincolors)
|
||||
return;
|
||||
return false;
|
||||
|
||||
var1 = 0;
|
||||
var2 = color;
|
||||
|
|
@ -4005,7 +4137,7 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
if (!stringargs[0])
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Linedef type 475: No script name given\n");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
ACS_Execute(stringargs[0], args, NUMLINEARGS, activator);
|
||||
|
|
@ -4014,7 +4146,7 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
if (!stringargs[0])
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Linedef type 476: No script name given\n");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
ACS_ExecuteAlways(stringargs[0], args, NUMLINEARGS, activator);
|
||||
|
|
@ -4023,7 +4155,7 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
if (!stringargs[0])
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Linedef type 477: No script name given\n");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
ACS_Suspend(stringargs[0]);
|
||||
|
|
@ -4032,7 +4164,7 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
if (!stringargs[0])
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Linedef type 478: No script name given\n");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
ACS_Terminate(stringargs[0]);
|
||||
|
|
@ -4097,9 +4229,56 @@ void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char *
|
|||
}
|
||||
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);
|
||||
|
||||
ACS_RunLapScript(mo, line);
|
||||
}
|
||||
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.state == RESPAWNST_NONE &&
|
||||
(!(line->args[0] & TMCRF_FRONTONLY) || side == 0)
|
||||
)
|
||||
{
|
||||
P_DamageMobj(mo, NULL, NULL, 1, DMG_DEATHPIT);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void P_SetupSignObject(mobj_t *sign, mobj_t *pmo, boolean error)
|
||||
|
|
|
|||
|
|
@ -557,7 +557,8 @@ 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
|
||||
|
|
@ -572,7 +573,8 @@ struct activator_t
|
|||
boolean fromLineSpecial; // Backwards compat for ACS
|
||||
};
|
||||
|
||||
void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char **stringargs);
|
||||
boolean P_CanActivateSpecial(INT16 special);
|
||||
boolean P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char **stringargs);
|
||||
|
||||
void P_SetupSignExit(player_t *player);
|
||||
|
||||
|
|
|
|||
|
|
@ -525,6 +525,7 @@ struct line_t
|
|||
|
||||
// Animation related.
|
||||
UINT32 flags;
|
||||
UINT32 activation;
|
||||
INT16 special;
|
||||
taglist_t tags;
|
||||
INT32 args[NUMLINEARGS];
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue