This commit is contained in:
Christoph Oelckers 2016-01-01 13:40:24 +01:00
commit bb355b3a78
3 changed files with 179 additions and 48 deletions

View file

@ -2224,6 +2224,154 @@ bool AM_Check3DFloors(line_t *line)
return false; return false;
} }
// [TP] Check whether a sector can trigger a special that satisfies the provided function.
// If found, specialptr and argsptr will be filled by the special and the arguments
// If needUseActivated is true, the special must be activated by use.
bool AM_checkSectorActions (sector_t *sector, bool (*function)(int, int *), int *specialptr, int **argsptr, bool needUseActivated)
{
for (ASectorAction* action = sector->SecActTarget; action; action = barrier_cast<ASectorAction *>(action->tracer))
{
if ((action->IsActivatedByUse() || false == needUseActivated)
&& (*function)(action->special, action->args)
&& action->CanTrigger (players[consoleplayer].mo))
{
*specialptr = action->special;
*argsptr = action->args;
return true;
}
}
return false;
}
// [TP] Check whether there's a boundary on the provided line for a special that satisfies the provided function.
// It's a boundary if the line can activate the special or the line's bordering sectors can activate it.
// If found, specialptr and argsptr will be filled with special and args if given.
bool AM_checkSpecialBoundary (line_t &line, bool (*function)(int, int *), int *specialptr = NULL, int **argsptr = NULL)
{
if (specialptr == NULL)
{
static int sink;
specialptr = &sink;
}
if (argsptr == NULL)
{
static int *sink;
argsptr = &sink;
}
// Check if the line special qualifies for this
if ((line.activation & SPAC_PlayerActivate) && (*function)(line.special, line.args))
{
*specialptr = line.special;
*argsptr = line.args;
return true;
}
// Check sector actions in the line's front sector -- the action has to be use-activated in order to
// show up if this is a one-sided line, because the player cannot trigger sector actions by crossing
// a one-sided line (since that's impossible, duh).
if (AM_checkSectorActions(line.frontsector, function, specialptr, argsptr, line.backsector == NULL))
return true;
// If it has a back sector, check sector actions in that.
return (line.backsector && AM_checkSectorActions(line.backsector, function, specialptr, argsptr, false));
}
bool AM_isTeleportSpecial (int special, int *)
{
return (special == Teleport ||
special == Teleport_NoFog ||
special == Teleport_ZombieChanger ||
special == Teleport_Line);
}
bool AM_isTeleportBoundary (line_t &line)
{
return AM_checkSpecialBoundary(line, &AM_isTeleportSpecial);
}
bool AM_isExitSpecial (int special, int *)
{
return (special == Teleport_NewMap ||
special == Teleport_EndGame ||
special == Exit_Normal ||
special == Exit_Secret);
}
bool AM_isExitBoundary (line_t& line)
{
return AM_checkSpecialBoundary(line, &AM_isExitSpecial);
}
bool AM_isTriggerSpecial (int special, int *)
{
return LineSpecialsInfo[special] != NULL
&& LineSpecialsInfo[special]->max_args >= 0
&& special != Door_Open
&& special != Door_Close
&& special != Door_CloseWaitOpen
&& special != Door_Raise
&& special != Door_Animated
&& special != Generic_Door;
}
bool AM_isTriggerBoundary (line_t &line)
{
return AM_checkSpecialBoundary(line, &AM_isTriggerSpecial);
}
bool AM_isLockSpecial (int special, int* args)
{
return special == Door_LockedRaise
|| special == ACS_LockedExecute
|| special == ACS_LockedExecuteDoor
|| (special == Door_Animated && args[3] != 0)
|| (special == Generic_Door && args[4] != 0)
|| (special == FS_Execute && args[2] != 0);
}
bool AM_isLockBoundary (line_t &line, int *lockptr = NULL)
{
if (lockptr == NULL)
{
static int sink;
lockptr = &sink;
}
if (line.locknumber)
{
*lockptr = line.locknumber;
return true;
}
int special;
int *args;
bool result = AM_checkSpecialBoundary(line, &AM_isLockSpecial, &special, &args);
if (result)
{
switch (special)
{
case FS_Execute:
*lockptr = args[2];
break;
case Door_Animated:
case Door_LockedRaise:
*lockptr = args[3];
break;
default:
*lockptr = args[4];
break;
}
}
return result;
}
//============================================================================= //=============================================================================
// //
// Determines visible lines, draws them. // Determines visible lines, draws them.
@ -2272,48 +2420,18 @@ void AM_drawWalls (bool allmap)
else else
AM_drawMline(&l, AMColors.WallColor); AM_drawMline(&l, AMColors.WallColor);
} }
else if (lines[i].locknumber > 0 && AMColors.displayLocks) else if (AM_isTeleportBoundary(lines[i]) && AMColors.isValid(AMColors.IntraTeleportColor))
{ // [Dusk] specials w/ locknumbers
lock = lines[i].locknumber;
color = P_GetMapColorForLock(lock);
AMColor c;
if (color >= 0) c.FromRGB(RPART(color), GPART(color), BPART(color));
else c = AMColors[AMColors.LockedColor];
AM_drawMline (&l, c);
}
else if ((lines[i].special == Teleport ||
lines[i].special == Teleport_NoFog ||
lines[i].special == Teleport_ZombieChanger ||
lines[i].special == Teleport_Line) &&
(lines[i].activation & SPAC_PlayerActivate) &&
AMColors.isValid(AMColors.IntraTeleportColor))
{ // intra-level teleporters { // intra-level teleporters
AM_drawMline(&l, AMColors.IntraTeleportColor); AM_drawMline(&l, AMColors.IntraTeleportColor);
} }
else if ((lines[i].special == Teleport_NewMap || else if (AM_isExitBoundary(lines[i]) && AMColors.isValid(AMColors.InterTeleportColor))
lines[i].special == Teleport_EndGame ||
lines[i].special == Exit_Normal ||
lines[i].special == Exit_Secret) &&
AMColors.isValid(AMColors.InterTeleportColor))
{ // inter-level/game-ending teleporters { // inter-level/game-ending teleporters
AM_drawMline(&l, AMColors.InterTeleportColor); AM_drawMline(&l, AMColors.InterTeleportColor);
} }
else if (lines[i].special == Door_LockedRaise || else if (AM_isLockBoundary(lines[i], &lock))
lines[i].special == ACS_LockedExecute ||
lines[i].special == ACS_LockedExecuteDoor ||
(lines[i].special == Door_Animated && lines[i].args[3] != 0) ||
(lines[i].special == Generic_Door && lines[i].args[4] != 0))
{ {
if (AMColors.displayLocks) if (AMColors.displayLocks)
{ {
int P_GetMapColorForLock(int lock);
if (lines[i].special==Door_LockedRaise || lines[i].special==Door_Animated)
lock=lines[i].args[3];
else lock=lines[i].args[4];
color = P_GetMapColorForLock(lock); color = P_GetMapColorForLock(lock);
AMColor c; AMColor c;
@ -2328,16 +2446,9 @@ void AM_drawWalls (bool allmap)
AM_drawMline (&l, AMColors.LockedColor); // locked special AM_drawMline (&l, AMColors.LockedColor); // locked special
} }
} }
else if (am_showtriggerlines && AMColors.isValid(AMColors.SpecialWallColor) else if (am_showtriggerlines
&& LineSpecialsInfo[lines[i].special] != NULL && AMColors.isValid(AMColors.SpecialWallColor)
&& LineSpecialsInfo[lines[i].special]->max_args >= 0 && AM_isTriggerBoundary(lines[i]))
&& lines[i].special != Door_Open
&& lines[i].special != Door_Close
&& lines[i].special != Door_CloseWaitOpen
&& lines[i].special != Door_Raise
&& lines[i].special != Door_Animated
&& lines[i].special != Generic_Door
&& (lines[i].activation & SPAC_PlayerActivate))
{ {
AM_drawMline(&l, AMColors.SpecialWallColor); // wall with special non-door action the player can do AM_drawMline(&l, AMColors.SpecialWallColor); // wall with special non-door action the player can do
} }

