From dcd4f377591abe3346e0ef059f23441d2888244f Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 9 Jan 2024 20:37:32 +0000 Subject: [PATCH 01/30] K_BotRubberbandDistance: Don't sniff spectators --- src/k_bot.cpp | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/src/k_bot.cpp b/src/k_bot.cpp index 6f7af8b32..0931a123d 100644 --- a/src/k_bot.cpp +++ b/src/k_bot.cpp @@ -540,21 +540,28 @@ static UINT32 K_BotRubberbandDistance(const player_t *player) continue; } - if (playeringame[i] && players[i].bot) + if (!playeringame[i] || players[i].spectator) { - // First check difficulty levels, then score, then settle it with port priority! - if (player->botvars.difficulty < players[i].botvars.difficulty) - { - pos += 3; - } - else if (player->score < players[i].score) - { - pos += 2; - } - else if (i < portpriority) - { - pos += 1; - } + continue; + } + + if (!players[i].bot) + { + continue; + } + + // First check difficulty levels, then score, then settle it with port priority! + if (player->botvars.difficulty < players[i].botvars.difficulty) + { + pos += 3; + } + else if (player->score < players[i].score) + { + pos += 2; + } + else if (i < portpriority) + { + pos += 1; } } From d94928880a6b4761775dc7962f54b111c00d00c0 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 9 Jan 2024 20:39:55 +0000 Subject: [PATCH 02/30] k_botsearch.cpp: Don't sniff spectators --- src/k_botsearch.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/k_botsearch.cpp b/src/k_botsearch.cpp index 1a4e9cc57..b7a479456 100644 --- a/src/k_botsearch.cpp +++ b/src/k_botsearch.cpp @@ -543,6 +543,7 @@ static BlockItReturn_t K_FindObjectsForNudging(mobj_t *thing) break; case MT_PLAYER: if (thing->player + && !thing->player->spectator && !thing->player->hyudorotimer && !g_nudgeSearch.botmo->player->hyudorotimer) { @@ -902,7 +903,7 @@ static BlockItReturn_t K_FindPlayersToBully(mobj_t *thing) return BMIT_CONTINUE; } - if (!thing->player) + if (!thing->player || thing->player->spectator) { return BMIT_CONTINUE; } From 77e85e08ea0d063c2ea77b3ad5d8ffe9d1f068f4 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 11 Jan 2024 13:49:31 -0800 Subject: [PATCH 03/30] Clouds: always use map scale for vertical bounce --- src/objects/cloud.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/src/objects/cloud.c b/src/objects/cloud.c index b0f011dc2..8f2c88262 100644 --- a/src/objects/cloud.c +++ b/src/objects/cloud.c @@ -157,20 +157,8 @@ void Obj_PlayerCloudThink(player_t *player) if (P_MobjWasRemoved(mo->tracer)) return; - switch(mo->tracer->type) - { - case MT_AHZ_CLOUD: - P_SetObjectMomZ(mo, CLOUDB_ZTHRUST, false); - break; - case MT_AGZ_CLOUD: - mo->momz = FixedMul(mapobjectscale, CLOUD_ZTHRUST * P_MobjFlip(mo->tracer)); - break; - case MT_SSZ_CLOUD: - P_SetObjectMomZ(mo, CLOUD_ZTHRUST, false); - break; - default: - break; - } + mo->momz = FixedMul(mapobjectscale, + (mo->tracer->type == MT_AHZ_CLOUD ? CLOUDB_ZTHRUST : CLOUD_ZTHRUST) * P_MobjFlip(mo->tracer)); player->cloudlaunch = TICRATE; P_InstaThrust(mo, mo->cusval, mo->cvmem); From f8bd70687852af63fdfd33e7119460efacaa691b Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 11 Jan 2024 14:06:49 -0800 Subject: [PATCH 04/30] Clouds: use consistent scale --- src/objects/cloud.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/objects/cloud.c b/src/objects/cloud.c index 8f2c88262..7eeaed95a 100644 --- a/src/objects/cloud.c +++ b/src/objects/cloud.c @@ -42,21 +42,15 @@ void Obj_CloudSpawn(mobj_t *mobj) return; } - if (mobj->type != MT_AGZ_CLOUDCLUSTER) - { - mobj->destscale = mapobjectscale * 4; - P_SetScale(mobj, mobj->destscale); - } + mobj->destscale = mapobjectscale * 4; + P_SetScale(mobj, mobj->destscale); mobj_t *cloud = P_SpawnMobj(mobj->x, mobj->y, mobj->z, cloudtype); angle_t ang = mobj->angle; UINT8 dist = 128; - if (cloudtype == MT_AGZ_CLOUD) - { - cloud->destscale = cloud->scale * 2; - P_SetScale(cloud, cloud->destscale); - } + cloud->destscale = cloud->scale * 2; + P_SetScale(cloud, cloud->destscale); for (UINT8 i = 0; i < 4; i++) { @@ -65,10 +59,11 @@ void Obj_CloudSpawn(mobj_t *mobj) cloud = P_SpawnMobj(x, y, mobj->z, cloudtype); + cloud->destscale = cloud->scale * 2; + P_SetScale(cloud, cloud->destscale); + if (cloudtype == MT_AGZ_CLOUD) { - cloud->destscale = cloud->scale * 2; - P_SetScale(cloud, cloud->destscale); cloud->frame = P_RandomRange(PR_DECORATION, 0, 3); } From 07a4474d4b3df5bf5e4b20fe85dd195300427dec Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Fri, 12 Jan 2024 15:48:01 -0700 Subject: [PATCH 05/30] Allow gamepad reassignment in vote + from joystick input --- src/g_input.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/g_input.c b/src/g_input.c index dffc6d550..4bcd521fe 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -396,9 +396,9 @@ static boolean AutomaticControllerReassignmentIsAllowed(INT32 device) { boolean device_is_gamepad = device > 0; boolean device_is_unassigned = G_GetPlayerForDevice(device) == -1; - boolean gamestate_is_in_level = gamestate == GS_LEVEL; + boolean gamestate_is_in_active_play = (gamestate == GS_LEVEL || gamestate == GS_VOTING); - return device_is_gamepad && device_is_unassigned && gamestate_is_in_level; + return device_is_gamepad && device_is_unassigned && gamestate_is_in_active_play; } static INT32 AssignDeviceToFirstUnassignedPlayer(INT32 device) @@ -564,6 +564,18 @@ void G_MapEventsToControls(event_t *ev) } else { + // We used to only allow this assignment for triggers, but it caused some confusion in vote screen. + // In case of misebhaving devices, break glass. + if (AutomaticControllerReassignmentIsAllowed(ev->device) + && (abs(ev->data2) > JOYAXISRANGE/2 || abs(ev->data3) > JOYAXISRANGE/2)) + { + INT32 assigned = AssignDeviceToFirstUnassignedPlayer(ev->device); + if (assigned >= 0) + { + CONS_Alert(CONS_NOTICE, "Player %d device was reassigned\n", assigned + 1); + } + } + // Actual analog sticks if (ev->data2 != INT32_MAX) { From 4bcdd22e2c587d15f1613052b266d12eaf85f9f7 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 13 Jan 2024 12:34:28 -0800 Subject: [PATCH 06/30] HUD: Battle GOAL uses leading player's color by default --- src/k_hud.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/k_hud.cpp b/src/k_hud.cpp index b71d5a8f6..d1ab57c6f 100644 --- a/src/k_hud.cpp +++ b/src/k_hud.cpp @@ -2224,13 +2224,14 @@ struct PositionFacesInfo void draw_1p(); void draw_4p_battle(int x, int y, INT32 flags); - UINT32 top_score() const { return players[rankplayer[0]].roundscore; } + player_t* top() const { return &players[rankplayer[0]]; } + UINT32 top_score() const { return top()->roundscore; } bool near_goal() const { return g_pointlimit - 5 <= top_score(); } skincolornum_t vomit_color() const { if (!near_goal()) { - return SKINCOLOR_NONE; + return static_cast(top()->skincolor); } constexpr int kCycleSpeed = 4; From 6bf9f994b5736397094920bac001b0b2f0efa82d Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 10 Jan 2024 23:01:44 -0800 Subject: [PATCH 07/30] Revert "HUD: draw tally of party member, not whoever may being spectated" This reverts commit dfd43014c6f8addbb194b5030dd6e778ecd6872f. --- src/k_tally.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/k_tally.cpp b/src/k_tally.cpp index 2c303ea60..b1de6e33e 100644 --- a/src/k_tally.cpp +++ b/src/k_tally.cpp @@ -34,7 +34,6 @@ #include "s_sound.h" #include "st_stuff.h" #include "r_fps.h" -#include "g_party.h" boolean level_tally_t::UseBonuses(void) { @@ -1384,8 +1383,7 @@ void K_TickPlayerTally(player_t *player) void K_DrawPlayerTally(void) { - // Draw the observer player's tally, not whoever they may be spectating - players[G_PartyMember(consoleplayer, R_GetViewNumber())].tally.Draw(); + stplyr->tally.Draw(); } boolean K_PlayerTallyActive(player_t *player) From f9e943b118463822517f86d4a92570c0fefef3e7 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 10 Jan 2024 23:24:08 -0800 Subject: [PATCH 08/30] Set displayplayer to own self when Tally starts --- src/k_tally.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/k_tally.cpp b/src/k_tally.cpp index b1de6e33e..0e868e082 100644 --- a/src/k_tally.cpp +++ b/src/k_tally.cpp @@ -34,6 +34,7 @@ #include "s_sound.h" #include "st_stuff.h" #include "r_fps.h" +#include "g_party.h" boolean level_tally_t::UseBonuses(void) { @@ -550,6 +551,16 @@ void level_tally_t::Init(player_t *player) state = TALLY_ST_IGNORE; delay = 0; } + + if (UINT8 pnum = player - players; G_IsPartyLocal(pnum)) + { + UINT8 view = G_PartyPosition(pnum); + // Battle: if this player's viewpoint has changed + // since being eliminated, set it back so they see + // their own Tally and not someone else's. + displayplayers[view] = pnum; + G_FixCamera(1 + view); + } } void level_tally_t::NewLine(void) From a76507e17ffc4a363479a8496947e011045431cc Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Sat, 13 Jan 2024 20:30:20 -0700 Subject: [PATCH 09/30] Slow down top if player's out of control --- src/d_player.h | 2 ++ src/g_game.c | 2 ++ src/k_kart.c | 25 +++++++++++++++++++++++-- src/k_kart.h | 3 +++ 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 4cb1b1539..70220414b 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -953,6 +953,8 @@ struct player_t UINT8 lastsafelap; + fixed_t topAccel; // Reduced on straight wall collisions to give players extra recovery time + mobj_t *stumbleIndicator; mobj_t *wavedashIndicator; mobj_t *trickIndicator; diff --git a/src/g_game.c b/src/g_game.c index 231b94f18..fdffd4459 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2362,6 +2362,8 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) p->ringvolume = 255; + p->topAccel = MAXTOPACCEL; + p->botvars.rubberband = FRACUNIT; p->spectatorReentry = spectatorReentry; diff --git a/src/k_kart.c b/src/k_kart.c index b17241488..69712001f 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3531,7 +3531,7 @@ fixed_t K_GetKartAccel(const player_t *player) // Marble Garden Top gets 1200% accel if (player->curshield == KSHIELD_TOP) { - k_accel *= 12; + k_accel = FixedMul(k_accel, player->topAccel); } if (K_PodiumSequence() == true) @@ -3651,7 +3651,17 @@ SINT8 K_GetForwardMove(const player_t *player) } else { - forwardmove = MAXPLMOVE; + // forwardmove = MAXPLMOVE; + + UINT8 minmove = MAXPLMOVE/10; + fixed_t assistmove = (MAXPLMOVE - minmove) * FRACUNIT; + + angle_t topdelta = player->mo->angle - K_MomentumAngle(player->mo); + fixed_t topmult = FINECOSINE(topdelta >> ANGLETOFINESHIFT); + topmult = (topmult/2) + (FRACUNIT/2); + assistmove = FixedMul(topmult, assistmove); + + forwardmove = minmove + FixedInt(assistmove); } } @@ -8723,6 +8733,17 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) } } + // Players that bounce far off walls get reduced Top accel, to give them some time to get their bearings. + if ((player->mo->eflags & MFE_JUSTBOUNCEDWALL) && player->curshield == KSHIELD_TOP) + { + angle_t topdelta = player->mo->angle - K_MomentumAngle(player->mo); + fixed_t topmult = FINECOSINE(topdelta >> ANGLETOFINESHIFT); + topmult = (topmult/2) + (FRACUNIT/2); // 0 to original + player->topAccel = FixedMul(topmult, player->topAccel); + } + + player->topAccel = min(player->topAccel + TOPACCELREGEN, MAXTOPACCEL); + if (player->stealingtimer == 0 && player->rocketsneakertimer && onground == true) diff --git a/src/k_kart.h b/src/k_kart.h index 698cec3c5..b1f631044 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -52,6 +52,9 @@ Make sure this matches the actual number of states #define RINGVOLUMEUSEPENALTY 15 #define RINGVOLUMEREGEN 1 +#define MAXTOPACCEL (12*FRACUNIT) +#define TOPACCELREGEN (FRACUNIT/16) + // Mispredicted turns can generate phantom sliptide inputs for a few tics. // Delay the wavedash visuals until we're reasonably sure that it's a deliberate turn. #define HIDEWAVEDASHCHARGE (60) From 98c390cbc55de55ac2f55071c7d39890cda20afe Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Sat, 13 Jan 2024 20:33:00 -0700 Subject: [PATCH 10/30] Expose topAccel to netsave/lua --- src/lua_playerlib.c | 4 ++++ src/p_saveg.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index d873a4f28..ae4d93343 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -345,6 +345,8 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->finalfailsafe); else if (fastcmp(field,"lastsafelap")) lua_pushinteger(L, plr->lastsafelap); + else if (fastcmp(field,"topAccel")) + lua_pushinteger(L, plr->topAccel); else if (fastcmp(field,"instaWhipCharge")) lua_pushinteger(L, plr->instaWhipCharge); else if (fastcmp(field,"defenseLockout")) @@ -865,6 +867,8 @@ static int player_set(lua_State *L) plr->finalfailsafe = luaL_checkinteger(L, 3); else if (fastcmp(field,"lastsafelap")) plr->lastsafelap = luaL_checkinteger(L, 3); + else if (fastcmp(field,"topAccel")) + plr->topAccel = luaL_checkinteger(L, 3); else if (fastcmp(field,"instaWhipCharge")) plr->instaWhipCharge = luaL_checkinteger(L, 3); else if (fastcmp(field,"defenseLockout")) diff --git a/src/p_saveg.c b/src/p_saveg.c index 25252ca02..e1ed123f9 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -571,6 +571,8 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITEUINT8(save->p, players[i].lastsafelap); + WRITEFIXED(save->p, players[i].topAccel); + WRITEMEM(save->p, players[i].public_key, PUBKEYLENGTH); WRITEUINT8(save->p, players[i].instaWhipCharge); @@ -1142,6 +1144,8 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) players[i].lastsafelap = READUINT8(save->p); + players[i].topAccel = READFIXED(save->p); + READMEM(save->p, players[i].public_key, PUBKEYLENGTH); players[i].instaWhipCharge = READUINT8(save->p); From da2e6f1bfefa329b298c6c0de5bc29416c741d8c Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 13 Jan 2024 12:41:57 -0800 Subject: [PATCH 11/30] battlebumpers: let minimum be 0 Useful for testing. --- src/cvars.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cvars.cpp b/src/cvars.cpp index 3c61539a0..f13457d4d 100644 --- a/src/cvars.cpp +++ b/src/cvars.cpp @@ -712,7 +712,7 @@ consvar_t cv_kartbot = UnsavedNetVar("bots", "Off").values({ {13,"Lv.MAX"}, }); -consvar_t cv_kartbumpers = UnsavedNetVar("battlebumpers", "3").min_max(1, 12); +consvar_t cv_kartbumpers = UnsavedNetVar("battlebumpers", "3").min_max(0, 12); void KartEliminateLast_OnChange(void); consvar_t cv_karteliminatelast = UnsavedNetVar("eliminatelast", "Yes").yes_no().onchange(KartEliminateLast_OnChange); From a349b1acf03083eae26883e91e41eb2685b00f37 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 13 Jan 2024 12:52:09 -0800 Subject: [PATCH 12/30] Revert "Add K_UpdateDamageFlashing, refactor Battle 0-flashing tics" This reverts commit 3856fbf1c63259a847346df46e9de00606f922da. --- src/k_kart.c | 19 +++++++------------ src/k_kart.h | 1 - src/p_inter.c | 2 +- 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index b17241488..8a2299b59 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3550,6 +3550,11 @@ UINT16 K_GetKartFlashing(const player_t *player) { UINT16 tics = flashingtics; + if (gametyperules & GTR_BUMPERS) + { + return 0; + } + if (player == NULL) { return tics; @@ -3559,16 +3564,6 @@ UINT16 K_GetKartFlashing(const player_t *player) return tics; } -void K_UpdateDamageFlashing(player_t *player, UINT16 tics) -{ - if (gametyperules & GTR_BUMPERS) - { - return; - } - - player->flashing = tics; -} - boolean K_PlayerShrinkCheat(const player_t *player) { return ( @@ -8396,9 +8391,9 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->spinouttimer != 0) { if (( player->spinouttype & KSPIN_IFRAMES ) == 0) - K_UpdateDamageFlashing(player, 0); + player->flashing = 0; else - K_UpdateDamageFlashing(player, K_GetKartFlashing(player)); + player->flashing = K_GetKartFlashing(player); } if (player->spinouttimer) diff --git a/src/k_kart.h b/src/k_kart.h index 698cec3c5..6b54f9a37 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -192,7 +192,6 @@ fixed_t K_GetKartSpeedFromStat(UINT8 kartspeed); fixed_t K_GetKartSpeed(const player_t *player, boolean doboostpower, boolean dorubberbanding); fixed_t K_GetKartAccel(const player_t *player); UINT16 K_GetKartFlashing(const player_t *player); -void K_UpdateDamageFlashing(player_t *player, UINT16 tics); boolean K_PlayerShrinkCheat(const player_t *player); void K_UpdateShrinkCheat(player_t *player); boolean K_KartKickstart(const player_t *player); diff --git a/src/p_inter.c b/src/p_inter.c index 53561406c..c0001e4c8 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3341,7 +3341,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da if (type != DMG_STUMBLE && type != DMG_WHUMBLE) { if (type != DMG_STING) - K_UpdateDamageFlashing(player, K_GetKartFlashing(player)); + player->flashing = K_GetKartFlashing(player); player->ringburst += ringburst; From 57c501f6ee2e67cbdbc576ec24e6fa5cad297db4 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 13 Jan 2024 12:54:43 -0800 Subject: [PATCH 13/30] Revert "0 flashtics in Battle" This reverts commit 79eb400f494cd9736e36e35b664fef11ab49f61e. --- src/k_kart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index 8a2299b59..095d5cfdd 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3552,7 +3552,7 @@ UINT16 K_GetKartFlashing(const player_t *player) if (gametyperules & GTR_BUMPERS) { - return 0; + return 1; } if (player == NULL) From 92cd95311c113305f0e410b729ff8f914ebc6b42 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 13 Jan 2024 13:07:02 -0800 Subject: [PATCH 14/30] Add P_IsKartItem: true for anything the player can hold or throw (except shield overlays) --- src/p_mobj.c | 33 +++++++++++++++++++++++++++++++++ src/p_mobj.h | 1 + 2 files changed, 34 insertions(+) diff --git a/src/p_mobj.c b/src/p_mobj.c index f1d393afc..517434f17 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -5317,6 +5317,39 @@ cont: // Kartitem stuff. +// These are held/thrown by players. +boolean P_IsKartItem(INT32 type) +{ + switch (type) + { + case MT_POGOSPRING: + case MT_EGGMANITEM: + case MT_EGGMANITEM_SHIELD: + case MT_BANANA: + case MT_BANANA_SHIELD: + case MT_ORBINAUT: + case MT_ORBINAUT_SHIELD: + case MT_JAWZ: + case MT_JAWZ_SHIELD: + case MT_SSMINE: + case MT_SSMINE_SHIELD: + case MT_LANDMINE: + case MT_DROPTARGET: + case MT_DROPTARGET_SHIELD: + case MT_BALLHOG: + case MT_SPB: + case MT_BUBBLESHIELDTRAP: + case MT_GARDENTOP: + case MT_HYUDORO: + case MT_SINK: + case MT_GACHABOM: + return true; + + default: + return false; + } +} + // This item is never attached to a player -- it can DIE // unconditionally in death sectors. boolean P_IsKartFieldItem(INT32 type) diff --git a/src/p_mobj.h b/src/p_mobj.h index dabdafe51..1e429aa26 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -540,6 +540,7 @@ void P_InitCachedActions(void); void P_RunCachedActions(void); void P_AddCachedAction(mobj_t *mobj, INT32 statenum); +boolean P_IsKartItem(INT32 type); boolean P_IsKartFieldItem(INT32 type); boolean K_IsMissileOrKartItem(mobj_t *mo); boolean P_CanDeleteKartItem(INT32 type); From 9fa7cb096b19087819318c565b7a1ec4bc3ddf82 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 13 Jan 2024 13:16:58 -0800 Subject: [PATCH 15/30] P_DamageMobj: items and PvP damage bypass flashing tics if the victim is in a damage state --- src/p_inter.c | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/src/p_inter.c b/src/p_inter.c index c0001e4c8..a36f74262 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2812,6 +2812,34 @@ static void AddNullHitlag(player_t *player, tic_t oldHitlag) } } +static boolean P_FlashingException(const player_t *player, const mobj_t *inflictor) +{ + if (!inflictor) + { + // Sector damage always behaves the same. + return false; + } + + if (!P_IsKartItem(inflictor->type) && inflictor->type != MT_PLAYER) + { + // Exception only applies to player items. + // Also applies to players because of PvP collision. + // Lightning Shield also uses the player object as inflictor. + return false; + } + + if (!P_PlayerInPain(player)) + { + // Flashing tics is sometimes used in a way unrelated to damage. + // E.g. picking up a power-up gives you flashing tics. + // Respect this usage of flashing tics. + return false; + } + + // Flashing tics are ignored. + return true; +} + /** Damages an object, which may or may not be a player. * For melee attacks, source and inflictor are the same. * @@ -3176,7 +3204,12 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da } // DMG_EXPLODE excluded from flashtic checks to prevent dodging eggbox/SPB with weak spinout - if ((target->hitlag == 0 || allowcombo == false) && player->flashing > 0 && type != DMG_EXPLODE && type != DMG_STUMBLE && type != DMG_WHUMBLE) + if ((target->hitlag == 0 || allowcombo == false) && + player->flashing > 0 && + type != DMG_EXPLODE && + type != DMG_STUMBLE && + type != DMG_WHUMBLE && + P_FlashingException(player, inflictor) == false) { // Post-hit invincibility K_DoInstashield(player); From fd7eb42e9d6358a257ce2fbc2e75f4b7ba23c10b Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 13 Jan 2024 14:31:15 -0800 Subject: [PATCH 16/30] Vote: fix Encore appearing on Battle, if gametype was changed --- src/d_netcmd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index b950aec95..165d8ca84 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2194,6 +2194,8 @@ void D_MapChange(UINT16 mapnum, INT32 newgametype, boolean pencoremode, boolean void D_SetupVote(INT16 newgametype) { + const UINT32 rules = gametypes[newgametype]->rules; + UINT8 buf[(VOTE_NUM_LEVELS * 2) + 4]; UINT8 *p = buf; @@ -2203,7 +2205,7 @@ void D_SetupVote(INT16 newgametype) memset(votebuffer, UINT16_MAX, sizeof(votebuffer)); WRITEINT16(p, newgametype); - WRITEUINT8(p, ((cv_kartencore.value == 1) && (gametyperules & GTR_ENCORE))); + WRITEUINT8(p, ((cv_kartencore.value == 1) && (rules & GTR_ENCORE))); WRITEUINT8(p, G_SometimesGetDifferentEncore()); for (i = 0; i < VOTE_NUM_LEVELS; i++) From db4e2e692b18ff06e060a3b21bc60c2193cd0415 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 13 Jan 2024 14:32:07 -0800 Subject: [PATCH 17/30] Add LobbySize option to level headers, controls whether the map appears in vote, based on player count - Prevents a map from appearing on the vote screen if there are too many players - LobbySize - Duel - 2 players max - Small - 5 players max - Medium - 10 players max - Large - 16 players max (default if not set) - Future proofing - Doesn't count bot players in gametypes that don't support bots --- src/d_netcmd.c | 25 +++++++++++++++++++++++-- src/deh_soc.c | 23 +++++++++++++++++++++++ src/doomstat.h | 1 + src/g_game.c | 13 ++++++++++++- src/g_game.h | 1 + src/p_setup.cpp | 1 + 6 files changed, 61 insertions(+), 3 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 165d8ca84..a4f52e383 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2208,13 +2208,34 @@ void D_SetupVote(INT16 newgametype) WRITEUINT8(p, ((cv_kartencore.value == 1) && (rules & GTR_ENCORE))); WRITEUINT8(p, G_SometimesGetDifferentEncore()); + UINT8 numPlayers = 0; + + for (i = 0; i < MAXPLAYERS; ++i) + { + if (!playeringame[i] || players[i].spectator) + { + continue; + } + + extern consvar_t cv_forcebots; // debug + + if (!(rules & GTR_BOTS) && players[i].bot && !cv_forcebots.value) + { + // Gametype doesn't support bots + continue; + } + + numPlayers++; + } + for (i = 0; i < VOTE_NUM_LEVELS; i++) { - UINT16 m = G_RandMap( + UINT16 m = G_RandMapPerPlayerCount( G_TOLFlag(newgametype), prevmap, false, (i < VOTE_NUM_LEVELS-1), - votebuffer + votebuffer, + numPlayers ); votebuffer[i] = m; WRITEUINT16(p, m); diff --git a/src/deh_soc.c b/src/deh_soc.c index 9ceb61f95..9d9ff8bf3 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -1417,6 +1417,29 @@ void readlevelheader(MYFILE *f, char * name) mapheaderinfo[num]->destroyforchallenge_size = j; } } + else if (fastcmp(word, "LOBBYSIZE")) + { + if (fastcmp(word2, "DUEL")) + { + mapheaderinfo[num]->playerLimit = 2; + } + else if (fastcmp(word2, "SMALL")) + { + mapheaderinfo[num]->playerLimit = 5; + } + else if (fastcmp(word2, "MEDIUM")) + { + mapheaderinfo[num]->playerLimit = 10; + } + else if (fastcmp(word2, "LARGE")) + { + mapheaderinfo[num]->playerLimit = 16; + } + else + { + deh_warning("Level header %d: invalid lobby size '%s'", num, word2); + } + } else deh_warning("Level header %d: unknown word '%s'", num, word); } diff --git a/src/doomstat.h b/src/doomstat.h index 5247ea082..333bfd6f0 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -501,6 +501,7 @@ struct mapheader_t UINT8 levelselect; ///< Is this map available in the level select? If so, which map list is it available in? UINT16 menuflags; ///< LF2_flags: options that affect record attack menus + UINT8 playerLimit; ///< This map does not appear in multiplayer vote if there are too many players // Operational metadata UINT16 levelflags; ///< LF_flags: merged booleans into one UINT16 for space, see below diff --git a/src/g_game.c b/src/g_game.c index 35161cb79..457062058 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3499,7 +3499,7 @@ static UINT16 *g_allowedMaps = NULL; static size_t g_randMapStack = 0; #endif -UINT16 G_RandMap(UINT32 tolflags, UINT16 pprevmap, boolean ignoreBuffers, boolean callAgainSoon, UINT16 *extBuffer) +UINT16 G_RandMapPerPlayerCount(UINT32 tolflags, UINT16 pprevmap, boolean ignoreBuffers, boolean callAgainSoon, UINT16 *extBuffer, UINT8 numPlayers) { INT32 allowedMapsCount = 0; INT32 extBufferCount = 0; @@ -3558,6 +3558,12 @@ tryAgain: continue; } + if (numPlayers > mapheaderinfo[i]->playerLimit) + { + // Too many players for this map. + continue; + } + // Only care about restrictions if the host is a listen server. if (!dedicated) { @@ -3665,6 +3671,11 @@ tryAgain: return ret; } +UINT16 G_RandMap(UINT32 tolflags, UINT16 pprevmap, boolean ignoreBuffers, boolean callAgainSoon, UINT16 *extBuffer) +{ + return G_RandMapPerPlayerCount(tolflags, pprevmap, ignoreBuffers, callAgainSoon, extBuffer, 0); +} + void G_AddMapToBuffer(UINT16 map) { if (mapheaderinfo[map]->justPlayed == 0) // Started playing a new map. diff --git a/src/g_game.h b/src/g_game.h index d1378ce30..4f08804c6 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -277,6 +277,7 @@ FUNCMATH INT32 G_TicsToMilliseconds(tic_t tics); UINT32 G_TOLFlag(INT32 pgametype); UINT16 G_GetFirstMapOfGametype(UINT16 pgametype); +UINT16 G_RandMapPerPlayerCount(UINT32 tolflags, UINT16 pprevmap, boolean ignoreBuffers, boolean callAgainSoon, UINT16 *extBuffer, UINT8 numPlayers); UINT16 G_RandMap(UINT32 tolflags, UINT16 pprevmap, boolean ignoreBuffers, boolean callAgainSoon, UINT16 *extBuffer); void G_AddMapToBuffer(UINT16 map); diff --git a/src/p_setup.cpp b/src/p_setup.cpp index a1af94db5..604f29b06 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -457,6 +457,7 @@ static void P_ClearSingleMapHeaderInfo(INT16 num) mapheaderinfo[num]->levelselect = 0; mapheaderinfo[num]->levelflags = 0; mapheaderinfo[num]->menuflags = 0; + mapheaderinfo[num]->playerLimit = MAXPLAYERS; mapheaderinfo[num]->mobj_scale = FRACUNIT; mapheaderinfo[num]->default_waypoint_radius = 0; P_ClearMapHeaderLighting(&mapheaderinfo[num]->lighting); From 5ec2e156ab13b63aaa78061349cd53e267f74078 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 13 Jan 2024 15:15:28 -0800 Subject: [PATCH 18/30] Battle: fix viewpoint switching to eliminated player --- src/g_game.c | 3 ++- src/k_director.cpp | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 457062058..cf3bc74e2 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1526,7 +1526,8 @@ boolean G_CouldView(INT32 playernum) // boolean G_CanView(INT32 playernum, UINT8 viewnum, boolean onlyactive) { - if (!playeringame[playernum] || players[playernum].spectator) + // PF_ELIMINATED: Battle Overtime Barrier killed this player + if (!playeringame[playernum] || players[playernum].spectator || (players[playernum].pflags & PF_ELIMINATED)) { return false; } diff --git a/src/k_director.cpp b/src/k_director.cpp index 118786d63..93f3ea47d 100644 --- a/src/k_director.cpp +++ b/src/k_director.cpp @@ -112,7 +112,9 @@ struct DirectorInfo } // pair finished? try the next one - if (players[playerstat[targetposition].sorted].exiting) + if (players[playerstat[targetposition].sorted].exiting || + // Battle: player was killed by Overtime Barrier + (players[playerstat[targetposition].sorted].pflags & PF_ELIMINATED)) { continue; } From 3c85a9a4365bed4b33da59756e5748798f2bfcd2 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 13 Jan 2024 15:44:29 -0800 Subject: [PATCH 19/30] Director: let it switch to splitscreen players --- src/k_director.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/k_director.cpp b/src/k_director.cpp index 93f3ea47d..308b30bca 100644 --- a/src/k_director.cpp +++ b/src/k_director.cpp @@ -139,12 +139,6 @@ struct DirectorInfo break; } - // if this is a splitscreen player, try next pair - if (P_IsDisplayPlayer(&players[target])) - { - continue; - } - // if we're certain the back half of the pair is actually in this position, try to switch if (!players[target].positiondelay) { From dd1db7cd4ad63c2945323b24afc56e6b8c696115 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 13 Jan 2024 15:46:06 -0800 Subject: [PATCH 20/30] Reset viewpoint to self when you spawn --- src/p_mobj.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 517434f17..b4634563c 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -12972,19 +12972,20 @@ void P_SpawnPlayer(INT32 playernum) if (G_IsPartyLocal(playernum)) { - // Spectating always enables director cam. If there - // is no one to view, this will do nothing. If - // someone enters the game later, it will - // automatically switch to that player. - K_ToggleDirector(G_PartyPosition(playernum), p->spectator); - // Spectators can switch to freecam. This should be // disabled when they enter the race, or when the level // changes. if (!demo.playback) { camera[G_PartyPosition(playernum)].freecam = false; + displayplayers[G_PartyPosition(playernum)] = playernum; } + + // Spectating always enables director cam. If there + // is no one to view, this will do nothing. If + // someone enters the game later, it will + // automatically switch to that player. + K_ToggleDirector(G_PartyPosition(playernum), p->spectator); } else if (pcount == 1 && !p->spectator) { From 99a2a3fb74b4067a6b68d82fc474e8f42fcb00e7 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 13 Jan 2024 16:31:54 -0800 Subject: [PATCH 21/30] Let Bubble blow-up destroy any MF_SHOOTABLE object --- src/k_collide.cpp | 11 ---------- src/p_map.c | 55 +++++++++++++++++++++++++++++++---------------- 2 files changed, 37 insertions(+), 29 deletions(-) diff --git a/src/k_collide.cpp b/src/k_collide.cpp index 38e69c8e4..d10dd845f 100644 --- a/src/k_collide.cpp +++ b/src/k_collide.cpp @@ -745,17 +745,6 @@ void K_LightningShieldAttack(mobj_t *actor, fixed_t size) boolean K_BubbleShieldCollide(mobj_t *t1, mobj_t *t2) { - if (t1->type == MT_PLAYER) - { - // Bubble Shield already has a hitbox, and it gets - // teleported every tic so the Bubble itself will - // always make contact with other objects. - // - // Therefore, we don't need a second, smaller hitbox - // on the player. It'll just cause unwanted hitlag. - return true; - } - if (t2->type == MT_PLAYER) { // Counter desyncs diff --git a/src/p_map.c b/src/p_map.c index 1f64946a3..782028790 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -522,6 +522,17 @@ static void P_DoFanAndGasJet(mobj_t *spring, mobj_t *object) } } +static boolean P_BubbleCanReflect(mobj_t *t1, mobj_t *t2) +{ + return (t2->type == MT_ORBINAUT || t2->type == MT_JAWZ || t2->type == MT_GACHABOM + || t2->type == MT_BANANA || t2->type == MT_EGGMANITEM || t2->type == MT_BALLHOG + || t2->type == MT_SSMINE || t2->type == MT_LANDMINE || t2->type == MT_SINK + || t2->type == MT_GARDENTOP + || t2->type == MT_DROPTARGET + || t2->type == MT_KART_LEFTOVER + || (t2->type == MT_PLAYER && t1->target != t2)); +} + // // PIT_CheckThing // @@ -994,15 +1005,8 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) return BMIT_CONTINUE; // Bubble Shield reflect - if (((thing->type == MT_BUBBLESHIELD && thing->target->player && thing->target->player->bubbleblowup) + if ((thing->type == MT_BUBBLESHIELD && thing->target->player && thing->target->player->bubbleblowup) || (thing->player && thing->player->bubbleblowup)) - && (tm.thing->type == MT_ORBINAUT || tm.thing->type == MT_JAWZ || tm.thing->type == MT_GACHABOM - || tm.thing->type == MT_BANANA || tm.thing->type == MT_EGGMANITEM || tm.thing->type == MT_BALLHOG - || tm.thing->type == MT_SSMINE || tm.thing->type == MT_LANDMINE || tm.thing->type == MT_SINK - || tm.thing->type == MT_GARDENTOP - || tm.thing->type == MT_DROPTARGET - || tm.thing->type == MT_KART_LEFTOVER - || (tm.thing->type == MT_PLAYER && thing->target != tm.thing))) { // see if it went over / under if (tm.thing->z > thing->z + thing->height) @@ -1010,17 +1014,21 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) if (tm.thing->z + tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_BubbleShieldCollide(thing, tm.thing) ? BMIT_CONTINUE : BMIT_ABORT; + if (P_BubbleCanReflect(thing, tm.thing)) + { + // don't let player hitbox touch it too + if (thing->player) + return BMIT_CONTINUE; + return K_BubbleShieldCollide(thing, tm.thing) ? BMIT_CONTINUE : BMIT_ABORT; + } + else if ((tm.thing->flags & MF_SHOOTABLE) && !thing->player) + { + P_DamageMobj(tm.thing, thing, thing->target, 1, DMG_NORMAL); + return BMIT_CONTINUE; + } } - else if (((tm.thing->type == MT_BUBBLESHIELD && tm.thing->target->player && tm.thing->target->player->bubbleblowup) + else if ((tm.thing->type == MT_BUBBLESHIELD && tm.thing->target->player && tm.thing->target->player->bubbleblowup) || (tm.thing->player && tm.thing->player->bubbleblowup)) - && (thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_GACHABOM - || thing->type == MT_BANANA || thing->type == MT_EGGMANITEM || thing->type == MT_BALLHOG - || thing->type == MT_SSMINE || thing->type == MT_LANDMINE || thing->type == MT_SINK - || thing->type == MT_GARDENTOP - || thing->type == MT_DROPTARGET - || thing->type == MT_KART_LEFTOVER - || (thing->type == MT_PLAYER && tm.thing->target != thing))) { // see if it went over / under if (tm.thing->z > thing->z + thing->height) @@ -1028,7 +1036,18 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) if (tm.thing->z + tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_BubbleShieldCollide(tm.thing, thing) ? BMIT_CONTINUE : BMIT_ABORT; + if (P_BubbleCanReflect(tm.thing, thing)) + { + // don't let player hitbox touch it too + if (tm.thing->player) + return BMIT_CONTINUE; + return K_BubbleShieldCollide(tm.thing, thing) ? BMIT_CONTINUE : BMIT_ABORT; + } + else if ((thing->flags & MF_SHOOTABLE) && !tm.thing->player) + { + P_DamageMobj(thing, tm.thing, tm.thing->target, 1, DMG_NORMAL); + return BMIT_CONTINUE; + } } // double make sure bubbles won't collide with anything else From 26b03a810c237a334015fba49c9e227e806e464c Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 13 Jan 2024 16:54:20 -0800 Subject: [PATCH 22/30] HUD: fix GOAL not turning rainbow if point limit is less than 5 --- src/k_hud.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/k_hud.cpp b/src/k_hud.cpp index d1ab57c6f..17b396872 100644 --- a/src/k_hud.cpp +++ b/src/k_hud.cpp @@ -2226,7 +2226,13 @@ struct PositionFacesInfo player_t* top() const { return &players[rankplayer[0]]; } UINT32 top_score() const { return top()->roundscore; } - bool near_goal() const { return g_pointlimit - 5 <= top_score(); } + + bool near_goal() const + { + constexpr tic_t kThreshold = 5; + return std::max(kThreshold, g_pointlimit) - kThreshold <= top_score(); + } + skincolornum_t vomit_color() const { if (!near_goal()) From 92f6e61243b7da1885930900bf6b047daa76404c Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 13 Jan 2024 16:59:12 -0800 Subject: [PATCH 23/30] Battle: downscale hitlag VFX and Gahabom explosion (not in Prisons) - Hitlag VFX: 3/4x - Gachabom explosion: 1/2x --- src/k_hitlag.c | 6 ++++++ src/objects/gachabom-rebound.cpp | 6 +++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/k_hitlag.c b/src/k_hitlag.c index 3f1a3afad..e211e90c0 100644 --- a/src/k_hitlag.c +++ b/src/k_hitlag.c @@ -14,6 +14,7 @@ #include "doomdef.h" #include "doomstat.h" +#include "k_battle.h" #include "k_kart.h" #include "m_random.h" #include "p_local.h" @@ -195,6 +196,11 @@ static void K_SpawnHitLagEFX(mobj_t *victim, mobj_t *inflictor, mobj_t *source, newScale = 3 * victim->destscale; } + if ((gametyperules & GTR_BUMPERS) && battleprisons == false) + { + newScale = 3 * newScale / 4; + } + if (P_MobjWasRemoved(source) == false) { color = (source->player != NULL) ? source->player->skincolor : source->color; diff --git a/src/objects/gachabom-rebound.cpp b/src/objects/gachabom-rebound.cpp index 9c12ba0ad..91e1f23c5 100644 --- a/src/objects/gachabom-rebound.cpp +++ b/src/objects/gachabom-rebound.cpp @@ -1,6 +1,7 @@ #include #include "../d_player.h" +#include "../k_battle.h" #include "../k_objects.h" #include "../m_fixed.h" #include "../info.h" @@ -230,7 +231,10 @@ void Obj_SpawnGachaBomRebound(mobj_t* source, mobj_t* target) x->color = target->color; x->angle = angle; - P_InstaScale(x, 2 * x->scale); + if (!(gametyperules & GTR_BUMPERS) || battleprisons) + { + P_InstaScale(x, 2 * x->scale); + } rebound_mode(x) = static_cast(mode); rebound_timer(x) = kReboundAcceptPause; From 9e650fa6c022483e727dc3ce0e1915c67a8fc60e Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 13 Jan 2024 17:30:16 -0800 Subject: [PATCH 24/30] Guard: reflect items like Bubble - Clash + player knockback --- src/k_collide.cpp | 5 +++++ src/p_map.c | 21 +++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/k_collide.cpp b/src/k_collide.cpp index d10dd845f..c9dd7085b 100644 --- a/src/k_collide.cpp +++ b/src/k_collide.cpp @@ -771,6 +771,11 @@ boolean K_BubbleShieldCollide(mobj_t *t1, mobj_t *t2) { if (!t2->threshold || t2->type == MT_DROPTARGET) { + if (t1->player && K_PlayerGuard(t1->player)) + { + K_KartSolidBounce(t1, t2); + K_DoPowerClash(t1, t2); + } if (!t2->momx && !t2->momy) { t2->momz += (24*t2->scale) * P_MobjFlip(t2); diff --git a/src/p_map.c b/src/p_map.c index 782028790..95e509cca 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -1004,6 +1004,27 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) if (tm.thing->type == MT_RANDOMITEM) return BMIT_CONTINUE; + if (tm.thing->type != MT_PLAYER && thing->player && K_PlayerGuard(thing->player) && P_BubbleCanReflect(thing, tm.thing)) + { + // see if it went over / under + if (tm.thing->z > thing->z + thing->height) + return BMIT_CONTINUE; // overhead + if (tm.thing->z + tm.thing->height < thing->z) + return BMIT_CONTINUE; // underneath + + return K_BubbleShieldCollide(thing, tm.thing) ? BMIT_CONTINUE : BMIT_ABORT; + } + else if (thing->type != MT_PLAYER && tm.thing->player && K_PlayerGuard(tm.thing->player) && P_BubbleCanReflect(tm.thing, thing)) + { + // see if it went over / under + if (tm.thing->z > thing->z + thing->height) + return BMIT_CONTINUE; // overhead + if (tm.thing->z + tm.thing->height < thing->z) + return BMIT_CONTINUE; // underneath + + return K_BubbleShieldCollide(tm.thing, thing) ? BMIT_CONTINUE : BMIT_ABORT; + } + // Bubble Shield reflect if ((thing->type == MT_BUBBLESHIELD && thing->target->player && thing->target->player->bubbleblowup) || (thing->player && thing->player->bubbleblowup)) From f8f2c51a8d810e2618dd7e9a852f3b9c2d4130d6 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 13 Jan 2024 17:43:48 -0800 Subject: [PATCH 25/30] Bubble/Guard: reflect strength 4x -> 6x --- src/k_collide.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/k_collide.cpp b/src/k_collide.cpp index c9dd7085b..30cdf5745 100644 --- a/src/k_collide.cpp +++ b/src/k_collide.cpp @@ -782,9 +782,9 @@ boolean K_BubbleShieldCollide(mobj_t *t1, mobj_t *t2) } else { - t2->momx = -4*t2->momx; - t2->momy = -4*t2->momy; - t2->momz = -4*t2->momz; + t2->momx = -6*t2->momx; + t2->momy = -6*t2->momy; + t2->momz = -6*t2->momz; t2->angle += ANGLE_180; } if (t2->type == MT_JAWZ) From 9af09ec5076a67d35df1141331be71ced47b41dd Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 13 Jan 2024 18:38:33 -0800 Subject: [PATCH 26/30] Bubble/Guard: fix reflected item intangibility, transfer ownership of reflected items - Ignores item just-thrown intangibility only if the item owner is the same (standard behavior) - Player who reflected the item takes ownership of it - Required to make intangibility work correctly - Improvement to game design --- src/k_collide.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/k_collide.cpp b/src/k_collide.cpp index 30cdf5745..afc72e998 100644 --- a/src/k_collide.cpp +++ b/src/k_collide.cpp @@ -769,7 +769,9 @@ boolean K_BubbleShieldCollide(mobj_t *t1, mobj_t *t2) } else { - if (!t2->threshold || t2->type == MT_DROPTARGET) + mobj_t *owner = t1->player ? t1 : t1->target; + + if (t2->target != owner || !t2->threshold || t2->type == MT_DROPTARGET) { if (t1->player && K_PlayerGuard(t1->player)) { @@ -789,6 +791,7 @@ boolean K_BubbleShieldCollide(mobj_t *t1, mobj_t *t2) } if (t2->type == MT_JAWZ) P_SetTarget(&t2->tracer, t2->target); // Back to the source! + P_SetTarget(&t2->target, owner); // Let the source reflect it back again! t2->threshold = 10; S_StartSound(t1, sfx_s3k44); } From ce1fe0028a05e69f8f8f41a1a4b6a94dec7723d7 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 13 Jan 2024 19:17:57 -0800 Subject: [PATCH 27/30] Insta-Whip: respect flashing tics unless player is in damage state - Matches new flashing tics behavior --- src/k_collide.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/k_collide.cpp b/src/k_collide.cpp index afc72e998..b9fc3c391 100644 --- a/src/k_collide.cpp +++ b/src/k_collide.cpp @@ -822,8 +822,7 @@ boolean K_InstaWhipCollide(mobj_t *shield, mobj_t *victim) { player_t *victimPlayer = victim->player; - //if (victim != attacker && !P_PlayerInPain(victimPlayer) && victimPlayer->flashing == 0) - if (victim != attacker && victim->hitlag == 0) + if (victim != attacker && (P_PlayerInPain(victimPlayer) ? victim->hitlag == 0 : victimPlayer->flashing == 0)) { // If both players have a whip, hits are order-of-execution dependent and that sucks. // Player expectation is a clash here. From 9c7e8b8be33aec982207fac4d54734908bfddf16 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 13 Jan 2024 20:00:14 -0800 Subject: [PATCH 28/30] Battle: cap point limit at 20 --- src/k_kart.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/k_kart.c b/src/k_kart.c index 095d5cfdd..6e5434a85 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -13328,6 +13328,11 @@ UINT32 K_PointLimitForGametype(void) ptsCap += 4; } } + + if (ptsCap > 20) + { + ptsCap = 20; + } } return ptsCap; From bb2affc484f72a100dfcb9da687fa5fd01988b36 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 13 Jan 2024 20:23:35 -0800 Subject: [PATCH 29/30] Battle: base PWR level on correct score value --- src/k_pwrlv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_pwrlv.c b/src/k_pwrlv.c index 0a15b6c9b..4d7bc80e4 100644 --- a/src/k_pwrlv.c +++ b/src/k_pwrlv.c @@ -131,7 +131,7 @@ INT16 K_PowerLevelPlacementScore(player_t *player) } else { - return player->score; + return player->roundscore; } } From 2213386498aff7bb79ecd4bf546a48b022dd31be Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 13 Jan 2024 20:44:24 -0800 Subject: [PATCH 30/30] HUD: fix 1P Battle GOAL offset in Duel --- src/k_hud.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/k_hud.cpp b/src/k_hud.cpp index 17b396872..7afd5a493 100644 --- a/src/k_hud.cpp +++ b/src/k_hud.cpp @@ -2315,7 +2315,11 @@ void PositionFacesInfo::draw_1p() UINT32 skinflags; if (gametyperules & GTR_POINTLIMIT) // playing battle - Y += (9*5) - 5; // <-- arbitrary calculation + { + Y += 40; + if (ranklines < 3) + Y -= 18; + } else if (ranklines < 5) Y += (9*ranklines); else