I come here with a big request. A friend of mine has written a knife-throwing plugin: But knifes dont do damage when they ricochet. Anyone able to fix that?
PHP Code:
/*
* SourceMod Hosties Project
* by: databomb & dataviruset
*
* This file is part of the SM Hosties project.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* 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/>.
*/
// Sample Last Request Plugin: Shotgun Wars!
#include <sourcemod>
#include <sdktools>
#include <sdkhooks>
// Make certain the lastrequest.inc is last on the list
#include <hosties>
#include <lastrequest>
#pragma semicolon 1
#define PLUGIN_VERSION "1.0"
#define KNIFE_MDL "models/weapons/w_knife_ct.mdl"
#define KNIFEHIT_SOUND "weapons/knife/knife_hit3.wav"
#define TRAIL_MDL "materials/sprites/cbbl_smoke.vmt"
#define ADD_OUTPUT "OnUser1 !self:Kill::1.5:1"
// Colours
#define TRAIL_COLOR_T_0 {255, 20, 20, 255}
#define TRAIL_COLOR_T_1 {33, 128, 40, 255}
#define TRAIL_COLOR_T_2 {50, 255, 20, 255}
#define TRAIL_COLOR_T_3 {200, 20, 130, 255}
#define TRAIL_COLOR_T_4 {20, 126, 170, 255}
#define TRAIL_COLOR_T_5 {219, 200, 2, 255}
#define TRAIL_COLOR_CT_0 {13, 255, 12, 255}
#define TRAIL_COLOR_CT_1 {255, 20, 255, 255}
#define TRAIL_COLOR_CT_2 {255, 255, 255, 255}
#define TRAIL_COLOR_CT_3 {20, 20, 255, 255}
#define TRAIL_COLOR_CT_4 {255, 255, 15, 255}
#define TRAIL_COLOR_CT_5 {66, 166, 111, 255}
// This global will store the index number for the new Last Request
new g_LREntryNum;
new String:g_sLR_Name[64];
new Handle:gH_Timer_Countdown = INVALID_HANDLE;
new bool:bAllCountdownsCompleted = false;
new Handle:g_hLethalArray;
new Handle:g_CVarVelocity;
new Float:g_fVelocity;
new Handle:g_CVarDamage;
new String:g_sDamage[8];
new Handle:g_CVarHSDamage;
new String:g_sHSDamage[8];
new Handle:g_CVarTrail;
new bool:g_bTrail;
new Handle:g_CVarFF;
new const Float:g_fSpin[3] = {4877.4, 0.0, 0.0};
new const Float:g_fMinS[3] = {-24.0, -24.0, -24.0};
new const Float:g_fMaxS[3] = {24.0, 24.0, 24.0};
new g_iKnifeMI;
new g_iPointHurt;
new g_iEnvBlood;
new g_iTrailMI;
new bool:allow[MAXPLAYERS+1] = false;
new colourt[MAXPLAYERS+1];
new colourct[MAXPLAYERS+1];
public Plugin:myinfo =
{
name = "Last Request: Throwing Knives",
description = "Throwing Knives Fight",
version = PLUGIN_VERSION,
url = "hellclan.co.uk/"
};
public OnPluginStart()
{
// Load translations
LoadTranslations("throwingknives.phrases");
// Load the name in default server language
Format(g_sLR_Name, sizeof(g_sLR_Name), "%T", "Throwing Knives", LANG_SERVER);
// Create any cvars you need here
g_CVarVelocity = CreateConVar("sm_throwingknives_velocity", "7", "Velocity (speed) adjustment.", _, true, 1.0, true, 10.0);
g_CVarDamage = CreateConVar("sm_throwingknives_damage", "57", "Damage adjustment.", _, true, 10.0, true, 200.0);
g_CVarHSDamage = CreateConVar("sm_throwingknives_hsdamage", "127", "Headshot damage adjustment.", _, true, 20.0, true, 200.0);
g_CVarTrail = CreateConVar("sm_throwingknives_trail", "1", "Enable/disable trail effect.", _, true, 0.0, true, 1.0);
g_CVarFF = FindConVar("mp_friendlyfire");
// initialize global vars, hook CVar changes
g_fVelocity = (1000.0 + (250.0 * GetConVarFloat(g_CVarVelocity)));
HookConVarChange(g_CVarVelocity, CVarChange);
GetConVarString(g_CVarDamage, g_sDamage, sizeof(g_sDamage));
HookConVarChange(g_CVarDamage, CVarChange);
GetConVarString(g_CVarHSDamage, g_sHSDamage, sizeof(g_sHSDamage));
HookConVarChange(g_CVarHSDamage, CVarChange);
g_bTrail = GetConVarBool(g_CVarTrail);
HookConVarChange(g_CVarTrail, CVarChange);
AutoExecConfig(true, "throwingknives");
g_hLethalArray = CreateArray();
AddNormalSoundHook(NormalSHook:SoundsHook);
HookEvent("round_start", EventRoundStart, EventHookMode_PostNoCopy);
HookEvent("weapon_fire", EventWeaponFire);
HookEvent("player_death", EventPlayerDeath, EventHookMode_Pre);
for(new idx = 1; idx <= MaxClients ; idx++)
{
if(IsClientInGame(idx))
{
SDKHook(idx, SDKHook_WeaponCanUse, OnWeaponDecideUse);
}
}
}
public OnClientPutInServer(client)
{
SDKHook(client, SDKHook_WeaponCanUse, OnWeaponDecideUse);
}
public Action:OnWeaponDecideUse(client, weapon)
{
if(client > 0 && IsClientInGame(client) && IsPlayerAlive(client) && allow[client])
{
decl String:sClassname[128];
GetEntityClassname(weapon, sClassname, sizeof(sClassname));
if(StrContains(sClassname, "knife", false) == -1)
{
return Plugin_Handled;
}
}
return Plugin_Continue;
}
public CVarChange(Handle:convar, const String:oldValue[], const String:newValue[]) {
if (g_iPointHurt == -1)
CreateEnts();
else if (convar == g_CVarVelocity)
g_fVelocity = (1000.0 + (250.0 * StringToFloat(newValue)));
else if (convar == g_CVarDamage)
strcopy(g_sDamage, sizeof(g_sDamage), newValue);
else if (convar == g_CVarHSDamage)
strcopy(g_sHSDamage, sizeof(g_sHSDamage), newValue);
else if (convar == g_CVarTrail)
g_bTrail = GetConVarBool(g_CVarTrail);
}
public OnMapStart() {
g_iKnifeMI = PrecacheModel(KNIFE_MDL);
g_iTrailMI = PrecacheModel(TRAIL_MDL);
PrecacheSound(KNIFEHIT_SOUND);
}
public EventRoundStart(Handle:event, const String:name[], bool:dontBroadcast) {
g_iPointHurt = -1;
g_iEnvBlood = -1;
ClearArray(g_hLethalArray);
CreateEnts();
}
public OnConfigsExecuted()
{
static bool:bAddedThrowingKnives = false;
if (!bAddedThrowingKnives)
{
g_LREntryNum = AddLastRequestToList(ThrowingKnives_Start, ThrowingKnives_Stop, g_sLR_Name);
bAddedThrowingKnives = true;
}
}
// The plugin should remove any LRs it loads when it's unloaded
public OnPluginEnd()
{
RemoveLastRequestFromList(ThrowingKnives_Start, ThrowingKnives_Stop, g_sLR_Name);
}
public ThrowingKnives_Start(Handle:LR_Array, iIndexInArray)
{
new This_LR_Type = GetArrayCell(LR_Array, iIndexInArray, _:Block_LRType);
if (This_LR_Type == g_LREntryNum)
{
new LR_Player_Prisoner = GetArrayCell(LR_Array, iIndexInArray, _:Block_Prisoner);
new LR_Player_Guard = GetArrayCell(LR_Array, iIndexInArray, _:Block_Guard);
// check datapack value
new LR_Pack_Value = GetArrayCell(LR_Array, iIndexInArray, _:Block_Global1);
switch (LR_Pack_Value)
{
case -1:
{
PrintToServer("no info included");
}
}
SetEntityHealth(LR_Player_Prisoner, 250);
SetEntityHealth(LR_Player_Guard, 250);
StripAllWeapons(LR_Player_Prisoner);
StripAllWeapons(LR_Player_Guard);
allow[LR_Player_Prisoner] = true;
allow[LR_Player_Guard] = true;
colourt[LR_Player_Prisoner] = GetRandomInt(0, 5);
colourct[LR_Player_Guard] = GetRandomInt(0, 5);
// Store a countdown timer variable - we'll use 3 seconds
SetArrayCell(LR_Array, iIndexInArray, 3, _:Block_Global1);
if (gH_Timer_Countdown == INVALID_HANDLE)
{
gH_Timer_Countdown = CreateTimer(1.0, Timer_Countdown, _, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE);
}
PrintToChatAll(CHAT_BANNER, "LR TKF Start", LR_Player_Prisoner, LR_Player_Guard);
}
}
public ThrowingKnives_Stop(This_LR_Type, LR_Player_Prisoner, LR_Player_Guard)
{
if (This_LR_Type == g_LREntryNum)
{
if (IsClientInGame(LR_Player_Prisoner))
{
allow[LR_Player_Prisoner] = false;
allow[LR_Player_Guard] = false;
SetEntityGravity(LR_Player_Prisoner, 1.0);
if (IsPlayerAlive(LR_Player_Prisoner))
{
SetEntityHealth(LR_Player_Prisoner, 100);
GivePlayerItem(LR_Player_Prisoner, "weapon_knife");
PrintToChatAll(CHAT_BANNER, "TKF Win", LR_Player_Prisoner);
}
}
if (IsClientInGame(LR_Player_Guard))
{
allow[LR_Player_Prisoner] = false;
allow[LR_Player_Guard] = false;
SetEntityGravity(LR_Player_Guard, 1.0);
if (IsPlayerAlive(LR_Player_Guard))
{
SetEntityHealth(LR_Player_Guard, 100);
GivePlayerItem(LR_Player_Guard, "weapon_knife");
PrintToChatAll(CHAT_BANNER, "TKF Win", LR_Player_Guard);
}
}
}
}
public Action:Timer_Countdown(Handle:timer)
{
new numberOfLRsActive = ProcessAllLastRequests(ThrowingKnives_Countdown, g_LREntryNum);
if ((numberOfLRsActive <= 0) || bAllCountdownsCompleted)
{
gH_Timer_Countdown = INVALID_HANDLE;
return Plugin_Stop;
}
return Plugin_Continue;
}
public ThrowingKnives_Countdown(Handle:LR_Array, iIndexInArray)
{
new LR_Player_Prisoner = GetArrayCell(LR_Array, iIndexInArray, _:Block_Prisoner);
new LR_Player_Guard = GetArrayCell(LR_Array, iIndexInArray, _:Block_Guard);
new countdown = GetArrayCell(LR_Array, iIndexInArray, _:Block_Global1);
if (countdown > 0)
{
StripAllWeapons(LR_Player_Prisoner);
StripAllWeapons(LR_Player_Guard);
bAllCountdownsCompleted = false;
PrintCenterText(LR_Player_Prisoner, "LR begins in %i...", countdown);
PrintCenterText(LR_Player_Guard, "LR begins in %i...", countdown);
SetArrayCell(LR_Array, iIndexInArray, --countdown, _:Block_Global1);
}
else if (countdown == 0)
{
bAllCountdownsCompleted = true;
SetArrayCell(LR_Array, iIndexInArray, --countdown, _:Block_Global1);
new PrisonerKnife = GivePlayerItem(LR_Player_Prisoner, "weapon_knife");
new GuardKnife = GivePlayerItem(LR_Player_Guard, "weapon_knife");
SetArrayCell(LR_Array, iIndexInArray, PrisonerKnife, _:Block_PrisonerData);
SetArrayCell(LR_Array, iIndexInArray, GuardKnife, _:Block_GuardData);
SetEntityGravity(LR_Player_Prisoner, 0.7);
SetEntityGravity(LR_Player_Guard, 0.7);
}
}
public EventWeaponFire(Handle:event,const String:name[],bool:dontBroadcast)
{
new client = GetClientOfUserId(GetEventInt(event, "userid"));
static String:sWeapon[32];
GetEventString(event, "weapon", sWeapon, sizeof(sWeapon));
if(IsPlayerAlive(client) && IsClientInGame(client) && allow[client] && !IsFakeClient(client) && StrEqual(sWeapon, "knife"))
{
ThrowKnife(client);
}
}
public EventPlayerDeath(Handle:event,const String:name[],bool:dontBroadcast)
{
decl String:sWeapon[32];
GetEventString(event, "weapon", sWeapon, sizeof(sWeapon));
new bool:tknife = StrEqual(sWeapon, "tknife");
new bool:tknifehs = StrEqual(sWeapon, "tknifehs");
if (tknife || tknifehs)
{
// the event is pre-hooked,
// setting the weapon string will change the icon used in the kill notification
SetEventString(event, "weapon", "knife");
}
}
ThrowKnife(client)
{
static Float:fPos[3], Float:fAng[3], Float:fVel[3], Float:fPVel[3];
GetClientEyePosition(client, fPos);
// create & spawn entity. set model & owner. set to kill itself OnUser1
// calc & set spawn position, angle, velocity & spin
// add to lethal knife array, teleport, add trial, ...
new entity = CreateEntityByName("flashbang_projectile");
if ((entity != -1) && DispatchSpawn(entity)) {
SetEntityModel(entity, KNIFE_MDL);
SetEntPropEnt(entity, Prop_Send, "m_hOwnerEntity", client);
SetVariantString(ADD_OUTPUT);
AcceptEntityInput(entity, "AddOutput");
GetClientEyeAngles(client, fAng);
GetAngleVectors(fAng, fVel, NULL_VECTOR, NULL_VECTOR);
ScaleVector(fVel, g_fVelocity);
GetEntPropVector(client, Prop_Data, "m_vecVelocity", fPVel);
AddVectors(fVel, fPVel, fVel);
SetEntPropVector(entity, Prop_Data, "m_vecAngVelocity", g_fSpin);
SetEntPropFloat(entity, Prop_Send, "m_flElasticity", 0.2);
PushArrayCell(g_hLethalArray, entity);
TeleportEntity(entity, fPos, fAng, fVel);
if (g_bTrail)
{
if(GetClientTeam(client) == 2)
{
if(colourt[client] == 0)
{
TE_SetupBeamFollow(entity, g_iTrailMI, 0, 0.7, 7.7, 7.7, 3, TRAIL_COLOR_T_0);
}
if(colourt[client] == 1)
{
TE_SetupBeamFollow(entity, g_iTrailMI, 0, 0.7, 7.7, 7.7, 3, TRAIL_COLOR_T_1);
}
if(colourt[client] == 2)
{
TE_SetupBeamFollow(entity, g_iTrailMI, 0, 0.7, 7.7, 7.7, 3, TRAIL_COLOR_T_2);
}
if(colourt[client] == 3)
{
TE_SetupBeamFollow(entity, g_iTrailMI, 0, 0.7, 7.7, 7.7, 3, TRAIL_COLOR_T_3);
}
if(colourt[client] == 4)
{
TE_SetupBeamFollow(entity, g_iTrailMI, 0, 0.7, 7.7, 7.7, 3, TRAIL_COLOR_T_4);
}
if(colourt[client] == 5)
{
TE_SetupBeamFollow(entity, g_iTrailMI, 0, 0.7, 7.7, 7.7, 3, TRAIL_COLOR_T_5);
}
}
if(GetClientTeam(client) == 3)
{
if(colourct[client] == 0)
{
TE_SetupBeamFollow(entity, g_iTrailMI, 0, 0.7, 7.7, 7.7, 3, TRAIL_COLOR_CT_0);
}
if(colourct[client] == 1)
{
TE_SetupBeamFollow(entity, g_iTrailMI, 0, 0.7, 7.7, 7.7, 3, TRAIL_COLOR_CT_1);
}
if(colourct[client] == 2)
{
TE_SetupBeamFollow(entity, g_iTrailMI, 0, 0.7, 7.7, 7.7, 3, TRAIL_COLOR_CT_2);
}
if(colourct[client] == 3)
{
TE_SetupBeamFollow(entity, g_iTrailMI, 0, 0.7, 7.7, 7.7, 3, TRAIL_COLOR_CT_3);
}
if(colourct[client] == 4)
{
TE_SetupBeamFollow(entity, g_iTrailMI, 0, 0.7, 7.7, 7.7, 3, TRAIL_COLOR_CT_4);
}
if(colourct[client] == 5)
{
TE_SetupBeamFollow(entity, g_iTrailMI, 0, 0.7, 7.7, 7.7, 3, TRAIL_COLOR_CT_5);
}
}
TE_SendToAll();
}
}
}
public Action:SoundsHook(clients[64], &numClients, String:sample[PLATFORM_MAX_PATH], &entity, &channel, &Float:volume, &level, &pitch, &flags) {
if (StrEqual(sample, "weapons/flashbang/grenade_hit1.wav", false)) {
new index = FindValueInArray(g_hLethalArray, entity);
if (index != -1) {
volume = 0.2;
RemoveFromArray(g_hLethalArray, index); // delethalize on first bounce
new attacker = GetEntPropEnt(entity, Prop_Send, "m_hOwnerEntity");
static Float:fKnifePos[3], Float:fAttPos[3], Float:fVicEyePos[3];
GetEntPropVector(entity, Prop_Data, "m_vecOrigin", fKnifePos);
new victim = GetTraceHullEntityIndex(fKnifePos, attacker);
if (IsClientIndex(victim) && IsClientInGame(attacker)) {
RemoveEdict(entity);
if (GetConVarBool(g_CVarFF) || (GetClientTeam(victim) != GetClientTeam(attacker))) {
GetClientAbsOrigin(attacker, fAttPos);
GetClientEyePosition(victim, fVicEyePos);
EmitAmbientSound(KNIFEHIT_SOUND, fKnifePos, victim, SNDLEVEL_NORMAL, _, 0.8);
// HURT!
if (IsValidEntity(g_iPointHurt)) {
new bool:headShot = (FloatAbs(fKnifePos[2] - fVicEyePos[2]) < 4.7) ? true : false;
DispatchKeyValue(victim, "targetname", "hurt");
DispatchKeyValue(g_iPointHurt, "Damage", (headShot) ? g_sHSDamage : g_sDamage);
DispatchKeyValue(g_iPointHurt, "classname", (headShot) ? "weapon_tknifehs" : "weapon_tknife");
TeleportEntity(g_iPointHurt, fAttPos, NULL_VECTOR, NULL_VECTOR);
AcceptEntityInput(g_iPointHurt, "Hurt", attacker);
DispatchKeyValue(g_iPointHurt, "classname", "point_hurt");
DispatchKeyValue(victim, "targetname", "nohurt");
SetVariantString("BloodImpact");
AcceptEntityInput(entity, "DispatchEffect");
if (IsValidEntity(g_iEnvBlood))
AcceptEntityInput(g_iEnvBlood, "EmitBlood", victim);
}
}
}
else // didn't hit a player, kill itself in a few seconds
AcceptEntityInput(entity, "FireUser1");
return Plugin_Changed;
}
else if (GetEntProp(entity, Prop_Send, "m_nModelIndex") == g_iKnifeMI) {
volume = 0.2;
return Plugin_Changed;
}
}
return Plugin_Continue;
}
GetTraceHullEntityIndex(Float:pos[3], xindex) {
TR_TraceHullFilter(pos, pos, g_fMinS, g_fMaxS, MASK_SHOT, THFilter, xindex);
return TR_GetEntityIndex();
}
public bool:THFilter(entity, contentsMask, any:data) {
return IsClientIndex(entity) && (entity != data);
}
bool:IsClientIndex(index) {
return (index > 0) && (index <= MaxClients);
}
CreateEnts() {
if (((g_iPointHurt = CreateEntityByName("point_hurt")) != -1) && DispatchSpawn(g_iPointHurt)) {
DispatchKeyValue(g_iPointHurt, "DamageTarget", "hurt");
DispatchKeyValue(g_iPointHurt, "DamageType", "0");
}
if (((g_iEnvBlood = CreateEntityByName("env_blood")) != -1) && DispatchSpawn(g_iEnvBlood)) {
DispatchKeyValue(g_iEnvBlood, "spawnflags", "13");
DispatchKeyValue(g_iEnvBlood, "amount", "1000");
}
}