From 8c28b094a19c0c6926851f77dfecdbdac846e11d Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Thu, 20 Jan 2022 15:23:32 -0600 Subject: [PATCH] general post-review unfuck --- src/k_director.c | 254 +++++++++++++++++++++++++++++++++-------------- src/k_director.h | 13 +++ src/k_kart.c | 7 +- src/p_setup.c | 3 + 4 files changed, 198 insertions(+), 79 deletions(-) diff --git a/src/k_director.c b/src/k_director.c index 0dc33c140..d3b2ce7bd 100644 --- a/src/k_director.c +++ b/src/k_director.c @@ -12,13 +12,14 @@ #include "d_netcmd.h" #include "p_local.h" -#define SWITCHTIME TICRATE*5 // cooldown between unforced switches -#define BOREDOMTIME 3*TICRATE/2 // how long until players considered far apart? -#define TRANSFERTIME TICRATE // how long to delay reaction shots? -#define BREAKAWAYDIST 4000 // how *far* until players considered far apart? -#define WALKBACKDIST 600 // how close should a trailing player be before we switch? -#define PINCHDIST 30000 // how close should the leader be to be considered "end of race"? +#define SWITCHTIME TICRATE * 5 // cooldown between unforced switches +#define BOREDOMTIME 3 * TICRATE / 2 // how long until players considered far apart? +#define TRANSFERTIME TICRATE // how long to delay reaction shots? +#define BREAKAWAYDIST 4000 // how *far* until players considered far apart? +#define WALKBACKDIST 600 // how close should a trailing player be before we switch? +#define PINCHDIST 30000 // how close should the leader be to be considered "end of race"? +void K_InitDirector(void); void K_UpdateDirectorPositions(void); boolean K_CanSwitchDirector(void); fixed_t K_GetFinishGap(INT32 leader, INT32 follower); @@ -27,173 +28,274 @@ void K_DirectorFollowAttack(player_t *player, mobj_t *inflictor, mobj_t *source) void K_UpdateDirector(void); void K_DirectorForceSwitch(INT32 player, INT32 time); -INT32 cooldown = 0; // how long has it been since we last switched? -INT32 freeze = 0; // when nonzero, fixed switch pending, freeze logic! -INT32 attacker = 0; // who to switch to when freeze delay elapses -INT32 maxdist = 0; // how far is the closest player from finishing? +struct directorinfo directorinfo; -INT32 sortedplayers[MAXPLAYERS] = {0}; // position-1 goes in, player index comes out. -INT32 gap[MAXPLAYERS] = {0}; // gap between a given position and their closest pursuer -INT32 boredom[MAXPLAYERS] = {0}; // how long has a given position had no credible attackers? - -fixed_t K_GetFinishGap(INT32 leader, INT32 follower) { - fixed_t dista = players[follower].distancetofinish; - fixed_t distb = players[leader].distancetofinish; - if (players[follower].position < players[leader].position) { - return distb-dista; - } else { - return dista-distb; - } -} - -void K_UpdateDirectorPositions(void) { +void K_InitDirector(void) +{ INT32 playernum; - memset(sortedplayers, -1, sizeof(sortedplayers)); - for (playernum = 0; playernum < MAXPLAYERS; ++playernum) { - if (playeringame[playernum]) - sortedplayers[players[playernum].position-1] = playernum; - } + directorinfo.cooldown = SWITCHTIME; + directorinfo.freeze = 0; + directorinfo.attacker = 0; + directorinfo.maxdist = 0; - memset(gap, INT32_MAX, sizeof(gap)); - for (playernum = 0; playernum < MAXPLAYERS-1; ++playernum) { - if (sortedplayers[playernum] == -1 || sortedplayers[playernum+1] == -1) - break; - gap[playernum] = P_ScaleFromMap(K_GetFinishGap(sortedplayers[playernum], sortedplayers[playernum+1]), FRACUNIT); - if (gap[playernum] >= BREAKAWAYDIST) - boredom[playernum] = min(BOREDOMTIME*2, boredom[playernum]+1); - else if (boredom[playernum] > 0) - boredom[playernum]--; + for (playernum = 0; playernum < MAXPLAYERS; playernum++) + { + directorinfo.sortedplayers[playernum] = -1; + directorinfo.gap[playernum] = INT32_MAX; + directorinfo.boredom[playernum] = 0; } - - maxdist = P_ScaleFromMap(players[sortedplayers[0]].distancetofinish, FRACUNIT); } -boolean K_CanSwitchDirector(void) { +fixed_t K_GetFinishGap(INT32 leader, INT32 follower) +{ + fixed_t dista = players[follower].distancetofinish; + fixed_t distb = players[leader].distancetofinish; + + if (players[follower].position < players[leader].position) + { + return distb - dista; + } + else + { + return dista - distb; + } +} + +void K_UpdateDirectorPositions(void) +{ + INT32 playernum; + INT32 position; + player_t target; + + memset(directorinfo.sortedplayers, -1, sizeof(directorinfo.sortedplayers)); + + for (playernum = 0; playernum < MAXPLAYERS; playernum++) + { + target = players[playernum]; + + if (playeringame[playernum] && !target.spectator && target.position > 0) + { + directorinfo.sortedplayers[target.position - 1] = playernum; + } + } + + for (position = 0; position < MAXPLAYERS - 1; position++) + { + directorinfo.gap[position] = INT32_MAX; + + if (directorinfo.sortedplayers[position] == -1 || directorinfo.sortedplayers[position + 1] == -1) + { + continue; + } + + directorinfo.gap[position] = P_ScaleFromMap(K_GetFinishGap(directorinfo.sortedplayers[position], directorinfo.sortedplayers[position + 1]), FRACUNIT); + + if (directorinfo.gap[position] >= BREAKAWAYDIST) + { + directorinfo.boredom[position] = min(BOREDOMTIME * 2, directorinfo.boredom[position] + 1); + } + else if (directorinfo.boredom[position] > 0) + { + directorinfo.boredom[position]--; + } + } + + directorinfo.maxdist = P_ScaleFromMap(players[directorinfo.sortedplayers[0]].distancetofinish, FRACUNIT); +} + +boolean K_CanSwitchDirector(void) +{ INT32 *displayplayerp = &displayplayers[0]; + if (players[*displayplayerp].trickpanel > 0) + { return false; - if (cooldown < SWITCHTIME) + } + + if (directorinfo.cooldown > 0) + { return false; + } + return true; } -void K_DirectorSwitch(INT32 player, boolean force) { +void K_DirectorSwitch(INT32 player, boolean force) +{ if (P_IsDisplayPlayer(&players[player])) + { return; + } + if (players[player].exiting) + { return; + } + if (!force && !K_CanSwitchDirector()) + { return; + } + G_ResetView(1, player, true); - cooldown = 0; + directorinfo.cooldown = SWITCHTIME; } -void K_DirectorForceSwitch(INT32 player, INT32 time) { +void K_DirectorForceSwitch(INT32 player, INT32 time) +{ if (players[player].exiting) + { return; - attacker = player; - freeze = time; + } + + directorinfo.attacker = player; + directorinfo.freeze = time; } -void K_DirectorFollowAttack(player_t *player, mobj_t *inflictor, mobj_t *source) { +void K_DirectorFollowAttack(player_t *player, mobj_t *inflictor, mobj_t *source) +{ if (!P_IsDisplayPlayer(player)) + { return; + } + if (inflictor && inflictor->player) - K_DirectorForceSwitch(inflictor->player-players, TRANSFERTIME); - if (source && source->player) - K_DirectorForceSwitch(source->player-players, TRANSFERTIME); + { + K_DirectorForceSwitch(inflictor->player - players, TRANSFERTIME); + } + else if (source && source->player) + { + K_DirectorForceSwitch(source->player - players, TRANSFERTIME); + } } -void K_DrawDirectorDebugger(void) { +void K_DrawDirectorDebugger(void) +{ INT32 playernum; INT32 leader; INT32 follower; INT32 ytxt; if (!cv_kartdebugdirector.value) + { return; + } V_DrawThinString(10, 0, V_70TRANS, va("PLACE")); V_DrawThinString(40, 0, V_70TRANS, va("CONF?")); V_DrawThinString(80, 0, V_70TRANS, va("GAP")); V_DrawThinString(120, 0, V_70TRANS, va("BORED")); - V_DrawThinString(150, 0, V_70TRANS, va("COOLDOWN: %d", cooldown)); - V_DrawThinString(230, 0, V_70TRANS, va("MAXDIST: %d", maxdist)); + V_DrawThinString(150, 0, V_70TRANS, va("COOLDOWN: %d", directorinfo.cooldown)); + V_DrawThinString(230, 0, V_70TRANS, va("MAXDIST: %d", directorinfo.maxdist)); + + for (playernum = 0; playernum < MAXPLAYERS - 1; playernum++) + { + ytxt = 10 * (playernum + 1); + leader = directorinfo.sortedplayers[playernum]; + follower = directorinfo.sortedplayers[playernum + 1]; - for (playernum = 0; playernum < MAXPLAYERS-1; ++playernum) { - ytxt = 10*playernum+10; - leader = sortedplayers[playernum]; - follower = sortedplayers[playernum+1]; if (leader == -1 || follower == -1) break; V_DrawThinString(10, ytxt, V_70TRANS, va("%d", playernum)); - V_DrawThinString(20, ytxt, V_70TRANS, va("%d", playernum+1)); + V_DrawThinString(20, ytxt, V_70TRANS, va("%d", playernum + 1)); + if (players[leader].positiondelay) + { V_DrawThinString(40, ytxt, V_70TRANS, va("NG")); - V_DrawThinString(80, ytxt, V_70TRANS, va("%d", gap[playernum])); - if (boredom[playernum] >= BOREDOMTIME) + } + + V_DrawThinString(80, ytxt, V_70TRANS, va("%d", directorinfo.gap[playernum])); + + if (directorinfo.boredom[playernum] >= BOREDOMTIME) + { V_DrawThinString(120, ytxt, V_70TRANS, va("BORED")); + } else - V_DrawThinString(120, ytxt, V_70TRANS, va("%d", boredom[playernum])); + { + V_DrawThinString(120, ytxt, V_70TRANS, va("%d", directorinfo.boredom[playernum])); + } + V_DrawThinString(150, ytxt, V_70TRANS, va("%s", player_names[leader])); V_DrawThinString(230, ytxt, V_70TRANS, va("%s", player_names[follower])); } } -void K_UpdateDirector(void) { +void K_UpdateDirector(void) +{ INT32 *displayplayerp = &displayplayers[0]; INT32 targetposition; if (!cv_director.value) + { return; + } K_UpdateDirectorPositions(); - cooldown++; + + if (directorinfo.cooldown > 0) { + directorinfo.cooldown--; + } // handle pending forced switches - if (freeze > 0) { - if (freeze == 1) - K_DirectorSwitch(attacker, true); - freeze--; + if (directorinfo.freeze > 0) + { + if (!(--directorinfo.freeze)) + K_DirectorSwitch(directorinfo.attacker, true); + + directorinfo.freeze--; return; } // aaight, time to walk through the standings to find the first interesting pair - for(targetposition = 0; targetposition < MAXPLAYERS-1; targetposition++) { + for (targetposition = 1; targetposition < MAXPLAYERS; targetposition++) + { INT32 target; // you are out of players, try again - if (sortedplayers[targetposition+1] == -1) + if (directorinfo.sortedplayers[targetposition] == -1) + { break; + } // pair too far apart? try the next one - if (boredom[targetposition] >= BOREDOMTIME) + if (directorinfo.boredom[targetposition - 1] >= BOREDOMTIME) + { continue; + } // pair finished? try the next one - if (players[sortedplayers[targetposition+1]].exiting) + if (players[directorinfo.sortedplayers[targetposition]].exiting) + { continue; + } // don't risk switching away from forward pairs at race end, might miss something! - if (maxdist > PINCHDIST) { + if (directorinfo.maxdist > PINCHDIST) + { // if the "next" player is close enough, they should be able to see everyone fine! // walk back through the standings to find a vantage that gets everyone in frame. // (also creates a pretty cool effect w/ overtakes at speed) - while (targetposition < MAXPLAYERS && gap[targetposition+1] < WALKBACKDIST) { + while (targetposition < MAXPLAYERS && directorinfo.gap[targetposition] < WALKBACKDIST) + { targetposition++; } } - target = sortedplayers[targetposition+1]; + target = directorinfo.sortedplayers[targetposition]; // if we're certain the back half of the pair is actually in this position, try to switch if (*displayplayerp != target && !players[target].positiondelay) + { K_DirectorSwitch(target, false); + } + // even if we're not certain, if we're certain we're watching the WRONG player, try to switch if (players[*displayplayerp].position != targetposition && !players[target].positiondelay) + { K_DirectorSwitch(target, false); + } break; } diff --git a/src/k_director.h b/src/k_director.h index a7d9fd2a6..db19fbe8b 100644 --- a/src/k_director.h +++ b/src/k_director.h @@ -3,6 +3,19 @@ /// \file k_director.h /// \brief SRB2kart automatic spectator camera. +extern struct directorinfo +{ + tic_t cooldown; // how long has it been since we last switched? + tic_t freeze; // when nonzero, fixed switch pending, freeze logic! + INT32 attacker; // who to switch to when freeze delay elapses + INT32 maxdist; // how far is the closest player from finishing? + + INT32 sortedplayers[MAXPLAYERS]; // position-1 goes in, player index comes out. + INT32 gap[MAXPLAYERS]; // gap between a given position and their closest pursuer + INT32 boredom[MAXPLAYERS]; // how long has a given position had no credible attackers? +} directorinfo; + +void K_InitDirector(void); void K_UpdateDirector(void); void K_DrawDirectorDebugger(void); void K_DirectorFollowAttack(player_t *player, mobj_t *inflictor, mobj_t *source); \ No newline at end of file diff --git a/src/k_kart.c b/src/k_kart.c index 4332d4416..f7fc380a3 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3233,10 +3233,11 @@ void K_BattleAwardHit(player_t *player, player_t *victim, mobj_t *inflictor, UIN void K_SpinPlayer(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 type) { - K_DirectorFollowAttack(player, inflictor, source); (void)inflictor; (void)source; + K_DirectorFollowAttack(player, inflictor, source); + player->spinouttype = type; if (( player->spinouttype & KSPIN_THRUST )) @@ -3415,10 +3416,10 @@ INT32 K_ExplodePlayer(player_t *player, mobj_t *inflictor, mobj_t *source) // A { INT32 ringburst = 10; - K_DirectorFollowAttack(player, inflictor, source); - (void)source; + K_DirectorFollowAttack(player, inflictor, source); + player->mo->momz = 18*mapobjectscale*P_MobjFlip(player->mo); // please stop forgetting mobjflip checks!!!! player->mo->momx = player->mo->momy = 0; diff --git a/src/p_setup.c b/src/p_setup.c index ef5d80070..704bb99ec 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -93,6 +93,7 @@ #include "k_grandprix.h" #include "k_brightmap.h" #include "k_terrain.h" // TRF_TRIPWIRE +#include "k_director.h" // K_InitDirector // Replay names have time #if !defined (UNDER_CE) @@ -4142,6 +4143,8 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) memset(localaiming, 0, sizeof(localaiming)); } + K_InitDirector(); + wantedcalcdelay = wantedfrequency*2; indirectitemcooldown = 0; hyubgone = 0;