diff --git a/src/p_maputl.c b/src/p_maputl.c index e1ceeb0fe..b0c477b9a 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -1024,6 +1024,7 @@ void P_UnsetPrecipThingPosition(precipmobj_t *thing) void P_SetThingPosition(mobj_t *thing) { // link into subsector subsector_t *ss; + sector_t *prevsec = NULL; sector_t *oldsec = NULL; fixed_t tfloorz, tceilz; @@ -1031,7 +1032,15 @@ void P_SetThingPosition(mobj_t *thing) I_Assert(!P_MobjWasRemoved(thing)); if (thing->player && thing->z <= thing->floorz && thing->subsector) + { + // I don't trust this so I'm leaving it alone. -Sal oldsec = thing->subsector->sector; + } + + if (thing->subsector) + { + prevsec = thing->subsector->sector; + } ss = thing->subsector = R_PointInSubsector(thing->x, thing->y); @@ -1106,6 +1115,12 @@ void P_SetThingPosition(mobj_t *thing) else if (thing->z <= tfloorz) thing->eflags |= MFE_JUSTSTEPPEDDOWN; } + + if (udmf && prevsec != thing->subsector->sector) + { + // Check for each time / once sector special actions + P_CheckMobjTouchingSectorActions(thing, false); + } } // diff --git a/src/p_mobj.c b/src/p_mobj.c index 4322e8478..aa0734bac 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -9855,8 +9855,8 @@ void P_MobjThinker(mobj_t *mobj) if (udmf) { - // Check for sector special actions - P_CheckMobjTouchingSectorActions(mobj); + // Check for continuous sector special actions + P_CheckMobjTouchingSectorActions(mobj, true); } else { diff --git a/src/p_setup.c b/src/p_setup.c index 0ca14594b..1417ff179 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1613,7 +1613,9 @@ static void ParseTextmapSectorParameter(UINT32 i, const char *param, const char sectors[i].args[argnum] = atol(val); } else if (fastcmp(param, "repeatspecial") && fastcmp("true", val)) - sectors[i].activation |= SECSPAC_REPEATSPECIAL; + sectors[i].activation |= ((sectors[i].activation & ~SECSPAC_TRIGGERMASK) | SECSPAC_REPEATSPECIAL); + else if (fastcmp(param, "continuousspecial") && fastcmp("true", val)) + sectors[i].activation |= ((sectors[i].activation & ~SECSPAC_TRIGGERMASK) | SECSPAC_CONTINUOUSSPECIAL); else if (fastcmp(param, "playerenter") && fastcmp("true", val)) sectors[i].activation |= SECSPAC_ENTER; else if (fastcmp(param, "playerfloor") && fastcmp("true", val)) @@ -2551,8 +2553,19 @@ static void P_WriteTextmap(void) for (j = 0; j < NUMSECTORSTRINGARGS; j++) if (wsectors[i].stringargs[j]) fprintf(f, "stringarg%s = \"%s\";\n", sizeu1(j), wsectors[i].stringargs[j]); - if (wsectors[i].activation & SECSPAC_REPEATSPECIAL) - fprintf(f, "repeatspecial = true;\n"); + switch (wsectors[i].activation & SECSPAC_TRIGGERMASK) + { + case SECSPAC_REPEATSPECIAL: + { + fprintf(f, "repeatspecial = true;\n"); + break; + } + case SECSPAC_CONTINUOUSSPECIAL: + { + fprintf(f, "continuousspecial = true;\n"); + break; + } + } if (wsectors[i].activation & SECSPAC_ENTER) fprintf(f, "playerenter = true;\n"); if (wsectors[i].activation & SECSPAC_FLOOR) diff --git a/src/p_spec.c b/src/p_spec.c index 32ca12dd7..14be8d21d 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -5647,12 +5647,17 @@ void P_CheckMobjTrigger(mobj_t *mobj, boolean pushable) static void P_SectorActionWasActivated(sector_t *sec) { - if ((sec->activation & SECSPAC_REPEATSPECIAL) == 0) + if ((sec->activation & SECSPAC_TRIGGERMASK) == SECSPAC_ONCESPECIAL) { sec->action = 0; } } +static boolean P_SectorActionIsContinuous(sector_t *sec) +{ + return ((sec->activation & SECSPAC_TRIGGERMASK) == SECSPAC_CONTINUOUSSPECIAL); +} + static boolean P_AllowSpecialEnter(sector_t *sec, mobj_t *thing) { if (thing->player != NULL) @@ -5710,7 +5715,7 @@ static boolean P_AllowSpecialCeiling(sector_t *sec, mobj_t *thing) return false; } -static void P_CheckMobj3DFloorAction(mobj_t *mo, sector_t *sec) +static void P_CheckMobj3DFloorAction(mobj_t *mo, sector_t *sec, boolean continuous) { sector_t *originalsector = mo->subsector->sector; ffloor_t *rover; @@ -5723,6 +5728,12 @@ static void P_CheckMobj3DFloorAction(mobj_t *mo, sector_t *sec) { roversec = rover->master->frontsector; + if (P_SectorActionIsContinuous(roversec) != continuous) + { + // Does not match continuous state. + continue; + } + if (P_CanActivateSpecial(roversec->action) == false) { // No special to even activate. @@ -5770,7 +5781,7 @@ static void P_CheckMobj3DFloorAction(mobj_t *mo, sector_t *sec) } } -static void P_CheckMobjPolyobjAction(mobj_t *mo) +static void P_CheckMobjPolyobjAction(mobj_t *mo, boolean continuous) { sector_t *originalsector = mo->subsector->sector; polyobj_t *po; @@ -5785,11 +5796,11 @@ static void P_CheckMobjPolyobjAction(mobj_t *mo) { polysec = po->lines[0]->backsector; - touching = P_MobjTouchingPolyobj(po, mo); - inside = P_MobjInsidePolyobj(po, mo); - - if (!(inside || touching)) + if (P_SectorActionIsContinuous(polysec) != continuous) + { + // Does not match continuous state. continue; + } if (P_CanActivateSpecial(polysec->action) == false) { @@ -5797,6 +5808,14 @@ static void P_CheckMobjPolyobjAction(mobj_t *mo) continue; } + touching = P_MobjTouchingPolyobj(po, mo); + inside = P_MobjInsidePolyobj(po, mo); + + if (!(inside || touching)) + { + continue; + } + if (P_AllowSpecialEnter(polysec, mo) == false) { boolean floor = false; @@ -5838,11 +5857,17 @@ static void P_CheckMobjPolyobjAction(mobj_t *mo) } } -static void P_CheckMobjSectorAction(mobj_t *mo, sector_t *sec) +static void P_CheckMobjSectorAction(mobj_t *mo, sector_t *sec, boolean continuous) { activator_t *activator = NULL; boolean result = false; + if (P_SectorActionIsContinuous(sec) != continuous) + { + // Does not match continuous state. + return; + } + if (P_CanActivateSpecial(sec->action) == false) { // No special to even activate. @@ -5887,7 +5912,7 @@ static void P_CheckMobjSectorAction(mobj_t *mo, sector_t *sec) } } -void P_CheckMobjTouchingSectorActions(mobj_t *mobj) +void P_CheckMobjTouchingSectorActions(mobj_t *mobj, boolean continuous) { sector_t *originalsector; @@ -5896,13 +5921,13 @@ void P_CheckMobjTouchingSectorActions(mobj_t *mobj) originalsector = mobj->subsector->sector; - P_CheckMobj3DFloorAction(mobj, originalsector); + P_CheckMobj3DFloorAction(mobj, originalsector, continuous); if TELEPORTED(mobj) return; - P_CheckMobjPolyobjAction(mobj); + P_CheckMobjPolyobjAction(mobj, continuous); if TELEPORTED(mobj) return; - P_CheckMobjSectorAction(mobj, originalsector); + P_CheckMobjSectorAction(mobj, originalsector, continuous); } #undef TELEPORTED diff --git a/src/p_spec.h b/src/p_spec.h index 1ec766f09..b7a48f992 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -561,7 +561,7 @@ sector_t *P_PlayerTouchingSectorSpecial(player_t *player, INT32 section, INT32 n sector_t *P_PlayerTouchingSectorSpecialFlag(player_t *player, sectorspecialflags_t flag); void P_PlayerInSpecialSector(player_t *player); void P_CheckMobjTrigger(mobj_t *mobj, boolean pushable); -void P_CheckMobjTouchingSectorActions(mobj_t *mobj); +void P_CheckMobjTouchingSectorActions(mobj_t *mobj, boolean continuous); sector_t *P_FindPlayerTrigger(player_t *player, line_t *sourceline); boolean P_IsPlayerValid(size_t playernum); boolean P_CanPlayerTrigger(size_t playernum); diff --git a/src/r_defs.h b/src/r_defs.h index 4e947616b..7445e44e9 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -373,35 +373,44 @@ typedef enum typedef enum { + // Mask to get trigger type. + SECSPAC_TRIGGERMASK = 0x0000000F, + + // Special action is activated once. + SECSPAC_ONCESPECIAL = 0x00000000, + // Special action is repeatable. SECSPAC_REPEATSPECIAL = 0x00000001, + // Special action is activated continously. + SECSPAC_CONTINUOUSSPECIAL = 0x00000002, + // When a player enters this sector. - SECSPAC_ENTER = 0x00000002, + SECSPAC_ENTER = 0x00000010, // When a player touches the floor of this sector. - SECSPAC_FLOOR = 0x00000004, + SECSPAC_FLOOR = 0x00000020, // When a player touches the ceiling of this sector. - SECSPAC_CEILING = 0x00000008, + SECSPAC_CEILING = 0x00000040, // When an enemy enters this sector. - SECSPAC_ENTERMONSTER = 0x00000010, + SECSPAC_ENTERMONSTER = 0x00000080, // When an enemy touches the floor of this sector. - SECSPAC_FLOORMONSTER = 0x00000020, + SECSPAC_FLOORMONSTER = 0x00000100, // When an enemy touches the ceiling of this sector. - SECSPAC_CEILINGMONSTER = 0x00000040, + SECSPAC_CEILINGMONSTER = 0x00000200, // When a projectile enters this sector. - SECSPAC_ENTERMISSILE = 0x00000080, + SECSPAC_ENTERMISSILE = 0x00000400, // When a projectile touches the floor of this sector. - SECSPAC_FLOORMISSILE = 0x00000100, + SECSPAC_FLOORMISSILE = 0x00000800, // When a projectile touches the ceiling of this sector. - SECSPAC_CEILINGMISSILE = 0x00000200, + SECSPAC_CEILINGMISSILE = 0x00001000, } sectoractionflags_t; typedef enum