#include <amxmodx>
#include <fm_cstrike>
#include <fun>
#define get_bit(%1,%2) (%1 & (1 << (%2 & 31)))
#define set_bit(%1,%2) %1 |= (1 << (%2 & 31))
#define clr_bit(%1,%2) %1 &= ~(1 << (%2 & 31))
#define inv_bit(%1,%2) %1 ^= (1 << (%2 & 31))
#define is_valid_client(%0) ((0 < (%0) <= max_players) && get_bit(ingame, %0))
#define is_teams_equal(%0,%1) (get_user_team(%0) == get_user_team(%1))
#define get_bpammo(%0,%1) get_pdata_int(%0, _CSW_to_offset[%1], 5)
#define set_bpammo(%0,%1,%2) set_pdata_int(%0, _CSW_to_offset[%1], %2, 5)
#define get_owner(%0) get_pdata_cbase(%0, 41, 4)
#define WRITE_COORD(%0) engfunc(EngFunc_WriteCoord,%0[0]);engfunc(EngFunc_WriteCoord, %0[1]); engfunc(EngFunc_WriteCoord, %0[2])
#define UTIL_RemoveEntity(%0) set_pev(%0, pev_flags, FL_KILLME);set_pev(%0, pev_targetname, "")
#define is_health_grenade(%0) (pev(%0, pev_iuser2) == CSW_HEALTH_GRENADE)
const MAX_CLIENTS = 32;
const POST = 1;
const CSW_HEALTH_GRENADE = 76263;
enum
{
GRENADE_RADIUS = 250.0,
GRENADE_HEALTH = 100,
GRENADE_MAXHEALTH = 100,
GRENADE_FLAG = ADMIN_LEVEL_H,
GRENADE_COLORFADE_RED = 0,
GRENADE_COLORFADE_GREEN = 255,
GRENADE_COLORFADE_BLUE = 0,
GRENADE_RENDER_COLOR_RED = 124.0,
GRENADE_RENDER_COLOR_GREEN = 252.0,
GRENADE_RENDER_COLOR_BLUE = 0.0
}
enum
{
GIBS_COUNT = 35,
GIBS_LIFE_MIN = 15,
GIBS_LIFE_MAX = 25,
GIBS_SCALE = 2
}
enum _: model_type
{
VIEWPORT,
PLAYER,
WEAPONBOX
}
new const HEALTH_GRENADE_MODEL[model_type][] = {
"models/v_health_grenade.mdl",
"models/p_health_grenade.mdl",
"models/w_health_grenade.mdl"
};
enum _: sprites
{
GIBS_RED,
GIBS_GREEN,
GIBS_BLUE,
HEAL
}
new const HEALTH_GRENADE_SPRITE[sprites][] = {
"sprites/red.spr",
"sprites/green.spr",
"sprites/blue.spr",
"sprites/heal_effect.spr"
};
new const SOUND_EXPLODE[] = "health_grenade_explosion.wav";
new max_players, ingame, need_auto_eqip, gmsgScreenFade, sprite_index[sprites], have_health_grenade;
public plugin_init()
{
register_plugin("Health Grenade", "1.1", "Autor");
RegisterHam(Ham_Spawn, "player", "player_Spawn_Post", POST);
RegisterHam(Ham_Touch, "grenade", "fw_TouchGrenade");
RegisterHam(Ham_Item_Deploy, "weapon_smokegrenade", "smokegrenade_Deploy_Post", POST);
gmsgScreenFade = get_user_msgid("ScreenFade");
max_players = get_maxplayers();
}
public plugin_natives()
{
register_native("give_health_grenade", "_give_health_grenade", 1);
register_native("get_hg_auto_equip_status", "_get_hg_auto_equip_status", 1);
register_native("set_hg_auto_equip_status", "_set_hg_auto_equip_status", 1);
}
public _give_health_grenade(id)
{
give_health_grenade(id);
}
public _get_hg_auto_equip_status(id)
{
return get_bit(need_auto_eqip, id) ? 1 : 0;
}
public _set_hg_auto_equip_status(id, new_status)
{
if (new_status) {
set_bit(need_auto_eqip, id);
}
else {
clr_bit(need_auto_eqip, id);
}
}
public plugin_precache()
{
new i, error_index = -1;
for (; i < sizeof HEALTH_GRENADE_MODEL; i++) {
if (file_exists(HEALTH_GRENADE_MODEL[i])) {
precache_model(HEALTH_GRENADE_MODEL[i]);
}
else {
error_index = i;
break;
}
}
if (error_index == -1) {
log_amx("[OK] All models precached successfully");
}
else {
log_amx("[:(] Error opening ^"%s^" file", HEALTH_GRENADE_MODEL[i]);
pause("ad");
}
i = 0;
error_index = -1;
for(; i < sizeof HEALTH_GRENADE_SPRITE; i++) {
if (file_exists(HEALTH_GRENADE_SPRITE[i])) {
sprite_index[i] = precache_model(HEALTH_GRENADE_SPRITE[i]);
}
else {
error_index = i;
break;
}
}
if (error_index == -1) {
log_amx("[OK] All sprites precached successfully");
}
else {
log_amx("[:(] Error opening ^"%s^" file", HEALTH_GRENADE_SPRITE[i]);
pause("ad");
}
precache_sound(SOUND_EXPLODE);
}
public client_putinserver(id)
{
set_bit(ingame, id);
clr_bit(have_health_grenade, id);
set_bit(need_auto_eqip, id);
}
public client_disconnect(id)
{
clr_bit(ingame, id);
}
public player_Spawn_Post(id)
{
if (!is_user_alive(id)) {
return;
}
if (get_bit(need_auto_eqip, id) && get_user_flags(id) & GRENADE_FLAG) {
give_health_grenade(id);
}
}
give_health_grenade(id)
{
if (user_has_weapon(id, CSW_SMOKEGRENADE)) {
set_bpammo(id, CSW_SMOKEGRENADE, get_bpammo(id, CSW_SMOKEGRENADE) + 1);
}
else {
give_item(id, "weapon_smokegrenade");
}
set_bit(have_health_grenade, id);
}
public smokegrenade_Deploy_Post(entity)
{
static owner; owner = get_owner(entity);
if (is_valid_client(owner) && get_bit(have_health_grenade, owner)) {
set_pev(owner, pev_viewmodel2 , HEALTH_GRENADE_MODEL[VIEWPORT]);
set_pev(owner, pev_weaponmodel2, HEALTH_GRENADE_MODEL[PLAYER]);
}
return HAM_IGNORED;
}
public grenade_throw(id, grenade_entity, weaponid)
{
if (weaponid == CSW_SMOKEGRENADE && get_bit(have_health_grenade, id)) {
set_pev(grenade_entity, pev_renderfx, kRenderFxGlowShell);
set_pev(grenade_entity, pev_rendercolor, Float: {GRENADE_RENDER_COLOR_RED, GRENADE_RENDER_COLOR_GREEN, GRENADE_RENDER_COLOR_BLUE});
set_pev(grenade_entity, pev_rendermode, kRenderNormal);
set_pev(grenade_entity, pev_renderamt, 25.0);
engfunc(EngFunc_SetModel, grenade_entity, HEALTH_GRENADE_MODEL[WEAPONBOX]);
set_pev(grenade_entity, pev_iuser2, CSW_HEALTH_GRENADE);
clr_bit(have_health_grenade, id);
}
}
public fw_TouchGrenade(entity, toucher)
{
if (is_health_grenade(entity) && (pev_valid(entity) != 2 || pev(toucher, pev_solid) > SOLID_TRIGGER)) {
grenade_explode(entity);
}
}
public grenade_explode(grenade_entity)
{
static grenade_owner, victim, Float: grenade_origin[3], Float: origin[3];
grenade_owner = pev(grenade_entity, pev_owner);
if (is_valid_client(grenade_owner)) {
pev(grenade_entity, pev_origin, grenade_origin);
make_gibs(grenade_origin);
emit_sound(grenade_entity, CHAN_ITEM, SOUND_EXPLODE, VOL_NORM, ATTN_NORM, 0, PITCH_NORM);
victim = -1;
while ((victim = engfunc( EngFunc_FindEntityInSphere, victim, grenade_origin, GRENADE_RADIUS)) != 0) {
if (is_user_alive(victim) && is_teams_equal(victim, grenade_owner)) {
set_user_health(victim, clamp(get_user_health(victim) + GRENADE_HEALTH, 1, GRENADE_MAXHEALTH));
pev(victim, pev_origin, origin);
origin[2]+= 30.0;
message_begin(MSG_BROADCAST,SVC_TEMPENTITY);
write_byte(TE_SPRITE);
WRITE_COORD(origin);
write_short(sprite_index[HEAL]);
write_byte(8);
write_byte(255);
message_end();
message_begin(MSG_ONE_UNRELIABLE, gmsgScreenFade, .player = victim);
write_short(1 << 12);
write_short(0);
write_short(0);
write_byte(GRENADE_COLORFADE_RED);
write_byte(GRENADE_COLORFADE_GREEN);
write_byte(GRENADE_COLORFADE_BLUE);
write_byte(80);
message_end();
}
}
}
UTIL_RemoveEntity(grenade_entity);
}
make_gibs(Float:origin[3])
{
static Float: start_pos[3], Float: end_pos[3];
start_pos[0] = origin[0]; start_pos[1] = origin[1]; start_pos[2] = origin[2] + 150.0;
end_pos[0] = origin[0]; end_pos[1] = origin[1]; end_pos[2] = origin[2] + 10.0;
message_begin (MSG_BROADCAST,SVC_TEMPENTITY);
write_byte(TE_SPRITETRAIL);
WRITE_COORD(start_pos);
WRITE_COORD(end_pos);
write_short(sprite_index[GIBS_BLUE]);
write_byte(GIBS_COUNT);
write_byte(random_num(GIBS_LIFE_MIN, GIBS_LIFE_MAX));
write_byte(GIBS_SCALE);
write_byte(50); // (velocity along vector in 10's)
write_byte(10); // (randomness of velocity in 10's)
message_end() ;
message_begin (MSG_BROADCAST,SVC_TEMPENTITY);
write_byte(TE_SPRITETRAIL);
WRITE_COORD(start_pos);
WRITE_COORD(end_pos);
write_short(sprite_index[GIBS_GREEN]);
write_byte(GIBS_COUNT);
write_byte(random_num(GIBS_LIFE_MIN, GIBS_LIFE_MAX));
write_byte(GIBS_SCALE);
write_byte(50); // (velocity along vector in 10's)
write_byte(10); // (randomness of velocity in 10's)
message_end();
message_begin (MSG_BROADCAST,SVC_TEMPENTITY);
write_byte(TE_SPRITETRAIL);
WRITE_COORD(start_pos);
WRITE_COORD(end_pos);
write_short(sprite_index[GIBS_RED]);
write_byte(GIBS_COUNT);
write_byte(random_num(GIBS_LIFE_MIN, GIBS_LIFE_MAX));
write_byte(GIBS_SCALE);
write_byte(50); // (velocity along vector in 10's)
write_byte(10); // (randomness of velocity in 10's)
message_end();
}