Untitled diff

Created Diff never expires
20 removals
Words removed54
Total words1086
Words removed (%)4.97
303 lines
57 additions
Words added148
Total words1180
Words added (%)12.54
340 lines
#pragma semicolon 1

#include <sourcemod>
#include <sourcemod>
#include <sdktools>
#include <sdktools>
#include <sdkhooks>
#include <sdkhooks>
#include <zombiereloaded>

#pragma newdecls required
//Create ConVar handles
//Create ConVar handles
ConVar g_ConVar_Enabled;
ConVar g_ConVar_Enabled;
ConVar g_ConVar_Debug;
ConVar g_ConVar_Debug;
ConVar g_ConVar_pDistance;
ConVar g_ConVar_pDistance;
ConVar g_ConVar_vKnockback;
ConVar g_ConVar_vKnockback;
ConVar g_ConVar_hKnockback;
ConVar g_ConVar_hKnockback;
ConVar g_ConVar_StamPenalty;
ConVar g_ConVar_StamPenalty;
ConVar g_ConVar_dmgCap;
ConVar g_ConVar_dmgCap;
//Separate ConVar variables to prevent looping in hooks
//Separate ConVar variables to prevent looping in hooks
bool g_Enabled = true;
bool g_Enabled = true;
bool g_Debug = false;
bool g_Debug = false;
float g_pDistance = 1.0;
float g_pDistance = 1.0;
float g_vKnockback = 1.0;
float g_vKnockback = 1.0;
float g_hKnockback = 1.0;
float g_hKnockback = 1.0;
float g_StamPenalty = 0.0;
float g_StamPenalty = 0.0;
float g_dmgCap = 50.0;
float g_dmgCap = 50.0;
int g_StaminaOffset = -1;
int g_StaminaOffset = -1;
//Create our hash map handles
//Create our hash map handles
StringMap hMapDirection;
StringMap hMapDirection;
StringMap hMapOrigin;
StringMap hMapOrigin;


