I've been working on a modification of Spacedude's hook plugin (well, a modification of AssKicR's update, but I deleted most of his code) that lets players buy rights to a hook and use it until they die. It makes them wait a few turns until they can buy a new one. It also has checks in place to avoid annoying things (e.g. VIPs using a hook, more than half of the server using hooks).
I just did a rewrite of some parts to slightly optimize it and add some extra features, and the compiler is throwing all kinds of errors. I don't know how to interpret them because it's naming functions (which are defined) as undefined symbols, and I'm pretty new so I've never seen this kind of thing. I've checked for typos, comment delimiters that might have been left open, and so on. I'd really appreciate it if someone could take a quick look and spot the errors. Feel free to correct any bad practices in my code.
Code:
/**************************************************************************************************
Buyhook v2.0 - Main beef coded by Spacedude... "Buy Hook" & refinements by Harman of SF, with help from friends.
**** CVARS (FEATURES) ****
sv_adminhook = Turn Plugin On/off
mp_hookcost = Cost of hook
mp_buyhook = Allow buying hooks
**** ADMIN COMMANDS ****
ADMIN_LEVEL_E (flag="q") || Allows admins to bypass buyhook()
Attaching Rope = +rope
Deattaching Rope = -rope
Attaching Hook = +hook
Deattaching Hook = -hook
**************************************************************************************************/
#define USING_AMX 0 // 1 = Using AMX \ 0 = Using AMXX
#if USING_AMX
#include <amxmod>
#include <amxmisc>
#include <VexdUM>
#include <fun>
new gModName[32] = "AMX"
#else
#include <amxmodx>
#include <amxmisc>
#include <cstrike>
#include <fun>
#include <engine>
new gModName[32] = "AMXX"
#endif
#define TE_BEAMENTPOINT 1
#define TE_KILLBEAM 99
#define DELTA_T 0.1 // seconds
#define BEAMLIFE 100 // deciseconds
#define MOVEACCELERATION 150 // units per second^2
#define REELSPEED 300 // units per second
#define ADMIN ADMIN_LEVEL_E
/* Hook Stuff */
new gHookLocation[33][3]
new gHookLength[33]
new bool:gIsHooked[33]
new Float:gBeamIsCreated[33]
new beam
new p_HookCvar //pointer to sv_adminhook
new global_gravity
new p_GravityCvar //pointer to sv_gravity
/* Buy Hook */
new gAllowedHook[33] //whether a player can use the hook (i.e. whether the player bought one)
new gHadHook[33] //whether a player had a hook before they died
new gHadHookCount[33] //how many rounds have elapsed since a player with a hook died
new gNumHooks //number of players with hooks
new gNumPlayers //number of players in the server
new roundsLeft[33] //how many rounds left until a player can buy a new hook
new roundsTotal = 3 //number of rounds players must wait to buy hook once they die
new p_HookCost
new p_BuyHook
/************************************************************************************************************************/
public plugin_init() //Called on plugin start
{
// Plugin Info
register_plugin("Buy Hook","2.0","Spacedude & SF")
//CVARS
p_HookCost = register_cvar("mp_hookcost", "6000")
p_HookCvar = register_cvar("sv_adminhook", "1" )
p_BuyHook = register_cvar("mp_buyhook", "1")
p_GravityCvar = get_cvar_pointer("sv_gravity")
//USER COMMANDS
register_clcmd("buyhook", "buyHook")
register_clcmd("/buyhook", "buyHook")
register_clcmd("say /buyhook", "buyHook")
register_clcmd("say buyhook", "buyHook")
register_clcmd("+rope", "hook_on")
register_clcmd("-rope", "hook_off")
register_clcmd("+hook", "hook_on")
register_clcmd("-hook", "hook_off")
//HOOKED EVENTS
register_event("ResetHUD", "playerSpawn", "b")
register_event("DeathMsg", "playerDeath", "a")
register_event("WeapPickup", "weaponPickup", "b")
}
public plugin_precache()
{
beam = precache_model("sprites/zbeam4.spr")
//precache_sound("weapons/xbow_hit2.wav")
}
/*************************************************************************************************************************/
/**************************************************** HOOKED EVENTS ******************************************************/
/*************************************************************************************************************************/
public playerSpawn(id)
{
if (gIsHooked[id]) RopeRelease(id)
if (gHadHook[id]) gHadHookCount[id]++
if (gHadHookCount[id] == roundsTotal)
{
gHadHook[id] = false
gHadHookCount[id] = 0
}
}
public playerDeath()
{
new victimID = read_data(2)
if(gAllowedHook[victimID])
{
gAllowedHook[victimID] = false
gHadHook[victimID] = true
gTotalHooks--
}
}
public weaponPickup(id)
{
if(gAllowedHook[id] && read_data(1) != 29 && read_data(1) != 6)
{
set_task(0.2, "stripGuns", id)
}
}
public stripGuns(id)
{
if(user_has_weapon(id, CSW_C4))
{
strip_user_weapons(id)
give_item(id, "weapon_knife")
give_item(id, "weapon_c4")
cs_set_user_plant(id, 1, 1)
}
else
{
strip_user_weapons(id)
give_item(id, "weapon_knife")
}
return PLUGIN_HANDLED
}
/*************************************************************************************************************************/
stock kz_velocity_set(id,vel[3]) {
//Set Their Velocity to 0 so that they they fall straight down from
new Float:Ivel[3]
Ivel[0]=float(vel[0])
Ivel[1]=float(vel[1])
Ivel[2]=float(vel[2])
entity_set_vector(id, EV_VEC_velocity, Ivel)
}
stock kz_velocity_get(id,vel[3]) {
//Set Their Velocity to 0 so that they they fall straight down from
new Float:Ivel[3]
entity_get_vector(id, EV_VEC_velocity, Ivel)
vel[0]=floatround(Ivel[0])
vel[1]=floatround(Ivel[1])
vel[2]=floatround(Ivel[2])
}
/************************************************************************************************************************/
/****************************************************** NINJAROPE *******************************************************/
/************************************************************************************************************************/
public ropetask(parm[])
{
new id = parm[0]
new user_origin[3], user_look[3], user_direction[3], move_direction[3]
new A[3], D[3], buttonadjust[3]
new acceleration, velocity_towards_A, desired_velocity_towards_A
new velocity[3], null[3]
if (!is_user_alive(id))
{
RopeRelease(id)
return
}
if (gBeamIsCreated[id] + BEAMLIFE/10 <= get_gametime())
{
beamentpoint(id)
}
null[0] = 0
null[1] = 0
null[2] = 0
get_user_origin(id, user_origin)
get_user_origin(id, user_look,2)
kz_velocity_get(id, velocity)
buttonadjust[0]=0
buttonadjust[1]=0
if (get_user_button(id)&IN_FORWARD) buttonadjust[0]+=1
if (get_user_button(id)&IN_BACK) buttonadjust[0]-=1
if (get_user_button(id)&IN_MOVERIGHT) buttonadjust[1]+=1
if (get_user_button(id)&IN_MOVELEFT) buttonadjust[1]-=1
if (get_user_button(id)&IN_JUMP) buttonadjust[2]+=1
if (get_user_button(id)&IN_DUCK) buttonadjust[2]-=1
if (buttonadjust[0] || buttonadjust[1])
{
user_direction[0] = user_look[0] - user_origin[0]
user_direction[1] = user_look[1] - user_origin[1]
move_direction[0] = buttonadjust[0]*user_direction[0] + user_direction[1]*buttonadjust[1]
move_direction[1] = buttonadjust[0]*user_direction[1] - user_direction[0]*buttonadjust[1]
move_direction[2] = 0
velocity[0] += floatround(move_direction[0] * MOVEACCELERATION * DELTA_T / get_distance(null,move_direction))
velocity[1] += floatround(move_direction[1] * MOVEACCELERATION * DELTA_T / get_distance(null,move_direction))
}
if (buttonadjust[2]) gHookLength[id] -= floatround(buttonadjust[2] * REELSPEED * DELTA_T)
if (gHookLength[id] < 100) gHookLength[id] = 100
A[0] = gHookLocation[id][0] - user_origin[0]
A[1] = gHookLocation[id][1] - user_origin[1]
A[2] = gHookLocation[id][2] - user_origin[2]
D[0] = A[0]*A[2] / get_distance(null,A)
D[1] = A[1]*A[2] / get_distance(null,A)
D[2] = -(A[1]*A[1] + A[0]*A[0]) / get_distance(null,A)
acceleration = - global_gravity * D[2] / get_distance(null,D)
velocity_towards_A = (velocity[0] * A[0] + velocity[1] * A[1] + velocity[2] * A[2]) / get_distance(null,A)
desired_velocity_towards_A = (get_distance(user_origin,gHookLocation[id]) - gHookLength[id] /*- 10*/) * 4
if (get_distance(null,D)>10)
{
velocity[0] += floatround((acceleration * DELTA_T * D[0]) / get_distance(null,D))
velocity[1] += floatround((acceleration * DELTA_T * D[1]) / get_distance(null,D))
velocity[2] += floatround((acceleration * DELTA_T * D[2]) / get_distance(null,D))
}
velocity[0] += ((desired_velocity_towards_A - velocity_towards_A) * A[0]) / get_distance(null,A)
velocity[1] += ((desired_velocity_towards_A - velocity_towards_A) * A[1]) / get_distance(null,A)
velocity[2] += ((desired_velocity_towards_A - velocity_towards_A) * A[2]) / get_distance(null,A)
kz_velocity_set(id, velocity)
}
public hooktask(parm[])
{
new id = parm[0]
new velocity[3]
if ( !gIsHooked[id] ) return
new user_origin[3],oldvelocity[3]
parm[0] = id
if (!is_user_alive(id))
{
RopeRelease(id)
return
}
if (gBeamIsCreated[id] + BEAMLIFE/10 <= get_gametime())
{
beamentpoint(id)
}
get_user_origin(id, user_origin)
kz_velocity_get(id, oldvelocity)
new distance=get_distance( gHookLocation[id], user_origin )
if ( distance > 10 )
{
velocity[0] = floatround( (gHookLocation[id][0] - user_origin[0]) * ( 2.0 * REELSPEED / distance ) )
velocity[1] = floatround( (gHookLocation[id][1] - user_origin[1]) * ( 2.0 * REELSPEED / distance ) )
velocity[2] = floatround( (gHookLocation[id][2] - user_origin[2]) * ( 2.0 * REELSPEED / distance ) )
}
else
{
velocity[0]=0
velocity[1]=0
velocity[2]=0
}
kz_velocity_set(id, velocity)
}
public hook_on(id)
{
if (get_pcvar_num(p_HookCvar)==1)
{
if (gAllowedHook[id] || (get_user_flags(id) & ADMIN)) {
if (!gIsHooked[id] && is_user_alive(id))
{
new cmd[32]
read_argv(0,cmd,31)
if(equal(cmd,"+rope")) RopeAttach(id,0)
if(equal(cmd,"+hook")) RopeAttach(id,1)
}
}else{
client_print(id, print_chat, "[Hook] You must buy a hook! Say /buyhook or type buyhook in console.")
return PLUGIN_HANDLED
}
}else{
client_print(id,print_chat,"[%s] This command is deativated",gModName)
}
return PLUGIN_HANDLED
}
public hook_off(id)
{
if (gAllowedHook[id] || (get_user_flags(id) & ADMIN)) {
if (gIsHooked[id])
{
RopeRelease(id)
}
}
return PLUGIN_HANDLED
}
public RopeAttach(id,hook)
{
new parm[1], user_origin[3]
parm[0] = id
gIsHooked[id] = true
get_user_origin(id,user_origin)
get_user_origin(id,gHookLocation[id], 3)
gHookLength[id] = get_distance(gHookLocation[id],user_origin)
global_gravity = get_pcvar_num(p_GravityCvar)
set_user_gravity(id,0.001)
beamentpoint(id)
//emit_sound(id, CHAN_STATIC, "weapons/xbow_hit2.wav", 1.0, ATTN_NORM, 0, PITCH_NORM)
if (hook) set_task(DELTA_T, "hooktask", 200+id, parm, 1, "b")
else set_task(DELTA_T, "ropetask", 200+id, parm, 1, "b")
}
public RopeRelease(id)
{
gIsHooked[id] = false
killbeam(id)
set_user_gravity(id)
remove_task(200+id)
}
public beamentpoint(id)
{
message_begin( MSG_BROADCAST, SVC_TEMPENTITY )
write_byte( TE_BEAMENTPOINT )
write_short( id )
write_coord( gHookLocation[id][0] )
write_coord( gHookLocation[id][1] )
write_coord( gHookLocation[id][2] )
write_short( beam ) // sprite index
write_byte( 0 ) // start frame
write_byte( 0 ) // framerate
write_byte( BEAMLIFE ) // life
write_byte( 10 ) // width
write_byte( 0 ) // noise
if (get_user_team(id)==1) // Terrorist
{
write_byte( 255 ) // r, g, b
write_byte( 0 ) // r, g, b
write_byte( 0 ) // r, g, b
}
else // Counter-Terrorist
{
write_byte( 0 ) // r, g, b
write_byte( 0 ) // r, g, b
write_byte( 255 ) // r, g, b
}
write_byte( 150 ) // brightness
write_byte( 0 ) // speed
message_end( )
gBeamIsCreated[id] = get_gametime()
}
public killbeam(id)
{
message_begin( MSG_BROADCAST, SVC_TEMPENTITY )
write_byte( TE_KILLBEAM )
write_short( id )
message_end()
}
public buyHook(id)
{
if(get_user_flags(id) & ADMIN) return PLUGIN_HANDLED
if(cs_get_user_money(id) < get_pcvar_num(p_HookCost))
{
client_print(id, print_console, "[Hook] You don't have enough money for a hook! You need $%i.", get_pcvar_num(p_HookCost))
client_print(id, print_chat, "[Hook] You don't have enough money for a hook! You need $%i.", get_pcvar_num(p_HookCost))
return PLUGIN_HANDLED
}
if(gAllowedHook[id])
{
client_print(id, print_console, "[Hook] You already have a hook!")
client_print(id, print_chat, "[Hook] You already have a hook!")
return PLUGIN_HANDLED
}
if(get_pcvar_num(p_BuyHook)==0)
{
client_print(id, print_console, "[Hook] Buyhook is disabled for this map type.")
client_print(id, print_chat, "[Hook] Buyhook is disabled for this map type.")
return PLUGIN_HANDLED
}
gNumPlayers = get_playersnum(0)
switch(gNumPlayers) //looks ugly but just restricts number of hooks in server
{
case 0 .. 7:
{
if(gNumHooks > 4)
{
client_print(id, print_console, "[Hook] Too many players are using hook. Try again later.")
client_print(id, print_chat, "[Hook] Too many players are using hook. Try again later.")
return PLUGIN_HANDLED
}
}
case 8 .. 20:
{
if(2*gNumHooks > gNumPlayers)
{
client_print(id, print_console, "[Hook] Too many players are using hook. Try again later.")
client_print(id, print_chat, "[Hook] Too many players are using hook. Try again later.")
return PLUGIN_HANDLED
}
}
default: //whatever
}
if(cs_get_user_vip(id) == 1)
{
client_print(id, print_console, "[Hook] The VIP cannot buy a hook.")
client_print(id, print_chat, "[Hook] The VIP cannot buy a hook.")
return PLUGIN_HANDLED
}
if(gHadHook[id])
{
roundsLeft[id] = roundsTotal - gHadHookCount[id]
client_print(id, print_console, "[Hook] You had a hook recently. You must wait %i round(s).", roundsLeft[id])
client_print(id, print_chat, "[Hook] You had a hook recently. You must wait %i round(s).", roundsLeft[id])
}
else
{
cs_set_user_money(id, cs_get_user_money(id) - get_pcvar_num(p_HookCost), 1)
stripGuns(id)
client_print(id, print_console, "[Hook] Enjoy your new hook! You'll lose it if you die.")
client_print(id, print_console, "[Hook] Bind a key to +hook or +rope (in console type: bind <key> <command>).")
client_print(id, print_console, "[Hook] Your guns have been stripped and will return if you lose your hook.")
client_print(id, print_console, "[Hook] Once you lose your hook, you have to wait 2 rounds until you can get a new one.")
client_print(id, print_chat, "[Hook] Enjoy your new hook! Check your console for more info.")
gAllowedHook[id] = true
gTotalHooks++
}
return PLUGIN_HANDLED
}
/************************************************************************************************************************/
/******************************************************* FORWARDS *******************************************************/
/************************************************************************************************************************/
public client_disconnect(id)
{
if(gAllowedHook[id])
{
gAllowedHook[id] = false
gTotalHooks--
}
}
/************************************************************************************************************************/
/************************************************** AMXX -> AMX funcs ***************************************************/
/************************************************************************************************************************/
#if USING_AMX
stock get_user_button(id) return entity_get_int(id, EV_INT_button)
#endif