#pragma semicolon 1
#include <amxmodx>
#include <hamsandwich>
#include <fakemeta>
#include <reapi>
new const DEFAULT_ATTACKER_FLAGS[] = "";
new const DEFAULT_ATTACKER_COLOR[] = "0 100 200";
new const DEFAULT_ATTACKER_POSITION[] = "-1.0 0.55";
new const DEFAULT_SPECTATORS_FLAGS[] = "d";
new const DEFAULT_SPECTATORS_COLOR[] = "0 100 200";
new const DEFAULT_SPECTATORS_POSITION[] = "-1.0 0.55";
new damager_block_wall;
new damager_multi_hits_count;
new damager_attacker_flags;
new damager_attacker_color[3];
new Float:damager_attacker_position[2];
new damager_spectators_flags;
new damager_spectators_color[3];
new Float:damager_spectators_position[2];
new g_pCvarAttackerFlags;
new g_pCvarAttackerColor;
new g_pCvarAttackerPosition;
new g_pCvarSpectatorsFlags;
new g_pCvarSpectatorsColor;
new g_pCvarSpectatorsPosition;
new g_iTotalHits[MAX_PLAYERS + 1];
new Float:g_flTotalDamage[MAX_PLAYERS + 1];
new Float:g_flLastDamageTime[MAX_PLAYERS + 1];
new Float:g_vecLastEndPos[3];
new g_iHudSync_Damage;
public plugin_init()
{
register_plugin("Simple Damager", "2.1.0", "fl0wer");
RegisterHookChain(RG_CBasePlayer_TraceAttack, "@CBasePlayer_TraceAttack_Post", true);
RegisterHookChain(RG_CBasePlayer_TakeDamage, "@CBasePlayer_TakeDamage_Post", true);
g_iHudSync_Damage = CreateHudSyncObj();
}
public plugin_cfg()
{
bind_pcvar_num(create_cvar("damager_block_wall", "0", _, "Show damage through walls^n0 - disabled^n1 - enabled", true, 0.0, true, 1.0), damager_block_wall);
bind_pcvar_num(create_cvar("damager_multi_hits", "1", _, "Show multi-hits counter if they more than one.^n0 - disabled^n1 - enabled", true, 0.0, true, 1.0), damager_multi_hits_count);
g_pCvarAttackerFlags = create_cvar("damager_attacker_flags", DEFAULT_ATTACKER_FLAGS, _, "Attacker damager flags");
UpdateFlagsVar(damager_attacker_flags, DEFAULT_ATTACKER_FLAGS);
hook_cvar_change(g_pCvarAttackerFlags, "@HandleCvarChanged");
g_pCvarAttackerColor = create_cvar("damager_attacker_color", DEFAULT_ATTACKER_COLOR, _, "Attacker damager colors");
UpdateColorVar(damager_attacker_color, g_pCvarAttackerColor, DEFAULT_ATTACKER_COLOR);
hook_cvar_change(g_pCvarAttackerColor, "@HandleCvarChanged");
g_pCvarAttackerPosition = create_cvar("damager_attacker_position", DEFAULT_ATTACKER_POSITION, _, "Attacker damager position");
UpdatePositionVar(damager_attacker_position, g_pCvarAttackerPosition, DEFAULT_ATTACKER_POSITION);
hook_cvar_change(g_pCvarAttackerPosition, "@HandleCvarChanged");
g_pCvarSpectatorsFlags = create_cvar("damager_spectators_flags", DEFAULT_SPECTATORS_FLAGS, _, "Spectators damager flags");
UpdateFlagsVar(damager_spectators_flags, DEFAULT_SPECTATORS_FLAGS);
hook_cvar_change(g_pCvarSpectatorsFlags, "@HandleCvarChanged");
g_pCvarSpectatorsColor = create_cvar("damager_spectators_color", DEFAULT_SPECTATORS_COLOR, _, "Spectators damager colors");
UpdateColorVar(damager_spectators_color, g_pCvarSpectatorsColor, DEFAULT_SPECTATORS_COLOR);
hook_cvar_change(g_pCvarSpectatorsColor, "@HandleCvarChanged");
g_pCvarSpectatorsPosition = create_cvar("damager_spectators_position", DEFAULT_SPECTATORS_POSITION, _, "Spectators damager position");
UpdatePositionVar(damager_spectators_position, g_pCvarSpectatorsPosition, DEFAULT_SPECTATORS_POSITION);
hook_cvar_change(g_pCvarSpectatorsPosition, "@HandleCvarChanged");
AutoExecConfig(true, "simple_damager");
}
@CBasePlayer_TraceAttack_Post(id, attacker, Float:damage, Float:vecDir[3], trace, bitsDamageType)
{
get_tr2(trace, TR_vecEndPos, g_vecLastEndPos);
}
@CBasePlayer_TakeDamage_Post(id, inflictor, attacker, Float:damage, bitsDamageType)
{
if (id == attacker || !is_user_connected(attacker))
return;
if (!rg_is_player_can_takedamage(id, attacker))
return;
if (damager_block_wall && !IsPlayerInView(attacker, id, bitsDamageType))
return;
new Float:time = get_gametime();
new shotsFired;
if (bitsDamageType & DMG_BULLET)
{
new activeItem = get_member(attacker, m_pActiveItem);
if (!is_nullent(activeItem) && (get_member(activeItem, m_Weapon_iWeaponState) & (WPNSTATE_GLOCK18_BURST_MODE | WPNSTATE_FAMAS_BURST_MODE)))
{
switch (get_member(activeItem, m_iId))
{
case WEAPON_FAMAS: shotsFired = get_member(activeItem, m_Weapon_iFamasShotsFired);
case WEAPON_GLOCK18: shotsFired = get_member(activeItem, m_Weapon_iGlock18ShotsFired);
}
}
}
if (!shotsFired && g_flLastDamageTime[attacker] != time)
{
g_iTotalHits[attacker] = 0;
g_flTotalDamage[attacker] = 0.0;
}
g_iTotalHits[attacker]++;
g_flTotalDamage[attacker] += damage;
g_flLastDamageTime[attacker] = time;
new intDamage = floatround(g_flTotalDamage[attacker], floatround_floor);
if (intDamage < 1)
return;
new fmtDamage[32];
if (damager_multi_hits_count && g_iTotalHits[attacker] > 1)
formatex(fmtDamage, charsmax(fmtDamage), "%d (%d*)", intDamage, g_iTotalHits[attacker]);
else
formatex(fmtDamage, charsmax(fmtDamage), "%d", intDamage);
if (!damager_attacker_flags || get_user_flags(attacker) & damager_attacker_flags)
{
new color[3];
new Float:position[2];
color = damager_attacker_color;
position = damager_attacker_position;
set_hudmessage(color[0], color[1], color[2], position[0], position[1], 2, 0.1, 1.5, 0.01, 0.01);
ShowSyncHudMsg(attacker, g_iHudSync_Damage, fmtDamage);
}
ShowDamageToSpectators(attacker, fmtDamage);
}
ShowDamageToSpectators(attacker, damage[])
{
#define GetObserverMode(%0) get_entvar(%0, var_iuser1)
new color[3];
new Float:position[2];
color = damager_spectators_color;
position = damager_spectators_position;
set_hudmessage(color[0], color[1], color[2], position[0], position[1], 2, 0.1, 1.5, 0.01, 0.01);
for (new i = 1; i <= MaxClients; i++)
{
if (i == attacker)
continue;
if (!is_user_connected(i))
continue;
if (damager_spectators_flags && !(get_user_flags(i) & damager_spectators_flags))
continue;
if (GetObserverMode(i) != OBS_IN_EYE)
continue;
if (get_member(i, m_hObserverTarget) != attacker)
continue;
ShowSyncHudMsg(i, g_iHudSync_Damage, damage);
}
}
bool:IsPlayerInView(attacker, id, bitsDamageType)
{
new Float:fraction;
new Float:vecSrc[3];
new Float:vecEnd[3];
if (bitsDamageType & DMG_GRENADE)
ExecuteHam(Ham_EyePosition, id, vecEnd);
else
vecEnd = g_vecLastEndPos;
ExecuteHam(Ham_EyePosition, attacker, vecSrc);
engfunc(EngFunc_TraceLine, vecSrc, vecEnd, IGNORE_MONSTERS, attacker, 0);
get_tr2(0, TR_flFraction, fraction);
if (fraction == 1.0)
return true;
return false;
}
@HandleCvarChanged(pCvar, const oldValue[], const newValue[])
{
if (pCvar == g_pCvarAttackerFlags)
{
UpdateFlagsVar(damager_attacker_flags, newValue);
}
else if (pCvar == g_pCvarAttackerColor)
{
UpdateColorVar(damager_attacker_color, pCvar, newValue, DEFAULT_ATTACKER_COLOR);
}
else if (pCvar == g_pCvarAttackerPosition)
{
UpdatePositionVar(damager_attacker_position, pCvar, newValue, DEFAULT_ATTACKER_POSITION);
}
else if (pCvar == g_pCvarSpectatorsFlags)
{
UpdateFlagsVar(damager_attacker_flags, newValue);
}
else if (pCvar == g_pCvarSpectatorsColor)
{
UpdateColorVar(damager_spectators_color, pCvar, newValue, DEFAULT_SPECTATORS_COLOR);
}
else if (pCvar == g_pCvarSpectatorsPosition)
{
UpdatePositionVar(damager_spectators_position, pCvar, newValue, DEFAULT_SPECTATORS_POSITION);
}
}
UpdateFlagsVar(&valueVar, const newValue[])
{
valueVar = read_flags(newValue);
}
UpdateColorVar(valueVar[3], pCvar, const newValue[], const defaultValue[] = "")
{
new color[3][5];
if (parse(newValue, color[0], charsmax(color[]), color[1], charsmax(color[]), color[2], charsmax(color[])) == sizeof(color))
{
for (new i = 0; i < sizeof(color); i++)
valueVar[i] = clamp(str_to_num(color[i]), 0, 255);
set_pcvar_string(pCvar, fmt("%d %d %d", valueVar[0], valueVar[1], valueVar[2]));
}
else
set_pcvar_string(pCvar, defaultValue);
}
UpdatePositionVar(Float:valueVar[2], pCvar, const newValue[], const defaultValue[] = "")
{
new position[2][6];
if (parse(newValue, position[0], charsmax(position[]), position[1], charsmax(position[])) == sizeof(position))
{
new Float:temp;
for (new i = 0; i < sizeof(position); i++)
{
temp = str_to_float(position[i]);
valueVar[i] = temp < 0.0 ? -1.0 : floatclamp(temp, 0.0, 1.0);
}
set_pcvar_string(pCvar, fmt("%f %f", valueVar[0], valueVar[1]));
}
else
set_pcvar_string(pCvar, defaultValue);
}