From 1400f401e72860d7ecceecfaa956c33de5cdc562 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 13 Jan 2017 01:34:43 +0100 Subject: [PATCH] - fixed use of multiple sector actions in the same sector. The entire setup was quite broken with each item using its own activation result and the ones of the subsequent items in the list as the return value. This rendered the STANDSTILL check in the main function totally unpredictable because the value it depended on could come from any item in the list. Changed it so that the main dispatcher function is part of sector_t and does the stepping through the list iteratively instead of letting each item recursively call its successor and let this function decide for each item alone whether it should be removed. The broken setup also had the effect that any MusicChanger would trigger all following SecActEnter specials right on msp start. --- src/g_shared/a_sectoraction.cpp | 19 +-------------- src/p_3dfloors.cpp | 4 +-- src/p_enemy.cpp | 2 +- src/p_map.cpp | 14 +++++------ src/p_mobj.cpp | 18 +++++++------- src/p_sectors.cpp | 43 +++++++++++++++++++++++++++++++++ src/r_defs.h | 2 +- src/s_advsound.cpp | 4 +-- wadsrc/static/zscript/base.txt | 1 + 9 files changed, 67 insertions(+), 40 deletions(-) diff --git a/src/g_shared/a_sectoraction.cpp b/src/g_shared/a_sectoraction.cpp index 308527b65c..5c180cc47f 100644 --- a/src/g_shared/a_sectoraction.cpp +++ b/src/g_shared/a_sectoraction.cpp @@ -94,26 +94,9 @@ void ASectorAction::Deactivate (AActor *source) flags2 |= MF2_DORMANT; // Projectiles can trigger } -bool ASectorAction::TriggerAction(AActor *triggerer, int activationType) -{ - if (DoTriggerAction(triggerer, activationType)) - { - if (flags4 & MF4_STANDSTILL) - { - Destroy(); - } - } - return false; -} - bool ASectorAction::DoTriggerAction (AActor *triggerer, int activationType) { - bool didit = (activationType & health) ? CheckTrigger(triggerer) : false; - - if (tracer != NULL) - return didit | barrier_cast(tracer)->DoTriggerAction (triggerer, activationType); - else - return didit; + return (activationType & health) ? CheckTrigger(triggerer) : false; } bool ASectorAction::CanTrigger (AActor *triggerer) const diff --git a/src/p_3dfloors.cpp b/src/p_3dfloors.cpp index c25d4a532c..102ed57b07 100644 --- a/src/p_3dfloors.cpp +++ b/src/p_3dfloors.cpp @@ -369,7 +369,7 @@ bool P_CheckFor3DFloorHit(AActor * mo, double z) { if (fabs(z - rover->top.plane->ZatPoint(mo)) < EQUAL_EPSILON) { - rover->model->SecActTarget->TriggerAction (mo, SECSPAC_HitFloor); + rover->model->TriggerSectorActions (mo, SECSPAC_HitFloor); return true; } } @@ -395,7 +395,7 @@ bool P_CheckFor3DCeilingHit(AActor * mo, double z) { if(fabs(z - rover->bottom.plane->ZatPoint(mo)) < EQUAL_EPSILON) { - rover->model->SecActTarget->TriggerAction (mo, SECSPAC_HitCeiling); + rover->model->TriggerSectorActions (mo, SECSPAC_HitCeiling); return true; } } diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 1587ef9f8e..83b96af398 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -713,7 +713,7 @@ bool P_Move (AActor *actor) if (actor->floorsector->SecActTarget != NULL && actor->floorz == actor->floorsector->floorplane.ZatPoint(actor->PosRelative(actor->floorsector))) { - actor->floorsector->SecActTarget->TriggerAction(actor, SECSPAC_HitFloor); + actor->floorsector->TriggerSectorActions(actor, SECSPAC_HitFloor); } P_CheckFor3DFloorHit(actor, actor->Z()); } diff --git a/src/p_map.cpp b/src/p_map.cpp index 4e873c99a5..c3fd2dc884 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -2616,11 +2616,11 @@ bool P_TryMove(AActor *thing, const DVector2 &pos, if (!oldAboveFakeFloor && eyez > fakez) { // View went above fake floor - newsec->SecActTarget->TriggerAction(thing, SECSPAC_EyesSurface); + newsec->TriggerSectorActions(thing, SECSPAC_EyesSurface); } else if (oldAboveFakeFloor && eyez <= fakez) { // View went below fake floor - newsec->SecActTarget->TriggerAction(thing, SECSPAC_EyesDive); + newsec->TriggerSectorActions(thing, SECSPAC_EyesDive); } if (!(hs->MoreFlags & SECF_FAKEFLOORONLY)) @@ -2628,11 +2628,11 @@ bool P_TryMove(AActor *thing, const DVector2 &pos, fakez = hs->ceilingplane.ZatPoint(pos); if (!oldAboveFakeCeiling && eyez > fakez) { // View went above fake ceiling - newsec->SecActTarget->TriggerAction(thing, SECSPAC_EyesAboveC); + newsec->TriggerSectorActions(thing, SECSPAC_EyesAboveC); } else if (oldAboveFakeCeiling && eyez <= fakez) { // View went below fake ceiling - newsec->SecActTarget->TriggerAction(thing, SECSPAC_EyesBelowC); + newsec->TriggerSectorActions(thing, SECSPAC_EyesBelowC); } } } @@ -5304,7 +5304,7 @@ bool P_UseTraverse(AActor *usething, const DVector2 &start, const DVector2 &end, sec = usething->Sector; - if (sec->SecActTarget && sec->SecActTarget->TriggerAction(usething, SECSPAC_Use)) + if (sec->SecActTarget && sec->TriggerSectorActions(usething, SECSPAC_Use)) { return true; } @@ -5313,7 +5313,7 @@ bool P_UseTraverse(AActor *usething, const DVector2 &start, const DVector2 &end, in->d.line->frontsector : in->d.line->backsector; if (sec != NULL && sec->SecActTarget && - sec->SecActTarget->TriggerAction(usething, SECSPAC_UseWall)) + sec->TriggerSectorActions(usething, SECSPAC_UseWall)) { return true; } @@ -5434,7 +5434,7 @@ void P_UseLines(player_t *player) sector_t *sec = player->mo->Sector; int spac = SECSPAC_Use; if (foundline) spac |= SECSPAC_UseWall; - if ((!sec->SecActTarget || !sec->SecActTarget->TriggerAction(player->mo, spac)) && + if ((!sec->SecActTarget || !sec->TriggerSectorActions(player->mo, spac)) && P_NoWayTraverse(player->mo, start, end)) { S_Sound(player->mo, CHAN_VOICE, "*usefail", 1, ATTN_IDLE); diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 4af97bbee5..c3a7ac4241 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -2810,7 +2810,7 @@ void P_ZMovement (AActor *mo, double oldfloorz) mo->Sector->SecActTarget != NULL && mo->Sector->floorplane.ZatPoint(mo) == mo->floorz) { // [RH] Let the sector do something to the actor - mo->Sector->SecActTarget->TriggerAction (mo, SECSPAC_HitFloor); + mo->Sector->TriggerSectorActions (mo, SECSPAC_HitFloor); } P_CheckFor3DFloorHit(mo, mo->floorz); // [RH] Need to recheck this because the sector action might have @@ -2913,7 +2913,7 @@ void P_ZMovement (AActor *mo, double oldfloorz) mo->Sector->SecActTarget != NULL && mo->Sector->ceilingplane.ZatPoint(mo) == mo->ceilingz) { // [RH] Let the sector do something to the actor - mo->Sector->SecActTarget->TriggerAction (mo, SECSPAC_HitCeiling); + mo->Sector->TriggerSectorActions (mo, SECSPAC_HitCeiling); } P_CheckFor3DCeilingHit(mo, mo->ceilingz); // [RH] Need to recheck this because the sector action might have @@ -2981,7 +2981,7 @@ void P_CheckFakeFloorTriggers (AActor *mo, double oldz, bool oldz_has_viewheight if (oldz > waterz && mo->Z() <= waterz) { // Feet hit fake floor - sec->SecActTarget->TriggerAction (mo, SECSPAC_HitFakeFloor); + sec->TriggerSectorActions (mo, SECSPAC_HitFakeFloor); } newz = mo->Z() + viewheight; @@ -2992,11 +2992,11 @@ void P_CheckFakeFloorTriggers (AActor *mo, double oldz, bool oldz_has_viewheight if (oldz <= waterz && newz > waterz) { // View went above fake floor - sec->SecActTarget->TriggerAction (mo, SECSPAC_EyesSurface); + sec->TriggerSectorActions (mo, SECSPAC_EyesSurface); } else if (oldz > waterz && newz <= waterz) { // View went below fake floor - sec->SecActTarget->TriggerAction (mo, SECSPAC_EyesDive); + sec->TriggerSectorActions (mo, SECSPAC_EyesDive); } if (!(hs->MoreFlags & SECF_FAKEFLOORONLY)) @@ -3004,11 +3004,11 @@ void P_CheckFakeFloorTriggers (AActor *mo, double oldz, bool oldz_has_viewheight waterz = hs->ceilingplane.ZatPoint(mo); if (oldz <= waterz && newz > waterz) { // View went above fake ceiling - sec->SecActTarget->TriggerAction (mo, SECSPAC_EyesAboveC); + sec->TriggerSectorActions (mo, SECSPAC_EyesAboveC); } else if (oldz > waterz && newz <= waterz) { // View went below fake ceiling - sec->SecActTarget->TriggerAction (mo, SECSPAC_EyesBelowC); + sec->TriggerSectorActions (mo, SECSPAC_EyesBelowC); } } } @@ -4353,7 +4353,7 @@ void AActor::CheckSectorTransition(sector_t *oldsec) { if (oldsec->SecActTarget != NULL) { - oldsec->SecActTarget->TriggerAction(this, SECSPAC_Exit); + oldsec->TriggerSectorActions(this, SECSPAC_Exit); } if (Sector->SecActTarget != NULL) { @@ -4370,7 +4370,7 @@ void AActor::CheckSectorTransition(sector_t *oldsec) { act |= SECSPAC_HitFakeFloor; } - Sector->SecActTarget->TriggerAction(this, act); + Sector->TriggerSectorActions(this, act); } if (Z() == floorz) { diff --git a/src/p_sectors.cpp b/src/p_sectors.cpp index c95f48d150..b8b2fdfa07 100644 --- a/src/p_sectors.cpp +++ b/src/p_sectors.cpp @@ -1446,6 +1446,49 @@ DEFINE_ACTION_FUNCTION(_Sector, NextLowestFloorAt) } + //=========================================================================== + // + // + // + //=========================================================================== + + bool sector_t::TriggerSectorActions(AActor *thing, int activation) + { + auto act = SecActTarget; + bool res = false; + + while (act != nullptr) + { + AActor *next = act->tracer; + + bool didit = act->DoTriggerAction(thing, activation); + if (didit) + { + if (act->flags4 & MF4_STANDSTILL) + { + act->Destroy(); + } + } + act = static_cast(next); + res |= didit; + } + return res; + } + + DEFINE_ACTION_FUNCTION(_Sector, TriggerSectorActions) + { + PARAM_SELF_STRUCT_PROLOGUE(sector_t); + PARAM_OBJECT(thing, AActor); + PARAM_INT(activation); + ACTION_RETURN_BOOL(self->TriggerSectorActions(thing, activation)); + } + + //=========================================================================== + // + // + // + //=========================================================================== + DEFINE_ACTION_FUNCTION(_Sector, PointInSector) { PARAM_PROLOGUE; diff --git a/src/r_defs.h b/src/r_defs.h index 9f6291852f..c1bee09cf0 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -287,7 +287,6 @@ public: void BeginPlay (); void Activate (AActor *source); void Deactivate (AActor *source); - bool TriggerAction(AActor *triggerer, int activationType); bool CanTrigger (AActor *triggerer) const; bool IsActivatedByUse() const; virtual bool DoTriggerAction(AActor *triggerer, int activationType); @@ -674,6 +673,7 @@ public: int GetCeilingLight () const; sector_t *GetHeightSec() const; double GetFriction(int plane = sector_t::floor, double *movefac = NULL) const; + bool TriggerSectorActions(AActor *thing, int activation); DInterpolation *SetInterpolation(int position, bool attach); diff --git a/src/s_advsound.cpp b/src/s_advsound.cpp index b374483b5e..052abf04ed 100644 --- a/src/s_advsound.cpp +++ b/src/s_advsound.cpp @@ -2483,7 +2483,7 @@ bool AMusicChanger::DoTriggerAction (AActor *triggerer, int activationType) triggerer->player->MUSINFOtics = 30; } } - return tracer == nullptr? false : barrier_cast(tracer)->DoTriggerAction(triggerer, activationType); + return false; } void AMusicChanger::PostBeginPlay() @@ -2495,7 +2495,7 @@ void AMusicChanger::PostBeginPlay() { if (playeringame[i] && players[i].mo && players[i].mo->Sector == this->Sector) { - TriggerAction(players[i].mo, SECSPAC_Enter); + DoTriggerAction(players[i].mo, SECSPAC_Enter); } } } diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 5751aceac5..f0e2806238 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -508,6 +508,7 @@ struct Sector native native int GetOppositePortalGroup(int plane); native double CenterFloor(); native double CenterCeiling(); + native bool TriggerSectorActions(Actor thing, int activation); native int MoveFloor(double speed, double dest, int crush, int direction, bool hexencrush, bool instant = false); native int MoveCeiling(double speed, double dest, int crush, int direction, bool hexencrush);