And I've edited another plugin so players have a 30% chance to get a hook when they finish the map.
But the problem is, when you shoot the hook on one of those boxes where players need to jump, they fall.
So players who complete the map can use the hook to ruin the game for other players:
PHP Code:
/***********************************************************************************\
* Hook By P34nut * Thanks to Joka69, Chaosphere for testing and stuff! *
*************************************************************************************
* Commands/ bindings:
* +hook to throw the hook
* -hook to delete your hook
*
* Cvars:
* sv_hook - Turns hook on or off
* sv_hookthrowspeed - Throw speed (default: 1000)
* sv_hookspeed - Speed to hook (default: 300)
* sv_hookwidth - Width of the hook (default: 32)
* sv_hooksound - Sounds of the hook on or off (default: 1)
* sv_hookcolor - The color of the hook 0 is white and 1 is team color (default: 1)
* sv_hookplayers - If set 1 you can hook on players (default: 0)
* sv_hookinterrupt - Remove the hook when something comes in its line (default: 0)
* sv_hookadminonly - Hook for admin only (default: 0)
* sv_hooksky - If set 1 you can hook in the sky (default: 0)
* sv_hookopendoors - If set 1 you can open doors with the hook (default: 1)
* sv_hookbuttons - If set 1 you can use buttons with the hook (default: 0)
* sv_hookpickweapons - If set 1 you can pickup weapons with the hook (default: 1)
* sv_hookhostflollow - If set 1 you can make hostages follow you (default 1)
* sv_hookinstant - Hook doesnt throw (default: 0)
* sv_hooknoise - adds some noise to the hook line (default: 0)
* sv_hookmax - Maximun numbers of hooks a player can use in 1 round
* - 0 for infinitive hooks (default: 0)
* sv_hookdelay - delay on the start of each round before a player can hook
* - 0.0 for no delay (default: 0.0)
*
* ChangeLog:
* 1.0: Release
* 1.5: added cvars:
* sv_hooknoise
* sv_hookmax
* sv_hookdelay
* public cvar: sv_amxxhookmod
* added commands:
* amx_givehook <username>
* amx_takehook <username>
*
\***********************************************************************************/
// Players admin level
#define ADMINLEVEL ADMIN_SLAY
#include <amxmodx>
#include <amxmisc>
#include <fakemeta>
#include <cstrike>
#include <xs>
#define message_begin_f(%1,%2,%3,%4) engfunc(EngFunc_MessageBegin, %1, %2, %3, %4)
#define write_coord_f(%1) engfunc(EngFunc_WriteCoord, %1)
//Cvars
new pHook, pThrowSpeed, pSpeed, pWidth, pSound, pColor
new pInterrupt, pAdmin, pHookSky, pOpenDoors, pPlayers
new pUseButtons, pHostage, pWeapons, pInstant, pHookNoise
new pMaxHooks, pRndStartDelay
// Sprite
new sprBeam
// Players hook entity
new Hook[33]
// MaxPlayers
new gMaxPlayers
// some booleans
new bool:gHooked[33]
new bool:canThrowHook[33]
new bool:rndStarted
// Player Spawn
new bool:gRestart[33] = {false, ...}
new bool:gUpdate[33] = {false, ...}
new gHooksUsed[33] // Used with sv_hookmax
new bool:g_bHookAllowed[33] // Used with sv_hookadminonly
public plugin_init()
{
register_plugin("Hook", "1.5", "P34nut")
// Hook commands
register_clcmd("+hook", "make_hook")
register_clcmd("-hook", "del_hook")
register_concmd("amx_givehook", "give_hook", ADMINLEVEL, "<Username> - Give somebody access to the hook")
register_concmd("amx_takehook", "take_hook", ADMINLEVEL, "<UserName> - Take away somebody his access to the hook")
// Events for roundstart
register_event("HLTV", "round_bstart", "a", "1=0", "2=0")
register_logevent("round_estart", 2, "1=Round_Start")
// Player spawn stuff
register_event("TextMsg", "Restart", "a", "2=#Game_will_restart_in")
register_clcmd("fullupdate", "Update")
register_event("ResetHUD", "ResetHUD", "b")
// Register cvars
register_cvar("sv_amxxhookmod", "version 1.5", FCVAR_SERVER) // yay public cvar
pHook = register_cvar("sv_hook", "1")
pThrowSpeed = register_cvar("sv_hookthrowspeed", "2000")
pSpeed = register_cvar("sv_hookspeed", "720")
pWidth = register_cvar("sv_hookwidth", "16")
pSound = register_cvar("sv_hooksound", "0")
pColor = register_cvar("sv_hookcolor", "1")
pPlayers = register_cvar("sv_hookplayers", "0")
pInterrupt = register_cvar("sv_hookinterrupt", "0")
pAdmin = register_cvar("sv_hookadminonly", "1")
pHookSky = register_cvar("sv_hooksky", "0")
pOpenDoors = register_cvar("sv_hookopendoors", "0")
pUseButtons = register_cvar("sv_hookusebuttons", "0")
pHostage = register_cvar("sv_hookhostflollow", "0")
pWeapons = register_cvar("sv_hookpickweapons", "0")
pInstant = register_cvar("sv_hookinstant", "0")
pHookNoise = register_cvar("sv_hooknoise", "0")
pMaxHooks = register_cvar("sv_hookmax", "0")
pRndStartDelay = register_cvar("sv_hookrndstartdelay", "0.0")
// Touch forward
register_forward(FM_Touch, "fwTouch")
// Get maxplayers
gMaxPlayers = get_maxplayers()
}
public plugin_precache()
{
// Hook Model
engfunc(EngFunc_PrecacheModel, "models/rpgrocket.mdl")
// Hook Beam
sprBeam = engfunc(EngFunc_PrecacheModel, "sprites/zbeam4.spr")
// Hook Sounds
engfunc(EngFunc_PrecacheSound, "weapons/xbow_hit1.wav") // good hit
engfunc(EngFunc_PrecacheSound, "weapons/xbow_hit2.wav") // wrong hit
engfunc(EngFunc_PrecacheSound, "weapons/xbow_hitbod1.wav") // player hit
engfunc(EngFunc_PrecacheSound, "weapons/xbow_fire1.wav") // deploy
}
public make_hook(id)
{
if (get_pcvar_num(pHook) && is_user_alive(id) && canThrowHook[id] && !gHooked[id]) {
if (get_pcvar_num(pAdmin))
{
// Only the admins can throw the hook
// if(is_user_admin(id)) { <- does not work...
if (!(get_user_flags(id) & ADMINLEVEL) && !g_bHookAllowed[id])
{
// Show a message
client_print(id, print_chat, "[Hook] Nemas kuku.")
console_print(id, "[Hook] Nemas kuku.")
return PLUGIN_HANDLED
}
}
new iMaxHooks = get_pcvar_num(pMaxHooks)
if (iMaxHooks > 0)
{
if (gHooksUsed[id] >= iMaxHooks)
{
client_print(id, print_chat, "[Hook] You already used your maximum ammount of hooks")
statusMsg(id, "[Hook] %d of %d hooks used.", gHooksUsed[id], get_pcvar_num(pMaxHooks))
return PLUGIN_HANDLED
}
else
{
gHooksUsed[id]++
statusMsg(id, "[Hook] %d of %d hooks used.", gHooksUsed[id], get_pcvar_num(pMaxHooks))
}
}
new Float:fDelay = get_pcvar_float(pRndStartDelay)
if (fDelay > 0 && !rndStarted)
client_print(id, print_chat, "[Hook] You cannot use the hook in the first %0.0f seconds of the round", fDelay)
throw_hook(id)
}
return PLUGIN_HANDLED
}
public del_hook(id)
{
// Remove players hook
if (!canThrowHook[id])
remove_hook(id)
return PLUGIN_HANDLED
}
public round_bstart()
{
// Round is not started anymore
if (rndStarted)
rndStarted = false
// Remove all hooks
for (new i = 1; i <= gMaxPlayers; i++)
{
if (is_user_connected(i))
{
if(!canThrowHook[i])
remove_hook(i)
}
}
}
public round_estart()
{
new Float:fDelay = get_pcvar_float(pRndStartDelay)
if (fDelay > 0.0)
set_task(fDelay, "rndStartDelay")
else
{
// Round is started...
if (!rndStarted)
rndStarted = true
}
}
public rndStartDelay()
{
if (!rndStarted)
rndStarted = true
}
public Restart()
{
for (new id = 0; id < gMaxPlayers; id++)
{
if (is_user_connected(id))
gRestart[id] = true
}
}
public Update(id)
{
if (!gUpdate[id])
gUpdate[id] = true
return PLUGIN_CONTINUE
}
public ResetHUD(id)
{
if (gRestart[id])
{
gRestart[id] = false
return
}
if (gUpdate[id])
{
gUpdate[id] = false
return
}
if (gHooked[id])
{
remove_hook(id)
}
if (get_pcvar_num(pMaxHooks) > 0)
{
gHooksUsed[id] = 0
statusMsg(0, "[Hook] 0 of %d hooks used.", get_pcvar_num(pMaxHooks))
}
}
public fwTouch(ptr, ptd)
{
if (!pev_valid(ptr))
return FMRES_IGNORED
new id = pev(ptr, pev_owner)
// Get classname
static szPtrClass[32]
pev(ptr, pev_classname, szPtrClass, charsmax(szPtrClass))
if (equali(szPtrClass, "Hook"))
{
static Float:fOrigin[3]
pev(ptr, pev_origin, fOrigin)
if (pev_valid(ptd))
{
static szPtdClass[32]
pev(ptd, pev_classname, szPtdClass, charsmax(szPtdClass))
if (!get_pcvar_num(pPlayers) && /*equali(szPtdClass, "player")*/ is_user_alive(ptd))
{
// Hit a player
if (get_pcvar_num(pSound))
emit_sound(ptr, CHAN_STATIC, "weapons/xbow_hitbod1.wav", 1.0, ATTN_NORM, 0, PITCH_NORM)
remove_hook(id)
return FMRES_HANDLED
}
else if (equali(szPtdClass, "hostage_entity"))
{
// Makes an hostage follow
if (get_pcvar_num(pHostage) && get_user_team(id) == 2)
{
//cs_set_hostage_foll(ptd, (cs_get_hostage_foll(ptd) == id) ? 0 : id)
// With the use function we have the sounds!
dllfunc(DLLFunc_Use, ptd, id)
}
if (!get_pcvar_num(pPlayers))
{
if(get_pcvar_num(pSound))
emit_sound(ptr, CHAN_STATIC, "weapons/xbow_hitbod1.wav", 1.0, ATTN_NORM, 0, PITCH_NORM)
remove_hook(id)
}
return FMRES_HANDLED
}
else if (get_pcvar_num(pOpenDoors) && equali(szPtdClass, "func_door") || equali(szPtdClass, "func_door_rotating"))
{
// Open doors
// Double doors tested in de_nuke and de_wallmart
static szTargetName[32]
pev(ptd, pev_targetname, szTargetName, charsmax(szTargetName))
if (strlen(szTargetName) > 0)
{
static ent
while ((ent = engfunc(EngFunc_FindEntityByString, ent, "target", szTargetName)) > 0)
{
static szEntClass[32]
pev(ent, pev_classname, szEntClass, charsmax(szEntClass))
if (equali(szEntClass, "trigger_multiple"))
{
dllfunc(DLLFunc_Touch, ent, id)
goto stopdoors // No need to touch anymore
}
}
}
// No double doors.. just touch it
dllfunc(DLLFunc_Touch, ptd, id)
stopdoors:
}
else if (get_pcvar_num(pUseButtons) && equali(szPtdClass, "func_button"))
{
if (pev(ptd, pev_spawnflags) & SF_BUTTON_TOUCH_ONLY)
dllfunc(DLLFunc_Touch, ptd, id) // Touch only
else
dllfunc(DLLFunc_Use, ptd, id) // Use Buttons
}
}
// If cvar sv_hooksky is 0 and hook is in the sky remove it!
new iContents = engfunc(EngFunc_PointContents, fOrigin)
if (!get_pcvar_num(pHookSky) && iContents == CONTENTS_SKY)
{
if(get_pcvar_num(pSound))
emit_sound(ptr, CHAN_STATIC, "weapons/xbow_hit2.wav", 1.0, ATTN_NORM, 0, PITCH_NORM)
remove_hook(id)
return FMRES_HANDLED
}
// Pick up weapons..
if (get_pcvar_num(pWeapons))
{
static ent
while ((ent = engfunc(EngFunc_FindEntityInSphere, ent, fOrigin, 15.0)) > 0)
{
static szentClass[32]
pev(ent, pev_classname, szentClass, charsmax(szentClass))
if (equali(szentClass, "weaponbox") || equali(szentClass, "armoury_entity"))
dllfunc(DLLFunc_Touch, ent, id)
}
}
// Player is now hooked
gHooked[id] = true
// Play sound
if (get_pcvar_num(pSound))
emit_sound(ptr, CHAN_STATIC, "weapons/xbow_hit1.wav", 1.0, ATTN_NORM, 0, PITCH_NORM)
// Make some sparks :D
message_begin_f(MSG_BROADCAST, SVC_TEMPENTITY, fOrigin, 0)
write_byte(9) // TE_SPARKS
write_coord_f(fOrigin[0]) // Origin
write_coord_f(fOrigin[1])
write_coord_f(fOrigin[2])
message_end()
// Stop the hook from moving
set_pev(ptr, pev_velocity, Float:{0.0, 0.0, 0.0})
set_pev(ptr, pev_movetype, MOVETYPE_NONE)
//Task
if (!task_exists(id + 856))
{
static TaskData[2]
TaskData[0] = id
TaskData[1] = ptr
gotohook(TaskData)
set_task(0.1, "gotohook", id + 856, TaskData, 2, "b")
}
}
return FMRES_HANDLED
}
public hookthink(param[])
{
new id = param[0]
new HookEnt = param[1]
if (!is_user_alive(id) || !pev_valid(HookEnt) || !pev_valid(id))
{
remove_task(id + 890)
return PLUGIN_HANDLED
}
static Float:entOrigin[3]
pev(HookEnt, pev_origin, entOrigin)
// If user is behind a box or something.. remove it
// only works if sv_interrupt 1 or higher is
if (get_pcvar_num(pInterrupt) && rndStarted)
{
static Float:usrOrigin[3]
pev(id, pev_origin, usrOrigin)
static tr
engfunc(EngFunc_TraceLine, usrOrigin, entOrigin, 1, -1, tr)
static Float:fFraction
get_tr2(tr, TR_flFraction, fFraction)
if (fFraction != 1.0)
remove_hook(id)
}
// If cvar sv_hooksky is 0 and hook is in the sky remove it!
new iContents = engfunc(EngFunc_PointContents, entOrigin)
if (!get_pcvar_num(pHookSky) && iContents == CONTENTS_SKY)
{
if(get_pcvar_num(pSound))
emit_sound(HookEnt, CHAN_STATIC, "weapons/xbow_hit2.wav", 1.0, ATTN_NORM, 0, PITCH_NORM)
remove_hook(id)
}
return PLUGIN_HANDLED
}
public gotohook(param[])
{
new id = param[0]
new HookEnt = param[1]
if (!is_user_alive(id) || !pev_valid(HookEnt) || !pev_valid(id))
{
remove_task(id + 856)
return PLUGIN_HANDLED
}
// If the round isnt started velocity is just 0
static Float:fVelocity[3]
fVelocity = Float:{0.0, 0.0, 1.0}
// If the round is started and player is hooked we can set the user velocity!
if (rndStarted && gHooked[id])
{
static Float:fHookOrigin[3], Float:fUsrOrigin[3], Float:fDist
pev(HookEnt, pev_origin, fHookOrigin)
pev(id, pev_origin, fUsrOrigin)
fDist = vector_distance(fHookOrigin, fUsrOrigin)
if (fDist >= 30.0)
{
new Float:fSpeed = get_pcvar_float(pSpeed)
fSpeed *= 0.52
fVelocity[0] = (fHookOrigin[0] - fUsrOrigin[0]) * (2.0 * fSpeed) / fDist
fVelocity[1] = (fHookOrigin[1] - fUsrOrigin[1]) * (2.0 * fSpeed) / fDist
fVelocity[2] = (fHookOrigin[2] - fUsrOrigin[2]) * (2.0 * fSpeed) / fDist
}
}
// Set the velocity
set_pev(id, pev_velocity, fVelocity)
return PLUGIN_HANDLED
}
public throw_hook(id)
{
// Get origin and angle for the hook
static Float:fOrigin[3], Float:fAngle[3],Float:fvAngle[3]
static Float:fStart[3]
pev(id, pev_origin, fOrigin)
pev(id, pev_angles, fAngle)
pev(id, pev_v_angle, fvAngle)
if (get_pcvar_num(pInstant))
{
get_user_hitpoint(id, fStart)
if (engfunc(EngFunc_PointContents, fStart) != CONTENTS_SKY)
{
static Float:fSize[3]
pev(id, pev_size, fSize)
fOrigin[0] = fStart[0] + floatcos(fvAngle[1], degrees) * (-10.0 + fSize[0])
fOrigin[1] = fStart[1] + floatsin(fvAngle[1], degrees) * (-10.0 + fSize[1])
fOrigin[2] = fStart[2]
}
else
xs_vec_copy(fStart, fOrigin)
}
// Make the hook!
Hook[id] = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "info_target"))
if (Hook[id])
{
// Player cant throw hook now
canThrowHook[id] = false
static const Float:fMins[3] = {-2.840000, -14.180000, -2.840000}
static const Float:fMaxs[3] = {2.840000, 0.020000, 2.840000}
//Set some Data
set_pev(Hook[id], pev_classname, "Hook")
engfunc(EngFunc_SetModel, Hook[id], "models/rpgrocket.mdl")
engfunc(EngFunc_SetOrigin, Hook[id], fOrigin)
engfunc(EngFunc_SetSize, Hook[id], fMins, fMaxs)
//set_pev(Hook[id], pev_mins, fMins)
//set_pev(Hook[id], pev_maxs, fMaxs)
set_pev(Hook[id], pev_angles, fAngle)
set_pev(Hook[id], pev_solid, 2)
set_pev(Hook[id], pev_movetype, 5)
set_pev(Hook[id], pev_owner, id)
//Set hook velocity
static Float:fForward[3], Float:Velocity[3]
new Float:fSpeed = get_pcvar_float(pThrowSpeed)
engfunc(EngFunc_MakeVectors, fvAngle)
global_get(glb_v_forward, fForward)
Velocity[0] = fForward[0] * fSpeed
Velocity[1] = fForward[1] * fSpeed
Velocity[2] = fForward[2] * fSpeed
set_pev(Hook[id], pev_velocity, Velocity)
// Make the line between Hook and Player
message_begin_f(MSG_BROADCAST, SVC_TEMPENTITY, Float:{0.0, 0.0, 0.0}, 0)
if (get_pcvar_num(pInstant))
{
write_byte(1) // TE_BEAMPOINT
write_short(id) // Startent
write_coord_f(fStart[0]) // End pos
write_coord_f(fStart[1])
write_coord_f(fStart[2])
}
else
{
write_byte(8) // TE_BEAMENTS
write_short(id) // Start Ent
write_short(Hook[id]) // End Ent
}
write_short(sprBeam) // Sprite
write_byte(1) // StartFrame
write_byte(1) // FrameRate
write_byte(600) // Life
write_byte(get_pcvar_num(pWidth)) // Width
write_byte(get_pcvar_num(pHookNoise)) // Noise
// Colors now
if (get_pcvar_num(pColor))
{
if (get_user_team(id) == 1) // Terrorist
{
write_byte(255) // R
write_byte(0) // G
write_byte(0) // B
}
#if defined _cstrike_included
else if(cs_get_user_vip(id)) // vip for cstrike
{
write_byte(0) // R
write_byte(255) // G
write_byte(0) // B
}
#endif // _cstrike_included
else if(get_user_team(id) == 2) // CT
{
write_byte(0) // R
write_byte(0) // G
write_byte(255) // B
}
else
{
write_byte(255) // R
write_byte(255) // G
write_byte(255) // B
}
}
else
{
write_byte(255) // R
write_byte(255) // G
write_byte(255) // B
}
write_byte(192) // Brightness
write_byte(0) // Scroll speed
message_end()
if (get_pcvar_num(pSound) && !get_pcvar_num(pInstant))
emit_sound(id, CHAN_BODY, "weapons/xbow_fire1.wav", VOL_NORM, ATTN_NORM, 0, PITCH_HIGH)
static TaskData[2]
TaskData[0] = id
TaskData[1] = Hook[id]
set_task(0.1, "hookthink", id + 890, TaskData, 2, "b")
}
else
client_print(id, print_chat, "Can't create hook")
}
public remove_hook(id)
{
//Player can now throw hooks
canThrowHook[id] = true
// Remove the hook if it is valid
if (pev_valid(Hook[id]))
engfunc(EngFunc_RemoveEntity, Hook[id])
Hook[id] = 0
// Remove the line between user and hook
if (is_user_connected(id))
{
message_begin(MSG_BROADCAST, SVC_TEMPENTITY, {0,0,0}, id)
write_byte(99) // TE_KILLBEAM
write_short(id) // entity
message_end()
}
// Player is not hooked anymore
gHooked[id] = false
return 1
}
public give_hook(id, level, cid)
{
if (!cmd_access(id ,level, cid, 1))
return PLUGIN_HANDLED
if (!get_pcvar_num(pAdmin))
{
console_print(id, "[Hook] Admin only mode is currently disabled")
return PLUGIN_HANDLED
}
static szTarget[32]
read_argv(1, szTarget, charsmax(szTarget))
new iUsrId = cmd_target(id, szTarget)
if (!iUsrId)
return PLUGIN_HANDLED
static szName[32]
get_user_name(iUsrId, szName, charsmax(szName))
if (!g_bHookAllowed[iUsrId])
{
g_bHookAllowed[iUsrId] = true
console_print(id, "[Hook] You gave %s access to the hook", szName)
}
else
console_print(id, "[Hook] %s already have access to the hook", szName)
return PLUGIN_HANDLED
}
public take_hook(id, level, cid)
{
if (!cmd_access(id ,level, cid, 1))
return PLUGIN_HANDLED
if (!get_pcvar_num(pAdmin))
{
console_print(id, "[Hook] Admin only mode is currently disabled")
return PLUGIN_HANDLED
}
static szTarget[32]
read_argv(1, szTarget, charsmax(szTarget))
new iUsrId = cmd_target(id, szTarget)
if (!iUsrId)
return PLUGIN_HANDLED
static szName[32]
get_user_name(iUsrId, szName, charsmax(szName))
if (g_bHookAllowed[iUsrId])
{
g_bHookAllowed[iUsrId] = false
console_print(id, "[Hook] You took away %s his access to the hook", szName)
}
else
console_print(id, "[Hook] %s does not have access to the hook", szName)
return PLUGIN_HANDLED
}
// Stock by Chaosphere
stock get_user_hitpoint(id, Float:hOrigin[3])
{
if (!is_user_alive(id))
return 0
static Float:fOrigin[3], Float:fvAngle[3], Float:fvOffset[3], Float:fvOrigin[3], Float:feOrigin[3]
static Float:fTemp[3]
pev(id, pev_origin, fOrigin)
pev(id, pev_v_angle, fvAngle)
pev(id, pev_view_ofs, fvOffset)
xs_vec_add(fOrigin, fvOffset, fvOrigin)
engfunc(EngFunc_AngleVectors, fvAngle, feOrigin, fTemp, fTemp)
xs_vec_mul_scalar(feOrigin, 8192.0, feOrigin)
xs_vec_add(fvOrigin, feOrigin, feOrigin)
static tr
engfunc(EngFunc_TraceLine, fvOrigin, feOrigin, 0, id, tr)
get_tr2(tr, TR_vecEndPos, hOrigin)
//global_get(glb_trace_endpos, hOrigin)
return 1
}
stock statusMsg(id, szMsg[], {Float,_}:...)
{
static iStatusText
if (!iStatusText)
iStatusText = get_user_msgid("StatusText")
static szBuffer[512]
vformat(szBuffer, charsmax(szBuffer), szMsg, 3)
message_begin((id == 0) ? MSG_ALL : MSG_ONE, iStatusText, _, id)
write_byte(0) // Unknown
write_string(szBuffer) // Message
message_end()
return 1
}