|
Стаж: 10 лет
Сообщений: 10
Благодарностей: 1
Полезность: 0
|
сервер counter-strike 1.6 есть мод Just Capture the Flag 1.32c ( на флаги ) есть мод gg_213_beta4_full ( Gun Game ) как можно сделать что-б за 1 флаг шло как за убийство с ножа в гангейм моде ? ну или лучше что-б с статистику убийств шло число которое настраивается в Just Capture the Flag моде ... может для кого это легко .. и он сможет сделать костыль за 2 мин ))) надо написать мод ( костыль ) ? или надо править часть мода? много ли надо изучить что-б самому разобраться как это сделать .. ? как я понимаю надо написать плагин с функцией отлова событии .. и передать это в gungame мод ... если правильно понимаю то буду стараться дальше ... Код /* Uncomment the below define to use SQL stats intead of flat-file stats. */
//#define SQL
/* Uncomment the below define to have a player's timestamp get refreshed right away as soon as they join, instead of only when they play to the end of a game. ** There is a slight overhead for flat-file stats, but it's fairly speedy. When using SQL stats, you might as well uncomment this -- it'll be speedy. */
#define REFRESH_TIMESTAMP_ON_JOIN
// 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 BAILOPAN for binary logging, and for // CSDM spawn files that I could leech off of. Oh, and // also AMXX, etcetera. // // Thanks to VEN for Fakemeta Utilities to ease development. // // Thanks a lot to all of my supporters, but especially: // 3volution, aligind4h0us3, arkshine, bmp, Curryking, // Gunny, IdiotSavant, Mordekay, polakpolak, raa, Silver // Dragon, ToT | V!PER, and Vm|Mayhem. // // Thanks especially to all of the translators: // arkshine, b!orn, commonbullet, Curryking, Deviance, // D o o m, e-N-z, Fr3ak0ut, godlike, harbu, iggy_bus, // jopmako, KylixMynxAltoLAG, Min2liz, Morpheus759, rpm, // SAMURAI16, Simbad,TEG, ToT | V!PER, trawiator, // Twilight Suzuka, and webpsiho. // // If I missed you, please yell at me.
#pragma dynamic 8192 // just a little bit extra, not too much
#include <amxmodx> #include <amxmisc> #include <fakemeta> #include <fakemeta_util> #include <cstrike> #include <hamsandwich>
// defines to be left alone new const GG_VERSION[] = "2.13(BETA4)"; #define LANG_PLAYER_C -76 // for gungame_print (arbitrary number) #define TNAME_SAVE pev_noise3 // for blocking game_player_equip and player_weaponstrip #define WINSOUNDS_SIZE (MAX_WINSOUNDS*MAX_WINSOUND_LEN)+1 // for gg_sound_winner
// more customizable-friendly defines #define TOP_PLAYERS 10 // for !top10 #define MAX_WEAPONS 36 // for gg_weapon_order #define MAX_WINSOUNDS 12 // for gg_sound_winnner #define MAX_WINSOUND_LEN 48 // for gg_sound_winner #define TEMP_SAVES 32 // for gg_save_temp #define MAX_WEAPON_ORDERS 10 // for random gg_weapon_order #define LEADER_DISPLAY_RATE 10.0 // for gg_leader_display #define MAX_SPAWNS 128 // for gg_dm_spawn_random #define MAX_STATS_RANK 1000 // cap of 1000 = 0.0063495ish sec for longest stats_get_position, cap of 5000 = 0.0327655ish sec
// returns which of the two stats files we should be using currently (si stands for Stats Index) #define get_gg_si() (get_pcvar_num(gg_stats_split) && get_pcvar_num(gg_teamplay))
// cs_set_user_money #if cellbits == 32 #define OFFSET_CSMONEY 115 #else #define OFFSET_CSMONEY 140 #endif #define OFFSET_LINUX 5 // animations #define USP_DRAWANIM 6 #define M4A1_DRAWANIM 5
// saves memory??? new const WEAPON_HEGRENADE[] = "weapon_hegrenade"; new const WEAPON_KNIFE[] = "weapon_knife"; new const WEAPON_GLOCK18[] = "weapon_glock18"; new const HEGRENADE[] = "hegrenade"; new const KNIFE[] = "knife"; new const BRASS_BELL_SOUND[] = "gungame/gg_brass_bell_old.wav"; new const KILL_DING_SOUND[] = "buttons/bell1.wav";
// toggle_gungame enum { TOGGLE_FORCE = -1, TOGGLE_DISABLE, TOGGLE_ENABLE };
// gg_status_display enum { STATUS_LEADERWPN = 1, STATUS_YOURWPN, STATUS_KILLSLEFT, STATUS_KILLSDONE };
// value of bombStatus[3] enum { BOMB_PICKEDUP = -1, BOMB_DROPPED, BOMB_PLANTED };
// for gg_messages #define MSGS_CLASSIC 2 #define MSGS_NOCOLOR 4 #define MSGS_HIDETEXT 8 #define MSGS_HIDEHUD 16
// task ids #define TASK_END_STAR 200 #define TASK_RESPAWN 300 #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 #define TASK_LEADER_DISPLAY 1300 #define TASK_PLAY_LEAD_SOUNDS 1400 #define TASK_CHECK_JOINCLASS 1500 #define TASK_AUTOVOTE_RESULT 1600 #define TASK_GET_TOP_PLAYERS 1700
//********************************************************************** // 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_handicap_on, gg_top10_handicap, gg_warmup_timer_setting, gg_warmup_weapon, gg_sound_levelup, gg_sound_leveldown, gg_sound_levelsteal, gg_sound_nade, gg_sound_knife, gg_sound_welcome, gg_sound_triple, gg_sound_winner, gg_kills_per_lvl, gg_vote_custom, gg_changelevel_custom, gg_ammo_amount, gg_stats_prune, gg_refill_on_kill, gg_messages, gg_tk_penalty, gg_save_temp, gg_stats_mode, gg_pickup_others, gg_stats_winbonus, gg_map_iterations, gg_warmup_multi, gg_stats_ip, gg_extra_nades, gg_endmap_setup, gg_autovote_rounds, gg_autovote_ratio, gg_autovote_delay, gg_autovote_time, gg_autovote_mode, gg_ignore_bots, gg_nade_refresh, gg_block_equips, gg_leader_display, gg_leader_display_x, gg_leader_display_y, gg_sound_takenlead, gg_sound_tiedlead, gg_sound_lostlead, gg_lead_sounds, gg_knife_elite, gg_teamplay, gg_teamplay_knife_mod, gg_teamplay_nade_mod, gg_suicide_penalty, gg_winner_motd, gg_bomb_defuse_lvl, gg_nade_glock, gg_nade_smoke, gg_nade_flash, gg_give_armor, gg_give_helmet, gg_dm, gg_dm_sp_time, gg_dm_sp_mode, gg_dm_spawn_random, gg_dm_spawn_delay, gg_dm_corpses, 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_host_kill_penalty, gg_dm_start_random, gg_allow_changeteam, gg_teamplay_timeratio, gg_disable_money, gg_kills_botmod, gg_bots_skipnade, gg_bots_knifeable, gg_afk_protection, gg_stats_split, gg_top10_ppp;
// weapon information new 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 };
new 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 }; new weaponSlots[31] = { -1, 2, -1, 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 };
enum statsData { sdAuthid[32], sdWins[2], sdName[32], sdTimestamp, // [1] sdPoints[2], sdStreak[2] }; // size = 71
enum saveData { svAuthid[32], svLevel, // [1] svScore, // [1] svStatsPosition[2], svTeamTimes[2], svTime // [1] }; // size = 39
// misc new weapons_menu, scores_menu, level_menu, warmup = -1, warmupWeapon[24], voted, won, trailSpr, roundEnded, menuText[512], dummy[2], tempSave[TEMP_SAVES][saveData], czero, maxPlayers, mapIteration = 1, cfgDir[32], autovoted, autovotes[3], autovote_mode, roundsElapsed, gameCommenced, cycleNum = -1, czbot_hams, mp_friendlyfire, winSounds[MAX_WINSOUNDS][MAX_WINSOUND_LEN+1], numWinSounds, currentWinSound, hudSyncWarmup, hudSyncReqKills, hudSyncLDisplay, shouldWarmup, ggActive, teamLevel[3], teamLvlWeapon[3][24], teamScore[3], bombMap, hostageMap, bombStatus[4], c4planter, Float:spawns[MAX_SPAWNS][9], spawnCount, csdmSpawnCount, hudSyncCountdown, weaponName[MAX_WEAPONS+1][24], Float:weaponGoal[MAX_WEAPONS+1], weaponNum, initTeamplayStr[32], initTeamplayInt = -1, bot_quota, spareName[32], sqlInit, galileoID = -1;
// stats file stuff new sfStatsStruct[statsData], lastStatsMode = -909;
// event ids new gmsgSayText, gmsgCurWeapon, gmsgStatusIcon, gmsgBombDrop, gmsgBombPickup, gmsgHideWeapon, gmsgCrosshair, gmsgScenario;
// player values new level[33], levelsThisRound[33], score[33], lvlWeapon[33][24], star[33], welcomed[33], page[33], lastKilled[33], hosties[33][2], silenced[33], respawn_timeleft[33], Float:lastSwitch[33], lastTeam[33], spawnSounds[33], spawnProtected[33], statsPosition[33][2], Float:teamTimes[33][2], pointsExtraction[33][5], Float:spawnOrigin[33][3], Float:spawnAngles[33][3], afkCheck[33], playerStats[33][statsData];
#if defined SQL #include <sqlx> // flags for the "flags" field in the gg_sql_winmotd table #define WON 1 #define LOST 2 #define LASTKILL 4 #define NEWRECORD 8
new gg_sql_host, gg_sql_user, gg_sql_pass, gg_sql_db, gg_sql_table, gg_sql_streak_table, gg_sql_winmotd_table, sqlTable[32], sqlStreakTable[32], sqlPlayersTable[32], serverip[22], Handle:tuple, Handle:db, Handle:query, safeName[64], mkQuery[1536]; #else new gg_stats_file, gg_stats_streak_file;
new sfFile[64], sfLineData[112], sfAuthid[32], sfTimestamp[12], Array:statsArray, Array:statsPointers[2], statsSize[2]; #endif
//********************************************************************** // INITIATION FUNCTIONS //**********************************************************************
new gg_knife_debug;
// plugin load public plugin_init() { gg_knife_debug = register_cvar("gg_knife_debug","0");
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"); gmsgStatusIcon = get_user_msgid("StatusIcon"); 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");
// events register_event("ResetHUD","event_resethud","be"); register_event("HLTV","event_new_round","a","1=0","2=0"); register_event("CurWeapon","event_curweapon","be","1=1"); register_event("AmmoX","event_ammox","be"); register_event("30","event_intermission","a"); register_event("TextMsg","event_round_restart","a","2=#Game_Commencing","2=#Game_will_restart_in"); register_event("23","event_bomb_detonation","a","1=17","6=-105","7=17"); // planted bomb exploded // forwards register_forward(FM_SetModel,"fw_setmodel"); register_forward(FM_EmitSound,"fw_emitsound"); // logevents register_logevent("event_bomb_detonation",6,"3=Target_Bombed"); // another bomb exploded event, for security register_logevent("logevent_bomb_planted",3,"2=Planted_The_Bomb"); // bomb planted register_logevent("logevent_bomb_defused",3,"2=Defused_The_Bomb"); // bomb defused register_logevent("logevent_round_end",2,"1=Round_End"); // round ended 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"); // messages register_message(gmsgScenario,"message_scenario"); register_message(get_user_msgid("ClCorpse"),"message_clcorpse"); register_message(get_user_msgid("Money"),"message_money"); 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 // hams RegisterHam(Ham_Touch,"weaponbox","ham_weapon_touch",0); RegisterHam(Ham_Touch,"armoury_entity","ham_weapon_touch",0); RegisterHam(Ham_Spawn,"player","ham_player_spawn",1); RegisterHam(Ham_Killed,"player","ham_player_killed_pre",0); RegisterHam(Ham_Killed,"player","ham_player_killed_post",1);
// commands register_clcmd("joinclass","cmd_joinclass"); // new menus register_menucmd(register_menuid("Terrorist_Select",1),511,"cmd_joinclass"); // old menus register_menucmd(register_menuid("CT_Select",1),511,"cmd_joinclass"); // old menus 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_score","cmd_gungame_score",ADMIN_BAN,"<target> <score> [dont_refill] - sets target's score. use + or - for relative, otherwise it's absolute."); register_concmd("amx_gungame_vote","cmd_gungame_vote",ADMIN_VOTE,"[mode] - starts a vote to toggle GunGame."); register_concmd("amx_gungame_win","cmd_gungame_win",ADMIN_BAN,"[target] - if target, forces target to win. if no target, forces highest level player to win."); register_concmd("amx_gungame_teamplay","cmd_gungame_teamplay",ADMIN_BAN,"<0|1> [killsperlvl] [suicidepenalty] - toggles teamplay mode. optionally specify new cvar values."); register_concmd("amx_gungame_restart","cmd_gungame_restart",ADMIN_BAN,"[delay] [full] - restarts GunGame. optionally specify a delay, in seconds. if full, reloads config and everything."); register_srvcmd("gg_reloadweapons","cmd_reloadweapons",ADMIN_CVAR,"- reloads the weapon order and kills per level from cvars"); 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_3|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"); weapons_menu = register_menuid("weapons_menu"); register_menucmd(weapons_menu,MENU_KEY_1|MENU_KEY_2|MENU_KEY_3|MENU_KEY_0,"weapons_menu_handler"); register_menucmd(register_menuid("top10_menu"),MENU_KEY_1|MENU_KEY_2|MENU_KEY_3|MENU_KEY_4|MENU_KEY_0,"top10_menu_handler"); scores_menu = register_menuid("scores_menu"); register_menucmd(scores_menu,MENU_KEY_1|MENU_KEY_2|MENU_KEY_3|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","2"); 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_messages = register_cvar("gg_messages","1"); gg_save_temp = register_cvar("gg_save_temp","300"); // = 5 * 60 = 5 minutes gg_status_display = register_cvar("gg_status_display","1"); 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","2"); gg_leader_display = register_cvar("gg_leader_display","1"); gg_leader_display_x = register_cvar("gg_leader_display_x","-1.0"); gg_leader_display_y = register_cvar("gg_leader_display_y","0.0"); gg_allow_changeteam = register_cvar("gg_allow_changeteam","2"); gg_disable_money = register_cvar("gg_disable_money","1"); gg_winner_motd = register_cvar("gg_winner_motd","1"); gg_afk_protection = register_cvar("gg_afk_protection","0"); gg_top10_ppp = register_cvar("gg_top10_ppp","8");
// autovote cvars gg_autovote_mode = register_cvar("gg_autovote_mode","0"); gg_autovote_rounds = register_cvar("gg_autovote_rounds","1"); 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 #if !defined SQL gg_stats_file = register_cvar("gg_stats_file","gungame.stats"); gg_stats_streak_file = register_cvar("gg_stats_streak_file","gungame.streaks"); #endif 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","2"); gg_stats_split = register_cvar("gg_stats_split","0"); gg_stats_winbonus = register_cvar("gg_stats_winbonus","1.5"); // deathmatch cvars gg_dm = register_cvar("gg_dm","1"); 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","2"); gg_dm_start_random = register_cvar("gg_dm_start_random","1"); gg_dm_spawn_delay = register_cvar("gg_dm_spawn_delay","3.0"); 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","2"); // 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","2"); gg_host_rescue_reward = register_cvar("gg_host_rescue_reward","2"); gg_host_kill_reward = register_cvar("gg_host_kill_reward","1"); gg_host_kill_penalty = register_cvar("gg_host_kill_penalty","1"); // teamplay cvars gg_teamplay = register_cvar("gg_teamplay","0"); gg_teamplay_knife_mod = register_cvar("gg_teamplay_knife_mod","0.33"); gg_teamplay_nade_mod = register_cvar("gg_teamplay_nade_mod","0.50"); gg_teamplay_timeratio = register_cvar("gg_teamplay_timeratio","1");
// 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,p9 0,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","1"); gg_knife_pro = register_cvar("gg_knife_pro","1"); gg_knife_elite = register_cvar("gg_knife_elite","0"); gg_suicide_penalty = register_cvar("gg_suicide_penalty","1"); gg_worldspawn_suicide = register_cvar("gg_worldspawn_suicide","1"); 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_warmup_weapon = register_cvar("gg_warmup_weapon",KNIFE); gg_warmup_multi = register_cvar("gg_warmup_multi","0"); gg_nade_glock = register_cvar("gg_nade_glock","1"); 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","1"); gg_nade_refresh = register_cvar("gg_nade_refresh","5.0"); gg_kills_per_lvl = register_cvar("gg_kills_per_lvl","2"); gg_kills_botmod = register_cvar("gg_kills_botmod","1.0"); 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","1"); gg_awp_oneshot = register_cvar("gg_awp_oneshot","1"); gg_bots_skipnade = register_cvar("gg_bots_skipnade","0"); gg_bots_knifeable = register_cvar("gg_bots_knifeable","1");
#if defined SQL // SQL cvars gg_sql_host = register_cvar("gg_sql_host","localhost",FCVAR_PROTECTED); gg_sql_user = register_cvar("gg_sql_user","root",FCVAR_PROTECTED); gg_sql_pass = register_cvar("gg_sql_pass","",FCVAR_PROTECTED); gg_sql_db = register_cvar("gg_sql_db","gungame",FCVAR_PROTECTED); // default should be: amx gg_sql_table = register_cvar("gg_sql_table","gg_stats",FCVAR_PROTECTED); gg_sql_streak_table = register_cvar("gg_sql_streak_table","gg_streaks",FCVAR_PROTECTED); gg_sql_winmotd_table = register_cvar("gg_sql_winmotd_table","gg_winmotd",FCVAR_PROTECTED);
get_user_ip(0,serverip,21,0); // with port #else sqlInit = 1; #endif // sound cvars done in plugin_precache now
// 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,""); } // update status immediately ggActive = get_pcvar_num(gg_enabled);
// 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); // make sure we have this to trick mapchooser.amxx into working if(!cvar_exists("mp_maxrounds")) register_cvar("mp_maxrounds","0",FCVAR_SERVER|FCVAR_EXTDLL|FCVAR_SPONLY);
// collect some other information that would be handy maxPlayers = get_maxplayers(); // create hud sync objects hudSyncWarmup = CreateHudSyncObj(); hudSyncReqKills = CreateHudSyncObj(); hudSyncLDisplay = CreateHudSyncObj(); hudSyncCountdown = CreateHudSyncObj(); // remember the mod new modName[7]; get_modname(modName,6); if(equal(modName,"czero")) { czero = 1; bot_quota = get_cvar_pointer("bot_quota"); } // identify this as a bomb map if(fm_find_ent_by_class(maxPlayers,"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(maxPlayers,"hostage_entity")) hostageMap = 1; // get spawns for deathmatch init_spawns();
// 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"); // map configs take 6.1 seconds to load set_task(6.2,"setup_weapon_order"); set_task(6.2,"stats_get_top_players",TASK_GET_TOP_PLAYERS); }
// plugin precache public plugin_precache() { // used in precache_sounds_from_config() get_configsdir(cfgDir,31);
// sound cvars gg_sound_levelup = register_cvar("gg_sound_levelup","sound/gungame/smb3_powerup.wav"); gg_sound_leveldown = register_cvar("gg_sound_leveldown","sound/gungame/smb3_powerdown.wav"); gg_sound_levelsteal = register_cvar("gg_sound_levelsteal","sound/gungame/smb3_1-up.wav"); gg_sound_nade = register_cvar("gg_sound_nade","sound/gungame/nade_level.wav"); gg_sound_knife = register_cvar("gg_sound_knife","sound/gungame/knife_level.wav"); gg_sound_welcome = register_cvar("gg_sound_welcome","sound/gungame/gungame2.wav"); gg_sound_triple = register_cvar("gg_sound_triple","sound/gungame/smb_star.wav"); gg_sound_winner = register_cvar("gg_sound_winner","media/Half-Life03.mp3;media/Half-Life08.mp3;media/Half-Life11.mp3;media/Half-Life17.mp3"); gg_sound_takenlead = register_cvar("gg_sound_takenlead","sound/gungame/takenlead.wav"); gg_sound_tiedlead = register_cvar("gg_sound_tiedlead","sound/gungame/tiedlead.wav"); gg_sound_lostlead = register_cvar("gg_sound_lostlead","sound/gungame/lostlead.wav"); gg_lead_sounds = register_cvar("gg_lead_sounds","0.8");
mp_friendlyfire = get_cvar_pointer("mp_friendlyfire");
// precache everything in the config (regular and teamplay) -- we might need them precache_sounds_from_config();
// also precache what we have now, in case the server doesn't have a GunGame config precache_sound_by_cvar(gg_sound_levelup); precache_sound_by_cvar(gg_sound_leveldown); precache_sound_by_cvar(gg_sound_levelsteal); precache_sound_by_cvar(gg_sound_nade); precache_sound_by_cvar(gg_sound_knife); precache_sound_by_cvar(gg_sound_welcome); precache_sound_by_cvar(gg_sound_triple); precache_sound_by_cvar(gg_sound_takenlead); precache_sound_by_cvar(gg_sound_tiedlead); precache_sound_by_cvar(gg_sound_lostlead);
get_pcvar_string(gg_sound_winner,dummy,1); if(dummy[0]) // win sounds enabled { // gg_sound_winner might contain multiple sounds new buffer[WINSOUNDS_SIZE], temp[MAX_WINSOUND_LEN+1], pos; get_pcvar_string(gg_sound_winner,buffer,WINSOUNDS_SIZE-1); while(numWinSounds < MAX_WINSOUNDS) { pos = contain_char(buffer,';'); // no more after this, precache what we have left if(pos == -1) { if(buffer[0]) { precache_sound_special(buffer); copy(winSounds[numWinSounds++],MAX_WINSOUND_LEN,buffer); } break; } // copy up to the semicolon and precache that copy(temp,pos,buffer); if(temp[0]) { precache_sound_special(temp); copy(winSounds[numWinSounds++],MAX_WINSOUND_LEN,temp); }
// copy everything after the semicolon copy(buffer,WINSOUNDS_SIZE-1,buffer[pos+1]); } }
// some generic, non-changing things precache_sound(BRASS_BELL_SOUND); precache_sound(KILL_DING_SOUND); precache_sound("common/null.wav");
// for the star trailSpr = precache_model("sprites/laserbeam.spr"); }
public plugin_cfg() { galileoID = is_plugin_loaded("Galileo"); }
public plugin_end() { #if defined SQL sql_uninit(); #endif
// run endmap setup on plugin close if(ggActive) { // reset random teamplay if(initTeamplayInt != -1) set_pcvar_string(gg_teamplay,initTeamplayStr);
new setup[512]; get_pcvar_string(gg_endmap_setup,setup,511); if(setup[0]) server_cmd(setup); } }
//********************************************************************** // FORWARDS //**********************************************************************
// client gets a steamid public client_authorized(id) { clear_values(id);
static authid[32]; get_gg_authid(id,authid,31);
// load temporary save if(ggActive && 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][svAuthid],31)) { save = i; break; } }
// we found a save if(save > -1) { if(!get_pcvar_num(gg_teamplay)) { // these are solo-only level[id] = tempSave[save][svLevel]; score[id] = tempSave[save][svScore]; get_level_weapon(level[id],lvlWeapon[id],23); }
statsPosition[id][0] = tempSave[save][svStatsPosition][0]; statsPosition[id][1] = tempSave[save][svStatsPosition][1]; teamTimes[id][0] = Float:tempSave[save][svTeamTimes][0]; teamTimes[id][1] = Float:tempSave[save][svTeamTimes][1];
// clear it clear_save(TASK_CLEAR_SAVE+save); } } #if defined SQL if(!statsPosition[id][0]) stats_get_position(id,authid,0); if(!statsPosition[id][1]) stats_get_position(id,authid,1); #else // cache our position if we didn't get it from a save if(!statsPosition[id][0] || !statsPosition[id][1]) { if(statsArray) // we've set up the stats array { recheck_stats_sorting(); // see if anything changed
// if nothing happened, get my position if(!statsPosition[id][0]) stats_get_position(id,authid,0); if(!statsPosition[id][1]) stats_get_position(id,authid,1); } } #endif #if defined REFRESH_TIMESTAMP_ON_JOIN stats_refresh_timestamp(authid); #endif }
// client leaves, reset values public client_disconnect(id) { // remove certain tasks remove_task(TASK_VERIFY_WEAPON+id); remove_task(TASK_REFRESH_NADE+id); remove_task(TASK_RESPAWN+id); remove_task(TASK_CHECK_DEATHMATCH+id); remove_task(TASK_REMOVE_PROTECTION+id); remove_task(TASK_DELAYED_SUICIDE+id); // don't bother saving if in winning period or warmup if(!won && warmup <= 0) { new save_temp = get_pcvar_num(gg_save_temp);
// temporarily save values if(ggActive && save_temp && (level[id] > 1 || score[id] > 0)) { // keep track of times new team = get_user_team(id); if(team == 1 || team == 2) teamTimes[id][team-1] += get_gametime() - lastSwitch[id];
new freeSave = -1, oldestSave = -1, i;
for(i=0;i<TEMP_SAVES;i++) { // we found a free one if(!tempSave[i][svAuthid][0]) { freeSave = i; break; }
// keep track of one soonest to expire if(oldestSave == -1 || tempSave[i][svTime] < tempSave[oldestSave][svTime]) oldestSave = i; }
// no free, use oldest if(freeSave == -1) freeSave = oldestSave;
get_gg_authid(id,tempSave[freeSave][svAuthid],31);
tempSave[freeSave][svLevel] = level[id]; tempSave[freeSave][svScore] = score[id]; tempSave[freeSave][svStatsPosition][0] = statsPosition[id][0]; tempSave[freeSave][svStatsPosition][1] = statsPosition[id][1]; tempSave[freeSave][svTeamTimes][0] = _:teamTimes[id][0]; tempSave[freeSave][svTeamTimes][1] = _:teamTimes[id][1]; tempSave[freeSave][svTime] = _:get_gametime();
set_task(float(save_temp),"clear_save",TASK_CLEAR_SAVE+freeSave); } }
clear_values(id); statsPosition[id][0] = 0; statsPosition[id][1] = 0; stats_clear_struct(playerStats[id]); }
// someone joins, monitor ham hooks public client_putinserver(id) { if(czero && !czbot_hams && is_user_bot(id) && get_pcvar_num(bot_quota) > 0) set_task(0.1,"czbot_hook_ham",id); // bots don't call joinclass if(is_user_bot(id)) cmd_joinclass(id); }
// delay for private data to initialize -- // here is the problem: registering a ham hook for "player" won't // register it for CZ bots, for some reason. so we have to register // it by entity. so we do this ridiculous thing in order to do so. public czbot_hook_ham(id) { if(czbot_hams || !is_user_connected(id)) return;
// probably a czero bot if(is_user_bot(id) && get_pcvar_num(bot_quota) > 0) { RegisterHamFromEntity(Ham_Spawn,id,"ham_player_spawn",1); RegisterHamFromEntity(Ham_Killed,id,"ham_player_killed_pre",0); RegisterHamFromEntity(Ham_Killed,id,"ham_player_killed_post",1);
czbot_hams = 1; // bug fix for mid-round spawning, thanks to MeRcyLeZZ if(is_user_alive(id)) ham_player_spawn(id); } }
// remove a save public clear_save(taskid) { remove_task(taskid); tempSave[taskid-TASK_CLEAR_SAVE][svAuthid][0] = 0; }
// my info... it's changed! public client_infochanged(id) { if(!ggActive || !is_user_connected(id)) return PLUGIN_CONTINUE; new oldTeam = lastTeam[id], newTeam = _:cs_get_user_team(id); // this means it was caught by logevent_team_join, or wasn't a team change if(oldTeam == newTeam) return PLUGIN_CONTINUE; player_teamchange(id,oldTeam,newTeam); // invalid team if((newTeam != 1 && newTeam != 2) || !get_pcvar_num(gg_teamplay)) return PLUGIN_CONTINUE; // something is out of synch if(teamLevel[newTeam] && (level[id] != teamLevel[newTeam] || score[id] != teamScore[newTeam] || !equal(lvlWeapon[id],teamLvlWeapon[newTeam]))) { // set them directly level[id] = teamLevel[newTeam]; lvlWeapon[id] = teamLvlWeapon[newTeam]; score[id] = teamScore[newTeam];
// gimme mah weapon! if(is_user_alive(id)) give_level_weapon(id); } return PLUGIN_CONTINUE; }
//********************************************************************** // FORWARD HOOKS //**********************************************************************
// an entity is given a model, check for silenced/burst status public fw_setmodel(ent,model[]) { if(!ggActive) return FMRES_IGNORED;
new owner = pev(ent,pev_owner);
// no owner if(!is_user_connected(owner)) return FMRES_IGNORED;
static classname[24]; // the extra space is used later 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;
// ignore C4 // checks for models/w_backpack.mdl if(len == 21 && model[9] == 'b') return FMRES_IGNORED;
// checks for models/w_usp.mdl, usp, models/w_m4a1.mdl, m4a1 if((len == 16 && model[10] == 's' && lvlWeapon[owner][1] == 's') || (len == 17 && model[10] == '4' && lvlWeapon[owner][1] == '4') ) { copyc(model,len-1,model[contain_char(model,'_')+1],'.'); // strips off models/w_ and .mdl formatex(classname,23,"weapon_%s",model);
// remember silenced status 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' && lvlWeapon[owner][6] == '8') || (len == 18 && model[9] == 'f' && model[10] == 'a' && lvlWeapon[owner][0] == 'f' && lvlWeapon[owner][1] == 'a') ) { copyc(model,len-1,model[contain_char(model,'_')+1],'.'); // strips off models/w_ and .mdl formatex(classname,23,"weapon_%s",model);
// remember burst status new wEnt = fm_find_ent_by_owner(maxPlayers,classname,ent); if(pev_valid(wEnt)) silenced[owner] = cs_get_weapon_burst(wEnt); } // if owner is dead, remove it if we need to if(get_user_health(owner) <= 0 && get_pcvar_num(gg_dm) && !get_pcvar_num(gg_pickup_others)) { dllfunc(DLLFunc_Think,ent); return FMRES_SUPERCEDE; }
return FMRES_IGNORED; }
// HELLO HELLo HELlo HEllo Hello hello public fw_emitsound(ent,channel,sample[],Float:volume,Float:atten,flags,pitch) { if(!ggActive || !is_user_connected(ent) || !get_pcvar_num(gg_dm) || spawnSounds[ent]) return FMRES_IGNORED;
// used to stop spawn sounds in deathmatch return FMRES_SUPERCEDE; }
//********************************************************************** // EVENT HOOKS //**********************************************************************
// our HUD gets reset (obviously) public event_resethud(id) { if(ggActive && is_user_connected(id)) set_task(0.1,"reset_hud",id); }
// fix the leader display and hide money public reset_hud(id) { if(is_user_connected(id)) { status_display(id); if(get_pcvar_num(gg_disable_money)) hide_money(id); } }
// someone changes weapons public event_curweapon(id) { if(!ggActive || !is_user_connected(id)) return;
// keep star speed if(star[id]) fm_set_user_maxspeed(id,fm_get_user_maxspeed(id)*1.5); // monitor weapon activity if(afkCheck[id] && is_user_alive(id)) afkCheck[id]++;
// have at least one bullet 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); // current? write_byte(CSW_AWP); // weapon write_byte(1); // clip message_end(); } }
// a new round has begun public event_new_round() { static armourysHidden = 0;
roundEnded = 0; roundsElapsed++; c4planter = 0; bombStatus[3] = BOMB_PICKEDUP;
if(gameCommenced && !autovoted) { new info[6]; get_localinfo("gg_av_iter",info,5); new iter = str_to_num(info); new rotation[32]; get_pcvar_string(gg_autovote_mode,rotation,31); new amount = str_count(rotation,',')+1; if(iter <= 0 || iter > amount) { iter = 1; set_localinfo("gg_av_iter","1"); } // no rotation, just use the given value if(amount <= 1) { if(iter != 1) set_localinfo("gg_av_iter","1"); autovote_mode = str_to_num(rotation); } else { for(new i=1;i<=amount;i++) { if(contain(rotation,",") != -1) { strtok(rotation,info,5,rotation,31,','); if(i == iter) // this is the one we're looking for { autovote_mode = str_to_num(info); break; } } else // we've stripped away everything else and are left with the last one, so use it { autovote_mode = str_to_num(rotation); break; } } iter++; if(iter > amount) iter = 1; num_to_str(iter,info,5); set_localinfo("gg_av_iter",info); }
if(autovote_mode && roundsElapsed >= get_pcvar_num(gg_autovote_rounds)) { autovoted = 1; set_task(get_pcvar_float(gg_autovote_delay),"autovote_start"); } }
// game_player_equip manage_equips();
if(!ggActive) return; // we should probably warmup... // don't ask me where I'm getting this from. if(shouldWarmup) { shouldWarmup = 0; start_warmup(); } if(warmup <= 0) { new leader = get_leader();
if(equal(lvlWeapon[leader],HEGRENADE)) play_sound_by_cvar(0,gg_sound_nade); else if(equal(lvlWeapon[leader],KNIFE)) play_sound_by_cvar(0,gg_sound_knife); } // reset leader display remove_task(TASK_LEADER_DISPLAY); set_task(0.5,"show_leader_display"); // wait to initialize levels
new pickup_others = get_pcvar_num(gg_pickup_others); if(!pickup_others /*&& !armourysHidden*/) // they show up again on new round { set_task(0.1,"hide_armory_entitys"); armourysHidden = 1; } else if(pickup_others && armourysHidden) { set_task(0.1,"show_armory_entitys"); armourysHidden = 0; }
// block hostages if(hostageMap) { // block hostages if(get_pcvar_num(gg_block_objectives)) set_task(0.1,"move_hostages"); else { // reset hostage info new i; for(i=0;i<33;i++) { hosties[i][0] = 0; hosties[i][1] = 0; } } }
// 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"); }
// hide the armoury_entity's so players cannot pick them up public hide_armory_entitys() { new ent = maxPlayers; while((ent = fm_find_ent_by_class(ent,"armoury_entity"))) { set_pev(ent,pev_solid,SOLID_NOT); fm_set_entity_visibility(ent,0); } }
// reveal the armoury_entity's so players CAN pick them up public show_armory_entitys() { new ent = maxPlayers; while((ent = fm_find_ent_by_class(ent,"armoury_entity"))) { set_pev(ent,pev_solid,SOLID_TRIGGER); fm_set_entity_visibility(ent,1); } }
// move the hostages so that CTs can't get to them public move_hostages() { new ent = maxPlayers; while((ent = fm_find_ent_by_class(ent,"hostage_entity"))) set_pev(ent,pev_origin,Float:{8192.0,8192.0,8192.0}); }
// round is restarting (TAG: sv_restartround) public event_round_restart() { // re-entrancy fix static Float:lastThis; new Float:now = get_gametime(); if(now == lastThis) return; lastThis = now;
static message[17]; read_data(2,message,16);
if(equal(message,"#Game_Commencing")) { // don't reset values on game commencing, // if it has already commenced once if(gameCommenced) return; gameCommenced = 1; // start warmup if(ggActive) { clear_all_values();
shouldWarmup = 0; start_warmup(); return; } } /*else if(ggActive) // #Game_will_restart_in { read_data(3,message,4); // time to restart in new Float:time = floatstr(message) - 0.1; set_task((time < 0.1) ? 0.1 : time,"clear_all_values"); }*/ }
// a delayed clearing public clear_all_values() { new player; for(player=1;player<=maxPlayers;player++) { if(is_user_connected(player)) clear_values(player,1); } clear_team_values(1); clear_team_values(2); }
// the bomb explodes public event_bomb_detonation() { if(!ggActive || get_pcvar_num(gg_bomb_defuse_lvl) != 2 || !c4planter) return; // re-entrancy fix static Float:lastThis; new Float:now = get_gametime(); if(now == lastThis) return; lastThis = now;
new id = c4planter; c4planter = 0;
if(!is_user_connected(id)) return;
if(!equal(lvlWeapon[id],HEGRENADE) && !equal(lvlWeapon[id],KNIFE) && level[id] < weaponNum) { change_level(id,1); //score[id] = 0; } else if(is_user_alive(id)) refill_ammo(id); }
// 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 || !equal(lvlWeapon[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); }
// map is changing public event_intermission() { if(!ggActive) return; if(won) { if(set_nextmap()) set_task(1.0,"goto_nextmap"); return; } new player, found; for(player=1;player<=maxPlayers;player++) { if(is_user_connected(player) && on_valid_team(player)) { found = 1; break; } } // did not find any players on a valid team, game over man if(!found) { if(set_nextmap()) set_task(1.0,"goto_nextmap"); return; } // teamplay, easier to decide if(get_pcvar_num(gg_teamplay)) { new winner;
// clear winner if(teamLevel[1] > teamLevel[2]) winner = 1; else if(teamLevel[2] > teamLevel[1]) winner = 2; else { // tied for level, check score if(teamScore[1] > teamScore[2]) winner = 1; else if(teamScore[2] > teamScore[1]) winner = 2; else { // tied for level and score, pick random winner = random_num(1,2); } } // grab a player from the winning and losing teams new plWinner, plLoser, team; for(player=1;player<=maxPlayers;player++) { if(is_user_connected(player) && on_valid_team(player)) { team = _:cs_get_user_team(player);
if(!plWinner && team == winner) plWinner = player; else if(!plLoser && team != winner) plLoser = player;
if(plWinner && plLoser) break; } } win(plWinner,plLoser); if(set_nextmap()) set_task(1.0,"goto_nextmap");
return; }
// grab highest level new leaderLevel; get_leader(leaderLevel);
// grab player list new players[32], pNum, winner, i; get_players(players,pNum); // no one here if(pNum <= 0) { if(set_nextmap()) set_task(1.0,"goto_nextmap"); return; }
new topLevel[32], tlNum;
// get all of the highest level players for(i=0;i<pNum;i++) { player = players[i]; if(level[player] == leaderLevel) topLevel[tlNum++] = player; }
// 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,0); // go to next map in cycle if(set_nextmap()) set_task(1.0,"goto_nextmap"); }
//********************************************************************** // MESSAGE HOOKS //**********************************************************************
// bomb is dropped, remember for DM public message_bombdrop(msg_id,msg_dest,msg_entity) { if(ggActive && 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; }
// scenario changes public message_scenario(msg_id,msg_dest,msg_entity) { // disabled if(!ggActive) 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; }
// remove c4 if we disabled objectives public message_weappickup(msg_id,msg_dest,msg_entity) { if(!bombMap || !ggActive || !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) { if(!is_user_connected(id)) return;
ham_strip_weapon(id,"weapon_c4"); // remove it from HUD message_begin(MSG_ONE,gmsgStatusIcon,_,id); write_byte(0); write_string("c4"); message_end(); }
// block c4 ammo message if we disabled objectives public message_ammopickup(msg_id,msg_dest,msg_entity) { if(!bombMap || !ggActive || !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 || !ggActive || !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(!ggActive || !get_pcvar_num(gg_block_objectives)) return PLUGIN_CONTINUE;
return PLUGIN_HANDLED; }
// a corpse is to be set, stop player shells bug (thanks sawce) public message_clcorpse(msg_id,msg_dest,msg_entity) { if(!ggActive || get_msg_args() < 12) return PLUGIN_CONTINUE;
if(get_pcvar_num(gg_dm) && !get_pcvar_num(gg_dm_corpses)) return PLUGIN_HANDLED;
return PLUGIN_CONTINUE; }
// money money money! public message_money(msg_id,msg_dest,msg_entity) { if(!ggActive || !is_user_connected(msg_entity) || !is_user_alive(msg_entity) || !get_pcvar_num(gg_disable_money)) 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; }
//********************************************************************** // LOG EVENT HOOKS //**********************************************************************
// someone planted the bomb public logevent_bomb_planted() { if(!ggActive || !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(lvlWeapon[id],HEGRENADE) && !equal(lvlWeapon[id],KNIFE) && level[id] < weaponNum) { change_level(id,1); } else refill_ammo(id); }
}
// someone defused the bomb public logevent_bomb_defused() { if(!ggActive || !get_pcvar_num(gg_bomb_defuse_lvl)) return;
new id = get_loguser_index(); if(!is_user_connected(id)) return;
if(!equal(lvlWeapon[id],HEGRENADE) && !equal(lvlWeapon[id],KNIFE) && level[id] < weaponNum) { change_level(id,1); } 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(!ggActive || !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(lvlWeapon[id],HEGRENADE) && !equal(lvlWeapon[id],KNIFE) && level[id] < weaponNum) || score[id] + 1 < get_level_goal(level[id],id)) { // didn't level off of it if(!change_score(id,1)) show_required_kills(id); } else refill_ammo(id);
hosties[id][0] = -1; if(get_pcvar_num(gg_teamplay)) { new CsTeams:team = cs_get_user_team(id), i; for(i=1;i<=maxPlayers;i++) { // one per team if(is_user_connected(i) && cs_get_user_team(i) == team) hosties[i][0] = -1; } } } }
// hostage is rescued public logevent_hostage_rescued() { new reward = get_pcvar_num(gg_host_rescue_reward);
if(!ggActive || !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(lvlWeapon[id],HEGRENADE) && !equal(lvlWeapon[id],KNIFE) && level[id] < weaponNum) change_level(id,1); else refill_ammo(id);
hosties[id][1] = -1; if(get_pcvar_num(gg_teamplay)) { new CsTeams:team = cs_get_user_team(id), i; for(i=1;i<=maxPlayers;i++) { // one per team if(is_user_connected(i) && cs_get_user_team(i) == team) hosties[i][1] = -1; } } } }
// hostage is killed public logevent_hostage_killed() { new penalty = get_pcvar_num(gg_host_kill_penalty);
if(!ggActive || !penalty) return;
new id = get_loguser_index(); if(!is_user_connected(id)) return; new teamplay = get_pcvar_num(gg_teamplay), name[32]; if(teamplay) get_user_team(id,name,9); else get_user_name(id,name,31);
if(score[id] - penalty < 0) gungame_print(0,id,1,"%L",LANG_PLAYER_C,(teamplay) ? "HK_LEVEL_DOWN_TEAM" : "HK_LEVEL_DOWN",name,(level[id] > 1) ? level[id]-1 : level[id]); else gungame_print(0,id,1,"%L",LANG_PLAYER_C,(teamplay) ? "HK_SCORE_DOWN_TEAM" : "HK_SCORE_DOWN",name,penalty);
change_score(id,-penalty); }
// someone joins a team public logevent_team_join() { if(!ggActive) return;
new id = get_loguser_index(); if(!is_user_connected(id)) return;
new oldTeam = get_user_team(id), newTeam = _:cs_get_user_team(id); player_teamchange(id,oldTeam,newTeam); // teamplay, team switch allowed if(get_pcvar_num(gg_teamplay)) { remove_task(TASK_DELAYED_SUICIDE+id); // I was the one who planted the bomb if(c4planter == id) { // clear in case we don't find anyone c4planter = 0; new player; for(player=1;player<=maxPlayers;player++) { if(player != id && is_user_connected(player) && cs_get_user_team(player) == CS_TEAM_T) { // assign it to someone else so terrorists get points c4planter = player; break; } } } return; } // no (valid) previous team or didn't switch teams, ignore (suicide) if(oldTeam < 1 || oldTeam > 2 || newTeam < 1 || newTeam > 2 || oldTeam == 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-1]) remove_task(TASK_DELAYED_SUICIDE+id); } else remove_task(TASK_DELAYED_SUICIDE+id); }
//********************************************************************** // HAM HOOKS //**********************************************************************
// a player respawned public ham_player_spawn(id) { if(ggActive && is_user_alive(id) && cs_get_user_team(id)) // do team check here for bots spawned(id);
return HAM_IGNORED; }
// what do you think happened here? public ham_player_killed_pre(victim,killer,gib) { if(!ggActive || won || !is_user_connected(victim)) return HAM_IGNORED;
// 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(lvlWeapon[victim],"usp") || equal(lvlWeapon[victim],"m4a1")) { new wEnt = get_weapon_ent(victim,_,lvlWeapon[victim]); if(pev_valid(wEnt)) silenced[victim] = cs_get_weapon_silen(wEnt); }
// or, remember burst status else if(equal(lvlWeapon[victim],"glock18") || equal(lvlWeapon[victim],"famas")) { new wEnt = get_weapon_ent(victim,_,lvlWeapon[victim]); if(pev_valid(wEnt)) silenced[victim] = cs_get_weapon_burst(wEnt); } // some sort of death that we don't want to count if(killer == victim || !is_user_connected(killer) || cs_get_user_team(killer) == cs_get_user_team(victim)) return HAM_IGNORED;
// 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(lvlWeapon[killer],HEGRENADE) && !equal(lvlWeapon[killer],KNIFE)) { // check for hostages following this player new hostage = maxPlayers; while((hostage = fm_find_ent_by_class(hostage,"hostage_entity"))) { if(cs_get_hostage_foll(hostage) == victim && pev(hostage,pev_deadflag) == DEAD_NO) break; }
// award bonus score if victim had hostages if(hostage) { if(!equal(lvlWeapon[killer],HEGRENADE) && !equal(lvlWeapon[killer],KNIFE) && level[killer] < weaponNum) { // didn't level off of it if(!change_score(killer,host_kill_reward) || score[killer]) show_required_kills(killer); } } } return HAM_IGNORED; }
// it's just that easy (multiplay_gamerules.cpp, ln 709) public ham_player_killed_post(victim,killer,gib) { if(!ggActive || won) return HAM_IGNORED; // log in bounds if(killer > 0 && killer < 33 && victim > 0 && victim < 33) lastKilled[killer] = victim;
if(!is_user_connected(victim)) return HAM_IGNORED; // moved the below from killed_pre to killed_post because sometimes user is still alive in pre. // don't know why this wasn't here before, but just in case I need to change it back... (thanks addam)
// 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_REMOVE_PROTECTION+victim); begin_respawn(victim); fm_set_user_rendering(victim); // clear spawn protection }
remove_task(TASK_VERIFY_WEAPON+victim);
star[victim] = 0; remove_task(TASK_END_STAR+victim);
static wpnName[24]; get_killer_weapon(killer,pev(victim,pev_dmg_inflictor),wpnName,23); // grenade death if(equal(wpnName,"grenade")) { new inflictor = pev(victim,pev_dmg_inflictor); if(pev_valid(inflictor)) { new Float:dmgtime; pev(inflictor,pev_dmgtime,dmgtime); // a C4 kill will be reported as hegrenade. however, C4 has no // pev_dmgtime, while a real hegrenade does. so distinguish between hegrenade // and C4, and ignore C4 kills. also note that we can't compare models, // because at this stage both an hegrenade and C4 have no model. if(!dmgtime) { afkCheck[victim] = 0; return 0; } }
// fix name formatex(wpnName,23,HEGRENADE); }
// killed self with world if(killer == victim && equal(wpnName,"world") && is_user_connected(killer)) { // this might be a valid team switch, wait it out if(!roundEnded && get_pcvar_num(gg_allow_changeteam)) { set_task(0.1,"delayed_suicide",TASK_DELAYED_SUICIDE+victim); afkCheck[victim] = 0;
return 0; // in the meantime, don't penalize the suicide }
player_suicided(killer); afkCheck[victim] = 0;
return 1; } // afk checker if(afkCheck[victim] && afkCheck[victim] < 3) // 0 = no afk check, 3+ = they did something with a weapon (it is set to 1, and it goes to 2 when they get their new weapon) { new Float:origin[3], Float:angles[3], afk; pev(victim,pev_origin,origin); pev(victim,pev_v_angle,angles);
if(get_pcvar_num(gg_afk_protection) == 2) { // this mode requires that your origin and angles be exactly as they were when you spawned, // but it ignores the z-component because often players spawn a few units above ground afk = (origin[0] == spawnOrigin[victim][0]) && (origin[1] == spawnOrigin[victim][1]) && (angles[0] == spawnAngles[victim][0]) && (angles[1] == spawnAngles[victim][1]) && (angles[2] == spawnAngles[victim][2]); } else { // this mode allows a slight XY shift due to pushback from getting shot by certain weapons, // and also ignores the Y-component of the angle, because it sometimes inexplicably doesn't match up origin[2] = spawnOrigin[victim][2]; // ignore Z-component, they fall afk = (vector_distance(origin,spawnOrigin[victim]) < 28.0) && (angles[0] == spawnAngles[victim][0]) && (angles[2] == spawnAngles[victim][2]); }
if(afk) { new name[32]; get_user_name(victim,name,31);
gungame_print(killer,victim,1,"%L",killer,"AFK_KILL",name); afkCheck[victim] = 0; return 0; } }
afkCheck[victim] = 0;
// other player had spawn protection if(spawnProtected[victim]) { new name[32]; get_user_name(victim,name,31); gungame_print(killer,victim,1,"%L",killer,"SPAWNPROTECTED_KILL",name,floatround(get_pcvar_float(gg_dm_sp_time))); spawnProtected[victim] = 0; return 0; }
// killed self with worldspawn (fall damage usually) if(equal(wpnName,"worldspawn")) { if(get_pcvar_num(gg_worldspawn_suicide)) player_suicided(victim); return HAM_IGNORED; }
// killed self not with worldspawn if(!killer || killer == victim) { player_suicided(victim); return HAM_IGNORED; } // a non-player entity killed this man! if(!is_user_connected(killer)) { // not linked so return is hit either way if(pev_valid(killer)) { static classname[14]; pev(killer,pev_classname,classname,13); // killed by a trigger_hurt, count as suicide if(equal(classname,"trigger_hurt")) player_suicided(victim); } return HAM_IGNORED; } new teamplay = get_pcvar_num(gg_teamplay), penalty = get_pcvar_num(gg_tk_penalty);
// team kill if(is_user_connected(victim) && cs_get_user_team(killer) == cs_get_user_team(victim) && penalty >= 0) { if(penalty > 0) { new name[32]; if(teamplay) get_user_team(killer,name,9); else get_user_name(killer,name,31); if(warmup <= 0 || !warmupWeapon[0]) { if(score[killer] - penalty < 0) gungame_print(0,killer,1,"%L",LANG_PLAYER_C,(teamplay) ? "TK_LEVEL_DOWN_TEAM" : "TK_LEVEL_DOWN",name,(level[killer] > 1) ? level[killer]-1 : level[killer]); else gungame_print(0,killer,1,"%L",LANG_PLAYER_C,(teamplay) ? "TK_SCORE_DOWN_TEAM" : "TK_SCORE_DOWN",name,penalty); }
change_score(killer,-penalty); }
return HAM_IGNORED; }
new canLevel = 1, scored;
// already reached max levels this round new max_lvl = get_pcvar_num(gg_max_lvl); if(!teamplay && !get_pcvar_num(gg_turbo) && max_lvl > 0 && levelsThisRound[killer] >= max_lvl) canLevel = 0; new nade = equal(lvlWeapon[killer],HEGRENADE), knife_pro = get_pcvar_num(gg_knife_pro), victimIsBot = is_user_bot(victim), knifeLevel = equal(lvlWeapon[killer],KNIFE), bots_knifeable = get_pcvar_num(gg_bots_knifeable); // knife_pro: // 0 - nothing // 1 - killer +1 level, victim -1 level // 2 - killer +1 level, victim stays // 3 - killer +1 point, victim -1 level if(get_pcvar_num(gg_knife_debug) && equal(wpnName,KNIFE)) { new killerTeam = _:cs_get_user_team(killer), victimTeam = _:cs_get_user_team(victim);
log_message("&*&*&KNIFE KILL&*&*& %i (score %i/%i/%i lvl %i/%s -- team %i score %i lvl %i/%s) killed %i (score %i/%i/%i lvl %i/%s -- team %i score %i lvl %i/%s). knife_pro=%i, canLevel=%i, teamplay=%i", killer,score[killer],get_level_goal(level[killer],killer),get_level_goal(level[killer],0),level[killer],lvlWeapon[killer],killerTeam,teamScore[killerTeam],teamLevel[killerTeam],teamLvlWeapon[killerTeam], victim,score[victim],get_level_goal(level[victim],victim),get_level_goal(level[victim],0),level[victim],lvlWeapon[victim],victimTeam,teamScore[victimTeam],teamLevel[victimTeam],teamLvlWeapon[victimTeam], knife_pro,canLevel,teamplay); }
// was it a melee kill, and does it matter? if( !(victimIsBot && !bots_knifeable) && !knifeLevel && knife_pro && equal(wpnName,KNIFE)) { static killerName[32], victimName[32], authid[24], teamName[10]; get_user_name(killer,killerName,31); get_user_name(victim,victimName,31); get_user_authid(killer,authid,23); get_user_team(killer,teamName,9); log_message("^"%s<%i><%s><%s>^" triggered ^"Stole_Level^"",killerName,get_user_userid(killer),authid,teamName); new tpGainPoints, tpLosePoints, tpOverride; if(teamplay) { tpGainPoints = (knife_pro == 3) ? 1 : get_level_goal(level[killer],0); tpLosePoints = (knife_pro == 2) ? 0 : get_level_goal(level[victim],0);
if(warmup <= 0 || !warmupWeapon[0]) gungame_print(0,killer,1,"%L",LANG_PLAYER_C,"STOLE_LEVEL_TEAM",killerName,tpLosePoints,victimName,tpGainPoints); // allow points awarded on nade or final level if it won't level us tpOverride = (score[killer] + tpGainPoints < get_level_goal(level[killer],killer)); } else // solo play { if(warmup <= 0 || !warmupWeapon[0]) gungame_print(0,killer,1,"%L",LANG_PLAYER_C,"STOLE_LEVEL",killerName,victimName); // not a knife warmup if(nade && knife_pro == 3 && score[killer] + 1 < get_level_goal(level[killer],killer)) tpOverride = 1; // if I'm just getting 1 point and it won't level me, it's okay for the nade level }
if(tpOverride || (canLevel && !nade)) { if(tpOverride || level[killer] < weaponNum) { if(teamplay) { if(!change_score(killer,tpGainPoints,_,0)) show_required_kills(killer); // don't play sounds } else { if(knife_pro == 3) { if(!change_score(killer,1,_,0)) show_required_kills(killer); // don't play sounds } else { change_level(killer,1,_,_,_,0); // don't play sounds } } } }
play_sound_by_cvar(killer,gg_sound_levelsteal); // use this one instead!
// knife pro 2 = victim doesn't lose a level if(knife_pro != 2 && (level[victim] > 1 || teamplay)) { if(teamplay) change_score(victim,-tpLosePoints); else change_level(victim,-1); } }
// otherwise, if he killed with his appropiate weapon, give him a point else if( !(victimIsBot && !bots_knifeable && knifeLevel) && canLevel && equal(lvlWeapon[killer],wpnName)) { scored = 1;
// didn't level off of it if(!change_score(killer,1)) show_required_kills(killer); } // refresh grenades if(nade && get_pcvar_num(gg_extra_nades)) { remove_task(TASK_REFRESH_NADE+killer); // instant refresh, and refresh_nade makes sure we don't already have a nade refresh_nade(TASK_REFRESH_NADE+killer); }
if((!scored || !get_pcvar_num(gg_turbo)) && get_pcvar_num(gg_refill_on_kill)) refill_ammo(killer,1); return HAM_IGNORED; }
// a player is touching a weaponbox or armoury_entity, possibly disallow public ham_weapon_touch(weapon,other) { // gungame off and non-player or dead-player if(!ggActive || !is_user_alive(other)) return HAM_IGNORED; new knife_elite = get_pcvar_num(gg_knife_elite); // pickup others enabled, and no conflict with knife elite, stop here if(get_pcvar_num(gg_pickup_others) && (!knife_elite || !levelsThisRound[other])) return HAM_IGNORED; static model[24]; pev(weapon,pev_model,model,23);
// strips off models/w_ and .mdl copyc(model,23,model[contain_char(model,'_')+1],'.'); // weaponbox model is no good, but C4 is okay // checks for weaponbox, backpack if(model[8] == 'x' || model[0] == 'b') return HAM_IGNORED; // now that we allowed C4, check for knife elite again if(knife_elite && levelsThisRound[other]) return HAM_SUPERCEDE; // weapon is weapon_mp5navy, but model is w_mp5.mdl // checks for mp5 if(model[1] == 'p' && model[2] == '5') model = "mp5navy";
// check hegrenade exceptions // checks for hegrenade if(lvlWeapon[other][0] == 'h') { // checks for glock18, smokegrenade, flashbang if((model[6] == '8' && get_pcvar_num(gg_nade_glock)) || (model[0] == 's' && model[1] == 'm' && get_pcvar_num(gg_nade_smoke)) || (model[0] == 'f' && model[1] == 'l' && get_pcvar_num(gg_nade_flash))) return HAM_IGNORED; } // this is our weapon, don't mess with it if(equal(lvlWeapon[other],model)) return HAM_IGNORED;
return HAM_SUPERCEDE; }
//********************************************************************** // 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 = ggActive, 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; }
restart_round(5); set_task(4.8,"toggle_gungame",TASK_TOGGLE_GUNGAME+newStatus);
if(!newStatus) { set_pcvar_num(gg_enabled,0); ggActive = 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; if(autovotes[0] || autovotes[1] || autovotes[2] || task_exists(TASK_AUTOVOTE_RESULT)) { console_print(id,"[GunGame] Could not start vote: another vote is already in progress!"); return PLUGIN_HANDLED; } new arg[8]; read_argv(1,arg,7);
// override our autovote mode, but default to our autovote setting, then to 1 autovote_mode = str_to_num(arg); //if(autovote_mode < 1 || autovote_mode > 3) autovote_mode = get_pcvar_num(gg_autovote_mode); // won't work with autovote rotation, so forget it for now if(autovote_mode < 1 || autovote_mode > 3) autovote_mode = 1;
console_print(id,"[GunGame] Started a vote to play GunGame (mode %i)",autovote_mode); autovote_start();
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[8], targets[32], name[32], tnum, i; read_argv(1,arg1,31); read_argv(2,arg2,7); if(equali(arg1,"@T")) arg1 = "@TERRORIST";
// get player list if(equali(arg1,"*") || equali(arg1,"@ALL")) { get_players(targets,tnum); name = "ALL PLAYERS"; } else if(arg1[0] == '@') { new players[32], team[10], pnum; get_players(players,pnum);
for(i=0;i<pnum;i++) { get_user_team(players[i],team,9); 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,_,_,1); // always score
// absolute else for(i=0;i<tnum;i++) change_level(targets[i],intval-level[targets[i]],_,_,1); // always score
console_print(id,"[GunGame] Changed %s's level to %s",name,arg2);
return PLUGIN_HANDLED; }
// setting players score public cmd_gungame_score(id,lvl,cid) { if(!cmd_access(id,lvl,cid,3)) return PLUGIN_HANDLED;
new arg1[32], arg2[8], arg3[8], targets[32], name[32], tnum, i; read_argv(1,arg1,31); read_argv(2,arg2,7); read_argv(3,arg3,7); if(equali(arg1,"@T")) arg1 = "@TERRORIST";
// get player list if(equali(arg1,"*") || equali(arg1,"@ALL")) { get_players(targets,tnum); name = "ALL PLAYERS"; } else if(arg1[0] == '@') { new players[32], team[10], pnum; get_players(players,pnum);
for(i=0;i<pnum;i++) { get_user_team(players[i],team,9); 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), dont_refill = str_to_num(arg3);
// relative if(arg2[0] == '+' || arg2[0] == '-') for(i=0;i<tnum;i++) change_score(targets[i],intval,!dont_refill,_,_,1); // always score
// absolute else for(i=0;i<tnum;i++) change_score(targets[i],intval-score[targets[i]],!dont_refill,_,_,1); // always score
console_print(id,"[GunGame] Changed %s's score to %s",name,arg2);
return PLUGIN_HANDLED; }
// forcing a win public cmd_gungame_win(id,lvl,cid) { if(!cmd_access(id,lvl,cid,1)) return PLUGIN_HANDLED; new arg[32]; read_argv(1,arg,31); // no target given, select best player if(!arg[0]) { console_print(id,"[GunGame] Forcing the best player to win..."); event_intermission(); return PLUGIN_HANDLED; } new target = cmd_target(id,arg,2); if(!target) return PLUGIN_HANDLED;
new name[32]; get_user_name(target,name,31); console_print(id,"[GunGame] Forcing %s to win (cheater)...",name); // make our target win (oh, we're dirty!) win(target,0); return PLUGIN_HANDLED; }
// turn teamplay on or off public cmd_gungame_teamplay(id,lvl,cid) { if(!cmd_access(id,lvl,cid,2)) return PLUGIN_HANDLED;
new oldValue = get_pcvar_num(gg_teamplay);
new arg1[8], arg2[8], arg3[8]; read_argv(1,arg1,7); read_argv(2,arg2,7); read_argv(3,arg3,7);
new teamplay = str_to_num(arg1); new Float:killsperlvl = floatstr(arg2); new suicideloselvl = str_to_num(arg3); if(teamplay != oldValue) { restart_round(1); // rerun configs if teamplay changes, and don't allow toggling of GunGame on/off exec_gg_config_file(0,0); if(teamplay) exec_gg_config_file(1,0); set_pcvar_num(gg_teamplay,teamplay); map_start_cvars(1); // keepTeamplay } //server_cmd("gg_teamplay %i",teamplay); new result[128]; new len = formatex(result,127,"[GunGame] Turned Teamplay Mode %s",(teamplay) ? "on" : "off"); // important to run these after the config above
if(killsperlvl > 0.0) { server_cmd("gg_kills_per_lvl %f",killsperlvl); len += formatex(result[len],127-len,", set kills per level to %f",killsperlvl); } if(arg3[0]) { server_cmd("gg_suicide_penalty %i",suicideloselvl); len += formatex(result[len],127-len,", set suicide penalty to %i",suicideloselvl); }
console_print(id,"%s",result);
return PLUGIN_HANDLED; }
// restarts GunGame public cmd_gungame_restart(id,lvl,cid) { if(!cmd_access(id,lvl,cid,1)) return PLUGIN_HANDLED;
new arg[8]; read_argv(1,arg,7); new Float:time = floatstr(arg); if(time < 0.2) time = 0.2;
restart_round(floatround(time,floatround_ceil)); console_print(id,"[GunGame] Restarting GunGame in %i seconds",floatround(time,floatround_ceil)); read_argv(2,arg,1); if(str_to_num(arg)) set_task(time-0.1,"toggle_gungame",TASK_TOGGLE_GUNGAME+TOGGLE_ENABLE);
return PLUGIN_HANDLED; }
// reload weapon order public cmd_reloadweapons(id,lvl,cid) { if(!cmd_access(id,lvl,cid,1)) return PLUGIN_HANDLED; setup_weapon_order(); console_print(id,"* Reloaded the weapon order"); return PLUGIN_HANDLED; }
// hook say public cmd_say(id) { if(!ggActive) return PLUGIN_CONTINUE;
static message[10]; read_argv(1,message,9);
// 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_knife_elite)) console_print(id,"%L",id,"RULES_CONSOLE_LINE10",num++); if(get_pcvar_num(gg_dm) || get_cvar_num("csdm_active")) console_print(id,"%L",id,"RULES_CONSOLE_LINE11",num++); if(get_pcvar_num(gg_teamplay)) console_print(id,"%L",id,"RULES_CONSOLE_LINE12",num++); console_print(id,"****************************************************************"); 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,"%L",id,"RULES_CONSOLE_LINE16"); console_print(id,"%L",id,"RULES_CONSOLE_LINE17"); console_print(id,"-----------------------------"); console_print(id,"-----------------------------");
new 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); weapons_menu_handler(id,2); // jump to me
return PLUGIN_HANDLED; } else if(equali(message,"!top",4) && !str_count(message,' ')) // !topANYTHING { if(!sqlInit || !get_pcvar_num(gg_stats_mode)) { client_print(id,print_chat,"%L",id,"NO_WIN_LOGGING"); return PLUGIN_HANDLED; }
page[id] = 1; if(get_pcvar_num(gg_stats_split) && get_pcvar_num(gg_teamplay)) page[id] *= -1; // use negative page numbers to denote teamplay stats
show_top10_menu(id); //top10_menu_handler(id,2); // jump to me
return PLUGIN_HANDLED; } else if(equali(message,"!score") || equali(message,"!scores")) { page[id] = 1; //show_scores_menu(id); scores_menu_handler(id,2); // jump to me
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; }
new 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(!ggActive) 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(5.0,"check_joinclass",TASK_CHECK_JOINCLASS+id); return PLUGIN_CONTINUE; }
// wait a bit after joinclass to see if we should jump in public check_joinclass(taskid) { new id = taskid-TASK_CHECK_JOINCLASS;
if(!is_user_connected(id)) return;
// already respawning if(task_exists(TASK_RESPAWN+id) || is_user_alive(id) || !on_valid_team(id)) return;
respawn(TASK_RESPAWN+id); }
//********************************************************************** // RESPAWN FUNCTIONS //**********************************************************************
// get all of our spawns into their arrays init_spawns() { // grab CSDM file new mapName[32], csdmFile[64], lineData[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,lineData,63);
// invalid spawn if(!lineData[0] || str_count(lineData,' ') < 2) continue;
// BREAK IT UP! parse(lineData,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 { collect_spawns("info_player_deathmatch"); collect_spawns("info_player_start"); } }
// collect boring spawns into our spawn data collect_spawns(classname[]) { new ent = maxPlayers, Float:spawnData[3]; while((ent = fm_find_ent_by_class(ent,classname))) { // 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; } }
// bring someone back to life public begin_respawn(id) { if(!ggActive || !get_pcvar_num(gg_dm) || !is_user_connected(id)) return;
// now on spectator if(!on_valid_team(id)) 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) { set_hudmessage(255,255,255,-1.0,0.75,0,6.0,1.0,0.1,0.5); ShowSyncHudMsg(id,hudSyncCountdown,"%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) || !ggActive) 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 if(!on_valid_team(id)) 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) ClearSyncHud(id,hudSyncCountdown);
// alive, and not in the broken sort of way if(is_user_alive(id)) return; static model[22];
// remove his dropped weapons from before new ent = maxPlayers; while((ent = fm_find_ent_by_class(ent,"weaponbox"))) { 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;
ExecuteHamB(Ham_CS_RoundRespawn,id); // note the B
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,8); // goldenish } else fm_set_rendering(id,kRenderFxGlowShell,100,100,100,kRenderNormal,8); // 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 bother if(!is_user_alive(id)) 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) { // attempt to pick another random one up to three times new i; for(i=0;i<3;i++) { sp_index = random_num(0,spawnCount-1);
vecHolder[0] = spawns[sp_index][0]; vecHolder[1] = spawns[sp_index][1]; vecHolder[2] = spawns[sp_index][2]; if(is_hull_vacant(vecHolder,HULL_HUMAN)) break; }
// we made it through the entire loop, no free spaces if(i == 3) { // just find the first available 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); }
// get rid of the spawn protection effects public remove_spawn_protection(taskid) { new id = taskid-TASK_REMOVE_PROTECTION; spawnProtected[id] = 0;
if(!is_user_connected(id)) return; if(get_pcvar_num(gg_dm_sp_mode) == 2) fm_set_user_godmode(id,0); fm_set_rendering(id); // reset back to normal }
// 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) || !ggActive) return;
// now on spectator, or spawned already if(!on_valid_team(id) || is_user_alive(id)) return;
// DM still not enabled, keep waiting (or: we are still on choose-a-class screen) if(!get_pcvar_num(gg_dm) || !pev(id,pev_iuser1)) { set_task(10.0,"check_deathmatch",taskid); return; }
// DM is enabled, respawn respawn(TASK_RESPAWN+id); }
// what do you think?? public randomly_place_everyone() { // count number of legitimate players new player, validNum; for(player=1;player<=maxPlayers;player++) { if(is_user_connected(player) && on_valid_team(player)) validNum++; }
// not enough CSDM spawns for everyone if(validNum > csdmSpawnCount) return;
// now randomly place them for(player=1;player<=maxPlayers;player++) { // not spectator or unassigned if(is_user_connected(player) && on_valid_team(player)) do_random_spawn(player,2); } }
//********************************************************************** // MENU FUNCTIONS //**********************************************************************
// 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(get_pcvar_num(gg_teamplay)) { client_print(id,print_chat,"%L",id,"RESET_NOT_ALLOWED"); return PLUGIN_HANDLED; }
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),_,_,1); // back to level 1 -- always score gungame_print(0,id,1,"%L",LANG_PLAYER_C,"PLAYER_RESET",name); }
return PLUGIN_HANDLED; }
// show the level display show_level_menu(id) { #if !defined SQL recheck_stats_sorting(); #endif
new goal, tied, leaderNum, leaderList[128], name[32]; new leaderLevel, numLeaders, leader, runnerUp, len; new teamplay = get_pcvar_num(gg_teamplay), team; if(teamplay) leader = teamplay_get_lead_team(leaderLevel,numLeaders,runnerUp); else leader = get_leader(leaderLevel,numLeaders,runnerUp);
if(numLeaders > 1) tied = 1; if(teamplay) { team = _:cs_get_user_team(id);
if(numLeaders == 1) { new team1[10]; get_team_name(CsTeams:leader,team1,9); len += formatex(leaderList[len],127-len,"%s %L",team1,id,"TEAM"); } else { new team1[10], team2[10]; get_team_name(CS_TEAM_T,team1,9); get_team_name(CS_TEAM_CT,team2,9); len += formatex(leaderList[len],127-len,"%s %L, %s %L",team1,id,"TEAM",team2,id,"TEAM"); } } else { new players[32], num, i, player; get_players(players,num);
// check for multiple leaders for(i=0;i<num;i++) { player = players[i]; if(level[player] == leaderLevel) { if(++leaderNum == 5) { len += formatex(leaderList[len],127-len,", ..."); break; }
if(leaderList[0]) len += formatex(leaderList[len],127-len,", "); get_user_name(player,name,31); len += formatex(leaderList[len],127-len,"%s",name); } } }
goal = get_level_goal(level[id],id);
new displayWeapon[16]; if(level[id]) copy(displayWeapon,15,lvlWeapon[id]); else formatex(displayWeapon,15,"%L",id,"NONE");
len = formatex(menuText,511,"%L %i (%s)^n",id,(teamplay) ? "ON_LEVEL_TEAM" : "ON_LEVEL",level[id],displayWeapon); len += formatex(menuText[len],511-len,"%L^n",id,(teamplay) ? "LEVEL_MESSAGE_LINE1B" : "LEVEL_MESSAGE_LINE1A",score[id],goal);
// winning if(!tied && ((teamplay && leader == team) || (!teamplay && leader == id))) { if(teamplay) len += formatex(menuText[len],511-len,"%L^n",id,"PROGRESS_DISPLAY_TEAM1",teamLevel[leader]-teamLevel[runnerUp]); else len += formatex(menuText[len],511-len,"%L^n",id,"PROGRESS_DISPLAY1",level[id]-level[runnerUp]); } // tied else if(tied) { if(teamplay) len += formatex(menuText[len],511-len,"%L^n",id,"PROGRESS_DISPLAY_TEAM2"); else len += formatex(menuText[len],511-len,"%L^n",id,"LEVEL_MESSAGE_LINE2B"); } // losing else { if(teamplay) len += formatex(menuText[len],511-len,"%L^n",id,"PROGRESS_DISPLAY_TEAM3",teamLevel[leader]-teamLevel[runnerUp]); else len += formatex(menuText[len],511-len,"%L^n",id,"PROGRESS_DISPLAY4",leaderLevel-level[id]); }
len += formatex(menuText[len],511-len,"\d----------\w^n");
new authid[32]; get_gg_authid(id,authid,31);
new stats_mode = get_pcvar_num(gg_stats_mode);
if(sqlInit && stats_mode) { new stats_split = get_pcvar_num(gg_stats_split); // decide which sentences we should be using based on current split/teamplay settings new keyLINE3A[25], keyLINE3B[25], keyLINE4[24]; // should I rename these? nah, too long if(stats_split) { keyLINE3A = "LEVEL_MESSAGE_LINE3A_REG"; keyLINE3B = "LEVEL_MESSAGE_LINE3B_REG"; keyLINE4 = "LEVEL_MESSAGE_LINE4_REG"; } else { keyLINE3A = "LEVEL_MESSAGE_LINE3A"; keyLINE3B = "LEVEL_MESSAGE_LINE3B"; keyLINE4 = "LEVEL_MESSAGE_LINE4"; }
stats_get_data(authid,playerStats[id],id);
if(statsPosition[id][0] > 0) // show rank { new statsSuffix[3]; get_number_suffix(statsPosition[id][0],statsSuffix,2); if(stats_mode == 1) len += formatex(menuText[len],511-len,"%L (%i%s)^n",id,keyLINE3A,playerStats[id][sdWins][0],statsPosition[id][0],statsSuffix); else len += formatex(menuText[len],511-len,"%L (%i%s)^n",id,keyLINE3B,playerStats[id][sdPoints][0],playerStats[id][sdWins][0],statsPosition[id][0],statsSuffix); } else // don't show rank { if(stats_mode == 1) len += formatex(menuText[len],511-len,"%L^n",id,keyLINE3A,playerStats[id][sdWins][0]); else len += formatex(menuText[len],511-len,"%L^n",id,keyLINE3B,playerStats[id][sdPoints][0],playerStats[id][sdWins][0]); } len += formatex(menuText[len],511-len,"%L^n",id,keyLINE4,playerStats[id][sdStreak][0]); // now show teamplay if we can/should if(stats_split) { if(statsPosition[id][1] > 0) // show rank { new statsSuffix[3]; get_number_suffix(statsPosition[id][1],statsSuffix,2); if(stats_mode == 1) len += formatex(menuText[len],511-len,"%L (%i%s)^n",id,"LEVEL_MESSAGE_LINE3A_TP",playerStats[id][sdWins][1],statsPosition[id][1],statsSuffix); else len += formatex(menuText[len],511-len,"%L (%i%s)^n",id,"LEVEL_MESSAGE_LINE3B_TP",playerStats[id][sdPoints][1],playerStats[id][sdWins][1],statsPosition[id][1],statsSuffix); } else // don't show rank { if(stats_mode == 1) len += formatex(menuText[len],511-len,"%L^n",id,"LEVEL_MESSAGE_LINE3A_TP",playerStats[id][sdWins][1]); else len += formatex(menuText[len],511-len,"%L^n",id,"LEVEL_MESSAGE_LINE3B_TP",playerStats[id][sdPoints][1],playerStats[id][sdWins][1]); } len += formatex(menuText[len],511-len,"%L^n",id,"LEVEL_MESSAGE_LINE4_TP",playerStats[id][sdStreak][1]); }
len += formatex(menuText[len],511-len,"\d----------\w^n"); }
if(leaderNum > 1) len += formatex(menuText[len],511-len,"%L^n",id,"LEVEL_MESSAGE_LINE5A",leaderList); else len += formatex(menuText[len],511-len,"%L^n",id,"LEVEL_MESSAGE_LINE5B",leaderList);
if(teamplay) { if(teamLevel[leader]) copy(displayWeapon,15,teamLvlWeapon[leader]); else formatex(displayWeapon,15,"%L",id,"NONE"); } else { if(level[leader]) copy(displayWeapon,15,lvlWeapon[leader]); else formatex(displayWeapon,15,"%L",id,"NONE"); }
len += formatex(menuText[len],511-len,"%L^n",id,"LEVEL_MESSAGE_LINE6",leaderLevel,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 pppString[74], len = get_pcvar_string(gg_top10_ppp,pppString,63); // URL specified if(pppString[0] && !isdigit(pppString[0])) { new header[32], lang[3]; formatex(header,31,"%L %L",id,"GUNGAME",id,"STATS"); get_user_info(id,"lang",lang,2);
formatex(pppString[len],73-len,"?i=%i&l=%s",id,lang); show_motd(id,pppString,header);
return; }
#if !defined SQL recheck_stats_sorting(); #endif new absPage = abs(page[id]), stats_split = get_pcvar_num(gg_stats_split), si = (page[id] < 0);
new playersPerPage = str_to_num(pppString), stats_mode = get_pcvar_num(gg_stats_mode); //if(stats_split == 2) playersPerPage = 7; #if defined SQL new winsColumn[8], pointsColumn[10], streakColumn[10], totalPlayers, numRows;
if(si == 0) { winsColumn = "wins"; pointsColumn = "points"; streakColumn = "streak"; } else { winsColumn = "wins_tp"; pointsColumn = "points_tp"; streakColumn = "streak_tp"; } if(stats_mode == 2) query = SQL_PrepareQuery(db,"SELECT NULL FROM `%s` WHERE serverip='%s' AND (%s > 0 OR %s > 0);",sqlTable,serverip,winsColumn,pointsColumn); else query = SQL_PrepareQuery(db,"SELECT NULL FROM `%s` WHERE serverip='%s' AND %s > 0;",sqlTable,serverip,winsColumn);
if(SQL_ExecuteAndLog(query)) { numRows = SQL_NumRows(query); totalPlayers = playersPerPage * floatround(float(numRows+1) / float(playersPerPage),floatround_ceil); }
SQL_FreeHandle(query); #else new totalPlayers = playersPerPage * floatround(float(statsSize[si]+1) / float(playersPerPage),floatround_ceil); // +1 for streak display #endif new pageTotal = floatround(float(totalPlayers) / float(playersPerPage),floatround_ceil); if(pageTotal < 1) pageTotal = 1; if(totalPlayers < playersPerPage) totalPlayers = playersPerPage;
if(absPage > pageTotal) { new negative = (page[id] < 0); page[id] = absPage = pageTotal; if(negative) page[id] *= -1; }
if(stats_split) len = formatex(menuText,511,"\y%L %L (%i/%i)^n",id,"GUNGAME",id,(page[id] < 0) ? "STATS_TEAMPLAY" : "STATS_REGULAR",absPage,pageTotal); else len = formatex(menuText,511,"\y%L %L (%i/%i)^n",id,"GUNGAME",id,"STATS",absPage,pageTotal); new start = (playersPerPage * (absPage-1)), i; // show the top streak for the first page new topStreak, champName[32], champAuthid[32]; if(absPage == 1) { #if defined SQL query = SQL_PrepareQuery(db,"SELECT authid,streak,name FROM `%s` WHERE type='%iR' AND serverip='%s' LIMIT 1;",sqlStreakTable,si,serverip); if(SQL_ExecuteAndLog(query) && SQL_NumResults(query)) { SQL_ReadResult(query,0,champAuthid,31); topStreak = SQL_ReadResult(query,1); SQL_ReadResult(query,2,champName,31); } SQL_FreeHandle(query); #else new sfStreak[4], stats_streak_file[64]; get_pcvar_string(gg_stats_streak_file,stats_streak_file,63);
if(file_exists(stats_streak_file)) { new file = fopen(stats_streak_file,"rt"); while(file && !feof(file)) { fgets(file,sfLineData,82);
// blank, not for our stats mode, or not the record if(!sfLineData[0] || str_to_num(sfLineData[0]) != si || sfLineData[1] != 'R') continue; strtok(sfLineData[3],champAuthid,31,sfLineData,82,'^t'); // cut off prefix and authid from the left strtok(sfLineData,sfStreak,3,champName,31,'^t'); // get our streak, and the name as well
new pos = contain_char(champName,'^t'); if(pos != -1) champName[pos] = 0; // cut off the name at the tab
topStreak = str_to_num(sfStreak); } if(file) fclose(file); } #endif
if(!champName[0]) formatex(champName,31,"%L",id,"NO_ONE"); }
//len += formatex(menuText[len],511-len,"\d-----------\w^n");
new authid[32]; get_gg_authid(id,authid,31);
#if defined SQL if(numRows) { // do this to account for the streak display in our LIMIT clause if(absPage == 1) playersPerPage--; else start--;
if(stats_mode == 2) { query = SQL_PrepareQuery(db,"SELECT authid,name,%s,%s,%s,(SELECT COUNT(*)+1 FROM `%s` y WHERE y.%s > x.%s AND serverip='%s' AND (y.%s > 0 OR y.%s > 0) LIMIT 1) AS ranking FROM `%s` x WHERE x.serverip='%s' AND (x.%s > 0 OR x.%s > 0) ORDER BY %s DESC, %s DESC LIMIT %i, %i;", winsColumn,pointsColumn,streakColumn,sqlTable,pointsColumn,pointsColumn,ser verip,winsColumn,pointsColumn,sqlTable,serverip,winsColumn,pointsColumn,pointsCol umn,winsColumn,start,playersPerPage); } else { query = SQL_PrepareQuery(db,"SELECT authid,name,%s,%s,%s,(SELECT COUNT(*)+1 FROM `%s` y WHERE y.%s > x.%s AND serverip='%s' AND y.%s > 0 LIMIT 1) AS ranking FROM `%s` x WHERE x.serverip='%s' AND x.%s > 0 ORDER BY %s DESC LIMIT %i, %i;", winsColumn,pointsColumn,streakColumn,sqlTable,winsColumn,winsColumn,serveri p,winsColumn,sqlTable,serverip,winsColumn,winsColumn,start,playersPerPage); } // reverse changes made above for LIMIT if(absPage == 1) playersPerPage++; else start++; }
if(!numRows || SQL_ExecuteAndLog(query)) { new ranking, moreResults, lastRanking = start; if(numRows) moreResults = SQL_MoreResults(query);
for(i=start;i<start+playersPerPage;i++) { if(i >= totalPlayers) break;
// use the first slot to display the record streak if(i == 0) { len += formatex(menuText[len],511-len,"%s%L^n",(equal(authid,champAuthid)) ? "\r" : "\w",id,"RECORD_STREAK",champName,topStreak); continue; } // all out of rows if(!moreResults) { lastRanking++; len += formatex(menuText[len],511-len,"\w#%i \d%L^n",lastRanking,id,"NONE"); continue; } SQL_ReadResult(query,0,sfStatsStruct[sdAuthid],31); SQL_ReadResult(query,1,sfStatsStruct[sdName],31); sfStatsStruct[sdWins][si] = SQL_ReadResult(query,2); sfStatsStruct[sdPoints][si] = SQL_ReadResult(query,3); sfStatsStruct[sdStreak][si] = SQL_ReadResult(query,4); ranking = SQL_ReadResult(query,5);
if(stats_mode == 1) { if(sfStatsStruct[sdStreak][si] > 1) len += formatex(menuText[len],511-len,"%s#%i %s (%i %L, %L)^n",(equal(authid,sfStatsStruct[sdAuthid])) ? "\r" : "\w",ranking,sfStatsStruct[sdName],sfStatsStruct[sdWins][si],id,"WINS",id,"IN_A_ROW",sfStatsStruct[sdStreak][si]); else len += formatex(menuText[len],511-len,"%s#%i %s (%i %L)^n",(equal(authid,sfStatsStruct[sdAuthid])) ? "\r" : "\w",ranking,sfStatsStruct[sdName],sfStatsStruct[sdWins][si],id,"WINS"); } else { if(sfStatsStruct[sdStreak][si] > 1) len += formatex(menuText[len],511-len,"%s#%i %s (%i %L, %i %L, %L)^n",(equal(authid,sfStatsStruct[sdAuthid])) ? "\r" : "\w",ranking,sfStatsStruct[sdName],sfStatsStruct[sdPoints][si],id,"POINTS",sfStatsStruct[sdWins][si],id,"WINS",id,"IN_A_ROW",sfStatsStruct[sdStreak][si]); else len += formatex(menuText[len],511-len,"%s#%i %s (%i %L, %i %L)^n",(equal(authid,sfStatsStruct[sdAuthid])) ? "\r" : "\w",ranking,sfStatsStruct[sdName],sfStatsStruct[sdPoints][si],id,"POINTS",sfStatsStruct[sdWins][si],id,"WINS"); }
SQL_NextRow(query); moreResults = SQL_MoreResults(query); lastRanking = ranking; } }
if(numRows) SQL_FreeHandle(query); #else for(i=start;i<start+playersPerPage;i++) { if(i >= totalPlayers) break;
// use the first slot to display the record streak if(i == 0) { len += formatex(menuText[len],511-len,"%s%L^n",(equal(authid,champAuthid)) ? "\r" : "\w",id,"RECORD_STREAK",champName,topStreak); continue; }
// blank if(i-1 >= statsSize[si]) { len += formatex(menuText[len],511-len,"\w#%i \d%L^n",i/*+1-1*/,id,"NONE"); continue; }
ArrayGetArray(statsArray,ArrayGetCell(statsPointers[si],i-1),sfStatsStruct);
if(stats_mode == 1) { if(sfStatsStruct[sdStreak][si] > 1) len += formatex(menuText[len],511-len,"%s#%i %s (%i %L, %L)^n",(equal(authid,sfStatsStruct[sdAuthid])) ? "\r" : "\w",i/*+1-1*/,sfStatsStruct[sdName],sfStatsStruct[sdWins][si],id,"WINS",id,"IN_A_ROW",sfStatsStruct[sdStreak][si]); else len += formatex(menuText[len],511-len,"%s#%i %s (%i %L)^n",(equal(authid,sfStatsStruct[sdAuthid])) ? "\r" : "\w",i/*+1-1*/,sfStatsStruct[sdName],sfStatsStruct[sdWins][si],id,"WINS"); } else { if(sfStatsStruct[sdStreak][si] > 1) len += formatex(menuText[len],511-len,"%s#%i %s (%i %L, %i %L, %L)^n",(equal(authid,sfStatsStruct[sdAuthid])) ? "\r" : "\w",i/*+1-1*/,sfStatsStruct[sdName],sfStatsStruct[sdPoints][si],id,"POINTS",sfStatsStruct[sdWins][si],id,"WINS",id,"IN_A_ROW",sfStatsStruct[sdStreak][si]); else len += formatex(menuText[len],511-len,"%s#%i %s (%i %L, %i %L)^n",(equal(authid,sfStatsStruct[sdAuthid])) ? "\r" : "\w",i/*+1-1*/,sfStatsStruct[sdName],sfStatsStruct[sdPoints][si],id,"POINTS",sfStatsStruct[sdWins][si],id,"WINS"); } } #endif
len += formatex(menuText[len],511-len,"\d-----------\w^n");
new keys = MENU_KEY_0;
if(absPage > 1) { len += formatex(menuText[len],511-len,"1. %L^n",id,"PREVIOUS"); keys |= MENU_KEY_1; } if(absPage < pageTotal) { len += formatex(menuText[len],511-len,"2. %L^n",id,"NEXT"); keys |= MENU_KEY_2; } if(statsPosition[id][si] > 0) { len += formatex(menuText[len],511-len,"3. %L^n",id,"JUMP_TO_ME"); keys |= MENU_KEY_3; } if(stats_split) { len += formatex(menuText[len],511-len,"4. %L^n",id,(page[id] < 0) ? "STATS_REGULAR" : "STATS_TEAMPLAY"); keys |= MENU_KEY_4; } 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) { #if !defined SQL recheck_stats_sorting(); #endif new si = (page[id] < 0); new playersPerPage = get_pcvar_num(gg_top10_ppp); //if(get_pcvar_num(gg_stats_split) == 2) playersPerPage = 7; #if defined SQL new winsColumn[8], pointsColumn[10], totalPlayers, stats_mode = get_pcvar_num(gg_stats_mode);
if(si == 0) { winsColumn = "wins"; pointsColumn = "points"; } else { winsColumn = "wins_tp"; pointsColumn = "points_tp"; } if(stats_mode == 2) query = SQL_PrepareQuery(db,"SELECT NULL FROM `%s` WHERE serverip='%s' AND (%s > 0 OR %s > 0);",sqlTable,serverip,winsColumn,pointsColumn); else query = SQL_PrepareQuery(db,"SELECT NULL FROM `%s` WHERE serverip='%s' AND %s > 0;",sqlTable,serverip,winsColumn);
if(SQL_ExecuteAndLog(query)) totalPlayers = playersPerPage * floatround(float(SQL_NumRows(query)+1) / float(playersPerPage),floatround_ceil); SQL_FreeHandle(query); #else new totalPlayers = playersPerPage * floatround(float(statsSize[si]+1) / float(playersPerPage),floatround_ceil); // +1 for streak display #endif
new pageTotal = floatround(float(totalPlayers) / float(playersPerPage),floatround_ceil); if(pageTotal < 1) pageTotal = 1;
if(!page[id] || page[id] > pageTotal) return;
// 1. Previous if(key == 0) { if(page[id] < 0) page[id]++; else page[id]--;
show_top10_menu(id); }
// 2. Next else if(key == 1) { if(page[id] < 0) page[id]--; else page[id]++;
show_top10_menu(id); } // 3. Jump to me else if(key == 2) { #if defined SQL if(statsPosition[id][si] > 0) { // using SQL stats, players can have tied rankings (ie: 1st, 1st, 3rd). so, if we know a player's ranking, we don't necessarily know // what page they're on (they could be the last of 20 players all tied for 1st, for example). however, we do know what position (and // therefore also the page) that their ranking starts on. then we can select everyone with an equal score, and process the results // until we find their authid, to see how many positions off they are from the start of their ranking. then find the page for that.
new authid[32], myPoints; get_gg_authid(id,authid,31);
stats_get_data(authid,playerStats[id],id);
if(stats_mode == 2) { myPoints = playerStats[id][sdPoints][si]; query = SQL_PrepareQuery(db,"SELECT authid FROM `%s` WHERE %s='%i' AND serverip='%s' ORDER BY %s, %s DESC;",sqlTable,pointsColumn,myPoints,serverip,pointsColumn,winsColumn); } else { myPoints = playerStats[id][sdWins][si]; query = SQL_PrepareQuery(db,"SELECT authid FROM `%s` WHERE %s='%i' AND serverip='%s' ORDER BY %s DESC;",sqlTable,winsColumn,myPoints,serverip,winsColumn); } if(SQL_ExecuteAndLog(query)) { new position = statsPosition[id][si]; // start at my position
if(SQL_NumRows(query) > 1) // if I'm the only one with my score, no searching is necessary { new rowAuthid[32]; while(SQL_MoreResults(query)) { SQL_ReadResult(query,0,rowAuthid,31); if(equal(authid,rowAuthid)) break; position++; SQL_NextRow(query); } } new negative = (page[id] < 0); page[id] = floatround(float(position) / float(playersPerPage),floatround_floor) + 1; if(negative) page[id] *= -1; } SQL_FreeHandle(query); } #else if(statsPosition[id][si] > 0) { // this method of finding the page is slightly different from the weapons and scores menu because // this listing is 0-based, because we use the 0th index to display the record win streak. also, // because we use negative numbers for the teamplay stats index.
new negative = (page[id] < 0); page[id] = floatround(float(statsPosition[id][si]) / float(playersPerPage),floatround_floor) + 1; if(negative) page[id] *= -1; } #endif show_top10_menu(id); } // 4. Regular Stats / Teamplay Stats else if(key == 3) { page[id] *= -1; show_top10_menu(id); }
// 0. Close // do nothing, menu closes automatically }
// show the weapon list menu show_weapons_menu(id) { new totalWeapons = weaponNum, 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;
new len = formatex(menuText,511,"\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;
// are there any custom kill requirements? new customKills, Float:expected, Float:killsperlvl = get_pcvar_float(gg_kills_per_lvl); for(i=0;i<weaponNum;i++) { if(equal(weaponName[i],KNIFE) || equal(weaponName[i],HEGRENADE)) expected = 1.0; else expected = killsperlvl; if(weaponGoal[i] != expected) { customKills = 1; break; } }
for(i=start;i<start+wpnsPerPage;i++) { if(i > totalWeapons) break;
if(customKills) len += formatex(menuText[len],511-len,"%s%L %i: %s (%i)^n",(i == level[id]) ? "\r" : "\w",id,"LEVEL",i,weaponName[i-1],get_level_goal(i)); else len += formatex(menuText[len],511-len,"%s%L %i: %s^n",(i == level[id]) ? "\r" : "\w",id,"LEVEL",i,weaponName[i-1]); }
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,"3. %L^n",id,"JUMP_TO_ME"); keys |= MENU_KEY_3;
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 wpnsPerPage = 10, pageTotal = floatround(float(weaponNum) / 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; } // 3. Jump to me else if(key == 2) { page[id] = clamp(floatround(float(level[id]) / float(wpnsPerPage),floatround_ceil),1,pageTotal); show_weapons_menu(id); }
// 0. Close // do nothing, menu closes automatically }
// show the score list menu show_scores_menu(id) { #if !defined SQL recheck_stats_sorting(); #endif
new keys, len, teamplay = get_pcvar_num(gg_teamplay);
if(teamplay) { if(page[id] != 1) page[id] = 1; new leader = teamplay_get_lead_team(), otherTeam = (leader == 1) ? 2 : 1; new displayWeapon[24], teamName[10];
len = formatex(menuText,511,"\y%L %L (%i/%i)\w^n",id,"GUNGAME",id,"SCORES",page[id],1); new team, myTeam = _:cs_get_user_team(id); for(team=leader;team>0;team=otherTeam) { if(teamLevel[team] && teamLvlWeapon[team][0]) copy(displayWeapon,23,teamLvlWeapon[team]); else formatex(displayWeapon,23,"%L",id,"NONE");
get_team_name(CsTeams:team,teamName,9); len += formatex(menuText[len],511-len,"%s#%i %s %L, %L %i (%s) %i/%i^n",(team == myTeam) ? "\r" : "\w",(team == leader) ? 1 : 2,teamName,id,"TEAM",id,"LEVEL",teamLevel[team],displayWeapon,teamScore[team],teamplay_get_team_goal(team)); // finished if(team == otherTeam) break; }
// nice separator! len += formatex(menuText[len],511-len,"\d-----------\w^n");
keys = MENU_KEY_0; len += formatex(menuText[len],511-len,"0. %L",id,"CLOSE"); } else { new totalPlayers = get_playersnum(), playersPerPage = 7, 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");
if(get_pcvar_num(gg_stats_split)) len = formatex(menuText,511,"\y%L %L (%i/%i) %L\w^n",id,"GUNGAME",id,"SCORES",page[id],pageTotal,id,"STATS_REGULAR"); else 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[32]; new stats_ip = get_pcvar_num(gg_stats_ip), displayWeapon[24], statsSuffix[3]; new si = get_gg_si();
for(i=start;i<start+playersPerPage;i++) { if(i >= totalPlayers) break;
player = players[i]; get_user_name(player,name,31);
if(level[player] && lvlWeapon[player][0]) copy(displayWeapon,23,lvlWeapon[player]); else formatex(displayWeapon,23,"%L",id,"NONE");
if(sqlInit && stats_mode) { get_gg_authid(player,authid,31,stats_ip); stats_get_data(authid,playerStats[player],player);
if(statsPosition[player][si] > 0) { get_number_suffix(statsPosition[player][si],statsSuffix,2); len += formatex(menuText[len],511-len,"%s#%i %s, %L %i (%s) %i/%i, %i %L (%i%s)^n",(player == id) ? "\r" : "\w",i+1,name,id,"LEVEL",level[player],displayWeapon,score[player],get_level_goal(level[player],player),(stats_mode == 1) ? playerStats[player][sdWins][si] : playerStats[player][sdPoints][si],id,(stats_mode == 1) ? "WINS" : "POINTS_ABBR",statsPosition[player][si],statsSuffix); } else len += formatex(menuText[len],511-len,"%s#%i %s, %L %i (%s) %i/%i, %i %L^n",(player == id) ? "\r" : "\w",i+1,name,id,"LEVEL",level[player],displayWeapon,score[player],get_level_goal(level[player],player),(stats_mode == 1) ? playerStats[player][sdWins][si] : playerStats[player][sdPoints][si],id,(stats_mode == 1) ? "WINS" : "POINTS_ABBR"); } else len += formatex(menuText[len],511-len,"#%i %s, %L %i (%s) %i/%i^n",i+1,name,id,"LEVEL",level[player],displayWeapon,score[player],get_level_goal(level[player],player)); }
len += formatex(menuText[len],511-len,"\d-----------\w^n");
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,"3. %L^n",id,"JUMP_TO_ME"); keys |= MENU_KEY_3;
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 = 7; 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; } // 3. Jump to me else if(key == 2) { new players[32], num, i; get_players(players,num); SortCustom1D(players,num,"score_custom_compare"); for(i=0;i<num;i++) { if(players[i] == id) break; }
page[id] = floatround(float(i+1) / float(playersPerPage),floatround_ceil); show_scores_menu(id); }
// 0. Close // do nothing, menu closes automatically }
//********************************************************************** // MAIN 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++) clear_values(i); clear_team_values(1); clear_team_values(2);
// clear temp saves for(i=0;i<TEMP_SAVES;i++) clear_save(TASK_CLEAR_SAVE+i);
if(status == TOGGLE_FORCE || status == TOGGLE_ENABLE) { // these allow toggling of GunGame on/off exec_gg_config_file(0,1); // run the regular config file if(get_pcvar_num(gg_teamplay)) exec_gg_config_file(1,1); // if teamplay, run the teamplay config file also }
// set to what we chose from amx_gungame if(status != TOGGLE_FORCE) { set_pcvar_num(gg_enabled,status); ggActive = status; } else ggActive = get_pcvar_num(gg_enabled); // otherwise see what this is after the configs have been run
// run appropiate cvars map_start_cvars(0); // this sets up weapon order
// reset some things if(!ggActive) { // set armouries to be solid again show_armory_entitys();
// clear HUD message if(warmup > 0) ClearSyncHud(0,hudSyncWarmup);
warmup = -1; warmupWeapon[0] = 0; voted = 0; won = 0;
remove_task(TASK_WARMUP_CHECK); }
// we need to get these stats (GunGame is on, we don't have them, and we aren't in the process of getting them) #if defined SQL if(ggActive && !task_exists(TASK_GET_TOP_PLAYERS)) stats_get_top_players(); // there is no statsArray for SQL #else if(ggActive && !statsArray && !task_exists(TASK_GET_TOP_PLAYERS)) stats_get_top_players(); #endif
// game_player_equip manage_equips(); // start (or stop) the leader display remove_task(TASK_LEADER_DISPLAY); show_leader_display(); // warmup weapon may've change if(warmup > 0) get_pcvar_string(gg_warmup_weapon,warmupWeapon,23); #if defined SQL // fire up the engines!! if(!sqlInit) { sql_init(); // because we can't refresh timestamps before SQL is initiated, refresh timestamps for people who joined before this #if defined REFRESH_TIMESTAMP_ON_JOIN new authid[32]; for(new i=1;i<=maxPlayers;i++) { if(is_user_connected(i)) { get_gg_authid(i,authid,31); stats_refresh_timestamp(authid); } } #endif // REFRESH_TIMESTAMP_ON_JOIN } #endif // SQL }
// run cvars that should be run on map start // // see declaration of d_rOrder for explanation of keepTeamplay public map_start_cvars(keepTeamplay) { new setup[512];
// gungame is disabled, run endmap_setup if(!ggActive) { 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); do_rOrder(keepTeamplay); // also does random teamplay setup_weapon_order(); // random win sounds currentWinSound = do_rWinSound(); } }
precache_sounds_from_config() { new cfgFile[64], command[WINSOUNDS_SIZE+32], cvar[32], value[WINSOUNDS_SIZE], file, i, pos, len; for(i=0;i<2;i++) { get_gg_config_file(i,cfgFile,63); if(cfgFile[0] && file_exists(cfgFile)) { file = fopen(cfgFile,"rt"); while(file && !feof(file)) { fgets(file,command,WINSOUNDS_SIZE+31); len = strlen(command) - 2;
// stop at coding-style (//) comments for(pos=0;pos<len;pos++) { if(command[pos] == '/' && command[pos+1] == '/') { copy(command,pos,command); break; } }
// this is a sound if(equal(command,"gg_sound_",9)) { parse(command,cvar,31,value,WINSOUNDS_SIZE-1); // gg_sound_winner might contain multiple sounds if(command[9] == 'w' && command[10] == 'i' && value[0]) // check w AND i, thanks Tomek Kalkowski { new temp[MAX_WINSOUND_LEN+1]; while(numWinSounds < MAX_WINSOUNDS) { pos = contain_char(value,';'); // no more after this, precache what we have left if(pos == -1) { if(value[0]) { precache_sound_special(value); copy(winSounds[numWinSounds++],MAX_WINSOUND_LEN,value); } break; } // copy up to the semicolon and precache that copy(temp,pos,value); if(temp[0]) { precache_sound_special(temp); copy(winSounds[numWinSounds++],MAX_WINSOUND_LEN,temp); }
// copy everything after the semicolon copy(value,WINSOUNDS_SIZE-1,value[pos+1]); } } else precache_sound_special(value); } } if(file) fclose(file); } } }
// manage stats pruning public manage_pruning() { // stats disabled/file doesn't exist/pruning disabled if(!sqlInit || !get_pcvar_num(gg_stats_mode) || !get_pcvar_num(gg_stats_prune)) return;
#if !defined SQL get_pcvar_string(gg_stats_file,sfFile,63); if(!file_exists(sfFile)) return; // no existy #endif // get how many plugin loads 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 <= 0) { set_localinfo("gg_prune_in","9"); return; }
// time to prune if(prune_in == 1) { // result is -1 for a threaded query, so wait for results until we display new result = stats_prune(); if(result != -1) { #if defined SQL log_amx("%L",LANG_SERVER,"PRUNING",sqlTable,result); #else log_amx("%L",LANG_SERVER,"PRUNING",sfFile,result); #endif }
set_localinfo("gg_prune_in","10"); // reset our prune count 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);
if(warmup <= 0) { warmup = -13; warmupWeapon[0] = 0;
ShowSyncHudMsg(0,hudSyncWarmup,"%L",LANG_PLAYER,"WARMUP_ROUND_OVER"); restart_round(1); return; }
ShowSyncHudMsg(0,hudSyncWarmup,"%L",LANG_PLAYER,"WARMUP_ROUND_DISPLAY",warmup); set_task(1.0,"warmup_check",taskid); }
// show the leader display public show_leader_display() { static Float:lastDisplay, lastLeader, lastLevel, leaderName[32];
if(!ggActive || !get_pcvar_num(gg_leader_display)) { remove_task(TASK_LEADER_DISPLAY); return 0; } // keep it going if(!task_exists(TASK_LEADER_DISPLAY)) set_task(LEADER_DISPLAY_RATE,"show_leader_display",TASK_LEADER_DISPLAY,_,_,"b");
// don't show during warmup or game over if(warmup > 0 || won) return 0; new leaderLevel, numLeaders, leader, teamplay = get_pcvar_num(gg_teamplay); if(teamplay) leader = teamplay_get_lead_team(leaderLevel,numLeaders); else leader = get_leader(leaderLevel,numLeaders);
if(!leader || leaderLevel <= 0) return 0; // we just displayed the same message, don't flood new Float:now = get_gametime(); if(lastLevel == leaderLevel && lastLeader == leader && lastDisplay == now) return 0;
// remember for later lastDisplay = now; lastLeader = leader; lastLevel = leaderLevel; if(teamplay) get_team_name(CsTeams:leader,leaderName,9); else get_user_name(leader,leaderName,31); set_hudmessage(200,200,200,get_pcvar_float(gg_leader_display_x),get_pcvar_float(gg_leader_display_y),_,_,LEADER_DISPLAY_RATE+0.5,0.0,0.0); if(numLeaders > 1) { if(teamplay) { static otherName[10]; get_team_name((leader == 1) ? CS_TEAM_CT : CS_TEAM_T,otherName,9);
ShowSyncHudMsg(0,hudSyncLDisplay,"%L: %s + %s (%i - %s)",LANG_PLAYER,"LEADER",leaderName,otherName,leaderLevel,teamLvlWeapon[leader]) } else ShowSyncHudMsg(0,hudSyncLDisplay,"%L: %s +%i (%i - %s)",LANG_PLAYER,"LEADER",leaderName,numLeaders-1,leaderLevel,lvlWeapon[leader]); } else ShowSyncHudMsg(0,hudSyncLDisplay,"%L: %s (%i - %s)",LANG_PLAYER,"LEADER",leaderName,leaderLevel,(teamplay) ? teamLvlWeapon[leader] : lvlWeapon[leader]); return 1; }
// show the nice HUD progress display show_progress_display(id) { static statusString[48]; // weapon-specific warmup if(warmup > 0 && warmupWeapon[0]) return; new teamplay = get_pcvar_num(gg_teamplay); // old-school: sweet and simple if((get_pcvar_num(gg_messages) & MSGS_CLASSIC)) { new goal; if(teamplay) goal = get_level_goal(teamLevel[_:cs_get_user_team(id)],id); else goal = get_level_goal(level[id],id);
gungame_print(id,0,1,"%L %%n%i%%e :: %%n%s%%e",id,(teamplay) ? "ON_LEVEL_TEAM" : "ON_LEVEL",level[id],lvlWeapon[id]); gungame_print(id,0,1,"%L",id,"PROGRESS_DISPLAY",goal-score[id],score[id],goal);
return; }
if(teamplay) { new team = _:cs_get_user_team(id), otherTeam = (team == 1) ? 2 : 1; if(team != 1 && team != 2) return;
new leaderLevel, numLeaders, leader = teamplay_get_lead_team(leaderLevel,numLeaders); // tied if(numLeaders > 1) formatex(statusString,47,"%L",id,"PROGRESS_DISPLAY_TEAM2"); // leading else if(leader == team) formatex(statusString,47,"%L",id,"PROGRESS_DISPLAY_TEAM1",teamLevel[team]-teamLevel[otherTeam]);
// losing else formatex(statusString,47,"%L",id,"PROGRESS_DISPLAY_TEAM3",teamLevel[otherTeam]-teamLevel[team]); } else { new leaderLevel, numLeaders, runnerUp; new leader = get_leader(leaderLevel,numLeaders,runnerUp); if(level[id] == leaderLevel) { if(numLeaders == 1) formatex(statusString,47,"%L",id,"PROGRESS_DISPLAY1",leaderLevel-level[runnerUp]); else if(numLeaders == 2) { new otherLeader; if(leader != id) otherLeader = leader; else { new player; for(player=1;player<=maxPlayers;player++) { if(is_user_connected(player) && level[player] == leaderLevel && player != id) { otherLeader = player; break; } } } static otherName[32]; get_user_name(otherLeader,otherName,31); formatex(statusString,47,"%L",id,"PROGRESS_DISPLAY2",otherName); } else { static numWord[16], lang[3];
// if english, use words, otherwise use digits get_user_info(id,"lang",lang,2); if(equali(lang,"en")) { num_to_word(numLeaders-1,numWord,15); trim(numWord); } else formatex(numWord,15,"%i",numLeaders-1);
formatex(statusString,47,"%L",id,"PROGRESS_DISPLAY3",numWord); } } else formatex(statusString,47,"%L",id,"PROGRESS_DISPLAY4",leaderLevel-level[id]); }
gungame_hudmessage(id,5.0,"%L %i (%s)^n%s",id,(teamplay) ? "ON_LEVEL_TEAM" : "ON_LEVEL",level[id],lvlWeapon[id],statusString); }
// play the taken/tied/lost lead sounds public play_lead_sounds(id,oldLevel,Float:playDelay) { // id: the player whose level changed // oldLevel: his level before it changed // playDelay: how long to wait until we play id's sounds if(get_pcvar_num(gg_teamplay)) { // redirect to other function teamplay_play_lead_sounds(id,oldLevel,Float:playDelay); return; } // warmup or game over, no one cares if(warmup > 0 || won) return;
// no level change if(level[id] == oldLevel) return; // // monitor MY stuff first //
new leaderLevel, numLeaders; get_leader(leaderLevel,numLeaders); // I'm now on the leader level if(level[id] == leaderLevel) { // someone else here? if(numLeaders > 1) { new params[2]; params[0] = id; params[1] = gg_sound_tiedlead; remove_task(TASK_PLAY_LEAD_SOUNDS+id); set_task(playDelay,"play_sound_by_cvar_task",TASK_PLAY_LEAD_SOUNDS+id,params,2); } // just me, I'm the winner! else { // did I just pass someone? if(level[id] > oldLevel && num_players_on_level(oldLevel)) { new params[2]; params[0] = id; params[1] = gg_sound_takenlead; remove_task(TASK_PLAY_LEAD_SOUNDS+id); set_task(playDelay,"play_sound_by_cvar_task",TASK_PLAY_LEAD_SOUNDS+id,params,2); } } } // WAS I on the leader level? else if(oldLevel == leaderLevel) { new params[2]; params[0] = id; params[1] = gg_sound_lostlead; remove_task(TASK_PLAY_LEAD_SOUNDS+id); set_task(playDelay,"play_sound_by_cvar_task",TASK_PLAY_LEAD_SOUNDS+id,params,2);
//return; // will not effect other players } // nothing of importance else return; // will not effect other players // // now monitor other players. // if we get this far, id is now in the lead level // new player; for(player=1;player<=maxPlayers;player++) { if(!is_user_connected(player) || player == id) continue; // PLAYER tied with ID if(level[player] == level[id]) { // don't tell him if he already got it from another player if(num_players_on_level(level[id]) <= 2 || (oldLevel > level[id] && leaderLevel == level[id])) // dropped into tied position { new params[2]; params[0] = player; params[1] = gg_sound_tiedlead; remove_task(TASK_PLAY_LEAD_SOUNDS+player); set_task(0.1,"play_sound_by_cvar_task",TASK_PLAY_LEAD_SOUNDS+player,params,2); }
continue; } // PLAYER passed by ID else if(level[id] > level[player] && level[player] == oldLevel) { // don't tell him if he already got it from another player if(num_players_on_level(level[id]) <= 1) { new params[2]; params[0] = player; params[1] = gg_sound_lostlead; remove_task(TASK_PLAY_LEAD_SOUNDS+player); set_task(0.1,"play_sound_by_cvar_task",TASK_PLAY_LEAD_SOUNDS+player,params,2); }
continue; } // ID passed by PLAYER else if(level[player] > level[id] && leaderLevel == level[player]) { // I stand alone! if(num_players_on_level(level[player]) <= 1) { new params[2]; params[0] = player; params[1] = gg_sound_takenlead; remove_task(TASK_PLAY_LEAD_SOUNDS+player); set_task(0.1,"play_sound_by_cvar_task",TASK_PLAY_LEAD_SOUNDS+player,params,2); }
continue; } } }
// manage game_player_equip and player_weaponstrip entities public manage_equips() { static classname[20], targetname[24]; new ent, i, block_equips = get_pcvar_num(gg_block_equips), enabled = ggActive;
// go through both entities to monitor for(i=0;i<4;i++) { // get classname for current iteration switch(i) { case 0: classname = "game_player_equip"; case 1: classname = "game_player_equip2"; case 2: classname = "player_weaponstrip"; default: classname = "player_weaponstrip2"; }
// go through whatever entity ent = 0; while((ent = fm_find_ent_by_class(ent,classname))) { // allowed to have this, reverse possible changes if(!enabled || !block_equips || (i >= 2 && block_equips < 2)) // player_weaponstrip switch { pev(ent,pev_targetname,targetname,23);
// this one was blocked if(equal(targetname,"gg_block_equips")) { pev(ent,TNAME_SAVE,targetname,23);
set_pev(ent,pev_targetname,targetname); set_pev(ent,TNAME_SAVE,""); switch(i) { case 0, 1: set_pev(ent,pev_classname,"game_player_equip"); default: set_pev(ent,pev_classname,"player_weaponstrip"); } } }
// not allowed to pickup others, make possible changes else { pev(ent,pev_targetname,targetname,23);
// needs to be blocked, but hasn't been yet if(targetname[0] && !equal(targetname,"gg_block_equips")) { set_pev(ent,TNAME_SAVE,targetname); set_pev(ent,pev_targetname,"gg_block_equips"); // classname change is required sometimes for some reason switch(i) { case 0, 1: set_pev(ent,pev_classname,"game_player_equip2"); default: set_pev(ent,pev_classname,"player_weaponstrip2"); } } } } } }
// someone respawned spawned(id) { // should be filtered in ham hook if(/*!ggActive || !is_user_connected(id) ||*/ !on_valid_team(id)) return; remove_task(TASK_CHECK_DEATHMATCH+id);
// should be frozen? if(won) { new iterations = get_pcvar_num(gg_map_iterations); if(mapIteration < iterations || !iterations) { // not done yet, just freeze players set_pev(id,pev_flags,pev(id,pev_flags) | FL_FROZEN); fm_set_user_godmode(id,1); }
// done, make sure HUD is hidden emessage_begin(MSG_ALL,gmsgHideWeapon); ewrite_byte((1<<0)|(1<<1)|(1<<3)|(1<<4)|(1<<5)|(1<<6)); // can't use (1<<2) or text disappears emessage_end(); emessage_begin(MSG_ALL,gmsgCrosshair); ewrite_byte(0); // hide emessage_end(); return; } if(get_pcvar_num(gg_pickup_others)) strip_starting_pistols(id);
afkCheck[id] = 0; levelsThisRound[id] = 0;
// just joined if(!level[id]) { new teamplay = get_pcvar_num(gg_teamplay);
// warming up if(warmup > 0 && !teamplay) { change_level(id,1,1,_,1); // just joined, always score } else { // handicap new handicapMode = get_pcvar_num(gg_handicap_on); if(handicapMode && !teamplay) { new rcvHandicap = 1;
// top10 doesn't receive handicap -- also make sure we are using top10 if(sqlInit && !get_pcvar_num(gg_top10_handicap) && get_pcvar_num(gg_stats_mode)) { static authid[32]; get_gg_authid(id,authid,31); new si = get_gg_si(); #if defined SQL if(!statsPosition[id][si]) statsPosition[id][si] = stats_get_position(id,authid,si); if(0 < statsPosition[id][si] <= TOP_PLAYERS) rcvHandicap = 0; // I'm in the top10 #else for(new i=0;i<TOP_PLAYERS;i++) { if(i >= statsSize[si]) continue; ArrayGetArray(statsArray,ArrayGetCell(statsPointers[si],i),sfStatsStruct);
// I'm in top10, don't give me handicap if(equal(authid,sfStatsStruct[sdAuthid])) { rcvHandicap = 0; break; } } #endif }
if(rcvHandicap) { new player;
// find lowest level (don't use bots unless we have to) if(handicapMode == 2) { new isBot, myLevel, lowestLevel, lowestBotLevel; for(player=1;player<=maxPlayers;player++) { if(!is_user_connected(player) || player == id) continue;
isBot = is_user_bot(player); myLevel = level[player];
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,_,1); // just joined, always score }
// find average level else { new Float:average, num; for(player=1;player<=maxPlayers;player++) { if(is_user_connected(player) && level[player]) { average += float(level[player]); num++; } }
average /= float(num); change_level(id,(average >= 0.5) ? floatround(average) : 1,1,_,1); // just joined, always score } }
// not eligible for handicap (in top10 with gg_top10_handicap disabled) else change_level(id,1,1,_,1); // just joined, always score }
// no handicap enabled or playing teamplay else { if(teamplay) { new team = _:cs_get_user_team(id); if(team == 1 || team == 2) { // my team has a level already if(teamLevel[team]) { change_level(id,teamLevel[team],1,_,1,_,0); // just joined, always score, don't effect team if(score[id] != teamScore[team]) change_score(id,teamScore[team]-score[id],_,_,0); // don't effect team } // my team just started else { // initialize its values teamplay_update_level(team,1,id); teamplay_update_score(team,0,id);
change_level(id,teamLevel[team],1,_,1,_,0); // just joined, always score, don't effect team } } } // solo-play else change_level(id,1,1,_,1); // just joined, always score } } }
// didn't just join else { if(star[id]) { end_star(TASK_END_STAR+id); remove_task(TASK_END_STAR+id); } if(get_pcvar_num(gg_teamplay)) { new team = _:cs_get_user_team(id); // my team just started if((team == 1 || team == 2) && !teamLevel[team]) { // initialize its values teamplay_update_level(team,1,id); teamplay_update_score(team,0,id);
change_level(id,teamLevel[team]-level[id],_,_,1,_,0); // always score, don't effect team change_score(id,teamScore[team]-score[id],_,_,0); // don't effect team } }
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(); } }
if(get_pcvar_num(gg_disable_money)) hide_money(id); // switch to our appropiate weapon, for those without the switch to new weapon option if((warmup > 0 && warmupWeapon[0] && equal(warmupWeapon,KNIFE)) || equal(lvlWeapon[id],KNIFE) /* || (get_pcvar_num(gg_knife_elite) && levelsThisRound[id] > 0)*/) { engclient_cmd(id,WEAPON_KNIFE); client_cmd(id,WEAPON_KNIFE); } else if(get_pcvar_num(gg_nade_glock) && equal(lvlWeapon[id],HEGRENADE)) { engclient_cmd(id,WEAPON_GLOCK18); client_cmd(id,WEAPON_GLOCK18); } else if(lvlWeapon[id][0]) { static wpnName[24]; formatex(wpnName,23,"weapon_%s",lvlWeapon[id]);
engclient_cmd(id,wpnName); client_cmd(id,wpnName); } // remember spawn info for AFK protection if(get_pcvar_num(gg_afk_protection)) { pev(id,pev_origin,spawnOrigin[id]); pev(id,pev_v_angle,spawnAngles[id]); afkCheck[id] = 1; } }
// player changed his team player_teamchange(id,oldTeam,newTeam) { if(!ggActive) return 0; // remember for crazy team switches lastTeam[id] = newTeam; // allow us to join in on deathmatch if(oldTeam == 0 && (newTeam == 1 || newTeam == 2) && !roundEnded && get_pcvar_num(gg_dm) && !task_exists(TASK_CHECK_JOINCLASS+id)) { remove_task(TASK_CHECK_DEATHMATCH+id); set_task(5.0,"check_deathmatch",TASK_CHECK_DEATHMATCH+id); } // keep track of time new Float:now = get_gametime(); if(oldTeam == 1 || oldTeam == 2) teamTimes[id][oldTeam-1] += now - lastSwitch[id]; lastSwitch[id] = now; // we already have a level, set our values to our new team's if(level[id] && get_pcvar_num(gg_teamplay) && (newTeam == 1 || newTeam == 2)) { // set them directly level[id] = teamLevel[newTeam]; lvlWeapon[id] = teamLvlWeapon[newTeam]; score[id] = teamScore[newTeam]; } return 1; }
// restart the round public restart_round(delay) { // clear values /*new player; for(player=1;player<=maxPlayers;player++) { if(is_user_connected(player)) clear_values(player,1); // ignore welcome }
// reset teams as well clear_team_values(1); clear_team_values(2);*/ if(delay < 1) delay = 1;
set_cvar_num("sv_restartround",delay); set_task(float(delay)-0.1,"clear_all_values"); }
// select a random weapon order // // in cmd_gungame_teamplay we call map_start_cvars which leads to d_rOrder. // when called this way we don't want to let it change teamplay or run teamplay // configs, so we added the keepTeamplay parameter. do_rOrder(keepTeamplay) { // manage random teamplay if(initTeamplayInt == -1) { get_pcvar_string(gg_teamplay,initTeamplayStr,31); initTeamplayInt = str_to_num(initTeamplayStr[0]); } new amount; // if we are allowed to change teamplay, and our initial teamplay value was either a // sequence, or it was just 2 (so select one randomly), then sort through it and pick a value if(!keepTeamplay && ((amount = str_count(initTeamplayStr,',')+1) > 1 || initTeamplayInt == 2)) { new info[6], rotation[32]; get_localinfo("gg_tp_iter",info,5); copy(rotation,31,initTeamplayStr); // store initTeamplayStr in a variable that we can break apart, so on map end we can set gg_teamplay back to initTeamplayStr
new iter = str_to_num(info), teamplay; if(iter <= 0 || iter > amount) { iter = 1; set_localinfo("gg_tp_iter","1"); } // no rotation, just use the given value if(amount <= 1) { if(iter != 1) set_localinfo("gg_tp_iter","1"); // initTeamplayInt should still be set to the one we want to use } else { for(new i=1;i<=amount;i++) { if(contain(rotation,",") != -1) { strtok(rotation,info,5,rotation,31,','); if(i == iter) // this is the one we're looking for { initTeamplayInt = str_to_num(info); break; } } else // we've stripped away everything else and are left with the last one, so use it { initTeamplayInt = str_to_num(rotation); break; } } iter++; if(iter > amount) iter = 1; num_to_str(iter,info,5); set_localinfo("gg_tp_iter",info); } if(initTeamplayInt == 2) teamplay = random_num(0,1); else teamplay = initTeamplayInt;
set_pcvar_num(gg_teamplay,teamplay); // re-run config files based on teamplay, don't allow toggling exec_gg_config_file(0,0); if(teamplay) exec_gg_config_file(1,0); }
new i, maxRandom, cvar[20], weaponOrder[(MAX_WEAPONS*16)+1]; 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,MAX_WEAPONS*16); trim(weaponOrder);
// found a blank one, stop here if(!weaponOrder[0]) { maxRandom = i - 1; break; } } // there is just one if(maxRandom == 1) { // get its weapon order and set as current formatex(cvar,19,"gg_weapon_order1"); get_cvar_string(cvar,weaponOrder,MAX_WEAPONS*16); set_pcvar_string(gg_weapon_order,weaponOrder); return; }
// 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,MAX_WEAPONS*16);
// set as current set_pcvar_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); } }
// play a random win sound do_rWinSound() { // just one, no one cares if(numWinSounds <= 1) { return 0; // 1 minus 1 }
new randomOrder[30], lastWSIstr[6], lastWSI, orderAmt; get_localinfo("gg_winsound_order",randomOrder,29); get_localinfo("gg_last_wsi",lastWSIstr,5); lastWSI = str_to_num(lastWSIstr); orderAmt = get_rWinSound_amount(randomOrder);
// no random order yet, or amount of random orders changed if(!randomOrder[0] || orderAmt != numWinSounds) { shuffle_rWinSound(randomOrder,29); lastWSI = 0; }
// reached the end, reshuffle while avoiding this one else if(get_rWinSound_index_val(orderAmt,randomOrder) == get_rWinSound_index_val(lastWSI,randomOrder)) { shuffle_rWinSound(randomOrder,29,lastWSI); lastWSI = 0; }
new choice = get_rWinSound_index_val(lastWSI+1,randomOrder);
// remember for next time num_to_str(lastWSI+1,lastWSIstr,5); set_localinfo("gg_last_wsi",lastWSIstr); return choice-1; }
// get the value of an order index in an order string get_rWinSound_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_rWinSound_amount(randomOrder[]) { return str_count(randomOrder,',')+1; }
// shuffle up our random order stock shuffle_rWinSound(randomOrder[],len,avoid=-1) { randomOrder[0] = 0;
// fill up array with order indexes new order[MAX_WINSOUNDS], i; for(i=0;i<numWinSounds;i++) order[i] = i+1;
// shuffle it SortCustom1D(order,numWinSounds,"sort_shuffle");
// avoid a specific number as the starting number while(avoid > 0 && order[0] == avoid) SortCustom1D(order,numWinSounds,"sort_shuffle");
// get them into a string for(i=0;i<numWinSounds;i++) { format(randomOrder,len,"%s%s%i",randomOrder,(i>0) ? "," : "",order[i]); set_localinfo("gg_winsound_order",randomOrder); } }
// shuffle an array public sort_shuffle(elem1,elem2) { return random_num(-1,1); }
// clear all saved values clear_values(id,ignoreWelcome=0) { level[id] = 0; levelsThisRound[id] = 0; score[id] = 0; lvlWeapon[id][0] = 0; star[id] = 0; if(!ignoreWelcome) welcomed[id] = 0; page[id] = 0; lastKilled[id] = 0; respawn_timeleft[id] = 0; silenced[id] = 0; spawnSounds[id] = 1; spawnProtected[id] = 0; teamTimes[id][0] = 0.0; teamTimes[id][1] = 0.0; lastSwitch[id] = get_gametime(); lastTeam[id] = 0;
if(c4planter == id) c4planter = 0; remove_task(TASK_RESPAWN+id); remove_task(TASK_CHECK_DEATHMATCH+id); remove_task(TASK_REMOVE_PROTECTION+id); if(is_user_connected(id)) fm_set_rendering(id);
return 1; }
// clears a TEAM's values clear_team_values(team) { if(team != 1 && team != 2) return;
teamLevel[team] = 0; teamLvlWeapon[team][0] = 0; teamScore[team] = 0; }
// possibly start a warmup round start_warmup() { new warmup_value = get_pcvar_num(gg_warmup_timer_setting); // warmup is set to -13 after its finished if gg_warmup_multi is 0, // so this stops multiple warmups for multiple map iterations if(warmup_value > 0 && warmup != -13) { warmup = warmup_value; get_pcvar_string(gg_warmup_weapon,warmupWeapon,23); set_task(0.1,"warmup_check",TASK_WARMUP_CHECK); // now that warmup is in effect, reset player weapons new player; for(player=1;player<=maxPlayers;player++) { if(is_user_connected(player)) { // just joined for all intents and purposes change_level(player,-MAX_WEAPONS,1,_,1,0,0); // just joined, always score, don't play sounds, don't effect team } } // a single team update instead of for everyone if(get_pcvar_num(gg_teamplay)) { teamplay_update_score(1,0); teamplay_update_score(2,0); teamplay_update_level(1,1); teamplay_update_level(2,1); } // clear leader display for warmup if(warmup > 0) ClearSyncHud(0,hudSyncLDisplay); } }
// 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) || !ggActive) return;
// on the grenade level, and lacking that aforementioned thing if(equal(lvlWeapon[id],HEGRENADE) && !user_has_weapon(id,CSW_HEGRENADE)) ham_give_weapon(id,WEAPON_HEGRENADE); // get bots to use the grenade (doesn't work very well) if(is_user_bot(id)) { engclient_cmd(id,WEAPON_HEGRENADE); client_cmd(id,WEAPON_HEGRENADE); } }
// refill a player's ammo stock refill_ammo(id,current=0) { if(!is_user_alive(id)) return 0;
// weapon-specific warmup, no ammo for knives only if(warmup > 0 && warmupWeapon[0] && equal(warmupWeapon,KNIFE)) return 0;
// get weapon name and index static fullName[24], curWpnName[24]; new wpnid, curWpnMelee, curweapon = get_user_weapon(id);
// re-init start of strings fullName[0] = 0; curWpnName[0] = 0;
// we have a valid current weapon (stupid runtime errors) if(curweapon) { get_weaponname(curweapon,curWpnName,23); curWpnMelee = equal(curWpnName,WEAPON_KNIFE); }
// if we are refilling our current weapon instead of our level weapon, // we actually have a current weapon, and this isn't a melee weapon or the // other alternative, our level weapon, is a melee weapon if(current && curweapon && (!curWpnMelee || equal(lvlWeapon[id],KNIFE))) { // refill our current weapon get_weaponname(curweapon,fullName,23); wpnid = curweapon; } else { // refill our level weapon formatex(fullName,23,"weapon_%s",lvlWeapon[id]); wpnid = get_weaponid(fullName); // so that we know for sure current = 0; } 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);
// didn't find anything valid to refill somehow if(wpnid < 1 || wpnid > 30 || !fullName[0]) return 0; // no reason to refill a melee weapon, or a bomb. // make use of our curWpnMelee cache here if((current && curWpnMelee) || wpnid == CSW_KNIFE || wpnid == CSW_C4) return 1;
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]); // glock on the nade level if(wpnid == CSW_GLOCK18 && equal(lvlWeapon[id],HEGRENADE)) cs_set_user_bpammo(id,CSW_GLOCK18,50); else { // set backpack ammo 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 { // we don't have this nade yet if(!user_has_weapon(id,wpnid)) { ham_give_weapon(id,fullName); remove_task(TASK_REFRESH_NADE+id); } if(get_pcvar_num(gg_nade_glock)) { // set clip ammo new wEnt = get_weapon_ent(id,CSW_GLOCK18); if(pev_valid(wEnt)) cs_set_weapon_ammo(wEnt,20);
// set backpack ammo cs_set_user_bpammo(id,CSW_GLOCK18,50); new curweapon = get_user_weapon(id);
// 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(20); message_end(); } }
if(get_pcvar_num(gg_nade_smoke) && !cs_get_user_bpammo(id,CSW_SMOKEGRENADE)) ham_give_weapon(id,"weapon_smokegrenade");
if(get_pcvar_num(gg_nade_flash) && !cs_get_user_bpammo(id,CSW_FLASHBANG)) ham_give_weapon(id,"weapon_flashbang"); } // keep melee weapon out if we had it out if(curweapon && curWpnMelee) { engclient_cmd(id,curWpnName); client_cmd(id,curWpnName); }
return 1; }
// 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);
new 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_knife_elite)) { len += formatex(menuText[len],511-len,"%L^n",id,"WELCOME_MESSAGE_LINE4"); special = 1; } if(get_pcvar_num(gg_dm) || get_cvar_num("csdm_active")) { len += formatex(menuText[len],511-len,"%L^n",id,"WELCOME_MESSAGE_LINE5"); special = 1; } if(get_pcvar_num(gg_teamplay)) { len += formatex(menuText[len],511-len,"%L^n",id,"WELCOME_MESSAGE_LINE6"); special = 1; }
if(special) len += formatex(menuText[len],511-len,"\d---------------\w^n"); len += formatex(menuText[len],511-len,"%L^n",id,"WELCOME_MESSAGE_LINE7",weaponNum); len += formatex(menuText[len],511-len,"\d---------------\w^n"); len += formatex(menuText[len],511-len,"%L",id,"WELCOME_MESSAGE_LINE8"); 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 stock show_required_kills(id,always_individual=0) { // weapon-specific warmup, who cares if(warmup > 0 && warmupWeapon[0]) return 0;
if(always_individual || !get_pcvar_num(gg_teamplay)) return gungame_hudmessage(id,3.0,"%L: %i / %i",id,"REQUIRED_KILLS",score[id],get_level_goal(level[id],id)); new player, myTeam = _:cs_get_user_team(id), goal = get_level_goal(teamLevel[myTeam],id); for(player=1;player<=maxPlayers;player++) { if(player == id || (is_user_connected(player) && _:cs_get_user_team(player) == myTeam)) gungame_hudmessage(player,3.0,"%L: %i / %i",player,"REQUIRED_KILLS",teamScore[myTeam],goal); } return 1; }
// player killed himself player_suicided(id) { static name[32];
// we still have protection (round ended, new one hasn't started yet) // or, suicide level downs are disabled if(roundEnded || !get_pcvar_num(gg_suicide_penalty)) return 0; // weapon-specific warmup, no one cares if(warmup > 0 && warmupWeapon[0]) return 0; if(!get_pcvar_num(gg_teamplay)) { get_user_name(id,name,31);
gungame_print(0,id,1,"%L",LANG_PLAYER_C,"SUICIDE_LEVEL_DOWN",name); // this is going to start a respawn counter HUD message if(get_pcvar_num(gg_dm) && (get_pcvar_num(gg_dm_countdown) & 2)) return change_level(id,-1,_,0,1); // don't show message, always score
// show with message return change_level(id,-1,_,_,1); // always score } else { new team = _:cs_get_user_team(id); if(team != 1 && team != 2) return 0; new penalty = get_level_goal(teamLevel[team],0); if(penalty > 0) { get_user_team(id,name,9);
if(teamScore[team] - penalty < 0) gungame_print(0,id,1,"%L",LANG_PLAYER_C,"SUICIDE_LEVEL_DOWN_TEAM",name,(teamLevel[team] > 1) ? teamLevel[team]-1 : teamLevel[team]); else gungame_print(0,id,1,"%L",LANG_PLAYER_C,"SUICIDE_SCORE_DOWN_TEAM",name,penalty);
return change_score(id,-penalty); } } return 0; }
// player scored or lost a point stock change_score(id,value,refill=1,play_sounds=1,effect_team=1,always_score=0) { // don't bother scoring up on weapon-specific warmup if(warmup > 0 && warmupWeapon[0] && value > 0) return 0;
// can't score! if(!always_score && !can_score(id)) return 0; // already won, isn't important if(level[id] > weaponNum) return 0;
new oldScore = score[id], goal = get_level_goal(level[id],id); new teamplay = get_pcvar_num(gg_teamplay), team; if(teamplay) team = _:cs_get_user_team(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(!teamplay && !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;
if(teamplay && effect_team && (team == 1 || team == 2) && teamScore[team] != score[id]) teamplay_update_score(team,score[id],id,1); // direct
change_level(id,1,_,_,always_score,play_sounds); return 1; }
// check for level down if(score[id] < 0) { if(value < 0) show_required_kills(id);
// can't go down below level 1 if(level[id] <= 1) { score[id] = 0;
if(teamplay && effect_team && (team == 1 || team == 2) && teamScore[team] != score[id]) teamplay_update_score(team,score[id],id,1); // direct new sdisplay = get_pcvar_num(gg_status_display); if(sdisplay == STATUS_KILLSLEFT || sdisplay == STATUS_KILLSDONE) status_display(id);
return 0; } else { goal = get_level_goal(level[id] > 1 ? level[id]-1 : 1,id);
score[id] = (oldScore + value) + goal; // carry over points if(score[id] < 0) score[id] = 0; if(teamplay && effect_team && (team == 1 || team == 2) && teamScore[team] != score[id]) teamplay_update_score(team,score[id],id,1); // direct
change_level(id,-1,_,_,always_score); return -1; } }
// refresh menus new menu; get_user_menu(id,menu,dummy[0]); if(menu == level_menu) show_level_menu(id);
if(refill && get_pcvar_num(gg_refill_on_kill)) refill_ammo(id); if(teamplay && effect_team && (team == 1 || team == 2) && teamScore[team] != score[id]) teamplay_update_score(team,score[id],id,1); // direct
if(value < 0) show_required_kills(id); else if(play_sounds) client_cmd(id,"spk ^"%s^"",KILL_DING_SOUND); new sdisplay = get_pcvar_num(gg_status_display); if(sdisplay == STATUS_KILLSLEFT || sdisplay == STATUS_KILLSDONE) status_display(id);
return 0; }
// player gained or lost a level stock change_level(id,value,just_joined=0,show_message=1,always_score=0,play_sounds=1,effect_te am=1) { // can't score if(level[id] > 0 && !always_score && !can_score(id)) return 0;
// don't bother leveling up on weapon-specific warmup if(level[id] > 0 && warmup > 0 && warmupWeapon[0] && value > 0) return 0; new oldLevel = level[id], oldValue = value; new teamplay = get_pcvar_num(gg_teamplay), team; if(teamplay) team = _:cs_get_user_team(id); // teamplay, on a valid team if(teamplay && (team == 1 || team == 2) && value != -MAX_WEAPONS) // ignore warmup reset { // not effecting team, but setting me to something that doesn't match team // OR // effecting team, and not even starting on same thing as team if((!effect_team && level[id] + value != teamLevel[team]) || (effect_team && level[id] != teamLevel[team])) { log_amx("MISSYNCH -- id: %i, value: %i, just_joined: %i, show_message: %i, always_score: %i, play_sounds: %i, effect_team: %i, team: %i, level: %i, teamlevel: %i, usertime: %i, score: %i, teamscore: %i, lvlweapon: %s, teamlvlweapon: %s", id,value,just_joined,show_message,always_score,play_sounds,effect_team,team ,level[id],teamLevel[team],get_user_time(id,1),score[id],teamScore[team],lvlWeapon[id],teamLvlWeapon[team]); log_message("MISSYNCH -- id: %i, value: %i, just_joined: %i, show_message: %i, always_score: %i, play_sounds: %i, effect_team: %i, team: %i, level: %i, teamlevel: %i, usertime: %i, score: %i, teamscore: %i, lvlweapon: %s, teamlvlweapon: %s", id,value,just_joined,show_message,always_score,play_sounds,effect_team,team ,level[id],teamLevel[team],get_user_time(id,1),score[id],teamScore[team],lvlWeapon[id],teamLvlWeapon[team]); } }
// this will put us below level 1 if(level[id] + value < 1) { value = 1 - level[id]; // go down only to level 1 // bottom out the score score[id] = 0; if(teamplay && effect_team && (team == 1 || team == 2) && teamScore[team] != score[id]) teamplay_update_score(team,score[id],id,1); // direct }
// going up if(value > 0) { new max_lvl = get_pcvar_num(gg_max_lvl);
// already reached max levels for this round if(!teamplay && !get_pcvar_num(gg_turbo) && max_lvl > 0 && levelsThisRound[id] >= max_lvl) return 0; } // can't win on the warmup round if(level[id] + value > weaponNum && warmup > 0) { score[id] = get_level_goal(level[id],id) - 1; if(teamplay && effect_team && (team == 1 || team == 2) && teamScore[team] != score[id]) teamplay_update_score(team,score[id],id,1); // direct return 0; }
level[id] += value; if(!just_joined) levelsThisRound[id] += value;
silenced[id] = 0; // for going to Glock->USP, for example
// win??? if(level[id] > weaponNum) { // already won, ignore this if(won) return 1; // 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,_,1); // always score return 1; }
// cap out score score[id] = get_level_goal(level[id],id); if(teamplay && effect_team && (team == 1 || team == 2) && teamScore[team] != score[id]) teamplay_update_score(team,score[id],id,1); // direct if(teamplay && effect_team && (team == 1 || team == 2) && teamLevel[team] != level[id]) teamplay_update_level(team,level[id],id,1); // direct
// crown the winner win(id,lastKilled[id]);
return 1; } // set weapon based on it get_level_weapon(level[id],lvlWeapon[id],23); // update the 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 new nade = equal(lvlWeapon[id],HEGRENADE); // I'm a leader! if(warmup <= 0 && level[get_leader()] == level[id]) { new sound_cvar; if(nade) sound_cvar = gg_sound_nade; else if(equal(lvlWeapon[id],KNIFE)) sound_cvar = gg_sound_knife; if(sound_cvar) { // only play sound if we reached this level first if(num_players_on_level(level[id]) == 1) play_sound_by_cvar(0,sound_cvar); } } // NOW play level up sounds, so that they potentially // override the global "Player is on X level" sounds
if(play_sounds) { // level up! if(oldValue >= 0) play_sound_by_cvar(id,gg_sound_levelup);
// level down :( else play_sound_by_cvar(id,gg_sound_leveldown); }
// remember to modify changes new oldTeamLevel; if(team == 1 || team == 2) oldTeamLevel = teamLevel[team];
if(teamplay && effect_team && (team == 1 || team == 2) && teamLevel[team] != level[id]) teamplay_update_level(team,level[id],id);
// refresh menus new player, menu; for(player=1;player<=maxPlayers;player++) { if(!is_user_connected(player)) continue; get_user_menu(player,menu,dummy[0]);
if(menu == scores_menu) show_scores_menu(player); else if(menu == level_menu) show_level_menu(player); else if(player == id && menu == weapons_menu) show_weapons_menu(player); }
// make sure we don't have more than required now new goal = get_level_goal(level[id],id); if(score[id] >= goal) { score[id] = goal-1; // 1 under if(teamplay && effect_team && (team == 1 || team == 2) && teamScore[team] != score[id]) teamplay_update_score(team,score[id],id,1); // direct } new turbo = get_pcvar_num(gg_turbo);
// give weapon right away? if((turbo || just_joined) && is_user_alive(id)) give_level_weapon(id); else show_progress_display(id); // still show display anyway // update the leader display (cvar check done in that function) if(!just_joined) { remove_task(TASK_LEADER_DISPLAY); show_leader_display(); new Float:lead_sounds = get_pcvar_float(gg_lead_sounds); if(lead_sounds > 0.0 && (!teamplay || effect_team)) play_lead_sounds(id,oldLevel,lead_sounds); }
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] >= weaponNum - (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(); } }
// grab my name static name[32]; if(!teamplay) get_user_name(id,name,31);
// only calculate position if we didn't just join if(!just_joined && show_message) { if(teamplay) { // is the first call for this level change if((team == 1 || team == 2) && teamLevel[team] != oldTeamLevel) { new leaderLevel, numLeaders, leader = teamplay_get_lead_team(leaderLevel,numLeaders); // tied if(numLeaders > 1) gungame_print(0,id,1,"%L",LANG_PLAYER_C,"TIED_LEADER_TEAM",leaderLevel,teamLvlWeapon[team]); // leading else if(leader == team) { get_user_team(id,name,9); gungame_print(0,id,1,"%L",LANG_PLAYER_C,"LEADING_ON_LEVEL_TEAM",name,leaderLevel,teamLvlWeapon[team]); } // trailing else { get_user_team(id,name,9); gungame_print(0,id,1,"%L",LANG_PLAYER_C,"TRAILING_ON_LEVEL_TEAM",name,teamLevel[team],teamLvlWeapon[team]); } } } else { new leaderLevel, numLeaders, leader = get_leader(leaderLevel,numLeaders); // tied if(level[id] == leaderLevel && numLeaders > 1 && level[id] > 1) { if(numLeaders == 2) { new otherLeader; if(leader != id) otherLeader = leader; else { new player; for(player=1;player<=maxPlayers;player++) { if(is_user_connected(player) && level[player] == leaderLevel && player != id) { otherLeader = player; break; } } } static otherName[32]; get_user_name(otherLeader,otherName,31); gungame_print(0,id,1,"%L",LANG_PLAYER_C,"TIED_LEADER_ONE",name,leaderLevel,lvlWeapon[id],otherName); } else { static numWord[16], digiWord[3], lang[3]; num_to_word(numLeaders-1,numWord,15); trim(numWord); formatex(digiWord,2,"%i",numLeaders-1); new player; for(player=1;player<=maxPlayers;player++) { if(is_user_connected(player)) { // use word for english, digit otherwise get_user_info(player,"lang",lang,2); gungame_print(player,id,1,"%L",player,"TIED_LEADER_MULTI",name,leaderLevel,lvlWeapon[id],equali(lang,"en") ? numWord : digiWord); } } } }
// I'M THE BEST!!!!!!! else if(leader == id && level[id] > 1) { gungame_print(0,id,1,"%L",LANG_PLAYER_C,"LEADING_ON_LEVEL",name,level[id],lvlWeapon[id]); } } } // teamplay, didn't grab name yet if(teamplay) get_user_name(id,name,31); // triple bonus! if(levelsThisRound[id] == 3) { new triple_on = get_pcvar_num(gg_triple_on);
if(triple_on == 2 || (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]) engfunc(EngFunc_EmitSound,id,CHAN_VOICE,sound[6],VOL_NORM,ATTN_NORM,0,PITCH_NORM); // ignore sound/ prefix else engfunc(EngFunc_EmitSound,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,1,"%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_pcvar_num(mp_friendlyfire);
// turn on FF? if(ff_auto && !ff && nade) { server_cmd("mp_friendlyfire 1"); // so console is notified set_pcvar_num(mp_friendlyfire,1); // so it changes instantly
gungame_print(0,0,1,"%L",LANG_PLAYER_C,"FRIENDLYFIRE_ON");
client_cmd(0,"spk ^"%s^"",BRASS_BELL_SOUND); }
// turn off FF? else if(ff_auto && ff) { new keepFF, player;
for(player=1;player<=maxPlayers;player++) { if(equal(lvlWeapon[player],HEGRENADE) || equal(lvlWeapon[player],KNIFE)) { keepFF = 1; break; } }
// no one is on nade or knife level anymore if(!keepFF) { server_cmd("mp_friendlyfire 0"); // so console is notified set_pcvar_num(mp_friendlyfire,0); // so it changes instantly } }
// some bots are actually allergic to the chemicals used in HE grenades if(is_user_bot(id) && get_pcvar_num(gg_bots_skipnade) && !get_pcvar_num(gg_teamplay) && equal(lvlWeapon[id],HEGRENADE)) change_level(id,1);
return 1; }
// forces a player to a level, skipping a lot of important stuff. // it's assumed that this is used as a result of "id" being leveled // up because his teammate leveled up in teamplay. stock set_level_noifandsorbuts(id,newLevel,play_sounds=1) { // okay, this is our only but if(!is_user_connected(id)) return 0;
new oldLevel = level[id];
level[id] = newLevel; get_level_weapon(level[id],lvlWeapon[id],23);
if(play_sounds) { // level up! if(newLevel >= oldLevel) play_sound_by_cvar(id,gg_sound_levelup);
// level down :( else play_sound_by_cvar(id,gg_sound_leveldown); }
// refresh menus new player, menu; for(player=1;player<=maxPlayers;player++) { if(!is_user_connected(player)) continue; get_user_menu(player,menu,dummy[0]);
if(menu == scores_menu) show_scores_menu(player); else if(menu == level_menu) show_level_menu(player); }
// give weapon right away? if(get_pcvar_num(gg_turbo) && is_user_alive(id)) give_level_weapon(id); else show_progress_display(id); // still show display anyway
return 1; }
// 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,1,"Your star has run out!");
if(is_user_alive(id)) { fm_set_user_maxspeed(id,fm_get_user_maxspeed(id)/1.5); engfunc(EngFunc_EmitSound,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) || level[id] <= 0) return 0; // not warming up, didn't just win if(notify && warmup <= 0 && level[id] > 0 && level[id] <= weaponNum) show_progress_display(id); // stop attacks from bleeding over into the new weapon //client_cmd(id,"-attack;-attack2"); // 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);
new oldWeapon = get_user_weapon(id);
static wpnName[24]; new weapons = pev(id,pev_weapons), wpnid, alright, myCategory, hasMain;
new ammo = get_pcvar_num(gg_ammo_amount), knife_elite = get_pcvar_num(gg_knife_elite), pickup_others = (get_pcvar_num(gg_pickup_others) && (!knife_elite || !levelsThisRound[id])), mainCategory = get_weapon_category(_,lvlWeapon[id]);
new hasGlock, hasSmoke, hasFlash, nade_level = (equal(lvlWeapon[id],HEGRENADE)), nade_glock = get_pcvar_num(gg_nade_glock), nade_smoke = get_pcvar_num(gg_nade_smoke), nade_flash = get_pcvar_num(gg_nade_flash);
new melee_only = ((warmup > 0 && warmupWeapon[0] && equal(warmupWeapon,KNIFE)) || (knife_elite && levelsThisRound[id] > 0)); // remove stuff first for(wpnid=1;wpnid<31;wpnid++) { // don't have this, or it's the C4 if(!(weapons & (1<<wpnid)) || wpnid == CSW_C4) continue;
alright = 0; get_weaponname(wpnid,wpnName,23);
if(melee_only) { if(wpnid == CSW_KNIFE) { alright = 1; hasMain = 1; } } else { replace(wpnName,23,"weapon_","");
// this is our designated weapon if(equal(lvlWeapon[id],wpnName)) { alright = 1; hasMain = 1; } // nade extras else if(nade_level) { if(nade_glock && wpnid == CSW_GLOCK18) { alright = 1; hasGlock = 1; } else if(nade_smoke && wpnid == CSW_SMOKEGRENADE) { alright = 1; hasSmoke = 1; } else if(nade_flash && wpnid == CSW_FLASHBANG) { alright = 1; hasFlash = 1; } } // get the tag back on there format(wpnName,23,"weapon_%s",wpnName); } // don't do anything about the knife if(wpnid != CSW_KNIFE) { // was it alright? if(alright) { // reset ammo if(wpnid != CSW_HEGRENADE && wpnid != CSW_FLASHBANG && wpnid != CSW_SMOKEGRENADE) { if(nade_level && nade_glock && wpnid == CSW_GLOCK18) cs_set_user_bpammo(id,CSW_GLOCK18,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 } // we should probably remove this weapon else { myCategory = get_weapon_category(wpnid);
// pistol in the way of glock, remove it if(nade_level && nade_glock && myCategory == 2) ham_strip_weapon(id,wpnName); else { // we aren't allowed to have any other weapons, // or this is in the way of the weapon that I want. if(!pickup_others || myCategory == mainCategory) ham_strip_weapon(id,wpnName); } }/*not alright*/ }/*not a knife*/ }/*wpnid for-loop*/
// I should have a weapon but don't if(lvlWeapon[id][0] && !hasMain) { formatex(wpnName,23,"weapon_%s",lvlWeapon[id]);
// give a player his weapon ham_give_weapon(id,wpnName);
remove_task(TASK_REFRESH_NADE+id);
if(!equal(lvlWeapon[id],HEGRENADE) && !equal(lvlWeapon[id],KNIFE)) { wpnid = get_weaponid(wpnName);
if(!wpnid) log_amx("INVALID WEAPON ID FOR ^"%s^"",lvlWeapon[id]); else { if(ammo > 0) cs_set_user_bpammo(id,wpnid,ammo); else cs_set_user_bpammo(id,wpnid,maxAmmo[wpnid]); } } } if(nade_level) { if(nade_glock && !hasGlock) { ham_give_weapon(id,WEAPON_GLOCK18); cs_set_user_bpammo(id,CSW_GLOCK18,50); } if(nade_smoke && !hasSmoke) ham_give_weapon(id,"weapon_smokegrenade"); if(nade_flash && !hasFlash) ham_give_weapon(id,"weapon_flashbang"); }
new weapon = get_user_weapon(id); // using a knife probably if(melee_only || equal(lvlWeapon[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 knife engclient_cmd(id,WEAPON_KNIFE); client_cmd(id,WEAPON_KNIFE); }
// 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. else if(verify /*&& !notify*/ && oldWeapon) { get_weaponname(oldWeapon,wpnName,23); if(wpnName[0] && equal(wpnName,WEAPON_KNIFE)) { engclient_cmd(id,wpnName); client_cmd(id,wpnName); } else if(lvlWeapon[id][0]) { formatex(wpnName,23,"weapon_%s",lvlWeapon[id]); engclient_cmd(id,wpnName); client_cmd(id,wpnName); } } // switch to glock for nade level else if(weapon != CSW_KNIFE && equal(lvlWeapon[id],HEGRENADE) && nade_glock) { engclient_cmd(id,WEAPON_GLOCK18); client_cmd(id,WEAPON_GLOCK18); }
// otherwise, switch to our new weapon else if(lvlWeapon[id][0]) { formatex(wpnName,23,"weapon_%s",lvlWeapon[id]); engclient_cmd(id,wpnName); client_cmd(id,wpnName); }
// make sure that we get this... if(verify) { remove_task(TASK_VERIFY_WEAPON+id); set_task(1.0,"verify_weapon",TASK_VERIFY_WEAPON+id); } // remember burst or silenced status if(silenced[id]) { if(equal(lvlWeapon[id],"usp") || equal(lvlWeapon[id],"m4a1")) { new wEnt = get_weapon_ent(id,_,lvlWeapon[id]); if(pev_valid(wEnt)) { cs_set_weapon_silen(wEnt,1,0);
// play draw with silencer animation if(lvlWeapon[id][0] == 'u') set_pev(id,pev_weaponanim,USP_DRAWANIM); else set_pev(id,pev_weaponanim,M4A1_DRAWANIM); } } else if(equal(lvlWeapon[id],"glock18") || equal(lvlWeapon[id],"famas")) { new wEnt = get_weapon_ent(id,_,lvlWeapon[id]); if(pev_valid(wEnt)) cs_set_weapon_burst(wEnt,1); }
silenced[id] = 0; } return 1; }
// 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",lvlWeapon[id]); new wpnid = get_weaponid(wpnName);
if(!wpnid) return;
// we don't have it, but we want it if(!user_has_weapon(id,wpnid)) give_level_weapon(id,0,0); }
// crown a winner win(winner,loser) { // we have an invalid winner here if(won || !is_user_connected(winner) || !can_score(winner)) return;
won = 1; roundEnded = 1;
server_cmd("sv_alltalk 1"); client_cmd(0,"stopsound;speak null;mp3 stop"); play_sound(0,winSounds[currentWinSound]);
new map_iterations = get_pcvar_num(gg_map_iterations), restart, player, Float:chattime = get_cvar_float("mp_chattime");
// final playthrough, get ready for next map if(mapIteration >= map_iterations && map_iterations > 0) { set_nextmap(); set_task(floatmax(chattime,2.5),"goto_nextmap");
// as of GG1.16, we always send a non-emessage intermission, because // other map changing plugins (as well as StatsMe) intercepting it // was causing problems.
// as of GG1.20, we no longer do this because it closes the MOTD.
// as of GG2.10, we use finale, which freezes players like the // intermission but doesn't otherwise do any intermission stuff. message_begin(MSG_ALL,SVC_FINALE); write_string(""); // although you could put a nice typewrite-style centersay here message_end(); // godmode everyone new fullName[32]; for(player=1;player<=maxPlayers;player++) { if(!is_user_alive(player)) continue; // finale won't stop players from shooting technically formatex(fullName,31,"weapon_%s",lvlWeapon[player]); ham_strip_weapon(player,fullName);
fm_set_user_godmode(player,1); } }
// get ready to go again!! else { restart = 1;
// freeze and godmode everyone for(player=1;player<=maxPlayers;player++) { if(!is_user_connected(player)) continue; client_cmd(player,"-attack;-attack2"); set_pev(player,pev_flags,pev(player,pev_flags) | FL_FROZEN); fm_set_user_godmode(player,1); set_pev(player,pev_viewmodel2,""); } } emessage_begin(MSG_ALL,gmsgHideWeapon); ewrite_byte((1<<0)|(1<<1)|(1<<3)|(1<<4)|(1<<5)|(1<<6)); // can't use (1<<2) or text disappears emessage_end(); emessage_begin(MSG_ALL,gmsgCrosshair); ewrite_byte(0); // hide emessage_end(); new winnerName[32], i, teamplay = get_pcvar_num(gg_teamplay); if(teamplay) get_user_team(winner,winnerName,9); else get_user_name(winner,winnerName,31); // old-fashioned for(i=0;i<5;i++) { if(teamplay) gungame_print(0,winner,1,"%L!!",LANG_PLAYER_C,"WON_TEAM",winnerName); else gungame_print(0,winner,1,"%L!",LANG_PLAYER_C,"WON",winnerName); } // our new super function stats_award_points(winner); // finally show it off new winner_motd[64]; get_pcvar_string(gg_winner_motd,winner_motd,63); if(winner_motd[0] && winner_motd[0] != '0') { new params[66]; params[0] = winner; params[1] = loser; copy(params[2],63,winner_motd); set_task(1.0,"show_win_screen",_,params,65); } // we can restart now (do it after calculations because points might get reset) if(restart) { // delay it, because it will reset stuff set_task(1.1,"restart_round",floatround(chattime-1.1));
set_task(floatmax(chattime-0.1,1.2),"restart_gungame",czero ? get_cvar_num("bot_stop") : 0); set_task(floatmax(chattime+5.0,0.1),"stop_win_sound",currentWinSound); if(czero) server_cmd("bot_stop 1"); // freeze CZ bots } }
// restart gungame, for the next map iteration public restart_gungame(old_bot_stop_value) { won = 0; mapIteration++; /*new i; for(i=0;i<sizeof teamLevel;i++) clear_team_values(i);*/ // game already commenced, but we are restarting, allow us to warmup again if(gameCommenced) shouldWarmup = 1; stats_clear_all(); // clear out everything about our stats
toggle_gungame(TASK_TOGGLE_GUNGAME + TOGGLE_ENABLE); // reset stuff
// toggle_gungame calls map_start_cvars which calls do_rOrder, so we theoretically don't need to do it again here //do_rOrder(0); // also does random teamplay
setup_weapon_order(); currentWinSound = do_rWinSound(); // pick the next win sound
// unfreeze and ungodmode everyone for(new player=1;player<=maxPlayers;player++) { if(!is_user_connected(player)) continue; set_pev(player,pev_flags,pev(player,pev_flags) & ~FL_FROZEN); fm_set_user_godmode(player,0); welcomed[player] = 1; // also don't show welcome again } if(czero) server_cmd("bot_stop %i",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... :( warmupWeapon[0] = 0; }
// stop the winner sound (for multiple map iterations) public stop_win_sound(winSound) { // stop winning sound if(containi(winSounds[winSound],".mp3") != -1) client_cmd(0,"mp3 stop"); else client_cmd(0,"speak null"); }
// calculate the winner screen... severely cut down from before public show_win_screen(params[66]) // [winner,loser,gg_win_motd[64]] { new winner = params[0], loser = params[1]; if(!is_user_connected(winner)) return 0; new winner_motd[64]; copy(winner_motd,63,params[2]);
new motd[1536], len, header[32];
new teamplay = get_pcvar_num(gg_teamplay), stats_mode = get_pcvar_num(gg_stats_mode), stats_split = get_pcvar_num(gg_stats_split), timeratio = get_pcvar_num(gg_teamplay_timeratio), iterations = get_pcvar_num(gg_map_iterations), roundsleft = iterations - mapIteration, nextmap[32], loserDC = !is_user_connected(loser);
get_cvar_string("amx_nextmap",nextmap,31);
new winnerTeam[10], winnerName[32], winnerColor[8], winnerWinSuffix[3], winnerStreakSuffix[3], streakChampColor[8], myStreakSuffix[3], winningTeam = _:cs_get_user_team(winner), losingTeam = _:(!(winningTeam-1)) + 1;
#if defined SQL // web page if(!isdigit(winner_motd[0]) || winner_motd[0] == '2') { if(!sqlInit) return 0;
new systime = get_systime(), player, playerAuthid[32], playerName[32], playerSafeAuthid[64], playerSafeName[64], si = get_gg_si(), flags, team, origLen = len = formatex(motd,1535,"DELETE FROM `%s`; INSERT INTO `%s` VALUES ('0','','%s','%i','%i','','%i','%i','%i','%i','%i','%i','%i','%i','%i','%i','%s'),",sqlPlayersTable,sqlPlayersTable,nextmap,stats_mode,stats_split,teamplay,tim eratio,winner,loser,loserDC,winningTeam,losingTeam,iterations,roundsleft,systime, serverip);
for(player=1;player<=maxPlayers;player++) { if(!is_user_connected(player)) continue; if(len >= 1200) // getting too close for comfort, cash in what we have and start a new query { motd[len] = ';'; motd[len+1] = 0; // thread this to prevent weird connection errors??? only solution I could find SQL_ThreadQuery(tuple,"sql_qhandler_dummy",motd); len = origLen = formatex(motd,1535,"INSERT INTO `%s` VALUES ",sqlPlayersTable); } flags = 0; team = _:cs_get_user_team(player); if(team == winningTeam) { flags |= WON; if(player == winner) flags |= LASTKILL; } else if(team > 0 && team < 3) { flags |= LOST; if(player == loser) flags |= LASTKILL; } if(player == pointsExtraction[0][1]) flags |= NEWRECORD; get_gg_authid(player,playerAuthid[player],31); get_user_name(player,playerName[player],31); // get new stats position stats_clear_struct(playerStats[player]); stats_get_position(player,playerAuthid[player],si); SQL_QuoteString(db,playerSafeName[player],63,playerName[player]); SQL_QuoteString(db,playerSafeAuthid[player],63,playerAuthid[player]);
len += formatex(motd[len],1535-len,"%s('%i','%s','%s','%i','%i','%s','%i','%i','%i','%i','%i','%i','%i','%i','%i','%i','%s')",(len != origLen) ? "," : "", player,playerSafeAuthid[player],playerSafeName[player],team,level[player],lvlWeapon[player],flags,pointsExtraction[player][0],pointsExtraction[player][2],pointsExtraction[player][1],pointsExtraction[player][4],pointsExtraction[player][3],statsPosition[player][si],floatround(teamTimes[player][winningTeam-1]),floatround(teamTimes[player][losingTeam-1]),systime,serverip); } // if we actually added someone if(len > origLen) { motd[len] = ';'; motd[len+1] = 0;
query = SQL_PrepareQuery(db,motd); SQL_ExecuteAndLog(query); SQL_FreeHandle(query); } // an actual web page if(winner_motd[0] != '2') { new url[74], lang[3]; for(player=1;player<=maxPlayers;player++) { if(!is_user_connected(player)) continue;
get_user_info(player,"lang",lang,2);
formatex(header,31,"%L",player,"WIN_MOTD_LINE1",winnerName); formatex(url,73,"%s?i=%i&l=%s",winner_motd,player,lang);
show_motd(player,url,header); } }
return 1; } #endif
if(sqlInit && stats_mode && is_user_connected(pointsExtraction[0][1])) get_team_color(CsTeams:get_user_team(pointsExtraction[0][1]),streakChampColor,7);
get_user_team(winner,winnerTeam,9); get_user_name(winner,winnerName,31); get_team_color(CsTeams:winningTeam,winnerColor,7); get_number_suffix(pointsExtraction[winner][0],winnerWinSuffix,2); get_number_suffix(pointsExtraction[winner][3],winnerStreakSuffix,2); // pointsExtraction[player][0] = total wins // pointsExtraction[player][1] = points from this round // pointsExtraction[player][2] = total points // pointsExtraction[player][3] = current streak // pointsExtraction[player][4] = previous record streak // pointsExtraction[0][0] = old record (0 = no old record) // pointsExtraction[0][1] = record holder (-1 = old guy) // pointsExtraction[0][2] = new record (0 = no new record) new loserName[32], loserColor[8]; if(!loserDC) { get_user_name(loser,loserName,31); get_team_color(cs_get_user_team(loser),loserColor,7); } else loserColor = "gray";
// figure out which lines to use based on stats split stuff new key_LINE5A[20], key_LINE5B[20], key_LINE5C[20], key_LINE7A[20], key_LINE7B[20], key_LINE7C[20], key_STREAK1[21], key_STREAK2[21], key_STREAK3[21], key_STREAK4[21];
if(stats_split) { if(teamplay) { key_LINE5A = "WIN_MOTD_LINE5A_TP"; key_LINE5B = "WIN_MOTD_LINE5B_TP"; key_LINE5C = "WIN_MOTD_LINE5C_TP"; key_LINE7A = "WIN_MOTD_LINE7A_TP"; key_LINE7B = "WIN_MOTD_LINE7B_TP"; key_LINE7C = "WIN_MOTD_LINE7C_TP"; key_STREAK1 = "WIN_MOTD_STREAK1_TP"; key_STREAK2 = "WIN_MOTD_STREAK2_TP"; key_STREAK3 = "WIN_MOTD_STREAK3_TP"; key_STREAK4 = "WIN_MOTD_STREAK4_TP"; } else { key_LINE5A = "WIN_MOTD_LINE5A_REG"; key_LINE5B = "WIN_MOTD_LINE5B_REG"; key_LINE5C = "WIN_MOTD_LINE5C_REG"; key_LINE7A = "WIN_MOTD_LINE7A_REG"; key_LINE7B = "WIN_MOTD_LINE7B_REG"; key_LINE7C = "WIN_MOTD_LINE7C_REG"; key_STREAK1 = "WIN_MOTD_STREAK1_REG"; key_STREAK2 = "WIN_MOTD_STREAK2_REG"; key_STREAK3 = "WIN_MOTD_STREAK3_REG"; key_STREAK4 = "WIN_MOTD_STREAK4_REG"; } } else { key_LINE5A = "WIN_MOTD_LINE5A"; key_LINE5B = "WIN_MOTD_LINE5B"; key_LINE5C = "WIN_MOTD_LINE5C"; key_LINE7A = "WIN_MOTD_LINE7A"; key_LINE7B = "WIN_MOTD_LINE7B"; key_LINE7C = "WIN_MOTD_LINE7C"; key_STREAK1 = "WIN_MOTD_STREAK1"; key_STREAK2 = "WIN_MOTD_STREAK2"; key_STREAK3 = "WIN_MOTD_STREAK3"; key_STREAK4 = "WIN_MOTD_STREAK4"; }
// format for each language new player; for(player=1;player<=maxPlayers;player++) { if(!is_user_connected(player)) continue; /*if(pointsExtraction[player][0] == 0 && pointsExtraction[player][1] == 0 && pointsExtraction[player][2] == 0) { log_amx("&&&&& ZERO POINTS! (3) player %i, team %i, team times: %f , %f",player,cs_get_user_team(player),teamTimes[player][winningTeam-1],teamTimes[player][losingTeam-1]); log_message("&&&&& ZERO POINTS! (3) player %i, team %i, team times: %f , %f",player,cs_get_user_team(player),teamTimes[player][winningTeam-1],teamTimes[player][losingTeam-1]); }*/
if(loserDC) formatex(loserName,31,"%L",player,"NO_ONE"); formatex(header,31,"%L",player,"WIN_MOTD_LINE1",winnerName); // DEBUG len = formatex(motd,1535,"<meta http-equiv=^"Content-Type^" content=^"text/html;charset=UTF-8^">"); len = formatex(motd,1535,"<html><head><meta http-equiv=^"Content-Type^" content=^"text/html; charset=utf-8^"></head><body bgcolor=black style=line-height:1;color:white><center><font color=00CC00 size=7 face=Georgia>[GUNGAME] AMXX<p>");
len += formatex(motd[len],1535-len,"<font color=%s size=6 style=letter-spacing:2px>",winnerColor); len += formatex(motd[len],1535-len,"<div style=height:1px;width:80%%;background-color:%s;overflow:hidden></div>",winnerColor); if(teamplay) len += formatex(motd[len],1535-len,"%L",player,"WIN_MOTD_LINE2",winnerTeam); else len += formatex(motd[len],1535-len,"%s",winnerName); len += formatex(motd[len],1535-len,"<div style=height:1px;width:80%%;background-color:%s;overflow:hidden></div>",winnerColor); len += formatex(motd[len],1535-len,"<font size=4 color=white style=letter-spacing:1px>%L<p>",player,"WIN_MOTD_LINE3");
if(!teamplay) len += formatex(motd[len],1535-len,"<font size=3>%L</font>.<p>",player,"WIN_MOTD_LINE4A",lvlWeapon[winner],loserColor,loserName); else len += formatex(motd[len],1535-len,"<font size=3>%L</font>.<p>",player,"WIN_MOTD_LINE4B",lvlWeapon[winner],loserColor,loserName,winnerColor,winnerName);
if(sqlInit && stats_mode == 1) { if(teamplay && timeratio) { // not enough for a win if(teamTimes[winner][winningTeam-1]/(teamTimes[winner][winningTeam-1]+teamTimes[winner][losingTeam-1]) < 0.5) len += formatex(motd[len],1535-len,"<p>"); else len += formatex(motd[len],1535-len,"%L<p>",player,key_LINE5A,winnerColor,winnerName,pointsExtraction[winner][0],winnerWinSuffix,pointsExtraction[winner][3],winnerStreakSuffix,pointsExtraction[winner][4]); // no play time if(teamTimes[player][winningTeam-1] < 1.0 && teamTimes[player][losingTeam-1] < 1.0) len += formatex(motd[len],1535-len,"%L<br>",player,"WIN_MOTD_LINE6",0); else len += formatex(motd[len],1535-len,"%L<br>",player,"WIN_MOTD_LINE6",floatround(teamTimes[player][winningTeam-1]/(teamTimes[player][winningTeam-1]+teamTimes[player][losingTeam-1])*100.0)); } else len += formatex(motd[len],1535-len,"%L<p>",player,key_LINE5A,winnerColor,winnerName,pointsExtraction[winner][0],winnerWinSuffix,pointsExtraction[winner][3],winnerStreakSuffix,pointsExtraction[winner][4]); // we won somehow if( (!teamplay && winner == player) || (teamplay && !timeratio && winningTeam == _:cs_get_user_team(player)) || (teamplay && timeratio && teamTimes[player][winningTeam-1]/(teamTimes[player][winningTeam-1]+teamTimes[player][losingTeam-1]) >= 0.5) ) { get_number_suffix(pointsExtraction[player][3],myStreakSuffix,2); len += formatex(motd[len],1535-len,"%L<br>",player,key_LINE7A,pointsExtraction[player][0],pointsExtraction[player][3],myStreakSuffix,pointsExtraction[player][4]); }
// we didn't get a win else len += formatex(motd[len],1535-len,"%L<p>",player,key_LINE7B,pointsExtraction[player][0]); } else if(sqlInit && stats_mode == 2) { if(teamplay && timeratio) { // winner didn't play enough to get a win if(teamTimes[winner][winningTeam-1]/(teamTimes[winner][winningTeam-1]+teamTimes[winner][losingTeam-1]) < 0.5) len += formatex(motd[len],1535-len,"%L<p>",player,key_LINE5B,winnerColor,winnerName,pointsExtraction[winner][2]); else len += formatex(motd[len],1535-len,"%L<p>",player,key_LINE5C,winnerColor,winnerName,pointsExtraction[winner][0],winnerWinSuffix,pointsExtraction[winner][2],pointsExtraction[winner][3],winnerStreakSuffix,pointsExtraction[winner][4]); // no play time if(teamTimes[player][winningTeam-1] < 1.0 && teamTimes[player][losingTeam-1] < 1.0) len += formatex(motd[len],1535-len,"%L<br>",player,"WIN_MOTD_LINE6",0); else len += formatex(motd[len],1535-len,"%L<br>",player,"WIN_MOTD_LINE6",floatround(teamTimes[player][winningTeam-1]/(teamTimes[player][winningTeam-1]+teamTimes[player][losingTeam-1])*100.0)); } else len += formatex(motd[len],1535-len,"%L<p>",player,key_LINE5C,winnerColor,winnerName,pointsExtraction[winner][0],winnerWinSuffix,pointsExtraction[winner][2],pointsExtraction[winner][3],winnerStreakSuffix,pointsExtraction[winner][4]); len += formatex(motd[len],1535-len,"%L<%s>",player,key_LINE7C,pointsExtraction[player][1],pointsExtraction[player][2],pointsExtraction[player][0],(pointsExtraction[player][3]) ? "p" : "p");
if(pointsExtraction[player][3]) { get_number_suffix(pointsExtraction[player][3],myStreakSuffix,2); len += formatex(motd[len],1535-len,"%L<br>",player,key_STREAK1,pointsExtraction[player][3],myStreakSuffix,pointsExtraction[player][4]); } } else len += formatex(motd[len],1535-len,"<p>"); if(sqlInit && stats_mode) { if(!pointsExtraction[player][3] && pointsExtraction[player][4]) // I'm not on a streak, but I do have a record { len += formatex(motd[len],1535-len,"%L<br>",player,key_STREAK2,pointsExtraction[player][4]); }
if(pointsExtraction[0][1] == -1) // champion is the previous record holder { // there actually was a previous record if(pointsExtraction[0][0]) len += formatex(motd[len],1535-len,"%L<p>",player,key_STREAK3,pointsExtraction[0][0],spareName); } else len += formatex(motd[len],1535-len,"%L<p>",player,key_STREAK4,streakChampColor,spareName,pointsExtraction[0][2]); } if(iterations > 0) { if(roundsleft <= 0) len += formatex(motd[len],1535-len,"%L",player,"WIN_MOTD_LINE8A",nextmap); else if(roundsleft == 1) len += formatex(motd[len],1535-len,"%L",player,"WIN_MOTD_LINE8B"); else len += formatex(motd[len],1535-len,"%L",player,"WIN_MOTD_LINE8C",roundsleft); } show_motd(player,motd,header); } return 1; }
//********************************************************************** // TEAMPLAY FUNCTIONS //**********************************************************************
// change the score of a team stock teamplay_update_score(team,newScore,exclude=0,direct=0) { if(team != 1 && team != 2) return;
teamScore[team] = newScore; new player, sdisplay = get_pcvar_num(gg_status_display); for(player=1;player<=maxPlayers;player++) { if(is_user_connected(player) && player != exclude && _:cs_get_user_team(player) == team) { if(direct) { score[player] = newScore; if(sdisplay == STATUS_KILLSLEFT || sdisplay == STATUS_KILLSDONE) status_display(player); } else change_score(player,newScore-score[player],0); // don't refill } } }
// change the level of a team stock teamplay_update_level(team,newLevel,exclude=0,direct=1) { if(team != 1 && team != 2) return;
teamLevel[team] = newLevel; get_level_weapon(teamLevel[team],teamLvlWeapon[team],23); new player; for(player=1;player<=maxPlayers;player++) { if(is_user_connected(player) && player != exclude && _:cs_get_user_team(player) == team) { //if(direct) level[player] = newLevel; if(direct) set_level_noifandsorbuts(player,newLevel); else change_level(player,newLevel-level[player],_,_,1); // always score } } }
// play the taken/tied/lost lead sounds public teamplay_play_lead_sounds(id,oldLevel,Float:playDelay) { // both teams not initialized yet if(!teamLevel[1] || !teamLevel[2]) return;
// id: the player whose level changed // oldLevel: his level before it changed // playDelay: how long to wait until we play id's sounds // warmup or game over, no one cares if(warmup > 0 || won) return;
// no level change if(level[id] == oldLevel) return; new team = _:cs_get_user_team(id), otherTeam = (team == 1) ? 2 : 1, thisTeam, player, params[2]; if(team != 1 && team != 2) return;
new leaderLevel, numLeaders, leader = teamplay_get_lead_team(leaderLevel,numLeaders); // this team is leading if(leader == team) { // the other team here? if(numLeaders > 1) { params[1] = gg_sound_tiedlead; // play to both teams for(player=1;player<=maxPlayers;player++) { if(!is_user_connected(player)) continue;
thisTeam = _:cs_get_user_team(player); if(thisTeam == team || thisTeam == otherTeam) { params[0] = player; remove_task(TASK_PLAY_LEAD_SOUNDS+player); set_task((thisTeam == team) ? playDelay : 0.1,"play_sound_by_cvar_task",TASK_PLAY_LEAD_SOUNDS+player,params,2); } } } // just us, we are the winners! else { // did we just pass the other team? if(level[id] > oldLevel && teamLevel[otherTeam] == oldLevel) { // play to both teams (conditional) for(player=1;player<=maxPlayers;player++) { if(!is_user_connected(player)) continue; thisTeam = _:cs_get_user_team(player); if(thisTeam == team) params[1] = gg_sound_takenlead; else if(thisTeam == otherTeam) params[1] = gg_sound_lostlead; else continue; params[0] = player; remove_task(TASK_PLAY_LEAD_SOUNDS+player); set_task((thisTeam == team) ? playDelay : 0.1,"play_sound_by_cvar_task",TASK_PLAY_LEAD_SOUNDS+player,params,2); } } } } // WAS this team on the leader level? else if(oldLevel == leaderLevel) { // play to entire team for(player=1;player<=maxPlayers;player++) { if(!is_user_connected(player)) continue; thisTeam = _:cs_get_user_team(player); if(thisTeam == team) params[1] = gg_sound_lostlead; else if(thisTeam == otherTeam) params[1] = gg_sound_takenlead; else continue; params[0] = player; remove_task(TASK_PLAY_LEAD_SOUNDS+player); set_task((thisTeam == team) ? playDelay : 0.1,"play_sound_by_cvar_task",TASK_PLAY_LEAD_SOUNDS+player,params,2); } } }
// find the highest level team and such stock teamplay_get_lead_team(&retLevel=0,&retNumLeaders=0,&retRunnerUp=0) { new leader, numLeaders, runnerUp; if(teamLevel[1] >= teamLevel[2]) leader = 1; else leader = 2;
if(teamLevel[1] == teamLevel[2]) numLeaders = 2; else { numLeaders = 1; runnerUp = (leader == 1) ? 2 : 1; }
retLevel = teamLevel[leader]; retNumLeaders = numLeaders; retRunnerUp = runnerUp;
return leader; }
// gets the team's level goal without a player passed teamplay_get_team_goal(team) { if(team != 1 && team != 2) return 0;
new player; for(player=1;player<=maxPlayers;player++) { if(is_user_connected(player) && _:cs_get_user_team(player) == team) return get_level_goal(teamLevel[team],player); } return 0; }
//********************************************************************** // AUTOVOTE FUNCTIONS //**********************************************************************
// start the autovote public autovote_start() { // vote in progress if(autovotes[0] || autovotes[1] || autovotes[2] || task_exists(TASK_AUTOVOTE_RESULT)) return 0;
new Float:autovote_time = get_pcvar_float(gg_autovote_time);
new i; for(i=1;i<=maxPlayers;i++) { if(!is_user_connected(i)) continue;
switch(autovote_mode) { case 1: { formatex(menuText,511,"\y%L^n^n\w1. %L^n2. %L^n^n0. %L",i,"PLAY_GUNGAME",i,"YES",i,"NO",i,"CANCEL"); show_menu(i,MENU_KEY_1|MENU_KEY_2|MENU_KEY_0,menuText,floatround(autovote_time),"autovote_menu"); } case 2: { formatex(menuText,511,"\y%L^n^n\w1. %L^n2. %L^n^n0. %L",i,"PLAY_GUNGAME",i,"YES_TEAMPLAY",i,"YES_REGULAR",i,"CANCEL"); show_menu(i,MENU_KEY_1|MENU_KEY_2|MENU_KEY_0,menuText,floatround(autovote_time),"autovote_menu"); } default: { formatex(menuText,511,"\y%L^n^n\w1. %L^n2. %L^n3. %L^n^n0. %L",i,"PLAY_GUNGAME",i,"YES_TEAMPLAY",i,"YES_REGULAR",i,"NO",i,"CANCEL"); show_menu(i,MENU_KEY_1|MENU_KEY_2|MENU_KEY_3|MENU_KEY_0,menuText,floatround(autovote_time),"autovote_menu"); } } }
gungame_print(0,0,1,"%L",LANG_PLAYER_C,"VOTING_STARTED"); set_task(autovote_time,"autovote_result",TASK_AUTOVOTE_RESULT);
return 1; }
// take in votes public autovote_menu_handler(id,key) { switch(key) { case 0: // 1. { /* MODE 1- YES MODE 2- YES_TEAMPLAY MODE 3- YES_TEAMPLAY */ autovotes[0]++; } case 1: // 2. { /* MODE 1- NO MODE 2- YES_REGULAR MODE 3- YES_REGULAR */ if(autovote_mode == 1) autovotes[2]++; else autovotes[1]++; } case 2: // 3. { /* MODE 1- MODE 2- MODE 3- NO */ autovotes[2]++; } //case 9: 0. /* ALL MODES- CANCEL */ let menu close }
return PLUGIN_HANDLED; }
// calculate end of vote, some of this was thanks to VEN public autovote_result() { new vYes = autovotes[0] + autovotes[1], vNo = autovotes[2], vTotal = vYes + vNo, vSuccess, teamplay = get_pcvar_num(gg_teamplay), key[16];
switch(autovote_mode) { case 1: // this mode asks if they want to play GunGame, yes/no { if(vTotal) { if(float(vYes) / float(vTotal) >= get_pcvar_float(gg_autovote_ratio)) vSuccess = 1; // the choice that changes the current game mode is the one that needs to meet the ratio. so if you are // playing GunGame, at least however many people as defined by the ratio need to vote for it off to switch it, // and vice-versa. if( ( ggActive && (float(vNo) / float(vTotal)) < get_pcvar_float(gg_autovote_ratio)) || (!ggActive && (float(vYes) / float(vTotal)) >= get_pcvar_float(gg_autovote_ratio)) ) vSuccess = 1; // means that we will be playing GunGame } else if(ggActive) vSuccess = 1;
if(vSuccess && !ggActive) { restart_round(5); set_task(4.8,"toggle_gungame",TASK_TOGGLE_GUNGAME+TOGGLE_ENABLE); } else if(!vSuccess && ggActive) { restart_round(5); set_task(4.8,"toggle_gungame",TASK_TOGGLE_GUNGAME+TOGGLE_DISABLE); set_pcvar_num(gg_enabled,0); ggActive = 0; } if(vSuccess && teamplay) key = "AUTOVOTE_RES1"; else if(vSuccess && !teamplay) key = "AUTOVOTE_RES2"; else key = "AUTOVOTE_RES3"; gungame_print(0,0,1,"%L %i %L - %i %L - %L :: %L",LANG_PLAYER_C,"PLAY_GUNGAME",vYes,LANG_PLAYER_C,"YES",vNo,LANG_PLAYER_C,"NO",LANG_PLAYER_C,"THE_RESULT",LANG_PLAYER_C,key); } case 2: // this mode asks if they want to play teamplay, yes/no { if(!ggActive) { restart_round(5); set_task(4.8,"toggle_gungame",TASK_TOGGLE_GUNGAME+TOGGLE_ENABLE); }
if(vTotal) { // see above comment if( ( teamplay && (float(autovotes[1]) / float(vTotal)) < get_pcvar_float(gg_autovote_ratio)) || (!teamplay && (float(autovotes[0]) / float(vTotal)) >= get_pcvar_float(gg_autovote_ratio)) ) vSuccess = 1; // means that we will be playing teamplay mode } else if(teamplay) vSuccess = 1;
if(vSuccess) { if(!teamplay) { set_pcvar_num(gg_teamplay,1); if(ggActive && warmup <= 0) restart_round(3); exec_gg_config_file(0,0); exec_gg_config_file(1,0); }
set_task(4.9,"force_teamplay",1); } else if(!vSuccess) { if(teamplay) { set_pcvar_num(gg_teamplay,0); if(ggActive && warmup <= 0) restart_round(3); exec_gg_config_file(0,0); }
set_task(4.9,"force_teamplay",0); }
if(vSuccess) key = "AUTOVOTE_RES1"; else key = "AUTOVOTE_RES2"; gungame_print(0,0,1,"%L %i %L - %i %L - %L :: %L",LANG_PLAYER_C,"PLAY_GUNGAME",autovotes[0],LANG_PLAYER_C,"YES_TEAMPLAY",autovotes[1],LANG_PLAYER_C,"YES_REGULAR",LANG_PLAYER_C,"THE_RESULT",LANG_PLAYER_C,key); } default: // this mode asks if they want to play, teamplay/regular/no { if(vTotal) { // see above comment if( ( ggActive && (float(vNo) / float(vTotal)) < get_pcvar_float(gg_autovote_ratio)) || (!ggActive && (float(vYes) / float(vTotal)) >= get_pcvar_float(gg_autovote_ratio)) ) vSuccess = 1; // means that we will be playing GunGame } else if(ggActive) vSuccess = 1;
if(vSuccess) { if(!ggActive) { restart_round(5); set_task(4.8,"toggle_gungame",TASK_TOGGLE_GUNGAME+TOGGLE_ENABLE); } // pick a random value for teamplay if we need it, then see if we should be using it. // use it in the case that we have a tie, and we are using random teamplay mode. new rand_val = random_num(0,1); new use_rand = (autovotes[0] == autovotes[1] && (teamplay == 2 || initTeamplayInt == 2));
if(autovotes[0] > autovotes[1] || (use_rand && rand_val == 1)) // more votes for teamplay { if(!teamplay) { set_pcvar_num(gg_teamplay,1); if(ggActive && warmup <= 0) restart_round(3); exec_gg_config_file(0,0); exec_gg_config_file(1,0); } key = "AUTOVOTE_RES1"; set_task(4.9,"force_teamplay",1); } else if(autovotes[0] < autovotes[1] || (use_rand && rand_val == 0)) // more votes for regular { if(teamplay) { set_pcvar_num(gg_teamplay,0); if(ggActive && warmup <= 0) restart_round(3); exec_gg_config_file(0,0); } key = "AUTOVOTE_RES2"; set_task(4.9,"force_teamplay",0); } else // if equal, leave it be { if(teamplay) { key = "AUTOVOTE_RES1"; set_task(4.9,"force_teamplay",1); } else { key = "AUTOVOTE_RES2"; set_task(4.9,"force_teamplay",0); } } } else if(!vSuccess && ggActive) { restart_round(5); set_task(4.8,"toggle_gungame",TASK_TOGGLE_GUNGAME+TOGGLE_DISABLE); set_pcvar_num(gg_enabled,0); ggActive = 0; }
if(!vSuccess) key = "AUTOVOTE_RES3"; gungame_print(0,0,1,"%L %i %L - %i %L - %i %L - %L :: %L",LANG_PLAYER_C,"PLAY_GUNGAME",autovotes[0],LANG_PLAYER_C,"YES_TEAMPLAY",autovotes[1],LANG_PLAYER_C,"YES_REGULAR",vNo,LANG_PLAYER_C,"NO",LANG_PLAYER_C,"THE_RESULT",LANG_PLAYER_C,key); } } autovotes[0] = 0; autovotes[1] = 0; autovotes[2] = 0; }
// force teamplay mode to what we want after a vote has been completed. // otherwise, when switching from GunGame off to on, it will be overwritten by gungame.cfg. public force_teamplay(teamplay) { set_pcvar_num(gg_teamplay,teamplay); exec_gg_config_file(0,0); if(teamplay) exec_gg_config_file(1,0); }
//********************************************************************** // STAT FUNCTIONS //**********************************************************************
// clear out everything about our stats stats_clear_all() { #if !defined SQL // destroy large array if(statsArray) ArrayDestroy(statsArray);
// destroy the two "pointer" arrays if(statsPointers[0]) { ArrayDestroy(statsPointers[0]); statsSize[0] = 0; } if(statsPointers[1]) { ArrayDestroy(statsPointers[1]); statsSize[1] = 0; } #endif // clear out saved stats data for the players for(new i=1;i<=maxPlayers;i++) { statsPosition[i][0] = 0; statsPosition[i][1] = 0; stats_clear_struct(playerStats[i]); } // clear out saved stats data from the temp saves for(new i=0;i<TEMP_SAVES;i++) { tempSave[i][svStatsPosition][0] = 0; tempSave[i][svStatsPosition][1] = 0; } }
#if !defined SQL // converts a stats string (as in gungame.stats) into a stats struct (by reference) stats_str_to_struct(str[],struct[statsData]) { // The format for str (as saved in gungame.stats): // // AUTHID WINS LAST_USED_NAME TIMESTAMP POINTS STREAK TPWINS TPPOINTS TPSTREAK
static piece[32], whole[112]; piece[0] = 0; whole[0] = 0; stats_clear_struct(struct); strtok(str,piece,31,whole,111,'^t'); copy(struct[sdAuthid],31,piece); strtok(whole,piece,5,whole,111,'^t'); struct[sdWins][0] = str_to_num(piece); strtok(whole,piece,31,whole,111,'^t'); copy(struct[sdName],31,piece); strtok(whole,piece,11,whole,111,'^t'); struct[sdTimestamp] = str_to_num(piece); strtok(whole,piece,7,whole,111,'^t'); struct[sdPoints][0] = str_to_num(piece); strtok(whole,piece,3,whole,111,'^t'); struct[sdStreak][0] = str_to_num(piece); strtok(whole,piece,5,whole,111,'^t'); struct[sdWins][1] = str_to_num(piece); strtok(whole,piece,7,whole,3,'^t'); struct[sdPoints][1] = str_to_num(piece); //strtok(whole,piece,3,whole,1,'^t'); struct[sdStreak][1] = str_to_num(whole); } #endif
#if defined SQL // sql version] much simpler. stock stats_refresh_timestamp(authid[]) { if(!sqlInit) return 0;
SQL_QuoteString(db,safeName,63,authid); query = SQL_PrepareQuery(db,"UPDATE `%s` SET timestamp='%i' WHERE authid='%s' AND serverip='%s' LIMIT 1;",sqlTable,get_systime(),safeName,serverip);
SQL_ExecuteAndLog(query); SQL_FreeHandle(query); return 1; } #else // IT'S BEEN REVIVED! // // This took me way too long to develop, but it actually is able to overwrite the // old timestamp without having to copy over to a new file or anything. It should // work until sometime in the year 2287 when Unix timestamps will be 11 digits. // // On my old 2.80 gHz Pentium IV, it takes less than a tenth of a second to read to // the bottom of a 10,000 line stats file and then refresh the final player's timestamp. stock stats_refresh_timestamp(authid[]) { get_pcvar_string(gg_stats_file,sfFile,63); if(!file_exists(sfFile)) return 0;
new file = fopen(sfFile,"rt+"); if(!file) return 0; new readLen, authidLen = strlen(authid), q, lastPos; formatex(sfTimestamp,10,"%10i",get_systime());
while(!feof(file)) { readLen = fgets(file,sfLineData,111); // check to see if this line starts with our authid for(q=0;q<authidLen;q++) { if(sfLineData[q] != authid[q]) { q = 255; break; } } if(q == 255) // this means we didn't have a match (see above) { lastPos += readLen + 1; // keep track of how far we've come continue; } new tabs; q += 2; // one to advance to first tab, another to skip over it while(sfLineData[q] != 0) { q++; // format is: AUTHID WINS NAME TIMESTAMP POINTS if(sfLineData[q-1] == '^t' && ++tabs == 2) break; // we skipped first tab above, so go until we get past the third tab overall } // now q is the position of our timestamp fseek(file,lastPos+q,SEEK_SET); fwrite_blocks(file,sfTimestamp,10,BLOCK_CHAR); // overwrite timestamp with current one
break; } fclose(file);
return (q != 255); } #endif
// we now have a super-duper function so that we only have to go through // the stats file once, instead of rereading and rewriting it for every // single player in a points match. // // also, timestamps are refreshed here, instead of every time you join. public stats_award_points(winner) { new stats_mode = get_pcvar_num(gg_stats_mode); if(!sqlInit || !stats_mode) return;
new teamplay = get_pcvar_num(gg_teamplay), winningTeam =_:cs_get_user_team(winner), losingTeam = _:(!(winningTeam-1)) + 1, stats_ip = get_pcvar_num(gg_stats_ip), timeratio = get_pcvar_num(gg_teamplay_timeratio), ignore_bots = get_pcvar_num(gg_ignore_bots); new si = get_gg_si(); //log_amx("AWARDING POINTS USING FILE [%s], TEAMPLAY IS [%i]",STATS_FILE[si],teamplay); // DEBUG
new player, playerWins[32], playerPoints[32], playerStreak[32], playerAuthid[32][32], playerName[32][32], playerTotalPoints[32], players[32], intStreak, playerNum, i, team, Float:time = get_gametime(), systime = get_systime();
#if defined SQL new playerSafeName[32][64], playerSafeAuthid[32][64]; #endif
//new botid;
get_players(players,playerNum); for(i=0;i<playerNum;i++) { player = players[i]; // keep track of time team = _:cs_get_user_team(player); if(team == 1 || team == 2) teamTimes[player][team-1] += time - lastSwitch[player]; lastSwitch[player] = time; get_gg_authid(player,playerAuthid[i],31,stats_ip); get_user_name(player,playerName[i],31); /*if(equal(playerAuthid[i],"BOT")) { botid++; formatex(playerAuthid[i],31,"BOT_%i",botid); }*/ #if defined SQL SQL_QuoteString(db,playerSafeName[i],63,playerName[i]); SQL_QuoteString(db,playerSafeAuthid[i],63,playerAuthid[i]); #endif // solo wins only if(player == winner && stats_mode == 1 && !teamplay) playerWins[i] = 1; } // // COLLECT LIST OF PLAYERS AND THEIR INFORMATION //
// points system if(stats_mode == 2) { new wins, Float:flPoints, Float:winbonus = get_pcvar_float(gg_stats_winbonus), Float:percent;
for(i=0;i<playerNum;i++) { player = players[i]; if(!is_user_connected(player) || (ignore_bots && is_user_bot(player))) continue; wins = 0; // WHY DID I FORGET THIS BEFORE // point ratio based on time played in teamplay if(teamplay && timeratio) { // no play time if(teamTimes[player][winningTeam-1] < 1.0 && teamTimes[player][losingTeam-1] < 1.0) continue;
// give us points from losing team flPoints = (float(teamLevel[losingTeam]) - 1.0) * teamTimes[player][losingTeam-1]/(teamTimes[player][winningTeam-1]+teamTimes[player][losingTeam-1]);
// give us points from winning team percent = teamTimes[player][winningTeam-1]/(teamTimes[player][winningTeam-1]+teamTimes[player][losingTeam-1]); flPoints += (float(teamLevel[winningTeam]) - 1.0) * percent; // we played over half on winning team, give us a bonus and win if(percent >= 0.5) { flPoints *= winbonus; wins = 1; } } else { flPoints = float(level[player]) - 1.0; // calculate points and add
// winner gets bonus points plus a win if(player == winner || (teamplay && _:cs_get_user_team(player) == winningTeam)) { flPoints *= winbonus; wins = 1; } }
// unnecessary if(flPoints < 0.5 && !wins) continue;
playerWins[i] = wins; playerPoints[i] = floatround(flPoints); if(playerPoints[i] < 0) playerPoints[i] = 0; // DEBUG /*if(playerPoints[i] < 1) { log_amx("***** ERROR! (1) Negative points for player %i: %i (%f / %i) | Team times: %f , %f",players[i],playerPoints[i],flPoints,wins,teamTimes[players[i]][winningTeam-1],teamTimes[players[i]][losingTeam-1]); log_message("***** ERROR! (1) Negative points for player %i: %i (%f / %i) | Team times: %f , %f",players[i],playerPoints[i],flPoints,wins,teamTimes[players[i]][winningTeam-1],teamTimes[players[i]][losingTeam-1]); }*/ } }
// regular wins teamplay (solo regular wins is above) else if(teamplay) { for(i=0;i<playerNum;i++) { player = players[i]; if(_:cs_get_user_team(player) == winningTeam && (!ignore_bots || !is_user_bot(player))) { // no play time if(teamTimes[player][winningTeam-1] < 1.0 && teamTimes[player][losingTeam-1] < 1.0) continue;
// have to play at least half to get a win if(!timeratio || teamTimes[player][winningTeam-1]/(teamTimes[player][winningTeam-1]+teamTimes[player][losingTeam-1]) >= 0.5) playerWins[i] = 1; } } } // // START MANAGING STREAKS // new streakToBeat = 0, streakChamp = -1; #if defined SQL new champRowExists;
// find current champion's info query = SQL_PrepareQuery(db,"SELECT streak,name FROM `%s` WHERE type='%iR' AND serverip='%s' LIMIT 1;",sqlStreakTable,si,serverip); if(SQL_ExecuteAndLog(query)) { if(SQL_NumResults(query)) { champRowExists = 1; streakToBeat = SQL_ReadResult(query,0); SQL_ReadResult(query,1,spareName,31); } } SQL_FreeHandle(query); pointsExtraction[0][0] = streakToBeat; // record old record pointsExtraction[0][1] = -1; // record champion new len, origLen;
// form query to delete players who did not win this round from the cache origLen = len = formatex(mkQuery,1535,"DELETE FROM `%s` WHERE type='%iC' AND serverip='%s' AND authid NOT IN (",sqlStreakTable,si,serverip); for(i=0;i<playerNum;i++) { if(playerWins[i]) len += formatex(mkQuery[len],1535-len,"%s'%s'",(len!=origLen) ? "," : "",playerSafeAuthid[i]); }
if(len == origLen) { // no one was added, then add empty apostrophes to avoid SQL syntax error len += formatex(mkQuery[len],1535-len,"''"); }
len += formatex(mkQuery[len],1535-len,");");
query = SQL_PrepareQuery(db,mkQuery); SQL_ExecuteAndLog(query); SQL_FreeHandle(query); // use one query to get all current streaks, then process them in the loop and save to playerStreak array new authid[64]; query = SQL_PrepareQuery(db,"SELECT authid,streak FROM `%s` WHERE type='%iC' AND serverip='%s';",sqlStreakTable,si,serverip); if(SQL_ExecuteAndLog(query) && SQL_NumResults(query)) { while(SQL_MoreResults(query)) { SQL_ReadResult(query,0,authid,63); for(i=0;i<playerNum;i++) { if(equal(authid,playerSafeAuthid[i])) { playerStreak[i] = SQL_ReadResult(query,1); break; } } SQL_NextRow(query); } } SQL_FreeHandle(query); len = origLen = formatex(mkQuery,1535,"INSERT INTO `%s` VALUES ",sqlStreakTable); // now go through players, and make sure to start a streak for those who don't have one for(i=0;i<playerNum;i++) { if(playerWins[i]) { playerStreak[i]++; // if they won, they get one added to their streak
// am I the champion?? also, in the case of a tie, allow the winner of this round to be considered the champ if(playerStreak[i] > streakToBeat || (streakChamp != -1 && playerStreak[i] == streakToBeat && players[i] == winner)) { streakToBeat = playerStreak[i]; streakChamp = i; } // didn't find one with previous loop if(playerStreak[i] == 1) // because of increment above, will be 1 at minimum { // insert a new row. note that the streak is inserted as 0 because it gets incremented below. len += formatex(mkQuery[len],1535-len,"('%iC','%s','0','%s','%i','%s'),",si,playerSafeAuthid[i],playerSafeName[i],systime,serverip); // cash in if we get too close if(len >= 1200) { mkQuery[len-1] = ';'; mkQuery[len] = 0;
query = SQL_PrepareQuery(db,mkQuery); SQL_ExecuteAndLog(query); SQL_FreeHandle(query); len = origLen = formatex(mkQuery,1535,"INSERT INTO `%s` VALUES ",sqlStreakTable); } } } } // if we have some leftover query if(len > origLen) { mkQuery[len-1] = ';'; mkQuery[len] = 0;
query = SQL_PrepareQuery(db,mkQuery); SQL_ExecuteAndLog(query); SQL_FreeHandle(query); }
// update everyone's current streaks by +1 query = SQL_PrepareQuery(db,"UPDATE `%s` SET streak=streak+1 WHERE type='%iC' AND serverip='%s';",sqlStreakTable,si,serverip); SQL_ExecuteAndLog(query); SQL_FreeHandle(query); // somebody beat the champion! if(streakToBeat && streakChamp != -1) { if(champRowExists) query = SQL_PrepareQuery(db,"UPDATE `%s` SET authid='%s', streak='%i', name='%s', timestamp='%i' WHERE type='%iR' AND serverip='%s' LIMIT 1;",sqlStreakTable,playerSafeAuthid[streakChamp],streakToBeat,playerSafeName[streakChamp],systime,si,serverip); else query = SQL_PrepareQuery(db,"INSERT INTO `%s` VALUES ('%iR','%s','%i','%s',%i,'%s');",sqlStreakTable,si,playerSafeAuthid[streakChamp],streakToBeat,playerSafeName[streakChamp],systime,serverip);
SQL_ExecuteAndLog(query); SQL_FreeHandle(query); } #else // go through and copy down the list of players who got a win last round new sfStreak[2][4], tempFileName[65], streakRecord[53], streakFile, stats_streak_file[64]; get_pcvar_string(gg_stats_streak_file,stats_streak_file,63);
if(file_exists(stats_streak_file)) { formatex(tempFileName,64,"%s2",stats_streak_file); // our temp file, append 2 rename_file(stats_streak_file,tempFileName,1); // copy it over to the temp name (relative flag)
// there are two basic types of lines: // a record line, ie: 0R AUTHID STREAK NAME TIMESTAMP // a "cache" line (a player with a running streak), ie: 0C AUTHID STREAK // the first digit is the stats index (0 for regular, 1 for teamplay)
new streakTempFile = fopen(tempFileName,"rt"); streakFile = fopen(stats_streak_file,"wt");
// go through the old file, copy over unimportant lines, figure out the record, and distribute streaks while(!feof(streakTempFile)) { fgets(streakTempFile,sfLineData,82); if(!sfLineData[0]) continue;
// not for our stats mode if(str_to_num(sfLineData[0]) != si) { fprintf(streakFile,sfLineData); // just copy it over continue; }
// this is the record if(sfLineData[1] == 'R') { copy(streakRecord,82,sfLineData); // just save it for now continue; }
// this is a cache (a player who got a win last game) if(sfLineData[1] == 'C') { // use sfLineData[3] to skip characters "0C " (should be a tab) strtok(sfLineData[3],sfAuthid,31,sfStreak[0],3,'^t'); // split them up
for(i=0;i<playerNum;i++) { // if we won, and we haven't read our streak yet, and this is our authid if(playerWins[i] && !playerStreak[i] && equal(playerAuthid[i],sfAuthid)) { playerStreak[i] = str_to_num(sfStreak[0]); // set our streak to our previous one break; // in the case of duplicate authids, don't continually add to the streak } } continue; }
// don't copy over the rest, so it sort of auto-prunes //fprintf(streakFile,sfLineData); // OLD COMMENT IGNORE ME: anything else, we might as well copy it }
// get rid of the old copy fclose(streakTempFile); delete_file(tempFileName); } else if(stats_streak_file[0]) streakFile = fopen(stats_streak_file,"wt"); // did not exist, create it //new streakToBeat = 0, streakChamp = -1; if(streakRecord[0]) // if there was a record, figure it out { strtok(streakRecord[3],dummy,1,sfLineData,82,'^t'); // cut off prefix and authid from the left strtok(sfLineData,sfStreak[0],3,spareName,31,'^t'); // get our streak, and the name as well new pos = contain_char(spareName,'^t'); if(pos != -1) spareName[pos] = 0; // cut off the timestamp from the name
streakToBeat = str_to_num(sfStreak[0]); } pointsExtraction[0][0] = streakToBeat; // record old record pointsExtraction[0][1] = -1; // record champion
// now go through current players, and rewrite them with their new streaks into the file for(i=0;i<playerNum;i++) { if(playerWins[i]) { playerStreak[i]++; // if they won, they get one added to their streak // am I the champion?? also, in the case of a tie, allow the winner of this round to be considered the champ if(playerStreak[i] > streakToBeat || (streakChamp != -1 && playerStreak[i] == streakToBeat && players[i] == winner)) { streakToBeat = playerStreak[i]; streakChamp = i; }
if(streakFile) { fprintf(streakFile,"%iC^t%s^t%i",si,playerAuthid[i],playerStreak[i]); fputc(streakFile,'^n'); } } } if(streakFile) { if(streakToBeat) { if(streakChamp == -1) fprintf(streakFile,"%s",streakRecord); // no one here beat the champ, reprint old champ else // otherwise, give the new guy credit { fprintf(streakFile,"%iR^t%s^t%i^t%s^t%i",si,playerAuthid[streakChamp],playerStreak[streakChamp],playerName[streakChamp],systime); fputc(streakFile,'^n'); } }
fclose(streakFile); } #endif // we have a new champion, record their stuff if(streakChamp != -1) { pointsExtraction[0][1] = players[streakChamp]; // record champion pointsExtraction[0][2] = playerStreak[streakChamp]; // record new record copy(spareName,31,playerName[streakChamp]); } // // NOW GO THROUGH THE FILE // #if defined SQL new sfWins[2], sfPoints[2], sfStreak[2];
// do one query to grab all stats we need len = formatex(mkQuery,1535,"SELECT authid,wins,points,streak,wins_tp,points_tp,streak_tp FROM `%s` WHERE serverip='%s' AND authid IN(",sqlTable,serverip); for(i=0;i<playerNum;i++) { len += formatex(mkQuery[len],1535-len,"'%s'%s",playerSafeAuthid[i],(i==playerNum-1) ? "" : ","); } len += formatex(mkQuery[len],1535-len,");"); // go through results new foundMe[33]; query = SQL_PrepareQuery(db,mkQuery); if(SQL_ExecuteAndLog(query) && SQL_NumResults(query)) { new Handle:query2;
while(SQL_MoreResults(query)) { SQL_ReadResult(query,0,authid,63); for(i=0;i<playerNum;i++) { if(foundMe[i] || !equal(authid,playerSafeAuthid[i])) continue; // remember for later iterations foundMe[i] = 1; // nothing worth reporting if(!playerWins[i] && !playerPoints[i]) continue; sfWins[0] = SQL_ReadResult(query,1); sfPoints[0] = SQL_ReadResult(query,2); sfStreak[0] = SQL_ReadResult(query,3); sfWins[1] = SQL_ReadResult(query,4); sfPoints[1] = SQL_ReadResult(query,5); sfStreak[1] = SQL_ReadResult(query,6); // if we set a new personal streak record, save it intStreak = sfStreak[si]; pointsExtraction[players[i]][4] = intStreak; // show old record if(playerStreak[i] > intStreak) intStreak = playerStreak[i]; // so we can reference this for the MOTD playerTotalPoints[i] = playerPoints[i] + sfPoints[si]; pointsExtraction[players[i]][0] = sfWins[si] + playerWins[i]; pointsExtraction[players[i]][1] = playerPoints[i]; pointsExtraction[players[i]][2] = playerTotalPoints[i]; pointsExtraction[players[i]][3] = playerStreak[i]; //pointsExtraction[players[i]][4] = intStreak; // uncomment to show new record
if(si == 0) query2 = SQL_PrepareQuery(db,"UPDATE `%s` SET wins=wins+'%i',name='%s',timestamp='%i',points=points+'%i',streak='%i' WHERE authid='%s' AND serverip='%s' LIMIT 1;",sqlTable,playerWins[i],playerSafeName[i],systime,playerPoints[i],intStreak,playerSafeAuthid[i],serverip); else query2 = SQL_PrepareQuery(db,"UPDATE `%s` SET wins_tp=wins_tp+'%i',name='%s',timestamp='%i',points_tp=points_tp+'%i',streak_tp='%i' WHERE authid='%s' AND serverip='%s' LIMIT 1;",sqlTable,playerWins[i],playerSafeName[i],systime,playerPoints[i],intStreak,playerSafeAuthid[i],serverip);
SQL_ExecuteAndLog(query2); SQL_FreeHandle(query2);
break; }
SQL_NextRow(query); } } SQL_FreeHandle(query);
len = 0; // go through again for people we didn't find for(i=0;i<playerNum;i++) { // nothing worth reporting, still refresh timestamp if(!playerWins[i] && !playerPoints[i]) { stats_refresh_timestamp(playerAuthid[i]); continue; } // already found me if(foundMe[i]) continue; // so we can reference this for the MOTD playerTotalPoints[i] = playerPoints[i]; pointsExtraction[players[i]][0] = playerWins[i]; pointsExtraction[players[i]][1] = playerPoints[i]; pointsExtraction[players[i]][2] = playerTotalPoints[i]; pointsExtraction[players[i]][3] = playerStreak[i]; pointsExtraction[players[i]][4] = 0; // show old record // haven't started yet if(len == 0) { if(si == 0) len = origLen = formatex(mkQuery,1535,"INSERT INTO `%s` (authid,name,timestamp,wins,points,streak,serverip) VALUES ",sqlTable); else len = origLen = formatex(mkQuery,1535,"INSERT INTO `%s` (authid,name,timestamp,wins_tp,points_tp,streak_tp,serverip) VALUES ",sqlTable); } len += formatex(mkQuery[len],1535-len,"('%s','%s','%i','%i','%i','%i','%s'),",playerSafeAuthid[i],playerSafeName[i],systime,playerWins[i],playerTotalPoints[i],playerStreak[i],serverip);
// cash in if we get too close if(len >= 1200) { mkQuery[len-1] = ';'; mkQuery[len] = 0;
query = SQL_PrepareQuery(db,mkQuery); SQL_ExecuteAndLog(query); SQL_FreeHandle(query); len = 0; } }
// if we have some leftover query if(len && len > origLen) { mkQuery[len-1] = ';'; mkQuery[len] = 0;
query = SQL_PrepareQuery(db,mkQuery); SQL_ExecuteAndLog(query); SQL_FreeHandle(query); } #else new file; get_pcvar_string(gg_stats_file,sfFile,63); formatex(tempFileName,64,"%s2",sfFile); // our temp file, append 2
// create file if it does not exist (thanks Min2liz) if(!file_exists(sfFile)) { file = fopen(sfFile,"wt"); fclose(file); }
rename_file(sfFile,tempFileName,1); // copy over current stat file (relative flag) if(!file_exists(tempFileName)) return; // rename failed? new sfWins[2][6], sfPoints[2][8], set[32], setNum;
new tempFile = fopen(tempFileName,"rt"), lastSetNum; file = fopen(sfFile,"wt");
// go through our old copy and rewrite entries while(tempFile && file && !feof(tempFile)) { fgets(tempFile,sfLineData,111); if(!sfLineData[0]) continue; // still have scores to add to lastSetNum = setNum; if(setNum < playerNum) { strtok(sfLineData,sfAuthid,31,sfLineData,111,'^t'); // isolate authid // see if we need to change this one for(i=0;i<playerNum;i++) { if(!set[i] && equal(playerAuthid[i],sfAuthid)) { set[i] = 1; // I didn't win anything, who cares if(!playerWins[i] && !playerPoints[i]) break;
setNum++; // important that this is below the if statement strtok(sfLineData,sfWins[0],5,sfLineData,111,'^t'); // get wins strtok(sfLineData,dummy,1,sfLineData,111,'^t'); // get name strtok(sfLineData,dummy,1,sfLineData,111,'^t'); // get timestamp strtok(sfLineData,sfPoints[0],7,sfLineData,111,'^t'); // get points strtok(sfLineData,sfStreak[0],3,sfLineData,111,'^t'); // get streak
strtok(sfLineData,sfWins[1],5,sfLineData,111,'^t'); // get teamplay wins strtok(sfLineData,sfPoints[1],7,sfStreak[1],3,'^t'); // get teamplay points and teamplay streak // if we set a new personal streak record, save it intStreak = str_to_num(sfStreak[si]); pointsExtraction[players[i]][4] = intStreak; // show old record if(playerStreak[i] > intStreak) intStreak = playerStreak[i];
playerTotalPoints[i] = playerPoints[i] + str_to_num(sfPoints[si]); // AUTHID WINS NAME TIMESTAMP POINTS STREAK TPWINS TPPOINTS TPSTREAK
if(si == 0) fprintf(file,"%s^t%i^t%s^t%i^t%i^t%i^t%i^t%i^t%i",sfAuthid,str_to_num(sfWins[0])+playerWins[i],playerName[i],systime,playerTotalPoints[i],intStreak,str_to_num(sfWins[1]),str_to_num(sfPoints[1]),str_to_num(sfStreak[1])); else fprintf(file,"%s^t%i^t%s^t%i^t%i^t%i^t%i^t%i^t%i",sfAuthid,str_to_num(sfWins[0]),playerName[i],systime,str_to_num(sfPoints[0]),str_to_num(sfStreak[0]),str_to_num(sfWins[1])+playerWins[i],playerTotalPoints[i],intStreak);
fputc(file,'^n'); // so we can reference this for the MOTD pointsExtraction[players[i]][0] = str_to_num(sfWins[si])+playerWins[i]; pointsExtraction[players[i]][1] = playerPoints[i]; pointsExtraction[players[i]][2] = playerTotalPoints[i]; pointsExtraction[players[i]][3] = playerStreak[i]; //pointsExtraction[players[i]][4] = intStreak; // uncomment to show new record // DEBUG /*if(playerTotalPoints[i] < 1) { log_amx("***** ERROR! (2) Negative points for player %i: %i | Team times: %f , %f",players[i],playerTotalPoints[i],teamTimes[players[i]][winningTeam-1],teamTimes[players[i]][losingTeam-1]); log_message("***** ERROR! (2) Negative points for player %i: %i | Team times: %f , %f",players[i],playerTotalPoints[i],teamTimes[players[i]][winningTeam-1],teamTimes[players[i]][losingTeam-1]); }*/ break; } } // nothing to replace, just copy it over (newline is already included) if(lastSetNum == setNum) fprintf(file,"%s^t%s",sfAuthid,sfLineData); // we cut authid earlier } else fprintf(file,"%s",sfLineData); // nothing to replace, just copy it over (newline is already included) }
for(i=0;i<playerNum;i++) { // never found an existing entry, make a new one if(!set[i] && (playerWins[i] || playerPoints[i])) { playerTotalPoints[i] = playerPoints[i]; // AUTHID WINS NAME TIMESTAMP POINTS STREAK TPWINS TPPOINTS TPSTREAK if(si == 0) fprintf(file,"%s^t%i^t%s^t%i^t%i^t%i^t0^t0^t0",playerAuthid[i],playerWins[i],playerName[i],systime,playerTotalPoints[i],playerStreak[i]); else fprintf(file,"%s^t0^t%s^t%i^t0^t0^t%i^t%i^t%i",playerAuthid[i],playerName[i],systime,playerWins[i],playerTotalPoints[i],playerStreak[i]);
fputc(file,'^n'); // so we can reference this for the MOTD pointsExtraction[players[i]][0] = playerWins[i]; pointsExtraction[players[i]][1] = playerPoints[i]; pointsExtraction[players[i]][2] = playerTotalPoints[i]; pointsExtraction[players[i]][3] = playerStreak[i]; pointsExtraction[players[i]][4] = 0; // show old record // DEBUG /*if(playerTotalPoints[i] < 1) { log_amx("***** ERROR! (3) Negative points for player %i: %i | Team times: %f , %f",players[i],playerTotalPoints[i],teamTimes[players[i]][winningTeam-1],teamTimes[players[i]][losingTeam-1]); log_message("***** ERROR! (3) Negative points for player %i: %i | Team times: %f , %f",players[i],playerTotalPoints[i],teamTimes[players[i]][winningTeam-1],teamTimes[players[i]][losingTeam-1]); }*/ } }
if(tempFile) fclose(tempFile); if(file) fclose(file);
// remove our copy delete_file(tempFileName); #endif new teamName[10], key_GAINED_POINTS[18];
// decide what to use based on split and such if(get_pcvar_num(gg_stats_split)) { if(teamplay) key_GAINED_POINTS = "GAINED_POINTS_TP"; else key_GAINED_POINTS = "GAINED_POINTS_REG"; } else key_GAINED_POINTS = "GAINED_POINTS"; for(i=0;i<playerNum;i++) { get_user_team(players[i],teamName,9); //if(players[i] == winner || (teamplay && _:cs_get_user_team(players[i]) == winningTeam)) if(playerWins[i]) log_message("^"%s<%i><%s><%s>^" triggered ^"Won_GunGame^"",playerName[i],get_user_userid(players[i]),playerAuthid[i],teamName);
if(stats_mode == 2 && playerPoints[i]) { log_message("^"%s<%i><%s><%s>^" triggered ^"GunGame_Points^" amount ^"%i^"",playerName[i],get_user_userid(players[i]),playerAuthid[i],teamName,playerPoints[i]); gungame_print(players[i],0,1,"%L",players[i],key_GAINED_POINTS,playerPoints[i],playerTotalPoints[i],pointsExtraction[players[i]][0]); } } }
stock stats_clear_struct(struct[statsData],clearAuthid=1) { if(clearAuthid) struct[sdAuthid][0] = 0; struct[sdWins][0] = 0; struct[sdName][0] = 0; struct[sdTimestamp] = 0; struct[sdPoints][0] = 0; struct[sdStreak][0] = 0; struct[sdWins][1] = 0; struct[sdPoints][1] = 0; struct[sdStreak][1] = 0; }
#if defined SQL // sql version] get a player's last used name and wins from save file stock stats_get_data(authid[],struct[statsData],id=0) { stats_clear_struct(struct,0); // don't clear authid, in case this is the playerStats array
if(!sqlInit || !get_pcvar_num(gg_stats_mode)) return 0;
if(playerStats[id][sdAuthid][0]) // already saved my stats { struct = playerStats[id]; return 1; }
SQL_QuoteString(db,safeName,63,authid); query = SQL_PrepareQuery(db,"SELECT wins,name,points,streak,wins_tp,points_tp,streak_tp FROM `%s` WHERE authid='%s' AND serverip='%s' LIMIT 1;",sqlTable,safeName,serverip);
if(!SQL_ExecuteAndLog(query)) { SQL_FreeHandle(query); return 0; }
if(!SQL_NumResults(query)) { // just plop my authid in here, so next call to stats_get_data won't have to query stats_clear_struct(playerStats[id]); copy(playerStats[id][sdAuthid],31,authid); SQL_FreeHandle(query); return 0; }
struct[sdWins][0] = SQL_ReadResult(query,0); SQL_ReadResult(query,1,struct[sdName],31); struct[sdPoints][0] = SQL_ReadResult(query,2); struct[sdStreak][0] = SQL_ReadResult(query,3); struct[sdWins][1] = SQL_ReadResult(query,4); struct[sdPoints][1] = SQL_ReadResult(query,5); struct[sdStreak][1] = SQL_ReadResult(query,6);
if(id) playerStats[id] = struct; // if this is a connected player, save it
SQL_FreeHandle(query); return 1; } #else // get a player's last used name and wins from save file stock stats_get_data(authid[],struct[statsData],id=0) { stats_clear_struct(struct,0); // don't clear authid, in case this is the playerStats array
if(!get_pcvar_num(gg_stats_mode)) return 0;
get_pcvar_string(gg_stats_file,sfFile,63); if(!file_exists(sfFile)) return 0;
if(playerStats[id][sdAuthid][0]) // already saved my stats { struct = playerStats[id]; return 1; } else if(statsPosition[id][0] > 0) // check top regular players { ArrayGetArray(statsArray,ArrayGetCell(statsPointers[0],statsPosition[id][0]-1),playerStats[id]); struct = playerStats[id]; return 1; } else if(statsPosition[id][1] > 0) // check top teamplay players { ArrayGetArray(statsArray,ArrayGetCell(statsPointers[1],statsPosition[id][1]-1),playerStats[id]); struct = playerStats[id]; return 1; }
// now we have to go through the file
// open 'er up, boys! new found, file = fopen(sfFile,"rt"); if(!file) return 0;
// go through it while(!feof(file)) { fgets(file,sfLineData,111); strtok(sfLineData,sfAuthid,31,dummy,1,'^t'); // isolate authid
// 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) { // just plop my authid in here, so next call to stats_get_data won't have to search through the file stats_clear_struct(playerStats[id]); copy(playerStats[id][sdAuthid],31,authid); return 0; } stats_str_to_struct(sfLineData,struct); // convert line from file to a struct if(id) playerStats[id] = struct; // if this is a connected player, save it
return 1; } #endif #if defined SQL public stats_get_top_players() { if(!ggActive || !sqlInit) return 0; lastStatsMode = get_pcvar_num(gg_stats_mode); if(!lastStatsMode) return 0; // assign stat position to players already in the game new i, authid[32], stats_ip = get_pcvar_num(gg_stats_ip); for(i=1;i<=maxPlayers;i++) { if(is_user_connected(i)) { get_gg_authid(i,authid,31,stats_ip); if(!statsPosition[i][0]) stats_get_position(i,authid,0); if(!statsPosition[i][1]) stats_get_position(i,authid,1); } }
return 1; } #else public stats_get_top_players() { if(!ggActive || !sqlInit) return 0; lastStatsMode = get_pcvar_num(gg_stats_mode); if(!lastStatsMode) return 0; // we never made the array if(!statsArray) { get_pcvar_string(gg_stats_file,sfFile,63); if(!file_exists(sfFile)) return 0;
statsArray = ArrayCreate(statsData,100); statsPointers[0] = ArrayCreate(1,100); statsPointers[1] = ArrayCreate(1,100);
new file = fopen(sfFile,"rt"); if(file) { new entryNum;
while(!feof(file)) { fgets(file,sfLineData,111); if(!sfLineData[0]) continue; stats_str_to_struct(sfLineData,sfStatsStruct);
// put all of our stats entries, with all of the info and stuff, into our big stats array ArrayPushArray(statsArray,sfStatsStruct);
// and then put just their indexes into our "pointer" cell arrays if(sfStatsStruct[sdWins][0] || sfStatsStruct[sdPoints][0]) { ArrayPushCell(statsPointers[0],entryNum); statsSize[0]++; } if(sfStatsStruct[sdWins][1] || sfStatsStruct[sdPoints][1]) { ArrayPushCell(statsPointers[1],entryNum); statsSize[1]++; } entryNum++; } fclose(file);
ArraySort(statsPointers[0],"stats_pointer_sort_reg"); ArraySort(statsPointers[1],"stats_pointer_sort_tp");
if(statsSize[0] > MAX_STATS_RANK) statsSize[0] = MAX_STATS_RANK; if(statsSize[1] > MAX_STATS_RANK) statsSize[1] = MAX_STATS_RANK; } } // if we were able to get anything put together if(statsSize[0] || statsSize[1]) { // assign stat position to players already in the game new i, authid[32], stats_ip = get_pcvar_num(gg_stats_ip); for(i=1;i<=maxPlayers;i++) { if(is_user_connected(i)) { get_gg_authid(i,authid,31,stats_ip); if(!statsPosition[i][0]) stats_get_position(i,authid,0); // these only work if statsSize[si] > 0 if(!statsPosition[i][1]) stats_get_position(i,authid,1); } } }
return 1; }
// seems to be slightly faster without passing in extra data, and this is how we used to do it, so we'll continue to use two functions to sort public stats_pointer_sort_reg(Array:array,item1,item2) { static score[2]; if(lastStatsMode == 1) // sort by wins { ArrayGetArray(statsArray,ArrayGetCell(array,item1),sfStatsStruct); score[0] = sfStatsStruct[sdWins][0];
ArrayGetArray(statsArray,ArrayGetCell(array,item2),sfStatsStruct); score[1] = sfStatsStruct[sdWins][0]; } else // sort by points { ArrayGetArray(statsArray,ArrayGetCell(array,item1),sfStatsStruct); score[0] = sfStatsStruct[sdPoints][0];
ArrayGetArray(statsArray,ArrayGetCell(array,item2),sfStatsStruct); score[1] = sfStatsStruct[sdPoints][0]; }
return score[1] - score[0]; }
// seems to be slightly faster without passing in extra data, and this is how we used to do it, so we'll continue to use two functions to sort public stats_pointer_sort_tp(Array:array,item1,item2) { static score[2]; if(lastStatsMode == 1) // sort by wins { ArrayGetArray(statsArray,ArrayGetCell(array,item1),sfStatsStruct); score[0] = sfStatsStruct[sdWins][1];
ArrayGetArray(statsArray,ArrayGetCell(array,item2),sfStatsStruct); score[1] = sfStatsStruct[sdWins][1]; } else // sort by points { ArrayGetArray(statsArray,ArrayGetCell(array,item1),sfStatsStruct); score[0] = sfStatsStruct[sdPoints][1];
ArrayGetArray(statsArray,ArrayGetCell(array,item2),sfStatsStruct); score[1] = sfStatsStruct[sdPoints][1]; }
return score[1] - score[0]; } #endif
// gather up our players /*public stats_get_top_players() { if(!ggActive) return 0;
glStatsMode = get_pcvar_num(gg_stats_mode); if(!glStatsMode) return 0; get_pcvar_string(gg_stats_file,sfFile,63); if(!file_exists(sfFile)) return 0;
new buildMe[2], stats_split = get_pcvar_num(gg_stats_split);
// figure out if we need to build any of the arrays still if(!statsArray[0]) { statsArray[0] = ArrayCreate(statsData,100); statsSize[0] = 0; buildMe[0] = 1; } if(!statsArray[1] && stats_split) { statsArray[1] = ArrayCreate(statsData,100); statsSize[1] = 0; buildMe[1] = 1; }
// if we do have an array or two to build if(buildMe[0] || buildMe[1]) { // storage format: // AUTHID WINS LAST_USED_NAME TIMESTAMP POINTS STREAK TPWINS TPPOINTS TPSTREAK
new file = fopen(sfFile,"rt"); if(file) { while(!feof(file)) { fgets(file,sfLineData,111); if(!sfLineData[0]) continue; stats_str_to_struct(sfLineData,sfStatsStruct);
// if we are working on this array, and we have some wins or points for it if(buildMe[0] && (sfStatsStruct[sdWins][0] || sfStatsStruct[sdPoints][0])) { ArrayPushArray(statsArray[0],sfStatsStruct); statsSize[0]++; } if(buildMe[1] && (sfStatsStruct[sdWins][1] || sfStatsStruct[sdPoints][1])) { ArrayPushArray(statsArray[1],sfStatsStruct); statsSize[1]++; } } fclose(file); if(buildMe[0] && statsSize[0] > 1) // if we were working on this array and we have something to sort { ArraySort(statsArray[0],"stats_custom_compare_regular"); if(statsSize[0] > 1000) statsSize[0] = 1000; // arbitrarily limit because we have to look through this every time someone connects } if(buildMe[1] && statsSize[1] > 1) { ArraySort(statsArray[1],"stats_custom_compare_teamplay"); if(statsSize[1] > 1000) statsSize[1] = 1000; } } // clear any saved stats positions out of the tempsaves, so no one rejoins with the wrong position for(new i=0;i<TEMP_SAVES;i++) { tempSave[i][34] = 0; tempSave[i][35] = 0; } }
// if we were able to get anything put together if(statsSize[0] || statsSize[1]) { // assign stat position to players already in the game new i, authid[32], stats_ip = get_pcvar_num(gg_stats_ip); for(i=1;i<=maxPlayers;i++) { if(is_user_connected(i)) { get_gg_authid(i,authid,31,stats_ip); if(!statsPosition[i][0]) stats_get_position(i,authid,0); // these will only do anything if we created the respective array above if(!statsPosition[i][1]) stats_get_position(i,authid,1); } } }
lastStatsMode = glStatsMode; statsLastSplit = stats_split;
return 1; }*/
// our custom sorting functions /*public stats_custom_compare_regular(Array:array,item1,item2) { static score[2];
ArrayGetArray(array,item1,sfStatsStruct); if(glStatsMode == 1) score[0] = sfStatsStruct[sdWins][0]; // sort by wins else score[0] = sfStatsStruct[sdPoints][0]; // sort by wins ArrayGetArray(array,item2,sfStatsStruct); if(glStatsMode == 1) score[1] = sfStatsStruct[sdWins][0]; // sort by wins else score[1] = sfStatsStruct[sdPoints][0]; // sort by wins
return score[1] - score[0]; }*/
/*public stats_custom_compare_teamplay(Array:array,item1,item2) { static score[2];
ArrayGetArray(array,item1,sfStatsStruct); if(glStatsMode == 1) score[0] = sfStatsStruct[sdWins][1]; // sort by wins else score[0] = sfStatsStruct[sdPoints][1]; // sort by wins ArrayGetArray(array,item2,sfStatsStruct); if(glStatsMode == 1) score[1] = sfStatsStruct[sdWins][1]; // sort by wins else score[1] = sfStatsStruct[sdPoints][1]; // sort by wins
return score[1] - score[0]; }*/
#if defined SQL // get a player's overall position stats_get_position(id,authid[],si) { if(!sqlInit) return 0; // can't get position yet
statsPosition[id][si] = -1; // mark that we've at least attempted to find it new stats_mode = get_pcvar_num(gg_stats_mode), myPoints; // first, we need to get their current amount of wins/points. this allows us to make sure that they are really in the database // (could cause problems with a sub-query returning 0 instead of NULL) and that they actually have wins/points for the current // stats mode (could cause problems when they are in the database but you are looking at their stats index for which they have // no points). then, we might as well use the result for our ranking query instead of using a sub-query. // if we don't have the cached stats, we will have to do a query to get the wins/points. since we would be doing a query for it // anyway, we might as well just get all of the stats at once. stats_get_data(authid,playerStats[id],id); // stats_get_data should automatically manage cache if(stats_mode == 2) myPoints = playerStats[id][sdPoints][si]; else myPoints = playerStats[id][sdWins][si];
if(myPoints <= 0 && (stats_mode != 2 || playerStats[id][sdWins][si] <= 0)) return -1; new winsColumn[8], pointsColumn[10];
if(si == 0) { winsColumn = "wins"; pointsColumn = "points"; } else { winsColumn = "wins_tp"; pointsColumn = "points_tp"; }
// select the number of people who have a score higher than I do, plus one. query from Giuseppe Maxia if(stats_mode == 2) { query = SQL_PrepareQuery(db,"SELECT COUNT(*)+1 AS ranking FROM `%s` WHERE %s > %i AND serverip='%s' AND (%s > 0 OR %s > 0);", sqlTable,pointsColumn,myPoints,serverip,winsColumn,pointsColumn); } else { query = SQL_PrepareQuery(db,"SELECT COUNT(*)+1 AS ranking FROM `%s` WHERE %s > %i AND serverip='%s';", sqlTable,winsColumn,myPoints,serverip); } if(SQL_ExecuteAndLog(query)) { new result = SQL_ReadResult(query,0); SQL_FreeHandle(query);
statsPosition[id][si] = result; return result; } SQL_FreeHandle(query); return -1; } #else // get a player's overall position stats_get_position(id,authid[],si) { if(statsArray && statsPointers[si] && statsSize[si]) { //log_amx("assigning stats position to %i for array %i",id,index);
statsPosition[id][si] = -1; // mark that we've at least attempted to find it
for(new i=0;i<statsSize[si];i++) { ArrayGetArray(statsArray,ArrayGetCell(statsPointers[si],i),sfStatsStruct); if(equal(authid,sfStatsStruct[sdAuthid])) { statsPosition[id][si] = i+1; return i+1; } }
return -1; } return 0; } #endif
#if defined SQL // prune old entries stock stats_prune(max_time=-1) { if(!sqlInit) return 0;
if(max_time == -1) max_time = get_pcvar_num(gg_stats_prune); // -1 = use value from cvar if(max_time == 0) return 0; // 0 = no pruning
// prune old entries formatex(mkQuery,255,"DELETE FROM `%s` WHERE timestamp < %i AND serverip='%s';",sqlTable,get_systime() - max_time,serverip); SQL_ThreadQuery(tuple,"sql_qhandler_prune",mkQuery); // fix up all of our tables formatex(mkQuery,255,"REPAIR TABLE `%s`;",sqlTable); SQL_ThreadQuery(tuple,"sql_qhandler_dummy",mkQuery); formatex(mkQuery,255,"OPTIMIZE TABLE `%s`;",sqlTable); SQL_ThreadQuery(tuple,"sql_qhandler_dummy",mkQuery); formatex(mkQuery,255,"REPAIR TABLE `%s`;",sqlStreakTable); SQL_ThreadQuery(tuple,"sql_qhandler_dummy",mkQuery); formatex(mkQuery,255,"OPTIMIZE TABLE `%s`;",sqlStreakTable); SQL_ThreadQuery(tuple,"sql_qhandler_dummy",mkQuery);
return -1; } #else // prune old entries stock stats_prune(max_time=-1) { get_pcvar_string(gg_stats_file,sfFile,63); if(!file_exists(sfFile)) return 0; if(max_time == -1) max_time = get_pcvar_num(gg_stats_prune); // -1 = use value from cvar if(max_time == 0) return 0; // 0 = no pruning
new tempFileName[33]; formatex(tempFileName,32,"%s2",sfFile); // our temp file, append 2
// copy over current stat file rename_file(sfFile,tempFileName,1); // relative
// 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 systime = get_systime(), original[112], removed; while(tempFile && file && !feof(tempFile)) { fgets(tempFile,sfLineData,111); if(!sfLineData[0]) continue;
// save original original = sfLineData;
// break off authid strtok(sfLineData,dummy,1,sfLineData,111,'^t');
// break off wins strtok(sfLineData,dummy,1,sfLineData,111,'^t');
// break off name, and thus get timestamp strtok(sfLineData,dummy,1,sfTimestamp,11,'^t'); copyc(sfTimestamp,11,sfTimestamp,'^t'); // cut off points
// not too old, write it to our new file if(systime - 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; } #endif
//********************************************************************** // SQL FUNCTIONS //**********************************************************************
#if defined SQL // opens the database stock sql_init(creation_queries=1) { new host[32], user[32], pass[32], dbname[32]; get_pcvar_string(gg_sql_host,host,31); get_pcvar_string(gg_sql_user,user,31); get_pcvar_string(gg_sql_pass,pass,31); get_pcvar_string(gg_sql_db,dbname,31);
new sqlErrorCode, sqlError[1024]; // free old stuff if reconnecting if(tuple != Empty_Handle) SQL_FreeHandleAndClear(tuple); if(db != Empty_Handle) SQL_FreeHandleAndClear(db);
tuple = SQL_MakeDbTuple(host,user,pass,dbname); if(tuple == Empty_Handle) { log_amx("Could not create database tuple. Error #%i: %s",sqlErrorCode,sqlError); return 0; } db = SQL_Connect(tuple,sqlErrorCode,sqlError,1023);
if(db == Empty_Handle) { log_amx("Could not connect to database. Error #%i: %s",sqlErrorCode,sqlError); return 0; } if(creation_queries) { // set up the main table, unfortunately we have to split it up to avoid "input line too long" compile errors get_pcvar_string(gg_sql_table,sqlTable,31); new super_long_query[716], len = formatex(super_long_query,715,"CREATE TABLE IF NOT EXISTS `%s`(`authid` VARCHAR(31) NOT NULL,`wins` SMALLINT(6) default '0',`name` VARCHAR(31) NOT NULL,`timestamp` INT(10) UNSIGNED default '0',`points` MEDIUMINT(9) default '0',`streak` SMALLINT(6) default '0',`wins_tp` SMALLINT(6) default '0',`points_tp` MEDIUMINT(9) default '0',",sqlTable); formatex(super_long_query[len],715-len,"`streak_tp` SMALLINT(6) default '0',`serverip` VARCHAR(21) NOT NULL,PRIMARY KEY(`authid`,`serverip`),INDEX(`wins`),INDEX(`points`),INDEX(`wins_tp`), INDEX(`points_tp`));");
query = SQL_PrepareQuery(db,super_long_query); if(!SQL_ExecuteAndLog(query)) { SQL_FreeHandle(query); return 0; } // set up the streaks table get_pcvar_string(gg_sql_streak_table,sqlStreakTable,31); query = SQL_PrepareQuery(db,"CREATE TABLE IF NOT EXISTS `%s`(`type` ENUM('0C','0R','1C','1R') default NULL,`authid` VARCHAR(31) NOT NULL,`streak` SMALLINT(6) default '0',`name` VARCHAR(31) NOT NULL,`timestamp` INT(10) UNSIGNED default '0',`serverip` VARCHAR(21) NOT NULL,INDEX(`authid`,`serverip`),INDEX(`type`));",sqlStreakTable); if(!SQL_ExecuteAndLog(query)) { SQL_FreeHandle(query); return 0; } // set up the players table get_pcvar_string(gg_sql_winmotd_table,sqlPlayersTable,31); len = formatex(super_long_query,715,"CREATE TABLE IF NOT EXISTS `%s`(`id` tinyint(4) NOT NULL default '0',`authid` varchar(31) NOT NULL,`name` varchar(31) NOT NULL,`team` tinyint(4) default '0',`level` tinyint(4) default '0',`weapon` varchar(23) NOT NULL,`flags` tinyint(4) default '0',`wins` smallint(6) default '0',`points` mediumint(9) default '0',`new_points` mediumint(9) default '0',`record_streak` smallint(6) default '0',",sqlPlayersTable); formatex(super_long_query[len],715-len,"`current_streak` smallint(6) default '0',`stats_position` smallint(6) unsigned default '0',`teamtime_winning` smallint(6) unsigned default '0',`teamtime_losing` smallint(6) unsigned default '0',`timestamp` int(10) unsigned default '0',`serverip` varchar(21) NOT NULL, PRIMARY KEY(`id`));");
query = SQL_PrepareQuery(db,super_long_query); if(!SQL_ExecuteAndLog(query)) { SQL_FreeHandle(query); return 0; } SQL_FreeHandle(query); }
sqlInit = 1; return 1; }
// closes the database public sql_uninit() { if(sqlInit) { if(db != Empty_Handle) SQL_FreeHandleAndClear(db); if(tuple != Empty_Handle) SQL_FreeHandleAndClear(tuple); } }
// frees a handle and resets its variable to empty SQL_FreeHandleAndClear(&Handle:arg) { SQL_FreeHandle(arg); arg = Empty_Handle; }
// execute a query and log any errors that come up stock SQL_ExecuteAndLog(&Handle:queryHandle,const queryStr[]="") { static preventLoopback = 0;
if(!SQL_Execute(queryHandle)) { static error[256]; new errnum = SQL_QueryError(queryHandle,error,255);
if(queryStr[0]) log_amx("Could not execute query [%s] -- err #%i [%s]",queryStr,errnum,error); else { SQL_GetQueryString(queryHandle,mkQuery,255); log_amx("Could not execute query [%s] -- err #%i [%s]",mkQuery,errnum,error); } // fix thanks to 2inspyr if(errnum == 2006 && !preventLoopback) // MySQL server has gone away { log_amx("Attempting to reconnect to server");
if(sql_init(0)) // no creation queries { log_amx("Successfully reconnected to server, executing query again"); SQL_GetQueryString(queryHandle,mkQuery,1535); new Handle:newQuery = SQL_PrepareQuery(db,mkQuery); preventLoopback = 1; SQL_ExecuteAndLog(newQuery); // transfer handles SQL_FreeHandle(queryHandle); queryHandle = newQuery;
preventLoopback = 0; return 1; //return SQL_Execute(queryHandle); } else { log_amx("Could not reconnect to server"); preventLoopback = 0; return 0; } }
preventLoopback = 0; return 0; }
preventLoopback = 0; return 1; }
public sql_qhandler_prune(failstate,Handle:query,error[],errnum,data[],size,Float:queuetime) { if(error[0]) { SQL_GetQueryString(query,mkQuery,255); log_amx("Could not execute query [%s] -- err #%i [%s]",mkQuery,errnum,error); } else log_amx("%L",LANG_SERVER,"PRUNING",sqlTable,SQL_NumRows(query)); } public sql_qhandler_dummy(failstate,Handle:query,error[],errnum,data[],size,Float:queuetime) { if(error[0]) { SQL_GetQueryString(query,mkQuery,255); log_amx("Could not execute query [%s] -- err #%i [%s]",mkQuery,errnum,error); } }
#endif
//********************************************************************** // WHATEV //**********************************************************************
#if !defined SQL // monitor stats mode and resort if it changed public recheck_stats_sorting() { new stats_mode = get_pcvar_num(gg_stats_mode);
if(stats_mode && stats_mode != lastStatsMode && lastStatsMode != -909) // set to -909 on init { lastStatsMode = stats_mode;
// we are judging by a different criteria, so we need to resort if(statsPointers[0] && statsSize[0]) ArraySort(statsPointers[0],"stats_pointer_sort_reg"); if(statsPointers[1] && statsSize[1]) ArraySort(statsPointers[1],"stats_pointer_sort_tp"); // clear any saved stats positions out of the tempsaves, so no one rejoins with the wrong position for(new i=0;i<TEMP_SAVES;i++) { tempSave[i][svStatsPosition][0] = 0; tempSave[i][svStatsPosition][1] = 0; }
// also make sure that everyone will get assigned new positions for(new i=1;i<=maxPlayers;i++) { statsPosition[i][0] = 0; statsPosition[i][1] = 0; }
stats_get_top_players(); }
lastStatsMode = stats_mode; } #endif
// 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; if(is_user_connected(id)) player_suicided(id); }
// remove those annoying pesky pistols, if they haven't been already strip_starting_pistols(id) { if(!is_user_alive(id)) return;
switch(cs_get_user_team(id)) { case CS_TEAM_T: { if(!equal(lvlWeapon[id],"glock18") && user_has_weapon(id,CSW_GLOCK18)) ham_strip_weapon(id,WEAPON_GLOCK18); } case CS_TEAM_CT: { if(!equal(lvlWeapon[id],"usp") && user_has_weapon(id,CSW_USP)) ham_strip_weapon(id,"weapon_usp"); } } }
// weapon display stock status_display(id,status=1) { new sdisplay = get_pcvar_num(gg_status_display);
// display disabled if(!sdisplay) return;
// dead if(id && !is_user_alive(id)) 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 warmup if(!status || warmup > 0) { // don't send to bots if(dest == MSG_BROADCAST || !is_user_bot(id)) { 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; copy(sprite,31,weaponName[ldrLevel-1]); } else { // get your weapon if(level[id] <= 0) return; copy(sprite,31,lvlWeapon[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],id); formatex(sprite,31,"number_%i",goal-score[id]); } else if(sdisplay == STATUS_KILLSDONE) { formatex(sprite,31,"number_%i",score[id]); }
// don't send to bots if(!id || !is_user_bot(id)) { message_begin(dest,gmsgScenario,_,id); write_byte(1); write_string(sprite); write_byte(150); message_end(); } }
// hide someone's money display public hide_money(id) { // hide money emessage_begin(MSG_ONE,gmsgHideWeapon,_,id); ewrite_byte(1<<5); emessage_end();
// hide crosshair that appears from hiding money emessage_begin(MSG_ONE,gmsgCrosshair,_,id); ewrite_byte(0); emessage_end(); }
//********************************************************************** // SUPPORT FUNCTIONS //**********************************************************************
// gets a players info, intended for other plugins to callfunc public get_player_info(id,&rf_level,&rf_score,rf_lvlWeapon[],len,&rf_spawnProtected,rf_statsPosition[2]) { rf_level = level[id]; rf_score = score[id]; copy(rf_lvlWeapon,len,lvlWeapon[id]); rf_spawnProtected = spawnProtected[id]; rf_statsPosition = statsPosition[id]; return 1; }
// analyzes the weapon order and saves it into our variables public setup_weapon_order() { new weaponOrder[(MAX_WEAPONS*16)+1], temp[27]; get_pcvar_string(gg_weapon_order,weaponOrder,MAX_WEAPONS*16); new Float:killsperlvl = get_pcvar_float(gg_kills_per_lvl), i, done, colon, goal[6]; // cut them apart for(i=0;i<MAX_WEAPONS;i++) { // out of stuff if(strlen(weaponOrder) <= 1) { i--; // for our count break; }
// we still have a comma, go up to it if(contain_char(weaponOrder,',') != -1) { strtok(weaponOrder,temp,26,weaponOrder,MAX_WEAPONS*16,','); trim(temp); strtolower(temp); }
// otherwise, finish up else { copy(temp,26,weaponOrder); trim(temp); strtolower(temp); done = 1; // flag for end of loop } colon = contain_char(temp,':'); // no custom requirement, easy if(colon == -1) { copy(weaponName[i],23,temp); if(equal(temp,KNIFE) || equal(temp,HEGRENADE)) weaponGoal[i] = (killsperlvl > 1.0) ? 1.0 : killsperlvl; else weaponGoal[i] = killsperlvl; } else { copyc(weaponName[i],23,temp,':'); copy(goal,5,temp[colon+1]); weaponGoal[i] = floatstr(goal); }
if(done) break; } // we break to end our loop, so "i" will be where we left it. but it's 0-based. weaponNum = i+1; }
// gets the goal for a level, taking into account default and custom values stock get_level_goal(level,id=0) { if(level < 1) return 1;
// no teamplay, return preset goal if(!is_user_connected(id) || !get_pcvar_num(gg_teamplay)) { if(is_user_bot(id)) return floatround(weaponGoal[level-1]*get_pcvar_float(gg_kills_botmod),floatround_ceil); return floatround(weaponGoal[level-1],floatround_ceil); }
// one of this for every player on team new Float:result = weaponGoal[level-1] * float(team_player_count(cs_get_user_team(id))); // modifiers for nade and knife levels if(equal(weaponName[level-1],HEGRENADE)) result *= get_pcvar_float(gg_teamplay_nade_mod); else if(equal(weaponName[level-1],KNIFE)) result *= get_pcvar_float(gg_teamplay_knife_mod); if(result <= 0.0) result = 1.0; return floatround(result,floatround_ceil); }
// gets the level a player should use for his level stock get_level_weapon(theLevel,var[],varLen) { if(warmup > 0 && warmupWeapon[0]) copy(var,varLen,warmupWeapon); else if(theLevel > 0) copy(var,varLen,weaponName[theLevel-1]); else var[0] = 0; }
// easy function to precache sound via cvar stock precache_sound_by_cvar(pcvar) { new value[64]; get_pcvar_string(pcvar,value,63); precache_sound_special(value); }
// precache sounds with a little bit of magic stock precache_sound_special(sound[]) { if(!sound[0]) return; if(containi(sound,".mp3") != -1) precache_generic(sound); else { // stop at ( character to allow precaching sounds that use speak's special functions, eg sound/ambience/xtal_down1(e70) new value[64], len = copyc(value,63,sound,'(');
// make sure we have a suffix for precaching if(containi(value,".wav") == -1) formatex(value[len],63-len,".wav");
// precache_sound doesn't take the "sound/" prefix if(equali(value,"sound/",6)) precache_sound(value[6]); else precache_sound(value); } }
// gets a player's "authid", or whatever token we want to identify them with. // if you already know the value of gg_stats_ip, you can pass it in and save a cvar check. stock get_gg_authid(id,ret[],len,stats_ip=-777) { new mode = stats_ip; if(mode == -777) mode = get_pcvar_num(gg_stats_ip);
switch(mode) { case 0: return get_user_authid(id,ret,len); // 0 = by authid case -1, 2: return get_user_name(id,ret,len); // 2 = by name } return get_user_ip(id,ret,len); // 1 = by ip }
// figure out which gungame.cfg (or gungame_teamplay.cfg) file to use stock get_gg_config_file(teamplay=0,filename[],len) { formatex(filename,len,"%s/gungame%s.cfg",cfgDir,(teamplay) ? "_teamplay" : "");
if(!file_exists(filename)) { formatex(filename,len,"gungame%s.cfg",(teamplay) ? "_teamplay" : ""); if(!file_exists(filename)) filename[0] = 0; } }
// executes what's inside of the config file stock exec_gg_config_file(teamplay=0,allowToggling=0) { new oldActive = ggActive, oldTeamplay = get_pcvar_num(gg_teamplay);
new cfgFile[64]; get_gg_config_file(teamplay,cfgFile,63); if(cfgFile[0] && file_exists(cfgFile)) { server_cmd("exec ^"%s^"",cfgFile); server_exec(); } // remember old values of gg_enabled and gg_teamplay if toggling is not allowed. // this is like we just turned teamplay on via command and we want to make sure // the configs get run appropriately, but obviously teamplay should still be on afterwards. if(!allowToggling) { set_pcvar_num(gg_enabled,oldActive); set_pcvar_num(gg_teamplay,oldTeamplay); } // reselect random weapon order new lastOIstr[6], lastOI;
get_localinfo("gg_last_oi",lastOIstr,5); lastOI = str_to_num(lastOIstr);
// decrement it 1 b/c we probably already did do_rOrder // and don't want to end up skipping orders if(lastOI > 0) { num_to_str(lastOI-1,lastOIstr,5); set_localinfo("gg_last_oi",lastOIstr); } do_rOrder(1); // thanks for pointing this out Tomek Kalkowski // in case cvars changed. thanks BbIX! setup_weapon_order(); }
// figure out which gungame_mapcycle file to use stock 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)) { copy(filename,len,testFile); return 1; }
// cstrike/addons/amxmodx/configs/gungame_mapcycle.txt formatex(testFile,63,"%s/gungame_mapcycle.txt",cfgDir); if(file_exists(testFile)) { copy(filename,len,testFile); return 1; }
// cstrike/gungame_mapcycle.cfg testFile = "gungame_mapcycle.cfg"; if(file_exists(testFile)) { copy(filename,len,testFile); return 1; }
// cstrike/gungame_mapcycle.txt testFile = "gungame_mapcycle.txt"; if(file_exists(testFile)) { copy(filename,len,testFile); return 1; }
return 0; }
// another easy function to play sound via cvar stock play_sound_by_cvar(id,pcvar) { static value[64]; get_pcvar_string(pcvar,value,63);
if(!value[0]) return;
if(containi(value,".mp3") != -1) client_cmd(id,"mp3 play ^"%s^"",value); else client_cmd(id,"spk ^"%s^"",value); }
// a taskable play_sound_by_cvar public play_sound_by_cvar_task(params[2]) { play_sound_by_cvar(params[0],params[1]); }
// this functions take a filepath, but manages speak/mp3 play stock play_sound(id,value[]) { if(!value[0]) return;
if(containi(value,".mp3") != -1) client_cmd(id,"mp3 play ^"%s^"",value); else { if(equali(value,"sound/",6)) client_cmd(id,"spk ^"%s^"",value[6]); else client_cmd(id,"spk ^"%s^"",value); } }
// find the highest level player and his level stock get_leader(&retLevel=0,&retNumLeaders=0,&retRunnerUp=0) { new player, leader, numLeaders, runnerUp;
// locate highest player for(player=1;player<=maxPlayers;player++) { if(!is_user_connected(player)) continue; if(leader == 0 || level[player] > level[leader]) { // about to dethrown leader, monitor runnerup if(leader && (runnerUp == 0 || level[leader] > level[runnerUp])) runnerUp = leader;
leader = player; numLeaders = 1; // reset tied count } else if(level[player] == level[leader]) numLeaders++; else { // monitor runnerup if(runnerUp == 0 || level[player] > level[runnerUp]) runnerUp = player; } }
retLevel = level[leader]; retNumLeaders = numLeaders; retRunnerUp = runnerUp;
return leader; }
// gets the number of players on a particular level stock num_players_on_level(checkLvl) { new player, result; for(player=1;player<=maxPlayers;player++) { if(is_user_connected(player) && level[player] == checkLvl) result++; } return result; }
// a butchered version of teame06's CS Color Chat Function. // actually it's now almost completely different, but that's // where I started from. gungame_print(id,custom,tag,msg[],any:...) { new messages = get_pcvar_num(gg_messages); if(!messages || (messages & MSGS_HIDETEXT)) return 0;
new changeCount, num, i, j, argnum = numargs(), player, colored_messages = !(messages & MSGS_NOCOLOR); static newMsg[191], message[191], changed[8], players[32];
if(id) { players[0] = id; num = 1; } else get_players(players,num);
for(i=0;i<num;i++) { player = players[i]; changeCount = 0; if(!is_user_connected(player)) continue;
// we have to change LANG_PLAYER into // a player-specific argument, because // ML doesn't work well with SayText for(j=4;j<argnum;j++) { if(getarg(j) == LANG_PLAYER_C) { setarg(j,0,player); changed[changeCount++] = j; } }
// do user formatting vformat(newMsg,190,msg,5);
// 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(tag) { if(colored_messages) formatex(message,190,"^x04[%L]^x01 %s",player,"GUNGAME",newMsg); else formatex(message,190,"^x01[%L] %s",player,"GUNGAME",newMsg); } else formatex(message,190,"^x01%s",newMsg);
message_begin(MSG_ONE,gmsgSayText,_,player); write_byte((custom > 0) ? custom : player); write_string(message); message_end(); } return 1; }
// show a HUD message to a user gungame_hudmessage(id,Float:holdTime,msg[],any:...) { new messages = get_pcvar_num(gg_messages); if(!messages || (messages & MSGS_HIDEHUD)) return 0;
// 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); return ShowSyncHudMsg(id,hudSyncReqKills,newMsg); }
// start a map vote stock start_mapvote() { new dmmName[24], plugin; // Galileo - galileo.amxx if(galileoID != -1) { log_amx("Starting a map vote from Galileo"); server_cmd("gal_startvote -nochange"); }
// AMXX Nextmap Chooser - mapchooser.amxx else if((plugin = is_plugin_loaded("Nextmap Chooser")) != -1) { log_amx("Starting a map vote from Nextmap Chooser");
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_i(get_func_id("voteNextmap",plugin),plugin) == 1) callfunc_end();
// set maxrounds back set_cvar_num("mp_winlimit",oldWinLimit); set_cvar_num("mp_maxrounds",oldMaxRounds); }
// Deagles' Map Management 2.30b - deagsmapmanage230b.amxx else if((plugin = is_plugin_loaded("DeagsMapManage")) != -1) { dmmName = "DeagsMapManage"; }
// Deagles' Map Management 2.40 - deagsmapmanager.amxx else if((plugin = is_plugin_loaded("DeagsMapManager")) != -1) { dmmName = "DeagsMapManager"; }
// Mapchooser4 - mapchooser4.amxx else if((plugin = is_plugin_loaded("Nextmap Chooser 4")) != -1) { log_amx("Starting a map vote from Nextmap Chooser 4"); 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_i(get_func_id("buyFinished",plugin),plugin) == 1) callfunc_end();
// call the vote if(callfunc_begin_i(get_func_id("voteNextmap",plugin),plugin) == 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 any compatible plugins: could not start a vote!");
// do DMM stuff if(dmmName[0]) { log_amx("Starting a map vote from %s",dmmName);
// 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_i(get_func_id("startthevote",plugin),plugin) == 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_task(20.1,"dmm_stop_mapchange"); } }
// stop DMM from changing maps after the vote has been tallied public dmm_stop_mapchange() { remove_task(333333,1); // outside }
// set amx_nextmap to the next map stock 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 0; }
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 new len = strlen(lineData) - 2;
// stop at a comment for(i=0;i<len;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]) copy(firstMap,31,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); } return 1; }
// go to amx_nextmap public goto_nextmap() { 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; } } if(galileoID != -1) { if(callfunc_begin_i(get_func_id("map_change",galileoID),galileoID) == 1) { callfunc_end(); return; } }
// otherwise, go to amx_nextmap new nextMap[32]; get_cvar_string("amx_nextmap",nextMap,31);
server_cmd("changelevel %s",nextMap); }
// find a player's weapon entity stock get_weapon_ent(id,wpnid=0,wpnName[]="") { // who knows what wpnName will be static newName[24];
// need to find the name if(wpnid) get_weaponname(wpnid,newName,23);
// go with what we were told else copy(newName,23,wpnName);
// prefix it if we need to if(!equal(newName,"weapon_",7)) format(newName,23,"weapon_%s",newName);
return fm_find_ent_by_owner(maxPlayers,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; }
// works like contain, but looks only for a specific character stock contain_char(str[],chara) { new i; while(str[i] != 0) { if(str[i] == chara) return i; i++; } return -1; }
// cuts a snippet out of a string stock remove_snippet(string[],strLen,start,end) { new i, newpos; for(i=start;i<strLen;i++) { if(!string[i]) break; newpos = i + end - start + 1;
if(newpos >= strLen) string[i] = 0; else string[i] = string[newpos]; } 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, just a shortcut to the weaponSlots table basically stock get_weapon_category(id=0,name[]="") { if(name[0]) { if(equal(name,"weapon_",7)) id = get_weaponid(name); else { static newName[24]; formatex(newName,23,"weapon_%s",name); id = get_weaponid(newName); } }
if(id < 1 || id > 30) return -1; return weaponSlots[id]; }
// if a player is allowed to score (at least 1 rival player) stock can_score(id) { if(!is_user_connected(id)) return 0;
new penalty = get_pcvar_num(gg_tk_penalty); for(new player=1;player<=maxPlayers;player++) { // this player is on a real team, and he's on the opposite team, or we are playing FFA if( player != id && is_user_connected(player) && on_valid_team(player) && (penalty < 0 || cs_get_user_team(id) != cs_get_user_team(player)) ) return 1; }
return 0; }
// returns 1 if there are only bots in the server, 0 if not stock only_bots() { new player; for(player=1;player<=maxPlayers;player++) { if(is_user_connected(player) && !is_user_bot(player)) return 0; }
// didn't find any humans return 1; }
// gives a player a weapon efficiently stock ham_give_weapon(id,const weapon[]) { if(!equal(weapon,"weapon_",7)) return 0;
new wEnt = engfunc(EngFunc_CreateNamedEntity,engfunc(EngFunc_AllocString,weapon)); if(!pev_valid(wEnt)) return 0;
set_pev(wEnt,pev_spawnflags,SF_NORESPAWN); dllfunc(DLLFunc_Spawn,wEnt); if(!ExecuteHamB(Ham_AddPlayerItem,id,wEnt)) { if(pev_valid(wEnt)) set_pev(wEnt,pev_flags,pev(wEnt,pev_flags) | FL_KILLME); return 0; }
ExecuteHamB(Ham_Item_AttachToPlayer,wEnt,id) return 1; } // takes a weapon from a player efficiently stock ham_strip_weapon(id,const weapon[]) { if(!equal(weapon,"weapon_",7)) return 0;
new wId = get_weaponid(weapon); if(!wId) return 0;
new wEnt; while((wEnt = engfunc(EngFunc_FindEntityByString,wEnt,"classname",weapon)) && pev(wEnt,pev_owner) != id) {} if(!wEnt) return 0;
if(get_user_weapon(id) == wId) ExecuteHamB(Ham_Weapon_RetireWeapon,wEnt);
if(!ExecuteHamB(Ham_RemovePlayerItem,id,wEnt)) return 0; ExecuteHamB(Ham_Item_Kill,wEnt);
set_pev(id,pev_weapons,pev(id,pev_weapons) & ~(1<<wId)); if(wId == CSW_C4) { cs_set_user_plant(id,0,0); cs_set_user_bpammo(id,CSW_C4,0); } else if(wId == CSW_SMOKEGRENADE || wId == CSW_FLASHBANG || wId == CSW_HEGRENADE) cs_set_user_bpammo(id,wId,0);
return 1; }
// gets the weapon that a killer used, just like CHalfLifeMultiplay::DeathNotice stock get_killer_weapon(killer,inflictor,retVar[],retLen) { static killer_weapon_name[32]; killer_weapon_name = "world"; // by default, the player is killed by the world
if(pev_valid(killer) && (pev(killer,pev_flags) & FL_CLIENT)) { if(pev_valid(inflictor)) { if(inflictor == killer) { // if the inflictor is the killer, then it must be their current weapon doing the damage new weapon = get_user_weapon(killer); get_weaponname(weapon,killer_weapon_name,31); } else pev(inflictor,pev_classname,killer_weapon_name,31); // it's just that easy } } else { if(pev_valid(killer)) pev(inflictor,pev_classname,killer_weapon_name,31); else if(killer == 0) killer_weapon_name = "worldspawn"; }
// strip the monster_* or weapon_* from the inflictor's classname if(equal(killer_weapon_name,"weapon_",7)) copy(killer_weapon_name,31,killer_weapon_name[7]); else if(equal(killer_weapon_name,"monster_",8)) copy(killer_weapon_name,31,killer_weapon_name[8]); else if(equal(killer_weapon_name,"func_",5)) copy(killer_weapon_name,31,killer_weapon_name[5]);
// output copy(retVar,retLen,killer_weapon_name); }
// gets a team's color stock get_team_color(CsTeams:team,ret[],retLen) { switch(team) { case CS_TEAM_T: return formatex(ret,retLen,"FF3F3F"); case CS_TEAM_CT: return formatex(ret,retLen,"99CCFF"); }
return formatex(ret,retLen,"FFFFFF"); }
// gets the name of a team stock get_team_name(CsTeams:team,ret[],retLen) { switch(team) { case CS_TEAM_T: return formatex(ret,retLen,"TERRORIST"); case CS_TEAM_CT: return formatex(ret,retLen,"CT"); case CS_TEAM_SPECTATOR: return formatex(ret,retLen,"SPECTATOR"); } return formatex(ret,retLen,"UNASSIGNED"); }
// gets the amount of players on a team stock team_player_count(CsTeams:team) { new player, count; for(player=1;player<=maxPlayers;player++) { if(is_user_connected(player) && cs_get_user_team(player) == team) count++; } return count; }
// is this player on a valid team? on_valid_team(id) { new CsTeams:team = cs_get_user_team(id); return (team == CS_TEAM_T || team == CS_TEAM_CT); }
// gets a number's suffix. sort of bad, has to convert to string. stock get_number_suffix(number,ret[],retLen) { static str[8]; num_to_str(number,str,7); new len = strlen(str);
if(number >= 10 && str[len-2] == '1') // second to last digit return formatex(ret,retLen,"th"); // 10-19 end in 'th
switch(str[len-1]) // last digit { case '1': return formatex(ret,retLen,"st"); case '2': return formatex(ret,retLen,"nd"); case '3': return formatex(ret,retLen,"rd"); } return formatex(ret,retLen,"th"); }
// Note to self: gordank offered translations Код /* --------------------------------------------------------------------------------------------
"Just Capture The Flag" - by Digi (aka Hunter-Digital)
Thread: http://forums.alliedmods.net/showthread.php?t=132115
Change log below.
-------------------------------------------------------------------------------------------- */
new const MOD_TITLE[] = "Just Capture the Flag" /* Please don't modify. */ new const MOD_AUTHOR[] = "Digi" /* If you make major changes, add " & YourName" at the end */ new const MOD_VERSION[] = "1.32c" /* If you make major changes, add "custom" at the end but do not modify the actual version number! */
/* Below you can enable/disable each individual feature of this plugin NOTE: Remember to compile the plugin again after you modify anything in this file!
-----------------------------------
Description: This uses Orpheu module to make infinite round end and trigger round end on flag captures If set to false, ophreu will not be used anymore and rounds could end if all players from one team are dead and round can't end upon flag capture. */ #define FEATURE_ORPHEU true
/* Description: This hooks the buy system of the game and changes it, allowing everybody to buy all weapons. If set to false, it will disable all buy related stuff like: buy menu, spawn weaopns, special weapons, even C4! Disable this if you want to use another plugin that manages buy or doesn't use buy at all (like GunGame) */ #define FEATURE_BUY true
/* Description: This allows players to buy and use C4 as a weapon, not an objective, it can be defused tough but the defuser gets a usable C4 back. C4 kills everything in it's radius, including teammates. If set to false, C4 usage will be completly disabled so it can't be bought.
Requirements: FEATURE_BUY must be true */ #define FEATURE_BUYC4 true
/* Description: This allows players to have an adrenaline amount and when it reaches 100, they can use combos. If set to false, it will disable all adrenaline stuff, including combos, rewards, buying with adrenaline, everything. */ #define FEATURE_ADRENALINE true
/* -------------------------------------------------------------------------------------------- Skip this, advanced configuration more below */ #if FEATURE_BUY == true && FEATURE_BUYC4 == true #define FEATURE_C4 true #else #define FEATURE_C4 false #endif
#include <amxmodx> #include <amxmisc> #include <hamsandwich>
#if FEATURE_ORPHEU == true #include <orpheu_memory> #include <orpheu> #endif
#include <fakemeta> #include <cstrike> #include <engine> #include <fun>
/* --------------------------------------------------------------------------------------------
CVars for .cfg files:
ctf_flagreturn (default 120) - flag auto-return time ctf_weaponstay (default 30) - how long do weapons and items stay on ground ctf_itempercent (default 30) - chance that items spawn when a player is killed, values from 0 to 100 ctf_sound_taken (default 1) - toggles if the "flag taken" sounds can be heard ctf_sound_dropped (default 1) - toggles if the "flag dropped" sounds can be heard ctf_sound_returned (default 1) - toggles if the "flag returned" sounds can be heard ctf_sound_score (default 1) - toggles if the "X team scores" sounds can be heard ctf_respawntime (default 10) - players respawn time (use -1 to disable respawn) ctf_spawnmoney (default 1000) - money bonus when spawning (unless it's a suicide) ctf_protection (default 5) - players spawn protection time (use -1 to disable protection) ctf_dynamiclights (default 1) - set the default dynamic lights setting, players will still be able to toggle individually using /lights ctf_glows (default 1) - set if entities can glow, like when players have flag or an adrenaline combo, weapons start to fade, etc. ctf_nospam_flash (default 20) - delay of rebuying two flashbangs in a life ctf_nospam_he (default 20) - delay of rebuying a HE grenade in a life ctf_nospam_smoke (default 20) - delay of rebuying a smoke grenade in a life ctf_spawn_prim (default "m3") - spawning primary weapon, set to "" to disable ctf_spawn_sec (default "glock") - spawning secondary weapon, set to "" to disable ctf_spawn_knife (default 1) - toggle if players spawn with knife or not ctf_sound_taken (default 1) - toggles if the "flag taken" sounds can be heard ctf_sound_dropped (default 1) - toggles if the "flag dropped" sounds can be heard ctf_sound_returned (default 1) - toggles if the "flag returned" sounds can be heard ctf_sound_score (default 1) - toggles if the "X team scores" sounds can be heard
Primary weapons: m3,xm1014,tmp,mac10,mp5,ump45,p90,galil,ak47,famas,m4a1,aug,sg552,awp,scout,sg55 0,g3sg1,m249,shield Secondary weapons: glock,usp,p228,deagle,elites,fiveseven
mp_c4timer (recommended 20) - time before the C4 devices explode mp_winlimit - first team who reaches this number wins mp_timelimit - time limit for the map (displayed in the round timer) mp_startmoney (recommended 3000) - for first spawn money and minimum amount of money mp_forcecamera - (0/1 - spectate enemies or not) mod fades to black if this is on and player is in free look (no teammates alive) mp_forcechasecam - (0/1/2 - force chase cammera all/team/firstperson) same as above mp_autoteambalance - enable/disable auto-team balance (checks at every player death)
Map configurations are made with;
ctf_moveflag red/blue at your position (even if dead/spec) ctf_save to save flag origins in maps/<mapname>.ctf
Reward configuration, 0 on all values disables reward/penalty.
[REWARD FOR] [MONEY] [FRAGS] [ADRENALINE] */ #define REWARD_RETURN 500, 0, 10 #define REWARD_RETURN_ASSIST 500, 0, 10
#define REWARD_CAPTURE 3000, 3, 25 #define REWARD_CAPTURE_ASSIST 3000, 3, 25 #define REWARD_CAPTURE_TEAM 1000, 0, 10
#define REWARD_STEAL 1000, 1, 10 #define REWARD_PICKUP 500, 1, 5 #define PENALTY_DROP -1500, -1, -10
#define REWARD_KILL 0, 0, 5 #define REWARD_KILLCARRIER 500, 1, 10
#define PENALTY_SUICIDE 0, 0, -20 #define PENALTY_TEAMKILL 0, 0, -20
/* Advanced configuration */
const ADMIN_RETURN = ADMIN_RCON // access required for admins to return flags (full list in includes/amxconst.inc) const ADMIN_RETURNWAIT = 15 // time the flag needs to stay dropped before it can be returned by command
new const bool:CHAT_SHOW_COMMANDS = true // show commands (like /buy) in chat, true or false
const ITEM_MEDKIT_GIVE = 25 // medkit award health for picking up
new const bool:ITEM_DROP_AMMO = true // toggle if killed players drop ammo items new const bool:ITEM_DROP_MEDKIT = true // toggle if killed players drop medkit items
#if FEATURE_ADRENALINE == true new const bool:ITEM_DROP_ADRENALINE = true // toggle if killed players drop adrenaline items const ITEM_ADRENALINE_GIVE = 5 // adrenaline reaward for picking up adrenaline
const Float:SPEED_ADRENALINE = 1.3 // speed while using "speed" adrenaline combo (this and SPEED_FLAG are cumulative)
const Float:BERSERKER_SPEED1 = 0.7 // primary weapon shooting speed percent while in berserk const Float:BERSERKER_SPEED2 = 0.3 // secondary weapon shooting speed percent while in berserk const Float:BERSERKER_DAMAGE = 2.0 // weapon damage percent while in berserk
const INSTANTSPAWN_COST = 50 // instant spawn (/spawn) adrenaline cost
#endif // FEATURE_ADRENALINE
const REGENERATE_EXTRAHP = 50 // extra max HP for regeneration and flag healing
const Float:SPEED_FLAG = 0.9 // speed while carying the enemy flag
new const Float:BASE_HEAL_DISTANCE = 96.0 // healing distance for flag
#if FEATURE_C4 == true
new const C4_RADIUS[] = "600" // c4 explosion radius (must be string!) new const C4_DEFUSETIME = 3 // c4 defuse time
#endif // FEATURE_C4
new const FLAG_SAVELOCATION[] = "maps/%s.ctf" // you can change where .ctf files are saved/loaded from
#define FLAG_IGNORE_BOTS true // set to true if you don't want bots to pick up flags
/* Change log:
v1.32c: * Changed files: jctf.sma - Added ctf_dynamiclights cvar to enable server operators to disable dynamic lights by default, players can still re-enable them individually using /lights - Added ctf_glows cvar to enable server operators to disable glows on entities for performance, however it will degrade gameplay due to lack of visual information
v1.32b: * Changed files: jctf.sma - Fixed rewards beeing default to 0 for steal and capturing flags (my bad).
v1.32: * Changes files: jctf.sma - Removed forcing of CVars - if you depended on that, use amxx.cfg to store default values of cvars. - Added posibility to disable respawn using ctf_respawntime 0. - Added posibility to disable spawn protection using ctf_protection 0. - Added posibility to disable dropped weapons fading out using ctf_weaponstay 0. - Added posibility to disable flag auto-return using ctf_flagreturn 0. - Fixed GameName printing CS 1.6 for CZ too, now it detects game name, if's unknown it doesn't write anything. - Fixed player rewards still printing if all rewards are 0. - Fixed MP3 files printing WAV error messages due to incorrect precaching method.
v1.31: * Changed files: jctf.sma, jctf_resources.zip - Fixed issue where plugin wouldn't trigger "Round_End" on ctf_flagendround 1 that caused issues with other plugins. - Added new orpheu signatures: functions/EndRoundMessage and functions/CHalfLifeMultiplay/UpdateTeamScores. - Changed "TeamScore" message to emessage, that way it can be hooked by other plugins. - Added updating team scores internally too. - Some other minor changes.
v1.3: * Changed files: jctf.sma, lang/jctf.txt, jctf_resources.zip - Added CVars: ctf_flagendround, ctf_flagcaptureslay and ctf_infiniteround (see thread for descriptions) - Changed /help command, it now prints most mod settings and features (which are enabled/disabled) - Added new orpheu signatures: functions/InstallGameRules and memory/CGameRulesOffsets (they're in jctf_resources.zip) - Changed feature define FEATURE_INFROUND to FEATURE_ORPHEU because it also disables flag capture ending round - Changed contents of lang keys: JOIN_NOFEATURES - Renamed lang keys: HELP_3_* to HELP_4_* and DEAH_NOFREELOOK to DEATH_NOFREELOOK - Added lang keys: DEATH_FLAGCAPTURED, STARTING_NEWROUND, and HELP_3_* - Added so that on new round, flags are returned to base (no matter what the reason of new round)
v1.28c: * Changed files: jctf.sma - Fixed if you reload map with the plugin disabled the rounds will end normally.
v1.28b: * Changed files: jctf.sma - Fixed a compile error when switching FEATURE_ADRENALINE to false.
v1.28: * Changed files: jctf.sma, jctf.txt - Fixed buying VGUI issues, plugin now closes buy VGUI and opens custom buy menu without client changes. - Removed VGUI related ML keys from jctf.txt.
v1.27: * Changed files: jctf.sma, jctf.txt - Added FEATURE disabling, you can now toggle individual features from the sma file. - Added ctf_flagheal cvar which toggles if flag bases heal teammates. - Changed HUD message to Director HUD messages, nicer and have no channel limit - Increased char limit for "Freelook mode blocked" ML text from 32 to 48 chars. - Rearranged sma configuration variables, you can find them easier on top of the file. - Added hints and adrenaline menu to the ML support. - Decreased chance that flag gets stuck in a wall (dramatically decreased collision box and added proximity check for pickup) - Decreased C4's price from $15000 to $12000 and adrenaline cost from 100 to 80 - Some minor optimizations
v1.26: * Changed files: jctf.sma, jctf.inc(jctf_api.zip), lang/jctf.txt - Fixed "ED_Alloc: No free edicts" crashes (hopefully). - Added Multilingual support, natives support it too. - Added printing of admin commands in chat that obey amx_show_activity. - Added a check of players spawning HP and Armor so Booster and flags know how much to heal. - Added configurable extra HP the booster heals. - Changed armor regeneration from Booster so it no longer sets armor to kevlar+helm if you have kevlar only. - Added option to ignore bots from taking flags, default OFF (search sma for // CONFIGURABLE). - Added checking of player's team range when touching flag in case it's a spawned spectator. - Fixed bots not buying weapons, but be warned, they buy at default prices and without adrenaline. - Changed default mp_buytime from 0 to 99999999 so bots can always buy, this doesn't affect players. - Added API natives: jctf_get_flagcarrier(id) and jctf_get_team(id) - Added FLAG_ADMINRETURN for the jctf_flag() forward, it triggers when an admin returns the flag using command - Fixed ctf_moveflag command not showing Y axis in the log
v1.25: - Changed ctf_moveflag to support red and blue inputs - Fade to black no longer affects spectators - Added "ctf_returnflag <red/blue>" admin command that returns the specified flag if it was dropped for at least 15 seconds (configurable) - Optimized some minor stuff
v1.24: - Changed ctf_weaponstay's default value from 30 to 15 (seconds) - Changed ctf_itempercent's default value from 30 to 25 (percent) - Added Scout and G3SG1 as special weapons. - Added the "configurable" flag in the source for weapon money and adrenaline costs - Added configurable weapon and zoom-in running speeds - Added cvars for controling sounds: ctf_sound_taken/dropped/returned/score - Added how much money/adrenaline you need in the "Not enough money/adrenaline" message
v1.23: - plugin no longer disables VGUI menu automatically but it notifies VGUI menu users upon spawn - added new in-source configuration: CHAT_SHOW_COMMANDS
v1.22: - fixed a bug where you'd get twice the adrenaline when using the jctf_add_adrenaline() native while using a reason - fixed adrenaline HUD not updating when using jctf_add_adrenaline()
v1.21: - added FLAG_MANUALDROP for jctf_flag() events - fixed some example issues in jctf_addon_example.sma - updated version check to 1.21 since jctf.inc was altered - added a console print upon plugin load with plugin name and version - forced to reset jctf_version to the current version if mod is updated while server is running
v1.2: - added forwards and natives that other plugins could use - added configurable spawning weapons using CVars, they're also forced to reset to prevent unwanted usage between maps - minor adjustments in the code to fit the latest modifications
v1.13: - fixed some issues with the autoteambalance - fixed spawn protection countdown not stop when prematurely disabling protection - fixed game name displaying version as number instead of string - added mod version in quick help and help console message - added checking of mp_forcechasecam too for the fade to black feature - fixed the possiblity of not beeing blinded while in freelook after a respawn
v1.12: - fixed a bug where transfered people (autoteambalance) would actually block the team they left from beeing joined, the "there are too many CTs/Ts" thing. - added fade to black when mp_fadetoblack is disabled and mp_forcecamera is enabled while player is on free view (no teammates alive)
v1.11: - fixed a rare bug where players won't respawn after beeing killed - some optimizations in code
v1.1: - removed previous round-end blocking and added new round blocking method via Orpheu module - fixed various possible crashes caused by previous round-end blocking methods
v1.06: - changed buy menu text so that items you can't afford are in red text - fixed various speed issues with player zooming, shield and flag taking - re-done player rendering system and altered some colors and values - unforced most mod cvars, only two cvars remain forced
v1.05: - fixed round-blocking player deaths's animations - changed the sounds of medkit and adrenaline item pickup - and of course, other small adjustments
v1.04: - other small adjustments here and there - removed the spectating bots, now players' deaths are blocked if they'll trigger round end, they wouldn't even notice - altered C4 plant radio message to a be compatible with client modifications and other hooks
v1.03: - added /help - minor adjustments and code moved around
v1.02: - fixed items not fading out - fixed the simple auto-team balance - fixed various possible errors
v1.01: - minor fixes of typos and checks
-------------------------------------------------------------------------------------------- */
new const INFO_TARGET[] = "info_target" new const ITEM_CLASSNAME[] = "ctf_item" new const WEAPONBOX[] = "weaponbox"
#if FEATURE_C4 == true
new const GRENADE[] = "grenade"
#endif // FEATURE_C4
new const Float:ITEM_HULL_MIN[3] = {-1.0, -1.0, 0.0} new const Float:ITEM_HULL_MAX[3] = {1.0, 1.0, 10.0}
const ITEM_AMMO = 0 const ITEM_MEDKIT = 1
#if FEATURE_ADRENALINE == true
const ITEM_ADRENALINE = 2
#endif // FEATURE_ADRENALINE
new const ITEM_MODEL_AMMO[] = "models/w_chainammo.mdl" new const ITEM_MODEL_MEDKIT[] = "models/w_medkit.mdl"
#if FEATURE_ADRENALINE == true
new const ITEM_MODEL_ADRENALINE[] = "models/can.mdl"
#endif // FEATURE_ADRENALINE
new const BASE_CLASSNAME[] = "ctf_flagbase" new const Float:BASE_THINK = 0.25
new const FLAG_CLASSNAME[] = "ctf_flag" new const FLAG_MODEL[] = "models/th_jctf.mdl"
new const Float:FLAG_THINK = 0.1 const FLAG_SKIPTHINK = 20 /* FLAG_THINK * FLAG_SKIPTHINK = 2.0 seconds ! */
new const Float:FLAG_HULL_MIN[3] = {-2.0, -2.0, 0.0} new const Float:FLAG_HULL_MAX[3] = {2.0, 2.0, 16.0}
new const Float:FLAG_SPAWN_VELOCITY[3] = {0.0, 0.0, -500.0} new const Float:FLAG_SPAWN_ANGLES[3] = {0.0, 0.0, 0.0}
new const Float:FLAG_DROP_VELOCITY[3] = {0.0, 0.0, 50.0}
new const Float:FLAG_PICKUPDISTANCE = 80.0
const FLAG_LIGHT_RANGE = 12 const FLAG_LIGHT_LIFE = 5 const FLAG_LIGHT_DECAY = 1
const FLAG_ANI_DROPPED = 0 const FLAG_ANI_STAND = 1 const FLAG_ANI_BASE = 2
const FLAG_HOLD_BASE = 33 const FLAG_HOLD_DROPPED = 34
#if FEATURE_ADRENALINE == true
const ADRENALINE_SPEED = 1 const ADRENALINE_BERSERK = 2 const ADRENALINE_REGENERATE = 3 const ADRENALINE_INVISIBILITY = 4
new const MENU_ADRENALINE[] = "menu_adrenaline" new const MENU_KEYS_ADRENALINE = (1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<9)
#endif // FEATURE_ADRENALINE
#if FEATURE_BUY == true
new const WHITESPACE[] = " " new const MENU_BUY[] = "menu_buy" new const MENU_KEYS_BUY = (1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)
new const BUY_ITEM_DISABLED[] = "r" new const BUY_ITEM_AVAILABLE[] = "w"
#if FEATURE_ADRENALINE == true
new const BUY_ITEM_AVAILABLE2[] = "y"
#endif // FEATURE_ADRENALINE
#endif // FEATURE_BUY
new const SND_GETAMMO[] = "items/9mmclip1.wav" new const SND_GETMEDKIT[] = "items/smallmedkit1.wav"
#if FEATURE_ADRENALINE == true
new const SND_GETADRENALINE[] = "items/medshot4.wav" new const SND_ADRENALINE[] = "ambience/des_wind3.wav"
#endif // FEATURE_ADRENALINE
#if FEATURE_C4 == true
new const SND_C4DISARMED[] = "weapons/c4_disarmed.wav"
#endif // FEATURE_C4
new const CHAT_PREFIX[] = "^x03[^x04 CTF^x03 ]^x01 " new const CONSOLE_PREFIX[] = "[ CTF ] "
const FADE_OUT = 0x0000 const FADE_IN = 0x0001 const FADE_MODULATE = 0x0002 const FADE_STAY = 0x0004
const m_iUserPrefs = 510 const m_flNextPrimaryAttack = 46 const m_flNextSecondaryAttack = 47
new const PLAYER[] = "player" new const SEPARATOR[] = " - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -" #define NULL ""
#define HUD_HINT 255, 255, 255, 0.15, -0.3, 0, 0.0, 10.0, 2.0, 10.0, 4 #define HUD_HELP 255, 255, 0, -1.0, 0.2, 2, 0.1, 2.0, 0.01, 2.0, 2 #define HUD_HELP2 255, 255, 0, -1.0, 0.25, 2, 0.1, 2.0, 0.01, 2.0, 3 #define HUD_ANNOUNCE -1.0, 0.3, 0, 0.0, 3.0, 0.1, 1.0, 4 #define HUD_RESPAWN 0, 255, 0, -1.0, 0.6, 2, 0.5, 0.1, 0.0, 1.0, 1 #define HUD_PROTECTION 255, 255, 0, -1.0, 0.6, 2, 0.5, 0.1, 0.0, 1.0, 1 #define HUD_ADRENALINE 255, 255, 255, -1.0, -0.1, 0, 0.0, 600.0, 0.0, 0.0, 1
#define entity_create(%1) create_entity(%1) #define entity_spawn(%1) DispatchSpawn(%1) #define entity_think(%1) call_think(%1) #define entity_remove(%1) remove_entity(%1) #define weapon_remove(%1) call_think(%1)
#define task_set(%1) set_task(%1) #define task_remove(%1) remove_task(%1)
#define player_hasFlag(%1) (g_iFlagHolder[TEAM_RED] == %1 || g_iFlagHolder[TEAM_BLUE] == %1)
#define player_allowChangeTeam(%1) set_pdata_int(%1, 125, get_pdata_int(%1, 125) & ~(1<<8))
#define gen_color(%1,%2) %1 == TEAM_RED ? %2 : 0, 0, %1 == TEAM_RED ? 0 : %2
#define get_opTeam(%1) (%1 == TEAM_BLUE ? TEAM_RED : (%1 == TEAM_RED ? TEAM_BLUE : 0))
enum { x, y, z }
enum { pitch, yaw, roll }
enum (+= 64) { TASK_RESPAWN = 64, TASK_PROTECTION, TASK_DAMAGEPROTECTION, TASK_EQUIPAMENT, TASK_PUTINSERVER, TASK_TEAMBALANCE, TASK_ADRENALINE, TASK_DEFUSE, TASK_CHECKHP }
enum { TEAM_NONE = 0, TEAM_RED, TEAM_BLUE, TEAM_SPEC }
new const g_szCSTeams[][] = { NULL, "TERRORIST", "CT", "SPECTATOR" }
new const g_szTeamName[][] = { NULL, "Red", "Blue", "Spectator" }
new const g_szMLTeamName[][] = { NULL, "TEAM_RED", "TEAM_BLUE", "TEAM_SPEC" }
new const g_szMLFlagTeam[][] = { NULL, "FLAG_RED", "FLAG_BLUE", NULL }
enum { FLAG_STOLEN = 0, FLAG_PICKED, FLAG_DROPPED, FLAG_MANUALDROP, FLAG_RETURNED, FLAG_CAPTURED, FLAG_AUTORETURN, FLAG_ADMINRETURN }
enum { EVENT_TAKEN = 0, EVENT_DROPPED, EVENT_RETURNED, EVENT_SCORE, }
new const g_szSounds[][][] = { {NULL, "red_flag_taken", "blue_flag_taken"}, {NULL, "red_flag_dropped", "blue_flag_dropped"}, {NULL, "red_flag_returned", "blue_flag_returned"}, {NULL, "red_team_scores", "blue_team_scores"} }
#if FEATURE_ADRENALINE == true new const g_szAdrenalineUseML[][] = { NULL, "ADR_SPEED", "ADR_BERSERK", "ADR_REGENERATE", "ADR_INVISIBILITY" } #endif // FEATURE_ADRENALINE
#if FEATURE_BUY == true
enum { no_weapon, primary, secondary, he, flash, smoke, armor, nvg }
new const g_szRebuyCommands[][] = { NULL, "PrimaryWeapon", "SecondaryWeapon", "HEGrenade", "Flashbang", "SmokeGrenade", "Armor", "NightVision" }
#endif // FEATURE_BUY
new const g_szRemoveEntities[][] = { "func_buyzone", "armoury_entity", "func_bomb_target", "info_bomb_target", "hostage_entity", "monster_scientist", "func_hostage_rescue", "info_hostage_rescue", "info_vip_start", "func_vip_safetyzone", "func_escapezone", "info_map_parameters", "player_weaponstrip", "game_player_equip" }
enum { ZERO = 0, W_P228, W_SHIELD, W_SCOUT, W_HEGRENADE, W_XM1014, W_C4, W_MAC10, W_AUG, W_SMOKEGRENADE, W_ELITE, W_FIVESEVEN, W_UMP45, W_SG550, W_GALIL, W_FAMAS, W_USP, W_GLOCK18, W_AWP, W_MP5NAVY, W_M249, W_M3, W_M4A1, W_TMP, W_G3SG1, W_FLASHBANG, W_DEAGLE, W_SG552, W_AK47, W_KNIFE, W_P90, W_VEST, W_VESTHELM, W_NVG }
new const g_iClip[] = { 0, // (unknown) 13, // P228 0, // SHIELD (not used) 10, // SCOUT 0, // HEGRENADE (not used) 7, // XM1014 0, // C4 (not used) 30, // MAC10 30, // AUG 0, // SMOKEGRENADE (not used) 30, // ELITE 20, // FIVESEVEN 25, // UMP45 30, // SG550 35, // GALIL 25, // FAMAS 12, // USP 20, // GLOCK18 10, // AWP 30, // MP5NAVY 100, // M249 8, // M3 30, // M4A1 30, // TMP 20, // G3SG1 0, // FLASHBANG (not used) 7, // DEAGLE 30, // SG552 30, // AK47 0, // KNIFE (not used) 50, // P90 0, // Kevlar (not used) 0, // Kevlar + Helm (not used) 0 // NVG (not used) }
new const g_iBPAmmo[] = { 0, // (unknown) 52, // P228 0, // SHIELD 90, // SCOUT 0, // HEGRENADE (not used) 32, // XM1014 0, // C4 (not used) 100, // MAC10 90, // AUG 0, // SMOKEGRENADE (not used) 120, // ELITE 100, // FIVESEVEN 100, // UMP45 90, // SG550 90, // GALIL 90, // FAMAS 100, // USP 120, // GLOCK18 30, // AWP 120, // MP5NAVY 200, // M249 32, // M3 90, // M4A1 120, // TMP 90, // G3SG1 0, // FLASHBANG (not used) 35, // DEAGLE 90, // SG552 90, // AK47 0, // KNIFE (not used) 100, // P90 0, // Kevlar (not used) 0, // Kevlar + Helm (not used) 0 // NVG (not used) }
#if FEATURE_BUY == true
new const g_iWeaponPrice[] = { 0, // (unknown) 600, // P228 10000, // SHIELD 6000, // SCOUT 300, // HEGRENADE 3000, // XM1014 12000, // C4 1400, // MAC10 3500, // AUG 100, // SMOKEGRENADE 1000, // ELITE 750, // FIVESEVEN 1700, // UMP45 6000, // SG550 2000, // GALIL 2250, // FAMAS 500, // USP 400, // GLOCK18 8000, // AWP 1500, // MP5NAVY 5000, // M249 1700, // M3 3100, // M4A1 1250, // TMP 7000, // G3SG1 200, // FLASHBANG 650, // DEAGLE 3500, // SG552 2500, // AK47 0, // KNIFE (not used) 2350, // P90 650, // Kevlar 1000, // Kevlar + Helm 1250 // NVG }
#endif // FEATURE_BUY
#if FEATURE_BUY == true && FEATURE_ADRENALINE == true
new const g_iWeaponAdrenaline[] = { 0, // (unknown) 0, // P228 50, // SHIELD 50, // SCOUT 0, // HEGRENADE 0, // XM1014 80, // C4 0, // MAC10 0, // AUG 0, // SMOKEGRENADE 0, // ELITE 0, // FIVESEVEN 0, // UMP45 30, // SG550 0, // GALIL 0, // FAMAS 0, // USP 0, // GLOCK18 50, // AWP 0, // MP5NAVY 10, // M249 0, // M3 0, // M4A1 0, // TMP 30, // G3SG1 0, // FLASHBANG 0, // DEAGLE 0, // SG552 0, // AK47 0, // KNIFE (not used) 0, // P90 0, // Kevlar 0, // Kevlar + Helm 0 // NVG }
#endif // FEATURE_ADRENALINE
new const Float:g_fWeaponRunSpeed[] = // CONFIGURABLE - weapon running speed (edit the numbers in the list) { 150.0, // Zoomed speed with any weapon 250.0, // P228 0.0, // SHIELD (not used) 260.0, // SCOUT 250.0, // HEGRENADE 240.0, // XM1014 250.0, // C4 250.0, // MAC10 240.0, // AUG 250.0, // SMOKEGRENADE 250.0, // ELITE 250.0, // FIVESEVEN 250.0, // UMP45 210.0, // SG550 240.0, // GALIL 240.0, // FAMAS 250.0, // USP 250.0, // GLOCK18 210.0, // AWP 250.0, // MP5NAVY 220.0, // M249 230.0, // M3 230.0, // M4A1 250.0, // TMP 210.0, // G3SG1 250.0, // FLASHBANG 250.0, // DEAGLE 235.0, // SG552 221.0, // AK47 250.0, // KNIFE 245.0, // P90 0.0, // Kevlar (not used) 0.0, // Kevlar + Helm (not used) 0.0 // NVG (not used) }
#if FEATURE_BUY == true
new const g_iWeaponSlot[] = { 0, // none 2, // P228 1, // SHIELD 1, // SCOUT 4, // HEGRENADE 1, // XM1014 5, // C4 1, // MAC10 1, // AUG 4, // SMOKEGRENADE 2, // ELITE 2, // FIVESEVEN 1, // UMP45 1, // SG550 1, // GALIL 1, // FAMAS 2, // USP 2, // GLOCK18 1, // AWP 1, // MP5NAVY 1, // M249 1, // M3 1, // M4A1 1, // TMP 1, // G3SG1 4, // FLASHBANG 2, // DEAGLE 1, // SG552 1, // AK47 3, // KNIFE (not used) 1, // P90 0, // Kevlar 0, // Kevlar + Helm 0 // NVG }
#endif // FEATURE_BUY
new const g_szWeaponEntity[][24] = { NULL, "weapon_p228", "weapon_shield", "weapon_scout", "weapon_hegrenade", "weapon_xm1014", "weapon_c4", "weapon_mac10", "weapon_aug", "weapon_smokegrenade", "weapon_elite", "weapon_fiveseven", "weapon_ump45", "weapon_sg550", "weapon_galil", "weapon_famas", "weapon_usp", "weapon_glock18", "weapon_awp", "weapon_mp5navy", "weapon_m249", "weapon_m3", "weapon_m4a1", "weapon_tmp", "weapon_g3sg1", "weapon_flashbang", "weapon_deagle", "weapon_sg552", "weapon_ak47", "weapon_knife", "weapon_p90", "item_kevlar", "item_assaultsuit", NULL }
#if FEATURE_BUY == true
new const g_szWeaponCommands[][] = { {NULL, NULL}, {"p228", "228compact"}, {"shield", NULL}, {"scout", NULL}, {"hegren", NULL}, {"xm1014", "autoshotgun"}, {NULL, NULL}, {"mac10", NULL}, {"aug", "bullpup"}, {"sgren", NULL}, {"elites", NULL}, {"fiveseven", "fn57"}, {"ump45", "sm"}, {"sg550", "krieg550"}, {"galil", "defender"}, {"famas", "clarion"}, {"usp", "km45"}, {"glock", "9x19mm"}, {"awp", "magnum"}, {"mp5", "mp"}, {"m249", NULL}, {"m3", "12gauge"}, {"m4a1", NULL}, {"tmp", NULL}, {"g3sg1", "d3au1"}, {"flash", NULL}, {"deagle", "nighthawk"}, {"sg552", "krieg552"}, {"ak47", "cv47"}, {NULL, NULL}, {"p90", "c90"}, {"vest", NULL}, {"vesthelm", NULL}, {"nvgs", NULL} }
#endif // FEATURE_BUY
new g_iMaxPlayers new g_szMap[32] new g_szGame[16] new g_iTeam[33] new g_iScore[3] new g_iFlagHolder[3] new g_iFlagEntity[3] new g_iBaseEntity[3] new Float:g_fFlagDropped[3]
#if FEATURE_BUY == true
new g_iMenu[33] new g_iRebuy[33][8] new g_iAutobuy[33][64] new g_iRebuyWeapons[33][8]
new pCvar_ctf_nospam_flash new pCvar_ctf_nospam_he new pCvar_ctf_nospam_smoke new pCvar_ctf_spawn_prim new pCvar_ctf_spawn_sec new pCvar_ctf_spawn_knife
new gMsg_BuyClose
#endif // FEATURE_BUY
new g_iMaxArmor[33] new g_iMaxHealth[33] new g_iAdrenaline[33] new g_iAdrenalineUse[33] new bool:g_bRestarting new bool:g_bBot[33] new bool:g_bAlive[33] new bool:g_bDefuse[33] new bool:g_bLights[33] new bool:g_bBuyZone[33] new bool:g_bSuicide[33] new bool:g_bFreeLook[33] new bool:g_bAssisted[33][3] new bool:g_bProtected[33] new bool:g_bRestarted[33] new bool:g_bFirstSpawn[33]
new Float:g_fFlagBase[3][3] new Float:g_fFlagLocation[3][3] new Float:g_fWeaponSpeed[33] new Float:g_fLastDrop[33] new Float:g_fLastBuy[33][4]
new pCvar_ctf_flagcaptureslay new pCvar_ctf_flagheal new pCvar_ctf_flagreturn new pCvar_ctf_respawntime new pCvar_ctf_protection new pCvar_ctf_dynamiclights new pCvar_ctf_glows new pCvar_ctf_weaponstay new pCvar_ctf_spawnmoney new pCvar_ctf_itempercent
new pCvar_ctf_sound[4] new pCvar_mp_winlimit new pCvar_mp_startmoney new pCvar_mp_fadetoblack new pCvar_mp_forcecamera new pCvar_mp_forcechasecam new pCvar_mp_autoteambalance
#if FEATURE_C4 == true
new pCvar_mp_c4timer
new gMsg_BarTime new gMsg_DeathMsg new gMsg_SendAudio
#endif // FEATURE_C4
new gMsg_SayText new gMsg_RoundTime new gMsg_ScreenFade new gMsg_HostageK new gMsg_HostagePos new gMsg_ScoreInfo new gMsg_ScoreAttrib new gMsg_TextMsg new gMsg_TeamScore
new gHook_EntSpawn
#if FEATURE_ADRENALINE == true
new gSpr_trail new gSpr_blood1 new gSpr_blood2
#endif // FEATURE_ADRENALINE
new gSpr_regeneration
new g_iForwardReturn new g_iFW_flag
#if FEATURE_ORPHEU == true
new pCvar_ctf_infiniteround new pCvar_ctf_flagendround
new g_pGameRules new bool:g_bLinux new OrpheuHook:g_oMapConditions new OrpheuHook:g_oWinConditions new OrpheuHook:g_oRoundTimeExpired new MEMORY_ROUNDTIME[] = "roundTimeCheck"
#endif // FEATURE_ORPHEU
public plugin_precache() { precache_model(FLAG_MODEL) precache_model(ITEM_MODEL_AMMO) precache_model(ITEM_MODEL_MEDKIT)
#if FEATURE_ADRENALINE == true
precache_model(ITEM_MODEL_ADRENALINE)
precache_sound(SND_GETADRENALINE) precache_sound(SND_ADRENALINE)
gSpr_trail = precache_model("sprites/zbeam5.spr") gSpr_blood1 = precache_model("sprites/blood.spr") gSpr_blood2 = precache_model("sprites/bloodspray.spr")
#endif // FEATURE_ADRENALINE
precache_sound(SND_GETAMMO) precache_sound(SND_GETMEDKIT)
gSpr_regeneration = precache_model("sprites/th_jctf_heal.spr")
for(new szSound[64], i = 0; i < sizeof g_szSounds; i++) { for(new t = 1; t <= 2; t++) { formatex(szSound, charsmax(szSound), "sound/ctf/%s.mp3", g_szSounds[i][t])
precache_generic(szSound) } }
#if FEATURE_C4 == true precache_sound(SND_C4DISARMED)
new ent = entity_create(g_szRemoveEntities[11])
if(ent) { DispatchKeyValue(ent, "buying", "0") DispatchKeyValue(ent, "bombradius", C4_RADIUS) DispatchSpawn(ent) } #endif // FEATURE_C4
gHook_EntSpawn = register_forward(FM_Spawn, "ent_spawn")
#if FEATURE_ORPHEU == true
OrpheuRegisterHook(OrpheuGetFunction("InstallGameRules"), "game_onInstallGameRules", OrpheuHookPost)
#endif // FEATURE_ORPHEU }
public ent_spawn(ent) { if(!is_valid_ent(ent)) return FMRES_IGNORED
static szClass[32]
entity_get_string(ent, EV_SZ_classname, szClass, charsmax(szClass))
for(new i = 0; i < sizeof g_szRemoveEntities; i++) { if(equal(szClass, g_szRemoveEntities[i])) { entity_remove(ent)
return FMRES_SUPERCEDE } }
return FMRES_IGNORED }
public plugin_init() { register_plugin(MOD_TITLE, MOD_VERSION, MOD_AUTHOR) set_pcvar_string(register_cvar("jctf_version", MOD_VERSION, FCVAR_SERVER|FCVAR_SPONLY), MOD_VERSION)
register_dictionary("jctf.txt") register_dictionary("common.txt")
new const SEPARATOR_TEMP[] = " - - - - - - - - - - - - - - - - -"
server_print(SEPARATOR_TEMP) server_print(" %s - v%s", MOD_TITLE, MOD_VERSION) server_print(" Mod by %s", MOD_AUTHOR)
#if FEATURE_ORPHEU == false server_print("[!] Orpheu module usage is disabled! (FEATURE_ORPHEU = false)") #endif
#if FEATURE_BUY == false server_print("[!] Custom buy feature is disabled! (FEATURE_BUY = false)") #endif
#if FEATURE_C4 == false server_print("[!] C4 feature is disabled! (FEATURE_BUYC4 = false)") #endif
#if FEATURE_ADRENALINE == false server_print("[!] Adrenaline feature is disabled! (FEATURE_ADRENALINE = false)") #endif
server_print(SEPARATOR_TEMP)
// Forwards, hooks, events, etc
unregister_forward(FM_Spawn, gHook_EntSpawn)
register_forward(FM_GetGameDescription, "game_description")
register_touch(FLAG_CLASSNAME, PLAYER, "flag_touch")
register_think(FLAG_CLASSNAME, "flag_think") register_think(BASE_CLASSNAME, "base_think")
register_logevent("event_restartGame", 2, "1&Restart_Round", "1&Game_Commencing") register_event("HLTV", "event_roundStart", "a", "1=0", "2=0")
register_clcmd("fullupdate", "msg_block")
register_event("TeamInfo", "player_joinTeam", "a")
RegisterHam(Ham_Spawn, PLAYER, "player_spawn", 1) RegisterHam(Ham_Killed, PLAYER, "player_killed", 1) RegisterHam(Ham_TakeDamage, PLAYER, "player_damage")
register_clcmd("say", "player_cmd_say") register_clcmd("say_team", "player_cmd_sayTeam")
#if FEATURE_ADRENALINE == true
register_menucmd(register_menuid(MENU_ADRENALINE), MENU_KEYS_ADRENALINE, "player_key_adrenaline")
register_clcmd("adrenaline", "player_cmd_adrenaline")
#endif // FEATURE_ADRENALINE
#if FEATURE_BUY == true
register_menucmd(register_menuid(MENU_BUY), MENU_KEYS_BUY, "player_key_buy")
register_event("StatusIcon", "player_inBuyZone", "be", "2=buyzone")
register_clcmd("buy", "player_cmd_buy_main") register_clcmd("buyammo1", "player_fillAmmo") register_clcmd("buyammo2", "player_fillAmmo") register_clcmd("primammo", "player_fillAmmo") register_clcmd("secammo", "player_fillAmmo") register_clcmd("client_buy_open", "player_cmd_buyVGUI")
register_clcmd("autobuy", "player_cmd_autobuy") register_clcmd("cl_autobuy", "player_cmd_autobuy") register_clcmd("cl_setautobuy", "player_cmd_setAutobuy")
register_clcmd("rebuy", "player_cmd_rebuy") register_clcmd("cl_rebuy", "player_cmd_rebuy") register_clcmd("cl_setrebuy", "player_cmd_setRebuy")
register_clcmd("buyequip", "player_cmd_buy_equipament")
#endif // FEATURE_BUY
for(new w = W_P228; w <= W_NVG; w++) { #if FEATURE_BUY == true for(new i = 0; i < 2; i++) { if(strlen(g_szWeaponCommands[w][i])) register_clcmd(g_szWeaponCommands[w][i], "player_cmd_buyWeapon") } #endif // FEATURE_BUY
if(w != W_SHIELD && w <= W_P90) RegisterHam(Ham_Weapon_PrimaryAttack, g_szWeaponEntity[w], "player_useWeapon", 1) }
register_clcmd("ctf_moveflag", "admin_cmd_moveFlag", ADMIN_RCON, "<red/blue> - Moves team's flag base to your origin (for map management)") register_clcmd("ctf_save", "admin_cmd_saveFlags", ADMIN_RCON) register_clcmd("ctf_return", "admin_cmd_returnFlag", ADMIN_RETURN)
register_clcmd("dropflag", "player_cmd_dropFlag")
#if FEATURE_C4 == true
RegisterHam(Ham_Use, GRENADE, "c4_defuse", 1) register_logevent("c4_planted", 3, "2=Planted_The_Bomb") register_logevent("c4_defused", 3, "2=Defused_The_Bomb")
register_touch(WEAPONBOX, PLAYER, "c4_pickup")
#endif // FEATURE_C4
register_touch(ITEM_CLASSNAME, PLAYER, "item_touch")
register_event("CurWeapon", "player_currentWeapon", "be", "1=1") register_event("SetFOV", "player_currentWeapon", "be", "1>1")
RegisterHam(Ham_Spawn, WEAPONBOX, "weapon_spawn", 1)
RegisterHam(Ham_Weapon_SecondaryAttack, g_szWeaponEntity[W_KNIFE], "player_useWeapon", 1) // not a typo
#if FEATURE_ADRENALINE == true
RegisterHam(Ham_Weapon_SecondaryAttack, g_szWeaponEntity[W_USP], "player_useWeaponSec", 1) RegisterHam(Ham_Weapon_SecondaryAttack, g_szWeaponEntity[W_FAMAS], "player_useWeaponSec", 1) RegisterHam(Ham_Weapon_SecondaryAttack, g_szWeaponEntity[W_M4A1], "player_useWeaponSec", 1)
#endif // FEATURE_ADRENALINE
#if FEATURE_C4 == true
gMsg_BarTime = get_user_msgid("BarTime") gMsg_DeathMsg = get_user_msgid("DeathMsg") gMsg_SendAudio = get_user_msgid("SendAudio")
register_message(gMsg_BarTime, "c4_used") register_message(gMsg_SendAudio, "msg_sendAudio")
#endif // FEATURE_C4
gMsg_HostagePos = get_user_msgid("HostagePos") gMsg_HostageK = get_user_msgid("HostageK") gMsg_RoundTime = get_user_msgid("RoundTime") gMsg_SayText = get_user_msgid("SayText") gMsg_ScoreInfo = get_user_msgid("ScoreInfo") gMsg_ScoreAttrib = get_user_msgid("ScoreAttrib") gMsg_ScreenFade = get_user_msgid("ScreenFade") gMsg_TextMsg = get_user_msgid("TextMsg") gMsg_TeamScore = get_user_msgid("TeamScore")
register_message(gMsg_TextMsg, "msg_textMsg") register_message(get_user_msgid("BombDrop"), "msg_block") register_message(get_user_msgid("ClCorpse"), "msg_block") register_message(gMsg_HostageK, "msg_block") register_message(gMsg_HostagePos, "msg_block") register_message(gMsg_RoundTime, "msg_roundTime") register_message(gMsg_ScreenFade, "msg_screenFade") register_message(gMsg_ScoreAttrib, "msg_scoreAttrib") register_message(gMsg_TeamScore, "msg_teamScore") register_message(gMsg_SayText, "msg_sayText")
// CVARS
pCvar_ctf_flagcaptureslay = register_cvar("ctf_flagcaptureslay", "0") pCvar_ctf_flagheal = register_cvar("ctf_flagheal", "1") pCvar_ctf_flagreturn = register_cvar("ctf_flagreturn", "120") pCvar_ctf_respawntime = register_cvar("ctf_respawntime", "10") pCvar_ctf_protection = register_cvar("ctf_protection", "5") pCvar_ctf_dynamiclights = register_cvar("ctf_dynamiclights", "1") pCvar_ctf_glows = register_cvar("ctf_glows", "1") pCvar_ctf_weaponstay = register_cvar("ctf_weaponstay", "15") pCvar_ctf_spawnmoney = register_cvar("ctf_spawnmoney", "1000") pCvar_ctf_itempercent = register_cvar("ctf_itempercent", "25")
#if FEATURE_ORPHEU == true
register_srvcmd("ctf_infiniteround", "server_cmd_infiniteround")
pCvar_ctf_infiniteround = register_cvar("_ctf_infiniteround_memory", "1") pCvar_ctf_flagendround = register_cvar("ctf_flagendround", "0")
#endif // FEATURE_ORPHEU
#if FEATURE_BUY == true
pCvar_ctf_nospam_flash = register_cvar("ctf_nospam_flash", "20") pCvar_ctf_nospam_he = register_cvar("ctf_nospam_he", "20") pCvar_ctf_nospam_smoke = register_cvar("ctf_nospam_smoke", "20") pCvar_ctf_spawn_prim = register_cvar("ctf_spawn_prim", "m3") pCvar_ctf_spawn_sec = register_cvar("ctf_spawn_sec", "glock") pCvar_ctf_spawn_knife = register_cvar("ctf_spawn_knife", "1")
gMsg_BuyClose = get_user_msgid("BuyClose")
#endif // FEATURE_BUY
pCvar_ctf_sound[EVENT_TAKEN] = register_cvar("ctf_sound_taken", "1") pCvar_ctf_sound[EVENT_DROPPED] = register_cvar("ctf_sound_dropped", "1") pCvar_ctf_sound[EVENT_RETURNED] = register_cvar("ctf_sound_returned", "1") pCvar_ctf_sound[EVENT_SCORE] = register_cvar("ctf_sound_score", "1")
#if FEATURE_C4 == true
pCvar_mp_c4timer = get_cvar_pointer("mp_c4timer")
#endif // FEATURE_C4
pCvar_mp_winlimit = get_cvar_pointer("mp_winlimit") pCvar_mp_startmoney = get_cvar_pointer("mp_startmoney") pCvar_mp_fadetoblack = get_cvar_pointer("mp_fadetoblack") pCvar_mp_forcecamera = get_cvar_pointer("mp_forcecamera") pCvar_mp_forcechasecam = get_cvar_pointer("mp_forcechasecam") pCvar_mp_autoteambalance = get_cvar_pointer("mp_autoteambalance")
// Plugin's forwards
g_iFW_flag = CreateMultiForward("jctf_flag", ET_IGNORE, FP_CELL, FP_CELL, FP_CELL, FP_CELL)
// Variables
new szGame[3]
get_modname(szGame, charsmax(szGame))
if(szGame[0] == 'c') { switch(szGame[1]) { case 's': copy(g_szGame, charsmax(g_szGame), "CS 1.6 ") // leave the space at the end case 'z': copy(g_szGame, charsmax(g_szGame), "CS:CZ ") } }
get_mapname(g_szMap, charsmax(g_szMap))
g_iMaxPlayers = get_maxplayers()
#if FEATURE_C4 == true // fake bomb target
new ent = entity_create(g_szRemoveEntities[2])
if(ent) { entity_spawn(ent) entity_set_size(ent, Float:{-8192.0, -8192.0, -8192.0}, Float:{8192.0, 8192.0, 8192.0}) } #endif // FEATURE_C4
#if FEATURE_ORPHEU == true g_bLinux = bool:is_linux_server()
state disabled
game_enableForwards() #endif // FEATURE_ORPHEU }
#if FEATURE_ORPHEU == true
public game_onInstallGameRules() g_pGameRules = OrpheuGetReturn();
public game_enableForwards() <> {} public game_enableForwards() <disabled> { g_oMapConditions = OrpheuRegisterHook(OrpheuGetFunction("CheckMapConditions", "CHalfLifeMultiplay"), "game_blockConditions") g_oWinConditions = OrpheuRegisterHook(OrpheuGetFunction("CheckWinConditions", "CHalfLifeMultiplay"), "game_blockConditions")
if(g_bLinux) g_oRoundTimeExpired = OrpheuRegisterHook(OrpheuGetFunction("HasRoundTimeExpired", "CHalfLifeMultiplay"), "game_blockConditions") else game_memoryReplace(MEMORY_ROUNDTIME, {0x90, 0x90, 0x90})
state enabled }
public game_disableForwards() <> {} public game_disableForwards() <enabled> { OrpheuUnregisterHook(g_oMapConditions) OrpheuUnregisterHook(g_oWinConditions)
if(g_bLinux) OrpheuUnregisterHook(g_oRoundTimeExpired) else game_memoryReplace(MEMORY_ROUNDTIME, {0xF6, 0xC4, 0x41})
state disabled }
public OrpheuHookReturn:game_blockConditions() <> return OrpheuIgnored
public OrpheuHookReturn:game_blockConditions() <enabled> { OrpheuSetReturn(false)
return OrpheuSupercede }
game_memoryReplace(szID[], const iBytes[], const iLen = sizeof iBytes) { new iAddress
OrpheuMemoryGet(szID, iAddress)
for(new i; i < iLen; i++) { OrpheuMemorySetAtAddress(iAddress, "roundTimeCheck|dummy", 1, iBytes[i], iAddress)
iAddress++ }
server_cmd("sv_restart 1") }
public server_cmd_infiniteround() { if(read_argc() == 2) { new szArg[2]
read_argv(1, szArg, charsmax(szArg))
new iSet = clamp(str_to_num(szArg), 0, 1)
set_pcvar_num(pCvar_ctf_infiniteround, iSet)
switch(iSet) { case 0: game_disableForwards() case 1: game_enableForwards() } } else server_print("^"ctf_infiniteround^" is ^"%d^"", get_pcvar_num(pCvar_ctf_infiniteround)) }
#endif // FEATURE_ORPHEU
public game_description() { new szFormat[32]
formatex(szFormat, charsmax(szFormat), "%sjCTF v%s", g_szGame, MOD_VERSION) forward_return(FMV_STRING, szFormat)
return FMRES_SUPERCEDE }
public plugin_cfg() { new szFile[64]
formatex(szFile, charsmax(szFile), FLAG_SAVELOCATION, g_szMap)
new hFile = fopen(szFile, "rt")
if(hFile) { new iFlagTeam = TEAM_RED new szData[24] new szOrigin[3][6]
while(fgets(hFile, szData, charsmax(szData))) { if(iFlagTeam > TEAM_BLUE) break
trim(szData) parse(szData, szOrigin[x], charsmax(szOrigin[]), szOrigin[y], charsmax(szOrigin[]), szOrigin[z], charsmax(szOrigin[]))
g_fFlagBase[iFlagTeam][x] = str_to_float(szOrigin[x]) g_fFlagBase[iFlagTeam][y] = str_to_float(szOrigin[y]) g_fFlagBase[iFlagTeam][z] = str_to_float(szOrigin[z])
iFlagTeam++ }
fclose(hFile) }
flag_spawn(TEAM_RED) flag_spawn(TEAM_BLUE)
task_set(6.5, "plugin_postCfg") }
public plugin_postCfg() { set_cvar_num("mp_freezetime", 0) set_cvar_num("mp_limitteams", 0) set_cvar_num("mp_buytime", 99999999) server_cmd("sv_restart 1") }
public plugin_natives() { register_library("jctf")
register_native("jctf_get_team", "native_get_team") register_native("jctf_get_flagcarrier", "native_get_flagcarrier") register_native("jctf_get_adrenaline", "native_get_adrenaline") register_native("jctf_add_adrenaline", "native_add_adrenaline") }
public plugin_end() { #if FEATURE_ORPHEU == true
game_disableForwards()
#endif // FEATURE_ORPHEU
DestroyForward(g_iFW_flag) }
public native_get_team(iPlugin, iParams) { /* jctf_get_team(id) */
return g_iTeam[get_param(1)] }
public native_get_flagcarrier(iPlugin, iParams) { /* jctf_get_flagcarrier(id) */
new id = get_param(1)
return g_iFlagHolder[get_opTeam(g_iTeam[id])] == id }
public native_get_adrenaline(iPlugin, iParams) { #if FEATURE_ADRENALINE == true
/* jctf_get_adrenaline(id) */
return g_iAdrenaline[get_param(1)]
#else // FEATURE_ADRENALINE
log_error(AMX_ERR_NATIVE, "jctf_get_adrenaline() does not work ! main jCTF plugin has FEATURE_ADRENALINE = false")
return 0
#endif // FEATURE_ADRENALINE }
public native_add_adrenaline(iPlugin, iParams) { #if FEATURE_ADRENALINE == true
/* jctf_add_adrenaline(id, iAdd, szReason[]) */
new id = get_param(1) new iAdd = get_param(2) new szReason[64]
get_string(3, szReason, charsmax(szReason))
if(strlen(szReason)) player_award(id, 0, 0, iAdd, szReason)
else { g_iAdrenaline[id] = clamp(g_iAdrenaline[id] + iAdd, 0, 100)
player_hudAdrenaline(id) }
return g_iAdrenaline[id]
#else // FEATURE_ADRENALINE
log_error(AMX_ERR_NATIVE, "jctf_add_adrenaline() does not work ! main jCTF plugin has FEATURE_ADRENALINE = false")
return 0
#endif // FEATURE_ADRENALINE }
public flag_spawn(iFlagTeam) { if(g_fFlagBase[iFlagTeam][x] == 0.0 && g_fFlagBase[iFlagTeam][y] == 0.0 && g_fFlagBase[iFlagTeam][z] == 0.0) { new iFindSpawn = find_ent_by_class(g_iMaxPlayers, iFlagTeam == TEAM_BLUE ? "info_player_start" : "info_player_deathmatch")
if(iFindSpawn) { entity_get_vector(iFindSpawn, EV_VEC_origin, g_fFlagBase[iFlagTeam])
server_print("[CTF] %s flag origin not defined, set on player spawn.", g_szTeamName[iFlagTeam]) log_error(AMX_ERR_NOTFOUND, "[CTF] %s flag origin not defined, set on player spawn.", g_szTeamName[iFlagTeam]) } else { server_print("[CTF] WARNING: player spawn for ^"%s^" team does not exist !", g_szTeamName[iFlagTeam]) log_error(AMX_ERR_NOTFOUND, "[CTF] WARNING: player spawn for ^"%s^" team does not exist !", g_szTeamName[iFlagTeam]) set_fail_state("Player spawn unexistent!")
return PLUGIN_CONTINUE } } else server_print("[CTF] %s flag and base spawned at: %.1f %.1f %.1f", g_szTeamName[iFlagTeam], g_fFlagBase[iFlagTeam][x], g_fFlagBase[iFlagTeam][y], g_fFlagBase[iFlagTeam][z])
new ent new Float:fGameTime = get_gametime()
// the FLAG
ent = entity_create(INFO_TARGET)
if(!ent) return flag_spawn(iFlagTeam)
entity_set_model(ent, FLAG_MODEL) entity_set_string(ent, EV_SZ_classname, FLAG_CLASSNAME) entity_set_int(ent, EV_INT_body, iFlagTeam) entity_set_int(ent, EV_INT_sequence, FLAG_ANI_STAND) entity_spawn(ent) entity_set_origin(ent, g_fFlagBase[iFlagTeam]) entity_set_size(ent, FLAG_HULL_MIN, FLAG_HULL_MAX) entity_set_vector(ent, EV_VEC_velocity, FLAG_SPAWN_VELOCITY) entity_set_vector(ent, EV_VEC_angles, FLAG_SPAWN_ANGLES) entity_set_edict(ent, EV_ENT_aiment, 0) entity_set_int(ent, EV_INT_movetype, MOVETYPE_TOSS) entity_set_int(ent, EV_INT_solid, SOLID_TRIGGER) entity_set_float(ent, EV_FL_gravity, 2.0) entity_set_float(ent, EV_FL_nextthink, fGameTime + FLAG_THINK)
g_iFlagEntity[iFlagTeam] = ent g_iFlagHolder[iFlagTeam] = FLAG_HOLD_BASE
// flag BASE
ent = entity_create(INFO_TARGET)
if(!ent) return flag_spawn(iFlagTeam)
entity_set_string(ent, EV_SZ_classname, BASE_CLASSNAME) entity_set_model(ent, FLAG_MODEL) entity_set_int(ent, EV_INT_body, 0) entity_set_int(ent, EV_INT_sequence, FLAG_ANI_BASE) entity_spawn(ent) entity_set_origin(ent, g_fFlagBase[iFlagTeam]) entity_set_vector(ent, EV_VEC_velocity, FLAG_SPAWN_VELOCITY) entity_set_int(ent, EV_INT_movetype, MOVETYPE_TOSS)
if(get_pcvar_num(pCvar_ctf_glows)) entity_set_int(ent, EV_INT_renderfx, kRenderFxGlowShell)
entity_set_float(ent, EV_FL_renderamt, 100.0) entity_set_float(ent, EV_FL_nextthink, fGameTime + BASE_THINK)
if(iFlagTeam == TEAM_RED) entity_set_vector(ent, EV_VEC_rendercolor, Float:{150.0, 0.0, 0.0}) else entity_set_vector(ent, EV_VEC_rendercolor, Float:{0.0, 0.0, 150.0})
g_iBaseEntity[iFlagTeam] = ent
return PLUGIN_CONTINUE }
public flag_think(ent) { if(!is_valid_ent(ent)) return
entity_set_float(ent, EV_FL_nextthink, get_gametime() + FLAG_THINK)
static id static iStatus static iFlagTeam static iSkip[3] static Float:fOrigin[3] static Float:fPlayerOrigin[3]
iFlagTeam = (ent == g_iFlagEntity[TEAM_BLUE] ? TEAM_BLUE : TEAM_RED)
if(g_iFlagHolder[iFlagTeam] == FLAG_HOLD_BASE) fOrigin = g_fFlagBase[iFlagTeam] else entity_get_vector(ent, EV_VEC_origin, fOrigin)
g_fFlagLocation[iFlagTeam] = fOrigin
iStatus = 0
if(++iSkip[iFlagTeam] >= FLAG_SKIPTHINK) { iSkip[iFlagTeam] = 0
if(1 <= g_iFlagHolder[iFlagTeam] <= g_iMaxPlayers) { id = g_iFlagHolder[iFlagTeam]
set_hudmessage(HUD_HELP) show_hudmessage(id, "%L", id, "HUD_YOUHAVEFLAG")
iStatus = 1 } else if(g_iFlagHolder[iFlagTeam] == FLAG_HOLD_DROPPED) iStatus = 2
message_begin(MSG_BROADCAST, gMsg_HostagePos) write_byte(0) write_byte(iFlagTeam) engfunc(EngFunc_WriteCoord, fOrigin[x]) engfunc(EngFunc_WriteCoord, fOrigin[y]) engfunc(EngFunc_WriteCoord, fOrigin[z]) message_end()
message_begin(MSG_BROADCAST, gMsg_HostageK) write_byte(iFlagTeam) message_end()
static iStuck[3]
if(g_iFlagHolder[iFlagTeam] >= FLAG_HOLD_BASE && !(entity_get_int(ent, EV_INT_flags) & FL_ONGROUND)) { if(++iStuck[iFlagTeam] > 4) { flag_autoReturn(ent)
log_message("^"%s^" flag is outside world, auto-returned.", g_szTeamName[iFlagTeam])
return } } else iStuck[iFlagTeam] = 0 }
for(id = 1; id <= g_iMaxPlayers; id++) { if(g_iTeam[id] == TEAM_NONE || g_bBot[id]) continue
/* Check flag proximity for pickup */ if(g_iFlagHolder[iFlagTeam] >= FLAG_HOLD_BASE) { entity_get_vector(id, EV_VEC_origin, fPlayerOrigin)
if(get_distance_f(fOrigin, fPlayerOrigin) <= FLAG_PICKUPDISTANCE) flag_touch(ent, id) }
/* Send dynamic lights to players that have them enabled */ if(g_iFlagHolder[iFlagTeam] != FLAG_HOLD_BASE && g_bLights[id]) { message_begin(MSG_ONE_UNRELIABLE, SVC_TEMPENTITY, _, id) write_byte(TE_DLIGHT) engfunc(EngFunc_WriteCoord, fOrigin[x]) engfunc(EngFunc_WriteCoord, fOrigin[y]) engfunc(EngFunc_WriteCoord, fOrigin[z] + (g_iFlagHolder[iFlagTeam] == FLAG_HOLD_DROPPED ? 32 : -16)) write_byte(FLAG_LIGHT_RANGE) write_byte(iFlagTeam == TEAM_RED ? 100 : 0) write_byte(0) write_byte(iFlagTeam == TEAM_BLUE ? 155 : 0) write_byte(FLAG_LIGHT_LIFE) write_byte(FLAG_LIGHT_DECAY) message_end() }
/* If iFlagTeam's flag is stolen or dropped, constantly warn team players */ if(iStatus && g_iTeam[id] == iFlagTeam) { set_hudmessage(HUD_HELP2) show_hudmessage(id, "%L", id, (iStatus == 1 ? "HUD_ENEMYHASFLAG" : "HUD_RETURNYOURFLAG")) } } }
flag_sendHome(iFlagTeam) { new ent = g_iFlagEntity[iFlagTeam]
entity_set_edict(ent, EV_ENT_aiment, 0) entity_set_origin(ent, g_fFlagBase[iFlagTeam]) entity_set_int(ent, EV_INT_sequence, FLAG_ANI_STAND) entity_set_int(ent, EV_INT_movetype, MOVETYPE_TOSS) entity_set_int(ent, EV_INT_solid, SOLID_TRIGGER) entity_set_vector(ent, EV_VEC_velocity, FLAG_SPAWN_VELOCITY) entity_set_vector(ent, EV_VEC_angles, FLAG_SPAWN_ANGLES)
g_iFlagHolder[iFlagTeam] = FLAG_HOLD_BASE }
flag_take(iFlagTeam, id) { if(g_bProtected[id]) player_removeProtection(id, "PROTECTION_TOUCHFLAG")
new ent = g_iFlagEntity[iFlagTeam]
entity_set_edict(ent, EV_ENT_aiment, id) entity_set_int(ent, EV_INT_movetype, MOVETYPE_FOLLOW) entity_set_int(ent, EV_INT_solid, SOLID_NOT)
g_iFlagHolder[iFlagTeam] = id
message_begin(MSG_BROADCAST, gMsg_ScoreAttrib) write_byte(id) write_byte(g_iTeam[id] == TEAM_BLUE ? 4 : 2) message_end()
player_updateSpeed(id) }
public flag_touch(ent, id) { #if FLAG_IGNORE_BOTS == true
if(!g_bAlive[id] || g_bBot[id]) return
#else // FLAG_IGNORE_BOTS
if(!g_bAlive[id]) return
#endif // FLAG_IGNORE_BOTS
new iFlagTeam = (g_iFlagEntity[TEAM_BLUE] == ent ? TEAM_BLUE : TEAM_RED)
if(1 <= g_iFlagHolder[iFlagTeam] <= g_iMaxPlayers) // if flag is carried we don't care return
new Float:fGameTime = get_gametime()
if(g_fLastDrop[id] > fGameTime) return
new iTeam = g_iTeam[id]
if(!(TEAM_RED <= g_iTeam[id] <= TEAM_BLUE)) return
new iFlagTeamOp = get_opTeam(iFlagTeam) new szName[32]
get_user_name(id, szName, charsmax(szName))
if(iTeam == iFlagTeam) // If the PLAYER is on the same team as the FLAG { if(g_iFlagHolder[iFlagTeam] == FLAG_HOLD_DROPPED) // if the team's flag is dropped, return it to base { flag_sendHome(iFlagTeam)
task_remove(ent)
player_award(id, REWARD_RETURN, "%L", id, "REWARD_RETURN")
ExecuteForward(g_iFW_flag, g_iForwardReturn, FLAG_RETURNED, id, iFlagTeam, false)
new iAssists = 0
for(new i = 1; i <= g_iMaxPlayers; i++) { if(i != id && g_bAssisted[i][iFlagTeam] && g_iTeam[i] == iFlagTeam) { player_award(i, REWARD_RETURN_ASSIST, "%L", i, "REWARD_RETURN_ASSIST")
ExecuteForward(g_iFW_flag, g_iForwardReturn, FLAG_RETURNED, i, iFlagTeam, true)
iAssists++ }
g_bAssisted[i][iFlagTeam] = false }
if(1 <= g_iFlagHolder[iFlagTeamOp] <= g_iMaxPlayers) g_bAssisted[id][iFlagTeamOp] = true
if(iAssists) { new szFormat[64]
format(szFormat, charsmax(szFormat), "%s + %d assists", szName, iAssists)
game_announce(EVENT_RETURNED, iFlagTeam, szFormat) } else game_announce(EVENT_RETURNED, iFlagTeam, szName)
log_message("<%s>%s returned the ^"%s^" flag.", g_szTeamName[iTeam], szName, g_szTeamName[iFlagTeam])
set_hudmessage(HUD_HELP) show_hudmessage(id, "%L", id, "HUD_RETURNEDFLAG")
if(g_bProtected[id]) player_removeProtection(id, "PROTECTION_TOUCHFLAG") } else if(g_iFlagHolder[iFlagTeam] == FLAG_HOLD_BASE && g_iFlagHolder[iFlagTeamOp] == id) // if the PLAYER has the ENEMY FLAG and the FLAG is in the BASE make SCORE { message_begin(MSG_BROADCAST, gMsg_ScoreAttrib) write_byte(id) write_byte(0) message_end()
player_award(id, REWARD_CAPTURE, "%L", id, "REWARD_CAPTURE")
ExecuteForward(g_iFW_flag, g_iForwardReturn, FLAG_CAPTURED, id, iFlagTeamOp, false)
new iAssists = 0
for(new i = 1; i <= g_iMaxPlayers; i++) { if(i != id && g_iTeam[i] > 0 && g_iTeam[i] == iTeam) { if(g_bAssisted[i][iFlagTeamOp]) { player_award(i, REWARD_CAPTURE_ASSIST, "%L", i, "REWARD_CAPTURE_ASSIST")
ExecuteForward(g_iFW_flag, g_iForwardReturn, FLAG_CAPTURED, i, iFlagTeamOp, true)
iAssists++ } else player_award(i, REWARD_CAPTURE_TEAM, "%L", i, "REWARD_CAPTURE_TEAM") }
g_bAssisted[i][iFlagTeamOp] = false }
set_hudmessage(HUD_HELP) show_hudmessage(id, "%L", id, "HUD_CAPTUREDFLAG")
if(iAssists) { new szFormat[64]
format(szFormat, charsmax(szFormat), "%s + %d assists", szName, iAssists)
game_announce(EVENT_SCORE, iFlagTeam, szFormat) } else game_announce(EVENT_SCORE, iFlagTeam, szName)
log_message("<%s>%s captured the ^"%s^" flag. (%d assists)", g_szTeamName[iTeam], szName, g_szTeamName[iFlagTeamOp], iAssists)
emessage_begin(MSG_BROADCAST, gMsg_TeamScore) ewrite_string(g_szCSTeams[iFlagTeam]) ewrite_short(++g_iScore[iFlagTeam]) emessage_end()
flag_sendHome(iFlagTeamOp)
player_updateSpeed(id)
g_fLastDrop[id] = fGameTime + 3.0
if(g_bProtected[id]) player_removeProtection(id, "PROTECTION_TOUCHFLAG") else player_updateRender(id)
if(0 < get_pcvar_num(pCvar_mp_winlimit) <= g_iScore[iFlagTeam]) { emessage_begin(MSG_ALL, SVC_INTERMISSION) // hookable mapend emessage_end()
return }
#if FEATURE_ORPHEU == true
new iFlagRoundEnd = get_pcvar_num(pCvar_ctf_flagendround)
if(iFlagRoundEnd) { static OrpheuFunction:ofEndRoundMsg static OrpheuFunction:ofUpdateTeamScores static OrpheuFunction:ofCheckWinConditions
if(!ofEndRoundMsg) ofEndRoundMsg = OrpheuGetFunction("EndRoundMessage")
if(!ofUpdateTeamScores) ofUpdateTeamScores = OrpheuGetFunction("UpdateTeamScores", "CHalfLifeMultiplay")
if(!ofCheckWinConditions) ofCheckWinConditions = OrpheuGetFunction("CheckWinConditions", "CHalfLifeMultiplay")
new iEvent new iWinStatus new szWinOffset[20] new szWinMessage[16]
switch(iFlagTeam) { case TEAM_RED: { iEvent = 9 iWinStatus = 2 copy(szWinOffset, charsmax(szWinOffset), "m_iNumTerroristWins") copy(szWinMessage, charsmax(szWinMessage), "#Terrorists_Win") }
case TEAM_BLUE: { iEvent = 8 iWinStatus = 1 copy(szWinOffset, charsmax(szWinOffset), "m_iNumCTWins") copy(szWinMessage, charsmax(szWinMessage), "#CTs_Win") } }
OrpheuCallSuper(ofUpdateTeamScores, g_pGameRules) OrpheuCallSuper(ofEndRoundMsg, szWinMessage, iEvent)
OrpheuMemorySetAtAddress(g_pGameRules, "m_iRoundWinStatus", 1, iWinStatus) OrpheuMemorySetAtAddress(g_pGameRules, "m_fTeamCount", 1, get_gametime() + 3.0) OrpheuMemorySetAtAddress(g_pGameRules, "m_bRoundTerminating", 1, true) OrpheuMemorySetAtAddress(g_pGameRules, szWinOffset, 1, g_iScore[iFlagTeam])
OrpheuCallSuper(ofCheckWinConditions, g_pGameRules) }
#else new iFlagRoundEnd = 1
#endif // FEATURE_ORPHEU
if(iFlagRoundEnd && get_pcvar_num(pCvar_ctf_flagcaptureslay)) { for(new i = 1; i <= g_iMaxPlayers; i++) { if(g_iTeam[i] == iFlagTeamOp) { user_kill(i) player_print(i, i, "%L", i, "DEATH_FLAGCAPTURED") } } } } } else { if(g_iFlagHolder[iFlagTeam] == FLAG_HOLD_BASE) { player_award(id, REWARD_STEAL, "%L", id, "REWARD_STEAL")
ExecuteForward(g_iFW_flag, g_iForwardReturn, FLAG_STOLEN, id, iFlagTeam, false)
log_message("<%s>%s stole the ^"%s^" flag.", g_szTeamName[iTeam], szName, g_szTeamName[iFlagTeam]) } else { player_award(id, REWARD_PICKUP, "%L", id, "REWARD_PICKUP")
ExecuteForward(g_iFW_flag, g_iForwardReturn, FLAG_PICKED, id, iFlagTeam, false)
log_message("<%s>%s picked up the ^"%s^" flag.", g_szTeamName[iTeam], szName, g_szTeamName[iFlagTeam]) }
set_hudmessage(HUD_HELP) show_hudmessage(id, "%L", id, "HUD_YOUHAVEFLAG")
flag_take(iFlagTeam, id)
g_bAssisted[id][iFlagTeam] = true
task_remove(ent)
if(g_bProtected[id]) player_removeProtection(id, "PROTECTION_TOUCHFLAG") else player_updateRender(id)
game_announce(EVENT_TAKEN, iFlagTeam, szName) } }
public flag_autoReturn(ent) { task_remove(ent)
new iFlagTeam = (g_iFlagEntity[TEAM_BLUE] == ent ? TEAM_BLUE : (g_iFlagEntity[TEAM_RED] == ent ? TEAM_RED : 0))
if(!iFlagTeam) return
flag_sendHome(iFlagTeam)
ExecuteForward(g_iFW_flag, g_iForwardReturn, FLAG_AUTORETURN, 0, iFlagTeam, false)
game_announce(EVENT_RETURNED, iFlagTeam, NULL)
log_message("^"%s^" flag returned automatically", g_szTeamName[iFlagTeam]) }
public base_think(ent) { if(!is_valid_ent(ent)) return
if(!get_pcvar_num(pCvar_ctf_flagheal)) { entity_set_float(ent, EV_FL_nextthink, get_gametime() + 10.0) /* recheck each 10s seconds */
return }
entity_set_float(ent, EV_FL_nextthink, get_gametime() + BASE_THINK)
new iFlagTeam = (g_iBaseEntity[TEAM_BLUE] == ent ? TEAM_BLUE : TEAM_RED)
if(g_iFlagHolder[iFlagTeam] != FLAG_HOLD_BASE) return
static id static iHealth
id = -1
while((id = find_ent_in_sphere(id, g_fFlagBase[iFlagTeam], BASE_HEAL_DISTANCE)) != 0) { if(1 <= id <= g_iMaxPlayers && g_bAlive[id] && g_iTeam[id] == iFlagTeam) { iHealth = get_user_health(id)
if(iHealth < g_iMaxHealth[id]) { set_user_health(id, iHealth + 1)
player_healingEffect(id) } }
if(id >= g_iMaxPlayers) break } }
public client_putinserver(id) { g_bBot[id] = (is_user_bot(id) ? true : false)
g_iTeam[id] = TEAM_SPEC g_bFirstSpawn[id] = true g_bRestarted[id] = false g_bLights[id] = (g_bBot[id] ? false : (get_pcvar_num(pCvar_ctf_dynamiclights) ? true : false));
task_set(3.0, "client_putinserverPost", id - TASK_PUTINSERVER) }
public client_putinserverPost(id) { id += TASK_PUTINSERVER
player_print(id, id, "%L", id, "JOIN_INFO", "^x04", MOD_TITLE, "^x01", "^x03", MOD_AUTHOR, "^x01")
client_print(id, print_console, "^n%s", SEPARATOR) client_print(id, print_console, " %s v%s - %L", MOD_TITLE, MOD_VERSION, id, "QH_TITLE") client_print(id, print_console, " %L %s^n%s", id, "QH_MADEBY", MOD_AUTHOR, SEPARATOR) client_print(id, print_console, " %L", id, "QH_LINE1") client_print(id, print_console, " %L", id, "QH_LINE2") client_print(id, print_console, " %L", id, "QH_LINE3") client_print(id, print_console, "^n %L", id, "QH_HELP")
#if FEATURE_ADRENALINE == true
client_print(id, print_console, "^n %L", id, "QH_ADRENALINE")
#endif // FEATURE_ADRENALINE
#if FEATURE_ORPHEU == false || FEATURE_BUY == false || FEATURE_C4 == false || FEATURE_ADRENALINE == false
player_print(id, id, "%L", id, "JOIN_NOFEATURES")
#endif // FEATURE_ORPHEU || FEATURE_BUY || FEATURE_C4 || FEATURE_ADRENALINE }
public client_disconnect(id) { player_dropFlag(id) task_remove(id)
g_iTeam[id] = TEAM_NONE g_iAdrenaline[id] = 0 g_iAdrenalineUse[id] = 0
g_bAlive[id] = false g_bLights[id] = false g_bFreeLook[id] = false g_bAssisted[id][TEAM_RED] = false g_bAssisted[id][TEAM_BLUE] = false }
public player_joinTeam() { new id = read_data(1)
if(g_bAlive[id]) return
new szTeam[2]
read_data(2, szTeam, charsmax(szTeam))
switch(szTeam[0]) { case 'T': { if(g_iTeam[id] == TEAM_RED && g_bFirstSpawn[id]) { new iRespawn = get_pcvar_num(pCvar_ctf_respawntime)
if(iRespawn > 0) player_respawn(id - TASK_RESPAWN, iRespawn + 1)
task_remove(id - TASK_TEAMBALANCE) task_set(1.0, "player_checkTeam", id - TASK_TEAMBALANCE) }
g_iTeam[id] = TEAM_RED }
case 'C': { if(g_iTeam[id] == TEAM_BLUE && g_bFirstSpawn[id]) { new iRespawn = get_pcvar_num(pCvar_ctf_respawntime)
if(iRespawn > 0) player_respawn(id - TASK_RESPAWN, iRespawn + 1)
task_remove(id - TASK_TEAMBALANCE) task_set(1.0, "player_checkTeam", id - TASK_TEAMBALANCE) }
g_iTeam[id] = TEAM_BLUE }
case 'U': { g_iTeam[id] = TEAM_NONE g_bFirstSpawn[id] = true }
default: { player_screenFade(id, {0,0,0,0}, 0.0, 0.0, FADE_OUT, false) player_allowChangeTeam(id)
g_iTeam[id] = TEAM_SPEC g_bFirstSpawn[id] = true } } }
public player_spawn(id) { if(!is_user_alive(id) || (!g_bRestarted[id] && g_bAlive[id])) return
/* make sure we have team right */
switch(cs_get_user_team(id)) { case CS_TEAM_T: g_iTeam[id] = TEAM_RED case CS_TEAM_CT: g_iTeam[id] = TEAM_BLUE default: return }
g_bAlive[id] = true g_bDefuse[id] = false g_bBuyZone[id] = true g_bFreeLook[id] = false g_fLastBuy[id] = Float:{0.0, 0.0, 0.0, 0.0}
task_remove(id - TASK_PROTECTION) task_remove(id - TASK_EQUIPAMENT) task_remove(id - TASK_DAMAGEPROTECTION) task_remove(id - TASK_TEAMBALANCE) task_remove(id - TASK_ADRENALINE) task_remove(id - TASK_DEFUSE)
#if FEATURE_BUY == true
task_set(0.1, "player_spawnEquipament", id - TASK_EQUIPAMENT)
#endif // FEATURE_BUY
task_set(0.2, "player_checkVitals", id - TASK_CHECKHP)
#if FEATURE_ADRENALINE == true
player_hudAdrenaline(id)
#endif // FEATURE_ADRENALINE
new iProtection = get_pcvar_num(pCvar_ctf_protection)
if(iProtection > 0) player_protection(id - TASK_PROTECTION, iProtection)
message_begin(MSG_BROADCAST, gMsg_ScoreAttrib) write_byte(id) write_byte(0) message_end()
if(g_bFirstSpawn[id] || g_bRestarted[id]) { g_bRestarted[id] = false g_bFirstSpawn[id] = false
cs_set_user_money(id, get_pcvar_num(pCvar_mp_startmoney)) } else if(g_bSuicide[id]) { g_bSuicide[id] = false
player_print(id, id, "%L", id, "SPAWN_NOMONEY") } else cs_set_user_money(id, clamp((cs_get_user_money(id) + get_pcvar_num(pCvar_ctf_spawnmoney)), get_pcvar_num(pCvar_mp_startmoney), 16000)) }
public player_checkVitals(id) { id += TASK_CHECKHP
if(!g_bAlive[id]) return
/* in case player is VIP or whatever special class that sets armor */ new CsArmorType:iArmorType new iArmor = cs_get_user_armor(id, iArmorType)
g_iMaxArmor[id] = (iArmor > 0 ? iArmor : 100) g_iMaxHealth[id] = get_user_health(id) }
#if FEATURE_BUY == true
public player_spawnEquipament(id) { id += TASK_EQUIPAMENT
if(!g_bAlive[id]) return
strip_user_weapons(id)
if(get_pcvar_num(pCvar_ctf_spawn_knife)) give_item(id, g_szWeaponEntity[W_KNIFE])
new szWeapon[3][24]
get_pcvar_string(pCvar_ctf_spawn_prim, szWeapon[1], charsmax(szWeapon[])) get_pcvar_string(pCvar_ctf_spawn_sec, szWeapon[2], charsmax(szWeapon[]))
for(new iWeapon, i = 2; i >= 1; i--) { iWeapon = 0
if(strlen(szWeapon[i])) { for(new w = 1; w < sizeof g_szWeaponCommands; w++) { if(g_iWeaponSlot[w] == i && equali(szWeapon[i], g_szWeaponCommands[w][0])) { iWeapon = w break } }
if(iWeapon) { give_item(id, g_szWeaponEntity[iWeapon]) cs_set_user_bpammo(id, iWeapon, g_iBPAmmo[iWeapon]) } else log_error(AMX_ERR_NOTFOUND, "Invalid %s weapon: ^"%s^", please fix ctf_spawn_%s cvar", (i == 1 ? "primary" : "secondary"), szWeapon[i], (i == 1 ? "prim" : "sec")) } } }
#endif // FEATURE_BUY
public player_protection(id, iStart) { id += TASK_PROTECTION
if(!(TEAM_RED <= g_iTeam[id] <= TEAM_BLUE)) return
static iCount[33]
if(iStart) { iCount[id] = iStart + 1
g_bProtected[id] = true
player_updateRender(id) }
if(--iCount[id] > 0) { set_hudmessage(HUD_RESPAWN) show_hudmessage(id, "%L", id, "PROTECTION_LEFT", iCount[id])
task_set(1.0, "player_protection", id - TASK_PROTECTION) } else player_removeProtection(id, "PROTECTION_EXPIRED") }
public player_removeProtection(id, szLang[]) { if(!(TEAM_RED <= g_iTeam[id] <= TEAM_BLUE)) return
g_bProtected[id] = false
task_remove(id - TASK_PROTECTION) task_remove(id - TASK_DAMAGEPROTECTION)
set_hudmessage(HUD_PROTECTION) show_hudmessage(id, "%L", id, szLang)
player_updateRender(id) }
public player_currentWeapon(id) { if(!g_bAlive[id]) return
static bool:bZoom[33]
new iZoom = read_data(1)
if(1 < iZoom <= 90) /* setFOV event */ bZoom[id] = bool:(iZoom <= 40)
else /* CurWeapon event */ { if(!bZoom[id]) /* if not zooming, get weapon speed */ g_fWeaponSpeed[id] = g_fWeaponRunSpeed[read_data(2)]
else /* if zooming, set zoom speed */ g_fWeaponSpeed[id] = g_fWeaponRunSpeed[0]
player_updateSpeed(id) } }
public client_PostThink(id) { if(!g_bAlive[id]) return
static iOffset static iShield[33]
iOffset = get_pdata_int(id, m_iUserPrefs)
if(iOffset & (1<<24)) /* Shield available */ { if(iOffset & (1<<16)) /* Uses shield */ { if(iShield[id] < 2) /* Trigger only once */ { iShield[id] = 2
g_fWeaponSpeed[id] = 180.0
player_updateSpeed(id) } } else if(iShield[id] == 2) /* Doesn't use the shield anymore */ { iShield[id] = 1
g_fWeaponSpeed[id] = 250.0
player_updateSpeed(id) } } else if(iShield[id]) /* Shield not available anymore */ iShield[id] = 0 }
public player_useWeapon(ent) { if(!is_valid_ent(ent)) return
static id
id = entity_get_edict(ent, EV_ENT_owner)
if(1 <= id <= g_iMaxPlayers && g_bAlive[id]) { if(g_bProtected[id]) player_removeProtection(id, "PROTECTION_WEAPONUSE")
#if FEATURE_ADRENALINE == true else if(g_iAdrenalineUse[id] == ADRENALINE_BERSERK) { set_pdata_float(ent, m_flNextPrimaryAttack, get_pdata_float(ent, m_flNextPrimaryAttack, 4) * BERSERKER_SPEED1) set_pdata_float(ent, m_flNextSecondaryAttack, get_pdata_float(ent, m_flNextSecondaryAttack, 4) * BERSERKER_SPEED2) } #endif // FEATURE_ADRENALINE } }
#if FEATURE_ADRENALINE == true
public player_useWeaponSec(ent) { if(!is_valid_ent(ent)) return
static id
id = entity_get_edict(ent, EV_ENT_owner)
if(1 <= id <= g_iMaxPlayers && g_bAlive[id] && g_iAdrenalineUse[id] == ADRENALINE_BERSERK) { set_pdata_float(ent, m_flNextPrimaryAttack, get_pdata_float(ent, m_flNextPrimaryAttack, 4) * BERSERKER_SPEED1) set_pdata_float(ent, m_flNextSecondaryAttack, get_pdata_float(ent, m_flNextSecondaryAttack, 4) * BERSERKER_SPEED2) } }
#endif // FEATURE_ADRENALINE
public player_damage(id, iWeapon, iAttacker, Float:fDamage, iType) { if(g_bProtected[id]) { player_updateRender(id, fDamage)
task_remove(id - TASK_DAMAGEPROTECTION) task_set(0.1, "player_damageProtection", id - TASK_DAMAGEPROTECTION)
entity_set_vector(id, EV_VEC_punchangle, FLAG_SPAWN_ANGLES)
return HAM_SUPERCEDE }
#if FEATURE_ADRENALINE == true
else if(1 <= iAttacker <= g_iMaxPlayers && g_iAdrenalineUse[iAttacker] == ADRENALINE_BERSERK && g_iTeam[iAttacker] != g_iTeam[id]) { SetHamParamFloat(4, fDamage * BERSERKER_DAMAGE)
new iOrigin[3]
get_user_origin(id, iOrigin)
message_begin(MSG_PVS, SVC_TEMPENTITY, iOrigin) write_byte(TE_BLOODSPRITE) write_coord(iOrigin[x] + random_num(-15, 15)) write_coord(iOrigin[y] + random_num(-15, 15)) write_coord(iOrigin[z] + random_num(-15, 15)) write_short(gSpr_blood2) write_short(gSpr_blood1) write_byte(248) write_byte(18) message_end()
return HAM_OVERRIDE }
#endif // FEATURE_ADRENALINE
return HAM_IGNORED }
public player_damageProtection(id) { id += TASK_DAMAGEPROTECTION
if(g_bAlive[id]) player_updateRender(id) }
public player_killed(id, killer) { g_bAlive[id] = false g_bBuyZone[id] = false
task_remove(id - TASK_RESPAWN) task_remove(id - TASK_PROTECTION) task_remove(id - TASK_EQUIPAMENT) task_remove(id - TASK_DAMAGEPROTECTION) task_remove(id - TASK_TEAMBALANCE) task_remove(id - TASK_ADRENALINE) task_remove(id - TASK_DEFUSE)
new szHint[10]
#if FEATURE_C4 == true && FEATURE_ADRENALINE == true
formatex(szHint, charsmax(szHint), "HINT_%d", random_num(1, 12))
#else
new iHint
while((iHint = random_num(1, 12))) { #if FEATURE_ADRENALINE == false if(iHint == 1 || iHint == 7 || iHint == 9) continue #endif // FEATURE_ADRENALINE
#if FEATURE_C4 == false if(iHint == 4 || iHint == 8 || iHint == 10) continue #endif // FEATURE_C4
break }
formatex(szHint, charsmax(szHint), "HINT_%d", iHint)
#endif // FEATURE_C4 || FEATURE_ADRENALINE
set_hudmessage(HUD_HINT) show_hudmessage(id, "%L: %L", id, "HINT", id, szHint) client_print(id, print_console, "%s%L: %L", CONSOLE_PREFIX, id, "HINT", id, szHint)
#if FEATURE_C4 == true
new iWeapon = entity_get_edict(id, EV_ENT_dmg_inflictor) new szWeapon[10] new bool:bC4 = false
if(iWeapon > g_iMaxPlayers && is_valid_ent(iWeapon)) { entity_get_string(iWeapon, EV_SZ_classname, szWeapon, charsmax(szWeapon))
if(equal(szWeapon, GRENADE) && get_pdata_int(iWeapon, 96) & (1<<8)) { message_begin(MSG_ALL, gMsg_DeathMsg) write_byte(killer) write_byte(id) write_byte(0) write_string("c4") message_end()
bC4 = true } }
#endif // FEATURE_C4
if(id == killer || !(1 <= killer <= g_iMaxPlayers)) { g_bSuicide[id] = true
player_award(id, PENALTY_SUICIDE, "%L", id, "PENALTY_SUICIDE")
#if FEATURE_C4 == true
if(bC4) player_setScore(id, -1, 1)
#endif // FEATURE_C4
} else if(1 <= killer <= g_iMaxPlayers) { if(g_iTeam[id] == g_iTeam[killer]) {
#if FEATURE_C4 == true
if(bC4) { player_setScore(killer, -1, 0) cs_set_user_money(killer, clamp(cs_get_user_money(killer) - 3300, 0, 16000), 1) }
#endif // FEATURE_C4
player_award(killer, PENALTY_TEAMKILL, "%L", killer, "PENALTY_TEAMKILL") } else {
#if FEATURE_C4 == true
if(bC4) { player_setScore(killer, -1, 0) player_setScore(id, 0, 1)
cs_set_user_money(killer, clamp(cs_get_user_money(killer) + 300, 0, 16000), 1) }
#endif // FEATURE_C4
if(id == g_iFlagHolder[g_iTeam[killer]]) { g_bAssisted[killer][g_iTeam[killer]] = true
player_award(killer, REWARD_KILLCARRIER, "%L", killer, "REWARD_KILLCARRIER")
message_begin(MSG_BROADCAST, gMsg_ScoreAttrib) write_byte(id) write_byte(0) message_end() } else { player_spawnItem(id) player_award(killer, REWARD_KILL, "%L", killer, "REWARD_KILL") } } }
#if FEATURE_ADRENALINE == true
if(g_iAdrenalineUse[id]) {
switch(g_iAdrenalineUse[id]) { case ADRENALINE_SPEED: { message_begin(MSG_BROADCAST, SVC_TEMPENTITY) write_byte(TE_KILLBEAM) write_short(id) message_end() } }
g_iAdrenaline[id] = 0 g_iAdrenalineUse[id] = 0
player_updateRender(id) player_hudAdrenaline(id) }
#endif // FEATURE_ADRENALINE
new iRespawn = get_pcvar_num(pCvar_ctf_respawntime)
if(iRespawn > 0) player_respawn(id - TASK_RESPAWN, iRespawn)
player_dropFlag(id) player_allowChangeTeam(id)
task_set(1.0, "player_checkTeam", id - TASK_TEAMBALANCE) }
public player_checkTeam(id) { id += TASK_TEAMBALANCE
if(!(TEAM_RED <= g_iTeam[id] <= TEAM_BLUE) || g_bAlive[id] || !get_pcvar_num(pCvar_mp_autoteambalance)) return
new iPlayers[3] new iTeam = g_iTeam[id] new iOpTeam = get_opTeam(iTeam)
for(new i = 1; i <= g_iMaxPlayers; i++) { if(TEAM_RED <= g_iTeam[i] <= TEAM_BLUE) iPlayers[g_iTeam[i]]++ }
if((iPlayers[iTeam] > 1 && !iPlayers[iOpTeam]) || iPlayers[iTeam] > (iPlayers[iOpTeam] + 1)) { player_allowChangeTeam(id)
engclient_cmd(id, "jointeam", (iOpTeam == TEAM_BLUE ? "2" : "1"))
set_task(2.0, "player_forceJoinClass", id)
player_print(id, id, "%L", id, "DEATH_TRANSFER", "^x04", id, g_szMLTeamName[iOpTeam], "^x01") } }
public player_forceJoinClass(id) { engclient_cmd(id, "joinclass", "5") }
public player_respawn(id, iStart) { id += TASK_RESPAWN
if(!(TEAM_RED <= g_iTeam[id] <= TEAM_BLUE) || g_bAlive[id]) return
static iCount[33]
if(iStart) iCount[id] = iStart + 1
set_hudmessage(HUD_RESPAWN)
if(--iCount[id] > 0) { show_hudmessage(id, "%L", id, "RESPAWNING_IN", iCount[id]) client_print(id, print_console, "%L", id, "RESPAWNING_IN", iCount[id])
task_set(1.0, "player_respawn", id - TASK_RESPAWN) } else { show_hudmessage(id, "%L", id, "RESPAWNING") client_print(id, print_console, "%L", id, "RESPAWNING")
entity_set_int(id, EV_INT_deadflag, DEAD_RESPAWNABLE) entity_set_int(id, EV_INT_iuser1, 0) entity_think(id) entity_spawn(id) set_user_health(id, 100) } }
#if FEATURE_ADRENALINE == true
public player_cmd_buySpawn(id) { if(g_bAlive[id] || !(TEAM_RED <= g_iTeam[id] <= TEAM_BLUE)) player_print(id, id, "%L", id, "INSTANTSPAWN_NOTEAM")
else if(g_iAdrenaline[id] < INSTANTSPAWN_COST) player_print(id, id, "%L", id, "INSTANTSPAWN_NOADRENALINE", INSTANTSPAWN_COST)
else { g_iAdrenaline[id] -= INSTANTSPAWN_COST
player_print(id, id, "%L", id, "INSTANTSPAWN_BOUGHT", INSTANTSPAWN_COST)
task_remove(id) player_respawn(id - TASK_RESPAWN, -1) }
return PLUGIN_HANDLED }
#endif // FEATURE_ADRENALINE
public player_cmd_dropFlag(id) { if(!g_bAlive[id] || id != g_iFlagHolder[get_opTeam(g_iTeam[id])]) player_print(id, id, "%L", id, "DROPFLAG_NOFLAG")
else { new iOpTeam = get_opTeam(g_iTeam[id])
player_dropFlag(id) player_award(id, PENALTY_DROP, "%L", id, "PENALTY_MANUALDROP")
ExecuteForward(g_iFW_flag, g_iForwardReturn, FLAG_MANUALDROP, id, iOpTeam, false)
g_bAssisted[id][iOpTeam] = false }
return PLUGIN_HANDLED }
public player_dropFlag(id) { new iOpTeam = get_opTeam(g_iTeam[id])
if(id != g_iFlagHolder[iOpTeam]) return
new ent = g_iFlagEntity[iOpTeam]
if(!is_valid_ent(ent)) return
g_fLastDrop[id] = get_gametime() + 2.0 g_iFlagHolder[iOpTeam] = FLAG_HOLD_DROPPED
entity_set_edict(ent, EV_ENT_aiment, -1) entity_set_int(ent, EV_INT_movetype, MOVETYPE_TOSS) entity_set_int(ent, EV_INT_sequence, FLAG_ANI_DROPPED) entity_set_int(ent, EV_INT_solid, SOLID_TRIGGER) entity_set_origin(ent, g_fFlagLocation[iOpTeam])
new Float:fReturn = get_pcvar_float(pCvar_ctf_flagreturn)
if(fReturn > 0) task_set(fReturn, "flag_autoReturn", ent)
if(g_bAlive[id]) { new Float:fVelocity[3]
velocity_by_aim(id, 200, fVelocity)
fVelocity[z] = 0.0
entity_set_vector(ent, EV_VEC_velocity, fVelocity)
player_updateSpeed(id) player_updateRender(id)
message_begin(MSG_BROADCAST, gMsg_ScoreAttrib) write_byte(id) write_byte(0) message_end() } else entity_set_vector(ent, EV_VEC_velocity, FLAG_DROP_VELOCITY)
new szName[32]
get_user_name(id, szName, charsmax(szName))
game_announce(EVENT_DROPPED, iOpTeam, szName)
ExecuteForward(g_iFW_flag, g_iForwardReturn, FLAG_DROPPED, id, iOpTeam, false)
g_fFlagDropped[iOpTeam] = get_gametime()
log_message("<%s>%s dropped the ^"%s^" flag.", g_szTeamName[g_iTeam[id]], szName, g_szTeamName[iOpTeam]) }
public player_cmd_say(id) { static Float:fLastUsage[33]
new Float:fGameTime = get_gametime()
if((fLastUsage[id] + 0.5) > fGameTime) return PLUGIN_HANDLED
fLastUsage[id] = fGameTime
new szMsg[128]
read_args(szMsg, charsmax(szMsg)) remove_quotes(szMsg) trim(szMsg)
if(equal(szMsg, NULL)) return PLUGIN_HANDLED
if(equal(szMsg[0], "@")) return PLUGIN_CONTINUE
new szFormat[192] new szName[32]
get_user_name(id, szName, charsmax(szName))
switch(g_iTeam[id]) { case TEAM_RED, TEAM_BLUE: formatex(szFormat, charsmax(szFormat), "^x01%s^x03%s ^x01: %s", (g_bAlive[id] ? NULL : "^x01*DEAD* "), szName, szMsg) case TEAM_NONE, TEAM_SPEC: formatex(szFormat, charsmax(szFormat), "^x01*SPEC* ^x03%s ^x01: %s", szName, szMsg) }
for(new i = 1; i <= g_iMaxPlayers; i++) { if(i == id || g_iTeam[i] == TEAM_NONE || g_bAlive[i] == g_bAlive[id] || g_bBot[id]) continue
message_begin(MSG_ONE, gMsg_SayText, _, i) write_byte(id) write_string(szFormat) message_end() }
#if FEATURE_BUY == true
if(equali(szMsg, "/buy")) { player_menu_buy(id, 0)
return CHAT_SHOW_COMMANDS ? PLUGIN_CONTINUE : PLUGIN_HANDLED }
#endif // FEATURE_BUY
#if FEATURE_ADRENALINE == true
if(equali(szMsg, "/spawn")) { player_cmd_buySpawn(id)
return CHAT_SHOW_COMMANDS ? PLUGIN_CONTINUE : PLUGIN_HANDLED }
if(equali(szMsg, "/adrenaline")) { player_cmd_adrenaline(id)
return CHAT_SHOW_COMMANDS ? PLUGIN_CONTINUE : PLUGIN_HANDLED }
#endif // FEATURE_ADRENALINE
if(equali(szMsg, "/help")) { player_cmd_help(id)
return CHAT_SHOW_COMMANDS ? PLUGIN_CONTINUE : PLUGIN_HANDLED }
if(equali(szMsg, "/dropflag")) { player_cmd_dropFlag(id)
return CHAT_SHOW_COMMANDS ? PLUGIN_CONTINUE : PLUGIN_HANDLED }
if(equali(szMsg, "/lights", 7)) { player_cmd_setLights(id, szMsg[8])
return CHAT_SHOW_COMMANDS ? PLUGIN_CONTINUE : PLUGIN_HANDLED }
if(equali(szMsg, "/sounds", 7)) { player_cmd_setSounds(id, szMsg[8])
return CHAT_SHOW_COMMANDS ? PLUGIN_CONTINUE : PLUGIN_HANDLED }
return PLUGIN_CONTINUE }
public player_cmd_sayTeam(id) { static Float:fLastUsage[33]
new Float:fGameTime = get_gametime()
if((fLastUsage[id] + 0.5) > fGameTime) return PLUGIN_HANDLED
fLastUsage[id] = fGameTime
new szMsg[128]
read_args(szMsg, charsmax(szMsg)) remove_quotes(szMsg) trim(szMsg)
if(equal(szMsg, NULL)) return PLUGIN_HANDLED
if(equal(szMsg[0], "@")) return PLUGIN_CONTINUE
new szFormat[192] new szName[32]
get_user_name(id, szName, charsmax(szName))
switch(g_iTeam[id]) { case TEAM_RED, TEAM_BLUE: formatex(szFormat, charsmax(szFormat), "^x01%s(%L) ^x03%s ^x01: %s", (g_bAlive[id] ? NULL : "*DEAD* "), LANG_PLAYER, g_szMLFlagTeam[g_iTeam[id]], szName, szMsg) case TEAM_NONE, TEAM_SPEC: formatex(szFormat, charsmax(szFormat), "^x01*SPEC*(%L) ^x03%s ^x01: %s", LANG_PLAYER, g_szMLTeamName[TEAM_SPEC], szName, szMsg) }
for(new i = 1; i <= g_iMaxPlayers; i++) { if(i == id || g_iTeam[i] == TEAM_NONE || g_iTeam[i] != g_iTeam[id] || g_bAlive[i] == g_bAlive[id] || g_bBot[id]) continue
message_begin(MSG_ONE, gMsg_SayText, _, i) write_byte(id) write_string(szFormat) message_end() }
#if FEATURE_BUY == true
if(equali(szMsg, "/buy")) { player_menu_buy(id, 0)
return CHAT_SHOW_COMMANDS ? PLUGIN_CONTINUE : PLUGIN_HANDLED }
#endif // FEATURE_BUY
#if FEATURE_ADRENALINE == true
if(equali(szMsg, "/spawn")) { player_cmd_buySpawn(id)
return CHAT_SHOW_COMMANDS ? PLUGIN_CONTINUE : PLUGIN_HANDLED }
if(equali(szMsg, "/adrenaline")) { player_cmd_adrenaline(id)
return CHAT_SHOW_COMMANDS ? PLUGIN_CONTINUE : PLUGIN_HANDLED }
#endif // FEATURE_ADRENALINE
if(equali(szMsg, "/dropflag")) { player_cmd_dropFlag(id)
return CHAT_SHOW_COMMANDS ? PLUGIN_CONTINUE : PLUGIN_HANDLED }
if(equali(szMsg, "/help")) { player_cmd_help(id)
return CHAT_SHOW_COMMANDS ? PLUGIN_CONTINUE : PLUGIN_HANDLED }
return PLUGIN_CONTINUE }
public player_cmd_help(id) { client_cmd(id, "hideconsole;toggleconsole")
client_print(id, print_console, "^n^n^n^n%s", SEPARATOR) client_print(id, print_console, " %s v%s - %L^n Mod by %s", MOD_TITLE, MOD_VERSION, id, "HELP_TITLE", MOD_AUTHOR) client_print(id, print_console, SEPARATOR) client_print(id, print_console, " 1. %L^n 2. %L^n 3. %L^n 4. %L", id, "HELP_1", id, "HELP_2", id, "HELP_3", id, "HELP_4") client_print(id, print_console, "^n --- 1: %L ---^n", id, "HELP_1") client_print(id, print_console, "%L", id, "HELP_1_LINE1") client_print(id, print_console, "%L", id, "HELP_1_LINE2") client_print(id, print_console, "%L", id, "HELP_1_LINE3") client_print(id, print_console, "%L", id, "HELP_1_LINE4") client_print(id, print_console, "^n --- 2: %L ---", id, "HELP_2") client_print(id, print_console, "%L", id, "HELP_2_NOTE") client_print(id, print_console, "%L", id, "HELP_2_LINE1") client_print(id, print_console, "%L", id, "HELP_2_LINE2")
#if FEATURE_ADRENALINE == true client_print(id, print_console, "%L", id, "HELP_2_LINE3", INSTANTSPAWN_COST) #endif // FEATURE_ADRENALINE
client_print(id, print_console, "%L", id, "HELP_2_LINE4")
#if FEATURE_ADRENALINE == true client_print(id, print_console, "%L", id, "HELP_2_LINE5") #endif // FEATURE_ADRENALINE
client_print(id, print_console, "^n --- 3: %L ---", id, "HELP_3")
#if FEATURE_ORPHEU == false client_print(id, print_console, " * %L", id, "HELP_3_INFROUND", id, "OFF") client_print(id, print_console, " * %L", id, "HELP_3_ROUNDEND", id, "OFF") #else client_print(id, print_console, " * %L", id, "HELP_3_INFROUND", id, get_pcvar_num(pCvar_ctf_infiniteround) ? "ON" : "OFF") client_print(id, print_console, " * %L", id, "HELP_3_ROUNDEND", id, get_pcvar_num(pCvar_ctf_flagendround) ? "ON" : "OFF") #endif
client_print(id, print_console, " * %L", id, "HELP_3_CAPTURESLAY", id, get_pcvar_num(pCvar_ctf_flagcaptureslay) ? "ON" : "OFF")
#if FEATURE_BUY == true client_print(id, print_console, " * %L", id, "HELP_3_BUY", id, "ON") #else client_print(id, print_console, " * %L", id, "HELP_3_BUY", id, "OFF") #endif
#if FEATURE_C4 == true client_print(id, print_console, " * %L", id, "HELP_3_C4", id, "ON") #else client_print(id, print_console, " * %L", id, "HELP_3_C4", id, "OFF") #endif
#if FEATURE_ADRENALINE == true client_print(id, print_console, " * %L", id, "HELP_3_ADRENALINE", id, "ON") #else client_print(id, print_console, " * %L", id, "HELP_3_ADRENALINE", id, "OFF") #endif
client_print(id, print_console, " * %L", id, "HELP_3_FLAGHEAL", id, get_pcvar_num(pCvar_ctf_flagheal) ? "ON" : "OFF") client_print(id, print_console, " * %L", id, "HELP_3_RESPAWN", get_pcvar_num(pCvar_ctf_respawntime)) client_print(id, print_console, " * %L", id, "HELP_3_PROTECTION", get_pcvar_num(pCvar_ctf_protection)) client_print(id, print_console, " * %L", id, "HELP_3_FLAGRETURN", get_pcvar_num(pCvar_ctf_flagreturn)) client_print(id, print_console, " * %L", id, "HELP_3_WEAPONSTAY", get_pcvar_num(pCvar_ctf_weaponstay)) client_print(id, print_console, " * %L", id, "HELP_3_ITEMDROP", get_pcvar_num(pCvar_ctf_itempercent))
client_print(id, print_console, "^n --- 4: %L ---", id, "HELP_4") client_print(id, print_console, " %L: http://forums.alliedmods.net/showthread.php?t=132115", id, "HELP_4_LINE1") client_print(id, print_console, " %L: http://thehunters.ro/jctf", id, "HELP_4_LINE2") client_print(id, print_console, SEPARATOR)
return PLUGIN_HANDLED }
public player_cmd_setLights(id, const szMsg[]) { switch(szMsg[1]) { case 'n': { g_bLights[id] = true player_print(id, id, "%L", id, "LIGHTS_ON", "^x04", "^x01") }
case 'f': { g_bLights[id] = false player_print(id, id, "%L", id, "LIGHTS_OFF", "^x04", "^x01") }
default: player_print(id, id, "%L", id, "LIGHTS_INVALID", "^x04", "^x01", "^x04") }
return PLUGIN_HANDLED }
public player_cmd_setSounds(id, const szMsg[]) { if(equali(szMsg, "test")) { player_print(id, id, "%L", id, "SOUNDS_TEST", "^x04 Red Flag Taken^x01") client_cmd(id, "mp3 play ^"sound/ctf/red_flag_taken.mp3^"")
return PLUGIN_HANDLED }
new iVol = (strlen(szMsg) ? str_to_num(szMsg) : -1)
if(0 <= iVol <= 10) { client_cmd(id, "mp3volume %.2f", iVol == 0 ? 0.0 : iVol * 0.1) player_print(id, id, "%L", id, "SOUNDS_SET", "^x04", iVol) } else player_print(id, id, "%L", id, "SOUNDS_INVALID", "^x04 0^x01", "^x04 10^x01", "^x04 test")
return PLUGIN_HANDLED }
#if FEATURE_ADRENALINE == true
public player_cmd_adrenaline(id) { player_hudAdrenaline(id)
if(!(TEAM_RED <= g_iTeam[id] <= TEAM_BLUE) || !g_bAlive[id]) return player_print(id, id, "%L", id, "ADR_ALIVE")
if(g_iAdrenalineUse[id]) return player_print(id, id, "%L", id, "ADR_USING")
if(g_iAdrenaline[id] < 100) return player_print(id, id, "%L", id, "ADR_MORE", 100)
new szFormat[256]
formatex(szFormat, charsmax(szFormat), "\r%L:^n^n\w1. \y%L \d(%L)^n\w2. \y%L \d(%L)^n\w3. \y%L \d(%L)^n\w4. \y%L \d(%L)^n^n\d\w0. %L", id, "ADR_MENU_TITLE", id, "ADR_SPEED", id, "ADR_SPEED_DESC", id, "ADR_BERSERK", id, "ADR_BERSERK_DESC", id, "ADR_REGENERATE", id, "ADR_REGENERATE_DESC", id, "ADR_INVISIBILITY", id, "ADR_INVISIBILITY_DESC", id, "EXIT" )
show_menu(id, MENU_KEYS_ADRENALINE, szFormat, -1, MENU_ADRENALINE)
return PLUGIN_HANDLED }
public player_key_adrenaline(id, iKey) { if(!(TEAM_RED <= g_iTeam[id] <= TEAM_BLUE) || !g_bAlive[id]) return player_print(id, id, "%L", id, "ADR_ALIVE")
if(g_iAdrenalineUse[id]) return player_print(id, id, "%L", id, "ADR_USING")
if(g_iAdrenaline[id] < 100) return player_print(id, id, "%L", id, "ADR_USING", 100)
iKey += 1
if(1 <= iKey <= 4) player_useAdrenaline(id, iKey)
return PLUGIN_HANDLED }
public player_useAdrenaline(id, iUse) { if(!(1 <= iUse <= 4)) return PLUGIN_HANDLED
if(!(TEAM_RED <= g_iTeam[id] <= TEAM_BLUE) || !g_bAlive[id]) return player_print(id, id, "%L", id, "ADR_ALIVE")
if(g_iAdrenalineUse[id]) return player_print(id, id, "%L", id, "ADR_USING")
if(g_iAdrenaline[id] < 100) return player_print(id, id, "%L", id, "ADR_USING", 100)
if(g_bProtected[id]) player_removeProtection(id, "PROTECTION_ADRENALINE")
g_iAdrenalineUse[id] = iUse
task_set(0.25, "player_adrenalineDrain", id - TASK_ADRENALINE)
if(iUse == ADRENALINE_SPEED) { message_begin(MSG_BROADCAST, SVC_TEMPENTITY) write_byte(TE_BEAMFOLLOW) write_short(id) write_short(gSpr_trail) write_byte(8) // life in 0.1's write_byte(6) // line width in 0.1's write_byte(255) write_byte(255) write_byte(0) write_byte(255) // brightness message_end()
player_updateSpeed(id) }
player_updateRender(id)
new iOrigin[3]
get_user_origin(id, iOrigin)
message_begin(MSG_PVS, SVC_TEMPENTITY, iOrigin) write_byte(TE_IMPLOSION) write_coord(iOrigin[x]) write_coord(iOrigin[y]) write_coord(iOrigin[z]) write_byte(128) // radius write_byte(32) // count write_byte(4) // life in 0.1's message_end()
emit_sound(id, CHAN_ITEM, SND_ADRENALINE, VOL_NORM, ATTN_NORM, 0, 255)
return PLUGIN_HANDLED }
public player_adrenalineDrain(id) { id += TASK_ADRENALINE
if(!g_bAlive[id] || !g_iAdrenalineUse[id] || !(TEAM_RED <= g_iTeam[id] <= TEAM_BLUE)) { g_iAdrenaline[id] = 0 return }
if(g_iAdrenaline[id] > 0) { new iDrain = (player_hasFlag(id) ? 2 : 1)
g_iAdrenaline[id] = clamp(g_iAdrenaline[id] - (g_iAdrenalineUse[id] == ADRENALINE_REGENERATE ? iDrain : iDrain * 2), 0, 100)
switch(g_iAdrenalineUse[id]) { case ADRENALINE_REGENERATE: { new iHealth = get_user_health(id)
if(iHealth < (g_iMaxHealth[id] + REGENERATE_EXTRAHP)) set_user_health(id, iHealth + 1)
else { new CsArmorType:ArmorType new iArmor = cs_get_user_armor(id, ArmorType)
if(iArmor < g_iMaxArmor[id]) cs_set_user_armor(id, iArmor + 1, ArmorType) }
player_healingEffect(id) } }
task_set(0.25, "player_adrenalineDrain", id - TASK_ADRENALINE) } else { new iUsed = g_iAdrenalineUse[id]
g_iAdrenaline[id] = 0 g_iAdrenalineUse[id] = 0 /* to allow player_updateSpeed() to work correctly */
switch(iUsed) { case ADRENALINE_SPEED: { player_updateSpeed(id)
message_begin(MSG_BROADCAST, SVC_TEMPENTITY) write_byte(TE_KILLBEAM) write_short(id) message_end() }
case ADRENALINE_BERSERK, ADRENALINE_INVISIBILITY: player_updateRender(id) } }
player_hudAdrenaline(id) }
#endif // FEATURE_ADRENALINE
public admin_cmd_moveFlag(id, level, cid) { if(!cmd_access(id, level, cid, 2)) return PLUGIN_HANDLED
new szTeam[2]
read_argv(1, szTeam, charsmax(szTeam))
new iTeam = str_to_num(szTeam)
if(!(TEAM_RED <= iTeam <= TEAM_BLUE)) { switch(szTeam[0]) { case 'r', 'R': iTeam = 1 case 'b', 'B': iTeam = 2 } }
if(!(TEAM_RED <= iTeam <= TEAM_BLUE)) return PLUGIN_HANDLED
entity_get_vector(id, EV_VEC_origin, g_fFlagBase[iTeam])
entity_set_origin(g_iBaseEntity[iTeam], g_fFlagBase[iTeam]) entity_set_vector(g_iBaseEntity[iTeam], EV_VEC_velocity, FLAG_SPAWN_VELOCITY)
if(g_iFlagHolder[iTeam] == FLAG_HOLD_BASE) { entity_set_origin(g_iFlagEntity[iTeam], g_fFlagBase[iTeam]) entity_set_vector(g_iFlagEntity[iTeam], EV_VEC_velocity, FLAG_SPAWN_VELOCITY) }
new szName[32] new szSteam[48]
get_user_name(id, szName, charsmax(szName)) get_user_authid(id, szSteam, charsmax(szSteam))
log_amx("Admin %s<%s><%s> moved %s flag to %.2f %.2f %.2f", szName, szSteam, g_szTeamName[g_iTeam[id]], g_szTeamName[iTeam], g_fFlagBase[iTeam][0], g_fFlagBase[iTeam][1], g_fFlagBase[iTeam][2])
show_activity_key("ADMIN_MOVEBASE_1", "ADMIN_MOVEBASE_2", szName, LANG_PLAYER, g_szMLFlagTeam[iTeam])
client_print(id, print_console, "%s%L", CONSOLE_PREFIX, id, "ADMIN_MOVEBASE_MOVED", id, g_szMLFlagTeam[iTeam])
return PLUGIN_HANDLED }
public admin_cmd_saveFlags(id, level, cid) { if(!cmd_access(id, level, cid, 1)) return PLUGIN_HANDLED
new iOrigin[3][3] new szFile[96] new szBuffer[1024]
FVecIVec(g_fFlagBase[TEAM_RED], iOrigin[TEAM_RED]) FVecIVec(g_fFlagBase[TEAM_BLUE], iOrigin[TEAM_BLUE])
formatex(szBuffer, charsmax(szBuffer), "%d %d %d^n%d %d %d", iOrigin[TEAM_RED][x], iOrigin[TEAM_RED][y], iOrigin[TEAM_RED][z], iOrigin[TEAM_BLUE][x], iOrigin[TEAM_BLUE][y], iOrigin[TEAM_BLUE][z]) formatex(szFile, charsmax(szFile), FLAG_SAVELOCATION, g_szMap)
if(file_exists(szFile)) delete_file(szFile)
write_file(szFile, szBuffer)
new szName[32] new szSteam[48]
get_user_name(id, szName, charsmax(szName)) get_user_authid(id, szSteam, charsmax(szSteam))
log_amx("Admin %s<%s><%s> saved flag positions.", szName, szSteam, g_szTeamName[g_iTeam[id]])
client_print(id, print_console, "%s%L %s", CONSOLE_PREFIX, id, "ADMIN_MOVEBASE_SAVED", szFile)
return PLUGIN_HANDLED }
public admin_cmd_returnFlag(id, level, cid) { if(!cmd_access(id, level, cid, 2)) return PLUGIN_HANDLED
new szTeam[2]
read_argv(1, szTeam, charsmax(szTeam))
new iTeam = str_to_num(szTeam)
if(!(TEAM_RED <= iTeam <= TEAM_BLUE)) { switch(szTeam[0]) { case 'r', 'R': iTeam = 1 case 'b', 'B': iTeam = 2 } }
if(!(TEAM_RED <= iTeam <= TEAM_BLUE)) return PLUGIN_HANDLED
if(g_iFlagHolder[iTeam] == FLAG_HOLD_DROPPED) { if(g_fFlagDropped[iTeam] < (get_gametime() - ADMIN_RETURNWAIT)) { new szName[32] new szSteam[48]
new Float:fFlagOrigin[3]
entity_get_vector(g_iFlagEntity[iTeam], EV_VEC_origin, fFlagOrigin)
flag_sendHome(iTeam)
ExecuteForward(g_iFW_flag, g_iForwardReturn, FLAG_ADMINRETURN, id, iTeam, false)
game_announce(EVENT_RETURNED, iTeam, NULL)
get_user_name(id, szName, charsmax(szName)) get_user_authid(id, szSteam, charsmax(szSteam))
log_message("^"%s^" flag returned by admin %s<%s><%s>", g_szTeamName[iTeam], szName, szSteam, g_szTeamName[g_iTeam[id]]) log_amx("Admin %s<%s><%s> returned %s flag from %.2f %.2f %.2f", szName, szSteam, g_szTeamName[g_iTeam[id]], g_szTeamName[iTeam], fFlagOrigin[0], fFlagOrigin[1], fFlagOrigin[2])
show_activity_key("ADMIN_RETURN_1", "ADMIN_RETURN_2", szName, LANG_PLAYER, g_szMLFlagTeam[iTeam])
client_print(id, print_console, "%s%L", CONSOLE_PREFIX, id, "ADMIN_RETURN_DONE", id, g_szMLFlagTeam[iTeam]) } else client_print(id, print_console, "%s%L", CONSOLE_PREFIX, id, "ADMIN_RETURN_WAIT", id, g_szMLFlagTeam[iTeam], ADMIN_RETURNWAIT) } else client_print(id, print_console, "%s%L", CONSOLE_PREFIX, id, "ADMIN_RETURN_NOTDROPPED", id, g_szMLFlagTeam[iTeam])
return PLUGIN_HANDLED }
#if FEATURE_BUY == true
public player_inBuyZone(id) { if(!g_bAlive[id]) return
g_bBuyZone[id] = (read_data(1) ? true : false)
if(!g_bBuyZone[id]) set_pdata_int(id, 205, 0) // no "close menu upon exit buyzone" thing }
public player_cmd_setAutobuy(id) { new iIndex new szWeapon[24] new szArgs[1024]
read_args(szArgs, charsmax(szArgs)) remove_quotes(szArgs) trim(szArgs)
while(contain(szArgs, WHITESPACE) != -1) { strbreak(szArgs, szWeapon, charsmax(szWeapon), szArgs, charsmax(szArgs))
for(new bool:bFound, w = W_P228; w <= W_NVG; w++) { if(!bFound) { for(new i = 0; i < 2; i++) { if(!bFound && equali(g_szWeaponCommands[w][i], szWeapon)) { bFound = true
g_iAutobuy[id][iIndex++] = w } } } } }
player_cmd_autobuy(id)
return PLUGIN_HANDLED }
public player_cmd_autobuy(id) { if(!g_bAlive[id]) return PLUGIN_HANDLED
if(!g_bBuyZone[id]) { client_print(id, print_center, "%L", id, "BUY_NOTINZONE") return PLUGIN_HANDLED }
new iMoney = cs_get_user_money(id)
for(new bool:bBought[6], iWeapon, i = 0; i < sizeof g_iAutobuy[]; i++) { if(!g_iAutobuy[id][i]) return PLUGIN_HANDLED
iWeapon = g_iAutobuy[id][i]
if(bBought[g_iWeaponSlot[iWeapon]]) continue
#if FEATURE_ADRENALINE == true
if((g_iWeaponPrice[iWeapon] > 0 && g_iWeaponPrice[iWeapon] > iMoney) || (g_iWeaponAdrenaline[iWeapon] > 0 && g_iWeaponAdrenaline[iWeapon] > g_iAdrenaline[id])) continue
#else // FEATURE_ADRENALINE
if(g_iWeaponPrice[iWeapon] > 0 && g_iWeaponPrice[iWeapon] > iMoney) continue
#endif // FEATURE_ADRENALINE
player_buyWeapon(id, iWeapon) bBought[g_iWeaponSlot[iWeapon]] = true }
return PLUGIN_HANDLED }
public player_cmd_setRebuy(id) { new iIndex new szType[18] new szArgs[256]
read_args(szArgs, charsmax(szArgs)) replace_all(szArgs, charsmax(szArgs), "^"", NULL) trim(szArgs)
while(contain(szArgs, WHITESPACE) != -1) { split(szArgs, szType, charsmax(szType), szArgs, charsmax(szArgs), WHITESPACE)
for(new i = 1; i < sizeof g_szRebuyCommands; i++) { if(equali(szType, g_szRebuyCommands[i])) g_iRebuy[id][++iIndex] = i } }
player_cmd_rebuy(id)
return PLUGIN_HANDLED }
public player_cmd_rebuy(id) { if(!g_bAlive[id]) return PLUGIN_HANDLED
if(!g_bBuyZone[id]) { client_print(id, print_center, "%L", id, "BUY_NOTINZONE") return PLUGIN_HANDLED }
new iBought
for(new iType, iBuy, i = 1; i < sizeof g_iRebuy[]; i++) { iType = g_iRebuy[id][i]
if(!iType) continue
iBuy = g_iRebuyWeapons[id][iType]
if(!iBuy) continue
switch(iType) { case primary, secondary: player_buyWeapon(id, iBuy)
case armor: player_buyWeapon(id, (iBuy == 2 ? W_VESTHELM : W_VEST))
case he: player_buyWeapon(id, W_HEGRENADE)
case flash: { player_buyWeapon(id, W_FLASHBANG)
if(iBuy == 2) player_buyWeapon(id, W_FLASHBANG) }
case smoke: player_buyWeapon(id, W_SMOKEGRENADE)
case nvg: player_buyWeapon(id, W_NVG) }
iBought++
if(iType == flash && iBuy == 2) iBought++ }
if(iBought) client_print(id, print_center, "%L", id, "BUY_REBOUGHT", iBought)
return PLUGIN_HANDLED }
public player_addRebuy(id, iWeapon) { if(!g_bAlive[id]) return
switch(g_iWeaponSlot[iWeapon]) { case 1: g_iRebuyWeapons[id][primary] = iWeapon case 2: g_iRebuyWeapons[id][secondary] = iWeapon
default: { switch(iWeapon) { case W_VEST: g_iRebuyWeapons[id][armor] = (g_iRebuyWeapons[id][armor] == 2 ? 2 : 1) case W_VESTHELM: g_iRebuyWeapons[id][armor] = 2 case W_FLASHBANG: g_iRebuyWeapons[id][flash] = clamp(g_iRebuyWeapons[id][flash] + 1, 0, 2) case W_HEGRENADE: g_iRebuyWeapons[id][he] = 1 case W_SMOKEGRENADE: g_iRebuyWeapons[id][smoke] = 1 case W_NVG: g_iRebuyWeapons[id][nvg] = 1 } } } }
public player_cmd_buy_main(id) return player_menu_buy(id, 0)
public player_cmd_buy_equipament(id) return player_menu_buy(id, 8)
public player_cmd_buyVGUI(id) { message_begin(MSG_ONE, gMsg_BuyClose, _, id) message_end()
return player_menu_buy(id, 0) }
public player_menu_buy(id, iMenu) { if(!g_bAlive[id]) return PLUGIN_HANDLED
if(!g_bBuyZone[id]) { client_print(id, print_center, "%L", id, "BUY_NOTINZONE") return PLUGIN_HANDLED }
static szMenu[1024]
new iMoney = cs_get_user_money(id)
switch(iMenu) { case 1: { formatex(szMenu, charsmax(szMenu), "\y%L: %L^n^n\d1. \%sGlock 18\R$%d^n\d2. \%sUSP\R$%d^n\d3. \%sP228\R$%d^n\d4. \%sDesert Eagle\R$%d^n\d5. \%sFiveseven\R$%d^n\d6. \%sDual Elites\R$%d^n^n\d0. \w%L", id, "BUYMENU_TITLE", id, "BUYMENU_PISTOLS", (iMoney >= g_iWeaponPrice[W_GLOCK18] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_GLOCK18], (iMoney >= g_iWeaponPrice[W_USP] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_USP], (iMoney >= g_iWeaponPrice[W_P228] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_P228], (iMoney >= g_iWeaponPrice[W_DEAGLE] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_DEAGLE], (iMoney >= g_iWeaponPrice[W_FIVESEVEN] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_FIVESEVEN], (iMoney >= g_iWeaponPrice[W_ELITE] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_ELITE], id, "EXIT" ) }
case 2: { formatex(szMenu, charsmax(szMenu), "\y%L: %L^n^n\d1. \%sM3 Super90\R$%d^n\d2. \%sXM1014\R$%d^n^n\d0. \w%L", id, "BUYMENU_TITLE", id, "BUYMENU_SHOTGUNS", (iMoney >= g_iWeaponPrice[W_M3] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_M3], (iMoney >= g_iWeaponPrice[W_XM1014] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_XM1014], id, "EXIT" ) }
case 3: { formatex(szMenu, charsmax(szMenu), "\y%L: %L^n^n\d1. \%sTMP\R$%d^n\d2. \%sMac-10\R$%d^n\d3. \%sMP5 Navy\R$%d^n\d4. \%sUMP-45\R$%d^n\d5. \%sP90\R$%d^n^n\d0. \w%L", id, "BUYMENU_TITLE", id, "BUYMENU_SMGS", (iMoney >= g_iWeaponPrice[W_TMP] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_TMP], (iMoney >= g_iWeaponPrice[W_MAC10] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_MAC10], (iMoney >= g_iWeaponPrice[W_MP5NAVY] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_MP5NAVY], (iMoney >= g_iWeaponPrice[W_UMP45] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_UMP45], (iMoney >= g_iWeaponPrice[W_P90] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_P90], id, "EXIT" ) }
case 4: { formatex(szMenu, charsmax(szMenu), "\y%L: %L^n^n\d1. \%sGalil\R$%d^n\d2. \%sFamas\R$%d^n\d3. \%sAK-47\R$%d^n\d4. \%sM4A1\R$%d^n\d5. \%sAUG\R$%d^n\d6. \%sSG552\R$%d^n^n\d0. \w%L", id, "BUYMENU_TITLE", id, "BUYMENU_RIFLES", (iMoney >= g_iWeaponPrice[W_GALIL] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_GALIL], (iMoney >= g_iWeaponPrice[W_FAMAS] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_FAMAS], (iMoney >= g_iWeaponPrice[W_AK47] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_AK47], (iMoney >= g_iWeaponPrice[W_M4A1] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_M4A1], (iMoney >= g_iWeaponPrice[W_AUG] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_AUG], (iMoney >= g_iWeaponPrice[W_SG552] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_SG552], id, "EXIT" ) }
case 5: {
#if FEATURE_ADRENALINE == true
#if FEATURE_C4 == true
formatex(szMenu, charsmax(szMenu), "\y%L: %L^n^n\d1. \%sM249 \w(\%s%d %L\w)\R\%s$%d^n\d3. \%sSG550 \w(\%s%d %L\w)\R\%s$%d^n\d3. \%sG3SG1 \w(\%s%d %L\w)\R\%s$%d^n\d4. \%sScout \w(\%s%d %L\w)\R\%s$%d^n\d5. \%sAWP \w(\%s%d %L\w)\R\%s$%d^n\d6. \%s%L \w(\%s%d %L\w)\R\%s$%d^n\d7. \%s%L \w(\%s%d %L\w)\R\%s$%d^n^n\d0. \w%L", id, "BUYMENU_TITLE", id, "BUYMENU_SPECIAL", (iMoney >= g_iWeaponPrice[W_M249] && g_iAdrenaline[id] >= g_iWeaponAdrenaline[W_M249] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), (g_iAdrenaline[id] >= g_iWeaponAdrenaline[W_M249] ? BUY_ITEM_AVAILABLE2 : BUY_ITEM_DISABLED), g_iWeaponAdrenaline[W_M249], id, "ADRENALINE", (iMoney >= g_iWeaponPrice[W_M249] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_M249], (iMoney >= g_iWeaponPrice[W_SG550] && g_iAdrenaline[id] >= g_iWeaponAdrenaline[W_SG550] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), (g_iAdrenaline[id] >= g_iWeaponAdrenaline[W_SG550] ? BUY_ITEM_AVAILABLE2 : BUY_ITEM_DISABLED), g_iWeaponAdrenaline[W_SG550], id, "ADRENALINE", (iMoney >= g_iWeaponPrice[W_SG550] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_SG550], (iMoney >= g_iWeaponPrice[W_G3SG1] && g_iAdrenaline[id] >= g_iWeaponAdrenaline[W_G3SG1] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), (g_iAdrenaline[id] >= g_iWeaponAdrenaline[W_G3SG1] ? BUY_ITEM_AVAILABLE2 : BUY_ITEM_DISABLED), g_iWeaponAdrenaline[W_G3SG1], id, "ADRENALINE", (iMoney >= g_iWeaponPrice[W_G3SG1] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_G3SG1], (iMoney >= g_iWeaponPrice[W_SCOUT] && g_iAdrenaline[id] >= g_iWeaponAdrenaline[W_SCOUT] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), (g_iAdrenaline[id] >= g_iWeaponAdrenaline[W_SCOUT] ? BUY_ITEM_AVAILABLE2 : BUY_ITEM_DISABLED), g_iWeaponAdrenaline[W_SCOUT], id, "ADRENALINE", (iMoney >= g_iWeaponPrice[W_SCOUT] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_SCOUT], (iMoney >= g_iWeaponPrice[W_AWP] && g_iAdrenaline[id] >= g_iWeaponAdrenaline[W_AWP] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), (g_iAdrenaline[id] >= g_iWeaponAdrenaline[W_AWP] ? BUY_ITEM_AVAILABLE2 : BUY_ITEM_DISABLED), g_iWeaponAdrenaline[W_AWP], id, "ADRENALINE", (iMoney >= g_iWeaponPrice[W_AWP] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_AWP], (iMoney >= g_iWeaponPrice[W_SHIELD] && g_iAdrenaline[id] >= g_iWeaponAdrenaline[W_SHIELD] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), id, "BUYMENU_ITEM_SHIELD", (g_iAdrenaline[id] >= g_iWeaponAdrenaline[W_SHIELD] ? BUY_ITEM_AVAILABLE2 : BUY_ITEM_DISABLED), g_iWeaponAdrenaline[W_SHIELD], id, "ADRENALINE", (iMoney >= g_iWeaponPrice[W_SHIELD] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_SHIELD], (iMoney >= g_iWeaponPrice[W_C4] && g_iAdrenaline[id] >= g_iWeaponAdrenaline[W_C4] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), id, "BUYMENU_ITEM_C4", (g_iAdrenaline[id] >= g_iWeaponAdrenaline[W_C4] ? BUY_ITEM_AVAILABLE2 : BUY_ITEM_DISABLED), g_iWeaponAdrenaline[W_C4], id, "ADRENALINE", (iMoney >= g_iWeaponPrice[W_C4] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_C4], id, "EXIT" )
#else // FEATURE_C4
formatex(szMenu, charsmax(szMenu), "\y%L: %L^n^n\d1. \%sM249 \w(\%s%d %L\w)\R\%s$%d^n\d3. \%sSG550 \w(\%s%d %L\w)\R\%s$%d^n\d3. \%sG3SG1 \w(\%s%d %L\w)\R\%s$%d^n\d4. \%sScout \w(\%s%d %L\w)\R\%s$%d^n\d5. \%sAWP \w(\%s%d %L\w)\R\%s$%d^n\d6. \%s%L \w(\%s%d %L\w)\R\%s$%d^n^n\d0. \w%L", id, "BUYMENU_TITLE", id, "BUYMENU_SPECIAL", (iMoney >= g_iWeaponPrice[W_M249] && g_iAdrenaline[id] >= g_iWeaponAdrenaline[W_M249] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), (g_iAdrenaline[id] >= g_iWeaponAdrenaline[W_M249] ? BUY_ITEM_AVAILABLE2 : BUY_ITEM_DISABLED), g_iWeaponAdrenaline[W_M249], id, "ADRENALINE", (iMoney >= g_iWeaponPrice[W_M249] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_M249], (iMoney >= g_iWeaponPrice[W_SG550] && g_iAdrenaline[id] >= g_iWeaponAdrenaline[W_SG550] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), (g_iAdrenaline[id] >= g_iWeaponAdrenaline[W_SG550] ? BUY_ITEM_AVAILABLE2 : BUY_ITEM_DISABLED), g_iWeaponAdrenaline[W_SG550], id, "ADRENALINE", (iMoney >= g_iWeaponPrice[W_SG550] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_SG550], (iMoney >= g_iWeaponPrice[W_G3SG1] && g_iAdrenaline[id] >= g_iWeaponAdrenaline[W_G3SG1] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), (g_iAdrenaline[id] >= g_iWeaponAdrenaline[W_G3SG1] ? BUY_ITEM_AVAILABLE2 : BUY_ITEM_DISABLED), g_iWeaponAdrenaline[W_G3SG1], id, "ADRENALINE", (iMoney >= g_iWeaponPrice[W_G3SG1] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_G3SG1], (iMoney >= g_iWeaponPrice[W_SCOUT] && g_iAdrenaline[id] >= g_iWeaponAdrenaline[W_SCOUT] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), (g_iAdrenaline[id] >= g_iWeaponAdrenaline[W_SCOUT] ? BUY_ITEM_AVAILABLE2 : BUY_ITEM_DISABLED), g_iWeaponAdrenaline[W_SCOUT], id, "ADRENALINE", (iMoney >= g_iWeaponPrice[W_SCOUT] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_SCOUT], (iMoney >= g_iWeaponPrice[W_AWP] && g_iAdrenaline[id] >= g_iWeaponAdrenaline[W_AWP] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), (g_iAdrenaline[id] >= g_iWeaponAdrenaline[W_AWP] ? BUY_ITEM_AVAILABLE2 : BUY_ITEM_DISABLED), g_iWeaponAdrenaline[W_AWP], id, "ADRENALINE", (iMoney >= g_iWeaponPrice[W_AWP] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_AWP], (iMoney >= g_iWeaponPrice[W_SHIELD] && g_iAdrenaline[id] >= g_iWeaponAdrenaline[W_SHIELD] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), id, "BUYMENU_ITEM_SHIELD", (g_iAdrenaline[id] >= g_iWeaponAdrenaline[W_SHIELD] ? BUY_ITEM_AVAILABLE2 : BUY_ITEM_DISABLED), g_iWeaponAdrenaline[W_SHIELD], id, "ADRENALINE", (iMoney >= g_iWeaponPrice[W_SHIELD] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_SHIELD], id, "EXIT" )
#endif // FEATURE_C4
#else // FEATURE_ADRENALINE
#if FEATURE_C4 == true
formatex(szMenu, charsmax(szMenu), "\y%L: %L^n^n\d1. \%sM249\R\%s$%d^n\d3. \%sSG550\R\%s$%d^n\d3. \%sG3SG1\R\%s$%d^n\d4. \%sScout\R\%s$%d^n\d5. \%sAWP\R\%s$%d^n\d6. \%s%L\R\%s$%d^n\d7. \%s%L\R\%s$%d^n^n\d0. \w%L", id, "BUYMENU_TITLE", id, "BUYMENU_SPECIAL", (iMoney >= g_iWeaponPrice[W_M249] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED),(iMoney >= g_iWeaponPrice[W_M249] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_M249], (iMoney >= g_iWeaponPrice[W_SG550] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), (iMoney >= g_iWeaponPrice[W_SG550] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_SG550], (iMoney >= g_iWeaponPrice[W_G3SG1] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), (iMoney >= g_iWeaponPrice[W_G3SG1] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_G3SG1], (iMoney >= g_iWeaponPrice[W_SCOUT] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), (iMoney >= g_iWeaponPrice[W_SCOUT] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_SCOUT], (iMoney >= g_iWeaponPrice[W_AWP] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), (iMoney >= g_iWeaponPrice[W_AWP] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_AWP], (iMoney >= g_iWeaponPrice[W_SHIELD] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), id, "BUYMENU_ITEM_SHIELD", (iMoney >= g_iWeaponPrice[W_SHIELD] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_SHIELD], (iMoney >= g_iWeaponPrice[W_C4] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), id, "BUYMENU_ITEM_C4", (iMoney >= g_iWeaponPrice[W_C4] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_C4], id, "EXIT" )
#else // FEATURE_C4
formatex(szMenu, charsmax(szMenu), "\y%L: %L^n^n\d1. \%sM249\R\%s$%d^n\d3. \%sSG550\R\%s$%d^n\d3. \%sG3SG1\R\%s$%d^n\d4. \%sScout\R\%s$%d^n\d5. \%sAWP\R\%s$%d^n\d6. \%s%L\R\%s$%d^n^n\d0. \w%L", id, "BUYMENU_TITLE", id, "BUYMENU_SPECIAL", (iMoney >= g_iWeaponPrice[W_M249] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED),(iMoney >= g_iWeaponPrice[W_M249] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_M249], (iMoney >= g_iWeaponPrice[W_SG550] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), (iMoney >= g_iWeaponPrice[W_SG550] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_SG550], (iMoney >= g_iWeaponPrice[W_G3SG1] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), (iMoney >= g_iWeaponPrice[W_G3SG1] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_G3SG1], (iMoney >= g_iWeaponPrice[W_SCOUT] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), (iMoney >= g_iWeaponPrice[W_SCOUT] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_SCOUT], (iMoney >= g_iWeaponPrice[W_AWP] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), (iMoney >= g_iWeaponPrice[W_AWP] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_AWP], (iMoney >= g_iWeaponPrice[W_SHIELD] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), id, "BUYMENU_ITEM_SHIELD", (iMoney >= g_iWeaponPrice[W_SHIELD] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), g_iWeaponPrice[W_SHIELD], id, "EXIT" )
#endif // FEATURE_C4
#endif // FEATURE_ADRENALINE
}
case 8: { formatex(szMenu, charsmax(szMenu), "\y%L: %L^n^n\d1. \%s%L\R$%d^n\d2. \%s%L\R$%d^n^n\d3. \%s%L\R$%d^n\d4. \%s%L\R$%d^n\d5. \%s%L\R$%d^n^n\d7. \%s%L\R$%d^n^n\d0. \w%L", id, "BUYMENU_TITLE", id, "BUYMENU_EQUIPAMENT", (iMoney >= g_iWeaponPrice[W_VEST] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), id, "BUYMENU_ITEM_VEST", g_iWeaponPrice[W_VEST], (iMoney >= g_iWeaponPrice[W_VESTHELM] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), id, "BUYMENU_ITEM_VESTHELM", g_iWeaponPrice[W_VESTHELM], (iMoney >= g_iWeaponPrice[W_FLASHBANG] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), id, "BUYMENU_ITEM_FLASHBANG", g_iWeaponPrice[W_FLASHBANG], (iMoney >= g_iWeaponPrice[W_HEGRENADE] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), id, "BUYMENU_ITEM_HE", g_iWeaponPrice[W_HEGRENADE], (iMoney >= g_iWeaponPrice[W_SMOKEGRENADE] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), id, "BUYMENU_ITEM_SMOKE", g_iWeaponPrice[W_SMOKEGRENADE], (iMoney >= g_iWeaponPrice[W_NVG] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), id, "BUYMENU_ITEM_NVG", g_iWeaponPrice[W_NVG], id, "EXIT" ) }
default: {
#if FEATURE_ADRENALINE == true
formatex(szMenu, charsmax(szMenu), "\y%L^n^n\d1. \%s%L^n\d2. \%s%L^n\d3. \%s%L^n\d4. \%s%L^n\d5. \%s%L^n^n\d6. \w%L\R$0^n^n\d8. \%s%L^n^n\d0. \w%L", id, "BUYMENU_TITLE", (iMoney >= g_iWeaponPrice[W_GLOCK18] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), id, "BUYMENU_PISTOLS", (iMoney >= g_iWeaponPrice[W_M3] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), id, "BUYMENU_SHOTGUNS", (iMoney >= g_iWeaponPrice[W_TMP] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), id, "BUYMENU_SMGS", (iMoney >= g_iWeaponPrice[W_GALIL] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), id, "BUYMENU_RIFLES", (iMoney >= g_iWeaponPrice[W_M249] && g_iAdrenaline[id] >= g_iWeaponAdrenaline[W_M249] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), id, "BUYMENU_SPECIAL", id, "BUYMENU_AMMO", (iMoney >= g_iWeaponPrice[W_FLASHBANG] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), id, "BUYMENU_EQUIPAMENT", id, "EXIT" )
#else // FEATURE_ADRENALINE
formatex(szMenu, charsmax(szMenu), "\y%L^n^n\d1. \%s%L^n\d2. \%s%L^n\d3. \%s%L^n\d4. \%s%L^n\d5. \%s%L^n^n\d6. \w%L\R$0^n^n\d8. \%s%L^n^n\d0. \w%L", id, "BUYMENU_TITLE", (iMoney >= g_iWeaponPrice[W_GLOCK18] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), id, "BUYMENU_PISTOLS", (iMoney >= g_iWeaponPrice[W_M3] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), id, "BUYMENU_SHOTGUNS", (iMoney >= g_iWeaponPrice[W_TMP] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), id, "BUYMENU_SMGS", (iMoney >= g_iWeaponPrice[W_GALIL] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), id, "BUYMENU_RIFLES", (iMoney >= g_iWeaponPrice[W_M249] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), id, "BUYMENU_SPECIAL", id, "BUYMENU_AMMO", (iMoney >= g_iWeaponPrice[W_FLASHBANG] ? BUY_ITEM_AVAILABLE : BUY_ITEM_DISABLED), id, "BUYMENU_EQUIPAMENT", id, "EXIT" )
#endif // FEATURE_ADRENALINE
} }
g_iMenu[id] = iMenu
show_menu(id, MENU_KEYS_BUY, szMenu, -1, MENU_BUY)
return PLUGIN_HANDLED }
public player_key_buy(id, iKey) { iKey += 1
if(!g_bAlive[id] || iKey == 10) return PLUGIN_HANDLED
if(!g_bBuyZone[id]) { client_print(id, print_center, "%L", id, "BUY_NOTINZONE") return PLUGIN_HANDLED }
switch(g_iMenu[id]) { case 1: { switch(iKey) { case 1: player_buyWeapon(id, W_GLOCK18) case 2: player_buyWeapon(id, W_USP) case 3: player_buyWeapon(id, W_P228) case 4: player_buyWeapon(id, W_DEAGLE) case 5: player_buyWeapon(id, W_FIVESEVEN) case 6: player_buyWeapon(id, W_ELITE) } }
case 2: { switch(iKey) { case 1: player_buyWeapon(id, W_M3) case 2: player_buyWeapon(id, W_XM1014) } }
case 3: { switch(iKey) { case 1: player_buyWeapon(id, W_TMP) case 2: player_buyWeapon(id, W_MAC10) case 3: player_buyWeapon(id, W_MP5NAVY) case 4: player_buyWeapon(id, W_UMP45) case 5: player_buyWeapon(id, W_P90) } }
case 4: { switch(iKey) { case 1: player_buyWeapon(id, W_GALIL) case 2: player_buyWeapon(id, W_FAMAS) case 3: player_buyWeapon(id, W_AK47) case 4: player_buyWeapon(id, W_M4A1) case 5: player_buyWeapon(id, W_AUG) case 6: player_buyWeapon(id, W_SG552) } }
case 5: { switch(iKey) { case 1: player_buyWeapon(id, W_M249) case 2: player_buyWeapon(id, W_SG550) case 3: player_buyWeapon(id, W_G3SG1) case 4: player_buyWeapon(id, W_SCOUT) case 5: player_buyWeapon(id, W_AWP) case 6: player_buyWeapon(id, W_SHIELD) case 7: player_buyWeapon(id, W_C4) } }
case 8: { switch(iKey) { case 1: player_buyWeapon(id, W_VEST) case 2: player_buyWeapon(id, W_VESTHELM) case 3: player_buyWeapon(id, W_FLASHBANG) case 4: player_buyWeapon(id, W_HEGRENADE) case 5: player_buyWeapon(id, W_SMOKEGRENADE) case 7: player_buyWeapon(id, W_NVG) } }
default: { switch(iKey) { case 1,2,3,4,5,8: player_menu_buy(id, iKey) case 6,7: player_fillAmmo(id) } } }
return PLUGIN_HANDLED }
public player_cmd_buyWeapon(id) { if(!g_bBuyZone[id]) { client_print(id, print_center, "%L", id, "BUY_NOTINZONE") return PLUGIN_HANDLED }
new szCmd[12]
read_argv(0, szCmd, charsmax(szCmd))
for(new w = W_P228; w <= W_NVG; w++) { for(new i = 0; i < 2; i++) { if(equali(g_szWeaponCommands[w][i], szCmd)) { player_buyWeapon(id, w) return PLUGIN_HANDLED } } }
return PLUGIN_HANDLED }
public player_buyWeapon(id, iWeapon) { if(!g_bAlive[id]) return
new CsArmorType:ArmorType new iArmor = cs_get_user_armor(id, ArmorType)
new iMoney = cs_get_user_money(id)
/* apply discount if you already have a kevlar and buying a kevlar+helmet */ new iCost = g_iWeaponPrice[iWeapon] - (ArmorType == CS_ARMOR_KEVLAR && iWeapon == W_VESTHELM ? 650 : 0)
#if FEATURE_ADRENALINE == true
new iCostAdrenaline = g_iWeaponAdrenaline[iWeapon]
#endif // FEATURE_ADRENALINE
if(iCost > iMoney) { client_print(id, print_center, "%L", id, "BUY_NEEDMONEY", iCost) return }
#if FEATURE_ADRENALINE == true
else if(!(iCostAdrenaline <= g_iAdrenaline[id])) { client_print(id, print_center, "%L", id, "BUY_NEEDADRENALINE", iCostAdrenaline) return }
#endif // FEATURE_ADRENALINE
switch(iWeapon) {
#if FEATURE_C4 == true
case W_C4: { if(user_has_weapon(id, W_C4)) { client_print(id, print_center, "%L", id, "BUY_HAVE_C4") return }
player_giveC4(id) }
#endif // FEATURE_C4
case W_NVG: { if(cs_get_user_nvg(id)) { client_print(id, print_center, "%L", id, "BUY_HAVE_NVG") return }
cs_set_user_nvg(id, 1) }
case W_VEST: { if(iArmor >= 100) { client_print(id, print_center, "%L", id, "BUY_HAVE_KEVLAR") return } }
case W_VESTHELM: { if(iArmor >= 100 && ArmorType == CS_ARMOR_VESTHELM) { client_print(id, print_center, "%L", id, "BUY_HAVE_KEVLARHELM") return } }
case W_FLASHBANG: { new iGrenades = cs_get_user_bpammo(id, W_FLASHBANG)
if(iGrenades >= 2) { client_print(id, print_center, "%L", id, "BUY_NOMORE_FLASH") return }
new iCvar = get_pcvar_num(pCvar_ctf_nospam_flash) new Float:fGameTime = get_gametime()
if(g_fLastBuy[id][iGrenades] > fGameTime) { client_print(id, print_center, "%L", id, "BUY_DELAY_FLASH", iCvar) return }
g_fLastBuy[id][iGrenades] = fGameTime + iCvar
if(iGrenades == 1) g_fLastBuy[id][0] = g_fLastBuy[id][iGrenades] }
case W_HEGRENADE: { if(cs_get_user_bpammo(id, W_HEGRENADE) >= 1) { client_print(id, print_center, "%L", id, "BUY_NOMORE_HE") return }
new iCvar = get_pcvar_num(pCvar_ctf_nospam_he) new Float:fGameTime = get_gametime()
if(g_fLastBuy[id][2] > fGameTime) { client_print(id, print_center, "%L", id, "BUY_DELAY_HE", iCvar) return }
g_fLastBuy[id][2] = fGameTime + iCvar }
case W_SMOKEGRENADE: { if(cs_get_user_bpammo(id, W_SMOKEGRENADE) >= 1) { client_print(id, print_center, "%L", id, "BUY_NOMORE_SMOKE") return }
new iCvar = get_pcvar_num(pCvar_ctf_nospam_smoke) new Float:fGameTime = get_gametime()
if(g_fLastBuy[id][3] > fGameTime) { client_print(id, print_center, "%L", id, "BUY_DELAY_SMOKE", iCvar) return }
g_fLastBuy[id][3] = fGameTime + iCvar } }
if(1 <= g_iWeaponSlot[iWeapon] <= 2) { new iWeapons new iWeaponList[32]
get_user_weapons(id, iWeaponList, iWeapons)
if(cs_get_user_shield(id)) iWeaponList[iWeapons++] = W_SHIELD
for(new w, i = 0; i < iWeapons; i++) { w = iWeaponList[i]
if(1 <= g_iWeaponSlot[w] <= 2) { if(w == iWeapon) { client_print(id, print_center, "%L", id, "BUY_HAVE_WEAPON") return }
if(iWeapon == W_SHIELD && w == W_ELITE) engclient_cmd(id, "drop", g_szWeaponEntity[W_ELITE]) // drop the dual elites too if buying a shield
if(iWeapon == W_ELITE && w == W_SHIELD) engclient_cmd(id, "drop", g_szWeaponEntity[W_SHIELD]) // drop the too shield if buying dual elites
if(g_iWeaponSlot[w] == g_iWeaponSlot[iWeapon]) { if(g_iWeaponSlot[w] == 2 && iWeaponList[iWeapons-1] == W_SHIELD) { engclient_cmd(id, "drop", g_szWeaponEntity[W_SHIELD]) // drop the shield
new ent = find_ent_by_owner(g_iMaxPlayers, g_szWeaponEntity[W_SHIELD], id)
if(ent) { entity_set_int(ent, EV_INT_flags, FL_KILLME) // kill the shield call_think(ent) }
engclient_cmd(id, "drop", g_szWeaponEntity[w]) // drop the secondary
give_item(id, g_szWeaponEntity[W_SHIELD]) // give back the shield } else engclient_cmd(id, "drop", g_szWeaponEntity[w]) // drop weapon if it's of the same slot } } } }
if(iWeapon != W_NVG && iWeapon != W_C4) give_item(id, g_szWeaponEntity[iWeapon])
player_addRebuy(id, iWeapon)
if(g_iWeaponPrice[iWeapon]) cs_set_user_money(id, iMoney - iCost, 1)
#if FEATURE_ADRENALINE == true
if(iCostAdrenaline) { g_iAdrenaline[id] -= iCostAdrenaline player_hudAdrenaline(id) }
#endif // FEATURE_ADRENALINE
if(g_iBPAmmo[iWeapon]) cs_set_user_bpammo(id, iWeapon, g_iBPAmmo[iWeapon]) }
public player_fillAmmo(id) { if(!g_bAlive[id]) return PLUGIN_HANDLED
if(!g_bBuyZone[id]) { client_print(id, print_center, "%L", id, "BUY_NOTINZONE") return PLUGIN_HANDLED }
if(player_getAmmo(id)) { emit_sound(id, CHAN_ITEM, SND_GETAMMO, VOL_NORM, ATTN_NORM, 0, PITCH_NORM) client_print(id, print_center, "%L", id, "BUY_FULLAMMO") }
return PLUGIN_HANDLED }
#endif // FEATURE_BUY
#if FEATURE_C4 == true
public c4_used(msgid, dest, id) { if(g_iTeam[id]) player_updateSpeed(id)
if(get_msg_arg_int(1) == 0) g_bDefuse[id] = false
return PLUGIN_HANDLED }
public c4_planted() { new szLogUser[80], szName[32]
read_logargv(0, szLogUser, charsmax(szLogUser)) parse_loguser(szLogUser, szName, charsmax(szName))
new id = get_user_index(szName) new ent = g_iMaxPlayers new Float:fAngles[3] new szFormat[40]
entity_get_vector(id, EV_VEC_angles, fAngles)
fAngles[pitch] = 0.0 fAngles[yaw] += 90.0 fAngles[roll] = 0.0
new iC4Timer = get_pcvar_num(pCvar_mp_c4timer)
client_print(id, print_center, "%L", id, "C4_ARMED", iC4Timer)
formatex(szFormat, charsmax(szFormat), "%L", LANG_PLAYER, "C4_ARMED_RADIO", iC4Timer)
for(new i = 1; i <= g_iMaxPlayers; i++) { if(g_iTeam[i] == g_iTeam[id] && !g_bBot[id]) { /* fully fake hookable radio message and event */
emessage_begin(MSG_ONE, gMsg_TextMsg, _, i) ewrite_byte(3) ewrite_string("#Game_radio") ewrite_string(szName) ewrite_string(szFormat) emessage_end()
emessage_begin(MSG_ONE, gMsg_SendAudio, _, i) ewrite_byte(id) ewrite_string("%!MRAD_BLOW") ewrite_short(100) emessage_end() } }
while((ent = find_ent_by_owner(ent, GRENADE, id))) { if(get_pdata_int(ent, 96) & (1<<8)) { entity_set_int(ent, EV_INT_solid, SOLID_NOT) entity_set_int(ent, EV_INT_movetype, MOVETYPE_TOSS) entity_set_float(ent, EV_FL_gravity, 1.0) entity_set_vector(ent, EV_VEC_angles, fAngles)
return } } }
public c4_defuse(ent, id, activator, iType, Float:fValue) { if(g_bAlive[id] && get_pdata_int(ent, 96) & (1<<8)) { new iOwner = entity_get_edict(ent, EV_ENT_owner)
if(id != iOwner && 1 <= iOwner <= g_iMaxPlayers && g_iTeam[id] == g_iTeam[iOwner]) { client_print(id, print_center, "%L", id, "C4_NODEFUSE") client_cmd(id, "-use")
return HAM_SUPERCEDE }
if(g_iTeam[id] == TEAM_RED) { set_pdata_int(id, 114, TEAM_BLUE, 5)
ExecuteHam(Ham_Use, ent, id, activator, iType, fValue)
set_pdata_int(id, 114, TEAM_RED, 5) }
if(!g_bDefuse[id]) { client_print(id, print_center, "%L", id, "C4_DEFUSING", C4_DEFUSETIME)
message_begin(MSG_ONE_UNRELIABLE, gMsg_BarTime, _, id) write_short(C4_DEFUSETIME) message_end()
set_pdata_float(ent, 99, get_gametime() + C4_DEFUSETIME, 5)
g_bDefuse[id] = true } }
return HAM_IGNORED }
public c4_defused() { new szLogUser[80], szName[32]
read_logargv(0, szLogUser, charsmax(szLogUser)) parse_loguser(szLogUser, szName, charsmax(szName))
new id = get_user_index(szName)
if(!g_bAlive[id]) return
g_bDefuse[id] = false
player_giveC4(id) client_print(id, print_center, "%L", id, "C4_DEFUSED") }
public c4_pickup(ent, id) { if(g_bAlive[id] && is_valid_ent(ent) && (entity_get_int(ent, EV_INT_flags) & FL_ONGROUND)) { static szModel[32]
entity_get_string(ent, EV_SZ_model, szModel, charsmax(szModel))
if(equal(szModel, "models/w_backpack.mdl")) { if(user_has_weapon(id, W_C4)) return PLUGIN_HANDLED
player_giveC4(id)
weapon_remove(ent)
return PLUGIN_HANDLED } }
return PLUGIN_CONTINUE }
#endif // FEATURE_C4 == true
public weapon_spawn(ent) { if(!is_valid_ent(ent)) return
new Float:fWeaponStay = get_pcvar_float(pCvar_ctf_weaponstay)
if(fWeaponStay > 0) { task_remove(ent) task_set(fWeaponStay, "weapon_startFade", ent) } }
public weapon_startFade(ent) { if(!is_valid_ent(ent)) return
new szClass[32]
entity_get_string(ent, EV_SZ_classname, szClass, charsmax(szClass))
if(!equal(szClass, WEAPONBOX) && !equal(szClass, ITEM_CLASSNAME)) return
entity_set_int(ent, EV_INT_movetype, MOVETYPE_FLY) entity_set_int(ent, EV_INT_rendermode, kRenderTransAlpha)
if(get_pcvar_num(pCvar_ctf_glows)) entity_set_int(ent, EV_INT_renderfx, kRenderFxGlowShell)
entity_set_float(ent, EV_FL_renderamt, 255.0) entity_set_vector(ent, EV_VEC_rendercolor, Float:{255.0, 255.0, 0.0}) entity_set_vector(ent, EV_VEC_velocity, Float:{0.0, 0.0, 20.0})
weapon_fadeOut(ent, 255.0) }
public weapon_fadeOut(ent, Float:fStart) { if(!is_valid_ent(ent)) { task_remove(ent) return }
static Float:fFadeAmount[4096]
if(fStart) { task_remove(ent) fFadeAmount[ent] = fStart }
fFadeAmount[ent] -= 25.5
if(fFadeAmount[ent] > 0.0) { entity_set_float(ent, EV_FL_renderamt, fFadeAmount[ent])
task_set(0.1, "weapon_fadeOut", ent) } else { new szClass[32]
entity_get_string(ent, EV_SZ_classname, szClass, charsmax(szClass))
if(equal(szClass, WEAPONBOX)) weapon_remove(ent) else entity_remove(ent) } }
public item_touch(ent, id) { if(g_bAlive[id] && is_valid_ent(ent) && entity_get_int(ent, EV_INT_flags) & FL_ONGROUND) { new iType = entity_get_int(ent, EV_INT_iuser2)
switch(iType) { case ITEM_AMMO: { if(!player_getAmmo(id)) return PLUGIN_HANDLED
client_print(id, print_center, "%L", id, "PICKED_AMMO")
emit_sound(id, CHAN_ITEM, SND_GETAMMO, VOL_NORM, ATTN_NORM, 0, PITCH_NORM) }
case ITEM_MEDKIT: { new iHealth = get_user_health(id)
if(iHealth >= g_iMaxHealth[id]) return PLUGIN_HANDLED
set_user_health(id, clamp(iHealth + ITEM_MEDKIT_GIVE, 0, 100))
client_print(id, print_center, "%L", id, "PICKED_HEALTH", ITEM_MEDKIT_GIVE)
emit_sound(id, CHAN_ITEM, SND_GETMEDKIT, VOL_NORM, ATTN_NORM, 0, 110) }
#if FEATURE_ADRENALINE == true
case ITEM_ADRENALINE: { if(g_iAdrenaline[id] >= 100) return PLUGIN_HANDLED
g_iAdrenaline[id] = clamp(g_iAdrenaline[id] + ITEM_ADRENALINE_GIVE, 0, 100)
player_hudAdrenaline(id)
client_print(id, print_center, "%L", id, "PICKED_ADRENALINE", ITEM_ADRENALINE_GIVE)
emit_sound(id, CHAN_ITEM, SND_GETADRENALINE, VOL_NORM, ATTN_NORM, 0, 140) }
#endif // FEATURE_ADRENALINE == true }
task_remove(ent) entity_remove(ent) }
return PLUGIN_CONTINUE }
public event_restartGame() g_bRestarting = true
public event_roundStart() { new ent = -1
while((ent = find_ent_by_class(ent, WEAPONBOX)) > 0) { task_remove(ent) weapon_remove(ent) }
ent = -1
while((ent = find_ent_by_class(ent, ITEM_CLASSNAME)) > 0) { task_remove(ent) entity_remove(ent) }
for(new id = 1; id < g_iMaxPlayers; id++) { if(!g_bAlive[id]) continue
g_bDefuse[id] = false g_bFreeLook[id] = false g_fLastBuy[id] = Float:{0.0, 0.0, 0.0, 0.0}
task_remove(id - TASK_EQUIPAMENT) task_remove(id - TASK_TEAMBALANCE) task_remove(id - TASK_DEFUSE)
if(g_bRestarting) { task_remove(id) task_remove(id - TASK_ADRENALINE)
g_bRestarted[id] = true g_iAdrenaline[id] = 0 g_iAdrenalineUse[id] = 0 }
player_updateSpeed(id) }
for(new iFlagTeam = TEAM_RED; iFlagTeam <= TEAM_BLUE; iFlagTeam++) { flag_sendHome(iFlagTeam)
task_remove(g_iFlagEntity[iFlagTeam])
log_message("%s, %s flag returned back to base.", (g_bRestarting ? "Game restarted" : "New round started"), g_szTeamName[iFlagTeam]) }
if(g_bRestarting) { g_iScore = {0,0,0} g_bRestarting = false } }
public msg_block() return PLUGIN_HANDLED
#if FEATURE_C4 == true
public msg_sendAudio() { new szAudio[14]
get_msg_arg_string(2, szAudio, charsmax(szAudio))
return equal(szAudio, "%!MRAD_BOMB", 11) ? PLUGIN_HANDLED : PLUGIN_CONTINUE }
#endif // FEATURE_C4 == true
public msg_screenFade(msgid, dest, id) return (g_bProtected[id] && g_bAlive[id] && get_msg_arg_int(4) == 255 && get_msg_arg_int(5) == 255 && get_msg_arg_int(6) == 255 && get_msg_arg_int(7) > 199 ? PLUGIN_HANDLED : PLUGIN_CONTINUE)
public msg_scoreAttrib() return (get_msg_arg_int(2) & (1<<1) ? PLUGIN_HANDLED : PLUGIN_CONTINUE)
public msg_teamScore() { new szTeam[2]
get_msg_arg_string(1, szTeam, 1)
switch(szTeam[0]) { case 'T': set_msg_arg_int(2, ARG_SHORT, g_iScore[TEAM_RED]) case 'C': set_msg_arg_int(2, ARG_SHORT, g_iScore[TEAM_BLUE]) } }
public msg_roundTime() set_msg_arg_int(1, ARG_SHORT, get_timeleft())
public msg_sayText(msgid, dest, id) { new szString[32]
get_msg_arg_string(2, szString, charsmax(szString))
new iTeam = (szString[14] == 'T' ? TEAM_RED : (szString[14] == 'C' ? TEAM_BLUE : TEAM_SPEC)) new bool:bDead = (szString[16] == 'D' || szString[17] == 'D')
if(TEAM_RED <= iTeam <= TEAM_BLUE && equali(szString, "#Cstrike_Chat_", 14)) { formatex(szString, charsmax(szString), "^x01%s(%L)^x03 %%s1^x01 : %%s2", (bDead ? "*DEAD* " : NULL), id, g_szMLFlagTeam[iTeam]) set_msg_arg_string(2, szString) } }
public msg_textMsg(msgid, dest, id) { static szMsg[48]
get_msg_arg_string(2, szMsg, charsmax(szMsg))
if(equal(szMsg, "#Spec_Mode", 10) && !get_pcvar_num(pCvar_mp_fadetoblack) && (get_pcvar_num(pCvar_mp_forcecamera) || get_pcvar_num(pCvar_mp_forcechasecam))) { if(TEAM_RED <= g_iTeam[id] <= TEAM_BLUE && szMsg[10] == '3') { if(!g_bFreeLook[id]) { player_screenFade(id, {0,0,0,255}, 0.25, 9999.0, FADE_IN, true) g_bFreeLook[id] = true }
formatex(szMsg, charsmax(szMsg), "%L", id, "DEATH_NOFREELOOK")
set_msg_arg_string(2, szMsg) } else if(g_bFreeLook[id]) { player_screenFade(id, {0,0,0,255}, 0.25, 0.0, FADE_OUT, true) g_bFreeLook[id] = false } } else if(equal(szMsg, "#Terrorists_Win") || equal(szMsg, "#CTs_Win")) { static szString[32]
formatex(szString, charsmax(szString), "%L", LANG_PLAYER, "STARTING_NEWROUND")
set_msg_arg_string(2, szString) } else if(equal(szMsg, "#Only_1", 7)) { formatex(szMsg, charsmax(szMsg), "%L", id, "DEATH_ONLY1CHANGE")
set_msg_arg_string(2, szMsg) }
#if FEATURE_C4 == true
else if(equal(szMsg, "#Defusing", 9) || equal(szMsg, "#Got_bomb", 9) || equal(szMsg, "#Game_bomb", 10) || equal(szMsg, "#Bomb", 5) || equal(szMsg, "#Target", 7)) return PLUGIN_HANDLED
#endif // FEATURE_C4 == true
return PLUGIN_CONTINUE }
player_award(id, iMoney, iFrags, iAdrenaline, szText[], any:...) { #if FEATURE_ADRENALINE == false
iAdrenaline = 0
#endif // FEATURE_ADRENALINE
if(!g_iTeam[id] || (!iMoney && !iFrags && !iAdrenaline)) return
new szMsg[48] new szMoney[24] new szFrags[48] new szFormat[192] new szAdrenaline[48]
if(iMoney != 0) { cs_set_user_money(id, clamp(cs_get_user_money(id) + iMoney, 0, 16000), 1)
formatex(szMoney, charsmax(szMoney), "%s%d$", iMoney > 0 ? "+" : NULL, iMoney) }
if(iFrags != 0) { player_setScore(id, iFrags, 0)
formatex(szFrags, charsmax(szFrags), "%s%d %L", iFrags > 0 ? "+" : NULL, iFrags, id, (iFrags > 1 ? "FRAGS" : "FRAG")) }
#if FEATURE_ADRENALINE == true
if(iAdrenaline != 0) { g_iAdrenaline[id] = clamp(g_iAdrenaline[id] + iAdrenaline, 0, 100)
player_hudAdrenaline(id)
formatex(szAdrenaline, charsmax(szAdrenaline), "%s%d %L", iAdrenaline > 0 ? "+" : NULL, iAdrenaline, id, "ADRENALINE") }
#endif // FEATURE_ADRENALINE == true
vformat(szMsg, charsmax(szMsg), szText, 6) formatex(szFormat, charsmax(szFormat), "%s%s%s%s%s %s", szMoney, (szMoney[0] && (szFrags[0] || szAdrenaline[0]) ? ", " : NULL), szFrags, (szFrags[0] && szAdrenaline[0] ? ", " : NULL), szAdrenaline, szMsg)
client_print(id, print_console, "%s%L: %s", CONSOLE_PREFIX, id, "REWARD", szFormat) client_print(id, print_center, szFormat) }
#if FEATURE_ADRENALINE == true
player_hudAdrenaline(id) { set_hudmessage(HUD_ADRENALINE)
if(g_iAdrenalineUse[id]) show_hudmessage(id, "%L", id, "HUD_ADRENALINECOMBO", id, g_szAdrenalineUseML[g_iAdrenalineUse[id]], g_iAdrenaline[id], 100)
else if(g_iAdrenaline[id] >= 100) show_hudmessage(id, "%L", id, "HUD_ADRENALINEFULL")
else show_hudmessage(id, "%L", id, "HUD_ADRENALINE", g_iAdrenaline[id], 100) }
#endif // FEATURE_ADRENALINE == true
player_print(id, iSender, szMsg[], any:...) { if(g_bBot[id] || (id && !g_iTeam[id])) return PLUGIN_HANDLED
new szFormat[192]
vformat(szFormat, charsmax(szFormat), szMsg, 4) format(szFormat, charsmax(szFormat), "%s%s", CHAT_PREFIX, szFormat)
if(id) message_begin(MSG_ONE, gMsg_SayText, _, id) else message_begin(MSG_ALL, gMsg_SayText)
write_byte(iSender) write_string(szFormat) message_end()
return PLUGIN_HANDLED }
bool:player_getAmmo(id) { if(!g_bAlive[id]) return false
new iWeapons new iWeaponList[32] new bool:bGotAmmo = false
get_user_weapons(id, iWeaponList, iWeapons)
for(new iAmmo, iClip, ent, w, i = 0; i < iWeapons; i++) { w = iWeaponList[i]
if(g_iBPAmmo[w]) { ent = find_ent_by_owner(g_iMaxPlayers, g_szWeaponEntity[w], id)
iAmmo = cs_get_user_bpammo(id, w) iClip = (ent ? cs_get_weapon_ammo(ent) : 0)
if((iAmmo + iClip) < (g_iBPAmmo[w] + g_iClip[w])) { cs_set_user_bpammo(id, w, g_iBPAmmo[w] + (g_iClip[w] - iClip)) bGotAmmo = true } } }
return bGotAmmo }
player_setScore(id, iAddFrags, iAddDeaths) { new iFrags = get_user_frags(id) new iDeaths = cs_get_user_deaths(id)
if(iAddFrags != 0) { iFrags += iAddFrags
set_user_frags(id, iFrags) }
if(iAddDeaths != 0) { iDeaths += iAddDeaths
cs_set_user_deaths(id, iDeaths) }
message_begin(MSG_BROADCAST, gMsg_ScoreInfo) write_byte(id) write_short(iFrags) write_short(iDeaths) write_short(0) write_short(g_iTeam[id]) message_end() }
player_spawnItem(id) { #if FEATURE_ADRENALINE == true if(!ITEM_DROP_AMMO && !ITEM_DROP_MEDKIT && !ITEM_DROP_ADRENALINE) return #else if(!ITEM_DROP_AMMO && !ITEM_DROP_MEDKIT) return #endif
if(random_num(1, 100) > get_pcvar_float(pCvar_ctf_itempercent)) return
new ent = entity_create(INFO_TARGET)
if(!ent) return
new iType new Float:fOrigin[3] new Float:fAngles[3] new Float:fVelocity[3]
entity_get_vector(id, EV_VEC_origin, fOrigin)
fVelocity[x] = random_float(-100.0, 100.0) fVelocity[y] = random_float(-100.0, 100.0) fVelocity[z] = 50.0
fAngles[yaw] = random_float(0.0, 360.0)
#if FEATURE_ADRENALINE == true while((iType = random(3))) #else while((iType = random(2))) #endif { switch(iType) { case ITEM_AMMO: { if(ITEM_DROP_AMMO) { entity_set_model(ent, ITEM_MODEL_AMMO) break } }
case ITEM_MEDKIT: { if(ITEM_DROP_MEDKIT) { entity_set_model(ent, ITEM_MODEL_MEDKIT) break } }
#if FEATURE_ADRENALINE == true case ITEM_ADRENALINE: { if(ITEM_DROP_ADRENALINE) { entity_set_model(ent, ITEM_MODEL_ADRENALINE) entity_set_int(ent, EV_INT_skin, 2) break } } #endif // FEATURE_ADRENALINE == true } }
entity_set_string(ent, EV_SZ_classname, ITEM_CLASSNAME) entity_spawn(ent) entity_set_size(ent, ITEM_HULL_MIN, ITEM_HULL_MAX) entity_set_origin(ent, fOrigin) entity_set_vector(ent, EV_VEC_angles, fAngles) entity_set_vector(ent, EV_VEC_velocity, fVelocity) entity_set_int(ent, EV_INT_movetype, MOVETYPE_TOSS) entity_set_int(ent, EV_INT_solid, SOLID_TRIGGER) entity_set_int(ent, EV_INT_iuser2, iType)
task_remove(ent) task_set(get_pcvar_float(pCvar_ctf_weaponstay), "weapon_startFade", ent) }
#if FEATURE_C4 == true
player_giveC4(id) { give_item(id, g_szWeaponEntity[W_C4])
cs_set_user_plant(id, 1, 1) }
#endif // FEATURE_C4
player_healingEffect(id) { new iOrigin[3]
get_user_origin(id, iOrigin)
message_begin(MSG_PVS, SVC_TEMPENTITY, iOrigin) write_byte(TE_PROJECTILE) write_coord(iOrigin[x] + random_num(-10, 10)) write_coord(iOrigin[y] + random_num(-10, 10)) write_coord(iOrigin[z] + random_num(0, 30)) write_coord(0) write_coord(0) write_coord(15) write_short(gSpr_regeneration) write_byte(1) write_byte(id) message_end() }
player_updateRender(id, Float:fDamage = 0.0) { new bool:bGlows = (get_pcvar_num(pCvar_ctf_glows) == 1) new iTeam = g_iTeam[id] new iMode = kRenderNormal new iEffect = kRenderFxNone new iAmount = 0 new iColor[3] = {0,0,0}
if(g_bProtected[id]) { if(bGlows) iEffect = kRenderFxGlowShell
iAmount = 200
iColor[0] = (iTeam == TEAM_RED ? 155 : 0) iColor[1] = (fDamage > 0.0 ? 100 - clamp(floatround(fDamage), 0, 100) : 0) iColor[2] = (iTeam == TEAM_BLUE ? 155 : 0) }
#if FEATURE_ADRENALINE == true switch(g_iAdrenalineUse[id]) { case ADRENALINE_BERSERK: { if(bGlows) iEffect = kRenderFxGlowShell
iAmount = 160 iColor = {55, 0, 55} }
case ADRENALINE_INVISIBILITY: { iMode = kRenderTransAlpha
if(bGlows) iEffect = kRenderFxGlowShell
iAmount = 10 iColor = {15, 15, 15} } } #endif // FEATURE_ADRENALINE == true
if(player_hasFlag(id)) { if(iMode != kRenderTransAlpha) iMode = kRenderNormal
if(bGlows) iEffect = kRenderFxGlowShell
iColor[0] = (iTeam == TEAM_RED ? (iColor[0] > 0 ? 200 : 155) : 0) iColor[1] = (iAmount == 160 ? 55 : 0) iColor[2] = (iTeam == TEAM_BLUE ? (iColor[2] > 0 ? 200 : 155) : 0)
iAmount = (iAmount == 160 ? 50 : (iAmount == 10 ? 20 : 30)) }
set_user_rendering(id, iEffect, iColor[0], iColor[1], iColor[2], iMode, iAmount) }
player_updateSpeed(id) { new Float:fSpeed = 1.0
if(player_hasFlag(id)) fSpeed *= SPEED_FLAG
#if FEATURE_ADRENALINE == true
if(g_iAdrenalineUse[id] == ADRENALINE_SPEED) fSpeed *= SPEED_ADRENALINE
#endif // FEATURE_ADRENALINE
set_user_maxspeed(id, g_fWeaponSpeed[id] * fSpeed) }
player_screenFade(id, iColor[4] = {0,0,0,0}, Float:fEffect = 0.0, Float:fHold = 0.0, iFlags = FADE_OUT, bool:bReliable = false) { if(id && !g_iTeam[id]) return
static iType
if(1 <= id <= g_iMaxPlayers) iType = (bReliable ? MSG_ONE : MSG_ONE_UNRELIABLE) else iType = (bReliable ? MSG_ALL : MSG_BROADCAST)
message_begin(iType, gMsg_ScreenFade, _, id) write_short(clamp(floatround(fEffect * (1<<12)), 0, 0xFFFF)) write_short(clamp(floatround(fHold * (1<<12)), 0, 0xFFFF)) write_short(iFlags) write_byte(iColor[0]) write_byte(iColor[1]) write_byte(iColor[2]) write_byte(iColor[3]) message_end() }
game_announce(iEvent, iFlagTeam, szName[]) { new iColor = iFlagTeam new szText[64]
switch(iEvent) { case EVENT_TAKEN: { iColor = get_opTeam(iFlagTeam) formatex(szText, charsmax(szText), "%L", LANG_PLAYER, "ANNOUNCE_FLAGTAKEN", szName, LANG_PLAYER, g_szMLFlagTeam[iFlagTeam]) }
case EVENT_DROPPED: formatex(szText, charsmax(szText), "%L", LANG_PLAYER, "ANNOUNCE_FLAGDROPPED", szName, LANG_PLAYER, g_szMLFlagTeam[iFlagTeam])
case EVENT_RETURNED: { if(strlen(szName) != 0) formatex(szText, charsmax(szText), "%L", LANG_PLAYER, "ANNOUNCE_FLAGRETURNED", szName, LANG_PLAYER, g_szMLFlagTeam[iFlagTeam]) else formatex(szText, charsmax(szText), "%L", LANG_PLAYER, "ANNOUNCE_FLAGAUTORETURNED", LANG_PLAYER, g_szMLFlagTeam[iFlagTeam]) }
case EVENT_SCORE: formatex(szText, charsmax(szText), "%L", LANG_PLAYER, "ANNOUNCE_FLAGCAPTURED", szName, LANG_PLAYER, g_szMLFlagTeam[get_opTeam(iFlagTeam)]) }
set_hudmessage(iColor == TEAM_RED ? 255 : 0, 0, iColor == TEAM_BLUE ? 255 : 0, HUD_ANNOUNCE) show_hudmessage(0, szText)
client_print(0, print_console, "%s%L: %s", CONSOLE_PREFIX, LANG_PLAYER, "ANNOUNCEMENT", szText)
if(get_pcvar_num(pCvar_ctf_sound[iEvent])) client_cmd(0, "mp3 play ^"sound/ctf/%s.mp3^"", g_szSounds[iEvent][iFlagTeam]) }
|