diff --git a/src/d_clisrv.c b/src/d_clisrv.c index ead340d51..5676d1633 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -4739,7 +4739,7 @@ static void FuzzTiccmd(ticcmd_t* target) { target->forwardmove = P_RandomRange(PR_FUZZ, -MAXPLMOVE, MAXPLMOVE); target->turning = P_RandomRange(PR_FUZZ, -KART_FULLTURN, KART_FULLTURN); - target->throwdir = P_RandomRange(PR_FUZZ, -1, 1); + target->throwdir = P_RandomRange(PR_FUZZ, -KART_FULLTURN, KART_FULLTURN); target->buttons = P_RandomRange(PR_FUZZ, 0, 255); // Make fuzzed players more likely to do impactful things @@ -5942,7 +5942,7 @@ static void SV_Maketic(void) for (i = 0; i < MAXPLAYERS; i++) { packetloss[i][maketic%PACKETMEASUREWINDOW] = false; - + if (!playeringame[i]) continue; diff --git a/src/d_player.h b/src/d_player.h index 8847b16b4..9659340ed 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -983,6 +983,8 @@ struct player_t INT16 incontrol; // -1 to -175 when spinning out or tumbling, 1 to 175 when not. Use to check for combo hits or emergency inputs. UINT16 progressivethrust; // When getting beat up in GTR_BUMPERS, speed up the longer you've been out of control. + boolean analoginput; // Has an input been recorded that requires analog usage? For input display. + boolean markedfordeath; boolean dotrickfx; UINT8 bumperinflate; diff --git a/src/g_build_ticcmd.cpp b/src/g_build_ticcmd.cpp index 2bfd10fb7..134c47366 100644 --- a/src/g_build_ticcmd.cpp +++ b/src/g_build_ticcmd.cpp @@ -164,7 +164,7 @@ class TiccmdBuilder cmd->forwardmove = clamp(cmd->forwardmove, MAXPLMOVE); cmd->turning = clamp(cmd->turning, KART_FULLTURN); - cmd->throwdir = clamp(cmd->throwdir, 1); + cmd->throwdir = clamp(cmd->throwdir, KART_FULLTURN); // Send leveltime when this tic was generated to the server for control lag calculations. // Only do this when in a level. Also do this after the hook, so that it can't overwrite this. @@ -343,12 +343,9 @@ class TiccmdBuilder } // But forward/backward IS used for aiming. - // throwdir > 0 throws forward, throwdir < 0 throws backward - // but we always use -1, 0 or 1 for consistency here. - // this allows the throw deadzone to be adjusted in the future without breaking demos - if (std::abs(joystickvector.yaxis) > JOYAXISRANGE / 2) + if (joystickvector.yaxis != 0) { - cmd->throwdir = -std::clamp(joystickvector.yaxis, -1, 1); + cmd->throwdir -= (joystickvector.yaxis * KART_FULLTURN) / JOYAXISRANGE; } } @@ -382,7 +379,7 @@ class TiccmdBuilder kart_analog_input(); // Digital users can input diagonal-back for shallow turns. - // + // // There's probably some principled way of doing this in the gamepad handler itself, // by only applying this filtering to inputs sourced from an axis. This is a little // ugly with the current abstractions, though, and there's a fortunate trick here: diff --git a/src/hud/input-display.cpp b/src/hud/input-display.cpp index abc66752b..1acc0c068 100644 --- a/src/hud/input-display.cpp +++ b/src/hud/input-display.cpp @@ -62,6 +62,7 @@ const char* dpad_suffix(const Vec2& v) void K_DrawInputDisplay(INT32 x, INT32 y, INT32 flags, char mode, UINT8 pid, boolean local, boolean transparent) { const ticcmd_t& cmd = players[displayplayers[pid]].cmd; + const boolean analog = (mode == '4' || mode == '5') ? players[displayplayers[pid]].analoginput : false; const std::string prefix = fmt::format("PR{}", mode); auto gfx = [&](auto format, auto&&... args) { return prefix + fmt::format(format, args...); }; auto but = [&](char key, INT32 gc, UINT32 bt) @@ -81,10 +82,10 @@ void K_DrawInputDisplay(INT32 x, INT32 y, INT32 flags, char mode, UINT8 pid, boo } : Vec2 { -cmd.turning / (float)KART_FULLTURN, - (float)cmd.throwdir, + -cmd.throwdir / (float)KART_FULLTURN, }; - box.patch(gfx("PAD{}", dpad_suffix(dpad))); + box.patch(gfx("PAD{}", analog ? "N" : dpad_suffix(dpad))); box.patch(but('A', gc_a, BT_ACCELERATE)); box.patch(but('B', gc_b, BT_LOOKBACK)); box.patch(but('C', gc_c, BT_SPINDASHMASK)); @@ -99,6 +100,9 @@ void K_DrawInputDisplay(INT32 x, INT32 y, INT32 flags, char mode, UINT8 pid, boo { float dist = (mode == '4') ? 3.f : 2.f; + if (!analog) + dist = 0; + box.patch(gfx("JOY1")); box.xy(dpad.x * dist, -dpad.y * dist).patch(gfx("JOY2")); } diff --git a/src/k_bot.cpp b/src/k_bot.cpp index 90e951cde..65c559943 100644 --- a/src/k_bot.cpp +++ b/src/k_bot.cpp @@ -497,7 +497,7 @@ fixed_t K_BotMapModifier(void) { constexpr INT32 complexity_scale = 10000; constexpr fixed_t modifier_max = FRACUNIT * 2; - + const fixed_t complexity_value = std::clamp( FixedDiv(K_GetTrackComplexity(), complexity_scale), -FixedDiv(FRACUNIT, modifier_max), @@ -1210,10 +1210,10 @@ static void K_BotTrick(const player_t *player, ticcmd_t *cmd, const botcontrolle cmd->turning = -KART_FULLTURN; break; case TMBOTTR_UP: - cmd->throwdir = 1; + cmd->throwdir = KART_FULLTURN; break; case TMBOTTR_DOWN: - cmd->throwdir = -1; + cmd->throwdir = -KART_FULLTURN; break; } } @@ -1304,7 +1304,7 @@ static INT32 K_HandleBotTrack(const player_t *player, ticcmd_t *cmd, botpredicti { turnsign = 1; } - else + else { turnsign = -1; } @@ -1440,7 +1440,7 @@ static INT32 K_HandleBotReverse(const player_t *player, ticcmd_t *cmd, botpredic turnsign = -1; // Turn right anglediff = AngleFixed(angle)>>FRACBITS; } - else + else { turnsign = 1; // Turn left anglediff = 360-(AngleFixed(angle)>>FRACBITS); @@ -1461,7 +1461,7 @@ static INT32 K_HandleBotReverse(const player_t *player, ticcmd_t *cmd, botpredic { momdiff = AngleFixed(angle)>>FRACBITS; } - else + else { momdiff = 360-(AngleFixed(angle)>>FRACBITS); } diff --git a/src/k_botitem.cpp b/src/k_botitem.cpp index b35221433..84baaab6b 100644 --- a/src/k_botitem.cpp +++ b/src/k_botitem.cpp @@ -366,7 +366,7 @@ static boolean K_BotGenericPressItem(const player_t *player, ticcmd_t *cmd, SINT return false; } - cmd->throwdir = std::clamp(static_cast(dir), -1, 1); + cmd->throwdir = KART_FULLTURN * dir; cmd->buttons |= BT_ATTACK; //player->botvars.itemconfirm = 0; return true; @@ -1023,7 +1023,7 @@ static void K_BotItemBallhog(const player_t *player, ticcmd_t *cmd) if (hold == true) { - cmd->throwdir = std::clamp(static_cast(throwdir), -1, 1); + cmd->throwdir = KART_FULLTURN * throwdir; cmd->buttons |= BT_ATTACK; } } diff --git a/src/k_kart.c b/src/k_kart.c index ab61d7cc5..0444d3c11 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3822,14 +3822,14 @@ void K_DoPowerClash(mobj_t *t1, mobj_t *t2) { { t1->player->instashield = 1; t1->player->speedpunt += 20; - lag1 -= min(lag1, t1->player->speedpunt/10); + lag1 -= min(lag1, t1->player->speedpunt/10); } if (t2->player) { t2->player->instashield = 1; t2->player->speedpunt += 20; - lag2 -= min(lag1, t2->player->speedpunt/10); + lag2 -= min(lag1, t2->player->speedpunt/10); } S_StartSound(t1, sfx_parry); @@ -8226,7 +8226,7 @@ static void K_UpdateTripwire(player_t *player) if (triplevel != TRIPWIRE_CONSUME) player->tripwireLeniency = max(player->tripwireLeniency, TRIPWIRETIME); } - + // TRIPWIRE_CONSUME is only applied in very specific cases (currently, riding Garden Top) // and doesn't need leniency; however, it should track leniency from other pass conditions, // so that stripping Garden Top feels consistent. @@ -8575,10 +8575,10 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (P_PlayerInPain(player)) { - player->ringboost = 0; + player->ringboost = 0; } else if (player->ringboost) - { + { // These values can get FUCKED ever since ring-stacking speed changes. // If we're not actively being awarded rings, roll off extreme ringboost durations. if (player->superring == 0) @@ -8603,7 +8603,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->flamedash) { player->flamedash--; - + if (player->flamedash == 0) S_StopSoundByID(player->mo, sfx_fshld1); else if (player->flamedash == 3 && player->curshield == KSHIELD_FLAME) // "Why 3?" We can't blend sounds so this is the best shit I've got @@ -8875,6 +8875,19 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->defenseLockout--; } + UINT16 normalturn = abs(cmd->turning); + UINT16 normalaim = abs(cmd->throwdir); + + if (normalturn != 0 || normalaim != 0) + { + if (normalturn != KART_FULLTURN && normalturn != KART_FULLTURN/2 && normalturn != 0) + player->analoginput = true; + if (normalaim != KART_FULLTURN && normalaim != KART_FULLTURN/2 && normalaim != 0) + player->analoginput = true; + if (normalturn == KART_FULLTURN/2 && normalaim == KART_FULLTURN) + player->analoginput = false; + } + if (player->dotrickfx && !player->mo->hitlag) { int i; @@ -11812,7 +11825,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) UINT32 behind = K_GetItemRouletteDistance(player, player->itemRoulette.playing); UINT32 behindMulti = behind / 500; behindMulti = min(behindMulti, 60); - + UINT32 award = 5*player->ringboxaward + 10; if (!cv_thunderdome.value) @@ -12305,7 +12318,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->ballhogcharge++; if (player->ballhogcharge % BALLHOGINCREMENT == 0) { - sfxenum_t hogsound[] = + sfxenum_t hogsound[] = { sfx_bhog00, sfx_bhog01, @@ -12850,12 +12863,11 @@ void K_MoveKartPlayer(player_t *player, boolean onground) const angle_t angledelta = FixedAngle(36*FRACUNIT); angle_t baseangle = player->mo->angle + angledelta/2; - boolean throwing = cmd->throwdir != 0; - INT16 turnmagnitude = abs(cmd->turning); + INT16 aimingcompare = abs(cmd->throwdir) - abs(cmd->turning); // Uses cmd->turning over steering intentionally. -#define TRICKTHRESHOLD (KART_FULLTURN/4) - if (abs(turnmagnitude) > TRICKTHRESHOLD && !throwing) // side trick +#define TRICKTHRESHOLD (KART_FULLTURN/2) + if (aimingcompare < -TRICKTHRESHOLD) // side trick { S_StartSoundAtVolume(player->mo, sfx_trick0, 255/2); player->dotrickfx = true; @@ -12894,7 +12906,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) P_SetPlayerMobjState(player->mo, S_KART_FAST_LOOK_R); } } - else if (abs(turnmagnitude) <= TRICKTHRESHOLD && throwing) // forward/back trick + else if (aimingcompare > TRICKTHRESHOLD) // forward/back trick { S_StartSoundAtVolume(player->mo, sfx_trick0, 255/2); player->dotrickfx = true; @@ -12965,7 +12977,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (P_MobjWasRemoved(player->trickIndicator) == false) trickcolor = player->trickIndicator->color; - if (player->trickpanel == TRICKSTATE_FORWARD) + if (player->trickpanel == TRICKSTATE_FORWARD) { for (j = 0; j < 2; j++) { diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index bde4e2469..fbd93153a 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -255,6 +255,8 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->justDI); else if (fastcmp(field,"flipDI")) lua_pushboolean(L, plr->flipDI); + else if (fastcmp(field,"analoginput")) + lua_pushboolean(L, plr->analoginput); else if (fastcmp(field,"markedfordeath")) lua_pushboolean(L, plr->markedfordeath); else if (fastcmp(field,"incontrol")) @@ -793,6 +795,8 @@ static int player_set(lua_State *L) plr->incontrol = luaL_checkinteger(L, 3); else if (fastcmp(field,"progressivethrust")) plr->progressivethrust = luaL_checkboolean(L, 3); + else if (fastcmp(field,"analoginput")) + plr->markedfordeath = luaL_checkboolean(L, 3); else if (fastcmp(field,"markedfordeath")) plr->markedfordeath = luaL_checkboolean(L, 3); else if (fastcmp(field,"dotrickfx")) diff --git a/src/p_saveg.c b/src/p_saveg.c index 83ac301ad..8a423f5ec 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -595,6 +595,8 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITEINT16(save->p, players[i].incontrol); WRITEUINT16(save->p, players[i].progressivethrust); + WRITEUINT8(save->p, players[i].analoginput); + WRITEUINT8(save->p, players[i].markedfordeath); WRITEUINT8(save->p, players[i].dotrickfx); WRITEUINT8(save->p, players[i].bumperinflate); @@ -1175,6 +1177,8 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) players[i].incontrol = READINT16(save->p); players[i].progressivethrust = READUINT16(save->p); + players[i].analoginput = READUINT8(save->p); + players[i].markedfordeath = READUINT8(save->p); players[i].dotrickfx = READUINT8(save->p); players[i].bumperinflate = READUINT8(save->p); diff --git a/src/p_user.c b/src/p_user.c index d6fdc3a8b..8b99043a3 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2126,7 +2126,7 @@ static INT16 P_FindClosestTurningForAngle(player_t *player, INT32 targetAngle, I // Slightly frumpy binary search for the ideal turning input. // We do this instead of reversing K_GetKartTurnValue so that future handling changes are automatically accounted for. - + while (attempts++ < 20) // Practical calls of this function search maximum 10 times, this is solely for safety. { // These need to be treated as signed, or situations where boundaries straddle 0 are a mess. @@ -2247,7 +2247,7 @@ static void P_UpdatePlayerAngle(player_t *player) // Corrections via fake turn go through easing. // That means undoing them takes the same amount of time as doing them. // This can lead to oscillating death spiral states on a multi-tic correction, as we swing past the target angle. - // So before we go into death-spirals, if our predicton is _almost_ right... + // So before we go into death-spirals, if our predicton is _almost_ right... angle_t leniency = (4*ANG1/3) * min(player->cmd.latency, 6); // Don't force another turning tic, just give them the desired angle! @@ -2346,7 +2346,7 @@ void P_MovePlayer(player_t *player) ////////////////////// P_UpdatePlayerAngle(player); - + ticruned++; if (!(cmd->flags & TICCMD_RECEIVED)) ticmiss++; @@ -4075,11 +4075,12 @@ void P_PlayerThink(player_t *player) // Save the dir the player is holding // to allow items to be thrown forward or backward. { - if (cmd->throwdir > 0) + const INT16 threshold = 6*KART_FULLTURN/10; + if (cmd->throwdir > threshold) { player->throwdir = 1; } - else if (cmd->throwdir < 0) + else if (cmd->throwdir < -threshold) { player->throwdir = -1; } @@ -4397,7 +4398,7 @@ void P_PlayerThink(player_t *player) { player->stairjank--; } - + // Random skin / "ironman" { UINT32 skinflags = (demo.playback)