public Plugin myinfo = {
public Plugin myinfo = {
name = "Nade_Kick",
name = "Nade_Kick",
author = "AgentWesker",
author = "AgentWesker",
description = "Zombie knockback plugin.",
description = "Zombie knockback plugin.",
version = "1.4",
version = "1.4",
url = "http://steam-gamers.net"
url = "http://steam-gamers.net"
};
};
public void OnPluginStart()
public void OnPluginStart()
{
{


//Get stamina offset
//Get stamina offset
g_StaminaOffset = FindSendPropInfo("CCSPlayer", "m_flStamina");
g_StaminaOffset = FindSendPropInfo("CCSPlayer", "m_flStamina");
if (g_StaminaOffset == -1) {
if (g_StaminaOffset == -1) {
SetFailState("CCSPlayer::m_flStamina could not be found.");
SetFailState("CCSPlayer::m_flStamina could not be found.");
}
}
//Stamina ConVar
//Stamina ConVar
g_ConVar_StamPenalty = CreateConVar("sm_nadekick_stampenalty", "100.0", "How much to slow the player. Default = 100.0", _, true, 0.0, true, 100.0);
g_ConVar_StamPenalty = CreateConVar("sm_nadekick_stampenalty", "100.0", "How much to slow the player. Default = 100.0", _, true, 0.0, true, 100.0);
g_StamPenalty = GetConVarFloat(g_ConVar_StamPenalty);
g_StamPenalty = GetConVarFloat(g_ConVar_StamPenalty);
HookConVarChange(g_ConVar_StamPenalty, OnStamPenaltyChanged);
HookConVarChange(g_ConVar_StamPenalty, OnStamPenaltyChanged);
//Damage Cap ConVar
//Damage Cap ConVar
g_ConVar_dmgCap = CreateConVar("sm_nadekick_dmgcap", "30.0", "How much damage can affect velocity. Default = 50.0", _, true, 1.0, true, 100.0);
g_ConVar_dmgCap = CreateConVar("sm_nadekick_dmgcap", "30.0", "How much damage can affect velocity. Default = 50.0", _, true, 1.0, true, 100.0);
g_dmgCap = GetConVarFloat(g_ConVar_dmgCap);
g_dmgCap = GetConVarFloat(g_ConVar_dmgCap);
HookConVarChange(g_ConVar_dmgCap, OnDmgCapChanged);
HookConVarChange(g_ConVar_dmgCap, OnDmgCapChanged);
//Enabled ConVar
//Enabled ConVar
g_ConVar_Enabled = CreateConVar("sm_nadekick_enabled", "1", "Enable/Disable the plugin. Enable = 1", _, true, 0.0, true, 1.0);
g_ConVar_Enabled = CreateConVar("sm_nadekick_enabled", "1", "Enable/Disable the plugin. Enable = 1", _, true, 0.0, true, 1.0);
g_Enabled = GetConVarBool(g_ConVar_Enabled);
g_Enabled = GetConVarBool(g_ConVar_Enabled);
HookConVarChange(g_ConVar_Enabled, OnEnabledChanged);
HookConVarChange(g_ConVar_Enabled, OnEnabledChanged);
//Debug ConVar
//Debug ConVar
g_ConVar_Debug = CreateConVar("sm_nadekick_debug", "0", "Print debug to chat. Enable = 1", _, true, 0.0, true, 1.0);
g_ConVar_Debug = CreateConVar("sm_nadekick_debug", "0", "Print debug to chat. Enable = 1", _, true, 0.0, true, 1.0);
g_Debug = GetConVarBool(g_ConVar_Debug);
g_Debug = GetConVarBool(g_ConVar_Debug);
HookConVarChange(g_ConVar_Debug, OnDebugChanged);
HookConVarChange(g_ConVar_Debug, OnDebugChanged);
//Distance ConVars
//Distance ConVars
g_ConVar_pDistance = CreateConVar("sm_nadekick_pdistance", "115.0", "How far to measure in front of attacker. Default = 115.0", _, true, 0.1, true, 1500.0);
g_ConVar_pDistance = CreateConVar("sm_nadekick_pdistance", "115.0", "How far to measure in front of attacker. Default = 115.0", _, true, 0.1, true, 1500.0);
g_pDistance = GetConVarFloat(g_ConVar_pDistance);
g_pDistance = GetConVarFloat(g_ConVar_pDistance);
HookConVarChange(g_ConVar_pDistance, OnPlayerDistanceChanged);
HookConVarChange(g_ConVar_pDistance, OnPlayerDistanceChanged);
//Knockback ConVars
//Knockback ConVars
g_ConVar_vKnockback = CreateConVar("sm_nadekick_vknockback", "20.0", "Vertical knockback multiplier. Default = 20.0", _, true, 0.1, true, 1000.0);
g_ConVar_vKnockback = CreateConVar("sm_nadekick_vknockback", "20.0", "Vertical knockback multiplier. Default = 20.0", _, true, 0.1, true, 1000.0);
g_ConVar_hKnockback = CreateConVar("sm_nadekick_hknockback", "30.0", "Horizontal knockback multiplier. Default = 30.0", _, true, 0.1, true, 1000.0);
g_ConVar_hKnockback = CreateConVar("sm_nadekick_hknockback", "30.0", "Horizontal knockback multiplier. Default = 30.0", _, true, 0.1, true, 1000.0);
g_vKnockback = GetConVarFloat(g_ConVar_vKnockback);
g_vKnockback = GetConVarFloat(g_ConVar_vKnockback);
g_hKnockback = GetConVarFloat(g_ConVar_hKnockback);
g_hKnockback = GetConVarFloat(g_ConVar_hKnockback);
HookConVarChange(g_ConVar_vKnockback, OnVerKnockbackChanged);
HookConVarChange(g_ConVar_vKnockback, OnVerKnockbackChanged);
HookConVarChange(g_ConVar_hKnockback, OnHorKnockbackChanged);
HookConVarChange(g_ConVar_hKnockback, OnHorKnockbackChanged);
//Create our hash maps
//Create our hash maps
hMapDirection = new StringMap();
hMapDirection = new StringMap();
hMapOrigin = new StringMap();
hMapOrigin = new StringMap();
//Execute the config and create if not yet made
//Execute the config and create if not yet made
AutoExecConfig(true, "nade_kick");
AutoExecConfig(true, "nade_kick");
// Late load
// Late load
for (new i = 1; i <= MaxClients; i++)
for (int i = 1; i <= MaxClients; i++)
{
{
if (IsClientInGame(i))
if (IsClientInGame(i))
{
{
OnClientPutInServer(i);
OnClientPutInServer(i);
}
}
}
}
}
}


