new const PLUGIN_VERSION[] = "1.1"
const Float:NOT_SET_F = -1.0
const Float:DEFAULT_GRAVITY_I = 800.0
const Float:DEFAULT_GRAVITY_F = 1.0
const Float:FREEZE_TIME_DELAY = 0.1
const DEFAULT_MAX_HEALTH = 100
const DEFAULT_MAX_ARMOR = 100
const DEFAULT_MAX_MONEY = 16000
const DEFAULT_GLOW_AMOUNT = 40
new const ATTRIBUTE_GRAVITY[] = "GRAVITY"
new const ATTRIBUTE_SPEED[] = "SPEED"
new const ATTRIBUTE_DAMAGE[] = "DAMAGE"
new const ATTRIBUTE_PROTECTION[] = "PROTECTION"
new const ATTRIBUTE_SILENT_STEPS[] = "SILENT_STEPS"
new const ATTRIBUTE_HEALTH_ON_KILL[] = "HEALTH_ON_KILL"
new const ATTRIBUTE_ARMOR_ON_KILL[] = "ARMOR_ON_KILL"
new const ATTRIBUTE_MONEY_ON_KILL[] = "MONEY_ON_KILL"
new const ATTRIBUTE_GLOW[] = "GLOW"
enum Glow { bool:is_set, fx, r, g, b, render, amount }
enum HealthOnKill { health_on_kill, max_health }
enum ArmorOnKill { armor_on_kill, max_armor }
enum MoneyOnKill { money_on_kill, max_money }
new g_iGravity [MAX_PLAYERS + 1],
Float:g_fSpeed [MAX_PLAYERS + 1],
g_szDamage [MAX_PLAYERS + 1][8],
g_szProtection [MAX_PLAYERS + 1][8],
bool:g_bSilentSteps [MAX_PLAYERS + 1],
g_eHealthOnKill [MAX_PLAYERS + 1][HealthOnKill],
g_eArmorOnKill [MAX_PLAYERS + 1][ArmorOnKill],
g_eMoneyOnKill [MAX_PLAYERS + 1][MoneyOnKill],
g_eGlow [MAX_PLAYERS + 1][Glow],
register_plugin("Basic Skills", PLUGIN_VERSION, "OciXCrom")
register_cvar("CRXBasicSkills", PLUGIN_VERSION, FCVAR_SERVER|FCVAR_SPONLY|FCVAR_UNLOGGED)
register_event("DeathMsg", "OnPlayerKilled", "a")
register_event("CurWeapon", "OnChangeWeapon", "be", "1=1")
register_event("HLTV", "OnFreezeTime", "a", "1=0", "2=0")
register_logevent("OnRoundStart", 2, "0=World triggered", "1=Round_Start")
RegisterHam(Ham_TakeDamage, "player", "PreTakeDamage", 0)
g_bKnifeOnlySkills = get_cvar_num("km_knife_only_skills") != 0
g_pFreezeTime = get_cvar_pointer("mp_freezetime")
public crxknives_knife_updated(id, iKnife, bool:bOnConnect)
g_szProtection[id][0] = EOS
g_bSilentSteps[id] = false
g_eHealthOnKill[id][health_on_kill] = NOT_SET
g_eArmorOnKill[id][armor_on_kill] = NOT_SET
g_eMoneyOnKill[id][money_on_kill] = NOT_SET
g_eGlow[id][is_set] = false
static szValue[CRXKNIVES_MAX_ATTRIBUTE_LENGTH], szTemp[6][8], bool:bConnected, iValue
bConnected = is_user_connected(id) != 0
if(crxknives_get_attribute_int(id, ATTRIBUTE_GRAVITY, iValue))
else if(g_iGravity[id] != NOT_SET)
if(crxknives_get_attribute_int(id, ATTRIBUTE_SPEED, iValue))
g_fSpeed[id] = float(iValue)
else if(g_fSpeed[id] != NOT_SET_F)
if(!crxknives_get_attribute_str(id, ATTRIBUTE_DAMAGE, g_szDamage[id], charsmax(g_szDamage[])))
if(!crxknives_get_attribute_str(id, ATTRIBUTE_PROTECTION, g_szProtection[id], charsmax(g_szProtection[])))
g_szProtection[id][0] = EOS
if(crxknives_get_attribute_int(id, ATTRIBUTE_SILENT_STEPS, iValue) && iValue == 1)
g_bSilentSteps[id] = true
else if(g_bSilentSteps[id])
g_bSilentSteps[id] = false
set_user_footsteps(id, 0)
if(crxknives_get_attribute_str(id, ATTRIBUTE_HEALTH_ON_KILL, szValue, charsmax(szValue)))
parse(szValue, szTemp[0], charsmax(szTemp[]), szTemp[1], charsmax(szTemp[]))
g_eHealthOnKill[id][health_on_kill] = str_to_num(szTemp[0])
g_eHealthOnKill[id][max_health] = szTemp[1][0] ? str_to_num(szTemp[1]) : DEFAULT_MAX_HEALTH
g_eHealthOnKill[id][health_on_kill] = NOT_SET
if(crxknives_get_attribute_str(id, ATTRIBUTE_ARMOR_ON_KILL, szValue, charsmax(szValue)))
parse(szValue, szTemp[0], charsmax(szTemp[]), szTemp[1], charsmax(szTemp[]))
g_eArmorOnKill[id][armor_on_kill] = str_to_num(szTemp[0])
g_eArmorOnKill[id][max_armor] = szTemp[1][0] ? str_to_num(szTemp[1]) : DEFAULT_MAX_ARMOR
g_eArmorOnKill[id][armor_on_kill] = NOT_SET
if(crxknives_get_attribute_str(id, ATTRIBUTE_MONEY_ON_KILL, szValue, charsmax(szValue)))
parse(szValue, szTemp[0], charsmax(szTemp[]), szTemp[1], charsmax(szTemp[]))
g_eMoneyOnKill[id][money_on_kill] = str_to_num(szTemp[0])
g_eMoneyOnKill[id][max_money] = szTemp[1][0] ? str_to_num(szTemp[1]) : DEFAULT_MAX_MONEY
g_eMoneyOnKill[id][money_on_kill] = NOT_SET
if(crxknives_get_attribute_str(id, ATTRIBUTE_GLOW, szValue, charsmax(szValue)))
for(new i; i < sizeof(szTemp); i++)
parse(szValue, szTemp[0], charsmax(szTemp[]), szTemp[1], charsmax(szTemp[]), szTemp[2], charsmax(szTemp[]),\
szTemp[3], charsmax(szTemp[]), szTemp[4], charsmax(szTemp[]), szTemp[5], charsmax(szTemp[]))
g_eGlow[id][is_set] = true
g_eGlow[id][r] = str_to_num(szTemp[0])
g_eGlow[id][g] = str_to_num(szTemp[1])
g_eGlow[id][b] = str_to_num(szTemp[2])
g_eGlow[id][amount] = szTemp[3][0] ? str_to_num(szTemp[3]) : DEFAULT_GLOW_AMOUNT
g_eGlow[id][fx] = szTemp[4][0] ? str_to_num(szTemp[4]) : kRenderFxGlowShell
g_eGlow[id][render] = str_to_num(szTemp[5])
g_eGlow[id][is_set] = false
if(get_pcvar_num(g_pFreezeTime) > 0)
set_task(FREEZE_TIME_DELAY, "update_player_speed")
new iAttacker = read_data(1), iVictim = read_data(2)
if(!is_user_connected(iAttacker) || iAttacker == iVictim || !can_use_skill(iAttacker))
if(g_eHealthOnKill[iAttacker][health_on_kill] != NOT_SET)
set_user_health(iAttacker, clamp(get_user_health(iAttacker) + g_eHealthOnKill[iAttacker][health_on_kill], .max = g_eHealthOnKill[iAttacker][max_health]))
if(g_eArmorOnKill[iAttacker][armor_on_kill] != NOT_SET)
set_user_armor(iAttacker, clamp(get_user_armor(iAttacker) + g_eArmorOnKill[iAttacker][armor_on_kill], .max = g_eArmorOnKill[iAttacker][max_armor]))
if(g_eMoneyOnKill[iAttacker][money_on_kill] != NOT_SET)
cs_set_user_money(iAttacker, clamp(cs_get_user_money(iAttacker) + g_eMoneyOnKill[iAttacker][money_on_kill], .max = g_eMoneyOnKill[iAttacker][max_money]))
public OnChangeWeapon(id)
new bool:bCanUseSkill = can_use_skill(id)
if(g_iGravity[id] != NOT_SET)
set_user_gravity(id, bCanUseSkill ? (float(g_iGravity[id]) / DEFAULT_GRAVITY_I) : DEFAULT_GRAVITY_F)
if(g_fSpeed[id] != NOT_SET_F)
set_user_maxspeed(id, g_fSpeed[id])
set_user_footsteps(id, bCanUseSkill ? 1 : 0)
set_user_rendering(id, g_eGlow[id][fx], g_eGlow[id][r], g_eGlow[id][g], g_eGlow[id][b], g_eGlow[id][render], g_eGlow[id][amount])
public PreTakeDamage(iVictim, iInflictor, iAttacker, Float:fDamage, iDamageBits)
if(g_szProtection[iVictim][0] && can_use_skill(iVictim))
SetHamParamFloat(4, math_add_f(fDamage, g_szProtection[iVictim]))
if(is_user_alive(iAttacker) && g_szDamage[iAttacker][0] && can_use_skill(iAttacker) && iAttacker == iInflictor)
SetHamParamFloat(4, math_add_f(fDamage, g_szDamage[iAttacker]))
public update_player_speed()
new iPlayers[MAX_PLAYERS], iPnum
get_players(iPlayers, iPnum, "a")
for(new i, iPlayer; i < iPnum; i++)
if(g_fSpeed[iPlayer] != NOT_SET_F && can_use_skill(iPlayer))
set_user_maxspeed(iPlayer, g_fSpeed[iPlayer])
ExecuteHam(Ham_CS_Player_ResetMaxSpeed, id)
static const Float:fDefaultSpeed = 250.0
set_user_maxspeed(id, fDefaultSpeed)
return !g_bKnifeOnlySkills || (get_user_weapon(id) == CSW_KNIFE)
Float:math_add_f(Float:fNum, const szMath[])
static szNewMath[16], Float:fMath, bool:bPercent, cOperator
copy(szNewMath, charsmax(szNewMath), szMath)
bPercent = szNewMath[strlen(szNewMath) - 1] == '%'
if(!isdigit(szNewMath[0]))
replace(szNewMath, charsmax(szNewMath), "%", "")
fMath = str_to_float(szNewMath)