Raised This Month: $ Target: $400
 0% 

[CSS/CSGO] Hide and Seek (Prop Hunt)


Post New Thread Closed Thread   
 
Thread Tools Display Modes
apocalyptic
Senior Member
Join Date: Feb 2013
Location: China
Old 12-18-2014 , 09:37   Re: [CSS/CSGO] Hide and Seek (Prop Hunt)
#91

Thank you for your wonderful job. But I found an interesting bug here:
1.For some unknown reason, hiders will suddenly be completely stealth(attached image 1). If hiders jump, they can be seen for a little while (when they are in the air), but they will be stealth again when they are back on the ground.
2.When hiders are stealth, they can press "screenshot" to make themselve appear again(attached image 2).
3."heightfix" dose NOT work.
Would someone please tell me how to do?
Thanks a lot.
Attached Images
File Type: jpg 1.jpg (90.3 KB, 903 views)
File Type: jpg 2.jpg (78.9 KB, 702 views)

Last edited by apocalyptic; 12-18-2014 at 09:39.
apocalyptic is offline
Nemdox
Member
Join Date: Aug 2012
Old 01-14-2015 , 03:37   Re: [CSS/CSGO] Hide and Seek (Prop Hunt)
#92

What is? I install clear server+metamod+sourcemod+ plugin Hide and Seek. Now, i have log error. What is?

L 01/14/2015 - 18:25:00: SourceMod error session started
L 01/14/2015 - 18:25:00: Info (map "de_dust2") (file "errors_20150114.log")
L 01/14/2015 - 18:25:00: [SM] Native "GetClientLanguage" reported: Invalid client index 0
L 01/14/2015 - 18:25:00: [SM] Displaying call stack trace for plugin "hide_and_seek.smx":
L 01/14/2015 - 18:25:00: [SM] [0] Line 2478, C:\Users\aiszhait\Documents\GitHub\Hide_And_S eek\addons\sourcemod\scripting\hide_and_seek. sp::GetClientLanguageID()
L 01/14/2015 - 18:25:00: [SM] [1] Line 1719, C:\Users\aiszhait\Documents\GitHub\Hide_And_S eek\addons\sourcemod\scripting\hide_and_seek. sp::Menu_SelectModel()
Nemdox is offline
Nemdox
Member
Join Date: Aug 2012
Old 01-14-2015 , 03:38   Re: [CSS/CSGO] Hide and Seek (Prop Hunt)
#93

I tried to compile a plugin, to me me gave out SmLib error
Nemdox is offline
Nemdox
Member
Join Date: Aug 2012
Old 01-14-2015 , 03:48   Re: [CSS/CSGO] Hide and Seek (Prop Hunt)
#94

I solved a problem by change of the coding with ansi on utf8-no bom (bcoz ru lang)

Last edited by Nemdox; 01-14-2015 at 05:10.
Nemdox is offline
Nemdox
Member
Join Date: Aug 2012
Old 01-14-2015 , 05:09   Re: [CSS/CSGO] Hide and Seek (Prop Hunt)
#95

Pls help! Three problems:
1) If you come to play for terrorists, often black screen until the end of expectation, as at KT. Such shouldn't be!

2) If you play for terrorists when you move in the form of a subject, twitchings of the screen, small friezes are noticeable! On other servers I come also such I don't observe!

3) error logs.
L 01/14/2015 - 20:06:14: SourceMod error session started
L 01/14/2015 - 20:06:14: Info (map "de_inferno") (file "errors_20150114.log")
L 01/14/2015 - 20:06:14: [SM] Native "KillTimer" reported: Invalid timer handle 13b00b5 (error 1)
L 01/14/2015 - 20:06:14: [SM] Displaying call stack trace for plugin "hide_and_seek.smx":
L 01/14/2015 - 20:06:14: [SM] [0] Line 859, D:\csgo-hide\csgo\addons\sourcemod\scripting\hide_and _seek.sp::Event_OnPlayerSpawn()
L 01/14/2015 - 20:06:14: [SM] Native "KillTimer" reported: Invalid timer handle 13b00b5 (error 1)
L 01/14/2015 - 20:06:15: [SM] Displaying call stack trace for plugin "hide_and_seek.smx":
L 01/14/2015 - 20:06:15: [SM] [0] Line 859, D:\csgo-hide\csgo\addons\sourcemod\scripting\hide_and _seek.sp::Event_OnPlayerSpawn()

maybe gamemode_casual.cfg problem?
Code:
Quote:
bot_autodifficulty_threshold_high 0.0 // Value between -20.0 and 20.0 (Amount above avg human contribution score, above which a bot should lower its difficulty) bot_autodifficulty_threshold_low -2.0 // Value between -20.0 and 20.0 (Amount below avg human contribution score, below which a bot should raise its difficulty) bot_chatter normal bot_defer_to_human_goals 0 bot_defer_to_human_items 1 bot_difficulty 1 bot_quota 6 bot_quota_mode fill cash_player_bomb_defused 200 cash_player_bomb_planted 200 cash_player_damage_hostage -30 cash_player_interact_with_hostage 300 cash_player_killed_enemy_default 200 cash_player_killed_enemy_factor 0.5 cash_player_killed_hostage -1000 cash_player_killed_teammate -300 cash_player_rescued_hostage 1000 cash_team_elimination_bomb_map 2700 cash_team_elimination_hostage_map_t 2000 cash_team_elimination_hostage_map_ct 2300 cash_team_hostage_alive 0 cash_team_hostage_interaction 500 cash_team_loser_bonus 2400 cash_team_loser_bonus_consecutive_rounds 0 cash_team_planted_bomb_but_defused 200 cash_team_rescued_hostage 0 cash_team_terrorist_win_bomb 2700 cash_team_win_by_defusing_bomb 2700 cash_team_win_by_hostage_rescue 3000 cash_team_win_by_time_running_out_hostage 2000 cash_team_win_by_time_running_out_bomb 2700 ff_damage_reduction_bullets 0 ff_damage_reduction_grenade 0 ff_damage_reduction_grenade_self 0 ff_damage_reduction_other 0 mp_afterroundmoney 0 mp_buytime 45 mp_buy_anywhere 0 mp_buy_during_immunity 0 mp_death_drop_defuser 1 mp_death_drop_grenade 2 // 0=none, 1=best, 2=current or best mp_death_drop_gun 1 // 0=none, 1=best, 2=current or best mp_defuser_allocation 2 // 0=none, 1=random, 2=everyone mp_force_pick_time 15 mp_forcecamera 1 // Set to 1 for team only spectating. mp_free_armor 1 mp_freezetime 0 mp_friendlyfire 1 mp_win_panel_display_time 3 mp_ggprogressive_round_restart_delay 15 mp_ggtr_bomb_defuse_bonus 1 mp_ggtr_bomb_detonation_bonus 1 mp_ggtr_bomb_pts_for_flash 4 mp_ggtr_bomb_pts_for_he 3 mp_ggtr_bomb_pts_for_molotov 5 mp_ggtr_bomb_pts_for_upgrade 2 mp_ggtr_bomb_respawn_delay 0 mp_ggtr_end_round_kill_bonus 1 mp_ggtr_halftime_delay 0.0 mp_ggtr_last_weapon_kill_ends_half 0 mp_respawn_immunitytime 0 mp_halftime 0 mp_match_can_clinch 0 // 0=No mercy rule, 1=team can clinch match win early if they win > 1/2 total rounds mp_maxmoney 10000 mp_maxrounds 0 mp_molotovusedelay 0 mp_playercashawards 1 mp_roundtime 6 mp_roundtime_hostage 6 mp_roundtime_defuse 6 mp_solid_teammates 0 mp_startmoney 1000 mp_teamcashawards 1 mp_timelimit 30 mp_warmuptime 0 mp_weapons_allow_zeus 0 spec_freeze_panel_extended_time 0 spec_freeze_time 5.0 sv_allow_votes 1 // Voting allowed in this mode sv_alltalk 1 sv_arms_race_vote_to_restart_disallowed_after 0 sv_deadtalk 0 sv_ignoregrenaderadio 0 tv_delay 30 mp_warmup_pausetimer 0 mp_halftime_pausetimer 0 mp_randomspawn 0 mp_randomspawn_los 0 sv_infinite_ammo 0 ammo_grenade_limit_flashbang 1 ammo_grenade_limit_total 3 mp_limitteams 0 mp_autoteambalance 0 mp_playerid 1 mp_teams_unbalance_limit 0 // // mp_weapons_allow_map_placed 1 mp_weapons_glow_on_ground 0 mp_display_kill_assists 1 mp_respawn_on_death_t 0 mp_respawn_on_death_ct 0 mp_ct_default_melee weapon_knife mp_ct_default_secondary weapon_hkp2000 mp_ct_default_primary "" mp_t_default_melee weapon_knife mp_t_default_secondary weapon_glock mp_t_default_primary "" mp_default_team_winner_no_objective -1 // 2 == CTs, 3 == Ts
Or server.cfg

Code:
log "off" // включение логироваия "off" - выключение 
mp_afterroundmoney 10000 // деньги после раунда 
mp_autokick 1 // автоматически кикать с сервера 
mp_autoteambalance 0 // балансировка команд
mp_limitteams 0 // количество игроков которые могут быть за одну команду выше баланса (к примеру если 3 CT и 3 T, то можно зайти 2м игрокам за одни из них 3 CT - 5 T), значение - это количество игроков.
mp_backup_round_auto 0
mp_backup_round_file ""
mp_backup_round_file_last ""
mp_backup_round_file_pattern ""
sv_allow_votes 1 // разрешить голосование (1 - да, 0 - нет) 
sv_alltalk 0 // разрешить всем разговаривать 
sv_cheats 0 // разрешить использовать чит-коды
sv_deadtalk 0 // разрешить мертвым говорить с живими 
sv_full_alltalk 0 // разрешить всем говорить между собой
sv_log_onefile 0 // записывать логи в один файл 
sv_logbans 1 // логировать баны 
sv_logfile 1 // логировать в файл 
sv_logflush 0  
sv_maxrate 128000
sv_mincmdrate 64 // минимальные рейты 
sv_minrate 80000
sv_minupdaterate 64
sv_region -1 // в каком регионе находится сервер 
sv_search_key 0
sv_spec_hear 1 // спектаторы слышат других 
sv_steamgroup 0 
sv_steamgroup_exclusive 0 
sv_tags "csgo,public,steam,quake," // теги сервера 
//sv_voiceenable 1 // включить возможность использовать микрофон в игре 
//sv_vote_allow_spectators 0 // разрешить голосовать спектрам 
//sv_vote_command_delay 2 
//sv_vote_creation_timer 1 
//sv_vote_failure_timer 200 
//sv_vote_quorum_ratio 0.5 
//sv_vote_timer_duration 15
//sv_allowdownload 1 // разрешить загружать файлы с сервера 
//sv_allowupload 1 // разрешить загружать файлы на сервер 
sv_hibernate_when_empty 0 // чтобы фпс был нормальным
//sv_hibernate_postgame_delay 20
//sv_reservation_timeout 60
tv_enable 0 // включить SourceTV (0 - выключить, 1 - включить) 
tv_autorecord 1 // автоматическая запись SourceTV 
tv_name "GOTV Nemdox" // имя SourceTV 
tv_title "GOTV - Nemdox" // титульное название 
tv_relaypassword "123" // пароль SourceTV 
tv_dispatchmode 0 
tv_snapshotrate 33 
tv_maxrate 0 
tv_delay 60 
tv_relayvoice 0 
tv_allow_camera_man 0 
tv_allow_static_shots 0 
tv_autoretry 1 
tv_chatgroupsize 0 
tv_chattimelimit 0 
tv_debug 0 
tv_delaymapchange 1 
tv_deltacache 2 
tv_overridemaster 0 
tv_transmitall 1 
tv_timeout 30
writeid
writeip
host_players_show 2
host_info_show 2
sv_lan 0
sm_advertisements_interval 120
mp_match_restart_delay 8 // смена карты
exec banned_ip.cfg
exec banned_user.cfg
writeid
writeip
sm_cvar mp_flashlight 0
sm_cvar sv_footsteps 0
sm_cvar sv_nonemesis 1
sm_cvar sv_nomvp 1
sm_cvar sv_nostats 1
mp_playerid 1
sm_cvar sv_allowminmodels 0
mp_teams_unbalance_limit 0
sm_cvar sv_turbophysics 1
mp_forcecamera 1
sm plugins list
Code:
[SM] Listing 19 plugins:
  01 "Admin File Reader" (1.6.3) by AlliedModders LLC
  02 "Admin Help" (1.6.3) by AlliedModders LLC
  03 "Admin Menu" (1.6.3) by AlliedModders LLC
  04 "Anti-Flood" (1.6.3) by AlliedModders LLC
  05 "Basic Ban Commands" (1.6.3) by AlliedModders LLC
  06 "Basic Chat" (1.6.3) by AlliedModders LLC
  07 "Basic Comm Control" (1.6.3) by AlliedModders LLC
  08 "Basic Commands" (1.6.3) by AlliedModders LLC
  09 "Basic Info Triggers" (1.6.3) by AlliedModders LLC
  10 "Basic Votes" (1.6.3) by AlliedModders LLC
  11 "Client Preferences" (1.6.3) by AlliedModders LLC
  12 "Disable Radar" (1.2) by Internet Bully
  13 "Fun Commands" (1.6.3) by AlliedModders LLC
  14 "Fun Votes" (1.6.3) by AlliedModders LLC
  15 "Hide and Seek" (1.5.2) by Jannik 'Peace-Maker' Hartung and Vladislav Dolgo
v and edited by Dk-- for works on CSGO
  16 "Nextmap" (1.6.3) by AlliedModders LLC
  17 "Player Commands" (1.6.3) by AlliedModders LLC
  18 "Reserved Slots" (1.6.3) by AlliedModders LLC
  19 "Sound Commands" (1.6.3) by AlliedModders LLC
sm exts list
Code:
[SM] Displaying 9 extensions:
[01] Automatic Updater (1.6.3): Updates SourceMod gamedata files
[02] Webternet (1.6.3): Extension for interacting with URLs
[03] CS Tools (1.6.3): CS extended functionality
[04] BinTools (1.6.3): Low-level C/C++ Calling API
[05] SDK Tools (1.6.3): Source SDK Tools
[06] Top Menus (1.6.3): Creates sorted nested menus
[07] Client Preferences (1.6.3): Saves client preference settings
[08] SQLite (1.6.3): SQLite Driver
[09] SDK Hooks (1.6.4-dev+4607): Source SDK Hooks
meta list
Code:
Listing 4 plugins:
  [01] SourceMod (1.6.3) by AlliedModders LLC
  [02] CS Tools (1.6.3) by AlliedModders LLC
  [03] SDK Tools (1.6.3) by AlliedModders LLC
  [04] SDK Hooks (1.6.4-dev+4607) by AlliedModders LLC
plugin.hide_and_seek
Code:
// This file was auto-generated by SourceMod (v1.6.3)
// ConVars for plugin "hide_and_seek.smx"


// Проверка переменных у игрока, 0 = выкл/1 = вкл.
// -
// Default: "0"
// Minimum: "0.000000"
// Maximum: "1.000000"
sm_hns_anticheat "0"

// Автоматически включить просмотр от третьего лица для "Прячущихся" . (Стандартно: 1)
// -
// Default: "1"
// Minimum: "0.000000"
// Maximum: "1.000000"
sm_hns_auto_thirdperson "1"

// Будет ли плагин автоматически выбирать модель для "Прячущихся"? 
// -
// Default: "0"
// Minimum: "0.000000"
// Maximum: "1.000000"
sm_hns_autochoose "0"

// Как часто "Прячущиеся" могут менять модель во время игры? 0 = бесконечно
// -
// Default: "2"
// Minimum: "0.000000"
sm_hns_changelimit "2"

// Как долго "Прячущиеся" могут выбирать модели после респауна?
// -
// Default: "30.0"
// Minimum: "0.000000"
sm_hns_changelimittime "30.0"

// Что делать с игроками у которых неправильно настроенные переменные, псоле истечения 15 секунд? 0: выкл. 1: переместить в наблюдатели. 2: кикнуть
// -
// Default: "1"
// Minimum: "0.000000"
// Maximum: "2.000000"
sm_hns_cheat_punishment "1"

// Отношение "Прячущихся" к "Ищущем". 0 = отключить баланс. (Стандартно: 3:1)
// -
// Default: "3"
// Minimum: "1.000000"
// Maximum: "64.000000"
sm_hns_ct_ratio "3"

// Отключить возможность приседать. (Стандартно: 1).
// -
// Default: "1"
// Minimum: "0.000000"
// Maximum: "1.000000"
sm_hns_disable_ducking "1"

// Отключить удар ножом на вторую клавишу мышки? Предотвращает случайные нажатия у игроков, что бы не потерять HP. (Стандартно: 1).
// -
// Default: "1"
// Minimum: "0.000000"
// Maximum: "1.000000"
sm_hns_disable_rightknife "1"

// Отключить использование вещей у CT. (Default: 1)
// -
// Default: "1"
// Minimum: "0.000000"
// Maximum: "1.000000"
sm_hns_disable_use "1"

// Включить мод  Hide and Seek?
// -
// Default: "1"
// Minimum: "0.000000"
// Maximum: "1.000000"
sm_hns_enable "1"

// "Ищущие" должны быть "заморожены" и ослеплены во время того, как прячутся игроки?
// -
// Default: "1"
// Minimum: "0.000000"
// Maximum: "1.000000"
sm_hns_freezects "1"

// Как долго "Ищущие" будут ослеплены и "заморожены"?
// -
// Default: "25.0"
// Minimum: "1.000000"
// Maximum: "120.000000"
sm_hns_freezetime "60.0"

// Скрыть кровь у "Прячущихся" при нанесении урона. (Стандартно: 1)
// -
// Default: "1"
// Minimum: "0.000000"
// Maximum: "1.000000"
sm_hns_hide_blood "1"

// Hide the location info shown next to players name on voice chat and teamsay? (Default: 1)
// -
// Default: "1"
// Minimum: "0.000000"
// Maximum: "1.000000"
sm_hns_hide_player_locations "1"

// Разрешить "Прячущимся" "замораживать" себя в прыжке? (Стандартно: 0)
// -
// Default: "0"
// Minimum: "0.000000"
// Maximum: "1.000000"
sm_hns_hider_freeze_inair "0"

// 0: Отключить /freeze команду для "Прячущихся", 1: "Замораживать" только движение модели, оставить возможность свободного обзора, 2: "Заморозить" и движение модели и не давать возможности вращать камерой. (Стандартно: 2)
// -
// Default: "1"
// Minimum: "0.000000"
// Maximum: "2.000000"
sm_hns_hider_freeze_mode "1"

