diff --git a/src/d_clisrv.c b/src/d_clisrv.c index e26debd91..f26ec7274 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -5092,7 +5092,7 @@ static void SV_Maketic(void) { INT32 i; - ps_botticcmd_time = 0; + PS_ResetBotInfo(); for (i = 0; i < MAXPLAYERS; i++) { @@ -5101,9 +5101,13 @@ static void SV_Maketic(void) if (K_PlayerUsesBotMovement(&players[i])) { - precise_t t = I_GetPreciseTime(); + const precise_t t = I_GetPreciseTime(); + K_BuildBotTiccmd(&players[i], &netcmds[maketic%BACKUPTICS][i]); - ps_botticcmd_time += I_GetPreciseTime() - t; + + ps_bots[i].isBot = true; + ps_bots[i].total = I_GetPreciseTime() - t; + ps_botticcmd_time += ps_bots[i].total; continue; } diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 7e8143427..1fef5acd1 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -61,6 +61,7 @@ #include "k_follower.h" #include "doomstat.h" #include "deh_tables.h" +#include "m_perfstats.h" #ifdef NETGAME_DEVMODE #define CV_RESTRICT CV_NETVAR @@ -511,7 +512,13 @@ consvar_t cv_mute = CVAR_INIT ("mute", "Off", CV_NETVAR|CV_CALL, CV_OnOff, Mute_ consvar_t cv_sleep = CVAR_INIT ("cpusleep", "1", CV_SAVE, sleeping_cons_t, NULL); static CV_PossibleValue_t perfstats_cons_t[] = { - {0, "Off"}, {1, "Rendering"}, {2, "Logic"}, {3, "ThinkFrame"}, {0, NULL}}; + {PS_OFF, "Off"}, + {PS_RENDER, "Rendering"}, + {PS_LOGIC, "Logic"}, + {PS_BOT, "Bots"}, + {PS_THINKFRAME, "ThinkFrame"}, + {0, NULL} +}; consvar_t cv_perfstats = CVAR_INIT ("perfstats", "Off", 0, perfstats_cons_t, NULL); consvar_t cv_director = CVAR_INIT ("director", "Off", 0, CV_OnOff, NULL); diff --git a/src/k_bot.c b/src/k_bot.c index 605a955c2..6bc0f573d 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -28,6 +28,7 @@ #include "r_things.h" // numskins #include "k_race.h" // finishBeamLine #include "k_boss.h" +#include "m_perfstats.h" /*-------------------------------------------------- @@ -638,6 +639,8 @@ fixed_t K_DistanceOfLineFromPoint(fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t --------------------------------------------------*/ static botprediction_t *K_CreateBotPrediction(player_t *player) { + const precise_t time = I_GetPreciseTime(); + // Stair janking makes it harder to steer, so attempt to steer harder. const UINT8 jankDiv = (player->stairjank > 0) ? 2 : 1; @@ -765,6 +768,7 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) predict->y += P_ReturnThrustY(NULL, angletonext, min(disttonext, distanceleft) * FRACUNIT); } + ps_bots[player - players].prediction += I_GetPreciseTime() - time; return predict; } @@ -1219,6 +1223,7 @@ static INT32 K_HandleBotReverse(player_t *player, ticcmd_t *cmd, botprediction_t --------------------------------------------------*/ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) { + precise_t t = 0; botprediction_t *predict = NULL; boolean trySpindash = true; angle_t destangle = 0; @@ -1439,7 +1444,9 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) { // Don't pointlessly try to use rings/sneakers while charging a spindash. // TODO: Allowing projectile items like orbinaut while e-braking would be nice, maybe just pass in the spindash variable? + t = I_GetPreciseTime(); K_BotItemUsage(player, cmd, turnamt); + ps_bots[player - players].item = I_GetPreciseTime() - t; } if (turnamt != 0) diff --git a/src/k_botsearch.c b/src/k_botsearch.c index 1192324e3..af7464c30 100644 --- a/src/k_botsearch.c +++ b/src/k_botsearch.c @@ -27,6 +27,7 @@ #include "m_random.h" #include "r_things.h" // numskins #include "p_slopes.h" // P_GetZAt +#include "m_perfstats.h" struct globalsmuggle { @@ -613,6 +614,8 @@ static BlockItReturn_t K_FindObjectsForNudging(mobj_t *thing) --------------------------------------------------*/ void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player) { + const precise_t time = I_GetPreciseTime(); + INT32 xl, xh, yl, yh, bx, by; fixed_t distToPredict = R_PointToDist2(player->mo->x, player->mo->y, predict->x, predict->y); @@ -727,7 +730,7 @@ void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player) // Check if our side is invalid, if so, don't do the code below. if (gotoSide != -1 && globalsmuggle.gotoObjs[gotoSide] == 0) { - // Do not use a side + // Do not use a side gotoSide = -1; } @@ -769,6 +772,8 @@ void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player) //distToPredict = R_PointToDist2(player->mo->x, player->mo->y, predict->x, predict->y); } } + + ps_bots[player - players].nudge += I_GetPreciseTime() - time; } /*-------------------------------------------------- diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 0a46674c2..771182a59 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -482,7 +482,7 @@ void LUAh_ThinkFrame(void) if (hookp->type != hook_ThinkFrame) continue; - if (cv_perfstats.value == 3) + if (cv_perfstats.value == PS_THINKFRAME) time_taken = I_GetPreciseTime(); PushHook(gL, hookp); if (lua_pcall(gL, 0, 0, 1)) { @@ -491,7 +491,7 @@ void LUAh_ThinkFrame(void) lua_pop(gL, 1); hookp->error = true; } - if (cv_perfstats.value == 3) + if (cv_perfstats.value == PS_THINKFRAME) { lua_Debug ar; time_taken = I_GetPreciseTime() - time_taken; diff --git a/src/m_perfstats.c b/src/m_perfstats.c index a1d4d0fba..0be2eb805 100644 --- a/src/m_perfstats.c +++ b/src/m_perfstats.c @@ -18,6 +18,7 @@ #include "i_time.h" #include "z_zone.h" #include "p_local.h" +#include "g_game.h" #ifdef HWRENDER #include "hardware/hw_main.h" @@ -62,6 +63,8 @@ ps_hookinfo_t *thinkframe_hooks = NULL; int thinkframe_hooks_length = 0; int thinkframe_hooks_capacity = 16; +ps_botinfo_t ps_bots[MAXPLAYERS]; + static INT32 draw_row; void PS_SetThinkFrameHookInfo(int index, precise_t time_taken, char* short_src) @@ -85,6 +88,12 @@ void PS_SetThinkFrameHookInfo(int index, precise_t time_taken, char* short_src) thinkframe_hooks_length = index + 1; } +void PS_ResetBotInfo(void) +{ + memset(ps_bots, 0, sizeof(ps_bots)); + ps_botticcmd_time = 0; +} + static void PS_SetFrameTime(void) { precise_t currenttime = I_GetPreciseTime(); @@ -486,15 +495,126 @@ void M_DrawPerfStats(void) PS_SetFrameTime(); - if (cv_perfstats.value == 1) // rendering + if (cv_perfstats.value == PS_RENDER) // rendering { M_DrawRenderStats(); } - else if (cv_perfstats.value == 2) // logic + else if (cv_perfstats.value == PS_LOGIC) // logic { M_DrawTickStats(); } - else if (cv_perfstats.value == 3) // lua thinkframe + else if (cv_perfstats.value == PS_BOT) // bot ticcmd + { + if (vid.width < 640 || vid.height < 400) // low resolution + { + // it's not gonna fit very well.. + V_DrawThinString(30, 30, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, "Not available for resolutions below 640x400"); + } + else // high resolution + { + precise_t otherTime = 0; + int i; + + // text writing position + int x = 2; + int y = 4; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (ps_bots[i].isBot == false) + { + continue; + } + + snprintf(s, sizeof s - 1, "Bot %d (%s):", i + 1, player_names[i]); + V_DrawSmallString(x, y, V_MONOSPACE | V_ALLOWLOWERCASE | V_GRAYMAP, s); + + snprintf(s, sizeof s - 1, "%ld", (long)((ps_bots[i].total) / (I_GetPrecisePrecision() / 1000000))); + V_DrawRightAlignedSmallString(x + 98, y, V_MONOSPACE | V_ALLOWLOWERCASE | V_GRAYMAP, s); + + y += 4; // repeated code! + if (y > 192) + { + y = 4; + x += 106; + if (x > 214) + break; + } + + snprintf(s, sizeof s - 1, "Prediction:"); + V_DrawSmallString(x, y, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s); + + snprintf(s, sizeof s - 1, "%ld", (long)((ps_bots[i].prediction) / (I_GetPrecisePrecision() / 1000000))); + V_DrawRightAlignedSmallString(x + 98, y, V_MONOSPACE | V_ALLOWLOWERCASE, s); + + y += 4; // repeated code! + if (y > 192) + { + y = 4; + x += 106; + if (x > 214) + break; + } + + snprintf(s, sizeof s - 1, "Nudge:"); + V_DrawSmallString(x, y, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s); + + snprintf(s, sizeof s - 1, "%ld", (long)((ps_bots[i].nudge) / (I_GetPrecisePrecision() / 1000000))); + V_DrawRightAlignedSmallString(x + 98, y, V_MONOSPACE | V_ALLOWLOWERCASE, s); + + y += 4; // repeated code! + if (y > 192) + { + y = 4; + x += 106; + if (x > 214) + break; + } + + snprintf(s, sizeof s - 1, "Item:"); + V_DrawSmallString(x, y, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s); + + snprintf(s, sizeof s - 1, "%ld", (long)((ps_bots[i].item) / (I_GetPrecisePrecision() / 1000000))); + V_DrawRightAlignedSmallString(x + 98, y, V_MONOSPACE | V_ALLOWLOWERCASE, s); + + y += 4; // repeated code! + if (y > 192) + { + y = 4; + x += 106; + if (x > 214) + break; + } + + snprintf(s, sizeof s - 1, "Other:"); + V_DrawSmallString(x, y, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s); + + otherTime = ps_bots[i].total - ps_bots[i].prediction - ps_bots[i].nudge - ps_bots[i].item; + snprintf(s, sizeof s - 1, "%ld", (long)(otherTime / (I_GetPrecisePrecision() / 1000000))); + V_DrawRightAlignedSmallString(x + 98, y, V_MONOSPACE | V_ALLOWLOWERCASE, s); + + y += 4; // repeated code! + if (y > 192) + { + y = 4; + x += 106; + if (x > 214) + break; + } + + // add an extra space + y += 4; // repeated code! + if (y > 192) + { + y = 4; + x += 106; + if (x > 214) + break; + } + } + } + } + else if (cv_perfstats.value == PS_THINKFRAME) // lua thinkframe { if (!(gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction))) return; diff --git a/src/m_perfstats.h b/src/m_perfstats.h index dae2f2030..2c448031c 100644 --- a/src/m_perfstats.h +++ b/src/m_perfstats.h @@ -16,6 +16,15 @@ #include "lua_script.h" #include "p_local.h" +typedef enum +{ + PS_OFF = 0, + PS_RENDER, + PS_LOGIC, + PS_BOT, + PS_THINKFRAME, +} ps_types_t; + extern precise_t ps_tictime; extern precise_t ps_playerthink_time; @@ -37,6 +46,19 @@ typedef struct void PS_SetThinkFrameHookInfo(int index, precise_t time_taken, char* short_src); +typedef struct +{ + boolean isBot; + precise_t total; + precise_t prediction; // K_CreateBotPrediction + precise_t nudge; // K_NudgePredictionTowardsObjects + precise_t item; // K_BotItemUsage +} ps_botinfo_t; + +extern ps_botinfo_t ps_bots[MAXPLAYERS]; + +void PS_ResetBotInfo(void); + void M_DrawPerfStats(void); #endif