View file

@ -39,6 +39,14 @@
IMPLEMENT_CLASS (ASectorAction) IMPLEMENT_CLASS (ASectorAction)
ASectorAction::ASectorAction (bool activatedByUse) :
ActivatedByUse (activatedByUse) {}
bool ASectorAction::IsActivatedByUse() const
{
return ActivatedByUse;
}
void ASectorAction::Destroy () void ASectorAction::Destroy ()
{ {
// Remove ourself from this sector's list of actions // Remove ourself from this sector's list of actions
@ -102,12 +110,17 @@ bool ASectorAction::DoTriggerAction (AActor *triggerer, int activationType)
return false; return false;
} }
bool ASectorAction::CanTrigger (AActor *triggerer) const
{
return special &&
((triggerer->player && !(flags & MF_FRIENDLY)) ||
((flags & MF_AMBUSH) && (triggerer->flags2 & MF2_MCROSS)) ||
((flags2 & MF2_DORMANT) && (triggerer->flags2 & MF2_PCROSS)));
}
bool ASectorAction::CheckTrigger (AActor *triggerer) const bool ASectorAction::CheckTrigger (AActor *triggerer) const
{ {
if (special && if (CanTrigger(triggerer))
((triggerer->player && !(flags & MF_FRIENDLY)) ||
((flags & MF_AMBUSH) && (triggerer->flags2 & MF2_MCROSS)) ||
((flags2 & MF2_DORMANT) && (triggerer->flags2 & MF2_PCROSS))))
{ {
bool res = !!P_ExecuteSpecial(special, NULL, triggerer, false, args[0], args[1], bool res = !!P_ExecuteSpecial(special, NULL, triggerer, false, args[0], args[1],
args[2], args[3], args[4]); args[2], args[3], args[4]);
@ -196,6 +209,7 @@ class ASecActUse : public ASectorAction
{ {
DECLARE_CLASS (ASecActUse, ASectorAction) DECLARE_CLASS (ASecActUse, ASectorAction)
public: public:
ASecActUse() : ASectorAction (true) {}
bool DoTriggerAction (AActor *triggerer, int activationType); bool DoTriggerAction (AActor *triggerer, int activationType);
}; };
@ -214,6 +228,7 @@ class ASecActUseWall : public ASectorAction
{ {
DECLARE_CLASS (ASecActUseWall, ASectorAction) DECLARE_CLASS (ASecActUseWall, ASectorAction)
public: public:
ASecActUseWall() : ASectorAction (true) {}
bool DoTriggerAction (AActor *triggerer, int activationType); bool DoTriggerAction (AActor *triggerer, int activationType);
}; };

View file

@ -225,14 +225,19 @@ class ASectorAction : public AActor
{ {
DECLARE_CLASS (ASectorAction, AActor) DECLARE_CLASS (ASectorAction, AActor)
public: public:
ASectorAction (bool activatedByUse = false);
void Destroy (); void Destroy ();
void BeginPlay (); void BeginPlay ();
void Activate (AActor *source); void Activate (AActor *source);
void Deactivate (AActor *source); void Deactivate (AActor *source);
bool TriggerAction(AActor *triggerer, int activationType); bool TriggerAction(AActor *triggerer, int activationType);
bool CanTrigger (AActor *triggerer) const;
bool IsActivatedByUse() const;
protected: protected:
virtual bool DoTriggerAction(AActor *triggerer, int activationType); virtual bool DoTriggerAction(AActor *triggerer, int activationType);
bool CheckTrigger(AActor *triggerer) const; bool CheckTrigger(AActor *triggerer) const;
private:
bool ActivatedByUse;
}; };
class ASkyViewpoint; class ASkyViewpoint;