hallo ich wollte mal fragen ob und wenn ja wie man gungame ändern muss damit wenn man jemanden erschiesst das man dann auch wieder Hp bekommt
dieses sollte man auch über die gg config einstellen können wie viel hp man bekommt Danke für die hilfe
Code:
// Thanks a lot to 3volution for helping me iron out some
// bugs and for giving me some helpful suggestions.
//
// Thanks a lot to raa for helping me pinpoint the crash,
// and discovering the respawn bug.
//
// Thanks a lot to VEN for being so smart.
//
// Thanks a lot to BAILOPAN for binary logging, and for
// CSDM spawn files that I could leech off of.
//
// Thanks a lot to all of my supporters, predominantly:
// 3volution, aligind4h0us3, arkshine, Curryking, Gunny,
// IdiotSavant, Mordekay, polakpolak, raa, Silver Dragon,
// and ToT | V!PER. (alphabetically)
//
// Thanks especially to all of the translators:
// arkshine, b!orn, commonbullet, Curryking, Deviance,
// D o o m, Fr3ak0ut, godlike, harbu, iggy_bus, jopmako,
// KylixMynxAltoLAG, Morpheus759, SAMURAI16, TEG,
// ToT | V!PER, Twilight Suzuka, and webpsiho. (alphabetically)
#include <amxmodx>
#include <amxmisc>
#include <fakemeta>
#include <fakemeta_util>
#include <cstrike>
// defines
#define GG_VERSION "1.17b"
#define TOP_PLAYERS 10 // for !top10
#define MAX_SPAWNS 128 // for gg_dm_spawn_random
#define COMMAND_ACCESS ADMIN_CVAR // for amx_gungame
#define LANG_PLAYER_C -76 // for gungame_print (arbitrary number)
#define MAX_WEAPON_ORDERS 10 // for random gg_weapon_order
#define TEMP_SAVES 32 // for gg_save_temp
#define TNAME_SAVE pev_noise3 // for blocking game_player_equip and player_weaponstrip
// gg_status_display
enum
{
STATUS_LEADERWPN = 1,
STATUS_YOURWPN,
STATUS_KILLSLEFT,
STATUS_KILLSDONE
};
// toggle_gungame
enum
{
TOGGLE_FORCE = -1,
TOGGLE_DISABLE,
TOGGLE_ENABLE
};
// bombStatus[3]
enum
{
BOMB_PICKEDUP = -1,
BOMB_DROPPED,
BOMB_PLANTED
};
// cs_set_user_money
#if cellbits == 32
#define OFFSET_CSMONEY 115
#else
#define OFFSET_CSMONEY 140
#endif
#define OFFSET_LINUX 5
// task ids
#define TASK_END_STAR 200
#define TASK_RESPAWN 300
#define TASK_CHECK_RESPAWN 400
#define TASK_CHECK_RESPAWN2 1100
#define TASK_CLEAR_SAVE 500
#define TASK_CHECK_DEATHMATCH 600
#define TASK_REMOVE_PROTECTION 700
#define TASK_TOGGLE_GUNGAME 800
#define TASK_WARMUP_CHECK 900
#define TASK_VERIFY_WEAPON 1000
#define TASK_DELAYED_SUICIDE 1100
#define TASK_REFRESH_NADE 1200
// hud channels
#define CHANNEL_STATUS 3
#define CHANNEL_WARMUP 1
// animations
#define USP_DRAWANIM 6
#define M4A1_DRAWANIM 5
//
// VARIABLE DEFINITIONS
//
// pcvar holders
new gg_enabled, gg_ff_auto, gg_vote_setting, gg_map_setup, gg_join_msg,
gg_weapon_order, gg_max_lvl, gg_triple_on, gg_turbo, gg_knife_pro,
gg_worldspawn_suicide, gg_bomb_defuse_lvl, gg_handicap_on, gg_top10_handicap,
gg_warmup_timer_setting, gg_knife_warmup, gg_nade_glock, gg_nade_smoke,
gg_nade_flash, gg_sound_levelup, gg_sound_leveldown, gg_sound_nade,
gg_sound_knife, gg_sound_welcome, gg_sound_triple, gg_sound_winner,
gg_kills_per_lvl, gg_give_armor, gg_give_helmet, gg_vote_custom,
gg_changelevel_custom, gg_ammo_amount, gg_dm, gg_dm_sp_time, gg_dm_sp_mode,
gg_dm_spawn_random, gg_dm_spawn_delay, gg_stats_file, gg_stats_prune,
gg_refill_on_kill, gg_colored_messages, gg_tk_penalty, gg_dm_corpses, gg_save_temp,
gg_awp_oneshot, gg_host_touch_reward, gg_host_rescue_reward, gg_host_kill_reward,
gg_dm_countdown, gg_status_display, gg_dm_spawn_afterplant, gg_block_objectives,
gg_stats_mode, gg_pickup_others, gg_stats_winbonus, gg_map_iterations, gg_warmup_multi,
gg_host_kill_penalty, gg_dm_start_random, gg_stats_ip, gg_extra_nades, gg_endmap_setup,
gg_allow_changeteam, gg_autovote_rounds, gg_autovote_ratio, gg_autovote_delay,
gg_autovote_time, gg_ignore_bots, gg_nade_refresh, gg_block_equips;
// max clip
stock const maxClip[31] = { -1, 13, -1, 10, 1, 7, 1, 30, 30, 1, 30, 20, 25, 30, 35, 25, 12, 20,
10, 30, 100, 8, 30, 30, 20, 2, 7, 30, 30, -1, 50 };
// max bpammo
stock const maxAmmo[31] = { -1, 52, -1, 90, -1, 32, -1, 100, 90, -1, 120, 100, 100, 90, 90, 90, 100, 100,
30, 120, 200, 32, 90, 120, 60, -1, 35, 90, 90, -1, 100 };
// weapon slot lookup table
stock const weaponSlots[] = { 0, 2, 0, 1, 4, 1, 5, 1, 1, 4, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1,
1, 4, 2, 1, 1, 3, 1 };
// misc
new scores_menu, level_menu, bombMap, hostageMap, warmup = -1, len, voted, won, trailSpr, roundEnded,
weaponOrder[416], menuText[512], dummy[2], tempSave[TEMP_SAVES][27], c4planter, czero, bombStatus[4], maxPlayers,
gameStarted, mapIteration = 1, Float:spawns[MAX_SPAWNS][9], spawnCount, csdmSpawnCount, cfgDir[32],
top10[TOP_PLAYERS][81], csrespawnEnabled, modName[12], autovoted, autovotes[2], roundsElapsed,
gameCommenced, cycleNum = -1;
// stats file stuff
new sfFile[64], sfAuthid[24], sfWins[6], sfPoints[8], sfName[32], sfTimestamp[12], sfLineData[81];
// event ids
new gmsgSayText, gmsgCurWeapon, gmsgScenario, gmsgBombDrop, gmsgBombPickup, gmsgHideWeapon, gmsgCrosshair;
// player values
new level[33], levelsThisRound[33], score[33], weapon[33][24], star[33], welcomed[33],
spawnProtected[33], blockResetHUD[33], page[33], blockCorpse[33], Float:lastDeathMsg[33], hosties[33][2],
respawn_timeleft[33], Float:spawnTime[33], silenced[33], spawnSounds[33], oldTeam[33];
//
// INITIATION FUNCTIONS
//
native cs_respawn(index);
// plugin load
public plugin_init()
{
register_plugin("GunGame AMXX",GG_VERSION,"Avalanche");
register_cvar("gg_version",GG_VERSION,FCVAR_SERVER);
set_cvar_string("gg_version",GG_VERSION);
// mehrsprachige unterstützung (nein, spreche ich nicht Deutsches)
register_dictionary("gungame.txt");
register_dictionary("common.txt");
register_dictionary("adminvote.txt");
// event ids
gmsgSayText = get_user_msgid("SayText");
gmsgCurWeapon = get_user_msgid("CurWeapon");
gmsgScenario = get_user_msgid("Scenario");
gmsgBombDrop = get_user_msgid("BombDrop");
gmsgBombPickup = get_user_msgid("BombPickup");
gmsgHideWeapon = get_user_msgid("HideWeapon");
gmsgCrosshair = get_user_msgid("Crosshair");
// forwards
register_forward(FM_SetModel,"fw_setmodel");
register_forward(FM_Touch,"fw_touch");
register_forward(FM_EmitSound,"fw_emitsound");
// events
register_event("DeathMsg","event_deathmsg","a");
register_event("ResetHUD","event_resethud","b");
register_event("CurWeapon","event_curweapon","b","1=1");
register_event("AmmoX","event_ammox","b");
register_event("HLTV","event_new_round","a","1=0","2=0"); // VEN
register_event("TextMsg","event_round_restart","a","2=#Game_Commencing","2=#Game_will_restart_in");
register_event("30","event_intermission","a");
register_event("23","event_bomb_detonation","a","1=17","6=-105","7=17"); // planted bomb exploded (before/after round end) event (discovered by Ryan)
register_message(get_user_msgid("ClCorpse"),"message_clcorpse");
register_message(get_user_msgid("Money"),"message_money");
register_message(gmsgScenario,"message_scenario");
register_message(gmsgBombDrop,"message_bombdrop");
register_message(gmsgBombPickup,"message_bombpickup");
register_message(get_user_msgid("WeapPickup"),"message_weappickup"); // for gg_block_objectives
register_message(get_user_msgid("AmmoPickup"),"message_ammopickup"); // for gg_block_objectives
register_message(get_user_msgid("TextMsg"),"message_textmsg"); // for gg_block_objectives
register_message(get_user_msgid("HostagePos"),"message_hostagepos"); // for gg_block_objectives
// logevents
register_logevent("event_bomb_detonation",6,"3=Target_Bombed"); // another bomb exploded event, for security (VEN)
register_logevent("logevent_bomb_planted",3,"2=Planted_The_Bomb"); // bomb planted (VEN)
register_logevent("logevent_bomb_defused",3,"2=Defused_The_Bomb"); // bomb defused (VEN)
register_logevent("logevent_round_end",2,"1=Round_End"); // round ended (VEN)
register_logevent("logevent_hostage_touched",3,"2=Touched_A_Hostage");
register_logevent("logevent_hostage_rescued",3,"2=Rescued_A_Hostage");
register_logevent("logevent_hostage_killed",3,"2=Killed_A_Hostage");
register_logevent("logevent_team_join",3,"1=joined team");
// commands
register_concmd("amx_gungame","cmd_gungame",ADMIN_CVAR,"<0|1> - toggles the functionality of GunGame");
register_concmd("amx_gungame_level","cmd_gungame_level",ADMIN_BAN,"<target> <level> - sets target's level. use + or - for relative, otherwise it's absolute.");
register_concmd("amx_gungame_vote","cmd_gungame_vote",ADMIN_VOTE,"- starts a vote to toggle GunGame");
register_clcmd("fullupdate","cmd_fullupdate");
register_clcmd("joinclass","cmd_joinclass"); // new menus
register_menucmd(register_menuid("Terrorist_Select",1),511,"cmd_joinclass"); // old menus (thanks teame06)
register_menucmd(register_menuid("CT_Select",1),511,"cmd_joinclass"); // old menus (thanks teame06)
register_clcmd("say","cmd_say");
register_clcmd("say_team","cmd_say");
// menus
register_menucmd(register_menuid("autovote_menu"),MENU_KEY_1|MENU_KEY_2|MENU_KEY_0,"autovote_menu_handler");
register_menucmd(register_menuid("welcome_menu"),1023,"welcome_menu_handler");
register_menucmd(register_menuid("restart_menu"),MENU_KEY_1|MENU_KEY_0,"restart_menu_handler");
register_menucmd(register_menuid("weapons_menu"),MENU_KEY_1|MENU_KEY_2|MENU_KEY_0,"weapons_menu_handler");
register_menucmd(register_menuid("top10_menu"),MENU_KEY_1|MENU_KEY_2|MENU_KEY_0,"top10_menu_handler");
scores_menu = register_menuid("scores_menu");
register_menucmd(scores_menu,MENU_KEY_1|MENU_KEY_2|MENU_KEY_0,"scores_menu_handler");
level_menu = register_menuid("level_menu");
register_menucmd(level_menu,1023,"level_menu_handler");
// basic cvars
gg_enabled = register_cvar("gg_enabled","1");
gg_vote_setting = register_cvar("gg_vote_setting","1");
gg_vote_custom = register_cvar("gg_vote_custom","");
gg_changelevel_custom = register_cvar("gg_changelevel_custom","");
gg_map_setup = register_cvar("gg_map_setup","mp_timelimit 45; mp_winlimit 0; sv_alltalk 0; mp_chattime 10; mp_c4timer 25");
gg_endmap_setup = register_cvar("gg_endmap_setup","");
gg_join_msg = register_cvar("gg_join_msg","1");
gg_colored_messages = register_cvar("gg_colored_messages","1");
gg_save_temp = register_cvar("gg_save_temp","300"); // = 5 * 60 = 5 minutes
gg_status_display = register_cvar("gg_status_display","0");
gg_map_iterations = register_cvar("gg_map_iterations","1");
gg_ignore_bots = register_cvar("gg_ignore_bots","0");
gg_block_equips = register_cvar("gg_block_equips","0");
// autovote cvars
gg_autovote_rounds = register_cvar("gg_autovote_rounds","0");
gg_autovote_delay = register_cvar("gg_autovote_delay","8.0");
gg_autovote_ratio = register_cvar("gg_autovote_ratio","0.51");
gg_autovote_time = register_cvar("gg_autovote_time","10.0");
// stats cvars
gg_stats_file = register_cvar("gg_stats_file","gungame.stats");
gg_stats_ip = register_cvar("gg_stats_ip","0");
gg_stats_prune = register_cvar("gg_stats_prune","2592000"); // = 60 * 60 * 24 * 30 = 30 days
gg_stats_mode = register_cvar("gg_stats_mode","1");
gg_stats_winbonus = register_cvar("gg_stats_winbonus","1.5");
// deathmatch cvars
gg_dm = register_cvar("gg_dm","0");
gg_dm_sp_time = register_cvar("gg_dm_sp_time","1.0");
gg_dm_sp_mode = register_cvar("gg_dm_sp_mode","1");
gg_dm_spawn_random = register_cvar("gg_dm_spawn_random","0");
gg_dm_start_random = register_cvar("gg_dm_start_random","0");
gg_dm_spawn_delay = register_cvar("gg_dm_spawn_delay","1.5");
gg_dm_spawn_afterplant = register_cvar("gg_dm_spawn_afterplant","1");
gg_dm_corpses = register_cvar("gg_dm_corpses","1");
gg_dm_countdown = register_cvar("gg_dm_countdown","0");
// objective cvars
gg_block_objectives = register_cvar("gg_block_objectives","0");
gg_bomb_defuse_lvl = register_cvar("gg_bomb_defuse_lvl","1");
gg_host_touch_reward = register_cvar("gg_host_touch_reward","0");
gg_host_rescue_reward = register_cvar("gg_host_rescue_reward","0");
gg_host_kill_reward = register_cvar("gg_host_kill_reward","0");
gg_host_kill_penalty = register_cvar("gg_host_kill_penalty","0");
// gameplay cvars
gg_ff_auto = register_cvar("gg_ff_auto","1");
gg_weapon_order = register_cvar("gg_weapon_order","glock18,usp,p228,deagle,fiveseven,elite,m3,xm1014,tmp,mac10,mp5navy,ump45,p90,galil,famas,ak47,scout,m4a1,sg552,aug,m249,hegrenade,knife");
gg_max_lvl = register_cvar("gg_max_lvl","3");
gg_triple_on = register_cvar("gg_triple_on","0");
gg_turbo = register_cvar("gg_turbo","0");
gg_knife_pro = register_cvar("gg_knife_pro","0");
gg_worldspawn_suicide = register_cvar("gg_worldspawn_suicide","1");
gg_allow_changeteam = register_cvar("gg_allow_changeteam","0");
gg_pickup_others = register_cvar("gg_pickup_others","0");
gg_handicap_on = register_cvar("gg_handicap_on","1");
gg_top10_handicap = register_cvar("gg_top10_handicap","1");
gg_warmup_timer_setting = register_cvar("gg_warmup_timer_setting","60");
gg_knife_warmup = register_cvar("gg_knife_warmup","1");
gg_warmup_multi = register_cvar("gg_warmup_multi","0");
gg_nade_glock = register_cvar("gg_nade_glock","0");
gg_nade_smoke = register_cvar("gg_nade_smoke","0");
gg_nade_flash = register_cvar("gg_nade_flash","0");
gg_extra_nades = register_cvar("gg_extra_nades","0");
gg_nade_refresh = register_cvar("gg_nade_refresh","0.0");
gg_kills_per_lvl = register_cvar("gg_kills_per_lvl","1");
gg_give_armor = register_cvar("gg_give_armor","100");
gg_give_helmet = register_cvar("gg_give_helmet","1");
gg_ammo_amount = register_cvar("gg_ammo_amount","200");
gg_refill_on_kill = register_cvar("gg_refill_on_kill","1");
gg_tk_penalty = register_cvar("gg_tk_penalty","0");
gg_awp_oneshot = register_cvar("gg_awp_oneshot","1");
// sound cvars
gg_sound_levelup = register_cvar("gg_sound_levelup","gungame/smb3_powerup.wav");
gg_sound_leveldown = register_cvar("gg_sound_leveldown","gungame/smb3_powerdown.wav");
gg_sound_nade = register_cvar("gg_sound_nade","gungame/nade_level.wav");
gg_sound_knife = register_cvar("gg_sound_knife","gungame/knife_level.wav");
gg_sound_welcome = register_cvar("gg_sound_welcome","gungame/gungame2.wav");
gg_sound_triple = register_cvar("gg_sound_triple","gungame/smb_star.wav");
gg_sound_winner = register_cvar("gg_sound_winner","media/Half-Life08.mp3");
// random weapon order cvars
new i, cvar[20];
for(i=1;i<=MAX_WEAPON_ORDERS;i++)
{
formatex(cvar,19,"gg_weapon_order%i",i);
register_cvar(cvar,"");
}
// check for mini respawn module
csrespawnEnabled = module_exists("csrespawn");
// make sure to setup amx_nextmap incase nextmap.amxx isn't running
if(!cvar_exists("amx_nextmap")) register_cvar("amx_nextmap","",FCVAR_SERVER|FCVAR_EXTDLL|FCVAR_SPONLY);
// identify this as a bomb map
if(fm_find_ent_by_class(1,"info_bomb_target") || fm_find_ent_by_class(1,"func_bomb_target"))
bombMap = 1;
// identify this as a hostage map
if(fm_find_ent_by_class(1,"hostage_entity"))
hostageMap = 1;
get_modname(modName,11);
// remember if we are running czero or not
if(equali(modName,"czero")) czero = 1;
maxPlayers = get_maxplayers();
// grab CSDM file
new mapName[32], csdmFile[64];
get_configsdir(cfgDir,31);
get_mapname(mapName,31);
formatex(csdmFile,63,"%s/csdm/%s.spawns.cfg",cfgDir,mapName);
// collect CSDM spawns
if(file_exists(csdmFile))
{
new csdmData[10][6];
new file = fopen(csdmFile,"rt");
while(file && !feof(file))
{
fgets(file,sfLineData,63);
// invalid spawn
if(!sfLineData[0] || str_count(sfLineData,' ') < 2)
continue;
// BREAK IT UP!
parse(sfLineData,csdmData[0],5,csdmData[1],5,csdmData[2],5,csdmData[3],5,csdmData[4],5,csdmData[5],5,csdmData[6],5,csdmData[7],5,csdmData[8],5,csdmData[9],5);
// origin
spawns[spawnCount][0] = floatstr(csdmData[0]);
spawns[spawnCount][1] = floatstr(csdmData[1]);
spawns[spawnCount][2] = floatstr(csdmData[2]);
// angles
spawns[spawnCount][3] = floatstr(csdmData[3]);
spawns[spawnCount][4] = floatstr(csdmData[4]);
spawns[spawnCount][5] = floatstr(csdmData[5]);
// team, csdmData[6], unused
// vangles
spawns[spawnCount][6] = floatstr(csdmData[7]);
spawns[spawnCount][7] = floatstr(csdmData[8]);
spawns[spawnCount][8] = floatstr(csdmData[9]);
spawnCount++;
csdmSpawnCount++;
if(spawnCount >= MAX_SPAWNS) break;
}
if(file) fclose(file);
}
// collect regular, boring spawns
else
{
new ent, Float:spawnData[3];
while((ent = fm_find_ent_by_class(ent,"info_player_deathmatch")) != 0)
{
// origin
pev(ent,pev_origin,spawnData);
spawns[spawnCount][0] = spawnData[0];
spawns[spawnCount][1] = spawnData[1];
spawns[spawnCount][2] = spawnData[2];
// angles
pev(ent,pev_angles,spawnData);
spawns[spawnCount][3] = spawnData[0];
spawns[spawnCount][4] = spawnData[1];
spawns[spawnCount][5] = spawnData[2];
// vangles
spawns[spawnCount][6] = spawnData[0];
spawns[spawnCount][7] = spawnData[1];
spawns[spawnCount][8] = spawnData[2];
spawnCount++;
if(spawnCount >= MAX_SPAWNS) break;
}
// yeah, I probably should've optimized this
ent = 0;
while((ent = fm_find_ent_by_class(ent,"info_player_start")) != 0)
{
// origin
pev(ent,pev_origin,spawnData);
spawns[spawnCount][0] = spawnData[0];
spawns[spawnCount][1] = spawnData[1];
spawns[spawnCount][2] = spawnData[2];
// angles
pev(ent,pev_angles,spawnData);
spawns[spawnCount][3] = spawnData[0];
spawns[spawnCount][4] = spawnData[1];
spawns[spawnCount][5] = spawnData[2];
// vangles
spawns[spawnCount][6] = spawnData[0];
spawns[spawnCount][7] = spawnData[1];
spawns[spawnCount][8] = spawnData[2];
spawnCount++;
if(spawnCount >= MAX_SPAWNS) break;
}
}
// delay for server.cfg
set_task(1.0,"toggle_gungame",TASK_TOGGLE_GUNGAME + TOGGLE_FORCE);
// manage pruning (longer delay for toggle_gungame)
set_task(2.0,"manage_pruning");
}
// plugin ends, prune stats file maybe
public plugin_end()
{
// run endmap setup on plugin close
if(get_pcvar_num(gg_enabled))
{
new setup[512];
get_pcvar_string(gg_endmap_setup,setup,511);
if(setup[0]) server_cmd(setup);
}
}
// setup native filter for cs_respawn
public plugin_natives()
{
set_native_filter("native_filter");
}
// don't throw error on cs_respawn if not running module
public native_filter(const name[],index,trap)
{
if(equal(name,"cs_respawn"))
return PLUGIN_HANDLED;
return PLUGIN_CONTINUE;
}
// manage stats pruning
public manage_pruning()
{
get_pcvar_string(gg_stats_file,sfFile,63);
// stats disabled/file doesn't exist/pruning disabled
if(!sfFile[0] || !file_exists(sfFile) || !get_pcvar_num(gg_stats_prune)) return;
// get how many plugin ends more until we prune
new prune_in_str[3], prune_in;
get_localinfo("gg_prune_in",prune_in_str,2);
prune_in = str_to_num(prune_in_str);
// localinfo not set yet
if(!prune_in)
{
set_localinfo("gg_prune_in","9");
return;
}
// time to prune
if(prune_in == 1)
{
// prune and log
log_amx("%L",LANG_SERVER,"PRUNING",sfFile,stats_prune());
// reset our prune count
set_localinfo("gg_prune_in","10");
return;
}
// decrement our count
num_to_str(prune_in-1,prune_in_str,2);
set_localinfo("gg_prune_in",prune_in_str);
}
// manage warmup mode
public warmup_check(taskid)
{
warmup--;
set_hudmessage(255,255,255,-1.0,0.4,0,6.0,1.0,0.1,0.2,CHANNEL_WARMUP);
if(warmup <= 0)
{
warmup = -13;
show_hudmessage(0,"%L",LANG_PLAYER,"WARMUP_ROUND_OVER");
set_cvar_num("sv_restartround",1);
}
else
{
show_hudmessage(0,"%L",LANG_PLAYER,"WARMUP_ROUND_DISPLAY",warmup);
set_task(1.0,"warmup_check",taskid);
}
}
// plugin precache
public plugin_precache()
{
precache_sound_by_cvar("gg_sound_levelup","gungame/smb3_powerup.wav");
precache_sound_by_cvar("gg_sound_leveldown","gungame/smb3_powerdown.wav");
precache_sound_by_cvar("gg_sound_nade","gungame/nade_level.wav");
precache_sound_by_cvar("gg_sound_knife","gungame/knife_level.wav");
precache_sound_by_cvar("gg_sound_welcome","gungame/gungame2.wav");
precache_sound_by_cvar("gg_sound_triple","gungame/smb_star.wav");
precache_sound_by_cvar("gg_sound_winner","media/Half-Life08.mp3");
precache_sound("gungame/brass_bell_C.wav");
precache_sound("buttons/bell1.wav");
precache_sound("common/null.wav");
trailSpr = precache_model("sprites/laserbeam.spr");
}
//
// FORWARDS
//
// client gets a steamid
public client_authorized(id)
{
clear_values(id);
get_pcvar_string(gg_stats_file,sfFile,63);
static authid[24];
if(get_pcvar_num(gg_stats_ip)) get_user_ip(id,authid,23);
else get_user_authid(id,authid,23);
// refresh timestamp if we should
if(sfFile[0]) stats_refresh_timestamp(authid);
// load temporary save
if(get_pcvar_num(gg_enabled) && get_pcvar_num(gg_save_temp))
{
new i, save = -1;
// find our possible temp save
for(i=0;i<TEMP_SAVES;i++)
{
if(equal(authid,tempSave[i],23))
{
save = i;
break;
}
}
// no temp save
if(save == -1) return;
// load values
level[id] = tempSave[save][24];
score[id] = tempSave[save][25];
// clear it
clear_save(TASK_CLEAR_SAVE+save);
// get the name (almost forgot!)
get_weapon_name_by_level(level[id],weapon[id],23);
}
}
// client leaves, reset values
public client_disconnect(id)
{
// remove certain tasks
remove_task(TASK_RESPAWN+id);
remove_task(TASK_CHECK_RESPAWN+id);
remove_task(TASK_CHECK_RESPAWN2+id);
remove_task(TASK_CHECK_DEATHMATCH+id);
remove_task(TASK_REMOVE_PROTECTION+id);
remove_task(TASK_VERIFY_WEAPON+id);
remove_task(TASK_DELAYED_SUICIDE+id);
remove_task(TASK_REFRESH_NADE+id);
// clear bomb planter
if(c4planter == id) c4planter = 0;
// don't bother saving if in winning period
if(!won)
{
new save_temp = get_pcvar_num(gg_save_temp);
// temporarily save values
if(get_pcvar_num(gg_enabled) && save_temp && (level[id] > 1 || score[id] > 0))
{
new freeSave = -1, oldestSave = -1, i;
for(i=0;i<TEMP_SAVES;i++)
{
// we found a free one
if(!tempSave[i][0])
{
freeSave = i;
break;
}
// keep track of one soonest to expire
if(oldestSave == -1 || tempSave[i][26] < tempSave[oldestSave][26])
oldestSave = i;
}
// no free, use oldest
if(freeSave == -1) freeSave = oldestSave;
if(get_pcvar_num(gg_stats_ip)) get_user_ip(id,tempSave[freeSave],23);
else get_user_authid(id,tempSave[freeSave],23);
tempSave[freeSave][24] = level[id];
tempSave[freeSave][25] = score[id];
tempSave[freeSave][26] = floatround(get_gametime());
set_task(float(save_temp),"clear_save",TASK_CLEAR_SAVE+freeSave);
}
}
clear_values(id);
}
// remove a save
public clear_save(taskid)
{
remove_task(taskid);
tempSave[taskid-TASK_CLEAR_SAVE][0] = 0;
}
// clear all saved values
stock clear_values(id,ignoreWelcome=0)
{
level[id] = 0;
levelsThisRound[id] = 0;
score[id] = 0;
weapon[id][0] = 0;
star[id] = 0;
if(!ignoreWelcome) welcomed[id] = 0;
spawnProtected[id] = 0;
blockResetHUD[id] = 0;
page[id] = 0;
blockCorpse[id] = 0;
respawn_timeleft[id] = 0;
silenced[id] = 0;
spawnSounds[id] = 1;
oldTeam[id] = 0;
}
// an entity is given a model, stop weapons from
// dropping in DM mode so that it doesn't get clustered
public fw_setmodel(ent,model[])
{
if(!get_pcvar_num(gg_enabled) || !pev_valid(ent) || !model[0])
return FMRES_IGNORED;
new owner = pev(ent,pev_owner);
// no owner
if(!is_user_connected(owner)) return FMRES_IGNORED;
static classname[24];
pev(ent,pev_classname,classname,10);
// not a weapon
// checks for weaponbox, weapon_shield
if(classname[8] != 'x' && !(classname[6] == '_' && classname[7] == 's' && classname[8] == 'h'))
return FMRES_IGNORED;
// makes sure we don't get memory access error,
// but also helpful to narrow down matches
new len = strlen(model);
// ignore weaponboxes whose models haven't been set to correspond with their weapon types yet
// checks for models/w_weaponbox.mdl
if(len == 22 && model[17] == 'x') return FMRES_IGNORED;
// C4 should always drop
// checks for models/w_backpack.mdl
if(len == 21 && model[9] == 'b') return FMRES_IGNORED;
// if owner is dead
if(get_user_health(owner) <= 0)
{
// first, remember silenced or burst status
// checks for models/w_usp.mdl, usp, models/w_m4a1.mdl, m4a1
if( (len == 16 && model[10] == 's' && weapon[owner][1] == 's')
|| (len == 17 && model[10] == '4' && weapon[owner][1] == '4') )
{
copyc(model,len-1,model[containi(model,"_")+1],'.'); // strips off models/w_ and .mdl
formatex(classname,23,"weapon_%s",model);
new wEnt = fm_find_ent_by_owner(maxPlayers,classname,ent);
if(pev_valid(wEnt)) silenced[owner] = cs_get_weapon_silen(wEnt);
}
// checks for models/w_glock18.mdl, glock18, models/w_famas.mdl, famas
else if( (len == 20 && model[15] == '8' && weapon[owner][6] == '8')
|| (len == 18 && model[9] == 'f' && model[10] == 'a' && weapon[owner][0] == 'f' && weapon[owner][1] == 'a') )
{
copyc(model,len-1,model[containi(model,"_")+1],'.'); // strips off models/w_ and .mdl
formatex(classname,23,"weapon_%s",model);
new wEnt = fm_find_ent_by_owner(maxPlayers,classname,ent);
if(pev_valid(wEnt)) silenced[owner] = cs_get_weapon_burst(wEnt);
}
if(get_pcvar_num(gg_dm) && !get_pcvar_num(gg_pickup_others))
{
// then remove it
dllfunc(DLLFunc_Think,ent);
}
}
return FMRES_IGNORED;
}
// touchy touchy
public fw_touch(touched,toucher)
{
// invalid entities involved or gungame disabled
if(!get_pcvar_num(gg_enabled) || !pev_valid(touched) || !is_user_connected(toucher))
return FMRES_IGNORED;
static classname[10];
pev(touched,pev_classname,classname,9);
// not touching a weapon-giver
// checks for weaponbox, weapon_*, armoury_*
if(classname[8] != 'x'
&& !(classname[0] == 'w' && classname[1] == 'e' && classname[2] == 'a')
&& !(classname[0] == 'a' && classname[1] == 'r' && classname[2] == 'm'))
return FMRES_IGNORED;
// removing starting pistols
if(fm_halflife_time() - spawnTime[toucher] < 0.2)
{
dllfunc(DLLFunc_Think,touched);
return FMRES_SUPERCEDE;
}
static model[24];
pev(touched,pev_model,model,23);
// not touching the kind of weaponbox that we like
// checks for models/w_weaponbox.mdl
if(model[17] == 'x') return FMRES_IGNORED;
// allow pickup of C4
// checks for models/w_backpack.mdl
if(model[9] == 'b') return FMRES_IGNORED;
// knife warmup, no weapons allowed
if(warmup > 0 && get_pcvar_num(gg_knife_warmup))
return FMRES_SUPERCEDE;
// we are allowed to pick up other weapons
if(get_pcvar_num(gg_pickup_others))
return FMRES_IGNORED;
// weapon is weapon_mp5navy, but model is w_mp5.mdl
// checks for models/w_mp5.mdl
if(model[10] == 'p' && model[11] == '5') model = "mp5navy";
// get the type of weapon based on model
else
{
replace(model,23,"models/w_","");
replace(model,23,".mdl","");
}
// everyone is allowed to use knife
// checks for knife
if(model[0] == 'k') return FMRES_IGNORED;
// check hegrenade exceptions
// checks for hegrenade
if(weapon[toucher][0] == 'h')
{
if(model[6] == '8' && get_pcvar_num(gg_nade_glock)) return FMRES_IGNORED; // glock18
if(model[0] == 's' && model[1] == 'm' && get_pcvar_num(gg_nade_smoke)) return FMRES_IGNORED; // smokegrenade
if(model[0] == 'f' && model[1] == 'l' && get_pcvar_num(gg_nade_flash)) return FMRES_IGNORED; // flashbang
}
// this is our weapon, don't mess with it
if(equal(weapon[toucher],model)) return FMRES_IGNORED;
// otherwise, this is an item we're not allowed to have
return FMRES_SUPERCEDE;
}
// HELLO HELLo HELlo HEllo Hello hello
public fw_emitsound(ent,channel,sample[],Float:volume,Float:atten,flags,pitch)
{
if(!get_pcvar_num(gg_enabled) || !is_user_connected(ent) || !get_pcvar_num(gg_dm) || spawnSounds[ent])
return FMRES_IGNORED;
return FMRES_SUPERCEDE;
}
//
// EVENT HOOKS
//
// respawnish
public event_resethud(id)
{
if(!get_pcvar_num(gg_enabled) || !is_user_connected(id))
return;
remove_task(TASK_CHECK_DEATHMATCH+id);
// ignore first ResetHUD after sv_restartround
if(blockResetHUD[id])
{
set_task(0.1,"hide_money",id);
blockResetHUD[id]--;
return;
}
// have not joined yet
new CsTeams:team = cs_get_user_team(id);
if(team != CS_TEAM_T && team != CS_TEAM_CT) return;
spawnTime[id] = fm_halflife_time();
status_display(id);
set_task(0.1,"post_resethud",id);
}
// our delay
public post_resethud(id)
{
if(!is_user_connected(id) || pev(id,pev_iuser1)) return;
levelsThisRound[id] = 0;
// just joined
if(!level[id])
{
// handicap
new handicapMode = get_pcvar_num(gg_handicap_on);
if(handicapMode)
{
new rcvHandicap = 1;
get_pcvar_string(gg_stats_file,sfFile,63);
// top10 doesn't receive handicap -- also make sure we are using top10
if(!get_pcvar_num(gg_top10_handicap) && sfFile[0] && file_exists(sfFile) && get_pcvar_num(gg_stats_mode))
{
static authid[24];
if(get_pcvar_num(gg_stats_ip)) get_user_ip(id,authid,23);
else get_user_authid(id,authid,23);
new i;
for(i=0;i<TOP_PLAYERS;i++)
{
// blank
if(!top10[i][0]) continue;
// isolate authid
strtok(top10[i],sfAuthid,23,dummy,1,'^t');
// I'm in top10, don't give me handicap
if(equal(authid,sfAuthid))
{
rcvHandicap = 0;
break;
}
}
}
if(rcvHandicap)
{
new players[32], num, i;
get_players(players,num);
// find lowest level (don't use bots unless we have to)
if(handicapMode == 2)
{
new isBot, myLevel, lowestLevel, lowestBotLevel;
for(i=0;i<num;i++)
{
if(players[i] == id)
continue;
isBot = is_user_bot(players[i]);
myLevel = level[players[i]];
if(!myLevel) continue;
if(!isBot && (!lowestLevel || myLevel < lowestLevel))
lowestLevel = myLevel;
else if(isBot && (!lowestBotLevel || myLevel < lowestBotLevel))
lowestBotLevel = myLevel;
}
// CLAMP!
if(!lowestLevel) lowestLevel = 1;
if(!lowestBotLevel) lowestBotLevel = 1;
change_level(id,(lowestLevel > 1) ? lowestLevel : lowestBotLevel,1,0);
}
// find average level
else
{
new Float:average;
for(i=0;i<num;i++)
{
if(players[i] != id)
average += float(level[players[i]]);
}
average /= float(num)-1;
change_level(id,(average >= 0.5) ? floatround(average) : 1,1,0);
}
}
// not eligible for handicap (in top10 with gg_top10_handicap disabled)
else change_level(id,1,1,0);
}
// no handicap enabled
else change_level(id,1,1,0);
give_level_weapon(id);
}
// didn't just join
else
{
if(star[id])
{
end_star(TASK_END_STAR+id);
remove_task(TASK_END_STAR+id);
}
get_weapon_name_by_level(level[id],weapon[id],23);
give_level_weapon(id);
refill_ammo(id);
}
// show welcome message
if(!welcomed[id] && get_pcvar_num(gg_join_msg))
show_welcome(id);
// update bomb for DM
if(cs_get_user_team(id) == CS_TEAM_T && !get_pcvar_num(gg_block_objectives) && get_pcvar_num(gg_dm))
{
if(bombStatus[3] == BOMB_PICKEDUP)
{
message_begin(MSG_ONE,gmsgBombPickup,_,id);
message_end();
}
else if(bombStatus[0] || bombStatus[1] || bombStatus[2])
{
message_begin(MSG_ONE,gmsgBombDrop,_,id);
write_coord(bombStatus[0]);
write_coord(bombStatus[1]);
write_coord(bombStatus[2]);
write_byte(bombStatus[3]);
message_end();
}
}
hide_money(id);
}
// hide someone's money display
public hide_money(id)
{
// hide money
message_begin(MSG_ONE,gmsgHideWeapon,_,id);
write_byte(1<<5);
message_end();
// hide crosshair that appears from hiding money
message_begin(MSG_ONE,gmsgCrosshair,_,id);
write_byte(0);
message_end();
}
// someone has been killed
public event_deathmsg()
{
if(!get_pcvar_num(gg_enabled)) return;
new killer = read_data(1);
new victim = read_data(2);
new Float:time = fm_halflife_time();
// a bug with valve's code (dvander said so!):
// sometimes, when using an item giving code
// (as that's where this can lead) within a message
// hook, the message hook can get called twice.
// so, if this player "dies" twice within X seconds,
// it's obviously a bugged message, so ignore.
if(time - lastDeathMsg[victim] < 0.2)
return;
lastDeathMsg[victim] = time;
remove_task(TASK_VERIFY_WEAPON+victim);
star[victim] = 0;
remove_task(TASK_END_STAR+victim);
// allow us to join in on deathmatch
if(!get_pcvar_num(gg_dm))
{
remove_task(TASK_CHECK_DEATHMATCH+victim);
set_task(10.0,"check_deathmatch",TASK_CHECK_DEATHMATCH+victim);
}
// respawn us
else
{
remove_task(TASK_RESPAWN+victim);
remove_task(TASK_CHECK_RESPAWN+victim);
remove_task(TASK_CHECK_RESPAWN2+victim);
remove_task(TASK_REMOVE_PROTECTION+victim);
set_task(0.1,"begin_respawn",victim);
fm_set_user_rendering(victim); // clear spawn protection
}
// stops defusal kits from dropping in deathmatch mode
if(bombMap && get_pcvar_num(gg_dm)) cs_set_user_defuse(victim,0);
// remember victim's silenced status
if(equal(weapon[victim],"usp") || equal(weapon[victim],"m4a1"))
{
new wEnt = get_weapon_ent(victim,_,weapon[victim]);
if(pev_valid(wEnt)) silenced[victim] = cs_get_weapon_silen(wEnt);
}
// or, remember burst status
else if(equal(weapon[victim],"glock18") || equal(weapon[victim],"famas"))
{
new wEnt = get_weapon_ent(victim,_,weapon[victim]);
if(pev_valid(wEnt)) silenced[victim] = cs_get_weapon_burst(wEnt);
}
// NOTE: simply calling fm_remove_entity on defusal kits after they are dropped
// has the potential to cause a crash. the crash was pinpointed with the help of
// raa, and the solution was offered by VEN.
static wpnName[24];
read_data(4,wpnName,23);
// deaths by hegrenade are reported as grenade, fix
if(wpnName[0] == 'g' && wpnName[1] == 'r' && wpnName[2] == 'e')
wpnName = "hegrenade";
// killed self with worldspawn
if(equal(wpnName,"worldspawn"))
{
if(get_pcvar_num(gg_worldspawn_suicide)) player_suicided(victim);
return;
}
// killed self not with worldspawn
if(killer == victim)
{
if(!roundEnded && get_pcvar_num(gg_allow_changeteam) && equal(wpnName,"world"))
{
oldTeam[victim] = get_user_team(victim);
set_task(0.1,"delayed_suicide",TASK_DELAYED_SUICIDE+victim);
}
else player_suicided(victim);
return;
}
// team kill
if(get_user_team(killer) == get_user_team(victim))
{
new penalty = get_pcvar_num(gg_tk_penalty);
if(penalty > 0)
{
new name[32];
get_user_name(killer,name,31);
if(score[killer] - penalty < 0)
gungame_print(0,killer,"%L",LANG_PLAYER_C,"TK_LEVEL_DOWN",name,(level[killer] > 1) ? level[killer]-1 : level[killer]);
else
gungame_print(0,killer,"%L",LANG_PLAYER_C,"TK_SCORE_DOWN",name,penalty);
change_score(killer,-penalty);
}
return;
}
// other player had spawn protection
if(spawnProtected[victim])
{
new name[32];
get_user_name(victim,name,31);
gungame_print(killer,victim,"%L",killer,"SPAWNPROTECTED_KILL",name,floatround(get_pcvar_float(gg_dm_sp_time)));
return;
}
new canLevel = 1, scored;
// already reached max levels this round
new max_lvl = get_pcvar_num(gg_max_lvl);
if(!get_pcvar_num(gg_turbo) && max_lvl > 0 && levelsThisRound[killer] >= max_lvl)
canLevel = 0;
// was it a knife kill, and does it matter?
if(equal(wpnName,"knife") && get_pcvar_num(gg_knife_pro) && !equal(weapon[killer],"knife"))
{
// knife warmup, don't bother leveling up
if(warmup > 0 && get_pcvar_num(gg_knife_warmup)) return;
static killerName[32], victimName[32];
get_user_name(killer,killerName,31);
get_user_name(victim,victimName,31);
gungame_print(0,killer,"%L",LANG_PLAYER_C,"STOLE_LEVEL",killerName,victimName);
if(canLevel && !equal(weapon[killer],"hegrenade"))
{
if(level[killer] < get_weapon_num()) change_level(killer,1);
}
if(level[victim] > 1) change_level(victim,-1);
}
// otherwise, if he killed with his appropiate weapon, give him a point
else if(canLevel && equal(weapon[killer],wpnName))
{
scored = 1;
// didn't level off of it
if(!change_score(killer,1)) show_required_kills(killer);
}
// award for killing hostage carrier
new host_kill_reward = get_pcvar_num(gg_host_kill_reward);
// note that this doesn't work with CZ hostages
if(hostageMap && !czero && host_kill_reward && !equal(weapon[killer],"hegrenade") && !equal(weapon[killer],"knife"))
{
// check for hostages following this player
new hostage;
while((hostage = fm_find_ent_by_class(hostage,"hostage_entity")) != 0)
{
if(cs_get_hostage_foll(hostage) == victim && pev(hostage,pev_deadflag) == DEAD_NO)
break;
}
// award bonus score if victim had hostages
if(hostage)
{
scored = 1;
if(!equali(weapon[killer],"hegrenade") && !equali(weapon[killer],"knife") && level[killer] < get_weapon_num())
{
// didn't level off of it
if(!change_score(killer,host_kill_reward) || score[killer])
show_required_kills(killer);
}
}
}
if(equal(weapon[killer],"hegrenade") && get_pcvar_num(gg_extra_nades) && !cs_get_user_bpammo(killer,CSW_HEGRENADE))
{
fm_give_item(killer,"weapon_hegrenade");
remove_task(TASK_REFRESH_NADE+killer);
}
if((!scored || !get_pcvar_num(gg_turbo)) && get_pcvar_num(gg_refill_on_kill))
refill_ammo(killer,1);
}
// task is set on a potential team change, and removed on an
// approved team change, so if we reach it, deduct level
public delayed_suicide(taskid)
{
new id = taskid-TASK_DELAYED_SUICIDE;
oldTeam[id] = 0;
if(is_user_connected(id)) player_suicided(id);
}
// someone changes weapons
public event_curweapon(id)
{
if(!get_pcvar_num(gg_enabled)) return;
// keep star speed
if(star[id]) fm_set_user_maxspeed(id,fm_get_user_maxspeed(id)*1.5);
// have only 1 ammo in awp clip
if(get_pcvar_num(gg_awp_oneshot) && read_data(2) == CSW_AWP && read_data(3) > 1)
{
new wEnt = get_weapon_ent(id,CSW_AWP);
if(pev_valid(wEnt)) cs_set_weapon_ammo(wEnt,1);
message_begin(MSG_ONE,gmsgCurWeapon,_,id);
write_byte(1);
write_byte(CSW_AWP);
write_byte(1);
message_end();
}
}
// ammo amount changes
public event_ammox(id)
{
new type = read_data(1);
// not HE grenade ammo, or not on the grenade level
if(type != 12 || !equali(weapon[id],"hegrenade")) return;
new amount = read_data(2);
// still have some left, ignore
if(amount > 0)
{
remove_task(TASK_REFRESH_NADE+id);
return;
}
new Float:refresh = get_pcvar_float(gg_nade_refresh);
// refreshing is disabled, or we are already giving one out
if(refresh <= 0.0 || task_exists(TASK_REFRESH_NADE+id)) return;
// start the timer for the new grenade
set_task(refresh,"refresh_nade",TASK_REFRESH_NADE+id);
}
// a new round has begun
public event_new_round()
{
roundsElapsed++;
if(!autovoted)
{
new autovote_rounds = get_pcvar_num(gg_autovote_rounds);
if(autovote_rounds && gameCommenced && roundsElapsed >= autovote_rounds)
{
autovoted = 1;
set_task(get_pcvar_float(gg_autovote_delay),"autovote_start");
}
}
// game_player_equip
manage_equips();
if(!get_pcvar_num(gg_enabled)) return;
roundEnded = 0;
c4planter = 0;
bombStatus[3] = BOMB_PICKEDUP;
// block hostages
if(hostageMap && get_pcvar_num(gg_block_objectives))
set_task(0.1,"move_hostages");
new i;
for(i=0;i<33;i++)
{
hosties[i][0] = 0;
hosties[i][1] = 0;
}
new leader = get_leader(dummy[0]);
if(equal(weapon[leader],"hegrenade")) play_sound_by_cvar(0,gg_sound_nade);
else if(equal(weapon[leader],"knife")) play_sound_by_cvar(0,gg_sound_knife);
// start in random positions at round start
if(get_pcvar_num(gg_dm) && get_pcvar_num(gg_dm_start_random))
set_task(0.1,"randomly_place_everyone");
}
// what do you think??
public randomly_place_everyone()
{
new players[32], num, i, CsTeams:team;
get_players(players,num);
// count number of legitimate players
new validNum;
for(i=0;i<num;i++)
{
team = cs_get_user_team(players[i]);
if(team == CS_TEAM_T || team == CS_TEAM_CT) validNum++;
}
// not enough CSDM spawns for everyone
if(validNum > csdmSpawnCount)
return;
// now randomly place them
for(i=0;i<num;i++)
{
team = cs_get_user_team(players[i]);
// not spectator or unassigned
if(team == CS_TEAM_T || team == CS_TEAM_CT)
do_random_spawn(players[i],2);
}
}
// manage game_player_equip and player_weaponstrip entities
public manage_equips()
{
static classname[20], targetname[256];
new ent, i, block_equips = get_pcvar_num(gg_block_equips), enabled = get_pcvar_num(gg_enabled);
// go through both entities to monitor
for(i=0;i<2;i++)
{
// get classname for current iteration
switch(i)
{
case 0: classname = "game_player_equip";
default: classname = "player_weaponstrip";
}
// go through whatever entity
while((ent = fm_find_ent_by_class(ent,classname)) != 0)
{
pev(ent,pev_targetname,targetname,255);
// allowed to have this, reverse possible changes
if(!enabled || !block_equips || (i == 1 && block_equips < 2)) // player_weaponstrip switch
{
// this one was blocked
if(equali(targetname,"gg_block_equips"))
{
pev(ent,TNAME_SAVE,targetname,255);
set_pev(ent,pev_targetname,targetname);
set_pev(ent,TNAME_SAVE,"");
}
}
// not allowed to pickup others, make possible changes
else
{
pev(ent,pev_targetname,targetname,255);
// needs to be blocked, but hasn't been yet
if(targetname[0] && !equali(targetname,"gg_block_equips"))
{
set_pev(ent,TNAME_SAVE,targetname);
set_pev(ent,pev_targetname,"gg_block_equips");
}
}
}
}
}
// move the hostages so that CTs can't get to them
public move_hostages()
{
new ent;
while((ent = fm_find_ent_by_class(ent,"hostage_entity")) != 0)
set_pev(ent,pev_origin,Float:{8192.0,8192.0,8192.0});
}
// round is restarting (TAG: sv_restartround)
public event_round_restart()
{
static message[32];
read_data(2,message,31);
if(equal(message,"#Game_Commencing")) gameCommenced = 1;
if(!get_pcvar_num(gg_enabled)) return;
new block;
// block only on round restart, not game commencing
if(equal(message,"#Game_will_restart_in")) block = 1;
// don't reset values on game commencing,
// if it has already commenced once
else
{
if(gameStarted) return;
gameStarted = 1;
}
new players[32], num, i;
get_players(players,num);
for(i=0;i<num;i++)
{
clear_values(players[i],1);
// bots don't experience that ResetHUD on round restart
if(!is_user_bot(players[i]) && block) blockResetHUD[players[i]]++;
}
}
// map is changing
public event_intermission()
{
if(!get_pcvar_num(gg_enabled) || won) return;
// grab highest level
new leaderLevel;
get_leader(leaderLevel);
// grab player list
new players[32], pNum, winner, i;
get_players(players,pNum);
new topLevel[32], tlNum;
// get all of the highest level players
for(i=0;i<pNum;i++)
{
if(level[players[i]] == leaderLevel)
topLevel[tlNum++] = players[i];
}
// only one on top level
if(tlNum == 1) winner = topLevel[0];
else
{
new highestKills, frags;
// get the most kills
for(i=0;i<tlNum;i++)
{
frags = get_user_frags(topLevel[i]);
if(frags >= highestKills)
highestKills = frags;
}
new topKillers[32], tkNum;
// get all of the players with highest kills
for(i=0;i<tlNum;i++)
{
if(get_user_frags(topLevel[i]) == highestKills)
topKillers[tkNum++] = topLevel[i];
}
// only one on top kills
if(tkNum == 1) winner = topKillers[0];
else
{
new leastDeaths, deaths;
// get the least deaths
for(i=0;i<tkNum;i++)
{
deaths = cs_get_user_deaths(topKillers[i]);
if(deaths <= leastDeaths)
leastDeaths = deaths;
}
new leastDead[32], ldNum;
// get all of the players with lowest deaths
for(i=0;i<tkNum;i++)
{
if(cs_get_user_deaths(topKillers[i]) == leastDeaths)
leastDead[ldNum++] = topKillers[i];
}
leastDead[random_num(0,ldNum-1)];
}
}
// crown them
win(winner);
}
// the bomb explodes
public event_bomb_detonation()
{
if(!get_pcvar_num(gg_enabled) || get_pcvar_num(gg_bomb_defuse_lvl) != 2 || !c4planter)
return;
new id = c4planter;
c4planter = 0;
if(!is_user_connected(id)) return;
if(!equal(weapon[id],"hegrenade") && !equal(weapon[id],"knife") && level[id] < get_weapon_num())
{
change_level(id,1);
//score[id] = 0;
}
else if(is_user_alive(id)) refill_ammo(id);
}
// scenario changes
public message_scenario(msg_id,msg_dest,msg_entity)
{
// disabled
if(!get_pcvar_num(gg_enabled))
return PLUGIN_CONTINUE;
// don't override our custom display, if we have one
if(get_pcvar_num(gg_status_display))
return PLUGIN_HANDLED;
// block hostage display if we disabled objectives
else if(get_msg_args() > 1 && get_pcvar_num(gg_block_objectives))
{
new sprite[8];
get_msg_arg_string(2,sprite,7);
if(equal(sprite,"hostage"))
return PLUGIN_HANDLED;
}
return PLUGIN_CONTINUE;
}
// bomb is dropped, remember for DM
public message_bombdrop(msg_id,msg_dest,msg_entity)
{
if(get_pcvar_num(gg_enabled) && get_pcvar_num(gg_block_objectives))
return PLUGIN_HANDLED;
// you can't simply get_msg_arg_int the coords
bombStatus[0] = floatround(get_msg_arg_float(1));
bombStatus[1] = floatround(get_msg_arg_float(2));
bombStatus[2] = floatround(get_msg_arg_float(3));
bombStatus[3] = get_msg_arg_int(4);
return PLUGIN_CONTINUE;
}
// bomb is picked up, remember for DM
public message_bombpickup(msg_id,msg_dest,msg_entity)
{
bombStatus[3] = BOMB_PICKEDUP;
return PLUGIN_CONTINUE;
}
// money money money!
public message_money(msg_id,msg_dest,msg_entity)
{
if(!get_pcvar_num(gg_enabled) || !is_user_connected(msg_entity) || !is_user_alive(msg_entity))
return PLUGIN_CONTINUE;
// this now just changes the value of the message, passes it along,
// and then modifies the pdata, instead of calling another cs_set_user_money
// and sending out more messages than needed.
set_msg_arg_int(1,ARG_LONG,0); // money
set_msg_arg_int(2,ARG_BYTE,0); // flash
set_pdata_int(msg_entity,OFFSET_CSMONEY,0,OFFSET_LINUX);
return PLUGIN_CONTINUE;
}
// a corpse is to be set, stop player shells bug (thanks sawce)
public message_clcorpse(msg_id,msg_dest,msg_entity)
{
if(!get_pcvar_num(gg_enabled) || get_msg_args() < 12)
return PLUGIN_CONTINUE;
if((get_pcvar_num(gg_dm) && !get_pcvar_num(gg_dm_corpses)) || blockCorpse[get_msg_arg_int(12)])
return PLUGIN_HANDLED;
return PLUGIN_CONTINUE;
}
// remove c4 if we disabled objectives
public message_weappickup(msg_id,msg_dest,msg_entity)
{
if(!bombMap || !get_pcvar_num(gg_enabled) || !get_pcvar_num(gg_block_objectives))
return PLUGIN_CONTINUE;
if(get_msg_arg_int(1) == CSW_C4)
{
set_task(0.1,"strip_c4",msg_entity);
return PLUGIN_HANDLED;
}
return PLUGIN_CONTINUE;
}
// delay, since weappickup is slightly before we actually get the weapon
public strip_c4(id)
{
fm_strip_user_gun(id,CSW_C4);
}
// block c4 ammo message if we disabled objectives
public message_ammopickup(msg_id,msg_dest,msg_entity)
{
if(!bombMap || !get_pcvar_num(gg_enabled) || !get_pcvar_num(gg_block_objectives))
return PLUGIN_CONTINUE;
if(get_msg_arg_int(1) == 14) // C4
return PLUGIN_HANDLED;
return PLUGIN_CONTINUE;
}
// block dropped the bomb message if we disabled objectives
public message_textmsg(msg_id,msg_dest,msg_entity)
{
if(!bombMap || !get_pcvar_num(gg_enabled) || !get_pcvar_num(gg_block_objectives))
return PLUGIN_CONTINUE;
static message[16];
get_msg_arg_string(2,message,15);
if(equal(message,"#Game_bomb_drop"))
return PLUGIN_HANDLED;
return PLUGIN_CONTINUE;
}
// block hostages from appearing on radar if we disabled objectives
public message_hostagepos(msg_id,msg_dest,msg_entity)
{
if(!get_pcvar_num(gg_enabled) || !get_pcvar_num(gg_block_objectives))
return PLUGIN_CONTINUE;
return PLUGIN_HANDLED;
}
//
// LOG EVENT HOOKS
//
// someone planted the bomb
public logevent_bomb_planted()
{
if(!get_pcvar_num(gg_enabled) || !get_pcvar_num(gg_bomb_defuse_lvl) || roundEnded)
return;
new id = get_loguser_index();
if(!is_user_connected(id)) return;
if(get_pcvar_num(gg_bomb_defuse_lvl) == 2) c4planter = id;
else
{
if(!equal(weapon[id],"hegrenade") && !equal(weapon[id],"knife") && level[id] < get_weapon_num())
{
change_level(id,1);
//score[id] = 0;
}
else refill_ammo(id);
}
}
// someone defused the bomb
public logevent_bomb_defused()
{
if(!get_pcvar_num(gg_enabled) || !get_pcvar_num(gg_bomb_defuse_lvl))
return;
new id = get_loguser_index();
if(!is_user_connected(id)) return;
if(!equal(weapon[id],"hegrenade") && !equal(weapon[id],"knife") && level[id] < get_weapon_num())
{
change_level(id,1);
//score[id] = 0;
}
else refill_ammo(id);
}
// the round ends
public logevent_round_end()
{
roundEnded = 1;
}
// hostage is touched
public logevent_hostage_touched()
{
new reward = get_pcvar_num(gg_host_touch_reward);
if(!get_pcvar_num(gg_enabled) || !reward || roundEnded)
return;
new id = get_loguser_index();
if(!is_user_connected(id) || hosties[id][0] == -1) return;
hosties[id][0]++;
if(hosties[id][0] >= reward)
{
if(!equal(weapon[id],"hegrenade") && !equal(weapon[id],"knife") && level[id] < get_weapon_num())
{
// didn't level off of it
if(!change_score(id,1)) show_required_kills(id);
}
hosties[id][0] = -1;
}
}
// hostage is rescued
public logevent_hostage_rescued()
{
new reward = get_pcvar_num(gg_host_rescue_reward);
if(!get_pcvar_num(gg_enabled) || !reward || roundEnded)
return;
new id = get_loguser_index();
if(!is_user_connected(id) || hosties[id][1] == -1) return;
hosties[id][1]++;
if(hosties[id][1] >= reward)
{
if(!equal(weapon[id],"hegrenade") && !equal(weapon[id],"knife") && level[id] < get_weapon_num())
change_level(id,1);
hosties[id][1] = -1;
}
}
// hostage is killed
public logevent_hostage_killed()
{
new penalty = get_pcvar_num(gg_host_kill_penalty);
if(!get_pcvar_num(gg_enabled) || !penalty)
return;
new id = get_loguser_index();
if(!is_user_connected(id)) return;
new name[32];
get_user_name(id,name,31);
if(score[id] - penalty < 0)
gungame_print(0,id,"%L",LANG_PLAYER_C,"HK_LEVEL_DOWN",name,(level[id] > 1) ? level[id]-1 : level[id]);
else
gungame_print(0,id,"%L",LANG_PLAYER_C,"HK_SCORE_DOWN",name,penalty);
change_score(id,-penalty);
}
// someone joins a team
public logevent_team_join()
{
new id = get_loguser_index();
if(!is_user_connected(id) || (oldTeam[id] != 1 && oldTeam[id] != 2)) return;
static arg2[10];
read_logargv(2,arg2,9);
// get the new team
new newTeam;
if(equal(arg2,"TERRORIST")) newTeam = 1;
else if(equal(arg2,"CT")) newTeam = 2;
// didn't switch teams, too bad for you (suicide)
if(!newTeam || oldTeam[id] == newTeam)
return;
// check to see if the team change was beneficial
if(get_pcvar_num(gg_allow_changeteam) == 2)
{
new teamCount[2], i;
for(i=1;i<=maxPlayers;i++)
{
if(!is_user_connected(i))
continue;
switch(cs_get_user_team(i))
{
case CS_TEAM_T: teamCount[0]++;
case CS_TEAM_CT: teamCount[1]++;
}
}
if(teamCount[newTeam-1] <= teamCount[oldTeam[id]-1])
remove_task(TASK_DELAYED_SUICIDE+id);
}
else remove_task(TASK_DELAYED_SUICIDE+id);
}
//
// COMMAND HOOKS
//
// turning GunGame on or off
public cmd_gungame(id,level,cid)
{
// no access, or GunGame ending anyway
if(!cmd_access(id,level,cid,2) || won)
return PLUGIN_HANDLED;
// already working on toggling GunGame
if(task_exists(TASK_TOGGLE_GUNGAME + TOGGLE_FORCE)
|| task_exists(TASK_TOGGLE_GUNGAME + TOGGLE_DISABLE)
|| task_exists(TASK_TOGGLE_GUNGAME + TOGGLE_ENABLE))
{
console_print(id,"[GunGame] GunGame is already being turned on or off");
return PLUGIN_HANDLED;
}
new arg[32], oldStatus = get_pcvar_num(gg_enabled), newStatus;
read_argv(1,arg,31);
if(equali(arg,"on") || str_to_num(arg))
newStatus = 1;
// no change
if((!oldStatus && !newStatus) || (oldStatus && newStatus))
{
console_print(id,"[GunGame] GunGame is already %s!",(newStatus) ? "on" : "off");
return PLUGIN_HANDLED;
}
set_task(4.8,"toggle_gungame",TASK_TOGGLE_GUNGAME+newStatus);
set_cvar_num("sv_restartround",5);
if(!newStatus) set_pcvar_num(gg_enabled,0);
console_print(id,"[GunGame] Turned GunGame %s",(newStatus) ? "on" : "off");
return PLUGIN_HANDLED;
}
// voting for GunGame
public cmd_gungame_vote(id,lvl,cid)
{
if(!cmd_access(id,lvl,cid,1))
return PLUGIN_HANDLED;
autovote_start();
console_print(id,"[GunGame] Started a vote to play GunGame");
return PLUGIN_HANDLED;
}
// setting players levels
public cmd_gungame_level(id,lvl,cid)
{
if(!cmd_access(id,lvl,cid,3))
return PLUGIN_HANDLED;
new arg1[32], arg2[32], targets[32], name[32], tnum, i;
read_argv(1,arg1,31);
read_argv(2,arg2,31);
// get player list
if(equali(arg1,"*") || equali(arg1,"@ALL"))
{
get_players(targets,tnum);
name = "ALL PLAYERS";
}
else if(equali(arg1,"@TERRORIST") || equali(arg1,"@CT"))
{
new players[32], team[32], pnum;
get_players(players,pnum);
for(i=0;i<pnum;i++)
{
get_user_team(players[i],team,31);
if(equali(team,arg1[1])) targets[tnum++] = players[i];
}
formatex(name,31,"ALL %s",arg1[1]);
}
else
{
targets[tnum++] = cmd_target(id,arg1,2);
if(!targets[0]) return PLUGIN_HANDLED;
get_user_name(targets[0],name,31);
}
new intval = str_to_num(arg2);
// relative
if(arg2[0] == '+' || arg2[0] == '-')
for(i=0;i<tnum;i++) change_level(targets[i],intval,0,1,1);
// absolute
else
for(i=0;i<tnum;i++) change_level(targets[i],intval-level[targets[i]],0,1,1);
console_print(id,"[GunGame] Changed %s's level to %s",name,arg2);
return PLUGIN_HANDLED;
}
// block fullupdate
public cmd_fullupdate(id)
{
return PLUGIN_HANDLED;
}
// hook say
public cmd_say(id)
{
if(!get_pcvar_num(gg_enabled)) return PLUGIN_CONTINUE;
static message[256];
read_argv(1,message,255);
// doesn't begin with !, ignore
if(message[0] != '!') return PLUGIN_CONTINUE;
if(equali(message,"!rules") || equali(message,"!help"))
{
new num = 1, max_lvl = get_pcvar_num(gg_max_lvl), turbo = get_pcvar_num(gg_turbo);
console_print(id,"-----------------------------");
console_print(id,"-----------------------------");
console_print(id,"*** Avalanche's %L %s %L ***",id,"GUNGAME",GG_VERSION,id,"RULES");
console_print(id,"%L",id,"RULES_CONSOLE_LINE1",num++);
console_print(id,"%L",id,"RULES_CONSOLE_LINE2",num++);
if(get_pcvar_num(gg_bomb_defuse_lvl)) console_print(id,"%L",id,"RULES_CONSOLE_LINE3",num++);
console_print(id,"%L",id,"RULES_CONSOLE_LINE4",num++);
if(get_pcvar_num(gg_ff_auto)) console_print(id,"%L",id,"RULES_CONSOLE_LINE5",num++);
if(turbo || !max_lvl) console_print(id,"%L",id,"RULES_CONSOLE_LINE6A",num++);
else if(max_lvl == 1) console_print(id,"%L",id,"RULES_CONSOLE_LINE6B",num++);
else if(max_lvl > 1) console_print(id,"%L",id,"RULES_CONSOLE_LINE6C",num++,max_lvl);
console_print(id,"%L",id,"RULES_CONSOLE_LINE7",num++);
if(get_pcvar_num(gg_knife_pro)) console_print(id,"%L",id,"RULES_CONSOLE_LINE8",num++);
if(turbo) console_print(id,"%L",id,"RULES_CONSOLE_LINE9",num++);
if(get_pcvar_num(gg_dm) || get_cvar_num("csdm_active")) console_print(id,"%L",id,"RULES_CONSOLE_LINE10",num++);
console_print(id,"****************************************************************");
console_print(id,"%L",id,"RULES_CONSOLE_LINE11");
console_print(id,"%L",id,"RULES_CONSOLE_LINE12");
console_print(id,"%L",id,"RULES_CONSOLE_LINE13");
console_print(id,"%L",id,"RULES_CONSOLE_LINE14");
console_print(id,"%L",id,"RULES_CONSOLE_LINE15");
console_print(id,"-----------------------------");
console_print(id,"-----------------------------");
len = formatex(menuText,511,"%L^n",id,"RULES_MESSAGE_LINE1");
len += formatex(menuText[len],511-len,"\d----------\w^n");
len += formatex(menuText[len],511-len,"%L^n",id,"RULES_MESSAGE_LINE2");
len += formatex(menuText[len],511-len,"\d----------\w^n");
len += formatex(menuText[len],511-len,"%L^n",id,"RULES_MESSAGE_LINE3");
len += formatex(menuText[len],511-len,"\d----------\w^n%L",id,"PRESS_KEY_TO_CONTINUE");
show_menu(id,1023,menuText);
return PLUGIN_HANDLED;
}
else if(equali(message,"!weapons") || equali(message,"!guns"))
{
page[id] = 1;
show_weapons_menu(id);
return PLUGIN_HANDLED;
}
else if(equali(message,"!top10"))
{
get_pcvar_string(gg_stats_file,sfFile,63);
// stats disabled
if(!sfFile[0] || !get_pcvar_num(gg_stats_mode))
{
client_print(id,print_chat,"%L",id,"NO_WIN_LOGGING");
return PLUGIN_HANDLED;
}
page[id] = 1;
show_top10_menu(id);
return PLUGIN_HANDLED;
}
else if(equali(message,"!score") || equali(message,"!scores"))
{
page[id] = 1;
show_scores_menu(id);
return PLUGIN_HANDLED;
}
else if(equali(message,"!level"))
{
show_level_menu(id);
return PLUGIN_HANDLED;
}
else if(equali(message,"!restart") || equali(message,"!reset"))
{
if(level[id] <= 1)
{
client_print(id,print_chat,"%L",id,"STILL_LEVEL_ONE");
return PLUGIN_HANDLED;
}
len = formatex(menuText,511,"%L^n^n",id,"RESET_QUERY");
len += formatex(menuText[len],511-len,"1. %L^n",id,"YES");
len += formatex(menuText[len],511-len,"0. %L",id,"CANCEL");
show_menu(id,MENU_KEY_1|MENU_KEY_0,menuText,-1,"restart_menu");
return PLUGIN_HANDLED;
}
return PLUGIN_CONTINUE;
}
// joining a team
public cmd_joinclass(id)
{
if(!get_pcvar_num(gg_enabled))
return PLUGIN_CONTINUE;
// allow us to join in on deathmatch
if(!get_pcvar_num(gg_dm))
{
remove_task(TASK_CHECK_DEATHMATCH+id);
set_task(10.0,"check_deathmatch",TASK_CHECK_DEATHMATCH+id);
return PLUGIN_CONTINUE;
}
if(roundEnded || (bombStatus[3] == BOMB_PLANTED && !get_pcvar_num(gg_dm_spawn_afterplant)))
return PLUGIN_CONTINUE;
set_task(2.0,"check_joinclass",id);
return PLUGIN_CONTINUE;
}
// wait a bit after joinclass to see if we should jump in
public check_joinclass(id)
{
if(!is_user_connected(id)) return;
// already respawning
if(task_exists(TASK_RESPAWN+id) || task_exists(TASK_CHECK_RESPAWN+id)
|| task_exists(TASK_CHECK_RESPAWN2+id) || is_user_alive(id))
return;
// not on a valid team
new CsTeams:team = cs_get_user_team(id);
if(team == CS_TEAM_UNASSIGNED || team == CS_TEAM_SPECTATOR) return;
set_task(0.1,"respawn",TASK_RESPAWN+id);
}
//
// MENU FUNCTIONS
//
// toggle the status of gungame
public toggle_gungame(taskid)
{
new status = taskid-TASK_TOGGLE_GUNGAME, i;
// clear player tasks and values
for(i=1;i<=32;i++)
{
remove_task(TASK_RESPAWN+i);
remove_task(TASK_CHECK_RESPAWN+i);
remove_task(TASK_CHECK_RESPAWN2+i);
remove_task(TASK_CHECK_DEATHMATCH+i);
remove_task(TASK_REMOVE_PROTECTION+i);
clear_values(i);
}
// clear temp saves
for(i=0;i<TEMP_SAVES;i++) clear_save(TASK_CLEAR_SAVE+i);
if(status == TOGGLE_FORCE || status == TOGGLE_ENABLE)
{
new cfgFile[64];
get_gg_config_file(cfgFile,63);
// run the gungame config
if(cfgFile[0] && file_exists(cfgFile))
{
new command[512], file, i;
file = fopen(cfgFile,"rt");
while(file && !feof(file))
{
fgets(file,command,511);
trim(command);
// stop at a comment
for(i=0;i<strlen(command)-2;i++)
{
// only check config-style (;) comments as first character,
// since they could be used ie in gg_map_setup to separate
// commands. also check for coding-style (//) comments
if((i == 0 && command[i] == ';') || (command[i] == '/' && command[i+1] == '/'))
{
copy(command,i,command);
break;
}
}
// don't override our setting from amx_gungame
if(containi(command,"gg_enabled") != -1 && status == TOGGLE_ENABLE)
continue;
trim(command);
if(command[0]) server_cmd(command);
}
if(file) fclose(file);
}
}
// set to what we chose from amx_gungame
if(status != TOGGLE_FORCE) set_pcvar_num(gg_enabled,status);
// execute all of those cvars that we just set
server_exec();
// run appropiate cvars
map_start_cvars();
// reset some things
if(!get_pcvar_num(gg_enabled))
{
// clear HUD message
if(warmup > 0)
{
set_hudmessage(255,255,255,-1.0,0.4,0,6.0,1.0,0.1,0.2,CHANNEL_WARMUP);
show_hudmessage(0," ");
}
warmup = -1;
voted = 0;
won = 0;
remove_task(TASK_WARMUP_CHECK);
}
stats_get_top_players(TOP_PLAYERS,top10,80);
// game_player_equip
manage_equips();
}
// run cvars that should be run on map start
public map_start_cvars()
{
new setup[512];
// gungame is disabled, run endmap_setup
if(!get_pcvar_num(gg_enabled))
{
get_pcvar_string(gg_endmap_setup,setup,511);
if(setup[0]) server_cmd(setup);
}
else
{
// run map setup
get_pcvar_string(gg_map_setup,setup,511);
if(setup[0]) server_cmd(setup);
// warmup is -13 after its finished, this stops multiple warmups for multiple map iterations
new warmup_value = get_pcvar_num(gg_warmup_timer_setting);
if(warmup_value > 0 && warmup != -13)
{
warmup = warmup_value;
set_task(0.1,"warmup_check",TASK_WARMUP_CHECK);
}
// random weapon orders
do_rOrder();
}
}
// select a random weapon order
do_rOrder()
{
new i, maxRandom, cvar[20];
for(i=1;i<=MAX_WEAPON_ORDERS+1;i++) // +1 so we can detect final
{
formatex(cvar,19,"gg_weapon_order%i",i);
get_cvar_string(cvar,weaponOrder,415);
trim(weaponOrder);
// found a blank one, stop here
if(!weaponOrder[0])
{
maxRandom = i - 1;
break;
}
}
// we found some random ones
if(maxRandom)
{
new randomOrder[30], lastOIstr[6], lastOI, orderAmt;
get_localinfo("gg_rand_order",randomOrder,29);
get_localinfo("gg_last_oi",lastOIstr,5);
lastOI = str_to_num(lastOIstr);
orderAmt = get_rOrder_amount(randomOrder);
// no random order yet, or amount of random orders changed
if(!randomOrder[0] || orderAmt != maxRandom)
{
shuffle_rOrder(randomOrder,29,maxRandom);
lastOI = 0;
}
// reached the end, reshuffle while avoiding this one
else if(get_rOrder_index_val(orderAmt,randomOrder) == get_rOrder_index_val(lastOI,randomOrder))
{
shuffle_rOrder(randomOrder,29,maxRandom,lastOI);
lastOI = 0;
}
new choice = get_rOrder_index_val(lastOI+1,randomOrder);
// get its weapon order
formatex(cvar,19,"gg_weapon_order%i",choice);
get_cvar_string(cvar,weaponOrder,415);
// set as current
set_cvar_string("gg_weapon_order",weaponOrder);
// remember for next time
num_to_str(lastOI+1,lastOIstr,5);
set_localinfo("gg_last_oi",lastOIstr);
}
}
// get the value of an order index in an order string
get_rOrder_index_val(index,randomOrder[])
{
// only one listed
if(str_count(randomOrder,',') < 1)
return str_to_num(randomOrder);
// find preceding comma
new search = str_find_num(randomOrder,',',index-1);
// go until succeeding comma
new extract[6];
copyc(extract,5,randomOrder[search+1],',');
return str_to_num(extract);
}
// gets the amount of orders in an order string
get_rOrder_amount(randomOrder[])
{
return str_count(randomOrder,',')+1;
}
// shuffle up our random order
stock shuffle_rOrder(randomOrder[],len,maxRandom,avoid=-1)
{
randomOrder[0] = 0;
// fill up array with order indexes
new order[MAX_WEAPON_ORDERS], i;
for(i=0;i<maxRandom;i++) order[i] = i+1;
// shuffle it
SortCustom1D(order,maxRandom,"sort_shuffle");
// avoid a specific number as the starting number
while(avoid > 0 && order[0] == avoid)
SortCustom1D(order,maxRandom,"sort_shuffle");
// get them into a string
for(i=0;i<maxRandom;i++)
{
format(randomOrder,len,"%s%s%i",randomOrder,(i>0) ? "," : "",order[i]);
set_localinfo("gg_rand_order",randomOrder);
}
}
// shuffle an array
public sort_shuffle(elem1,elem2)
{
return random_num(-1,1);
}
// handle the welcome menu
public welcome_menu_handler(id,key)
{
// just save welcomed status and let menu close
welcomed[id] = 1;
return PLUGIN_HANDLED;
}
// this menu does nothing but display stuff
public level_menu_handler(id,key)
{
return PLUGIN_HANDLED;
}
// handle the reset level menu
public restart_menu_handler(id,key)
{
if(level[id] <= 1)
{
client_print(id,print_chat,"%L",id,"STILL_LEVEL_ONE");
return PLUGIN_HANDLED;
}
// 1. Yes
if(key == 0)
{
new name[32];
get_user_name(id,name,31);
change_level(id,-(level[id]-1)); // back to level 1
gungame_print(0,id,"%L",LANG_PLAYER_C,"PLAYER_RESET",name);
}
return PLUGIN_HANDLED;
}
// show the level display
show_level_menu(id)
{
new goal, tied, leaderNum, leaderList[128], name[32];
new bestLevel, bestPlayer = get_leader(bestLevel);
len = 0;
new players[32], num, i;
get_players(players,num);
if(bestPlayer == id)
{
// check for ties first
for(i=0;i<num;i++)
{
if(level[players[i]] == level[id] && players[i] != id)
{
tied = 1;
break;
}
}
}
else if(level[bestPlayer] == level[id]) tied = 1;
// check for multiple leaders
for(i=0;i<num;i++)
{
if(level[players[i]] == bestLevel)
{
if(++leaderNum == 5)
{
len += formatex(leaderList[len],127-len,", ...");
break;
}
if(leaderList[0]) len += formatex(leaderList[len],127-len,", ");
get_user_name(players[i],name,31);
len += formatex(leaderList[len],127-len,"%s",name);
}
}
goal = get_level_goal(level[id]);
new displayWeapon[16];
if(level[id]) formatex(displayWeapon,15,"%s",weapon[id]);
else formatex(displayWeapon,15,"%L",id,"NONE");
len = formatex(menuText,511,"%L %i (%s)^n",id,"ON_LEVEL",level[id],displayWeapon);
len += formatex(menuText[len],511-len,"%L^n",id,"LEVEL_MESSAGE_LINE1",score[id],goal);
if(bestPlayer == id && !tied) len += formatex(menuText[len],511-len,"%L^n",id,"LEVEL_MESSAGE_LINE2A");
else if(tied) len += formatex(menuText[len],511-len,"%L^n",id,"LEVEL_MESSAGE_LINE2B");
else len += formatex(menuText[len],511-len,"%L^n",id,"LEVEL_MESSAGE_LINE2C",bestLevel-level[id]);
len += formatex(menuText[len],511-len,"\d----------\w^n");
new authid[24], wins, points;
if(get_pcvar_num(gg_stats_ip)) get_user_ip(id,authid,23);
else get_user_authid(id,authid,23);
stats_get_data(authid,wins,points,dummy,1,dummy[0]);
new stats_mode = get_pcvar_num(gg_stats_mode);
if(stats_mode)
{
if(stats_mode == 1) len += formatex(menuText[len],511-len,"%L^n",id,"LEVEL_MESSAGE_LINE3A",wins);
else len += formatex(menuText[len],511-len,"%L (%i %L)^n",id,"LEVEL_MESSAGE_LINE3B",points,wins,id,"WINS");
len += formatex(menuText[len],511-len,"\d----------\w^n");
}
if(leaderNum > 1) len += formatex(menuText[len],511-len,"%L^n",id,"LEVEL_MESSAGE_LINE4A",leaderList);
else len += formatex(menuText[len],511-len,"%L^n",id,"LEVEL_MESSAGE_LINE4B",leaderList);
if(level[bestPlayer]) formatex(displayWeapon,15,"%s",weapon[bestPlayer]);
else formatex(displayWeapon,15,"%L",id,"NONE");
len += formatex(menuText[len],511-len,"%L^n",id,"LEVEL_MESSAGE_LINE5",bestLevel,displayWeapon);
len += formatex(menuText[len],511-len,"\d----------\w^n");
len += formatex(menuText[len],511-len,"%L",id,"PRESS_KEY_TO_CONTINUE");
show_menu(id,1023,menuText,-1,"level_menu");
}
// show the top10 list menu
show_top10_menu(id)
{
new totalPlayers = TOP_PLAYERS, playersPerPage = 5, stats_mode = get_pcvar_num(gg_stats_mode);
new pageTotal = floatround(float(totalPlayers) / float(playersPerPage),floatround_ceil);
if(page[id] < 1) page[id] = 1;
if(page[id] > pageTotal) page[id] = pageTotal;
len = formatex(menuText,511-len,"\y%L %L (%i/%i)\w^n",id,"GUNGAME",id,"TOP_10",page[id],pageTotal);
//len += formatex(menuText[len],511-len,"\d-----------\w^n");
static top10listing[81];
new start = (playersPerPage * (page[id]-1)), i;
for(i=start;i<start+playersPerPage;i++)
{
if(i > totalPlayers) break;
// blank
if(!top10[i][0])
{
len += formatex(menuText[len],511-len,"#%i \d%L\w^n",i+1,id,"NONE");
continue;
}
// assign it to a new variable so that strtok
// doesn't tear apart our constant top10 variable
top10listing = top10[i];
// get rid of authid
strtok(top10listing,sfAuthid,1,top10listing,80,'^t');
// isolate wins
strtok(top10listing,sfWins,5,top10listing,80,'^t');
// isolate name
strtok(top10listing,sfName,31,top10listing,80,'^t');
// break off timestamp and get points
strtok(top10listing,sfTimestamp,1,sfPoints,7,'^t');
if(stats_mode == 1)
len += formatex(menuText[len],511-len,"#%i %s (%s %L)^n",i+1,sfName,sfWins,id,"WINS");
else
len += formatex(menuText[len],511-len,"#%i %s (%i %L, %s %L)^n",i+1,sfName,str_to_num(sfPoints),id,"POINTS",sfWins,id,"WINS");
}
len += formatex(menuText[len],511-len,"\d-----------\w^n");
new keys = MENU_KEY_0;
if(page[id] > 1)
{
len += formatex(menuText[len],511-len,"1. %L^n",id,"PREVIOUS");
keys |= MENU_KEY_1;
}
if(page[id] < pageTotal)
{
len += formatex(menuText[len],511-len,"2. %L^n",id,"NEXT");
keys |= MENU_KEY_2;
}
len += formatex(menuText[len],511-len,"0. %L",id,"CLOSE");
show_menu(id,keys,menuText,-1,"top10_menu");
}
// someone pressed a key on the top10 list menu page
public top10_menu_handler(id,key)
{
new totalPlayers = TOP_PLAYERS, playersPerPage = 5;
new pageTotal = floatround(float(totalPlayers) / float(playersPerPage),floatround_ceil);
if(page[id] < 1 || page[id] > pageTotal) return;
// 1. Previous
if(key == 0)
{
page[id]--;
show_top10_menu(id);
return;
}
// 2. Next
else if(key == 1)
{
page[id]++;
show_top10_menu(id);
return;
}
// 0. Close
// do nothing, menu closes automatically
}
// show the weapon list menu
show_weapons_menu(id)
{
new totalWeapons = get_weapon_num(), wpnsPerPage = 10;
new pageTotal = floatround(float(totalWeapons) / float(wpnsPerPage),floatround_ceil);
if(page[id] < 1) page[id] = 1;
if(page[id] > pageTotal) page[id] = pageTotal;
len = formatex(menuText,511-len,"\y%L %L (%i/%i)\w^n",id,"GUNGAME",id,"WEAPONS",page[id],pageTotal);
//len += formatex(menuText[len],511-len,"\d-----------\w^n");
new start = (wpnsPerPage * (page[id]-1)) + 1, i, wName[24];
// are there any custom kill requirements?
get_pcvar_string(gg_weapon_order,weaponOrder,415);
new customKills = (containi(weaponOrder,":") != -1);
for(i=start;i<start+wpnsPerPage;i++)
{
if(i > totalWeapons) break;
get_weapon_name_by_level(i,wName,23);
if(customKills)
len += formatex(menuText[len],511-len,"%L %i: %s (%i)^n",id,"LEVEL",i,wName,get_level_goal(i));
else
len += formatex(menuText[len],511-len,"%L %i: %s^n",id,"LEVEL",i,wName);
}
len += formatex(menuText[len],511-len,"\d-----------\w^n");
new keys = MENU_KEY_0;
if(page[id] > 1)
{
len += formatex(menuText[len],511-len,"1. %L^n",id,"PREVIOUS");
keys |= MENU_KEY_1;
}
if(page[id] < pageTotal)
{
len += formatex(menuText[len],511-len,"2. %L^n",id,"NEXT");
keys |= MENU_KEY_2;
}
len += formatex(menuText[len],511-len,"0. %L",id,"CLOSE");
show_menu(id,keys,menuText,-1,"weapons_menu");
}
// someone pressed a key on the weapon list menu page
public weapons_menu_handler(id,key)
{
new totalWeapons = get_weapon_num(), wpnsPerPage = 10;
new pageTotal = floatround(float(totalWeapons) / float(wpnsPerPage),floatround_ceil);
if(page[id] < 1 || page[id] > pageTotal) return;
// 1. Previous
if(key == 0)
{
page[id]--;
show_weapons_menu(id);
return;
}
// 2. Next
else if(key == 1)
{
page[id]++;
show_weapons_menu(id);
return;
}
// 0. Close
// do nothing, menu closes automatically
}
// show the score list menu
show_scores_menu(id)
{
new totalPlayers = get_playersnum(), playersPerPage = 5, stats_mode = get_pcvar_num(gg_stats_mode);
new pageTotal = floatround(float(totalPlayers) / float(playersPerPage),floatround_ceil);
if(page[id] < 1) page[id] = 1;
if(page[id] > pageTotal) page[id] = pageTotal;
new players[32], num;
get_players(players,num);
// order by highest level first
SortCustom1D(players,num,"score_custom_compare");
len = formatex(menuText,511,"\y%L %L (%i/%i)\w^n",id,"GUNGAME",id,"SCORES",page[id],pageTotal);
//len += formatex(menuText[len],511-len,"\d-----------\w^n");
new start = (playersPerPage * (page[id]-1)), i, name[32], player, authid[24], wins, points;
// check for stats
get_pcvar_string(gg_stats_file,sfFile,63);
new stats_ip = get_pcvar_num(gg_stats_ip);
for(i=start;i<start+playersPerPage;i++)
{
if(i >= totalPlayers) break;
player = players[i];
get_user_name(player,name,31);
new displayWeapon[16];
if(level[player] && weapon[player][0]) formatex(displayWeapon,15,"%s",weapon[player]);
else formatex(displayWeapon,15,"%L",id,"NONE");
if(sfFile[0] && stats_mode)
{
if(stats_ip) get_user_ip(player,authid,23);
else get_user_authid(player,authid,23);
stats_get_data(authid,wins,points,dummy,1,dummy[0]);
len += formatex(menuText[len],511-len,"#%i %s, %L %i (%s), %i %L^n",i+1,name,id,"LEVEL",level[player],displayWeapon,(stats_mode == 1) ? wins : points,id,(stats_mode == 1) ? "WINS" : "POINTS");
}
else len += formatex(menuText[len],511-len,"#%i %s, %L %i (%s)^n",i+1,name,id,"LEVEL",level[player],displayWeapon);
}
len += formatex(menuText[len],511-len,"\d-----------\w^n");
new keys = MENU_KEY_0;
if(page[id] > 1)
{
len += formatex(menuText[len],511-len,"1. %L^n",id,"PREVIOUS");
keys |= MENU_KEY_1;
}
if(page[id] < pageTotal)
{
len += formatex(menuText[len],511-len,"2. %L^n",id,"NEXT");
keys |= MENU_KEY_2;
}
len += formatex(menuText[len],511-len,"0. %L",id,"CLOSE");
show_menu(id,keys,menuText,-1,"scores_menu");
}
// sort list of players with their level first
public score_custom_compare(elem1,elem2)
{
// invalid players
if(elem1 < 1 || elem1 > 32 || elem2 < 1 || elem2 > 32)
return 0;
// tied levels, compare scores
if(level[elem1] == level[elem2])
{
if(score[elem1] > score[elem2]) return -1;
else if(score[elem1] < score[elem2]) return 1;
else return 0;
}
// compare levels
else if(level[elem1] > level[elem2]) return -1;
else if(level[elem1] < level[elem2]) return 1;
return 0; // equal
}
// someone pressed a key on the score list menu page
public scores_menu_handler(id,key)
{
new totalPlayers = get_playersnum(), playersPerPage = 5;
new pageTotal = floatround(float(totalPlayers) / float(playersPerPage),floatround_ceil);
if(page[id] < 1 || page[id] > pageTotal) return;
// 1. Previous
if(key == 0)
{
page[id]--;
show_scores_menu(id);
return;
}
// 2. Next
else if(key == 1)
{
page[id]++;
show_scores_menu(id);
return;
}
// 0. Close
// do nothing, menu closes automatically
}
//
// MAIN FUNCTIONS
//
// refresh a player's hegrenade stock
public refresh_nade(taskid)
{
new id = taskid-TASK_REFRESH_NADE;
// player left, player died, or GunGame turned off
if(!is_user_connected(id) || !is_user_alive(id) || !get_pcvar_num(gg_enabled)) return;
// not on the grenade level, or have one already
if(!equali(weapon[id],"hegrenade") || cs_get_user_bpammo(id,CSW_HEGRENADE))
return;
// give another hegrenade
fm_give_item(id,"weapon_hegrenade");
}
// keep checking if a player needs to rejoin
public check_deathmatch(taskid)
{
new id = taskid-TASK_CHECK_DEATHMATCH;
// left the game, or gungame is now disabled
if(!is_user_connected(id) || !get_pcvar_num(gg_enabled)) return;
// now on spectator
new CsTeams:team = cs_get_user_team(id);
if(team == CS_TEAM_UNASSIGNED || team == CS_TEAM_SPECTATOR) return;
// DM still not enabled, keep waiting
if(!get_pcvar_num(gg_dm))
{
set_task(10.0,"check_deathmatch",taskid);
return;
}
// DM is enabled, respawn
if(!is_user_alive(id)) set_task(0.1,"respawn",TASK_RESPAWN+id);
}
// show someone a welcome message
public show_welcome(id)
{
if(welcomed[id]) return;
new menuid, keys;
get_user_menu(id,menuid,keys);
// another old-school menu opened
if(menuid > 0)
{
// wait and try again
set_task(3.0,"show_welcome",id);
return;
}
play_sound_by_cvar(id,gg_sound_welcome);
len = formatex(menuText,511,"\y%L\w^n",id,"WELCOME_MESSAGE_LINE1",GG_VERSION);
len += formatex(menuText[len],511-len,"\d---------------\w^n");
new special;
if(get_pcvar_num(gg_knife_pro))
{
len += formatex(menuText[len],511-len,"%L^n",id,"WELCOME_MESSAGE_LINE2");
special = 1;
}
if(get_pcvar_num(gg_turbo))
{
len += formatex(menuText[len],511-len,"%L^n",id,"WELCOME_MESSAGE_LINE3");
special = 1;
}
if(get_pcvar_num(gg_dm) || get_cvar_num("csdm_active"))
{
len += formatex(menuText[len],511-len,"%L^n",id,"WELCOME_MESSAGE_LINE4");
special = 1;
}
if(special) len += formatex(menuText[len],511-len,"\d---------------\w^n");
len += formatex(menuText[len],511-len,"%L",id,"WELCOME_MESSAGE_LINE5");
len += formatex(menuText[len],511-len,"\d---------------\w^n");
len += formatex(menuText[len],511-len,"%L",id,"PRESS_KEY_TO_CONTINUE");
show_menu(id,1023,menuText,-1,"welcome_menu");
}
// show the required kills message
show_required_kills(id)
{
gungame_hudmessage(id,3.0,"%L, %i/%i",id,"REQUIRED_KILLS",score[id],get_level_goal(level[id]));
}
// player killed himself
player_suicided(id)
{
// we still have protection (round ended, new one hasn't started yet)
if(roundEnded) return;
static name[32];
get_user_name(id,name,31);
gungame_print(0,id,"%L",LANG_PLAYER_C,"SUICIDE_LEVEL_DOWN",name);
// decrease level if we can
change_level(id,-1);
}
// player scored or lost a point
public change_score(id,value)
{
if(!can_score(id)) return 0;
new oldScore = score[id], goal = get_level_goal(level[id]);
// if this is going to level us
if(score[id] + value >= goal)
{
new max_lvl = get_pcvar_num(gg_max_lvl);
// already reached max levels this round
if(!get_pcvar_num(gg_turbo) && max_lvl > 0 && levelsThisRound[id] >= max_lvl)
{
// put it as high as we can without leveling
score[id] = goal - 1;
}
else score[id] += value;
}
else score[id] += value;
// check for level up
if(score[id] >= goal)
{
score[id] = 0;
change_level(id,1);
return 1;
}
// check for level down
if(score[id] < 0)
{
goal = get_level_goal(level[id] > 1 ? level[id]-1 : 1);
score[id] = (oldScore + value) + goal; // carry over points
if(score[id] < 0) score[id] = 0;
//if(level[id] > 1)
change_level(id,-1);
return -1;
}
// refresh menus
new menu;
get_user_menu(id,menu,dummy[0]);
if(menu == level_menu) show_level_menu(id);
new sdisplay = get_pcvar_num(gg_status_display);
if(sdisplay == STATUS_KILLSLEFT || sdisplay == STATUS_KILLSDONE)
status_display(id);
if(value < 0)
show_required_kills(id);
else
client_cmd(id,"speak ^"buttons/bell1.wav^"");
if(get_pcvar_num(gg_refill_on_kill)) refill_ammo(id);
return 0;
}
// player gained or lost a level
stock change_level(id,value,just_joined=0,show_message=1,always_score=0)
{
if(level[id] > 0 && !always_score && !can_score(id))
return;
// knife warmup, don't bother leveling up
if(level[id] > 0 && warmup > 0 && get_pcvar_num(gg_knife_warmup)) return;
// this will put us below level 1
if(level[id] + value < 1)
value = 1 - level[id]; // go down only to level 1
// going up
if(value > 0)
{
new max_lvl = get_pcvar_num(gg_max_lvl);
// already reached max levels for this round
if(!get_pcvar_num(gg_turbo) && max_lvl > 0 && levelsThisRound[id] >= max_lvl)
return;
}
level[id] += value;
levelsThisRound[id] += value;
// level up!
if(value > 0) play_sound_by_cvar(id,gg_sound_levelup);
// level down :(
else play_sound_by_cvar(id,gg_sound_leveldown);
// grab my name
static name[32];
get_user_name(id,name,31);
// win???
if(level[id] >= get_weapon_num()+1)
{
// still warming up (wow, this guy is good)
if(warmup > 0)
{
change_level(id,-value,just_joined);
client_print(id,print_chat,"%L",id,"SLOW_DOWN");
client_print(id,print_center,"%L",id,"SLOW_DOWN");
return;
}
// bot, and not allowed to win
if(is_user_bot(id) && get_pcvar_num(gg_ignore_bots) == 2 && !only_bots())
{
change_level(id,-value,just_joined);
return;
}
// crown the winner
if(!won) win(id);
return;
}
silenced[id] = 0; // for going to Glock->USP, for example
// set weapon based on it
get_weapon_name_by_level(level[id],weapon[id],23);
new players[32], num, i, menu;
get_players(players,num);
// refresh menus
for(i=0;i<num;i++)
{
get_user_menu(players[i],menu,dummy[0]);
if(menu == scores_menu) show_scores_menu(players[i]);
else if(menu == level_menu) show_level_menu(players[i]);
}
// make sure we don't have more than required now
new goal = get_level_goal(level[id]);
if(score[id] >= goal) score[id] = goal-1; // 1 under
// status display
new sdisplay = get_pcvar_num(gg_status_display);
if(sdisplay == STATUS_LEADERWPN) status_display(0); // to all
else if(sdisplay) status_display(id); // only to me
// give weapon right away?
new turbo = get_pcvar_num(gg_turbo);
if((turbo || just_joined) && is_user_alive(id)) set_task(0.1,"give_level_weapon_delay",id);
if(show_message) gungame_hudmessage(id,3.0,"%L %i (%s)",id,"NOW_ON_LEVEL",level[id],weapon[id]);
new vote_setting = get_pcvar_num(gg_vote_setting), map_iterations = get_pcvar_num(gg_map_iterations);
// the level to start a map vote on
if(!voted && warmup <= 0 && vote_setting > 0
&& level[id] >= get_weapon_num() - (vote_setting - 1)
&& mapIteration >= map_iterations && map_iterations > 0)
{
new mapCycleFile[64];
get_gg_mapcycle_file(mapCycleFile,63);
// start map vote?
if(!mapCycleFile[0] || !file_exists(mapCycleFile))
{
voted = 1;
// check for a custom vote
new custom[256];
get_pcvar_string(gg_vote_custom,custom,255);
if(custom[0]) server_cmd(custom);
else start_mapvote();
}
}
// only calculate position if we didn't just join
if(!just_joined)
{
new bestLevel, bestPlayer = get_leader(bestLevel);
// I'M THE BEST!!!!!!!
if(bestPlayer == id)
{
// check for ties first
new players[32], num, i, tied;
get_players(players,num);
for(i=0;i<num;i++)
{
if(level[players[i]] == level[id] && players[i] != id)
{
tied = 1;
break;
}
}
if(tied && level[id] > 1) gungame_print(0,id,"%L",LANG_PLAYER_C,"TIED_LEADER",name);
else if(level[id] > 1) gungame_print(0,id,"%L",LANG_PLAYER_C,"LEADING_ON_LEVEL",name,level[id],weapon[id]);
}
// maybe still??
else if(level[bestPlayer] == level[id])
{
if(level[id] > 1) gungame_print(0,id,"%L",LANG_PLAYER_C,"TIED_LEADER",name);
}
// awww...
else gungame_print(id,0,"%L",id,"LEVELS_BEHIND_LEADER",level[bestPlayer]-level[id]);
// triple bonus!
if(levelsThisRound[id] == 3 && get_pcvar_num(gg_triple_on) && !turbo)
{
star[id] = 1;
new sound[64];
get_pcvar_string(gg_sound_triple,sound,63);
fm_set_user_maxspeed(id,fm_get_user_maxspeed(id)*1.5);
if(sound[0]) emit_sound(id,CHAN_VOICE,sound,VOL_NORM,ATTN_NORM,0,PITCH_NORM);
set_pev(id,pev_effects,pev(id,pev_effects) | EF_BRIGHTLIGHT);
fm_set_rendering(id,kRenderFxGlowShell,255,255,100,kRenderNormal,1);
fm_set_user_godmode(id,1);
message_begin(MSG_BROADCAST,SVC_TEMPENTITY);
write_byte(22); // TE_BEAMFOLLOW
write_short(id); // entity
write_short(trailSpr); // sprite
write_byte(20); // life
write_byte(10); // width
write_byte(255); // r
write_byte(255); // g
write_byte(100); // b
write_byte(100); // brightness
message_end();
gungame_print(0,id,"%L",LANG_PLAYER_C,"TRIPLE_LEVELED",name);
set_task(10.0,"end_star",TASK_END_STAR+id);
}
}
new ff_auto = get_pcvar_num(gg_ff_auto), ff = get_cvar_num("mp_friendlyfire");
// turn on FF?
if(ff_auto && !ff && equal(weapon[id],"hegrenade"))
{
set_cvar_num("mp_friendlyfire",1);
gungame_print(0,0,"%L",LANG_PLAYER_C,"FRIENDLYFIRE_ON");
client_cmd(0,"speak ^"gungame/brass_bell_C.wav^"");
}
// turn off FF?
else if(ff_auto && ff)
{
new keepFF, i;
for(i=1;i<=maxPlayers;i++)
{
if(equal(weapon[i],"hegrenade") || equal(weapon[i],"knife"))
{
keepFF = 1;
break;
}
}
// no one is on nade or knife level anymore
if(!keepFF) set_cvar_num("mp_friendlyfire",0);
}
}
// delay before giving weapon after leveling. without this, the game
// crashes without error. note that you couldn't just set_task to
// give_level_weapon, because it has multiple parameters, and so
// set_task won't accept it.
public give_level_weapon_delay(id)
{
if(is_user_connected(id)) give_level_weapon(id,0);
}
// get rid of a player's star
public end_star(taskid)
{
new id = taskid - TASK_END_STAR;
if(!star[id]) return;
star[id] = 0;
//gungame_print(id,0,"Your star has run out!");
if(is_user_alive(id))
{
fm_set_user_maxspeed(id,fm_get_user_maxspeed(id)/1.5);
emit_sound(id,CHAN_VOICE,"common/null.wav",VOL_NORM,ATTN_NORM,0,PITCH_NORM); // stop sound
set_pev(id,pev_effects,pev(id,pev_effects) & ~EF_BRIGHTLIGHT);
fm_set_rendering(id);
fm_set_user_godmode(id,0);
message_begin(MSG_BROADCAST,SVC_TEMPENTITY);
write_byte(99); // TE_KILLBEAM
write_short(id); // entity
message_end();
}
}
// give a player a weapon based on his level
stock give_level_weapon(id,notify=1,verify=1)
{
if(!is_user_alive(id) || pev(id,pev_iuser1)) return;
give_essentials(id);
new oldWeapon = get_user_weapon(id,dummy[0],dummy[0]);
static wpnName[24];
new weapons[32], wpnid, alright, num, i;
get_user_weapons(id,weapons,num);
new hasMain, hasGlock, hasSmoke, hasFlash;
new ammo = get_pcvar_num(gg_ammo_amount);
new knife_warmup = get_pcvar_num(gg_knife_warmup);
new pickup_others = get_pcvar_num(gg_pickup_others);
new myCategory = get_weapon_category(_,weapon[id]);
new nade_glock = get_pcvar_num(gg_nade_glock);
new nade_smoke = get_pcvar_num(gg_nade_smoke);
new nade_flash = get_pcvar_num(gg_nade_flash);
// remove stuff first
for(i=0;i<num;i++)
{
wpnid = weapons[i];
if(!wpnid) continue;
// ignore knife and C4
if(wpnid == CSW_KNIFE || wpnid == CSW_C4)
continue;
alright = 0;
// if we shouldn't be doing knives only,
// check to see if we already have certain weapons
if(warmup <= 0 || !knife_warmup)
{
// check for special grenade allowances
if(equal(weapon[id],"hegrenade"))
{
if(wpnid == CSW_GLOCK18 && nade_glock)
{
alright = 1;
hasGlock = 1;
}
else if(wpnid == CSW_SMOKEGRENADE && nade_smoke)
{
alright = 1;
hasSmoke = 1;
}
else if(wpnid == CSW_FLASHBANG && nade_flash)
{
alright = 1;
hasFlash = 1;
}
}
// weapon id -> weapon name
get_weaponname(wpnid,wpnName,23);
replace(wpnName,23,"weapon_","");
// this is our designated weapon
if(equal(weapon[id],wpnName))
{
alright = 1;
hasMain = 1;
}
}
// was it alright?
if(alright)
{
// reset ammo
if(wpnid != CSW_HEGRENADE && wpnid != CSW_SMOKEGRENADE && wpnid != CSW_FLASHBANG)
{
if(equal(weapon[id],"hegrenade") && wpnid == CSW_GLOCK18)
cs_set_user_bpammo(id,wpnid,50);
else if(ammo > 0) cs_set_user_bpammo(id,wpnid,ammo);
else cs_set_user_bpammo(id,wpnid,maxAmmo[wpnid]);
}
else cs_set_user_bpammo(id,wpnid,1); // grenades
}
// only remove this if we aren't allowed to have any other weapons,
// or if it takes up the same category as the weapon that we need
else if(!pickup_others || get_weapon_category(wpnid) == myCategory)
{
// remove grenades by clearing bpammo
if(wpnid == CSW_HEGRENADE || wpnid == CSW_SMOKEGRENADE || wpnid == CSW_FLASHBANG)
{
user_has_weapon(id,wpnid,0); // remove form
cs_set_user_bpammo(id,wpnid,0); // remove function
}
// remove regular weapons with this
else fm_strip_user_gun(id,wpnid);
}
}
// give CTs defuse kits on bomb maps
if(bombMap && !get_pcvar_num(gg_block_objectives) && cs_get_user_team(id) == CS_TEAM_CT)
cs_set_user_defuse(id,1);
new armor = get_pcvar_num(gg_give_armor), helmet = get_pcvar_num(gg_give_helmet);
// giving armor and helmets away like candy
if(helmet) cs_set_user_armor(id,armor,CS_ARMOR_VESTHELM);
else cs_set_user_armor(id,armor,CS_ARMOR_KEVLAR);
// extras for grenade level
if((warmup <= 0 || !knife_warmup) && equal(weapon[id],"hegrenade"))
{
if(nade_glock && !hasGlock)
{
fm_give_item(id,"weapon_glock18");
cs_set_user_bpammo(id,CSW_GLOCK18,50);
}
if(nade_smoke && !hasSmoke) fm_give_item(id,"weapon_smokegrenade");
if(nade_flash && !hasFlash) fm_give_item(id,"weapon_flashbang");
}
if(notify)
{
if(warmup > 0)
{
if(knife_warmup) gungame_print(id,-1,"%L -- %L",id,"WARMUP_ROUND",id,"KNIVES_ONLY");
else gungame_print(id,-1,"%L",id,"WARMUP_ROUND");
}
else if(level[id] <= get_weapon_num()) // didn't just win
{
new goal = get_level_goal(level[id]);
gungame_print(id,-1,"%L %%n%i%%e :: %%n%s%%e",id,"ON_LEVEL",level[id],weapon[id]);
gungame_print(id,-1,"%L",id,"PROGRESS_DISPLAY",goal-score[id],score[id],goal);
}
//[GunGame] You are on level 9 : : tmp
//[GunGame] You need 2 kills to advance. Score : 0 / 2
}
// don't give anything away if knife-only warmup
if((warmup > 0 && knife_warmup) || equal(weapon[id],"knife"))
{
// draw knife on knife warmup and knife level... this is so that
// the terrorist that spawns with the C4 won't be spawned with his
// C4 selected, but instead his knfe
client_cmd(id,"weapon_knife");
return;
}
if(weapon[id][0] && !hasMain)
{
// stop double grenades
if(equal(weapon[id],"hegrenade") && cs_get_user_bpammo(id,CSW_HEGRENADE))
return;
formatex(wpnName,23,"weapon_%s",weapon[id]);
// make sure player gets his weapon
for(i=0;i<3;i++)
{
if(fm_give_item(id,wpnName))
break;
}
remove_task(TASK_REFRESH_NADE+id);
if(!equal(weapon[id],"hegrenade"))
{
wpnid = get_weaponid(wpnName);
if(!wpnid) log_amx("INVALID WEAPON ID FOR ^"%s^"",weapon[id]);
else
{
if(ammo > 0) cs_set_user_bpammo(id,wpnid,ammo);
else cs_set_user_bpammo(id,wpnid,maxAmmo[wpnid]);
}
}
}
// switch back to knife if we had it out. also don't do this when called
// by the verification check, because their old weapon will obviously be
// a knife and they will want to use their new one.
if(verify && oldWeapon == CSW_KNIFE && !notify) client_cmd(id,"weapon_knife");
// otherwise, switch to our new weapon
else
{
// glock18 for nade level?
if(equal(weapon[id],"hegrenade") && gg_nade_glock)
wpnName = "weapon_glock18";
else
formatex(wpnName,23,"weapon_%s",weapon[id]);
client_cmd(id,wpnName);
}
// remember burst or silenced status
if(silenced[id])
{
if(equal(weapon[id],"usp") || equal(weapon[id],"m4a1"))
{
new wEnt = get_weapon_ent(id,_,weapon[id]);
if(pev_valid(wEnt))
{
cs_set_weapon_silen(wEnt,1,0);
// play draw with silencer animation
if(weapon[id][0] == 'u') set_pev(id,pev_weaponanim,USP_DRAWANIM);
else set_pev(id,pev_weaponanim,M4A1_DRAWANIM);
}
}
else if(equal(weapon[id],"glock18") || equal(weapon[id],"famas"))
{
new wEnt = get_weapon_ent(id,_,weapon[id]);
if(pev_valid(wEnt)) cs_set_weapon_burst(wEnt,1);
}
silenced[id] = 0;
}
// make sure that we get this...
if(verify)
{
remove_task(TASK_VERIFY_WEAPON+id);
set_task(1.0,"verify_weapon",TASK_VERIFY_WEAPON+id);
}
}
// verify that we have our stupid weapon
public verify_weapon(taskid)
{
new id = taskid-TASK_VERIFY_WEAPON;
if(!is_user_alive(id)) return;
static wpnName[24];
formatex(wpnName,23,"weapon_%s",weapon[id]);
new wpnid = get_weaponid(wpnName);
if(!wpnid) return;
// we don't have it, but we want it
if((wpnid != CSW_HEGRENADE && !user_has_weapon(id,wpnid))
|| (wpnid == CSW_HEGRENADE && !cs_get_user_bpammo(id,CSW_HEGRENADE)))
give_level_weapon(id,0,0);
}
// bring someone back to life
public begin_respawn(id)
{
if(!get_pcvar_num(gg_enabled) || !get_pcvar_num(gg_dm) || !is_user_connected(id))
return;
// now on spectator
new CsTeams:team = cs_get_user_team(id);
if(team == CS_TEAM_UNASSIGNED || team == CS_TEAM_SPECTATOR) return;
// alive, and not in the broken sort of way
if(is_user_alive(id) && !pev(id,pev_iuser1)) return;
// round is over, or bomb is planted
if(roundEnded || (bombStatus[3] == BOMB_PLANTED && !get_pcvar_num(gg_dm_spawn_afterplant)))
return;
new Float:delay = get_pcvar_float(gg_dm_spawn_delay);
if(delay < 0.1) delay = 0.1;
new dm_countdown = get_pcvar_num(gg_dm_countdown);
if((dm_countdown & 1) || (dm_countdown & 2))
{
respawn_timeleft[id] = floatround(delay);
respawn_countdown(id);
}
remove_task(TASK_RESPAWN+id);
set_task(delay,"respawn",TASK_RESPAWN+id);
}
// show the respawn countdown to a player
public respawn_countdown(id)
{
if(!is_user_connected(id) || is_user_alive(id))
{
respawn_timeleft[id] = 0;
return;
}
new dm_countdown = get_pcvar_num(gg_dm_countdown);
if(dm_countdown & 1)
client_print(id,print_center,"%L",id,"RESPAWN_COUNTDOWN",respawn_timeleft[id]);
if(dm_countdown & 2)
gungame_hudmessage(id,1.0,"%L",id,"RESPAWN_COUNTDOWN",respawn_timeleft[id]);
if(--respawn_timeleft[id] >= 1) set_task(1.0,"respawn_countdown",id);
}
// REALLY bring someone back to life
public respawn(taskid)
{
new id = taskid-TASK_RESPAWN;
if(!is_user_connected(id) || !get_pcvar_num(gg_enabled)) return;
// round is over, or bomb is planted
if(roundEnded || (bombStatus[3] == BOMB_PLANTED && !get_pcvar_num(gg_dm_spawn_afterplant)))
return;
// now on spectator
new CsTeams:team = cs_get_user_team(id);
if(team == CS_TEAM_UNASSIGNED || team == CS_TEAM_SPECTATOR) return;
// clear countdown
new dm_countdown = get_pcvar_num(gg_dm_countdown);
if(dm_countdown & 1) client_print(id,print_center," ");
if(dm_countdown & 2) gungame_hudmessage(id,1.0," ");
// alive, and not in the broken sort of way
if(is_user_alive(id) && !pev(id,pev_iuser1)) return;
// remove his dropped weapons from before
new ent;
static model[22];
while((ent = fm_find_ent_by_class(ent,"weaponbox")) != 0)
{
pev(ent,pev_model,model,21);
// don't remove the bomb!! (thanks ToT | V!PER)
if(equal(model,"models/w_c4.mdl",15) || equal(model,"models/w_backpack.mdl"))
continue;
// this is mine
if(pev(ent,pev_owner) == id)
dllfunc(DLLFunc_Think,ent);
}
new spawn_random = get_pcvar_num(gg_dm_spawn_random);
if(spawn_random) spawnSounds[id] = 0;
if(csrespawnEnabled)
cs_respawn(id);
else
{
// properly respawn
blockCorpse[id] = 1;
fm_cs_user_spawn(id);
// make sure they made it
remove_task(TASK_CHECK_RESPAWN+id);
remove_task(TASK_CHECK_RESPAWN2+id);
set_task(0.5,"check_respawn",TASK_CHECK_RESPAWN+id);
set_task(1.5,"check_respawn",TASK_CHECK_RESPAWN2+id);
}
if(spawn_random)
{
do_random_spawn(id,spawn_random);
spawnSounds[id] = 1;
// to be fair, play a spawn noise at new location
engfunc(EngFunc_EmitSound,id,CHAN_ITEM,"items/gunpickup2.wav",VOL_NORM,ATTN_NORM,0,PITCH_NORM);
}
new Float:time = get_pcvar_float(gg_dm_sp_time);
new mode = get_pcvar_num(gg_dm_sp_mode);
// spawn protection
if(time > 0.0 && mode)
{
spawnProtected[id] = 1;
if(mode == 2)
{
fm_set_user_godmode(id,1);
fm_set_rendering(id,kRenderFxGlowShell,200,200,100,kRenderNormal,1); // goldenish
}
else fm_set_rendering(id,kRenderFxGlowShell,100,100,100,kRenderNormal,1); // gray/white
set_task(time,"remove_spawn_protection",TASK_REMOVE_PROTECTION+id);
}
}
// place a user at a random spawn
do_random_spawn(id,spawn_random)
{
// not even alive, don't brother
if(!is_user_alive(id) || pev(id,pev_iuser1))
return;
// no spawns???
if(spawnCount <= 0) return;
// no CSDM spawns, mode 2
if(spawn_random == 2 && !csdmSpawnCount)
return;
static Float:vecHolder[3];
new sp_index = random_num(0,spawnCount-1);
// get origin for comparisons
vecHolder[0] = spawns[sp_index][0];
vecHolder[1] = spawns[sp_index][1];
vecHolder[2] = spawns[sp_index][2];
// this one is taken
if(!is_hull_vacant(vecHolder,HULL_HUMAN) && spawnCount > 1)
{
new i;
for(i=sp_index+1;i!=sp_index;i++)
{
// start over when we reach the end
if(i >= spawnCount) i = 0;
vecHolder[0] = spawns[i][0];
vecHolder[1] = spawns[i][1];
vecHolder[2] = spawns[i][2];
// free space! office space!
if(is_hull_vacant(vecHolder,HULL_HUMAN))
{
sp_index = i;
break;
}
}
}
// origin
vecHolder[0] = spawns[sp_index][0];
vecHolder[1] = spawns[sp_index][1];
vecHolder[2] = spawns[sp_index][2];
engfunc(EngFunc_SetOrigin,id,vecHolder);
// angles
vecHolder[0] = spawns[sp_index][3];
vecHolder[1] = spawns[sp_index][4];
vecHolder[2] = spawns[sp_index][5];
set_pev(id,pev_angles,vecHolder);
// vangles
vecHolder[0] = spawns[sp_index][6];
vecHolder[1] = spawns[sp_index][7];
vecHolder[2] = spawns[sp_index][8];
set_pev(id,pev_v_angle,vecHolder);
set_pev(id,pev_fixangle,1);
}
// make sure a user respawned alright
public check_respawn(taskid)
{
new id;
if(taskid > TASK_CHECK_RESPAWN2) id = taskid-TASK_CHECK_RESPAWN2;
else id = taskid-TASK_CHECK_RESPAWN;
blockCorpse[id] = 0;
if(!is_user_connected(id))
return;
// now on spectator
new CsTeams:team = cs_get_user_team(id);
if(team == CS_TEAM_UNASSIGNED || team == CS_TEAM_SPECTATOR) return;
// didn't respawn properly
if(pev(id,pev_iuser1) || !is_user_alive(id))
{
//blockResetHUD[id]++; // no longer needed, since post_resethud checks pev_iuser1 now
remove_task(TASK_CHECK_RESPAWN+id);
remove_task(TASK_CHECK_RESPAWN2+id);
respawn(TASK_RESPAWN+id); // respawn them again
}
else
{
// double guarantee
give_essentials(id);
set_task(0.1,"give_essentials",id);
}
}
// give a user a knife and HUD after
// spawning in case he doesn't get one regularly
public give_essentials(id)
{
if(!is_user_alive(id) || pev(id,pev_iuser1)) return;
fm_set_user_suit(id,true,false);
if(!user_has_weapon(id,CSW_KNIFE)) fm_give_item(id,"weapon_knife");
}
// get rid of the spawn protection effects
public remove_spawn_protection(taskid)
{
new id = taskid-TASK_REMOVE_PROTECTION;
if(!is_user_connected(id)) return;
spawnProtected[id] = 0;
if(get_pcvar_num(gg_dm_sp_mode) == 2) fm_set_user_godmode(id,0);
fm_set_rendering(id); // reset back to normal
}
// crown a winner
win(id)
{
if(won) return;
won = 1;
roundEnded = 1;
set_cvar_num("sv_alltalk",1);
play_sound_by_cvar(0,gg_sound_winner);
new map_iterations = get_pcvar_num(gg_map_iterations);
// final playthrough, get ready for next map
if(mapIteration >= map_iterations && map_iterations > 0)
{
set_nextmap();
set_task(10.0,"goto_nextmap");
// as of 1.16, we always send a non-emessage intermission, because
// other map changing plugins (as well as StatsMe) intercepting it
// was causing problems.
message_begin(MSG_ALL,SVC_INTERMISSION);
message_end();
}
// get ready to go again!!
else
{
client_cmd(0,"+showscores");
set_task(4.9,"restart_gungame",czero ? get_cvar_num("bot_stop") : 0);
set_task(10.0,"stop_win_sound");
set_cvar_num("sv_restartround",5);
if(czero) set_cvar_num("bot_stop",1); // freeze CZ bots
}
new players[32], num, i;
get_players(players,num);
// freeze and godmode everyone
for(i=0;i<num;i++)
{
set_pev(players[i],pev_flags,pev(players[i],pev_flags) | FL_FROZEN);
fm_set_user_godmode(players[i],1);
}
// we have an invalid winner here
if(!is_user_connected(id) || !can_score(id))
return;
new winnerName[32], myName[32], authid[24], team[10];
get_user_name(id,winnerName,31);
for(i=0;i<5;i++) gungame_print(0,id,"%%n%s%%e %L!",winnerName,LANG_PLAYER_C,"WON");
set_cvar_num("sv_alltalk",1);
get_pcvar_string(gg_stats_file,sfFile,63);
new stats_mode = get_pcvar_num(gg_stats_mode), stats_ip = get_pcvar_num(gg_stats_ip),
ignore_bots = get_pcvar_num(gg_ignore_bots);
// points system
if(sfFile[0] && stats_mode == 2)
{
new wins, Float:flPoints, iPoints, totalPoints, player;
for(i=0;i<num;i++)
{
player = players[i];
// calculate points and add
flPoints = float(level[player]) - 1.0;
wins = 0;
// winner gets bonus points plus a win
if(player == id)
{
flPoints *= get_pcvar_float(gg_stats_winbonus);
wins = 1;
}
// unnecessary
if(flPoints <= 0.0 && !wins) continue;
iPoints = floatround(flPoints);
// it's okay to add to stats
if(!ignore_bots || !is_user_bot(player))
stats_add_to_score(player,wins,iPoints,dummy[0],totalPoints);
// log it
get_user_name(player,myName,31);
if(stats_ip) get_user_ip(player,authid,23);
else get_user_authid(player,authid,23);
get_user_team(player,team,9);
log_message("^"%s<%i><%s><%s>^" triggered ^"GunGame_Points^" amount ^"%i^"",myName,get_user_userid(player),authid,team,iPoints);
// display it
gungame_print(player,0,"%L",player,"GAINED_POINTS",iPoints,totalPoints);
}
}
// regular wins, no points
else if(sfFile[0] && stats_mode && (!ignore_bots || !is_user_bot(id)))
stats_add_to_score(id,1,0,dummy[0],dummy[0]);
if(stats_ip) get_user_ip(id,authid,23);
else get_user_authid(id,authid,23);
get_user_team(id,team,9);
log_message("^"%s<%i><%s><%s>^" triggered ^"Won_GunGame^"",winnerName,get_user_userid(id),authid,team);
//"Avalanche<2><VALVE_ID_LOOPBACK><TERRORIST>" triggered "Killed_A_Hostage"
}
// restart gungame, for the next map iteration
public restart_gungame(old_bot_stop_value)
{
won = 0;
mapIteration++;
toggle_gungame(TASK_TOGGLE_GUNGAME + TOGGLE_ENABLE); // reset stuff
do_rOrder(); // pick the next weapon order
// remove cheesey scoreboard
client_cmd(0,"-showscores");
new players[32], num, i;
get_players(players,num);
// unfreeze and ungodmode everyone
for(i=0;i<num;i++)
{
set_pev(players[i],pev_flags,pev(players[i],pev_flags) & ~FL_FROZEN);
fm_set_user_godmode(players[i],0);
welcomed[players[i]] = 1; // also don't show welcome again
}
if(czero) set_cvar_num("bot_stop",old_bot_stop_value); // unfreeze CZ bots
// only have warmup once?
if(!get_pcvar_num(gg_warmup_multi)) warmup = -13; // -13 is the magical stop number
else warmup = -1; // -1 isn't magical at all... :(
}
// stop the winner sound (for multiple map iterations)
public stop_win_sound()
{
new winSound[64];
get_pcvar_string(gg_sound_winner,winSound,63);
// stop winning sound
if(containi(winSound,".mp3") != -1) client_cmd(0,"mp3 stop");
else client_cmd(0,"speak null");
}
//
// AUTOVOTE FUNCTIONS
//
// start the autovote
public autovote_start()
{
// vote in progress
if(autovotes[0] || autovotes[1]) return;
new Float:autovote_time = get_pcvar_float(gg_autovote_time);
format(menuText,511,"\y%L^n^n\w1. %L^n2. %L^n^n0. %L",LANG_PLAYER,"PLAY_GUNGAME",LANG_PLAYER,"YES",LANG_PLAYER,"NO",LANG_PLAYER,"CANCEL");
show_menu(0,MENU_KEY_1|MENU_KEY_2|MENU_KEY_0,menuText,floatround(autovote_time),"autovote_menu");
set_task(autovote_time,"autovote_result");
}
// take in votes
public autovote_menu_handler(id,key)
{
switch(key)
{
case 0: autovotes[1]++;
case 1: autovotes[0]++;
//case 9: let menu close
}
return PLUGIN_HANDLED;
}
// calculate end of vote
public autovote_result()
{
new enable, enabled = get_pcvar_num(gg_enabled);
if(autovotes[0] || autovotes[1])
{
if(float(autovotes[1]) / float(autovotes[0] + autovotes[1]) >= get_pcvar_float(gg_autovote_ratio))
enable = 1;
}
gungame_print(0,-1,"%L (%L: %i, %L: %i)",LANG_PLAYER_C,(enable) ? "VOTING_SUCCESS" : "VOTING_FAILED",LANG_PLAYER_C,"YES",autovotes[1],LANG_PLAYER_C,"NO",autovotes[0]);
if(enable && !enabled)
{
set_task(4.8,"toggle_gungame",TASK_TOGGLE_GUNGAME+TOGGLE_ENABLE);
set_cvar_num("sv_restartround",5);
}
else if(!enable && enabled)
{
set_task(4.8,"toggle_gungame",TASK_TOGGLE_GUNGAME+TOGGLE_DISABLE);
set_cvar_num("sv_restartround",5);
set_pcvar_num(gg_enabled,0);
}
// reset votes
autovotes[0] = 0;
autovotes[1] = 0;
}
//
// STAT FUNCTIONS
//
// add to a player's wins
stats_add_to_score(id,wins,points,&newWins,&newPoints)
{
// stats disabled
if(!get_pcvar_num(gg_stats_mode)) return 0;
get_pcvar_string(gg_stats_file,sfFile,63);
// stats disabled
if(!sfFile[0]) return 0;
// get data
new authid[24], name[32];
if(get_pcvar_num(gg_stats_ip)) get_user_ip(id,authid,23);
else get_user_authid(id,authid,23);
get_user_name(id,name,31);
// clean up the name
trim(name);
replace_all(name,31,"^t"," ");
// replace it with new data
new oldWins, oldPoints, line;
line = stats_get_data(authid,oldWins,oldPoints,dummy,1,dummy[0]);
newWins = oldWins+wins;
newPoints = oldPoints+points;
return stats_set_data(authid,oldWins+wins,oldPoints+points,name,get_systime(),line);
}
// get a player's last used name and wins from save file
stock stats_get_data(authid[],&wins,&points,lastName[],nameLen,×tamp,knownLine=-1)
{
wins = 0;
points = 0;
timestamp = 0;
// stats disabled
if(!get_pcvar_num(gg_stats_mode)) return -1;
get_pcvar_string(gg_stats_file,sfFile,63);
// stats disabled/file doesn't exist
if(!sfFile[0] || !file_exists(sfFile)) return -1;
// storage format:
// AUTHID WINS LAST_USED_NAME TIMESTAMP POINTS
// reset
sfLineData[0] = 0;
// open 'er up, boys!
new line, found, file = fopen(sfFile,"rt");
if(!file) return -1;
// go through it
while(!feof(file))
{
fgets(file,sfLineData,80);
line++;
// go to the line we know
if(knownLine > -1)
{
if(line-1 == knownLine)
{
found = 1;
break;
}
else continue;
}
// isolate authid
strtok(sfLineData,sfAuthid,23,dummy,1,'^t');
// this is it, stop now because our
// data is already stored in sfLineData
if(equal(authid,sfAuthid))
{
found = 1;
break;
}
}
// close 'er up, boys! (hmm....)
fclose(file);
// couldn't find
if(!found) return -1;
// isolate authid
strtok(sfLineData,sfAuthid,23,sfLineData,80,'^t');
// isolate wins
strtok(sfLineData,sfWins,5,sfLineData,80,'^t');
wins = str_to_num(sfWins);
// isolate name
strtok(sfLineData,lastName,nameLen,sfLineData,80,'^t');
// isolate timestamp
strtok(sfLineData,sfTimestamp,11,sfPoints,7,'^t');
timestamp = str_to_num(sfTimestamp);
// isolate points (only thing left)
points = str_to_num(sfPoints);
// return the line we got it on
if(knownLine > -1) return knownLine;
return line - 1;
}
// set a player's last used name and wins from save file
stock stats_set_data(authid[],wins,points,lastName[],timestamp,knownLine=-1)
{
// stats disabled
if(!get_pcvar_num(gg_stats_mode)) return 0;
get_pcvar_string(gg_stats_file,sfFile,63);
// stats disabled
if(!sfFile[0]) return 0;
// storage format:
// AUTHID WINS LAST_USED_NAME TIMESTAMP POINTS
new tempFileName[65], sfFile_rename[64], newFile_rename[65], file;
formatex(tempFileName,64,"%s2",sfFile); // our temp file, append 2
// rename_file backwards compatibility (thanks Mordekay)
formatex(sfFile_rename,63,"%s/%s",modName,sfFile);
formatex(newFile_rename,64,"%s/%s",modName,tempFileName);
// create stats file if it doesn't exist
if(!file_exists(sfFile))
{
file = fopen(sfFile,"wt");
fclose(file);
}
// copy over current stat file
rename_file(sfFile_rename,newFile_rename);
// rename failed?
if(!file_exists(tempFileName)) return 0;
new tempFile = fopen(tempFileName,"rt");
new line, goal;
file = fopen(sfFile,"wt");
// go through our old copy and rewrite entries
while(tempFile && file && !feof(tempFile))
{
fgets(tempFile,sfLineData,80);
if(!sfLineData[0])
{
line++;
continue;
}
// see if this is the line we are trying to overwrite
if(!goal)
{
if(knownLine > -1)
{
if(line == knownLine) goal = 1;
}
else
{
// isolate authid
strtok(sfLineData,sfAuthid,23,dummy,1,'^t');
// this is what we are looking for
if(equal(authid,sfAuthid)) goal = 1;
}
}
// overwrite with new values
if(goal == 1)
{
goal = -1;
fprintf(file,"%s^t%i^t%s^t%i^t%i",authid,wins,lastName,timestamp,points);
fputc(file,'^n');
}
// otherwise just copy it over as it was (newline is already included)
else fprintf(file,"%s",sfLineData);
line++;
}
// never found an existing entry, make a new one
if(!goal)
{
fprintf(file,"%s^t%i^t%s^t%i^t%i",authid,wins,lastName,timestamp,points);
fputc(file,'^n');
}
if(tempFile) fclose(tempFile);
if(file) fclose(file);
// remove our copy
delete_file(tempFileName);
return 1;
}
// update a user's timestamp
stats_refresh_timestamp(authid[])
{
new wins, points, lastName[32], timestamp;
new line = stats_get_data(authid,wins,points,lastName,31,timestamp);
if(line > -1) stats_set_data(authid,wins,points,lastName,get_systime(),line);
}
// gets the top X amount of players into an array
// of the format: storage[amount][storageLen]
stats_get_top_players(amount,storage[][],storageLen)
{
// stats disabled
if(!get_pcvar_num(gg_stats_mode)) return 0;
get_pcvar_string(gg_stats_file,sfFile,63);
// stats disabled/file doesn't exist
if(!sfFile[0] || !file_exists(sfFile)) return 0;
// storage format:
// AUTHID WINS LAST_USED_NAME TIMESTAMP POINTS
// not so much OMG OMG OMG OMG as of 1.16
static tempList[TOP_PLAYERS+1][82], tempLineData[81];
new count, stats_mode = get_pcvar_num(gg_stats_mode), score[10];
// open sesame
new file = fopen(sfFile,"rt");
if(!file) return 0;
// reading, reading, reading...
while(!feof(file))
{
fgets(file,sfLineData,80);
// empty line
if(!sfLineData[0]) continue;
// assign it to a new variable so that strtok
// doesn't tear apart our constant sfLineData variable
tempLineData = sfLineData;
// get rid of authid
strtok(tempLineData,dummy,1,tempLineData,80,'^t');
// sort by wins
if(stats_mode == 1)
{
strtok(tempLineData,score,9,tempLineData,1,'^t');
}
// sort by points
else
{
// break off wins
strtok(tempLineData,dummy,1,tempLineData,80,'^t');
// break off name
strtok(tempLineData,dummy,1,tempLineData,80,'^t');
// break off timestamp and get points
strtok(tempLineData,dummy,1,score,9,'^t');
}
// don't store more than 11
if(count >= amount) count = amount;
tempList[count][0] = str_to_num(score);
formatex(tempList[count][1],81,"%s",sfLineData);
count++;
// filled list with 11, sort
if(count > amount) SortCustom2D(tempList,count,"stats_custom_compare");
}
// nolisting
if(!count)
{
fclose(file);
return 0;
}
// not yet sorted (didn't reach 11 entries)
else if(count <= amount)
SortCustom2D(tempList,count,"stats_custom_compare");
new i;
// now that it's sorted, return it
for(i=0;i<amount&&i<count;i++)
formatex(storage[i],storageLen,"%s",tempList[i][1]);
// close
fclose(file);
return 1;
}
// our custom sorting function (check first dimension for score)
public stats_custom_compare(elem1[],elem2[])
{
if(elem1[0] > elem2[0]) return -1;
else if(elem1[0] < elem2[0]) return 1;
return 0;
}
// prune old entries
stock stats_prune(max_time=-1)
{
get_pcvar_string(gg_stats_file,sfFile,63);
// stats disabled/file doesn't exist
if(!sfFile[0] || !file_exists(sfFile)) return 0;
// -1 = use value from cvar
if(max_time == -1) max_time = get_pcvar_num(gg_stats_prune);
// 0 = no pruning
if(max_time == 0) return 0;
new tempFileName[65], sfFile_rename[64], newFile_rename[65];
formatex(tempFileName,64,"%s2",sfFile); // our temp file, append 2
// rename_file backwards compatibility (thanks Mordekay)
formatex(sfFile_rename,63,"%s/%s",modName,sfFile);
formatex(newFile_rename,64,"%s/%s",modName,tempFileName);
// copy over current stat file
rename_file(sfFile_rename,newFile_rename);
// rename failed?
if(!file_exists(tempFileName)) return 0;
new tempFile = fopen(tempFileName,"rt");
new file = fopen(sfFile,"wt");
// go through our old copy and rewrite valid entries into the new copy
new current_time = get_systime(), original[81], removed;
while(tempFile && file && !feof(tempFile))
{
fgets(tempFile,sfLineData,80);
if(!sfLineData[0]) continue;
// save original
original = sfLineData;
// break off authid
strtok(sfLineData,sfAuthid,1,sfLineData,80,'^t');
// break off wins
strtok(sfLineData,sfWins,1,sfLineData,80,'^t');
// break off name, and thus get timestamp
strtok(sfLineData,sfName,1,sfTimestamp,11,'^t');
copyc(sfTimestamp,11,sfTimestamp,'^t'); // cut off points
// not too old, write it to our new file
if(current_time - str_to_num(sfTimestamp) <= max_time)
fprintf(file,"%s",original); // newline is already included
else
removed++;
}
if(tempFile) fclose(tempFile);
if(file) fclose(file);
// remove our copy
delete_file(tempFileName);
return removed;
}
//
// SUPPORT FUNCTIONS
//
stock get_level_goal(level)
{
get_pcvar_string(gg_weapon_order,weaponOrder,415);
new comma = str_find_num(weaponOrder,',',level-1)+1;
static crop[32];
copyc(crop,31,weaponOrder[comma],',');
new colon = containi(crop,":");
// no custom goal
if(colon == -1)
{
if(equal(crop,"hegrenade") || equal(crop,"knife"))
return 1;
else
return get_pcvar_num(gg_kills_per_lvl);
}
static goal[4];
copyc(goal,3,crop[colon+1],',');
return str_to_num(goal);
}
// get the name of a weapon by level
stock get_weapon_name_by_level(theLevel,var[],varLen,includeGoal=0)
{
if(!theLevel)
{
formatex(var,varLen,"glock18");
return;
}
else if(theLevel > 32 || theLevel > get_weapon_num())
{
formatex(var,varLen,"knife");
return;
}
static weapons[32][24];
get_weapon_order(weapons);
if(!includeGoal && containi(var,":")) // strip off goal if we don't want it
copyc(var,varLen,weapons[theLevel-1],':');
else
formatex(var,varLen,"%s",weapons[theLevel-1]);
strtolower(var);
}
// get the weapons, in order
get_weapon_order(weapons[32][24])
{
get_pcvar_string(gg_weapon_order,weaponOrder,415);
new i;
for(i=0;i<32;i++)
{
// out of stuff
if(strlen(weaponOrder) <= 1) break;
// we still have a comma, go up to it
if(containi(weaponOrder,",") != -1)
{
strtok(weaponOrder,weapons[i],23,weaponOrder,415,',');
trim(weapons[i]);
}
// otherwise, finish up
else
{
formatex(weapons[i],23,"%s",weaponOrder);
trim(weapons[i]);
break;
}
}
}
// get the number of weapons to go through
get_weapon_num()
{
get_pcvar_string(gg_weapon_order,weaponOrder,415);
return str_count(weaponOrder,',') + 1;
}
// easy function to precache sound via cvar
precache_sound_by_cvar(cvar[],default_val[])
{
new value[64];
get_cvar_string(cvar,value,63);
// mp3s precache as generic (full filepath)
if(containi(value,".mp3") != -1 || (!value[0] && containi(default_val,".mp3") != -1))
{
if(!strlen(value) || !file_exists(value)) precache_generic(default_val);
else precache_generic(value);
}
// wavs precache as sound (in sound/ directory by default)
else
{
new filepath[64];
formatex(filepath,63,"sound/%s",value);
if(!strlen(value) || !file_exists(filepath)) precache_sound(default_val);
else precache_sound(value);
}
}
// figure out which gungame.cfg file to use
get_gg_config_file(filename[],len)
{
formatex(filename,len,"%s/gungame.cfg",cfgDir);
if(!file_exists(filename))
{
formatex(filename,len,"gungame.cfg");
if(!file_exists(filename)) filename[0] = 0;
}
}
// figure out which gungame_mapcycle file to use
get_gg_mapcycle_file(filename[],len)
{
static testFile[64];
// cstrike/addons/amxmodx/configs/gungame_mapcycle.cfg
formatex(testFile,63,"%s/gungame_mapcycle.cfg",cfgDir);
if(file_exists(testFile))
{
formatex(filename,len,"%s",testFile);
return 1;
}
// cstrike/addons/amxmodx/configs/gungame_mapcycle.txt
formatex(testFile,63,"%s/gungame_mapcycle.txt",cfgDir);
if(file_exists(testFile))
{
formatex(filename,len,"%s",testFile);
return 1;
}
// cstrike/gungame_mapcycle.cfg
testFile = "gungame_mapcycle.cfg";
if(file_exists(testFile))
{
formatex(filename,len,"%s",testFile);
return 1;
}
// cstrike/gungame_mapcycle.txt
testFile = "gungame_mapcycle.txt";
if(file_exists(testFile))
{
formatex(filename,len,"%s",testFile);
return 1;
}
return 0;
}
// another easy function to play sound via cvar
play_sound_by_cvar(id,cvar)
{
static value[64];
get_pcvar_string(cvar,value,63);
if(!value[0]) return;
if(containi(value,".mp3") != -1) client_cmd(id,"mp3 play ^"%s^"",value);
else client_cmd(id,"speak ^"%s^"",value);
}
// find the highest level player and his level
get_leader(&Rlevel)
{
new players[32], num, i, leader;
get_players(players,num);
// locate highest player
for(i=0;i<num;i++)
{
if(leader == 0 || level[players[i]] > level[leader])
leader = players[i];
}
Rlevel = level[leader];
return leader;
}
// a butchered version of teame06's CS Color Chat Function
gungame_print(id,custom,msg[],{Float,Sql,Result,_}:...)
{
new changeCount, num, i, j;
static newMsg[191], message[191], changed[5], players[32];
if(id)
{
players[0] = id;
num = 1;
}
else get_players(players,num);
new colored_messages = get_pcvar_num(gg_colored_messages);
for(i=0;i<num;i++)
{
changeCount = 0;
// we have to change LANG_PLAYER into
// a player-specific argument, because
// ML doesn't work well with SayText
for(j=3;j<numargs();j++)
{
if(getarg(j) == LANG_PLAYER_C)
{
setarg(j,0,players[i]);
changed[changeCount++] = j;
}
}
// do user formatting
vformat(newMsg,190,msg,4);
// and now we have to change what we changed
// back into LANG_PLAYER, so that the next
// player will be able to have it in his language
for(j=0;j<changeCount;j++)
{
setarg(changed[j],0,LANG_PLAYER_C);
}
// optimized color swapping
if(colored_messages)
{
replace_all(newMsg,190,"%n","^x03"); // %n = team color
replace_all(newMsg,190,"%g","^x04"); // %g = green
replace_all(newMsg,190,"%e","^x01"); // %e = regular
}
else
{
replace_all(newMsg,190,"%n","");
replace_all(newMsg,190,"%g","");
replace_all(newMsg,190,"%e","");
}
// now do our formatting (I used two variables because sharing one caused glitches)
if(custom == -1) formatex(message,190,"^x04[%L]^x01 %s",players[i],"GUNGAME",newMsg);
else formatex(message,190,"^x01%s",newMsg);
message_begin(MSG_ONE,gmsgSayText,_,players[i]);
write_byte((custom > 0) ? custom : players[i]);
write_string(message);
message_end();
}
}
// show a HUD message to a user
gungame_hudmessage(id,Float:holdTime,msg[],{Float,Sql,Result,_}:...)
{
// user formatting
static newMsg[191];
vformat(newMsg,190,msg,4);
// show it
set_hudmessage(255,255,255,-1.0,0.8,0,6.0,holdTime,0.1,0.5,CHANNEL_STATUS);
show_hudmessage(id,newMsg);
}
// start a map vote
start_mapvote()
{
new dmmName[32];
// AMXX Nextmap Chooser
if(find_plugin_byfile("mapchooser.amxx") != INVALID_PLUGIN_ID)
{
new oldWinLimit = get_cvar_num("mp_winlimit"), oldMaxRounds = get_cvar_num("mp_maxrounds");
set_cvar_num("mp_winlimit",0); // skip winlimit check
set_cvar_num("mp_maxrounds",-1); // trick plugin to think game is almost over
// call the vote
if(callfunc_begin("voteNextmap","mapchooser.amxx") == 1)
callfunc_end();
// set maxrounds back
set_cvar_num("mp_winlimit",oldWinLimit);
set_cvar_num("mp_maxrounds",oldMaxRounds);
}
// Deagles' Map Management 2.30b
else if(find_plugin_byfile("deagsmapmanage230b.amxx") != INVALID_PLUGIN_ID)
{
dmmName = "deagsmapmanage230b.amxx";
}
// Deagles' Map Management 2.40
else if(find_plugin_byfile("deagsmapmanager.amxx") != INVALID_PLUGIN_ID)
{
dmmName = "deagsmapmanager.amxx";
}
// Mapchooser4
else if(find_plugin_byfile("mapchooser4.amxx") != INVALID_PLUGIN_ID)
{
new oldWinLimit = get_cvar_num("mp_winlimit"), oldMaxRounds = get_cvar_num("mp_maxrounds");
set_cvar_num("mp_winlimit",0); // skip winlimit check
set_cvar_num("mp_maxrounds",1); // trick plugin to think game is almost over
// deactivate g_buyingtime variable
if(callfunc_begin("buyFinished","mapchooser4.amxx") == 1)
callfunc_end();
// call the vote
if(callfunc_begin("voteNextmap","mapchooser4.amxx") == 1)
{
callfunc_push_str("",false);
callfunc_end();
}
// set maxrounds back
set_cvar_num("mp_winlimit",oldWinLimit);
set_cvar_num("mp_maxrounds",oldMaxRounds);
}
// NOTHING?
else log_amx("Using gg_vote_setting without mapchooser.amxx, mapchooser4.amxx, deagsmapmanage230b.amxx, or deagsmapmanager.amxx: could not start a vote!");
// do DMM stuff
if(dmmName[0])
{
// allow voting
/*if(callfunc_begin("dmapvotemode",dmmName) == 1)
{
callfunc_push_int(0); // server
callfunc_end();
}*/
new oldWinLimit = get_cvar_num("mp_winlimit"), Float:oldTimeLimit = get_cvar_float("mp_timelimit");
set_cvar_num("mp_winlimit",99999); // don't allow extending
set_cvar_float("mp_timelimit",0.0); // don't wait for buying
set_cvar_num("enforce_timelimit",1); // don't change map after vote
// call the vote
if(callfunc_begin("startthevote",dmmName) == 1)
callfunc_end();
set_cvar_num("mp_winlimit",oldWinLimit);
set_cvar_float("mp_timelimit",oldTimeLimit);
// disallow further voting
/*if(callfunc_begin("dmapcyclemode",dmmName) == 1)
{
callfunc_push_int(0); // server
callfunc_end();
}*/
}
}
// set amx_nextmap to the next map
set_nextmap()
{
new mapCycleFile[64];
get_gg_mapcycle_file(mapCycleFile,63);
// no mapcycle, leave amx_nextmap alone
if(!mapCycleFile[0] || !file_exists(mapCycleFile))
{
set_localinfo("gg_cycle_num","0");
return;
}
new strVal[10];
// have not gotten cycleNum yet (only get it once, because
// set_nextmap is generally called at least twice per map, and we
// don't want to change it twice)
if(cycleNum == -1)
{
get_localinfo("gg_cycle_num",strVal,9);
cycleNum = str_to_num(strVal);
}
new firstMap[32], currentMap[32], lineData[32], i, line, foundMap;
get_mapname(currentMap,31);
new file = fopen(mapCycleFile,"rt");
while(file && !feof(file))
{
fgets(file,lineData,31);
trim(lineData);
replace(lineData,31,".bsp",""); // remove extension
// stop at a comment
for(i=0;i<strlen(lineData)-2;i++)
{
// supports config-style (;) and coding-style (//)
if(lineData[i] == ';' || (lineData[i] == '/' && lineData[i+1] == '/'))
{
copy(lineData,i,lineData);
break;
}
}
trim(lineData);
if(!lineData[0]) continue;
// save first map
if(!firstMap[0]) formatex(firstMap,31,"%s",lineData);
// we reached the line after our current map's line
if(line == cycleNum+1)
{
// remember so
foundMap = 1;
// get ready to change to it
set_cvar_string("amx_nextmap",lineData);
// remember this map's line for next time
num_to_str(line,strVal,9);
set_localinfo("gg_cycle_num",strVal);
break;
}
line++;
}
if(file) fclose(file);
// we didn't find next map
if(!foundMap)
{
// reset line number to first (it's zero-based)
set_localinfo("gg_cycle_num","0");
// no maps listed, go to current
if(!firstMap[0]) set_cvar_string("amx_nextmap",currentMap);
// go to first map listed
else set_cvar_string("amx_nextmap",firstMap);
}
}
// go to amx_nextmap
public goto_nextmap()
{
set_nextmap(); // for good measure
new mapCycleFile[64];
get_gg_mapcycle_file(mapCycleFile,63);
// no gungame mapcycle
if(!mapCycleFile[0] || !file_exists(mapCycleFile))
{
new custom[256];
get_pcvar_string(gg_changelevel_custom,custom,255);
// try custom changelevel command
if(custom[0])
{
server_cmd(custom);
return;
}
}
// otherwise, go to amx_nextmap
new nextMap[32];
get_cvar_string("amx_nextmap",nextMap,31);
server_cmd("changelevel %s",nextMap);
}
// weapon display
stock status_display(id,status=1)
{
new sdisplay;
sdisplay = get_pcvar_num(gg_status_display);
// display disabled
if(!sdisplay) return;
// dead
if(id && (!is_user_alive(id) || pev(id,pev_iuser1)))
return;
new dest;
static sprite[32];
if(!id) dest = MSG_BROADCAST;
else dest = MSG_ONE_UNRELIABLE;
// disable display if status is 0, or we are doing a knife warmup
if(!status || (warmup > 0 && get_pcvar_num(gg_knife_warmup)))
{
message_begin(dest,gmsgScenario,_,id);
write_byte(0);
message_end();
return;
}
// weapon display
if(sdisplay == STATUS_LEADERWPN || sdisplay == STATUS_YOURWPN)
{
if(sdisplay == STATUS_LEADERWPN)
{
new ldrLevel;
get_leader(ldrLevel);
// get leader's weapon
if(ldrLevel <= 0) return;
get_weapon_name_by_level(ldrLevel,sprite,31);
}
else
{
// get your weapon
if(level[id] <= 0) return;
formatex(sprite,31,"%s",weapon[id]);
}
strtolower(sprite);
// sprite is d_grenade, not d_hegrenade
if(sprite[0] == 'h') sprite = "grenade";
// get true sprite name
format(sprite,31,"d_%s",sprite);
}
// kill display
else if(sdisplay == STATUS_KILLSLEFT)
{
new goal = get_level_goal(level[id]);
formatex(sprite,31,"number_%i",goal-score[id]);
}
else if(sdisplay == STATUS_KILLSDONE)
{
formatex(sprite,31,"number_%i",score[id]);
}
// display it already!
message_begin(dest,gmsgScenario,_,id);
write_byte(1);
write_string(sprite);
write_byte(150);
message_end();
}
// refill a player's ammo
stock refill_ammo(id,current=0)
{
if(!is_user_alive(id) || pev(id,pev_iuser1)) return;
new armor = get_pcvar_num(gg_give_armor), helmet = get_pcvar_num(gg_give_helmet);
// giving armor and helmets away like candy
if(helmet) cs_set_user_armor(id,armor,CS_ARMOR_VESTHELM);
else cs_set_user_armor(id,armor,CS_ARMOR_KEVLAR);
// no ammo for knives only
if(warmup > 0 && get_pcvar_num(gg_knife_warmup)) return;
// get weapon name and index
new wpnid, curweapon = get_user_weapon(id,dummy[0],dummy[0]);
if(current && (curweapon != CSW_KNIFE || equal(weapon[id],"knife")))
{
wpnid = curweapon;
}
else
{
static fullName[24];
formatex(fullName,23,"weapon_%s",weapon[id]);
wpnid = get_weaponid(fullName);
}
if(!wpnid) return;
// no reason to refill a knife
if(wpnid == CSW_KNIFE) return;
new ammo, wEnt;
ammo = get_pcvar_num(gg_ammo_amount);
// don't give away hundreds of grenades
if(wpnid != CSW_HEGRENADE)
{
// set clip ammo
wEnt = get_weapon_ent(id,wpnid);
if(pev_valid(wEnt)) cs_set_weapon_ammo(wEnt,maxClip[wpnid]);
// set backpack ammo
if(equal(weapon[id],"hegrenade") && wpnid == CSW_GLOCK18)
cs_set_user_bpammo(id,wpnid,50);
else if(ammo > 0) cs_set_user_bpammo(id,wpnid,ammo);
else cs_set_user_bpammo(id,wpnid,maxAmmo[wpnid]);
// update display if we need to
if(curweapon == wpnid)
{
message_begin(MSG_ONE,gmsgCurWeapon,_,id);
write_byte(1);
write_byte(wpnid);
write_byte(maxClip[wpnid]);
message_end();
}
}
// now do stupid grenade stuff
else
{
if(get_pcvar_num(gg_nade_glock))
{
// set clip ammo
wEnt = get_weapon_ent(id,CSW_GLOCK18);
if(pev_valid(wEnt)) cs_set_weapon_ammo(wEnt,maxClip[CSW_GLOCK18]);
// set backpack ammo
cs_set_user_bpammo(id,CSW_GLOCK18,50);
// update display if we need to
if(curweapon == CSW_GLOCK18)
{
message_begin(MSG_ONE,gmsgCurWeapon,_,id);
write_byte(1);
write_byte(CSW_GLOCK18);
write_byte(maxClip[CSW_GLOCK18]);
message_end();
}
}
if(get_pcvar_num(gg_nade_smoke) && !cs_get_user_bpammo(id,CSW_SMOKEGRENADE))
fm_give_item(id,"weapon_smokegrenade");
if(get_pcvar_num(gg_nade_flash) && !cs_get_user_bpammo(id,CSW_FLASHBANG))
fm_give_item(id,"weapon_flashbang");
if(!cs_get_user_bpammo(id,CSW_HEGRENADE))
{
fm_give_item(id,"weapon_hegrenade");
remove_task(TASK_REFRESH_NADE+id);
}
}
// keep knife out
if(curweapon == CSW_KNIFE) client_cmd(id,"weapon_knife");
}
// find a player's weapon entity
stock get_weapon_ent(id,wpnid=0,wpnName[]="")
{
// who knows what wpnName will be
static newName[32];
// need to find the name
if(wpnid) get_weaponname(wpnid,newName,31);
// go with what we were told
else formatex(newName,31,"%s",wpnName);
// prefix it if we need to
if(!equal(newName,"weapon_",7))
format(newName,31,"weapon_%s",newName);
return fm_find_ent_by_owner(0,newName,id);
}
// counts number of chars in a string, by (probably) Twilight Suzuka
stock str_count(str[],searchchar)
{
new i = 0;
new maxlen = strlen(str);
new count = 0;
for(i=0;i<=maxlen;i++)
{
if(str[i] == searchchar)
count++;
}
return count;
}
// find the nth occurance of a character in a string, based on str_count
stock str_find_num(str[],searchchar,number)
{
new i;
new maxlen = strlen(str);
new found = 0;
for(i=0;i<=maxlen;i++)
{
if(str[i] == searchchar)
{
if(++found == number)
return i;
}
}
return -1;
}
// gets a player id that triggered certain logevents, by VEN
stock get_loguser_index()
{
static loguser[80], name[32];
read_logargv(0,loguser,79);
parse_loguser(loguser,name,31);
return get_user_index(name);
}
// checks if a space is vacant, by VEN
stock bool:is_hull_vacant(const Float:origin[3],hull)
{
new tr = 0;
engfunc(EngFunc_TraceHull,origin,origin,0,hull,0,tr);
if(!get_tr2(tr,TR_StartSolid) && !get_tr2(tr,TR_AllSolid) && get_tr2(tr,TR_InOpen))
return true;
return false;
}
// gets a weapon's category, for Counter-Strike
stock get_weapon_category(id=0,name[]="")
{
if(name[0])
{
if(equal(name,"weapon_",7)) id = get_weaponid(name);
else
{
static newName[32];
formatex(newName,31,"weapon_%s",name);
id = get_weaponid(newName);
}
}
return weaponSlots[id];
}
// if a player is allowed to score (at least 1 player on opposite team)
can_score(id)
{
new CsTeams:team = cs_get_user_team(id);
// find opposite team
switch(team)
{
case CS_TEAM_T: team = CS_TEAM_CT;
case CS_TEAM_CT: team = CS_TEAM_T;
default: return 0; // spectator
}
new i;
for(i=1;i<=maxPlayers;i++)
{
if(is_user_connected(i) && cs_get_user_team(i) == team)
return 1;
}
// didn't find anyone on opposing team
return 0;
}
// returns 1 if there are only bots in the server, 0 if not
only_bots()
{
new i;
for(i=1;i<=maxPlayers;i++)
{
if(is_user_connected(i) && !is_user_bot(i))
return 0;
}
// didn't find any humans
return 1;
}