From cdb1d02bc78b7b665aa7d8bacb4a132eb02c2a98 Mon Sep 17 00:00:00 2001 From: WessTorn Date: Tue, 24 Oct 2023 19:51:10 +0300 Subject: [PATCH] add stats, ownage, bestround --- data/lang/hidenseek.txt | 10 ++ hns_main.sma | 13 ++- hns_ownage.sma | 47 ++++++++ hns_showbest.sma | 183 +++++++++++++++++++++++++++++++ hns_stats.sma | 219 +++++++++++++++++++++++++++++++++++++ include/hns_mode_main.inc | 4 +- include/hns_mode_stats.inc | 10 ++ 7 files changed, 482 insertions(+), 4 deletions(-) create mode 100644 hns_ownage.sma create mode 100644 hns_showbest.sma create mode 100644 hns_stats.sma create mode 100644 include/hns_mode_stats.inc diff --git a/data/lang/hidenseek.txt b/data/lang/hidenseek.txt index 8b85b53..ac0aef7 100644 --- a/data/lang/hidenseek.txt +++ b/data/lang/hidenseek.txt @@ -19,6 +19,11 @@ KNIFE_HIDE = Hide knife KNIFE_CT = Hide for \yCT \r%s KNIFE_TT = Hide for \yTT \r%s +ROUNDINFO_ON = [^3%s^1] Round info is now ^3enabled. +ROUNDINFO_OFF = [^3%s^1] Round info is now ^3disabled. + +HNS_OWNAGE = %n owned %n's head! + HNS_YES = Yes HNS_NO = No @@ -43,5 +48,10 @@ KNIFE_HIDE = Спрятать нож KNIFE_CT = Спрятать у \yКТ \r%s KNIFE_TT = Спрятать у \yТТ \r%s +ROUNDINFO_ON = [^3%s^1] Информация о раунде ^3включена. +ROUNDINFO_OFF = [^3%s^1] Информация о раунде ^3выключена. + +HNS_OWNAGE = %n запрыгнул на голову %n! + HNS_YES = Да HNS_NO = Нет \ No newline at end of file diff --git a/hns_main.sma b/hns_main.sma index c36a4c8..1e7e481 100644 --- a/hns_main.sma +++ b/hns_main.sma @@ -38,7 +38,9 @@ new const g_szDefaultEntities[][] = { } enum _: Forwards_s { - hns_team_swap + hns_round_start, + hns_team_swap, + hns_round_end }; new g_hForwards[Forwards_s]; @@ -82,7 +84,9 @@ public plugin_init() { set_task(0.5, "delayed_mode"); + g_hForwards[hns_round_start] = CreateMultiForward("hns_round_start", ET_CONTINUE); g_hForwards[hns_team_swap] = CreateMultiForward("hns_team_swap", ET_CONTINUE); + g_hForwards[hns_round_end] = CreateMultiForward("hns_round_end", ET_CONTINUE); register_dictionary("hidenseek.txt"); } @@ -150,6 +154,7 @@ public rgFreezeEnd() { public rgRoundStart() { set_task(1.0, "taskDestroyBreakables"); + ExecuteForward(g_hForwards[hns_round_start]); } public rgPlayerResetMaxSpeed(id) { @@ -171,8 +176,8 @@ public rgPlayerSpawn(id) { public checkBalanceTeams() { new iPlayers[MAX_PLAYERS], iCTNum, iTTNum - get_players(iPlayers, iCTNum, "he", "CT"); - get_players(iPlayers, iTTNum, "he", "TERRORIST"); + get_players(iPlayers, iCTNum, "che", "CT"); + get_players(iPlayers, iTTNum, "che", "TERRORIST"); if (abs(iCTNum - iTTNum) < 2) return PLUGIN_HANDLED; @@ -294,6 +299,8 @@ public rgRoundEnd(WinStatus: status, ScenarioEventEndRound: event, Float:tmDelay } } + ExecuteForward(g_hForwards[hns_round_end]); + return HC_CONTINUE; } diff --git a/hns_ownage.sma b/hns_ownage.sma new file mode 100644 index 0000000..552360d --- /dev/null +++ b/hns_ownage.sma @@ -0,0 +1,47 @@ +#include +#include +#include + +#define rg_get_user_team(%0) get_member(%0, m_iTeam) + +new Float:g_pCvarDelay; + +new Float:g_flLastHeadTouch[MAX_PLAYERS + 1]; + +new g_hForwardOwnage; + +new const g_szSound[][] = { + "openhns/mario.wav", + "openhns/ownage.wav" +}; + +public plugin_init() { + register_plugin("HNS Ownage", "1.0", "OpenHNS"); + + bind_pcvar_float(register_cvar("hns_ownage_delay", "5.0"), g_pCvarDelay); + + register_touch("player", "player", "iTouchPlayer"); + + g_hForwardOwnage = CreateMultiForward("hns_ownage", ET_CONTINUE, FP_CELL, FP_CELL); +} + +public plugin_precache() { + for(new i; i < sizeof(g_szSound); i++) + precache_sound(g_szSound[i]); +} + +public iTouchPlayer(iToucher, iTouched) { + if(entity_get_int(iToucher, EV_INT_flags) & FL_ONGROUND && entity_get_edict(iToucher, EV_ENT_groundentity) == iTouched && rg_get_user_team(iToucher) == TEAM_TERRORIST && rg_get_user_team(iTouched) == TEAM_CT) { + new Float:flGametime = get_gametime(); + + if(flGametime > (g_flLastHeadTouch[iToucher] + g_pCvarDelay)) { + set_dhudmessage(250, 255, 0, -1.0, 0.2, .holdtime = 4.0); + show_dhudmessage(0, "%L", LANG_PLAYER, "HNS_OWNAGE", iToucher, iTouched); + + g_flLastHeadTouch[iToucher] = flGametime; + rg_send_audio(0, g_szSound[random(sizeof(g_szSound))]); + + ExecuteForward(g_hForwardOwnage, _, iToucher, iTouched); + } + } +} \ No newline at end of file diff --git a/hns_showbest.sma b/hns_showbest.sma new file mode 100644 index 0000000..f7d8945 --- /dev/null +++ b/hns_showbest.sma @@ -0,0 +1,183 @@ +#include + +#include +#include + +#define rg_get_user_team(%0) get_member(%0, m_iTeam) + +#define TASK_SHOWSTATS 1328 + +new g_szPrefix[24]; + +enum _: PLAYER_STATS { + PLR_STATS_KILLS, + PLR_STATS_DEATHS, + PLR_STATS_ASSISTS, + PLR_STATS_STABS, + PLR_STATS_DMG_CT, + PLR_STATS_DMG_TT, + Float:PLR_STATS_RUNNED, + Float:PLR_STATS_FLASHTIME, + Float:PLR_STATS_SURVTIME, + PLR_STATS_OWNAGES, +} + +new g_StatsRound[MAX_PLAYERS + 1][PLAYER_STATS]; + +new bool:g_bRoundInfo[MAX_PLAYERS + 1]; + +new g_eBestIndex[PLAYER_STATS]; +new g_eBestStats[PLAYER_STATS]; + +new g_szMess[2048]; + +new g_iSecShow; + +new g_HudSync; + +public plugin_init() { + register_plugin("HNS Show round best players", "1.0", "OpenHNS"); + + register_clcmd("say /roundinfo", "cmdRoundInfo"); + register_clcmd("say_team /roundinfo", "cmdRoundInfo"); + + g_HudSync = CreateHudSyncObj(); +} + +public client_putinserver(id) { + g_bRoundInfo[id] = true; +} + +public plugin_cfg() { + hns_get_prefix(g_szPrefix, charsmax(g_szPrefix)); +} + +public cmdRoundInfo(id) { + g_bRoundInfo[id] = !g_bRoundInfo[id]; + + if (g_bRoundInfo[id]) + client_print_color(id, print_team_blue, "%L", id, "ROUNDINFO_ON", g_szPrefix); + else + client_print_color(id, print_team_blue, "%L", id, "ROUNDINFO_OFF", g_szPrefix); + + return PLUGIN_HANDLED; +} + +public hns_round_end() { + new iPlayers[MAX_PLAYERS], iCTNum, iTTNum + get_players(iPlayers, iCTNum, "che", "CT"); + get_players(iPlayers, iTTNum, "che", "TERRORIST"); + + if (iCTNum + iTTNum > 1) { + set_best_stats(); + + set_best_mess(); + + g_iSecShow = 10; + set_task(1.0, "taskShowStats", TASK_SHOWSTATS, .flags = "b"); + } +} + +public set_best_stats() { + new iPlayers[MAX_PLAYERS], iNum; + get_players(iPlayers, iNum, "ch"); + + for (new i = 0; i < iNum; i++) { + new id = iPlayers[i]; + + get_player_stats(id); + + for (new j = 0; j < PLAYER_STATS; j++) { + if (g_StatsRound[id][j] > g_eBestStats[j]) + { + g_eBestStats[j] = g_StatsRound[id][j]; + g_eBestIndex[j] = id; + } + } + } +} + +public get_player_stats(id) { + g_StatsRound[id][PLR_STATS_KILLS] = hns_get_stats_kills(id); + g_StatsRound[id][PLR_STATS_DEATHS] = hns_get_stats_deaths(id); + g_StatsRound[id][PLR_STATS_ASSISTS] = hns_get_stats_assists(id); + g_StatsRound[id][PLR_STATS_STABS] = hns_get_stats_stabs(id); + g_StatsRound[id][PLR_STATS_DMG_CT] = hns_get_stats_dmgct(id); + g_StatsRound[id][PLR_STATS_DMG_TT] = hns_get_stats_dmgtt(id); + g_StatsRound[id][PLR_STATS_RUNNED] = hns_get_stats_run(id); + g_StatsRound[id][PLR_STATS_FLASHTIME] = hns_get_stats_flashtime(id); + g_StatsRound[id][PLR_STATS_SURVTIME] = hns_get_stats_surv(id); + g_StatsRound[id][PLR_STATS_OWNAGES] = hns_get_stats_ownages(id); +} + +public set_best_mess() { + new iLen = format(g_szMess, sizeof g_szMess - 1, "Best players of the round:^n^n"); + + new sTime[24]; + fnConvertTime(g_eBestStats[PLR_STATS_SURVTIME], sTime, charsmax(sTime)); + + if (g_eBestIndex[PLR_STATS_SURVTIME]) iLen += format(g_szMess[iLen], sizeof g_szMess - iLen, "Survived: %n - %s^n", g_eBestIndex[PLR_STATS_SURVTIME], sTime) + if (g_eBestIndex[PLR_STATS_OWNAGES]) iLen += format(g_szMess[iLen], sizeof g_szMess - iLen, "Ownages: %n - %d^n", g_eBestIndex[PLR_STATS_OWNAGES], g_eBestStats[PLR_STATS_OWNAGES]) + if (g_eBestIndex[PLR_STATS_KILLS]) iLen += format(g_szMess[iLen], sizeof g_szMess - iLen, "Killed: %n - %d^n", g_eBestIndex[PLR_STATS_KILLS], g_eBestStats[PLR_STATS_KILLS]) + if (g_eBestIndex[PLR_STATS_ASSISTS]) iLen += format(g_szMess[iLen], sizeof g_szMess - iLen, "Assists: %n - %d^n", g_eBestIndex[PLR_STATS_ASSISTS], g_eBestStats[PLR_STATS_ASSISTS]) + if (g_eBestIndex[PLR_STATS_STABS]) iLen += format(g_szMess[iLen], sizeof g_szMess - iLen, "Stabs: %n - %d^n", g_eBestIndex[PLR_STATS_STABS], g_eBestStats[PLR_STATS_STABS]) + if (g_eBestIndex[PLR_STATS_DMG_CT]) iLen += format(g_szMess[iLen], sizeof g_szMess - iLen, "CT Dmg: %n - %d^n", g_eBestIndex[PLR_STATS_DMG_CT], g_eBestStats[PLR_STATS_DMG_CT]) + if (g_eBestIndex[PLR_STATS_DMG_TT]) iLen += format(g_szMess[iLen], sizeof g_szMess - iLen, "TT Dmg: %n - %d^n", g_eBestIndex[PLR_STATS_DMG_TT], g_eBestStats[PLR_STATS_DMG_TT]) + if (g_eBestIndex[PLR_STATS_RUNNED]) iLen += format(g_szMess[iLen], sizeof g_szMess - iLen, "Runned: %n - %.2f^n", g_eBestIndex[PLR_STATS_RUNNED], g_eBestStats[PLR_STATS_RUNNED]) + if (g_eBestIndex[PLR_STATS_FLASHTIME]) iLen += format(g_szMess[iLen], sizeof g_szMess - iLen, "Flashed: %n - %.2f^n", g_eBestIndex[PLR_STATS_FLASHTIME], g_eBestStats[PLR_STATS_FLASHTIME]) +} + +public fnConvertTime(Float:time, convert_time[], len) { + new sTemp[24]; + new Float:fSeconds = time, iMinutes; + + iMinutes = floatround(fSeconds / 60.0, floatround_floor); + fSeconds -= iMinutes * 60.0; + new intpart = floatround(fSeconds, floatround_floor); + new Float:decpart = (fSeconds - intpart) * 100.0; + intpart = floatround(decpart); + + formatex(sTemp, charsmax(sTemp), "%02i:%02.0f.%d", iMinutes, fSeconds, intpart); + + formatex(convert_time, len, sTemp); + + return (PLUGIN_HANDLED); +} + + +public taskShowStats(id) { + if (g_iSecShow) { + g_iSecShow--; + } else { + remove_task(TASK_SHOWSTATS); + } + + new iPlayers[MAX_PLAYERS], iNum; + get_players(iPlayers, iNum, "ch"); + + for (new i = 0; i < iNum; i++) { + new id = iPlayers[i]; + + if (!is_user_connected(id) || !g_bRoundInfo[id]) { + continue; + } + + set_hudmessage(.red = 100, .green = 100, .blue = 100, .x = 0.1, .y = -1.0, .fxtime = 0.0, .holdtime = 1.0); + ShowSyncHudMsg(id, g_HudSync, g_szMess); + } +} + +public hns_round_start() { + new iPlayers[MAX_PLAYERS], iNum; + get_players(iPlayers, iNum, "ch"); + + for (new i = 0; i < iNum; i++) { + new id = iPlayers[i]; + arrayset(g_StatsRound[id], 0, PLAYER_STATS); + + } + + arrayset(g_eBestIndex, 0, PLAYER_STATS); + arrayset(g_eBestStats, 0, PLAYER_STATS); + g_szMess[0] = 0; +} \ No newline at end of file diff --git a/hns_stats.sma b/hns_stats.sma new file mode 100644 index 0000000..33e0c12 --- /dev/null +++ b/hns_stats.sma @@ -0,0 +1,219 @@ +#include +#include +#include + +#include + +forward hns_ownage(iToucher, iTouched); + +#define rg_get_user_team(%0) get_member(%0, m_iTeam) + +#define TASK_TIMER 54345 + +enum _: PLAYER_STATS { + PLR_STATS_KILLS, + PLR_STATS_DEATHS, + PLR_STATS_ASSISTS, + PLR_STATS_STABS, + PLR_STATS_DMG_CT, + PLR_STATS_DMG_TT, + Float:PLR_STATS_AVG_SPEED, + Float:PLR_STATS_RUNNED, + Float:PLR_STATS_RUNTIME, + Float:PLR_STATS_FLASHTIME, + Float:PLR_STATS_SURVTIME, + PLR_STATS_OWNAGES, +} + +new g_StatsRound[MAX_PLAYERS + 1][PLAYER_STATS]; + +new iLastAttacker[MAX_PLAYERS + 1]; + +new Float:last_position[MAX_PLAYERS+ 1][3]; + +public plugin_init() { + register_plugin("HNS Stats", "1.0", "OpenHNS"); // Garey + + RegisterHookChain(RG_CBasePlayer_Killed, "rgPlayerKilled", true); + RegisterHookChain(RG_CBasePlayer_TakeDamage, "rgPlayerTakeDamage", false); + RegisterHookChain(RG_CBasePlayer_PreThink, "rgPlayerPreThink", true); + RegisterHookChain(RG_CSGameRules_FlPlayerFallDamage, "rgPlayerFallDamage", true); + RegisterHookChain(RG_CSGameRules_OnRoundFreezeEnd, "rgRoundFreezeEnd", true); + RegisterHookChain(RG_CSGameRules_RestartRound, "rgRestartRound", true); +} + +public plugin_natives() { + register_native("hns_get_stats_kills", "native_get_stats_kills"); + register_native("hns_get_stats_deaths", "native_get_stats_deaths"); + register_native("hns_get_stats_assists", "native_get_stats_assists"); + register_native("hns_get_stats_stabs", "native_get_stats_stabs"); + register_native("hns_get_stats_dmgct", "native_get_stats_dmgct"); + register_native("hns_get_stats_dmgtt", "native_get_stats_dmgtt"); + register_native("hns_get_stats_run", "native_get_stats_run"); + register_native("hns_get_stats_flashtime", "native_get_stats_flashtime"); + register_native("hns_get_stats_surv", "native_get_stats_surv"); + register_native("hns_get_stats_ownages", "native_get_stats_ownages"); +} + +public native_get_stats_kills(amxx, params) { + enum { id = 1 }; + return g_StatsRound[get_param(id)][PLR_STATS_KILLS]; +} + +public native_get_stats_deaths(amxx, params) { + enum { id = 1 }; + return g_StatsRound[get_param(id)][PLR_STATS_DEATHS]; +} + +public native_get_stats_assists(amxx, params) { + enum { id = 1 }; + return g_StatsRound[get_param(id)][PLR_STATS_ASSISTS]; +} + +public native_get_stats_stabs(amxx, params) { + enum { id = 1 }; + return g_StatsRound[get_param(id)][PLR_STATS_STABS]; +} + +public native_get_stats_dmgct(amxx, params) { + enum { id = 1 }; + return g_StatsRound[get_param(id)][PLR_STATS_DMG_CT]; +} + +public native_get_stats_dmgtt(amxx, params) { + enum { id = 1 }; + return g_StatsRound[get_param(id)][PLR_STATS_DMG_TT]; +} + +public Float:native_get_stats_run(amxx, params) { + enum { id = 1 }; + return g_StatsRound[get_param(id)][PLR_STATS_RUNNED]; +} + +public Float:native_get_stats_flashtime(amxx, params) { + enum { id = 1 }; + return g_StatsRound[get_param(id)][PLR_STATS_FLASHTIME]; +} + +public Float:native_get_stats_surv(amxx, params) { + enum { id = 1 }; + return g_StatsRound[get_param(id)][PLR_STATS_SURVTIME]; +} + +public native_get_stats_ownages(amxx, params) { + enum { id = 1 }; + return g_StatsRound[get_param(id)][PLR_STATS_OWNAGES]; +} + +public hns_ownage(iToucher, iTouched) { + g_StatsRound[iToucher][PLR_STATS_OWNAGES]++; +} + +public rgPlayerKilled(victim, attacker) { + if (is_user_connected(attacker) && victim != attacker) { + g_StatsRound[attacker][PLR_STATS_KILLS]++; + } + + if (iLastAttacker[victim] && iLastAttacker[victim] != attacker) { + g_StatsRound[iLastAttacker[victim]][PLR_STATS_ASSISTS]++; + iLastAttacker[victim] = 0; + } +} + +public rgPlayerTakeDamage(iVictim, iWeapon, iAttacker, Float:fDamage) { + if (is_user_alive(iAttacker) && iVictim != iAttacker) { + new Float:fHealth; get_entvar(iVictim, var_health, fHealth); + if (fDamage < fHealth) { + iLastAttacker[iVictim] = iAttacker; + } + + g_StatsRound[iAttacker][PLR_STATS_STABS]++; + } +} + +public rgPlayerFallDamage(id) { + new dmg = floatround(Float:GetHookChainReturn(ATYPE_FLOAT)); + + if (rg_get_user_team(id) == TEAM_TERRORIST) { + g_StatsRound[id][PLR_STATS_DMG_TT] += dmg; + } else { + g_StatsRound[id][PLR_STATS_DMG_CT] += dmg; + } +} + +public PlayerBlind(const index, const inflictor, const attacker, const Float:fadeTime, const Float:fadeHold, const alpha) { + g_StatsRound[attacker][PLR_STATS_FLASHTIME] += fadeHold; +} + +public rgPlayerPreThink(id) { + static Float:origin[3]; + static Float:velocity[3]; + static Float:last_updated[MAX_PLAYERS + 1]; + static Float:frametime; + get_entvar(id, var_origin, origin); + get_entvar(id, var_velocity, velocity); + + frametime = get_gametime() - last_updated[id]; + if (frametime > 1.0) { + frametime = 1.0; + } + + if (is_user_alive(id)) { + if (rg_get_user_team(id) == TEAM_TERRORIST) { + if (vector_length(velocity) * frametime >= get_distance_f(origin, last_position[id])) { + velocity[2] = 0.0; + if (vector_length(velocity) > 125.0) { + g_StatsRound[id][PLR_STATS_RUNNED] += vector_length(velocity) * frametime; + g_StatsRound[id][PLR_STATS_RUNTIME] += frametime; + if (g_StatsRound[id][PLR_STATS_RUNTIME]) { + g_StatsRound[id][PLR_STATS_AVG_SPEED] = g_StatsRound[id][PLR_STATS_RUNNED] / g_StatsRound[id][PLR_STATS_RUNTIME]; + } + } + } + + } + } + + last_updated[id] = get_gametime(); + xs_vec_copy(origin, last_position[id]); +} + +public rgRoundFreezeEnd() { + set_task(0.25, "taskRoundEvent", .id = TASK_TIMER, .flags = "b"); +} + +public rgRestartRound() { + remove_task(TASK_TIMER); +} + +public taskRoundEvent() { + new iPlayers[MAX_PLAYERS], iNum; + get_players(iPlayers, iNum, "ech", "TERRORIST"); + + for (new i = 0; i < iNum; i++) + { + new id = iPlayers[i]; + if (is_user_alive(id)) + { + g_StatsRound[id][PLR_STATS_SURVTIME] += 0.25; + } + } +} + +public hns_round_end() { + remove_task(TASK_TIMER); +} + +public hns_round_start() { + new iPlayers[MAX_PLAYERS], iNum; + get_players(iPlayers, iNum, "ch"); + + for (new i = 0; i < iNum; i++) { + new id = iPlayers[i]; + arrayset(g_StatsRound[id], 0, PLAYER_STATS); + arrayset(last_position[id], 0, 3); + + iLastAttacker[id] = 0; + } + +} \ No newline at end of file diff --git a/include/hns_mode_main.inc b/include/hns_mode_main.inc index 2d1f1c7..00bfb3a 100644 --- a/include/hns_mode_main.inc +++ b/include/hns_mode_main.inc @@ -14,4 +14,6 @@ native hns_get_prefix(prefix[], len); native bool:is_deathmatch(); native hns_set_mode(HNS_MODE:eMode); -forward hns_team_swap(); \ No newline at end of file +forward hns_round_start(); +forward hns_team_swap(); +forward hns_round_end(); \ No newline at end of file diff --git a/include/hns_mode_stats.inc b/include/hns_mode_stats.inc new file mode 100644 index 0000000..a8ed955 --- /dev/null +++ b/include/hns_mode_stats.inc @@ -0,0 +1,10 @@ +native hns_get_stats_kills(id); +native hns_get_stats_deaths(id); +native hns_get_stats_assists(id); +native hns_get_stats_stabs(id); +native hns_get_stats_dmgct(id); +native hns_get_stats_dmgtt(id); +native Float:hns_get_stats_run(id); +native Float:hns_get_stats_flashtime(id); +native Float:hns_get_stats_surv(id); +native hns_get_stats_ownages(id); \ No newline at end of file