// Untitled-1.sp
// SourceMod plugin: display player's HP and SP with horizontal bars
// Place in: addons/sourcemod/scripting/Untitled-1.sp
#include <sourcemod>
#include <sdktools>
public Plugin myinfo =
{
name = "HP_SP_Bars",
author = "GitHub Copilot",
description = "Shows HP and SP as horizontal bars using HUD text",
version = "1.0",
url = ""
};
#define BAR_LEN 20
public void OnPluginStart()
{
// Update HUD for all players ~4 times per second
CreateTimer(0.25, Timer_UpdateHud, _, TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE);
}
public Action Timer_UpdateHud(Handle timer)
{
HudTextParams params;
params.x = -1.0; // -1 = center horizontally
params.y = 0.85; // near bottom
params.channel = 5; // unique channel so it overwrites itself
params.holdTime = 0.3;
params.fadeIn = 0.05;
params.fadeOut = 0.05;
params.effect = 0;
int maxClients = MaxClients;
char msg[256];
// Set channel once before the loop
params.channel = 5;
for (int client = 1; client <= maxClients; client++)
{
if (!IsClientInGame(client) || !IsPlayerAlive(client))
{
// clear HUD for not-in-game players
ShowHudText(client, params, "");
continue;
}
// Health
int hp = GetClientHealth(client);
int hpMax = 100;
// try to fetch max health entity prop if available
int tryMax = GetEntProp(client, Prop_Data, "m_iMaxHealth");
if (tryMax > 0) hpMax = tryMax;
// Stamina (SP) - property names differ by gamemode/mod; try common names
float sp = GetEntPropFloat(client, Prop_Data, "m_flStamina");
if (sp == 0.0)
{
sp = GetEntPropFloat(client, Prop_Data, "m_flStaminaLevel");
}
if (sp == 0.0)
{
// fallback: use duck amount or sprint? (best-effort)
// 使用 m_flMaxspeed 作为体力回退方案并不准确,可能导致显示误导。
// TODO: 优化回退逻辑以更准确反映体力值。
sp = GetEntPropFloat(client, Prop_Send, "m_flMaxspeed"); // not real SP; just fallback
}
float spMax = GetEntPropFloat(client, Prop_Data, "m_flMaxStamina");
if (spMax <= 0.01)
{
spMax = 100.0; // default max stamina if property not found
}
// Build bars
char hpBar[64];
char spBar[64];
hpBar[0] = '\0';
spBar[0] = '\0';
int filledHP = RoundToFloor(float(hp) / float(hpMax) * float(BAR_LEN));
if (filledHP < 0) filledHP = 0;
if (filledHP > BAR_LEN) filledHP = BAR_LEN;
int filledSP = RoundToFloor(sp / spMax * float(BAR_LEN));
if (filledSP < 0) filledSP = 0;
if (filledSP > BAR_LEN) filledSP = BAR_LEN;
for (int i = 0; i < BAR_LEN; i++)
{
if (i < filledHP)
StrCat(hpBar, sizeof(hpBar), "|");
else
StrCat(hpBar, sizeof(hpBar), "-");
if (i < filledSP)
StrCat(spBar, sizeof(spBar), "|");
else
StrCat(spBar, sizeof(spBar), "-");
// Assemble HUD message: HP then SP on next line
char hpLine[128];
// Assemble HUD message: HP then SP on next line
Format(msg, sizeof(msg), "HP: [%s] %d/%d\nSP: [%s] %d/%d", hpBar, hp, hpMax, spBar, RoundToNearest(sp), RoundToNearest(spMax));
// Show to player
ShowHudText(client, params, msg);
}
ShowHudText(client, params, msg);
params.channel = 5;
ShowHudText(client, params, msg);
}
return Plugin_Continue;
}