public void OnPluginEnd()
//This is auto done if the plugin ends
/*public void OnPluginEnd()
{
{
//Close the handle if the plugin unloads
//Close the handle if the plugin unloads
delete hMapDirection;
delete hMapDirection;
delete hMapOrigin;
delete hMapOrigin;
}
}*/


public void OnEnabledChanged(Handle:cvar, const String:oldVal[], const String:newVal[])
public void OnEnabledChanged(ConVar cvar, const char[] oldVal, const char[] newVal)
{
{
if(StringToInt(newVal) == 1) {
if(StringToInt(newVal) == 1) {
g_Enabled = true;
g_Enabled = true;
HookClients();
} else {
} else {
g_Enabled = false;
g_Enabled = false;
UnHookClients();
}
}
}
}


public void OnDebugChanged(Handle:cvar, const String:oldVal[], const String:newVal[])
public void HookClients()
{
for (int i = 1; i <= MaxClients; i++)
{
if(IsClientInGame(i))
{
SDKHook(i, SDKHook_OnTakeDamagePost, OnTakeDamagePost);
}
}
}

public void UnHookClients()
{
for (int i = 1; i <= MaxClients; i++)
{
if(IsClientInGame(i))
{
SDKUnhook(i, SDKHook_OnTakeDamagePost, OnTakeDamagePost);
}
}
}

public void OnDebugChanged(ConVar cvar, const char[] oldVal, const char[] newVal)
{
{
if(StringToInt(newVal) == 1) {
if(StringToInt(newVal) == 1) {
g_Debug = true;
g_Debug = true;
} else {
} else {
g_Debug = false;
g_Debug = false;
}
}
}
}


public void OnDmgCapChanged(Handle:cvar, const String:oldVal[], const String:newVal[])
public void OnDmgCapChanged(ConVar cvar, const char[] oldVal, const char[] newVal)
{
{
g_dmgCap = StringToFloat(newVal);
g_dmgCap = StringToFloat(newVal);
}
}


public void OnStamPenaltyChanged(Handle:cvar, const String:oldVal[], const String:newVal[])
public void OnStamPenaltyChanged(ConVar cvar, const char[] oldVal, const char[] newVal)
{
{
g_StamPenalty = StringToFloat(newVal);
g_StamPenalty = StringToFloat(newVal);
}
}


public void OnPlayerDistanceChanged(Handle:cvar, const String:oldVal[], const String:newVal[])
public void OnPlayerDistanceChanged(ConVar cvar, const char[] oldVal, const char[] newVal)
{
{
g_pDistance = StringToFloat(newVal);
g_pDistance = StringToFloat(newVal);
}
}


public void OnVerKnockbackChanged(Handle:cvar, const String:oldVal[], const String:newVal[])
public void OnVerKnockbackChanged(ConVar cvar, const char[] oldVal, const char[] newVal)
{
{
g_vKnockback = StringToFloat(newVal);
g_vKnockback = StringToFloat(newVal);
}
}


public void OnHorKnockbackChanged(Handle:cvar, const String:oldVal[], const String:newVal[])
public void OnHorKnockbackChanged(ConVar cvar, const char[] oldVal, const char[] newVal)
{
{
g_hKnockback = StringToFloat(newVal);
g_hKnockback = StringToFloat(newVal);
}
}


public void OnClientPutInServer(client)
public void OnClientPutInServer(int client)
{
{
//dont hook stuff that isnt needed :)
if(!g_Enabled)
return;
//Use an SDKHook for inflictor index
//Use an SDKHook for inflictor index
SDKHook(client, SDKHook_OnTakeDamagePost, OnTakeDamagePost);
SDKHook(client, SDKHook_OnTakeDamagePost, OnTakeDamagePost);
}
}


