AlliedModders

AlliedModders (https://forums.alliedmods.net/index.php)
-   Suggestions / Requests (https://forums.alliedmods.net/forumdisplay.php?f=12)
-   -   [Error] register_option (https://forums.alliedmods.net/showthread.php?t=262829)

BaD CopY 05-13-2015 12:16

[Error] register_option
 
Can anyone help me to remove error from 'FrostNade' plugin.

error:
Code:

Undefined Symbol: register_option

JusTGo 05-13-2015 12:26

Re: [Error] register_option
 
you should provied the code...

BaD CopY 05-13-2015 12:32

Re: [Error] register_option
 
man you can download it from alliedmodders, just type: 'Frost nade amxx'

BaD CopY 05-13-2015 12:33

Re: [Error] register_option
 
https://forums.alliedmods.net/showthread.php?t=41126

RaZ_HU 05-13-2015 14:32

Re: [Error] register_option
 
You have edited it in some way, since this plugin has no "register_option" variable.
Download it again and compile it, it compiles without errors.

BaD CopY 05-13-2015 14:42

Re: [Error] register_option
 
Sorry, nade modes plugin :3

RaZ_HU 05-13-2015 14:55

Re: [Error] register_option
 
If you mean this one: https://forums.alliedmods.net/showthread.php?t=75322

It complies without errors, so come on, post your code.

BaD CopY 05-13-2015 15:52

Re: [Error] register_option
 
I just edit some things:

Code:

new const ACTIVATE[] =        "weapons/mine_activate.wav"
new const DEPLOY[] =          "weapons/mine_deploy.wav"
new const CHARGE[] =          "weapons/mine_charge.wav"
new const GEIGER[] =          "player/geiger1.wav"
new const PING[] =                "turret/tu_ping.wav"
new const BUTTON[] =        "buttons/button9.wav"

new const SOUND_HIT[5][] = { "debris/bustmetal1.wav", "debris/bustmetal2.wav", "debris/metal1.wav", "debris/metal2.wav", "debris/metal3.wav" }

// Defines that can be modified
#define MAX_PLAYERS                                                                32

#define ADMIN_ACCESS                                                        ADMIN_RCON

#define NOTEAM_RGB_R_COLOR                                                0
#define NOTEAM_RGB_G_COLOR                                                214
#define NOTEAM_RGB_B_COLOR                                                198

#define TEAMCT_RGB_R_COLOR                                                0
#define TEAMCT_RGB_G_COLOR                                                0
#define TEAMCT_RGB_B_COLOR                                                255

#define TEAMTE_RGB_R_COLOR                                                255
#define TEAMTE_RGB_G_COLOR                                                0
#define TEAMTE_RGB_B_COLOR                                                0

#define DELAY_ADDED_TO_USE                                                0.2

// Some defines, I suggest not modifying these! Only if you understand the code completely!
#define RING_SIZE_CONSTANT_PROXIMITY                        2.1
#define RING_SIZE_CONSTANT_MOTION                                9.27

#define SETTINGS_REFRESH_TIME                                        2.0

#define OFFSET_WEAPONID                                                        43
#define EXTRAOFFSET_WEAPONS                                                4

#define SMART_DISTANCE_LINE_PVS                                        800.0
#define SMART_RADIUS_RING_SHOW                                        1500.0
#define CONE_DROP_ANGLE_COSINUS                                        -0.30
#define EXTRALENGTH_VECTOR                                                200.0

#define SHOT_PENETRATION_DISTANCE                                4.0
#define SHOT_PENETRATION_READD_TIMES                        20
#define SHOT_SECOND_TEST_RADIUS                                        10.0
#define SHOT_KNIFE_REAL_RADIUS                                        6.0
#define SHOT_ENTITY_QUEUE_LENGTH                                5

#define BOT_MIN_DISTANCE_ATTACH                                        400.0
#define BOT_WALL_MIN_COSINUS                                        0.866026
#define BOT_MIN_HEIGHT_ALLOW                                        18.0
#define BOT_MIN_CROUCH_HEIGHT_ALLOW                        10.0
#define BOT_MAX_HEIGHT_ALLOW                                        55.0
#define BOT_FORCE_CROUCH_HEIGHT_CONST                        76.0

#define CVAR_STRING_ALLOC                                                100
#define CVAR_MAX_ASSIGNED_VALUES                                30
#define CVAR_MAX_STRING_LENGTH                                        10

#define DMG_CS_KNIFE_BULLETS                                        (1 << 12 | 1 << 0)

#define CONE_CALC_ANGLE_MAX                                                75.0
#define CONE_CALC_ANGLE_MIN                                                2.0
#define CONE_CALC_DISTANCE_MAX                                        400.0
#define CONE_CALC_DISTANCE_MIN                                        10000.0
#define CONE_BASE_RADIUS                                                200.0

// Macros, made specially to make the code easier to read
#define CONVERT_TO_METERS(%0)                                        (%0 * 0.0254)

#define get_option(%1)                                                        ccvars[%1]
#define toggle_option(%1)                                                set_pcvar_num(pcvars[%1], !get_pcvar_num(pcvars[%1]))
#define get_option_float(%1)                                        Float:ccvars[%1]
#define set_option_float(%1,%2)                                        set_pcvar_float(pcvars[%1], %2)

#define is_player_alive(%1)                                                ((cl_is_alive & (1<<%1)) && (0 < %1 <= g_maxplayers))

#define is_grenade_c4(%1)                                                (get_pdata_int(%1, 96) & (1<<8))                        // 96 is the C4 offset

#define make_explode(%1)                                                entity_set_float(%1, EV_FL_dmgtime, 0.0)
#define grenade_can_be_used(%1)                                        (get_option(OPTION_NADES_IN_EFFECT) & NADE_BIT[%1]) ? 1 : 0
#define allow_grenade_explode(%1)                                (get_gametime() < entity_get_float(%1, EV_FL_fuser2)) ? 0 : 1
#define get_grenade_type(%1)                                        NadeType:entity_get_int(%1, EV_INT_iuser1)
#define set_grenade_allow_explode(%1,%2)                entity_set_float(%1, EV_FL_fuser2, get_gametime() + %2)
#define delay_explosion(%1)                                                entity_set_float(%1, EV_FL_dmgtime, get_gametime() + get_option_float(OPTION_EXPLOSION_DELAY_TIME))
#define get_trip_grenade_end_origin(%1,%2)                entity_get_vector(%1, EV_VEC_vuser1, %2)
#define set_trip_grenade_end_origin(%1,%2)                entity_set_vector(%1, EV_VEC_vuser1, %2)
#define set_trip_grenade_fly_velocity(%1,%2)        entity_set_vector(%1, EV_VEC_vuser2, %2)
#define get_trip_grenade_fly_velocity(%1,%2)        entity_get_vector(%1, EV_VEC_vuser2, %2)
#define get_trip_grenade_middle_origin(%1,%2)        entity_get_vector(%1, EV_VEC_vuser3, %2)
#define set_trip_grenade_middle_origin(%1,%2)        entity_set_vector(%1, EV_VEC_vuser3, %2)
#define get_trip_grenade_arm_time(%1)                        entity_get_float(%1, EV_FL_fuser1)
#define set_trip_grenade_arm_time(%1,%2)                entity_set_float(%1, EV_FL_fuser1, get_gametime() + %2)
#define set_trip_grenade_attached_to(%1,%2)        entity_set_int(%1, EV_INT_iuser4, %2)
#define get_trip_grenade_attached_to(%1)                entity_get_int(%1, EV_INT_iuser4)
#define get_trip_grenade_mode(%1)                                TripNadeMode:entity_get_int(%1, EV_INT_iuser3)
#define set_trip_grenade_mode(%1,%2)                        entity_set_int(%1, EV_INT_iuser3, _:%2)
#define play_sound(%1,%2)                                                (get_option(OPTION_PLAY_SOUNDS)) ? emit_sound(%1, CHAN_WEAPON, %2, 1.0, ATTN_STATIC, 0, PITCH_NORM) : 0
#define play_sound2(%1,%2)                                                (get_option(OPTION_PLAY_SOUNDS)) ? emit_sound(%1, CHAN_ITEM, %2, 1.0, ATTN_STATIC, 0, PITCH_NORM) : 0
#define refresh_can_use_nade(%1,%2)                                get_enabled_modes(%1,%2) ? (cl_can_use_nade[%2] |= (1<<%1)) : (cl_can_use_nade[%2] &= ~(1<<%1))

// Enums! First time I've ever used them. These should make the code infinitely easier to read.
enum NadeRace
{
        GRENADE_EXPLOSIVE = 0,
        GRENADE_FLASHBANG,
        GRENADE_SMOKEGREN,
}

new const NADE_MODEL[][] =
{
        "w_hegrenade.mdl",
        "w_flashbang.mdl",
        "w_smokegrenade.mdl"
}

new const NADE_WPID[NadeRace] =
{
        CSW_HEGRENADE,
        CSW_FLASHBANG,
        CSW_SMOKEGRENADE
}

new const NADE_BIT[NadeRace] =
{
        (1<<0),
        (1<<1),
        (1<<2)
}

enum NadeType
{
        NADE_DUD = -1, 
        NADE_NORMAL,
        NADE_PROXIMITY,
        NADE_IMPACT,
        NADE_TRIP,
        NADE_MOTION,
        NADE_SATCHEL,
        NADE_HOMING
}

new UNCOUNTABLE_NADE_MODES                =        ((1 << (_:NADE_DUD + 1)) | (1 << (_:NADE_NORMAL + 1)) | (1 << (_:NADE_IMPACT + 1)) | (1 << (_:NADE_HOMING + 1)))
new const NADE_DONT_COUNT                = (1<<31)

enum Fward
{
        FWD_NONE_ACTIVE        = 0,
        FWD_CMDSTART                  = (1<<0),
        FWD_THINK                  = (1<<1),
        FWD_SETMODEL                  = (1<<2),
        FWD_TOUCH                    = (1<<3),
        FWD_SEC_EXPLODE        = (1<<4),
        FWD_TAKEDAMAGE                = (1<<5),
        FWD_THINK_POST                = (1<<6),
        FWD_MESSAGE                = (1<<7),
        FWD_HPSYSTEM                = (1<<8)
}

enum ZmFunc
{
        ZM_NO_ZM_ACTIVE        = 0,
        ZM_ZM_ACTIVE                  = 1,
        ZM_CAN_THINK                  = 2,
        ZM_DO_ALL                        = 3
}
 
enum TripNadeMode
{
        TRIP_NOT_ATTACHED = 0,
        TRIP_ATTACHED,
        TRIP_WAITING,
        TRIP_SCANNING,
        TRIP_SHOULD_DETONATE,
        TRIP_DETONATED
}

enum Option
{
        // Primary Off/On cvar
        OPTION_ENABLE_NADE_MODES,
       
        // General settings
        OPTION_FRIENDLY_FIRE,
        OPTION_BOT_ALLOW,
        OPTION_NADES_IN_EFFECT,
        OPTION_REMOVE_IF_DIES,
        OPTION_SUPPRESS_FITH,
        OPTION_DISPLAY_MODE_ON_DRAW,
        OPTION_PLAY_SOUNDS,
        OPTION_RESET_MODE_ON_THROW,
        OPTION_RESOURCE_USE,
        OPTION_MSG_SVC_BAD,
        OPTION_TEAM_PLAY,
        OPTION_AFFECT_OWNER,
        OPTION_UNITS_SYSTEM,
        OPTION_MONSTERMOD_SUPPORT,
       
        // Grenade modes control menu
        OPTION_NORMAL_ENABLED,
        OPTION_PROXIMITY_ENABLED,
        OPTION_IMPACT_ENABLED,
        OPTION_TRIP_ENABLED,
        OPTION_MOTION_ENABLED,
        OPTION_SATCHEL_ENABLED,
        OPTION_HOMING_ENABLED,
       
        OPTION_REACT_TRIP_G,
        OPTION_REACT_TRIP_F,
        OPTION_REACT_TRIP_S,
       
        OPTION_PROXIMITY_LOS,
        OPTION_MOTION_LOS,
        OPTION_SATCHEL_DELAY,
       
        // Limit settings
        OPTION_LIMIT_SYSTEM,
       
        OPTION_LIMIT_PROXIMITY,
        OPTION_LIMIT_TRIP,
        OPTION_LIMIT_MOTION,
        OPTION_LIMIT_SATCHEL,
       
        OPTION_INFINITE_GRENADES,
        OPTION_INFINITE_FLASHES,
        OPTION_INFINITE_SMOKES,
       
        // Hitpoints system settings
        OPTION_MATERIAL_SYSTEM,
       
        OPTION_SEC_EXPLO_AFFECT,
       
        OPTION_HITPOINT_NORMAL,
        OPTION_HITPOINT_PROXIMITY,
        OPTION_HITPOINT_IMPACT,
        OPTION_HITPOINT_TRIP,
        OPTION_HITPOINT_MOTION,
        OPTION_HITPOINT_SATCHEL,
        OPTION_HITPOINT_HOMING,
       
        OPTION_HITPOINT_DEATH,
        OPTION_HITPOINT_FF,
        OPTION_HITPOINT_INTER_DMG,
       
        // Damage settings
        OPTION_DAMAGE_SYSTEM,
       
        OPTION_DMG_THROUGH_WALL,
        OPTION_DMG_SELF,
        OPTION_DMG_TEAMMATES,
       
        OPTION_DMG_NORMAL,
        OPTION_DMG_PROXIMITY,
        OPTION_DMG_IMPACT,
        OPTION_DMG_TRIP,
        OPTION_DMG_MOTION,
        OPTION_DMG_SATCHEL,
        OPTION_DMG_HOMING,
       
        // Internal functional settings
        OPTION_EXPLOSION_DELAY_TIME,
        OPTION_RADIUS_SEC_EXPLOSION,
       
        OPTION_ARM_TIME_TRIP,
        OPTION_ARM_TIME_MOTION,
        OPTION_ARM_TIME_SATCHEL,
        OPTION_ARM_TIME_PROXIMITY,
       
        OPTION_TRIP_DETECT_DISTANCE,
        OPTION_TRIP_FLY_SPEED,
       
        OPTION_RADIUS_PROXIMITY,
        OPTION_RADIUS_MOTION,
       
        OPTION_HOMING_SCAN_RANGE,
        OPTION_HOMING_SUPER_RANGE,
        OPTION_HOMING_EXTRATIME,
        OPTION_HOMING_SPEED_ADD
}

enum OptionType
{
        TOPTION_TOGGLE = 1,
        TOPTION_CELL,
        TOPTION_FLOAT,
}

enum TraceHandles
{
        TH_LOS,
        TH_DMG,
        TH_TRIP,
        TH_BOT
}

// Mod texts that appear when right clicking for mode change
new modetext[][] = { "Normal", "Proximity", "Impact", "Trip laser", "Motion sensor", "Satchel chage", "Homing" }

// Current nade mode
new NadeType:mode[MAX_PLAYERS + 1][NadeRace]

// Global server variables
new g_maxplayers

// Cached client data [bot,alive,weapon,team]
new cl_is_bot = 0
new cl_is_alive = 0
new cl_weapon[MAX_PLAYERS + 1]
new CsTeams:cl_team[MAX_PLAYERS + 1]

// Limit system counter/blocker
new cl_counter[MAX_PLAYERS + 1][NadeRace][NadeType]
new cl_can_use_nade[NadeRace]

// Next +use time, used in satchel charge nade types when the delay explosion is set
new Float:cl_nextusetime[MAX_PLAYERS + 1]

// Special queue used in penetration detection of grenades
new cl_entity_queue[MAX_PLAYERS + 1][SHOT_ENTITY_QUEUE_LENGTH]

// Trace handles used in different situations
new g_ptrace[TraceHandles]

// Hp system global variables [enable/disable, global trace attack class registration]
new g_check_hpsystem = -1
new Trie:trace_attack_reg_class

// First enabled modes, so that the plugin knows where to start
new NadeType:g_firstenabledmode[NadeRace]

// Plugin functionality enable/disable mechanism
new Fward:bs_forward_collection = FWD_NONE_ACTIVE

// Cvars [Options]
new OptionType:option_type[Option]
new Array:option_value[Option]
new pcvars[Option] // Cvar pointers
new ccvars[Option] // Cached cvars

// Mod dependent variables [CZ/ZM]
new ZmFunc:g_zombie_mod
new g_botquota

// Forwards
new g_FW_property, g_PFW_property

// Messages
new beampoint
new shockwave
new nadebits

// Advanced bullet damage
new const Float:g_flCoords[][] =
{
        {0.50, 0.40},
        {0.56, 0.44},
        {0.60, 0.50},
        {0.56, 0.56},
        {0.50, 0.60},
        {0.44, 0.56},
        {0.40, 0.50},
        {0.44, 0.44}
}

new g_iPlayerPos[MAX_PLAYERS+1]

new g_iMaxPlayers
new g_pCvarEnabled

public plugin_init() {

        register_cvar("nademodes_version", VERSION, FCVAR_SERVER|FCVAR_SPONLY)
       
        // General Settings Options
        pcvars[OPTION_FRIENDLY_FIRE] = get_cvar_pointer("mp_friendlyfire")
       
        register_option(OPTION_ENABLE_NADE_MODES, "nademodes_enable", "1")
        register_option(OPTION_NADES_IN_EFFECT, "nademodes_nades_in_effect", "7", TOPTION_CELL)
        register_option(OPTION_MSG_SVC_BAD, "nademodes_svc_bad_error_fix", "0")
       
        register_option(OPTION_PLAY_SOUNDS, "nademodes_play_grenade_sounds", "1")
        register_option(OPTION_RESOURCE_USE, "nademodes_effects", "2", TOPTION_CELL)
       
        register_option(OPTION_DISPLAY_MODE_ON_DRAW, "nademodes_display_mode_on_draw", "1")
        register_option(OPTION_RESET_MODE_ON_THROW, "nademodes_reset_mode_on_throw", "0")
        register_option(OPTION_SUPPRESS_FITH, "nademodes_suppress_fire_in_the_hole", "0")
       
        register_option(OPTION_BOT_ALLOW, "nademodes_bot_support", "1")
       
        register_option(OPTION_REMOVE_IF_DIES, "nademodes_remove_if_player_dies", "0")
        register_option(OPTION_AFFECT_OWNER, "nademodes_affect_owner", "1")
        register_option(OPTION_TEAM_PLAY, "nademodes_team_play", "1")
        register_option(OPTION_UNITS_SYSTEM, "nademodes_unit_system", "1")
       
        register_option(OPTION_MONSTERMOD_SUPPORT, "nademodes_monstermod_support", "0")
       
        // General Settings Option Values
        register_option_value(OPTION_RESOURCE_USE, "0;1;2;3")
        register_option_value(OPTION_NADES_IN_EFFECT, "0;1;2;3;4;5;6;7")
       
        // Mode Settings Options
        register_option(OPTION_NORMAL_ENABLED, "nademodes_normal_enabled", "1")
        register_option(OPTION_PROXIMITY_ENABLED, "nademodes_proximity_enabled", "1")
        register_option(OPTION_IMPACT_ENABLED, "nademodes_impact_enabled", "1")
        register_option(OPTION_TRIP_ENABLED, "nademodes_trip_enabled", "1")
        register_option(OPTION_MOTION_ENABLED, "nademodes_motion_enabled", "1")
        register_option(OPTION_SATCHEL_ENABLED, "nademodes_satchel_enabled", "1")
        register_option(OPTION_HOMING_ENABLED, "nademodes_homing_enabled", "1")
       
        register_option(OPTION_REACT_TRIP_G, "nademodes_grenade_react", "1")
        register_option(OPTION_REACT_TRIP_F, "nademodes_flash_react", "1")
        register_option(OPTION_REACT_TRIP_S, "nademodes_smoke_react", "1")
       
        register_option(OPTION_PROXIMITY_LOS, "nademodes_proximity_fov", "0")
        register_option(OPTION_MOTION_LOS, "nademodes_motion_fov", "1")
        register_option(OPTION_SATCHEL_DELAY, "nademodes_satchel_delay", "0")
       
        // Limit Settings Options
        register_option(OPTION_LIMIT_SYSTEM, "nademodes_limit_system", "2", TOPTION_CELL)
        register_option(OPTION_LIMIT_PROXIMITY, "nademodes_proximity_limit", "5", TOPTION_CELL)
        register_option(OPTION_LIMIT_TRIP, "nademodes_trip_limit", "5", TOPTION_CELL)
        register_option(OPTION_LIMIT_MOTION, "nademodes_motion_limit", "5", TOPTION_CELL)
        register_option(OPTION_LIMIT_SATCHEL, "nademodes_satchel_limit", "5", TOPTION_CELL)
       
        register_option(OPTION_INFINITE_GRENADES, "nademodes_infinite_grenades", "0")
        register_option(OPTION_INFINITE_FLASHES, "nademodes_infinite_flashes", "0")
        register_option(OPTION_INFINITE_SMOKES, "nademodes_infinite_smokes", "0")
       
        // Limit Settings Option Values
        register_option_value(OPTION_LIMIT_SYSTEM, "0;1;2")
       
        register_option_value(OPTION_LIMIT_PROXIMITY, "0;1;2;3;4;5;6;7;8;9;10;11;12;13;14;15")
        register_option_value(OPTION_LIMIT_TRIP, "0;1;2;3;4;5;6;7;8;9;10;11;12;13;14;15")
        register_option_value(OPTION_LIMIT_MOTION, "0;1;2;3;4;5;6;7;8;9;10;11;12;13;14;15")
        register_option_value(OPTION_LIMIT_SATCHEL, "0;1;2;3;4;5;6;7;8;9;10;11;12;13;14;15")
       
        // Hitpoint Options
        register_option(OPTION_MATERIAL_SYSTEM, "nademodes_material_system", "0", TOPTION_CELL)
        register_option(OPTION_HITPOINT_DEATH, "nademodes_grenade_death","1")
       
        register_option(OPTION_SEC_EXPLO_AFFECT, "nademodes_secondary_explosions_mode", "0")
       
        register_option(OPTION_HITPOINT_NORMAL, "nademodes_hitpoints_normal", "10", TOPTION_CELL)
        register_option(OPTION_HITPOINT_PROXIMITY, "nademodes_hitpoints_proximity", "100", TOPTION_CELL)
        register_option(OPTION_HITPOINT_IMPACT, "nademodes_hitpoints_impact", "10", TOPTION_CELL)
        register_option(OPTION_HITPOINT_TRIP, "nademodes_hitpoints_trip", "100", TOPTION_CELL)
        register_option(OPTION_HITPOINT_MOTION, "nademodes_hitpoints_motion", "100", TOPTION_CELL)
        register_option(OPTION_HITPOINT_SATCHEL, "nademodes_hitpoints_satchel", "100", TOPTION_CELL)
        register_option(OPTION_HITPOINT_HOMING, "nademodes_hitpoints_homing", "10", TOPTION_CELL)
       
        register_option(OPTION_HITPOINT_INTER_DMG, "nademodes_hitpoints_intergrenade_damage", "100", TOPTION_FLOAT)
        register_option(OPTION_HITPOINT_FF, "nademodes_hitpoints_friendlyfire_ammount", "50", TOPTION_FLOAT)
       
        // Hitpoint Options Values
        register_option_value(OPTION_MATERIAL_SYSTEM, "0;1;2")
       
        register_option_value(OPTION_HITPOINT_NORMAL, "0;1;10;20;30;40;50;60;70;80;90;100;110;120;130;140;150;175;200;250;300;400;500;750;1000")
        register_option_value(OPTION_HITPOINT_PROXIMITY, "0;1;10;20;30;40;50;60;70;80;90;100;110;120;130;140;150;175;200;250;300;400;500;750;1000")
        register_option_value(OPTION_HITPOINT_IMPACT, "0;1;10;20;30;40;50;60;70;80;90;100;110;120;130;140;150;175;200;250;300;400;500;750;1000")
        register_option_value(OPTION_HITPOINT_TRIP, "0;1;10;20;30;40;50;60;70;80;90;100;110;120;130;140;150;175;200;250;300;400;500;750;1000")
        register_option_value(OPTION_HITPOINT_MOTION, "0;1;10;20;30;40;50;60;70;80;90;100;110;120;130;140;150;175;200;250;300;400;500;750;1000")
        register_option_value(OPTION_HITPOINT_SATCHEL, "0;1;10;20;30;40;50;60;70;80;90;100;110;120;130;140;150;175;200;250;300;400;500;750;1000")
        register_option_value(OPTION_HITPOINT_HOMING, "0;1;10;20;30;40;50;60;70;80;90;100;110;120;130;140;150;175;200;250;300;400;500;750;1000")
       
        register_option_value(OPTION_HITPOINT_INTER_DMG, "0;5;10;15;20;25;30;35;45;50;55;60;65;70;75;80;85;90;95;100")
        register_option_value(OPTION_HITPOINT_FF, "0;5;10;15;20;25;30;35;45;50;55;60;65;70;75;80;85;90;95;100")
       
        // Damage System Option Registration
        register_option(OPTION_DAMAGE_SYSTEM, "nademodes_damage_system", "2", TOPTION_CELL)
       
        register_option(OPTION_DMG_THROUGH_WALL, "nademodes_damage_through_wall", "50", TOPTION_CELL)
        register_option(OPTION_DMG_SELF, "nademodes_damage_self", "50", TOPTION_CELL)
        register_option(OPTION_DMG_TEAMMATES, "nademodes_damage_teammate", "50", TOPTION_CELL)
       
        register_option(OPTION_DMG_NORMAL, "nademodes_damage_normal", "1.0", TOPTION_FLOAT)
        register_option(OPTION_DMG_IMPACT, "nademodes_damage_impact", "1.0", TOPTION_FLOAT)
        register_option(OPTION_DMG_PROXIMITY, "nademodes_damage_proximity", "1.0", TOPTION_FLOAT)
        register_option(OPTION_DMG_MOTION, "nademodes_damage_motion", "1.0", TOPTION_FLOAT)
        register_option(OPTION_DMG_SATCHEL, "nademodes_damage_satchel", "1.0", TOPTION_FLOAT)
        register_option(OPTION_DMG_TRIP, "nademodes_damage_trip", "1.0", TOPTION_FLOAT)
        register_option(OPTION_DMG_HOMING, "nademodes_damage_homing", "1.0", TOPTION_FLOAT)
       
        // Damage System Option Values
        register_option_value(OPTION_DAMAGE_SYSTEM, "0;1;2")
       
        register_option_value(OPTION_DMG_THROUGH_WALL, "0;5;10;15;20;25;30;35;45;50;55;60;65;70;75;80;85;90;95;100")
        register_option_value(OPTION_DMG_SELF, "0;5;10;15;20;25;30;35;45;50;55;60;65;70;75;80;85;90;95;100")
        register_option_value(OPTION_DMG_TEAMMATES, "0;5;10;15;20;25;30;35;45;50;55;60;65;70;75;80;85;90;95;100")
       
        register_option_value(OPTION_DMG_NORMAL, "0.2;0.4;0.6;0.8;1;1.2;1.4;1.6;1.8;2;2.2;2.4;2.6;2.8;3;3.2;3.4;3.6;3.8;4;5;6;7")
        register_option_value(OPTION_DMG_IMPACT, "0.2;0.4;0.6;0.8;1;1.2;1.4;1.6;1.8;2;2.2;2.4;2.6;2.8;3;3.2;3.4;3.6;3.8;4;5;6;7")
        register_option_value(OPTION_DMG_MOTION, "0.2;0.4;0.6;0.8;1;1.2;1.4;1.6;1.8;2;2.2;2.4;2.6;2.8;3;3.2;3.4;3.6;3.8;4;5;6;7")
        register_option_value(OPTION_DMG_PROXIMITY, "0.2;0.4;0.6;0.8;1;1.2;1.4;1.6;1.8;2;2.2;2.4;2.6;2.8;3;3.2;3.4;3.6;3.8;4;5;6;7")
        register_option_value(OPTION_DMG_SATCHEL, "0.2;0.4;0.6;0.8;1;1.2;1.4;1.6;1.8;2;2.2;2.4;2.6;2.8;3;3.2;3.4;3.6;3.8;4;5;6;7")
        register_option_value(OPTION_DMG_TRIP, "0.2;0.4;0.6;0.8;1;1.2;1.4;1.6;1.8;2;2.2;2.4;2.6;2.8;3;3.2;3.4;3.6;3.8;4;5;6;7")
        register_option_value(OPTION_DMG_HOMING, "0.2;0.4;0.6;0.8;1;1.2;1.4;1.6;1.8;2;2.2;2.4;2.6;2.8;3;3.2;3.4;3.6;3.8;4;5;6;7")
       
        // Internal Settings Float Options
        register_option(OPTION_EXPLOSION_DELAY_TIME, "nademodes_explosion_delay_time", "60000.0", TOPTION_FLOAT)
       
        register_option(OPTION_RADIUS_SEC_EXPLOSION, "nademodes_secondary_explosion_radius", "275.0", TOPTION_FLOAT)
       
        register_option(OPTION_ARM_TIME_TRIP, "nademodes_trip_grenade_arm_time", "3.0", TOPTION_FLOAT)
        register_option(OPTION_ARM_TIME_PROXIMITY, "nademodes_proximity_arm_time", "2.0", TOPTION_FLOAT)
        register_option(OPTION_ARM_TIME_MOTION, "nademodes_motion_arm_time", "2.0",  TOPTION_FLOAT)
        register_option(OPTION_ARM_TIME_SATCHEL, "nademodes_satchel_arm_time", "2.0", TOPTION_FLOAT)
       
        register_option(OPTION_TRIP_FLY_SPEED, "nademodes_trip_grenade_fly_speed", "400.0", TOPTION_FLOAT)
        register_option(OPTION_TRIP_DETECT_DISTANCE, "nademodes_trip_grenade_detection_limit", "16000.0", TOPTION_FLOAT)
       
        register_option(OPTION_RADIUS_PROXIMITY, "nademodes_proximity_radius", "150.0", TOPTION_FLOAT)
        register_option(OPTION_RADIUS_MOTION, "nademodes_motion_radius", "200.0", TOPTION_FLOAT)
       
        register_option(OPTION_HOMING_SCAN_RANGE, "nademodes_homing_detection_range", "500.0", TOPTION_FLOAT)
        register_option(OPTION_HOMING_SUPER_RANGE, "nademodes_homing_superhoming_range", "100.0", TOPTION_FLOAT)
        register_option(OPTION_HOMING_EXTRATIME, "nademodes_homing_extratime", "0.5", TOPTION_FLOAT)
        register_option(OPTION_HOMING_SPEED_ADD, "nademodes_homing_velocity_deviation", "60.0", TOPTION_FLOAT)
       
        // Internal Settings Option Values
        register_option_value(OPTION_EXPLOSION_DELAY_TIME, "600;700;800;900;1000;1400;1800;2200;2600;3000;4000;5000;6000;10000;60000")
       
        register_option_value(OPTION_RADIUS_SEC_EXPLOSION, "25;50;75;100;125;150;175;200;225;250;275;300;325;350")
       
        register_option_value(OPTION_ARM_TIME_TRIP, "1;1.5;2;2.5;3;3.5;4;4.5;5")
        register_option_value(OPTION_ARM_TIME_PROXIMITY, "1;1.5;2;2.5;3;3.5;4;4.5;5")
        register_option_value(OPTION_ARM_TIME_MOTION, "1;1.5;2;2.5;3;3.5;4;4.5;5")
        register_option_value(OPTION_ARM_TIME_SATCHEL, "1;1.5;2;2.5;3;3.5;4;4.5;5")
       
        register_option_value(OPTION_TRIP_FLY_SPEED, "200;250;300;350;400;450;500;550;600;650;700;750;800;850;900;1000")
        register_option_value(OPTION_TRIP_DETECT_DISTANCE, "400;800;1000;2000;4000;8000;16000")
       
        register_option_value(OPTION_RADIUS_PROXIMITY, "100;110;120;130;140;150;160;170;180;190;200")
        register_option_value(OPTION_RADIUS_MOTION, "150;160;170;180;190;200;210;220;230;240;250")
       
        register_option_value(OPTION_HOMING_SCAN_RANGE,"200;250;300;350;400;450;500;550;600;650;700;750;800;850;900;950;1000")
        register_option_value(OPTION_HOMING_SUPER_RANGE, "40;60;80;100;120;140;160;180;200;220;240;260;280;300")
        register_option_value(OPTION_HOMING_EXTRATIME, "0;0.1;0.2;0.3;0.4;0.5;0.6;0.7;0.8;0.9;1")
        register_option_value(OPTION_HOMING_SPEED_ADD, "10;15;20;25;30;35;40;45;50;55;60;65;70;75;80;85;90;95;100;125;150")
       
        cacheCvars()
       
        register_event("CurWeapon", "event_armnade", "b", "1=1", "2=4", "2=9", "2=25")
        register_event("CurWeapon", "event_curweapon", "b", "1=1")
        register_event("HLTV", "event_new_round3", "a", "1=0", "2=0")
       
        g_firstenabledmode[GRENADE_EXPLOSIVE] = NADE_NORMAL
        g_firstenabledmode[GRENADE_FLASHBANG] = NADE_NORMAL
        g_firstenabledmode[GRENADE_SMOKEGREN] = NADE_NORMAL
       
        g_ptrace[TH_LOS] = create_tr2()
        g_ptrace[TH_DMG] = create_tr2()
        g_ptrace[TH_TRIP] = create_tr2()
        g_ptrace[TH_BOT] = create_tr2()
       
        // Register all the forwards
        RegisterHam(Ham_TakeDamage,          "player", "fw_takedamage")
        RegisterHam(Ham_Killed,                  "player", "fw_killed_post", 1)
        RegisterHam(Ham_Spawn,                        "player", "fw_spawn_post", 1)
        RegisterHam(Ham_TakeDamage,          "func_wall", "fw_monster_takedamage")
        RegisterHam(Ham_Player_PreThink, "player", "fw_playerprethink2")
       
        RegisterHam(Ham_Touch,                "grenade", "fw_touch")
        RegisterHam(Ham_TakeDamage, "grenade", "fw_grenade_takedamage")
       
        RegisterHam(Ham_TraceAttack, "worldspawn", "fw_global_traceattack", 1)
        RegisterHam(Ham_TraceAttack, "player", "fw_global_traceattack", 1)
       
        g_FW_property = CreateMultiForward("fw_NM_nade_property_set", ET_STOP, FP_CELL, FP_CELL)
        g_PFW_property = CreateMultiForward("fw_NM_nade_property_set_post", ET_IGNORE, FP_CELL, FP_CELL, FP_CELL)
       
        register_forward(FM_CmdStart,        "fw_cmdstart")
        register_forward(FM_SetModel,        "fw_setmodel2", 1)
        register_forward(FM_TraceLine,        "fw_traceline")
       
        register_message(get_user_msgid("SendAudio"), "fith_audio")
        register_message(get_user_msgid("TextMsg"),  "fith_text")
       
        set_task(SETTINGS_REFRESH_TIME, "update_forward_registration", 0, "", 0, "b", 0)
       
        g_botquota = cvar_exists("bot_quota") ? get_cvar_pointer("bot_quota") : 0;
        g_zombie_mod = ZM_NO_ZM_ACTIVE  // Initially we are not sure if a zombie mod is on or not

public plugin_end()
{
        // Nade Modes
        DestroyForward(fnFwdPlayerChilled);
        DestroyForward(fnFwdPlayerFrozen);
}

public plugin_prcache()
{
        // Registered before all the nade plugins
        RegisterHam(Ham_Think, "grenade", "fw_think")
        RegisterHam(Ham_Think, "grenade", "fw_track_explosion")
        RegisterHam(Ham_Think, "grenade", "fw_think_post", 1)
       
        // Trace attack register trie
        trace_attack_reg_class = TrieCreate()
       
        // We register this here to track shots, it is also important
        register_forward(FM_Spawn, "fw_spawn", 1)
       
        beampoint = precache_model("sprites/laserbeam.spr")
        shockwave = precache_model("sprites/shockwave.spr")
        nadebits  = precache_model("models/chromegibs.mdl")
       
        precache_sound(ACTIVATE)
        precache_sound(CHARGE)
        precache_sound(DEPLOY)
        precache_sound(GEIGER)
        precache_sound(PING)
        precache_sound(BUTTON)
}

public client_putinserver(id)
{
        // Nade Modes
        if (is_user_bot(id))
        {
                cl_is_bot |= (1<<id)
               
                if (g_botquota != 0)
                {
                        // Delay for private data to initialize
                        if (get_pcvar_num(g_botquota))
                                set_task(0.1, "task_botHamHooks", id)
                }
        }
       
        set_task(30.0,"Show_Repture_reminder",id,_,_,"b");
}

public client_disconnect(id)
{
        cl_is_bot &= ~(1<<id)
       
        mode[id][GRENADE_EXPLOSIVE] = FirstEnabledMode(GRENADE_EXPLOSIVE)
        mode[id][GRENADE_FLASHBANG] = FirstEnabledMode(GRENADE_FLASHBANG)
        mode[id][GRENADE_SMOKEGREN] = FirstEnabledMode(GRENADE_SMOKEGREN)
       
        resetCounter(id)
       
        cl_nextusetime[id] = 0.0
       
        cl_team[id] = CS_TEAM_UNASSIGNED
}

public client_connect(id)
{
        mode[id][GRENADE_EXPLOSIVE] = FirstEnabledMode(GRENADE_EXPLOSIVE)
        mode[id][GRENADE_FLASHBANG] = FirstEnabledMode(GRENADE_FLASHBANG)
        mode[id][GRENADE_SMOKEGREN] = FirstEnabledMode(GRENADE_SMOKEGREN)
       
        resetCounter(id)
}

register_option(Option:option, const name[300], const string[], OptionType:type = TOPTION_TOGGLE, flags = 0, Float:value = 0.0)
{
        pcvars[option] = register_cvar(name, string, flags, value)
        option_type[option] = type
        return
}

register_option_value(Option:option, values[CVAR_STRING_ALLOC])
{
        if (option_type[option] == TOPTION_TOGGLE)
                return
       
        option_value[option] = ArrayCreate(CVAR_STRING_ALLOC + 1)
        ArrayPushString(option_value[option], values)
}

stock unregister_all_option_value()
{
        for (new Option:option=OPTION_ENABLE_NADE_MODES; option <= OPTION_HOMING_SPEED_ADD; option += OPTION_FRIENDLY_FIRE)
        {
                if (option_type[option] == TOPTION_TOGGLE)
                        return
               
                ArrayDestroy(option_value[option])
        }
}

cacheCvars()
{
        for (new Option:option=OPTION_ENABLE_NADE_MODES; option <= OPTION_HOMING_SPEED_ADD; option += OPTION_FRIENDLY_FIRE)
        {
                if (option_type[option] == TOPTION_FLOAT)
                {
                        ccvars[option] = _:get_pcvar_float(pcvars[option])
                }
                else
                {
                        ccvars[option] = get_pcvar_num(pcvars[option])
                }
        }
}

public callback_enabled(id, menu, item)
{
        return ITEM_ENABLED
}

public task_botHamHooks(id)
{
        if (g_botquota == 0 || !is_user_connected(id))
                return
       
        // Check again for safety
        if (is_user_bot(id) && get_pcvar_num(g_botquota) > 0)
        {
                // Post spawn fix for cz bots, since RegisterHam does not work for them
                RegisterHamFromEntity(Ham_Killed,                        id, "fw_killed_post", 1)
                RegisterHamFromEntity(Ham_Spawn,                        id, "fw_spawn_post", 1)
                RegisterHamFromEntity(Ham_TakeDamage,                  id, "fw_takedamage")
                RegisterHamFromEntity(Ham_Player_PreThink,        id, "fw_playerprethink")
               
                // Only needs to run once after ham is registed.
                g_botquota = 0
        }
       
        // Added this if other bots that come here and don't know what to do.
        fw_spawn_post(id)

}

public update_forward_registration()
{
        // Here we also update some global constants
        cacheCvars()
        g_maxplayers = get_maxplayers()
       
        if (g_check_hpsystem == -1)
        {
                g_check_hpsystem = get_option(OPTION_MATERIAL_SYSTEM)
        }
        else
        {
                if (!is_nademodes_enabled() && get_option(OPTION_MATERIAL_SYSTEM) == 2)
                {
                        new i=-1
                        while ((i = find_ent_by_class(i, "grenade")))
                        {
                                if (!is_grenade(i))
                                        continue
                               
                                if (entity_get_float(i, EV_FL_health))
                                {
                                        entity_set_float(i, EV_FL_takedamage, DAMAGE_NO)
                                }
                        }
                }
               
                if (g_check_hpsystem != get_option(OPTION_MATERIAL_SYSTEM))
                {
                        if ((get_option(OPTION_MATERIAL_SYSTEM) == 0 || get_option(OPTION_MATERIAL_SYSTEM) == 1) && g_check_hpsystem == 2)
                        {
                                new i=-1
                                while ((i = find_ent_by_class(i, "grenade")))
                                {
                                        if (!is_grenade(i))
                                                continue
                                       
                                        if (entity_get_float(i, EV_FL_health))
                                        {
                                                entity_set_float(i, EV_FL_takedamage, DAMAGE_NO)
                                        }
                                }
                        }
                       
                        if (get_option(OPTION_MATERIAL_SYSTEM) == 2 && (g_check_hpsystem == 1 || g_check_hpsystem == 0))
                        {
                               
                                new i=-1
                                while ((i = find_ent_by_class(i, "grenade")))
                                {
                                        if (!is_grenade(i))
                                                continue
                                       
                                        if (entity_get_float(i, EV_FL_health))
                                        {
                                                entity_set_float(i, EV_FL_takedamage, DAMAGE_YES)
                                        }
                                }
                        }
                }
               
                g_check_hpsystem = get_option(OPTION_MATERIAL_SYSTEM)
        }
       
        if (is_nademodes_enabled())
        {
                bs_forward_collection |= FWD_CMDSTART | FWD_SETMODEL | FWD_THINK | FWD_TOUCH
               
                if (get_option(OPTION_DAMAGE_SYSTEM))
                {
                        bs_forward_collection |= FWD_TAKEDAMAGE
                }
                else
                {
                        bs_forward_collection &= ~FWD_TAKEDAMAGE
                }
               
                if (get_option(OPTION_RESOURCE_USE))
                {
                        bs_forward_collection |= FWD_THINK_POST
                }
                else
                {
                        bs_forward_collection &= ~FWD_THINK_POST
                }
               
                if (!get_option(OPTION_MATERIAL_SYSTEM) || get_option(OPTION_MATERIAL_SYSTEM) > 2 || get_option(OPTION_MATERIAL_SYSTEM) < 0)
                {
                        bs_forward_collection &= ~(FWD_SEC_EXPLODE | FWD_HPSYSTEM)
                }
               
                if (get_option(OPTION_MATERIAL_SYSTEM) == 1)
                {
                        bs_forward_collection |= FWD_SEC_EXPLODE
                }
                else
                {
                        bs_forward_collection &= ~FWD_SEC_EXPLODE
                }
               
                if (get_option(OPTION_MATERIAL_SYSTEM) == 2)
                {
                        bs_forward_collection |= FWD_HPSYSTEM
                }
                else
                {
                        bs_forward_collection &= ~FWD_HPSYSTEM
                }
               
                if (get_option(OPTION_SUPPRESS_FITH))
                {
                        bs_forward_collection |= FWD_MESSAGE
                }
                else
                {
                        bs_forward_collection &= ~FWD_MESSAGE
                }
               
        }
        else
        {
                bs_forward_collection = FWD_NONE_ACTIVE
        }
}
/* -------------------------------
[Events]
------------------------------- */
public event_armnade(id)
{
        static nade
       
        switch (read_data(2))
        {
                case CSW_HEGRENADE:        nade = _:GRENADE_EXPLOSIVE
                case CSW_FLASHBANG:        nade = _:GRENADE_FLASHBANG
                case CSW_SMOKEGRENADE:        nade = _:GRENADE_SMOKEGREN
                default: return PLUGIN_CONTINUE
        }
       
        if (!is_nademodes_enabled())
                return PLUGIN_CONTINUE
       
        if (get_option(OPTION_INFINITE_GRENADES + Option:nade))
        {
                cs_set_user_bpammo(id, NADE_WPID[NadeRace:nade], 2000)
        }
       
        if (!(cl_can_use_nade[NadeRace:nade] & (1<<id)))
        {
                client_print(id, print_center, "Mode: Not allowed to throw anymore!")
                return PLUGIN_CONTINUE
        }
       
        if (get_option(OPTION_DISPLAY_MODE_ON_DRAW) && grenade_can_be_used(NadeRace:nade))
        {
                client_print(id, print_center, "Mode: %s", modetext[_:mode[id][NadeRace:nade]])
        }
       
        if (!is_mode_enabled(id, mode[id][NadeRace:nade], NadeRace:nade))
        {
                changemode(id, NadeRace:nade)
        }
       
        return PLUGIN_CONTINUE
}

public event_curweapon(id)
{
        cl_weapon[id] = read_data(2)
}

public event_new_round3()
{
        static players[32], count, id
        get_players(players, count)
       
        for (new i=0;i<count;i++)
        {
                id = players[i]
                resetCounter(id)
        }
       
        static ent
       
        ent = -1
        while ((ent = find_ent_by_class(ent, "grenade")))
        {
                if(is_grenade(ent) && get_grenade_type(ent) != NADE_NORMAL)
                        entity_set_int(ent, EV_INT_flags, entity_get_int(ent, EV_INT_flags) | FL_KILLME)
        }
       
        cacheCvars()
       
        g_zombie_mod &= ~ZM_CAN_THINK  // Disable thinking of ents before the first infection (this will prevent false explosions)
       
        return PLUGIN_CONTINUE
}

/* -------------------------------
[Message Engine Forwads]
------------------------------- */
public fith_audio(msg_id, msg_dest, entity)
{
        if (!(bs_forward_collection & FWD_MESSAGE))
                return PLUGIN_CONTINUE
       
        // Get the string that holds the message and test it to see wether to block it or not
        static string[18]
        get_msg_arg_string(2, string, charsmax(string))
       
        if (equal(string, "%!MRAD_FIREINHOLE")) return PLUGIN_HANDLED
       
        return PLUGIN_CONTINUE
}

public fith_text(msg_id, msg_dest, entity)
{
        if (!(bs_forward_collection & FWD_MESSAGE))
                return PLUGIN_CONTINUE
       
        static string[18]
       
        // Get the string that holds the message and test it to see wether to block it or not
        if (get_msg_args() == 5) // CS
        {
                get_msg_arg_string(5, string, charsmax(string))
        }
        else
        {
                if (get_msg_args() == 6) // CZ
                {
                        get_msg_arg_string(6, string, charsmax(string))
                }
                else
                {
                        return PLUGIN_CONTINUE
                }
        }
       
        return (equal(string, "#Fire_in_the_hole")) ? PLUGIN_HANDLED : PLUGIN_CONTINUE
}

/* -------------------------------
[Ham & Fakemeta Forwards]
------------------------------- */
public fw_playerprethink2(id)
{
        if (!is_user_connected(id) || is_user_connecting(id) || is_user_hltv(id))
                return HAM_IGNORED
       
        switch (cs_get_user_team(id))
        {
                case CS_TEAM_T: cl_team[id] = CS_TEAM_T
                case CS_TEAM_CT: cl_team[id] = CS_TEAM_CT
                default: return HAM_IGNORED
        }
       
        return HAM_IGNORED
}

public fw_cmdstart(id, uc_handle, seed)
{
        if (!(bs_forward_collection & FWD_CMDSTART))
                return FMRES_IGNORED
       
        if (!(cl_is_alive & (1<<id)))
                return FMRES_IGNORED
       
        static bool:key[MAX_PLAYERS + 1] = {false, ...}
       
        static buttons
        buttons = get_uc(uc_handle, UC_Buttons)
       
        if (!(buttons & IN_USE))
        {
                cl_nextusetime[id] = 0.0
        }
       
        if (buttons & IN_ATTACK)
        {
                switch (cl_weapon[id])
                {
                        case CSW_HEGRENADE:        if (!(cl_can_use_nade[GRENADE_EXPLOSIVE] & (1<<id))) set_uc(uc_handle, UC_Buttons, buttons & ~IN_ATTACK)
                        case CSW_FLASHBANG:        if (!(cl_can_use_nade[GRENADE_FLASHBANG] & (1<<id))) set_uc(uc_handle, UC_Buttons, buttons & ~IN_ATTACK)
                        case CSW_SMOKEGRENADE:        if (!(cl_can_use_nade[GRENADE_SMOKEGREN] & (1<<id))) set_uc(uc_handle, UC_Buttons, buttons & ~IN_ATTACK)
                }
        }

        if (buttons & IN_ATTACK2)
        {
                if (!key[id])
                {
                        switch (cl_weapon[id])
                        {
                                case CSW_HEGRENADE:        if (cl_can_use_nade[GRENADE_EXPLOSIVE] & (1<<id)) changemode(id, GRENADE_EXPLOSIVE)
                                case CSW_FLASHBANG:        if (cl_can_use_nade[GRENADE_FLASHBANG] & (1<<id)) changemode(id, GRENADE_FLASHBANG)
                                case CSW_SMOKEGRENADE:        if (cl_can_use_nade[GRENADE_SMOKEGREN] & (1<<id)) changemode(id, GRENADE_SMOKEGREN)
                        }
                }
               
                key[id] = true
        }
        else
        {
                key[id] = false
        }
       
        return FMRES_IGNORED
}

public fw_setmodel2(ent, model[])
{
        if (!pev_valid(ent))
        {
                return FMRES_IGNORED
        }
       
        // Not yet thrown
        if (entity_get_float(ent, EV_FL_gravity) == 0.0)
        {
                return FMRES_IGNORED
        }
       
        for (new i=0;i<3;i++)
        {
                if (containi(model, NADE_MODEL[i]) != -1)
                {
                        set_pdata_int(ent, OFFSET_WEAPONID, NADE_WPID[NadeRace:i], EXTRAOFFSET_WEAPONS)
                       
                        if (bs_forward_collection & FWD_SETMODEL)
                                grenade_process(pev(ent, pev_owner), ent, NadeRace:i)
                       
                        break
                }
        }
       
        return FMRES_IGNORED
}

grenade_process(id, grenade, NadeRace:nade)
{
        if ((cl_is_bot & (1<<id)) && get_option(OPTION_BOT_ALLOW) && grenade_can_be_used(nade))
        {
                // We place the NADE_TRIP last so we can easily make another choice if it doesn't work ;)
                static const NadeType:random_vec[] = {NADE_NORMAL, NADE_IMPACT, NADE_MOTION, NADE_PROXIMITY, NADE_HOMING, NADE_TRIP}
                static NadeType:decision
               
                decision = random_vec[random_num(0, charsmax(random_vec))]
                mode[id][nade] = decision
               
                if (is_mode_enabled(id, mode[id][nade], nade))
                {
                        if (decision == NADE_TRIP)
                        {
                                static loop[4][2] = { {0, 1}, {0, -1}, {1, 1}, {1, -1} }
                                // Search in order: axis +X axis -X axis +Y axis -Y axis
                               
                                new Float:origin[3], Float:end[3], Float:fdest[3], Float:calc_vector[3], Float:height, Float: minimum, Float:distance = 9999999.999, Float:fraction
                               
                                entity_get_vector(id, EV_VEC_origin, origin)
                               
                                xs_vec_copy(origin, end)
                                end[2] += 16000.0
                               
                                engfunc(EngFunc_TraceLine, origin, end, IGNORE_MONSTERS, id, g_ptrace[TH_BOT])
                               
                                get_tr2(g_ptrace[TH_BOT], TR_vecEndPos, end)
                               
                                xs_vec_sub(end, origin, end)
                               
                                height = xs_vec_len(end)
                               
                               
                                xs_vec_copy(origin, end)
                                end[2] -= 16000.0
                               
                                engfunc(EngFunc_TraceLine, origin, end, IGNORE_MONSTERS, id, g_ptrace[TH_BOT])
                               
                                get_tr2(g_ptrace[TH_BOT], TR_vecEndPos, end)
                               
                                xs_vec_sub(end, origin, end)
                               
                                height += xs_vec_len(end)
                               
                                if ( height > BOT_FORCE_CROUCH_HEIGHT_CONST)
                                {
                                        minimum = BOT_MIN_HEIGHT_ALLOW
                                }
                                else
                                {
                                        minimum = BOT_MIN_CROUCH_HEIGHT_ALLOW
                                        height -= BOT_MIN_CROUCH_HEIGHT_ALLOW
                                       
                                }
                               
                                if ( height > BOT_MAX_HEIGHT_ALLOW )
                                {
                                        height = BOT_MAX_HEIGHT_ALLOW
                                }
                               
                                if (xs_vec_len(end) < height)
                                {
                                        xs_vec_mul_scalar(end, - random_float(minimum - xs_vec_len(end),height  - xs_vec_len(end)) / xs_vec_len(end), end)
                                        xs_vec_add(end, origin, origin)
                                }
                                else
                                {
                                        if (xs_vec_len(end) < height)
                                        {
                                                xs_vec_mul_scalar(end,  (xs_vec_len(end) - random_float(minimum, height)) / xs_vec_len(end), end)
                                                xs_vec_add(end, origin, origin)
                                        }
                                        else
                                        {
                                                xs_vec_mul_scalar(end, (xs_vec_len(end) - random_float(minimum, height)) / xs_vec_len(end), end)
                                                xs_vec_add(end, origin, origin)
                                        }
                                }
                               
                                for(new i=0;i<4;i++)
                                {
                                        xs_vec_copy(origin, end)
                                        end[loop[i][0]] = origin[loop[i][0]] + (16000.0 * float(loop[i][1]))
                                       
                                        engfunc(EngFunc_TraceLine, origin, end, IGNORE_MONSTERS, id, g_ptrace[TH_BOT])
                                       
                                        get_tr2(g_ptrace[TH_BOT], TR_flFraction, fraction)
                                       
                                        if (fraction < 1.0)
                                        {
                                                if ( (!is_attachable_surface(get_tr2(g_ptrace[TH_BOT], TR_pHit))) || get_tr2(g_ptrace[TH_BOT], TR_AllSolid) )
                                                {
                                                        continue
                                                }
                                               
                                                get_tr2(g_ptrace[TH_BOT], TR_vecPlaneNormal, calc_vector)
                                               
                                                if ( xs_vec_dot(calc_vector, Float:{0.0,0.0,1.0}) > BOT_WALL_MIN_COSINUS || xs_vec_dot(calc_vector, Float:{0.0,0.0,1.0}) < (-BOT_WALL_MIN_COSINUS) )
                                                {
                                                        continue
                                                }
                                               
                                                get_tr2(g_ptrace[TH_BOT], TR_vecEndPos, end)
                                               
                                                xs_vec_sub(origin, end, calc_vector)
                                               
                                                if (xs_vec_len(calc_vector) < distance)
                                                {
                                                        distance = xs_vec_len(calc_vector)
                                                        xs_vec_normalize(calc_vector, calc_vector)
                                                        xs_vec_mul_scalar(calc_vector, 1.5, calc_vector)
                                                        xs_vec_add(end, calc_vector, end)
                                                        xs_vec_copy(end, fdest)
                                                }
                                        }
                                       
                                }
                               
                                for(new i=0;i<2;i++)
                                {
                                        for(new j=2;j<4;j++)
                                        {
                                                xs_vec_copy(origin, end)
                                               
                                                end[loop[i][0]] = origin[loop[i][0]] + (16000.0 * float(loop[i][1]))
                                                end[loop[j][0]] = origin[loop[j][0]] + (16000.0 * float(loop[j][1]))
                                               
                                                engfunc(EngFunc_TraceLine, origin, end, IGNORE_MONSTERS, id, g_ptrace[TH_BOT])
                                               
                                                get_tr2(g_ptrace[TH_BOT], TR_flFraction, fraction)
                                               
                                                if (fraction < 1.0)
                                                {
                                                        if ( (!is_attachable_surface(get_tr2(g_ptrace[TH_BOT], TR_pHit))) || get_tr2(g_ptrace[TH_BOT], TR_AllSolid) )
                                                        {
                                                                continue
                                                        }
                                                       
                                                        get_tr2(g_ptrace[TH_BOT], TR_vecPlaneNormal, calc_vector)
                                                       
                                                        if ( xs_vec_dot(calc_vector, Float:{0.0,0.0,1.0}) > BOT_WALL_MIN_COSINUS || xs_vec_dot(calc_vector, Float:{0.0,0.0,1.0}) < (-BOT_WALL_MIN_COSINUS) )
                                                        {
                                                                continue
                                                        }
                                                       
                                                        get_tr2(g_ptrace[TH_BOT], TR_vecEndPos, end)
                                                       
                                                        xs_vec_sub(origin, end, calc_vector)
                                                       
                                                        if (xs_vec_len(calc_vector) < distance)
                                                        {
                                                                distance = xs_vec_len(calc_vector)
                                                                xs_vec_normalize(calc_vector, calc_vector)
                                                                xs_vec_mul_scalar(calc_vector, 3.0, calc_vector)
                                                                xs_vec_add(end, calc_vector, end)
                                                                xs_vec_copy(end, fdest)
                                                        }
                                                       
                                                }
                                               
                                        }
                                }
                               
                                xs_vec_sub(fdest, origin, calc_vector)
                               
                                if (xs_vec_len(calc_vector) <= BOT_MIN_DISTANCE_ATTACH)
                                {
                                        xs_vec_normalize(calc_vector, calc_vector)
                                        xs_vec_mul_scalar(calc_vector, 20.0, calc_vector)
                                        entity_set_vector(grenade, EV_VEC_velocity, calc_vector)
                                        entity_set_int(grenade, EV_INT_movetype, MOVETYPE_FLY)
                                        entity_set_origin(grenade, fdest)
                                        set_grenade_type(grenade, mode[id][nade])
                                       
                                }
                                else
                                {
                                        decision = random_vec[random_num(0, charsmax(random_vec) - 1)]
                                        mode[id][nade] = decision
                                        set_grenade_type(grenade, mode[id][nade])
                                }
                               
                        }
                        else
                        {
                                set_grenade_type(grenade, mode[id][nade])
                        }
                }
                else
                {
                        mode[id][nade] = NADE_NORMAL
                        set_grenade_type(grenade, mode[id][nade])
                }
               
                return
        }
       
        if (is_nademodes_enabled() && is_mode_enabled(id, mode[id][nade], nade) && grenade_can_be_used(nade))
        {
                set_grenade_type(grenade, mode[id][nade])
        }
        else
        {
                changemode(id,nade);
                set_grenade_type(grenade, mode[id][nade])
        }
       
        if (get_option(OPTION_RESET_MODE_ON_THROW))
        {
                mode[id][nade] = NADE_NORMAL
        }
       
        return
}

public fw_spawn(ent)
{
        if (!pev_valid(ent))
                return FMRES_IGNORED
       
        static classname[32]
        pev(ent, pev_classname, classname, charsmax(classname))
       
        if(!TrieKeyExists(trace_attack_reg_class, classname))
        {
                RegisterHam(Ham_TraceAttack, classname, "fw_global_traceattack", 1)
                TrieSetCell(trace_attack_reg_class, classname, true)
        }
       
        return FMRES_IGNORED
}

public fw_track_explosion(grenade)
{
        if (entity_get_float(grenade, EV_FL_dmgtime) >= get_gametime())
                return HAM_IGNORED
       
        if (is_grenade_c4(grenade))
                return HAM_IGNORED
       
        new NadeType:type, owner
        owner = entity_get_edict(grenade, EV_ENT_owner)
        type = get_grenade_type(grenade)
       
        if (!is_user_connected(owner) || is_user_connecting(owner) || cl_team[owner] == CS_TEAM_UNASSIGNED)
        {
                entity_set_int(grenade, EV_INT_flags, entity_get_int(grenade, EV_INT_flags) | FL_KILLME)
                return HAM_IGNORED
        }
       
        if (_:type & NADE_DONT_COUNT)
        {
                return HAM_IGNORED
        }
        else
        {
                type &= ~NadeType:NADE_DONT_COUNT
               
                if (get_grenade_race(grenade) == _:GRENADE_SMOKEGREN)
                {
                        if (entity_get_float(grenade, EV_FL_animtime) == 0.0)
                        {
                                return HAM_IGNORED
                        }
                        else
                        {
                                entity_set_float(grenade, EV_FL_animtime, 0.0)
                        }
                       
                        clear_line(grenade)
                }
                else
                {
                        clear_line(grenade)
                }
               
                if (!(_:UNCOUNTABLE_NADE_MODES & (1 << (_:type + 1))))
                {
                        cl_counter[owner][NadeRace:get_grenade_race(grenade)][type] -= 1
                        refresh_can_use_nade(owner, GRENADE_EXPLOSIVE)
                        refresh_can_use_nade(owner, GRENADE_FLASHBANG)
                        refresh_can_use_nade(owner, GRENADE_SMOKEGREN)
                }
               
                entity_set_int(grenade, EV_INT_iuser1, entity_get_int(grenade, EV_INT_iuser1) | NADE_DONT_COUNT)
        }
       
        if (!(bs_forward_collection & FWD_SEC_EXPLODE))
                return HAM_IGNORED
       
        new Float:origin[3]
        new Float:range
        entity_get_vector(grenade, EV_VEC_origin, origin)
        range = get_option_float(OPTION_RADIUS_SEC_EXPLOSION)
       
        new i
        i = g_maxplayers
       
        if (!get_option(OPTION_SEC_EXPLO_AFFECT) && get_grenade_race(grenade) == _:GRENADE_EXPLOSIVE)
        {
                while ((i = find_ent_in_sphere(i, origin, range)))
                {
                        if (i == grenade)
                                continue
                       
                        if (is_grenade(i, true))
                        {
                                if (entity_get_float(i, EV_FL_animtime) == 0.0 && get_grenade_race(i) == _:GRENADE_SMOKEGREN)
                                {
                                        continue
                                }
                               
                                make_explode(i)
                               
                                if (get_grenade_race(i) == _:GRENADE_SMOKEGREN)
                                {
                                        entity_set_int(i, EV_INT_flags, entity_get_int(i, EV_INT_flags) | FL_ONGROUND)
                                        dllfunc(DLLFunc_Think, i)
                                }
                        }
                }
        }
        else
        {
                static race
                race = get_grenade_race(grenade)
               
                while ((i = find_ent_in_sphere(i, origin, range)))
                {
                        if (i == grenade)
                                continue
                       
                        if (is_grenade(i, true))
                        {
                                if (get_grenade_race(i) == race)
                                {
                                        if (entity_get_float(i, EV_FL_animtime) == 0.0 && race == _:GRENADE_SMOKEGREN)
                                        {
                                                continue
                                        }
                                       
                                        make_explode(i)
                                       
                                        if (race == _:GRENADE_SMOKEGREN)
                                        {
                                                entity_set_int(i, EV_INT_flags, entity_get_int(i, EV_INT_flags) | FL_ONGROUND)
                                                dllfunc(DLLFunc_Think, i)
                                        }
                                }
                        }
                }
        }

        return HAM_IGNORED
}

public fw_think(ent)
{
        if (!(bs_forward_collection & FWD_THINK) || !is_valid_ent(ent))
                return HAM_IGNORED
       
        if (is_grenade_c4(ent))
                return HAM_IGNORED
       
        if ((g_zombie_mod & ZM_ZM_ACTIVE) && !(g_zombie_mod & ZM_CAN_THINK) && !(get_grenade_type(ent) == NADE_TRIP && (TRIP_ATTACHED <= get_trip_grenade_mode(ent) <= TRIP_WAITING)))
                return HAM_IGNORED
       
        static i, Float:origin[3], Float:porigin[3], Float:fraction, owner, bs_holds
        static Float:radius, affect_owner, team_play, los
       
        affect_owner = get_option(OPTION_AFFECT_OWNER)
        team_play = get_option(OPTION_TEAM_PLAY)
       
        entity_get_vector(ent, EV_VEC_origin, origin)
       
        owner = entity_get_edict(ent, EV_ENT_owner)
       
        if (!is_user_connected(owner) || is_user_connecting(owner) || cl_team[owner] == CS_TEAM_UNASSIGNED)
        {
                entity_set_int(ent, EV_INT_flags, entity_get_int(ent, EV_INT_flags) | FL_KILLME)
                return HAM_IGNORED
        }
       
        switch (get_grenade_type(ent))
        {
                case NADE_DUD:
                {
                        return HAM_SUPERCEDE
                }
               
                case NADE_NORMAL:
                {
                        return HAM_IGNORED
                }
               
                case NADE_PROXIMITY:
                {
                        if (!allow_grenade_explode(ent))
                                return HAM_IGNORED
                       
                        if (entity_get_float(ent, EV_FL_fuser4) <= get_gametime())
                                play_sound(ent, BUTTON);
                       
                        i = -1
                        radius = get_option_float(OPTION_RADIUS_PROXIMITY)
                        los = get_option(OPTION_PROXIMITY_LOS)
                       
                        while ((i = find_ent_in_sphere(i, origin, radius)))
                        {
                                if (i > g_maxplayers)
                                {
                                        if (get_option(OPTION_MONSTERMOD_SUPPORT))
                                        {
                                                if (is_ent_monster(i))
                                                {
                                                        entity_get_vector(i, EV_VEC_origin, porigin)
                                                       
                                                        engfunc(EngFunc_TraceLine, origin, porigin, IGNORE_MONSTERS, 0, g_ptrace[TH_LOS])
                                                        get_tr2(g_ptrace[TH_LOS], TR_flFraction, fraction)
                                                       
                                                        if (fraction < 1.0)
                                                                continue
                                                       
                                                        make_explode(ent)
                                                        return HAM_IGNORED
                                                }
                                                else
                                                        continue
                                        }
                                       
                                        return HAM_IGNORED
                                }
                               
                                if (!is_player_alive(i))
                                        continue
                               
                                if (los)
                                {
                                        entity_get_vector(i, EV_VEC_origin, porigin)
                                       
                                        engfunc(EngFunc_TraceLine, origin, porigin, IGNORE_MONSTERS, 0, g_ptrace[TH_LOS])
                                        get_tr2(g_ptrace[TH_LOS], TR_flFraction, fraction)
                                       
                                        if (fraction < 1.0)
                                                continue
                                }
                               
                                if (i == owner)
                                {
                                        if (affect_owner)
                                        {
                                                make_explode(ent)
                                                return HAM_IGNORED
                                        }
                                        else
                                        {
                                                continue
                                        }
                                }
                               
                                if (!team_play)
                                {
                                        make_explode(ent)
                                        return HAM_IGNORED
                                }
                                else
                                {
                                        if (cl_team[i] != cl_team[owner])
                                        {
                                                make_explode(ent)
                                                return HAM_IGNORED
                                        }
                                }
                        }
                        return HAM_IGNORED
                }
               
                case NADE_TRIP:
                {
                        static hit, Float:point[3], Float:normal[3], Float:temp[3], Float:end[3], Float:fly[3]
                        static Float:fly_speed, Float:detect_distance, Float:arm_time
                       
                        fly_speed = get_option_float(OPTION_TRIP_FLY_SPEED)
                        detect_distance = get_option_float(OPTION_TRIP_DETECT_DISTANCE)
                        arm_time = get_option_float(OPTION_ARM_TIME_TRIP)
                       
                        switch (get_trip_grenade_mode(ent))
                        {
                                case TRIP_NOT_ATTACHED, TRIP_DETONATED:
                                {
                                        return HAM_IGNORED
                                }
                               
                                case TRIP_ATTACHED:
                                {
                                        static loop[6][2] = { {2, 1}, {2, -1}, {0, 1}, {0, -1}, {1, 1}, {1, -1} }
                                       
                                        for (new i; i < 6; i++)
                                        {
                                                xs_vec_copy(origin, point)
                                               
                                                point[loop[i][0]] = origin[loop[i][0]] + (2.0 * float(loop[i][1]))
                                               
                                                engfunc(EngFunc_TraceLine, origin, point, IGNORE_MONSTERS, ent, g_ptrace[TH_TRIP])
                                               
                                                get_tr2(g_ptrace[TH_TRIP], TR_flFraction, fraction)
                                               
                                                if (fraction < 1.0)
                                                {
                                                        hit = get_tr2(g_ptrace[TH_TRIP], TR_pHit)
                                                       
                                                        if (!is_attachable_surface(hit))
                                                        {
                                                                set_grenade_type(ent, NADE_DUD)
                                                                return HAM_IGNORED
                                                        }
                                                       
                                                        get_tr2(g_ptrace[TH_TRIP], TR_vecPlaneNormal, normal)
                                                       
                                                        set_trip_grenade_attached_to(ent, hit)
                                                       
                                                        xs_vec_mul_scalar(normal, fly_speed, temp)
                                                        set_trip_grenade_fly_velocity(ent, temp)
                                                       
                                                        xs_vec_mul_scalar(normal, detect_distance, temp)
                                                        xs_vec_add(temp, origin, end)
                                                       
                                                        engfunc(EngFunc_TraceLine, origin, end, IGNORE_MONSTERS, ent, g_ptrace[TH_TRIP])
                                                        get_tr2(g_ptrace[TH_TRIP], TR_flFraction, fraction)

                                                        xs_vec_mul_scalar(normal, (detect_distance * fraction), temp)
                                                        xs_vec_add(temp, origin, end)
                                                        set_trip_grenade_end_origin(ent, end)
                                                       
                                                        xs_vec_mul_scalar(temp, 0.5, temp)
                                                        xs_vec_add(temp, origin, temp)
                                                        set_trip_grenade_middle_origin(ent, temp)
                                                       
                                                        set_trip_grenade_arm_time(ent, arm_time)
                                                       
                                                        play_sound(ent, DEPLOY)
                                                       
                                                        entity_set_vector(ent, EV_VEC_velocity, Float:{0.0, 0.0, 0.0}) // Stop if from moving
                                                       
                                                        entity_set_int(ent, EV_INT_sequence, 0) // Otherwise, grenade might make wierd motions.
                                                       
                                                        vector_to_angle(normal, normal)
                                                       
                                                        entity_set_vector(ent, EV_VEC_angles, normal)
                                                       
                                                        set_trip_grenade_mode(ent, TRIP_WAITING)
                                                       
                                                        set_task(0.1, "trip_activation", ent)
                                                       
                                                        return HAM_IGNORED
                                                }
                                        }
                                       
                                        make_explode(ent)
                                       
                                        if (NadeRace:get_grenade_race(ent) == GRENADE_SMOKEGREN)
                                        {
                                                entity_set_int(ent, EV_INT_flags, entity_get_int(ent, EV_INT_flags) | FL_ONGROUND)
                                        }
                                       
                                        return HAM_IGNORED
                                }
                               
                                case TRIP_WAITING:
                                {
                                       
                                        if (!is_attachable_surface(get_trip_grenade_attached_to(ent)))
                                        {
                                                make_explode(ent)
                                       
                                                if (NadeRace:get_grenade_race(ent) == GRENADE_SMOKEGREN)
                                                {
                                                        entity_set_int(ent, EV_INT_flags, entity_get_int(ent, EV_INT_flags) | FL_ONGROUND)
                                                        clear_line(ent)
                                                }
                                               
                                                return HAM_IGNORED
                                        }
                                       
                                        if (get_gametime() > get_trip_grenade_arm_time(ent))
                                        {
                                                set_trip_grenade_mode(ent, TRIP_SCANNING)
                                                play_sound(ent, ACTIVATE)
                                        }
                                       
                                        return HAM_IGNORED
                                }
                               
                                case TRIP_SCANNING:
                                {
                                        if (!is_attachable_surface(get_trip_grenade_attached_to(ent)))
                                        {
                                                make_explode(ent)
                                               
                                                if (NadeRace:get_grenade_race(ent) == GRENADE_SMOKEGREN)
                                                {
                                                        entity_set_int(ent, EV_INT_flags, entity_get_int(ent, EV_INT_flags) | FL_ONGROUND)
                                                        clear_line(ent)
                                                }
                                               
                                                return HAM_IGNORED
                                        }
                                       
                                        get_trip_grenade_end_origin(ent, end)
                                        engfunc(EngFunc_TraceLine, end, origin, DONT_IGNORE_MONSTERS, 0, g_ptrace[TH_TRIP])
                                       
                                        static target
                                        target = get_tr2(g_ptrace[TH_TRIP], TR_pHit)
                                       
                                        if (is_player_alive(target))
                                        {
                                                if (owner == target)
                                                {
                                                        if (affect_owner)
                                                        {
                                                                set_trip_grenade_mode(ent, TRIP_SHOULD_DETONATE)
                                                                entity_set_float(ent, EV_FL_nextthink, get_gametime() + 0.001)
                                                                return HAM_IGNORED
                                                        }
                                                        else
                                                        {
                                                                entity_set_float(ent, EV_FL_nextthink, get_gametime() + 0.001)
                                                                return HAM_IGNORED
                                                        }
                                                }
                                               
                                                if (!team_play)
                                                {
                                                        set_trip_grenade_mode(ent, TRIP_SHOULD_DETONATE)
                                                }
                                                else
                                                {
                                                        if (cl_team[owner] != cl_team[target])
                                                                set_trip_grenade_mode(ent, TRIP_SHOULD_DETONATE)
                                                }
                                        }
                                        else if (get_option(OPTION_MONSTERMOD_SUPPORT) && is_ent_monster(target))
                                        {
                                                set_trip_grenade_mode(ent, TRIP_SHOULD_DETONATE)
                                        }
                                       
                                        entity_set_float(ent, EV_FL_nextthink, get_gametime() + 0.001)
                                        return HAM_IGNORED
                                }
                               
                                case TRIP_SHOULD_DETONATE:
                                {
                                        static mode
                                        mode = get_trip_grenade_react_method(ent)
                                        set_trip_grenade_mode(ent, TRIP_DETONATED)
                                       
                                        clear_line(ent)
                                        play_sound(ent, ACTIVATE)
                                       
                                        if (mode == 0)
                                        {
                                                cl_counter[owner][NadeRace:get_grenade_race(ent)][NADE_TRIP] -= 1
                                               
                                                refresh_can_use_nade(owner, GRENADE_EXPLOSIVE)
                                                refresh_can_use_nade(owner, GRENADE_FLASHBANG)
                                                refresh_can_use_nade(owner, GRENADE_SMOKEGREN)
                                               
                                                get_trip_grenade_fly_velocity(ent, fly)
                                                get_trip_grenade_end_origin(ent, end)
                                                entity_set_vector(ent, EV_VEC_velocity, fly)                        // Send the grenade on its way.
                                                set_grenade_type(ent, NADE_IMPACT)                                                // Kaboom!
                                        }
                                        else
                                        {
                                                make_explode(ent)
                                               
                                                if (NadeRace:get_grenade_race(ent) == GRENADE_SMOKEGREN)
                                                {
                                                        entity_set_int(ent, EV_INT_flags, entity_get_int(ent, EV_INT_flags) | FL_ONGROUND)
                                                        clear_line(ent)
                                                }
                                        }
                                       
                                        return HAM_IGNORED
                                }
                        }
                }
               
                case NADE_MOTION:
                {
                        if (!allow_grenade_explode(ent))
                                return HAM_IGNORED
                       
                        static Float:v[3], Float:velocity
                       
                        i = -1
                        bs_holds = 0
                        radius = get_option_float(OPTION_RADIUS_MOTION)
                        los = get_option(OPTION_MOTION_LOS)
                       
                        while ((i = find_ent_in_sphere(i, origin, radius)))
                        {
                                if (i > g_maxplayers)
                                {
                                        entity_set_int(ent, EV_INT_iuser2, bs_holds)
                                       
                                        if (get_option(OPTION_MONSTERMOD_SUPPORT))
                                        {
                                                if (is_ent_monster(i))
                                                {
                                                        entity_get_vector(i, EV_VEC_origin, porigin)
                                                       
                                                        engfunc(EngFunc_TraceLine, origin, porigin, IGNORE_MONSTERS, 0, g_ptrace[TH_LOS])
                                                        get_tr2(g_ptrace[TH_LOS], TR_flFraction, fraction)
                                                       
                                                        if (fraction < 1.0)
                                                                continue
                                                       
                                                        entity_get_vector(i, EV_VEC_velocity, v)
                                                        velocity = xs_vec_len(v)
                                                       
                                                        if (velocity > 100.0)
                                                        {
                                                                make_explode(ent)
                                                                return HAM_IGNORED
                                                        }
                                                }
                                                else
                                                        continue
                                        }
                                       
                                        return HAM_IGNORED
                                }
                               
                                if (!is_player_alive(i))
                                        continue
                               
                                if (los)
                                {
                                        entity_get_vector(i, EV_VEC_origin, porigin)
                                       
                                        engfunc(EngFunc_TraceLine, origin, porigin, IGNORE_MONSTERS, 0, g_ptrace[TH_LOS])
                                        get_tr2(g_ptrace[TH_LOS], TR_flFraction, fraction)
                                       
                                        if (fraction < 1.0)
                                                continue
                                }
                               
                                entity_get_vector(i, EV_VEC_velocity, v)
                                velocity = xs_vec_len(v)
                               
                                if (velocity > 200.0)
                                {
                                        if (i == owner)
                                        {
                                                if (affect_owner)
                                                {
                                                        make_explode(ent)
                                                        return HAM_IGNORED
                                                }
                                                else
                                                {
                                                        bs_holds |= (1<<i)
                                                        continue
                                                }
                                        }
                                        if (!team_play)
                                        {
                                                make_explode(ent)
                                                return HAM_IGNORED
                                        }
                                        else
                                        {
                                                if (cl_team[i] != cl_team[owner])
                                                {
                                                        make_explode(ent)
                                                        return HAM_IGNORED
                                                }
                                        }
                                       
                                        bs_holds |= (1<<i)
                                        entity_set_int(ent, EV_INT_iuser2, bs_holds)
                                        play_sound(ent, GEIGER)
                                }
                                else if (velocity == 0.0)
                                {
                                        continue
                                }
                                else
                                {
                                        play_sound(ent, GEIGER)
                                       
                                        bs_holds |= (1<<i)
                                }
                               
                        }
                       
                        entity_set_int(ent, EV_INT_iuser2, bs_holds)
                        return HAM_IGNORED
                }
               
                case NADE_SATCHEL:
                {
                        if (!allow_grenade_explode(ent))
                                return HAM_IGNORED
                       
                        if (entity_get_int(owner, EV_INT_button) & IN_USE)
                        {
                                if (get_option(OPTION_SATCHEL_DELAY))
                                {
                                        if (cl_nextusetime[owner] > get_gametime())
                                        {
                                                return HAM_IGNORED
                                        }
                                        else
                                        {
                                                cl_nextusetime[owner] = get_gametime() + DELAY_ADDED_TO_USE
                                        }
                                }
                               
                                make_explode(ent)
                               
                                if (NadeRace:get_grenade_race(ent) == GRENADE_SMOKEGREN)
                                {
                                        entity_set_int(ent, EV_INT_flags, entity_get_int(ent, EV_INT_flags) | FL_ONGROUND)
                                }
                        }
                       
                       
                        return HAM_IGNORED
                }
               
                case NADE_HOMING:
                {
                        static target, Float:extravel
                        target = entity_get_int(ent, EV_INT_iuser2)
                        extravel = get_option_float(OPTION_HOMING_SPEED_ADD)
                       
                        if (target == 0)
                        {
                                static i, Float:distance
                                i = -1
                                distance = get_option_float(OPTION_HOMING_SCAN_RANGE)
                               
                                while ((i = find_ent_in_sphere(i, origin, distance)))
                                {
                                        if (i > g_maxplayers)
                                        {
                                                if (get_option(OPTION_MONSTERMOD_SUPPORT))
                                                {
                                                        if (is_ent_monster(i))
                                                        {
                                                                static Float:o[3]
                                                                entity_get_vector(i, EV_VEC_origin, o)
                                                                static Float:new_distance
                                                                new_distance = get_distance_f(o, origin)
                                                               
                                                                if (new_distance < distance)
                                                                {
                                                                        distance = new_distance
                                                                        entity_set_int(ent, EV_INT_iuser2, i)
                                                                }
                                                        }
                                                        else
                                                        {
                                                                continue
                                                        }
                                                }
                                                else
                                                        break
                                        }
                                       
                                        if (!is_player_alive(i))
                                                continue
                                       
                                        if (i == owner)
                                                continue
                                       
                                        if ((cl_team[i] != cl_team[owner] && team_play) || !team_play)
                                        {
                                                static Float:o[3]
                                                entity_get_vector(i, EV_VEC_origin, o)
                                                static Float:new_distance
                                                new_distance = get_distance_f(o, origin)
                                               
                                                if (new_distance < distance)
                                                {
                                                        distance = new_distance
                                                        entity_set_int(ent, EV_INT_iuser2, i)
                                                }
                                        }
                                }
                               
                                return HAM_IGNORED
                        }
                        else if (!(cl_is_alive & (1<<target)) && target <= g_maxplayers)
                        {
                                return HAM_IGNORED
                        }
                        else if (is_in_los(ent, target))
                        {
                                static Float:velocity[3], Float:aim[3], Float:targetorigin[3], Float:velocity_normal[3], Float:aim_normal[3]
                               
                                entity_get_vector(target, EV_VEC_origin, targetorigin)
                               
                                entity_get_vector(ent, EV_VEC_velocity, velocity)
                               
                                xs_vec_sub(targetorigin, origin, aim)
                               
                                xs_vec_normalize(velocity, velocity_normal)
                                xs_vec_normalize(aim, aim_normal)
                               
                                play_sound(ent, PING)
                               
                                if (velocity_normal[0] < aim_normal[0])
                                {
                                        velocity[0] += extravel
                                }
                                else if (velocity_normal[0] > aim_normal[0])
                                {
                                        velocity[0] -= extravel
                                }
                               
                                if (velocity_normal[1] < aim_normal[1])
                                {
                                        velocity[1] += extravel
                                }
                                else if (velocity_normal[1] > aim_normal[1])
                                {
                                        velocity[1] -= extravel
                                }
                               
                                if (velocity_normal[2] < aim_normal[2])
                                {
                                        velocity[2] += extravel
                                }
                                else if (velocity_normal[2] > aim_normal[2])
                                {
                                        velocity[2] -= extravel
                                }
                               
                                velocity[2] += 5.0
                               
                                entity_set_vector(ent, EV_VEC_velocity, velocity)
                               
                                if (get_distance_f(origin, targetorigin) < get_option_float(OPTION_HOMING_SUPER_RANGE))
                                {
                                        entity_set_float(ent, EV_FL_nextthink, (get_gametime() + 0.05))
                                }
                                else
                                {
                                        entity_set_float(ent, EV_FL_nextthink, (get_gametime() + 0.15))
                                }
                        }
                       
                        return HAM_IGNORED
                }
        }
       
        return HAM_IGNORED
}

public trip_activation(ent)
{
        if (is_valid_ent(ent))
                play_sound(ent, CHARGE)
}

public fw_think_post(ent)
{
        if (!is_valid_ent(ent))
                return HAM_IGNORED
       
        if (is_grenade_c4(ent))
                return HAM_IGNORED
       
        static owner, Float:origin[3], Float:gametime, bs_affected
       
        gametime = get_gametime()
       
        if (entity_get_float(ent, EV_FL_dmgtime) <= gametime)
                return HAM_IGNORED
       
        entity_get_vector(ent, EV_VEC_origin, origin)
        owner = entity_get_edict(ent, EV_ENT_owner)
       
        if (!is_user_connected(owner) || is_user_connecting(owner) || cl_team[owner] == CS_TEAM_UNASSIGNED)
        {
                entity_set_int(ent, EV_INT_flags, entity_get_int(ent, EV_INT_flags) | FL_KILLME)
                return HAM_IGNORED
        }
       
        if (!(bs_forward_collection & FWD_THINK_POST))
        {
                switch (get_grenade_type(ent))
                {
                        case NADE_PROXIMITY:
                        {
                                if (entity_get_float(ent, EV_FL_fuser4) <= gametime)
                                        entity_set_float(ent, EV_FL_fuser4, gametime + 2.0)
                        }
                        case NADE_TRIP:
                        {
                                entity_set_float(ent, EV_FL_nextthink, get_gametime() + 0.001)
                        }
                }
               
                return HAM_IGNORED
        }
       
        bs_affected = 0
       
        if (get_option(OPTION_RESOURCE_USE) != 3)
        {
                bs_affected = ~0
        }
        else
        {
                static team_play, affect_owner
                team_play = get_option(OPTION_TEAM_PLAY)
                affect_owner = get_option(OPTION_AFFECT_OWNER)
               
                if (!team_play)
                {
                        bs_affected = affect_owner ? ~0 : ~(1<<owner)
                }
                else
                {
                        for (new i=1;i<=g_maxplayers;i++)
                        {
                                if (!is_user_connected(i))
                                        continue
                               
                                if (affect_owner & i == owner)
                                        bs_affected |= (1<<i)
                               
                                if (team_play && cs_get_user_team(i) != cs_get_user_team(owner))
                                        bs_affected |= (1<<i)
                        }
                }
        }
       
        switch (get_grenade_type(ent))
        {
                case NADE_PROXIMITY:
                {
                        if (!allow_grenade_explode(ent))
                                return HAM_IGNORED
                       
                        if (entity_get_float(ent, EV_FL_fuser4) <= gametime)
                        {                                               
                                entity_set_float(ent, EV_FL_fuser4, gametime + 2.0)
                               
                                if (entity_get_int(ent, EV_INT_flags) & FL_ONGROUND)
                                {
                                        if (!get_option(OPTION_TEAM_PLAY) || ((g_zombie_mod & ZM_ZM_ACTIVE) && !(g_zombie_mod & ZM_CAN_THINK)))
                                        {
                                                if (get_option(OPTION_RESOURCE_USE) == 1)
                                                {
                                                        show_ring(origin, get_option_float(OPTION_RADIUS_PROXIMITY) * RING_SIZE_CONSTANT_PROXIMITY, 5)
                                                }
                                                else
                                                {
                                                        static i
                                                        i = -1
                                                       
                                                        while ( (i = find_ent_in_sphere(i, origin, SMART_RADIUS_RING_SHOW)) )
                                                        {
                                                                if (i > g_maxplayers)
                                                                        break
                                                               
                                                                if (!(cl_is_alive & (1<<i)) || (cl_is_bot & (1<<i)))
                                                                        continue
                                                               
                                                                if (bs_affected & (1<<i))
                                                                        show_ring(origin, get_option_float(OPTION_RADIUS_PROXIMITY) * RING_SIZE_CONSTANT_PROXIMITY, 5, _, _, _, i)
                                                        }
                                                }
                                        }
                                        else
                                        {
                                                switch (cl_team[owner])
                                                {
                                                        case CS_TEAM_T:
                                                        {
                                                                if (get_option(OPTION_RESOURCE_USE) == 1)
                                                                {
                                                                        show_ring(origin, get_option_float(OPTION_RADIUS_PROXIMITY) * RING_SIZE_CONSTANT_PROXIMITY, 5, TEAMTE_RGB_R_COLOR, TEAMTE_RGB_G_COLOR, TEAMTE_RGB_B_COLOR)
                                                                }
                                                                else
                                                                {
                                                                        static i
                                                                        i = -1
                                                                       
                                                                        while ( (i = find_ent_in_sphere(i, origin, SMART_RADIUS_RING_SHOW)) )
                                                                        {
                                                                                if (i > g_maxplayers)
                                                                                        break
                                                                               
                                                                                if (!(cl_is_alive & (1<<i)) || (cl_is_bot & (1<<i)))
                                                                                        continue
                                                                               
                                                                                if (bs_affected & (1<<i))
                                                                                        show_ring(origin, get_option_float(OPTION_RADIUS_PROXIMITY) * RING_SIZE_CONSTANT_PROXIMITY, 5, TEAMTE_RGB_R_COLOR, TEAMTE_RGB_G_COLOR, TEAMTE_RGB_B_COLOR, i)
                                                                        }
                                                                }
                                                               
                                                        }
                                                        case CS_TEAM_CT:
                                                        {
                                                                if (get_option(OPTION_RESOURCE_USE) == 1)
                                                                {
                                                                        show_ring(origin, get_option_float(OPTION_RADIUS_PROXIMITY) * RING_SIZE_CONSTANT_PROXIMITY, 5, TEAMCT_RGB_R_COLOR, TEAMCT_RGB_G_COLOR, TEAMCT_RGB_B_COLOR)
                                                                }
                                                                else
                                                                {
                                                                        static i
                                                                        i = -1
                                                                       
                                                                        while ( (i = find_ent_in_sphere(i, origin, SMART_RADIUS_RING_SHOW)) )
                                                                        {
                                                                                if (i > g_maxplayers)
                                                                                        break
                                                                               
                                                                                if (!(cl_is_alive & (1<<i)) || (cl_is_bot & (1<<i)))
                                                                                        continue
                                                                               
                                                                                if (bs_affected & (1<<i))
                                                                                        show_ring(origin, get_option_float(OPTION_RADIUS_PROXIMITY) * RING_SIZE_CONSTANT_PROXIMITY, 5, TEAMCT_RGB_R_COLOR, TEAMCT_RGB_G_COLOR, TEAMCT_RGB_B_COLOR, i)
                                                                        }
                                                                }
                                                        }
                                                }
                                        }
                                }
                        }
                }
               
                case NADE_MOTION:
                {
                        static bs_holds
                        bs_holds = entity_get_int(ent, EV_INT_iuser2)
                       
                        if (bs_holds && entity_get_float(ent, EV_FL_fuser4) <= gametime)
                        {
                                entity_set_float(ent, EV_FL_fuser4, get_gametime() + 0.1)
                               
                                if (!get_option(OPTION_TEAM_PLAY) || ((g_zombie_mod & ZM_ZM_ACTIVE) && !(g_zombie_mod & ZM_CAN_THINK)))
                                {
                                        if ( get_option(OPTION_RESOURCE_USE) == 1)
                                        {
                                                show_ring(origin, get_option_float(OPTION_RADIUS_MOTION) * RING_SIZE_CONSTANT_MOTION, 1)
                                        }
                                        else
                                        {
                                                for (new i=1;i<=g_maxplayers;i++)
                                                {
                                                        if ((bs_holds & (1<<i)) && (bs_affected & (1<<i)))
                                                                show_ring(origin, get_option_float(OPTION_RADIUS_MOTION) * RING_SIZE_CONSTANT_MOTION, 1, _, _, _, i)
                                                }
                                        }
                                }
                                else
                                {
                                        switch (cl_team[owner])
                                        {
                                                case CS_TEAM_T:
                                                {
                                                        if ( get_option(OPTION_RESOURCE_USE) == 1 )
                                                        {
                                                                show_ring(origin, get_option_float(OPTION_RADIUS_MOTION) * RING_SIZE_CONSTANT_MOTION, 1, TEAMTE_RGB_R_COLOR, TEAMTE_RGB_G_COLOR, TEAMTE_RGB_B_COLOR)
                                                        }
                                                        else
                                                        {
                                                                for (new i=1;i<=g_maxplayers;i++)
                                                                {
                                                                        if ((bs_holds & (1<<i)) && (bs_affected & (1<<i)))
                                                                                show_ring(origin, get_option_float(OPTION_RADIUS_MOTION) * RING_SIZE_CONSTANT_MOTION, 1, TEAMTE_RGB_R_COLOR, TEAMTE_RGB_G_COLOR, TEAMTE_RGB_B_COLOR, i)
                                                                }
                                                        }
                                                }
                                                case CS_TEAM_CT:
                                                {
                                                        if ( get_option(OPTION_RESOURCE_USE) == 1 )
                                                        {
                                                                show_ring(origin, get_option_float(OPTION_RADIUS_MOTION) * RING_SIZE_CONSTANT_MOTION, 1, TEAMCT_RGB_R_COLOR, TEAMCT_RGB_G_COLOR, TEAMCT_RGB_B_COLOR)
                                                        }
                                                        else
                                                        {
                                                                for (new i=1;i<=g_maxplayers;i++)
                                                                {
                                                                        if ((bs_holds & (1<<i)) && (bs_affected & (1<<i)))
                                                                                show_ring(origin, get_option_float(OPTION_RADIUS_MOTION) * RING_SIZE_CONSTANT_MOTION, 1, TEAMCT_RGB_R_COLOR, TEAMCT_RGB_G_COLOR, TEAMCT_RGB_B_COLOR, i)
                                                                }
                                                        }
                                                }
                                                default:
                                                {
                                                        if ( get_option(OPTION_RESOURCE_USE) == 1 )
                                                        {
                                                                show_ring(origin, get_option_float(OPTION_RADIUS_MOTION) * RING_SIZE_CONSTANT_MOTION, 1, _, _, _)
                                                        }
                                                        else
                                                        {
                                                                for (new i=1;i<=g_maxplayers;i++)
                                                                {
                                                                        if ((bs_holds & (1<<i)) && (bs_affected & (1<<i)))
                                                                                show_ring(origin, get_option_float(OPTION_RADIUS_MOTION) * RING_SIZE_CONSTANT_MOTION, 1, _, _, _, i)
                                                                }
                                                        }
                                                }
                                        }
                                }
                        }
                }
               
                case NADE_TRIP:
                {
                        if (get_trip_grenade_mode(ent) != TRIP_SCANNING)
                                return HAM_IGNORED

                        entity_set_float(ent, EV_FL_nextthink, get_gametime() + 0.001)
                       
                        if (entity_get_float(ent, EV_FL_fuser4) <= gametime)
                        {
                                new Float:end[3]
                                get_trip_grenade_end_origin(ent, end)
                               
                                if (get_option(OPTION_RESOURCE_USE) == 1)
                                {
                                        if (!get_option(OPTION_TEAM_PLAY) || ((g_zombie_mod & ZM_ZM_ACTIVE) && !(g_zombie_mod & ZM_CAN_THINK)))
                                        {
                                                draw_line_from_entity_broadcast(ent, end, 5, _, _, _)
                                        }
                                        else
                                        {
                                                switch (cl_team[owner])
                                                {
                                                        case CS_TEAM_T:
                                                        {
                                                                draw_line_from_entity_broadcast(ent, end, 5, TEAMTE_RGB_R_COLOR, TEAMTE_RGB_G_COLOR, TEAMTE_RGB_B_COLOR)
                                                        }
                                                        case CS_TEAM_CT:
                                                        {
                                                                draw_line_from_entity_broadcast(ent, end, 5, TEAMCT_RGB_R_COLOR, TEAMCT_RGB_G_COLOR, TEAMCT_RGB_B_COLOR)
                                                        }
                                                        default:
                                                        {
                                                                draw_line_from_entity_broadcast(ent, end, 5, _, _, _)
                                                        }
                                                }
                                        }
                                       
                                        entity_set_float(ent, EV_FL_fuser4, gametime + 0.5)
                                        return HAM_IGNORED
                                }
                               
                                static  Float:first[3], Float:second[3], Float:porigin[3], Float:anglefraction, Float:third[3], Float:fourth[3]
                               
                                xs_vec_sub(origin,end,first)
                               
                                anglefraction = 1.0 - calc_cone_angle_from_distance(xs_vec_len(first))
                               
                                if (xs_vec_len(first) <= SMART_DISTANCE_LINE_PVS)
                                {
                                        get_trip_grenade_middle_origin(ent, first)
                                       
                                        if (!get_option(OPTION_TEAM_PLAY) || ((g_zombie_mod & ZM_ZM_ACTIVE) && !(g_zombie_mod & ZM_CAN_THINK)))
                                        {
                                                draw_line_from_entity(ent, end, 5, _, _, _, 0, first)
                                        }
                                        else
                                        {
                                                switch (cl_team[owner])
                                                {
                                                        case CS_TEAM_T:
                                                        {
                                                                draw_line_from_entity(ent, end, 5, TEAMTE_RGB_R_COLOR, TEAMTE_RGB_G_COLOR, TEAMTE_RGB_B_COLOR, 0, first)
                                                        }
                                                        case CS_TEAM_CT:
                                                        {
                                                                draw_line_from_entity(ent, end, 5, TEAMCT_RGB_R_COLOR, TEAMCT_RGB_G_COLOR, TEAMCT_RGB_B_COLOR, 0, first)
                                                        }
                                                        default:
                                                        {
                                                                draw_line_from_entity(ent, end, 5, _, _, _, 0, first)
                                                        }
                                                }
                                        }
                                       
                                        entity_set_float(ent, EV_FL_fuser4, gametime + 0.5)
                                        return HAM_IGNORED
                                }
                               
                                xs_vec_mul_scalar(first,EXTRALENGTH_VECTOR / xs_vec_len(first),first)
                                xs_vec_sub(end,first,fourth)
                                xs_vec_add(origin,first,first)
                               
                                static players[32],num,id
                                get_players(players,num,"ac")
                               
                                for (new i=0;i<num;i++)
                                {
                                        id = players[i]
                                        entity_get_vector(id, EV_VEC_origin, porigin)
                                       
                                        xs_vec_sub(porigin, fourth, second)
                                        xs_vec_normalize(second, second)
                                       
                                        xs_vec_sub(porigin, first, third)
                                        xs_vec_normalize(third, third)
                                       
                                        xs_vec_sub(first,fourth,first)
                                        xs_vec_normalize(first,first)
                                       
                                        if ( xs_vec_dot(first,second) <= CONE_DROP_ANGLE_COSINUS || (0 - xs_vec_dot(first,third)) <= CONE_DROP_ANGLE_COSINUS )
                                                continue
                                       
                                        if (bs_affected & (1<<id))
                                        {
                                                if ( xs_vec_dot(first, second) >= anglefraction )
                                                {
                                                        if (!get_option(OPTION_TEAM_PLAY) || ((g_zombie_mod & ZM_ZM_ACTIVE) && !(g_zombie_mod & ZM_CAN_THINK)))
                                                        {
                                                                draw_line_from_entity(ent, end, 5, _, _, _, id)
                                                        }
                                                        else
                                                        {
                                                                switch (cl_team[owner])
                                                                {
                                                                        case CS_TEAM_T:
                                                                        {
                                                                                draw_line_from_entity(ent, end, 5, TEAMTE_RGB_R_COLOR, TEAMTE_RGB_G_COLOR, TEAMTE_RGB_B_COLOR, id)
                                                                        }
                                                                        case CS_TEAM_CT:
                                                                        {
                                                                                draw_line_from_entity(ent, end, 5, TEAMCT_RGB_R_COLOR, TEAMCT_RGB_G_COLOR, TEAMCT_RGB_B_COLOR, id)
                                                                        }
                                                                        default:
                                                                        {
                                                                                draw_line_from_entity(ent, end, 5, _, _, _, id)
                                                                        }
                                                                }
                                                        }
                                                }
                                                else
                                                {
                                                        if ( (0 - xs_vec_dot(first, third)) >= anglefraction )
                                                        {
                                                                if (!get_option(OPTION_TEAM_PLAY) || ((g_zombie_mod & ZM_ZM_ACTIVE) && !(g_zombie_mod & ZM_CAN_THINK)))
                                                                {
                                                                        draw_line_from_entity(ent, end, 5, _, _, _, id)
                                                                }
                                                                else if (bs_affected & (1<<id))
                                                                {
                                                                        switch (cl_team[owner])
                                                                        {
                                                                                case CS_TEAM_T:
                                                                                {
                                                                                        draw_line_from_entity(ent, end, 5, TEAMTE_RGB_R_COLOR, TEAMTE_RGB_G_COLOR, TEAMTE_RGB_B_COLOR, id)
                                                                                }
                                                                                case CS_TEAM_CT:
                                                                                {
                                                                                        draw_line_from_entity(ent, end, 5, TEAMCT_RGB_R_COLOR, TEAMCT_RGB_G_COLOR, TEAMCT_RGB_B_COLOR, id)
                                                                                }
                                                                                default:
                                                                                {
                                                                                        draw_line_from_entity(ent, end, 5, _, _, _, id)
                                                                                }
                                                                        }
                                                                }
                                                        }
                                                }
                                        }
                                }
                               
                                entity_set_float(ent, EV_FL_fuser4, gametime + 0.5)
                               
                        }
                }
               
                default : return HAM_IGNORED
        }
       
        return HAM_IGNORED
}

public fw_touch(toucher, touched)
{
        if (!(bs_forward_collection & FWD_TOUCH))
                return HAM_IGNORED
       
        switch (get_grenade_type(toucher))
        {
                case NADE_IMPACT:
                {
                        if (is_solid(touched))
                        {
                                make_explode(toucher)
                               
                                entity_set_float(toucher, EV_FL_nextthink, get_gametime() + 0.001)
                               
                                if (NadeRace:get_grenade_race(toucher) == GRENADE_SMOKEGREN)
                                {
                                        entity_set_int(toucher, EV_INT_flags, entity_get_int(toucher, EV_INT_flags) | FL_ONGROUND)
                                }
                        }
                }
               
                case NADE_TRIP:
                {
                        static classname[10]
                        entity_get_string(touched, EV_SZ_classname, classname, charsmax(classname))
                       
                        if (get_trip_grenade_mode(toucher) > TRIP_NOT_ATTACHED || is_user_connected(touched))
                        {
                                return HAM_IGNORED
                        }
                        else
                        {
                                if (is_solid(touched))
                                {
                                        entity_set_int(toucher, EV_INT_movetype, MOVETYPE_NONE)
                                        set_trip_grenade_mode(toucher, TRIP_ATTACHED)
                                        return (containi(classname, "door") != -1) ? HAM_SUPERCEDE : HAM_IGNORED
                                }
                        }
                }
        }
       
        return HAM_IGNORED
}

public fw_spawn_post(id)
{       
        if (is_user_alive(id))
        {
                cl_is_alive |= (1<<id)
        }
        else
        {
                cl_is_alive &= ~(1<<id)
        }
       
        return HAM_IGNORED
}

public fw_killed_post(id, attacker, gib)
{
        if (is_user_alive(id))
        {
                cl_is_alive |= (1<<id)
        }
        else
        {
                cl_is_alive &= ~(1<<id)
        }
       
        if (!get_option(OPTION_REMOVE_IF_DIES))
                return HAM_IGNORED
       
        mode[id][GRENADE_EXPLOSIVE] = FirstEnabledMode(GRENADE_EXPLOSIVE)
        mode[id][GRENADE_FLASHBANG] = FirstEnabledMode(GRENADE_FLASHBANG)
        mode[id][GRENADE_SMOKEGREN] = FirstEnabledMode(GRENADE_SMOKEGREN)
       
        resetCounter(id)
        removeNades(id)
       
       
        return HAM_IGNORED
}

public fw_takedamage(victim, inflictor, attacker, Float:damage, damagebits)
{
        if (!(bs_forward_collection & FWD_TAKEDAMAGE))
                return HAM_IGNORED
       
        static aclassname[7], iclassname[8]
       
        entity_get_string(attacker,  EV_SZ_classname, aclassname, charsmax(aclassname))
        entity_get_string(inflictor,  EV_SZ_classname, iclassname, charsmax(iclassname))
       
        if ((damagebits & DMG_BLAST))
                return HAM_IGNORED
       
        if (!equal(aclassname, "player") || !equal(iclassname, "grenade"))
                return HAM_IGNORED
       
        if (attacker == victim)
        {
                damage *= (get_option_float(OPTION_DMG_SELF) / 100.0)
        }
        else
        {
                if (cl_team[attacker] == cl_team[victim] && get_option(OPTION_FRIENDLY_FIRE))
                {
                        damage *= 0.02 * get_option_float(OPTION_DMG_TEAMMATES)
                }
        }
       
        static Float:origin[3], Float:user_origin[3], Float:fraction
       
        entity_get_vector(victim, EV_VEC_origin, user_origin)
        entity_get_vector(inflictor, EV_VEC_origin, origin)
        origin[2] += 2.0
        engfunc(EngFunc_TraceLine, user_origin, origin, IGNORE_MONSTERS, victim, g_ptrace[TH_DMG])

        get_tr2(g_ptrace[TH_DMG], TR_flFraction, fraction)
       
        if (fraction < 1.0)
        {
                damage *= (get_option_float(OPTION_DMG_THROUGH_WALL) / 100.0)
        }
       
        if ( get_option(OPTION_DAMAGE_SYSTEM) == 1)
        {
                damage *= get_option_float(OPTION_DMG_NORMAL)
        }
        else
        {
                new type = _:get_grenade_type(inflictor)
                type &= ~NADE_DONT_COUNT
               
                switch ( type )
                {
                        case NADE_NORMAL:
                        {
                                damage *= get_option_float(OPTION_DMG_NORMAL)
                        }
                       
                        case NADE_PROXIMITY:
                        {
                                damage *= get_option_float(OPTION_DMG_PROXIMITY)
                        }
                       
                        case NADE_IMPACT:
                        {
                                damage *= get_option_float(OPTION_DMG_IMPACT)
                        }
                       
                        case NADE_TRIP:
                        {
                                damage *= get_option_float(OPTION_DMG_TRIP)
                        }
                       
                        case NADE_MOTION:
                        {
                                damage *= get_option_float(OPTION_DMG_MOTION)
                        }
                       
                        case NADE_SATCHEL:
                        {
                                damage *= get_option_float(OPTION_DMG_SATCHEL)
                        }
                       
                        case NADE_HOMING:
                        {
                                damage *= get_option_float(OPTION_DMG_HOMING)
                        }
                       
                        default:
                        {
                                damage *= get_option_float(OPTION_DMG_NORMAL)
                        }
                }
        }
       
        SetHamParamFloat(4, damage)
       
        return HAM_HANDLED
}

public fw_monster_takedamage(victim, inflictor, attacker, Float:damage, damagebits)
{
        if (!(bs_forward_collection & FWD_TAKEDAMAGE) || !get_option(OPTION_MONSTERMOD_SUPPORT))
                return HAM_IGNORED
       
        static aclassname[7], iclassname[8]
       
        entity_get_string(attacker,  EV_SZ_classname, aclassname, charsmax(aclassname))
        entity_get_string(inflictor,  EV_SZ_classname, iclassname, charsmax(iclassname))
       
        if ((damagebits & DMG_BLAST))
                return HAM_IGNORED
       
        if (!equal(aclassname, "player") || !equal(iclassname, "grenade"))
                return HAM_IGNORED
       
        static Float:origin[3], Float:user_origin[3], Float:fraction
       
        entity_get_vector(victim, EV_VEC_origin, user_origin)
        entity_get_vector(inflictor, EV_VEC_origin, origin)
        origin[2] += 2.0
        engfunc(EngFunc_TraceLine, user_origin, origin, IGNORE_MONSTERS, victim, g_ptrace[TH_DMG])

        get_tr2(g_ptrace[TH_DMG], TR_flFraction, fraction)
       
        if (fraction < 1.0)
        {
                damage *= (get_option_float(OPTION_DMG_THROUGH_WALL) / 100.0)
        }
       
        if ( get_option(OPTION_DAMAGE_SYSTEM) == 1)
        {
                damage *= get_option_float(OPTION_DMG_NORMAL)
        }
        else
        {
                new type = _:get_grenade_type(inflictor)
                type &= ~NADE_DONT_COUNT
               
                switch ( type )
                {
                        case NADE_NORMAL:
                        {
                                damage *= get_option_float(OPTION_DMG_NORMAL)
                        }
                       
                        case NADE_PROXIMITY:
                        {
                                damage *= get_option_float(OPTION_DMG_PROXIMITY)
                        }
                       
                        case NADE_IMPACT:
                        {
                                damage *= get_option_float(OPTION_DMG_IMPACT)
                        }
                       
                        case NADE_TRIP:
                        {
                                damage *= get_option_float(OPTION_DMG_TRIP)
                        }
                       
                        case NADE_MOTION:
                        {
                                damage *= get_option_float(OPTION_DMG_MOTION)
                        }
                       
                        case NADE_SATCHEL:
                        {
                                damage *= get_option_float(OPTION_DMG_SATCHEL)
                        }
                       
                        case NADE_HOMING:
                        {
                                damage *= get_option_float(OPTION_DMG_HOMING)
                        }
                       
                        default:
                        {
                                damage *= get_option_float(OPTION_DMG_NORMAL)
                        }
                }
        }
       
        SetHamParamFloat(4, damage)
       
        return HAM_HANDLED
}

public fw_grenade_takedamage(grenade, inflictor, attacker, Float:damage, bits)
{
        if (!(bs_forward_collection & FWD_HPSYSTEM))
                return HAM_IGNORED
       
        if (inflictor == grenade)
        {
                SetHamReturnInteger(0)
                return HAM_SUPERCEDE
        }
       
        new Float:health, Float:origin[3], ok = false
        health = entity_get_float(grenade, EV_FL_health)
       
        if (!(1 <= attacker <= g_maxplayers))
                return HAM_SUPERCEDE
       
        if ((entity_get_int(grenade, EV_INT_flags) & FL_GODMODE) || (entity_get_float(grenade, EV_FL_takedamage) == DAMAGE_NO))
                return HAM_SUPERCEDE
       
        entity_get_vector(grenade, EV_VEC_origin, origin)
       
        if (entity_get_edict(grenade, EV_ENT_owner) != attacker && cl_team[entity_get_edict(grenade, EV_ENT_owner)] == cl_team[attacker])
        {
                damage *= get_option_float(OPTION_HITPOINT_FF) / 100.0
                ok = true
        }
       
        new string[8]
        entity_get_string(inflictor, EV_SZ_classname, string, charsmax(string))
       
        if (equal(string,"grenade"))
        {
                damage *= get_option_float(OPTION_HITPOINT_INTER_DMG) / 100.0
                ok = true
        }
       
        play_sound2(grenade, SOUND_HIT[random_num(0,4)])
       
        if (floatcmp(damage,health) != -1)
        {
                static NadeType:type, owner
                owner = entity_get_edict(grenade, EV_ENT_owner)
                type = get_grenade_type(grenade)
                type &= ~NadeType:NADE_DONT_COUNT
               
                if (get_option(OPTION_HITPOINT_DEATH))
                {
                        make_explode(grenade)
                       
                        if (NadeRace:get_grenade_race(grenade) == GRENADE_SMOKEGREN)
                        {
                                entity_set_int(grenade, EV_INT_flags, entity_get_int(grenade, EV_INT_flags) | FL_ONGROUND)
                                dllfunc(DLLFunc_Think, grenade)
                                clear_line(grenade)
                        }
                       
                        return HAM_SUPERCEDE
                }
               
                entity_set_int(grenade, EV_INT_flags, entity_get_int(grenade, EV_INT_flags) | FL_KILLME)
               
                if (!(_:UNCOUNTABLE_NADE_MODES & (1 << (_:type + 1))))
                {       
                        cl_counter[owner][NadeRace:get_grenade_race(grenade)][type] -= 1
                        refresh_can_use_nade(owner, GRENADE_EXPLOSIVE)
                        refresh_can_use_nade(owner, GRENADE_FLASHBANG)
                        refresh_can_use_nade(owner, GRENADE_SMOKEGREN)
                }
               
                if (get_option(OPTION_RESOURCE_USE))
                        metal_gibs(origin)
               
                clear_line(grenade)
               
                return HAM_SUPERCEDE
        }
       
        if (ok)
        {
                SetHamParamFloat(4, damage)
                return HAM_HANDLED
        }
       
        return HAM_IGNORED
}

public fw_traceline(Float:start[3], Float:end[3], conditions, id, trace)
{
        if (!(bs_forward_collection & FWD_HPSYSTEM))
                return FMRES_IGNORED
       
        if (!is_player_alive(id))
                return FMRES_IGNORED
       
        if (cl_weapon[id] != CSW_KNIFE)
                return FMRES_IGNORED
       
        if (pev_valid(get_tr2(trace,TR_pHit)))
                return FMRES_IGNORED
       
        static Float:vec_end[3], i
        i = g_maxplayers
       
        get_tr2(trace, TR_vecEndPos, vec_end)
       
        while ((i = find_ent_in_sphere(i, vec_end, SHOT_SECOND_TEST_RADIUS)))
        {
                if (is_grenade(i, true))
                {
                        static Float:origin[3]
                        pev(i,pev_origin,origin)
                        xs_vec_sub(origin,vec_end,origin)
                        if (xs_vec_len(origin) > SHOT_KNIFE_REAL_RADIUS)
                                continue
                       
                        set_tr2(trace, TR_pHit, i)
                        break
                }
        }
       
        return FMRES_HANDLED
}

public fw_global_traceattack(ent, attacker, Float:damage, Float:direction[3], tracehdl, damagebits)
{
        if (!(bs_forward_collection & FWD_HPSYSTEM))
                return FMRES_IGNORED
       
        if (attacker > g_maxplayers || attacker < 1)
                return HAM_IGNORED
       
        if (cl_weapon[attacker] == CSW_KNIFE)
                return HAM_IGNORED
       
        static Float:origin[3],Float:offs[3]
        pev(attacker,pev_origin,origin)
        pev(attacker,pev_view_ofs,offs)
        xs_vec_add(origin,offs,origin)
       
        static Float:end[3], Float:point[3], Float:origin_nade[3], Float:track[3]
        get_tr2(tracehdl,TR_vecEndPos,end)
       
        xs_vec_sub(end,origin,point)
        xs_vec_mul_scalar(point, SHOT_PENETRATION_DISTANCE / xs_vec_len(point), point)
        xs_vec_add(end, point, end)
       
        static grenade
        static bool:ok
        static bool:reset_queue
       
        grenade = -1
        reset_queue = false
       
        while ((grenade = find_ent_by_class(grenade,"grenade")))
        {
                if (entity_get_float(grenade, EV_FL_dmgtime) < get_gametime())
                        continue
               
                ok = false
                entity_get_vector(grenade, EV_VEC_origin, origin_nade)
               
                for (new i=0;i<SHOT_ENTITY_QUEUE_LENGTH;i++)
                {
                        if (grenade == cl_entity_queue[attacker][i])
                        {
                                cl_entity_queue[attacker][i] = 0;
                                ok = true;
                                reset_queue = true;
                                break;
                        }
                }
               
                if (ok)
                {
                        continue;
                }
               
                engfunc(EngFunc_TraceModel,origin,end,HULL_POINT,grenade,g_ptrace[TH_DMG])
               
                if(get_tr2(g_ptrace[TH_DMG],TR_pHit) == grenade)
                {
                        ExecuteHamB(Ham_TraceAttack, grenade, attacker, damage, direction, g_ptrace[TH_DMG], damagebits)
                       
                        insert_in_queue(attacker, grenade)
                }
                else
                {
                        new times = 1
                       
                        xs_vec_sub(origin_nade, end, track)
                       
                        while (times != SHOT_PENETRATION_READD_TIMES + 1 && xs_vec_len(track) > SHOT_SECOND_TEST_RADIUS)
                        {
                                xs_vec_add(end, point, track)
                               
                                for (new i=1;i<=times;++i)
                                {
                                        xs_vec_add(track, point, track)
                                }
                               
                                xs_vec_sub(origin_nade, track, track)
                               
                                times++;
                        }
                       
                        if ( xs_vec_len(track) <= SHOT_SECOND_TEST_RADIUS )
                        {
                                set_tr2(g_ptrace[TH_DMG], TR_pHit, grenade)
                               
                                xs_vec_add(origin_nade, track, track)
                                set_tr2(g_ptrace[TH_DMG], TR_vecEndPos, track)
                               
                                ExecuteHamB(Ham_TraceAttack, grenade, attacker, (damage / 2), direction, g_ptrace[TH_DMG], damagebits)
                               
                                insert_in_queue(attacker, grenade)
                        }
                }
        }
       
        if (reset_queue)
        {
                for (new i=0;i<SHOT_ENTITY_QUEUE_LENGTH;i++)
                {
                        cl_entity_queue[attacker][i] = 0
                }
        }
       
        return HAM_IGNORED
}

public zp_user_infected_post(id, infector)
{
        g_zombie_mod |= ZM_DO_ALL

        mode[id][GRENADE_EXPLOSIVE] = FirstEnabledMode(GRENADE_EXPLOSIVE)
        mode[id][GRENADE_FLASHBANG] = FirstEnabledMode(GRENADE_FLASHBANG)
        mode[id][GRENADE_SMOKEGREN] = FirstEnabledMode(GRENADE_SMOKEGREN)
       
        resetCounter(id)
        removeNades(id)
       
        return PLUGIN_CONTINUE
}

public event_infect(id, attacker)
{
        g_zombie_mod |= ZM_DO_ALL

        mode[id][GRENADE_EXPLOSIVE] = FirstEnabledMode(GRENADE_EXPLOSIVE)
        mode[id][GRENADE_FLASHBANG] = FirstEnabledMode(GRENADE_FLASHBANG)
        mode[id][GRENADE_SMOKEGREN] = FirstEnabledMode(GRENADE_SMOKEGREN)
       
        resetCounter(id)
        removeNades(id)
       
        return PLUGIN_CONTINUE
}

stock is_nademodes_enabled()
{
        if (get_option(OPTION_ENABLE_NADE_MODES))
        {
                return ((get_option(OPTION_NORMAL_ENABLED)<<0) | (get_option(OPTION_PROXIMITY_ENABLED)<<1) | (get_option(OPTION_IMPACT_ENABLED)<<2) | (get_option(OPTION_TRIP_ENABLED)<<3) | (get_option(OPTION_MOTION_ENABLED)<<4) | (get_option(OPTION_SATCHEL_ENABLED)<<5) | (get_option(OPTION_HOMING_ENABLED)<<6))
        }
       
        return 0
}

stock NadeType:FirstEnabledMode(NadeRace:race)
{
        if (is_mode_cvarenabled(g_firstenabledmode[race], race))
                return g_firstenabledmode[race]
       
        for (new NadeType:i=NADE_NORMAL;i<=NADE_HOMING;i++)
        {
                if (is_mode_cvarenabled(i, race))
                {
                        g_firstenabledmode[race] = i
                        return i
                }
        }
       
        return NADE_NORMAL
}

public is_mode_cvarenabled(NadeType:type, NadeRace:nade)
{
        switch (type)
        {
                case NADE_NORMAL:
                {
                        return get_option(OPTION_NORMAL_ENABLED)
                }
               
                case NADE_PROXIMITY:
                {
                        return get_option(OPTION_PROXIMITY_ENABLED)
                }
               
                case NADE_IMPACT:
                {
                        return get_option(OPTION_IMPACT_ENABLED)
                }
               
                case NADE_TRIP:
                {
                        return get_option(OPTION_TRIP_ENABLED)
                }
               
                case NADE_MOTION:
                {
                        return get_option(OPTION_MOTION_ENABLED)
                }
               
                case NADE_SATCHEL:
                {
                        return get_option(OPTION_SATCHEL_ENABLED)
                }
               
                case NADE_HOMING:
                {
                        return get_option(OPTION_HOMING_ENABLED)
                }
        }
       
        return 0
}

public is_mode_enabled(id, NadeType:type, NadeRace:nade)
{
        switch (type)
        {
                case NADE_NORMAL:
                {
                        return get_option(OPTION_NORMAL_ENABLED)
                }
               
                case NADE_PROXIMITY:
                {
                        if (!get_option(OPTION_PROXIMITY_ENABLED))
                                return 0
                       
                        if (!get_option(OPTION_LIMIT_SYSTEM))
                                return 1
                       
                        if (!get_option(OPTION_LIMIT_PROXIMITY))
                                return 1
                       
                        if (get_option(OPTION_LIMIT_SYSTEM) == 1 && cl_counter[id][nade][type] < get_option(OPTION_LIMIT_PROXIMITY))
                                return 1
                       
                        if (get_option(OPTION_LIMIT_SYSTEM) == 2 && (cl_counter[id][GRENADE_EXPLOSIVE][type] + cl_counter[id][GRENADE_SMOKEGREN][type] + cl_counter[id][GRENADE_FLASHBANG][type]) < get_option(OPTION_LIMIT_PROXIMITY))
                                return 1
                       
                        return 0
                }
               
                case NADE_IMPACT:
                {
                        return get_option(OPTION_IMPACT_ENABLED)
                }
               
                case NADE_TRIP:
                {
                        if (!get_option(OPTION_TRIP_ENABLED))
                                return 0
                       
                        if (!get_option(OPTION_LIMIT_SYSTEM))
                                return 1
                       
                        if (!get_option(OPTION_LIMIT_TRIP))
                                return 1
                       
                        if (get_option(OPTION_LIMIT_SYSTEM) == 1 && cl_counter[id][nade][type] < get_option(OPTION_LIMIT_TRIP))
                                return 1
                       
                        if (get_option(OPTION_LIMIT_SYSTEM) == 2 && (cl_counter[id][GRENADE_EXPLOSIVE][type] + cl_counter[id][GRENADE_SMOKEGREN][type] + cl_counter[id][GRENADE_FLASHBANG][type]) < get_option(OPTION_LIMIT_TRIP))
                                return 1
                       
                        return 0
                }
               
                case NADE_MOTION:
                {
                        if (!get_option(OPTION_MOTION_ENABLED))
                                return 0
                       
                        if (!get_option(OPTION_LIMIT_SYSTEM))
                                return 1
                       
                        if (!get_option(OPTION_LIMIT_MOTION))
                                return 1
                       
                        if (get_option(OPTION_LIMIT_SYSTEM) == 1 && cl_counter[id][nade][type] < get_option(OPTION_LIMIT_MOTION))
                                return 1
                       
                        if (get_option(OPTION_LIMIT_SYSTEM) == 2 && (cl_counter[id][GRENADE_EXPLOSIVE][type] + cl_counter[id][GRENADE_SMOKEGREN][type] + cl_counter[id][GRENADE_FLASHBANG][type]) < get_option(OPTION_LIMIT_MOTION))
                                return 1
                       
                        return 0
                }
               
                case NADE_SATCHEL:
                {
                        if (!get_option(OPTION_SATCHEL_ENABLED))
                                return 0
                       
                        if (!get_option(OPTION_LIMIT_SYSTEM))
                                return 1
                       
                        if (!get_option(OPTION_LIMIT_SATCHEL))
                                return 1
                       
                        if (get_option(OPTION_LIMIT_SYSTEM) == 1 && cl_counter[id][nade][type] < get_option(OPTION_LIMIT_SATCHEL))
                                return 1
                       
                        if (get_option(OPTION_LIMIT_SYSTEM) == 2 && (cl_counter[id][GRENADE_EXPLOSIVE][type] + cl_counter[id][GRENADE_SMOKEGREN][type] + cl_counter[id][GRENADE_FLASHBANG][type]) < get_option(OPTION_LIMIT_SATCHEL))
                                return 1
                       
                        return 0
                }
               
                case NADE_HOMING:
                {
                        return get_option(OPTION_HOMING_ENABLED)
                }
        }
       
        return 1
}

public get_enabled_modes(id, NadeRace:nade)
{
        for (new NadeType:type = NADE_NORMAL; type <= NADE_HOMING; type = type + NADE_PROXIMITY)
        {
                if        (is_mode_enabled(id, type, nade))
                        return 1
        }
       
        return 0;
}


public changemode(id, NadeRace:NADE_TYPE)
{
        if (!(grenade_can_be_used(NADE_TYPE)))
        {
                return
        }
       
        if (!is_mode_enabled(id, ++mode[id][NADE_TYPE], NADE_TYPE))
        {
                changemode(id, NADE_TYPE)
                return
        }
       
        switch (mode[id][NADE_TYPE])
        {
                case NADE_NORMAL:
                {
                        client_print(id, print_center, "Mode - Normal")
                }
               
                case NADE_PROXIMITY:
                {
                        client_print(id, print_center, "Mode - Proximity")
                }
               
                case NADE_IMPACT:
                {
                        client_print(id, print_center, "Mode - Impact")
                }
               
                case NADE_TRIP:
                {
                        client_print(id, print_center, "Mode - Trip laser")
                }
               
                case NADE_MOTION:
                {
                        client_print(id, print_center, "Mode - Motion sensor")
                }
               
                case NADE_SATCHEL:
                {
                        client_print(id, print_center, "Mode - Satchel charge")
                }
               
                case NADE_HOMING:
                {
                        client_print(id, print_center, "Mode - Homing")
                }
               
                default:
                {
                        mode[id][NADE_TYPE] = NADE_DUD
                        changemode(id, NADE_TYPE)
                }
        }
}

resetCounter(id)
{
        cl_counter[id][GRENADE_EXPLOSIVE][NADE_MOTION] = 0
        cl_counter[id][GRENADE_EXPLOSIVE][NADE_PROXIMITY] = 0
        cl_counter[id][GRENADE_EXPLOSIVE][NADE_TRIP] = 0
        cl_counter[id][GRENADE_EXPLOSIVE][NADE_SATCHEL] = 0
        cl_counter[id][GRENADE_FLASHBANG][NADE_MOTION] = 0
        cl_counter[id][GRENADE_FLASHBANG][NADE_PROXIMITY] = 0
        cl_counter[id][GRENADE_FLASHBANG][NADE_TRIP] = 0
        cl_counter[id][GRENADE_FLASHBANG][NADE_SATCHEL] = 0
        cl_counter[id][GRENADE_SMOKEGREN][NADE_MOTION] = 0
        cl_counter[id][GRENADE_SMOKEGREN][NADE_PROXIMITY] = 0
        cl_counter[id][GRENADE_SMOKEGREN][NADE_TRIP] = 0
        cl_counter[id][GRENADE_SMOKEGREN][NADE_SATCHEL] = 0
       
        cl_can_use_nade[GRENADE_EXPLOSIVE] |= (1<<id)
        cl_can_use_nade[GRENADE_FLASHBANG] |= (1<<id)
        cl_can_use_nade[GRENADE_SMOKEGREN] |= (1<<id)
       
        return
}

removeNades(id)
{
        static ent
        ent = -1

        while ((ent = find_ent_by_class(ent, "grenade")))
        {
                if (entity_get_edict(ent, EV_ENT_owner) != id)
                        continue

                if(is_grenade(ent) && get_grenade_type(ent) != NADE_NORMAL)
                        entity_set_int(ent, EV_INT_flags , entity_get_int(ent, EV_INT_flags) | FL_KILLME)
        }       
       
        return
}

is_grenade(ent, bool:enforce = false)
{
        if (!is_valid_ent(ent))
        {
                return 0
        }
       
        if (enforce)
        {
                if (!is_classname(ent, "grenade"))
                        return 0
        }
       
        if (is_grenade_c4(ent))
                return 0
       
        static weapon_id
        weapon_id = cs_get_weapon_id(ent)
       
        for (new i=0;i<3;i++)
        {
                if (weapon_id == NADE_WPID[NadeRace:i])
                        return 1
        }
       
        return 0
}

is_classname(ent, const string[])
{
        new classname[20]
       
        entity_get_string(ent, EV_SZ_classname, classname, charsmax(classname))
       
        return equali(string, classname, strlen(string))
}

public get_grenade_race(grenade)
{
        switch (cs_get_weapon_id(grenade))
        {
                case CSW_HEGRENADE:        return _:GRENADE_EXPLOSIVE
                case CSW_FLASHBANG:        return _:GRENADE_FLASHBANG
                case CSW_SMOKEGRENADE:        return _:GRENADE_SMOKEGREN
        }
       
        return -1
}

set_grenade_type(grenade, NadeType:g_type, bool:property = true)
{
        if (!is_valid_ent(grenade)) return
       
        static NadeRace:nade
        static owner
       
        owner = entity_get_edict(grenade, EV_ENT_owner)
       
        nade = NadeRace:get_grenade_race(grenade)
       
        if (g_FW_property > 0 && g_type != NADE_DUD)
        {
                new ret
                ExecuteForward(g_FW_property, ret, grenade, g_type)
               
                if (ret > PLUGIN_CONTINUE)
                {
                        if (g_PFW_property > 0)
                                ExecuteForward(g_PFW_property, ret, grenade, g_type, 1)
                       
                        return
                }
               
                if (g_PFW_property > 0)
                        ExecuteForward(g_PFW_property, ret, grenade, g_type, 0)
        }

        entity_set_int(grenade, EV_INT_iuser1, _:g_type)
        entity_set_int(grenade, EV_INT_iuser2, 0)
        entity_set_int(grenade, EV_INT_iuser3, 0)
        entity_set_int(grenade, EV_INT_iuser4, 0)
       
        entity_set_vector(grenade, EV_VEC_vuser1, Float:{0.0, 0.0, 0.0})
        entity_set_vector(grenade, EV_VEC_vuser2, Float:{0.0, 0.0, 0.0})
        entity_set_vector(grenade, EV_VEC_vuser3, Float:{0.0, 0.0, 0.0})
        entity_set_vector(grenade, EV_VEC_vuser4, Float:{0.0, 0.0, 0.0})
       
        if (property == true)
        {
                switch (g_type)
                {
                        case NADE_DUD:
                        {
                                entity_set_int(grenade, EV_INT_movetype, MOVETYPE_BOUNCE)
                                entity_set_vector(grenade, EV_VEC_velocity, Float:{0.0, 0.0, 0.0})
                        }
                       
                        case NADE_NORMAL:
                        {
                                entity_set_float(grenade, EV_FL_health, floatabs(get_option_float(OPTION_HITPOINT_NORMAL)))
                               
                                if (get_option(OPTION_MATERIAL_SYSTEM) == 2 && get_option(OPTION_HITPOINT_NORMAL))
                                {
                                        entity_set_float(grenade, EV_FL_takedamage, DAMAGE_YES)
                                }
                        }
                       
                        case NADE_PROXIMITY:
                        {
                                delay_explosion(grenade)
                                set_grenade_allow_explode(grenade, get_option_float(OPTION_ARM_TIME_PROXIMITY))
                               
                                entity_set_float(grenade, EV_FL_health, floatabs(get_option_float(OPTION_HITPOINT_PROXIMITY)))
                               
                                if (get_option(OPTION_MATERIAL_SYSTEM) == 2 && get_option(OPTION_HITPOINT_PROXIMITY))
                                {
                                        entity_set_float(grenade, EV_FL_takedamage, DAMAGE_YES)
                                }
                               
                                cl_counter[owner][nade][NADE_PROXIMITY] += 1
                               
                                refresh_can_use_nade(owner, GRENADE_EXPLOSIVE)
                                refresh_can_use_nade(owner, GRENADE_FLASHBANG)
                                refresh_can_use_nade(owner, GRENADE_SMOKEGREN)
                        }
                       
                        case NADE_IMPACT:
                        {
                                delay_explosion(grenade)
                                entity_set_int(grenade, EV_INT_movetype, MOVETYPE_BOUNCE)
                               
                                entity_set_float(grenade, EV_FL_health, floatabs(get_option_float(OPTION_HITPOINT_IMPACT)))
                               
                                if (get_option(OPTION_MATERIAL_SYSTEM) == 2 && get_option(OPTION_HITPOINT_IMPACT))
                                {
                                        entity_set_float(grenade, EV_FL_takedamage, DAMAGE_YES)
                                }
                        }
                       
                        case NADE_TRIP:
                        {
                                delay_explosion(grenade)
                               
                                entity_set_float(grenade, EV_FL_health, floatabs(get_option_float(OPTION_HITPOINT_TRIP)))
                               
                                if (get_option(OPTION_MATERIAL_SYSTEM) == 2 && get_option(OPTION_HITPOINT_TRIP))
                                {
                                        entity_set_float(grenade, EV_FL_takedamage, DAMAGE_YES)
                                }
                               
                                cl_counter[owner][nade][NADE_TRIP] += 1
                               
                                refresh_can_use_nade(owner, GRENADE_EXPLOSIVE)
                                refresh_can_use_nade(owner, GRENADE_FLASHBANG)
                                refresh_can_use_nade(owner, GRENADE_SMOKEGREN)
                        }
                       
                        case NADE_MOTION:
                        {
                                delay_explosion(grenade)
                                set_grenade_allow_explode(grenade, get_option_float(OPTION_ARM_TIME_MOTION))
                               
                                entity_set_float(grenade, EV_FL_health, floatabs(get_option_float(OPTION_HITPOINT_MOTION)))
                               
                                if (get_option(OPTION_MATERIAL_SYSTEM) == 2 && get_option(OPTION_HITPOINT_MOTION))
                                {
                                        entity_set_float(grenade, EV_FL_takedamage, DAMAGE_YES)
                                }
                               
                                cl_counter[owner][nade][NADE_MOTION] += 1
                               
                                refresh_can_use_nade(owner, GRENADE_EXPLOSIVE)
                                refresh_can_use_nade(owner, GRENADE_FLASHBANG)
                                refresh_can_use_nade(owner, GRENADE_SMOKEGREN)
                        }
                       
                        case NADE_SATCHEL:
                        {
                                delay_explosion(grenade)
                                set_grenade_allow_explode(grenade,  get_option_float(OPTION_ARM_TIME_SATCHEL))
                               
                                entity_set_float(grenade, EV_FL_health, floatabs(get_option_float(OPTION_HITPOINT_SATCHEL)))
                               
                                if (get_option(OPTION_MATERIAL_SYSTEM) == 2 && get_option(OPTION_HITPOINT_SATCHEL))
                                {
                                        entity_set_float(grenade, EV_FL_takedamage, DAMAGE_YES)
                                }
                               
                                cl_counter[owner][nade][NADE_SATCHEL] += 1
                               
                                refresh_can_use_nade(owner, GRENADE_EXPLOSIVE)
                                refresh_can_use_nade(owner, GRENADE_FLASHBANG)
                                refresh_can_use_nade(owner, GRENADE_SMOKEGREN)
                        }
                       
                        case NADE_HOMING:
                        {
                                entity_set_float(grenade, EV_FL_dmgtime, entity_get_float(grenade, EV_FL_dmgtime) + get_option_float(OPTION_HOMING_EXTRATIME))
                               
                                entity_set_float(grenade, EV_FL_health, floatabs(get_option_float(OPTION_HITPOINT_HOMING)))
                               
                                if (get_option(OPTION_MATERIAL_SYSTEM) == 2 && get_option(OPTION_HITPOINT_HOMING))
                                {
                                        entity_set_float(grenade, EV_FL_takedamage, DAMAGE_YES)
                                }
                        }
                }
        }
}



public get_trip_grenade_react_method(grenade)
{
        new NadeRace:grenade_race = NadeRace:get_grenade_race(grenade)
       
        switch (grenade_race)
        {
                case GRENADE_EXPLOSIVE: return get_option(OPTION_REACT_TRIP_G)
                case GRENADE_FLASHBANG: return get_option(OPTION_REACT_TRIP_F)
                case GRENADE_SMOKEGREN: return get_option(OPTION_REACT_TRIP_S)
        }
       
        return -1
}

public bool:is_ent_monster(ent)
{
        if (!pev_valid(ent))
                return false
       
        if (!is_classname(ent, "func_wall"))
                return false
       
        return !!(pev(ent, pev_flags) & FL_MONSTER)
}

public bool:is_solid(ent)
{
        return ( ent ? ( (entity_get_int(ent, EV_INT_solid) > SOLID_TRIGGER) ? true : false ) : true )
}

public bool:is_attachable_surface(entity)
{
        static Float:velocity[3]
       
        if (is_valid_ent(entity))
        {
                if (!is_solid(entity)) return false                                                                        // This is for func_breakables. The entity technically exists, but isn't solid.
                entity_get_vector(entity, EV_VEC_velocity, velocity)                                        // This is for func_doors. The grenade touches the door, causing it to move.
                return (xs_vec_equal(velocity, Float:{0.0, 0.0, 0.0}) ? true : false)
        }
       
        return true
}

public bool:is_in_los(grenade_ent, player)
{
        static Float:start[3], Float:end[3]
        entity_get_vector(grenade_ent, EV_VEC_origin, start)
        entity_get_vector(player, EV_VEC_origin, end)
       
        start[2] += 2.0
       
        engfunc(EngFunc_TraceLine, start, end, IGNORE_MONSTERS, grenade_ent, g_ptrace[TH_LOS])
       
        static Float:dist
        get_tr2(g_ptrace[TH_LOS], TR_flFraction, dist)
       
        return ((dist == 1.0) ? true : false)
}

stock Float:calc_cone_angle_from_distance(Float:distance)
{
        static Float:A,Float:B;

        if (A == 0.0 && B == 0.0)
        {
                if (CONE_BASE_RADIUS == 0.0)
                {
                        A = ((CONE_CALC_DISTANCE_MIN-CONE_CALC_DISTANCE_MAX)*floattan(CONE_CALC_ANGLE_MAX, degrees)*floattan(CONE_CALC_ANGLE_MIN, degrees))/(floattan(CONE_CALC_ANGLE_MAX, degrees)-floattan(CONE_CALC_ANGLE_MIN, degrees))
                        B = (CONE_CALC_DISTANCE_MAX*floattan(CONE_CALC_ANGLE_MAX, degrees) - CONE_CALC_DISTANCE_MIN*floattan(CONE_CALC_ANGLE_MIN, degrees))/(floattan(CONE_CALC_ANGLE_MAX, degrees)-floattan(CONE_CALC_ANGLE_MIN, degrees))
                }
                else
                {
                        A = CONE_BASE_RADIUS;
                        B = CONE_CALC_DISTANCE_MAX - CONE_BASE_RADIUS/floattan(CONE_CALC_ANGLE_MAX, degrees)
                }
        }
       
        return (distance < CONE_CALC_DISTANCE_MAX) ? floatatan(A/((CONE_CALC_DISTANCE_MIN)-B), radian) : floatatan(A/((distance)-B), radian)
}

public insert_in_queue(id, ent_id)
{
        for (new i=0;i<SHOT_ENTITY_QUEUE_LENGTH;i++)
        {
                if (cl_entity_queue[id][i] == 0)
                {
                        cl_entity_queue[id][i] = ent_id
                        break;
                }
               
                if (i == SHOT_ENTITY_QUEUE_LENGTH - 1)
                {
                        server_print("[NDM] Error! Unable to save so much entities!")
                        server_print("[NDM] Increase the value of the ^"SHOT_ENTITY_QUEUE_LENGTH^" define and recompile!")
                        log_amx("[NDM] Error! Unable to save so much entities")
                        log_amx("[NDM] Increase the value of the ^"SHOT_ENTITY_QUEUE_LENGTH^" define and recompile!")
                }
        }
}

draw_line_from_entity(entid, Float:end[3], staytime, R = NOTEAM_RGB_R_COLOR, G = NOTEAM_RGB_G_COLOR, B = NOTEAM_RGB_B_COLOR, id = 0, Float:pvs[3] = {0.0, 0.0, 0.0})
{
        ( id == 0 ) ? engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, pvs, 0) : engfunc(EngFunc_MessageBegin, get_option(OPTION_MSG_SVC_BAD) ? MSG_ONE : MSG_ONE_UNRELIABLE, SVC_TEMPENTITY, pvs, id)
        write_byte(TE_BEAMENTPOINT)
        write_short(entid)        // start entity
        engfunc(EngFunc_WriteCoord, end[0])
        engfunc(EngFunc_WriteCoord, end[1])
        engfunc(EngFunc_WriteCoord, end[2])
        write_short(beampoint)
        write_byte(0)
        write_byte(0)
        write_byte(staytime)
        write_byte(10)
        write_byte(0)
        write_byte(R)
        write_byte(G)
        write_byte(B)
        write_byte(127)
        write_byte(1)
        message_end()       
}

stock draw_line(Float:start[3], Float:end[3], staytime, R = NOTEAM_RGB_R_COLOR, G = NOTEAM_RGB_G_COLOR, B = NOTEAM_RGB_B_COLOR)
{
        engfunc(EngFunc_MessageBegin, MSG_ALL, SVC_TEMPENTITY, Float:{0.0,0.0,0.0}, 0)
        write_byte(TE_BEAMPOINTS)
        engfunc(EngFunc_WriteCoord, start[0])
        engfunc(EngFunc_WriteCoord, start[1])
        engfunc(EngFunc_WriteCoord, start[2])
        engfunc(EngFunc_WriteCoord, end[0])
        engfunc(EngFunc_WriteCoord, end[1])
        engfunc(EngFunc_WriteCoord, end[2])
        write_short(beampoint)
        write_byte(0)
        write_byte(0)
        write_byte(staytime)
        write_byte(10)
        write_byte(0)
        write_byte(R)
        write_byte(G)
        write_byte(B)
        write_byte(127)
        write_byte(1)
        message_end()       
}

draw_line_from_entity_broadcast(entid, Float:end[3], staytime, R = NOTEAM_RGB_R_COLOR, G = NOTEAM_RGB_G_COLOR, B = NOTEAM_RGB_B_COLOR)
{
        engfunc(EngFunc_MessageBegin, get_option(OPTION_MSG_SVC_BAD) ? MSG_ALL : MSG_BROADCAST, SVC_TEMPENTITY, {0.0, 0.0, 0.0}, 0)
        write_byte(TE_BEAMENTPOINT)
        write_short(entid)        // start entity
        engfunc(EngFunc_WriteCoord, end[0])
        engfunc(EngFunc_WriteCoord, end[1])
        engfunc(EngFunc_WriteCoord, end[2])
        write_short(beampoint)
        write_byte(0)
        write_byte(0)
        write_byte(staytime)
        write_byte(10)
        write_byte(0)
        write_byte(R)
        write_byte(G)
        write_byte(B)
        write_byte(127)
        write_byte(1)
        message_end()       
}

clear_line(entid)
{
        message_begin(MSG_ALL, SVC_TEMPENTITY)
        write_byte(TE_KILLBEAM)
        write_short(entid)
        message_end()
}

show_ring(Float:origin[3], Float:addict, staytime, R = NOTEAM_RGB_R_COLOR, G = NOTEAM_RGB_G_COLOR, B = NOTEAM_RGB_B_COLOR , id = 0)
{
        ( id == 0 ) ? engfunc(EngFunc_MessageBegin, get_option(OPTION_MSG_SVC_BAD) ? MSG_ALL : MSG_BROADCAST, SVC_TEMPENTITY, {0.0, 0.0, 0.0}, 0) : engfunc(EngFunc_MessageBegin, get_option(OPTION_MSG_SVC_BAD) ? MSG_ONE : MSG_ONE_UNRELIABLE , SVC_TEMPENTITY, {0.0, 0.0, 0.0}, id)
        write_byte(TE_BEAMCYLINDER)                                                                                                          // TE_BEAMCYLINDER
        engfunc(EngFunc_WriteCoord, origin[0])                                                                                // start X
        engfunc(EngFunc_WriteCoord, origin[1])                                                                                // start Y
        engfunc(EngFunc_WriteCoord, origin[2])                                                                                // start Z
        engfunc(EngFunc_WriteCoord, origin[0])                                                                                // something X
        engfunc(EngFunc_WriteCoord, origin[1])                                                                                // something Y
        engfunc(EngFunc_WriteCoord, origin[2] + addict)                                                                // something Z
        write_short(shockwave)                                                                                                                  // sprite
        write_byte(0)                                                                                                                                  // startframe
        write_byte(0)                                                                                                                                  // framerate
        write_byte(staytime)                                                                                                                  // life
        write_byte(60)                                                                                                                                  // width
        write_byte(0)                                                                                                                                  // noise
        write_byte(R)                                                                                                                                  // red
        write_byte(G)                                                                                                                                  // green
        write_byte(B)                                                                                                                                  // blue
        write_byte(100)                                                                                                                          // brightness
        write_byte(0)                                                                                                                                // speed
        message_end()
}

metal_gibs(const Float: origin[3])
{
        message_begin(get_option(OPTION_MSG_SVC_BAD) ? MSG_ALL : MSG_BROADCAST, SVC_TEMPENTITY, {0, 0, 0}, 0)
        write_byte(TE_BREAKMODEL)                                                                                                          // TE_BREAKMODEL
        engfunc(EngFunc_WriteCoord,origin[0])                                                                                  // x
        engfunc(EngFunc_WriteCoord,origin[1])                                                                                  // y
        engfunc(EngFunc_WriteCoord,origin[2] + 24)                                                                          // z
        engfunc(EngFunc_WriteCoord,20.0)                                                                                        // size x
        engfunc(EngFunc_WriteCoord,20.0)                                                                                          // size y
        engfunc(EngFunc_WriteCoord,20.0)                                                                                        // size z
        engfunc(EngFunc_WriteCoord,random_num(-50,50))                                                                  // velocity x
        engfunc(EngFunc_WriteCoord,random_num(-50,50))                                                                // velocity y
        engfunc(EngFunc_WriteCoord,25.0)                                                                                          // velocity z
        write_byte(10)                                                                                                                                // random velocity
        write_short(nadebits)                                                                                                                  // model
        write_byte(10)                                                                                                                                  // count
        write_byte(25)                                                                                                                                  // life
        write_byte(2)                                                                                                                                  // flags: BREAK_METAL
        message_end()
}


RaZ_HU 05-13-2015 16:15

Re: [Error] register_option
 
Well, the whole code is messed up and important parts are missing.

What was the reason you edited the plugin?

fysiks 05-13-2015 20:18

Re: [Error] register_option
 
If you have issues with a plugin, post in that plugin's own thread.


All times are GMT -4. The time now is 20:16.

Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.