From 600aec3449c7cc8aaaa19f1502c7549e97dc1023 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 15 Nov 2023 14:48:53 -0800 Subject: [PATCH 1/6] renderhitbox: shown MF_PAPERCOLLISION correctly --- src/r_bbox.c | 43 +++++++++++++++++++++++++++---------------- src/r_things.cpp | 35 ++++++++++++++++++++++++++--------- 2 files changed, 53 insertions(+), 25 deletions(-) diff --git a/src/r_bbox.c b/src/r_bbox.c index ce4f3d758..d484c3b51 100644 --- a/src/r_bbox.c +++ b/src/r_bbox.c @@ -204,29 +204,40 @@ void R_DrawThingBoundingBox(vissprite_t *vis) .color = R_GetBoundingBoxColor(vis->mobj), }; - // 1--3 - // | | - // 0--2 + if (vis->mobjflags & MF_PAPERCOLLISION) + { + // 0--1 - // left + draw_bbox_col(&bb, 0, tx - rc, ty - rs); // left + draw_bbox_col(&bb, 1, tx + rc, ty + rs); // right + draw_bbox_row(&bb, 0, 1); // connect both + } + else + { + // 1--3 + // | | + // 0--2 - draw_bbox_col(&bb, 0, tx, ty); // bottom - draw_bbox_col(&bb, 1, tx - rc, ty + rs); // top + // left - // right + draw_bbox_col(&bb, 0, tx, ty); // bottom + draw_bbox_col(&bb, 1, tx - rc, ty + rs); // top - tx += rs; - ty += rc; + // right - draw_bbox_col(&bb, 2, tx, ty); // bottom - draw_bbox_col(&bb, 3, tx - rc, ty + rs); // top + tx += rs; + ty += rc; - // connect all four columns + draw_bbox_col(&bb, 2, tx, ty); // bottom + draw_bbox_col(&bb, 3, tx - rc, ty + rs); // top - draw_bbox_row(&bb, 0, 1); - draw_bbox_row(&bb, 1, 3); - draw_bbox_row(&bb, 3, 2); - draw_bbox_row(&bb, 2, 0); + // connect all four columns + + draw_bbox_row(&bb, 0, 1); + draw_bbox_row(&bb, 1, 3); + draw_bbox_row(&bb, 3, 2); + draw_bbox_row(&bb, 2, 0); + } } static boolean is_tangible (mobj_t *thing) diff --git a/src/r_things.cpp b/src/r_things.cpp index deacfce92..37dcc3bf4 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -1586,13 +1586,22 @@ static void R_ProjectBoundingBox(mobj_t *thing, vissprite_t *vis) R_InterpolateMobjState(thing, FRACUNIT, &interp); } - // 1--3 - // | | - // 0--2 - - // start in the (0) corner - gx = interp.x - thing->radius - viewx; - gy = interp.y - thing->radius - viewy; + if (thing->flags & MF_PAPERCOLLISION) + { + // 0--1 + // start in the middle + gx = interp.x - viewx; + gy = interp.y - viewy; + } + else + { + // 1--3 + // | | + // 0--2 + // start in the (0) corner + gx = interp.x - thing->radius - viewx; + gy = interp.y - thing->radius - viewy; + } tz = FixedMul(gx, viewcos) + FixedMul(gy, viewsin); @@ -1620,8 +1629,16 @@ static void R_ProjectBoundingBox(mobj_t *thing, vissprite_t *vis) box->gx = tx; box->gy = tz; - box->scale = 2 * FixedMul(thing->radius, viewsin); - box->xscale = 2 * FixedMul(thing->radius, viewcos); + if (thing->flags & MF_PAPERCOLLISION) + { + box->scale = FixedMul(thing->radius, FCOS(viewangle - interp.angle)); + box->xscale = FixedMul(thing->radius, FSIN(viewangle - interp.angle)); + } + else + { + box->scale = 2 * FixedMul(thing->radius, viewsin); + box->xscale = 2 * FixedMul(thing->radius, viewcos); + } box->pz = interp.z; box->pzt = box->pz + box->thingheight; From 2ebbfe3e7a3553fe72d7757347efd0fc340268d3 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 15 Nov 2023 14:51:16 -0800 Subject: [PATCH 2/6] MT_WALLSPIKE: let radius be increased without requiring map/HVR adjustment --- src/p_mobj.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/p_mobj.c b/src/p_mobj.c index 54d62622e..26265c21d 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -13867,7 +13867,16 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj) // Use per-thing collision for spikes unless the intangible flag is checked. if (!(mthing->thing_args[2] & TMSF_INTANGIBLE) && !metalrecording) { + const fixed_t kSpriteRadius = 16 * mobj->scale; + fixed_t x = FixedMul(mobj->radius - kSpriteRadius, FCOS(mobj->angle)); + fixed_t y = FixedMul(mobj->radius - kSpriteRadius, FSIN(mobj->angle)); + + mobj->sprxoff -= x; + mobj->spryoff -= y; + P_UnsetThingPosition(mobj); + mobj->x += x; + mobj->y += y; mobj->flags &= ~(MF_NOBLOCKMAP | MF_NOCLIPHEIGHT); mobj->flags |= MF_SOLID; P_SetThingPosition(mobj); From d9bf6119a3452e287e2f3c664c24c8da9cc1038d Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 15 Nov 2023 14:51:46 -0800 Subject: [PATCH 3/6] MT_WALLSPIKE: increase hitbox size to match sprite --- src/info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/info.c b/src/info.c index 546cd2b68..dc460763a 100644 --- a/src/info.c +++ b/src/info.c @@ -9386,7 +9386,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_WALLSPIKED2, // xdeathstate sfx_mspogo, // deathsound 2*TICRATE, // speed - 16*FRACUNIT, // radius + 48*FRACUNIT, // radius 14*FRACUNIT, // height 0, // display offset 4, // mass From 4065f56b98dd4038df4e521e44957db2a7f9f0f7 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 15 Nov 2023 15:36:49 -0800 Subject: [PATCH 4/6] MT_WALLSPIKE: always bounce toward tip --- src/k_kart.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 021e71158..4bf2c73a7 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -998,7 +998,7 @@ boolean K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2) boolean K_KartSolidBounce(mobj_t *bounceMobj, mobj_t *solidMobj) { const fixed_t minBump = 25*mapobjectscale; - fixed_t distx, disty, dist; + fixed_t distx, disty; fixed_t force; if ((!bounceMobj || P_MobjWasRemoved(bounceMobj)) @@ -1034,17 +1034,30 @@ boolean K_KartSolidBounce(mobj_t *bounceMobj, mobj_t *solidMobj) return false; } - // Multiply by force - distx = FixedMul(force, distx); - disty = FixedMul(force, disty); - dist = FixedHypot(distx, disty); - { // Normalize to the desired push value. - fixed_t normalisedx = FixedDiv(distx, dist); - fixed_t normalisedy = FixedDiv(disty, dist); + fixed_t normalisedx; + fixed_t normalisedy; fixed_t bounceSpeed; + // Multiply by force + distx = FixedMul(force, distx); + disty = FixedMul(force, disty); + fixed_t dist = FixedHypot(distx, disty); + + normalisedx = FixedDiv(distx, dist); + normalisedy = FixedDiv(disty, dist); + + if (solidMobj->type == MT_WALLSPIKE) + { + fixed_t co = FCOS(solidMobj->angle); + fixed_t si = FSIN(solidMobj->angle); + + // Always thrust out toward the tip + normalisedx = FixedMul(normalisedx, abs(si)) - co; + normalisedy = FixedMul(normalisedy, abs(co)) - si; + } + bounceSpeed = FixedHypot(bounceMobj->momx, bounceMobj->momy); bounceSpeed = FixedMul(bounceSpeed, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); bounceSpeed += minBump; From c4e4c9e9b0d11176a76fba8ac8f19f0055876396 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 15 Nov 2023 15:41:52 -0800 Subject: [PATCH 5/6] MT_SPIKE, MT_WALLSPIKE: entire hitbox hurts, hurt all objects, tumbles objects that fall onto spikes --- src/p_map.c | 128 ++++++++++++++++++++-------------------------------- 1 file changed, 49 insertions(+), 79 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index 69ff25357..7f1b3bf84 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -659,23 +659,6 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) && (tm.thing->type == MT_BLENDEYE_MAIN || tm.thing->type == MT_BLENDEYE_EYE || tm.thing->type == MT_BLENDEYE_PUYO)) return BMIT_CONTINUE; - // When solid spikes move, assume they just popped up and teleport things on top of them to hurt. - if (tm.thing->type == MT_SPIKE && tm.thing->flags & MF_SOLID) - { - if (thing->z > tm.thing->z + tm.thing->height) - return BMIT_CONTINUE; // overhead - if (thing->z + thing->height < tm.thing->z) - return BMIT_CONTINUE; // underneath - - if (tm.thing->eflags & MFE_VERTICALFLIP) - P_SetOrigin(thing, thing->x, thing->y, tm.thing->z - thing->height - FixedMul(FRACUNIT, tm.thing->scale)); - else - P_SetOrigin(thing, thing->x, thing->y, tm.thing->z + tm.thing->height + FixedMul(FRACUNIT, tm.thing->scale)); - if (thing->flags & MF_SHOOTABLE) - P_DamageMobj(thing, tm.thing, tm.thing, 1, 0); - return BMIT_CONTINUE; - } - if (thing->flags & MF_PAIN) { // Player touches painful thing sitting on the floor // see if it went over / under @@ -1326,78 +1309,65 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) } // Sprite Spikes! - // Do not return because solidity code comes below. - if (tm.thing->type == MT_SPIKE && tm.thing->flags & MF_SOLID && thing->player) // moving spike rams into player?! + if ((tm.thing->type == MT_SPIKE || tm.thing->type == MT_WALLSPIKE) && (tm.thing->flags & MF_SOLID)) // spike pops up { - if (tm.thing->eflags & MFE_VERTICALFLIP) + // see if it went over / under + if (tm.thing->z > thing->z + thing->height) + return BMIT_CONTINUE; // overhead + if (tm.thing->z + tm.thing->height < thing->z) + return BMIT_CONTINUE; // underneath + + if (thing->flags & MF_SHOOTABLE) { - if (thing->z + thing->height <= tm.thing->z + FixedMul(FRACUNIT, tm.thing->scale) - && thing->z + thing->height + thing->momz >= tm.thing->z + FixedMul(FRACUNIT, tm.thing->scale) + tm.thing->momz) - P_DamageMobj(thing, tm.thing, tm.thing, 1, DMG_TUMBLE); + if (P_MobjFlip(thing) == P_MobjFlip(tm.thing)) + { + if (P_DamageMobj(thing, tm.thing, tm.thing, 1, DMG_TUMBLE)) + { + // FIXME: None of this is correct for wall spikes, + // but I don't feel like testing that right now. + + // Increase vertical momentum for a strong effect + thing->momz += (tm.thing->height / 2) * P_MobjFlip(tm.thing); + + // Teleport on top of the spikes + P_MoveOrigin( + thing, + thing->x, + thing->y, + tm.thing->z + (P_MobjFlip(thing) > 0 ? tm.thing->height : -thing->height) + ); + } + } + else + { + P_DamageMobj(thing, tm.thing, tm.thing, 1, DMG_NORMAL); + } } - else if (thing->z >= tm.thing->z + tm.thing->height - FixedMul(FRACUNIT, tm.thing->scale) - && thing->z + thing->momz <= tm.thing->z + tm.thing->height - FixedMul(FRACUNIT, tm.thing->scale) + tm.thing->momz) - P_DamageMobj(thing, tm.thing, tm.thing, 1, DMG_TUMBLE); + return BMIT_CONTINUE; } - else if (thing->type == MT_SPIKE && thing->flags & MF_SOLID && tm.thing->player) // unfortunate player falls into spike?! + else if ((thing->type == MT_SPIKE || thing->type == MT_WALLSPIKE) && + (thing->flags & MF_SOLID) && (tm.thing->flags & MF_SHOOTABLE)) // stationary spike { - if (thing->eflags & MFE_VERTICALFLIP) + // see if it went over / under + if (tm.thing->z > thing->z + thing->height) + return BMIT_CONTINUE; // overhead + if (tm.thing->z + tm.thing->height < thing->z) + return BMIT_CONTINUE; // underneath + + if (tm.thing->player && tm.thing->player && tm.thing->player->tumbleBounces > 0) { - if (tm.thing->z + tm.thing->height <= thing->z - FixedMul(FRACUNIT, thing->scale) - && tm.thing->z + tm.thing->height + tm.thing->momz >= thing->z - FixedMul(FRACUNIT, thing->scale)) - P_DamageMobj(tm.thing, thing, thing, 1, DMG_TUMBLE); + return BMIT_CONTINUE; } - else if (tm.thing->z >= thing->z + thing->height + FixedMul(FRACUNIT, thing->scale) - && tm.thing->z + tm.thing->momz <= thing->z + thing->height + FixedMul(FRACUNIT, thing->scale)) + + if (!P_IsObjectOnGround(tm.thing) && tm.thing->momz * P_MobjFlip(tm.thing) < 0) // fell into it + { P_DamageMobj(tm.thing, thing, thing, 1, DMG_TUMBLE); - } - - if (tm.thing->type == MT_WALLSPIKE && tm.thing->flags & MF_SOLID && thing->player) // wall spike impales player - { - fixed_t bottomz, topz; - bottomz = tm.thing->z; - topz = tm.thing->z + tm.thing->height; - if (tm.thing->eflags & MFE_VERTICALFLIP) - bottomz -= FixedMul(FRACUNIT, tm.thing->scale); - else - topz += FixedMul(FRACUNIT, tm.thing->scale); - - if (thing->z + thing->height > bottomz // above bottom - && thing->z < topz) // below top - // don't check angle, the player was clearly in the way in this case - P_DamageMobj(thing, tm.thing, tm.thing, 1, DMG_NORMAL); - } - else if (thing->type == MT_WALLSPIKE && thing->flags & MF_SOLID && tm.thing->player) - { - fixed_t bottomz, topz; - angle_t touchangle = R_PointToAngle2(thing->tracer->x, thing->tracer->y, tm.thing->x, tm.thing->y); - - if (P_PlayerInPain(tm.thing->player) && (tm.thing->momx || tm.thing->momy)) - { - angle_t playerangle = R_PointToAngle2(0, 0, tm.thing->momx, tm.thing->momy) - touchangle; - if (playerangle > ANGLE_180) - playerangle = InvAngle(playerangle); - if (playerangle < ANGLE_90) - return BMIT_CONTINUE; // Yes, this is intentionally outside the z-height check. No standing on spikes whilst moving away from them. + return BMIT_CONTINUE; } - - bottomz = thing->z; - topz = thing->z + thing->height; - - if (thing->eflags & MFE_VERTICALFLIP) - bottomz -= FixedMul(FRACUNIT, thing->scale); else - topz += FixedMul(FRACUNIT, thing->scale); - - if (tm.thing->z + tm.thing->height > bottomz // above bottom - && tm.thing->z < topz // below top - && !P_MobjWasRemoved(thing->tracer)) // this probably wouldn't work if we didn't have a tracer - { // use base as a reference point to determine what angle you touched the spike at - touchangle = thing->angle - touchangle; - if (touchangle > ANGLE_180) - touchangle = InvAngle(touchangle); - if (touchangle <= ANGLE_22h) // if you touched it at this close an angle, you get poked! - P_DamageMobj(tm.thing, thing, thing, 1, DMG_NORMAL); + { + // Do not return because solidity code comes below. + P_DamageMobj(tm.thing, thing, thing, 1, DMG_NORMAL); } } From d6fb8eb03656d670085bf1569a3628a90b3ba167 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 15 Nov 2023 17:53:34 -0800 Subject: [PATCH 6/6] MT_SPIKE: taller hitbox, matches sprite --- src/info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/info.c b/src/info.c index dc460763a..71644da80 100644 --- a/src/info.c +++ b/src/info.c @@ -9360,7 +9360,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_mspogo, // deathsound 2*TICRATE, // speed 14*FRACUNIT, // radius - 64*FRACUNIT, // height + 90*FRACUNIT, // height 0, // display offset 4, // mass 0, // damage