/*
Displays information using hint text.
This is manually refreshed whenever player has taken off so that they see
their pre-speed as soon as possible, improving responsiveness.
*/
static bool infoPanelDuckPressedLast[MAXPLAYERS + 1];
static bool infoPanelOnGroundLast[MAXPLAYERS + 1];
static bool infoPanelShowDuckString[MAXPLAYERS + 1];
// =====[ PUBLIC ]=====
bool IsDrawingInfoPanel(int client)
{
KZPlayer player = KZPlayer(client);
return player.InfoPanel != InfoPanel_Disabled
&& !NothingEnabledInInfoPanel(player);
}
// =====[ EVENTS ]=====
void OnPlayerRunCmdPost_InfoPanel(int client, int cmdnum, HUDInfo info)
{
int updateSpeed = gB_FastUpdateRate[client] ? 1 : 10;
if (cmdnum % updateSpeed == 0 || info.IsTakeoff)
{
UpdateInfoPanel(client, info);
}
infoPanelOnGroundLast[info.ID] = info.OnGround;
infoPanelDuckPressedLast[info.ID] = info.Ducking;
}
// =====[ PRIVATE ]=====
static void UpdateInfoPanel(int client, HUDInfo info)
{
KZPlayer player = KZPlayer(client);
if (player.Fake || !IsDrawingInfoPanel(player.ID))
{
return;
}
char infoPanelText[512];
FormatEx(infoPanelText, sizeof(infoPanelText), GetInfoPanel(player, info));
if (infoPanelText[0] != '\0')
{
PrintCSGOHUDText(player.ID, infoPanelText);
}
}
static bool NothingEnabledInInfoPanel(KZPlayer player)
{
bool noTimerText = player.TimerText != TimerText_InfoPanel;
bool noSpeedText = player.SpeedText != SpeedText_InfoPanel || player.Paused;
bool noKeys = player.ShowKeys == ShowKeys_Disabled
|| player.ShowKeys == ShowKeys_Spectating && player.Alive;
return noTimerText && noSpeedText && noKeys;
}
static char[] GetInfoPanel(KZPlayer player, HUDInfo info)
{
char infoPanelText[512];
FormatEx(infoPanelText, sizeof(infoPanelText),
"%s%s%s%s",
GetSpectatorString(player, info),
GetTimeString(player, info),
GetSpeedString(player, info),
GetKeysString(player, info));
if (infoPanelText[0] == '\0')
{
return infoPanelText;
}
else
{
Format(infoPanelText, sizeof(infoPanelText), "%s", infoPanelText);
}
TrimString(infoPanelText);
return infoPanelText;
}
static char[] GetSpectatorString(KZPlayer player, HUDInfo info)
{
char spectatorString[255];
if (player.SpecListPosition != SpecListPosition_InfoPanel || player.ShowSpectators == ShowSpecs_Disabled)
{
return spectatorString;
}
// Only return something if the player is alive or observing someone else
if (player.Alive || player.ObserverTarget != -1)
{
FormatEx(spectatorString, sizeof(spectatorString), "%s", FormatSpectatorTextForInfoPanel(player, KZPlayer(info.ID)));
}
return spectatorString;
}
static char[] GetTimeString(KZPlayer player, HUDInfo info)
{
char timeString[128];
if (player.TimerText != TimerText_InfoPanel)
{
timeString = "";
}
else if (info.TimerRunning)
{
if (player.GetHUDOption(HUDOption_TimerType) == TimerType_Enabled)
{
switch (info.TimeType)
{
case TimeType_Nub:
{
FormatEx(timeString, sizeof(timeString),
"%T: %s %s\n",
"Info Panel Text - Time", player.ID,
GOKZ_HUD_FormatTime(player.ID, info.Time),
GetPausedString(player, info));
}
case TimeType_Pro:
{
FormatEx(timeString, sizeof(timeString),
"%T: %s %s\n",
"Info Panel Text - Time", player.ID,
GOKZ_HUD_FormatTime(player.ID, info.Time),
GetPausedString(player, info));
}
}
}
else
{
FormatEx(timeString, sizeof(timeString),
"%T: %s %s\n",
"Info Panel Text - Time", player.ID,
GOKZ_HUD_FormatTime(player.ID, info.Time),
GetPausedString(player, info));
}
}
else
{
FormatEx(timeString, sizeof(timeString),
"%T: %T %s\n",
"Info Panel Text - Time", player.ID,
"Info Panel Text - Stopped", player.ID,
GetPausedString(player, info));
}
return timeString;
}
static char[] GetPausedString(KZPlayer player, HUDInfo info)
{
char pausedString[64];
if (info.Paused)
{
FormatEx(pausedString, sizeof(pausedString),
"(%T)",
"Info Panel Text - PAUSED", player.ID);
}
else
{
pausedString = "";
}
return pausedString;
}
static char[] GetSpeedString(KZPlayer player, HUDInfo info)
{
char speedString[128];
if (player.SpeedText != SpeedText_InfoPanel || info.Paused)
{
speedString = "";
}
else
{
if (info.OnGround || info.OnLadder || info.Noclipping)
{
FormatEx(speedString, sizeof(speedString),
"%T: %.0f u/s\n",
"Info Panel Text - Speed", player.ID,
RoundToPowerOfTen(info.Speed, -2));
infoPanelShowDuckString[info.ID] = false;
}
else
{
if (GOKZ_HUD_GetOption(player.ID, HUDOption_DeadstrafeColor) == DeadstrafeColor_Enabled
&& Movement_GetVerticalVelocity(info.ID) > 0.0 && Movement_GetVerticalVelocity(info.ID) < 140.0)
{
FormatEx(speedString, sizeof(speedString),
"%T: %.0f %s\n",
"Info Panel Text - Speed", player.ID,
RoundToPowerOfTen(info.Speed, -2),
GetTakeoffString(info));
}
else
{
FormatEx(speedString, sizeof(speedString),
"%T: %.0f %s\n",
"Info Panel Text - Speed", player.ID,
RoundToPowerOfTen(info.Speed, -2),
GetTakeoffString(info));
}
}
}
return speedString;
}
static char[] GetTakeoffString(HUDInfo info)
{
char takeoffString[96], duckString[32];
if (infoPanelShowDuckString[info.ID]
|| (infoPanelOnGroundLast[info.ID]
&& !info.HitBhop
&& info.IsTakeoff
&& info.Jumped
&& info.Ducking
&& (infoPanelDuckPressedLast[info.ID] || GOKZ_GetCoreOption(info.ID, Option_Mode) == Mode_Vanilla)))
{
duckString = " C";
infoPanelShowDuckString[info.ID] = true;
}
else
{
duckString = "";
infoPanelShowDuckString[info.ID] = false;
}
if (info.HitJB)
{
FormatEx(takeoffString, sizeof(takeoffString),
"(%.0f)%s",
RoundToPowerOfTen(info.TakeoffSpeed, -2),
duckString);
}
else if (info.HitPerf)
{
FormatEx(takeoffString, sizeof(takeoffString),
"(%.0f)%s",
RoundToPowerOfTen(info.TakeoffSpeed, -2),
duckString);
}
else
{
FormatEx(takeoffString, sizeof(takeoffString),
"(%.0f)%s",
RoundToPowerOfTen(info.TakeoffSpeed, -2),
duckString);
}
return takeoffString;
}
static char[] GetKeysString(KZPlayer player, HUDInfo info)
{
char keysString[64];
if (player.ShowKeys == ShowKeys_Disabled)
{
keysString = "";
}
else if (player.ShowKeys == ShowKeys_Spectating && player.Alive)
{
keysString = "";
}
else
{
int buttons = info.Buttons;
FormatEx(keysString, sizeof(keysString),
"%T: %c %c %c %c %c %c\n",
"Info Panel Text - Keys", player.ID,
buttons & IN_MOVELEFT ? 'A' : '_',
buttons & IN_FORWARD ? 'W' : '_',
buttons & IN_BACK ? 'S' : '_',
buttons & IN_MOVERIGHT ? 'D' : '_',
buttons & IN_DUCK ? 'C' : '_',
buttons & IN_JUMP ? 'J' : '_');
}
return keysString;
}
// Credits to Franc1sco (https://github.com/Franc1sco/FixHintColorMessages)
void PrintCSGOHUDText(int client, const char[] format)
{
char buff[HUD_MAX_HINT_SIZE];
Format(buff, sizeof(buff), "%s", format);
for (int i = strlen(buff); i < sizeof(buff) - 1; i++)
{
buff[i] = ' ';
}
buff[sizeof(buff) - 1] = '\0';
Protobuf pb = view_as(StartMessageOne("TextMsg", client, USERMSG_BLOCKHOOKS));
pb.SetInt("msg_dst", 4);
pb.AddString("params", "#SFUI_ContractKillStart");
pb.AddString("params", buff);
pb.AddString("params", NULL_STRING);
pb.AddString("params", NULL_STRING);
pb.AddString("params", NULL_STRING);
pb.AddString("params", NULL_STRING);
EndMessage();
}