sm-plugins/ZItemKnockback/scripting/ZItemKnockback.sp
2019-09-05 19:45:20 +02:00

139 lines
3.5 KiB
SourcePawn

#pragma semicolon 1
#pragma newdecls required
#include <basic>
#include <sourcemod>
#include <sdkhooks>
#include <sdktools>
#include <dhooks>
public Plugin myinfo =
{
name = "ZItemKnockback",
author = "BotoX",
description = "",
version = "0.0",
url = ""
};
Handle hFireBulletDetour;
int g_LastAttacker = 0;
int g_LastVictim = 0;
public void OnPluginStart()
{
Handle hGameData = LoadGameConfigFile("ZItemKnockback.games");
if(!hGameData)
SetFailState("Failed to load ZItemKnockback gamedata.");
hFireBulletDetour = DHookCreateFromConf(hGameData, "CCSPlayer__FireBullet");
if(!hFireBulletDetour)
SetFailState("Failed to setup detour for CCSPlayer__FireBullet");
delete hGameData;
if(!DHookEnableDetour(hFireBulletDetour, false, Detour_OnFireBullet))
SetFailState("Failed to detour CCSPlayer__FireBullet.");
for(int client = 1; client <= MaxClients; client++)
{
if(IsClientInGame(client))
OnClientPutInServer(client);
}
}
public void OnClientPutInServer(int client)
{
SDKHook(client, SDKHook_WeaponEquipPost, OnWeaponEquip);
}
public Action OnWeaponEquip(int client, int entity)
{
if(!IsValidEntity(entity))
return;
char sClassname[64];
GetEntityClassname(entity, sClassname, sizeof(sClassname));
if(strcmp(sClassname, "weapon_knife", false) != 0)
return;
int HammerID = GetEntProp(entity, Prop_Data, "m_iHammerID");
if(!HammerID)
return;
CheckChildren(client, entity);
}
void CheckChildren(int client, int parent)
{
int entity = INVALID_ENT_REFERENCE;
while((entity = FindEntityByClassname(entity, "*")) != INVALID_ENT_REFERENCE)
{
if(GetEntPropEnt(entity, Prop_Data, "m_pParent") != parent)
continue;
char sClassname[64];
GetEntityClassname(entity, sClassname, sizeof(sClassname));
char sTargetname[64];
GetEntPropString(entity, Prop_Data, "m_iName", sTargetname, sizeof(sTargetname));
PrintToChatAll("%d child: \"%s\" %d (%s)", client, sClassname, entity, sTargetname);
if(!strncmp(sClassname, "func_physbox", 12, false) || !strcmp(sClassname, "func_breakable", false))
{
SDKHook(entity, SDKHook_OnTakeDamage, OnTakeDamage);
PrintToChatAll("Hooking \"%s\" %d (%s) OnTakeDamage", sClassname, entity, sTargetname);
}
else if(!strcmp(sClassname, "trigger_push", false))
{
AcceptEntityInput(entity, "Kill");
PrintToChatAll("Killing \"%s\" %d (%s)", sClassname, entity, sTargetname);
}
else
{
CheckChildren(client, entity);
}
}
}
public MRESReturn Detour_OnFireBullet(int pThis, Handle hParams)
{
PrintToServer("OnFireBullet called on entity %d!", pThis);
g_LastAttacker = 0;
g_LastVictim = 0;
return MRES_Handled;
}
public Action OnTakeDamage(int victim, int &attacker, int &inflictor, float &damage, int &damagetype, int &weapon, float damageForce[3], float damagePosition[3])
{
PrintToChatAll("OnTakeDamage(%d, %d, %d, %f, %d, %d)", victim, attacker, inflictor, damage, damagetype, weapon);
if(attacker <= 0 || attacker > MAXPLAYERS)
return Plugin_Continue;
int client = victim;
while((client = GetEntPropEnt(client, Prop_Data, "m_pParent")) != INVALID_ENT_REFERENCE)
{
if(client >= 1 && client <= MAXPLAYERS)
break;
}
PrintToChatAll("\tclient = %d", client);
if(client <= 0)
return Plugin_Handled;
// TODO: Fix for knife
if(g_LastAttacker == attacker && g_LastVictim == client)
return Plugin_Handled;
g_LastAttacker = attacker;
g_LastVictim = client;
victim = client;
PrintToChatAll("\tvictim = %d", victim);
SDKHooks_TakeDamage(victim, inflictor, attacker, damage, damagetype, weapon, damageForce, damagePosition);
return Plugin_Handled;
}