From 10319386c2469cb881b4fbd978a3b2868e4a1886 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 11 Feb 2021 20:25:22 -0500 Subject: [PATCH 01/50] Do starttime calculation on second tick instead Attempts to fix replays & adding bots. --- src/k_kart.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/k_kart.h | 1 + src/p_setup.c | 50 ++++++++++++-------------------------------------- src/p_tick.c | 7 +++++++ 4 files changed, 71 insertions(+), 38 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 2f01f2dc0..026ac665f 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -43,6 +43,57 @@ // indirectitemcooldown is timer before anyone's allowed another Shrink/SPB // mapreset is set when enough players fill an empty server +void K_TimerInit(void) +{ + UINT8 i; + UINT8 numPlayers = 0; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + { + continue; + } + + if (players[i].spectator == true) + { + continue; + } + + numPlayers++; + } + + if (numPlayers >= 2) + { + rainbowstartavailable = true; + } + else + { + rainbowstartavailable = false; + } + + if (numPlayers <= 2) + { + introtime = 0; // No intro in Record Attack / 1v1 + } + else + { + introtime = (108) + 5; // 108 for rotation, + 5 for white fade + } + + numbulbs = 5; + + if (numPlayers > 2) + { + numbulbs += (numPlayers-2); + } + + starttime = (introtime + (3*TICRATE)) + ((2*TICRATE) + (numbulbs * bulbtime)); // Start countdown time, + buffer time + + // NOW you can try to spawn in the Battle capsules, if there's not enough players for a match + K_SpawnBattleCapsules(); +} + UINT16 K_GetPlayerDontDrawFlag(player_t *player) { UINT16 flag = 0; diff --git a/src/k_kart.h b/src/k_kart.h index 9b92fff7c..71073587e 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -17,6 +17,7 @@ angle_t K_ReflectAngle(angle_t angle, angle_t against, fixed_t maxspeed, fixed_t void K_RegisterKartStuff(void); +void K_TimerInit(void); UINT16 K_GetPlayerDontDrawFlag(player_t *player); boolean K_IsPlayerLosing(player_t *player); fixed_t K_GetKartGameSpeedScalar(SINT8 value); diff --git a/src/p_setup.c b/src/p_setup.c index 6cd4ffd72..a9e05f6f8 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3427,29 +3427,6 @@ static void P_InitLevelSettings(void) players[i].follower = NULL; } - rainbowstartavailable = false; - - if (p >= 2) - rainbowstartavailable = true; - - if (p <= 2) - { - introtime = 0; // No intro in Record Attack / 1v1 - } - else - { - introtime = (108) + 5; // 108 for rotation, + 5 for white fade - } - - numbulbs = 5; - - if (p > 2) - { - numbulbs += (p-2); - } - - starttime = (introtime + (3*TICRATE)) + ((2*TICRATE) + (numbulbs * bulbtime)); // Start countdown time, + buffer time - // SRB2Kart: map load variables if (grandprixinfo.gp == true) { @@ -4149,21 +4126,6 @@ boolean P_LoadLevel(boolean fromnetsave) lastmaploaded = gamemap; // HAS to be set after saving!! } - if (!fromnetsave) // uglier hack - { // to make a newly loaded level start on the second frame. - INT32 buf = gametic % TICQUEUE; - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i]) - G_CopyTiccmd(&players[i].cmd, &netcmds[buf][i], 1); - } - P_PreTicker(2); - LUAh_MapLoad(); - } - - // NOW you can try to spawn in the Battle capsules, if there's not enough players for a match - K_SpawnBattleCapsules(); - if (grandprixinfo.gp == true) { if (grandprixinfo.initalize == true) @@ -4183,6 +4145,18 @@ boolean P_LoadLevel(boolean fromnetsave) K_UpdateMatchRaceBots(); } + if (!fromnetsave) // uglier hack + { // to make a newly loaded level start on the second frame. + INT32 buf = gametic % TICQUEUE; + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i]) + G_CopyTiccmd(&players[i].cmd, &netcmds[buf][i], 1); + } + P_PreTicker(2); + LUAh_MapLoad(); + } + // No render mode, stop here. if (rendermode == render_none) return true; diff --git a/src/p_tick.c b/src/p_tick.c index 71ded772c..85ee844dd 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -705,6 +705,13 @@ void P_Ticker(boolean run) if (demo.playback) G_StoreRewindInfo(); + if (leveltime == 2) + { + // The values needed to set this properly are not correct at map load, + // so we have to do it at the second tick instead... + K_TimerInit(); + } + // Z_CheckMemCleanup(); } From e2dcc35bcd5585709e320b4d87a713e2c50bf140 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 12 Feb 2021 20:25:03 -0500 Subject: [PATCH 02/50] Reset properties on map load --- src/g_game.c | 6 +++--- src/k_kart.c | 6 ++++++ src/k_kart.h | 1 + src/p_setup.c | 2 ++ 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 0a494918f..155633606 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -246,11 +246,11 @@ INT32 gameovertics = 15*TICRATE; UINT8 ammoremovaltics = 2*TICRATE; // SRB2kart -tic_t introtime = 0; -tic_t starttime = 0; +tic_t introtime = 3; +tic_t starttime = 3; const tic_t bulbtime = TICRATE/2; -UINT8 numbulbs = 0; +UINT8 numbulbs = 1; tic_t raceexittime = 5*TICRATE + (2*TICRATE/3); tic_t battleexittime = 8*TICRATE; diff --git a/src/k_kart.c b/src/k_kart.c index 026ac665f..5a808a7b4 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -43,6 +43,12 @@ // indirectitemcooldown is timer before anyone's allowed another Shrink/SPB // mapreset is set when enough players fill an empty server +void K_TimerReset(void) +{ + starttime = introtime = 3; + numbulbs = 1; +} + void K_TimerInit(void) { UINT8 i; diff --git a/src/k_kart.h b/src/k_kart.h index 71073587e..0e3aa0ff4 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -17,6 +17,7 @@ angle_t K_ReflectAngle(angle_t angle, angle_t against, fixed_t maxspeed, fixed_t void K_RegisterKartStuff(void); +void K_TimerReset(void); void K_TimerInit(void); UINT16 K_GetPlayerDontDrawFlag(player_t *player); boolean K_IsPlayerLosing(player_t *player); diff --git a/src/p_setup.c b/src/p_setup.c index a9e05f6f8..6ffb2e427 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4157,6 +4157,8 @@ boolean P_LoadLevel(boolean fromnetsave) LUAh_MapLoad(); } + K_TimerReset(); + // No render mode, stop here. if (rendermode == render_none) return true; From b91ceddcbf10b3c2fef55d311ea47dc408029dba Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 12 Feb 2021 20:27:14 -0500 Subject: [PATCH 03/50] Sync numbulbs I don't think this has ever caused issues (numbulbs is just for HUD), but the drawn bulbs on start up might as well be synched if the starttime needs to be resynched too. --- src/p_saveg.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/p_saveg.c b/src/p_saveg.c index 0eff1e1d3..7ea1decdf 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -4178,6 +4178,7 @@ static void P_NetArchiveMisc(void) WRITEUINT32(save_p, introtime); WRITEUINT32(save_p, starttime); + WRITEUINT8(save_p, numbulbs); // Is it paused? if (paused) @@ -4312,6 +4313,7 @@ static inline boolean P_NetUnArchiveMisc(void) introtime = READUINT32(save_p); starttime = READUINT32(save_p); + numbulbs = READUINT8(save_p); // Is it paused? if (READUINT8(save_p) == 0x2f) From b66965185ae692e669e32a0b96c303846f35212d Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 14 Feb 2021 21:48:55 +0000 Subject: [PATCH 04/50] Caltrop calstop (resolves #114). If a ring isn't lost from the counter, don't drop a caltrop. This is done by changing the function signature of P_GivePlayerRings to return the number of rings it has successfully given (or taken away) (which can differ from the rings provided to it). This change has been done for Lua as well. Super Ring absorbtion now uses this system too, so you only need to change one location to modify the maximum and minimum number of rings a player can have (as far as I am aware). --- src/lua_baselib.c | 4 ++-- src/p_enemy.c | 4 +--- src/p_inter.c | 7 +++---- src/p_local.h | 2 +- src/p_user.c | 22 ++++++++++++++-------- 5 files changed, 21 insertions(+), 18 deletions(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index b33db8728..c400f01c5 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -1195,8 +1195,8 @@ static int lib_pGivePlayerRings(lua_State *L) INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); - P_GivePlayerRings(player, num_rings); - return 0; + lua_pushinteger(L, P_GivePlayerRings(player, num_rings)); + return 1; } static int lib_pGivePlayerLives(lua_State *L) diff --git a/src/p_enemy.c b/src/p_enemy.c index a2c719609..c96bf979f 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -4186,10 +4186,8 @@ void A_AttractChase(mobj_t *actor) { if (actor->extravalue1 >= 16) { - if (actor->target->player->rings >= 20) + if (!P_GivePlayerRings(actor->target->player, 1)) // returns 0 if addition failed actor->target->player->kartstuff[k_ringboost] += K_GetKartRingPower(actor->target->player)+3; - else - P_GivePlayerRings(actor->target->player, 1); if (actor->cvmem) // caching S_StartSound(actor->target, sfx_s1c5); diff --git a/src/p_inter.c b/src/p_inter.c index 4371752c8..eb2cabc66 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2211,15 +2211,14 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings) if (K_GetShieldFromItem(player->kartstuff[k_itemtype]) != KSHIELD_NONE) return; - // 20 is the ring cap in kart + // 20 is the maximum number of rings that can be taken from you at once - half the span of your counter if (num_rings > 20) num_rings = 20; else if (num_rings <= 0) return; - num_fling_rings = min(num_rings, player->rings); - - P_GivePlayerRings(player, -num_rings); + num_rings = -P_GivePlayerRings(player, -num_rings); + num_fling_rings = num_rings+min(0, player->rings); // determine first angle fa = player->mo->angle + ((P_RandomByte() & 1) ? -ANGLE_90 : ANGLE_90); diff --git a/src/p_local.h b/src/p_local.h index c5eac863e..be4065466 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -167,7 +167,7 @@ boolean P_EndingMusic(player_t *player); void P_SpawnShieldOrb(player_t *player); void P_SwitchShield(player_t *player, UINT16 shieldtype); mobj_t *P_SpawnGhostMobj(mobj_t *mobj); -void P_GivePlayerRings(player_t *player, INT32 num_rings); +INT32 P_GivePlayerRings(player_t *player, INT32 num_rings); void P_GivePlayerSpheres(player_t *player, INT32 num_spheres); void P_GivePlayerLives(player_t *player, INT32 numlives); UINT8 P_GetNextEmerald(void); diff --git a/src/p_user.c b/src/p_user.c index e4785b249..963945c7a 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -487,23 +487,29 @@ void P_ResetPlayer(player_t *player) // // Gives rings to the player, and does any special things required. // Call this function when you want to increment the player's health. +// Returns the number of rings successfully given (or taken). // -void P_GivePlayerRings(player_t *player, INT32 num_rings) +INT32 P_GivePlayerRings(player_t *player, INT32 num_rings) { + INT32 test; + if (!player->mo) - return; + return 0; if ((gametyperules & GTR_BUMPERS)) // No rings in Battle Mode - return; + return 0; + + test = player->rings + num_rings; + if (test > 20) // Caps at 20 rings, sorry! + num_rings -= (test-20); + else if (test < -20) // Chaotix ring debt! + num_rings -= (test+20); player->rings += num_rings; - //player->totalring += num_rings; // Used for GP lives later + //player->totalring += num_rings; // Used for GP lives later -- maybe you might want to move this earlier to discourage ring debt... - if (player->rings > 20) - player->rings = 20; // Caps at 20 rings, sorry! - else if (player->rings < -20) - player->rings = -20; // Chaotix ring debt! + return num_rings; } // From b672ffa8ba598df341585ac02a7e5eae3dc3fe90 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 14 Feb 2021 22:55:03 -0800 Subject: [PATCH 05/50] Check previously considered best waypoint when pathfinding to solve overlapping waypoints Previously could skip the waypoint that was actually closer and assume the further is the best. --- src/k_waypoint.c | 58 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 18 deletions(-) diff --git a/src/k_waypoint.c b/src/k_waypoint.c index 39e9efa5e..4150ff333 100644 --- a/src/k_waypoint.c +++ b/src/k_waypoint.c @@ -253,6 +253,40 @@ waypoint_t *K_GetClosestWaypointToMobj(mobj_t *const mobj) return closestwaypoint; } +/*-------------------------------------------------- + static void K_CompareOverlappingWaypoint + ( waypoint_t *const checkwaypoint, + waypoint_t **const bestwaypoint, + fixed_t *const bestfindist) + + Solves touching overlapping waypoint radiuses by sorting by distance to + finish line. +--------------------------------------------------*/ +static void K_CompareOverlappingWaypoint +( waypoint_t *const checkwaypoint, + waypoint_t **const bestwaypoint, + fixed_t *const bestfindist) +{ + const boolean useshortcuts = false; + const boolean huntbackwards = false; + boolean pathfindsuccess = false; + path_t pathtofinish = {}; + + pathfindsuccess = + K_PathfindToWaypoint(checkwaypoint, finishline, &pathtofinish, useshortcuts, huntbackwards); + + if (pathfindsuccess == true) + { + if ((INT32)(pathtofinish.totaldist) < *bestfindist) + { + *bestwaypoint = checkwaypoint; + *bestfindist = pathtofinish.totaldist; + } + + Z_Free(pathtofinish.array); + } +} + /*-------------------------------------------------- waypoint_t *K_GetBestWaypointForMobj(mobj_t *const mobj) @@ -292,30 +326,18 @@ waypoint_t *K_GetBestWaypointForMobj(mobj_t *const mobj) rad = (checkwaypoint->mobj->radius / FRACUNIT); - if (closestdist < rad && checkdist < rad && finishline != NULL) + // remember: huge radius + if (closestdist <= rad && checkdist <= rad && finishline != NULL) { - const boolean useshortcuts = false; - const boolean huntbackwards = false; - boolean pathfindsuccess = false; - path_t pathtofinish = {}; - // If the mobj is touching multiple waypoints at once, // then solve ties by taking the one closest to the finish line. // Prevents position from flickering wildly when taking turns. - pathfindsuccess = - K_PathfindToWaypoint(checkwaypoint, finishline, &pathtofinish, useshortcuts, huntbackwards); + // For the first couple overlapping, check the previous best too. + if (bestfindist == INT32_MAX) + K_CompareOverlappingWaypoint(bestwaypoint, &bestwaypoint, &bestfindist); - if (pathfindsuccess == true) - { - if ((INT32)(pathtofinish.totaldist) < bestfindist) - { - bestwaypoint = checkwaypoint; - bestfindist = pathtofinish.totaldist; - } - - Z_Free(pathtofinish.array); - } + K_CompareOverlappingWaypoint(checkwaypoint, &bestwaypoint, &bestfindist); } else if (checkdist < closestdist && bestfindist == INT32_MAX) { From b4eefec81d143856bcd7d9cd4d91297dfe573249 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 14 Feb 2021 22:56:36 -0800 Subject: [PATCH 06/50] Fix angle issue with finish line waypoint hack The other hack which adds distance is also gone. It's not needed for ...reasons. All this was Sal's massive brain. --- src/k_kart.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index 4d5e1770e..94b2b1237 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -6553,8 +6553,12 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player) if (bestwaypoint == K_GetFinishLineWaypoint()) { + waypoint_t *nextwaypoint = waypoint->nextwaypoints[0]; + angle_t angletonextwaypoint = + R_PointToAngle2(waypoint->mobj->x, waypoint->mobj->y, nextwaypoint->mobj->x, nextwaypoint->mobj->y); + // facing towards the finishline - if (angledelta <= ANGLE_90) + if (abs(AngleDifference(angletonextwaypoint, angletowaypoint)) <= ANGLE_90) { finishlinehack = true; } @@ -6698,6 +6702,7 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player) return bestwaypoint; } +#if 0 static boolean K_PlayerCloserToNextWaypoints(waypoint_t *const waypoint, player_t *const player) { boolean nextiscloser = true; @@ -6758,6 +6763,7 @@ static boolean K_PlayerCloserToNextWaypoints(waypoint_t *const waypoint, player_ return nextiscloser; } +#endif /*-------------------------------------------------- void K_UpdateDistanceFromFinishLine(player_t *const player) @@ -6837,6 +6843,7 @@ void K_UpdateDistanceFromFinishLine(player_t *const player) player->distancetofinish += numfulllapsleft * K_GetCircuitLength(); +#if 0 // An additional HACK, to fix looking backwards towards the finish line // If the player's next waypoint is the finishline and the angle distance from player to // connectin waypoints implies they're closer to a next waypoint, add a full track distance @@ -6847,6 +6854,7 @@ void K_UpdateDistanceFromFinishLine(player_t *const player) player->distancetofinish += K_GetCircuitLength(); } } +#endif } } } From 29d9bafb9e405fe6df8db2abc273c06def5356dd Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 14 Feb 2021 23:04:17 -0800 Subject: [PATCH 07/50] Snap finish line waypoints to the nearest point of the finish line Finish line waypoints must be exactly on the finish line to avoid erroneous finish line distance from crossing the waypoint before/after the line. This is only a problem in circuit maps and on laps before the last, due to the multiplied circuit length. --- src/p_mobj.c | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 2bc6c620f..ac48b953d 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11325,6 +11325,39 @@ static boolean P_SetupBooster(mapthing_t* mthing, mobj_t* mobj, boolean strong) return true; } +static fixed_t dist2vert(const vertex_t *v, const mobj_t *o) +{ + return abs(FixedHypot(v->x - o->x, v->y - o->y)); +} + +static void P_SnapToFinishLine(mobj_t *mobj) +{ + const sector_t *sector = mobj->subsector->sector; + size_t i; + fixed_t d; + fixed_t nearest = INT32_MAX; + line_t *nearest_line = NULL; + for (i = 0; i < sector->linecount; ++i) + { + if ( + sector->lines[i]->special == 2001 && // case 2001: Finish Line + ( + (d = dist2vert(sector->lines[i]->v1, mobj)) < nearest || + (d = dist2vert(sector->lines[i]->v2, mobj)) < nearest + ) + ){ + nearest = d; + nearest_line = sector->lines[i]; + } + } + if (nearest < INT32_MAX) + { + P_UnsetThingPosition(mobj); + P_ClosestPointOnLine(mobj->x, mobj->y, nearest_line, (vertex_t *)&mobj->x); + P_SetThingPosition(mobj); + } +} + static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean *doangle) { boolean override = LUAh_MapThingSpawn(mobj, mthing); @@ -11708,7 +11741,8 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean } if (mthing->args[2] == 1) { - mobj->extravalue2 = 1; // args[1] of 1 means the waypoint is at the finish line + mobj->extravalue2 = 1; // args[2] of 1 means the waypoint is at the finish line + P_SnapToFinishLine(mobj); } else { From 4f96fead3a0f8025c5a926257a7eb7e8665db6ed Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 15 Feb 2021 01:46:29 -0800 Subject: [PATCH 08/50] Search entire map, not just waypoint's sector, for finish line --- src/p_mobj.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index ac48b953d..286c99742 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11332,22 +11332,19 @@ static fixed_t dist2vert(const vertex_t *v, const mobj_t *o) static void P_SnapToFinishLine(mobj_t *mobj) { - const sector_t *sector = mobj->subsector->sector; - size_t i; + INT32 i = -1; fixed_t d; fixed_t nearest = INT32_MAX; line_t *nearest_line = NULL; - for (i = 0; i < sector->linecount; ++i) + // case 2001: Finish Line + while ((i = P_FindSpecialLineFromTag(2001, -1, i)) != -1) { if ( - sector->lines[i]->special == 2001 && // case 2001: Finish Line - ( - (d = dist2vert(sector->lines[i]->v1, mobj)) < nearest || - (d = dist2vert(sector->lines[i]->v2, mobj)) < nearest - ) + (d = dist2vert(lines[i].v1, mobj)) < nearest || + (d = dist2vert(lines[i].v2, mobj)) < nearest ){ nearest = d; - nearest_line = sector->lines[i]; + nearest_line = &lines[i]; } } if (nearest < INT32_MAX) From a210049839f7bb3fe82c4e28f7d7c5f6dc221592 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 15 Feb 2021 11:43:45 +0000 Subject: [PATCH 09/50] Attempt to calculate postimg during chasecam hitlag - otherwise encore mode will temporarily flip back and it'll be confusing. --- src/p_user.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/p_user.c b/src/p_user.c index e4785b249..8ab54980d 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -3074,6 +3074,10 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall { // Do not move the camera while in hitlag! // The camera zooming out after you got hit makes it hard to focus on the vibration. + // of course, if you're in chase, don't forget the postimage - otherwise encore will flip back + if (thiscam->chase) + P_CalcChasePostImg(player, thiscam); + return true; } From 8a4542a5ef15ad4772aefe5665feed2a3fc5780f Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 15 Feb 2021 12:26:22 +0000 Subject: [PATCH 10/50] Reintroduce the mirroring aspect of Encore in OpenGL. I'm not familiar enough with the renderer to recreate the rest of the changes at current, but this is the most significant regression. --- src/hardware/hw_main.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index c299d9c87..df265e504 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5526,6 +5526,11 @@ static void HWR_DrawSkyBackground(player_t *player) else dometransform.flip = false; + if (*type == postimg_mirror) + dometransform.mirror = true; + else + dometransform.mirror = false; + dometransform.scalex = 1; dometransform.scaley = (float)vid.width/vid.height; dometransform.scalez = 1; @@ -5802,6 +5807,11 @@ void HWR_RenderSkyboxView(player_t *player) else atransform.flip = false; + if (*type == postimg_mirror) + atransform.mirror = true; + else + atransform.mirror = false; + atransform.x = gl_viewx; // FIXED_TO_FLOAT(viewx) atransform.y = gl_viewy; // FIXED_TO_FLOAT(viewy) atransform.z = gl_viewz; // FIXED_TO_FLOAT(viewz) @@ -6005,6 +6015,11 @@ void HWR_RenderPlayerView(void) else atransform.flip = false; + if (*type == postimg_mirror) + atransform.mirror = true; + else + atransform.mirror = false; + atransform.x = gl_viewx; // FIXED_TO_FLOAT(viewx) atransform.y = gl_viewy; // FIXED_TO_FLOAT(viewy) atransform.z = gl_viewz; // FIXED_TO_FLOAT(viewz) From a597d9b4636d575af110bd0fdd6b2c2c1619f74d Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 15 Feb 2021 16:37:37 +0000 Subject: [PATCH 11/50] Fixed a too-small memory allocation for Encore remaps, removing all memory-related crashes in Software. --- src/r_data.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_data.c b/src/r_data.c index 39c41d8bf..851e0cd93 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -731,7 +731,7 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) // Now allocate memory for the actual colormap array itself! // aligned on 8 bit for asm code - colormap_p = Z_MallocAlign((256 * 34) + 10, PU_LEVEL, NULL, 8); + colormap_p = Z_MallocAlign((256 * (encoremap ? 64 : 32)) + 10, PU_LEVEL, NULL, 8); lighttable = (UINT8 *)colormap_p; // Calculate the palette index for each palette index, for each light level From f40836dcecf87ff4004a15db2e86bfabbdfb4678 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 15 Feb 2021 21:55:40 +0000 Subject: [PATCH 12/50] Fix skies not being Encore-remapped (only affected software :regret:) --- src/r_plane.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/r_plane.c b/src/r_plane.c index 3ec74bc47..a987fa330 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -644,6 +644,8 @@ static void R_DrawSkyPlane(visplane_t *pl) // Because of this hack, sky is not affected // by sector colormaps (INVUL inverse mapping is not implemented in SRB2 so is irrelevant). dc_colormap = colormaps; + if (encoremap) + dc_colormap += (256*32); dc_texturemid = skytexturemid; dc_texheight = textureheight[skytexture] >>FRACBITS; From 82718216ccd11f0218d039da23f46af4ddabcabc Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 15 Feb 2021 23:01:13 -0800 Subject: [PATCH 13/50] Respawn slightly before a waypoint, in the direction you came from, if the waypoint is exactly on a line See notably the finish line. Basically respawning exactly on a line can let you cross it twice, if you crossed it before respawning, or NOT cross it, depending on which direction you drive after landing. So this just respawns very slightly before the line so you can cross (or not cross) it normally. --- src/k_respawn.c | 20 ++++++++++++++ src/k_waypoint.c | 38 ++++++++++++++++++++++++++ src/k_waypoint.h | 1 + src/p_maputl.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++ src/p_maputl.h | 1 + src/p_mobj.c | 26 +++--------------- 6 files changed, 134 insertions(+), 22 deletions(-) diff --git a/src/k_respawn.c b/src/k_respawn.c index 7052fe466..897300254 100644 --- a/src/k_respawn.c +++ b/src/k_respawn.c @@ -54,6 +54,21 @@ fixed_t K_RespawnOffset(player_t *player, boolean flip) return z; } +/*-------------------------------------------------- + static void K_FudgeRespawn(player_t *player, const waypoint_t *const waypoint) + + Fudges respawn coordinates to slightly before the waypoint if it would + be exactly on a line. See K_GetWaypointIsOnLine. +--------------------------------------------------*/ +static void K_FudgeRespawn(player_t *player, const waypoint_t *const waypoint) +{ + const angle_t from = R_PointToAngle2(waypoint->mobj->x, waypoint->mobj->y, + player->mo->x, player->mo->y) >> ANGLETOFINESHIFT; + + player->respawn.pointx += FixedMul(16, FINECOSINE(from)); + player->respawn.pointy += FixedMul(16, FINESINE(from)); +} + /*-------------------------------------------------- static void K_RespawnAtWaypoint(player_t *player, waypoint_t *waypoint) @@ -83,6 +98,11 @@ static void K_RespawnAtWaypoint(player_t *player, waypoint_t *waypoint) player->respawn.pointz = waypoint->mobj->z; player->respawn.flip = (waypoint->mobj->flags2 & MF2_OBJECTFLIP) ? true : false; // K_RespawnOffset wants a boolean! player->respawn.pointz += K_RespawnOffset(player, player->respawn.flip); + + if (waypoint->onaline) + { + K_FudgeRespawn(player, waypoint); + } } /*-------------------------------------------------- diff --git a/src/k_waypoint.c b/src/k_waypoint.c index 4150ff333..ae6841a34 100644 --- a/src/k_waypoint.c +++ b/src/k_waypoint.c @@ -153,6 +153,38 @@ boolean K_GetWaypointIsSpawnpoint(waypoint_t *waypoint) return waypointisspawnpoint; } +/*-------------------------------------------------- + static boolean K_GetWaypointIsOnLine(waypoint_t *const waypoint) + + Checks if a waypoint is exactly on a line. Moving to an exact point + on a line won't count as crossing it. Moving off of that point does. + Respawning to a waypoint which is exactly on a line is the easiest + way to for this to occur. + + Return:- + Whether the waypoint is exactly on a line. +--------------------------------------------------*/ +static boolean K_GetWaypointIsOnLine(waypoint_t *const waypoint) +{ + const fixed_t x = waypoint->mobj->x; + const fixed_t y = waypoint->mobj->y; + + line_t *line = P_FindNearestLine(x, y, + waypoint->mobj->subsector->sector, -1); + + vertex_t point; + + if (line != NULL) + { + P_ClosestPointOnLine(x, y, line, &point); + + if (x == point.x && y == point.y) + return true; + } + + return false; +} + /*-------------------------------------------------- INT32 K_GetWaypointNextID(waypoint_t *waypoint) @@ -1700,6 +1732,12 @@ static waypoint_t *K_SetupWaypoint(mobj_t *const mobj) finishline = thiswaypoint; } + /* only relevant for respawning */ + if (K_GetWaypointIsSpawnpoint(thiswaypoint)) + { + thiswaypoint->onaline = K_GetWaypointIsOnLine(thiswaypoint); + } + if (thiswaypoint->numnextwaypoints > 0) { waypoint_t *nextwaypoint = NULL; diff --git a/src/k_waypoint.h b/src/k_waypoint.h index 41230b49b..f49e162e8 100644 --- a/src/k_waypoint.h +++ b/src/k_waypoint.h @@ -23,6 +23,7 @@ typedef struct waypoint_s { mobj_t *mobj; + boolean onaline; struct waypoint_s **nextwaypoints; struct waypoint_s **prevwaypoints; UINT32 *nextwaypointdistances; diff --git a/src/p_maputl.c b/src/p_maputl.c index 9131c24bb..4dce1e6fd 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -259,6 +259,76 @@ fixed_t P_InterceptVector(divline_t *v2, divline_t *v1) return frac; } +static fixed_t dist2line(const line_t *ld, const fixed_t x, const fixed_t y) +{ + return FixedHypot + ( + ld->v1->x + (ld->dx / 2) - x, + ld->v1->y + (ld->dy / 2) - y + ); +} + +static void checknearline +( line_t * line, + fixed_t * near, + line_t ** near_line, + const fixed_t x, + const fixed_t y) +{ + const fixed_t d = dist2line(line, x, y); + + if (d < *near) + { + *near = d; + *near_line = line; + } +} + +// +// P_FindNearestLine +// Returns the nearest line to a point which +// is in a sector and/or a specific type. +// +line_t * P_FindNearestLine +( const fixed_t x, + const fixed_t y, + const sector_t * sector, + const INT32 special) +{ + fixed_t near = INT32_MAX; + line_t *near_line = NULL; + size_t i; + INT32 line = -1; + + if (special == -1) + { + if (sector == NULL) + sector = R_PointInSubsector(x, y)->sector; + + for (i = 0; i < sector->linecount; ++i) + { + checknearline(sector->lines[i], &near, &near_line, x, y); + } + } + else if (sector != NULL) + { + for (i = 0; i < sector->linecount; ++i) + { + if (sector->lines[i]->special == special) + checknearline(sector->lines[i], &near, &near_line, x, y); + } + } + else + { + while ((line = P_FindSpecialLineFromTag(special, -1, line)) != -1) + { + checknearline(&lines[line], &near, &near_line, x, y); + } + } + + return near_line; +} + // // P_LineOpening // Sets opentop and openbottom to the window through a two sided line. diff --git a/src/p_maputl.h b/src/p_maputl.h index ce4509ca9..6f0c1f8ad 100644 --- a/src/p_maputl.h +++ b/src/p_maputl.h @@ -49,6 +49,7 @@ void P_MakeDivline(line_t *li, divline_t *dl); void P_CameraLineOpening(line_t *plinedef); fixed_t P_InterceptVector(divline_t *v2, divline_t *v1); INT32 P_BoxOnLineSide(fixed_t *tmbox, line_t *ld); +line_t * P_FindNearestLine(const fixed_t x, const fixed_t y, const sector_t *, const INT32 special); void P_UnsetPrecipThingPosition(precipmobj_t *thing); void P_SetPrecipitationThingPosition(precipmobj_t *thing); void P_CreatePrecipSecNodeList(precipmobj_t *thing, fixed_t x,fixed_t y); diff --git a/src/p_mobj.c b/src/p_mobj.c index 286c99742..137802730 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11325,32 +11325,14 @@ static boolean P_SetupBooster(mapthing_t* mthing, mobj_t* mobj, boolean strong) return true; } -static fixed_t dist2vert(const vertex_t *v, const mobj_t *o) -{ - return abs(FixedHypot(v->x - o->x, v->y - o->y)); -} - static void P_SnapToFinishLine(mobj_t *mobj) { - INT32 i = -1; - fixed_t d; - fixed_t nearest = INT32_MAX; - line_t *nearest_line = NULL; - // case 2001: Finish Line - while ((i = P_FindSpecialLineFromTag(2001, -1, i)) != -1) - { - if ( - (d = dist2vert(lines[i].v1, mobj)) < nearest || - (d = dist2vert(lines[i].v2, mobj)) < nearest - ){ - nearest = d; - nearest_line = &lines[i]; - } - } - if (nearest < INT32_MAX) + line_t *finishline = P_FindNearestLine(mobj->x, mobj->y, + mobj->subsector->sector, 2001); // case 2001: Finish Line + if (finishline != NULL) { P_UnsetThingPosition(mobj); - P_ClosestPointOnLine(mobj->x, mobj->y, nearest_line, (vertex_t *)&mobj->x); + P_ClosestPointOnLine(mobj->x, mobj->y, finishline, (vertex_t *)&mobj->x); P_SetThingPosition(mobj); } } From 130e1fc4f92329cee00bc2de759d2ba1ba4d89c0 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 15 Feb 2021 23:12:30 -0800 Subject: [PATCH 14/50] Windows??? --- src/p_maputl.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/p_maputl.c b/src/p_maputl.c index 4dce1e6fd..5cf2e81fe 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -270,16 +270,16 @@ static fixed_t dist2line(const line_t *ld, const fixed_t x, const fixed_t y) static void checknearline ( line_t * line, - fixed_t * near, + fixed_t * nearest, line_t ** near_line, const fixed_t x, const fixed_t y) { const fixed_t d = dist2line(line, x, y); - if (d < *near) + if (d < *nearest) { - *near = d; + *nearest = d; *near_line = line; } } @@ -295,7 +295,7 @@ line_t * P_FindNearestLine const sector_t * sector, const INT32 special) { - fixed_t near = INT32_MAX; + fixed_t nearest = INT32_MAX; line_t *near_line = NULL; size_t i; INT32 line = -1; @@ -307,7 +307,7 @@ line_t * P_FindNearestLine for (i = 0; i < sector->linecount; ++i) { - checknearline(sector->lines[i], &near, &near_line, x, y); + checknearline(sector->lines[i], &nearest, &near_line, x, y); } } else if (sector != NULL) @@ -315,14 +315,14 @@ line_t * P_FindNearestLine for (i = 0; i < sector->linecount; ++i) { if (sector->lines[i]->special == special) - checknearline(sector->lines[i], &near, &near_line, x, y); + checknearline(sector->lines[i], &nearest, &near_line, x, y); } } else { while ((line = P_FindSpecialLineFromTag(special, -1, line)) != -1) { - checknearline(&lines[line], &near, &near_line, x, y); + checknearline(&lines[line], &nearest, &near_line, x, y); } } From 9fae8dbb41ed3c741a8b443da58fd5f8352273d6 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 15 Feb 2021 23:08:32 -0800 Subject: [PATCH 15/50] Don't respawn on the finish line waypoint This causes you to respawn at the waypoint before the finish line waypoint, which I think looks a bit nicer. --- src/p_mobj.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/p_mobj.c b/src/p_mobj.c index 137802730..3dd5108a0 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11721,6 +11721,8 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean if (mthing->args[2] == 1) { mobj->extravalue2 = 1; // args[2] of 1 means the waypoint is at the finish line + mobj->reactiontime = 0; // Also don't respawn at finish lines + P_SnapToFinishLine(mobj); } else From b77a67c0853cdfc84c897fd49c63e8208686f9fe Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 16 Feb 2021 03:54:09 -0800 Subject: [PATCH 16/50] Fix caltrop burst in reverse gravity; condense function I'm not sure how the rings were working though. --- src/p_inter.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/src/p_inter.c b/src/p_inter.c index 4371752c8..bb58ba555 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2138,7 +2138,6 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da static void P_FlingBurst ( player_t *player, angle_t fa, - fixed_t z, mobjtype_t objType, tic_t objFuse, fixed_t objScale, @@ -2149,18 +2148,17 @@ static void P_FlingBurst fixed_t momxy = 5<> 1; - z = player->mo->z; - if (player->mo->eflags & MFE_VERTICALFLIP) - z += player->mo->height - mobjinfo[objType].height; - - mo = P_SpawnMobj(player->mo->x, player->mo->y, z, objType); + mo = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, objType); mo->threshold = 10; // not useful for spikes mo->fuse = objFuse; P_SetTarget(&mo->target, player->mo); - mo->destscale = objScale; - P_SetScale(mo, objScale); + if (objScale != FRACUNIT) + { + P_SetScale(mo, FixedMul(objScale, mo->scale)); + mo->destscale = mo->scale; + } /* 0: 0 @@ -2197,7 +2195,6 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings) INT32 num_fling_rings; INT32 i; angle_t fa; - fixed_t z; // Rings shouldn't be in Battle! if (gametyperules & GTR_SPHERES) @@ -2224,19 +2221,13 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings) // determine first angle fa = player->mo->angle + ((P_RandomByte() & 1) ? -ANGLE_90 : ANGLE_90); - z = player->mo->z; - if (player->mo->eflags & MFE_VERTICALFLIP) - z += player->mo->height - mobjinfo[MT_RING].height; - for (i = 0; i < num_fling_rings; i++) { - P_FlingBurst(player, fa, z, - MT_FLINGRING, 60*TICRATE, player->mo->scale, i); + P_FlingBurst(player, fa, MT_FLINGRING, 60*TICRATE, FRACUNIT, i); } while (i < num_rings) { - P_FlingBurst(player, fa, z, - MT_DEBTSPIKE, 0, 3 * player->mo->scale / 2, i++); + P_FlingBurst(player, fa, MT_DEBTSPIKE, 0, 3 * FRACUNIT / 2, i++); } } From 0cf41dade0f860bc1b42b4056ef75f1204110578 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 16 Feb 2021 03:55:37 -0800 Subject: [PATCH 17/50] Improve P_SpawnMobjFromMobj by factoring the scale from P_SpawnMobj in This will copy the parent object's scale to the child, but scale it by the child's original scale relative to the map scale. Also uses the child's actual height, instead of the mobjinfo version. Might be useful if either the scale or height was changed in P_SpawnMobj. Say, from a Lua hook. --- src/p_local.h | 1 + src/p_mobj.c | 18 +++++++++++++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/p_local.h b/src/p_local.h index c5eac863e..a6622b5c1 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -521,5 +521,6 @@ void P_Thrust(mobj_t *mo, angle_t angle, fixed_t move); void P_ExplodeMissile(mobj_t *mo); void P_CheckGravity(mobj_t *mo, boolean affect); void P_SetPitchRollFromSlope(mobj_t *mo, pslope_t *slope); +fixed_t P_ScaleFromMap(fixed_t, fixed_t scale); #endif // __P_LOCAL__ diff --git a/src/p_mobj.c b/src/p_mobj.c index 2bc6c620f..5975da344 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -12748,6 +12748,15 @@ void P_FlashPal(player_t *pl, UINT16 type, UINT16 duration) pl->flashpal = type; } +// +// P_ScaleFromMap +// Scales a number relative to the mapobjectscale. +// +fixed_t P_ScaleFromMap(fixed_t n, fixed_t scale) +{ + return FixedMul(n, FixedDiv(scale, mapobjectscale)); +} + // // P_SpawnMobjFromMobj // Spawns an object with offsets relative to the position of another object. @@ -12765,16 +12774,15 @@ mobj_t *P_SpawnMobjFromMobj(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zo if (!newmobj) return NULL; + newmobj->destscale = P_ScaleFromMap(mobj->destscale, newmobj->destscale); + P_SetScale(newmobj, P_ScaleFromMap(mobj->scale, newmobj->scale)); + if (mobj->eflags & MFE_VERTICALFLIP) { - fixed_t elementheight = FixedMul(newmobj->info->height, mobj->scale); - newmobj->eflags |= MFE_VERTICALFLIP; newmobj->flags2 |= MF2_OBJECTFLIP; - newmobj->z = mobj->z + mobj->height - zofs - elementheight; + newmobj->z = mobj->z + mobj->height - zofs - newmobj->height; } - newmobj->destscale = mobj->destscale; - P_SetScale(newmobj, mobj->scale); return newmobj; } From 81d162d19c75258ea22a3ec6185e713d63eea4d5 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 16 Feb 2021 04:42:27 -0800 Subject: [PATCH 18/50] Add some helper functions for objects in reverse gravity --- src/p_local.h | 4 ++++ src/p_mobj.c | 25 +++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/p_local.h b/src/p_local.h index a6622b5c1..90408e011 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -158,6 +158,7 @@ boolean P_IsObjectInGoop(mobj_t *mo); boolean P_IsObjectOnGround(mobj_t *mo); boolean P_IsObjectOnGroundIn(mobj_t *mo, sector_t *sec); boolean P_IsObjectOnRealGround(mobj_t *mo, sector_t *sec); // SRB2Kart +#define P_IsObjectFlipped(o) ((o)->eflags & MFE_VERTICALFLIP) boolean P_InQuicksand(mobj_t *mo); boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff); @@ -522,5 +523,8 @@ void P_ExplodeMissile(mobj_t *mo); void P_CheckGravity(mobj_t *mo, boolean affect); void P_SetPitchRollFromSlope(mobj_t *mo, pslope_t *slope); fixed_t P_ScaleFromMap(fixed_t, fixed_t scale); +fixed_t P_GetMobjHead(const mobj_t *); +fixed_t P_GetMobjFeet(const mobj_t *); +fixed_t P_GetMobjGround(const mobj_t *); #endif // __P_LOCAL__ diff --git a/src/p_mobj.c b/src/p_mobj.c index 5975da344..ae5179c44 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -12786,3 +12786,28 @@ mobj_t *P_SpawnMobjFromMobj(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zo return newmobj; } + +// +// P_GetMobjHead & P_GetMobjFeet +// Returns the top and bottom of an object, follows appearance, not physics, +// in reverse gravity. +// + +fixed_t P_GetMobjHead(const mobj_t *mobj) +{ + return P_IsObjectFlipped(mobj) ? mobj->z : mobj->z + mobj->height; +} + +fixed_t P_GetMobjFeet(const mobj_t *mobj) +{ + return P_IsObjectFlipped(mobj) ? mobj->z + mobj->height : mobj->z; +} + +// +// P_GetMobjGround +// Returns the object's floor, or ceiling in reverse gravity. +// +fixed_t P_GetMobjGround(const mobj_t *mobj) +{ + return P_IsObjectFlipped(mobj) ? mobj->ceilingz : mobj->floorz; +} From 49bbdd537bfcbef8a6249d9310bca55fea28e7ba Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 16 Feb 2021 04:43:20 -0800 Subject: [PATCH 19/50] Move the debt spike fuse initialization from P_ZMovement to P_MobjThinker slopes + upward momentum = no upward momentum haha --- src/p_mobj.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index ae5179c44..c31624787 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2296,11 +2296,6 @@ boolean P_ZMovement(mobj_t *mo) { mom.x = mom.y = 0; mom.z = -mom.z/2; - - if (mo->fuse == 0) - { - mo->fuse = 90; - } } else if (mo->flags & MF_MISSILE) { @@ -6267,6 +6262,12 @@ static boolean P_MobjRegularThink(mobj_t *mobj) else A_AttractChase(mobj); break; + case MT_DEBTSPIKE: + if (mobj->fuse == 0 && P_GetMobjFeet(mobj) == P_GetMobjGround(mobj)) + { + mobj->fuse = 90; + } + break; case MT_EMBLEM: if (mobj->flags2 & MF2_NIGHTSPULL) P_NightsItemChase(mobj); From 4052e01f4a6055e4e51a49538a8975090e05ff99 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 16 Feb 2021 14:34:00 +0000 Subject: [PATCH 20/50] Introduce a sequence of macros to reduce the reliance of Colormap-related code (especially but not limited to Encore mode) on magic numbers. --- src/hardware/hw_cache.c | 4 ++-- src/hardware/hw_main.c | 4 ++-- src/r_data.c | 14 ++++++++------ src/r_draw8.c | 4 ++-- src/r_main.h | 2 +- src/r_plane.c | 4 ++-- src/r_segs.c | 16 ++++++++-------- src/r_state.h | 4 ++++ src/r_things.c | 4 ++-- src/v_video.c | 2 +- 10 files changed, 32 insertions(+), 26 deletions(-) diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index 73ba81c58..aa7338ad2 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -478,7 +478,7 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex) #ifdef GLENCORE if (encoremap) - grtex->mipmap.colormap += (256*32); + grtex->mipmap.colormap += COLORMAP_REMAPOFFSET; #endif blockwidth = texture->width; @@ -833,7 +833,7 @@ void HWR_LiterallyGetFlat(lumpnum_t flatlumpnum, boolean noencoremap) #ifdef GLENCORE if (!noencoremap && encoremap) - grmip->colormap += (256*32); + grmip->colormap += COLORMAP_REMAPOFFSET; #endif grmip = HWR_GetCachedGLPatch(flatlumpnum)->mipmap; diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index df265e504..4c06c8604 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5224,7 +5224,7 @@ static void HWR_ProjectSprite(mobj_t *thing) vis->colormap = colormaps; #ifdef GLENCORE if (encoremap && (thing->flags & (MF_SCENERY|MF_NOTHINK)) && !(thing->flags & MF_DONTENCOREMAP)) - vis->colormap += (256*32); + vis->colormap += COLORMAP_REMAPOFFSET; #endif } @@ -5331,7 +5331,7 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) #ifdef GLENCORE if (encoremap && !(thing->flags & MF_DONTENCOREMAP)) - vis->colormap += (256*32); + vis->colormap += COLORMAP_REMAPOFFSET; #endif // set top/bottom coords diff --git a/src/r_data.c b/src/r_data.c index 851e0cd93..7c5fb6ce5 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -287,7 +287,9 @@ static void R_InitColormaps(void) // Load in the light tables lump = W_GetNumForName("COLORMAP"); len = W_LumpLength(lump); - colormaps = Z_MallocAlign(len * 2, PU_STATIC, NULL, 8); // * 2 for encore + if (len < COLORMAP_SIZE*2) // accomodate encore mode later + len = COLORMAP_SIZE*2; + colormaps = Z_MallocAlign(len, PU_STATIC, NULL, 8); W_ReadLump(lump, colormaps); // no need to init encoremap at this stage @@ -330,9 +332,9 @@ void R_ReInitColormaps(UINT16 num, lumpnum_t newencoremap) encoremap = Z_MallocAlign(256 + 10, PU_LEVEL, NULL, 8); W_ReadLump(newencoremap, encoremap); colormap_p = colormap_p2 = colormaps; - colormap_p += (256 * 32); + colormap_p += COLORMAP_REMAPOFFSET; - for (p = 0; p < 32; p++) + for (p = 0; p < LIGHTLEVELS; p++) { for (i = 0; i < 256; i++) { @@ -731,12 +733,12 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) // Now allocate memory for the actual colormap array itself! // aligned on 8 bit for asm code - colormap_p = Z_MallocAlign((256 * (encoremap ? 64 : 32)) + 10, PU_LEVEL, NULL, 8); + colormap_p = Z_MallocAlign((COLORMAP_SIZE * (encoremap ? 2 : 1)) + 10, PU_LEVEL, NULL, 8); lighttable = (UINT8 *)colormap_p; // Calculate the palette index for each palette index, for each light level // (as well as the two unused colormap lines we inherited from Doom) - for (p = 0; p < 32; p++) + for (p = 0; p < LIGHTLEVELS; p++) { for (i = 0; i < 256; i++) { @@ -776,7 +778,7 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) { lighttable_t *colormap_p2 = lighttable; - for (p = 0; p < 32; p++) + for (p = 0; p < LIGHTLEVELS; p++) { for (i = 0; i < 256; i++) { diff --git a/src/r_draw8.c b/src/r_draw8.c index 2f7bb64b8..41c74ba3c 100644 --- a/src/r_draw8.c +++ b/src/r_draw8.c @@ -1698,7 +1698,7 @@ void R_DrawColumnShadowed_8(void) { dc_colormap = dc_lightlist[i].rcolormap; if (encoremap) - dc_colormap += (256*32); + dc_colormap += COLORMAP_REMAPOFFSET; if (solid && dc_yl < bheight) dc_yl = bheight; continue; @@ -1716,7 +1716,7 @@ void R_DrawColumnShadowed_8(void) dc_colormap = dc_lightlist[i].rcolormap; if (encoremap) - dc_colormap += (256*32); + dc_colormap += COLORMAP_REMAPOFFSET; } dc_yh = realyh; if (dc_yl <= realyh) diff --git a/src/r_main.h b/src/r_main.h index b4845af18..b7b4c9fd5 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -41,7 +41,7 @@ extern size_t validcount, linecount, loopcount, framecount; // Lighting constants. // Now with 32 levels. -#define LIGHTLEVELS 32 +// LIGHTLEVELS is now defined in r_state.h #define LIGHTSEGSHIFT 3 #define MAXLIGHTSCALE 48 diff --git a/src/r_plane.c b/src/r_plane.c index a987fa330..9ca8eb608 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -232,7 +232,7 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2) ds_colormap = planezlight[pindex]; if (encoremap && !currentplane->noencore) - ds_colormap += (256*32); + ds_colormap += COLORMAP_REMAPOFFSET; if (currentplane->extra_colormap) ds_colormap = currentplane->extra_colormap->colormap + (ds_colormap - colormaps); @@ -645,7 +645,7 @@ static void R_DrawSkyPlane(visplane_t *pl) // by sector colormaps (INVUL inverse mapping is not implemented in SRB2 so is irrelevant). dc_colormap = colormaps; if (encoremap) - dc_colormap += (256*32); + dc_colormap += COLORMAP_REMAPOFFSET; dc_texturemid = skytexturemid; dc_texheight = textureheight[skytexture] >>FRACBITS; diff --git a/src/r_segs.c b/src/r_segs.c index 8dcb61992..b0be67062 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -203,7 +203,7 @@ static void R_DrawWallSplats(void) pindex = MAXLIGHTSCALE - 1; dc_colormap = walllights[pindex]; if (encoremap && !(seg->linedef->flags & ML_TFERLINE)) - dc_colormap += (256*32); + dc_colormap += COLORMAP_REMAPOFFSET; if (frontsector->extra_colormap) dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps); @@ -578,7 +578,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) { dc_colormap = rlight->rcolormap; if (encoremap && !(ldef->flags & ML_TFERLINE)) - dc_colormap += (256*32); + dc_colormap += COLORMAP_REMAPOFFSET; continue; } @@ -599,7 +599,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) windowtop = windowbottom + 1; dc_colormap = rlight->rcolormap; if (encoremap && !(ldef->flags & ML_TFERLINE)) - dc_colormap += (256*32); + dc_colormap += COLORMAP_REMAPOFFSET; } windowbottom = realbot; if (windowtop < windowbottom) @@ -617,7 +617,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) dc_colormap = walllights[pindex]; if (encoremap && !(ldef->flags & ML_TFERLINE)) - dc_colormap += (256*32); + dc_colormap += COLORMAP_REMAPOFFSET; if (frontsector->extra_colormap) dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps); @@ -1163,7 +1163,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) { dc_colormap = rlight->rcolormap; if (encoremap && !(curline->linedef->flags & ML_TFERLINE)) - dc_colormap += (256*32); + dc_colormap += COLORMAP_REMAPOFFSET; } if (solid && windowtop < bheight) windowtop = bheight; @@ -1195,7 +1195,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) { dc_colormap = rlight->rcolormap; if (encoremap && !(curline->linedef->flags & ML_TFERLINE)) - dc_colormap += (256*32); + dc_colormap += COLORMAP_REMAPOFFSET; } } windowbottom = sprbotscreen; @@ -1216,7 +1216,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) dc_colormap = walllights[pindex]; if (encoremap && !(curline->linedef->flags & ML_TFERLINE)) - dc_colormap += (256*32); + dc_colormap += COLORMAP_REMAPOFFSET; if (pfloor->flags & FF_FOG && pfloor->master->frontsector->extra_colormap) dc_colormap = pfloor->master->frontsector->extra_colormap->colormap + (dc_colormap - colormaps); @@ -1476,7 +1476,7 @@ static void R_RenderSegLoop (void) dc_colormap = walllights[pindex]; if (encoremap && !(curline->linedef->flags & ML_TFERLINE)) - dc_colormap += (256*32); + dc_colormap += COLORMAP_REMAPOFFSET; dc_x = rw_x; dc_iscale = 0xffffffffu / (unsigned)rw_scale; diff --git a/src/r_state.h b/src/r_state.h index 1ae0adcf6..cb55e2c2b 100644 --- a/src/r_state.h +++ b/src/r_state.h @@ -44,6 +44,10 @@ extern UINT8 *encoremap; extern UINT8 invertmap[256]; #endif +#define LIGHTLEVELS 32 +#define COLORMAP_SIZE (256*LIGHTLEVELS) +#define COLORMAP_REMAPOFFSET COLORMAP_SIZE + // Boom colormaps. extern extracolormap_t *extra_colormaps; diff --git a/src/r_things.c b/src/r_things.c index c4e76303d..9824081dd 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -863,7 +863,7 @@ static void R_DrawVisSprite(vissprite_t *vis) dc_colormap = colormaps; if (encoremap && !vis->mobj->color && !(vis->mobj->flags & MF_DONTENCOREMAP)) - dc_colormap += (256*32); + dc_colormap += COLORMAP_REMAPOFFSET; dc_texturemid = vis->texturemid; dc_texheight = 0; @@ -993,7 +993,7 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis) dc_colormap = colormaps; if (encoremap) - dc_colormap += (256*32); + dc_colormap += COLORMAP_REMAPOFFSET; dc_iscale = FixedDiv(FRACUNIT, vis->scale); dc_texturemid = vis->texturemid; diff --git a/src/v_video.c b/src/v_video.c index f0c7e1a13..6ccddd89d 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1454,7 +1454,7 @@ void V_DrawCustomFadeScreen(const char *lump, UINT8 strength) if (lumpnum != LUMPERROR) { - clm = Z_MallocAlign((256 * 32), PU_STATIC, NULL, 8); + clm = Z_MallocAlign(COLORMAP_SIZE, PU_STATIC, NULL, 8); W_ReadLump(lumpnum, clm); if (clm != NULL) From ac0e291db6f293524a7611c8c6249a1952015b21 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 16 Feb 2021 17:08:49 +0000 Subject: [PATCH 21/50] Fixed Change Sky linedef type crashing the game. It was changed during v2 indev to operate off textures supplied rather than offsets. Unfortunately, she didn't bank on the 2.2 merge making it so that only linedefs of specific types would generate the necessary `->text` string from their texture fields. This branch corrects that issue, along with a bonus null-avoidance in P_SetupLevelSky just in case someone messes up the source linedef. --- src/p_setup.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/p_setup.c b/src/p_setup.c index 6cd4ffd72..45476ffef 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1261,6 +1261,24 @@ static void P_LoadSidedefs(UINT8 *data) break; } + case 423: // Change Sky + { + char process[8*3+1]; + memset(process,0,8*3+1); + sd->toptexture = sd->midtexture = sd->bottomtexture = 0; + if (msd->toptexture[0] != '-' && msd->toptexture[1] != '\0') + M_Memcpy(process,msd->toptexture,8); + if (msd->midtexture[0] != '-' || msd->midtexture[1] != '\0') + M_Memcpy(process+strlen(process), msd->midtexture, 8); + if (msd->bottomtexture[0] != '-' || msd->bottomtexture[1] != '\0') + M_Memcpy(process+strlen(process), msd->bottomtexture, 8); + if (!strlen(process)) + break; + sd->text = Z_Malloc(strlen(process)+1, PU_LEVEL, NULL); + M_Memcpy(sd->text, process, strlen(process)+1); + break; + } + case 9: // Mace parameters case 14: // Bustable block parameters case 15: // Fan particle spawner parameters @@ -3305,6 +3323,9 @@ static boolean P_LoadMapFromFile(void) void P_SetupLevelSky(const char *skytexname, boolean global) { char tex[9]; + if (!skytexname || !skytexname[0]) + return; + strncpy(tex, skytexname, 9); tex[8] = 0; From 4efd1fdc8c593adf426a9230df39e1e3cc55eae9 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 16 Feb 2021 17:16:22 +0000 Subject: [PATCH 22/50] minor typo --- src/p_setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_setup.c b/src/p_setup.c index 45476ffef..f58e378fc 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1266,7 +1266,7 @@ static void P_LoadSidedefs(UINT8 *data) char process[8*3+1]; memset(process,0,8*3+1); sd->toptexture = sd->midtexture = sd->bottomtexture = 0; - if (msd->toptexture[0] != '-' && msd->toptexture[1] != '\0') + if (msd->toptexture[0] != '-' || msd->toptexture[1] != '\0') M_Memcpy(process,msd->toptexture,8); if (msd->midtexture[0] != '-' || msd->midtexture[1] != '\0') M_Memcpy(process+strlen(process), msd->midtexture, 8); From dd5223f4d71b241ab633457136eec61f7c47c0af Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 16 Feb 2021 09:24:22 -0800 Subject: [PATCH 23/50] Draw an icon above players when they are typing in chat or console A little speech bubble is drawn, with dots cycling as they type. No typing = no dots. --- src/d_main.c | 3 +++ src/d_player.h | 3 +++ src/d_ticcmd.h | 2 ++ src/g_game.c | 22 ++++++++++++++++++++++ src/hu_stuff.c | 3 +++ src/hu_stuff.h | 3 +++ src/k_hud.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ src/p_user.c | 31 +++++++++++++++++++++++++++++++ 8 files changed, 112 insertions(+) diff --git a/src/d_main.c b/src/d_main.c index 045d558ed..3936559d5 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -233,7 +233,10 @@ void D_ProcessEvents(void) #endif if (eaten) + { + hu_keystrokes = true; continue; // ate the event + } G_Responder(ev); } diff --git a/src/d_player.h b/src/d_player.h index 95fd8adea..5ed5af013 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -697,6 +697,9 @@ typedef struct player_s tic_t jointime; // Timer when player joins game to change skin/color tic_t quittime; // Time elapsed since user disconnected, zero if connected + UINT8 typing_timer : 4; // Counts down while keystrokes are not emitted + UINT8 typing_duration : 6; // How long since resumed timer + #ifdef HWRENDER fixed_t fovadd; // adjust FOV for hw rendering #endif diff --git a/src/d_ticcmd.h b/src/d_ticcmd.h index ed72659e5..17c41cfbf 100644 --- a/src/d_ticcmd.h +++ b/src/d_ticcmd.h @@ -54,6 +54,8 @@ typedef enum // ticcmd flags #define TICCMD_RECEIVED 1 +#define TICCMD_TYPING 2/* chat window or console open */ +#define TICCMD_KEYSTROKE 4/* chat character input */ #if defined(_MSC_VER) #pragma pack(1) diff --git a/src/g_game.c b/src/g_game.c index 6cc1f9aa2..9f203e413 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1120,6 +1120,16 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) cmd->latency = modeattacking ? 0 : (leveltime & 0xFF); // Send leveltime when this tic was generated to the server for control lag calculations cmd->flags = 0; + if (chat_on || CON_Ready()) + { + cmd->flags |= TICCMD_TYPING; + + if (hu_keystrokes) + { + cmd->flags |= TICCMD_KEYSTROKE; + } + } + /* Lua: Allow this hook to overwrite ticcmd. We check if we're actually in a level because for some reason this Hook would run in menus and on the titlescreen otherwise. Be aware that within this hook, nothing but this player's cmd can be edited (otherwise we'd run in some pretty bad synching problems since this is clientsided, or something) @@ -1357,7 +1367,10 @@ boolean G_Responder(event_t *ev) if (gamestate == GS_LEVEL) { if (HU_Responder(ev)) + { + hu_keystrokes = true; return true; // chat ate the event + } if (AM_Responder(ev)) return true; // automap ate it // map the event (key/mouse/joy) to a gamecontrol @@ -1374,7 +1387,10 @@ boolean G_Responder(event_t *ev) else if (gamestate == GS_CUTSCENE) { if (HU_Responder(ev)) + { + hu_keystrokes = true; return true; // chat ate the event + } if (F_CutsceneResponder(ev)) { @@ -1385,7 +1401,10 @@ boolean G_Responder(event_t *ev) else if (gamestate == GS_CREDITS || gamestate == GS_ENDING) // todo: keep ending here? { if (HU_Responder(ev)) + { + hu_keystrokes = true; return true; // chat ate the event + } if (F_CreditResponder(ev)) { @@ -1408,7 +1427,10 @@ boolean G_Responder(event_t *ev) } else if (gamestate == GS_INTERMISSION || gamestate == GS_VOTING || gamestate == GS_EVALUATION) if (HU_Responder(ev)) + { + hu_keystrokes = true; return true; // chat ate the event + } // allow spy mode changes even during the demo if (gamestate == GS_LEVEL && ev->type == ev_keydown diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 35f977bd6..2e6ff3600 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -78,6 +78,7 @@ patch_t *frameslash; // framerate stuff. Used in screen.c static player_t *plr; boolean chat_on; // entering a chat message? +boolean hu_keystrokes; // :) static char w_chat[HU_MAXMSGLEN]; static size_t c_input = 0; // let's try to make the chat input less shitty. static boolean headsupactive = false; @@ -879,6 +880,8 @@ void HU_Ticker(void) hu_showscores = !chat_on; else hu_showscores = false; + + hu_keystrokes = false; } #ifndef NONET diff --git a/src/hu_stuff.h b/src/hu_stuff.h index afbbe7b73..6a425926b 100644 --- a/src/hu_stuff.h +++ b/src/hu_stuff.h @@ -94,6 +94,9 @@ void HU_AddChatText(const char *text, boolean playsound); // set true when entering a chat message extern boolean chat_on; +// keystrokes in the console or chat window +extern boolean hu_keystrokes; + extern patch_t *pinggfx[5]; extern patch_t *framecounter; extern patch_t *frameslash; diff --git a/src/k_hud.c b/src/k_hud.c index 87cda81cc..2e635581d 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -133,6 +133,9 @@ static patch_t *kp_check[6]; static patch_t *kp_rival[2]; static patch_t *kp_localtag[4][2]; +static patch_t *kp_talk; +static patch_t *kp_typdot; + static patch_t *kp_eggnum[4]; static patch_t *kp_flameshieldmeter[104][2]; @@ -503,6 +506,10 @@ void K_LoadKartHUDGraphics(void) } } + // Typing indicator + kp_talk = W_CachePatchName("K_TALK", PU_HUDGFX); + kp_typdot = W_CachePatchName("K_TYPDOT", PU_HUDGFX); + // Eggman warning numbers sprintf(buffer, "K_EGGNx"); for (i = 0; i < 4; i++) @@ -2598,6 +2605,43 @@ static void K_DrawRivalTagForPlayer(fixed_t x, fixed_t y) V_DrawFixedPatch(x, y, FRACUNIT, V_HUDTRANS|V_SPLITSCREEN, kp_rival[blink], NULL); } +static boolean K_DrawTypingDot(fixed_t x, fixed_t y, UINT8 duration, player_t *p) +{ + if (p->typing_duration > duration) + { + V_DrawFixedPatch(x, y, FRACUNIT, V_HUDTRANS|V_SPLITSCREEN, kp_typdot, NULL); + return true; + } + else + { + return false; + } +} + +static boolean K_DrawTypingNotifier(fixed_t x, fixed_t y, player_t *p) +{ + if (p->cmd.flags & TICCMD_TYPING) + { + V_DrawFixedPatch(x, y, FRACUNIT, V_HUDTRANS|V_SPLITSCREEN, kp_talk, NULL); + + y += 4*FRACUNIT; + + /* spacing closer with the last two looks a better most of the time */ + (void) + ( + K_DrawTypingDot(x + 3*FRACUNIT, y, 15, p) && + K_DrawTypingDot(x + 6*FRACUNIT - FRACUNIT/3, y, 31, p) && + K_DrawTypingDot(x + 9*FRACUNIT - FRACUNIT/3, y, 47, p) + ); + + return true; + } + else + { + return false; + } +} + static void K_DrawNameTagForPlayer(fixed_t x, fixed_t y, player_t *p, UINT8 cnum) { const INT32 clr = skincolors[p->skincolor].chatcolor; @@ -2840,6 +2884,7 @@ static void K_drawKartNameTags(void) if (K_ShowPlayerNametag(ntplayer) == true) { K_DrawNameTagForPlayer(result.x, result.y, ntplayer, cnum); + K_DrawTypingNotifier(result.x, result.y, ntplayer); } } } diff --git a/src/p_user.c b/src/p_user.c index e4785b249..6577b3eae 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4588,6 +4588,37 @@ void P_PlayerThink(player_t *player) player->mo->drawflags &= ~MFD_DONTDRAW; } + if (cmd->flags & TICCMD_TYPING) + { + if (cmd->flags & TICCMD_KEYSTROKE) + { + player->typing_timer = 15; + } + else if (player->typing_timer > 0) + { + player->typing_timer--; + } + + if (player->typing_timer + player->typing_duration > 0) + { + /* lag a little bit so we always get more than just a singular dot */ + if (player->typing_timer == 0 && + (player->typing_duration < 16 || player->typing_duration > 39)) + { + player->typing_duration = 0; + } + else + { + player->typing_duration++; + } + } + } + else + { + player->typing_timer = 0; + player->typing_duration = 0; + } + player->pflags &= ~PF_SLIDING; K_KartPlayerThink(player, cmd); // SRB2kart From 56dc373f76209d79117f790ce36ebc2c10755da8 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 16 Feb 2021 10:17:00 -0800 Subject: [PATCH 24/50] n --- src/p_local.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_local.h b/src/p_local.h index 90408e011..9f3390475 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -522,7 +522,7 @@ void P_Thrust(mobj_t *mo, angle_t angle, fixed_t move); void P_ExplodeMissile(mobj_t *mo); void P_CheckGravity(mobj_t *mo, boolean affect); void P_SetPitchRollFromSlope(mobj_t *mo, pslope_t *slope); -fixed_t P_ScaleFromMap(fixed_t, fixed_t scale); +fixed_t P_ScaleFromMap(fixed_t n, fixed_t scale); fixed_t P_GetMobjHead(const mobj_t *); fixed_t P_GetMobjFeet(const mobj_t *); fixed_t P_GetMobjGround(const mobj_t *); From 0d43c3e3addd78f3750f340ed0cccd1bdd9379cd Mon Sep 17 00:00:00 2001 From: Sryder Date: Tue, 16 Feb 2021 18:26:45 +0000 Subject: [PATCH 25/50] Invert the screen for encore circle transition in OpenGL --- src/hardware/hw_defs.h | 3 ++- src/hardware/hw_draw.c | 21 +++++++++++++++++++++ src/hardware/hw_main.h | 1 + src/hardware/r_opengl/r_opengl.c | 4 ++++ src/v_video.c | 2 +- 5 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index 9cb48620e..3752cbf05 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -219,7 +219,8 @@ enum EPolyFlags PF_Substractive = 0x00000010, // for splat PF_NoAlphaTest = 0x00000020, // hiden param PF_Fog = 0x00000040, // Fog blocks - PF_Blending = (PF_Environment|PF_Additive|PF_Translucent|PF_Masked|PF_Substractive|PF_Fog)&~PF_NoAlphaTest, + PF_Invert = 0x00000080, // Polygon inverts the colours of what it's in front of + PF_Blending = (PF_Environment|PF_Additive|PF_Translucent|PF_Masked|PF_Substractive|PF_Fog|PF_Invert)&~PF_NoAlphaTest, // other flag bits diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index 69f37a29b..d3812983e 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -697,6 +697,27 @@ void HWR_DrawConsoleBack(UINT32 color, INT32 height) HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); } +void HWR_EncoreInvertScreen(void) +{ + FOutVector v[4]; + FSurfaceInfo Surf; + + v[0].x = v[3].x = -1.0f; + v[2].x = v[1].x = 1.0f; + v[0].y = v[1].y = -1.0f; + v[2].y = v[3].y = 1.0f; + v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; + + v[0].s = v[3].s = 0.0f; + v[2].s = v[1].s = 1.0f; + v[0].t = v[1].t = 1.0f; + v[2].t = v[3].t = 0.0f; + + Surf.PolyColor.rgba = 0xFFFFFFFF; + + HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Invert|PF_NoDepthTest); +} + // Very similar to HWR_DrawConsoleBack, except we draw from the middle(-ish) of the screen to the bottom. void HWR_DrawTutorialBack(UINT32 color, INT32 boxheight) { diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 3efeca45b..dfefc2a2f 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -28,6 +28,7 @@ void HWR_Shutdown(void); void HWR_drawAMline(const fline_t *fl, INT32 color); void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength); void HWR_DrawConsoleBack(UINT32 color, INT32 height); +void HWR_EncoreInvertScreen(void); void HWR_DrawTutorialBack(UINT32 color, INT32 boxheight); void HWR_RenderSkyboxView(player_t *player); void HWR_RenderPlayerView(void); diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 9e9bbee81..ceea6558d 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -1599,6 +1599,10 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags) pglBlendFunc(GL_SRC_ALPHA, GL_SRC_COLOR); pglAlphaFunc(GL_ALWAYS, 0.0f); // Don't discard zero alpha fragments break; + case PF_Invert & PF_Invert: + pglBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO); + pglAlphaFunc(GL_GREATER, 0.5f); + break; default : // must be 0, otherwise it's an error // No blending pglBlendFunc(GL_ONE, GL_ZERO); // the same as no blending diff --git a/src/v_video.c b/src/v_video.c index 6ccddd89d..31c7eec95 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1505,7 +1505,7 @@ void V_EncoreInvertScreen(void) #ifdef HWRENDER if (rendermode != render_soft && rendermode != render_none) { - //HWR_EncoreInvertScreen(); + HWR_EncoreInvertScreen(); return; } #endif From 196d310052bc312f17a3fb4b979ca6209ba6aeff Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 16 Feb 2021 10:48:24 -0800 Subject: [PATCH 26/50] Sacrifice fun for readability :( --- src/d_player.h | 4 ++-- src/k_hud.c | 24 +++++------------------- src/p_user.c | 18 ++++++++++++++++-- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 5ed5af013..f2883eaa2 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -697,8 +697,8 @@ typedef struct player_s tic_t jointime; // Timer when player joins game to change skin/color tic_t quittime; // Time elapsed since user disconnected, zero if connected - UINT8 typing_timer : 4; // Counts down while keystrokes are not emitted - UINT8 typing_duration : 6; // How long since resumed timer + UINT8 typing_timer; // Counts down while keystrokes are not emitted + UINT8 typing_duration; // How long since resumed timer #ifdef HWRENDER fixed_t fovadd; // adjust FOV for hw rendering diff --git a/src/k_hud.c b/src/k_hud.c index 2e635581d..53859fe62 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -2605,20 +2605,15 @@ static void K_DrawRivalTagForPlayer(fixed_t x, fixed_t y) V_DrawFixedPatch(x, y, FRACUNIT, V_HUDTRANS|V_SPLITSCREEN, kp_rival[blink], NULL); } -static boolean K_DrawTypingDot(fixed_t x, fixed_t y, UINT8 duration, player_t *p) +static void K_DrawTypingDot(fixed_t x, fixed_t y, UINT8 duration, player_t *p) { if (p->typing_duration > duration) { V_DrawFixedPatch(x, y, FRACUNIT, V_HUDTRANS|V_SPLITSCREEN, kp_typdot, NULL); - return true; - } - else - { - return false; } } -static boolean K_DrawTypingNotifier(fixed_t x, fixed_t y, player_t *p) +static void K_DrawTypingNotifier(fixed_t x, fixed_t y, player_t *p) { if (p->cmd.flags & TICCMD_TYPING) { @@ -2627,18 +2622,9 @@ static boolean K_DrawTypingNotifier(fixed_t x, fixed_t y, player_t *p) y += 4*FRACUNIT; /* spacing closer with the last two looks a better most of the time */ - (void) - ( - K_DrawTypingDot(x + 3*FRACUNIT, y, 15, p) && - K_DrawTypingDot(x + 6*FRACUNIT - FRACUNIT/3, y, 31, p) && - K_DrawTypingDot(x + 9*FRACUNIT - FRACUNIT/3, y, 47, p) - ); - - return true; - } - else - { - return false; + K_DrawTypingDot(x + 3*FRACUNIT, y, 15, p); + K_DrawTypingDot(x + 6*FRACUNIT - FRACUNIT/3, y, 31, p); + K_DrawTypingDot(x + 9*FRACUNIT - FRACUNIT/3, y, 47, p); } } diff --git a/src/p_user.c b/src/p_user.c index 6577b3eae..82c1da681 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4590,6 +4590,12 @@ void P_PlayerThink(player_t *player) if (cmd->flags & TICCMD_TYPING) { + /* + typing_duration is slow to start and slow to stop. + + typing_timer counts down a grace period before the player is not + actually considered typing anymore. + */ if (cmd->flags & TICCMD_KEYSTROKE) { player->typing_timer = 15; @@ -4599,18 +4605,26 @@ void P_PlayerThink(player_t *player) player->typing_timer--; } + /* if we are in the grace period (including currently typing) */ if (player->typing_timer + player->typing_duration > 0) { - /* lag a little bit so we always get more than just a singular dot */ + /* + If one dot was already displayed, let the duration continue to + display two dots for a bit, before actually resetting. + */ if (player->typing_timer == 0 && (player->typing_duration < 16 || player->typing_duration > 39)) { player->typing_duration = 0; } - else + else if (player->typing_duration < 63) { player->typing_duration++; } + else + { + player->typing_duration = 0; + } } } else From 8f9d9d783be815ab517b7ab2a6818e44c28cb57f Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 16 Feb 2021 10:59:36 -0800 Subject: [PATCH 27/50] Adjust dot timing to look a bit nicer * The cycle always ends on two dots. * The second dot gets drawn slightly sooner after a wrap. --- src/p_user.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index 82c1da681..d69fd2304 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4608,12 +4608,9 @@ void P_PlayerThink(player_t *player) /* if we are in the grace period (including currently typing) */ if (player->typing_timer + player->typing_duration > 0) { - /* - If one dot was already displayed, let the duration continue to - display two dots for a bit, before actually resetting. - */ + /* always end the cycle on two dots */ if (player->typing_timer == 0 && - (player->typing_duration < 16 || player->typing_duration > 39)) + (player->typing_duration < 16 || player->typing_duration == 40)) { player->typing_duration = 0; } @@ -4623,7 +4620,8 @@ void P_PlayerThink(player_t *player) } else { - player->typing_duration = 0; + /* spend slightly less time on the first dot after wrapping */ + player->typing_duration = 20; } } } From 46e4d5c8eed56db3185d70bdb7141f1892ce2571 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 16 Feb 2021 11:03:19 -0800 Subject: [PATCH 28/50] Add typing_timer and typing_duration to netsave --- src/p_saveg.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/p_saveg.c b/src/p_saveg.c index e24e3d2f7..dc3523759 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -277,6 +277,9 @@ static void P_NetArchivePlayers(void) WRITESINT8(save_p, players[i].glanceDir); + WRITEUINT8(save_p, players[i].typing_timer); + WRITEUINT8(save_p, players[i].typing_duration); + // respawnvars_t WRITEUINT8(save_p, players[i].respawn.state); WRITEUINT32(save_p, K_GetWaypointHeapIndex(players[i].respawn.wp)); @@ -483,6 +486,9 @@ static void P_NetUnArchivePlayers(void) players[i].glanceDir = READSINT8(save_p); + players[i].typing_timer = READUINT8(save_p); + players[i].typing_duration = READUINT8(save_p); + // respawnvars_t players[i].respawn.state = READUINT8(save_p); players[i].respawn.wp = (waypoint_t *)(size_t)READUINT32(save_p); From 34744b03b16af1ae984cccb705ebc4480bf0e6a2 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 16 Feb 2021 12:08:47 -0800 Subject: [PATCH 29/50] Nevermind the part about making the first dot end sooner, might be a bird moment --- src/p_user.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index d69fd2304..0cb2eac29 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4620,8 +4620,7 @@ void P_PlayerThink(player_t *player) } else { - /* spend slightly less time on the first dot after wrapping */ - player->typing_duration = 20; + player->typing_duration = 16; } } } From 62ca6218271cb9e669ae089b2c160516c12a68b0 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 16 Feb 2021 13:03:36 -0800 Subject: [PATCH 30/50] Handle typing dot y offset in lump One less thing to do in the code. --- src/k_hud.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/k_hud.c b/src/k_hud.c index 53859fe62..843f0e2a3 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -2619,8 +2619,6 @@ static void K_DrawTypingNotifier(fixed_t x, fixed_t y, player_t *p) { V_DrawFixedPatch(x, y, FRACUNIT, V_HUDTRANS|V_SPLITSCREEN, kp_talk, NULL); - y += 4*FRACUNIT; - /* spacing closer with the last two looks a better most of the time */ K_DrawTypingDot(x + 3*FRACUNIT, y, 15, p); K_DrawTypingDot(x + 6*FRACUNIT - FRACUNIT/3, y, 31, p); From a3c72c0158448000bb56c34ddcb4d79cf04ea5e0 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 16 Feb 2021 14:50:00 -0800 Subject: [PATCH 31/50] Speed up the cycle if typing quickly --- src/p_user.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/p_user.c b/src/p_user.c index 0cb2eac29..2312279e4 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4598,6 +4598,22 @@ void P_PlayerThink(player_t *player) */ if (cmd->flags & TICCMD_KEYSTROKE) { + /* speed up if we are typing quickly! */ + if (player->typing_duration > 0 && player->typing_timer > 12) + { + if (player->typing_duration < 16) + { + player->typing_duration = 24; + } + else + { + /* slows down a tiny bit as it approaches the next dot */ + const UINT8 step = (((player->typing_duration + 15) & ~15) - + player->typing_duration) / 2; + player->typing_duration += max(step, 4); + } + } + player->typing_timer = 15; } else if (player->typing_timer > 0) From 7fb44bdb0239a8012be73cb9ee384a9fdca9addb Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 17 Feb 2021 10:21:58 +0000 Subject: [PATCH 32/50] Tweakmaps! Literally identical to Encore remapping, but *only applied when Encore mode is OFF*. Long-requested by Oni, and allows you to reuse textures and skies from other stages without having to duplicate them in different colours. --- src/p_setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_setup.c b/src/p_setup.c index 6cd4ffd72..ba46c60e5 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4013,7 +4013,7 @@ boolean P_LoadLevel(boolean fromnetsave) I_Error("Map %s not found.\n", maplumpname); R_ReInitColormaps(mapheaderinfo[gamemap-1]->palette, - (encoremode ? W_CheckNumForName(va("%sE", maplumpname)) : LUMPERROR)); + W_CheckNumForName(va("%s%c", maplumpname, (encoremode ? 'E' : 'T')))); CON_SetupBackColormap(); // SRB2 determines the sky texture to be used depending on the map header. From 2ec943a214c4b4e8f38c655996de83a2633702cf Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 17 Feb 2021 21:48:09 +0000 Subject: [PATCH 33/50] Several changes to respawning and race start. * Becoming a spectator is now instant, and leaves no bumpable corpse behind. * Players will now FAULT if they: * change from a spectator into a player after the initial camera turnaround but before the end of POSITION. * touch an instant kill FOF or get crushed during POSITION. * become a spectator during POSITION. (I might change this later, seems overkill) * If you respawn during POSITION, the jingle will not restart from the beginning. * Change the FAULT animation to match spinout/currents. * Clean up some of the spawning code to not place spectators on the ground. --- src/d_netcmd.c | 6 ++++-- src/g_game.c | 27 ++++++++++++++++++++++----- src/k_respawn.c | 29 +++++++++++++++++++++-------- src/k_respawn.h | 15 +++++++++++++++ src/p_inter.c | 7 +++++++ src/p_mobj.c | 10 +++++++++- src/p_user.c | 18 +++++++++--------- 7 files changed, 87 insertions(+), 25 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 8bc1bc905..ba5560802 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -3374,9 +3374,11 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) { if (players[playernum].mo) { - P_DamageMobj(players[playernum].mo, NULL, NULL, 1, DMG_INSTAKILL); + P_DamageMobj(players[playernum].mo, NULL, NULL, 1, + (NetPacket.packet.newteam ? DMG_INSTAKILL : DMG_SPECTATOR)); } - else + //else + if (!NetPacket.packet.newteam) { players[playernum].playerstate = PST_REBORN; } diff --git a/src/g_game.c b/src/g_game.c index 6cc1f9aa2..85a73e045 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2084,6 +2084,8 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) INT32 wanted; boolean songcredit = false; boolean eliminated; + UINT16 nocontrol; + INT32 khudfault; score = players[player].score; marescore = players[player].marescore; @@ -2183,6 +2185,14 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) wanted = players[player].kartstuff[k_wanted]; } + if (!betweenmaps) + { + khudfault = players[player].karthud[khud_fault]; + nocontrol = players[player].powers[pw_nocontrol]; + } + else + khudfault = nocontrol = 0; + // Obliterate follower from existence P_SetTarget(&players[player].follower, NULL); @@ -2244,6 +2254,8 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) p->kartstuff[k_wanted] = wanted; p->kartstuff[k_eggmanblame] = -1; p->kartstuff[k_lastdraft] = -1; + p->karthud[khud_fault] = khudfault; + p->powers[pw_nocontrol] = nocontrol; memcpy(&p->respawn, &respawn, sizeof (p->respawn)); @@ -2297,6 +2309,9 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) if (betweenmaps) return; + if (leveltime < starttime) + return; + if (p-players == consoleplayer) { if (mapmusflags & MUSIC_RELOADRESET) @@ -2319,11 +2334,6 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) if (songcredit) S_ShowMusicCredit(); - - if (leveltime > (starttime + (TICRATE/2)) && !p->spectator) - { - K_DoIngameRespawn(p); - } } // @@ -2385,10 +2395,17 @@ void G_SpawnPlayer(INT32 playernum) void G_MovePlayerToSpawnOrStarpost(INT32 playernum) { +#if 0 + if (leveltime <= introtime && !players[playernum].spectator) + P_MovePlayerToSpawn(playernum, G_FindMapStart(playernum)); + else + P_MovePlayerToStarpost(playernum); +#else if (leveltime > starttime) P_MovePlayerToStarpost(playernum); else P_MovePlayerToSpawn(playernum, G_FindMapStart(playernum)); +#endif } mapthing_t *G_FindTeamStart(INT32 playernum) diff --git a/src/k_respawn.c b/src/k_respawn.c index 7052fe466..016420105 100644 --- a/src/k_respawn.c +++ b/src/k_respawn.c @@ -85,6 +85,23 @@ static void K_RespawnAtWaypoint(player_t *player, waypoint_t *waypoint) player->respawn.pointz += K_RespawnOffset(player, player->respawn.flip); } +/*-------------------------------------------------- + void K_DoFault(player_t *player) + + See header file for description. +--------------------------------------------------*/ + +void K_DoFault(player_t *player) +{ + player->powers[pw_nocontrol] = (starttime - leveltime) + 50; + if (!(player->pflags & PF_FAULT)) + { + S_StartSound(player->mo, sfx_s3k83); + player->karthud[khud_fault] = 1; + player->pflags |= PF_FAULT; + } +} + /*-------------------------------------------------- void K_DoIngameRespawn(player_t *player) @@ -103,18 +120,14 @@ void K_DoIngameRespawn(player_t *player) return; } - if (leveltime < introtime) + if (leveltime <= introtime) { return; } - if (leveltime < starttime) // FAULT - { - player->powers[pw_nocontrol] = (starttime - leveltime) + 50; - player->pflags |= PF_FAULT; - S_StartSound(player->mo, sfx_s3k83); - player->karthud[khud_fault] = 1; - } + // FAULT + if (leveltime < starttime) + K_DoFault(player); player->kartstuff[k_ringboost] = 0; player->kartstuff[k_driftboost] = 0; diff --git a/src/k_respawn.h b/src/k_respawn.h index d5a946560..5dd78ff1f 100644 --- a/src/k_respawn.h +++ b/src/k_respawn.h @@ -38,6 +38,21 @@ fixed_t K_RespawnOffset(player_t *player, boolean flip); +/*-------------------------------------------------- + void K_DoFault(player_t *player); + + Faults the specified player. + + Input Arguments:- + player - Player to preform this for. + + Return:- + None +--------------------------------------------------*/ + +void K_DoFault(player_t *player); + + /*-------------------------------------------------- void K_DoIngameRespawn(player_t *player); diff --git a/src/p_inter.c b/src/p_inter.c index eb2cabc66..5c536b541 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1370,6 +1370,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget break; case MT_PLAYER: + if (damagetype != DMG_SPECTATOR) { angle_t flingAngle; mobj_t *kart; @@ -1755,6 +1756,12 @@ static boolean P_KillPlayer(player_t *player, mobj_t *inflictor, mobj_t *source, break; } + // FAULT + if (leveltime < starttime) + { + K_DoFault(player); + } + K_DropEmeraldsFromPlayer(player, player->powers[pw_emeralds]); K_SetHitLagForObjects(player->mo, inflictor, 15); diff --git a/src/p_mobj.c b/src/p_mobj.c index 2bc6c620f..953124820 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10591,7 +10591,7 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing) { fixed_t offset = mthing->z << FRACBITS; - if (p->respawn.state != RESPAWNST_NONE) + if (p->respawn.state != RESPAWNST_NONE || p->spectator) offset += K_RespawnOffset(p, (mthing->options & MTF_OBJECTFLIP)); // Flagging a player's ambush will make them start on the ceiling @@ -10637,6 +10637,12 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing) mobj->angle = angle; + // FAULT + if (leveltime > introtime) + { + K_DoIngameRespawn(p); + } + P_AfterPlayerSpawn(playernum); } @@ -10690,6 +10696,8 @@ void P_MovePlayerToStarpost(INT32 playernum) ); } } + else + p->drawangle = mobj->angle; // default to the camera angle P_AfterPlayerSpawn(playernum); } diff --git a/src/p_user.c b/src/p_user.c index 5430ca04b..b64c9e713 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2123,11 +2123,7 @@ void P_MovePlayer(player_t *player) // Control relinquishing stuff! if (player->powers[pw_nocontrol]) - { player->pflags |= PF_STASIS; - if (!(player->powers[pw_nocontrol] & (1<<15))) - player->pflags |= PF_JUMPSTASIS; - } // note: don't unset stasis here @@ -2183,9 +2179,13 @@ void P_MovePlayer(player_t *player) player->drawangle -= ANGLE_22h; player->mo->rollangle = 0; } - else if (player->kartstuff[k_spinouttimer] > 0) + else if ((player->pflags & PF_FAULT) || (player->kartstuff[k_spinouttimer] > 0)) { - UINT8 speed = max(1, min(8, player->kartstuff[k_spinouttimer]/8)); + UINT16 speed = ((player->pflags & PF_FAULT) ? player->powers[pw_nocontrol] : player->kartstuff[k_spinouttimer])/8; + if (speed > 8) + speed = 8; + else if (speed < 1) + speed = 1; P_SetPlayerMobjState(player->mo, S_KART_SPINOUT); @@ -2196,7 +2196,7 @@ void P_MovePlayer(player_t *player) player->mo->rollangle = 0; } - else if (player->pflags & PF_FAULT) + /*else if (player->pflags & PF_FAULT) -- v1 fault { P_SetPlayerMobjState(player->mo, S_KART_SPINOUT); @@ -2206,7 +2206,7 @@ void P_MovePlayer(player_t *player) player->drawangle -= ANGLE_11hh; player->mo->rollangle = 0; - } + }*/ else { K_KartMoveAnimation(player); @@ -4571,7 +4571,7 @@ void P_PlayerThink(player_t *player) player->powers[pw_flashing]--; } - if (player->powers[pw_nocontrol] & ((1<<15)-1) && player->powers[pw_nocontrol] < UINT16_MAX) + if (player->powers[pw_nocontrol] && player->powers[pw_nocontrol] < UINT16_MAX) { if (!(--player->powers[pw_nocontrol])) player->pflags &= ~PF_FAULT; From 5310acc84e39ef05c15d20edb89fe1affaa79844 Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 18 Feb 2021 11:11:50 +0000 Subject: [PATCH 34/50] * As predicted, remove FAULTing from simply becoming a spectator at the start of the race - only apply it if you attempt to rejoin! * Mark FAULTing players as in pain, preventing you from using your rings in mid-air (which is especially egregrious when re-entering the race from being a spectator uses the item button). --- src/p_inter.c | 13 +++++++------ src/p_mobj.c | 2 +- src/p_user.c | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/p_inter.c b/src/p_inter.c index 5c536b541..635a3f11b 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1751,17 +1751,18 @@ static boolean P_KillPlayer(player_t *player, mobj_t *inflictor, mobj_t *source, // Respawn kill types K_DoIngameRespawn(player); return false; + case DMG_SPECTATOR: + // disappearifies, but still gotta put items back in play + break; default: // Everything else REALLY kills + if (leveltime < starttime) + { + K_DoFault(player); + } break; } - // FAULT - if (leveltime < starttime) - { - K_DoFault(player); - } - K_DropEmeraldsFromPlayer(player, player->powers[pw_emeralds]); K_SetHitLagForObjects(player->mo, inflictor, 15); diff --git a/src/p_mobj.c b/src/p_mobj.c index 953124820..ac645a4e8 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10638,7 +10638,7 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing) mobj->angle = angle; // FAULT - if (leveltime > introtime) + if (leveltime > introtime && !p->spectator) { K_DoIngameRespawn(p); } diff --git a/src/p_user.c b/src/p_user.c index b64c9e713..a4d5d7908 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -461,7 +461,7 @@ UINT8 P_FindHighestLap(void) // boolean P_PlayerInPain(player_t *player) { - if (player->kartstuff[k_spinouttimer] || player->tumbleBounces > 0) + if (player->kartstuff[k_spinouttimer] || (player->tumbleBounces > 0) || (player->pflags & PF_FAULT)) return true; return false; From 34ebcdf696d6d9748d955933f1535e2b77032c12 Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 18 Feb 2021 13:23:44 +0000 Subject: [PATCH 35/50] Hitlag is now displayed in first-person view. --- src/k_hud.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/k_hud.c b/src/k_hud.c index 87cda81cc..82209ad43 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -3632,7 +3632,27 @@ static void K_drawKartFirstPerson(void) const angle_t ang = R_PointToAngle2(0, 0, stplyr->rmomx, stplyr->rmomy) - stplyr->drawangle; // yes, the following is correct. no, you do not need to swap the x and y. fixed_t xoffs = -P_ReturnThrustY(stplyr->mo, ang, (BASEVIDWIDTH<<(FRACBITS-2))/2); - fixed_t yoffs = -(P_ReturnThrustX(stplyr->mo, ang, 4*FRACUNIT) - 4*FRACUNIT); + fixed_t yoffs = -P_ReturnThrustX(stplyr->mo, ang, 4*FRACUNIT); + + // hitlag vibrating + if (stplyr->mo->hitlag > 0) + { + fixed_t mul = stplyr->mo->hitlag * (FRACUNIT / 10); + if (r_splitscreen && mul > FRACUNIT) + mul = FRACUNIT; + + if (leveltime & 1) + { + mul = -mul; + } + + xoffs = FixedMul(xoffs, mul); + yoffs = FixedMul(yoffs, mul); + + } + + if ((yoffs += 4*FRACUNIT) < 0) + yoffs = 0; if (r_splitscreen) xoffs = FixedMul(xoffs, scale); From 36099a900ff83e30eb01a053d1bd0e3ab93d5bd6 Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 19 Feb 2021 11:31:25 +0000 Subject: [PATCH 36/50] Fixed papersprites' shadows drifting - notably applies to Minecraft items. --- src/r_things.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index 9824081dd..b72341191 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1404,7 +1404,7 @@ static void R_ProjectSprite(mobj_t *thing) fixed_t scalestep; fixed_t offset, offset2; - fixed_t basetx; // drop shadows + fixed_t basetx, basetz; // drop shadows boolean papersprite = !!(thing->frame & FF_PAPERSPRITE); fixed_t paperoffset = 0, paperdistance = 0; angle_t centerangle = 0; @@ -1445,7 +1445,7 @@ static void R_ProjectSprite(mobj_t *thing) tr_x = thingxpos - viewx; tr_y = thingypos - viewy; - tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); // near/far distance + basetz = tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); // near/far distance // thing is behind view plane? if (!papersprite && (tz < FixedMul(MINZ, this_scale))) // papersprite clipping is handled later @@ -1911,7 +1911,7 @@ static void R_ProjectSprite(mobj_t *thing) R_SplitSprite(vis); if (oldthing->shadowscale && cv_shadow.value) - R_ProjectDropShadow(oldthing, vis, oldthing->shadowscale, basetx, tz); + R_ProjectDropShadow(oldthing, vis, oldthing->shadowscale, basetx, basetz); // Debug ++objectsdrawn; From 97d404de7bee06632236f76bc12f46fc1a212618 Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 19 Feb 2021 16:25:12 +0000 Subject: [PATCH 37/50] A few changes to cameras. * When lightsnaking, update the camera angle at each waypoint step to prevent being dropped the wrong way around. * The above bullet point is WIP. I've tried to restrict manual turning while lightsnaking, but it still happens and just gets yanked back at each waypoint. Would appreciate a bit of insight here. * Fix HUD tracking for spectators by setting thiscam->chase each tic more definitively. * Still happens for the very first tic of the map though, must be another data point I missed :pensive: * Fix the vertical jittering when a spectator's camera is on the ground. --- src/k_kart.c | 5 +++++ src/k_respawn.c | 6 ++++++ src/p_user.c | 4 ++-- src/r_main.c | 4 +--- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 0f97aa9d6..adb1cd871 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -7016,6 +7016,11 @@ INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue) return 0; } + if (player->respawn.state == RESPAWNST_MOVE) + { + return 0; + } + currentSpeed = R_PointToDist2(0, 0, player->mo->momx, player->mo->momy); if ((currentSpeed <= 0) // Not moving diff --git a/src/k_respawn.c b/src/k_respawn.c index 409340a3f..71f5ccd0e 100644 --- a/src/k_respawn.c +++ b/src/k_respawn.c @@ -371,6 +371,12 @@ static void K_MovePlayerToRespawnPoint(player_t *player) } // Set angle, regardless of if we're done or not + P_SetPlayerAngle(player, R_PointToAngle2( + player->respawn.wp->mobj->x, + player->respawn.wp->mobj->y, + player->respawn.wp->nextwaypoints[nwp]->mobj->x, + player->respawn.wp->nextwaypoints[nwp]->mobj->y + )); player->drawangle = R_PointToAngle2( player->mo->x, player->mo->y, dest.x, dest.y diff --git a/src/p_user.c b/src/p_user.c index 4d2705180..764a94883 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -206,7 +206,7 @@ void P_CalcHeight(player_t *player) player->bob = FixedMul(cv_movebob.value, bobmul); - if (!P_IsObjectOnGround(mo)) + if (!P_IsObjectOnGround(mo) || player->spectator) { if (mo->eflags & MFE_VERTICALFLIP) { @@ -2997,7 +2997,7 @@ void P_ResetCamera(player_t *player, camera_t *thiscam) if (thiscam->chase && player->mo->health <= 0) return; - thiscam->chase = true; + thiscam->chase = !player->spectator; x = player->mo->x - P_ReturnThrustX(player->mo, thiscam->angle, player->mo->radius); y = player->mo->y - P_ReturnThrustY(player->mo, thiscam->angle, player->mo->radius); if (player->mo->eflags & MFE_VERTICALFLIP) diff --git a/src/r_main.c b/src/r_main.c index 835ed26f7..93fadd134 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1191,9 +1191,7 @@ void R_SetupFrame(player_t *player) if (i > r_splitscreen) return; // shouldn't be possible, but just in case - if (player->playerstate == PST_DEAD || gamestate == GS_TITLESCREEN || tutorialmode) - chasecam = true; // force chasecam on - else if (player->spectator) // no spectator chasecam + if (player->spectator) // no spectator chasecam chasecam = false; // force chasecam off if (chasecam && !thiscam->chase) From 41bd3453566110976399062c3b8555d87ed9bc89 Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 19 Feb 2021 20:49:38 +0000 Subject: [PATCH 38/50] Fixed being able to turn the camera while lightsnaking. --- src/p_user.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index 764a94883..912ce2f2a 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4480,11 +4480,6 @@ void P_PlayerThink(player_t *player) // Allows some turning P_MovePlayer(player); } - else if (player->respawn.state == RESPAWNST_MOVE) - { - angle_t angleChange = player->cmd.turning << TICCMD_REDUCE; - P_SetPlayerAngle(player, player->angleturn + angleChange); - } } else if (player->mo->reactiontime) { From bcf07576c74a38a753375f678b027bfb9e17a12b Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 19 Feb 2021 20:51:58 +0000 Subject: [PATCH 39/50] Additional attempt to compensate for spectatoriness in K_ObjectTracking. --- src/k_hud.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_hud.c b/src/k_hud.c index 525f3eda3..a26e29573 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -823,7 +823,7 @@ void K_ObjectTracking(trackingResult_t *result, vector3_t *point, UINT8 cameraNu return; } - if (cam->chase == true) + if (cam->chase == true && !player->spectator) { // Use the camera's properties. viewpointX = cam->x; From ff4ea765c4674494dd1277c2f2bdf9953f89cf4e Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 20 Feb 2021 16:05:12 +0000 Subject: [PATCH 40/50] Fixed flashingtics not working if you've never taken any damage in a match before. Two notable consequences of this bug: * The delay when pressing the item button as a spectator to toggle PF_WANTSTOJOIN was not present, leading to a rapid toggle and spurious changeteam commands. * Lightsnaking through map hazards such as Lavender Shrine's stabbies caused you extra spicy unavoidable pain. --- src/k_kart.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 0f97aa9d6..4d70f3907 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -6213,15 +6213,13 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->karthud[khud_timeovercam] = 0; - // Specific hack because it insists on setting flashing tics during this anyway... - if (( player->kartstuff[k_spinouttype] & KSPIN_IFRAMES ) == 0) - { - player->powers[pw_flashing] = 0; - } // Make ABSOLUTELY SURE that your flashing tics don't get set WHILE you're still in hit animations. - else if (player->kartstuff[k_spinouttimer] != 0 || player->kartstuff[k_wipeoutslow] != 0) + if (player->kartstuff[k_spinouttimer] != 0 || player->kartstuff[k_wipeoutslow] != 0) { - player->powers[pw_flashing] = K_GetKartFlashing(player); + if (( player->kartstuff[k_spinouttype] & KSPIN_IFRAMES ) == 0) + player->powers[pw_flashing] = 0; + else + player->powers[pw_flashing] = K_GetKartFlashing(player); } if (player->kartstuff[k_spinouttimer]) From 08d087c6b5421623ebf25227fe50069a5ac15abd Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 20 Feb 2021 23:10:18 +0000 Subject: [PATCH 41/50] Acceleration Kickstart, my little hobby project. It's no secret that holding down a button a lot can fuck with your wrists and fingers. It's too late for me to be damageless, but I can at least create an option to reduce further harm. This accessibility feature, when enabled (kickstartaccel and kickstartaccel2/3/4 in the console) behaves with the following properties: * Hold accelerate for 1 second to lock it down. * Press again to release. * Short holds/presses do nothing (good for POSITION). * Continue holding it during the releasing press to re-lock it. * A small triangular UI element is added next to the speedometer sticker, which displays the current state of the acceleration kickstart for visual feedback. (NO SPLITS SUPPORT YET) In addition: * Add PF_ACCELDOWN and PF_BRAKEDOWN, and BT_REALACCELERATE (which ACCELDOWN tracks). Even if this feature never gets merged, BT_REALACCELERATE is required because sneakers and boosters force it on too (extending this is how I implemented it). * Fix the dehacked playerflag list being out of shape. * I replaced some existing flags during development of this branch, so their old uses have been whittled away. --- src/d_netcmd.c | 10 +++++---- src/d_player.h | 47 +++++++++++++++++++------------------- src/d_ticcmd.h | 17 +++++++------- src/dehacked.c | 34 ++++++++-------------------- src/g_demo.c | 16 +++++++++++-- src/g_game.c | 57 ++++++++++++++++++++++++++++++++++++++--------- src/g_game.h | 1 + src/k_hud.c | 38 +++++++++++++++++++++++++++---- src/lua_baselib.c | 12 ---------- src/p_inter.c | 29 ------------------------ src/p_local.h | 1 - src/p_spec.c | 4 ---- src/p_user.c | 30 ++++++++++++++++++++----- 13 files changed, 168 insertions(+), 128 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index ba5560802..7ad6b2727 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -939,6 +939,7 @@ void D_RegisterClientCommands(void) // g_input.c for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) { + CV_RegisterVar(&cv_kickstartaccel[i]); CV_RegisterVar(&cv_turnaxis[i]); CV_RegisterVar(&cv_moveaxis[i]); CV_RegisterVar(&cv_brakeaxis[i]); @@ -1627,6 +1628,8 @@ void SendWeaponPref(UINT8 n) buf[0] = 0; // Player option cvars that need to be synched go HERE + if (cv_kickstartaccel[n].value) + buf[0] |= 1; SendNetXCmdForPlayer(n, XD_WEAPONPREF, buf, 1); } @@ -1635,11 +1638,10 @@ static void Got_WeaponPref(UINT8 **cp,INT32 playernum) { UINT8 prefs = READUINT8(*cp); - (void)prefs; - (void)playernum; - - //players[playernum].pflags &= ~(PF_FLIPCAM); // Player option cvars that need to be synched go HERE + players[playernum].pflags &= ~(PF_KICKSTARTACCEL); + if (prefs & 1) + players[playernum].pflags |= PF_KICKSTARTACCEL; } static void Got_PowerLevel(UINT8 **cp,INT32 playernum) diff --git a/src/d_player.h b/src/d_player.h index f2883eaa2..0016a2cac 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -67,48 +67,45 @@ typedef enum // True if button down last tic. PF_ATTACKDOWN = 1<<7, - PF_SPINDOWN = 1<<8, - PF_JUMPDOWN = 1<<9, - PF_WPNDOWN = 1<<10, + PF_ACCELDOWN = 1<<8, + PF_BRAKEDOWN = 1<<9, + PF_WPNDOWN = 1<<10, // unused // Unmoving states PF_STASIS = 1<<11, // Player is not allowed to move - PF_JUMPSTASIS = 1<<12, // and that includes jumping. - PF_FULLSTASIS = PF_STASIS|PF_JUMPSTASIS, + PF_JUMPSTASIS = 1<<12, // unused // SRB2Kart: Spectator that wants to join PF_WANTSTOJOIN = 1<<13, // Character action status - PF_STARTJUMP = 1<<14, - PF_JUMPED = 1<<15, - PF_NOJUMPDAMAGE = 1<<16, - - PF_SPINNING = 1<<17, - PF_STARTDASH = 1<<18, - - PF_THOKKED = 1<<19, - PF_SHIELDABILITY = 1<<20, - PF_GLIDING = 1<<21, - PF_BOUNCING = 1<<22, + PF_STARTJUMP = 1<<14, // unused + PF_JUMPED = 1<<15, // unused + PF_NOJUMPDAMAGE = 1<<16, // unused + PF_SPINNING = 1<<17, // unused + PF_STARTDASH = 1<<18, // unused + PF_THOKKED = 1<<19, // unused + PF_SHIELDABILITY = 1<<20, // unused + PF_GLIDING = 1<<21, // unused + PF_BOUNCING = 1<<22, // unused // Sliding (usually in water) like Labyrinth/Oil Ocean PF_SLIDING = 1<<23, // NiGHTS stuff - PF_TRANSFERTOCLOSEST = 1<<24, - PF_DRILLING = 1<<25, + PF_TRANSFERTOCLOSEST = 1<<24, // unused + PF_DRILLING = 1<<25, // unused // Gametype-specific stuff - PF_GAMETYPEOVER = 1<<26, // Race time over, or H&S out-of-game - PF_TAGIT = 1<<27, // The player is it! For Tag Mode + PF_GAMETYPEOVER = 1<<26, // Race time over + PF_TAGIT = 1<<27, // unused /*** misc ***/ - PF_FORCESTRAFE = 1<<28, // Turning inputs are translated into strafing inputs - PF_CANCARRY = 1<<29, // Can carry another player? + PF_KICKSTARTACCEL = 1<<28, // Accessibility feature - is accelerate in kickstart mode? + PF_CANCARRY = 1<<29, // unused PF_HITFINISHLINE = 1<<30, // Already hit the finish line this tic - // up to 1<<31 is free + // up to 1<<31 is free, but try to hit unused stuff first } pflags_t; typedef enum @@ -298,6 +295,9 @@ typedef enum #undef KSPIN_TYPE } kartspinoutflags_t; +// for k_kickstartaccel +#define ACCEL_KICKSTART 35 + //{ SRB2kart - kartstuff typedef enum { @@ -398,6 +398,7 @@ typedef enum k_springcolor, // Color of spring stars k_killfield, // How long have you been in the kill field, stay in too long and lose a bumper k_wrongway, // Display WRONG WAY on screen + k_kickstartaccel, // how long you've been holding accel for, for PF_KICKSTARTACCEL NUMKARTSTUFF } kartstufftype_t; diff --git a/src/d_ticcmd.h b/src/d_ticcmd.h index 17c41cfbf..6f57fe784 100644 --- a/src/d_ticcmd.h +++ b/src/d_ticcmd.h @@ -26,17 +26,18 @@ // Button/action code definitions. typedef enum { - BT_ACCELERATE = 1, // Accelerate - BT_DRIFT = 1<<2, // Drift (direction is cmd->turning) - BT_BRAKE = 1<<3, // Brake - BT_ATTACK = 1<<4, // Use Item - BT_FORWARD = 1<<5, // Aim Item Forward - BT_BACKWARD = 1<<6, // Aim Item Backward - BT_LOOKBACK = 1<<7, // Look Backward + BT_ACCELERATE = 1, // Accelerate + BT_DRIFT = 1<<2, // Drift (direction is cmd->turning) + BT_BRAKE = 1<<3, // Brake + BT_ATTACK = 1<<4, // Use Item + BT_FORWARD = 1<<5, // Aim Item Forward + BT_BACKWARD = 1<<6, // Aim Item Backward + BT_LOOKBACK = 1<<7, // Look Backward + BT_REALACCELERATE = 1<<8, // Accelerate but not influenced by boosting or kickstart BT_EBRAKEMASK = (BT_ACCELERATE|BT_BRAKE), - // free: 1<<8 to 1<<12 + // free: 1<<9 to 1<<12 // Lua garbage BT_CUSTOM1 = 1<<13, diff --git a/src/dehacked.c b/src/dehacked.c index 5d77e61dc..8e3faba02 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -10645,17 +10645,13 @@ static const char *const PLAYERFLAG_LIST[] = { // True if button down last tic. "ATTACKDOWN", - "SPINDOWN", - "JUMPDOWN", + "ACCELDOWN", + "BRAKEDOWN", "WPNDOWN", // Unmoving states "STASIS", // Player is not allowed to move "JUMPSTASIS", // and that includes jumping. - // (we don't include FULLSTASIS here I guess because it's just those two together...?) - - // Did you get a time-over? - "TIMEOVER", // SRB2Kart: spectator that wants to join "WANTSTOJOIN", @@ -10664,10 +10660,8 @@ static const char *const PLAYERFLAG_LIST[] = { "STARTJUMP", "JUMPED", "NOJUMPDAMAGE", - "SPINNING", "STARTDASH", - "THOKKED", "SHIELDABILITY", "GLIDING", @@ -10681,13 +10675,13 @@ static const char *const PLAYERFLAG_LIST[] = { "DRILLING", // Gametype-specific stuff - "GAMETYPEOVER", // Race time over, or H&S out-of-game - "TAGIT", // The player is it! For Tag Mode + "GAMETYPEOVER", // Race time over + "TAGIT", /*** misc ***/ - "FORCESTRAFE", // Translate turn inputs into strafe inputs + "FORCESTRAFE", // Accessibility feature - is accelerate in kickstart mode? + "CANCARRY", "HITFINISHLINE", // Already hit the finish line this tic - "FINISHED", NULL // stop loop here. }; @@ -11054,7 +11048,8 @@ static const char *const KARTSTUFF_LIST[] = { "SPRINGSTARS", "SPRINGCOLOR", "KILLFIELD", - "WRONGWAY" + "WRONGWAY", + "KICKSTARTACCEL" }; static const char *const KARTHUD_LIST[] = { @@ -11655,6 +11650,7 @@ struct { {"BT_ATTACK",BT_ATTACK}, {"BT_FORWARD",BT_FORWARD}, {"BT_BACKWARD",BT_BACKWARD}, + {"BT_REALACCELERATE",BT_REALACCELERATE}, {"BT_CUSTOM1",BT_CUSTOM1}, // Lua customizable {"BT_CUSTOM2",BT_CUSTOM2}, // Lua customizable {"BT_CUSTOM3",BT_CUSTOM3}, // Lua customizable @@ -12183,8 +12179,6 @@ static fixed_t find_const(const char **rword) free(word); return (1<spectator ? DEMO_SPECTATOR : 0)); + i = p; + if (player->pflags & PF_KICKSTARTACCEL) + i |= DEMO_KICKSTART; + if (player->spectator) + i |= DEMO_SPECTATOR; + WRITEUINT8(demo_p, i); // Name memset(name, 0, 16); @@ -2903,6 +2909,12 @@ void G_DoPlayDemo(char *defdemoname) while (p != 0xFF) { + players[p].pflags &= ~PF_KICKSTARTACCEL; + if (p & DEMO_KICKSTART) + { + players[p].pflags |= PF_KICKSTARTACCEL; + p &= ~DEMO_KICKSTART; + } spectator = false; if (p & DEMO_SPECTATOR) { @@ -3194,7 +3206,7 @@ void G_AddGhost(char *defdemoname) return; } - if (READUINT8(p) != 0) + if ((READUINT8(p) & ~DEMO_KICKSTART) != 0) { CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Invalid player slot.\n"), pdemoname); Z_Free(pdemoname); diff --git a/src/g_game.c b/src/g_game.c index c6c831b76..8e076c2c4 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -342,10 +342,11 @@ INT16 prevmap, nextmap; static UINT8 *savebuffer; -void SendWeaponPref(void); -void SendWeaponPref2(void); -void SendWeaponPref3(void); -void SendWeaponPref4(void); +static void kickstartaccel_OnChange(void); +static void kickstartaccel2_OnChange(void); +static void kickstartaccel3_OnChange(void); +static void kickstartaccel4_OnChange(void); +void SendWeaponPref(UINT8 n); static CV_PossibleValue_t joyaxis_cons_t[] = {{0, "None"}, {1, "X-Axis"}, {2, "Y-Axis"}, {-1, "X-Axis-"}, {-2, "Y-Axis-"}, @@ -405,6 +406,13 @@ consvar_t cv_resetspecialmusic = CVAR_INIT ("resetspecialmusic", "Yes", CV_SAVE, consvar_t cv_resume = CVAR_INIT ("resume", "Yes", CV_SAVE, CV_YesNo, NULL); +consvar_t cv_kickstartaccel[MAXSPLITSCREENPLAYERS] = { + CVAR_INIT ("kickstartaccel", "Off", CV_SAVE|CV_CALL, CV_OnOff, kickstartaccel_OnChange), + CVAR_INIT ("kickstartaccel2", "Off", CV_SAVE|CV_CALL, CV_OnOff, kickstartaccel2_OnChange), + CVAR_INIT ("kickstartaccel3", "Off", CV_SAVE|CV_CALL, CV_OnOff, kickstartaccel3_OnChange), + CVAR_INIT ("kickstartaccel4", "Off", CV_SAVE|CV_CALL, CV_OnOff, kickstartaccel4_OnChange) +}; + consvar_t cv_turnaxis[MAXSPLITSCREENPLAYERS] = { CVAR_INIT ("joyaxis_turn", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL), CVAR_INIT ("joyaxis2_turn", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL), @@ -1003,10 +1011,15 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) { // forward with key or button // SRB2kart - we use an accel/brake instead of forward/backward. axis = PlayerJoyAxis(ssplayer, AXISMOVE); - if (PlayerInputDown(ssplayer, gc_accelerate) || (gamepadjoystickmove && axis > 0) || player->kartstuff[k_sneakertimer]) + if (PlayerInputDown(ssplayer, gc_accelerate) || (gamepadjoystickmove && axis > 0)) + { + cmd->buttons |= (BT_ACCELERATE|BT_REALACCELERATE); + forward = MAXPLMOVE; // 50 + } + else if ((gamestate == GS_LEVEL) && (player->kartstuff[k_sneakertimer] || (player->kartstuff[k_kickstartaccel] >= ACCEL_KICKSTART))) { cmd->buttons |= BT_ACCELERATE; - forward = MAXPLMOVE; // 50 + forward = MAXPLMOVE; } else if (analogjoystickmove && axis > 0) { @@ -1184,6 +1197,26 @@ ticcmd_t *G_MoveTiccmd(ticcmd_t* dest, const ticcmd_t* src, const size_t n) return dest; } +static void kickstartaccel_OnChange(void) +{ + SendWeaponPref(0); +} + +static void kickstartaccel2_OnChange(void) +{ + SendWeaponPref(1); +} + +static void kickstartaccel3_OnChange(void) +{ + SendWeaponPref(2); +} + +static void kickstartaccel4_OnChange(void) +{ + SendWeaponPref(3); +} + // // G_DoLoadLevel // @@ -2108,6 +2141,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) boolean eliminated; UINT16 nocontrol; INT32 khudfault; + INT32 kickstartaccel; score = players[player].score; marescore = players[player].marescore; @@ -2123,7 +2157,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) splitscreenindex = players[player].splitscreenindex; spectator = players[player].spectator; - pflags = (players[player].pflags & (PF_WANTSTOJOIN|PF_GAMETYPEOVER|PF_FAULT)); + pflags = (players[player].pflags & (PF_WANTSTOJOIN|PF_GAMETYPEOVER|PF_FAULT|PF_KICKSTARTACCEL)); playerangleturn = players[player].angleturn; // As long as we're not in multiplayer, carry over cheatcodes from map to map @@ -2177,6 +2211,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) spheres = 0; eliminated = false; wanted = 0; + kickstartaccel = 0; } else { @@ -2205,6 +2240,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) spheres = players[player].spheres; eliminated = players[player].eliminated; wanted = players[player].kartstuff[k_wanted]; + kickstartaccel = players[player].kartstuff[k_kickstartaccel]; } if (!betweenmaps) @@ -2278,6 +2314,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) p->kartstuff[k_lastdraft] = -1; p->karthud[khud_fault] = khudfault; p->powers[pw_nocontrol] = nocontrol; + players[player].kartstuff[k_kickstartaccel] = kickstartaccel; memcpy(&p->respawn, &respawn, sizeof (p->respawn)); @@ -2292,9 +2329,9 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) // Don't do anything immediately - p->pflags |= PF_SPINDOWN; + p->pflags |= PF_BRAKEDOWN; p->pflags |= PF_ATTACKDOWN; - p->pflags |= PF_JUMPDOWN; + p->pflags |= PF_ACCELDOWN; p->playerstate = PST_LIVE; p->panim = PA_STILL; // standing animation @@ -4446,7 +4483,7 @@ void G_InitNew(UINT8 pencoremode, const char *mapname, boolean resetplayer, bool memset(&players[i].respawn, 0, sizeof (players[i].respawn)); // The latter two should clear by themselves, but just in case - players[i].pflags &= ~(PF_GAMETYPEOVER|PF_FULLSTASIS|PF_FAULT); + players[i].pflags &= ~(PF_GAMETYPEOVER|PF_STASIS|PF_FAULT); // Clear cheatcodes too, just in case. players[i].pflags &= ~(PF_GODMODE|PF_NOCLIP|PF_INVIS); diff --git a/src/g_game.h b/src/g_game.h index 89156b82f..28321adc5 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -57,6 +57,7 @@ extern consvar_t cv_pauseifunfocused; extern consvar_t cv_invertmouse; +extern consvar_t cv_kickstartaccel[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_turnaxis[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_moveaxis[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_brakeaxis[MAXSPLITSCREENPLAYERS]; diff --git a/src/k_hud.c b/src/k_hud.c index 525f3eda3..9ab832c7b 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -2249,6 +2249,36 @@ static void K_drawKartSpeedometer(void) V_DrawScaledPatch(LAPS_X+13, LAPS_Y-25 + battleoffset, V_HUDTRANS|V_SLIDEIN|splitflags, kp_facenum[numbers[1]]); V_DrawScaledPatch(LAPS_X+19, LAPS_Y-25 + battleoffset, V_HUDTRANS|V_SLIDEIN|splitflags, kp_facenum[numbers[2]]); V_DrawScaledPatch(LAPS_X+29, LAPS_Y-25 + battleoffset, V_HUDTRANS|V_SLIDEIN|splitflags, kp_speedometerlabel[labeln]); + + if (stplyr->pflags & PF_KICKSTARTACCEL) + { + numbers[0] = 7-(stplyr->kartstuff[k_kickstartaccel]*7)/ACCEL_KICKSTART; + numbers[1] = 7; + numbers[2] = 0; + + V_DrawFill(LAPS_X+61, LAPS_Y-26, 2, 1, 31|V_SLIDEIN|splitflags); + V_DrawFill(LAPS_X+61-4, (LAPS_Y-26)+8, 10, 1, 31|V_SLIDEIN|splitflags); + + while (numbers[1]--) + { + numbers[2] = (numbers[1]/2)+1; + V_DrawFill(LAPS_X+61-numbers[2], (LAPS_Y-25)+numbers[1], 2+(numbers[2]*2), 1, 31|V_SLIDEIN|splitflags); + if (numbers[0]) + { + if (numbers[1] < numbers[0]) + labeln = 23; + else if (numbers[1] == numbers[0]) + labeln = 3; + else + labeln = 5 + (numbers[1]-numbers[0])*2; + } + else if ((leveltime % 7) == numbers[1]) + labeln = 0; + else + labeln = 3; + V_DrawFill(LAPS_X+62-numbers[2], (LAPS_Y-25)+numbers[1], (numbers[2]*2), 1, labeln|V_SLIDEIN|splitflags); + } + } } static void K_drawBlueSphereMeter(void) @@ -3770,10 +3800,10 @@ static void K_drawInput(void) V_DrawFill(x+(xoffs), y+offs, BUTTW-1, BUTTH, col);\ V_DrawFixedPatch((x+1+(xoffs))<powers[pw_shield] & SH_FORCE) - { // Multi-hit - if (player->powers[pw_shield] & SH_FORCEHP) - player->powers[pw_shield]--; - else - player->powers[pw_shield] &= SH_STACK; - } - else if (player->powers[pw_shield] & SH_NOSTACK) - { // First layer shields - if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ARMAGEDDON) // Give them what's coming to them! - { - player->pflags |= PF_JUMPDOWN; - } - else - player->powers[pw_shield] &= SH_STACK; - } - else - { // Second layer shields - if (((player->powers[pw_shield] & SH_STACK) == SH_FIREFLOWER) && !player->powers[pw_super]) - { - player->mo->color = player->skincolor; - G_GhostAddColor((INT32) (player - players), GHC_NORMAL); - } - player->powers[pw_shield] = SH_NONE; - } -} - /** Damages an object, which may or may not be a player. * For melee attacks, source and inflictor are the same. * diff --git a/src/p_local.h b/src/p_local.h index 5fc1ab956..4182d0658 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -486,7 +486,6 @@ typedef struct BasicFF_s void P_ForceFeed(const player_t *player, INT32 attack, INT32 fade, tic_t duration, INT32 period); void P_ForceConstant(const BasicFF_t *FFInfo); void P_RampConstant(const BasicFF_t *FFInfo, INT32 Start, INT32 End); -void P_RemoveShield(player_t *player); void P_SpecialStageDamage(player_t *player, mobj_t *inflictor, mobj_t *source); boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype); void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damagetype); diff --git a/src/p_spec.c b/src/p_spec.c index d0a8f085c..98ae6faf9 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -8763,12 +8763,8 @@ void T_Pusher(pusher_t *p) { if (p->slider && thing->player) { - pflags_t jumped = (thing->player->pflags & (PF_JUMPED|PF_NOJUMPDAMAGE)); P_ResetPlayer (thing->player); - if (jumped) - thing->player->pflags |= jumped; - thing->player->pflags |= PF_SLIDING; thing->angle = R_PointToAngle2 (0, 0, xspeed<<(FRACBITS-PUSH_FACTOR), yspeed<<(FRACBITS-PUSH_FACTOR)); diff --git a/src/p_user.c b/src/p_user.c index 4d2705180..491fec1f2 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4324,6 +4324,19 @@ void P_PlayerThink(player_t *player) player->kartstuff[k_throwdir] = 0; } + // Accessibility - kickstart your acceleration + if (!(player->pflags & PF_KICKSTARTACCEL)) + player->kartstuff[k_kickstartaccel] = 0; + else if (cmd->buttons & BT_REALACCELERATE) + { + if (!(player->pflags & PF_ACCELDOWN)) + player->kartstuff[k_kickstartaccel] = 0; + else if (player->kartstuff[k_kickstartaccel] < ACCEL_KICKSTART) + player->kartstuff[k_kickstartaccel]++; + } + else if (player->kartstuff[k_kickstartaccel] < ACCEL_KICKSTART) + player->kartstuff[k_kickstartaccel] = 0; + #ifdef PARANOIA if (player->playerstate == PST_REBORN) I_Error("player %s is in PST_REBORN\n", sizeu1(playeri)); @@ -4506,10 +4519,10 @@ void P_PlayerThink(player_t *player) player->mo->movefactor = FRACUNIT; // We're not going to do any more with this, so let's change it back for the next frame. - // Unset statis flags after moving. + // Unset statis flag after moving. // In other words, if you manually set stasis via code, // it lasts for one tic. - player->pflags &= ~PF_FULLSTASIS; + player->pflags &= ~PF_STASIS; if (player->onconveyor == 1) player->onconveyor = 3; @@ -4555,11 +4568,16 @@ void P_PlayerThink(player_t *player) } #endif - // check for use - if (cmd->buttons & BT_BRAKE) - player->pflags |= PF_SPINDOWN; + // check for buttons + if (cmd->buttons & BT_REALACCELERATE) + player->pflags |= PF_ACCELDOWN; else - player->pflags &= ~PF_SPINDOWN; + player->pflags &= ~PF_ACCELDOWN; + + if (cmd->buttons & BT_BRAKE) + player->pflags |= PF_BRAKEDOWN; + else + player->pflags &= ~PF_BRAKEDOWN; // Counters, time dependent power ups. // Time Bonus & Ring Bonus count settings From b49e44bd971a4e2561bbd945f3a995776ddc5052 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 21 Feb 2021 15:58:25 +0000 Subject: [PATCH 42/50] Bots will now pretend their imaginary accelerate buttons are real, just so PF_ACCELDOWN is properly tracked. --- src/k_bot.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/k_bot.c b/src/k_bot.c index 32270b419..c035b2864 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -990,7 +990,7 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) rad = playerwidth; } - cmd->buttons |= BT_ACCELERATE; + cmd->buttons |= (BT_ACCELERATE|BT_REALACCELERATE); // Full speed ahead! cmd->forwardmove = MAXPLMOVE; @@ -1067,7 +1067,7 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) // where we figure out what the shape of the track looks like. UINT16 oldButtons = cmd->buttons; - cmd->buttons &= ~(BT_ACCELERATE|BT_BRAKE); + cmd->buttons &= ~(BT_ACCELERATE|BT_REALACCELERATE|BT_BRAKE); if (oldButtons & BT_ACCELERATE) { @@ -1076,7 +1076,7 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) if (oldButtons & BT_BRAKE) { - cmd->buttons |= BT_ACCELERATE; + cmd->buttons |= (BT_ACCELERATE|BT_REALACCELERATE); } cmd->forwardmove = -cmd->forwardmove; From f71741f557dc75bcb4f3ae3a7c619764b2673e83 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 21 Feb 2021 16:58:37 +0000 Subject: [PATCH 43/50] MT_BRAKEDRIFT appears to be broken, and self-removing if BT_ACCELERATE ISN'T there, as opposed to if it is as the comment suggests. Fix that here. --- src/p_mobj.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 25a505821..94eef3530 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6839,7 +6839,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) if ((!mobj->target || !mobj->target->health || !mobj->target->player || !P_IsObjectOnGround(mobj->target)) || !mobj->target->player->kartstuff[k_drift] || !mobj->target->player->kartstuff[k_brakedrift] || !((mobj->target->player->cmd.buttons & BT_BRAKE) - || !(mobj->target->player->cmd.buttons & BT_ACCELERATE))) // Letting go of accel functions about the same as brake-drifting + || (mobj->target->player->cmd.buttons & BT_ACCELERATE))) // Letting go of accel functions about the same as brake-drifting { P_RemoveMobj(mobj); return false; From d039b14aa42e1e3dd7938d465f8d352f8085d4d2 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 21 Feb 2021 18:08:04 +0000 Subject: [PATCH 44/50] Make kickstartaccel a UINT8 instead of an INT32 kartstuff entry. --- src/d_player.h | 9 +++++---- src/dehacked.c | 3 +-- src/g_game.c | 6 +++--- src/k_hud.c | 2 +- src/p_saveg.c | 4 ++++ src/p_user.c | 12 ++++++------ 6 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 0016a2cac..b055f6d9f 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -295,9 +295,6 @@ typedef enum #undef KSPIN_TYPE } kartspinoutflags_t; -// for k_kickstartaccel -#define ACCEL_KICKSTART 35 - //{ SRB2kart - kartstuff typedef enum { @@ -398,7 +395,6 @@ typedef enum k_springcolor, // Color of spring stars k_killfield, // How long have you been in the kill field, stay in too long and lose a bumper k_wrongway, // Display WRONG WAY on screen - k_kickstartaccel, // how long you've been holding accel for, for PF_KICKSTARTACCEL NUMKARTSTUFF } kartstufftype_t; @@ -451,6 +447,9 @@ typedef enum //} +// for kickstartaccel +#define ACCEL_KICKSTART 35 + // player_t struct for all respawn variables typedef struct respawnvars_s { @@ -701,6 +700,8 @@ typedef struct player_s UINT8 typing_timer; // Counts down while keystrokes are not emitted UINT8 typing_duration; // How long since resumed timer + UINT8 kickstartaccel; + #ifdef HWRENDER fixed_t fovadd; // adjust FOV for hw rendering #endif diff --git a/src/dehacked.c b/src/dehacked.c index 8e3faba02..73f681fe4 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -11048,8 +11048,7 @@ static const char *const KARTSTUFF_LIST[] = { "SPRINGSTARS", "SPRINGCOLOR", "KILLFIELD", - "WRONGWAY", - "KICKSTARTACCEL" + "WRONGWAY" }; static const char *const KARTHUD_LIST[] = { diff --git a/src/g_game.c b/src/g_game.c index 8e076c2c4..93cbd0132 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1016,7 +1016,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) cmd->buttons |= (BT_ACCELERATE|BT_REALACCELERATE); forward = MAXPLMOVE; // 50 } - else if ((gamestate == GS_LEVEL) && (player->kartstuff[k_sneakertimer] || (player->kartstuff[k_kickstartaccel] >= ACCEL_KICKSTART))) + else if ((gamestate == GS_LEVEL) && (player->kartstuff[k_sneakertimer] || (player->kickstartaccel >= ACCEL_KICKSTART))) { cmd->buttons |= BT_ACCELERATE; forward = MAXPLMOVE; @@ -2240,7 +2240,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) spheres = players[player].spheres; eliminated = players[player].eliminated; wanted = players[player].kartstuff[k_wanted]; - kickstartaccel = players[player].kartstuff[k_kickstartaccel]; + kickstartaccel = players[player].kickstartaccel; } if (!betweenmaps) @@ -2314,7 +2314,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) p->kartstuff[k_lastdraft] = -1; p->karthud[khud_fault] = khudfault; p->powers[pw_nocontrol] = nocontrol; - players[player].kartstuff[k_kickstartaccel] = kickstartaccel; + p->kickstartaccel = kickstartaccel; memcpy(&p->respawn, &respawn, sizeof (p->respawn)); diff --git a/src/k_hud.c b/src/k_hud.c index 9ab832c7b..f325d8135 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -2252,7 +2252,7 @@ static void K_drawKartSpeedometer(void) if (stplyr->pflags & PF_KICKSTARTACCEL) { - numbers[0] = 7-(stplyr->kartstuff[k_kickstartaccel]*7)/ACCEL_KICKSTART; + numbers[0] = 7-(stplyr->kickstartaccel*7)/ACCEL_KICKSTART; numbers[1] = 7; numbers[2] = 0; diff --git a/src/p_saveg.c b/src/p_saveg.c index 367f21439..8f5a1c709 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -280,6 +280,8 @@ static void P_NetArchivePlayers(void) WRITEUINT8(save_p, players[i].typing_timer); WRITEUINT8(save_p, players[i].typing_duration); + WRITEUINT8(save_p, players[i].kickstartaccel); + // respawnvars_t WRITEUINT8(save_p, players[i].respawn.state); WRITEUINT32(save_p, K_GetWaypointHeapIndex(players[i].respawn.wp)); @@ -489,6 +491,8 @@ static void P_NetUnArchivePlayers(void) players[i].typing_timer = READUINT8(save_p); players[i].typing_duration = READUINT8(save_p); + players[i].kickstartaccel = READUINT8(save_p); + // respawnvars_t players[i].respawn.state = READUINT8(save_p); players[i].respawn.wp = (waypoint_t *)(size_t)READUINT32(save_p); diff --git a/src/p_user.c b/src/p_user.c index 491fec1f2..a010e85b3 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4326,16 +4326,16 @@ void P_PlayerThink(player_t *player) // Accessibility - kickstart your acceleration if (!(player->pflags & PF_KICKSTARTACCEL)) - player->kartstuff[k_kickstartaccel] = 0; + player->kickstartaccel = 0; else if (cmd->buttons & BT_REALACCELERATE) { if (!(player->pflags & PF_ACCELDOWN)) - player->kartstuff[k_kickstartaccel] = 0; - else if (player->kartstuff[k_kickstartaccel] < ACCEL_KICKSTART) - player->kartstuff[k_kickstartaccel]++; + player->kickstartaccel = 0; + else if (player->kickstartaccel < ACCEL_KICKSTART) + player->kickstartaccel++; } - else if (player->kartstuff[k_kickstartaccel] < ACCEL_KICKSTART) - player->kartstuff[k_kickstartaccel] = 0; + else if (player->kickstartaccel < ACCEL_KICKSTART) + player->kickstartaccel = 0; #ifdef PARANOIA if (player->playerstate == PST_REBORN) From 56d0a6e43d5fd7ed4677846850d4ce423cfffe8f Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 21 Feb 2021 18:10:43 +0000 Subject: [PATCH 45/50] Bunch of changes to how the Kickstart Acceleration icon is rendered. * Display even if the player (or Lua) has disabled the speedometer. * Support splits all the way up to 4p. * Abstract out to a function that could hypothetically display more accessibility-related icons down the line. --- src/k_hud.c | 97 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 65 insertions(+), 32 deletions(-) diff --git a/src/k_hud.c b/src/k_hud.c index f325d8135..eac4f291d 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -2200,6 +2200,64 @@ static void K_drawKartLapsAndRings(void) #undef RINGANIM_FLIPFRAME +static void K_drawKartAccessibilityIcons(INT32 fx) +{ + INT32 fy = LAPS_Y; + UINT8 col = 0, i, wid, fil; + INT32 splitflags = V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_SPLITSCREEN; + //INT32 step = 1; -- if there's ever more than one accessibility icon + + fx += LAPS_X; + + if (r_splitscreen < 2) // adjust to speedometer height + { + fy -= 25; + if (gametype == GT_BATTLE) + fy -= 4; + } + else + { + fx += 44; + if (!(stplyr == &players[displayplayers[0]] || stplyr == &players[displayplayers[2]])) // If we are not P1 or P3... + { + splitflags ^= (V_SNAPTOLEFT|V_SNAPTORIGHT); + fx = (BASEVIDWIDTH/2) - (fx + 10); + //step = -step; + } + } + + if (stplyr->pflags & PF_KICKSTARTACCEL) // just KICKSTARTACCEL right now, maybe more later + { + fil = 7-(stplyr->kickstartaccel*7)/ACCEL_KICKSTART; + i = 7; + + V_DrawFill(fx+4, fy-1, 2, 1, 31|V_SLIDEIN|splitflags); + V_DrawFill(fx, (fy-1)+8, 10, 1, 31|V_SLIDEIN|splitflags); + + while (i--) + { + wid = (i/2)+1; + V_DrawFill(fx+4-wid, fy+i, 2+(wid*2), 1, 31|V_SLIDEIN|splitflags); + if (fil) + { + if (i < fil) + col = 23; + else if (i == fil) + col = 3; + else + col = 5 + (i-fil)*2; + } + else if ((leveltime % 7) == i) + col = 0; + else + col = 3; + V_DrawFill(fx+5-wid, fy+i, (wid*2), 1, col|V_SLIDEIN|splitflags); + } + + //fx += step*12; + } +} + static void K_drawKartSpeedometer(void) { static fixed_t convSpeed; @@ -2250,35 +2308,7 @@ static void K_drawKartSpeedometer(void) V_DrawScaledPatch(LAPS_X+19, LAPS_Y-25 + battleoffset, V_HUDTRANS|V_SLIDEIN|splitflags, kp_facenum[numbers[2]]); V_DrawScaledPatch(LAPS_X+29, LAPS_Y-25 + battleoffset, V_HUDTRANS|V_SLIDEIN|splitflags, kp_speedometerlabel[labeln]); - if (stplyr->pflags & PF_KICKSTARTACCEL) - { - numbers[0] = 7-(stplyr->kickstartaccel*7)/ACCEL_KICKSTART; - numbers[1] = 7; - numbers[2] = 0; - - V_DrawFill(LAPS_X+61, LAPS_Y-26, 2, 1, 31|V_SLIDEIN|splitflags); - V_DrawFill(LAPS_X+61-4, (LAPS_Y-26)+8, 10, 1, 31|V_SLIDEIN|splitflags); - - while (numbers[1]--) - { - numbers[2] = (numbers[1]/2)+1; - V_DrawFill(LAPS_X+61-numbers[2], (LAPS_Y-25)+numbers[1], 2+(numbers[2]*2), 1, 31|V_SLIDEIN|splitflags); - if (numbers[0]) - { - if (numbers[1] < numbers[0]) - labeln = 23; - else if (numbers[1] == numbers[0]) - labeln = 3; - else - labeln = 5 + (numbers[1]-numbers[0])*2; - } - else if ((leveltime % 7) == numbers[1]) - labeln = 0; - else - labeln = 3; - V_DrawFill(LAPS_X+62-numbers[2], (LAPS_Y-25)+numbers[1], (numbers[2]*2), 1, labeln|V_SLIDEIN|splitflags); - } - } + K_drawKartAccessibilityIcons(57); } static void K_drawBlueSphereMeter(void) @@ -4205,10 +4235,13 @@ void K_drawKartHUD(void) if (!stplyr->spectator && !demo.freecam) // Bottom of the screen elements, don't need in spectate mode { // Draw the speedometer - if (cv_kartspeedometer.value && !r_splitscreen) + if (cv_kartspeedometer.value && !r_splitscreen && (LUA_HudEnabled(hud_speedometer))) { - if (LUA_HudEnabled(hud_speedometer)) - K_drawKartSpeedometer(); + K_drawKartSpeedometer(); + } + else + { + K_drawKartAccessibilityIcons(0); } if (demo.title) // Draw title logo instead in demo.titles From 75b53bbb5282142669e18399b69109f51cfd148e Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 21 Feb 2021 18:20:44 +0000 Subject: [PATCH 46/50] Don't delete your kickstartaccel if you cross the finish line and the bot driver takes over. --- 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 a010e85b3..640400b48 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4329,7 +4329,7 @@ void P_PlayerThink(player_t *player) player->kickstartaccel = 0; else if (cmd->buttons & BT_REALACCELERATE) { - if (!(player->pflags & PF_ACCELDOWN)) + if (!player->exiting && !(player->pflags & PF_ACCELDOWN)) player->kickstartaccel = 0; else if (player->kickstartaccel < ACCEL_KICKSTART) player->kickstartaccel++; From cce4165f359c63bab2ca5ed6102b9be23822075e Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 21 Feb 2021 21:37:56 +0000 Subject: [PATCH 47/50] After discussing with Oni, adjust the coordinates for the accel kickstart indicator. --- src/k_hud.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/k_hud.c b/src/k_hud.c index eac4f291d..1aa0c97f8 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -2202,7 +2202,7 @@ static void K_drawKartLapsAndRings(void) static void K_drawKartAccessibilityIcons(INT32 fx) { - INT32 fy = LAPS_Y; + INT32 fy = LAPS_Y-25; UINT8 col = 0, i, wid, fil; INT32 splitflags = V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_SPLITSCREEN; //INT32 step = 1; -- if there's ever more than one accessibility icon @@ -2211,13 +2211,12 @@ static void K_drawKartAccessibilityIcons(INT32 fx) if (r_splitscreen < 2) // adjust to speedometer height { - fy -= 25; if (gametype == GT_BATTLE) fy -= 4; } else { - fx += 44; + fy += 4; if (!(stplyr == &players[displayplayers[0]] || stplyr == &players[displayplayers[2]])) // If we are not P1 or P3... { splitflags ^= (V_SNAPTOLEFT|V_SNAPTORIGHT); @@ -2308,7 +2307,7 @@ static void K_drawKartSpeedometer(void) V_DrawScaledPatch(LAPS_X+19, LAPS_Y-25 + battleoffset, V_HUDTRANS|V_SLIDEIN|splitflags, kp_facenum[numbers[2]]); V_DrawScaledPatch(LAPS_X+29, LAPS_Y-25 + battleoffset, V_HUDTRANS|V_SLIDEIN|splitflags, kp_speedometerlabel[labeln]); - K_drawKartAccessibilityIcons(57); + K_drawKartAccessibilityIcons(56); } static void K_drawBlueSphereMeter(void) @@ -4234,16 +4233,6 @@ void K_drawKartHUD(void) if (!stplyr->spectator && !demo.freecam) // Bottom of the screen elements, don't need in spectate mode { - // Draw the speedometer - if (cv_kartspeedometer.value && !r_splitscreen && (LUA_HudEnabled(hud_speedometer))) - { - K_drawKartSpeedometer(); - } - else - { - K_drawKartAccessibilityIcons(0); - } - if (demo.title) // Draw title logo instead in demo.titles { INT32 x = BASEVIDWIDTH - 32, y = 128, offs; @@ -4294,6 +4283,16 @@ void K_drawKartHUD(void) K_drawKartBumpersOrKarma(); } + // Draw the speedometer and/or accessibility icons + if (cv_kartspeedometer.value && !r_splitscreen && (LUA_HudEnabled(hud_speedometer))) + { + K_drawKartSpeedometer(); + } + else + { + K_drawKartAccessibilityIcons((r_splitscreen > 1) ? 0 : 8); + } + if (gametyperules & GTR_SPHERES) { K_drawBlueSphereMeter(); From a43a762b466c6da81d4c66d3aa70999c3b9b496e Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 22 Feb 2021 12:21:48 +0000 Subject: [PATCH 48/50] Instead of hacking ticcmd generation, add/modify helper functions acting as intermediaries that add the necessary changes. * Introducing K_GetKartButtons(player_t), for adding false presses to. * K_GetForwardMove(player_t) takes kickstarting into account, and is now applied to engine sound generation too. * BT_REALACCELERATE has been deleted. --- src/d_ticcmd.h | 1 - src/dehacked.c | 1 - src/g_game.c | 7 +----- src/k_bot.c | 6 ++--- src/k_hud.c | 8 +++---- src/k_kart.c | 60 +++++++++++++++++++++++++++++++++---------------- src/k_kart.h | 2 ++ src/k_respawn.c | 6 ++--- src/p_mobj.c | 2 +- src/p_user.c | 4 ++-- 10 files changed, 57 insertions(+), 40 deletions(-) diff --git a/src/d_ticcmd.h b/src/d_ticcmd.h index 6f57fe784..226c8f4d8 100644 --- a/src/d_ticcmd.h +++ b/src/d_ticcmd.h @@ -33,7 +33,6 @@ typedef enum BT_FORWARD = 1<<5, // Aim Item Forward BT_BACKWARD = 1<<6, // Aim Item Backward BT_LOOKBACK = 1<<7, // Look Backward - BT_REALACCELERATE = 1<<8, // Accelerate but not influenced by boosting or kickstart BT_EBRAKEMASK = (BT_ACCELERATE|BT_BRAKE), diff --git a/src/dehacked.c b/src/dehacked.c index 73f681fe4..fb3608849 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -11649,7 +11649,6 @@ struct { {"BT_ATTACK",BT_ATTACK}, {"BT_FORWARD",BT_FORWARD}, {"BT_BACKWARD",BT_BACKWARD}, - {"BT_REALACCELERATE",BT_REALACCELERATE}, {"BT_CUSTOM1",BT_CUSTOM1}, // Lua customizable {"BT_CUSTOM2",BT_CUSTOM2}, // Lua customizable {"BT_CUSTOM3",BT_CUSTOM3}, // Lua customizable diff --git a/src/g_game.c b/src/g_game.c index 93cbd0132..9a766dc42 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1012,14 +1012,9 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) // forward with key or button // SRB2kart - we use an accel/brake instead of forward/backward. axis = PlayerJoyAxis(ssplayer, AXISMOVE); if (PlayerInputDown(ssplayer, gc_accelerate) || (gamepadjoystickmove && axis > 0)) - { - cmd->buttons |= (BT_ACCELERATE|BT_REALACCELERATE); - forward = MAXPLMOVE; // 50 - } - else if ((gamestate == GS_LEVEL) && (player->kartstuff[k_sneakertimer] || (player->kickstartaccel >= ACCEL_KICKSTART))) { cmd->buttons |= BT_ACCELERATE; - forward = MAXPLMOVE; + forward = MAXPLMOVE; // 50 } else if (analogjoystickmove && axis > 0) { diff --git a/src/k_bot.c b/src/k_bot.c index c035b2864..32270b419 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -990,7 +990,7 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) rad = playerwidth; } - cmd->buttons |= (BT_ACCELERATE|BT_REALACCELERATE); + cmd->buttons |= BT_ACCELERATE; // Full speed ahead! cmd->forwardmove = MAXPLMOVE; @@ -1067,7 +1067,7 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) // where we figure out what the shape of the track looks like. UINT16 oldButtons = cmd->buttons; - cmd->buttons &= ~(BT_ACCELERATE|BT_REALACCELERATE|BT_BRAKE); + cmd->buttons &= ~(BT_ACCELERATE|BT_BRAKE); if (oldButtons & BT_ACCELERATE) { @@ -1076,7 +1076,7 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) if (oldButtons & BT_BRAKE) { - cmd->buttons |= (BT_ACCELERATE|BT_REALACCELERATE); + cmd->buttons |= BT_ACCELERATE; } cmd->forwardmove = -cmd->forwardmove; diff --git a/src/k_hud.c b/src/k_hud.c index 1aa0c97f8..e72698cf8 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -3829,10 +3829,10 @@ static void K_drawInput(void) V_DrawFill(x+(xoffs), y+offs, BUTTW-1, BUTTH, col);\ V_DrawFixedPatch((x+1+(xoffs))<mo); - ticcmd_t *cmd = &player->cmd; - const boolean spinningwheels = (((cmd->buttons & BT_ACCELERATE) == BT_ACCELERATE) || (onground && player->speed > 0)); - const boolean lookback = ((cmd->buttons & BT_LOOKBACK) == BT_LOOKBACK); + UINT16 buttons = K_GetKartButtons(player); + const boolean spinningwheels = (((buttons & BT_ACCELERATE) == BT_ACCELERATE) || (onground && player->speed > 0)); + const boolean lookback = ((buttons & BT_LOOKBACK) == BT_LOOKBACK); SINT8 turndir = 0; SINT8 destGlanceDir = 0; SINT8 drift = player->kartstuff[k_drift]; - if (cmd->turning < -minturn) + if (player->cmd.turning < -minturn) { turndir = -1; } - else if (cmd->turning > minturn) + else if (player->cmd.turning > minturn) { turndir = 1; } @@ -2583,6 +2583,19 @@ UINT16 K_GetKartFlashing(player_t *player) return tics; } +boolean K_KartKickstart(player_t *player) +{ + return ((player->pflags & PF_KICKSTARTACCEL) + && (!K_PlayerUsesBotMovement(player)) + && (player->kickstartaccel >= ACCEL_KICKSTART)); +} + +UINT16 K_GetKartButtons(player_t *player) +{ + return (player->cmd.buttons | + (K_KartKickstart(player) ? BT_ACCELERATE : 0)); +} + SINT8 K_GetForwardMove(player_t *player) { SINT8 forwardmove = player->cmd.forwardmove; @@ -2602,6 +2615,13 @@ SINT8 K_GetForwardMove(player_t *player) return 0; } + if (K_KartKickstart(player)) // unlike the brute forward of sneakers, allow for backwards easing here + { + forwardmove += MAXPLMOVE; + if (forwardmove > MAXPLMOVE) + forwardmove = MAXPLMOVE; + } + return forwardmove; } @@ -5632,7 +5652,7 @@ player_t *K_FindJawzTarget(mobj_t *actor, player_t *source) } // Engine Sounds. -static void K_UpdateEngineSounds(player_t *player, ticcmd_t *cmd) +static void K_UpdateEngineSounds(player_t *player) { const INT32 numsnds = 13; @@ -5641,6 +5661,8 @@ static void K_UpdateEngineSounds(player_t *player, ticcmd_t *cmd) const UINT8 dampenval = 48; // 255 * 48 = close enough to FRACUNIT/6 + const UINT16 buttons = K_GetKartButtons(player); + INT32 class, s, w; // engine class number UINT8 volume = 255; @@ -5681,17 +5703,17 @@ static void K_UpdateEngineSounds(player_t *player, ticcmd_t *cmd) if (player->respawn.state == RESPAWNST_DROP) // Dropdashing { // Dropdashing - targetsnd = ((cmd->buttons & BT_ACCELERATE) ? 12 : 0); + targetsnd = ((buttons & BT_ACCELERATE) ? 12 : 0); } else if (K_PlayerEBrake(player) == true) { // Spindashing - targetsnd = ((cmd->buttons & BT_DRIFT) ? 12 : 0); + targetsnd = ((buttons & BT_DRIFT) ? 12 : 0); } else { // Average out the value of forwardmove and the speed that you're moving at. - targetsnd = (((6 * cmd->forwardmove) / 25) + ((player->speed / mapobjectscale) / 5)) / 2; + targetsnd = (((6 * K_GetForwardMove(player)) / 25) + ((player->speed / mapobjectscale) / 5)) / 2; } if (targetsnd < 0) { targetsnd = 0; } @@ -5989,7 +6011,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) { K_UpdateOffroad(player); K_UpdateDraft(player); - K_UpdateEngineSounds(player, cmd); // Thanks, VAda! + K_UpdateEngineSounds(player); // Thanks, VAda! // update boost angle if not spun out if (!player->kartstuff[k_spinouttimer] && !player->kartstuff[k_wipeoutslow]) @@ -6471,7 +6493,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (cmd->buttons & BT_DRIFT) { // Only allow drifting while NOT trying to do an spindash input. - if ((cmd->buttons & BT_EBRAKEMASK) != BT_EBRAKEMASK) + if ((K_GetKartButtons(player) & BT_EBRAKEMASK) != BT_EBRAKEMASK) { player->driftInput = true; } @@ -7019,7 +7041,7 @@ INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue) currentSpeed = R_PointToDist2(0, 0, player->mo->momx, player->mo->momy); if ((currentSpeed <= 0) // Not moving - && ((player->cmd.buttons & BT_EBRAKEMASK) != BT_EBRAKEMASK) // not e-braking + && ((K_GetKartButtons(player) & BT_EBRAKEMASK) != BT_EBRAKEMASK) // not e-braking && (player->respawn.state == RESPAWNST_NONE)) // Not respawning { return 0; @@ -7123,6 +7145,8 @@ static void K_KartDrift(player_t *player, boolean onground) const INT32 dstwo = dsone*2; const INT32 dsthree = dstwo*2; + const UINT16 buttons = K_GetKartButtons(player); + // Drifting is actually straffing + automatic turning. // Holding the Jump button will enable drifting. // (This comment is extremely funny) @@ -7329,8 +7353,8 @@ static void K_KartDrift(player_t *player, boolean onground) K_SpawnAIZDust(player); if (player->kartstuff[k_drift] - && ((player->cmd.buttons & BT_BRAKE) - || !(player->cmd.buttons & BT_ACCELERATE)) + && ((buttons & BT_BRAKE) + || !(buttons & BT_ACCELERATE)) && P_IsObjectOnGround(player->mo)) { if (!player->kartstuff[k_brakedrift]) @@ -7504,7 +7528,7 @@ static INT32 K_FlameShieldMax(player_t *player) boolean K_PlayerEBrake(player_t *player) { - return (player->cmd.buttons & BT_EBRAKEMASK) == BT_EBRAKEMASK + return (K_GetKartButtons(player) & BT_EBRAKEMASK) == BT_EBRAKEMASK && P_IsObjectOnGround(player->mo) == true && player->kartstuff[k_drift] == 0 && player->kartstuff[k_spinouttimer] == 0 @@ -7687,8 +7711,6 @@ static void K_AirFailsafe(player_t *player) const fixed_t maxSpeed = 6*player->mo->scale; const fixed_t thrustSpeed = 6*player->mo->scale; // 10*player->mo->scale - ticcmd_t *cmd = &player->cmd; - if (player->speed > maxSpeed // Above the max speed that you're allowed to use this technique. || player->respawn.state != RESPAWNST_NONE) // Respawning, you don't need this AND drop dash :V { @@ -7696,7 +7718,7 @@ static void K_AirFailsafe(player_t *player) return; } - if ((cmd->buttons & BT_ACCELERATE) || K_GetForwardMove(player) != 0) + if ((K_GetKartButtons(player) & BT_ACCELERATE) || K_GetForwardMove(player) != 0) { // Queue up later player->airFailsafe = true; @@ -7738,7 +7760,7 @@ void K_AdjustPlayerFriction(player_t *player) { player->mo->friction -= 1024; } - else if (player->speed > 0 && cmd->forwardmove < 0) + else if (player->speed > 0 && K_GetForwardMove(player) < 0) { player->mo->friction -= 512; } diff --git a/src/k_kart.h b/src/k_kart.h index 0e3aa0ff4..c91bba806 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -91,6 +91,8 @@ fixed_t K_GetKartSpeedFromStat(UINT8 kartspeed); fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower); fixed_t K_GetKartAccel(player_t *player); UINT16 K_GetKartFlashing(player_t *player); +boolean K_KartKickstart(player_t *player); +UINT16 K_GetKartButtons(player_t *player); SINT8 K_GetForwardMove(player_t *player); fixed_t K_3dKartMovement(player_t *player); boolean K_PlayerEBrake(player_t *player); diff --git a/src/k_respawn.c b/src/k_respawn.c index 409340a3f..dd424e6d6 100644 --- a/src/k_respawn.c +++ b/src/k_respawn.c @@ -648,7 +648,7 @@ static void K_DropDashWait(player_t *player) --------------------------------------------------*/ static void K_HandleDropDash(player_t *player) { - ticcmd_t *cmd = &player->cmd; + const UINT16 buttons = K_GetKartButtons(player); if (player->kartstuff[k_growshrinktimer] < 0) { @@ -673,7 +673,7 @@ static void K_HandleDropDash(player_t *player) // The old behavior was stupid and prone to accidental usage. // Let's rip off Mania instead, and turn this into a Drop Dash! - if ((cmd->buttons & BT_ACCELERATE) && !player->kartstuff[k_spinouttimer]) // Since we're letting players spin out on respawn, don't let them charge a dropdash in this state. (It wouldn't work anyway) + if ((buttons & BT_ACCELERATE) && !player->kartstuff[k_spinouttimer]) // Since we're letting players spin out on respawn, don't let them charge a dropdash in this state. (It wouldn't work anyway) { player->respawn.dropdash++; } @@ -698,7 +698,7 @@ static void K_HandleDropDash(player_t *player) } else { - if ((cmd->buttons & BT_ACCELERATE) && (player->respawn.dropdash >= TICRATE/4)) + if ((buttons & BT_ACCELERATE) && (player->respawn.dropdash >= TICRATE/4)) { S_StartSound(player->mo, sfx_s23c); player->kartstuff[k_startboost] = 50; diff --git a/src/p_mobj.c b/src/p_mobj.c index 94eef3530..6a58fc907 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6839,7 +6839,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) if ((!mobj->target || !mobj->target->health || !mobj->target->player || !P_IsObjectOnGround(mobj->target)) || !mobj->target->player->kartstuff[k_drift] || !mobj->target->player->kartstuff[k_brakedrift] || !((mobj->target->player->cmd.buttons & BT_BRAKE) - || (mobj->target->player->cmd.buttons & BT_ACCELERATE))) // Letting go of accel functions about the same as brake-drifting + || (K_GetKartButtons(mobj->target->player) & BT_ACCELERATE))) // Letting go of accel functions about the same as brake-drifting { P_RemoveMobj(mobj); return false; diff --git a/src/p_user.c b/src/p_user.c index 640400b48..5bfe06533 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4327,7 +4327,7 @@ void P_PlayerThink(player_t *player) // Accessibility - kickstart your acceleration if (!(player->pflags & PF_KICKSTARTACCEL)) player->kickstartaccel = 0; - else if (cmd->buttons & BT_REALACCELERATE) + else if (cmd->buttons & BT_ACCELERATE) { if (!player->exiting && !(player->pflags & PF_ACCELDOWN)) player->kickstartaccel = 0; @@ -4569,7 +4569,7 @@ void P_PlayerThink(player_t *player) #endif // check for buttons - if (cmd->buttons & BT_REALACCELERATE) + if (cmd->buttons & BT_ACCELERATE) player->pflags |= PF_ACCELDOWN; else player->pflags &= ~PF_ACCELDOWN; From 879c821d181bd1607d62b82c7fd39f3df892af7c Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 22 Feb 2021 12:58:03 +0000 Subject: [PATCH 49/50] Demo-sync weaponpref data, which just includes kickstartaccel right now. --- src/d_netcmd.c | 3 +++ src/g_demo.c | 17 ++++++++++++++++- src/g_demo.h | 17 +++++++++-------- 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 7ad6b2727..233252536 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1642,6 +1642,9 @@ static void Got_WeaponPref(UINT8 **cp,INT32 playernum) players[playernum].pflags &= ~(PF_KICKSTARTACCEL); if (prefs & 1) players[playernum].pflags |= PF_KICKSTARTACCEL; + + // SEE ALSO g_demo.c + demo_extradata[playernum] |= DXD_WEAPONPREF; } static void Got_PowerLevel(UINT8 **cp,INT32 playernum) diff --git a/src/g_demo.c b/src/g_demo.c index 859bb4421..fc9181717 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -341,7 +341,13 @@ void G_ReadDemoExtraData(void) K_CheckBumpers(); P_CheckRacers(); } - + if (extradata & DXD_WEAPONPREF) + { + extradata = READUINT8(demo_p); + players[p].pflags &= ~(PF_KICKSTARTACCEL); + if (extradata & 1) + players[p].pflags |= PF_KICKSTARTACCEL; + } p = READUINT8(demo_p); } @@ -447,6 +453,13 @@ void G_WriteDemoExtraData(void) else WRITEUINT8(demo_p, DXD_PST_PLAYING); } + if (demo_extradata[i] & DXD_WEAPONPREF) + { + UINT8 prefs = 0; + if (players[i].pflags & PF_KICKSTARTACCEL) + prefs |= 1; + WRITEUINT8(demo_p, prefs); + } } demo_extradata[i] = 0; @@ -1068,6 +1081,8 @@ void G_GhostTicker(void) g->p += 32; // ok (32 because there's both the skin and the colour) if (ziptic & DXD_PLAYSTATE && READUINT8(g->p) != DXD_PST_PLAYING) I_Error("Ghost is not a record attack ghost PLAYSTATE"); //@TODO lmao don't blow up like this + if (ziptic & DXD_WEAPONPREF) + g->p++; // ditto } else if (ziptic == DW_RNG) g->p += 4; // RNG seed diff --git a/src/g_demo.h b/src/g_demo.h index b4039434e..03d75cf4b 100644 --- a/src/g_demo.h +++ b/src/g_demo.h @@ -110,16 +110,17 @@ typedef enum extern UINT8 demo_extradata[MAXPLAYERS]; extern UINT8 demo_writerng; -#define DXD_RESPAWN 0x01 // "respawn" command in console -#define DXD_SKIN 0x02 // skin changed -#define DXD_NAME 0x04 // name changed -#define DXD_COLOR 0x08 // color changed -#define DXD_PLAYSTATE 0x10 // state changed between playing, spectating, or not in-game -#define DXD_FOLLOWER 0x20 // follower was changed +#define DXD_RESPAWN 0x01 // "respawn" command in console +#define DXD_SKIN 0x02 // skin changed +#define DXD_NAME 0x04 // name changed +#define DXD_COLOR 0x08 // color changed +#define DXD_PLAYSTATE 0x10 // state changed between playing, spectating, or not in-game +#define DXD_FOLLOWER 0x20 // follower was changed +#define DXD_WEAPONPREF 0x40 // netsynced playsim settings were changed -#define DXD_PST_PLAYING 0x01 +#define DXD_PST_PLAYING 0x01 #define DXD_PST_SPECTATING 0x02 -#define DXD_PST_LEFT 0x03 +#define DXD_PST_LEFT 0x03 // Record/playback tics void G_ReadDemoExtraData(void); From e4226c9ff92e7418078e9bdc94a0140c80f6498b Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 22 Feb 2021 18:17:50 -0800 Subject: [PATCH 50/50] Fix crash from trying to remove the 17th player when removing bots --- src/k_bot.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/k_bot.c b/src/k_bot.c index 32270b419..126e4cee9 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -237,6 +237,8 @@ void K_UpdateMatchRaceBots(void) while (numbots > wantedbots && i > 0) { + i--; + if (playeringame[i] && players[i].bot) { buf[0] = i; @@ -245,8 +247,6 @@ void K_UpdateMatchRaceBots(void) numbots--; } - - i--; } }