From 62bda51d89c16bc285bbb30866dc5c8d96579c7d Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 14 Nov 2022 13:51:46 -0500 Subject: [PATCH] Split EV_DoFloor, EV_DoCeiling, and EV_DoCrush And remove their dependency on a line_t existing. One step towards implementing linedef executor functions into ACS. --- src/p_ceilng.c | 636 ++++++++++++++++++++++++++++++++++++------------- src/p_floor.c | 430 ++++++++++++++++++++++++--------- src/p_saveg.c | 20 +- src/p_spec.h | 33 ++- 4 files changed, 822 insertions(+), 297 deletions(-) diff --git a/src/p_ceilng.c b/src/p_ceilng.c index bec47a1ba..dd819489c 100644 --- a/src/p_ceilng.c +++ b/src/p_ceilng.c @@ -47,8 +47,8 @@ void T_MoveCeiling(ceiling_t *ceiling) if (ceiling->type == bounceCeiling) { const fixed_t origspeed = FixedDiv(ceiling->origspeed, (ELEVATORSPEED/2)); - const fixed_t fs = abs(ceiling->sector->ceilingheight - lines[ceiling->sourceline].frontsector->ceilingheight); - const fixed_t bs = abs(ceiling->sector->ceilingheight - lines[ceiling->sourceline].backsector->ceilingheight); + const fixed_t fs = abs(ceiling->sector->ceilingheight - ceiling->crushHeight); + const fixed_t bs = abs(ceiling->sector->ceilingheight - ceiling->returnHeight); if (fs < bs) ceiling->speed = FixedDiv(fs, 25*FRACUNIT) + FRACUNIT/4; else @@ -84,15 +84,15 @@ void T_MoveCeiling(ceiling_t *ceiling) { fixed_t dest = (ceiling->direction == 1) ? ceiling->topheight : ceiling->bottomheight; - if (dest == lines[ceiling->sourceline].frontsector->ceilingheight) + if (dest == ceiling->crushHeight) { - dest = lines[ceiling->sourceline].backsector->ceilingheight; - ceiling->origspeed = lines[ceiling->sourceline].args[3] << (FRACBITS - 2); // return trip, use args[3] + dest = ceiling->returnHeight; + ceiling->origspeed = ceiling->returnSpeed; // return trip, use args[3] } else { - dest = lines[ceiling->sourceline].frontsector->ceilingheight; - ceiling->origspeed = lines[ceiling->sourceline].args[2] << (FRACBITS - 2); // going frontways, use args[2] + dest = ceiling->crushHeight; + ceiling->origspeed = ceiling->crushSpeed; // going frontways, use args[2] } if (ceiling->type == bounceCeilingCrush) @@ -144,7 +144,7 @@ void T_CrushCeiling(ceiling_t *ceiling) if (res == pastdest) { ceiling->direction = -1; - ceiling->speed = lines[ceiling->sourceline].args[2] << (FRACBITS - 2); + ceiling->speed = ceiling->crushSpeed; if (ceiling->type == crushCeilOnce || ceiling->type == crushBothOnce) @@ -186,7 +186,7 @@ void T_CrushCeiling(ceiling_t *ceiling) S_StartSound(mp,sfx_pstop); ceiling->direction = 1; - ceiling->speed = lines[ceiling->sourceline].args[3] << (FRACBITS - 2); + ceiling->speed = ceiling->returnSpeed; } break; } @@ -207,138 +207,347 @@ void T_CrushCeiling(ceiling_t *ceiling) */ INT32 EV_DoCeiling(mtag_t tag, line_t *line, ceiling_e type) { - INT32 rtn = 0, firstone = 1; + // This function is deprecated. + // Use any of the following functions directly, instead. + + switch (type) + { + default: + return 0; + + case raiseToHighest: + return (INT32)EV_DoRaiseCeilingToHighest(tag); + + case lowerToLowestFast: + return (INT32)EV_DoLowerCeilingToLowestFast(tag); + + case instantRaise: + return (INT32)EV_DoInstantRaiseCeiling(tag); + + case moveCeilingByFrontSector: + return (INT32)EV_DoMoveCeilingByHeight( + tag, + line->frontsector->ceilingheight, + line->args[2] << (FRACBITS - 3), + (line->args[1] == TMP_CEILING) ? line->args[3] : 0, + line->args[4] ? line->frontsector->ceilingpic : -1 + ); + + case instantMoveCeilingByFrontSector: + return (INT32)EV_DoInstantMoveCeilingByHeight( + tag, + line->frontsector->ceilingheight, + line->args[2] ? line->frontsector->ceilingpic : -1 + ); + + case moveCeilingByDistance: + return (INT32)EV_DoMoveCeilingByDistance( + tag, + line->args[2] << FRACBITS, + line->args[3] << (FRACBITS - 3), + line->args[4] + ); + + case bounceCeiling: + case bounceCeilingCrush: + return (INT32)EV_DoBounceCeiling( + tag, + (type == bounceCeilingCrush), + line->frontsector->ceilingheight, + line->args[2] << (FRACBITS - 2), + line->backsector->ceilingheight, + line->args[3] << (FRACBITS - 2), + line->args[4], + line->args[5] + ); + } +} + +static ceiling_t *CreateCeilingThinker(sector_t *sec) +{ + ceiling_t *ceiling = NULL; + + if (sec->ceilingdata) + { + return NULL; + } + + ceiling = Z_Calloc(sizeof (*ceiling), PU_LEVSPEC, NULL); + P_AddThinker(THINK_MAIN, &ceiling->thinker); + + sec->ceilingdata = ceiling; + + ceiling->thinker.function.acp1 = (actionf_p1)T_MoveCeiling; + ceiling->sector = sec; + ceiling->crush = false; + + // interpolation + R_CreateInterpolator_SectorPlane(&ceiling->thinker, sec, true); + + return ceiling; +} + +boolean EV_DoRaiseCeilingToHighest(mtag_t tag) +{ + boolean rtn = false; INT32 secnum = -1; sector_t *sec; - ceiling_t *ceiling; TAG_ITER_SECTORS(tag, secnum) { + ceiling_t *ceiling = NULL; sec = §ors[secnum]; - if (sec->ceilingdata) - continue; - - // new door thinker - rtn = 1; - ceiling = Z_Calloc(sizeof (*ceiling), PU_LEVSPEC, NULL); - P_AddThinker(THINK_MAIN, &ceiling->thinker); - sec->ceilingdata = ceiling; - ceiling->thinker.function.acp1 = (actionf_p1)T_MoveCeiling; - ceiling->sector = sec; - ceiling->crush = false; - ceiling->sourceline = (INT32)(line-lines); - - switch (type) + ceiling = CreateCeilingThinker(sec); + if (ceiling == NULL) { - case raiseToHighest: - ceiling->topheight = P_FindHighestCeilingSurrounding(sec); - ceiling->direction = 1; - ceiling->speed = CEILSPEED; - break; - - case lowerToLowestFast: - ceiling->bottomheight = P_FindLowestCeilingSurrounding(sec); - ceiling->direction = -1; - ceiling->speed = 4*FRACUNIT; - break; - - case instantRaise: - ceiling->topheight = P_FindHighestCeilingSurrounding(sec); - ceiling->direction = 1; - ceiling->speed = INT32_MAX/2; - break; - - // Linedef executor excellence - case moveCeilingByFrontSector: - ceiling->speed = line->args[2] << (FRACBITS - 3); - if (line->frontsector->ceilingheight >= sec->ceilingheight) // Move up - { - ceiling->direction = 1; - ceiling->topheight = line->frontsector->ceilingheight; - } - else // Move down - { - ceiling->direction = -1; - ceiling->bottomheight = line->frontsector->ceilingheight; - } - - // chained linedef executing ability - // only set it on ONE of the moving sectors (the smallest numbered) - // only set it if there isn't also a floor mover - if (line->args[3] && line->args[1] == 1) - ceiling->tag = firstone ? (INT16)line->args[3] : 0; - - // flat changing ability - ceiling->texture = line->args[4] ? line->frontsector->ceilingpic : -1; - break; - - // More linedef executor junk - case instantMoveCeilingByFrontSector: - ceiling->speed = INT32_MAX/2; - - if (line->frontsector->ceilingheight >= sec->ceilingheight) // Move up - { - ceiling->direction = 1; - ceiling->topheight = line->frontsector->ceilingheight; - } - else // Move down - { - ceiling->direction = -1; - ceiling->bottomheight = line->frontsector->ceilingheight; - } - - // If flag is set, change ceiling texture after moving - ceiling->texture = line->args[2] ? line->frontsector->ceilingpic : -1; - break; - - case moveCeilingByDistance: - if (line->args[4]) - ceiling->speed = INT32_MAX/2; // as above, "instant" is one tic - else - ceiling->speed = line->args[3] << (FRACBITS - 3); - if (line->args[2] > 0) - { - ceiling->direction = 1; // up - ceiling->topheight = sec->ceilingheight + (line->args[2] << FRACBITS); - } - else { - ceiling->direction = -1; // down - ceiling->bottomheight = sec->ceilingheight + (line->args[2] << FRACBITS); - } - break; - - case bounceCeiling: - case bounceCeilingCrush: - ceiling->speed = line->args[2] << (FRACBITS - 2); // same speed as elevateContinuous - ceiling->origspeed = ceiling->speed; - if (line->frontsector->ceilingheight >= sec->ceilingheight) // Move up - { - ceiling->direction = 1; - ceiling->topheight = line->frontsector->ceilingheight; - } - else // Move down - { - ceiling->direction = -1; - ceiling->bottomheight = line->frontsector->ceilingheight; - } - - // Any delay? - ceiling->delay = line->args[5]; - ceiling->delaytimer = line->args[4]; // Initial delay - break; - - default: - break; - + continue; } - ceiling->type = type; - firstone = 0; + ceiling->type = raiseToHighest; - // interpolation - R_CreateInterpolator_SectorPlane(&ceiling->thinker, sec, true); + ceiling->topheight = P_FindHighestCeilingSurrounding(sec); + ceiling->direction = 1; + ceiling->speed = CEILSPEED; + + rtn = true; } + + return rtn; +} + +boolean EV_DoLowerCeilingToLowestFast(mtag_t tag) +{ + boolean rtn = false; + INT32 secnum = -1; + sector_t *sec; + + TAG_ITER_SECTORS(tag, secnum) + { + ceiling_t *ceiling = NULL; + sec = §ors[secnum]; + + ceiling = CreateCeilingThinker(sec); + if (ceiling == NULL) + { + continue; + } + + ceiling->type = lowerToLowestFast; + + ceiling->bottomheight = P_FindLowestCeilingSurrounding(sec); + ceiling->direction = -1; + ceiling->speed = 4*FRACUNIT; + + rtn = true; + } + + return rtn; +} + +boolean EV_DoInstantRaiseCeiling(mtag_t tag) +{ + boolean rtn = false; + INT32 secnum = -1; + sector_t *sec; + + TAG_ITER_SECTORS(tag, secnum) + { + ceiling_t *ceiling = NULL; + sec = §ors[secnum]; + + ceiling = CreateCeilingThinker(sec); + if (ceiling == NULL) + { + continue; + } + + ceiling->type = instantRaise; + + ceiling->topheight = P_FindHighestCeilingSurrounding(sec); + ceiling->direction = 1; + ceiling->speed = INT32_MAX/2; + + rtn = true; + } + + return rtn; +} + +boolean EV_DoMoveCeilingByHeight(mtag_t tag, fixed_t height, fixed_t speed, mtag_t chain, INT32 texture) +{ + boolean rtn = false; + boolean firstone = true; + INT32 secnum = -1; + sector_t *sec; + + TAG_ITER_SECTORS(tag, secnum) + { + ceiling_t *ceiling = NULL; + sec = §ors[secnum]; + + ceiling = CreateCeilingThinker(sec); + if (ceiling == NULL) + { + continue; + } + + ceiling->type = moveCeilingByFrontSector; + + ceiling->speed = speed; + if (height >= sec->ceilingheight) // Move up + { + ceiling->direction = 1; + ceiling->topheight = height; + } + else // Move down + { + ceiling->direction = -1; + ceiling->bottomheight = height; + } + + // chained linedef executing ability + // only set it on ONE of the moving sectors (the smallest numbered) + if (chain) + ceiling->tag = firstone ? (INT16)chain : 0; + + // flat changing ability + ceiling->texture = texture; + + firstone = false; + rtn = true; + } + + return rtn; +} + +boolean EV_DoInstantMoveCeilingByHeight(mtag_t tag, fixed_t height, INT32 texture) +{ + boolean rtn = false; + INT32 secnum = -1; + sector_t *sec; + + TAG_ITER_SECTORS(tag, secnum) + { + ceiling_t *ceiling = NULL; + sec = §ors[secnum]; + + ceiling = CreateCeilingThinker(sec); + if (ceiling == NULL) + { + continue; + } + + ceiling->type = instantMoveCeilingByFrontSector; + + ceiling->speed = INT32_MAX/2; + if (height >= sec->ceilingheight) // Move up + { + ceiling->direction = 1; + ceiling->topheight = height; + } + else // Move down + { + ceiling->direction = -1; + ceiling->bottomheight = height; + } + + // flat changing ability + ceiling->texture = texture; + + rtn = true; + } + + return rtn; +} + +boolean EV_DoMoveCeilingByDistance(mtag_t tag, fixed_t distance, fixed_t speed, boolean instant) +{ + boolean rtn = false; + INT32 secnum = -1; + sector_t *sec; + + TAG_ITER_SECTORS(tag, secnum) + { + ceiling_t *ceiling = NULL; + sec = §ors[secnum]; + + ceiling = CreateCeilingThinker(sec); + if (ceiling == NULL) + { + continue; + } + + ceiling->type = moveCeilingByDistance; + + if (instant) + ceiling->speed = INT32_MAX/2; // as above, "instant" is one tic + else + ceiling->speed = speed; + + if (distance > 0) + { + ceiling->direction = 1; // up + ceiling->topheight = sec->ceilingheight + distance; + } + else + { + ceiling->direction = -1; // down + ceiling->bottomheight = sec->ceilingheight + distance; + } + + rtn = true; + } + + return rtn; +} + +boolean EV_DoBounceCeiling(mtag_t tag, boolean crush, fixed_t crushHeight, fixed_t crushSpeed, fixed_t returnHeight, fixed_t returnSpeed, INT32 delayInit, INT32 delay) +{ + boolean rtn = false; + INT32 secnum = -1; + sector_t *sec; + + TAG_ITER_SECTORS(tag, secnum) + { + ceiling_t *ceiling = NULL; + sec = §ors[secnum]; + + ceiling = CreateCeilingThinker(sec); + if (ceiling == NULL) + { + continue; + } + + ceiling->type = crush ? bounceCeilingCrush : bounceCeiling; + + ceiling->crushHeight = crushHeight; + ceiling->crushSpeed = crushSpeed; // same speed as elevateContinuous + + ceiling->returnHeight = returnHeight; + ceiling->returnSpeed = returnSpeed; + + ceiling->speed = ceiling->crushSpeed; + ceiling->origspeed = ceiling->speed; + + if (ceiling->crushHeight >= sec->ceilingheight) // Move up + { + ceiling->direction = 1; + ceiling->topheight = ceiling->crushHeight; + } + else // Move down + { + ceiling->direction = -1; + ceiling->bottomheight = ceiling->crushHeight; + } + + // Any delay? + ceiling->delay = delay; + ceiling->delaytimer = delayInit; // Initial delay + + rtn = true; + } + return rtn; } @@ -353,59 +562,144 @@ INT32 EV_DoCeiling(mtag_t tag, line_t *line, ceiling_e type) */ INT32 EV_DoCrush(mtag_t tag, line_t *line, ceiling_e type) { - INT32 rtn = 0; + // This function is deprecated. + // Use any of the following functions directly, instead. + + fixed_t speed = line->args[2] << (FRACBITS - 2); + + switch (type) + { + default: + return 0; + + case raiseAndCrush: + return (INT32)EV_DoRaiseAndCrushCeiling(tag, speed, + // Retain stupid behavior for backwards compatibility + (!udmf && !(line->flags & ML_MIDSOLID)) ? (speed / 2) + : (line->args[3] << (FRACBITS - 2)) + ); + + case crushBothOnce: + return (INT32)EV_DoCrushBothOnce(tag, speed); + + case crushCeilOnce: + return (INT32)EV_DoCrushCeilingOnce(tag, speed); + } +} + +static ceiling_t *CreateCrushThinker(sector_t *sec) +{ + ceiling_t *ceiling = NULL; + + if (sec->ceilingdata) + { + return NULL; + } + + ceiling = Z_Calloc(sizeof (*ceiling), PU_LEVSPEC, NULL); + P_AddThinker(THINK_MAIN, &ceiling->thinker); + + sec->ceilingdata = ceiling; + + ceiling->thinker.function.acp1 = (actionf_p1)T_MoveCeiling; + ceiling->sector = sec; + ceiling->crush = true; + + // interpolation + R_CreateInterpolator_SectorPlane(&ceiling->thinker, sec, true); + R_CreateInterpolator_SectorPlane(&ceiling->thinker, sec, false); + + return ceiling; +} + +boolean EV_DoRaiseAndCrushCeiling(mtag_t tag, fixed_t speed, fixed_t returnSpeed) +{ + boolean rtn = false; INT32 secnum = -1; sector_t *sec; - ceiling_t *ceiling; TAG_ITER_SECTORS(tag, secnum) { + ceiling_t *ceiling = NULL; sec = §ors[secnum]; - if (sec->ceilingdata) - continue; - - // new door thinker - rtn = 1; - ceiling = Z_Calloc(sizeof (*ceiling), PU_LEVSPEC, NULL); - P_AddThinker(THINK_MAIN, &ceiling->thinker); - sec->ceilingdata = ceiling; - ceiling->thinker.function.acp1 = (actionf_p1)T_CrushCeiling; - ceiling->sector = sec; - ceiling->crush = true; - ceiling->sourceline = (INT32)(line-lines); - ceiling->speed = ceiling->origspeed = line->args[2] << (FRACBITS - 2); - - switch(type) + ceiling = CreateCrushThinker(sec); + if (ceiling == NULL) { - case raiseAndCrush: // Up and then down - ceiling->topheight = P_FindHighestCeilingSurrounding(sec); - ceiling->direction = 1; - // Retain stupid behavior for backwards compatibility - if (!udmf && !(line->flags & ML_MIDSOLID)) - ceiling->speed /= 2; - else - ceiling->speed = line->args[3] << (FRACBITS - 2); - ceiling->bottomheight = sec->floorheight + FRACUNIT; - break; - case crushBothOnce: - ceiling->topheight = sec->ceilingheight; - ceiling->bottomheight = sec->floorheight + (sec->ceilingheight-sec->floorheight)/2; - ceiling->direction = -1; - break; - case crushCeilOnce: - default: // Down and then up. - ceiling->topheight = sec->ceilingheight; - ceiling->direction = -1; - ceiling->bottomheight = sec->floorheight + FRACUNIT; - break; + continue; } - ceiling->type = type; + ceiling->type = raiseAndCrush; + ceiling->speed = ceiling->origspeed = speed; - // interpolation - R_CreateInterpolator_SectorPlane(&ceiling->thinker, sec, false); - R_CreateInterpolator_SectorPlane(&ceiling->thinker, sec, true); + ceiling->topheight = P_FindHighestCeilingSurrounding(sec); + ceiling->direction = 1; + + ceiling->speed = returnSpeed; + ceiling->bottomheight = sec->floorheight + FRACUNIT; + + rtn = true; } + + return rtn; +} + +boolean EV_DoCrushBothOnce(mtag_t tag, fixed_t speed) +{ + boolean rtn = false; + INT32 secnum = -1; + sector_t *sec; + + TAG_ITER_SECTORS(tag, secnum) + { + ceiling_t *ceiling = NULL; + sec = §ors[secnum]; + + ceiling = CreateCrushThinker(sec); + if (ceiling == NULL) + { + continue; + } + + ceiling->type = crushBothOnce; + ceiling->speed = ceiling->origspeed = speed; + + ceiling->topheight = sec->ceilingheight; + ceiling->bottomheight = sec->floorheight + (sec->ceilingheight - sec->floorheight) / 2; + ceiling->direction = -1; + + rtn = true; + } + + return rtn; +} + +boolean EV_DoCrushCeilingOnce(mtag_t tag, fixed_t speed) +{ + boolean rtn = false; + INT32 secnum = -1; + sector_t *sec; + + TAG_ITER_SECTORS(tag, secnum) + { + ceiling_t *ceiling = NULL; + sec = §ors[secnum]; + + ceiling = CreateCrushThinker(sec); + if (ceiling == NULL) + { + continue; + } + + ceiling->type = crushBothOnce; + ceiling->speed = ceiling->origspeed = speed; + + ceiling->topheight = sec->ceilingheight; + ceiling->direction = -1; + ceiling->bottomheight = sec->floorheight + FRACUNIT; + + rtn = true; + } + return rtn; } diff --git a/src/p_floor.c b/src/p_floor.c index 268c289cc..f4b30ccec 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -180,8 +180,8 @@ void T_MoveFloor(floormove_t *movefloor) if (movefloor->type == bounceFloor) { const fixed_t origspeed = FixedDiv(movefloor->origspeed,(ELEVATORSPEED/2)); - const fixed_t fs = abs(movefloor->sector->floorheight - lines[movefloor->sourceline].frontsector->floorheight); - const fixed_t bs = abs(movefloor->sector->floorheight - lines[movefloor->sourceline].backsector->floorheight); + const fixed_t fs = abs(movefloor->sector->floorheight - movefloor->crushHeight); + const fixed_t bs = abs(movefloor->sector->floorheight - movefloor->returnHeight); if (fs < bs) movefloor->speed = FixedDiv(fs,25*FRACUNIT) + FRACUNIT/4; else @@ -205,15 +205,15 @@ void T_MoveFloor(floormove_t *movefloor) break; case bounceFloor: // Graue 03-12-2004 case bounceFloorCrush: // Graue 03-27-2004 - if (movefloor->floordestheight == lines[movefloor->sourceline].frontsector->floorheight) + if (movefloor->floordestheight == movefloor->crushHeight) { - movefloor->floordestheight = lines[movefloor->sourceline].backsector->floorheight; - movefloor->origspeed = lines[movefloor->sourceline].args[3] << (FRACBITS - 2); // return trip, use args[3] + movefloor->floordestheight = movefloor->returnHeight; + movefloor->origspeed = movefloor->returnSpeed; // return trip, use args[3] } else { - movefloor->floordestheight = lines[movefloor->sourceline].frontsector->floorheight; - movefloor->origspeed = lines[movefloor->sourceline].args[2] << (FRACBITS - 2); // forward again, use args[2] + movefloor->floordestheight = movefloor->crushHeight; + movefloor->origspeed = movefloor->crushSpeed; // forward again, use args[2] } if (movefloor->type == bounceFloorCrush) movefloor->speed = movefloor->origspeed; @@ -224,9 +224,9 @@ void T_MoveFloor(floormove_t *movefloor) case crushFloorOnce: if (movefloor->direction == 1) { - movefloor->floordestheight = lines[movefloor->sourceline].frontsector->floorheight; + movefloor->floordestheight = movefloor->crushHeight; movefloor->direction = -1; - movefloor->speed = lines[movefloor->sourceline].args[3] << (FRACBITS - 2); + movefloor->speed = movefloor->returnSpeed; movefloor->sector->soundorg.z = movefloor->sector->floorheight; S_StartSound(&movefloor->sector->soundorg, sfx_pstop); remove = false; @@ -1562,128 +1562,320 @@ void T_PlaneDisplace(planedisplace_t *pd) // void EV_DoFloor(mtag_t tag, line_t *line, floor_e floortype) { - INT32 firstone = 1; + // This function is deprecated. + // Use any of the following functions directly, instead. + + switch (floortype) + { + default: + break; + + case raiseFloorToNearestFast: + EV_DoRaiseFloorToNearestFast(tag); + break; + + case instantLower: + EV_DoInstantLowerFloor(tag); + break; + + case instantMoveFloorByFrontSector: + EV_DoInstantMoveFloorByHeight( + tag, + line->frontsector->floorheight, + line->args[2] ? line->frontsector->floorpic : -1 + ); + break; + + case moveFloorByFrontSector: + EV_DoMoveFloorByHeight( + tag, + line->frontsector->floorheight, + line->args[2] << (FRACBITS - 3), + line->args[3], + line->args[4] ? line->frontsector->floorpic : -1 + ); + break; + + case moveFloorByDistance: + EV_DoMoveFloorByDistance( + tag, + line->args[2] << FRACBITS, + line->args[3] << (FRACBITS - 3), + line->args[4] + ); + break; + + case bounceFloor: + case bounceFloorCrush: + EV_DoBounceFloor( + tag, + (floortype == bounceFloorCrush), + line->frontsector->floorheight, + line->args[2] << (FRACBITS - 2), + line->backsector->floorheight, + line->args[3] << (FRACBITS - 2), + line->args[4], + line->args[5] + ); + break; + + case crushFloorOnce: + EV_DoCrushFloorOnce( + tag, + line->frontsector->ceilingheight, + line->args[2] << (FRACBITS - 2) + ); + break; + } +} + +static floormove_t *CreateFloorThinker(sector_t *sec) +{ + floormove_t *dofloor = NULL; + + if (sec->floordata) + { + return NULL; + } + + dofloor = Z_Calloc(sizeof (*dofloor), PU_LEVSPEC, NULL); + P_AddThinker(THINK_MAIN, &dofloor->thinker); + + // make sure another floor thinker won't get started over this one + sec->floordata = dofloor; + + // set up some generic aspects of the floormove_t + dofloor->thinker.function.acp1 = (actionf_p1)T_MoveFloor; + dofloor->sector = sec; + dofloor->crush = false; // default: types that crush will change this + + // interpolation + R_CreateInterpolator_SectorPlane(&dofloor->thinker, sec, false); + + return dofloor; +} + +void EV_DoRaiseFloorToNearestFast(mtag_t tag) +{ INT32 secnum = -1; sector_t *sec; - floormove_t *dofloor; TAG_ITER_SECTORS(tag, secnum) { + floormove_t *dofloor = NULL; sec = §ors[secnum]; - if (sec->floordata) // if there's already a thinker on this floor, - continue; // then don't add another one - // new floor thinker - dofloor = Z_Calloc(sizeof (*dofloor), PU_LEVSPEC, NULL); - P_AddThinker(THINK_MAIN, &dofloor->thinker); - - // make sure another floor thinker won't get started over this one - sec->floordata = dofloor; - - // set up some generic aspects of the floormove_t - dofloor->thinker.function.acp1 = (actionf_p1)T_MoveFloor; - dofloor->type = floortype; - dofloor->crush = false; // default: types that crush will change this - dofloor->sector = sec; - dofloor->sourceline = (INT32)(line - lines); - - switch (floortype) + dofloor = CreateFloorThinker(sec); + if (dofloor == NULL) { - // Used to open the top of an Egg Capsule. - case raiseFloorToNearestFast: - dofloor->direction = -1; // down - dofloor->speed = FLOORSPEED*4; // 4 fracunits per tic - dofloor->floordestheight = P_FindNextHighestFloor(sec, sec->floorheight); - break; - - // Instantly lower floor to surrounding sectors. - // Used as a hack in the binary map format to allow thing heights above 4096. - case instantLower: - dofloor->direction = -1; // down - dofloor->speed = INT32_MAX/2; // "instant" means "takes one tic" - dofloor->floordestheight = P_FindLowestFloorSurrounding(sec); - break; - - case instantMoveFloorByFrontSector: - dofloor->speed = INT32_MAX/2; // as above, "instant" is one tic - dofloor->floordestheight = line->frontsector->floorheight; - - if (dofloor->floordestheight >= sec->floorheight) - dofloor->direction = 1; // up - else - dofloor->direction = -1; // down - - // If flag is set, change floor texture after moving - dofloor->texture = line->args[2] ? line->frontsector->floorpic : -1; - break; - - case moveFloorByFrontSector: - dofloor->speed = line->args[2] << (FRACBITS - 3); - dofloor->floordestheight = line->frontsector->floorheight; - - if (dofloor->floordestheight >= sec->floorheight) - dofloor->direction = 1; // up - else - dofloor->direction = -1; // down - - // chained linedef executing ability - // Only set it on one of the moving sectors (the smallest numbered) - if (line->args[3]) - dofloor->tag = firstone ? (INT16)line->args[3] : -1; - - // flat changing ability - dofloor->texture = line->args[4] ? line->frontsector->floorpic : -1; - break; - - case moveFloorByDistance: - if (line->args[4]) - dofloor->speed = INT32_MAX/2; // as above, "instant" is one tic - else - dofloor->speed = line->args[3] << (FRACBITS - 3); - dofloor->floordestheight = sec->floorheight + (line->args[2] << FRACBITS); - if (dofloor->floordestheight > sec->floorheight) - dofloor->direction = 1; // up - else - dofloor->direction = -1; // down - break; - - // Move floor up and down indefinitely. - // bounceFloor has slowdown at the top and bottom of movement. - case bounceFloor: - case bounceFloorCrush: - dofloor->speed = line->args[2] << (FRACBITS - 2); // same speed as elevateContinuous - dofloor->origspeed = dofloor->speed; - dofloor->floordestheight = line->frontsector->floorheight; - - if (dofloor->floordestheight >= sec->floorheight) - dofloor->direction = 1; // up - else - dofloor->direction = -1; // down - - // Any delay? - dofloor->delay = line->args[5]; - dofloor->delaytimer = line->args[4]; // Initial delay - break; - - case crushFloorOnce: - dofloor->speed = dofloor->origspeed = line->args[2] << (FRACBITS - 2); - dofloor->floordestheight = line->frontsector->ceilingheight; - - if (dofloor->floordestheight >= sec->floorheight) - dofloor->direction = 1; // up - else - dofloor->direction = -1; // down - break; - - default: - break; + continue; } - firstone = 0; + dofloor->type = raiseFloorToNearestFast; - // interpolation - R_CreateInterpolator_SectorPlane(&dofloor->thinker, sec, false); + dofloor->direction = -1; // down + dofloor->speed = FLOORSPEED*4; // 4 fracunits per tic + dofloor->floordestheight = P_FindNextHighestFloor(sec, sec->floorheight); + } +} + +void EV_DoInstantLowerFloor(mtag_t tag) +{ + INT32 secnum = -1; + sector_t *sec; + + TAG_ITER_SECTORS(tag, secnum) + { + floormove_t *dofloor = NULL; + sec = §ors[secnum]; + + // new floor thinker + dofloor = CreateFloorThinker(sec); + if (dofloor == NULL) + { + continue; + } + + dofloor->type = instantLower; + + dofloor->direction = -1; // down + dofloor->speed = INT32_MAX/2; // "instant" means "takes one tic" + dofloor->floordestheight = P_FindLowestFloorSurrounding(sec); + } +} + +void EV_DoInstantMoveFloorByHeight(mtag_t tag, fixed_t height, INT32 texture) +{ + INT32 secnum = -1; + sector_t *sec; + + TAG_ITER_SECTORS(tag, secnum) + { + floormove_t *dofloor = NULL; + sec = §ors[secnum]; + + // new floor thinker + dofloor = CreateFloorThinker(sec); + if (dofloor == NULL) + { + continue; + } + + dofloor->type = instantMoveFloorByFrontSector; + + dofloor->speed = INT32_MAX/2; // as above, "instant" is one tic + dofloor->floordestheight = height; + + if (dofloor->floordestheight >= sec->floorheight) + dofloor->direction = 1; // up + else + dofloor->direction = -1; // down + + // If flag is set, change floor texture after moving + dofloor->texture = texture; + } +} + +void EV_DoMoveFloorByHeight(mtag_t tag, fixed_t height, fixed_t speed, mtag_t chain, INT32 texture) +{ + INT32 secnum = -1; + sector_t *sec; + boolean firstone = true; + + TAG_ITER_SECTORS(tag, secnum) + { + floormove_t *dofloor = NULL; + sec = §ors[secnum]; + + // new floor thinker + dofloor = CreateFloorThinker(sec); + if (dofloor == NULL) + { + continue; + } + + dofloor->type = moveFloorByFrontSector; + + dofloor->speed = speed; + dofloor->floordestheight = height; + + if (dofloor->floordestheight >= sec->floorheight) + dofloor->direction = 1; // up + else + dofloor->direction = -1; // down + + // chained linedef executing ability + // Only set it on one of the moving sectors (the smallest numbered) + if (chain) + dofloor->tag = firstone ? (INT16)chain : -1; + + // flat changing ability + dofloor->texture = texture; + + firstone = false; + } +} + +void EV_DoMoveFloorByDistance(mtag_t tag, fixed_t distance, fixed_t speed, boolean instant) +{ + INT32 secnum = -1; + sector_t *sec; + + TAG_ITER_SECTORS(tag, secnum) + { + floormove_t *dofloor = NULL; + sec = §ors[secnum]; + + // new floor thinker + dofloor = CreateFloorThinker(sec); + if (dofloor == NULL) + { + continue; + } + + dofloor->type = moveFloorByDistance; + + if (instant) + dofloor->speed = INT32_MAX/2; // as above, "instant" is one tic + else + dofloor->speed = speed; + + dofloor->floordestheight = sec->floorheight + distance; + + if (dofloor->floordestheight > sec->floorheight) + dofloor->direction = 1; // up + else + dofloor->direction = -1; // down + } +} + +void EV_DoBounceFloor(mtag_t tag, boolean crush, fixed_t crushHeight, fixed_t crushSpeed, fixed_t returnHeight, fixed_t returnSpeed, INT32 delayInit, INT32 delay) +{ + INT32 secnum = -1; + sector_t *sec; + + TAG_ITER_SECTORS(tag, secnum) + { + floormove_t *dofloor = NULL; + sec = §ors[secnum]; + + // new floor thinker + dofloor = CreateFloorThinker(sec); + if (dofloor == NULL) + { + continue; + } + + dofloor->type = crush ? bounceFloorCrush : bounceFloor; + + dofloor->crushHeight = crushHeight; + dofloor->crushSpeed = crushSpeed; // same speed as elevateContinuous + + dofloor->returnHeight = returnHeight; + dofloor->returnSpeed = returnSpeed; + + dofloor->floordestheight = dofloor->crushHeight; + dofloor->speed = dofloor->crushSpeed; + dofloor->origspeed = dofloor->speed; + + if (dofloor->floordestheight >= sec->floorheight) + dofloor->direction = 1; // up + else + dofloor->direction = -1; // down + + // Any delay? + dofloor->delay = delay; + dofloor->delaytimer = delayInit; // Initial delay + } +} + +void EV_DoCrushFloorOnce(mtag_t tag, fixed_t height, fixed_t speed) +{ + INT32 secnum = -1; + sector_t *sec; + + TAG_ITER_SECTORS(tag, secnum) + { + floormove_t *dofloor = NULL; + sec = §ors[secnum]; + + // new floor thinker + dofloor = CreateFloorThinker(sec); + if (dofloor == NULL) + { + continue; + } + + dofloor->type = crushFloorOnce; + + dofloor->speed = dofloor->origspeed = speed; + dofloor->floordestheight = height; + + if (dofloor->floordestheight >= sec->floorheight) + dofloor->direction = 1; // up + else + dofloor->direction = -1; // down } } diff --git a/src/p_saveg.c b/src/p_saveg.c index c9ede8b78..da006536c 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2315,7 +2315,10 @@ static void SaveCeilingThinker(const thinker_t *th, const UINT8 type) WRITEINT32(save_p, ht->direction); WRITEINT16(save_p, ht->tag); WRITEFIXED(save_p, ht->origspeed); - WRITEFIXED(save_p, ht->sourceline); + WRITEFIXED(save_p, ht->crushHeight); + WRITEFIXED(save_p, ht->crushSpeed); + WRITEFIXED(save_p, ht->returnHeight); + WRITEFIXED(save_p, ht->returnSpeed); } static void SaveFloormoveThinker(const thinker_t *th, const UINT8 type) @@ -2333,7 +2336,10 @@ static void SaveFloormoveThinker(const thinker_t *th, const UINT8 type) WRITEFIXED(save_p, ht->delay); WRITEFIXED(save_p, ht->delaytimer); WRITEINT16(save_p, ht->tag); - WRITEFIXED(save_p, ht->sourceline); + WRITEFIXED(save_p, ht->crushHeight); + WRITEFIXED(save_p, ht->crushSpeed); + WRITEFIXED(save_p, ht->returnHeight); + WRITEFIXED(save_p, ht->returnSpeed); } static void SaveLightflashThinker(const thinker_t *th, const UINT8 type) @@ -3521,7 +3527,10 @@ static thinker_t* LoadCeilingThinker(actionf_p1 thinker) ht->direction = READINT32(save_p); ht->tag = READINT16(save_p); ht->origspeed = READFIXED(save_p); - ht->sourceline = READFIXED(save_p); + ht->crushHeight = READFIXED(save_p); + ht->crushSpeed = READFIXED(save_p); + ht->returnHeight = READFIXED(save_p); + ht->returnSpeed = READFIXED(save_p); if (ht->sector) ht->sector->ceilingdata = ht; return &ht->thinker; @@ -3542,7 +3551,10 @@ static thinker_t* LoadFloormoveThinker(actionf_p1 thinker) ht->delay = READFIXED(save_p); ht->delaytimer = READFIXED(save_p); ht->tag = READINT16(save_p); - ht->sourceline = READFIXED(save_p); + ht->crushHeight = READFIXED(save_p); + ht->crushSpeed = READFIXED(save_p); + ht->returnHeight = READFIXED(save_p); + ht->returnSpeed = READFIXED(save_p); if (ht->sector) ht->sector->floordata = ht; return &ht->thinker; diff --git a/src/p_spec.h b/src/p_spec.h index 91bc74150..3bac50dc4 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -727,17 +727,32 @@ typedef struct // ID INT16 tag; ///< Tag of linedef executor to run when movement is done. fixed_t origspeed; ///< The original, "real" speed. - INT32 sourceline; ///< Index of the source linedef + + fixed_t crushHeight; ///< Crusher height + fixed_t crushSpeed; ///< Crusher speed + fixed_t returnHeight; ///< Crusher return height + fixed_t returnSpeed; ///< Crusher return speed } ceiling_t; #define CEILSPEED (FRACUNIT) INT32 EV_DoCeiling(mtag_t tag, line_t *line, ceiling_e type); +void T_MoveCeiling(ceiling_t *ceiling); + +boolean EV_DoRaiseCeilingToHighest(mtag_t tag); +boolean EV_DoLowerCeilingToLowestFast(mtag_t tag); +boolean EV_DoInstantRaiseCeiling(mtag_t tag); +boolean EV_DoMoveCeilingByHeight(mtag_t tag, fixed_t height, fixed_t speed, mtag_t chain, INT32 texture); +boolean EV_DoInstantMoveCeilingByHeight(mtag_t tag, fixed_t height, INT32 texture); +boolean EV_DoMoveCeilingByDistance(mtag_t tag, fixed_t distance, fixed_t speed, boolean instant); +boolean EV_DoBounceCeiling(mtag_t tag, boolean crush, fixed_t crushHeight, fixed_t crushSpeed, fixed_t returnHeight, fixed_t returnSpeed, INT32 delayInit, INT32 delay); INT32 EV_DoCrush(mtag_t tag, line_t *line, ceiling_e type); void T_CrushCeiling(ceiling_t *ceiling); -void T_MoveCeiling(ceiling_t *ceiling); +boolean EV_DoRaiseAndCrushCeiling(mtag_t tag, fixed_t speed, fixed_t returnSpeed); +boolean EV_DoCrushBothOnce(mtag_t tag, fixed_t speed); +boolean EV_DoCrushCeilingOnce(mtag_t tag, fixed_t speed); // // P_FLOOR @@ -785,7 +800,10 @@ typedef struct fixed_t delay; fixed_t delaytimer; INT16 tag; - INT32 sourceline; + fixed_t crushHeight; + fixed_t crushSpeed; + fixed_t returnHeight; + fixed_t returnSpeed; } floormove_t; typedef struct @@ -943,7 +961,16 @@ typedef enum result_e T_MovePlane(sector_t *sector, fixed_t speed, fixed_t dest, boolean crush, boolean ceiling, INT32 direction); + void EV_DoFloor(mtag_t tag, line_t *line, floor_e floortype); +void EV_DoRaiseFloorToNearestFast(mtag_t tag); +void EV_DoInstantLowerFloor(mtag_t tag); +void EV_DoInstantMoveFloorByHeight(mtag_t tag, fixed_t height, INT32 texture); +void EV_DoMoveFloorByHeight(mtag_t tag, fixed_t height, fixed_t speed, mtag_t chain, INT32 texture); +void EV_DoMoveFloorByDistance(mtag_t tag, fixed_t distance, fixed_t speed, boolean instant); +void EV_DoBounceFloor(mtag_t tag, boolean crush, fixed_t crushHeight, fixed_t crushSpeed, fixed_t returnHeight, fixed_t returnSpeed, INT32 delayInit, INT32 delay); +void EV_DoCrushFloorOnce(mtag_t tag, fixed_t height, fixed_t speed); + void EV_DoElevator(mtag_t tag, line_t *line, elevator_e elevtype); void EV_CrumbleChain(sector_t *sec, ffloor_t *rover); void EV_BounceSector(sector_t *sector, fixed_t momz, line_t *sourceline);