Just as a final, for somebody else.
SDKHook version:
PHP Code:
#pragma semicolon 1
#pragma newdecls required
#include <sourcemod>
#include <sdktools>
#include <sdkhooks>
int g_iDamage[MAXPLAYERS+1][MAXPLAYERS+1];
bool g_bDied[MAXPLAYERS+1];
int times;
public void OnPluginStart()
{
HookEvent("tank_spawn", Event_TankSpawn);
HookEvent("tank_killed", Event_TankKilled);
}
public Action Event_TankSpawn(Event event, char[] name, bool dontBroadcast)
{
int tank = GetClientOfUserId(event.GetInt("userid"));
if( tank && IsClientInGame(tank) )
{
TraceTank(tank);
}
}
void TraceTank(int tank)
{
g_bDied[tank] = false;
for( int i = 1; i <= MaxClients; i++ )
{
g_iDamage[i][tank] = 0;
}
times = 0;
SDKHook(tank, SDKHook_OnTakeDamage, OnTakeDamage);
//Seemse, not useul at all
//SDKHook(tank, SDKHook_OnTakeDamageAlive, OnTakeDamage); // alternate
}
public Action OnTakeDamage(int victim, int &attacker, int &inflictor, float &damage, int &damagetype, int &weapon, float damageForce[3], float damagePosition[3])
{
if( g_bDied[victim] )
{
return Plugin_Continue;
}
int health = GetEntProp(victim, Prop_Data, "m_iHealth");
if( RoundToFloor(damage) >= health )
{
PrintToChatAll("incap. Damage = %f. Health: %i", damage, health);
damage = float(health);
g_bDied[victim] = true;
}
times ++;
if( 0 < attacker <= MaxClients )
{
g_iDamage[attacker][victim] += RoundToFloor(damage);
PrintToChatAll("[%i] [%i] damage = %i. Health: %i", g_iDamage[attacker][victim], times, RoundToFloor(damage), GetEntProp(victim, Prop_Data, "m_iHealth") );
}
return Plugin_Continue;
}
public Action Event_TankKilled(Event event, char[] name, bool dontBroadcast)
{
int victim = GetClientOfUserId(event.GetInt("userid"));
if( !victim )
{
return Plugin_Continue;
}
for( int i = 1; i <= MaxClients; i++ )
{
if( IsClientInGame(i) && !IsFakeClient(i) )
{
PrintToChatAll("Damage done: %i", g_iDamage[i][victim]);
}
}
return Plugin_Continue;
}
"player_hurt" event version:
PHP Code:
#pragma semicolon 1
#pragma newdecls required
#include <sourcemod>
#include <sdktools>
int g_iDamage[MAXPLAYERS+1][MAXPLAYERS+1];
int g_iLastAttacker[MAXPLAYERS+1];
bool g_bDied[MAXPLAYERS+1];
float g_fLastHP[MAXPLAYERS+1];
int times;
public void OnPluginStart()
{
HookEvent("tank_spawn", Event_TankSpawn);
HookEvent("tank_killed", Event_TankKilled);
HookEvent("player_hurt", Event_PlayerHurt, EventHookMode_Pre);
}
public Action Event_TankSpawn(Event event, char[] name, bool dontBroadcast)
{
int tank = GetClientOfUserId(event.GetInt("userid"));
if( tank && IsClientInGame(tank) )
{
TraceTank(tank);
}
}
void TraceTank(int tank)
{
g_bDied[tank] = false;
g_fLastHP[tank] = float(GetEntProp(tank, Prop_Data, "m_iHealth"));
for( int i = 1; i <= MaxClients; i++ )
{
g_iDamage[i][tank] = 0;
}
times = 0;
}
public Action Event_PlayerHurt(Event event, char[] name, bool dontBroadcast)
{
int victim = GetClientOfUserId(event.GetInt("userid"));
int attacker = GetClientOfUserId(event.GetInt("attacker"));
float damage = event.GetFloat("dmg_health");
if( g_bDied[victim] )
{
return Plugin_Continue;
}
if( GetEntProp(victim, Prop_Send, "m_isIncapacitated") )
{
g_bDied[victim] = true;
damage = g_fLastHP[victim];
if( !attacker ) attacker = g_iLastAttacker[victim];
PrintToChatAll("incap. dmg: %f. att: %i. vic: %i", damage, attacker, victim);
}
g_fLastHP[victim] = event.GetFloat("health");
g_iLastAttacker[victim] = attacker;
times ++;
if( 0 < attacker <= MaxClients && 0 < victim <= MaxClients )
{
g_iDamage[attacker][victim] += RoundToFloor(damage);
PrintToChatAll("[%i] [%i] damage = %i. Health: %f", g_iDamage[attacker][victim], times, RoundToFloor(damage), event.GetFloat("health") );
}
return Plugin_Continue;
}
public Action Event_TankKilled(Event event, char[] name, bool dontBroadcast)
{
int victim = GetClientOfUserId(event.GetInt("userid"));
if( !victim )
{
return Plugin_Continue;
}
for( int i = 1; i <= MaxClients; i++ )
{
if( IsClientInGame(i) && !IsFakeClient(i) )
{
PrintToChatAll("Damage done: %i", g_iDamage[i][victim]);
}
}
return Plugin_Continue;
}
Event Hook version is much more complicated, because hook is called after health is already set (even with Pre-mode). Even more, after incap, hurt event is called with 0 attacker index. So, both attacker and hp are required to be pre-saved beforehand to get a reliable results.
__________________