#include <amxmodx>
#include <csx>
#include <csstats_custom>
#if AMXX_VERSION_NUM < 183
#include <colorchat>
const MAX_PLAYERS = 32
const MAX_NAME_LENGTH = 32
#define client_disconnected client_disconnect
#endif
#define BUFF_LEN 1535
#define CSS_STYLE "http://space-zone.info/hlds/stats.css"
#define FRAGS 0
#define DEATHS 1
#define HS 2
#define TK 3
#define SHOTS 4
#define HITS 5
#define DAMAGE 6
#define RANK 7
#define ARRSIZE_STATS RANK +1
#define ARRSIZE_BODY HIT_RIGHTLEG +1
//#define NO_ROUND // Поддержка бесконечного раунда для /me, /hp
#define SAY_ME_HP // Выводить ли /me, /hp после смерти автоматически?
const NOT_ALIVE = 1 // Доступ к команде /me (0 - Только мёртвым. 1 - Всем.)
enum GetSayFunctions {SayRs, SayMe, SayHp, SayRank, SayHot, SayTop10, SayRankStats}
new const g_szHit[ARRSIZE_BODY][] = {"", "голову", "грудь", "живот", "левую руку", "правую руку", "левую ногу", "правую ногу"}
enum _:SayData {LastHit, HpKiller, ApKiller, KillerId, KillerName[MAX_NAME_LENGTH]}
new g_arrData[MAX_PLAYERS +1][SayData]
public plugin_init()
{
register_clcmd("say /rs", "clCMD_SayRs")
register_clcmd("say_team /rs", "clCMD_SayRs")
register_clcmd("say /me", "clCMD_SayMe")
register_clcmd("say_team /me", "clCMD_SayMe")
register_clcmd("say /hp", "clCMD_SayHp")
register_clcmd("say_team /hp", "clCMD_SayHp")
register_clcmd("say /rank", "clCMD_SayRank")
register_clcmd("say_team /rank", "clCMD_SayRank")
register_clcmd("say /hot", "clCMD_SayHot")
register_clcmd("say_team /hot", "clCMD_SayHot")
register_clcmd("say /top10", "clCMD_SayTop10")
register_clcmd("say_team /top10", "clCMD_SayTop10")
register_clcmd("say /rankstats", "clCMD_SayRankStats")
register_clcmd("say_team /rankstats", "clCMD_SayRankStats")
#if defined NO_ROUND
register_event("ResetHUD", "eResetHud", "be")
#else
register_event("HLTV", "StartRound", "a", "1=0", "2=0")
#endif
}
public clCMD_SayRs(id)
return Say(id, SayRs)
public clCMD_SayMe(id)
return Say(id, SayMe)
public clCMD_SayHp(id)
return Say(id, SayHp)
public clCMD_SayRank(id)
return Say(id, SayRank)
public clCMD_SayHot(id)
return Say(id, SayHot)
public clCMD_SayTop10(id)
return Say(id, SayTop10)
public clCMD_SayRankStats(id)
return Say(id, SayRankStats)
public client_putinserver(id)
arrayset(g_arrData[id], 0, SayData)
public client_disconnected(id)
arrayset(g_arrData[id], 0, SayData)
#if defined NO_ROUND
public eResetHud(id)
arrayset(g_arrData[id], 0, SayData)
#else
public StartRound()
{
new players[MAX_PLAYERS], pnum
get_players(players, pnum, "h")
for (new i; i < pnum; i ++)
arrayset(g_arrData[players[i]], 0, SayData)
}
#endif
public client_damage(attacker, victim, damage, wpn, hit, tk)
{
if (!is_user_connected(attacker) || attacker == victim) return
attacker = get_user_attacker(victim, 0, hit)
g_arrData[attacker][LastHit] = hit
}
public client_death(killer, victim, wpn, hit, tk)
{
if (!is_user_connected(killer) || killer == victim)
return
g_arrData[victim][KillerId] = killer
g_arrData[victim][HpKiller] = get_user_health(killer)
g_arrData[victim][ApKiller] = get_user_armor(killer)
get_user_name(killer, g_arrData[victim][KillerName], charsmax(g_arrData[][KillerName]))
#if defined SAY_ME_HP
Say(victim, SayMe)
Say(victim, SayHp)
#endif
}
Say(id, GetSayFunctions:type)
{
if (!is_user_connected(id))
return PLUGIN_HANDLED
switch(type)
{
case SayRs:
{
set_user_score(id, 0, 0)
client_cmd(id, "spk buttons/blip1.wav")
client_print_color(id, print_team_default, "^1[^4SayRs^1] Ваш счет ^3успешно ^1обнулён!")
}
case SayMe:
{
if (is_user_alive(id) && !NOT_ALIVE) client_print_color(id, print_team_default, "^1[^4SayMe^1] Команда доступна только ^3мёртвым ^1игрокам!")
else
{
new st[ARRSIZE_STATS], bh[ARRSIZE_BODY]
if (get_user_rstats(id, st, bh) && st[DAMAGE])
{
client_print_color(id, print_team_default, "^1[^4SayMe^1] Вы нанесли ^3%d ^1урона!", st[DAMAGE])
client_print_color(id, print_team_default, "^1[^4SayMe^1] Последнее попадание ^3в ^4%s", g_szHit[g_arrData[id][LastHit]])
}
else client_print_color(id, print_team_default, "^1[^4SayMe^1] Вы ни в кого ^3не ^1попали!")
}
}
case SayHp:
{
if (g_arrData[id][KillerId]) client_print_color(id, g_arrData[id][KillerId], "^1[^4SayHp^1] Вас убил ^3%s^1. У него осталось ^3%d^4HP ^1и ^3%d^4AP", g_arrData[id][KillerName], g_arrData[id][HpKiller], g_arrData[id][ApKiller])
else client_print_color(id, print_team_default, "^1[^4SayHp^1] Вас ^3никто ^1не убивал!")
}
case SayRank:
{
new st[ARRSIZE_STATS], bh[ARRSIZE_BODY]
new plRank = get_user_stats(id, st, bh)
if (!plRank) client_print_color(id, print_team_default, "^1[^4CSX^1] Нет данных!")
else
{
client_print_color(id, print_team_default, "^1[^4CSX^1] Вы занимаете ^3%d-е ^1место из ^3%d ^1игроков.", plRank, get_statsnum())
client_print_color(id, print_team_default, "^1[^4CSX^1] Убийств ^3%d^1, Смертей ^3%d^1, K/D ^3%0.2f^1%, HS ^3%0.2f^1%", st[FRAGS], st[DEATHS], kd(st[FRAGS], st[DEATHS]), hs(st[HS], st[FRAGS]))
}
}
case SayHot:
{
new players[MAX_PLAYERS], pnum
get_players(players, pnum, "h")
new current_top[MAX_PLAYERS][2]
if (pnum > 10) pnum = 10
for (new i, st[ARRSIZE_STATS], bh[ARRSIZE_BODY]; i < pnum; i ++)
{
current_top[i][0] = players[i]
current_top[i][1] = get_user_stats(players[i], st, bh)
}
SortCustom2D(current_top, sizeof current_top, "Sort_CurrentTop")
new OldLen, bool:IsCut, buff[BUFF_LEN], len = formatex(buff, BUFF_LEN, "<META http-equiv=Content-Type content='text/html;charset=UTF-8'><link href='%s' rel=stylesheet type=text/css>", CSS_STYLE)
len += formatex(buff[len], BUFF_LEN - len, "<p><strong>Oнлaйн игрoки</strong></p><table cellpadding=0><tr>")
len += formatex(buff[len], BUFF_LEN - len, "<th>#</th>")
len += formatex(buff[len], BUFF_LEN - len, "<th>Ник</th>")
len += formatex(buff[len], BUFF_LEN - len, "<th>Убийcтв</th>")
len += formatex(buff[len], BUFF_LEN - len, "<th>B гoлoву</th>")
len += formatex(buff[len], BUFF_LEN - len, "<th>Cмeртeй</th>")
len += formatex(buff[len], BUFF_LEN - len, "<th>Bыcтрeлoв</th>")
len += formatex(buff[len], BUFF_LEN - len, "<th>Пoпaдaний</th>")
len += formatex(buff[len], BUFF_LEN - len, "<th>Урoн</th>")
len += formatex(buff[len], BUFF_LEN - len, "</tr>")
for(new i, st[ARRSIZE_STATS], bh[ARRSIZE_BODY], player_id, szName[MAX_NAME_LENGTH]; i < sizeof current_top; i ++)
{
player_id = current_top[i][0]
if (!player_id)
{
continue
}
get_user_stats(player_id, st, bh)
get_user_name(player_id, szName, charsmax(szName))
replace_all(szName, charsmax(szName), "<", "<")
replace_all(szName, charsmax(szName), ">", ">")
OldLen = len
len += formatex(buff[len], BUFF_LEN - len, "<tr>")
len += formatex(buff[len], BUFF_LEN - len, "<td>%d</td>", current_top[i][1])
len += formatex(buff[len], BUFF_LEN - len, "<td>%s</td>", szName)
len += formatex(buff[len], BUFF_LEN - len, "<td>%d</td>", st[FRAGS])
len += formatex(buff[len], BUFF_LEN - len, "<td>%d</td>", st[HS])
len += formatex(buff[len], BUFF_LEN - len, "<td>%d</td>", st[DEATHS])
len += formatex(buff[len], BUFF_LEN - len, "<td>%d</td>", st[SHOTS])
len += formatex(buff[len], BUFF_LEN - len, "<td>%d</td>", st[HITS])
len += formatex(buff[len], BUFF_LEN - len, "<td>%d</td>", st[DAMAGE])
if (len + 9 >= BUFF_LEN)
{
buff[OldLen] = 0
IsCut = true
break
}
}
formatex(buff[IsCut ? OldLen : len], BUFF_LEN, "</tr></table>")
show_motd(id, buff, "Say /hot")
}
case SayTop10:
{
new statsNum = get_statsnum()
if (!statsNum) client_print_color(id, print_team_default, "^1[^4CSX^1] Нет данных!")
else
{
if (statsNum > 10) statsNum = 10
new OldLen, bool:IsCut, buff[BUFF_LEN], len = formatex(buff, BUFF_LEN, "<META http-equiv=Content-Type content='text/html;charset=UTF-8'><link href='%s' rel=stylesheet type=text/css>", CSS_STYLE)
len += formatex(buff[len], BUFF_LEN - len, "<p><strong>Тoп 10 лучшиx игрoкoв</strong></p><table cellpadding=0><tr>")
len += formatex(buff[len], BUFF_LEN - len, "<th>#</th>")
len += formatex(buff[len], BUFF_LEN - len, "<th>Ник</th>")
len += formatex(buff[len], BUFF_LEN - len, "<th>Убийcтв</th>")
len += formatex(buff[len], BUFF_LEN - len, "<th>B гoлoву</th>")
len += formatex(buff[len], BUFF_LEN - len, "<th>Cмeртeй</th>")
len += formatex(buff[len], BUFF_LEN - len, "<th>Bыcтрeлoв</th>")
len += formatex(buff[len], BUFF_LEN - len, "<th>Пoпaдaний</th>")
len += formatex(buff[len], BUFF_LEN - len, "<th>Урoн</th>")
len += formatex(buff[len], BUFF_LEN - len, "</tr>")
for (new i, st[ARRSIZE_STATS], bh[ARRSIZE_BODY], szName[MAX_NAME_LENGTH]; i < statsNum; ++ i)
{
get_stats(i, st, bh, szName, charsmax(szName))
replace_all(szName, charsmax(szName), "<", "<")
replace_all(szName, charsmax(szName), ">", ">")
OldLen = len
len += formatex(buff[len], BUFF_LEN - len, "<tr>")
len += formatex(buff[len], BUFF_LEN - len, "<td>%d</td>", i +1)
len += formatex(buff[len], BUFF_LEN - len, "<td>%s</td>", szName)
len += formatex(buff[len], BUFF_LEN - len, "<td>%d</td>", st[FRAGS])
len += formatex(buff[len], BUFF_LEN - len, "<td>%d</td>", st[HS])
len += formatex(buff[len], BUFF_LEN - len, "<td>%d</td>", st[DEATHS])
len += formatex(buff[len], BUFF_LEN - len, "<td>%d</td>", st[SHOTS])
len += formatex(buff[len], BUFF_LEN - len, "<td>%d</td>", st[HITS])
len += formatex(buff[len], BUFF_LEN - len, "<td>%d</td>", st[DAMAGE])
if (len + 9 >= BUFF_LEN)
{
buff[OldLen] = 0
IsCut = true
break
}
}
formatex(buff[IsCut ? OldLen : len], BUFF_LEN, "</tr></table>")
show_motd(id, buff, "Say /top10")
}
}
case SayRankStats:
{
new st[ARRSIZE_STATS], bh[ARRSIZE_BODY]
new plRank = get_user_stats(id, st, bh)
if (!plRank) client_print_color(id, print_team_default, "^1[^4CSX^1] Нет данных!")
else
{
new buff[BUFF_LEN], len
len += formatex(buff[len], BUFF_LEN - len, "<META http-equiv=Content-Type content='text/html;charset=UTF-8'><link href='%s' rel=stylesheet type=text/css>", CSS_STYLE)
len += formatex(buff[len], BUFF_LEN - len, "<p><strong>Oбщaя cтaтиcтикa</strong></p><table cellpadding=0><tr><td valign=top width=50%%><table cellspacing=0></td></tr><tr><th colspan=2>Вы нa %d мecтe из %d</th></tr>", plRank, get_statsnum())
len += formatex(buff[len], BUFF_LEN - len, "<tr><td>Убийcтв</td><td>%d</td></tr>", st[FRAGS])
len += formatex(buff[len], BUFF_LEN - len, "<tr><td>B гoлoву</td><td>%d</td></tr>", st[HS])
len += formatex(buff[len], BUFF_LEN - len, "<tr><td>Убил cвoих</td><td>%d</td></tr>", st[TK])
len += formatex(buff[len], BUFF_LEN - len, "<tr><td>Cмepтeй</td><td>%d</td></tr>", st[DEATHS])
len += formatex(buff[len], BUFF_LEN - len, "<tr><td>Bыcтpeлoв</td><td>%d</td>", st[SHOTS])
len += formatex(buff[len], BUFF_LEN - len, "<tr><td>Пoпaдaний</td><td>%d</td>", st[HITS])
len += formatex(buff[len], BUFF_LEN - len, "<tr><td>Haнёc урoн</td><td>%d</td></tr>", st[DAMAGE])
len += formatex(buff[len], BUFF_LEN - len, "<tr><td>Toчнocть</td><td>%0.2f%%</td></tr>", accuracy(st[HITS], st[SHOTS]))
len += formatex(buff[len], BUFF_LEN - len, "<tr><td>Эффeктивнocть</td><td>%0.2f%%</td></tr>", effec(st[FRAGS], st[DEATHS]))
len += formatex(buff[len], BUFF_LEN - len, "</table>")
len += formatex(buff[len], BUFF_LEN - len, "<td valign=top width=50%%><table cellspacing=0></td><tr><th colspan=2>Cтaтиcтикa пoпaдaний</th></tr>")
for (new i = 1; i < sizeof g_szHit; ++ i)
len += formatex(buff[len], BUFF_LEN - len, "<tr><td>B %s</td><td>%d</td></tr>", g_szHit[i], bh[i])
formatex(buff[len], BUFF_LEN - len, "</table>")
show_motd(id, buff, "Say /rankstats")
}
}
}
return PLUGIN_HANDLED
}
// Процент убийств/смертей.
stock Float:kd(kills, deaths)
return !kills ? (0.0) : (float(kills) / float(deaths))
// Процент убийств в голову.
stock Float:hs(hs_kills, kills)
return !hs_kills ? (0.0) : (100.0 * float(hs_kills) / float(kills))
// Toчнocть.
stock Float:accuracy(hits, shots)
return !shots ? (0.0) : (100.0 * float(hits) / float(shots))
// Эффeктивнocть.
stock Float:effec(kills, deaths)
return !kills ? (0.0) : (100.0 * float(kills) / float(kills + deaths))
// Сортировка игроков для команды hot.
public Sort_CurrentTop(const elem1[], const elem2[])
return (elem1[1] < elem2[1]) ? -1 : (elem1[1] > elem2[1]) ? 1 : 0