From 32607d61957dd4664c23e8aefafea28c0446aeb6 Mon Sep 17 00:00:00 2001 From: lachwright Date: Thu, 23 Jan 2020 01:02:44 +0800 Subject: [PATCH 1/9] Reduce severity of glide landing & move skid dust to separate function --- src/info.c | 2 +- src/p_user.c | 74 ++++++++++++++++++++++++++++++++-------------------- 2 files changed, 46 insertions(+), 30 deletions(-) diff --git a/src/info.c b/src/info.c index de6ff475c..5d403fa81 100644 --- a/src/info.c +++ b/src/info.c @@ -720,7 +720,7 @@ state_t states[NUMSTATES] = // CA_GLIDEANDCLIMB {SPR_PLAY, SPR2_GLID, 2, {NULL}, 0, 0, S_PLAY_GLIDE}, // S_PLAY_GLIDE - {SPR_PLAY, SPR2_LAND, 9, {NULL}, 0, 0, S_PLAY_STND}, // S_PLAY_GLIDE_LANDING + {SPR_PLAY, SPR2_LAND, 7, {NULL}, 0, 0, S_PLAY_STND}, // S_PLAY_GLIDE_LANDING {SPR_PLAY, SPR2_CLNG|FF_ANIMATE, -1, {NULL}, 0, 4, S_NULL}, // S_PLAY_CLING {SPR_PLAY, SPR2_CLMB, 5, {NULL}, 0, 0, S_PLAY_CLIMB}, // S_PLAY_CLIMB diff --git a/src/p_user.c b/src/p_user.c index a1df8a58b..9950cdf91 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2329,8 +2329,10 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff) P_SetPlayerMobjState(player->mo, S_PLAY_GLIDE_LANDING); S_StartSound(player->mo, sfx_s3k4c); player->pflags |= PF_STASIS; - player->mo->momx = ((player->mo->momx - player->cmomx)/3) + player->cmomx; - player->mo->momy = ((player->mo->momy - player->cmomy)/3) + player->cmomy; + if (player->speed > FixedMul(player->runspeed, player->mo->scale)) + player->skidtime += player->mo->tics; + player->mo->momx = ((player->mo->momx - player->cmomx) >> 1) + player->cmomx; + player->mo->momy = ((player->mo->momy - player->cmomy) >> 1) + player->cmomy; } } else if (player->charability2 == CA2_MELEE @@ -2380,6 +2382,8 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff) } } } + else if (player->charability == CA_GLIDEANDCLIMB && (player->mo->state-states == S_PLAY_GLIDE_LANDING)) + ; else if (player->charability2 == CA2_GUNSLINGER && player->panim == PA_ABILITY2) ; else if (player->panim != PA_IDLE && player->panim != PA_WALK && player->panim != PA_RUN && player->panim != PA_DASH) @@ -7852,6 +7856,36 @@ void P_ElementalFire(player_t *player, boolean cropcircle) } } +// +// P_SpawnSkidDust +// +// Spawns spindash dust randomly around the mobj using its radius as a bound +// +static void P_SpawnSkidDust(player_t *player, fixed_t radius, boolean sound) +{ + mobj_t *mo = player->mo; + mobj_t *particle; + + radius >>= FRACBITS; + if (radius) + particle = P_SpawnMobjFromMobj(mo, P_RandomRange(-radius, radius) << FRACBITS, P_RandomRange(-radius, radius) << FRACBITS, 0, MT_SPINDUST); + else + particle = P_SpawnMobjFromMobj(mo, 0, 0, 0, MT_SPINDUST); + particle->tics = 10; + + particle->destscale = (2*mo->scale)/3; + P_SetScale(particle, particle->destscale); + P_SetObjectMomZ(particle, FRACUNIT, false); + + if (mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER)) // overrides fire version + P_SetMobjState(particle, S_SPINDUST_BUBBLE1); + else if (player->powers[pw_shield] == SH_ELEMENTAL) + P_SetMobjState(particle, S_SPINDUST_FIRE1); + + if (sound) + S_StartSound(mo, sfx_s3k7e); // the proper "Knuckles eats dirt" sfx. +} + static void P_SkidStuff(player_t *player) { fixed_t pmx = player->rmomx + player->cmomx; @@ -7874,8 +7908,10 @@ static void P_SkidStuff(player_t *player) P_ResetPlayer(player); P_SetPlayerMobjState(player->mo, S_PLAY_GLIDE_LANDING); player->pflags |= PF_STASIS; - player->mo->momx = ((player->mo->momx - player->cmomx)/3) + player->cmomx; - player->mo->momy = ((player->mo->momy - player->cmomy)/3) + player->cmomy; + if (player->speed > FixedMul(player->runspeed, player->mo->scale)) + player->skidtime += player->mo->tics; + player->mo->momx = ((player->mo->momx - player->cmomx) >> 1) + player->cmomx; + player->mo->momy = ((player->mo->momy - player->cmomy) >> 1) + player->cmomy; } // Didn't stop yet? Skid FOREVER! else if (player->skidtime == 1) @@ -7883,20 +7919,7 @@ static void P_SkidStuff(player_t *player) // Spawn a particle every 3 tics. else if (!(player->skidtime % 3)) { - fixed_t radius = player->mo->radius >> FRACBITS; - mobj_t *particle = P_SpawnMobjFromMobj(player->mo, P_RandomRange(-radius, radius) << FRACBITS, P_RandomRange(-radius, radius) << FRACBITS, 0, MT_SPINDUST); - particle->tics = 10; - - particle->destscale = (2*player->mo->scale)/3; - P_SetScale(particle, particle->destscale); - P_SetObjectMomZ(particle, FRACUNIT, false); - - if (player->mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER)) // overrides fire version - P_SetMobjState(particle, S_SPINDUST_BUBBLE1); - else if (player->powers[pw_shield] == SH_ELEMENTAL) - P_SetMobjState(particle, S_SPINDUST_FIRE1); - - S_StartSound(player->mo, sfx_s3k7e); // the proper "Knuckles eats dirt" sfx. + P_SpawnSkidDust(player, player->mo->radius, true); } } // Skidding! @@ -7907,17 +7930,10 @@ static void P_SkidStuff(player_t *player) // Spawn a particle every 3 tics. if (!(player->skidtime % 3)) { - mobj_t *particle = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_SPINDUST); - particle->tics = 10; - - particle->destscale = (2*player->mo->scale)/3; - P_SetScale(particle, particle->destscale); - P_SetObjectMomZ(particle, FRACUNIT, false); - - if (player->mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER)) // overrides fire version - P_SetMobjState(particle, S_SPINDUST_BUBBLE1); - else if (player->powers[pw_shield] == SH_ELEMENTAL) - P_SetMobjState(particle, S_SPINDUST_FIRE1); + if (player->mo->state-states == S_PLAY_GLIDE_LANDING) + P_SpawnSkidDust(player, player->mo->radius, true); + else + P_SpawnSkidDust(player, 0, false); } } else if (P_AproxDistance(pmx, pmy) >= FixedMul(player->runspeed/2, player->mo->scale) // if you were moving faster than half your run speed last frame From 652a1984fe21d6416b33e8eda79820e1afc5f800 Mon Sep 17 00:00:00 2001 From: lachwright Date: Sun, 26 Jan 2020 03:44:10 +0800 Subject: [PATCH 2/9] Fix P_SpawnSkidDust description --- src/p_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_user.c b/src/p_user.c index 9950cdf91..ba38e190d 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -7859,7 +7859,7 @@ void P_ElementalFire(player_t *player, boolean cropcircle) // // P_SpawnSkidDust // -// Spawns spindash dust randomly around the mobj using its radius as a bound +// Spawns spindash dust randomly around the player within a certain radius. // static void P_SpawnSkidDust(player_t *player, fixed_t radius, boolean sound) { From b6106ca8c5ef00317ba6d0fa1245a80653c82aae Mon Sep 17 00:00:00 2001 From: lachwright Date: Sun, 26 Jan 2020 04:33:41 +0800 Subject: [PATCH 3/9] Don't spawn glide dust for SF_NOSKID characters --- src/p_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_user.c b/src/p_user.c index ba38e190d..fcc508688 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -7917,7 +7917,7 @@ static void P_SkidStuff(player_t *player) else if (player->skidtime == 1) player->skidtime = 3*TICRATE+1; // Spawn a particle every 3 tics. - else if (!(player->skidtime % 3)) + else if (!(player->skidtime % 3) && !(player->charflags & SF_NOSKID)) { P_SpawnSkidDust(player, player->mo->radius, true); } From 305559b3f4220a7971026154f25e2cb79021bc55 Mon Sep 17 00:00:00 2001 From: lachwright Date: Sun, 2 Feb 2020 23:07:45 +0800 Subject: [PATCH 4/9] Move climbing checks to a separate function --- src/p_local.h | 1 + src/p_map.c | 229 +---------------------------------------------- src/p_user.c | 240 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 242 insertions(+), 228 deletions(-) diff --git a/src/p_local.h b/src/p_local.h index a5f3d313c..a029b67b6 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -168,6 +168,7 @@ boolean P_AutoPause(void); void P_DoJumpShield(player_t *player); void P_DoBubbleBounce(player_t *player); +boolean P_TryClimb(player_t *player, line_t *line); void P_DoAbilityBounce(player_t *player, boolean changemomz); void P_TwinSpinRejuvenate(player_t *player, mobjtype_t type); void P_BlackOw(player_t *player); diff --git a/src/p_map.c b/src/p_map.c index 40fee7b46..2314b7964 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -3262,129 +3262,6 @@ isblocking: return false; // stop } -// -// P_IsClimbingValid -// -// Unlike P_DoClimbing, don't use when up against a one-sided linedef. -// -static boolean P_IsClimbingValid(player_t *player, angle_t angle) -{ - fixed_t platx, platy; - subsector_t *glidesector; - fixed_t floorz, ceilingz; - - platx = P_ReturnThrustX(player->mo, angle, player->mo->radius + FixedMul(8*FRACUNIT, player->mo->scale)); - platy = P_ReturnThrustY(player->mo, angle, player->mo->radius + FixedMul(8*FRACUNIT, player->mo->scale)); - - glidesector = R_PointInSubsector(player->mo->x + platx, player->mo->y + platy); - -#ifdef ESLOPE - floorz = glidesector->sector->f_slope ? P_GetZAt(glidesector->sector->f_slope, player->mo->x, player->mo->y) : glidesector->sector->floorheight; - ceilingz = glidesector->sector->c_slope ? P_GetZAt(glidesector->sector->c_slope, player->mo->x, player->mo->y) : glidesector->sector->ceilingheight; -#else - floorz = glidesector->sector->floorheight; - ceilingz = glidesector->sector->ceilingheight; -#endif - - if (glidesector->sector != player->mo->subsector->sector) - { - boolean floorclimb = false; - fixed_t topheight, bottomheight; - - if (glidesector->sector->ffloors) - { - ffloor_t *rover; - for (rover = glidesector->sector->ffloors; rover; rover = rover->next) - { - if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER)) - continue; - - topheight = *rover->topheight; - bottomheight = *rover->bottomheight; - -#ifdef ESLOPE - if (*rover->t_slope) - topheight = P_GetZAt(*rover->t_slope, player->mo->x, player->mo->y); - if (*rover->b_slope) - bottomheight = P_GetZAt(*rover->b_slope, player->mo->x, player->mo->y); -#endif - - floorclimb = true; - - if (player->mo->eflags & MFE_VERTICALFLIP) - { - if ((topheight < player->mo->z + player->mo->height) && ((player->mo->z + player->mo->height + player->mo->momz) < topheight)) - { - floorclimb = true; - } - if (topheight < player->mo->z) // Waaaay below the ledge. - { - floorclimb = false; - } - if (bottomheight > player->mo->z + player->mo->height - FixedMul(16*FRACUNIT,player->mo->scale)) - { - floorclimb = false; - } - } - else - { - if ((bottomheight > player->mo->z) && ((player->mo->z - player->mo->momz) > bottomheight)) - { - floorclimb = true; - } - if (bottomheight > player->mo->z + player->mo->height) // Waaaay below the ledge. - { - floorclimb = false; - } - if (topheight < player->mo->z + FixedMul(16*FRACUNIT,player->mo->scale)) - { - floorclimb = false; - } - } - - if (floorclimb) - break; - } - } - - if (player->mo->eflags & MFE_VERTICALFLIP) - { - if ((floorz <= player->mo->z + player->mo->height) - && ((player->mo->z + player->mo->height - player->mo->momz) <= floorz)) - floorclimb = true; - - if ((floorz > player->mo->z) - && glidesector->sector->floorpic == skyflatnum) - return false; - - if ((player->mo->z + player->mo->height - FixedMul(16*FRACUNIT,player->mo->scale) > ceilingz) - || (player->mo->z + player->mo->height <= floorz)) - floorclimb = true; - } - else - { - if ((ceilingz >= player->mo->z) - && ((player->mo->z - player->mo->momz) >= ceilingz)) - floorclimb = true; - - if ((ceilingz < player->mo->z+player->mo->height) - && glidesector->sector->ceilingpic == skyflatnum) - return false; - - if ((player->mo->z + FixedMul(16*FRACUNIT,player->mo->scale) < floorz) - || (player->mo->z >= ceilingz)) - floorclimb = true; - } - - if (!floorclimb) - return false; - - return true; - } - - return false; -} - // // PTR_SlideTraverse // @@ -3438,111 +3315,7 @@ isblocking: P_ProcessSpecialSector(slidemo->player, slidemo->subsector->sector, li->polyobj->lines[0]->backsector); } - if (slidemo->player && (slidemo->player->pflags & PF_GLIDING || slidemo->player->climbing) - && slidemo->player->charability == CA_GLIDEANDCLIMB) - { - line_t *checkline = li; - sector_t *checksector; - ffloor_t *rover; - fixed_t topheight, bottomheight; - boolean fofline = false; - INT32 side = P_PointOnLineSide(slidemo->x, slidemo->y, li); - - if (!side && li->backsector) - checksector = li->backsector; - else - checksector = li->frontsector; - - if (checksector->ffloors) - { - for (rover = checksector->ffloors; rover; rover = rover->next) - { - if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER) || (rover->flags & FF_BUSTUP)) - continue; - - topheight = *rover->topheight; - bottomheight = *rover->bottomheight; - -#ifdef ESLOPE - if (*rover->t_slope) - topheight = P_GetZAt(*rover->t_slope, slidemo->x, slidemo->y); - if (*rover->b_slope) - bottomheight = P_GetZAt(*rover->b_slope, slidemo->x, slidemo->y); -#endif - - if (topheight < slidemo->z) - continue; - - if (bottomheight > slidemo->z + slidemo->height) - continue; - - // Got this far, so I guess it's climbable. // TODO: Climbing check, also, better method to do this? - if (rover->master->flags & ML_TFERLINE) - { - size_t linenum = li-checksector->lines[0]; - checkline = rover->master->frontsector->lines[0] + linenum; - fofline = true; - } - - break; - } - } - - // see about climbing on the wall - if (!(checkline->flags & ML_NOCLIMB) && checkline->special != HORIZONSPECIAL) - { - boolean canclimb; - angle_t climbangle, climbline; - INT32 whichside = P_PointOnLineSide(slidemo->x, slidemo->y, li); - - climbangle = climbline = R_PointToAngle2(li->v1->x, li->v1->y, li->v2->x, li->v2->y); - - if (whichside) // on second side? - climbline += ANGLE_180; - - climbangle += (ANGLE_90 * (whichside ? -1 : 1)); - - canclimb = (li->backsector ? P_IsClimbingValid(slidemo->player, climbangle) : true); - - if (((!slidemo->player->climbing && abs((signed)(slidemo->angle - ANGLE_90 - climbline)) < ANGLE_45) - || (slidemo->player->climbing == 1 && abs((signed)(slidemo->angle - climbline)) < ANGLE_135)) - && canclimb) - { - slidemo->angle = climbangle; - /*if (!demoplayback || P_ControlStyle(slidemo->player) == CS_LMAOGALOG) - { - if (slidemo->player == &players[consoleplayer]) - localangle = slidemo->angle; - else if (slidemo->player == &players[secondarydisplayplayer]) - localangle2 = slidemo->angle; - }*/ - - if (!slidemo->player->climbing) - { - S_StartSound(slidemo->player->mo, sfx_s3k4a); - slidemo->player->climbing = 5; - } - - slidemo->player->pflags &= ~(PF_GLIDING|PF_SPINNING|PF_JUMPED|PF_NOJUMPDAMAGE|PF_THOKKED); - slidemo->player->glidetime = 0; - slidemo->player->secondjump = 0; - - if (slidemo->player->climbing > 1) - slidemo->momz = slidemo->momx = slidemo->momy = 0; - - if (fofline) - whichside = 0; - - if (!whichside) - { - slidemo->player->lastsidehit = checkline->sidenum[whichside]; - slidemo->player->lastlinehit = (INT16)(checkline - lines); - } - - P_Thrust(slidemo, slidemo->angle, FixedMul(5*FRACUNIT, slidemo->scale)); - } - } - } + P_TryClimb(slidemo->player, li); if (in->frac < bestslidefrac && (!slidemo->player || !slidemo->player->climbing)) { diff --git a/src/p_user.c b/src/p_user.c index 898286490..f029f7f72 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4907,6 +4907,246 @@ void P_DoBubbleBounce(player_t *player) player->mo->momz = FixedMul(player->mo->momz, 5*FRACUNIT/4); } +// +// P_IsClimbingValid +// +// Unlike P_DoClimbing, don't use when up against a one-sided linedef. +// +static boolean P_IsClimbingValid(player_t *player, angle_t angle) +{ + fixed_t platx, platy; + subsector_t *glidesector; + fixed_t floorz, ceilingz; + + platx = P_ReturnThrustX(player->mo, angle, player->mo->radius + FixedMul(8*FRACUNIT, player->mo->scale)); + platy = P_ReturnThrustY(player->mo, angle, player->mo->radius + FixedMul(8*FRACUNIT, player->mo->scale)); + + glidesector = R_PointInSubsector(player->mo->x + platx, player->mo->y + platy); + +#ifdef ESLOPE + floorz = glidesector->sector->f_slope ? P_GetZAt(glidesector->sector->f_slope, player->mo->x, player->mo->y) : glidesector->sector->floorheight; + ceilingz = glidesector->sector->c_slope ? P_GetZAt(glidesector->sector->c_slope, player->mo->x, player->mo->y) : glidesector->sector->ceilingheight; +#else + floorz = glidesector->sector->floorheight; + ceilingz = glidesector->sector->ceilingheight; +#endif + + if (glidesector->sector != player->mo->subsector->sector) + { + boolean floorclimb = false; + fixed_t topheight, bottomheight; + + if (glidesector->sector->ffloors) + { + ffloor_t *rover; + for (rover = glidesector->sector->ffloors; rover; rover = rover->next) + { + if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER)) + continue; + + topheight = *rover->topheight; + bottomheight = *rover->bottomheight; + +#ifdef ESLOPE + if (*rover->t_slope) + topheight = P_GetZAt(*rover->t_slope, player->mo->x, player->mo->y); + if (*rover->b_slope) + bottomheight = P_GetZAt(*rover->b_slope, player->mo->x, player->mo->y); +#endif + + floorclimb = true; + + if (player->mo->eflags & MFE_VERTICALFLIP) + { + if ((topheight < player->mo->z + player->mo->height) && ((player->mo->z + player->mo->height + player->mo->momz) < topheight)) + { + floorclimb = true; + } + if (topheight < player->mo->z) // Waaaay below the ledge. + { + floorclimb = false; + } + if (bottomheight > player->mo->z + player->mo->height - FixedMul(16*FRACUNIT,player->mo->scale)) + { + floorclimb = false; + } + } + else + { + if ((bottomheight > player->mo->z) && ((player->mo->z - player->mo->momz) > bottomheight)) + { + floorclimb = true; + } + if (bottomheight > player->mo->z + player->mo->height) // Waaaay below the ledge. + { + floorclimb = false; + } + if (topheight < player->mo->z + FixedMul(16*FRACUNIT,player->mo->scale)) + { + floorclimb = false; + } + } + + if (floorclimb) + break; + } + } + + if (player->mo->eflags & MFE_VERTICALFLIP) + { + if ((floorz <= player->mo->z + player->mo->height) + && ((player->mo->z + player->mo->height - player->mo->momz) <= floorz)) + floorclimb = true; + + if ((floorz > player->mo->z) + && glidesector->sector->floorpic == skyflatnum) + return false; + + if ((player->mo->z + player->mo->height - FixedMul(16*FRACUNIT,player->mo->scale) > ceilingz) + || (player->mo->z + player->mo->height <= floorz)) + floorclimb = true; + } + else + { + if ((ceilingz >= player->mo->z) + && ((player->mo->z - player->mo->momz) >= ceilingz)) + floorclimb = true; + + if ((ceilingz < player->mo->z+player->mo->height) + && glidesector->sector->ceilingpic == skyflatnum) + return false; + + if ((player->mo->z + FixedMul(16*FRACUNIT,player->mo->scale) < floorz) + || (player->mo->z >= ceilingz)) + floorclimb = true; + } + + if (!floorclimb) + return false; + + return true; + } + + return false; +} + +// P_TryClimb +// +// Attempts to climb a line from the player's current position +// Returns whether or not the line was climbed +// +boolean P_TryClimb(player_t *player, line_t *line) +{ + if (player && (player->pflags & PF_GLIDING || player->climbing) + && player->charability == CA_GLIDEANDCLIMB) + { + mobj_t *mo = player->mo; + line_t *checkline = line; + sector_t *checksector; + ffloor_t *rover; + fixed_t topheight, bottomheight; + boolean fofline = false; + INT32 side = P_PointOnLineSide(mo->x, mo->y, line); + + if (!side && line->backsector) + checksector = line->backsector; + else + checksector = line->frontsector; + + if (checksector->ffloors) + { + for (rover = checksector->ffloors; rover; rover = rover->next) + { + if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER) || (rover->flags & FF_BUSTUP)) + continue; + + topheight = *rover->topheight; + bottomheight = *rover->bottomheight; + +#ifdef ESLOPE + if (*rover->t_slope) + topheight = P_GetZAt(*rover->t_slope, mo->x, mo->y); + if (*rover->b_slope) + bottomheight = P_GetZAt(*rover->b_slope, mo->x, mo->y); +#endif + + if (topheight < mo->z) + continue; + + if (bottomheight > mo->z + mo->height) + continue; + + // Got this far, so I guess it's climbable. // TODO: Climbing check, also, better method to do this? + if (rover->master->flags & ML_TFERLINE) + { + size_t linenum = line-checksector->lines[0]; + checkline = rover->master->frontsector->lines[0] + linenum; + fofline = true; + } + + break; + } + } + + // see about climbing on the wall + if (!(checkline->flags & ML_NOCLIMB) && checkline->special != HORIZONSPECIAL) + { + boolean canclimb; + angle_t climbangle, climbline; + INT32 whichside = P_PointOnLineSide(mo->x, mo->y, line); + + climbangle = climbline = R_PointToAngle2(line->v1->x, line->v1->y, line->v2->x, line->v2->y); + + if (whichside) // on second side? + climbline += ANGLE_180; + + climbangle += (ANGLE_90 * (whichside ? -1 : 1)); + + canclimb = (line->backsector ? P_IsClimbingValid(player, climbangle) : true); + + if (((!player->climbing && abs((signed)(mo->angle - ANGLE_90 - climbline)) < ANGLE_45) + || (player->climbing == 1 && abs((signed)(mo->angle - climbline)) < ANGLE_135)) + && canclimb) + { + mo->angle = climbangle; + /*if (!demoplayback || P_ControlStyle(player) == CS_LMAOGALOG) + { + if (player == &players[consoleplayer]) + localangle = mo->angle; + else if (player == &players[secondarydisplayplayer]) + localangle2 = mo->angle; + }*/ + + if (!player->climbing) + { + S_StartSound(player->mo, sfx_s3k4a); + player->climbing = 5; + } + + player->pflags &= ~(PF_GLIDING|PF_SPINNING|PF_JUMPED|PF_NOJUMPDAMAGE|PF_THOKKED); + player->glidetime = 0; + player->secondjump = 0; + + if (player->climbing > 1) + mo->momz = mo->momx = mo->momy = 0; + + if (fofline) + whichside = 0; + + if (!whichside) + { + player->lastsidehit = checkline->sidenum[whichside]; + player->lastlinehit = (INT16)(checkline - lines); + } + + P_Thrust(mo, mo->angle, FixedMul(5*FRACUNIT, mo->scale)); + return true; + } + } + } + return false; +} + // // P_DoAbilityBounce // From 45173775528b46a66e7fb9f8b7354becddbbfadd Mon Sep 17 00:00:00 2001 From: lachwright Date: Sun, 23 Feb 2020 15:38:11 +0800 Subject: [PATCH 5/9] Start CA_GLIDEANDCLIMB swimming functionality --- src/p_mobj.c | 9 +++++++-- src/p_user.c | 27 +++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index f3f0b9ab0..d9d0f2b56 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -215,10 +215,15 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) return P_SetPlayerMobjState(mobj, S_PLAY_FALL); // Catch swimming versus flying - if (state == S_PLAY_FLY && player->mo->eflags & MFE_UNDERWATER) + if ((state == S_PLAY_FLY || state == S_PLAY_GLIDE) && player->mo->eflags & MFE_UNDERWATER && !player->skidtime) return P_SetPlayerMobjState(player->mo, S_PLAY_SWIM); else if (state == S_PLAY_SWIM && !(player->mo->eflags & MFE_UNDERWATER)) - return P_SetPlayerMobjState(player->mo, S_PLAY_FLY); + { + if (player->charability == CA_GLIDEANDCLIMB) + return P_SetPlayerMobjState(player->mo, S_PLAY_GLIDE); + else + return P_SetPlayerMobjState(player->mo, S_PLAY_FLY); + } // Catch SF_NOSUPERSPIN jumps for Supers if (player->powers[pw_super] && (player->charflags & SF_NOSUPERSPIN)) diff --git a/src/p_user.c b/src/p_user.c index e2a7943f1..a01267b73 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2344,6 +2344,7 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff) if (dorollstuff) { player->skidtime = TICRATE; + P_SetPlayerMobjState(player->mo, S_PLAY_GLIDE); player->mo->tics = -1; } else if (!player->skidtime) @@ -8583,6 +8584,32 @@ static void P_MovePlayer(player_t *player) if (!player->skidtime) // TODO: make sure this works in 2D! { + /*angle_t anglediff = angle - moveangle; + fixed_t scale = mo->scale; + fixed_t accelfactor = 4*FRACUNIT - 3*FINECOSINE(((angle-moveangle) >> ANGLETOFINESHIFT) & FINEMASK); // mamgic number BAD but this feels right + fixed_t speed = FixedHypot(momx, momy); + fixed_t minspeed; + + if (anglediff > ANGLE_180) + anglediff = InvAngle(InvAngle(anglediff) >> 4); + else + anglediff = anglediff >> 4; + + if (mo->eflags & MFE_UNDERWATER) + minspeed = FixedMul((glidespeed>>1) + player->glidetime*750, scale); + else + minspeed = FixedMul(glidespeed + player->glidetime*1500, scale); + + if (speed < minspeed) + { + momx += P_ReturnThrustX(mo, angle, FixedMul(accelfactor, scale)); + momy += P_ReturnThrustY(mo, angle, FixedMul(accelfactor, scale)); + speed = FixedHypot(momx, momy); // recalculate speed + } + + mo->momx = P_ReturnThrustX(mo, moveangle + anglediff, speed) + player->cmomx; + mo->momy = P_ReturnThrustY(mo, moveangle + anglediff, speed) + player->cmomy;*/ + fixed_t speed, scale = mo->scale; fixed_t newMagnitude, oldMagnitude = R_PointToDist2(momx, momy, 0, 0); fixed_t accelfactor = 4*FRACUNIT - 3*FINECOSINE(((angle-moveangle) >> ANGLETOFINESHIFT) & FINEMASK); // mamgic number BAD but this feels right From 8652bbc1a56c327eee13d8fbb61e6bbeba0bd5d9 Mon Sep 17 00:00:00 2001 From: lachwright Date: Sat, 4 Jul 2020 01:54:00 +0800 Subject: [PATCH 6/9] Knuckles changes: - Buffed crouch landing; lasts slightly shorter and cuts speed less - Support for swimming! Knuckles has slightly different glide controls when he has swim sprites underwater - Improved glide controls in 2D mode - Super Knuckles perks: land from a glide or latch onto a wall to generate a shockwave and damage nearby enemies - Refactored skid dust - Made super sparks use FF_FULLBRIGHT - Added P_SpawnSkidDust and P_Earthquake to Lua --- src/d_player.h | 1 + src/dehacked.c | 1 + src/info.c | 10 +- src/lua_baselib.c | 28 +++++ src/p_local.h | 2 + src/p_map.c | 7 +- src/p_mobj.c | 3 +- src/p_user.c | 283 ++++++++++++++++++++++++++++------------------ 8 files changed, 218 insertions(+), 117 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index fba2a6837..2c4483775 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -49,6 +49,7 @@ typedef enum SF_MULTIABILITY = 1<<13, // Revenge of Final Demo. SF_NONIGHTSROTATION = 1<<14, // Disable sprite rotation for NiGHTS SF_NONIGHTSSUPER = 1<<15, // Disable super colors for NiGHTS (if you have SF_SUPER) + SF_NOSUPERJUMPBOOST = 1<<16, // Disable the jump boost given while super (i.e. Knuckles) // free up to and including 1<<31 } skinflags_t; diff --git a/src/dehacked.c b/src/dehacked.c index 78120c5c4..de93ce50e 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -9655,6 +9655,7 @@ struct { {"SF_MULTIABILITY",SF_MULTIABILITY}, {"SF_NONIGHTSROTATION",SF_NONIGHTSROTATION}, {"SF_NONIGHTSSUPER",SF_NONIGHTSSUPER}, + {"SF_NOSUPERJUMPBOOST",SF_NOSUPERJUMPBOOST}, // Dashmode constants {"DASHMODE_THRESHOLD",DASHMODE_THRESHOLD}, diff --git a/src/info.c b/src/info.c index 62048b64a..a9619d7c7 100644 --- a/src/info.c +++ b/src/info.c @@ -2929,11 +2929,11 @@ state_t states[NUMSTATES] = {SPR_IVSP, FF_ANIMATE, 32, {NULL}, 31, 1, S_NULL}, // S_IVSP // Super Sonic Spark - {SPR_SSPK, 0, 2, {NULL}, 0, 0, S_SSPK2}, // S_SSPK1 - {SPR_SSPK, 1, 2, {NULL}, 0, 0, S_SSPK3}, // S_SSPK2 - {SPR_SSPK, 2, 2, {NULL}, 0, 0, S_SSPK4}, // S_SSPK3 - {SPR_SSPK, 1, 2, {NULL}, 0, 0, S_SSPK5}, // S_SSPK4 - {SPR_SSPK, 0, 2, {NULL}, 0, 0, S_NULL}, // S_SSPK5 + {SPR_SSPK, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_SSPK2}, // S_SSPK1 + {SPR_SSPK, 1|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_SSPK3}, // S_SSPK2 + {SPR_SSPK, 2|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_SSPK4}, // S_SSPK3 + {SPR_SSPK, 1|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_SSPK5}, // S_SSPK4 + {SPR_SSPK, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_SSPK5 // Flicky-sized bubble {SPR_FBUB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_FLICKY_BUBBLE diff --git a/src/lua_baselib.c b/src/lua_baselib.c index db70a11a2..53bb6e328 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -1259,6 +1259,19 @@ static int lib_pElementalFire(lua_State *L) return 0; } +static int lib_pSpawnSkidDust(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + fixed_t radius = luaL_checkfixed(L, 2); + boolean sound = lua_optboolean(L, 3); + NOHUD + INLEVEL + if (!player) + return LUA_ErrInvalid(L, "player_t"); + P_SpawnSkidDust(player, radius, sound); + return 0; +} + static int lib_pDoPlayerFinish(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); @@ -1346,6 +1359,19 @@ static int lib_pNukeEnemies(lua_State *L) return 0; } +static int lib_pEarthquake(lua_State *L) +{ + mobj_t *inflictor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + mobj_t *source = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); + fixed_t radius = luaL_checkfixed(L, 3); + NOHUD + INLEVEL + if (!inflictor || !source) + return LUA_ErrInvalid(L, "mobj_t"); + P_Earthquake(inflictor, source, radius); + return 0; +} + static int lib_pHomingAttack(lua_State *L) { mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); @@ -3262,6 +3288,7 @@ static luaL_Reg lib[] = { {"P_DoBubbleBounce",lib_pDoBubbleBounce}, {"P_BlackOw",lib_pBlackOw}, {"P_ElementalFire",lib_pElementalFire}, + {"P_SpawnSkidDust", lib_pSpawnSkidDust}, {"P_DoPlayerFinish",lib_pDoPlayerFinish}, {"P_DoPlayerExit",lib_pDoPlayerExit}, {"P_InstaThrust",lib_pInstaThrust}, @@ -3269,6 +3296,7 @@ static luaL_Reg lib[] = { {"P_ReturnThrustY",lib_pReturnThrustY}, {"P_LookForEnemies",lib_pLookForEnemies}, {"P_NukeEnemies",lib_pNukeEnemies}, + {"P_Earthquake",lib_pEarthquake}, {"P_HomingAttack",lib_pHomingAttack}, {"P_SuperReady",lib_pSuperReady}, {"P_DoJump",lib_pDoJump}, diff --git a/src/p_local.h b/src/p_local.h index e89343ca8..f10975702 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -175,6 +175,7 @@ void P_DoAbilityBounce(player_t *player, boolean changemomz); void P_TwinSpinRejuvenate(player_t *player, mobjtype_t type); void P_BlackOw(player_t *player); void P_ElementalFire(player_t *player, boolean cropcircle); +void P_SpawnSkidDust(player_t *player, fixed_t radius, boolean sound); void P_DoPityCheck(player_t *player); void P_PlayerThink(player_t *player); @@ -192,6 +193,7 @@ mobj_t *P_LookForFocusTarget(player_t *player, mobj_t *exclude, SINT8 direction, mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet); void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius); +void P_Earthquake(mobj_t *inflictor, mobj_t *source, fixed_t radius); boolean P_HomingAttack(mobj_t *source, mobj_t *enemy); /// \todo doesn't belong in p_user boolean P_SuperReady(player_t *player); void P_DoJump(player_t *player, boolean soundandstate); diff --git a/src/p_map.c b/src/p_map.c index 18d6a1853..acfffc901 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -3373,8 +3373,13 @@ static void PTR_GlideClimbTraverse(line_t *li) if (!slidemo->player->climbing) { - S_StartSound(slidemo->player->mo, sfx_s3k4a); + S_StartSound(slidemo, sfx_s3k4a); slidemo->player->climbing = 5; + if (slidemo->player->powers[pw_super]) + { + P_Earthquake(slidemo, slidemo, 256*slidemo->scale); + S_StartSound(slidemo, sfx_s3k49); + } } slidemo->player->pflags &= ~(PF_GLIDING|PF_SPINNING|PF_JUMPED|PF_NOJUMPDAMAGE|PF_THOKKED); diff --git a/src/p_mobj.c b/src/p_mobj.c index 40d0755b3..e2d93611d 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -211,7 +211,8 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) return P_SetPlayerMobjState(mobj, S_PLAY_FALL); // Catch swimming versus flying - if ((state == S_PLAY_FLY || state == S_PLAY_GLIDE) && player->mo->eflags & MFE_UNDERWATER && !player->skidtime) + if ((state == S_PLAY_FLY || (state == S_PLAY_GLIDE && skins[player->skin].sprites[SPR2_SWIM].numframes)) + && player->mo->eflags & MFE_UNDERWATER && !player->skidtime) return P_SetPlayerMobjState(player->mo, S_PLAY_SWIM); else if (state == S_PLAY_SWIM && !(player->mo->eflags & MFE_UNDERWATER)) { diff --git a/src/p_user.c b/src/p_user.c index 7a51e7bf3..9d23143b3 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2322,6 +2322,7 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff) } else { + P_MobjCheckWater(player->mo); if (player->pflags & PF_SPINNING) { if (player->mo->state-states != S_PLAY_ROLL && !(player->pflags & PF_STARTDASH)) @@ -2336,23 +2337,31 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff) { player->skidtime = TICRATE; P_SetPlayerMobjState(player->mo, S_PLAY_GLIDE); + P_SpawnSkidDust(player, player->mo->radius, true); // make sure the player knows they landed player->mo->tics = -1; } else if (!player->skidtime) player->pflags &= ~PF_GLIDING; } - else if (player->charability == CA_GLIDEANDCLIMB && player->pflags & PF_THOKKED && !(player->pflags & (PF_JUMPED|PF_SHIELDABILITY)) && player->mo->state-states == S_PLAY_FALL) + else if (player->charability == CA_GLIDEANDCLIMB && player->pflags & PF_THOKKED && !(player->pflags & (PF_JUMPED|PF_SHIELDABILITY)) + && (player->mo->floorz != player->mo->watertop) && player->mo->state-states == S_PLAY_FALL) { if (player->mo->state-states != S_PLAY_GLIDE_LANDING) { P_ResetPlayer(player); P_SetPlayerMobjState(player->mo, S_PLAY_GLIDE_LANDING); - S_StartSound(player->mo, sfx_s3k4c); player->pflags |= PF_STASIS; if (player->speed > FixedMul(player->runspeed, player->mo->scale)) player->skidtime += player->mo->tics; - player->mo->momx = ((player->mo->momx - player->cmomx) >> 1) + player->cmomx; - player->mo->momy = ((player->mo->momy - player->cmomy) >> 1) + player->cmomy; + player->mo->momx = ((player->mo->momx - player->cmomx)/2) + player->cmomx; + player->mo->momy = ((player->mo->momy - player->cmomy)/2) + player->cmomy; + if (player->powers[pw_super]) + { + P_Earthquake(player->mo, player->mo, 256*player->mo->scale); + S_StartSound(player->mo, sfx_s3k49); + } + else + S_StartSound(player->mo, sfx_s3k4c); } } else if (player->charability2 == CA2_MELEE @@ -4447,7 +4456,7 @@ void P_DoJump(player_t *player, boolean soundandstate) } else if (maptol & TOL_NIGHTS) player->mo->momz = 18*FRACUNIT; - else if (player->powers[pw_super]) + else if (player->powers[pw_super] && !(player->charflags & SF_NOSUPERJUMPBOOST)) { player->mo->momz = 13*FRACUNIT; @@ -5346,8 +5355,11 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) { glidespeed >>= 1; playerspeed >>= 1; - player->mo->momx = ((player->mo->momx - player->cmomx) >> 1) + player->cmomx; - player->mo->momy = ((player->mo->momy - player->cmomy) >> 1) + player->cmomy; + if (!(player->powers[pw_super] || player->powers[pw_sneakers])) + { + player->mo->momx = ((player->mo->momx - player->cmomx)/2) + player->cmomx; + player->mo->momy = ((player->mo->momy - player->cmomy)/2) + player->cmomy; + } } player->pflags |= PF_GLIDING|PF_THOKKED; @@ -5774,7 +5786,7 @@ static void P_2dMovement(player_t *player) if (player->climbing) { if (cmd->forwardmove != 0) - P_SetObjectMomZ(player->mo, FixedDiv(cmd->forwardmove*FRACUNIT, 15*FRACUNIT>>1), false); + P_SetObjectMomZ(player->mo, FixedDiv(cmd->forwardmove*FRACUNIT, player->powers[pw_super] ? 5*FRACUNIT : 15*FRACUNIT>>1), false); // 2/3 while super player->mo->momx = 0; } @@ -5989,9 +6001,9 @@ static void P_3dMovement(player_t *player) if (cmd->forwardmove) { if (player->mo->eflags & MFE_UNDERWATER) - P_SetObjectMomZ(player->mo, FixedDiv(cmd->forwardmove*FRACUNIT, 10*FRACUNIT), false); + P_SetObjectMomZ(player->mo, FixedDiv(cmd->forwardmove*FRACUNIT, player->powers[pw_super] ? 20*FRACUNIT/3 : 10*FRACUNIT), false); // 2/3 while super else - P_SetObjectMomZ(player->mo, FixedDiv(cmd->forwardmove*FRACUNIT, 15*FRACUNIT>>1), false); + P_SetObjectMomZ(player->mo, FixedDiv(cmd->forwardmove*FRACUNIT, player->powers[pw_super] ? 5*FRACUNIT : 15*FRACUNIT>>1), false); // 2/3 while super } } else if (!(controlstyle == CS_LMAOGALOG) @@ -6024,9 +6036,9 @@ static void P_3dMovement(player_t *player) if (player->climbing) { if (player->mo->eflags & MFE_UNDERWATER) - P_InstaThrust(player->mo, player->mo->angle-ANGLE_90, FixedDiv(cmd->sidemove*player->mo->scale, 10*FRACUNIT)); + P_InstaThrust(player->mo, player->mo->angle-ANGLE_90, FixedDiv(cmd->sidemove*player->mo->scale, player->powers[pw_super] ? 20*FRACUNIT/3 : 10*FRACUNIT)); // 2/3 while super else - P_InstaThrust(player->mo, player->mo->angle-ANGLE_90, FixedDiv(cmd->sidemove*player->mo->scale, 15*FRACUNIT>>1)); + P_InstaThrust(player->mo, player->mo->angle-ANGLE_90, FixedDiv(cmd->sidemove*player->mo->scale, player->powers[pw_super] ? 5*FRACUNIT : 15*FRACUNIT>>1)); // 2/3 while super } // Analog movement control else if (controlstyle == CS_LMAOGALOG) @@ -7759,7 +7771,7 @@ void P_ElementalFire(player_t *player, boolean cropcircle) // // Spawns spindash dust randomly around the player within a certain radius. // -static void P_SpawnSkidDust(player_t *player, fixed_t radius, boolean sound) +void P_SpawnSkidDust(player_t *player, fixed_t radius, boolean sound) { mobj_t *mo = player->mo; mobj_t *particle; @@ -7797,7 +7809,7 @@ static void P_SkidStuff(player_t *player) { player->skidtime = 0; player->pflags &= ~(PF_GLIDING|PF_JUMPED|PF_NOJUMPDAMAGE); - player->pflags |= PF_THOKKED; // nice try, speedrunners (but for real this is just behavior from S3K) + player->pflags |= PF_THOKKED; P_SetPlayerMobjState(player->mo, S_PLAY_FALL); } // Get up and brush yourself off, idiot. @@ -7808,8 +7820,8 @@ static void P_SkidStuff(player_t *player) player->pflags |= PF_STASIS; if (player->speed > FixedMul(player->runspeed, player->mo->scale)) player->skidtime += player->mo->tics; - player->mo->momx = ((player->mo->momx - player->cmomx) >> 1) + player->cmomx; - player->mo->momy = ((player->mo->momy - player->cmomy) >> 1) + player->cmomy; + player->mo->momx = ((player->mo->momx - player->cmomx)/2) + player->cmomx; + player->mo->momy = ((player->mo->momy - player->cmomy)/2) + player->cmomy; } // Didn't stop yet? Skid FOREVER! else if (player->skidtime == 1) @@ -8192,10 +8204,11 @@ static void P_MovePlayer(player_t *player) if (player->pflags & PF_GLIDING) { mobj_t *mo = player->mo; // seriously why isn't this at the top of the function hngngngng - fixed_t leeway = (P_ControlStyle(player) != CS_LMAOGALOG) ? FixedAngle(cmd->sidemove*(FRACUNIT)) : 0; fixed_t glidespeed = player->actionspd; fixed_t momx = mo->momx - player->cmomx, momy = mo->momy - player->cmomy; angle_t angle, moveangle = R_PointToAngle2(0, 0, momx, momy); + boolean swimming = mo->state - states == S_PLAY_SWIM; + boolean in2d = mo->flags2 & MF2_TWOD || twodlevel; if (player->powers[pw_super] || player->powers[pw_sneakers]) glidespeed *= 2; @@ -8212,42 +8225,83 @@ static void P_MovePlayer(player_t *player) } // Strafing while gliding. - angle = mo->angle - leeway; + if ((P_ControlStyle(player) & CS_LMAOGALOG) || in2d) + angle = mo->angle; + else if (swimming) + angle = mo->angle + R_PointToAngle2(0, 0, cmd->forwardmove<sidemove<angle - FixedAngle(cmd->sidemove * FRACUNIT); if (!player->skidtime) // TODO: make sure this works in 2D! { + angle_t anglediff = angle - moveangle; + fixed_t accelfactor = 4*FRACUNIT - 3*FINECOSINE((anglediff >> ANGLETOFINESHIFT) & FINEMASK); fixed_t speed, scale = mo->scale; - fixed_t newMagnitude, oldMagnitude = R_PointToDist2(momx, momy, 0, 0); - fixed_t accelfactor = 4*FRACUNIT - 3*FINECOSINE(((angle-moveangle) >> ANGLETOFINESHIFT) & FINEMASK); // mamgic number BAD but this feels right - if (mo->eflags & MFE_UNDERWATER) - speed = FixedMul((glidespeed>>1) + player->glidetime*750, scale); - else - speed = FixedMul(glidespeed + player->glidetime*1500, scale); - - P_Thrust(mo, angle, FixedMul(accelfactor, scale)); - - newMagnitude = R_PointToDist2(player->mo->momx - player->cmomx, player->mo->momy - player->cmomy, 0, 0); - if (newMagnitude > speed) + if (in2d) { - fixed_t tempmomx, tempmomy; - if (oldMagnitude > speed) + if (mo->eflags & MFE_UNDERWATER) + speed = FixedMul((glidespeed>>1) + player->glidetime*750, scale); + else + speed = FixedMul(glidespeed + player->glidetime*1500, scale); + P_InstaThrust(mo, angle, speed); + } + else if (swimming) + { + fixed_t minspeed; + + if (anglediff > ANGLE_180) + anglediff = InvAngle(InvAngle(anglediff) >> 3); + else + anglediff = anglediff >> 3; + + minspeed = FixedMul((glidespeed>>1) + player->glidetime*750, scale); // underwater-specific + speed = FixedHypot(momx, momy) - abs(P_ReturnThrustY(mo, anglediff, mo->scale)); + + if (speed < minspeed) { - if (newMagnitude > oldMagnitude) + momx += P_ReturnThrustX(mo, angle, FixedMul(accelfactor, scale)); + momy += P_ReturnThrustY(mo, angle, FixedMul(accelfactor, scale)); + speed = FixedHypot(momx, momy); // recalculate speed + } + + mo->momx = P_ReturnThrustX(mo, moveangle + anglediff, speed) + player->cmomx; + mo->momy = P_ReturnThrustY(mo, moveangle + anglediff, speed) + player->cmomy; + } + else + { + fixed_t newMagnitude, oldMagnitude = R_PointToDist2(momx, momy, 0, 0); + fixed_t accelfactor = 4*FRACUNIT - 3*FINECOSINE(((angle-moveangle) >> ANGLETOFINESHIFT) & FINEMASK); + + if (mo->eflags & MFE_UNDERWATER) + speed = FixedMul((glidespeed>>1) + player->glidetime*750, scale); + else + speed = FixedMul(glidespeed + player->glidetime*1500, scale); + + P_Thrust(mo, angle, FixedMul(accelfactor, scale)); + + newMagnitude = R_PointToDist2(player->mo->momx - player->cmomx, player->mo->momy - player->cmomy, 0, 0); + if (newMagnitude > speed) + { + fixed_t tempmomx, tempmomy; + if (oldMagnitude > speed) { - tempmomx = FixedMul(FixedDiv(player->mo->momx - player->cmomx, newMagnitude), oldMagnitude); - tempmomy = FixedMul(FixedDiv(player->mo->momy - player->cmomy, newMagnitude), oldMagnitude); + if (newMagnitude > oldMagnitude) + { + tempmomx = FixedMul(FixedDiv(player->mo->momx - player->cmomx, newMagnitude), oldMagnitude); + tempmomy = FixedMul(FixedDiv(player->mo->momy - player->cmomy, newMagnitude), oldMagnitude); + player->mo->momx = tempmomx + player->cmomx; + player->mo->momy = tempmomy + player->cmomy; + } + // else do nothing + } + else + { + tempmomx = FixedMul(FixedDiv(player->mo->momx - player->cmomx, newMagnitude), speed); + tempmomy = FixedMul(FixedDiv(player->mo->momy - player->cmomy, newMagnitude), speed); player->mo->momx = tempmomx + player->cmomx; player->mo->momy = tempmomy + player->cmomy; } - // else do nothing - } - else - { - tempmomx = FixedMul(FixedDiv(player->mo->momx - player->cmomx, newMagnitude), speed); - tempmomy = FixedMul(FixedDiv(player->mo->momy - player->cmomy, newMagnitude), speed); - player->mo->momx = tempmomx + player->cmomx; - player->mo->momy = tempmomy + player->cmomy; } } } @@ -8563,6 +8617,7 @@ static void P_MovePlayer(player_t *player) || ((player->pflags & PF_JUMPED) && !(player->pflags & PF_NOJUMPDAMAGE)) || (player->pflags & PF_SPINNING) || player->powers[pw_tailsfly] || player->pflags & PF_GLIDING + || (player->charability == CA_GLIDEANDCLIMB && player->mo->state-states == S_PLAY_GLIDE_LANDING) || (player->charability == CA_FLY && player->mo->state-states == S_PLAY_FLY_TIRED)) player->mo->height = P_GetPlayerSpinHeight(player); else @@ -8628,74 +8683,6 @@ static void P_MovePlayer(player_t *player) if (CheckForBustableBlocks) P_CheckBustableBlocks(player); - // Special handling for - // gliding in 2D mode - if ((twodlevel || player->mo->flags2 & MF2_TWOD) && player->pflags & PF_GLIDING && player->charability == CA_GLIDEANDCLIMB - && !(player->mo->flags & MF_NOCLIP)) - { - msecnode_t *node; // only place it's being used in P_MovePlayer now - fixed_t oldx; - fixed_t oldy; - fixed_t floorz, ceilingz; - - oldx = player->mo->x; - oldy = player->mo->y; - - P_UnsetThingPosition(player->mo); - player->mo->x += player->mo->momx; - player->mo->y += player->mo->momy; - P_SetThingPosition(player->mo); - - for (node = player->mo->touching_sectorlist; node; node = node->m_sectorlist_next) - { - if (!node->m_sector) - break; - - if (node->m_sector->ffloors) - { - ffloor_t *rover; - fixed_t topheight, bottomheight; - - for (rover = node->m_sector->ffloors; rover; rover = rover->next) - { - if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER)) - continue; - - topheight = P_GetFOFTopZ(player->mo, node->m_sector, rover, player->mo->x, player->mo->y, NULL); - bottomheight = P_GetFOFBottomZ(player->mo, node->m_sector, rover, player->mo->x, player->mo->y, NULL); - if (topheight > player->mo->z && bottomheight < player->mo->z) - { - P_ResetPlayer(player); - S_StartSound(player->mo, sfx_s3k4a); - player->climbing = 5; - player->mo->momx = player->mo->momy = player->mo->momz = 0; - break; - } - } - } - - floorz = P_GetFloorZ(player->mo, node->m_sector, player->mo->x, player->mo->y, NULL); - ceilingz = P_GetCeilingZ(player->mo, node->m_sector, player->mo->x, player->mo->y, NULL); - - if (player->mo->z+player->mo->height > ceilingz - && node->m_sector->ceilingpic == skyflatnum) - continue; - - if (floorz > player->mo->z || ceilingz < player->mo->z) - { - P_ResetPlayer(player); - S_StartSound(player->mo, sfx_s3k4a); - player->climbing = 5; - player->mo->momx = player->mo->momy = player->mo->momz = 0; - break; - } - } - P_UnsetThingPosition(player->mo); - player->mo->x = oldx; - player->mo->y = oldy; - P_SetThingPosition(player->mo); - } - // Check for a BOUNCY sector! if (CheckForBouncySector) P_CheckBouncySectors(player); @@ -9001,6 +8988,82 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius) } } +// +// P_Earthquake +// Used for Super Knuckles' landing - damages enemies within the given radius +// If inflictor is grounded, only grounded enemies are hurt +// +void P_Earthquake(mobj_t *inflictor, mobj_t *source, fixed_t radius) +{ + const fixed_t ns = radius/12; + mobj_t *mo; + angle_t fa; + thinker_t *think; + INT32 i; + boolean grounded = P_IsObjectOnGround(inflictor); + + for (i = 0; i < 16; i++) + { + fa = (i*(FINEANGLES/16)); + mo = P_SpawnMobjFromMobj(inflictor, 0, 0, 0, MT_SUPERSPARK); + if (!P_MobjWasRemoved(mo)) + { + if (grounded) + { + mo->momx = FixedMul(FINESINE(fa),ns); + mo->momy = FixedMul(FINECOSINE(fa),ns); + } + else + { + P_InstaThrust(mo, inflictor->angle + ANGLE_90, FixedMul(FINECOSINE(fa),ns)); + mo->momz = FixedMul(FINESINE(fa),ns); + } + } + } + + if (inflictor->player && P_IsLocalPlayer(inflictor->player)) + { + quake.epicenter = NULL; + quake.intensity = 8*FRACUNIT; + quake.time = 8; + quake.radius = radius; + } + + for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) + { + if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + + mo = (mobj_t *)think; + + if (grounded && !P_IsObjectOnGround(mo)) + continue; + + if (!(mo->flags & MF_SHOOTABLE) && !(mo->type == MT_EGGGUARD || mo->type == MT_MINUS)) + continue; + + if (mo->flags & MF_MONITOR) + continue; // Monitors cannot be 'nuked'. + + if (mo->type == MT_PLAYER) + continue; // Don't hurt players + + if (abs(inflictor->x - mo->x) > radius || abs(inflictor->y - mo->y) > radius || abs(inflictor->z - mo->z) > radius) + continue; // Workaround for possible integer overflow in the below -Red + + if (P_AproxDistance(P_AproxDistance(inflictor->x - mo->x, inflictor->y - mo->y), inflictor->z - mo->z) > radius) + continue; + + if (mo->type == MT_MINUS && !(mo->flags & (MF_SPECIAL|MF_SHOOTABLE))) + mo->flags = (mo->flags & ~MF_NOCLIPTHING)|MF_SPECIAL|MF_SHOOTABLE; + + if (mo->type == MT_EGGGUARD && mo->tracer) //nuke Egg Guard's shield! + P_KillMobj(mo->tracer, inflictor, source, 0); + + P_DamageMobj(mo, inflictor, source, 1, 0); + } +} + // // P_LookForFocusTarget // Looks for a target for a player to focus on, for Z-targeting etc. From 7e72009a87bd27d4f3acd7c2c923eee8fa350c31 Mon Sep 17 00:00:00 2001 From: Lachlan Date: Sat, 4 Jul 2020 03:21:48 +0800 Subject: [PATCH 7/9] Fix buildbot warning --- src/p_user.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/p_user.c b/src/p_user.c index 9d23143b3..beb2eedb1 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8271,7 +8271,6 @@ static void P_MovePlayer(player_t *player) else { fixed_t newMagnitude, oldMagnitude = R_PointToDist2(momx, momy, 0, 0); - fixed_t accelfactor = 4*FRACUNIT - 3*FINECOSINE(((angle-moveangle) >> ANGLETOFINESHIFT) & FINEMASK); if (mo->eflags & MFE_UNDERWATER) speed = FixedMul((glidespeed>>1) + player->glidetime*750, scale); From 84000a0add2643b68f9b603d699f45ccc6fed7fd Mon Sep 17 00:00:00 2001 From: Lachlan Date: Sat, 4 Jul 2020 04:00:28 +0800 Subject: [PATCH 8/9] P_Earthquake: Use P_RadiusAttack in favor of thinker iteration --- src/p_map.c | 2 +- src/p_user.c | 45 ++++++--------------------------------------- 2 files changed, 7 insertions(+), 40 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index acfffc901..a8cb33f1b 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -3377,7 +3377,7 @@ static void PTR_GlideClimbTraverse(line_t *li) slidemo->player->climbing = 5; if (slidemo->player->powers[pw_super]) { - P_Earthquake(slidemo, slidemo, 256*slidemo->scale); + P_Earthquake(slidemo, slidemo, 256*FRACUNIT); S_StartSound(slidemo, sfx_s3k49); } } diff --git a/src/p_user.c b/src/p_user.c index beb2eedb1..f973a7726 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2357,7 +2357,7 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff) player->mo->momy = ((player->mo->momy - player->cmomy)/2) + player->cmomy; if (player->powers[pw_super]) { - P_Earthquake(player->mo, player->mo, 256*player->mo->scale); + P_Earthquake(player->mo, player->mo, 256*FRACUNIT); S_StartSound(player->mo, sfx_s3k49); } else @@ -8990,14 +8990,13 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius) // // P_Earthquake // Used for Super Knuckles' landing - damages enemies within the given radius -// If inflictor is grounded, only grounded enemies are hurt // void P_Earthquake(mobj_t *inflictor, mobj_t *source, fixed_t radius) { - const fixed_t ns = radius/12; + const fixed_t scaledradius = FixedMul(radius, inflictor->scale); + const fixed_t ns = scaledradius/12; mobj_t *mo; angle_t fa; - thinker_t *think; INT32 i; boolean grounded = P_IsObjectOnGround(inflictor); @@ -9023,44 +9022,12 @@ void P_Earthquake(mobj_t *inflictor, mobj_t *source, fixed_t radius) if (inflictor->player && P_IsLocalPlayer(inflictor->player)) { quake.epicenter = NULL; - quake.intensity = 8*FRACUNIT; + quake.intensity = 8*inflictor->scale; quake.time = 8; - quake.radius = radius; + quake.radius = scaledradius; } - for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) - { - if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) - continue; - - mo = (mobj_t *)think; - - if (grounded && !P_IsObjectOnGround(mo)) - continue; - - if (!(mo->flags & MF_SHOOTABLE) && !(mo->type == MT_EGGGUARD || mo->type == MT_MINUS)) - continue; - - if (mo->flags & MF_MONITOR) - continue; // Monitors cannot be 'nuked'. - - if (mo->type == MT_PLAYER) - continue; // Don't hurt players - - if (abs(inflictor->x - mo->x) > radius || abs(inflictor->y - mo->y) > radius || abs(inflictor->z - mo->z) > radius) - continue; // Workaround for possible integer overflow in the below -Red - - if (P_AproxDistance(P_AproxDistance(inflictor->x - mo->x, inflictor->y - mo->y), inflictor->z - mo->z) > radius) - continue; - - if (mo->type == MT_MINUS && !(mo->flags & (MF_SPECIAL|MF_SHOOTABLE))) - mo->flags = (mo->flags & ~MF_NOCLIPTHING)|MF_SPECIAL|MF_SHOOTABLE; - - if (mo->type == MT_EGGGUARD && mo->tracer) //nuke Egg Guard's shield! - P_KillMobj(mo->tracer, inflictor, source, 0); - - P_DamageMobj(mo, inflictor, source, 1, 0); - } + P_RadiusAttack(inflictor, source, radius, 0); } // From e44d93f76b4e51cf71ee4a6abdc5bc0e187abb5b Mon Sep 17 00:00:00 2001 From: Lachlan Date: Sat, 4 Jul 2020 04:30:57 +0800 Subject: [PATCH 9/9] Fix skiddust positional scaling --- src/p_user.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index f973a7726..84fbd2e81 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -7776,11 +7776,14 @@ void P_SpawnSkidDust(player_t *player, fixed_t radius, boolean sound) mobj_t *mo = player->mo; mobj_t *particle; - radius >>= FRACBITS; - if (radius) - particle = P_SpawnMobjFromMobj(mo, P_RandomRange(-radius, radius) << FRACBITS, P_RandomRange(-radius, radius) << FRACBITS, 0, MT_SPINDUST); - else - particle = P_SpawnMobjFromMobj(mo, 0, 0, 0, MT_SPINDUST); + particle = P_SpawnMobjFromMobj(mo, 0, 0, 0, MT_SPINDUST); + if (radius >>= FRACBITS) + { + P_UnsetThingPosition(particle); + particle->x += P_RandomRange(-radius, radius) << FRACBITS; + particle->y += P_RandomRange(-radius, radius) << FRACBITS; + P_SetThingPosition(particle); + } particle->tics = 10; particle->destscale = (2*mo->scale)/3;