public void OnEntityCreated(int entity, const char[] classname)
public void OnEntityCreated(int entity, const char[] classname)
{
{
//Is the plugin enabled? Otherwise don't continue
//Is the plugin enabled? Otherwise don't continue
if (!g_Enabled) {
if (!g_Enabled) {
return;
return;
}
}
//Is this a valid entity?
//Is this a valid entity?
if (IsValidEdict(entity)) {
if (IsValidEdict(entity)) {
char class_name[32];
char class_name[32];
GetEdictClassname(entity, class_name, 32);
GetEdictClassname(entity, class_name, 32);
//Only hook projectiles if they are valid
//Only hook projectiles if they are valid
if ((StrContains(class_name, "hegrenade_projectile", false) != -1) && (IsValidEntity(entity))) {
if (StrContains(class_name, "hegrenade_projectile", false) != -1 && IsValidEntity(entity)) {
if (g_Debug) {
if (g_Debug) {
PrintToChatAll("[SM]Nade Kick: Hooked projectile %d", entity);
PrintToChatAll("[SM]Nade Kick: Hooked projectile %d", entity);
}
}
//Hook the entity, we must wait until post spawn
//Hook the entity, we must wait until post spawn
SDKHook(entity, SDKHook_SpawnPost, OnEntitySpawned);
SDKHook(entity, SDKHook_SpawnPost, OnEntitySpawned);
}
}
}
}
}
}
public void OnEntitySpawned(int entity)
public void OnEntitySpawned(int entity)
{
{
if(!g_Enabled)
return;
int owner = GetEntPropEnt(entity, Prop_Data, "m_hOwnerEntity"); //The client
int owner = GetEntPropEnt(entity, Prop_Data, "m_hOwnerEntity"); //The client
//Origin vectors define position (X, Y, Z)
//Origin vectors define position (X, Y, Z)
//Angle vectors define orientation (Pitch, Yaw, Roll)
//Angle vectors define orientation (Pitch, Yaw, Roll)
//Magnitude vectors define direction (X, Y, Z) anything from zero is distance
//Magnitude vectors define direction (X, Y, Z) anything from zero is distance
//Create vector from player
//Create vector from player
float pEyeOrigin[3], pEyeAngles[3];
float pEyeOrigin[3], pEyeAngles[3];
GetClientEyePosition(owner, pEyeOrigin); //Player origin
GetClientEyePosition(owner, pEyeOrigin); //Player origin
GetClientEyeAngles(owner, pEyeAngles); //Player angles
GetClientEyeAngles(owner, pEyeAngles); //Player angles
//Flatten player angles along Z axis
//Flatten player angles along Z axis
pEyeAngles[0] = 0.0; //Set pitch
pEyeAngles[0] = 0.0; //Set pitch
pEyeAngles[2] = 0.0; //Set roll
pEyeAngles[2] = 0.0; //Set roll
if (g_Debug) {
if (g_Debug) {
PrintToChatAll("[SM]Nade Kick: %N angle is %f", owner, pEyeAngles[1]);
PrintToChatAll("[SM]Nade Kick: %N angle is %f", owner, pEyeAngles[1]);
}
}
//Get direction
//Get direction
GetAngleVectors(pEyeAngles, pEyeAngles, NULL_VECTOR, NULL_VECTOR); //Transform into vector
GetAngleVectors(pEyeAngles, pEyeAngles, NULL_VECTOR, NULL_VECTOR); //Transform into vector
NormalizeVector(pEyeAngles, pEyeAngles); //Clamp vector
NormalizeVector(pEyeAngles, pEyeAngles); //Clamp vector
ScaleVector(pEyeAngles, g_pDistance); //How far ahead of player we go
ScaleVector(pEyeAngles, g_pDistance); //How far ahead of player we go
AddVectors(pEyeOrigin, pEyeAngles, pEyeOrigin); //Move origin along vector
AddVectors(pEyeOrigin, pEyeAngles, pEyeOrigin); //Move origin along vector
//Save pgVector to hash
//Save pgVector to hash
char entStr[12];
char entStr[12];
IntToString(entity, entStr, 12);
IntToString(entity, entStr, 12);
hMapDirection.SetArray(entStr, pEyeAngles, 3, true);
hMapDirection.SetArray(entStr, pEyeAngles, 3, true);
hMapOrigin.SetArray(entStr, pEyeOrigin, 3, true);
hMapOrigin.SetArray(entStr, pEyeOrigin, 3, true);
}
}
public void OnTakeDamagePost(int victim, int attacker, int inflictor, float damage, int damagetype, int weapon,
public void OnTakeDamagePost(int victim, int attacker, int inflictor, float damage, int damagetype, int weapon,
const float damageForce[3], const float damagePosition[3], int damagecustom)
const float damageForce[3], const float damagePosition[3], int damagecustom)
{
{
//Stop if disabled
//Stop if disabled
if (!g_Enabled) {
if (!g_Enabled) {
return;
return;
}
}


//Is player alive?
//Is player alive?
if (!IsPlayerAlive(attacker)) {
if (!IsPlayerAlive(attacker)) {
return;
return;
}
}
char sWeapon[32];
char sWeapon[32];
GetEdictClassname(inflictor, sWeapon, sizeof(sWeapon));
GetEdictClassname(inflictor, sWeapon, sizeof(sWeapon));
// If the player is a zombie and it is hurt with a grenade
// If the player is a zombie and it is hurt with a grenade
if ((GetClientTeam(victim) == 2) && (GetClientTeam(attacker) != 2) && (StrContains("hegrenade_projectile", sWeapon, false) != -1) && (damage >= 2.0)) {
if ((ZR_IsClientZombie(victim) && ZR_IsClientHuman(attacker)) && StrContains("hegrenade_projectile", sWeapon, false) != -1 && damage >= 2.0) {
//Initialize vector handles, aForward and aVictim directions
//Initialize vector handles, aForward and aVictim directions
float victimOrigin[3], attackerOrigin[3], grenadeOrigin[3], afVector[3], avVector[3];
float victimOrigin[3], attackerOrigin[3], grenadeOrigin[3], afVector[3], avVector[3];
if (g_Debug) {
if (g_Debug) {
char nameentname[225];
char nameentname[225];
GetEdictClassname(inflictor, nameentname, sizeof(nameentname));
GetEdictClassname(inflictor, nameentname, sizeof(nameentname));
PrintToChatAll("[SM]Nade Kick: Inflictor ent %d, %s", inflictor, nameentname);
PrintToChatAll("[SM]Nade Kick: Inflictor ent %d, %s", inflictor, nameentname);
}
}
//Use entity index as key and grab afVector from hash
//Use entity index as key and grab afVector from hash
char inflictorStr[12];
char inflictorStr[12];
IntToString(inflictor, inflictorStr, 12);
IntToString(inflictor, inflictorStr, 12);
//Check that hash values return successfully otherwise call the cops
//Check that hash values return successfully otherwise call the cops
if (!hMapDirection.GetArray(inflictorStr, afVector, 3, _)) {
if (!hMapDirection.GetArray(inflictorStr, afVector, 3, _)) {
ThrowError("Attacker has no direction vector, inflictor not found!");
ThrowError("Attacker has no direction vector, inflictor not found!");
}
}
if (!hMapOrigin.GetArray(inflictorStr, attackerOrigin, 3, _)) {
else if (!hMapOrigin.GetArray(inflictorStr, attackerOrigin, 3, _)) {
ThrowError("Attacker has no origin vector, inflictor not found!");
ThrowError("Attacker has no origin vector, inflictor not found!");
}
}
//Get the origin vector for victim
//Get the origin vector for victim
GetEntPropVector(victim, Prop_Send, "m_vecOrigin", victimOrigin);
GetEntPropVector(victim, Prop_Send, "m_vecOrigin", victimOrigin);
//Make new vector from player to victim
//Make new vector from player to victim
MakeVectorFromPoints(attackerOrigin, victimOrigin, avVector);
MakeVectorFromPoints(attackerOrigin, victimOrigin, avVector);
NormalizeVector(avVector, avVector);
NormalizeVector(avVector, avVector);
//Re-normalize the attacker forward vector
//Re-normalize the attacker forward vector
NormalizeVector(afVector, afVector);
NormalizeVector(afVector, afVector);
//Get the angle between player forward view and player viewing victim
//Get the angle between player forward view and player viewing victim
float dot = GetVectorDotProduct(afVector, avVector); //Get initial dot product
float dot = GetVectorDotProduct(afVector, avVector); //Get initial dot product
dot = (dot / FloatMul(GetVectorLength(avVector, true), GetVectorLength(afVector, true))); //Divide by vector magnitude
dot = (dot / FloatMul(GetVectorLength(avVector, true), GetVectorLength(afVector, true))); //Divide by vector magnitude
float vectorAngle = RadToDeg(ArcCosine(dot)); //Get angle in radians, then convert to degrees
float vectorAngle = RadToDeg(ArcCosine(dot)); //Get angle in radians, then convert to degrees


if (g_Debug) {
if (g_Debug) {
PrintToChatAll("[SM]Nade Kick: %N angle is %f", victim, vectorAngle);
PrintToChatAll("[SM]Nade Kick: %N angle is %f", victim, vectorAngle);
PrintToChatAll("[SM]Nade Kick: %N took %f damage", victim, damage);
PrintToChatAll("[SM]Nade Kick: %N took %f damage", victim, damage);
}
}
float dmgMulti = damage;
float dmgMulti = damage;
if (damage >= g_dmgCap) {
if (damage >= g_dmgCap) {
dmgMulti = g_dmgCap;
dmgMulti = g_dmgCap;
}
}
//Check if victim is behind attacker
//Check if victim is behind attacker
if (vectorAngle <= 90.0) {
if (vectorAngle <= 90.0) {
GetEntPropVector(inflictor, Prop_Send, "m_vecOrigin", grenadeOrigin);
GetEntPropVector(inflictor, Prop_Send, "m_vecOrigin", grenadeOrigin);
MakeVectorFromPoints(grenadeOrigin, victimOrigin, avVector);
MakeVectorFromPoints(grenadeOrigin, victimOrigin, avVector);
NormalizeVector(avVector, avVector);
NormalizeVector(avVector, avVector);
dot = GetVectorDotProduct(afVector, avVector); //Get initial dot product
dot = GetVectorDotProduct(afVector, avVector); //Get initial dot product
dot = (dot / FloatMul(GetVectorLength(avVector, true), GetVectorLength(afVector, true))); //Divide by vector magnitude
dot = (dot / FloatMul(GetVectorLength(avVector, true), GetVectorLength(afVector, true))); //Divide by vector magnitude
vectorAngle = RadToDeg(ArcCosine(dot)); //Get angle in radians, then convert to degrees
vectorAngle = RadToDeg(ArcCosine(dot)); //Get angle in radians, then convert to degrees
if (vectorAngle <= 80.0) {
if (vectorAngle <= 80.0) {
afVector[0] = avVector[0];
afVector[0] = avVector[0];
afVector[1] = avVector[1];
afVector[1] = avVector[1];
}
}
//Scale original values to maintain direction
//Scale original values to maintain direction
ScaleVector(afVector, g_hKnockback); //Scale by multiplier
ScaleVector(afVector, g_hKnockback); //Scale by multiplier
ScaleVector(afVector, dmgMulti); //Scale by damage
ScaleVector(afVector, dmgMulti); //Scale by damage
} else {
} else {
//Only go vertical
//Only go vertical
afVector[0] = 0.0;
afVector[0] = 0.0;
afVector[1] = 0.0;
afVector[1] = 0.0;
}
}
afVector[2] = FloatMul(g_vKnockback, dmgMulti); //Set vertical velocity
afVector[2] = FloatMul(g_vKnockback, dmgMulti); //Set vertical velocity
// Apply the directional push
// Apply the directional push
TeleportEntity(victim, NULL_VECTOR, NULL_VECTOR, afVector);
TeleportEntity(victim, NULL_VECTOR, NULL_VECTOR, afVector);
//Slow the player
//Slow the player
if (g_StamPenalty > 0.0) {
if (g_StamPenalty > 0.0) {
SetEntDataFloat(victim, g_StaminaOffset, g_StamPenalty, true);
SetEntDataFloat(victim, g_StaminaOffset, g_StamPenalty, true);
}
}
}
}
}
}