// Сколько фрагов должны получить терористы, если выживут в раунде?
// -
// Default: "5"
// Minimum: "0.000000"
// Maximum: "10.000000"
sm_hns_hider_win_frags "5"

// Скорость передвижение "Прячущихся" (Стандартно: 1.00).
// -
// Default: "1.00"
// Minimum: "1.000000"
// Maximum: "3.000000"
sm_hns_hidersspeed "1.00"

// Сколько HP получит "Ищущий", если убьёт "Прячущегося"?
// -
// Default: "50"
// Minimum: "0.000000"
sm_hns_hp_seeker_bonus "20"

// Сколько HP потеряет "Ищущий", если выстрелит мимо?
// -
// Default: "5"
// Minimum: "0.000000"
sm_hns_hp_seeker_dec "5"

// Будет ли "Ищущий" терять HP, если выстрелит мимо, 0 = выкл/1 = вкл.
// -
// Default: "1"
// Minimum: "0.000000"
// Maximum: "1.000000"
sm_hns_hp_seeker_enable "1"

// Как много HP получит "Ищущий" за попадание в "Прячущегося"?
// -
// Default: "15"
// Minimum: "0.000000"
sm_hns_hp_seeker_inc "10"

// How many hp should a CT gain when hitting a hider with shotgun? (CS:GO only)
// -
// Default: "5"
// Minimum: "0.000000"
sm_hns_hp_seeker_inc_shotgun "5"

// При низком здоровье "Прячущиеся" должны становится невидимыми, 0 = выкл/1 = вкл.
// -
// Default: "0"
// Minimum: "0.000000"
// Maximum: "1.000000"
sm_hns_opacity_enable "0"

// Удалять тени от игроков и моделей?
// -
// Default: "1"
// Minimum: "0.000000"
// Maximum: "1.000000"
sm_hns_remove_shadows "1"

// Показать меню помощи, при первом респауне игрока. (Стандартно: 1)
// -
// Default: "1"
// Minimum: "0.000000"
// Maximum: "1.000000"
sm_hns_show_hidehelp "1"

// Показать строку прогресса, когда  остаётся 15 сек, до окончания "Заморозки" "Ищущего". (Стандартно: 1)
// -
// Default: "1"
// Minimum: "0.000000"
// Maximum: "1.000000"
sm_hns_show_progressbar "1"

// Убивать "Ищущего", если к концу раунда остались "Прячущиеся"? (Стандартно: 0)
// -
// Default: "0"
// Minimum: "0.000000"
// Maximum: "1.000000"
sm_hns_slay_seekers "0"

// Include taxed models when using random model choice? (Default: 0)
// -
// Default: "0"
// Minimum: "0.000000"
// Maximum: "1.000000"
sm_hns_use_taxed_in_random "0"

// Разрешить "Прячущимся" свистеть?
// -
// Default: "1"
sm_hns_whistle "1"

// Allow CTs to enforce T whistle?
// -
// Default: "0"
sm_hns_whistle_seeker "0"

// Сколько раз за раунд "Прячущиеся" могут свистеть?
// -
// Default: "5"
sm_hns_whistle_times "5"

Last edited by Nemdox; 01-14-2015 at 06:31.
Nemdox is offline
wxl42640211
Member
Join Date: Apr 2014
Old 01-17-2015 , 14:13   Re: [CSS/CSGO] Hide and Seek (Prop Hunt)
#96

oh~my god

the URL "https://github.com/Zipcore/Hide_And_Seek" can't be opend

404 erro~

please help me ~~

i need it !!

thank you ~

Attached Images
File Type: jpg QQ??20150118031035.jpg (87.9 KB, 1668 views)

Last edited by wxl42640211; 01-17-2015 at 14:17.
wxl42640211 is offline
NomisCZ
AlliedModders Donor
Join Date: Mar 2014
Location: Czech_Republic
Old 01-18-2015 , 08:13   Re: [CSS/CSGO] Hide and Seek (Prop Hunt)
#97

Github - https://github.com/Zipcore/hidenseek-csgo
Quote:
Originally Posted by wxl42640211 View Post
oh~my god

the URL "https://github.com/Zipcore/Hide_And_Seek" can't be opend

404 erro~

please help me ~~

i need it !!

thank you ~

NomisCZ is offline
wxl42640211
Member
Join Date: Apr 2014
Old 01-18-2015 , 09:44   Re: [CSS/CSGO] Hide and Seek (Prop Hunt)
#98

Quote:
Originally Posted by NomisCZ View Post
Thank you very much , but this is not samed whit Hide and Seek

Last edited by wxl42640211; 01-18-2015 at 10:20.
wxl42640211 is offline
Nemdox
Member
Join Date: Aug 2012
Old 01-19-2015 , 01:01   Re: [CSS/CSGO] Hide and Seek (Prop Hunt)
#99

Dear author, you can add the adjusted crvar thanks to which it will be possible to establish an auto-freezing of players of Terrorists after the termination of a freezing of CT. And add pls admin comand !freeze_tt (freezing all terrorists)

The BUG a Half of players doesn't appear at the beginning a round.

Last edited by Nemdox; 01-19-2015 at 07:05.
Nemdox is offline
qiuhaian
Senior Member
Join Date: Nov 2009
Old 02-17-2015 , 01:53   Re: [CSS/CSGO] Hide and Seek (Prop Hunt)
#100

[CSS/CSGO] Hide and Seek (Prop Hunt) 1.5.2


Code:
#pragma semicolon 1
#include <sourcemod>
#include <sdktools>
#include <cstrike>
#include <sdkhooks>
#include <smlib>
#define PLUGIN_VERSION "1.5.2"
// that's what GetLanguageCount() got me
#define MAX_LANGUAGES 27
#define PREFIX "\x04Hide and Seek \x01> \x03"
new csgo = false;
// plugin cvars
new Handle:g_hCVEnable = INVALID_HANDLE;
new Handle:g_hCVFreezeCTs = INVALID_HANDLE;
new Handle:g_hCVFreezeTime = INVALID_HANDLE;
new Handle:g_hCVChangeLimit = INVALID_HANDLE;
new Handle:g_hCVChangeLimittime = INVALID_HANDLE;
new Handle:g_hCVAutoChoose = INVALID_HANDLE;
new Handle:g_hCVWhistle = INVALID_HANDLE;
new Handle:g_hCVWhistleTimes = INVALID_HANDLE;
new Handle:g_hCVWhistleSeeker = INVALID_HANDLE;
new Handle:g_hCVAntiCheat = INVALID_HANDLE;
new Handle:g_hCVCheatPunishment = INVALID_HANDLE;
new Handle:g_hCVHiderWinFrags = INVALID_HANDLE;
new Handle:g_hCVSlaySeekers = INVALID_HANDLE;
new Handle:g_hCVHPSeekerEnable = INVALID_HANDLE;
new Handle:g_hCVHPSeekerDec = INVALID_HANDLE;
new Handle:g_hCVHPSeekerInc = INVALID_HANDLE;
new Handle:g_hCVHPSeekerIncShotgun = INVALID_HANDLE;
new Handle:g_hCVHPSeekerBonus = INVALID_HANDLE;
new Handle:g_hCVOpacityEnable = INVALID_HANDLE;
new Handle:g_hCVHiderSpeed = INVALID_HANDLE;
new Handle:g_hCVDisableRightKnife = INVALID_HANDLE;
new Handle:g_hCVDisableDucking = INVALID_HANDLE;
new Handle:g_hCVAutoThirdPerson = INVALID_HANDLE;
new Handle:g_hCVHiderFreezeMode = INVALID_HANDLE;
new Handle:g_hCVHideBlood = INVALID_HANDLE;
new Handle:g_hCVShowHideHelp = INVALID_HANDLE;
new Handle:g_hCVShowProgressBar = INVALID_HANDLE;
new Handle:g_hCVCTRatio = INVALID_HANDLE;
new Handle:g_hCVDisableUse = INVALID_HANDLE;
new Handle:g_hCVHiderFreezeInAir = INVALID_HANDLE;
new Handle:g_hCVRemoveShadows = INVALID_HANDLE;
new Handle:g_hCVUseTaxedInRandom = INVALID_HANDLE;
new Handle:g_hCVHidePlayerLocation = INVALID_HANDLE;
// primary enableswitch
new bool:g_bEnableHnS = true;
// config and menu handles
new Handle:g_hModelMenu[MAX_LANGUAGES] = {INVALID_HANDLE, ...};
new String:g_sModelMenuLanguage[MAX_LANGUAGES][4];
new Handle:kv;
// offsets
new g_Render;
new g_flFlashDuration;
new g_flFlashMaxAlpha;
new g_Freeze;
new g_iHasNightVision;
new g_flLaggedMovementValue;
new g_flProgressBarStartTime;
new g_iProgressBarDuration;
new g_iAccount;
new bool:g_bInThirdPersonView[MAXPLAYERS+1] = {false,...};
new bool:g_bIsFreezed[MAXPLAYERS+1] = {false,...};
new bool:g_bShotgun[MAXPLAYERS+1] = {false,...};
new g_iFreezeEntity[MAXPLAYERS+1] = {-1,...};
new Handle:g_hRoundTimeTimer = INVALID_HANDLE;
new Handle:g_iRoundTime = INVALID_HANDLE;
new g_iRoundStartTime = 0;
new g_iFirstCTSpawn = 0;
new g_iFirstTSpawn = 0;
new Handle:g_hShowCountdownTimer = INVALID_HANDLE;
new Handle:g_hSpamCommandsTimer = INVALID_HANDLE;
new bool:g_bRoundEnded = false;
new bool:g_bFirstSpawn[MAXPLAYERS+1] = {true,...};
// Cheat cVar part
new Handle:g_hCheckVarTimer[MAXPLAYERS+1] = {INVALID_HANDLE,...};
new String:cheat_commands[][] = {"cl_radaralpha", "r_shadows"};
new bool:g_bConVarViolation[MAXPLAYERS+1][2]; // 2 = amount of cheat_commands. update if you add one.
new g_iConVarMessage[MAXPLAYERS+1][2]; // 2 = amount of cheat_commands. update if you add one.
new Handle:g_hCheatPunishTimer[MAXPLAYERS+1] = {INVALID_HANDLE};
// Terrorist Modelchange stuff
new g_iTotalModelsAvailable = 0;
new g_iModelChangeCount[MAXPLAYERS+1] = {0,...};
new bool:g_bAllowModelChange[MAXPLAYERS+1] = {true,...};
new Handle:g_hAllowModelChangeTimer[MAXPLAYERS+1] = {INVALID_HANDLE,...};
new bool:g_bShowFakeProp[MAXPLAYERS+1];
// Model ground fix
new Float:g_iFixedModelHeight[MAXPLAYERS+1] = {0.0,...};
new bool:g_bClientIsHigher[MAXPLAYERS+1] = {false,...};
new g_iLowModelSteps[MAXPLAYERS+1] = {0,...};
new bool:g_bIsCTWaiting[MAXPLAYERS+1] = {false,...};
new Handle:g_hFreezeCTTimer[MAXPLAYERS+1] = {INVALID_HANDLE,...};
new Handle:g_hUnfreezeCTTimer[MAXPLAYERS+1] = {INVALID_HANDLE,...};
// protected server cvars
new String:protected_cvars[][] = {"mp_flashlight", 
          "sv_footsteps", 
          "mp_limitteams", 
          "mp_autoteambalance", 
          "mp_freezetime", 
          "sv_nonemesis", 
          "sv_nomvp", 
          "sv_nostats", 
          "mp_playerid",
          "sv_allowminmodels",
          "sv_turbophysics",
          "mp_teams_unbalance_limit",
          "mp_show_voice_icons"
         };
new forced_values[] = {0, // mp_flashlight
        0, // sv_footsteps
        0, // mp_limitteams
        0, // mp_autoteambalance
        0, // mp_freezetime
        1, // sv_nonemesis
        1, // sv_nomvp
        1, // sv_nostats
        1, // mp_playerid
        0, // sv_allowminmodels
        1, // sv_turbophysics
        0, // mp_teams_unbalance_limit
        0 // mp_show_voice_icons
       };
