From 45a99ce318f32009eeb0de525db07160f4689ab7 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 18 Sep 2019 12:26:34 +0100 Subject: [PATCH 01/12] Change startchar's default value to 0 (Resolves #222). --- src/m_menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index d05048a9d..d3442fcf9 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -118,7 +118,7 @@ const char *quitmsg[NUM_QUITMESSAGES]; // Stuff for customizing the player select screen Tails 09-22-2003 description_t description[MAXSKINS]; -INT16 char_on = -1, startchar = 1; +INT16 char_on = -1, startchar = 0; static char *char_notes = NULL; static fixed_t char_scroll = 0; From e230d7351c379818ab0ae188456fe267b27aec1c Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 18 Sep 2019 12:46:18 +0100 Subject: [PATCH 02/12] Completely untested cuz I need to commit before I can merge the compile fix, but the intent of this commit is: * Fix S_PLAY_FLY_TIRED animation being fast. * Add moving tails to S_PLAY_SWIM animation! * Fix autobrake happening when your controls are locked by pw_nocontrol/PF_STASIS. (Resolves #219, hopefully..?) --- src/p_user.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index 43138d2e9..ff887a171 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8200,7 +8200,7 @@ static void P_MovePlayer(player_t *player) else { // Tails-gets-tired Stuff - if (player->panim == PA_ABILITY) + if (player->panim == PA_ABILITY && player->mo->state-states != S_PLAY_FLY_TIRED) P_SetPlayerMobjState(player->mo, S_PLAY_FLY_TIRED); if (player->charability == CA_FLY && (leveltime % 10 == 0) @@ -10604,7 +10604,7 @@ static void P_DoTailsOverlay(player_t *player, mobj_t *tails) angle_t horizangle = player->drawangle; fixed_t zoffs = 0; fixed_t backwards = -1*FRACUNIT; - boolean doroll = (player->panim == PA_ROLL || player->panim == PA_JUMP); + boolean doroll = (player->panim == PA_ROLL || (player->panim == PA_JUMP && !(player->charflags & SF_NOJUMPSPIN)) || player->mo->sprite2 == SPR2_SWIM); angle_t rollangle; boolean panimchange; INT32 ticnum = 0; @@ -10636,12 +10636,17 @@ static void P_DoTailsOverlay(player_t *player, mobj_t *tails) else zdist = player->mo->momz; rollangle = R_PointToAngle2(0, 0, testval, -P_MobjFlip(player->mo)*zdist); - zoffs = 3*FRACUNIT + 12*FINESINE(rollangle >> ANGLETOFINESHIFT); - backwards = -12*FINECOSINE(rollangle >> ANGLETOFINESHIFT); + if (player->mo->sprite2 == SPR2_SWIM) + backwards = -5*FRACUNIT; + else + { + zoffs = 3*FRACUNIT + 12*FINESINE(rollangle >> ANGLETOFINESHIFT); + backwards = -12*FINECOSINE(rollangle >> ANGLETOFINESHIFT); + } } else if (player->panim == PA_RUN) backwards = -5*FRACUNIT; - else if (player->panim == PA_SPRING) + else if (player->panim == PA_SPRING || player->panim == PA_JUMP) { zoffs += 4*FRACUNIT; backwards /= 2; @@ -10663,7 +10668,7 @@ static void P_DoTailsOverlay(player_t *player, mobj_t *tails) zoffs = -7*FRACUNIT; backwards = -9*FRACUNIT; } - else if (player->mo->sprite2 == SPR2_FLY || player->mo->sprite2 == SPR2_TIRE) + else if (player->panim == PA_ABILITY) backwards = -5*FRACUNIT; // sprite... @@ -10680,7 +10685,7 @@ static void P_DoTailsOverlay(player_t *player, mobj_t *tails) else chosenstate = S_TAILSOVERLAY_0DEGREES; } - else if (player->panim == PA_SPRING) + else if (player->panim == PA_SPRING || player->panim == PA_JUMP) chosenstate = S_TAILSOVERLAY_MINUS60DEGREES; else if (player->panim == PA_FALL || player->mo->state-states == S_PLAY_RIDE) chosenstate = S_TAILSOVERLAY_PLUS60DEGREES; @@ -10703,6 +10708,8 @@ static void P_DoTailsOverlay(player_t *player, mobj_t *tails) } else if (player->mo->sprite2 == SPR2_FLY) chosenstate = S_TAILSOVERLAY_FLY; + else if (player->mo->sprite2 == SPR2_SWIM) + chosenstate = S_TAILSOVERLAY_FLY; else if (player->mo->sprite2 == SPR2_TIRE) chosenstate = S_TAILSOVERLAY_TIRE; else if (player->panim == PA_ABILITY2) @@ -11269,8 +11276,8 @@ void P_PlayerThink(player_t *player) { boolean currentlyonground = P_IsObjectOnGround(player->mo); - if (!player->powers[pw_carry] - && ((player->pflags & (PF_AUTOBRAKE|PF_APPLYAUTOBRAKE)) == (PF_AUTOBRAKE|PF_APPLYAUTOBRAKE)) + if (!player->powers[pw_carry] && !player->powers[pw_nocontrol] + && ((player->pflags & (PF_AUTOBRAKE|PF_APPLYAUTOBRAKE|PF_STASIS)) == (PF_AUTOBRAKE|PF_APPLYAUTOBRAKE)) && !(cmd->forwardmove || cmd->sidemove) && (player->rmomx || player->rmomy) && (!player->capsule || (player->capsule->reactiontime != (player-players)+1))) From 9d774f7578a3e4b709980b1f9fbb588b77a69264 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 18 Sep 2019 13:46:17 +0100 Subject: [PATCH 03/12] More swim stuff! * Prevent being able to damage enemies from below while swimming. * Make the swim-specific bubbles happen at the hands instead of where the propeller would be. * Improve placement/angle of swimming tails overlay. * Immediately set flight time to 0 if a player is being carried underwater. --- src/p_user.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index ff887a171..699069592 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1109,7 +1109,7 @@ boolean P_PlayerCanDamage(player_t *player, mobj_t *thing) } else if (P_MobjFlip(player->mo)*(topheight - (thing->z + thing->height/2)) < 0) { - if (player->charability == CA_FLY && player->panim == PA_ABILITY && (P_MobjFlip(player->mo)*(player->mo->momz - thing->momz) > 0)) + if (player->charability == CA_FLY && player->panim == PA_ABILITY && !(player->mo->eflags & MFE_UNDERWATER) && (P_MobjFlip(player->mo)*(player->mo->momz - thing->momz) > 0)) return true; } @@ -2964,22 +2964,19 @@ static void P_DoBubbleBreath(player_t *player) P_SetScale(bubble, bubble->destscale); } - if (player->powers[pw_carry] == CR_NIGHTSMODE) // NiGHTS Super doesn't spawn flight bubbles - return; - // Tails stirs up the water while flying in it if (player->powers[pw_tailsfly] && (leveltime & 1) && player->charability != CA_SWIM) { - fixed_t radius = (3*player->mo->radius)>>1; + fixed_t radius = player->mo->radius; angle_t fa = ((leveltime%45)*FINEANGLES/8) & FINEMASK; fixed_t stirwaterx = FixedMul(FINECOSINE(fa),radius); fixed_t stirwatery = FixedMul(FINESINE(fa),radius); fixed_t stirwaterz; if (player->mo->eflags & MFE_VERTICALFLIP) - stirwaterz = player->mo->z + player->mo->height - FixedDiv(player->mo->height,3*FRACUNIT/2); + stirwaterz = player->mo->z + player->mo->height - (4<mo->z + FixedDiv(player->mo->height,3*FRACUNIT/2); + stirwaterz = player->mo->z + (4<mo->x + stirwaterx, @@ -10604,7 +10601,8 @@ static void P_DoTailsOverlay(player_t *player, mobj_t *tails) angle_t horizangle = player->drawangle; fixed_t zoffs = 0; fixed_t backwards = -1*FRACUNIT; - boolean doroll = (player->panim == PA_ROLL || (player->panim == PA_JUMP && !(player->charflags & SF_NOJUMPSPIN)) || player->mo->sprite2 == SPR2_SWIM); + boolean doswim = (player->panim == PA_ABILITY && (player->mo->eflags & MFE_UNDERWATER)); + boolean doroll = (player->panim == PA_ROLL || (player->panim == PA_JUMP && !(player->charflags & SF_NOJUMPSPIN)) || doswim); angle_t rollangle; boolean panimchange; INT32 ticnum = 0; @@ -10631,14 +10629,17 @@ static void P_DoTailsOverlay(player_t *player, mobj_t *tails) if (testval < FRACUNIT) testval = FRACUNIT; } - if (smilesonground && !player->mo->reactiontime) + + if (doswim) + zdist = player->mo->momz<<1; + else if (smilesonground && !player->mo->reactiontime) zdist = (player->mo->z - tails->threshold); else zdist = player->mo->momz; + rollangle = R_PointToAngle2(0, 0, testval, -P_MobjFlip(player->mo)*zdist); - if (player->mo->sprite2 == SPR2_SWIM) - backwards = -5*FRACUNIT; - else + + if (!doswim) { zoffs = 3*FRACUNIT + 12*FINESINE(rollangle >> ANGLETOFINESHIFT); backwards = -12*FINECOSINE(rollangle >> ANGLETOFINESHIFT); @@ -11819,6 +11820,8 @@ void P_PlayerAfterThink(player_t *player) { if (player->mo->state-states != S_PLAY_RIDE) P_SetPlayerMobjState(player->mo, S_PLAY_RIDE); + if (tails->eflags & MFE_UNDERWATER) + tails->player->powers[pw_tailsfly] = 0; } else P_SetTarget(&player->mo->tracer, NULL); From e993b8981ecf1f960de2ada89c590a79049302b4 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 18 Sep 2019 13:55:20 +0100 Subject: [PATCH 04/12] Fix solidity of lava in reverse gravity. (Resolves #216) --- src/p_mobj.c | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 44c6b9f6e..236347eae 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2381,22 +2381,42 @@ boolean P_CheckDeathPitCollide(mobj_t *mo) boolean P_CheckSolidLava(mobj_t *mo, ffloor_t *rover) { + fixed_t topheight; + I_Assert(mo != NULL); I_Assert(!P_MobjWasRemoved(mo)); - { - fixed_t topheight = - #ifdef ESLOPE - *rover->t_slope ? P_GetZAt(*rover->t_slope, mo->x, mo->y) : - #endif - *rover->topheight; + // not a lava block with solid planes + if (!(rover->flags & FF_SWIMMABLE && GETSECSPECIAL(rover->master->frontsector->special, 1) == 3 + && !(rover->master->flags & ML_BLOCKMONSTERS))) + return false; - if (rover->flags & FF_SWIMMABLE && GETSECSPECIAL(rover->master->frontsector->special, 1) == 3 - && !(rover->master->flags & ML_BLOCKMONSTERS) - && ((rover->master->flags & ML_EFFECT3) || mo->z-mo->momz > topheight - FixedMul(16*FRACUNIT, mo->scale))) + // is solid from the sides + if (rover->master->flags & ML_EFFECT3) + return true; + + if (mo->eflags & MFE_VERTICALFLIP) + { + topheight = + #ifdef ESLOPE + *rover->b_slope ? P_GetZAt(*rover->b_slope, mo->x, mo->y) : + #endif + *rover->bottomheight; + + if (mo->z+mo->height-mo->momz < topheight + FixedMul(16*FRACUNIT, mo->scale)) return true; + return false; } + topheight = + #ifdef ESLOPE + *rover->t_slope ? P_GetZAt(*rover->t_slope, mo->x, mo->y) : + #endif + *rover->topheight; + + if (mo->z-mo->momz > topheight - FixedMul(16*FRACUNIT, mo->scale)) + return true; + return false; } From a8a8ae0d0bdfb8a6c6eb1db644b24250ee8326f2 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 18 Sep 2019 14:11:06 +0100 Subject: [PATCH 05/12] Only set flight time to 0 if skin has SPR2_SWIM spriteset. --- 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 699069592..b719ae33b 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -11820,7 +11820,7 @@ void P_PlayerAfterThink(player_t *player) { if (player->mo->state-states != S_PLAY_RIDE) P_SetPlayerMobjState(player->mo, S_PLAY_RIDE); - if (tails->eflags & MFE_UNDERWATER) + if ((tails->skin && ((skin_t *)(tails->skin))->sprites[SPR2_SWIM].numframes) && (tails->eflags & MFE_UNDERWATER)) tails->player->powers[pw_tailsfly] = 0; } else From 5d37ddd676a75a68eb47b8cca3218df5cc17e060 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 18 Sep 2019 14:16:52 +0100 Subject: [PATCH 06/12] Change threshold on autobrake skidding sound/animaton to runspeed rather than half of runspeed. --- 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 b719ae33b..e0a4d710c 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -11289,7 +11289,7 @@ void P_PlayerThink(player_t *player) if (!currentlyonground) acceleration /= 2; // fake skidding! see P_SkidStuff for reference on conditionals - else if (!player->skidtime && !(player->mo->eflags & MFE_GOOWATER) && !(player->pflags & (PF_JUMPED|PF_SPINNING|PF_SLIDING)) && !(player->charflags & SF_NOSKID) && P_AproxDistance(player->mo->momx, player->mo->momy) >= FixedMul(player->runspeed/2, player->mo->scale)) + else if (!player->skidtime && !(player->mo->eflags & MFE_GOOWATER) && !(player->pflags & (PF_JUMPED|PF_SPINNING|PF_SLIDING)) && !(player->charflags & SF_NOSKID) && P_AproxDistance(player->mo->momx, player->mo->momy) >= FixedMul(player->runspeed, player->mo->scale)) // modified from player->runspeed/2 'cuz the skid was just TOO frequent ngl { if (player->mo->state-states != S_PLAY_SKID) P_SetPlayerMobjState(player->mo, S_PLAY_SKID); From 2ed9d957b082d5717bb4acbe51317cc4c0042478 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 18 Sep 2019 15:26:21 +0100 Subject: [PATCH 07/12] Fix Knuckles being able to climb up solid midtextures by repeatedly gliding at them. (addresses #174 checkbox 2) --- src/p_map.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_map.c b/src/p_map.c index 28bfd2806..dee1b5c40 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -3199,7 +3199,7 @@ static boolean P_IsClimbingValid(player_t *player, angle_t angle) && glidesector->sector->ceilingpic == skyflatnum) return false; - if ((player->mo->z + FixedMul(16*FRACUNIT,player->mo->scale) < ceilingz) + if ((player->mo->z + FixedMul(16*FRACUNIT,player->mo->scale) < floorz) || (player->mo->z >= ceilingz)) floorclimb = true; } From 3285cc9a0df647cf5d09cd56a4e11ca1abb512d4 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 18 Sep 2019 16:06:13 +0100 Subject: [PATCH 08/12] Properly scrub the player struct clean between level transitions. (Good chance this fixes our new bug where the player gets stuck in their standing pose when the map begins..?) --- src/g_game.c | 50 ++++++++++++++++++++++++-------------------------- src/g_game.h | 2 +- src/p_mobj.c | 2 +- src/p_setup.c | 40 +++++++++------------------------------- 4 files changed, 35 insertions(+), 59 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 7a876e968..a3025f949 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2100,7 +2100,7 @@ static inline void G_PlayerFinishLevel(INT32 player) // G_PlayerReborn // Called after a player dies. Almost everything is cleared and initialized. // -void G_PlayerReborn(INT32 player) +void G_PlayerReborn(INT32 player, boolean betweenmaps) { player_t *p; INT32 score; @@ -2205,7 +2205,7 @@ void G_PlayerReborn(INT32 player) bot = players[player].bot; pity = players[player].pity; - if (!G_IsSpecialStage(gamemap)) + if (betweenmaps || !G_IsSpecialStage(gamemap)) { rings = (ultimatemode ? 0 : mapheaderinfo[gamemap-1]->startrings); spheres = 0; @@ -2284,6 +2284,28 @@ void G_PlayerReborn(INT32 player) //if ((netgame || multiplayer) && !p->spectator) -- moved into P_SpawnPlayer to account for forced changes there //p->powers[pw_flashing] = flashingtics-1; // Babysitting deterrent + // Check to make sure their color didn't change somehow... + if (G_GametypeHasTeams()) + { + if (p->ctfteam == 1 && p->skincolor != skincolor_redteam) + { + if (p == &players[consoleplayer]) + CV_SetValue(&cv_playercolor, skincolor_redteam); + else if (p == &players[secondarydisplayplayer]) + CV_SetValue(&cv_playercolor2, skincolor_redteam); + } + else if (p->ctfteam == 2 && p->skincolor != skincolor_blueteam) + { + if (p == &players[consoleplayer]) + CV_SetValue(&cv_playercolor, skincolor_blueteam); + else if (p == &players[secondarydisplayplayer]) + CV_SetValue(&cv_playercolor2, skincolor_blueteam); + } + } + + if (betweenmaps) + return; + if (p-players == consoleplayer) { if (mapmusflags & MUSIC_RELOADRESET) @@ -2303,9 +2325,6 @@ void G_PlayerReborn(INT32 player) if (gametype == GT_COOP) P_FindEmerald(); // scan for emeralds to hunt for - // Reset Nights score and max link to 0 on death - p->marescore = p->maxlink = 0; - // If NiGHTS, find lowest mare to start with. p->mare = P_FindLowestMare(); @@ -2313,27 +2332,6 @@ void G_PlayerReborn(INT32 player) if (p->mare == 255) p->mare = 0; - - p->marelap = p->marebonuslap = 0; - - // Check to make sure their color didn't change somehow... - if (G_GametypeHasTeams()) - { - if (p->ctfteam == 1 && p->skincolor != skincolor_redteam) - { - if (p == &players[consoleplayer]) - CV_SetValue(&cv_playercolor, skincolor_redteam); - else if (p == &players[secondarydisplayplayer]) - CV_SetValue(&cv_playercolor2, skincolor_redteam); - } - else if (p->ctfteam == 2 && p->skincolor != skincolor_blueteam) - { - if (p == &players[consoleplayer]) - CV_SetValue(&cv_playercolor, skincolor_blueteam); - else if (p == &players[secondarydisplayplayer]) - CV_SetValue(&cv_playercolor2, skincolor_blueteam); - } - } } // diff --git a/src/g_game.h b/src/g_game.h index e161bc8ed..df1301dd7 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -100,7 +100,7 @@ extern INT32 localaiming, localaiming2; // should be an angle_t but signed // void G_ChangePlayerReferences(mobj_t *oldmo, mobj_t *newmo); void G_DoReborn(INT32 playernum); -void G_PlayerReborn(INT32 player); +void G_PlayerReborn(INT32 player, boolean betweenmaps); void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean skipprecutscene, boolean FLS); char *G_BuildMapTitle(INT32 mapnum); diff --git a/src/p_mobj.c b/src/p_mobj.c index 236347eae..994ddcfe7 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10432,7 +10432,7 @@ void P_SpawnPlayer(INT32 playernum) mobj_t *mobj; if (p->playerstate == PST_REBORN) - G_PlayerReborn(playernum); + G_PlayerReborn(playernum, false); // spawn as spectator determination if (!G_GametypeHasSpectators()) diff --git a/src/p_setup.c b/src/p_setup.c index 0753f01d3..c83c8cd5c 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2246,6 +2246,8 @@ static void P_LevelInitStuff(void) for (i = 0; i < MAXPLAYERS; i++) { + G_PlayerReborn(i, true); + if (canresetlives && (netgame || multiplayer) && playeringame[i] && (gametype == GT_COMPETITION || players[i].lives <= 0)) { // In Co-Op, replenish a user's lives if they are depleted. @@ -2253,42 +2255,18 @@ static void P_LevelInitStuff(void) } // obliteration station... - players[i].spheres =\ - players[i].xtralife = players[i].deadtimer =\ - players[i].numboxes = players[i].totalring =\ - players[i].laps = players[i].aiming =\ - players[i].losstime = players[i].timeshit =\ - players[i].marescore = players[i].lastmarescore =\ - players[i].maxlink = players[i].startedtime =\ - players[i].finishedtime = players[i].finishedspheres =\ - players[i].finishedrings = players[i].lastmare =\ - players[i].lastmarelap = players[i].lastmarebonuslap =\ - players[i].totalmarelap = players[i].totalmarebonuslap =\ - players[i].marebegunat = players[i].textvar =\ - players[i].texttimer = players[i].linkcount =\ - players[i].linktimer = players[i].flyangle =\ - players[i].anotherflyangle = players[i].nightstime =\ - players[i].oldscale = players[i].mare = players[i].marelap =\ - players[i].marebonuslap = players[i].lapbegunat =\ - players[i].lapstartedtime = players[i].totalmarescore =\ - players[i].realtime = players[i].exiting = 0; + players[i].numboxes = players[i].totalring =\ + players[i].laps = players[i].marescore = players[i].lastmarescore =\ + players[i].mare = players[i].exiting = 0; - // i guess this could be part of the above but i feel mildly uncomfortable implicitly casting - players[i].gotcontinue = false; - - // aha, the first evidence this shouldn't be a memset! players[i].drillmeter = 40*20; - players[i].rings = (ultimatemode ? 0 : mapheaderinfo[gamemap-1]->startrings); - P_ResetPlayer(&players[i]); // hit these too - players[i].pflags &= ~(PF_GAMETYPEOVER|PF_TRANSFERTOCLOSEST); - - // unset ALL the pointers. P_SetTarget isn't needed here because if this - // function is being called we're just going to clobber the data anyways - players[i].mo = players[i].followmobj = players[i].awayviewmobj =\ - players[i].capsule = players[i].axis1 = players[i].axis2 = players[i].drone = NULL; + players[i].pflags &= ~(PF_GAMETYPEOVER); } + + if (botingame) + CV_SetValue(&cv_analog2, true); } // From cf14d5fe5d4290f52e4ea04519edcc705ac6750a Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 19 Sep 2019 12:30:30 +0100 Subject: [PATCH 09/12] * Remove sounds from swimming. * Lower default swim animation speed. * Make speed of flight/swim animation increase whenever mashing jump. --- src/info.c | 2 +- src/p_user.c | 13 +++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/info.c b/src/info.c index 0fea743f6..05204fc86 100644 --- a/src/info.c +++ b/src/info.c @@ -739,7 +739,7 @@ state_t states[NUMSTATES] = // CA_FLY/CA_SWIM {SPR_PLAY, SPR2_FLY , 2, {NULL}, 0, 0, S_PLAY_FLY}, // S_PLAY_FLY - {SPR_PLAY, SPR2_SWIM, 2, {NULL}, 0, 0, S_PLAY_SWIM}, // S_PLAY_SWIM + {SPR_PLAY, SPR2_SWIM, 4, {NULL}, 0, 0, S_PLAY_SWIM}, // S_PLAY_SWIM {SPR_PLAY, SPR2_TIRE, 12, {NULL}, 0, 0, S_PLAY_FLY_TIRED}, // S_PLAY_FLY_TIRED // CA_GLIDEANDCLIMB diff --git a/src/p_user.c b/src/p_user.c index e0a4d710c..83c154fdf 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8180,12 +8180,18 @@ static void P_MovePlayer(player_t *player) if (P_MobjFlip(player->mo)*player->mo->momz < FixedMul(5*actionspd, player->mo->scale)) P_SetObjectMomZ(player->mo, actionspd/2, true); + P_SetPlayerMobjState(player->mo, player->mo->state->nextstate); + player->fly1--; } } // Tails Put-Put noise - if (player->charability == CA_FLY && player->bot != 1 && leveltime % 10 == 0 && !player->spectator) + if (player->charability == CA_FLY + && player->bot != 1 + && !(player->mo->eflags & MFE_UNDERWATER) + && leveltime % 10 == 0 + && !player->spectator) S_StartSound(player->mo, sfx_putput); // Descend @@ -8202,6 +8208,7 @@ static void P_MovePlayer(player_t *player) if (player->charability == CA_FLY && (leveltime % 10 == 0) && player->mo->state-states == S_PLAY_FLY_TIRED + && !(player->mo->eflags & MFE_UNDERWATER) && !player->spectator) S_StartSound(player->mo, sfx_pudpud); } @@ -10736,8 +10743,10 @@ static void P_DoTailsOverlay(player_t *player, mobj_t *tails) } } +#if 0 if (player->fly1 != 0 && player->powers[pw_tailsfly] != 0 && !smilesonground) P_SetMobjState(tails, chosenstate); +#endif // animation... if (player->panim == PA_SPRING || player->panim == PA_FALL || player->mo->state-states == S_PLAY_RIDE) @@ -10752,7 +10761,7 @@ static void P_DoTailsOverlay(player_t *player, mobj_t *tails) else if (player->mo->state-states == S_PLAY_GASP) tails->tics = -1; else if (player->mo->sprite2 == SPR2_TIRE) - ticnum = 4; + ticnum = (doswim ? 2 : 4); else if (player->panim != PA_IDLE) ticnum = player->mo->tics; From ca9e6e31dab7ee71a74c68e3a1dd992df933fb46 Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 19 Sep 2019 13:20:05 +0100 Subject: [PATCH 10/12] * Resolve #224 (landing frames on ceiling contact). * Fix some other landing weirdness with CA_BOUNCE. --- src/p_map.c | 7 +- src/p_user.c | 283 ++++++++++++++++++++++++++------------------------- 2 files changed, 146 insertions(+), 144 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index dfac3ae05..01c41131b 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2881,11 +2881,8 @@ static boolean P_ThingHeightClip(mobj_t *thing) thing->z = thing->ceilingz - thing->height; } - if (thing->z != oldz) - { - if (thing->player) - P_PlayerHitFloor(thing->player, !onfloor); - } + if (P_MobjFlip(thing)*(thing->z - oldz) > 0 && thing->player) + P_PlayerHitFloor(thing->player, !onfloor); // debug: be sure it falls to the floor thing->eflags &= ~MFE_ONGROUND; diff --git a/src/p_user.c b/src/p_user.c index 83c154fdf..572cf01fb 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2217,148 +2217,153 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff) player->pflags &= ~PF_SPINNING; } - if (player->pflags & PF_SPINNING) - { - if (player->mo->state-states != S_PLAY_ROLL && !(player->pflags & PF_STARTDASH)) - { - P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); - S_StartSound(player->mo, sfx_spin); - } - } - else if (player->pflags & PF_GLIDING) // ground gliding - { - if (dorollstuff) - { - player->skidtime = TICRATE; - player->mo->tics = -1; - } - else if (!player->skidtime) - player->pflags &= ~PF_GLIDING; - } - else if (player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2) - { - if (player->mo->state-states != S_PLAY_MELEE_LANDING) - { - mobjtype_t type = player->revitem; - P_SetPlayerMobjState(player->mo, S_PLAY_MELEE_LANDING); - player->mo->tics = (player->mo->movefactor == FRACUNIT) ? TICRATE/2 : (FixedDiv(35<<(FRACBITS-1), FixedSqrt(player->mo->movefactor)))>>FRACBITS; - S_StartSound(player->mo, sfx_s3k8b); - player->pflags |= PF_FULLSTASIS; - - // hearticles - if (type) - { - UINT8 i = 0; - angle_t throwang = -(2*ANG30); - fixed_t xo = P_ReturnThrustX(player->mo, player->drawangle, 16*player->mo->scale); - fixed_t yo = P_ReturnThrustY(player->mo, player->drawangle, 16*player->mo->scale); - fixed_t zo = 6*player->mo->scale; - fixed_t mu = FixedMul(player->maxdash, player->mo->scale); - fixed_t mu2 = FixedHypot(player->mo->momx, player->mo->momy); - fixed_t ev; - mobj_t *missile = NULL; - if (mu2 < mu) - mu2 = mu; - ev = (50*FRACUNIT - (mu/25))/50; - while (i < 5) - { - missile = P_SpawnMobjFromMobj(player->mo, xo, yo, zo, type); - P_SetTarget(&missile->target, player->mo); - missile->angle = throwang + player->drawangle; - P_Thrust(missile, player->drawangle + ANGLE_90, - P_ReturnThrustY(missile, throwang, mu)); // side to side component - P_Thrust(missile, player->drawangle, mu2); // forward component - P_SetObjectMomZ(missile, (4 + ((i&1)<<1))*FRACUNIT, true); - missile->momz += player->mo->pmomz; - missile->fuse = TICRATE/2; - missile->extravalue2 = ev; - - i++; - throwang += ANG30; - } - if (mobjinfo[type].seesound && missile) - S_StartSound(missile, missile->info->seesound); - } - } - } - 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) - { - if (player->cmomx || player->cmomy) - { - if (player->charflags & SF_DASHMODE && player->dashmode >= 3*TICRATE && player->panim != PA_DASH) - P_SetPlayerMobjState(player->mo, S_PLAY_DASH); - else if (player->speed >= FixedMul(player->runspeed, player->mo->scale) - && (player->panim != PA_RUN || player->mo->state-states == S_PLAY_FLOAT_RUN)) - P_SetPlayerMobjState(player->mo, S_PLAY_RUN); - else if ((player->rmomx || player->rmomy) - && (player->panim != PA_WALK || player->mo->state-states == S_PLAY_FLOAT)) - P_SetPlayerMobjState(player->mo, S_PLAY_WALK); - else if (!player->rmomx && !player->rmomy && player->panim != PA_IDLE) - P_SetPlayerMobjState(player->mo, S_PLAY_STND); - } - else - { - if (player->charflags & SF_DASHMODE && player->dashmode >= 3*TICRATE && player->panim != PA_DASH) - P_SetPlayerMobjState(player->mo, S_PLAY_DASH); - else if (player->speed >= FixedMul(player->runspeed, player->mo->scale) - && (player->panim != PA_RUN || player->mo->state-states == S_PLAY_FLOAT_RUN)) - P_SetPlayerMobjState(player->mo, S_PLAY_RUN); - else if ((player->mo->momx || player->mo->momy) - && (player->panim != PA_WALK || player->mo->state-states == S_PLAY_FLOAT)) - P_SetPlayerMobjState(player->mo, S_PLAY_WALK); - else if (!player->mo->momx && !player->mo->momy && player->panim != PA_IDLE) - P_SetPlayerMobjState(player->mo, S_PLAY_STND); - } - } - - if (!(player->pflags & PF_GLIDING)) - player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE); - player->pflags &= ~(PF_STARTJUMP|PF_THOKKED|PF_CANCARRY/*|PF_GLIDING*/); - player->secondjump = 0; - player->glidetime = 0; - player->climbing = 0; - player->powers[pw_tailsfly] = 0; - - if (player->pflags & PF_SHIELDABILITY) - { - player->pflags &= ~PF_SHIELDABILITY; - - if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL) // Elemental shield's stomp attack. - { - if (player->mo->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER)) // play a blunt sound - S_StartSound(player->mo, sfx_s3k4c); - else // create a fire pattern on the ground - { - S_StartSound(player->mo, sfx_s3k47); - P_ElementalFire(player, true); - } - P_SetObjectMomZ(player->mo, - (player->mo->eflags & MFE_UNDERWATER) - ? 6*FRACUNIT/5 - : 5*FRACUNIT/2, - false); - P_SetPlayerMobjState(player->mo, S_PLAY_FALL); - player->mo->momx = player->mo->momy = 0; - clipmomz = false; - } - else if ((player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP) // Bubble shield's bounce attack. - { - P_DoBubbleBounce(player); - clipmomz = false; - } - } - if (player->pflags & PF_BOUNCING) { - P_MobjCheckWater(player->mo); - player->mo->momz *= -1; - P_DoAbilityBounce(player, true); - if (player->scoreadd) - player->scoreadd--; + if (dorollstuff && player->mo->state-states != S_PLAY_BOUNCE_LANDING) + { + P_MobjCheckWater(player->mo); + player->mo->momz *= -1; + P_DoAbilityBounce(player, true); + if (player->scoreadd) + player->scoreadd--; + } clipmomz = false; } + else + { + if (player->pflags & PF_SPINNING) + { + if (player->mo->state-states != S_PLAY_ROLL && !(player->pflags & PF_STARTDASH)) + { + P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); + S_StartSound(player->mo, sfx_spin); + } + } + else if (player->pflags & PF_GLIDING) // ground gliding + { + if (dorollstuff) + { + player->skidtime = TICRATE; + player->mo->tics = -1; + } + else if (!player->skidtime) + player->pflags &= ~PF_GLIDING; + } + else if (player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2) + { + if (player->mo->state-states != S_PLAY_MELEE_LANDING) + { + mobjtype_t type = player->revitem; + P_SetPlayerMobjState(player->mo, S_PLAY_MELEE_LANDING); + player->mo->tics = (player->mo->movefactor == FRACUNIT) ? TICRATE/2 : (FixedDiv(35<<(FRACBITS-1), FixedSqrt(player->mo->movefactor)))>>FRACBITS; + S_StartSound(player->mo, sfx_s3k8b); + player->pflags |= PF_FULLSTASIS; + + // hearticles + if (type) + { + UINT8 i = 0; + angle_t throwang = -(2*ANG30); + fixed_t xo = P_ReturnThrustX(player->mo, player->drawangle, 16*player->mo->scale); + fixed_t yo = P_ReturnThrustY(player->mo, player->drawangle, 16*player->mo->scale); + fixed_t zo = 6*player->mo->scale; + fixed_t mu = FixedMul(player->maxdash, player->mo->scale); + fixed_t mu2 = FixedHypot(player->mo->momx, player->mo->momy); + fixed_t ev; + mobj_t *missile = NULL; + if (mu2 < mu) + mu2 = mu; + ev = (50*FRACUNIT - (mu/25))/50; + while (i < 5) + { + missile = P_SpawnMobjFromMobj(player->mo, xo, yo, zo, type); + P_SetTarget(&missile->target, player->mo); + missile->angle = throwang + player->drawangle; + P_Thrust(missile, player->drawangle + ANGLE_90, + P_ReturnThrustY(missile, throwang, mu)); // side to side component + P_Thrust(missile, player->drawangle, mu2); // forward component + P_SetObjectMomZ(missile, (4 + ((i&1)<<1))*FRACUNIT, true); + missile->momz += player->mo->pmomz; + missile->fuse = TICRATE/2; + missile->extravalue2 = ev; + + i++; + throwang += ANG30; + } + if (mobjinfo[type].seesound && missile) + S_StartSound(missile, missile->info->seesound); + } + } + } + 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) + { + if (player->cmomx || player->cmomy) + { + if (player->charflags & SF_DASHMODE && player->dashmode >= 3*TICRATE && player->panim != PA_DASH) + P_SetPlayerMobjState(player->mo, S_PLAY_DASH); + else if (player->speed >= FixedMul(player->runspeed, player->mo->scale) + && (player->panim != PA_RUN || player->mo->state-states == S_PLAY_FLOAT_RUN)) + P_SetPlayerMobjState(player->mo, S_PLAY_RUN); + else if ((player->rmomx || player->rmomy) + && (player->panim != PA_WALK || player->mo->state-states == S_PLAY_FLOAT)) + P_SetPlayerMobjState(player->mo, S_PLAY_WALK); + else if (!player->rmomx && !player->rmomy && player->panim != PA_IDLE) + P_SetPlayerMobjState(player->mo, S_PLAY_STND); + } + else + { + if (player->charflags & SF_DASHMODE && player->dashmode >= 3*TICRATE && player->panim != PA_DASH) + P_SetPlayerMobjState(player->mo, S_PLAY_DASH); + else if (player->speed >= FixedMul(player->runspeed, player->mo->scale) + && (player->panim != PA_RUN || player->mo->state-states == S_PLAY_FLOAT_RUN)) + P_SetPlayerMobjState(player->mo, S_PLAY_RUN); + else if ((player->mo->momx || player->mo->momy) + && (player->panim != PA_WALK || player->mo->state-states == S_PLAY_FLOAT)) + P_SetPlayerMobjState(player->mo, S_PLAY_WALK); + else if (!player->mo->momx && !player->mo->momy && player->panim != PA_IDLE) + P_SetPlayerMobjState(player->mo, S_PLAY_STND); + } + } + + if (!(player->pflags & PF_GLIDING)) + player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE); + player->pflags &= ~(PF_STARTJUMP|PF_THOKKED|PF_CANCARRY/*|PF_GLIDING*/); + player->secondjump = 0; + player->glidetime = 0; + player->climbing = 0; + player->powers[pw_tailsfly] = 0; + + if (player->pflags & PF_SHIELDABILITY) + { + player->pflags &= ~PF_SHIELDABILITY; + + if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL) // Elemental shield's stomp attack. + { + if (player->mo->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER)) // play a blunt sound + S_StartSound(player->mo, sfx_s3k4c); + else // create a fire pattern on the ground + { + S_StartSound(player->mo, sfx_s3k47); + P_ElementalFire(player, true); + } + P_SetObjectMomZ(player->mo, + (player->mo->eflags & MFE_UNDERWATER) + ? 6*FRACUNIT/5 + : 5*FRACUNIT/2, + false); + P_SetPlayerMobjState(player->mo, S_PLAY_FALL); + player->mo->momx = player->mo->momy = 0; + clipmomz = false; + } + else if ((player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP) // Bubble shield's bounce attack. + { + P_DoBubbleBounce(player); + clipmomz = false; + } + } + } } return clipmomz; @@ -8080,7 +8085,7 @@ static void P_MovePlayer(player_t *player) } else if (player->pflags & PF_BOUNCING) { - if (!(player->pflags & PF_JUMPDOWN) || (onground && P_MobjFlip(player->mo)*player->mo->momz <= 0)) // If not holding the jump button OR on flat ground + if (!(player->pflags & PF_JUMPDOWN)) // If not holding the jump button { P_ResetPlayer(player); // down, stop bouncing. player->pflags |= PF_THOKKED; From f8475eef26f4197d32a55cff19ded58e2fbdff3d Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 19 Sep 2019 13:20:52 +0100 Subject: [PATCH 11/12] Disable some code which sometimes makes the player enter walking frames when jumping up to a platform, such as the CEZ3 buttons, despite still being in jumping mode. If this causes more problems than it solves it can be reverted, but doing a bunch of playthroughs of DSZ1/2, GFZ1, and CEZ3 didn't seem to uncover anything, so I'm tentatively putting it in this branch. --- src/p_mobj.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/p_mobj.c b/src/p_mobj.c index 994ddcfe7..4cede843c 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -4001,6 +4001,7 @@ static void P_PlayerMobjThinker(mobj_t *mobj) } else { +#if 0 // i don't know why this is here, it's causing a few undesired state glitches, and disabling it doesn't appear to negatively affect the game, but i don't want it gone permanently just in case some obscure bug crops up if (!(mobj->player->powers[pw_carry] == CR_NIGHTSMODE)) // used for drilling mobj->player->pflags &= ~PF_STARTJUMP; mobj->player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE); @@ -4010,6 +4011,7 @@ static void P_PlayerMobjThinker(mobj_t *mobj) mobj->player->powers[pw_tailsfly] = 0; P_SetPlayerMobjState(mobj, S_PLAY_WALK); } +#endif mobj->eflags &= ~MFE_JUSTHITFLOOR; } From 802ddf94b15e6d4b1c5513f0a7cae554357727dd Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 19 Sep 2019 18:44:55 +0100 Subject: [PATCH 12/12] Always pretend cv_playersforexit is 4 in co-op special stages. --- src/p_user.c | 5 +++-- src/st_stuff.c | 60 +++++++++++++++++++++++++++----------------------- 2 files changed, 35 insertions(+), 30 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index 572cf01fb..0438075f2 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -10989,7 +10989,8 @@ void P_PlayerThink(player_t *player) if (player->exiting == 2 || countdown2 == 2) { - if (cv_playersforexit.value) // Count to be sure everyone's exited + UINT8 numneeded = (G_IsSpecialStage(gamemap) ? 4 : cv_playersforexit.value); + if (numneeded) // Count to be sure everyone's exited { INT32 i, total = 0, exiting = 0; @@ -11005,7 +11006,7 @@ void P_PlayerThink(player_t *player) exiting++; } - if (!total || ((4*exiting)/total) >= cv_playersforexit.value) + if (!total || ((4*exiting)/total) >= numneeded) { if (server) SendNetXCmd(XD_EXITLEVEL, NULL, 0); diff --git a/src/st_stuff.c b/src/st_stuff.c index c4f1327c0..20a132b3a 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -2100,39 +2100,43 @@ static void ST_drawTextHUD(void) textHUDdraw(M_GetText("\x82""FIRE:""\x80 Enter game")) } - if (gametype == GT_COOP && (!stplyr->spectator || (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap))) && stplyr->exiting && cv_playersforexit.value) + if (gametype == GT_COOP && (!stplyr->spectator || (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap))) && stplyr->exiting) { - INT32 i, total = 0, exiting = 0; - - for (i = 0; i < MAXPLAYERS; i++) + UINT8 numneeded = (G_IsSpecialStage(gamemap) ? 4 : cv_playersforexit.value); + if (numneeded) { - if (!playeringame[i] || players[i].spectator) - continue; - if (players[i].lives <= 0) - continue; + INT32 i, total = 0, exiting = 0; - total++; - if (players[i].exiting) - exiting++; - } - - if (cv_playersforexit.value != 4) - { - total *= cv_playersforexit.value; - if (total & 3) - total += 4; // round up - total /= 4; - } - - if (exiting < total) - { - if (!splitscreen && !donef12) + for (i = 0; i < MAXPLAYERS; i++) { - textHUDdraw(M_GetText("\x82""VIEWPOINT:""\x80 Switch view")) - donef12 = true; + if (!playeringame[i] || players[i].spectator) + continue; + if (players[i].lives <= 0) + continue; + + total++; + if (players[i].exiting) + exiting++; + } + + if (numneeded != 4) + { + total *= cv_playersforexit.value; + if (total & 3) + total += 4; // round up + total /= 4; + } + + if (exiting < total) + { + if (!splitscreen && !donef12) + { + textHUDdraw(M_GetText("\x82""VIEWPOINT:""\x80 Switch view")) + donef12 = true; + } + total -= exiting; + textHUDdraw(va(M_GetText("%d player%s remaining"), total, ((total == 1) ? "" : "s"))) } - total -= exiting; - textHUDdraw(va(M_GetText("%d player%s remaining"), total, ((total == 1) ? "" : "s"))) } } else if ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) && (!stplyr->spectator))