summaryrefslogtreecommitdiff
path: root/sourcemod/scripting/gokz-jumpstats/jump_reporting.sp
diff options
context:
space:
mode:
Diffstat (limited to 'sourcemod/scripting/gokz-jumpstats/jump_reporting.sp')
-rw-r--r--sourcemod/scripting/gokz-jumpstats/jump_reporting.sp508
1 files changed, 508 insertions, 0 deletions
diff --git a/sourcemod/scripting/gokz-jumpstats/jump_reporting.sp b/sourcemod/scripting/gokz-jumpstats/jump_reporting.sp
new file mode 100644
index 0000000..31a1bb2
--- /dev/null
+++ b/sourcemod/scripting/gokz-jumpstats/jump_reporting.sp
@@ -0,0 +1,508 @@
+/*
+ Chat and console reports for jumpstats.
+*/
+
+static char sounds[DISTANCETIER_COUNT][256];
+
+
+
+// =====[ PUBLIC ]=====
+
+void PlayJumpstatSound(int client, int tier)
+{
+ int soundOption = GOKZ_JS_GetOption(client, JSOption_MinSoundTier);
+ if (tier <= DistanceTier_Meh || soundOption == DistanceTier_None || soundOption > tier)
+ {
+ return;
+ }
+
+ GOKZ_EmitSoundToClient(client, sounds[tier], _, "Jumpstats");
+}
+
+
+
+// =====[ EVENTS ]=====
+
+void OnMapStart_JumpReporting()
+{
+ if (!LoadSounds())
+ {
+ SetFailState("Failed to load file: \"%s\".", JS_CFG_SOUNDS);
+ }
+}
+
+void OnLanding_JumpReporting(Jump jump)
+{
+ int minTier;
+ int tier = GetDistanceTier(jump.type, GOKZ_GetCoreOption(jump.jumper, Option_Mode), jump.distance, jump.offset);
+ if (tier == DistanceTier_None)
+ {
+ return;
+ }
+
+ // Report the jumpstat to the client and their spectators
+ DoJumpstatsReport(jump.jumper, jump, tier);
+
+ for (int client = 1; client <= MaxClients; client++)
+ {
+ if (IsValidClient(client) && client != jump.jumper)
+ {
+ if (GetObserverTarget(client) == jump.jumper)
+ {
+ DoJumpstatsReport(client, jump, tier);
+ }
+ else
+ {
+ minTier = GOKZ_JS_GetOption(client, JSOption_MinChatBroadcastTier);
+ if (minTier != 0 && tier >= minTier)
+ {
+ GOKZ_PrintToChat(client, true, "%t", "Broadcast Jumpstat Chat Report",
+ gC_DistanceTierChatColours[tier],
+ jump.jumper,
+ jump.distance,
+ gC_JumpTypes[jump.originalType]);
+ DoConsoleReport(client, false, jump, tier, "Console Jump Header");
+ }
+
+ minTier = GOKZ_JS_GetOption(client, JSOption_MinSoundBroadcastTier);
+ if (minTier != 0 && tier >= minTier)
+ {
+ PlayJumpstatSound(client, tier);
+ }
+ }
+ }
+ }
+}
+
+void OnFailstat_FailstatReporting(Jump jump)
+{
+ int tier = GetDistanceTier(jump.type, GOKZ_GetCoreOption(jump.jumper, Option_Mode), jump.distance);
+ if (tier == DistanceTier_None)
+ {
+ return;
+ }
+
+ // Report the failstat to the client and their spectators
+ DoFailstatReport(jump.jumper, jump, tier);
+
+ for (int client = 1; client <= MaxClients; client++)
+ {
+ if (IsValidClient(client) && GetObserverTarget(client) == jump.jumper)
+ {
+ DoFailstatReport(client, jump, tier);
+ }
+ }
+}
+
+void OnJumpstatAlways_JumpstatAlwaysReporting(Jump jump)
+{
+ DoJumpstatAlwaysReport(jump.jumper, jump);
+
+ for (int client = 1; client <= MaxClients; client++)
+ {
+ if (IsValidClient(client) && GetObserverTarget(client) == jump.jumper)
+ {
+ DoJumpstatAlwaysReport(client, jump);
+ }
+ }
+}
+
+
+void OnFailstatAlways_FailstatAlwaysReporting(Jump jump)
+{
+ DoFailstatAlwaysReport(jump.jumper, jump);
+
+ for (int client = 1; client <= MaxClients; client++)
+ {
+ if (IsValidClient(client) && GetObserverTarget(client) == jump.jumper)
+ {
+ DoFailstatAlwaysReport(client, jump);
+ }
+ }
+}
+
+
+
+// =====[ PRIVATE ]=====
+
+static void DoJumpstatsReport(int client, Jump jump, int tier)
+{
+ if (GOKZ_JS_GetOption(client, JSOption_JumpstatsMaster) == JSToggleOption_Disabled)
+ {
+ return;
+ }
+
+ DoChatReport(client, false, jump, tier);
+ DoConsoleReport(client, false, jump, tier, "Console Jump Header");
+ PlayJumpstatSound(client, tier);
+}
+
+static void DoFailstatReport(int client, Jump jump, int tier)
+{
+ if (GOKZ_JS_GetOption(client, JSOption_JumpstatsMaster) == JSToggleOption_Disabled)
+ {
+ return;
+ }
+
+ DoChatReport(client, true, jump, tier);
+ DoConsoleReport(client, true, jump, tier, "Console Failstat Header");
+}
+
+static void DoJumpstatAlwaysReport(int client, Jump jump)
+{
+ if (GOKZ_JS_GetOption(client, JSOption_JumpstatsMaster) == JSToggleOption_Disabled ||
+ GOKZ_JS_GetOption(client, JSOption_JumpstatsAlways) == JSToggleOption_Disabled)
+ {
+ return;
+ }
+
+ DoChatReport(client, false, jump, 1);
+ DoConsoleReport(client, false, jump, 1, "Console Jump Header");
+}
+
+static void DoFailstatAlwaysReport(int client, Jump jump)
+{
+ if (GOKZ_JS_GetOption(client, JSOption_JumpstatsMaster) == JSToggleOption_Disabled ||
+ GOKZ_JS_GetOption(client, JSOption_JumpstatsAlways) == JSToggleOption_Disabled)
+ {
+ return;
+ }
+
+ DoChatReport(client, true, jump, 1);
+ DoConsoleReport(client, true, jump, 1, "Console Failstat Header");
+}
+
+
+
+
+// CONSOLE REPORT
+
+static void DoConsoleReport(int client, bool isFailstat, Jump jump, int tier, char[] header)
+{
+ int minConsoleTier = GOKZ_JS_GetOption(client, JSOption_MinConsoleTier);
+ if ((minConsoleTier == 0 || minConsoleTier > tier) && GOKZ_JS_GetOption(client, JSOption_JumpstatsAlways) == JSToggleOption_Disabled
+ || isFailstat && GOKZ_JS_GetOption(client, JSOption_FailstatsConsole) == JSToggleOption_Disabled)
+ {
+ return;
+ }
+
+ char releaseWString[32], blockString[32], edgeString[32], deviationString[32], missString[32];
+
+ if (jump.originalType == JumpType_LongJump ||
+ jump.originalType == JumpType_LadderJump ||
+ jump.originalType == JumpType_WeirdJump ||
+ jump.originalType == JumpType_LowpreWeirdJump)
+ {
+ FormatEx(releaseWString, sizeof(releaseWString), " %s", GetIntConsoleString(client, "W Release", jump.releaseW));
+ }
+ else if (jump.crouchRelease < 20 && jump.crouchRelease > -20)
+ {
+ FormatEx(releaseWString, sizeof(releaseWString), " %s", GetIntConsoleString(client, "Crouch Release", jump.crouchRelease));
+ }
+
+ if (jump.miss > 0.0)
+ {
+ FormatEx(missString, sizeof(missString), " %s", GetFloatConsoleString2(client, "Miss", jump.miss));
+ }
+
+ if (jump.block > 0)
+ {
+ FormatEx(blockString, sizeof(blockString), " %s", GetIntConsoleString(client, "Block", jump.block));
+ FormatEx(deviationString, sizeof(deviationString), " %s", GetFloatConsoleString1(client, "Deviation", jump.deviation));
+ }
+
+ if (jump.edge > 0.0 || (jump.block > 0 && jump.edge == 0.0))
+ {
+ FormatEx(edgeString, sizeof(edgeString), " %s", GetFloatConsoleString2(client, "Edge", jump.edge));
+ }
+
+ PrintToConsole(client, "%t", header, jump.jumper, jump.distance, gC_JumpTypes[jump.originalType]);
+
+ PrintToConsole(client, "%s%s%s%s %s %s %s %s%s %s %s%s %s %s %s %s %s",
+ gC_ModeNamesShort[GOKZ_GetCoreOption(jump.jumper, Option_Mode)],
+ blockString,
+ edgeString,
+ missString,
+ GetIntConsoleString(client, jump.strafes == 1 ? "Strafe" : "Strafes", jump.strafes),
+ GetSyncConsoleString(client, jump.sync),
+ GetFloatConsoleString2(client, "Pre", jump.preSpeed),
+ GetFloatConsoleString2(client, "Max", jump.maxSpeed),
+ releaseWString,
+ GetIntConsoleString(client, "Overlap", jump.overlap),
+ GetIntConsoleString(client, "Dead Air", jump.deadair),
+ deviationString,
+ GetWidthConsoleString(client, jump.width, jump.strafes),
+ GetFloatConsoleString1(client, "Height", jump.height),
+ GetIntConsoleString(client, "Airtime", jump.duration),
+ GetFloatConsoleString1(client, "Offset", jump.offset),
+ GetIntConsoleString(client, "Crouch Ticks", jump.crouchTicks));
+
+ PrintToConsole(client, " #. %12t%12t%12t%12t%12t%9t%t", "Sync (Table)", "Gain (Table)", "Loss (Table)", "Airtime (Table)", "Width (Table)", "Overlap (Table)", "Dead Air (Table)");
+ if (jump.strafes_ticks[0] > 0)
+ {
+ PrintToConsole(client, " 0. ---- ----- ----- %3.0f%% ----- -- --", GetStrafeAirtime(jump, 0));
+ }
+ for (int strafe = 1; strafe <= jump.strafes && strafe < JS_MAX_TRACKED_STRAFES; strafe++)
+ {
+ PrintToConsole(client,
+ " %2d. %3.0f%% %5.2f %5.2f %3.0f%% %5.1f° %2d %2d",
+ strafe,
+ GetStrafeSync(jump, strafe),
+ jump.strafes_gain[strafe],
+ jump.strafes_loss[strafe],
+ GetStrafeAirtime(jump, strafe),
+ FloatAbs(jump.strafes_width[strafe]),
+ jump.strafes_overlap[strafe],
+ jump.strafes_deadair[strafe]);
+ }
+ PrintToConsole(client, ""); // New line
+}
+
+static char[] GetSyncConsoleString(int client, float sync)
+{
+ char resultString[32];
+ FormatEx(resultString, sizeof(resultString), "| %.0f%% %T", sync, "Sync", client);
+ return resultString;
+}
+
+static char[] GetWidthConsoleString(int client, float width, int strafes)
+{
+ char resultString[32];
+ FormatEx(resultString, sizeof(resultString), "| %.1f° %T", GetAverageStrafeWidth(strafes, width), "Width", client);
+ return resultString;
+}
+
+// I couldn't really merge those together
+static char[] GetFloatConsoleString1(int client, const char[] stat, float value)
+{
+ char resultString[32];
+ FormatEx(resultString, sizeof(resultString), "| %.1f %T", value, stat, client);
+ return resultString;
+}
+
+static char[] GetFloatConsoleString2(int client, const char[] stat, float value)
+{
+ char resultString[32];
+ FormatEx(resultString, sizeof(resultString), "| %.2f %T", value, stat, client);
+ return resultString;
+}
+
+static char[] GetIntConsoleString(int client, const char[] stat, int value)
+{
+ char resultString[32];
+ FormatEx(resultString, sizeof(resultString), "| %d %T", value, stat, client);
+ return resultString;
+}
+
+
+
+// CHAT REPORT
+
+static void DoChatReport(int client, bool isFailstat, Jump jump, int tier)
+{
+ int minChatTier = GOKZ_JS_GetOption(client, JSOption_MinChatTier);
+ if ((minChatTier == 0 || minChatTier > tier) // 0 means disabled
+ && GOKZ_JS_GetOption(client, JSOption_JumpstatsAlways) == JSToggleOption_Disabled)
+ {
+ return;
+ }
+
+ char typePostfix[3], color[16], blockStats[32], extBlockStats[32];
+ char releaseStats[32], edgeOffset[64], offsetEdge[32], missString[32];
+
+ if (isFailstat)
+ {
+ if (GOKZ_JS_GetOption(client, JSOption_FailstatsChat) == JSToggleOption_Disabled
+ && GOKZ_JS_GetOption(client, JSOption_JumpstatsAlways) == JSToggleOption_Disabled)
+ {
+ return;
+ }
+ strcopy(typePostfix, sizeof(typePostfix), "-F");
+ strcopy(color, sizeof(color), "{grey}");
+ }
+ else
+ {
+ strcopy(color, sizeof(color), gC_DistanceTierChatColours[tier]);
+ }
+
+ if (jump.block > 0)
+ {
+ FormatEx(blockStats, sizeof(blockStats), " | %s", GetFloatChatString(client, "Edge", jump.edge));
+ FormatEx(extBlockStats, sizeof(extBlockStats), " | %s", GetFloatChatString(client, "Deviation", jump.deviation));
+ }
+
+ if (jump.miss > 0.0)
+ {
+ FormatEx(missString, sizeof(missString), " | %s", GetFloatChatString(client, "Miss", jump.miss));
+ }
+
+ if (jump.edge > 0.0 || (jump.block > 0 && jump.edge == 0.0))
+ {
+ if (jump.originalType == JumpType_LadderJump)
+ {
+ FormatEx(offsetEdge, sizeof(offsetEdge), " | %s", GetFloatChatString(client, "Edge", jump.edge));
+ }
+ else
+ {
+ FormatEx(edgeOffset, sizeof(edgeOffset), " | %s", GetFloatChatString(client, "Edge", jump.edge));
+ }
+ }
+
+ if (jump.originalType == JumpType_LongJump ||
+ jump.originalType == JumpType_LadderJump ||
+ jump.originalType == JumpType_WeirdJump)
+ {
+ if (jump.releaseW >= 20 || jump.releaseW <= -20)
+ {
+ FormatEx(releaseStats, sizeof(releaseStats), " | {red}✗ {grey}W", GetReleaseChatString(client, "W Release", jump.releaseW));
+ }
+ else
+ {
+ FormatEx(releaseStats, sizeof(releaseStats), " | %s", GetReleaseChatString(client, "W Release", jump.releaseW));
+ }
+ }
+ else if (jump.crouchRelease < 20 && jump.crouchRelease > -20)
+ {
+ FormatEx(releaseStats, sizeof(releaseStats), " | %s", GetReleaseChatString(client, "Crouch Release", jump.crouchRelease));
+ }
+
+ if (jump.originalType == JumpType_LadderJump)
+ {
+ FormatEx(edgeOffset, sizeof(edgeOffset), " | %s", GetFloatChatString(client, "Offset Short", jump.offset));
+ }
+ else
+ {
+ FormatEx(offsetEdge, sizeof(offsetEdge), " | %s", GetFloatChatString(client, "Offset", jump.offset));
+ }
+
+ GOKZ_PrintToChat(client, true,
+ "%s%s%s{grey}: %s%.1f{grey} | %s | %s%s%s",
+ color,
+ gC_JumpTypesShort[jump.originalType],
+ typePostfix,
+ color,
+ jump.distance,
+ GetStrafesSyncChatString(client, jump.strafes, jump.sync),
+ GetSpeedChatString(client, jump.preSpeed, jump.maxSpeed),
+ edgeOffset,
+ releaseStats);
+
+ if (GOKZ_JS_GetOption(client, JSOption_ExtendedChatReport) == JSToggleOption_Enabled)
+ {
+ GOKZ_PrintToChat(client, false,
+ "%s | %s%s%s | %s | %s%s",
+ GetIntChatString(client, "Overlap", jump.overlap),
+ GetIntChatString(client, "Dead Air", jump.deadair),
+ offsetEdge,
+ extBlockStats,
+ GetWidthChatString(client, jump.width, jump.strafes),
+ GetFloatChatString(client, "Height", jump.height),
+ missString);
+ }
+}
+
+static char[] GetStrafesSyncChatString(int client, int strafes, float sync)
+{
+ char resultString[64];
+ FormatEx(resultString, sizeof(resultString),
+ "{lime}%d{grey} %T ({lime}%.0f%%%%{grey})",
+ strafes, "Strafes", client, sync);
+ return resultString;
+}
+
+static char[] GetSpeedChatString(int client, float preSpeed, float maxSpeed)
+{
+ char resultString[64];
+ FormatEx(resultString, sizeof(resultString),
+ "{lime}%.0f{grey} / {lime}%.0f{grey} %T",
+ preSpeed, maxSpeed, "Speed", client);
+ return resultString;
+}
+
+static char[] GetReleaseChatString(int client, char[] releaseType, int release)
+{
+ char resultString[32];
+ if (release == 0)
+ {
+ FormatEx(resultString, sizeof(resultString),
+ "{green}✓{grey} %T",
+ releaseType, client);
+ }
+ else if (release > 0)
+ {
+ FormatEx(resultString, sizeof(resultString),
+ "{red}+%d{grey} %T",
+ release,
+ releaseType, client);
+ }
+ else
+ {
+ FormatEx(resultString, sizeof(resultString),
+ "{blue}%d{grey} %T",
+ release,
+ releaseType, client);
+ }
+ return resultString;
+}
+
+static char[] GetWidthChatString(int client, float width, int strafes)
+{
+ char resultString[32];
+ FormatEx(resultString, sizeof(resultString),
+ "{lime}%.1f°{grey} %T",
+ GetAverageStrafeWidth(strafes, width), "Width", client);
+ return resultString;
+}
+
+static float GetAverageStrafeWidth(int strafes, float totalWidth)
+{
+ if (strafes == 0)
+ {
+ return 0.0;
+ }
+
+ return totalWidth / strafes;
+}
+
+static char[] GetFloatChatString(int client, const char[] stat, float value)
+{
+ char resultString[32];
+ FormatEx(resultString, sizeof(resultString),
+ "{lime}%.1f{grey} %T",
+ value, stat, client);
+ return resultString;
+}
+
+static char[] GetIntChatString(int client, const char[] stat, int value)
+{
+ char resultString[32];
+ FormatEx(resultString, sizeof(resultString),
+ "{lime}%d{grey} %T",
+ value, stat, client);
+ return resultString;
+}
+
+
+
+// SOUNDS
+
+static bool LoadSounds()
+{
+ KeyValues kv = new KeyValues("sounds");
+ if (!kv.ImportFromFile(JS_CFG_SOUNDS))
+ {
+ return false;
+ }
+
+ char downloadPath[256];
+ for (int tier = DistanceTier_Impressive; tier < DISTANCETIER_COUNT; tier++)
+ {
+ kv.GetString(gC_DistanceTierKeys[tier], sounds[tier], sizeof(sounds[]));
+ FormatEx(downloadPath, sizeof(downloadPath), "sound/%s", sounds[tier]);
+ AddFileToDownloadsTable(downloadPath);
+ PrecacheSound(sounds[tier], true);
+ }
+
+ delete kv;
+ return true;
+}