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_GetKilledByWorld");
|
||||
|
||||
MarkNativeAsOptional("ZR_SetClientKnockbackMaxVelocity");
|
||||
MarkNativeAsOptional("ZR_SetClientKnockbackScale");
|
||||
MarkNativeAsOptional("ZR_SetClientKnockbackMaxForce");
|
||||
MarkNativeAsOptional("ZR_SetClientKnockbackMaxVelocity");
|
||||
}
|
||||
#endif
|
||||
|
@ -27,15 +27,8 @@
|
||||
|
||||
#define ZR_KNOCKBACK_CUSTOM (1<<31)
|
||||
#define ZR_KNOCKBACK_SCALE (1<<1)
|
||||
#define ZR_KNOCKBACK_LIMITVEL (1<<2)
|
||||
|
||||
/**
|
||||
* Set a maximum knockback velocity.
|
||||
*
|
||||
* @param client The client.
|
||||
* @param fVelocity Maximum knockback velocity / force.
|
||||
*/
|
||||
native void ZR_SetClientKnockbackMaxVelocity(int client, float fVelocity);
|
||||
#define ZR_KNOCKBACK_LIMITFORCE (1<<2)
|
||||
#define ZR_KNOCKBACK_LIMITVEL (1<<3)
|
||||
|
||||
/**
|
||||
* Set a custom knockback scale.
|
||||
@ -44,3 +37,19 @@ native void ZR_SetClientKnockbackMaxVelocity(int client, float fVelocity);
|
||||
* @param fScale Custom knockback scale.
|
||||
*/
|
||||
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)
|
||||
|
||||
// Natives
|
||||
CreateNative("ZR_SetClientKnockbackMaxVelocity", APISetClientKnockbackMaxVelocity);
|
||||
CreateNative("ZR_SetClientKnockbackScale", APISetClientKnockbackScale);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
CreateNative("ZR_SetClientKnockbackMaxForce", APISetClientKnockbackMaxForce);
|
||||
CreateNative("ZR_SetClientKnockbackMaxVelocity", APISetClientKnockbackMaxVelocity);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -66,3 +52,33 @@ public int APISetClientKnockbackScale(Handle plugin, int numParams)
|
||||
|
||||
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.
|
||||
SDKHook(client, SDKHook_TraceAttack, DamageTraceAttack);
|
||||
SDKHook(client, SDKHook_OnTakeDamage, DamageOnTakeDamage);
|
||||
SDKHook(client, SDKHook_OnTakeDamageAlivePost, DamageOnTakeDamageAlivePost);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -97,6 +98,7 @@ DamageOnClientDisconnect(client)
|
||||
{
|
||||
SDKUnhook(client, SDKHook_TraceAttack, DamageTraceAttack);
|
||||
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.
|
||||
|
||||
// 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.
|
||||
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.
|
||||
* 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.
|
||||
decl String:classname[64];
|
||||
GetEdictClassname(inflictor, classname, sizeof(classname));
|
||||
@ -437,3 +444,48 @@ public Action:DamageSuicideIntercept(int client, const char[] command, int argc)
|
||||
// Block command.
|
||||
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("player_team", EventPlayerTeam, EventHookMode_Pre);
|
||||
UnhookEvent("player_spawn", EventPlayerSpawn);
|
||||
UnhookEvent("player_hurt", EventPlayerHurt);
|
||||
UnhookEvent("player_death", EventPlayerDeath);
|
||||
UnhookEvent("player_jump", EventPlayerJump);
|
||||
|
||||
@ -67,7 +66,6 @@ EventHook(bool:unhook = false)
|
||||
HookEvent("round_end", EventRoundEnd);
|
||||
HookEvent("player_team", EventPlayerTeam, EventHookMode_Pre);
|
||||
HookEvent("player_spawn", EventPlayerSpawn);
|
||||
HookEvent("player_hurt", EventPlayerHurt);
|
||||
HookEvent("player_death", EventPlayerDeath);
|
||||
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.
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
* Client has been killed.
|
||||
|
@ -161,7 +161,7 @@ bool:ImmunityOnClientInfect(client, attacker)
|
||||
*
|
||||
* @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).
|
||||
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.
|
||||
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.
|
||||
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_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.
|
||||
@ -43,14 +45,16 @@ float g_fKnockbackScale[MAXPLAYERS + 1];
|
||||
*/
|
||||
void KnockbackClientInit(int client)
|
||||
{
|
||||
g_fKnockbackScale[client] = 1.0;
|
||||
|
||||
g_fKnockbackForceLimit[client] = 0.0;
|
||||
g_bKnockbackFrame[client] = false;
|
||||
g_fKnockbackVelLimit[client] = 0.0;
|
||||
g_bKnockbackFrameLimitVel[client] = false;
|
||||
g_fKnockbackVectors[client][0] = 0.0;
|
||||
g_fKnockbackVectors[client][1] = 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)
|
||||
{
|
||||
g_bKnockbackFrame[client] = false;
|
||||
g_fKnockbackVelLimit[client] = 0.0;
|
||||
|
||||
SDKUnhook(client, SDKHook_OnTakeDamageAlivePost, KnockbackOnTakeDamageAlivePost);
|
||||
KnockbackClientInit(client);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -71,18 +72,7 @@ void KnockbackOnClientDisconnect(int client)
|
||||
*/
|
||||
void KnockbackOnClientDeath(int client)
|
||||
{
|
||||
g_bKnockbackFrame[client] = false;
|
||||
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;
|
||||
KnockbackClientInit(client);
|
||||
}
|
||||
|
||||
void KnockbackSetClientScale(int client, float fScale)
|
||||
@ -90,6 +80,17 @@ void KnockbackSetClientScale(int client, float 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
|
||||
* doing expensive computations or declaring large local arrays.
|
||||
@ -98,17 +99,22 @@ void KnockbackOnGameFrame()
|
||||
{
|
||||
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]);
|
||||
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_bKnockbackFrameLimitVel[client] = false;
|
||||
g_fKnockbackVectors[client][0] = 0.0;
|
||||
g_fKnockbackVectors[client][1] = 0.0;
|
||||
g_fKnockbackVectors[client][2] = 0.0;
|
||||
@ -117,23 +123,18 @@ void KnockbackOnGameFrame()
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook: KnockbackOnTakeDamageAlivePost
|
||||
* Hook: KnockbackOnClientHurt
|
||||
* Called after client has been hurt.
|
||||
*
|
||||
* @param client The client index.
|
||||
* @param inflictor The entity index of the inflictor.
|
||||
* @param victim The client index.
|
||||
* @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.
|
||||
*/
|
||||
public void KnockbackOnTakeDamageAlivePost(int victim, int attacker, int inflictor, float damage, int damagetype, int weapon,
|
||||
const float damageForce[3], const float damagePosition[3], int damagecustom)
|
||||
public void KnockbackOnClientHurt(int victim, int attacker, int inflictor, const char[] weaponname, int hitgroup, float damage, int damagetype, int weapon, int damagecustom)
|
||||
{
|
||||
// If attacker is invalid, then stop.
|
||||
if (!ZRIsClientValid(attacker))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Client is a human, then stop.
|
||||
if (InfectIsClientHuman(victim))
|
||||
{
|
||||
@ -160,19 +161,6 @@ public void KnockbackOnTakeDamageAlivePost(int victim, int attacker, int inflict
|
||||
|
||||
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.
|
||||
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 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);
|
||||
|
||||
int hitgroup = HITGROUP_GENERIC;
|
||||
if (!(damagetype & DMG_BLAST) && !custom)
|
||||
hitgroup = ToolsGetClientLastHitGroup(victim);
|
||||
|
||||
if (custom)
|
||||
ToolsSetClientLastHitGroup(victim, HITGROUP_GENERIC);
|
||||
|
||||
@ -239,7 +224,7 @@ public void KnockbackOnTakeDamageAlivePost(int victim, int attacker, int inflict
|
||||
|
||||
// Apply 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 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.
|
||||
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).
|
||||
ScaleVector(vector, magnitude);
|
||||
|
||||
if (limitvel && g_fKnockbackVelLimit[client])
|
||||
if (limitforce && g_fKnockbackForceLimit[client])
|
||||
{
|
||||
AddVectors(g_fKnockbackVectors[client], vector, g_fKnockbackVectors[client]);
|
||||
g_bKnockbackFrame[client] = true;
|
||||
g_bKnockbackFrameLimitVel[client] |= limitvel;
|
||||
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.
|
||||
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.
|
||||
ToolsClientVelocity(client, vector);
|
||||
// Get their current velocity.
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @param client The client index.
|
||||
|
Loading…
Reference in New Issue
Block a user