Add max client total velocity for knockback in addition to max force per tick.
This commit is contained in:
parent
197eb861bd
commit
37698b0c20
@ -66,7 +66,8 @@ public void __pl_zombiereloaded_SetNTVOptional()
|
|||||||
MarkNativeAsOptional("ZR_SetKilledByWorld");
|
MarkNativeAsOptional("ZR_SetKilledByWorld");
|
||||||
MarkNativeAsOptional("ZR_GetKilledByWorld");
|
MarkNativeAsOptional("ZR_GetKilledByWorld");
|
||||||
|
|
||||||
MarkNativeAsOptional("ZR_SetClientKnockbackMaxVelocity");
|
|
||||||
MarkNativeAsOptional("ZR_SetClientKnockbackScale");
|
MarkNativeAsOptional("ZR_SetClientKnockbackScale");
|
||||||
|
MarkNativeAsOptional("ZR_SetClientKnockbackMaxForce");
|
||||||
|
MarkNativeAsOptional("ZR_SetClientKnockbackMaxVelocity");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -27,15 +27,8 @@
|
|||||||
|
|
||||||
#define ZR_KNOCKBACK_CUSTOM (1<<31)
|
#define ZR_KNOCKBACK_CUSTOM (1<<31)
|
||||||
#define ZR_KNOCKBACK_SCALE (1<<1)
|
#define ZR_KNOCKBACK_SCALE (1<<1)
|
||||||
#define ZR_KNOCKBACK_LIMITVEL (1<<2)
|
#define ZR_KNOCKBACK_LIMITFORCE (1<<2)
|
||||||
|
#define ZR_KNOCKBACK_LIMITVEL (1<<3)
|
||||||
/**
|
|
||||||
* Set a maximum knockback velocity.
|
|
||||||
*
|
|
||||||
* @param client The client.
|
|
||||||
* @param fVelocity Maximum knockback velocity / force.
|
|
||||||
*/
|
|
||||||
native void ZR_SetClientKnockbackMaxVelocity(int client, float fVelocity);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a custom knockback scale.
|
* Set a custom knockback scale.
|
||||||
@ -44,3 +37,19 @@ native void ZR_SetClientKnockbackMaxVelocity(int client, float fVelocity);
|
|||||||
* @param fScale Custom knockback scale.
|
* @param fScale Custom knockback scale.
|
||||||
*/
|
*/
|
||||||
native void ZR_SetClientKnockbackScale(int client, float fScale);
|
native void ZR_SetClientKnockbackScale(int client, float fScale);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a maximum knockback force per tick.
|
||||||
|
*
|
||||||
|
* @param client The client.
|
||||||
|
* @param fForce Maximum knockback force per tick.
|
||||||
|
*/
|
||||||
|
native void ZR_SetClientKnockbackMaxForce(int client, float fForce);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a maximum knockback velocity.
|
||||||
|
*
|
||||||
|
* @param client The client.
|
||||||
|
* @param fVelocity Maximum knockback velocity.
|
||||||
|
*/
|
||||||
|
native void ZR_SetClientKnockbackMaxVelocity(int client, float fVelocity);
|
||||||
|
@ -33,23 +33,9 @@ APIKnockbackInit()
|
|||||||
// Class module natives/forwards (knockback.zr.inc)
|
// Class module natives/forwards (knockback.zr.inc)
|
||||||
|
|
||||||
// Natives
|
// Natives
|
||||||
CreateNative("ZR_SetClientKnockbackMaxVelocity", APISetClientKnockbackMaxVelocity);
|
|
||||||
CreateNative("ZR_SetClientKnockbackScale", APISetClientKnockbackScale);
|
CreateNative("ZR_SetClientKnockbackScale", APISetClientKnockbackScale);
|
||||||
}
|
CreateNative("ZR_SetClientKnockbackMaxForce", APISetClientKnockbackMaxForce);
|
||||||
|
CreateNative("ZR_SetClientKnockbackMaxVelocity", APISetClientKnockbackMaxVelocity);
|
||||||
/**
|
|
||||||
* Native call function (ZR_SetClientKnockbackMaxVelocity)
|
|
||||||
*
|
|
||||||
* int ZR_SetClientKnockbackMaxVelocity(int client, float fVelocity);
|
|
||||||
*/
|
|
||||||
public int APISetClientKnockbackMaxVelocity(Handle plugin, int numParams)
|
|
||||||
{
|
|
||||||
int client = GetNativeCell(1);
|
|
||||||
float fVelocity = view_as<float>(GetNativeCell(2));
|
|
||||||
|
|
||||||
APIValidateClientIndex(client);
|
|
||||||
|
|
||||||
KnockbackSetClientMaxVelocity(client, fVelocity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -66,3 +52,33 @@ public int APISetClientKnockbackScale(Handle plugin, int numParams)
|
|||||||
|
|
||||||
KnockbackSetClientScale(client, fScale);
|
KnockbackSetClientScale(client, fScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Native call function (ZR_SetClientKnockbackMaxForce)
|
||||||
|
*
|
||||||
|
* int ZR_SetClientKnockbackMaxForce(int client, float fForce);
|
||||||
|
*/
|
||||||
|
public int APISetClientKnockbackMaxForce(Handle plugin, int numParams)
|
||||||
|
{
|
||||||
|
int client = GetNativeCell(1);
|
||||||
|
float fForce = view_as<float>(GetNativeCell(2));
|
||||||
|
|
||||||
|
APIValidateClientIndex(client);
|
||||||
|
|
||||||
|
KnockbackSetClientMaxForce(client, fForce);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Native call function (ZR_SetClientKnockbackMaxVelocity)
|
||||||
|
*
|
||||||
|
* int ZR_SetClientKnockbackMaxVelocity(int client, float fVelocity);
|
||||||
|
*/
|
||||||
|
public int APISetClientKnockbackMaxVelocity(Handle plugin, int numParams)
|
||||||
|
{
|
||||||
|
int client = GetNativeCell(1);
|
||||||
|
float fVelocity = view_as<float>(GetNativeCell(2));
|
||||||
|
|
||||||
|
APIValidateClientIndex(client);
|
||||||
|
|
||||||
|
KnockbackSetClientMaxVelocity(client, fVelocity);
|
||||||
|
}
|
||||||
|
@ -86,6 +86,7 @@ DamageClientInit(client)
|
|||||||
// Hook damage callbacks.
|
// Hook damage callbacks.
|
||||||
SDKHook(client, SDKHook_TraceAttack, DamageTraceAttack);
|
SDKHook(client, SDKHook_TraceAttack, DamageTraceAttack);
|
||||||
SDKHook(client, SDKHook_OnTakeDamage, DamageOnTakeDamage);
|
SDKHook(client, SDKHook_OnTakeDamage, DamageOnTakeDamage);
|
||||||
|
SDKHook(client, SDKHook_OnTakeDamageAlivePost, DamageOnTakeDamageAlivePost);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -97,6 +98,7 @@ DamageOnClientDisconnect(client)
|
|||||||
{
|
{
|
||||||
SDKUnhook(client, SDKHook_TraceAttack, DamageTraceAttack);
|
SDKUnhook(client, SDKHook_TraceAttack, DamageTraceAttack);
|
||||||
SDKUnhook(client, SDKHook_OnTakeDamage, DamageOnTakeDamage);
|
SDKUnhook(client, SDKHook_OnTakeDamage, DamageOnTakeDamage);
|
||||||
|
SDKUnhook(client, SDKHook_OnTakeDamageAlivePost, DamageOnTakeDamageAlivePost);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -159,7 +161,7 @@ public Action DamageTraceAttack(int client, int &attacker, int &inflictor, float
|
|||||||
// Here we know that attacker and client are different teams.
|
// Here we know that attacker and client are different teams.
|
||||||
|
|
||||||
// Check if immunity module requires damage to be blocked.
|
// Check if immunity module requires damage to be blocked.
|
||||||
if (ImmunityOnClientTraceAttack(client, attacker, inflictor, damage, damagetype, ammotype))
|
if (ImmunityOnClientTraceAttack(client, attacker, inflictor, damage, damagetype, ammotype, hitgroup))
|
||||||
{
|
{
|
||||||
// Block damage.
|
// Block damage.
|
||||||
return Plugin_Handled;
|
return Plugin_Handled;
|
||||||
@ -216,8 +218,13 @@ public Action DamageTraceAttack(int client, int &attacker, int &inflictor, float
|
|||||||
* @return Return Plugin_Handled to stop the damage to client.
|
* @return Return Plugin_Handled to stop the damage to client.
|
||||||
* Plugin_Continue to allow damage to client.
|
* Plugin_Continue to allow damage to client.
|
||||||
*/
|
*/
|
||||||
public Action:DamageOnTakeDamage(client, &attacker, &inflictor, &Float:damage, &damagetype)
|
public Action DamageOnTakeDamage(int client, int &attacker, int &inflictor, float &damage, int &damagetype, int &weapon,
|
||||||
|
float damageForce[3], float damagePosition[3], int damagecustom)
|
||||||
{
|
{
|
||||||
|
bool custom = view_as<bool>(damagecustom & ZR_KNOCKBACK_CUSTOM);
|
||||||
|
if (custom)
|
||||||
|
return Plugin_Continue;
|
||||||
|
|
||||||
// Get classname of the inflictor.
|
// Get classname of the inflictor.
|
||||||
decl String:classname[64];
|
decl String:classname[64];
|
||||||
GetEdictClassname(inflictor, classname, sizeof(classname));
|
GetEdictClassname(inflictor, classname, sizeof(classname));
|
||||||
@ -437,3 +444,48 @@ public Action:DamageSuicideIntercept(int client, const char[] command, int argc)
|
|||||||
// Block command.
|
// Block command.
|
||||||
return Plugin_Handled;
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void DamageOnTakeDamageAlivePost(int victim, int attacker, int inflictor, float damage, int damagetype, int weapon,
|
||||||
|
const float damageForce[3], const float damagePosition[3], int damagecustom)
|
||||||
|
{
|
||||||
|
// If attacker is invalid, then stop.
|
||||||
|
if (!ZRIsClientValid(attacker))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool custom = view_as<bool>(damagecustom & ZR_KNOCKBACK_CUSTOM);
|
||||||
|
|
||||||
|
char weaponname[64];
|
||||||
|
if (inflictor == attacker)
|
||||||
|
{
|
||||||
|
weapon = WeaponsGetActiveWeaponIndex(attacker);
|
||||||
|
if (weapon > 0)
|
||||||
|
GetEdictClassname(weapon, weaponname, sizeof(weaponname));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
GetEdictClassname(inflictor, weaponname, sizeof(weaponname));
|
||||||
|
|
||||||
|
ReplaceString(weaponname, sizeof(weaponname), "weapon_", "");
|
||||||
|
ReplaceString(weaponname, sizeof(weaponname), "_projectile", "");
|
||||||
|
|
||||||
|
int hitgroup = HITGROUP_GENERIC;
|
||||||
|
if (!(damagetype & DMG_BLAST) && !custom)
|
||||||
|
hitgroup = ToolsGetClientLastHitGroup(victim);
|
||||||
|
|
||||||
|
KnockbackOnClientHurt(victim, attacker, inflictor, weaponname, hitgroup, damage, damagetype, weapon, damagecustom);
|
||||||
|
|
||||||
|
// If attacker is a human and is getting damaged through DamageProxy, then stop.
|
||||||
|
// We don't want to get infected if we're being knifed inside of a human item.
|
||||||
|
if (custom && InfectIsClientHuman(victim))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassAlphaUpdate(victim);
|
||||||
|
InfectOnClientHurt(victim, attacker, weaponname);
|
||||||
|
AccountOnClientHurt(victim, attacker, RoundToFloor(damage));
|
||||||
|
SEffectsOnClientHurt(victim);
|
||||||
|
NapalmOnClientHurt(victim, attacker, weaponname, RoundToFloor(damage));
|
||||||
|
ZHPOnClientHurt(victim);
|
||||||
|
}
|
||||||
|
@ -50,7 +50,6 @@ EventHook(bool:unhook = false)
|
|||||||
UnhookEvent("round_end", EventRoundEnd);
|
UnhookEvent("round_end", EventRoundEnd);
|
||||||
UnhookEvent("player_team", EventPlayerTeam, EventHookMode_Pre);
|
UnhookEvent("player_team", EventPlayerTeam, EventHookMode_Pre);
|
||||||
UnhookEvent("player_spawn", EventPlayerSpawn);
|
UnhookEvent("player_spawn", EventPlayerSpawn);
|
||||||
UnhookEvent("player_hurt", EventPlayerHurt);
|
|
||||||
UnhookEvent("player_death", EventPlayerDeath);
|
UnhookEvent("player_death", EventPlayerDeath);
|
||||||
UnhookEvent("player_jump", EventPlayerJump);
|
UnhookEvent("player_jump", EventPlayerJump);
|
||||||
|
|
||||||
@ -67,7 +66,6 @@ EventHook(bool:unhook = false)
|
|||||||
HookEvent("round_end", EventRoundEnd);
|
HookEvent("round_end", EventRoundEnd);
|
||||||
HookEvent("player_team", EventPlayerTeam, EventHookMode_Pre);
|
HookEvent("player_team", EventPlayerTeam, EventHookMode_Pre);
|
||||||
HookEvent("player_spawn", EventPlayerSpawn);
|
HookEvent("player_spawn", EventPlayerSpawn);
|
||||||
HookEvent("player_hurt", EventPlayerHurt);
|
|
||||||
HookEvent("player_death", EventPlayerDeath);
|
HookEvent("player_death", EventPlayerDeath);
|
||||||
HookEvent("player_jump", EventPlayerJump);
|
HookEvent("player_jump", EventPlayerJump);
|
||||||
|
|
||||||
@ -214,33 +212,6 @@ public Action:EventPlayerSpawnPost(Handle:timer, any:client)
|
|||||||
SpawnProtectOnClientSpawnPost(client); // Must be executed after class attributes are applied.
|
SpawnProtectOnClientSpawnPost(client); // Must be executed after class attributes are applied.
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Event callback (player_hurt)
|
|
||||||
* Client is being hurt.
|
|
||||||
*
|
|
||||||
* @param event The event handle.
|
|
||||||
* @param name Name of the event.
|
|
||||||
* @dontBroadcast If true, event is broadcasted to all clients, false if not.
|
|
||||||
*/
|
|
||||||
public Action:EventPlayerHurt(Handle:event, const String:name[], bool:dontBroadcast)
|
|
||||||
{
|
|
||||||
// Get all required event info.
|
|
||||||
new index = GetClientOfUserId(GetEventInt(event, "userid"));
|
|
||||||
new attacker = GetClientOfUserId(GetEventInt(event, "attacker"));
|
|
||||||
new dmg_health = GetEventInt(event, "dmg_health");
|
|
||||||
|
|
||||||
decl String:weapon[WEAPONS_MAX_LENGTH];
|
|
||||||
GetEventString(event, "weapon", weapon, sizeof(weapon));
|
|
||||||
|
|
||||||
// Forward event to modules.
|
|
||||||
ClassAlphaUpdate(index);
|
|
||||||
InfectOnClientHurt(index, attacker, weapon);
|
|
||||||
AccountOnClientHurt(index, attacker, dmg_health);
|
|
||||||
SEffectsOnClientHurt(index);
|
|
||||||
NapalmOnClientHurt(index, attacker, weapon, dmg_health);
|
|
||||||
ZHPOnClientHurt(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event callback (player_death)
|
* Event callback (player_death)
|
||||||
* Client has been killed.
|
* Client has been killed.
|
||||||
|
@ -161,7 +161,7 @@ bool:ImmunityOnClientInfect(client, attacker)
|
|||||||
*
|
*
|
||||||
* @return True if damage should be blocked, false otherwise.
|
* @return True if damage should be blocked, false otherwise.
|
||||||
*/
|
*/
|
||||||
bool ImmunityOnClientTraceAttack(int client, int &attacker, int &inflictor, float &damage, int &damagetype, int &ammotype)
|
bool ImmunityOnClientTraceAttack(int client, int &attacker, int &inflictor, float &damage, int &damagetype, int &ammotype, int hitgroup)
|
||||||
{
|
{
|
||||||
// Check if there is no attacker (world damage).
|
// Check if there is no attacker (world damage).
|
||||||
if (!ZRIsClientValid(attacker))
|
if (!ZRIsClientValid(attacker))
|
||||||
@ -225,7 +225,7 @@ bool ImmunityOnClientTraceAttack(int client, int &attacker, int &inflictor, floa
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Since damage is blocked, trigger knock back hurt event manually.
|
// Since damage is blocked, trigger knock back hurt event manually.
|
||||||
KnockbackOnTakeDamageAlivePost(client, attacker, inflictor, damage, damagetype, -1, NULL_VECTOR, NULL_VECTOR, 0);
|
KnockbackOnClientHurt(client, attacker, inflictor, weapon, hitgroup, damage, damagetype, -1, 0);
|
||||||
|
|
||||||
// Block damage from attacker.
|
// Block damage from attacker.
|
||||||
return true;
|
return true;
|
||||||
|
@ -25,10 +25,12 @@
|
|||||||
* ============================================================================
|
* ============================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool g_bKnockbackFrame[MAXPLAYERS + 1];
|
|
||||||
float g_fKnockbackVelLimit[MAXPLAYERS + 1];
|
|
||||||
float g_fKnockbackVectors[MAXPLAYERS + 1][3];
|
|
||||||
float g_fKnockbackScale[MAXPLAYERS + 1];
|
float g_fKnockbackScale[MAXPLAYERS + 1];
|
||||||
|
float g_fKnockbackForceLimit[MAXPLAYERS + 1];
|
||||||
|
bool g_bKnockbackFrame[MAXPLAYERS + 1];
|
||||||
|
bool g_bKnockbackFrameLimitVel[MAXPLAYERS + 1];
|
||||||
|
float g_fKnockbackVectors[MAXPLAYERS + 1][3];
|
||||||
|
float g_fKnockbackVelLimit[MAXPLAYERS + 1] = {-1.0, ...};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Minimum upwards boost that is required to push zombies off the ground.
|
* Minimum upwards boost that is required to push zombies off the ground.
|
||||||
@ -43,14 +45,16 @@ float g_fKnockbackScale[MAXPLAYERS + 1];
|
|||||||
*/
|
*/
|
||||||
void KnockbackClientInit(int client)
|
void KnockbackClientInit(int client)
|
||||||
{
|
{
|
||||||
|
g_fKnockbackScale[client] = 1.0;
|
||||||
|
|
||||||
|
g_fKnockbackForceLimit[client] = 0.0;
|
||||||
g_bKnockbackFrame[client] = false;
|
g_bKnockbackFrame[client] = false;
|
||||||
g_fKnockbackVelLimit[client] = 0.0;
|
g_bKnockbackFrameLimitVel[client] = false;
|
||||||
g_fKnockbackVectors[client][0] = 0.0;
|
g_fKnockbackVectors[client][0] = 0.0;
|
||||||
g_fKnockbackVectors[client][1] = 0.0;
|
g_fKnockbackVectors[client][1] = 0.0;
|
||||||
g_fKnockbackVectors[client][2] = 0.0;
|
g_fKnockbackVectors[client][2] = 0.0;
|
||||||
g_fKnockbackScale[client] = 1.0;
|
|
||||||
|
|
||||||
SDKHook(client, SDKHook_OnTakeDamageAlivePost, KnockbackOnTakeDamageAlivePost);
|
g_fKnockbackVelLimit[client] = -1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -60,10 +64,7 @@ void KnockbackClientInit(int client)
|
|||||||
*/
|
*/
|
||||||
void KnockbackOnClientDisconnect(int client)
|
void KnockbackOnClientDisconnect(int client)
|
||||||
{
|
{
|
||||||
g_bKnockbackFrame[client] = false;
|
KnockbackClientInit(client);
|
||||||
g_fKnockbackVelLimit[client] = 0.0;
|
|
||||||
|
|
||||||
SDKUnhook(client, SDKHook_OnTakeDamageAlivePost, KnockbackOnTakeDamageAlivePost);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -71,18 +72,7 @@ void KnockbackOnClientDisconnect(int client)
|
|||||||
*/
|
*/
|
||||||
void KnockbackOnClientDeath(int client)
|
void KnockbackOnClientDeath(int client)
|
||||||
{
|
{
|
||||||
g_bKnockbackFrame[client] = false;
|
KnockbackClientInit(client);
|
||||||
g_fKnockbackVelLimit[client] = 0.0;
|
|
||||||
g_fKnockbackVectors[client][0] = 0.0;
|
|
||||||
g_fKnockbackVectors[client][1] = 0.0;
|
|
||||||
g_fKnockbackVectors[client][2] = 0.0;
|
|
||||||
g_fKnockbackScale[client] = 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KnockbackSetClientMaxVelocity(int client, float fVelocity)
|
|
||||||
{
|
|
||||||
if(g_fKnockbackVelLimit[client] >= 0.0)
|
|
||||||
g_fKnockbackVelLimit[client] = fVelocity;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void KnockbackSetClientScale(int client, float fScale)
|
void KnockbackSetClientScale(int client, float fScale)
|
||||||
@ -90,6 +80,17 @@ void KnockbackSetClientScale(int client, float fScale)
|
|||||||
g_fKnockbackScale[client] = fScale;
|
g_fKnockbackScale[client] = fScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void KnockbackSetClientMaxForce(int client, float fForce)
|
||||||
|
{
|
||||||
|
if(g_fKnockbackForceLimit[client] >= 0.0)
|
||||||
|
g_fKnockbackForceLimit[client] = fForce;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KnockbackSetClientMaxVelocity(int client, float fVelocity)
|
||||||
|
{
|
||||||
|
g_fKnockbackForceLimit[client] = fVelocity;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called before every server frame. Note that you should avoid
|
* Called before every server frame. Note that you should avoid
|
||||||
* doing expensive computations or declaring large local arrays.
|
* doing expensive computations or declaring large local arrays.
|
||||||
@ -98,17 +99,22 @@ void KnockbackOnGameFrame()
|
|||||||
{
|
{
|
||||||
for(int client = 1; client <= MaxClients; client++)
|
for(int client = 1; client <= MaxClients; client++)
|
||||||
{
|
{
|
||||||
if (g_bKnockbackFrame[client] && g_fKnockbackVelLimit[client] > 0.0)
|
if (g_bKnockbackFrame[client] && g_fKnockbackForceLimit[client] > 0.0)
|
||||||
{
|
{
|
||||||
|
// Get the knockback force
|
||||||
float magnitude = GetVectorLength(g_fKnockbackVectors[client]);
|
float magnitude = GetVectorLength(g_fKnockbackVectors[client]);
|
||||||
if(magnitude > g_fKnockbackVelLimit[client])
|
|
||||||
|
// ... and limit it if it's too high.
|
||||||
|
if(magnitude > g_fKnockbackForceLimit[client])
|
||||||
{
|
{
|
||||||
ScaleVector(g_fKnockbackVectors[client], g_fKnockbackVelLimit[client] / magnitude);
|
ScaleVector(g_fKnockbackVectors[client], g_fKnockbackForceLimit[client] / magnitude);
|
||||||
}
|
}
|
||||||
|
|
||||||
KnockbackApplyVector(client, g_fKnockbackVectors[client]);
|
// Apply the knockback.
|
||||||
|
KnockbackApplyVector(client, g_fKnockbackVectors[client], g_bKnockbackFrameLimitVel[client]);
|
||||||
|
|
||||||
g_bKnockbackFrame[client] = false;
|
g_bKnockbackFrame[client] = false;
|
||||||
|
g_bKnockbackFrameLimitVel[client] = false;
|
||||||
g_fKnockbackVectors[client][0] = 0.0;
|
g_fKnockbackVectors[client][0] = 0.0;
|
||||||
g_fKnockbackVectors[client][1] = 0.0;
|
g_fKnockbackVectors[client][1] = 0.0;
|
||||||
g_fKnockbackVectors[client][2] = 0.0;
|
g_fKnockbackVectors[client][2] = 0.0;
|
||||||
@ -117,23 +123,18 @@ void KnockbackOnGameFrame()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hook: KnockbackOnTakeDamageAlivePost
|
* Hook: KnockbackOnClientHurt
|
||||||
* Called after client has been hurt.
|
* Called after client has been hurt.
|
||||||
*
|
*
|
||||||
* @param client The client index.
|
* @param victim The client index.
|
||||||
* @param inflictor The entity index of the inflictor.
|
|
||||||
* @param attacker The client index of the attacker.
|
* @param attacker The client index of the attacker.
|
||||||
|
* @param inflictor The entity index of the inflictor.
|
||||||
|
* @param weaponname The weapon used.
|
||||||
|
* @param hitgroup Hitgroup attacker has damaged.
|
||||||
* @param damage The amount of damage inflicted.
|
* @param damage The amount of damage inflicted.
|
||||||
*/
|
*/
|
||||||
public void KnockbackOnTakeDamageAlivePost(int victim, int attacker, int inflictor, float damage, int damagetype, int weapon,
|
public void KnockbackOnClientHurt(int victim, int attacker, int inflictor, const char[] weaponname, int hitgroup, float damage, int damagetype, int weapon, int damagecustom)
|
||||||
const float damageForce[3], const float damagePosition[3], int damagecustom)
|
|
||||||
{
|
{
|
||||||
// If attacker is invalid, then stop.
|
|
||||||
if (!ZRIsClientValid(attacker))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Client is a human, then stop.
|
// Client is a human, then stop.
|
||||||
if (InfectIsClientHuman(victim))
|
if (InfectIsClientHuman(victim))
|
||||||
{
|
{
|
||||||
@ -160,19 +161,6 @@ public void KnockbackOnTakeDamageAlivePost(int victim, int attacker, int inflict
|
|||||||
|
|
||||||
GetClientAbsOrigin(victim, clientloc);
|
GetClientAbsOrigin(victim, clientloc);
|
||||||
|
|
||||||
char weaponname[64];
|
|
||||||
if (inflictor == attacker)
|
|
||||||
{
|
|
||||||
int activeweapon = WeaponsGetActiveWeaponIndex(attacker);
|
|
||||||
if (activeweapon > 0)
|
|
||||||
GetEdictClassname(activeweapon, weaponname, sizeof(weaponname));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
GetEdictClassname(inflictor, weaponname, sizeof(weaponname));
|
|
||||||
|
|
||||||
ReplaceString(weaponname, sizeof(weaponname), "weapon_", "");
|
|
||||||
ReplaceString(weaponname, sizeof(weaponname), "_projectile", "");
|
|
||||||
|
|
||||||
// Check if a grenade was thrown.
|
// Check if a grenade was thrown.
|
||||||
if (StrEqual(weaponname, "hegrenade"))
|
if (StrEqual(weaponname, "hegrenade"))
|
||||||
{
|
{
|
||||||
@ -210,12 +198,9 @@ public void KnockbackOnTakeDamageAlivePost(int victim, int attacker, int inflict
|
|||||||
|
|
||||||
bool custom = view_as<bool>(damagecustom & ZR_KNOCKBACK_CUSTOM);
|
bool custom = view_as<bool>(damagecustom & ZR_KNOCKBACK_CUSTOM);
|
||||||
bool scale = custom && view_as<bool>(damagecustom & ZR_KNOCKBACK_SCALE);
|
bool scale = custom && view_as<bool>(damagecustom & ZR_KNOCKBACK_SCALE);
|
||||||
|
bool limitforce = custom && view_as<bool>(damagecustom & ZR_KNOCKBACK_LIMITFORCE);
|
||||||
bool limitvel = custom && view_as<bool>(damagecustom & ZR_KNOCKBACK_LIMITVEL);
|
bool limitvel = custom && view_as<bool>(damagecustom & ZR_KNOCKBACK_LIMITVEL);
|
||||||
|
|
||||||
int hitgroup = HITGROUP_GENERIC;
|
|
||||||
if (!(damagetype & DMG_BLAST) && !custom)
|
|
||||||
hitgroup = ToolsGetClientLastHitGroup(victim);
|
|
||||||
|
|
||||||
if (custom)
|
if (custom)
|
||||||
ToolsSetClientLastHitGroup(victim, HITGROUP_GENERIC);
|
ToolsSetClientLastHitGroup(victim, HITGROUP_GENERIC);
|
||||||
|
|
||||||
@ -239,7 +224,7 @@ public void KnockbackOnTakeDamageAlivePost(int victim, int attacker, int inflict
|
|||||||
|
|
||||||
// Apply knockback.
|
// Apply knockback.
|
||||||
if (knockback)
|
if (knockback)
|
||||||
KnockbackSetVelocity(victim, attackerloc, clientloc, knockback, limitvel);
|
KnockbackSetVelocity(victim, attackerloc, clientloc, knockback, limitforce, limitvel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -250,7 +235,7 @@ public void KnockbackOnTakeDamageAlivePost(int victim, int attacker, int inflict
|
|||||||
* @param endpoint The ending coordinate to push towards.
|
* @param endpoint The ending coordinate to push towards.
|
||||||
* @param magnitude Magnitude of the push.
|
* @param magnitude Magnitude of the push.
|
||||||
*/
|
*/
|
||||||
KnockbackSetVelocity(client, const Float:startpoint[3], const Float:endpoint[3], Float:magnitude, int limitvel)
|
KnockbackSetVelocity(client, const Float:startpoint[3], const Float:endpoint[3], Float:magnitude, bool limitforce, bool limitvel)
|
||||||
{
|
{
|
||||||
// Create vector from the given starting and ending points.
|
// Create vector from the given starting and ending points.
|
||||||
new Float:vector[3];
|
new Float:vector[3];
|
||||||
@ -262,17 +247,18 @@ KnockbackSetVelocity(client, const Float:startpoint[3], const Float:endpoint[3],
|
|||||||
// Apply the magnitude by scaling the vector (multiplying each of its components).
|
// Apply the magnitude by scaling the vector (multiplying each of its components).
|
||||||
ScaleVector(vector, magnitude);
|
ScaleVector(vector, magnitude);
|
||||||
|
|
||||||
if (limitvel && g_fKnockbackVelLimit[client])
|
if (limitforce && g_fKnockbackForceLimit[client])
|
||||||
{
|
{
|
||||||
AddVectors(g_fKnockbackVectors[client], vector, g_fKnockbackVectors[client]);
|
AddVectors(g_fKnockbackVectors[client], vector, g_fKnockbackVectors[client]);
|
||||||
g_bKnockbackFrame[client] = true;
|
g_bKnockbackFrame[client] = true;
|
||||||
|
g_bKnockbackFrameLimitVel[client] |= limitvel;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
KnockbackApplyVector(client, vector);
|
KnockbackApplyVector(client, vector, limitvel);
|
||||||
}
|
}
|
||||||
|
|
||||||
void KnockbackApplyVector(int client, float vector[3])
|
void KnockbackApplyVector(int client, float vector[3], bool limitvel)
|
||||||
{
|
{
|
||||||
// CS: GO workaround. Apply knock back boost if enabled.
|
// CS: GO workaround. Apply knock back boost if enabled.
|
||||||
if (g_Game == Game_CSGO && GetConVarBool(g_hCvarsList[CVAR_CLASSES_CSGO_KNOCKBACK_BOOST]))
|
if (g_Game == Game_CSGO && GetConVarBool(g_hCvarsList[CVAR_CLASSES_CSGO_KNOCKBACK_BOOST]))
|
||||||
@ -294,8 +280,36 @@ void KnockbackApplyVector(int client, float vector[3])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ADD the given vector to the client's current velocity.
|
// Get their current velocity.
|
||||||
ToolsClientVelocity(client, vector);
|
float velocity[3];
|
||||||
|
ToolsGetClientVelocity(client, velocity);
|
||||||
|
|
||||||
|
// Calculate their speed.
|
||||||
|
float magnitude_pre = GetVectorLength(velocity);
|
||||||
|
|
||||||
|
// Add the knockback to their velocity.
|
||||||
|
AddVectors(vector, velocity, velocity);
|
||||||
|
|
||||||
|
// Should we limit their knockback velocity?
|
||||||
|
if (limitvel && g_fKnockbackVelLimit[client] >= 0.0)
|
||||||
|
{
|
||||||
|
// Calculate their new speed.
|
||||||
|
float magnitude_post = GetVectorLength(velocity);
|
||||||
|
|
||||||
|
// Did we actually push them back or just slow them down?
|
||||||
|
if (magnitude_post > magnitude_pre)
|
||||||
|
{
|
||||||
|
// Would their knockback velocity be higher than wanted?
|
||||||
|
if(magnitude_post > g_fKnockbackVelLimit[client])
|
||||||
|
{
|
||||||
|
// ... then scale it down.
|
||||||
|
ScaleVector(velocity, g_fKnockbackVelLimit[client] / magnitude_post);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the new client's velocity.
|
||||||
|
ToolsSetClientVelocity(client, velocity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -70,6 +70,17 @@ stock ToolsGetClientVelocity(client, Float:vecVelocity[3])
|
|||||||
GetEntDataVector(client, g_iToolsVelocity, vecVelocity);
|
GetEntDataVector(client, g_iToolsVelocity, vecVelocity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets client's velocity.
|
||||||
|
*
|
||||||
|
* @param client The client index.
|
||||||
|
* @param vecVelocity Array to store vector in.
|
||||||
|
*/
|
||||||
|
stock ToolsSetClientVelocity(client, const Float:vecVelocity[3])
|
||||||
|
{
|
||||||
|
SetEntDataVector(client, g_iToolsVelocity, vecVelocity);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a client's lagged movement value.
|
* Set a client's lagged movement value.
|
||||||
* @param client The client index.
|
* @param client The client index.
|
||||||
|
Loading…
Reference in New Issue
Block a user