new previous_values[13] = {0,...}; // save previous values when forcing above, so we can restore the config if hns is disabled midgame. !same as comment next line!
new Handle:g_hProtectedConvar[13] = {INVALID_HANDLE,...}; // 13 = amount of protected_cvars. update if you add one.
new Handle:g_hForceCamera = INVALID_HANDLE;
// whistle sounds
new g_iWhistleCount[MAXPLAYERS+1] = {0,...};
new Handle:g_hWhistleDelay = INVALID_HANDLE;
new String:whistle_sounds[][] = {"ambient/animal/cow.wav", "ambient/animal/horse_4.wav", "ambient/animal/horse_5.wav", "ambient/machines/train_horn_3.wav", "ambient/misc/creak3.wav", "doors/door_metal_gate_close1.wav", "ambient/misc/flush1.wav"};
// Teambalance
new g_iLastJoinedCT = -1;
new bool:g_bCTToSwitch[MAXPLAYERS+1] = {false,...};
// AFK check
new Float:g_fSpawnPosition[MAXPLAYERS+1][3];
public Plugin:myinfo = 
{
 name = "Hide and Seek",
 author = "Jannik 'Peace-Maker' Hartung and Vladislav Dolgov and edited by Dk-- for works on CSGO",
 description = "Terrorists set a model and hide, CT seek terrorists.",
 version = PLUGIN_VERSION,
 url = "http://www.wcfan.de/ | http://www.elistor.ru/"
};
public OnPluginStart()
{
 new Handle:hVersion = CreateConVar("sm_hns_version", PLUGIN_VERSION, "Hide and seek", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD);
 if(hVersion != INVALID_HANDLE)
  SetConVarString(hVersion, PLUGIN_VERSION);
 
 // Config cvars
 g_hCVEnable =    CreateConVar("sm_hns_enable", "1", "Enable the Hide and Seek Mod?", FCVAR_PLUGIN, true, 0.0, true, 1.0);
 g_hCVFreezeCTs =   CreateConVar("sm_hns_freezects", "1", "Should CTs get freezed and blinded on spawn?", FCVAR_PLUGIN, true, 0.0, true, 1.0);
 g_hCVFreezeTime =   CreateConVar("sm_hns_freezetime", "25.0", "How long should the CTs are freezed after spawn?", FCVAR_PLUGIN, true, 1.00, true, 120.00);
 g_hCVChangeLimit =   CreateConVar("sm_hns_changelimit", "2", "How often a T is allowed to choose his model ingame? 0 = unlimited", FCVAR_PLUGIN, true, 0.00);
 g_hCVChangeLimittime =  CreateConVar("sm_hns_changelimittime", "30.0", "How long should a T be allowed to change his model again after spawn?", FCVAR_PLUGIN, true, 0.00);
 g_hCVAutoChoose =   CreateConVar("sm_hns_autochoose", "0", "Should the plugin choose models for the hiders automatically?", FCVAR_PLUGIN, true, 0.0, true, 1.0);
 g_hCVWhistle =    CreateConVar("sm_hns_whistle", "1", "Are terrorists allowed to whistle?", FCVAR_PLUGIN);
 g_hCVWhistleTimes =  CreateConVar("sm_hns_whistle_times", "5", "How many times a hider is allowed to whistle per round?", FCVAR_PLUGIN);
 g_hCVWhistleSeeker =  CreateConVar("sm_hns_whistle_seeker", "0", "Allow CTs to enforce T whistle?", FCVAR_PLUGIN);
 g_hCVAntiCheat =   CreateConVar("sm_hns_anticheat", "0", "Check player cheat convars, 0 = off/1 = on.", FCVAR_PLUGIN, true, 0.0, true, 1.0);
 g_hCVCheatPunishment =  CreateConVar("sm_hns_cheat_punishment", "1", "How to punish players with wrong cvar values after 15 seconds? 0: Disabled. 1: Switch to Spectator. 2: Kick", FCVAR_PLUGIN, true, 0.00, true, 2.00);
 g_hCVHiderWinFrags =  CreateConVar("sm_hns_hider_win_frags", "5", "How many frags should surviving terrorists gain?", FCVAR_PLUGIN, true, 0.00, true, 10.00);
 g_hCVSlaySeekers =   CreateConVar("sm_hns_slay_seekers", "0", "Should we slay all seekers on round end and there are still some hiders alive? (Default: 0)", FCVAR_PLUGIN, true, 0.0, true, 1.0);
 g_hCVHPSeekerEnable =  CreateConVar("sm_hns_hp_seeker_enable", "1", "Should CT lose HP when shooting, 0 = off/1 = on.", FCVAR_PLUGIN, true, 0.0, true, 1.0);
 g_hCVHPSeekerDec =   CreateConVar("sm_hns_hp_seeker_dec", "5", "How many hp should a CT lose on shooting?", FCVAR_PLUGIN, true, 0.00);
 g_hCVHPSeekerInc =   CreateConVar("sm_hns_hp_seeker_inc", "15", "How many hp should a CT gain when hitting a hider?", FCVAR_PLUGIN, true, 0.00);
 g_hCVHPSeekerIncShotgun=CreateConVar("sm_hns_hp_seeker_inc_shotgun", "5", "How many hp should a CT gain when hitting a hider with shotgun? (CS:GO only)", FCVAR_PLUGIN, true, 0.00);
 g_hCVHPSeekerBonus =  CreateConVar("sm_hns_hp_seeker_bonus", "50", "How many hp should a CT gain when killing a hider?", FCVAR_PLUGIN, true, 0.00);
 g_hCVOpacityEnable =  CreateConVar("sm_hns_opacity_enable", "0", "Should T get more invisible on low hp, 0 = off/1 = on.", FCVAR_PLUGIN, true, 0.0, true, 1.0);
 g_hCVHiderSpeed  =   CreateConVar("sm_hns_hidersspeed", "1.00", "Hiders speed (Default: 1.00).", FCVAR_PLUGIN, true, 1.00, true, 3.00);
 g_hCVDisableRightKnife =CreateConVar("sm_hns_disable_rightknife", "1", "Disable rightclick for CTs with knife? Prevents knifing without losing heatlh. (Default: 1).", FCVAR_PLUGIN, true, 0.00, true, 1.00);
 g_hCVDisableDucking = CreateConVar("sm_hns_disable_ducking", "1", "Disable ducking. (Default: 1).", FCVAR_PLUGIN, true, 0.00, true, 1.00);
 g_hCVAutoThirdPerson = CreateConVar("sm_hns_auto_thirdperson", "1", "Enable thirdperson view for hiders automatically. (Default: 1)", FCVAR_PLUGIN, true, 0.00, true, 1.00);
 g_hCVHiderFreezeMode = CreateConVar("sm_hns_hider_freeze_mode", "1", "0: Disables /freeze command for hiders, 1: Only freeze on position, be able to move camera, 2: Freeze completely (no cameramovements) (Default: 2)", FCVAR_PLUGIN, true, 0.00, true, 2.00);
 g_hCVHideBlood =  CreateConVar("sm_hns_hide_blood", "1", "Hide blood on hider damage. (Default: 1)", FCVAR_PLUGIN, true, 0.00, true, 1.00);
 g_hCVShowHideHelp =  CreateConVar("sm_hns_show_hidehelp", "1", "Show helpmenu explaining the game on first player spawn. (Default: 1)", FCVAR_PLUGIN, true, 0.00, true, 1.00);
 g_hCVShowProgressBar = CreateConVar("sm_hns_show_progressbar", "1", "Show progressbar for last 15 seconds of freezetime. (Default: 1)", FCVAR_PLUGIN, true, 0.00, true, 1.00);
 g_hCVCTRatio =   CreateConVar("sm_hns_ct_ratio", "3", "The ratio of hiders to 1 seeker. 0 to disables teambalance. (Default: 3)", FCVAR_PLUGIN, true, 1.00, true, 64.00);
 g_hCVDisableUse =  CreateConVar("sm_hns_disable_use", "1", "Disable CTs pushing things. (Default: 1)", FCVAR_PLUGIN, true, 0.00, true, 1.00);
 g_hCVHiderFreezeInAir = CreateConVar("sm_hns_hider_freeze_inair", "0", "Are hiders allowed to freeze in the air? (Default: 0)", FCVAR_PLUGIN, true, 0.00, true, 1.00);
 g_hCVRemoveShadows = CreateConVar("sm_hns_remove_shadows", "1", "Remove shadows from players and physic models? (Default: 1)", FCVAR_PLUGIN, true, 0.00, true, 1.00);
 g_hCVUseTaxedInRandom = CreateConVar("sm_hns_use_taxed_in_random", "0", "Include taxed models when using random model choice? (Default: 0)", FCVAR_PLUGIN, true, 0.00, true, 1.00);
 g_hCVHidePlayerLocation=CreateConVar("sm_hns_hide_player_locations", "1", "Hide the location info shown next to players name on voice chat and teamsay? (Default: 1)", FCVAR_PLUGIN, true, 0.00, true, 1.00);
 
 g_bEnableHnS = GetConVarBool(g_hCVEnable);
 HookConVarChange(g_hCVEnable, Cfg_OnChangeEnable);
 HookConVarChange(FindConVar("mp_restartgame"), RestartGame);
 
 if(g_bEnableHnS)
 {
  // !ToDo: Exclude hooks and other EnableHnS dependand functions into one seperate function.
  // Now you need to add the hooks to the Cfg_OnChangeEnable callback too..
  HookConVarChange(g_hCVHiderSpeed, OnChangeHiderSpeed);
  HookConVarChange(g_hCVAntiCheat, OnChangeAntiCheat);
  
  // Hooking events
  HookEvent("player_spawn", Event_OnPlayerSpawn);
  HookEvent("weapon_fire", Event_OnWeaponFire);
  HookEvent("player_death", Event_OnPlayerDeath);
  HookEvent("player_blind", Event_OnPlayerBlind);
  HookEvent("round_start", Event_OnRoundStart);
  HookEvent("round_end", Event_OnRoundEnd);
  HookEvent("player_team", Event_OnPlayerTeam);
  HookEvent("item_pickup", Event_OnItemPickup);
  
  decl String:theFolder[40];
  GetGameFolderName(theFolder, sizeof(theFolder));
  if(StrEqual(theFolder, "csgo"))
  {
   csgo = true;
   HookEvent("item_equip", Event_ItemEquip);
  }
 }
 
 // Register console commands
 RegConsoleCmd("hide", Menu_SelectModel, "Opens a menu with different models to choose as hider.");
 RegConsoleCmd("hidemenu", Menu_SelectModel, "Opens a menu with different models to choose as hider.");
 RegConsoleCmd("tp", Toggle_ThirdPerson, "Toggles the view to thirdperson for hiders.");
 RegConsoleCmd("thirdperson", Toggle_ThirdPerson, "Toggles the view to thirdperson for hiders.");
 RegConsoleCmd("third", Toggle_ThirdPerson, "Toggles the view to thirdperson for hiders.");
 RegConsoleCmd("+3rd", Enable_ThirdPerson, "Set the view to thirdperson for hiders.");
 RegConsoleCmd("-3rd", Disable_ThirdPerson, "Set the view to firstperson for hiders.");
 RegConsoleCmd("jointeam", Command_JoinTeam);
 RegConsoleCmd("whistle", Play_Whistle, "Plays a random sound from the hiders position to give the seekers a hint.");
 RegConsoleCmd("whoami", Display_ModelName, "Displays the current models description in chat.");
 RegConsoleCmd("hidehelp", Display_Help, "Displays a panel with informations how to play.");
 RegConsoleCmd("freeze", Freeze_Cmd, "Toggles freezing for hiders.");
 
 
 RegConsoleCmd("overview_mode", Block_Cmd);
 
 RegAdminCmd("sm_hns_force_whistle", ForceWhistle, ADMFLAG_CHAT, "Force a player to whistle");
 RegAdminCmd("sm_hns_reload_models", ReloadModels, ADMFLAG_RCON, "Reload the modellist from the map config file.");
  
 // Loading translations
 LoadTranslations("plugin.hide_and_seek");
 LoadTranslations("common.phrases"); // for FindTarget()
 
 // set the default values for cvar checking
 for(new x=1;x<=MaxClients;x++)
 {
  for(new y=0;y<sizeof(cheat_commands);y++)
  {
   g_bConVarViolation[x][y] = false;
   g_iConVarMessage[x][y] = 0;
  }
  if(IsClientInGame(x))
   OnClientPutInServer(x);
 }
 if(g_bEnableHnS)
 {
  // start advertising spam
  g_hSpamCommandsTimer = CreateTimer(120.0, SpamCommands, 0);
 }
 
 // hook cvars
 g_hForceCamera =  FindConVar("mp_forcecamera");
 g_iRoundTime =  FindConVar("mp_roundtime");
 
 // get the offsets
 // for transparency
 g_Render = FindSendPropOffs("CAI_BaseNPC", "m_clrRender");
 if(g_Render == -1)
  SetFailState("Couldnt find the m_clrRender offset!"); 
 
 // for hiding players on radar
 g_flFlashDuration = FindSendPropOffs("CCSPlayer", "m_flFlashDuration");
 if(g_flFlashDuration == -1)
  SetFailState("Couldnt find the m_flFlashDuration offset!");
 g_flFlashMaxAlpha = FindSendPropOffs("CCSPlayer", "m_flFlashMaxAlpha");
 if(g_flFlashMaxAlpha == -1)
  SetFailState("Couldnt find the m_flFlashMaxAlpha offset!");
 g_Freeze = FindSendPropOffs("CBasePlayer", "m_fFlags");
 if(g_Freeze == -1)
  SetFailState("Couldnt find the m_fFlags offset!");
 g_iHasNightVision = FindSendPropOffs("CCSPlayer", "m_bHasNightVision");
 if(g_iHasNightVision == -1)
  SetFailState("Couldnt find the m_bHasNightVision offset!");
 g_flLaggedMovementValue = FindSendPropOffs("CCSPlayer", "m_flLaggedMovementValue");
 if(g_flLaggedMovementValue == -1)
  SetFailState("Couldnt find the m_flLaggedMovementValue offset!");
 g_flProgressBarStartTime = FindSendPropOffs("CCSPlayer", "m_flProgressBarStartTime");
 if(g_flProgressBarStartTime == -1)
  SetFailState("Couldnt find the m_flProgressBarStartTime offset!");
 g_iProgressBarDuration = FindSendPropOffs("CCSPlayer", "m_iProgressBarDuration");
 if(g_iProgressBarDuration == -1)
  SetFailState("Couldnt find the m_iProgressBarDuration offset!");
 g_iAccount = FindSendPropOffs("CCSPlayer", "m_iAccount");
 if(g_iAccount == -1)
  SetFailState("Couldnt find the m_iAccount offset!");
 
 
 AutoExecConfig(true, "plugin.hide_and_seek");
}
public OnPluginEnd()
{
 if(g_bEnableHnS)
  ServerCommand("mp_restartgame 1");
}
public OnConfigsExecuted()
{
 if(g_bEnableHnS)
 {
  // set bad server cvars
  for(new i=0;i<sizeof(protected_cvars);i++)
  {
   g_hProtectedConvar[i] = FindConVar(protected_cvars[i]);
   if(g_hProtectedConvar[i] == INVALID_HANDLE)
    continue;
   
   previous_values[i] = GetConVarInt(g_hProtectedConvar[i]);
   SetConVarInt(g_hProtectedConvar[i], forced_values[i], true);
   HookConVarChange(g_hProtectedConvar[i], OnCvarChange);
  }
 }
}
/*
* 
* Generic Events
* 
*/
public OnMapStart()
{
 if(!g_bEnableHnS)
  return;
 
 BuildMainMenu();
 for(new i=0;i<sizeof(whistle_sounds);i++)
  PrecacheSound(whistle_sounds[i], true);
 
 PrecacheSound("radio/go.wav", true);
 
 // prevent us from bugging after mapchange
 g_iFirstCTSpawn = 0;
 g_iFirstTSpawn = 0;
 
 if(g_hShowCountdownTimer != INVALID_HANDLE)
 {
  KillTimer(g_hShowCountdownTimer);
  g_hShowCountdownTimer = INVALID_HANDLE;
 }
 
 new bool:foundHostageZone = false;
 
 // check if there is a hostage rescue zone
 new maxent = GetMaxEntities(), String:eName[64];
 for (new i=MaxClients;i<maxent;i++)
 {
  if ( IsValidEdict(i) && IsValidEntity(i) )
  {
   GetEdictClassname(i, eName, sizeof(eName));
   if(StrContains(eName, "func_hostage_rescue") != -1)
   {
    foundHostageZone = true;
   }
  }
 }
 
 // add a hostage rescue zone if there isn't one, so T will win after round time
 if(!foundHostageZone)
 {
  new ent = CreateEntityByName("func_hostage_rescue");
  if (ent>0)
  {
   new Float:orign[3] = {-1000.0,...};
   DispatchKeyValue(ent, "targetname", "hidenseek_roundend");
   DispatchKeyValueVector(ent, "orign", orign);
   DispatchSpawn(ent);
  }
 }
 
 // Remove shadows
 // Thanks to Bacardi and Leonardo @ http://forums.alliedmods.net/showthread.php?t=154269
 if(GetConVarBool(g_hCVRemoveShadows))
 {
  new bool:bShadowDisabled = false;
  new ent = -1;
  while((ent = FindEntityByClassname(ent, "shadow_control")) != -1)
  {
   SetVariantInt(1);
   AcceptEntityInput(ent, "SetShadowsDisabled");
   bShadowDisabled = true;
  }
  
  // Some maps don't have a shadow_control entity, so we create one.
  // Thanks to zipcore's suggestion http://forums.alliedmods.net/showpos...4&postcount=16
  if(!bShadowDisabled)
  {
   ent = CreateEntityByName("shadow_control");
   if(ent != -1)
   {
    SetVariantInt(1);
    AcceptEntityInput(ent, "SetShadowsDisabled");
   }
  }
 }
}
public OnMapEnd()
{
 if(!g_bEnableHnS)
  return;
 
 CloseHandle(kv);
 for(new i=0;i<MAX_LANGUAGES;i++)
 {
  if(g_hModelMenu[i] != INVALID_HANDLE)
  {
   CloseHandle(g_hModelMenu[i]);
   g_hModelMenu[i] = INVALID_HANDLE;
  }
  Format(g_sModelMenuLanguage[i], 4, "");
 }
 
 g_iFirstCTSpawn = 0;
 g_iFirstTSpawn = 0;
 
 if(g_hShowCountdownTimer != INVALID_HANDLE)
 {
  KillTimer(g_hShowCountdownTimer);
  g_hShowCountdownTimer = INVALID_HANDLE;
 }
 
 if(g_hRoundTimeTimer != INVALID_HANDLE)
 {
  KillTimer(g_hRoundTimeTimer);
  g_hRoundTimeTimer = INVALID_HANDLE;
 }
 
 if(g_hWhistleDelay != INVALID_HANDLE)
 {
  KillTimer(g_hWhistleDelay);
  g_hWhistleDelay = INVALID_HANDLE;
 }
}
public OnClientPutInServer(client)
{
 if(!g_bEnableHnS)
  return;
 
 if(!IsFakeClient(client) && GetConVarBool(g_hCVAntiCheat))
  g_hCheckVarTimer[client] = CreateTimer(1.0, StartVarChecker, client, TIMER_REPEAT);
 
 // Hook weapon pickup
 SDKHook(client, SDKHook_WeaponCanUse, OnWeaponCanUse);
 SDKHook(client, SDKHook_WeaponCanSwitchTo, OnWeaponCanUse);
 SDKHook(client, SDKHook_WeaponEquip, OnWeaponCanUse);
 SDKHook(client, SDKHook_WeaponSwitch, OnWeaponCanUse);
 
 // Hook attackings to hide blood
 SDKHook(client, SDKHook_TraceAttack, OnTraceAttack);
 
 // Hide player location info
 SDKHook(client, SDKHook_PostThinkPost, Hook_OnPostThinkPost);
 SDKHook(client, SDKHook_PostThink, Hook_OnPostThink);
}
public OnClientDisconnect(client)
{
 if(!g_bEnableHnS)
  return;
 
 // set the default values for cvar checking
 if(!IsFakeClient(client))
 {
  for(new i=0;i<sizeof(cheat_commands);i++)
  {
   g_bConVarViolation[client][i] = false;
   g_iConVarMessage[client][i] = 0;
  }
 
  g_bInThirdPersonView[client] = false;
  g_bIsFreezed[client] = false;
  g_iModelChangeCount[client] = 0;
  g_bIsCTWaiting[client] = false;
  g_iWhistleCount[client] = 0;
  if (g_hCheatPunishTimer[client] != INVALID_HANDLE)
  {
   KillTimer(g_hCheatPunishTimer[client]);
   g_hCheatPunishTimer[client] = INVALID_HANDLE;
  }
  if (g_bAllowModelChange[client] && g_hAllowModelChangeTimer[client] != INVALID_HANDLE)
  {
   KillTimer(g_hAllowModelChangeTimer[client]);
   g_hAllowModelChangeTimer[client] = INVALID_HANDLE;
  }
  if(g_hFreezeCTTimer[client] != INVALID_HANDLE)
  {
   KillTimer(g_hFreezeCTTimer[client]);
   g_hFreezeCTTimer[client] = INVALID_HANDLE;
  }
  if(g_hUnfreezeCTTimer[client] != INVALID_HANDLE)
  {
   KillTimer(g_hUnfreezeCTTimer[client]);
   g_hUnfreezeCTTimer[client] = INVALID_HANDLE;
  }
 }
 g_bAllowModelChange[client] = true;
 g_bFirstSpawn[client] = true;
 
 g_bClientIsHigher[client] = false;
 g_iFixedModelHeight[client] = 0.0;
 g_iLowModelSteps[client] = 0;
 
 // Teambalancer
 g_bCTToSwitch[client] = false;
 CreateTimer(0.1, Timer_ChangeTeam, client, TIMER_FLAG_NO_MAPCHANGE);
 
 // AFK check
 for(new i=0;i<3;i++)
 {
  g_fSpawnPosition[client][i] = 0.0;
 }
 
 /*if (g_hCheckVarTimer[client] != INVALID_HANDLE)
 {
  KillTimer(g_hCheckVarTimer[client]);
  g_hCheckVarTimer[client] = INVALID_HANDLE;
 }*/
}
// prevent players from ducking
public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:angles[3], &weapon, &subtype, &cmdnum, &tickcount, &seed, mouse[2])
{
 if(!g_bEnableHnS)
  return Plugin_Continue;
 
 new iInitialButtons = buttons;
 
 decl String:weaponName[30];
 // don't allow ct's to shoot in the beginning of the round
 new team = GetClientTeam(client);
 GetClientWeapon(client, weaponName, sizeof(weaponName));
 if(team == CS_TEAM_CT && g_bIsCTWaiting[client] && (buttons & IN_ATTACK || buttons & IN_ATTACK2))
 {
  buttons &= ~IN_ATTACK;
  buttons &= ~IN_ATTACK2;
 } // disable rightclick knifing for cts
 else if(team == CS_TEAM_CT && GetConVarBool(g_hCVDisableRightKnife) && buttons & IN_ATTACK2 && !strcmp(weaponName, "weapon_knife"))
 {
  buttons &= ~IN_ATTACK2;
 }
 
 //Freeze and rotation fix
 Client_UpdateFakeProp(client);
 
 // Modelfix
 if(g_iFixedModelHeight[client] != 0.0 && IsPlayerAlive(client) && GetClientTeam(client) == CS_TEAM_T)
 {
  new Float:vecVelocity[3];
  vecVelocity[0] = GetEntPropFloat(client, Prop_Send, "m_vecVelocity[0]");
  vecVelocity[1] = GetEntPropFloat(client, Prop_Send, "m_vecVelocity[1]");
  vecVelocity[2] = GetEntPropFloat(client, Prop_Send, "m_vecVelocity[2]");
  // Player isn't moving
  if(vecVelocity[0] == 0.0 && vecVelocity[1] == 0.0 && vecVelocity[2] == 0.0 && !(buttons & IN_FORWARD || buttons & IN_BACK || buttons & IN_MOVELEFT || buttons & IN_MOVERIGHT || buttons & IN_JUMP))
  {
   if(!g_bClientIsHigher[client] && GetEntPropEnt(client, Prop_Send, "m_hGroundEntity") != -1)
   {
    new Float:vecClientOrigin[3];
    GetClientAbsOrigin(client, vecClientOrigin);
    vecClientOrigin[2] += g_iFixedModelHeight[client];
    TeleportEntity(client, vecClientOrigin, NULL_VECTOR, NULL_VECTOR);
    SetEntityMoveType(client, MOVETYPE_NONE);
    g_bClientIsHigher[client] = true;
    g_iLowModelSteps[client] = 0;
   }
  }
  // Player is running for 60 thinks? make him visible for a short time
  else if(g_iLowModelSteps[client] == 60)
  {
   if(!g_bClientIsHigher[client] && GetEntPropEnt(client, Prop_Send, "m_hGroundEntity") != -1)
   {
    new Float:vecClientOrigin[3];
    GetClientAbsOrigin(client, vecClientOrigin);
    vecClientOrigin[2] += g_iFixedModelHeight[client];
    TeleportEntity(client, vecClientOrigin, NULL_VECTOR, NULL_VECTOR);
   }
   g_iLowModelSteps[client] = 0;
  }
  // Player is moving
  else if(!g_bIsFreezed[client])
  {
   if(g_bClientIsHigher[client])
   {
    new Float:vecClientOrigin[3];
    GetClientAbsOrigin(client, vecClientOrigin);
    vecClientOrigin[2] -= g_iFixedModelHeight[client];
    TeleportEntity(client, vecClientOrigin, NULL_VECTOR, NULL_VECTOR);
    SetEntityMoveType(client, MOVETYPE_WALK);
    g_bClientIsHigher[client] = false;
   }
   g_iLowModelSteps[client]++;
  }
  
  // Always disable ducking for that kind of models.
  if(buttons & IN_DUCK)
  {
   buttons &= ~IN_DUCK;
  }
 }
 
 // disable ducking for everyone
 if(buttons & IN_DUCK && GetConVarBool(g_hCVDisableDucking))
  buttons &= ~IN_DUCK;
 
 // disable use for everyone
 if(GetConVarBool(g_hCVDisableUse) && buttons & IN_USE)
  buttons &= ~IN_USE;
 
 if(iInitialButtons != buttons)
  return Plugin_Changed;
 else
  return Plugin_Continue;
}
// SDKHook Callbacks
public Action:OnWeaponCanUse(client, weapon)
{
 // Allow only CTs to use a weapon
 if(g_bEnableHnS && IsClientInGame(client) && GetClientTeam(client) != CS_TEAM_CT)
 {
  return Plugin_Handled;
 }
 return Plugin_Continue;
}
//Used to balance life hit for seekers
public Action:Event_ItemEquip(Handle:event, const String:name[], bool:dontBroadcast)
{
 new client = GetClientOfUserId(GetEventInt(event, "userid"));
 new type = GetEventInt(event, "weptype");
 if(type == 4) // 4 = Shotgun
 {
  //Player has a shutgun in his hand
  g_bShotgun[client] = true;
 }
 else g_bShotgun[client] = false;
}
// Used to block blood
// set a normal model right before death to avoid errors
public Action:OnTraceAttack(victim, &attacker, &inflictor, &Float:damage, &damagetype, &ammotype, hitbox, hitgroup)
{
 if(!g_bEnableHnS)
  return Plugin_Continue;
 
 if(GetClientTeam(victim) == CS_TEAM_T)
 {
  new remainingHealth = GetClientHealth(victim)-RoundToFloor(damage);
  
  // Attacker is a human?
  if(GetConVarBool(g_hCVHPSeekerEnable) && attacker > 0 && attacker <= MaxClients && IsPlayerAlive(attacker) && !IsPlayerAFK(victim))
  {
   new decrease = GetConVarInt(g_hCVHPSeekerDec);
   
   if(g_bShotgun[attacker])
    SetEntityHealth(attacker, GetClientHealth(attacker)+GetConVarInt(g_hCVHPSeekerIncShotgun)+decrease);
   else SetEntityHealth(attacker, GetClientHealth(attacker)+GetConVarInt(g_hCVHPSeekerInc)+decrease);
   
   // the hider died? give extra health! need to add the decreased value again, since he fired his gun and lost hp.
   // possible "bug": seeker could be slayed because weapon_fire is called earlier than player_hurt.
   if(remainingHealth < 0)
    SetEntityHealth(attacker, GetClientHealth(attacker)+GetConVarInt(g_hCVHPSeekerBonus)+decrease);
  }
  
  // prevent errors in console because of missing death animation of prop ;)
  if(remainingHealth < 0)
  {
   //SetEntityModel(victim, "models/player/t_guerilla.mdl");
   return Plugin_Continue; // just let the damage get through
  }
  else if(GetConVarBool(g_hCVOpacityEnable))
  {
   new alpha = 150 + RoundToNearest(10.5*float(remainingHealth/10));
   
   SetEntData(victim, g_Render+3, alpha, 1, true);
   SetEntityRenderMode(victim, RENDER_TRANSTEXTURE);
  }
  
  if(GetConVarBool(g_hCVHideBlood))
  {
   // Simulate the damage
   SetEntityHealth(victim, remainingHealth);
   
   // Don't show the blood!
   return Plugin_Handled;
  }
 }
 
 return Plugin_Continue;
}
public Hook_OnPostThinkPost(client)
{
 if(GetConVarBool(g_hCVHidePlayerLocation) && GetClientTeam(client) == CS_TEAM_T)
  SetEntPropString(client, Prop_Send, "m_szLastPlaceName", "");
}
public Hook_OnPostThink(client)
{
 if(csgo && GetClientTeam(client) == CS_TEAM_T)
  SetEntPropEnt(client, Prop_Send, "m_bSpotted", 0);
}
/*
* 
* Hooked Events
* 
*/
// Player Spawn event
public Action:Event_OnPlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast)
{
 if(!g_bEnableHnS)
  return Plugin_Continue;
 
 new client = GetClientOfUserId(GetEventInt(event, "userid"));
 new team = GetClientTeam(client);
 if(team <= CS_TEAM_SPECTATOR || !IsPlayerAlive(client))
  return Plugin_Continue;
 else if(team == CS_TEAM_T) // Team T
 {
  // set the mp_forcecamera value correctly, so he can use thirdperson again
  if(!IsFakeClient(client) && GetConVarInt(g_hForceCamera) == 1)
   SendConVarValue(client, g_hForceCamera, "0");
  
  // reset model change count
  g_iModelChangeCount[client] = 0;
  g_bInThirdPersonView[client] = false;
  if(!IsFakeClient(client) && g_hAllowModelChangeTimer[client] != INVALID_HANDLE)
  {
   KillTimer(g_hAllowModelChangeTimer[client]);
   g_hAllowModelChangeTimer[client] = INVALID_HANDLE;
  }
  g_bAllowModelChange[client] = true;
  
  // Reset model fix height
  g_iFixedModelHeight[client] = 0.0;
  g_bClientIsHigher[client] = false;
  
  // set the speed
  SetEntDataFloat(client, g_flLaggedMovementValue, GetConVarFloat(g_hCVHiderSpeed), true);
  
  // reset the transparent
  if(GetConVarBool(g_hCVOpacityEnable))
  {
   SetEntData(client,g_Render+3,255,1,true);
   SetEntityRenderMode(client, RENDER_TRANSTEXTURE);
  }
  
  new Float:changeLimitTime = GetConVarFloat(g_hCVChangeLimittime);
  
  // Assign a model to bots immediately and disable all menus or timers.
  if(IsFakeClient(client))
   g_hAllowModelChangeTimer[client] = CreateTimer(0.1, DisableModelMenu, client);
  else
  {
   // only disable the menu, if it's not unlimited
   if(changeLimitTime > 0.0)
    g_hAllowModelChangeTimer[client] = CreateTimer(changeLimitTime, DisableModelMenu, client);
   
   // Set them to thirdperson automatically
   if(GetConVarBool(g_hCVAutoThirdPerson))
    SetThirdPersonView(client, true);
   
   if(GetConVarBool(g_hCVAutoChoose))
    SetRandomModel(client);
   else if(changeLimitTime > 0.0)
    DisplayMenu(g_hModelMenu[GetClientLanguageID(client)], client, RoundToFloor(changeLimitTime));
   else
    DisplayMenu(g_hModelMenu[GetClientLanguageID(client)], client, MENU_TIME_FOREVER);
  }
  
  g_iWhistleCount[client] = 0;
  g_bIsFreezed[client] = false;
  
  if(g_iFirstTSpawn == 0)
  {
   g_iFirstTSpawn = GetTime();
  }
  if(GetConVarBool(g_hCVFreezeCTs))
   PrintToChat(client, "%s%t", PREFIX, "seconds to hide", RoundToFloor(GetConVarFloat(g_hCVFreezeTime)));
  else
   PrintToChat(client, "%s%t", PREFIX, "seconds to hide", 0);
   
  SetRandomModel(client);
 }
 else if(team == CS_TEAM_CT) // Team CT
 {
  if(!IsFakeClient(client) && GetConVarInt(g_hForceCamera) == 1)
   SendConVarValue(client, g_hForceCamera, "1");
  
  new currentTime = GetTime();
  new Float:freezeTime = GetConVarFloat(g_hCVFreezeTime);
  // don't keep late spawning cts blinded longer than the others :)
  if(g_iFirstCTSpawn == 0)
  {
   if(g_hShowCountdownTimer != INVALID_HANDLE)
   {
    KillTimer(g_hShowCountdownTimer);
    g_hShowCountdownTimer = INVALID_HANDLE;
    if(GetConVarBool(g_hCVShowProgressBar))
    {
     for(new i=1;i<=MaxClients;i++)
     {
      if(IsClientInGame(i))
      {
       SetEntDataFloat(i, g_flProgressBarStartTime, 0.0, true);
       SetEntData(i, g_iProgressBarDuration, 0, 4, true);
      }
     }
    }
   }
   else if(GetConVarBool(g_hCVFreezeCTs))
   {
    // show time in center
    g_hShowCountdownTimer = CreateTimer(0.01, ShowCountdown, RoundToFloor(GetConVarFloat(g_hCVFreezeTime)));
   }
   g_iFirstCTSpawn = currentTime;
  }
  // only freeze spawning players if the freezetime is still running.
  if(GetConVarBool(g_hCVFreezeCTs) && (float(currentTime - g_iFirstCTSpawn) < freezeTime))
  {
   g_bIsCTWaiting[client] = true;
   CreateTimer(0.05, FreezePlayer, client, TIMER_FLAG_NO_MAPCHANGE);
   
   // Start freezing player
   g_hFreezeCTTimer[client] = CreateTimer(2.0, FreezePlayer, client, TIMER_FLAG_NO_MAPCHANGE|TIMER_REPEAT);
   
   if(g_hUnfreezeCTTimer[client] != INVALID_HANDLE)
   {
    KillTimer(g_hUnfreezeCTTimer[client]);
    g_hUnfreezeCTTimer[client] = INVALID_HANDLE;
   }
   
   // Stop freezing player
   g_hUnfreezeCTTimer[client] = CreateTimer(freezeTime-float(currentTime - g_iFirstCTSpawn), UnFreezePlayer, client, TIMER_FLAG_NO_MAPCHANGE);
   
   PrintToChat(client, "%s%t", PREFIX, "Wait for t to hide", RoundToFloor(freezeTime-float(currentTime - g_iFirstCTSpawn)));
  }
  
  // show help menu on first spawn
  if(GetConVarBool(g_hCVShowHideHelp) && g_bFirstSpawn[client])
  {
   Display_Help(client, 0);
   g_bFirstSpawn[client] = false;
  }
  
  // Make sure CTs have a knife
  CreateTimer(2.0, Timer_CheckCTHasKnife, GetClientUserId(client), TIMER_FLAG_NO_MAPCHANGE);
 }
 
 // hide radar
 // Huge thanks to GoD-Tony!
 SetEntDataFloat(client, g_flFlashDuration, 10000.0, true);
 SetEntDataFloat(client, g_flFlashMaxAlpha, 0.5, true);
 
 CreateTimer(0.5, Timer_SaveSpawnPosition, GetClientUserId(client), TIMER_FLAG_NO_MAPCHANGE);
 
 return Plugin_Continue;
}
// subtract 5hp for every shot a seeker is giving
public Action:Event_OnWeaponFire(Handle:event, const String:name[], bool:dontBroadcast)
{
 if(!g_bEnableHnS)
  return Plugin_Continue;
 
 if(!GetConVarBool(g_hCVHPSeekerEnable) || g_bRoundEnded)
  return Plugin_Continue;
 
 new client = GetClientOfUserId(GetEventInt(event, "userid"));
 new decreaseHP = GetConVarInt(g_hCVHPSeekerDec);
 new clientHealth = GetClientHealth(client);
 
 // he can take it
 if((clientHealth-decreaseHP) > 0)
 {
  SetEntityHealth(client, (clientHealth-decreaseHP));
 }
 else // slay him
 {
  ForcePlayerSuicide(client);
 }
 return Plugin_Continue;
}
public Action:Event_OnRoundStart(Handle:event, const String:name[], bool:dontBroadcast)
{
 if(!g_bEnableHnS)
  return Plugin_Continue;
 
 g_bRoundEnded = false;
 
 // When disabling +use or "e" button open all doors on the map and keep them opened.
 new bool:bUse = GetConVarBool(g_hCVDisableUse);
 
 new maxent = GetMaxEntities(), String:eName[64];
 for (new i=MaxClients;i<maxent;i++)
 {
  if ( IsValidEdict(i) && IsValidEntity(i) )
  {
   GetEdictClassname(i, eName, sizeof(eName));
   // remove bombzones and hostages so no normal gameplay could end the round
   if ( StrContains(eName, "hostage_entity") != -1 || StrContains(eName, "func_bomb_target") != -1  || (StrContains(eName, "func_buyzone") != -1 && GetEntProp(i, Prop_Data, "m_iTeamNum", 4) == CS_TEAM_T))
   {
    RemoveEdict(i);
   }
   // Open all doors
   else if(bUse && StrContains(eName, "_door", false) != -1)
   {
    AcceptEntityInput(i, "Open");
    HookSingleEntityOutput(i, "OnClose", EntOutput_OnClose);
   }
  }
 }
 
 // Remove shadows
 // Thanks to Bacardi and Leonardo @ http://forums.alliedmods.net/showthread.php?t=154269
 if(GetConVarBool(g_hCVRemoveShadows))
 {
  new ent = -1;
  while((ent = FindEntityByClassname(ent, "shadow_control")) != -1)
  {
   SetVariantInt(1);
   AcceptEntityInput(ent, "SetShadowsDisabled");
  }
 }
 
 // show the roundtime in env_hudhint entity
 g_iRoundStartTime = GetTime();
 new realRoundTime = RoundToNearest(GetConVarFloat(g_iRoundTime)*60.0);
 //If it's CS:Source we need to show round time while in thirdperson
 if(!csgo)
 {
  g_hRoundTimeTimer = CreateTimer(0.5, ShowRoundTime, realRoundTime, TIMER_FLAG_NO_MAPCHANGE);
 }
 
 return Plugin_Continue;
}
// give terrorists frags
public Action:Event_OnRoundEnd(Handle:event, const String:name[], bool:dontBroadcast)
{
 if(!g_bEnableHnS)
  return Plugin_Continue;
 
 // round has ended. used to not decrease seekers hp on shoot
 g_bRoundEnded = true;
 
 g_iFirstCTSpawn = 0;
 g_iFirstTSpawn = 0;
 
 if(g_hShowCountdownTimer != INVALID_HANDLE)
 {
  KillTimer(g_hShowCountdownTimer);
  g_hShowCountdownTimer = INVALID_HANDLE;
 }
 
 if(g_hRoundTimeTimer != INVALID_HANDLE)
 {
  KillTimer(g_hRoundTimeTimer);
  g_hRoundTimeTimer = INVALID_HANDLE;
 }
 
 if(g_hWhistleDelay != INVALID_HANDLE)
 {
  KillTimer(g_hWhistleDelay);
  g_hWhistleDelay = INVALID_HANDLE;
 }
 
 new winnerTeam = GetEventInt(event, "winner");
 
 if(winnerTeam == CS_TEAM_T)
 {
  new increaseFrags = GetConVarInt(g_hCVHiderWinFrags);
  
  new bool:aliveTerrorists = false;
  new iFrags = 0;
  // increase playerscore of all alive Terrorists
  for(new i=1;i<=MaxClients;i++)
  {
   if(IsClientInGame(i) && IsPlayerAlive(i) && GetClientTeam(i) == CS_TEAM_T)
   {
    if(increaseFrags > 0)
    {
     // increase kills by x
     iFrags = GetClientFrags(i) + increaseFrags;
     SetEntProp(i, Prop_Data, "m_iFrags", iFrags, 4);
     aliveTerrorists = true;
    }
    
    // set godmode for the rest of the round
    SetEntProp(i, Prop_Data, "m_takedamage", 0, 1);
   }
  }
  
  if(aliveTerrorists)
  {
   PrintToChatAll("%s%t", PREFIX, "got frags", increaseFrags);
  }
  
  if(GetConVarBool(g_hCVSlaySeekers))
  {
   // slay all seekers
   for(new i=1;i<=MaxClients;i++)
   {
    if(IsClientInGame(i) && IsPlayerAlive(i) && GetClientTeam(i) == CS_TEAM_CT)
    {
     ForcePlayerSuicide(i);
    }
   }
  }
 }
 
 // Switch the flagged players to CT
 CreateTimer(0.1, Timer_SwitchTeams, _, TIMER_FLAG_NO_MAPCHANGE);
 
 return Plugin_Continue;
}
// remove ragdolls on death...
public Action:Event_OnPlayerDeath(Handle:event, const String:name[], bool:dontBroadcast)
{
 if(!g_bEnableHnS)
  return Plugin_Continue;
 
 new client = GetClientOfUserId(GetEventInt(event, "userid"));
 
 if(g_iFixedModelHeight[client] != 0.0 && g_bClientIsHigher[client])
 {
  SetEntityMoveType(client, MOVETYPE_WALK);
  g_bClientIsHigher[client] = false;
 }
 g_iFixedModelHeight[client] = 0.0;
 g_bClientIsHigher[client] = false;
 
 // Show guns again.
 SetThirdPersonView(client, false);
 
 // set the mp_forcecamera value correctly, so he can watch his teammates
 // This doesn't work. Even if the convar is set to 0, the hiders are only able to spectate their teammates..
 if(GetConVarInt(g_hForceCamera) == 1)
 {
  if(!IsFakeClient(client) && GetClientTeam(client) != CS_TEAM_T)
   SendConVarValue(client, g_hForceCamera, "1");
  else if(!IsFakeClient(client))
   SendConVarValue(client, g_hForceCamera, "0");
 }
 
 if (!IsValidEntity(client) || IsPlayerAlive(client))
  return Plugin_Continue;
 
 // Unfreeze, if freezed before
 if(g_bIsFreezed[client])
 {
  if(GetConVarInt(g_hCVHiderFreezeMode) == 1)
   SetEntityMoveType(client, MOVETYPE_WALK);
  else
  {
   SetEntData(client, g_Freeze, FL_FAKECLIENT|FL_ONGROUND|FL_PARTIALGROUND, 4, true);
   SetEntityMoveType(client, MOVETYPE_WALK);
  }
  
  g_bIsFreezed[client] = false;
 }
 
 new ragdoll = GetEntPropEnt(client, Prop_Send, "m_hRagdoll");
 if (ragdoll<0)
  return Plugin_Continue;
 
 RemoveEdict(ragdoll);
 
 return Plugin_Continue;
}
public Event_OnPlayerBlind(Handle:event, const String:name[], bool:dontBroadcast)
{
 if(!g_bEnableHnS)
  return;
 
 // Thanks to GoD-Tony!
 new userid = GetEventInt(event, "userid");
 new client = GetClientOfUserId(userid);
 new Float:iDuration = GetEntDataFloat(client, g_flFlashDuration);
 if(iDuration > 0.1)
  iDuration -= 0.1;
 
 if (client && GetClientTeam(client) > 1)
  CreateTimer(iDuration, Timer_FlashEnd, userid, TIMER_FLAG_NO_MAPCHANGE);
}
public Action:Event_OnPlayerTeam(Handle:event, const String:name[], bool:dontBroadcast)
{
 if(!g_bEnableHnS)
  return Plugin_Continue;
 
 new client = GetClientOfUserId(GetEventInt(event, "userid"));
 new team = GetEventInt(event, "team");
 new bool:disconnect = GetEventBool(event, "disconnect");
 
 // Handle the thirdperson view values
 // terrors are always allowed to view players in thirdperson
 if(client && !IsFakeClient(client) && GetConVarInt(g_hForceCamera) == 1)
 {
  if(team == CS_TEAM_T)
   SendConVarValue(client, g_hForceCamera, "0");
  else if(team != CS_TEAM_CT)
   SendConVarValue(client, g_hForceCamera, "1");
 }
 
 // Player disconnected?
 if(disconnect)
  g_bCTToSwitch[client] = false;
 
 // Player joined spectator?
 if(!disconnect && team < CS_TEAM_T)
 {
  g_bCTToSwitch[client] = false;
  
  // Unblind and show weapons again
  SetEntProp(client, Prop_Send, "m_bDrawViewmodel", 1);
  PerformBlind(client, 0);
  
  // Reset the model fix
  if(g_iFixedModelHeight[client] != 0.0 && g_bClientIsHigher[client])
  {
   SetEntityMoveType(client, MOVETYPE_OBSERVER);
  }
  g_iFixedModelHeight[client] = 0.0;
  g_bClientIsHigher[client] = false;
  
  // Unfreeze, if freezed before
  if(g_bIsFreezed[client])
  {
   if(GetConVarInt(g_hCVHiderFreezeMode) == 1)
    SetEntityMoveType(client, MOVETYPE_OBSERVER);
   else
   {
    SetEntData(client, g_Freeze, FL_FAKECLIENT|FL_ONGROUND|FL_PARTIALGROUND, 4, true);
    SetEntityMoveType(client, MOVETYPE_OBSERVER);
   }
   
   g_bIsFreezed[client] = false;
  }
 }
 
 // Reset the last joined ct, if he left
 if(disconnect && g_iLastJoinedCT == client)
  g_iLastJoinedCT = -1;
 
 // Strip the player if joined T midround
 if(!disconnect && team == CS_TEAM_T && IsPlayerAlive(client))
 {
  StripPlayerWeapons(client);
 }
 
 // Ignore, if Teambalance is disabled
 if(GetConVarFloat(g_hCVCTRatio) == 0.0)
  return Plugin_Continue;
 
 // GetTeamClientCount() doesn't handle the teamchange we're called for in player_team,
 // so wait two frames to update the counts
 CreateTimer(0.2, Timer_ChangeTeam, client, TIMER_FLAG_NO_MAPCHANGE);
 
 return Plugin_Continue;
}
public Event_OnItemPickup(Handle:event, const String:name[], bool:dontBroadcast)
{
 if(!g_bEnableHnS)
  return;
 
 new client = GetClientOfUserId(GetEventInt( event, "userid"));
 decl String:sItem[100];
 GetEventString(event, "item", sItem, sizeof(sItem));
 
 // restrict nightvision
 if(StrEqual(sItem, "nvgs", false))
  SetEntData(client, g_iHasNightVision, 0, 4, true);
}
public EntOutput_OnClose(const String:output[], caller, activator, Float:delay)
{
 AcceptEntityInput(caller, "Open");
}
/*
* 
* Timer Callbacks
* 
*/
// Freeze player function
public Action:FreezePlayer(Handle:timer, any:client)
{
 if(!IsClientInGame(client) || !IsPlayerAlive(client) || !g_bIsCTWaiting[client])
 {
  g_hFreezeCTTimer[client] = INVALID_HANDLE;
  return Plugin_Stop;
 }
 
 // Force him to watch at the ground.
 new Float:fPlayerEyes[3];
 GetClientEyeAngles(client, fPlayerEyes);
 fPlayerEyes[0] = 180.0;
 TeleportEntity(client, NULL_VECTOR, fPlayerEyes, NULL_VECTOR);
 SetEntData(client, g_Freeze, FL_CLIENT|FL_ATCONTROLS, 4, true);
 SetEntityMoveType(client, MOVETYPE_NONE);
 PerformBlind(client, 255);
 
 return Plugin_Continue;
}
// Unfreeze player function
public Action:UnFreezePlayer(Handle:timer, any:client)
{
 g_hUnfreezeCTTimer[client] = INVALID_HANDLE;
 
 if(!IsClientInGame(client) || !IsPlayerAlive(client))
  return Plugin_Stop;
 
 SetEntData(client, g_Freeze, FL_FAKECLIENT|FL_ONGROUND|FL_PARTIALGROUND, 4, true);
 SetEntityMoveType(client, MOVETYPE_WALK);
 
 if(!IsConVarCheater(client))
  PerformBlind(client, 0);
 
 g_bIsCTWaiting[client] = false;
 
 EmitSoundToClient(client, "radio/go.wav");
 
 PrintToChat(client, "%s%t", PREFIX, "Go search");
  
 return Plugin_Stop;
}
public Action:DisableModelMenu(Handle:timer, any:client)
{
 
 g_hAllowModelChangeTimer[client] = INVALID_HANDLE;
 
 if(!IsClientInGame(client))
  return Plugin_Stop;
 
 g_bAllowModelChange[client] = false;
 
 if(IsPlayerAlive(client))
  PrintToChat(client, "%s%t", PREFIX, "Modelmenu Disabled");
 
 // didn't he chose a model?
 if(GetClientTeam(client) == CS_TEAM_T && g_iModelChangeCount[client] == 0)
 {
  // give him a random one.
  PrintToChat(client, "%s%t", PREFIX, "Did not choose model");
  SetRandomModel(client);
 }
 
 return Plugin_Stop;
}
public Action:StartVarChecker(Handle:timer, any:client)
{ 
 if (!IsClientInGame(client))
  return Plugin_Stop;
 
 // allow watching
 if(GetClientTeam(client) < CS_TEAM_T)
 {
  PerformBlind(client, 0);
  return Plugin_Continue;
 }
 
 // check all defined cvars for value "0"
 for(new i=0;i<sizeof(cheat_commands);i++)
  QueryClientConVar(client, cheat_commands[i], ConVarQueryFinished:ClientConVar, client);
 
 if(IsConVarCheater(client))
 {
  // Blind and Freeze player
  PerformBlind(client, 255);
  SetEntityMoveType(client, MOVETYPE_NONE);
  
  if(GetConVarInt(g_hCVCheatPunishment) != 0 && g_hCheatPunishTimer[client] == INVALID_HANDLE)
  {
   g_hCheatPunishTimer[client] = CreateTimer(15.0, PerformCheatPunishment, client, TIMER_FLAG_NO_MAPCHANGE);
  }
 }
 else
 {
  if(g_hCheatPunishTimer[client] != INVALID_HANDLE)
  {
   KillTimer(g_hCheatPunishTimer[client]);
   g_hCheatPunishTimer[client] = INVALID_HANDLE;
  }
  
  if(!g_bIsCTWaiting[client])
  {
   if(IsPlayerAlive(client))
    SetEntityMoveType(client, MOVETYPE_WALK);
   PerformBlind(client, 0);
  }
 }
 
 return Plugin_Continue;
}
public Action:PerformCheatPunishment(Handle:timer, any:client)
{
 g_hCheatPunishTimer[client] = INVALID_HANDLE;
 
 if(!IsClientInGame(client) || !IsConVarCheater(client))
  return Plugin_Stop;
 
 new punishmentType = GetConVarInt(g_hCVCheatPunishment);
 if(punishmentType == 1 && GetClientTeam(client) != CS_TEAM_SPECTATOR )
 {
  g_bCTToSwitch[client] = false;
  
  // Unblind and show weapons again
  SetEntProp(client, Prop_Send, "m_bDrawViewmodel", 1);
  PerformBlind(client, 0);
  
  // Reset the model fix
  if(g_iFixedModelHeight[client] != 0.0 && g_bClientIsHigher[client])
  {
   SetEntityMoveType(client, MOVETYPE_OBSERVER);
  }
  g_iFixedModelHeight[client] = 0.0;
  g_bClientIsHigher[client] = false;
  
  // Unfreeze, if freezed before
  if(g_bIsFreezed[client])
  {
   if(GetConVarInt(g_hCVHiderFreezeMode) == 1)
    SetEntityMoveType(client, MOVETYPE_OBSERVER);
   else
   {
    SetEntData(client, g_Freeze, FL_FAKECLIENT|FL_ONGROUND|FL_PARTIALGROUND, 4, true);
    SetEntityMoveType(client, MOVETYPE_OBSERVER);
   }
   
   g_bIsFreezed[client] = false;
  }
  
  if(g_iLastJoinedCT == client)
   g_iLastJoinedCT = -1;
  
  ChangeClientTeam(client, CS_TEAM_SPECTATOR);
  PrintToChatAll("%s%N %t", PREFIX, client, "Spectator Cheater");
 }
 else if(punishmentType == 2)
 {
  for(new i=0;i<sizeof(cheat_commands);i++)
   if(g_bConVarViolation[client][i])
    PrintToConsole(client, "Hide and Seek: %t %s 0", "Print to console", cheat_commands[i]);
  KickClient(client, "Hide and Seek: %t", "Kick bad cvars");
 }
 return Plugin_Stop;
}
// teach the players the /whistle and /tp commands
public Action:SpamCommands(Handle:timer, any:data)
{
 if(GetConVarBool(g_hCVWhistle) && data == 1)
  PrintToChatAll("%s%t", PREFIX, "T type /whistle");
 else if(!GetConVarBool(g_hCVWhistle) || data == 0)
 {
  for(new i=1;i<=MaxClients;i++)
   if(IsClientInGame(i) && GetClientTeam(i) == CS_TEAM_T)
    PrintToChat(i, "%s%t", PREFIX, "T type /tp");
 }
 g_hSpamCommandsTimer = CreateTimer(120.0, SpamCommands, (data==0?1:0));
 return Plugin_Stop;
}
// show all players a countdown
// CT: I'm coming!
public Action:ShowCountdown(Handle:timer, any:freezeTime)
{
 new seconds = freezeTime - GetTime() + g_iFirstCTSpawn;
 PrintCenterTextAll("%d", seconds);
 if(seconds <= 0)
 {
  g_hShowCountdownTimer = INVALID_HANDLE;
  if(GetConVarBool(g_hCVShowProgressBar))
  {
   for(new i=1;i<=MaxClients;i++)
   {
    if(IsClientInGame(i))
    {
     SetEntDataFloat(i, g_flProgressBarStartTime, 0.0, true);
     SetEntData(i, g_iProgressBarDuration, 0, 4, true);
    }
   }
  }
  return Plugin_Stop;
 }
 
 // m_iProgressBarDuration has a limit of 15 seconds, so start showing the bar on 15 seconds left.
 if(GetConVarBool(g_hCVShowProgressBar) && (seconds) < 15)
 {
  for(new i=1;i<=MaxClients;i++)
  {
   if(IsClientInGame(i) && GetEntProp(i, Prop_Send, "m_iProgressBarDuration") == 0)
   {
    SetEntDataFloat(i, g_flProgressBarStartTime, GetGameTime(), true);
    SetEntData(i, g_iProgressBarDuration, seconds, 4, true);
   }
  }
 }
 
 g_hShowCountdownTimer = CreateTimer(0.5, ShowCountdown, freezeTime);
 
 return Plugin_Stop;
}
public Action:ShowRoundTime(Handle:timer, any:roundTime)
{
 if(csgo)
  return Plugin_Stop;
 
 decl String:timeLeft[10];
 new seconds = roundTime - GetTime() + g_iRoundStartTime;
 
 new minutes = RoundToFloor(float(seconds) / 60.0);
 new secs = seconds - minutes*60;
 if(secs < 10)
  Format(timeLeft, sizeof(timeLeft), "%d:0%d", minutes, secs);
 else
  Format(timeLeft, sizeof(timeLeft), "%d:%d", minutes, secs);
 for(new i=1;i<=MaxClients;i++)
 {
  if(IsClientInGame(i) && g_bInThirdPersonView[i])
  {
   Client_PrintKeyHintText(i, "%s", timeLeft);
  }
 }
 
 if(seconds > 0)
  g_hRoundTimeTimer = CreateTimer(0.5, ShowRoundTime, roundTime, TIMER_FLAG_NO_MAPCHANGE);
 else
  g_hRoundTimeTimer = INVALID_HANDLE;
 
 return Plugin_Stop;
}
public Action:Timer_SwitchTeams(Handle:timer, any:data)
{
 decl String:sName[64];
 for(new i=1;i<=MaxClients;i++)
 {
  if(g_bCTToSwitch[i])
  {
   if(IsClientInGame(i))
   {
    GetClientName(i, sName, sizeof(sName));
    CS_SwitchTeam(i, CS_TEAM_T);
    PrintToChatAll("%s%t", PREFIX, "switched", sName);
   }
   g_bCTToSwitch[i] = false;
  }
 }
 return Plugin_Stop;
}
public Action:Timer_ChangeTeam(Handle:timer, any:client)
{
 new iCTCount = GetTeamClientCount(CS_TEAM_CT);
 new iTCount = GetTeamClientCount(CS_TEAM_T);
 
 new iToBeSwitched = 0;
 
 // Check, how many cts are going to get switched to terror at the end of the round
 new iTeam;
 for(new i=1;i<=MaxClients;i++)
 {
  // Don't care for cheaters
  if(IsConVarCheater(i))
  {
   if(IsClientInGame(i))
   {
    iTeam = GetClientTeam(i);
    if(iTeam == CS_TEAM_CT)
     iCTCount--;
    else if(iTeam == CS_TEAM_T)
     iTCount--;
   }
  }
  else if(g_bCTToSwitch[i])
  {
   iCTCount--;
   iTCount++;
   iToBeSwitched++;
  }
 }
 //PrintToServer("Debug: %d players are flagged to switch at the end of the round.", iToBeSwitched);
 new Float:fRatio = FloatDiv(float(iCTCount), float(iTCount));
 
 new Float:fCFGCTRatio = GetConVarFloat(g_hCVCTRatio);
 
 new Float:fCFGRatio = FloatDiv(1.0, fCFGCTRatio);
 
 //PrintToServer("Debug: Initial CTCount: %d TCount: %d Ratio: %f, CFGRatio: %f", iCTCount, iTCount, fRatio, fCFGRatio);
 
 decl String:sName[64];
 // There are more CTs than we want in the CT team and it's not the first CT
 if((iCTCount > 0 || iTCount > 0) && iCTCount != 1 && fRatio > fCFGRatio)
 {
  //PrintToServer("Debug: Too much CTs! Taking action...");
  // Any players flagged to be moved at the end of the round?
  if(iToBeSwitched > 0)
  {
   for(new i=1;i<=MaxClients;i++)
   {
    if(g_bCTToSwitch[i])
    {
     g_bCTToSwitch[i] = false;
     iCTCount++;
     iTCount--;
     GetClientName(i, sName, sizeof(sName));
     PrintToChatAll("%s%t.", PREFIX, "stop switch", sName);
     
     //PrintToServer("Debug: Unflagged one player from being switched to T. CTCount: %d TCount: %d Ratio: %f", iCTCount, iTCount, FloatDiv(float(iCTCount), float(iTCount)));
     
     // switched enough players?
     if(float(iTCount) < fCFGCTRatio || FloatDiv(float(iCTCount), float(iTCount)) <= fCFGRatio)
     {
      //PrintToServer("Debug: Switched enough players after unflagging.");
      return Plugin_Stop;
     }
    }
   }
  }
  
  // First check, if the last change has been from x->CT
  if(client && IsClientInGame(client) && GetClientTeam(client) == CS_TEAM_CT)
  {
   // Reverse the change or put him in T directly
   iCTCount--;
   iTCount++;
   ChangeClientTeam(client, CS_TEAM_T);
   GetClientName(client, sName, sizeof(sName));
   PrintToChatAll("%s%t", PREFIX, "switched", sName);
   
   //PrintToServer("Debug: Switched the player %s straight back to T. CTCount: %d TCount: %d Ratio: %f", sName, iCTCount, iTCount, FloatDiv(float(iCTCount), float(iTCount)));
   
   // switched enough players?
   if(float(iTCount) < fCFGCTRatio || FloatDiv(float(iCTCount), float(iTCount)) <= fCFGRatio)
   {
    //PrintToServer("Debug: Switched enough players after reversing the last change.");
    return Plugin_Stop;
   }
  }
  // Switch last joined CT
  else if(g_iLastJoinedCT != -1)
  {
   // Dead? switch directly.
   if(IsClientInGame(g_iLastJoinedCT) && !IsPlayerAlive(g_iLastJoinedCT))
   {
    iCTCount--;
    iTCount++;
    ChangeClientTeam(g_iLastJoinedCT, CS_TEAM_T);
    GetClientName(g_iLastJoinedCT, sName, sizeof(sName));
    PrintToChatAll("%s%t", PREFIX, "switched", sName);
    //PrintToServer("Debug: Switched the last joined CT %s to T. CTCount: %d TCount: %d Ratio: %f", sName, iCTCount, iTCount, FloatDiv(float(iCTCount), float(iTCount)));
   }
   else if(IsClientInGame(g_iLastJoinedCT))
   {
    iCTCount--;
    iTCount++;
    g_bCTToSwitch[g_iLastJoinedCT] = true;
    GetClientName(g_iLastJoinedCT, sName, sizeof(sName));
    PrintToChatAll("%s%t", PREFIX, "going to switch", sName);
    //PrintToServer("Debug: Flagged the last joined CT %s to switch at roundend. CTCount: %d TCount: %d Ratio: %f", sName, iCTCount, iTCount, FloatDiv(float(iCTCount), float(iTCount)));
   }
   
   // switched enough players?
   if(float(iTCount) < fCFGCTRatio || FloatDiv(float(iCTCount), float(iTCount)) <= fCFGRatio)
   {
    //PrintToServer("Debug: Switched enough players after checking the last joined CT.");
    return Plugin_Stop;
   }
  }
  
  // First search for a dead seeker, so we can switch him
  // @TODO: Take care for ranking on the scoreboard or longest playtime as CT
  for(new i=1;i<=MaxClients;i++)
  {
   // switched enough players?
   if(float(iTCount) < fCFGCTRatio || FloatDiv(float(iCTCount), float(iTCount)) <= fCFGRatio)
   {
    //PrintToServer("Debug: Switched enough players after switching dead cts");
    return Plugin_Stop;
   }
   
   // Switch one ct to t immediately.
   if(IsClientInGame(i) && !IsPlayerAlive(i) && GetClientTeam(i) == CS_TEAM_CT && !g_bCTToSwitch[i])
   {
    iCTCount--;
    iTCount++;
    ChangeClientTeam(i, CS_TEAM_T);
    GetClientName(i, sName, sizeof(sName));
    PrintToChatAll("%s%t", PREFIX, "switched", sName);
    //PrintToServer("Debug: Switched dead CT %s to T. CTCount: %d TCount: %d Ratio: %f", sName, iCTCount, iTCount, FloatDiv(float(iCTCount), float(iTCount)));
   }
  }
  
  // Still not enough switched? Just pick a random one and switch him at the end of the round
  for(new i=1;i<=MaxClients;i++)
  {
   // switched enough players?
   if(float(iTCount) < fCFGCTRatio || FloatDiv(float(iCTCount), float(iTCount)) <= fCFGRatio)
   {
    //PrintToServer("Debug: Switched enough players after flagging alive CTs");
    return Plugin_Stop;
   }
   
   if(IsClientInGame(i) && GetClientTeam(i) == CS_TEAM_CT && !g_bCTToSwitch[i])
   {
    iCTCount--;
    iTCount++;
    g_bCTToSwitch[i] = true;
    GetClientName(i, sName, sizeof(sName));
    PrintToChatAll("%s%t", PREFIX, "going to switch", sName);
    //PrintToServer("Debug: Flagging alive CT %s to switch to T at roundend. CTCount: %d TCount: %d Ratio: %f", sName, iCTCount, iTCount, FloatDiv(float(iCTCount), float(iTCount)));
   }
  }
 }
 // Is the player in CT now?
 // He joined last!
 else if(client && IsClientInGame(client) && GetClientTeam(client) == CS_TEAM_CT)
 {
  g_iLastJoinedCT = client;
 }
 return Plugin_Stop;
}
// Make sure CTs have knifes
public Action:Timer_CheckCTHasKnife(Handle:timer, any:userid)
{
 new client = GetClientOfUserId(userid);
 if(!client)
  return Plugin_Stop;
 
 if(IsClientInGame(client) && IsPlayerAlive(client) && GetClientTeam(client) == CS_TEAM_CT)
 {
  new iWeapon = GetPlayerWeaponSlot(client, 2);
  if(iWeapon == -1)
  {
   iWeapon = GivePlayerItem(client, "weapon_knife");
   EquipPlayerWeapon(client, iWeapon);
  }
 }
 
 return Plugin_Stop;
}
// Hide the radar again after flashing
public Action:Timer_FlashEnd(Handle:timer, any:userid)
{
 new client = GetClientOfUserId(userid);
 
 if (client && GetClientTeam(client) > 1)
 {
  SetEntDataFloat(client, g_flFlashDuration, 10000.0, true);
  SetEntDataFloat(client, g_flFlashMaxAlpha, 0.5, true);
 }
  
 return Plugin_Stop;
}
public Action:Timer_SaveSpawnPosition(Handle:timer, any:userid)
{
 new client = GetClientOfUserId(userid);
 if(!client)
  return Plugin_Stop;
 
 GetClientAbsOrigin(client, g_fSpawnPosition[client]);
 return Plugin_Stop;
}
/*
* 
* Console Command Handling
* 
*/
// say /hide /hidemenu
public Action:Menu_SelectModel(client,args)
{
 if (!g_bEnableHnS || g_hModelMenu[GetClientLanguageID(client)] == INVALID_HANDLE)
 {
  return Plugin_Handled;
 }
 
 if(GetClientTeam(client) == CS_TEAM_T)
 {
  new changeLimit = GetConVarInt(g_hCVChangeLimit);
  if(g_bAllowModelChange[client] && (changeLimit == 0 || g_iModelChangeCount[client] < (changeLimit+1)))
  {
   if(GetConVarBool(g_hCVAutoChoose))
    SetRandomModel(client);
   else
    DisplayMenu(g_hModelMenu[GetClientLanguageID(client)], client, RoundToFloor(GetConVarFloat(g_hCVChangeLimittime)));
  }
  else
   PrintToChat(client, "%s%t", PREFIX, "Modelmenu Disabled");
 }
 else
 {
  PrintToChat(client, "%s%t", PREFIX, "Only terrorists can select models");
 }
 return Plugin_Handled;
}
// say /tp /third /thirdperson
public Action:Toggle_ThirdPerson(client, args)
{
 if (!g_bEnableHnS || !IsClientInGame(client) || !IsPlayerAlive(client))
  return Plugin_Handled;
 
 // Only allow Terrorists to use thirdperson view
 if(GetClientTeam(client) != CS_TEAM_T)
 {
  PrintToChat(client, "%s%t", PREFIX, "Only terrorists can use");
  return Plugin_Handled;
 }
 
 if(!g_bInThirdPersonView[client])
 {
  SetThirdPersonView(client, true);
  PrintToChat(client, "%s%t", PREFIX, "Type again for ego");
 }
 else
 {
  SetThirdPersonView(client, false);
  // remove the roundtime message
  if(!csgo) Client_PrintKeyHintText(client, "");
 }
 
 return Plugin_Handled;
}
// say /+3rd
public Action:Enable_ThirdPerson(client, args)
{
 if (!g_bEnableHnS || !IsClientInGame(client) || !IsPlayerAlive(client))
  return Plugin_Handled;
 
 // Only allow Terrorists to use thirdperson view
 if(GetClientTeam(client) != CS_TEAM_T)
 {
  PrintToChat(client, "%s%t", PREFIX, "Only terrorists can use");
  return Plugin_Handled;
 }
 
 if(!g_bInThirdPersonView[client])
 {
  SetThirdPersonView(client, true);
  PrintToChat(client, "%s%t", PREFIX, "Type again for ego");
 }
 
 return Plugin_Handled;
}
// say /-3rd
public Action:Disable_ThirdPerson(client, args)
{
 if (!g_bEnableHnS || !IsClientInGame(client) || !IsPlayerAlive(client))
  return Plugin_Handled;
 
 // Only allow Terrorists to use thirdperson view
 if(GetClientTeam(client) != CS_TEAM_T)
 {
  PrintToChat(client, "%s%t", PREFIX, "Only terrorists can use");
  return Plugin_Handled;
 }
 
 if(g_bInThirdPersonView[client])
 {
  SetThirdPersonView(client, false);
  // remove the roundtime message
  if(!csgo) Client_PrintKeyHintText(client, "");
 }
 
 return Plugin_Handled;
}
// jointeam command
// handle the team sizes
public Action:Command_JoinTeam(client, args)
{
 if (!g_bEnableHnS || !client || !IsClientInGame(client) || GetConVarFloat(g_hCVCTRatio) == 0.0)
 {
  return Plugin_Continue;
 }
 
 decl String:text[192];
 if (!GetCmdArgString(text, sizeof(text)))
 {
  return Plugin_Continue;
 }
 
 StripQuotes(text);
 
 // Player wants to join CT
 if(strcmp(text, "3", false) == 0)
 {
  new iCTCount = GetTeamClientCount(CS_TEAM_CT);
  new iTCount = GetTeamClientCount(CS_TEAM_T);
  
  // This client would be in CT if we continue.
  iCTCount++;
  
  // And would leave T
  if(GetClientTeam(client) == CS_TEAM_T)
   iTCount--;
  
  // Check, how many terrors are going to get switched to ct at the end of the round
  for(new i=1;i<=MaxClients;i++)
  {
   if(g_bCTToSwitch[i])
   {
    iCTCount--;
    iTCount++;
   }
  }
  
  new Float:fRatio = FloatDiv(float(iCTCount), float(iTCount));
  
  new Float:fCFGRatio = FloatDiv(1.0, GetConVarFloat(g_hCVCTRatio));
  
  //PrintToServer("Debug: Player %N wants to join CT. CTCount: %d TCount: %d Ratio: %f", client, iCTCount, iTCount, FloatDiv(float(iCTCount), float(iTCount)));
  
  // There are more CTs than we want in the CT team.
  if(iCTCount > 1 && fRatio > fCFGRatio)
  {
   PrintCenterText(client, "CT team is full");
   //PrintToServer("Debug: Blocked.");
   return Plugin_Handled;
  }
 }
 
 return Plugin_Continue;
}
// say /whistle
// plays a random sound loudly
public Action:Play_Whistle(client,args)
{
 // check if whistling is enabled
 if(!g_bEnableHnS || !GetConVarBool(g_hCVWhistle) || !IsPlayerAlive(client))
  return Plugin_Handled;
 
 new bool:cvarWhistleSeeker = bool:GetConVarInt(g_hCVWhistleSeeker);
 
 if(cvarWhistleSeeker && GetClientTeam(client) != CS_TEAM_CT)
 {
  PrintToChat(client, "%s%t", PREFIX, "Only counter-terrorists can use");
  return Plugin_Handled;
 }
 // only Ts are allowed to whistle
 else if(!cvarWhistleSeeker && GetClientTeam(client) != CS_TEAM_T)
 {
  PrintToChat(client, "%s%t", PREFIX, "Only terrorists can use");
  return Plugin_Handled;
 }
 
 new cvarWhistleTimes = GetConVarInt(g_hCVWhistleTimes);
 
 if(g_iWhistleCount[client] < cvarWhistleTimes)
 {
  if(!cvarWhistleSeeker)
  {
   EmitSoundToAll(whistle_sounds[GetRandomInt(0, sizeof(whistle_sounds)-1)], client, SNDCHAN_AUTO, SNDLEVEL_GUNFIRE);
   PrintToChatAll("%s%N %t", PREFIX, client, "whistled");
   g_iWhistleCount[client]++;
   PrintToChat(client, "%s%t", PREFIX, "whistles left", (cvarWhistleTimes-g_iWhistleCount[client]));
  }
  else
  {
   new target;
   new iCount;
   new Float:maxrange;
   new Float:range;
   
   for(new i=1;i<=MaxClients;i++)
   {
    if(IsClientInGame(i) && IsPlayerAlive(i) && GetClientTeam(i) == CS_TEAM_T)
    {
     iCount++;
     range = Entity_GetDistance(client, i);
     if(range > maxrange)
     {
      maxrange = range;
      target = i;
     }
    }
   }
   
   if(iCount > 1)
   {
    EmitSoundToAll(whistle_sounds[GetRandomInt(0, sizeof(whistle_sounds)-1)], target, SNDCHAN_AUTO, SNDLEVEL_GUNFIRE);
    PrintToChatAll("%s %N forced %N to whistle.", PREFIX, client, target);
    g_iWhistleCount[client]++;
    PrintToChat(client, "%s%t", PREFIX, "whistles left", (cvarWhistleTimes-g_iWhistleCount[client]));
   }
  }
 }
 else
 {
  PrintToChat(client, "%s%t", PREFIX, "whistle limit exceeded", cvarWhistleTimes);
 }
 
 return Plugin_Handled;
}
// say /whoami
// displays the model name in chat again
public Action:Display_ModelName(client,args)
{
 // only enable command, if player already chose a model
 if(!g_bEnableHnS || !IsPlayerAlive(client) || g_iModelChangeCount[client] == 0)
  return Plugin_Handled;
 
 // only Ts can use a model
 if(GetClientTeam(client) != CS_TEAM_T)
 {
  PrintToChat(client, "%s%t", PREFIX, "Only terrorists can use");
  return Plugin_Handled;
 }
 
 decl String:modelName[128], String:langCode[4];
 GetClientModel(client, modelName, sizeof(modelName));
 
 if (!KvGotoFirstSubKey(kv))
 {
  return Plugin_Handled;
 }
 
 decl String:name[30], String:path[100], String:fullPath[100];
 do
 {
  KvGetSectionName(kv, path, sizeof(path));
  FormatEx(fullPath, sizeof(fullPath), "models/%s.mdl", path);
  if(StrEqual(fullPath, modelName))
  {
   GetClientLanguageID(client, langCode, sizeof(langCode));
   KvGetString(kv, langCode, name, sizeof(name));
   PrintToChat(client, "%s%t\x01 %s.", PREFIX, "Model Changed", name);
  }
 } while (KvGotoNextKey(kv));
 KvRewind(kv);
 
 return Plugin_Handled;
}

