407 lines
12 KiB
SourcePawn
407 lines
12 KiB
SourcePawn
/*
|
|
* ============================================================================
|
|
*
|
|
* Zombie:Reloaded
|
|
*
|
|
* File: knockback.sp
|
|
* Type: Test plugin
|
|
* Description: Tests basic knock back.
|
|
*
|
|
* Copyright (C) 2009-2013 Greyscale, Richard Helgeby
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* ============================================================================
|
|
*/
|
|
|
|
#pragma semicolon 1
|
|
#include <sourcemod>
|
|
#include <sdktools>
|
|
#include <sdkhooks-2.2>
|
|
|
|
public Plugin:myinfo =
|
|
{
|
|
name = "Knock back",
|
|
author = "Greyscale | Richard Helgeby",
|
|
description = "Tests basic knock back.",
|
|
version = "1.0.0",
|
|
url = "http://code.google.com/p/zombiereloaded/"
|
|
};
|
|
|
|
new Handle:hKnockBackMultiplier;
|
|
new g_iToolsVelocity;
|
|
new bool:VelocityMonitor[MAXPLAYERS];
|
|
|
|
public OnPluginStart()
|
|
{
|
|
hKnockBackMultiplier = CreateConVar("zrtest_knockback", "4.0", "Knock back multiplier.");
|
|
|
|
if (!HookEventEx("player_hurt", Event_PlayerHurt))
|
|
{
|
|
LogError("Failed to hook event player_hurt.");
|
|
}
|
|
|
|
// If offset "m_vecVelocity[0]" can't be found, then stop the plugin.
|
|
g_iToolsVelocity = FindSendPropInfo("CBasePlayer", "m_vecVelocity[0]");
|
|
if (g_iToolsVelocity == -1)
|
|
{
|
|
LogError("Offset \"CBasePlayer::m_vecVelocity[0]\" was not found.");
|
|
}
|
|
|
|
RegConsoleCmd("zrtest_push_player", Command_PushPlayer, "Push a player. Usage: zrtest_push_player <x> <y> <z> [0|1 - base velocity]");
|
|
RegConsoleCmd("zrtest_parent", Command_Parent, "Prints your parent entity.");
|
|
RegConsoleCmd("zrtest_friction", Command_Friction, "Prints your floor friction multiplier.");
|
|
RegConsoleCmd("zrtest_maxspeed", Command_MaxSpeed, "Prints your max speed.");
|
|
}
|
|
|
|
public Action:Command_PushPlayer(client, argc)
|
|
{
|
|
if (argc < 3)
|
|
{
|
|
ReplyToCommand(client, "Push a player. Usage: zrtest_push_player <x> <y> <z> [0|1 - base velocity]");
|
|
return Plugin_Handled;
|
|
}
|
|
|
|
new Float:velocity[3];
|
|
new String:buffer[32];
|
|
new bool:baseVelocity = false;
|
|
|
|
for (new i = 0; i < 3; i++)
|
|
{
|
|
GetCmdArg(i + 1, buffer, sizeof(buffer));
|
|
velocity[i] = StringToFloat(buffer);
|
|
}
|
|
|
|
if (argc > 3)
|
|
{
|
|
GetCmdArg(4, buffer, sizeof(buffer));
|
|
baseVelocity = bool:StringToInt(buffer);
|
|
}
|
|
|
|
PrintToChatAll("Applying velocity on client %d (base: %d): %0.2f | %0.2f | %0.2f", client, baseVelocity, velocity[0], velocity[1], velocity[2]);
|
|
|
|
if (baseVelocity)
|
|
{
|
|
SetBaseVelocity(client, velocity);
|
|
}
|
|
else
|
|
{
|
|
TeleportEntity(client, NULL_VECTOR, NULL_VECTOR, velocity);
|
|
//SetVelocity(client, velocity);
|
|
}
|
|
|
|
return Plugin_Handled;
|
|
}
|
|
|
|
public Action:Command_Parent(client, argc)
|
|
{
|
|
new parent = GetParent(client);
|
|
ReplyToCommand(client, "Parent index: %d", parent);
|
|
|
|
return Plugin_Handled;
|
|
}
|
|
|
|
public Action:Command_Friction(client, argc)
|
|
{
|
|
new Float:friction = GetFriction(client);
|
|
ReplyToCommand(client, "Friction: %0.2f", friction);
|
|
|
|
return Plugin_Handled;
|
|
}
|
|
|
|
public Action:Command_MaxSpeed(client, argc)
|
|
{
|
|
new Float:maxSpeed = GetMaxSpeed(client);
|
|
ReplyToCommand(client, "Max speed: %0.2f", maxSpeed);
|
|
|
|
return Plugin_Handled;
|
|
}
|
|
|
|
public OnClientPutInServer(client)
|
|
{
|
|
//SDKHook(client, SDKHook_OnTakeDamagePost, OnTakeDamagePost);
|
|
//SDKHook(client, SDKHook_PreThink, PreThink);
|
|
//SDKHook(client, SDKHook_PreThinkPost, PreThinkPost);
|
|
SDKHook(client, SDKHook_PostThink, PostThink);
|
|
//SDKHook(client, SDKHook_PostThinkPost, PostThinkPost);
|
|
}
|
|
|
|
public OnClientDisconnect(client)
|
|
{
|
|
//SDKUnhook(client, SDKHook_OnTakeDamagePost, OnTakeDamagePost);
|
|
//SDKUnhook(client, SDKHook_PreThink, PreThink);
|
|
//SDKUnhook(client, SDKHook_PreThinkPost, PreThinkPost);
|
|
SDKUnhook(client, SDKHook_PostThink, PostThink);
|
|
//SDKUnhook(client, SDKHook_PostThinkPost, PostThinkPost);
|
|
}
|
|
|
|
public Action:Event_PlayerHurt(Handle:event, const String:name[], bool:dontBroadcast)
|
|
{
|
|
new victim = GetClientOfUserId(GetEventInt(event, "userid"));
|
|
new damage = GetEventInt(event, "dmg_health");
|
|
new attacker = GetClientOfUserId(GetEventInt(event, "attacker"));
|
|
KnockbackOnClientHurt(victim, attacker, float(damage));
|
|
}
|
|
|
|
/*public Action:OnTakeDamage(victim, &attacker, &inflictor, &Float:damage, &damagetype, &weapon, Float:damageForce[3], Float:damagePosition[3])
|
|
{
|
|
KnockbackOnClientHurt(victim, attacker, Float:damage);
|
|
|
|
// Allow damage.
|
|
return Plugin_Continue;
|
|
}
|
|
|
|
public OnTakeDamagePost(victim, attacker, inflictor, Float:damage, damagetype, weapon, const Float:damageForce[3], const Float:damagePosition[3])
|
|
{
|
|
if (attacker > 0 && attacker < MaxClients)
|
|
{
|
|
KnockbackOnClientHurt(victim, attacker, Float:damage);
|
|
}
|
|
}*/
|
|
|
|
/*public PreThink(client)
|
|
{
|
|
//if (VelocityMonitor[client])
|
|
{
|
|
PrintVelocity(client, "PreThink");
|
|
}
|
|
}*/
|
|
|
|
/*public PreThinkPost(client)
|
|
{
|
|
//if (VelocityMonitor[client])
|
|
{
|
|
PrintVelocity(client, "PreThinkPost");
|
|
}
|
|
}*/
|
|
|
|
public PostThink(client)
|
|
{
|
|
//if (VelocityMonitor[client])
|
|
/*{
|
|
PrintVelocity(client, "PostThink");
|
|
}*/
|
|
|
|
SetMaxSpeed(client, 1000.0);
|
|
}
|
|
|
|
/*public PostThinkPost(client)
|
|
{
|
|
//if (VelocityMonitor[client])
|
|
{
|
|
PrintVelocity(client, "PostThinkPost");
|
|
VelocityMonitor[client] = false;
|
|
}
|
|
}*/
|
|
|
|
stock PrintVelocity(client, const String:prefix[])
|
|
{
|
|
new Float:velocity[3];
|
|
GetVelocity(client, velocity);
|
|
PrintToChatAll("%s | client: %d | %0.2f | %0.2f | %0.2f", prefix, client, velocity[0], velocity[1], velocity[2]);
|
|
}
|
|
|
|
/** Client has been hurt.
|
|
*
|
|
* @param client The client index. (zombie)
|
|
* @param attacker The attacker index. (human)
|
|
* @param weapon The weapon used.
|
|
* @param hitgroup Hitgroup attacker has damaged.
|
|
* @param dmg_health Damage done.
|
|
*/
|
|
KnockbackOnClientHurt(client, attacker, Float:dmg_health)
|
|
{
|
|
// If attacker is invalid, then stop.
|
|
if (!(attacker > 0 && attacker < MaxClients))
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Get zombie knockback value.
|
|
new Float:knockback = GetConVarFloat(hKnockBackMultiplier);
|
|
|
|
new Float:clientloc[3];
|
|
new Float:attackerloc[3];
|
|
|
|
GetClientAbsOrigin(client, clientloc);
|
|
|
|
// Get attackers eye position.
|
|
GetClientEyePosition(attacker, attackerloc);
|
|
|
|
// Get attackers eye angles.
|
|
new Float:attackerang[3];
|
|
GetClientEyeAngles(attacker, attackerang);
|
|
|
|
// Calculate knockback end-vector.
|
|
TR_TraceRayFilter(attackerloc, attackerang, MASK_ALL, RayType_Infinite, KnockbackTRFilter);
|
|
TR_GetEndPosition(clientloc);
|
|
|
|
// Apply damage knockback multiplier.
|
|
knockback *= dmg_health;
|
|
|
|
// Apply knockback.
|
|
PrintToChat(attacker, "Applying knock back: %0.2f", knockback);
|
|
VelocityMonitor[client] = true;
|
|
KnockbackSetVelocity(client, attackerloc, clientloc, knockback);
|
|
}
|
|
|
|
/**
|
|
* Sets velocity on a player.
|
|
*
|
|
* @param client The client index.
|
|
* @param startpoint The starting coordinate to push from.
|
|
* @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)
|
|
{
|
|
// Create vector from the given starting and ending points.
|
|
new Float:vector[3];
|
|
MakeVectorFromPoints(startpoint, endpoint, vector);
|
|
|
|
// Normalize the vector (equal magnitude at varying distances).
|
|
NormalizeVector(vector, vector);
|
|
|
|
// Changes by zephyrus:
|
|
//new flags = GetEntityFlags(client);
|
|
//if(flags & FL_ONGROUND)
|
|
// vector[2]=0.5;
|
|
|
|
// Apply the magnitude by scaling the vector (multiplying each of its components).
|
|
ScaleVector(vector, magnitude);
|
|
|
|
// Changes by zephyrus:
|
|
//if(flags & FL_ONGROUND)
|
|
// if(vector[2]>350.0)
|
|
// vector[2]=350.0;
|
|
|
|
new flags = GetEntityFlags(client);
|
|
if (flags & FL_ONGROUND)
|
|
{
|
|
if (vector[2] < 251.0)
|
|
{
|
|
vector[2] = 251.0;
|
|
}
|
|
}
|
|
|
|
// ADD the given vector to the client's current velocity.
|
|
PrintToChatAll("Applying velocity on client %d: %0.2f | %0.2f | %0.2f", client, vector[0], vector[1], vector[2]);
|
|
ToolsClientVelocity(client, vector);
|
|
}
|
|
|
|
/**
|
|
* Get or set a client's velocity.
|
|
* @param client The client index.
|
|
* @param vecVelocity Array to store vector in, or velocity to set on client.
|
|
* @param retrieve True to get client's velocity, false to set it.
|
|
* @param stack If modifying velocity, then true will stack new velocity onto the client's
|
|
* current velocity, false will reset it.
|
|
*/
|
|
stock ToolsClientVelocity(client, Float:vecVelocity[3], bool:apply = true, bool:stack = true)
|
|
{
|
|
// If retrieve if true, then get client's velocity.
|
|
if (!apply)
|
|
{
|
|
// x = vector component.
|
|
for (new x = 0; x < 3; x++)
|
|
{
|
|
vecVelocity[x] = GetEntDataFloat(client, g_iToolsVelocity + (x*4));
|
|
}
|
|
|
|
// Stop here.
|
|
return;
|
|
}
|
|
|
|
// If stack is true, then add client's velocity.
|
|
if (stack)
|
|
{
|
|
// Get client's velocity.
|
|
new Float:vecClientVelocity[3];
|
|
|
|
// x = vector component.
|
|
for (new x = 0; x < 3; x++)
|
|
{
|
|
vecClientVelocity[x] = GetEntDataFloat(client, g_iToolsVelocity + (x*4));
|
|
}
|
|
|
|
AddVectors(vecClientVelocity, vecVelocity, vecVelocity);
|
|
}
|
|
|
|
// Apply velocity on client.
|
|
TeleportEntity(client, NULL_VECTOR, NULL_VECTOR, vecVelocity);
|
|
}
|
|
|
|
/**
|
|
* Trace Ray forward, used as a filter to continue tracing if told so. (See sdktools_trace.inc)
|
|
*
|
|
* @param entity The entity index.
|
|
* @param contentsMask The contents mask.
|
|
* @return True to allow hit, false to continue tracing.
|
|
*/
|
|
public bool:KnockbackTRFilter(entity, contentsMask)
|
|
{
|
|
// If entity is a player, continue tracing.
|
|
if (entity > 0 && entity < MAXPLAYERS)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Allow hit.
|
|
return true;
|
|
}
|
|
|
|
stock GetVelocity(client, Float:velocity[3])
|
|
{
|
|
velocity[0] = GetEntPropFloat(client, Prop_Send, "m_vecVelocity[0]");
|
|
velocity[1] = GetEntPropFloat(client, Prop_Send, "m_vecVelocity[1]");
|
|
velocity[2] = GetEntPropFloat(client, Prop_Send, "m_vecVelocity[2]");
|
|
}
|
|
|
|
stock SetVelocity(client, const Float:velocity[3])
|
|
{
|
|
SetEntPropFloat(client, Prop_Send, "m_vecVelocity[0]", velocity[0]);
|
|
SetEntPropFloat(client, Prop_Send, "m_vecVelocity[1]", velocity[1]);
|
|
SetEntPropFloat(client, Prop_Send, "m_vecVelocity[2]", velocity[2]);
|
|
}
|
|
|
|
stock GetBaseVelocity(client, Float:velocity[3])
|
|
{
|
|
GetEntPropVector(client, Prop_Send, "m_vecBaseVelocity", velocity);
|
|
}
|
|
|
|
stock SetBaseVelocity(client, const Float:velocity[3])
|
|
{
|
|
SetEntPropVector(client, Prop_Send, "m_vecBaseVelocity", velocity);
|
|
}
|
|
|
|
stock GetParent(client)
|
|
{
|
|
return GetEntProp(client, Prop_Send, "moveparent");
|
|
}
|
|
|
|
stock Float:GetFriction(client)
|
|
{
|
|
return GetEntPropFloat(client, Prop_Send, "m_flFriction");
|
|
}
|
|
|
|
stock Float:GetMaxSpeed(client)
|
|
{
|
|
return GetEntPropFloat(client, Prop_Send, "m_flMaxspeed");
|
|
}
|
|
|
|
stock SetMaxSpeed(client, Float:maxSpeed = 250.0)
|
|
{
|
|
SetEntPropFloat(client, Prop_Send, "m_flMaxspeed", maxSpeed);
|
|
}
|