// say /hidehelp
// Show the help menu
public Action:Display_Help(client,args)
{
 if(!g_bEnableHnS)
  return Plugin_Handled;
 
 new Handle:menu = CreateMenu(Menu_Help);
 
 decl String:buffer[512];
 Format(buffer, sizeof(buffer), "%T", "HnS Help", client);
 SetMenuTitle(menu, buffer);
 SetMenuExitButton(menu, true);
 
 Format(buffer, sizeof(buffer), "%T", "Running HnS", client);
 AddMenuItem(menu, "", buffer);
 
 Format(buffer, sizeof(buffer), "%T", "Instructions 1", client);
 AddMenuItem(menu, "", buffer);
 
 AddMenuItem(menu, "", "", ITEMDRAW_SPACER);
 
 Format(buffer, sizeof(buffer), "%T", "Available Commands", client);
 AddMenuItem(menu, "1", buffer);
 
 Format(buffer, sizeof(buffer), "%T", "Howto CT", client);
 AddMenuItem(menu, "2", buffer);
 
 Format(buffer, sizeof(buffer), "%T", "Howto T", client);
 AddMenuItem(menu, "3", buffer);
 
 DisplayMenu(menu, client, MENU_TIME_FOREVER);
 return Plugin_Handled;
}
// say /freeze
// Freeze hiders in position
public Action:Freeze_Cmd(client,args)
{
 if(!g_bEnableHnS || !GetConVarInt(g_hCVHiderFreezeMode) || GetClientTeam(client) != CS_TEAM_T || !IsPlayerAlive(client))
  return Plugin_Handled;
 
 if(g_bIsFreezed[client])
 {
  if(GetConVarInt(g_hCVHiderFreezeMode) == 1)
  {
   if(!g_bClientIsHigher[client])
    SetEntityMoveType(client, MOVETYPE_WALK);
  }
  else
  {
   SetEntData(client, g_Freeze, FL_FAKECLIENT|FL_ONGROUND|FL_PARTIALGROUND, 4, true);
   if(!g_bClientIsHigher[client])
    SetEntityMoveType(client, MOVETYPE_WALK);
  }
  
  g_bIsFreezed[client] = false;
  PrintToChat(client, "%s%t", PREFIX, "Hider Unfreezed");
 }
 else if (GetConVarBool(g_hCVHiderFreezeInAir) || (GetEntityFlags(client) & FL_ONGROUND || g_bClientIsHigher[client])) // only allow freezing when being on the ground!
 {
  // Don't allow fixed models to freeze while being bugged
  // Put him up before freezing
  if(g_iFixedModelHeight[client] > 0.0 && !g_bClientIsHigher[client] && GetEntityFlags(client) & FL_ONGROUND)
  {
   new Float:vecClientOrigin[3];
   GetClientAbsOrigin(client, vecClientOrigin);
   vecClientOrigin[2] += g_iFixedModelHeight[client];
   TeleportEntity(client, vecClientOrigin, NULL_VECTOR, NULL_VECTOR);
   g_bClientIsHigher[client] = true;
  }
  
  if(GetConVarInt(g_hCVHiderFreezeMode) == 1)
   SetEntityMoveType(client, MOVETYPE_NONE); // Still able to move camera
  else
  {
   SetEntData(client, g_Freeze, FL_CLIENT|FL_ATCONTROLS, 4, true); // Can't move anything
   SetEntityMoveType(client, MOVETYPE_NONE);
  }
  
  // Stop him
  TeleportEntity(client, NULL_VECTOR, NULL_VECTOR, Float:{0.0,0.0,0.0});
  
  g_bIsFreezed[client] = true;
  PrintToChat(client, "%s%t", PREFIX, "Hider Freezed");
 }
 
 return Plugin_Handled;
}
public Action:Block_Cmd(client,args)
{
 // only block if anticheat is enabled
 if(g_bEnableHnS && GetConVarBool(g_hCVAntiCheat))
  return Plugin_Handled;
 else
  return Plugin_Continue;
}
// Admin Command
// sm_hns_force_whistle
// Forces a terrorist player to whistle
public Action:ForceWhistle(client, args)
{
 if(!g_bEnableHnS || !GetConVarBool(g_hCVWhistle))
 {
  ReplyToCommand(client, "Disabled.");
  return Plugin_Handled;
 }
 
 if(GetCmdArgs() < 1)
 {
  ReplyToCommand(client, "Usage: sm_hns_force_whistle <#userid|steamid|name>");
  return Plugin_Handled;
 }
 
 decl String:player[70];
 GetCmdArg(1, player, sizeof(player));
 
 new target = FindTarget(client, player);
 if(target == -1)
  return Plugin_Handled;
 
 if(GetClientTeam(target) == CS_TEAM_T && IsPlayerAlive(target))
 {
  EmitSoundToAll(whistle_sounds[GetRandomInt(0, sizeof(whistle_sounds)-1)], target, SNDCHAN_AUTO, SNDLEVEL_GUNFIRE);
  PrintToChatAll("%s%N %t", PREFIX, target, "whistled");
 }
 else
 {
  ReplyToCommand(client, "Hide and Seek: %t", "Only terrorists can use");
 }
 
 return Plugin_Handled;
}
public Action:ReloadModels(client, args)
{
 if(!g_bEnableHnS)
 {
  ReplyToCommand(client, "Disabled.");
  return Plugin_Handled;
 }
 
 // reset the model menu
 OnMapEnd();
 
 // rebuild it
 BuildMainMenu();
 
 ReplyToCommand(client, "Hide and Seek: Reloaded config.");
 
 return Plugin_Handled;
}

/*
* 
* Menu Handler
* 
*/
public Menu_Group(Handle:menu, MenuAction:action, client, param2)
{
 // make sure again, the player is a Terrorist
 if(client > 0 && IsClientInGame(client) && GetClientTeam(client) == CS_TEAM_T && g_bAllowModelChange[client])
 {
  if (action == MenuAction_Select)
  {
   decl String:info[100], String:info2[100], String:sModelPath[100];
   new bool:found = GetMenuItem(menu, param2, info, sizeof(info), _, info2, sizeof(info2));
   if(found)
   {
    
    if(StrEqual(info, "random"))
    {
     SetRandomModel(client);
    }
    else
    {
     // Check for enough money
     decl String:sTax[32];
     new iPosition;
     if((iPosition = StrContains(info, "||t_")) != -1)
     {
      new iAccountValue = GetEntData(client, g_iAccount);
      
      // Stupid string information storage-.-
      new iPosition2 = StrContains(info[iPosition+4], "||hi_");
      if(iPosition2 != -1)
       strcopy(sTax, iPosition2-iPosition+3, info[iPosition+4]);
      else
       strcopy(sTax, sizeof(sTax), info[iPosition+4]);
      
      new iTax = StringToInt(sTax);
      // He doesn't have enough money?
      if(iTax > iAccountValue)
      {
       PrintToChat(client, "%s%t", PREFIX, "not enough money");
       // Show the menu again
       Menu_SelectModel(client, 0);
       return;
      }
      
      // Get the money
      SetEntData(client, g_iAccount, (iAccountValue - iTax), 4, true);
      
      PrintToChat(client, "%s%t", PREFIX, "tax charged", iTax);
     }
     
     // Put him down before changing the model again
     if(g_bClientIsHigher[client])
     {
      new Float:vecClientOrigin[3];
      GetClientAbsOrigin(client, vecClientOrigin);
      vecClientOrigin[2] -= g_iFixedModelHeight[client];
      TeleportEntity(client, vecClientOrigin, NULL_VECTOR, NULL_VECTOR);
      SetEntityMoveType(client, MOVETYPE_WALK);
      g_bClientIsHigher[client] = false;
     }
     
     // Modelheight fix
     if((iPosition = StrContains(info, "||hi_")) != -1)
     {
      g_iFixedModelHeight[client] = StringToFloat(info[iPosition+5]);
      PrintToChat(client, "%s%t", PREFIX, "is heightfixed");
     }
     else
     {
      g_iFixedModelHeight[client] = 0.0;
     }
     
     if(SplitString(info, "||", sModelPath, sizeof(sModelPath)) == -1)
      strcopy(sModelPath, sizeof(sModelPath), info);
     
     SetEntityModel(client, sModelPath);
     Client_ReCreateFakeProp(client);
     
     PrintToChat(client, "%s%t \x01%s.", PREFIX, "Model Changed", info2);
    }
    g_iModelChangeCount[client]++;
   }
  } else if(action == MenuAction_Cancel)
  {
   PrintToChat(client, "%s%t", PREFIX, "Type !hide");
  }
  
  // display the help menu afterwards on first spawn
  if(GetConVarBool(g_hCVShowHideHelp) && g_bFirstSpawn[client])
  {
   Display_Help(client, 0);
   g_bFirstSpawn[client] = false;
  }
 }
}
// Display the different help menus
public Menu_Help(Handle:menu, MenuAction:action, param1, param2)
{
 if (action == MenuAction_Select)
 {
  new String:info[32];
  GetMenuItem(menu, param2, info, sizeof(info));
  new iInfo = StringToInt(info);
  switch(iInfo)
  {
   case 1:
   {
    // Available Commands
    new Handle:menu2 = CreateMenu(Menu_Dummy);
    decl String:buffer[512];
    Format(buffer, sizeof(buffer), "%T", "Available Commands", param1);
    SetMenuTitle(menu2, buffer);
    SetMenuExitBackButton(menu2, true);
    
    Format(buffer, sizeof(buffer), "/hide, /hidemenu - %T", "cmd hide", param1);
    AddMenuItem(menu2, "", buffer, ITEMDRAW_DISABLED);
    Format(buffer, sizeof(buffer), "/tp, /third, /thirdperson - %T", "cmd tp", param1);
    AddMenuItem(menu2, "", buffer, ITEMDRAW_DISABLED);
    if(GetConVarBool(g_hCVWhistle))
    {
     Format(buffer, sizeof(buffer), "/whistle - %T", "cmd whistle", param1);
     AddMenuItem(menu2, "", buffer, ITEMDRAW_DISABLED);
    }
    if(GetConVarInt(g_hCVHiderFreezeMode))
    {
     Format(buffer, sizeof(buffer), "/freeze - %T", "cmd freeze", param1);
     AddMenuItem(menu2, "", buffer, ITEMDRAW_DISABLED);
    }
    Format(buffer, sizeof(buffer), "/whoami - %T", "cmd whoami", param1);
    AddMenuItem(menu2, "", buffer, ITEMDRAW_DISABLED);
    Format(buffer, sizeof(buffer), "/hidehelp - %T", "cmd hidehelp", param1);
    AddMenuItem(menu2, "", buffer, ITEMDRAW_DISABLED);
    
    DisplayMenu(menu2, param1, MENU_TIME_FOREVER);
   }
   case 2:
   {
    // Howto CT
    new Handle:menu2 = CreateMenu(Menu_Dummy);
    decl String:buffer[512];
    Format(buffer, sizeof(buffer), "%T", "Howto CT", param1);
    SetMenuTitle(menu2, buffer);
    SetMenuExitBackButton(menu2, true);
    
    Format(buffer, sizeof(buffer), "%T", "Instructions CT 1", param1);
    AddMenuItem(menu2, "", buffer, ITEMDRAW_DISABLED);
    
    AddMenuItem(menu2, "", "", ITEMDRAW_SPACER);
    
    Format(buffer, sizeof(buffer), "%T", "Instructions CT 2", param1, GetConVarInt(g_hCVHPSeekerDec));
    AddMenuItem(menu2, "", buffer, ITEMDRAW_DISABLED);
    
    Format(buffer, sizeof(buffer), "%T", "Instructions CT 3", param1, GetConVarInt(g_hCVHPSeekerInc), GetConVarInt(g_hCVHPSeekerBonus));
    AddMenuItem(menu2, "", buffer, ITEMDRAW_DISABLED);
    
    DisplayMenu(menu2, param1, MENU_TIME_FOREVER);
   }
   case 3:
   {
    // Howto T
    new Handle:menu2 = CreateMenu(Menu_Dummy);
    decl String:buffer[512];
    Format(buffer, sizeof(buffer), "%T", "Howto T", param1);
    SetMenuTitle(menu2, buffer);
    SetMenuExitBackButton(menu2, true);
    
    Format(buffer, sizeof(buffer), "%T", "Instructions T 1", param1);
    AddMenuItem(menu2, "", buffer, ITEMDRAW_DISABLED);
    
    Format(buffer, sizeof(buffer), "%T", "Instructions T 2", param1);
    AddMenuItem(menu2, "", buffer, ITEMDRAW_DISABLED);
    
    DisplayMenu(menu2, param1, MENU_TIME_FOREVER);
   }
  }
 }
 else if (action == MenuAction_End)
 {
  CloseHandle(menu);
 }
}
public Menu_Dummy(Handle:menu, MenuAction:action, param1, param2)
{
 if (action == MenuAction_Cancel && param2 != MenuCancel_Exit)
 {
  if(IsClientInGame(param1))
   Display_Help(param1, 0);
 }
 else if (action == MenuAction_End)
 {
  CloseHandle(menu);
 }
}
/*
* 
* Helper Functions
* 
*/
// read the hide_and_seek map config
// add all models to the menus according to the language
BuildMainMenu()
{
 g_iTotalModelsAvailable = 0;
  
 kv = CreateKeyValues("Models");
 new String:file[256], String:map[64], String:title[64], String:finalOutput[100];
 GetCurrentMap(map, sizeof(map));
 
 if(csgo)
 {
  BuildPath(Path_SM, file, 255, "configs/hide_and_seek/maps_csgo/%s.cfg", map);
  if(!FileExists(file))
  {
   BuildPath(Path_SM, file, 255, "configs/hide_and_seek/maps_csgo/default.cfg");
  }
 }
 else
 {
  BuildPath(Path_SM, file, 255, "configs/hide_and_seek/maps_css/%s.cfg", map);
  if(!FileExists(file))
  {
   BuildPath(Path_SM, file, 255, "configs/hide_and_seek/maps_css/default.cfg");
  }
 }
 
 FileToKeyValues(kv, file);
 
 if (!KvGotoFirstSubKey(kv))
 {
  SetFailState("Can't parse modelconfig file for map %s.", map);
  return;
 }
 
 decl String:name[30];
 decl String:lang[4];
 decl String:path[100];
 new langID, nextLangID = -1;
 do
 {
  // get the model path and precache it
  KvGetSectionName(kv, path, sizeof(path));
  FormatEx(finalOutput, sizeof(finalOutput), "models/%s.mdl", path);
  PrecacheModel(finalOutput, true);
  
  // Check for heightfixed models
  decl String:sHeightFix[32];
  KvGetString(kv, "heightfix", sHeightFix, sizeof(sHeightFix), "noo");
  if(!StrEqual(sHeightFix, "noo"))
  {
   Format(finalOutput, sizeof(finalOutput), "%s||hi_%s", finalOutput, sHeightFix);
  }
  
  // Check for tax
  decl String:sTax[32];
  KvGetString(kv, "tax", sTax, sizeof(sTax), "noo");
  if(!StrEqual(sTax, "noo"))
  {
   Format(finalOutput, sizeof(finalOutput), "%s||t_%s", finalOutput, sTax);
  }
  
  // roll through all available languages
  for(new i=0;i<GetLanguageCount();i++)
  {
   GetLanguageInfo(i, lang, sizeof(lang));
   // search for the translation
   KvGetString(kv, lang, name, sizeof(name));
   if(strlen(name) > 0)
   {
    // Show the tax
    if(!StrEqual(sTax, "noo"))
     Format(name, sizeof(name), "%s ($%d)", name, StringToInt(sTax));
    
    // language already in array, only in the wrong order in the file?
    langID = GetLanguageID(lang);
    
    // language new?
    if(langID == -1)
    {
     nextLangID = GetNextLangID();
     g_sModelMenuLanguage[nextLangID] = lang;
    }
    
    if(langID == -1 && g_hModelMenu[nextLangID] == INVALID_HANDLE)
    {
     // new language, create the menu
     g_hModelMenu[nextLangID] = CreateMenu(Menu_Group);
     Format(title, sizeof(title), "%T:", "Title Select Model", LANG_SERVER);
     
     SetMenuTitle(g_hModelMenu[nextLangID], title);
     SetMenuExitButton(g_hModelMenu[nextLangID], true);
     
     // Add random option
     Format(title, sizeof(title), "%T", "random", LANG_SERVER);
     AddMenuItem(g_hModelMenu[nextLangID], "random", title);
    }
    
    // add it to the menu
    if(langID == -1)
     AddMenuItem(g_hModelMenu[nextLangID], finalOutput, name);
    else
     AddMenuItem(g_hModelMenu[langID], finalOutput, name);
   }
   
  }
  
  g_iTotalModelsAvailable++;
 } while (KvGotoNextKey(kv));
 KvRewind(kv);
 
 if (g_iTotalModelsAvailable == 0)
 {
  SetFailState("No models parsed in %s.cfg", map);
  return;
 }
}
GetLanguageID(const String:langCode[])
{
 for(new i=0;i<MAX_LANGUAGES;i++)
 {
  if(StrEqual(g_sModelMenuLanguage[i], langCode))
   return i;
 }
 return -1;
}
GetClientLanguageID(client, String:languageCode[]="", maxlen=0)
{
 decl String:langCode[4];
 GetLanguageInfo(GetClientLanguage(client), langCode, sizeof(langCode));
 // is client's prefered language available?
 new langID = GetLanguageID(langCode);
 if(langID != -1)
 {
  strcopy(languageCode, maxlen, langCode);
  return langID; // yes.
 }
 else
 {
  GetLanguageInfo(GetServerLanguage(), langCode, sizeof(langCode));
  // is default server language available?
  langID = GetLanguageID(langCode);
  if(langID != -1)
  {
   strcopy(languageCode, maxlen, langCode);
   return langID; // yes.
  }
  else
  {
   // default to english
   for(new i=0;i<MAX_LANGUAGES;i++)
   {
    if(StrEqual(g_sModelMenuLanguage[i], "en"))
    {
     strcopy(languageCode, maxlen, "en");
     return i;
    }
   }
   
   // english not found? happens on custom map configs e.g.
   // use the first language available
   // this should always work, since we would have SetFailState() on parse
   if(strlen(g_sModelMenuLanguage[0]) > 0)
   {
    strcopy(languageCode, maxlen, g_sModelMenuLanguage[0]);
    return 0;
   }
  }
 }
 // this should never happen
 return -1;
}
GetNextLangID()
{
 for(new i=0;i<MAX_LANGUAGES;i++)
 {
  if(strlen(g_sModelMenuLanguage[i]) == 0)
   return i;
 }
 SetFailState("Can't handle more than %d languages. Increase MAX_LANGUAGES and recompile.", MAX_LANGUAGES);
 return -1;
}
// Check if a player has a bad convar value set
bool:IsConVarCheater(client)
{
 for(new i=0;i<sizeof(cheat_commands);i++)
 {
  if(g_bConVarViolation[client][i])
  {
   return true;
  }
 }
 return false;
}
bool:IsPlayerAFK(client)
{
 new Float:fOrigin[3];
 GetClientAbsOrigin(client, fOrigin);
 
 // Did he move after spawn?
 if(UTIL_VectorEqual(fOrigin, g_fSpawnPosition[client], 0.1))
  return true;
 return false;
}
stock bool:UTIL_VectorEqual(const Float:vec1[3], const Float:vec2[3], const Float:tolerance)
{
 for(new i=0;i<3;i++)
  if(vec1[i] > (vec2[i] + tolerance) || vec1[i] < (vec2[i] - tolerance))
   return false;
 return true;
}
// Fade a players screen to black (amount=0) or removes the fade (amount=255)
PerformBlind(client, amount)
{ 
 new mode;
 if(amount == 0)
  mode = FFADE_PURGE;
 else
  mode = FFADE_STAYOUT;
  
 if(!csgo)
 {
  Client_ScreenFade(client, 1536, mode, 1536, 0, 0, 0, amount);
 }
 else
 {
  new Handle:hFadeClient = StartMessageOne("Fade", client);
  PbSetInt(hFadeClient, "duration", 1);
  PbSetInt(hFadeClient, "hold_time", 3);
  if(amount == 0)
  {
   PbSetInt(hFadeClient, "flags", FFADE_PURGE);
  }
  else
  {
   PbSetInt(hFadeClient, "flags", FFADE_STAYOUT);
  }
  PbSetColor(hFadeClient, "clr", {0, 0, 0, 255});
  EndMessage();
 }
}
// set a random model to a client
SetRandomModel(client)
{
 // give him a random one.
 decl String:ModelPath[80], String:finalPath[100], String:ModelName[60];
 decl String:langCode[4], String:sHeightFix[35], String:sTax[32];
 new RandomNumber = GetRandomInt(0, g_iTotalModelsAvailable-1); 
 new currentI = 0;
 new iTax;
 new iAccountValue = GetEntData(client, g_iAccount);
 new bool:bUseTaxedInRandom = GetConVarBool(g_hCVUseTaxedInRandom);
 KvGotoFirstSubKey(kv);
 do
 {
  if(currentI == RandomNumber)
  {
   // Check for enough money
   KvGetString(kv, "tax", sTax, sizeof(sTax), "noo");
   if(!StrEqual(sTax, "noo"))
   {
    iTax = StringToInt(sTax);
    // He doesn't have enough money? skip this one
    if(!bUseTaxedInRandom || iTax > iAccountValue)
     continue;
    
    // Get the money
    SetEntData(client, g_iAccount, iAccountValue - iTax, 4, true);
    
    PrintToChat(client, "%s%t", PREFIX, "tax charged", iTax);
   }
   
   // set the model
   KvGetSectionName(kv, ModelPath, sizeof(ModelPath));
   
   FormatEx(finalPath, sizeof(finalPath), "models/%s.mdl", ModelPath);
   
   // Put him down before changing the model again
   if(g_bClientIsHigher[client])
   {
    new Float:vecClientOrigin[3];
    GetClientAbsOrigin(client, vecClientOrigin);
    vecClientOrigin[2] -= g_iFixedModelHeight[client];
    TeleportEntity(client, vecClientOrigin, NULL_VECTOR, NULL_VECTOR);
    SetEntityMoveType(client, MOVETYPE_WALK);
    g_bClientIsHigher[client] = false;
   }
   
   SetEntityModel(client, finalPath);
   Client_ReCreateFakeProp(client);
   
   // Check for heightfixed models
   KvGetString(kv, "heightfix", sHeightFix, sizeof(sHeightFix), "noo");
   if(!StrEqual(sHeightFix, "noo"))
   {
    g_iFixedModelHeight[client] = StringToFloat(sHeightFix);
    PrintToChat(client, "%s%t", PREFIX, "is heightfixed");
   }
   else
   {
    g_iFixedModelHeight[client] = 0.0;
   }
   
   if(!IsFakeClient(client))
   {
    // print name in chat
    GetClientLanguageID(client, langCode, sizeof(langCode));
    KvGetString(kv, langCode, ModelName, sizeof(ModelName));
    PrintToChat(client, "%s%t \x01%s.", PREFIX, "Model Changed", ModelName);
   }
   break;
  }
  currentI++;
 } while (KvGotoNextKey(kv));
 
 KvRewind(kv); 
 g_iModelChangeCount[client]++;
 
 // display the help menu afterwards on first spawn
 if(GetConVarBool(g_hCVShowHideHelp) && g_bFirstSpawn[client])
 {
  Display_Help(client, 0);
  g_bFirstSpawn[client] = false;
 }
}
bool:SetThirdPersonView(client, bool:third)
{
 static Handle:m_hAllowTP = INVALID_HANDLE;
 if(m_hAllowTP == INVALID_HANDLE)
  m_hAllowTP = FindConVar("sv_allow_thirdperson");
 SetConVarInt(m_hAllowTP, 1);
 if(third && !g_bInThirdPersonView[client])
 {
  ClientCommand(client, "thirdperson");
  g_bInThirdPersonView[client] = true;
  return true;
 }
 else if(!third && g_bInThirdPersonView[client])
 {
  ClientCommand(client, "firstperson");
  g_bInThirdPersonView[client] = false;
  return true;
 }
 return false;
}
stock StripPlayerWeapons(client)
{
 new iWeapon = -1;
 for(new i=CS_SLOT_PRIMARY;i<=CS_SLOT_C4;i++)
 {
  while((iWeapon = GetPlayerWeaponSlot(client, i)) != -1)
  {
   RemovePlayerItem(client, iWeapon);
   RemoveEdict(iWeapon);
  }
 }
}
/*
* 
* Handle ConVars
* 
*/
// Monitor the protected cvars and... well protect them ;)
public OnCvarChange(Handle:convar, const String:oldValue[], const String:newValue[])
{
 if(!g_bEnableHnS)
  return;
 
 decl String:cvarName[50];
 GetConVarName(convar, cvarName, sizeof(cvarName));
 for(new i=0;i<sizeof(protected_cvars);i++)
 {
  if(StrEqual(protected_cvars[i], cvarName) && StringToInt(newValue) != forced_values[i])
  {
   SetConVarInt(convar, forced_values[i]);
   PrintToServer("Hide and Seek: %T", "protected cvar", LANG_SERVER);
   break;
  }
 }
}
// directly change the hider speed on change
public OnChangeHiderSpeed(Handle:convar, const String:oldValue[], const String:newValue[])
{
 if(!g_bEnableHnS)
  return;
 
 for(new i=1;i<=MaxClients;i++)
 {
  if(IsClientInGame(i) && IsPlayerAlive(i) && GetClientTeam(i) == CS_TEAM_T)
   SetEntDataFloat(i, g_flLaggedMovementValue, GetConVarFloat(g_hCVHiderSpeed), true);
 }
}
// directly change the hider speed on change
public OnChangeAntiCheat(Handle:convar, const String:oldValue[], const String:newValue[])
{
 if(!g_bEnableHnS)
  return;
 
 if(StrEqual(oldValue, newValue))
  return;
 
 // disable anticheat
 if(StrEqual(newValue, "0"))
 {
  for(new i=1;i<=MaxClients;i++)
  {
   if(IsClientInGame(i) && !IsFakeClient(i))
   {
    if(g_hCheckVarTimer[i] != INVALID_HANDLE)
    {
     KillTimer(g_hCheckVarTimer[i]);
     g_hCheckVarTimer[i] = INVALID_HANDLE;
    }
    if(g_hCheatPunishTimer[i] != INVALID_HANDLE)
    {
     KillTimer(g_hCheatPunishTimer[i]);
     g_hCheatPunishTimer[i] = INVALID_HANDLE;
    }
   }
  }
 }
 // enable anticheat
 else if(StrEqual(newValue, "1"))
 {
  for(new i=1;i<=MaxClients;i++)
  {
   if(IsClientInGame(i) && !IsFakeClient(i) && g_hCheckVarTimer[i] == INVALID_HANDLE)
   {
    g_hCheckVarTimer[i] = CreateTimer(1.0, StartVarChecker, i, TIMER_REPEAT);
   }
  }
 }
}
// disable/enable plugin and restart round
public RestartGame(Handle:convar, const String:oldValue[], const String:newValue[])
{
 if(!g_bEnableHnS)
  return;
 
 // don't execute if it's unchanged
 if(StrEqual(oldValue, newValue))
  return;
 
 // disable - it's been enabled before.
 if(!StrEqual(newValue, "0"))
 {
  // round has ended. used to not decrease seekers hp on shoot
  g_bRoundEnded = true;
  
  g_iFirstCTSpawn = 0;
  g_iFirstTSpawn = 0;
  
  if(g_hShowCountdownTimer != INVALID_HANDLE)
  {
   KillTimer(g_hShowCountdownTimer);
   g_hShowCountdownTimer = INVALID_HANDLE;
  }
  
  if(g_hRoundTimeTimer != INVALID_HANDLE)
  {
   KillTimer(g_hRoundTimeTimer);
   g_hRoundTimeTimer = INVALID_HANDLE;
  }
  
  if(g_hWhistleDelay != INVALID_HANDLE)
  {
   KillTimer(g_hWhistleDelay);
   g_hWhistleDelay = INVALID_HANDLE;
  }
  
  // Switch the flagged players to CT
  CreateTimer(0.1, Timer_SwitchTeams, _, TIMER_FLAG_NO_MAPCHANGE);
 }
}
// disable/enable plugin and restart round
public Cfg_OnChangeEnable(Handle:convar, const String:oldValue[], const String:newValue[])
{
 // don't execute if it's unchanged
 if(StrEqual(oldValue, newValue))
  return;
 
 // disable - it's been enabled before.
 if(StrEqual(newValue, "0"))
 {
  UnhookConVarChange(g_hCVAntiCheat, OnChangeAntiCheat);
  UnhookConVarChange(g_hCVHiderSpeed, OnChangeHiderSpeed);
  
  // Unhooking events
  UnhookEvent("player_spawn", Event_OnPlayerSpawn);
  UnhookEvent("weapon_fire", Event_OnWeaponFire);
  UnhookEvent("player_death", Event_OnPlayerDeath);
  UnhookEvent("player_blind", Event_OnPlayerBlind);
  UnhookEvent("round_start", Event_OnRoundStart);
  UnhookEvent("round_end", Event_OnRoundEnd);
  UnhookEvent("player_team", Event_OnPlayerTeam);
  UnhookEvent("item_pickup", Event_OnItemPickup);
  
  // unprotect the cvars
  for(new i=0;i<sizeof(protected_cvars);i++)
  {
   // reset old cvar values
   if(g_hProtectedConvar[i] == INVALID_HANDLE)
    continue;
   UnhookConVarChange(g_hProtectedConvar[i], OnCvarChange);
   SetConVarInt(g_hProtectedConvar[i], previous_values[i], true);
  }
  
  // stop advertising spam
  if(g_hSpamCommandsTimer != INVALID_HANDLE)
  {
   KillTimer(g_hSpamCommandsTimer);
   g_hSpamCommandsTimer = INVALID_HANDLE;
  }
  
  // stop countdown
  if(g_hShowCountdownTimer != INVALID_HANDLE)
  {
   KillTimer(g_hShowCountdownTimer);
   g_hShowCountdownTimer = INVALID_HANDLE;
  }
  
  // stop roundtime counter
  if(g_hRoundTimeTimer != INVALID_HANDLE)
  {
   KillTimer(g_hRoundTimeTimer);
   g_hRoundTimeTimer = INVALID_HANDLE;
  }
  
  // close handles
  if(kv != INVALID_HANDLE)
   CloseHandle(kv);
  for(new i=0;i<MAX_LANGUAGES;i++)
  {
   if(g_hModelMenu[i] != INVALID_HANDLE)
   {
    CloseHandle(g_hModelMenu[i]);
    g_hModelMenu[i] = INVALID_HANDLE;
   }
   Format(g_sModelMenuLanguage[i], 4, "");
  }
  
  for(new c=1;c<=MaxClients;c++)
  {
   if(!IsClientInGame(c))
    continue;
   
   // stop cheat checking
   if(!IsFakeClient(c))
   {
    if(g_hCheckVarTimer[c] != INVALID_HANDLE)
    {
     KillTimer(g_hCheckVarTimer[c]);
     g_hCheckVarTimer[c] = INVALID_HANDLE;
    }
    if(g_hCheatPunishTimer[c] != INVALID_HANDLE)
    {
     KillTimer(g_hCheatPunishTimer[c]);
     g_hCheatPunishTimer[c] = INVALID_HANDLE;
    }
   }
   
   // Unhook weapon pickup
   SDKUnhook(c, SDKHook_WeaponCanUse, OnWeaponCanUse);
   
   // Unhook attacking
   SDKUnhook(c, SDKHook_TraceAttack, OnTraceAttack);
   
   // reset every players vars
   OnClientDisconnect(c);
  }
  
  g_bEnableHnS = false;
  // restart game to reset the models and scores
  ServerCommand("mp_restartgame 1");
 }
 else if(StrEqual(newValue, "1"))
 {
  // hook the convars again
  HookConVarChange(g_hCVHiderSpeed, OnChangeHiderSpeed);
  HookConVarChange(g_hCVAntiCheat, OnChangeAntiCheat);
  
  // Hook events again
  HookEvent("player_spawn", Event_OnPlayerSpawn);
  HookEvent("weapon_fire", Event_OnWeaponFire);
  HookEvent("player_death", Event_OnPlayerDeath);
  HookEvent("player_blind", Event_OnPlayerBlind);
  HookEvent("round_start", Event_OnRoundStart);
  HookEvent("round_end", Event_OnRoundEnd);
  HookEvent("player_team", Event_OnPlayerTeam);
  HookEvent("item_pickup", Event_OnItemPickup);
  
  // set bad server cvars
  for(new i=0;i<sizeof(protected_cvars);i++)
  {
   g_hProtectedConvar[i] = FindConVar(protected_cvars[i]);
   if(g_hProtectedConvar[i] == INVALID_HANDLE)
    continue;
   previous_values[i] = GetConVarInt(g_hProtectedConvar[i]);
   SetConVarInt(g_hProtectedConvar[i], forced_values[i], true);
   HookConVarChange(g_hProtectedConvar[i], OnCvarChange);
  }
  // start advertising spam
  g_hSpamCommandsTimer = CreateTimer(120.0, SpamCommands, 0);
  
  for(new c=1;c<=MaxClients;c++)
  {
   if(!IsClientInGame(c))
    continue;
   
   // start cheat checking
   if(!IsFakeClient(c) && GetConVarBool(g_hCVAntiCheat) && g_hCheckVarTimer[c] == INVALID_HANDLE)
   {
    g_hCheckVarTimer[c] = CreateTimer(1.0, StartVarChecker, c, TIMER_REPEAT);
   }
   
   // Hook weapon pickup
   SDKHook(c, SDKHook_WeaponCanUse, OnWeaponCanUse);
   
   // Hook attack to hide blood
   SDKHook(c, SDKHook_TraceAttack, OnTraceAttack);
  }
  
  g_bEnableHnS = true;
  // build the menu and setup the hostage_rescue zone
  OnMapStart();
  
  // restart game to reset the models and scores
  ServerCommand("mp_restartgame 1");
 }
}
// check the given cheat cvars on every client
public ClientConVar(QueryCookie:cookie, client, ConVarQueryResult:result, const String:cvarName[], const String:cvarValue[])
{
 if(!IsClientInGame(client))
  return;
 
 new bool:match = StrEqual(cvarValue, "0");
 
 for(new i=0;i<sizeof(cheat_commands);i++)
 {
  if(!StrEqual(cheat_commands[i], cvarName))
   continue;
  
  if(!match)
  {
   g_bConVarViolation[client][i] = true;
   // only spam the message every 5 checks
   if(g_iConVarMessage[client][i] == 0)
   {
    PrintToChat(client, "%s%t\x04 %s 0", PREFIX, "Print to console", cvarName);
    PrintHintText(client, "%t %s 0", "Print to console", cvarName);
   }
   g_iConVarMessage[client][i]++;
   if(g_iConVarMessage[client][i] > 5)
    g_iConVarMessage[client][i] = 0;
  }
  else
   g_bConVarViolation[client][i] = false;
 }
}
stock Client_ResetFakeProp(client)
{
 if(IsFakeClient(client))
  return;
 new entity = g_iFreezeEntity[client];
 if (entity > 0)
 {
  if (IsValidEntity(entity)) AcceptEntityInput(entity, "kill");
  g_iFreezeEntity[client] = -1;
 }
 if(IsClientInGame(client))
 {
  g_bIsFreezed[client] = false;
 }
}
stock Client_UpdateFakeProp(client)
{
 if(IsFakeClient(client))
  return;
 if(!IsClientInGame(client))
 {
  Client_ResetFakeProp(client);
  return;
 }
 new bool:showprop = true;
 //Not alive, reset prop
 if(!IsPlayerAlive(client))
 {
  if(g_bShowFakeProp[client])
  {
   g_bShowFakeProp[client] = false;
   
   if(csgo)
    SetEntityRenderMode(client, RENDER_TRANSCOLOR);
   else CSS_SetEntityAlpha(client, 255);
  }
  Client_ResetFakeProp(client);
  return;
 }
 //Wrong team, reset prop
 if(GetClientTeam(client) != CS_TEAM_T)
 {
  if(g_bShowFakeProp[client])
  {
   g_bShowFakeProp[client] = false;
   
   if(csgo)
    SetEntityRenderMode(client, RENDER_TRANSCOLOR);
   else CSS_SetEntityAlpha(client, 255);
  }
  Client_ResetFakeProp(client);
  return;
 }
 //No fake prop exist? Create a one
 if(g_iFreezeEntity[client] <= 0)
 {
  if(g_bShowFakeProp[client])
  {
   g_bShowFakeProp[client] = false;
   
   if(csgo)
    SetEntityRenderMode(client, RENDER_TRANSCOLOR);
   else CSS_SetEntityAlpha(client, 255);
  }
  Client_ReCreateFakeProp(client);
  return;
 }
 //Not a valid prop? Create a new one
 if(!Entity_IsValid(g_iFreezeEntity[client]))
 {
  if(g_bShowFakeProp[client])
  {
   g_bShowFakeProp[client] = false;
   
   if(csgo)
    SetEntityRenderMode(client, RENDER_TRANSCOLOR);
   else CSS_SetEntityAlpha(client, 255);
  }
  Client_ReCreateFakeProp(client);
  return;
 }
 decl Float:fVelocity[3];
 GetEntPropVector(client, Prop_Data, "m_vecVelocity", fVelocity); //velocity
 new Float:currentspeed = SquareRoot(Pow(fVelocity[0],2.0)+Pow(fVelocity[1],2.0));
 new Float:ang_eye[3], Float:ang_abs[3];
 GetClientEyeAngles(client, ang_eye);
 GetClientAbsAngles(client, ang_abs);
 decl String:fullPath[100];
 GetClientModel(client, fullPath, sizeof(fullPath));
 new Float:place[3], Float:place2[3], Float:secondpos[3];
 GetClientAbsOrigin(client, place);
 ang_eye[0] = 0.0; //no x-axis rotation
 ang_eye[2] = 0.0; //no z-axis rotation
 place[0] -= 0.0;
 place2[0] = 0.0;
 if(g_iFixedModelHeight[client] < 0.0)
 {
  place[2] += g_iFixedModelHeight[client];
  place2[2] += g_iFixedModelHeight[client];
 }
 GetEntPropVector(client, Prop_Data, "m_vecVelocity", secondpos);
 AddVectors(place2, secondpos, place2);
 if(g_bIsFreezed[client])
  TeleportEntity(g_iFreezeEntity[client], place, NULL_VECTOR, place2);
 else TeleportEntity(g_iFreezeEntity[client], place, ang_eye, place2);
 //Toggle visibility
 if(g_bShowFakeProp[client] != showprop)
 {
  g_bShowFakeProp[client] = showprop;
  if(showprop)
  {
   if(csgo)
   {
    SetEntityRenderMode(client, RENDER_NONE);
    SetEntityRenderMode(g_iFreezeEntity[client], RENDER_TRANSCOLOR);
   }
   else
   {
    CSS_SetEntityAlpha(client, 0);
    CSS_SetEntityAlpha(g_iFreezeEntity[client], 255);
   }
  }
  else
  {
   if(csgo)
   {
    SetEntityRenderMode(client, RENDER_TRANSCOLOR);
    SetEntityRenderMode(g_iFreezeEntity[client], RENDER_NONE);
   }
   else
   {
    CSS_SetEntityAlpha(client, 255);
    CSS_SetEntityAlpha(g_iFreezeEntity[client], 0);
   }
  }
 }
}
stock Client_ReCreateFakeProp(client)
{
 if(IsFakeClient(client))
  return;
 //delete old one if valid
 new entity_old = g_iFreezeEntity[client];
 if (entity_old > 0)
 {
  if (IsValidEntity(entity_old)) AcceptEntityInput(entity_old, "kill");
  g_iFreezeEntity[client] = -1;
 }
 //Det model
 decl String:fullPath[100];
 GetClientModel(client, fullPath, sizeof(fullPath));
 //Create Fake Model
 new entity = CreateEntityByName("prop_physics_override");
 if (IsValidEntity(entity))
 {
  g_iFreezeEntity[client] = entity;
  PrecacheModel(fullPath, true);
  SetEntityModel(entity, fullPath);
  SetEntityMoveType(entity, MOVETYPE_NONE);
  SetEntPropEnt(entity, Prop_Send, "m_hOwnerEntity", client);
  SetEntProp(entity, Prop_Data, "m_CollisionGroup", 1);
  SetEntProp(entity, Prop_Send, "m_usSolidFlags", 12);
  SetEntProp(entity, Prop_Send, "m_nSolidType", 6);
  DispatchSpawn(entity);
  SetEntData(entity, g_Freeze, FL_CLIENT|FL_ATCONTROLS, 4, true);
  SetEntityMoveType(entity, MOVETYPE_NONE);
  SetEntPropEnt(entity, Prop_Data, "m_hLastAttacker", client);
  
  if(g_bShowFakeProp[client])
  {
   if(csgo)
   {
    SetEntityRenderMode(g_iFreezeEntity[client], RENDER_TRANSCOLOR);
   }
   else
   {
    CSS_SetEntityAlpha(g_iFreezeEntity[client], 255);
   }
  }
  else
  {
   if(csgo)
   {
    SetEntityRenderMode(g_iFreezeEntity[client], RENDER_NONE);
   }
   else
   {
    CSS_SetEntityAlpha(g_iFreezeEntity[client], 0);
   }
  }
 }
 else g_iFreezeEntity[client] = -1;
}
public CSS_SetEntityAlpha(entity, alpha)
{
 // player model
 SetEntityRenderMode(entity, RENDER_TRANSCOLOR);
 SetEntityRenderColor(entity, 255, 255, 255, alpha);
 
 if(Entity_IsPlayer(entity))
 {
  // weapon model
  new iItems = FindSendPropOffs("CBaseCombatCharacter", "m_hMyWeapons");
  if(iItems != -1)
  {
   for(new i=0; i<=128; i+=4)
   {
    new nEntityID = GetEntDataEnt2(entity, (iItems+i));
    if(!IsValidEdict(nEntityID))
     continue;
    SetEntityRenderMode(nEntityID, RENDER_TRANSCOLOR);
    SetEntityRenderColor(nEntityID, 255, 255, 255, alpha);
   }
  }
 }
}
qiuhaian is offline
Closed Thread



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 17:32.


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