From 7936d87d1a91e5bb56c58bb61c1c7fd396dbf149 Mon Sep 17 00:00:00 2001 From: antithasys Date: Thu, 1 Oct 2009 21:28:54 +0000 Subject: [PATCH] Fixing dir structure for easier tagging of versions --- .../sourcemod/configs/simple-chatcolors.cfg | 15 - .../plugins/simple-alltalkmanager.smx | Bin 7028 -> 7052 bytes .../plugins/simple-donatorbenefits.smx | Bin 16600 -> 0 bytes .../plugins/simple-messagesuppression.smx | Bin 4845 -> 0 bytes .../sourcemod/plugins/simple-plugins.smx | Bin 9599 -> 0 bytes .../sourcemod/plugins/simple-spectate.smx | Bin 19129 -> 0 bytes .../sourcemod/plugins/simple-teambalancer.smx | Bin 17501 -> 0 bytes .../sourcemod/plugins/simple-teammanager.smx | Bin 17087 -> 0 bytes .../scripting/include/simple-plugins.inc | 337 --- .../scripting/simple-alltalkmanager.sp | 3 +- .../scripting/simple-autoscrambler.sp | 459 ---- .../sourcemod/scripting/simple-chatcolors.sp | 496 ---- .../scripting/simple-donatorbenefits.sp | 1312 ----------- .../scripting/simple-messagesuppression.sp | 227 -- .../sourcemod/scripting/simple-plugins.sp | 785 ------- .../scripting/simple-roundimmunity.sp | 947 -------- .../sourcemod/scripting/simple-spectate.sp | 2022 ----------------- .../scripting/simple-teambalancer.sp | 1797 --------------- .../sourcemod/scripting/simple-teammanager.sp | 1351 ----------- .../simpledonatorbenefits.phrases.txt | 62 - .../translations/simplespectate.phrases.txt | 42 - .../simpleteambalancer.phrases.txt | 130 -- .../simpleteammanager.phrases.txt | 92 - .../configs/simple-alltalkmanager_events.cfg | 43 - .../sourcemod/configs/simple-chatcolors.cfg | 15 - .../plugins/simple-alltalkmanager.smx | Bin 7028 -> 0 bytes .../plugins/simple-donatorbenefits.smx | Bin 16600 -> 0 bytes .../plugins/simple-messagesuppression.smx | Bin 4845 -> 0 bytes .../sourcemod/plugins/simple-plugins.smx | Bin 9599 -> 0 bytes .../sourcemod/plugins/simple-spectate.smx | Bin 19129 -> 0 bytes .../sourcemod/plugins/simple-teambalancer.smx | Bin 17501 -> 0 bytes .../sourcemod/plugins/simple-teammanager.smx | Bin 17087 -> 0 bytes .../scripting/include/simple-plugins.inc | 337 --- .../scripting/simple-alltalkmanager.sp | 515 ----- .../sourcemod/scripting/simple-chatcolors.sp | 496 ---- .../scripting/simple-donatorbenefits.sp | 1312 ----------- .../scripting/simple-messagesuppression.sp | 227 -- .../sourcemod/scripting/simple-plugins.sp | 785 ------- .../scripting/simple-roundimmunity.sp | 947 -------- .../sourcemod/scripting/simple-spectate.sp | 2022 ----------------- .../scripting/simple-teambalancer.sp | 1797 --------------- .../sourcemod/scripting/simple-teammanager.sp | 1351 ----------- .../simpledonatorbenefits.phrases.txt | 62 - .../translations/simplespectate.phrases.txt | 42 - .../simpleteambalancer.phrases.txt | 130 -- .../simpleteammanager.phrases.txt | 92 - .../configs/simple-alltalkmanager_events.cfg | 43 - .../plugins/simple-alltalkmanager.smx | Bin 7028 -> 0 bytes .../sourcemod/plugins/simple-chatcolors.smx | Bin 0 -> 9097 bytes .../plugins/simple-donatorbenefits.smx | Bin 16600 -> 0 bytes .../plugins/simple-messagesuppression.smx | Bin 4845 -> 0 bytes .../sourcemod/plugins/simple-plugins.smx | Bin 9599 -> 0 bytes .../sourcemod/plugins/simple-spectate.smx | Bin 19129 -> 0 bytes .../sourcemod/plugins/simple-teambalancer.smx | Bin 17501 -> 0 bytes .../sourcemod/plugins/simple-teammanager.smx | Bin 17087 -> 0 bytes .../scripting/include/simple-plugins.inc | 337 --- .../scripting/simple-alltalkmanager.sp | 515 ----- .../scripting/simple-autoscrambler.sp | 459 ---- .../scripting/simple-donatorbenefits.sp | 1312 ----------- .../scripting/simple-messagesuppression.sp | 227 -- .../sourcemod/scripting/simple-plugins.sp | 785 ------- .../scripting/simple-roundimmunity.sp | 947 -------- .../sourcemod/scripting/simple-spectate.sp | 2022 ----------------- .../scripting/simple-teambalancer.sp | 1797 --------------- .../sourcemod/scripting/simple-teammanager.sp | 1351 ----------- .../simpledonatorbenefits.phrases.txt | 62 - .../translations/simplespectate.phrases.txt | 42 - .../simpleteambalancer.phrases.txt | 130 -- .../simpleteammanager.phrases.txt | 92 - .../configs/simple-alltalkmanager_events.cfg | 43 - .../sourcemod/configs/simple-chatcolors.cfg | 15 - .../plugins/simple-alltalkmanager.smx | Bin 7028 -> 0 bytes .../plugins/simple-messagesuppression.smx | Bin 4845 -> 0 bytes .../sourcemod/plugins/simple-plugins.smx | Bin 9599 -> 0 bytes .../sourcemod/plugins/simple-spectate.smx | Bin 19129 -> 0 bytes .../sourcemod/plugins/simple-teambalancer.smx | Bin 17501 -> 0 bytes .../sourcemod/plugins/simple-teammanager.smx | Bin 17087 -> 0 bytes .../scripting/include/simple-plugins.inc | 337 --- .../scripting/simple-alltalkmanager.sp | 515 ----- .../scripting/simple-autoscrambler.sp | 459 ---- .../sourcemod/scripting/simple-chatcolors.sp | 496 ---- .../scripting/simple-messagesuppression.sp | 227 -- .../sourcemod/scripting/simple-plugins.sp | 785 ------- .../scripting/simple-roundimmunity.sp | 947 -------- .../sourcemod/scripting/simple-spectate.sp | 2022 ----------------- .../scripting/simple-teambalancer.sp | 1797 --------------- .../sourcemod/scripting/simple-teammanager.sp | 1351 ----------- .../translations/simplespectate.phrases.txt | 42 - .../simpleteambalancer.phrases.txt | 130 -- .../simpleteammanager.phrases.txt | 92 - .../configs/simple-alltalkmanager_events.cfg | 43 - .../sourcemod/configs/simple-chatcolors.cfg | 15 - .../plugins/simple-alltalkmanager.smx | Bin 7028 -> 0 bytes .../plugins/simple-donatorbenefits.smx | Bin 16600 -> 0 bytes .../sourcemod/plugins/simple-plugins.smx | Bin 9599 -> 0 bytes .../sourcemod/plugins/simple-spectate.smx | Bin 19129 -> 0 bytes .../sourcemod/plugins/simple-teambalancer.smx | Bin 17501 -> 0 bytes .../sourcemod/plugins/simple-teammanager.smx | Bin 17087 -> 0 bytes .../scripting/include/simple-plugins.inc | 337 --- .../scripting/simple-alltalkmanager.sp | 515 ----- .../scripting/simple-autoscrambler.sp | 459 ---- .../sourcemod/scripting/simple-chatcolors.sp | 496 ---- .../scripting/simple-donatorbenefits.sp | 1312 ----------- .../sourcemod/scripting/simple-plugins.sp | 785 ------- .../scripting/simple-roundimmunity.sp | 947 -------- .../sourcemod/scripting/simple-spectate.sp | 2022 ----------------- .../scripting/simple-teambalancer.sp | 1797 --------------- .../sourcemod/scripting/simple-teammanager.sp | 1351 ----------- .../simpledonatorbenefits.phrases.txt | 62 - .../translations/simplespectate.phrases.txt | 42 - .../simpleteambalancer.phrases.txt | 130 -- .../simpleteammanager.phrases.txt | 92 - .../configs/simple-alltalkmanager_events.cfg | 43 - .../sourcemod/configs/simple-chatcolors.cfg | 15 - .../plugins/simple-alltalkmanager.smx | Bin 7028 -> 0 bytes .../plugins/simple-donatorbenefits.smx | Bin 16600 -> 0 bytes .../plugins/simple-messagesuppression.smx | Bin 4845 -> 0 bytes .../sourcemod/plugins/simple-plugins.smx | Bin 9599 -> 10456 bytes .../sourcemod/plugins/simple-spectate.smx | Bin 19129 -> 0 bytes .../sourcemod/plugins/simple-teambalancer.smx | Bin 17501 -> 0 bytes .../sourcemod/plugins/simple-teammanager.smx | Bin 17087 -> 0 bytes .../scripting/include/simple-plugins.inc | 2 +- .../scripting/simple-alltalkmanager.sp | 515 ----- .../scripting/simple-autoscrambler.sp | 459 ---- .../sourcemod/scripting/simple-chatcolors.sp | 496 ---- .../scripting/simple-donatorbenefits.sp | 1312 ----------- .../scripting/simple-messagesuppression.sp | 227 -- .../sourcemod/scripting/simple-plugins.sp | 4 +- .../scripting/simple-roundimmunity.sp | 947 -------- .../sourcemod/scripting/simple-spectate.sp | 2022 ----------------- .../scripting/simple-teambalancer.sp | 1797 --------------- .../sourcemod/scripting/simple-teammanager.sp | 1351 ----------- .../simpledonatorbenefits.phrases.txt | 62 - .../translations/simplespectate.phrases.txt | 42 - .../simpleteambalancer.phrases.txt | 130 -- .../simpleteammanager.phrases.txt | 92 - .../configs/simple-alltalkmanager_events.cfg | 43 - .../sourcemod/configs/simple-chatcolors.cfg | 15 - .../plugins/simple-alltalkmanager.smx | Bin 7028 -> 0 bytes .../plugins/simple-donatorbenefits.smx | Bin 16600 -> 0 bytes .../plugins/simple-messagesuppression.smx | Bin 4845 -> 0 bytes .../sourcemod/plugins/simple-plugins.smx | Bin 9599 -> 0 bytes .../sourcemod/plugins/simple-spectate.smx | Bin 19129 -> 0 bytes .../sourcemod/plugins/simple-teambalancer.smx | Bin 17501 -> 0 bytes .../sourcemod/plugins/simple-teammanager.smx | Bin 17087 -> 0 bytes .../scripting/include/simple-plugins.inc | 337 --- .../scripting/simple-alltalkmanager.sp | 515 ----- .../scripting/simple-autoscrambler.sp | 459 ---- .../sourcemod/scripting/simple-chatcolors.sp | 496 ---- .../scripting/simple-donatorbenefits.sp | 1312 ----------- .../scripting/simple-messagesuppression.sp | 227 -- .../sourcemod/scripting/simple-plugins.sp | 785 ------- .../sourcemod/scripting/simple-spectate.sp | 2022 ----------------- .../scripting/simple-teambalancer.sp | 1797 --------------- .../sourcemod/scripting/simple-teammanager.sp | 1351 ----------- .../simpledonatorbenefits.phrases.txt | 62 - .../translations/simplespectate.phrases.txt | 42 - .../simpleteambalancer.phrases.txt | 130 -- .../simpleteammanager.phrases.txt | 92 - .../configs/simple-alltalkmanager_events.cfg | 43 - .../sourcemod/configs/simple-chatcolors.cfg | 15 - .../plugins/simple-alltalkmanager.smx | Bin 7028 -> 0 bytes .../plugins/simple-donatorbenefits.smx | Bin 16600 -> 0 bytes .../plugins/simple-messagesuppression.smx | Bin 4845 -> 0 bytes .../sourcemod/plugins/simple-plugins.smx | Bin 9599 -> 0 bytes .../sourcemod/plugins/simple-spectate.smx | Bin 19129 -> 19878 bytes .../sourcemod/plugins/simple-teambalancer.smx | Bin 17501 -> 0 bytes .../sourcemod/plugins/simple-teammanager.smx | Bin 17087 -> 0 bytes .../scripting/include/simple-plugins.inc | 337 --- .../scripting/simple-alltalkmanager.sp | 515 ----- .../scripting/simple-autoscrambler.sp | 459 ---- .../sourcemod/scripting/simple-chatcolors.sp | 496 ---- .../scripting/simple-donatorbenefits.sp | 1312 ----------- .../scripting/simple-messagesuppression.sp | 227 -- .../sourcemod/scripting/simple-plugins.sp | 785 ------- .../scripting/simple-roundimmunity.sp | 947 -------- .../sourcemod/scripting/simple-spectate.sp | 2 +- .../scripting/simple-teambalancer.sp | 1797 --------------- .../sourcemod/scripting/simple-teammanager.sp | 1351 ----------- .../simpledonatorbenefits.phrases.txt | 62 - .../simpleteambalancer.phrases.txt | 130 -- .../simpleteammanager.phrases.txt | 92 - .../configs/simple-alltalkmanager_events.cfg | 43 - .../sourcemod/configs/simple-chatcolors.cfg | 15 - .../plugins/simple-alltalkmanager.smx | Bin 7028 -> 0 bytes .../plugins/simple-donatorbenefits.smx | Bin 16600 -> 0 bytes .../plugins/simple-messagesuppression.smx | Bin 4845 -> 0 bytes .../sourcemod/plugins/simple-plugins.smx | Bin 9599 -> 0 bytes .../sourcemod/plugins/simple-spectate.smx | Bin 19129 -> 0 bytes .../sourcemod/plugins/simple-teambalancer.smx | Bin 17501 -> 17760 bytes .../sourcemod/plugins/simple-teammanager.smx | Bin 17087 -> 0 bytes .../scripting/include/simple-plugins.inc | 337 --- .../scripting/simple-alltalkmanager.sp | 515 ----- .../scripting/simple-autoscrambler.sp | 459 ---- .../sourcemod/scripting/simple-chatcolors.sp | 496 ---- .../scripting/simple-donatorbenefits.sp | 1312 ----------- .../scripting/simple-messagesuppression.sp | 227 -- .../sourcemod/scripting/simple-plugins.sp | 785 ------- .../scripting/simple-roundimmunity.sp | 947 -------- .../sourcemod/scripting/simple-spectate.sp | 2022 ----------------- .../sourcemod/scripting/simple-teammanager.sp | 1351 ----------- .../simpledonatorbenefits.phrases.txt | 62 - .../translations/simplespectate.phrases.txt | 42 - .../simpleteammanager.phrases.txt | 92 - .../configs/simple-alltalkmanager_events.cfg | 43 - .../sourcemod/configs/simple-chatcolors.cfg | 15 - .../plugins/simple-alltalkmanager.smx | Bin 7028 -> 0 bytes .../plugins/simple-donatorbenefits.smx | Bin 16600 -> 0 bytes .../plugins/simple-messagesuppression.smx | Bin 4845 -> 0 bytes .../sourcemod/plugins/simple-plugins.smx | Bin 9599 -> 0 bytes .../sourcemod/plugins/simple-spectate.smx | Bin 19129 -> 0 bytes .../sourcemod/plugins/simple-teambalancer.smx | Bin 17501 -> 0 bytes .../sourcemod/plugins/simple-teammanager.smx | Bin 17087 -> 17310 bytes .../scripting/include/simple-plugins.inc | 337 --- .../scripting/simple-alltalkmanager.sp | 515 ----- .../scripting/simple-autoscrambler.sp | 459 ---- .../sourcemod/scripting/simple-chatcolors.sp | 496 ---- .../scripting/simple-donatorbenefits.sp | 1312 ----------- .../scripting/simple-messagesuppression.sp | 227 -- .../sourcemod/scripting/simple-plugins.sp | 785 ------- .../scripting/simple-roundimmunity.sp | 947 -------- .../sourcemod/scripting/simple-spectate.sp | 2022 ----------------- .../scripting/simple-teambalancer.sp | 1797 --------------- .../simpledonatorbenefits.phrases.txt | 62 - .../translations/simplespectate.phrases.txt | 42 - .../simpleteambalancer.phrases.txt | 130 -- .../configs/simple-alltalkmanager_events.cfg | 43 - .../sourcemod/configs/simple-chatcolors.cfg | 15 - .../plugins/simple-alltalkmanager.smx | Bin 7028 -> 0 bytes .../plugins/simple-donatorbenefits.smx | Bin 16600 -> 0 bytes .../plugins/simple-messagesuppression.smx | Bin 4845 -> 0 bytes addons/sourcemod/plugins/simple-plugins.smx | Bin 9599 -> 0 bytes addons/sourcemod/plugins/simple-spectate.smx | Bin 19129 -> 0 bytes .../sourcemod/plugins/simple-teambalancer.smx | Bin 17501 -> 0 bytes .../sourcemod/plugins/simple-teammanager.smx | Bin 17087 -> 0 bytes .../scripting/include/simple-plugins.inc | 337 --- .../scripting/simple-alltalkmanager.sp | 515 ----- .../scripting/simple-autoscrambler.sp | 459 ---- .../sourcemod/scripting/simple-chatcolors.sp | 496 ---- .../scripting/simple-donatorbenefits.sp | 1312 ----------- .../scripting/simple-messagesuppression.sp | 227 -- addons/sourcemod/scripting/simple-plugins.sp | 785 ------- .../scripting/simple-roundimmunity.sp | 947 -------- addons/sourcemod/scripting/simple-spectate.sp | 2022 ----------------- .../scripting/simple-teambalancer.sp | 1797 --------------- .../sourcemod/scripting/simple-teammanager.sp | 1351 ----------- .../simpledonatorbenefits.phrases.txt | 62 - .../translations/simplespectate.phrases.txt | 42 - .../simpleteambalancer.phrases.txt | 130 -- .../simpleteammanager.phrases.txt | 92 - 250 files changed, 6 insertions(+), 106325 deletions(-) delete mode 100644 Simple AllTalk Manager/addons/sourcemod/configs/simple-chatcolors.cfg delete mode 100644 Simple AllTalk Manager/addons/sourcemod/plugins/simple-donatorbenefits.smx delete mode 100644 Simple AllTalk Manager/addons/sourcemod/plugins/simple-messagesuppression.smx delete mode 100644 Simple AllTalk Manager/addons/sourcemod/plugins/simple-plugins.smx delete mode 100644 Simple AllTalk Manager/addons/sourcemod/plugins/simple-spectate.smx delete mode 100644 Simple AllTalk Manager/addons/sourcemod/plugins/simple-teambalancer.smx delete mode 100644 Simple AllTalk Manager/addons/sourcemod/plugins/simple-teammanager.smx delete mode 100644 Simple AllTalk Manager/addons/sourcemod/scripting/include/simple-plugins.inc delete mode 100644 Simple AllTalk Manager/addons/sourcemod/scripting/simple-autoscrambler.sp delete mode 100644 Simple AllTalk Manager/addons/sourcemod/scripting/simple-chatcolors.sp delete mode 100644 Simple AllTalk Manager/addons/sourcemod/scripting/simple-donatorbenefits.sp delete mode 100644 Simple AllTalk Manager/addons/sourcemod/scripting/simple-messagesuppression.sp delete mode 100644 Simple AllTalk Manager/addons/sourcemod/scripting/simple-plugins.sp delete mode 100644 Simple AllTalk Manager/addons/sourcemod/scripting/simple-roundimmunity.sp delete mode 100644 Simple AllTalk Manager/addons/sourcemod/scripting/simple-spectate.sp delete mode 100644 Simple AllTalk Manager/addons/sourcemod/scripting/simple-teambalancer.sp delete mode 100644 Simple AllTalk Manager/addons/sourcemod/scripting/simple-teammanager.sp delete mode 100644 Simple AllTalk Manager/addons/sourcemod/translations/simpledonatorbenefits.phrases.txt delete mode 100644 Simple AllTalk Manager/addons/sourcemod/translations/simplespectate.phrases.txt delete mode 100644 Simple AllTalk Manager/addons/sourcemod/translations/simpleteambalancer.phrases.txt delete mode 100644 Simple AllTalk Manager/addons/sourcemod/translations/simpleteammanager.phrases.txt delete mode 100644 Simple AutoScrambler/addons/sourcemod/configs/simple-alltalkmanager_events.cfg delete mode 100644 Simple AutoScrambler/addons/sourcemod/configs/simple-chatcolors.cfg delete mode 100644 Simple AutoScrambler/addons/sourcemod/plugins/simple-alltalkmanager.smx delete mode 100644 Simple AutoScrambler/addons/sourcemod/plugins/simple-donatorbenefits.smx delete mode 100644 Simple AutoScrambler/addons/sourcemod/plugins/simple-messagesuppression.smx delete mode 100644 Simple AutoScrambler/addons/sourcemod/plugins/simple-plugins.smx delete mode 100644 Simple AutoScrambler/addons/sourcemod/plugins/simple-spectate.smx delete mode 100644 Simple AutoScrambler/addons/sourcemod/plugins/simple-teambalancer.smx delete mode 100644 Simple AutoScrambler/addons/sourcemod/plugins/simple-teammanager.smx delete mode 100644 Simple AutoScrambler/addons/sourcemod/scripting/include/simple-plugins.inc delete mode 100644 Simple AutoScrambler/addons/sourcemod/scripting/simple-alltalkmanager.sp delete mode 100644 Simple AutoScrambler/addons/sourcemod/scripting/simple-chatcolors.sp delete mode 100644 Simple AutoScrambler/addons/sourcemod/scripting/simple-donatorbenefits.sp delete mode 100644 Simple AutoScrambler/addons/sourcemod/scripting/simple-messagesuppression.sp delete mode 100644 Simple AutoScrambler/addons/sourcemod/scripting/simple-plugins.sp delete mode 100644 Simple AutoScrambler/addons/sourcemod/scripting/simple-roundimmunity.sp delete mode 100644 Simple AutoScrambler/addons/sourcemod/scripting/simple-spectate.sp delete mode 100644 Simple AutoScrambler/addons/sourcemod/scripting/simple-teambalancer.sp delete mode 100644 Simple AutoScrambler/addons/sourcemod/scripting/simple-teammanager.sp delete mode 100644 Simple AutoScrambler/addons/sourcemod/translations/simpledonatorbenefits.phrases.txt delete mode 100644 Simple AutoScrambler/addons/sourcemod/translations/simplespectate.phrases.txt delete mode 100644 Simple AutoScrambler/addons/sourcemod/translations/simpleteambalancer.phrases.txt delete mode 100644 Simple AutoScrambler/addons/sourcemod/translations/simpleteammanager.phrases.txt delete mode 100644 Simple Chat Colors/addons/sourcemod/configs/simple-alltalkmanager_events.cfg delete mode 100644 Simple Chat Colors/addons/sourcemod/plugins/simple-alltalkmanager.smx create mode 100644 Simple Chat Colors/addons/sourcemod/plugins/simple-chatcolors.smx delete mode 100644 Simple Chat Colors/addons/sourcemod/plugins/simple-donatorbenefits.smx delete mode 100644 Simple Chat Colors/addons/sourcemod/plugins/simple-messagesuppression.smx delete mode 100644 Simple Chat Colors/addons/sourcemod/plugins/simple-plugins.smx delete mode 100644 Simple Chat Colors/addons/sourcemod/plugins/simple-spectate.smx delete mode 100644 Simple Chat Colors/addons/sourcemod/plugins/simple-teambalancer.smx delete mode 100644 Simple Chat Colors/addons/sourcemod/plugins/simple-teammanager.smx delete mode 100644 Simple Chat Colors/addons/sourcemod/scripting/include/simple-plugins.inc delete mode 100644 Simple Chat Colors/addons/sourcemod/scripting/simple-alltalkmanager.sp delete mode 100644 Simple Chat Colors/addons/sourcemod/scripting/simple-autoscrambler.sp delete mode 100644 Simple Chat Colors/addons/sourcemod/scripting/simple-donatorbenefits.sp delete mode 100644 Simple Chat Colors/addons/sourcemod/scripting/simple-messagesuppression.sp delete mode 100644 Simple Chat Colors/addons/sourcemod/scripting/simple-plugins.sp delete mode 100644 Simple Chat Colors/addons/sourcemod/scripting/simple-roundimmunity.sp delete mode 100644 Simple Chat Colors/addons/sourcemod/scripting/simple-spectate.sp delete mode 100644 Simple Chat Colors/addons/sourcemod/scripting/simple-teambalancer.sp delete mode 100644 Simple Chat Colors/addons/sourcemod/scripting/simple-teammanager.sp delete mode 100644 Simple Chat Colors/addons/sourcemod/translations/simpledonatorbenefits.phrases.txt delete mode 100644 Simple Chat Colors/addons/sourcemod/translations/simplespectate.phrases.txt delete mode 100644 Simple Chat Colors/addons/sourcemod/translations/simpleteambalancer.phrases.txt delete mode 100644 Simple Chat Colors/addons/sourcemod/translations/simpleteammanager.phrases.txt delete mode 100644 Simple Donator Benefits/addons/sourcemod/configs/simple-alltalkmanager_events.cfg delete mode 100644 Simple Donator Benefits/addons/sourcemod/configs/simple-chatcolors.cfg delete mode 100644 Simple Donator Benefits/addons/sourcemod/plugins/simple-alltalkmanager.smx delete mode 100644 Simple Donator Benefits/addons/sourcemod/plugins/simple-messagesuppression.smx delete mode 100644 Simple Donator Benefits/addons/sourcemod/plugins/simple-plugins.smx delete mode 100644 Simple Donator Benefits/addons/sourcemod/plugins/simple-spectate.smx delete mode 100644 Simple Donator Benefits/addons/sourcemod/plugins/simple-teambalancer.smx delete mode 100644 Simple Donator Benefits/addons/sourcemod/plugins/simple-teammanager.smx delete mode 100644 Simple Donator Benefits/addons/sourcemod/scripting/include/simple-plugins.inc delete mode 100644 Simple Donator Benefits/addons/sourcemod/scripting/simple-alltalkmanager.sp delete mode 100644 Simple Donator Benefits/addons/sourcemod/scripting/simple-autoscrambler.sp delete mode 100644 Simple Donator Benefits/addons/sourcemod/scripting/simple-chatcolors.sp delete mode 100644 Simple Donator Benefits/addons/sourcemod/scripting/simple-messagesuppression.sp delete mode 100644 Simple Donator Benefits/addons/sourcemod/scripting/simple-plugins.sp delete mode 100644 Simple Donator Benefits/addons/sourcemod/scripting/simple-roundimmunity.sp delete mode 100644 Simple Donator Benefits/addons/sourcemod/scripting/simple-spectate.sp delete mode 100644 Simple Donator Benefits/addons/sourcemod/scripting/simple-teambalancer.sp delete mode 100644 Simple Donator Benefits/addons/sourcemod/scripting/simple-teammanager.sp delete mode 100644 Simple Donator Benefits/addons/sourcemod/translations/simplespectate.phrases.txt delete mode 100644 Simple Donator Benefits/addons/sourcemod/translations/simpleteambalancer.phrases.txt delete mode 100644 Simple Donator Benefits/addons/sourcemod/translations/simpleteammanager.phrases.txt delete mode 100644 Simple Message Suppression/addons/sourcemod/configs/simple-alltalkmanager_events.cfg delete mode 100644 Simple Message Suppression/addons/sourcemod/configs/simple-chatcolors.cfg delete mode 100644 Simple Message Suppression/addons/sourcemod/plugins/simple-alltalkmanager.smx delete mode 100644 Simple Message Suppression/addons/sourcemod/plugins/simple-donatorbenefits.smx delete mode 100644 Simple Message Suppression/addons/sourcemod/plugins/simple-plugins.smx delete mode 100644 Simple Message Suppression/addons/sourcemod/plugins/simple-spectate.smx delete mode 100644 Simple Message Suppression/addons/sourcemod/plugins/simple-teambalancer.smx delete mode 100644 Simple Message Suppression/addons/sourcemod/plugins/simple-teammanager.smx delete mode 100644 Simple Message Suppression/addons/sourcemod/scripting/include/simple-plugins.inc delete mode 100644 Simple Message Suppression/addons/sourcemod/scripting/simple-alltalkmanager.sp delete mode 100644 Simple Message Suppression/addons/sourcemod/scripting/simple-autoscrambler.sp delete mode 100644 Simple Message Suppression/addons/sourcemod/scripting/simple-chatcolors.sp delete mode 100644 Simple Message Suppression/addons/sourcemod/scripting/simple-donatorbenefits.sp delete mode 100644 Simple Message Suppression/addons/sourcemod/scripting/simple-plugins.sp delete mode 100644 Simple Message Suppression/addons/sourcemod/scripting/simple-roundimmunity.sp delete mode 100644 Simple Message Suppression/addons/sourcemod/scripting/simple-spectate.sp delete mode 100644 Simple Message Suppression/addons/sourcemod/scripting/simple-teambalancer.sp delete mode 100644 Simple Message Suppression/addons/sourcemod/scripting/simple-teammanager.sp delete mode 100644 Simple Message Suppression/addons/sourcemod/translations/simpledonatorbenefits.phrases.txt delete mode 100644 Simple Message Suppression/addons/sourcemod/translations/simplespectate.phrases.txt delete mode 100644 Simple Message Suppression/addons/sourcemod/translations/simpleteambalancer.phrases.txt delete mode 100644 Simple Message Suppression/addons/sourcemod/translations/simpleteammanager.phrases.txt delete mode 100644 Simple Plugins Core/addons/sourcemod/configs/simple-alltalkmanager_events.cfg delete mode 100644 Simple Plugins Core/addons/sourcemod/configs/simple-chatcolors.cfg delete mode 100644 Simple Plugins Core/addons/sourcemod/plugins/simple-alltalkmanager.smx delete mode 100644 Simple Plugins Core/addons/sourcemod/plugins/simple-donatorbenefits.smx delete mode 100644 Simple Plugins Core/addons/sourcemod/plugins/simple-messagesuppression.smx delete mode 100644 Simple Plugins Core/addons/sourcemod/plugins/simple-spectate.smx delete mode 100644 Simple Plugins Core/addons/sourcemod/plugins/simple-teambalancer.smx delete mode 100644 Simple Plugins Core/addons/sourcemod/plugins/simple-teammanager.smx delete mode 100644 Simple Plugins Core/addons/sourcemod/scripting/simple-alltalkmanager.sp delete mode 100644 Simple Plugins Core/addons/sourcemod/scripting/simple-autoscrambler.sp delete mode 100644 Simple Plugins Core/addons/sourcemod/scripting/simple-chatcolors.sp delete mode 100644 Simple Plugins Core/addons/sourcemod/scripting/simple-donatorbenefits.sp delete mode 100644 Simple Plugins Core/addons/sourcemod/scripting/simple-messagesuppression.sp delete mode 100644 Simple Plugins Core/addons/sourcemod/scripting/simple-roundimmunity.sp delete mode 100644 Simple Plugins Core/addons/sourcemod/scripting/simple-spectate.sp delete mode 100644 Simple Plugins Core/addons/sourcemod/scripting/simple-teambalancer.sp delete mode 100644 Simple Plugins Core/addons/sourcemod/scripting/simple-teammanager.sp delete mode 100644 Simple Plugins Core/addons/sourcemod/translations/simpledonatorbenefits.phrases.txt delete mode 100644 Simple Plugins Core/addons/sourcemod/translations/simplespectate.phrases.txt delete mode 100644 Simple Plugins Core/addons/sourcemod/translations/simpleteambalancer.phrases.txt delete mode 100644 Simple Plugins Core/addons/sourcemod/translations/simpleteammanager.phrases.txt delete mode 100644 Simple Round Immunity/addons/sourcemod/configs/simple-alltalkmanager_events.cfg delete mode 100644 Simple Round Immunity/addons/sourcemod/configs/simple-chatcolors.cfg delete mode 100644 Simple Round Immunity/addons/sourcemod/plugins/simple-alltalkmanager.smx delete mode 100644 Simple Round Immunity/addons/sourcemod/plugins/simple-donatorbenefits.smx delete mode 100644 Simple Round Immunity/addons/sourcemod/plugins/simple-messagesuppression.smx delete mode 100644 Simple Round Immunity/addons/sourcemod/plugins/simple-plugins.smx delete mode 100644 Simple Round Immunity/addons/sourcemod/plugins/simple-spectate.smx delete mode 100644 Simple Round Immunity/addons/sourcemod/plugins/simple-teambalancer.smx delete mode 100644 Simple Round Immunity/addons/sourcemod/plugins/simple-teammanager.smx delete mode 100644 Simple Round Immunity/addons/sourcemod/scripting/include/simple-plugins.inc delete mode 100644 Simple Round Immunity/addons/sourcemod/scripting/simple-alltalkmanager.sp delete mode 100644 Simple Round Immunity/addons/sourcemod/scripting/simple-autoscrambler.sp delete mode 100644 Simple Round Immunity/addons/sourcemod/scripting/simple-chatcolors.sp delete mode 100644 Simple Round Immunity/addons/sourcemod/scripting/simple-donatorbenefits.sp delete mode 100644 Simple Round Immunity/addons/sourcemod/scripting/simple-messagesuppression.sp delete mode 100644 Simple Round Immunity/addons/sourcemod/scripting/simple-plugins.sp delete mode 100644 Simple Round Immunity/addons/sourcemod/scripting/simple-spectate.sp delete mode 100644 Simple Round Immunity/addons/sourcemod/scripting/simple-teambalancer.sp delete mode 100644 Simple Round Immunity/addons/sourcemod/scripting/simple-teammanager.sp delete mode 100644 Simple Round Immunity/addons/sourcemod/translations/simpledonatorbenefits.phrases.txt delete mode 100644 Simple Round Immunity/addons/sourcemod/translations/simplespectate.phrases.txt delete mode 100644 Simple Round Immunity/addons/sourcemod/translations/simpleteambalancer.phrases.txt delete mode 100644 Simple Round Immunity/addons/sourcemod/translations/simpleteammanager.phrases.txt delete mode 100644 Simple Spectate/addons/sourcemod/configs/simple-alltalkmanager_events.cfg delete mode 100644 Simple Spectate/addons/sourcemod/configs/simple-chatcolors.cfg delete mode 100644 Simple Spectate/addons/sourcemod/plugins/simple-alltalkmanager.smx delete mode 100644 Simple Spectate/addons/sourcemod/plugins/simple-donatorbenefits.smx delete mode 100644 Simple Spectate/addons/sourcemod/plugins/simple-messagesuppression.smx delete mode 100644 Simple Spectate/addons/sourcemod/plugins/simple-plugins.smx delete mode 100644 Simple Spectate/addons/sourcemod/plugins/simple-teambalancer.smx delete mode 100644 Simple Spectate/addons/sourcemod/plugins/simple-teammanager.smx delete mode 100644 Simple Spectate/addons/sourcemod/scripting/include/simple-plugins.inc delete mode 100644 Simple Spectate/addons/sourcemod/scripting/simple-alltalkmanager.sp delete mode 100644 Simple Spectate/addons/sourcemod/scripting/simple-autoscrambler.sp delete mode 100644 Simple Spectate/addons/sourcemod/scripting/simple-chatcolors.sp delete mode 100644 Simple Spectate/addons/sourcemod/scripting/simple-donatorbenefits.sp delete mode 100644 Simple Spectate/addons/sourcemod/scripting/simple-messagesuppression.sp delete mode 100644 Simple Spectate/addons/sourcemod/scripting/simple-plugins.sp delete mode 100644 Simple Spectate/addons/sourcemod/scripting/simple-roundimmunity.sp delete mode 100644 Simple Spectate/addons/sourcemod/scripting/simple-teambalancer.sp delete mode 100644 Simple Spectate/addons/sourcemod/scripting/simple-teammanager.sp delete mode 100644 Simple Spectate/addons/sourcemod/translations/simpledonatorbenefits.phrases.txt delete mode 100644 Simple Spectate/addons/sourcemod/translations/simpleteambalancer.phrases.txt delete mode 100644 Simple Spectate/addons/sourcemod/translations/simpleteammanager.phrases.txt delete mode 100644 Simple Team Balancer/addons/sourcemod/configs/simple-alltalkmanager_events.cfg delete mode 100644 Simple Team Balancer/addons/sourcemod/configs/simple-chatcolors.cfg delete mode 100644 Simple Team Balancer/addons/sourcemod/plugins/simple-alltalkmanager.smx delete mode 100644 Simple Team Balancer/addons/sourcemod/plugins/simple-donatorbenefits.smx delete mode 100644 Simple Team Balancer/addons/sourcemod/plugins/simple-messagesuppression.smx delete mode 100644 Simple Team Balancer/addons/sourcemod/plugins/simple-plugins.smx delete mode 100644 Simple Team Balancer/addons/sourcemod/plugins/simple-spectate.smx delete mode 100644 Simple Team Balancer/addons/sourcemod/plugins/simple-teammanager.smx delete mode 100644 Simple Team Balancer/addons/sourcemod/scripting/include/simple-plugins.inc delete mode 100644 Simple Team Balancer/addons/sourcemod/scripting/simple-alltalkmanager.sp delete mode 100644 Simple Team Balancer/addons/sourcemod/scripting/simple-autoscrambler.sp delete mode 100644 Simple Team Balancer/addons/sourcemod/scripting/simple-chatcolors.sp delete mode 100644 Simple Team Balancer/addons/sourcemod/scripting/simple-donatorbenefits.sp delete mode 100644 Simple Team Balancer/addons/sourcemod/scripting/simple-messagesuppression.sp delete mode 100644 Simple Team Balancer/addons/sourcemod/scripting/simple-plugins.sp delete mode 100644 Simple Team Balancer/addons/sourcemod/scripting/simple-roundimmunity.sp delete mode 100644 Simple Team Balancer/addons/sourcemod/scripting/simple-spectate.sp delete mode 100644 Simple Team Balancer/addons/sourcemod/scripting/simple-teammanager.sp delete mode 100644 Simple Team Balancer/addons/sourcemod/translations/simpledonatorbenefits.phrases.txt delete mode 100644 Simple Team Balancer/addons/sourcemod/translations/simplespectate.phrases.txt delete mode 100644 Simple Team Balancer/addons/sourcemod/translations/simpleteammanager.phrases.txt delete mode 100644 Simple Team Manager/addons/sourcemod/configs/simple-alltalkmanager_events.cfg delete mode 100644 Simple Team Manager/addons/sourcemod/configs/simple-chatcolors.cfg delete mode 100644 Simple Team Manager/addons/sourcemod/plugins/simple-alltalkmanager.smx delete mode 100644 Simple Team Manager/addons/sourcemod/plugins/simple-donatorbenefits.smx delete mode 100644 Simple Team Manager/addons/sourcemod/plugins/simple-messagesuppression.smx delete mode 100644 Simple Team Manager/addons/sourcemod/plugins/simple-plugins.smx delete mode 100644 Simple Team Manager/addons/sourcemod/plugins/simple-spectate.smx delete mode 100644 Simple Team Manager/addons/sourcemod/plugins/simple-teambalancer.smx delete mode 100644 Simple Team Manager/addons/sourcemod/scripting/include/simple-plugins.inc delete mode 100644 Simple Team Manager/addons/sourcemod/scripting/simple-alltalkmanager.sp delete mode 100644 Simple Team Manager/addons/sourcemod/scripting/simple-autoscrambler.sp delete mode 100644 Simple Team Manager/addons/sourcemod/scripting/simple-chatcolors.sp delete mode 100644 Simple Team Manager/addons/sourcemod/scripting/simple-donatorbenefits.sp delete mode 100644 Simple Team Manager/addons/sourcemod/scripting/simple-messagesuppression.sp delete mode 100644 Simple Team Manager/addons/sourcemod/scripting/simple-plugins.sp delete mode 100644 Simple Team Manager/addons/sourcemod/scripting/simple-roundimmunity.sp delete mode 100644 Simple Team Manager/addons/sourcemod/scripting/simple-spectate.sp delete mode 100644 Simple Team Manager/addons/sourcemod/scripting/simple-teambalancer.sp delete mode 100644 Simple Team Manager/addons/sourcemod/translations/simpledonatorbenefits.phrases.txt delete mode 100644 Simple Team Manager/addons/sourcemod/translations/simplespectate.phrases.txt delete mode 100644 Simple Team Manager/addons/sourcemod/translations/simpleteambalancer.phrases.txt delete mode 100644 addons/sourcemod/configs/simple-alltalkmanager_events.cfg delete mode 100644 addons/sourcemod/configs/simple-chatcolors.cfg delete mode 100644 addons/sourcemod/plugins/simple-alltalkmanager.smx delete mode 100644 addons/sourcemod/plugins/simple-donatorbenefits.smx delete mode 100644 addons/sourcemod/plugins/simple-messagesuppression.smx delete mode 100644 addons/sourcemod/plugins/simple-plugins.smx delete mode 100644 addons/sourcemod/plugins/simple-spectate.smx delete mode 100644 addons/sourcemod/plugins/simple-teambalancer.smx delete mode 100644 addons/sourcemod/plugins/simple-teammanager.smx delete mode 100644 addons/sourcemod/scripting/include/simple-plugins.inc delete mode 100644 addons/sourcemod/scripting/simple-alltalkmanager.sp delete mode 100644 addons/sourcemod/scripting/simple-autoscrambler.sp delete mode 100644 addons/sourcemod/scripting/simple-chatcolors.sp delete mode 100644 addons/sourcemod/scripting/simple-donatorbenefits.sp delete mode 100644 addons/sourcemod/scripting/simple-messagesuppression.sp delete mode 100644 addons/sourcemod/scripting/simple-plugins.sp delete mode 100644 addons/sourcemod/scripting/simple-roundimmunity.sp delete mode 100644 addons/sourcemod/scripting/simple-spectate.sp delete mode 100644 addons/sourcemod/scripting/simple-teambalancer.sp delete mode 100644 addons/sourcemod/scripting/simple-teammanager.sp delete mode 100644 addons/sourcemod/translations/simpledonatorbenefits.phrases.txt delete mode 100644 addons/sourcemod/translations/simplespectate.phrases.txt delete mode 100644 addons/sourcemod/translations/simpleteambalancer.phrases.txt delete mode 100644 addons/sourcemod/translations/simpleteammanager.phrases.txt diff --git a/Simple AllTalk Manager/addons/sourcemod/configs/simple-chatcolors.cfg b/Simple AllTalk Manager/addons/sourcemod/configs/simple-chatcolors.cfg deleted file mode 100644 index 14b98c6..0000000 --- a/Simple AllTalk Manager/addons/sourcemod/configs/simple-chatcolors.cfg +++ /dev/null @@ -1,15 +0,0 @@ -"admin_colors" -{ - "groupname2" - { - "flag" "z" - "namecolor" "{green}" - "textcolor" "{olive}" - } - "groupname1" - { - "flag" "a" - "namecolor" "{teamcolor}" - "textcolor" "{green}" - } -} \ No newline at end of file diff --git a/Simple AllTalk Manager/addons/sourcemod/plugins/simple-alltalkmanager.smx b/Simple AllTalk Manager/addons/sourcemod/plugins/simple-alltalkmanager.smx index 6122756af68998fb531abcd0d08698e24cff25af..2524e2fc8f46091156be91b9151dd67b949e661e 100644 GIT binary patch delta 6984 zcmXZeRaBJi*9P!sNNJGn*MLE~J0vA!Na-#~X`~+{q(NawB_u_<1*A(rI)-kfWyl%& z&$rfhaP8}NwomT8)_o=%Cju%dY3g7=AaV2nu&e|CM0EfF@IW5M|F;(v0N^}0pBeyG zu>pYa!C{O5p!v|051D+h=tDC-gy3OxJT&wnL;q(C0N{FX>=OV`#svVu2T!sAz=sFR zK3JC*;0OMD!0U&2@dALs!vg&W{}BR!orkS953Z900Mdtk_mG|k(|xWE13xk7y9>0` z=161}CI_V|0=2^Ysnvl=#Fi9mqs#iuJHdAau(sd>d z7lprnIUr(Ri!=CQHM)-PUx3(#O;Bo1<>uWo))r}F<2UEv?ISo!wkctke9wOaNXb9?;md7T7g%OLCmH^t92RwpQP!TPpaRcd6* zafWt6sJdKXAC;4T2X=Z+F*|GWAch=M@%FzMj!-cn4Qz-^r*nsslyhF?G99|Tn8%Ym z>bcam8LWvPtyOPiJ4Dqa2poqfC0I)(Vj~voWY0wZy@l5|q~+Xq)R=YzGOp3`4o*14A42QsK!T zvopW6!7AC?TGiV-oby*yYwtPW+wkq~o3h$Fci6;0#D?gU(yesK*r-5|2LD)WQ5oNK zL+a_>j52F|rRjjhGIDV|Lx#$}idzWTBiz|MD=S)b5o0Bf$NI7=4(CliHpSGgJR!87 zz7u6C%^V%cAOEEyJ$sMeyD~q`P!aoTFO{v~Y}sy)eqWE<@MbYNAlHAU_mXxY+n)F= zK$Pik&Sv$q_8At)l4tB#x!6$f2k%UeV8_5;&z>^RQ5jW>1bZ5h`-NqDH>*um^uDdsgPf;< zLZbvDldc-$k}7i*RtyuZtn0YD&Kfm$^<+|i8nJv5ZYGaAmiJFovU2cFn{~yyQ6BAh zT)B#w2)_8uwAPp7`?M4Ltz@lvQkT?NPP>NSyL}P+fKLl{Pur%FKR!h{3fwZ*)45oDCYjph(bbzlB1n8!Wt zJRJ(;_h{hOA1T-obL01b3DyklML=>=6{>QwHe1i*2eW>AyTspCrZy;|MZ_a*?u#9A zT%*zA`Wzdd?@U<9>Kt}PO(~X{KiOI5RgPaWV6fVHNQpzvc zGHNZUQ8Iz`9+l4*a{MC>KkH?Ektw=m>iw&kSnJX$7UH6H{|s+}elI{`sJR`oltm`~ zVu9}OioHyG(mD6`KkQzgglgAREqj4Kr!?2bPVm}S!Q1P;OtA3XinU|2*qSnf9r6Lx zEAmdpKTDiWuf>dYCHyYeLwGL0pyy;|T64kWH5ZBO*Z;Ks5nT7Rnf($yU>;~P?G=~L zLYXiGlJCZjDV`$_49|FLp8nA}d=_&}byn+?`PV%t;FZK+ZSc~(_ddd>%otUS3_L7K zNKkiGBA+lIT8CAXcivhxZWuj+(yRwfr#>2{%r1&QcODjl&2_)8{Mp?PZu>aR^rIZk zCgBnVr?MFy^!DGUMYhe^!7{jt@w$k=3X!^TQ?Tg9r&k$SKb+Gs3e7(f`f6gcc1VXoD z{{pW#)L&^qc0ukoEEgdQ9=~o+%BeP~+?j!(j#y8 zxi7C==Fn)lPKO((Rq!C+NO+r5L0y}qAh1p5XKH_3_`(&wp{2`EBSW`Hgzdf~x zSGt}%5;#=0ntsB)L*%vgrNRKyThhy*^e!0Gfg7luXrFoj}0st27A7nuBWfRVz65FljyN~?Xw!}eY+2w#xpneQkU>&727KY$4K{p9^FsDAfGtt>k`vA&e<=)Smb=7; z3ur!ekC8DY-ip_(ai3U=6uUzL{hY`)((cE&8{qoEurw9*TbqmMpFe8{gN3=*jpv{n za^PHLpCZGH>mzsf_Aj@=CSNb-($?2+hVR(9*IDLPdLwe+LWF#8BM1nOxjy$^7jDsn z3id4dH7t>$x*{5B)+M>U=)0&#F6h^nc_i$j0?Ij;CCaf3_{W(N3iJn0+=?YUsBWrlO(aQzQoC4%UIMN!wHyk;NZzhK} zoO{m_o@ILki}HNhLSlj2fr+;!V>{ls00L(@8jrqkOQw(pYeIsaBRla&p*@%ITjr3} z2?`iw5$i}Ly`Zt{dZM6ey9+-AfqCZ*{m-9cCdyAwj?q#!uSSR+Tke+k0XQnK~H&ISNSQxN)q?V7dXz?aEHoNOdqoo=v2~ z^85W!fr0s)IV6z2LjZUMX(&?o%Gbir(uUx71$@and_oogGXmrx;Htb9Z1iEcHNChN z-|Wz(NTLr{4^`)&(W&&Y#gVBYH;~7ruiNK+6PAXXXqTR~F?n!s&+&~oleu_oO45>) zi~7M!!7TRH+8Kr6NaDytS+G`|^`hJIOCXp3&taOpL!J zABn&hgiX#nCHRNtg@?G*N4~{2#Y?fy4no=AxYTZuWY#|aRD2$AHs$L2QAaThCY+Y# zUi;NkePJl$AAHMc;fkTr>T3QG19tGphw*D8k*_3eijLz~tG?^6bn!r`q@+)bt*DgY z7bLXbD>Y*SuUC7j7N5XF#Q%AjdJ;24ywKJ!{O&yyhe2JLFaJ7M}j&%B4$L(QC4&)5dFBb!$CpR|C^~ZZC_=FSio%_6Ne7k=pPg zqmX|jjKaTEsBxGR(Xj^h;)p?gSHx@QjpB>)~F?yNs6ZQtwDRbE=`tae#;9VVP zFCgW*e>g&v$Zq#1@k9XEtgzcWgJUi^Ar;Z*o}f<8T5U&gd;Huf>ukonE?jgqId|77 zs4BG6cgwNMR-Wf}*8Hf#HE@R$kQpoH>*>PFHnMsp}}L{Ms}`U-ytlTRt?4oZNyq zl)N0*(`ufsGstrPb>i-q*^x>AW+kply^FPP1b-F0W+t&?XWX^utzGGVuaWkt&-(W< zAeen(f4*E*`LvGd=oO@KTm8)U;9y`}oRm4M=(zN~$urj`tk2TB6Ss&}UkDwYebJD))s^t~fX%Qx7jDL73S3tgj-*JvtM^4cH;7f#Szq^UH zwH*A3NrkOHlh8n%1!hi_y=iDk7jAayJ|$K-eZ}Q;W}-fUJ-H1aWsIx3QL#I+_6#Qe zuU?YwSC~Z}nZZU_stnPJP3b50g-$oAZf`;n$J#D%C4O1LP5xzB?O zV85_>ub?Bp{Y@4R3Zwrj`zmNen75PJp@PIFsE;A-biwR=GHL1Nr>LGIEb6Q)m4|cX zo&EtD7MqAL9u=Aq@rau_n^x#p^-PO%;5v!ydU?*22-A)mW;gD8HG0z{@XZpKlKhm4 zB@0bMg_V8>*pe_$?9QBo_^N4>B;rV|>Q6mUxuMOPJ}F?DnDDerSQ+1SI!GT$4n-E% z99DL_faYLth#Y6%OlZDi{5a7j3m-q>hhN~+K78|M%;KAvc6Z)_$FWR8#2<7a4fX-})Zec9UWCdhx;<7aSDI4);|xeg za_*_}HFS{UO(sW|pwl{qNxM>D&oQf8kfdOk=^CQ^9DzXU*KxlQq4(VaP=8P|U>iBHx!uxExq+FO{ za-J>P^*i|n(fdSI0mmx8mDejJ^AbdgrM6-9dt->whDlATc~hKX3fh>@_vM{p1&^bL znb)vFH0b5r6)suABJOJf(akm}moNgv2m6rD{7v1`26feg$s;Ln+PiBnMokh#M1e!IbM3Do^i4Ldr%{V zoog%QN6icO`_RAnvzV;!f?q$Dd2Hv-CX3r&EDHE?%0fyMlDNxeSR88ad5=;^+^V|& z4lT2rTbSlf+9LR~xXX;ZRlkDmn#HS7Gu5@rdbwh?Yc;RtI&(Z*J!p?yL_FE`>;pko+O1!>S_}da-qUpNuf!;mmeUf z*FZ3xY2tJ2T|U1vb4?yVCK8VvXb-tk8Mj^Y2HJZDzG`@$Z0qy#aVZW6Bx2mqLCu51 zl7-siZy`4%a00?DP)5w~B;YH5{S3Wr=C3^9RjT~4{7fRp4|M-fQ>e0 z5a|%`{X9s!>)@tiVN`fF=<)DUa~RKUZp^VkzB)1x`$5?7q9|ijp6=;@TjJJQuD%EHTG83 z-QWCk#{J6~dp7=p(2bzukjrb=AKFolPQ(Lny;TqBCSQEprV8nYv|%CuUsdd^$JH@_ zCjj+Ut@vRP5F%_ghM^#{FWRx-{%cjfNt{J;jc&dM&h1+aS^lPjK_+g&gYk=Cfva$6 zMGu*LhYxOH`HDCfXGgXMqMP7KcYx?!$dQq%G3i$ixH?b!>a% zZ-UH+n5&6y3;-B+P1SKPcMFkB$bSCQT&B| znKTMA@qzkd#rQbM)_fUbEtxuiTmC52Ax&t{0COy*V6n!SYO3j6{HBpX6{$qu1upxr z?&iEFbP>t!^DQUYX(}L`%6iOI)I@B2psLEWAZGDF@?XhmI(4h%#9Lw6)}>uR9 zkZc{?CvNoT!pV7O(xy&2RY$5SrT%^nAwi(($WvA)W~+l&+Hf|E{Z%U?_b93KJTGGT z0Gyo|4&|i8Vw*wibLmm<+4W-z!&iClo}mu|MHN$jOqUZ@YZOPxl`cT6+S9B`dU!5k zXLAbevv;XkUL9mm_-WK-M}UM658DABhfYrEiI7=9LE&TrOu2HVm5<9+8YgMbU!Dn3 zv@2%d8pWup6Ot6nrx0zxp+0&h(NQNcSw}r~L{$`|ky$Xa7l3Vbq&B$|IwyPZYLdTD z_n&Fht*8^1mN|A*kfgd!;)_h z)Rfn0>Tq;PL={Rz%iyQ+0)ot9+}z){la0wCPv>cz)S`mEf#rdYI^2%FFSt1RW|sG2 zi}l2+d)8OLv~8^%oCS_HV*9dyvi=-mm#(uizF%Jb#^<&D`K&!^8&wpDft@K|qU40S z7%}69gBPIDm*+QeyLyZ~6u;I}Uy~--M(-$&X9_ym=2Vo#ri!ekDwwE$q0lOIn55^N zGs4D~&aD0YCO&kIKaU(gLS0n&5oY(c8d}*tuC$-d3QCO!rg72K)5*~DNRUhXnqW+2 z_2BGDrqlV-@wAYSOwDRwBJRJ)Q{o z=J2M&8UEdZ5>#=@PQg`qTXs|M7z$USilNrli*NYvow8#O?;5dF0@H7td`K^&K&CR> zh{hnC&R)VfjlPHG+sKB68ZVU)k`0aE$_pjKWubZznb-F`nsL-->;>n4a?{qSuMH}r z`gk3To_ar}DVYhk{xWDV&ATml^U*rX+4b|Mw<-sGd43?<)c}E0|2z1oBTPo&lY`d`sZvt8}{5B&nbPrfT05be9yLK0svI70f2YUuH^&( z!k#VrY+eDtTL9xT)c+TO=b_IF44<7Z1OQAwZ?$>0D-Zx6{$D>Q`Dnj*mIrivLS z-q7Q}!}!CI>Wq%*yBrab!$X`*So=0o!>KvLqB9DqAFuO{MP_>chJ5!wxeNk!|EI{R zV4z(}$V1<3xAnEuQlwjfa)DQZ8~KB&yQE~)QBMIF{`sA%msmDp&E(p^w^u~+{Wk4h zey)l4p}}g6Nqfz4ZD98kP(u)$>wT1Rx=`V;oUQ~eNIl;6iZOWVemPyEg<4HrX0p6D zs90c9Wa_2SsgTVhPX(cCmL<8bCs1=7>gGce?*nmxhHD(&*iu!}dYo|WOsT|rgrqUVDiCwpKqYJ7$q<;s}G0%~OM zb7m4vAQqVDW@y!tZ`)D5cKuNFBh}}<%O?^ER}-?`c8qi`lOfRNW2N*1QaJq~5$9z` zCLOO}nbRk;mkSg5-@uP+g0m-XTI>DRvJdF=7Cf3>FJNp;xfJDm2P?e$tOqM{&b<0o%yHIFtP82p|0+}AnRBkW{7ITcDp zip6NB2STV!mD3Nr3#}!-pUAD{`8J1?p-Gd~Uw6muvD=oO0l}nvL9hR``0B6P>w4|S z>Oi5gDDCo)3Rx5q_~06SQT7!adoDi8u(0jtd<^`wT)nPLcE_R)Wj4=Bs6evmw^N*p z&D*OxT15E;ubzfXUjuQp>il)`m#!X`sr6$V%w?BeArxFMG%+ zsdtDnc}O$rPkdj^VFu{I!D+QW@QIKT0CF@3XAxDS+2aM`KnGyYEL6_yC z!BX%3zy9w&hzw)jOKUdO;^KvSPidJYl&FhN!o2wS1m_rk6W))QqJxK zGXA&Cu-C}~%_8qw^4~Ye-|c~kYjjEr^+^l$Hb@Wo{b={>omJcR=(FNi?I|0$vjt*R zXQi}(XI<2m41W~&nODL`9Z|#!P${ny>_L>HJKXa?6Z3G#XzsE<&=S}0HWhd5oS^4* z2Z+C@%=@c#cfN;8JJ9B2zfQCHF^NeG=~jOz_D@sc@Xnm3DE+op*4$0!_*4?^rd~V4 z{0CE=<<>jD^!KIy*F%fw?fARat^7N4@evoW?>qbMtQB^7$gHJ2^)*+Cr2Pw952h5u zHYh#rlxf*-6zixNo$iX9t@@Z9q(9qr@5<KC-Unb=J?OPKp1i0-x&9I@1An6CqIreP-BXi0vrp=sT&}?#B8){Z~{`iD#dX z&7tYHG38}Xm!^Qc=qvbF#BJz1x~4(l^hJ!ybV-1}w;76!U~t5D`fPH^4;)o8bFVqm zAY?;i@vVnp_-dke@Jgk&;ZM=@BS>*iD|zYaPBPR*`>~p8m|&+jVyLSY&5TQdV+ay{ zDbg+9kH4uW>F?-Jz<(9Y2{u?SZAPiuo=Df{cWZiDEQ(xtdpS%>eRT?aIf`%FXXSv( zQz?ph%^Sl~`DLK%JRCSD^`k?%xQGU?HMv$|!E4jcz^wQ4AAO#Mx)0t$+lKYvmAOO1 z?{kauQ#VKTz5NnaSz8})Jn_#6KB>j->S)d=b+uQ}Rc>1@jhm@)M@@oqgLK(yqrTT;Nl7Y>~!-@$GgXVKqVBGbMbWsB=lF}{lvetPu1Jj zq%)ek3D(w`PD>%v{F!`jj^_&8judXmgP_eJJ0rux!yrvBf7_@ob}v`(dXC>@#%cmC#R(6C5Py-Oi4v=PQpP1{2p=v<~fU5HV}w<{0vH z;BIWxsemX@;U5ut+{uO)d>^XctULa0-%iXEgNkZjR0_>si-Cb*?A65nq}1kqlLK!! zvjiLTKachN-J=bx!;xQz#{8l7&*tNDgDyzN`*WR9Ga2eUzb3C`gm7f6eeCTx*H$=O zhNAB;Zo&7BZv&2Of(ES#=4ccSQa!G4;9GY!m+Ay_9q3Y%n?oW4O?T84Yx20su zZ(62J-AgT3ttIfA{6e4e--GWiW{gT3O;*m*T<0K`|0vnJ^BuYPwFF>2+2DUVDdQ1? zLR+7ftTIQIm>lquTLifrzhn zRE(v;?h@<8S6_9Lv%uDx%yfINzYzTLX^c|0=0$rB+Nq!Y({i?io=SWh|-m*3kJBCKQ$q+3N*Q zM!pCyrZSMqg4}|}B+G$@VNxZ)zspe5+318PYm{r`u z(&NA4pICwi?3R?9__>eQkdIXzPP#-2zY4O&Y01HEdez^RqSm=DRrG%IUn=O`#OSQY z$6v!|Q%W|IHG7H4uU!txt4>qO%;RvoIc=$|{xt7VZLTo2jS*id9>~e}WK@b1oDt^t zju2nFK}LxoZZ#9cCqdOD@;%n&&C!0}RWk_AC^7=RGp#Ae+nzle5$)&pp6<=hfQrW%VmI0)H=0cv_DgH|9_li4fk;#;s-DS*%cH|5)GrLi?`6T{jH(OrH%Rt`4Uy)`R0buog9&y%jLH$zlWxQy8XOKE@wc`?F- z3qnr*M7-efLhRH3U=}YTYlrnf9MPRRB^r8Bp zy#P0i4r+v%hvjvd6hXVzI-k?4b-Q5^j2^U)9Izw6I^n4q;JeF@^H%(rKq+}&aR1T_4!5ApMlWmp&x@mo%X)ub#RcvO#QT= z?M{u9SH~ZE0Unl3ApBFBi(>h^MX-kJr!s{4zc_4r=z&8H{$eooJ1Rkej{b`)7jlL= z=9V&-cKGJvyWI4ZC7tk6pkaf39v>K%UxMcUp-8z?Do_y4{hwEJ=XPRld8^a1`Lfp# zpT)}BVTbL^LNtQ=bcS$jZJ`Sha?1BAVIFUR)J~f5^ZzhF`q}Y3&ql^Bqb^T`b ztbjohUHu{rDz4bqA4H83HRi0iq;2jni(eZ{>M9a#&z&S*cQkA<+CCmaur|3~ME#!VngHxt@o-hxZ~?JY zOcLXfb}Hs1K>hQYqW5e~6pnXtUT%!lH~F1HX}qFR-q*txjUoK9rf(ikf-2qcm>n*x zw?FV0P!Tjrfp4TDU*VKFGefQ>?@gK`ONun99aR`cj4*?2WPV}g10iR4=m{hEwJ{0r z0}V)V6Gs|cB62!@0l`99Q5)QiNS>@(;l%7NKyB4@R%P@Hk=@V5gyEz|*n)xsMzH%M!JjcpSMcE%yCWT3i|_u_+krui8G_AHOK1*6J_zq2JLz zFn9P8pA?h8Zez;hAmW!Pfk<*nRiI`p+(>Un9>hu$jK+w~ONNzcTW0Ew%t0jj*v?lK zN&9jlf4?UXf`i%gqSf7|xTls0L`lnd1~LhF*rJt|*0^qbXn*kuF-O0RU1?LewM?7E zAw11jynm%fE_K@KmBPpfhtyb9-`%8#ip%0o_O?Mq4|0#+ee#$(tJ_&Z)?+gp1{0&76Wtvo59Qcb1V7X*%cW}f$iAt#3Wf#dDXZ^IOBWXu8KIX90)06T0 zzbwfi7~h}zc(x+zBmGq{m{9O$?o=)Aw(aLbA(X?M#MJA6!yvG}pST9Iglx(yC?)`d z%q!@3mkPL2CYHyGf^fcJ;cvNf>9UQ=-dT@YWqX}Thr#LR3s^RXSG?LXn>|ZpkJ{C# zLxDNhb(~IqfT+<48nlG){pR<5-c03-(DXw5&kuzl3+o{-bFxTix(k@W`99_Y2_4QC z94EZ-8a_GxYM&lc}2Mz`IB__BOztTbT;j!)qz z=8`eTUp%OMe633ofC{uwFiw|XxxjyFif!fu(`-<$S{$MckPs@7p}?YYeb>q?7eA`D z+@V}FQsg!$jJPLb*5W~ah2OGIcvFHz_r70XpddE6w`~yn;-d4?Z3Xj+Y19A8 zj7h+3c6S+@EXhP+P95eBEl5k3b-v^JJViQksahQLga}J0Bm3#5|4Yf7W2h683@iT@O9FNZFz%}Wlf2vH^ z7HY>(0?_Sse}8_ujfec^6c^+-;waQ?V*%Vy>>oj5ABYz0?MN40^5Ky6tWC%&XzJL& zA)3J8gyye=eqhQsl{TA3J-WMqId%fu($!C?D<9jxao$$qClh3-I6o@-+<=#e!&ye$ zsDL*^w!3*>SA7XS_s|KZx1cKfxt`?4k0VKp!lkLU5n>LUD^RwUz*3X_bF-CURKhaR?|x);n_Skg`LV?$ zJVp{0(|UFN^(H}Dupho)of-#9F^};+({3o3{H5Fp5ti%k z^;0dGxp0qseNIYpru~{ebMj5Eu&VWtj6u+sOSC?0Hgtg@6QTl!q0;T2E`q-aRnT}n zPE%{OwTPr}H@67-#5b)8akq!_G86|^>!ny(M0)7l1TR^g5cxd!a?7MXYX{0LsVi@Crd;|}n#>pRQZ(rhhPhOC}!|{bb+lK08 zBFI{j8N*j%aV{mdC~oGj<7^{V@u-KtUi)~pr<3=MAPw&J_~Gn|O@2tCwSBkHbQx!H z<<>M<)>o&M)13~oNS+1sX)Hze4=Nk9Hn_ObOLrAT9+7%z+*Xr{Nl%`I^{&!n8T|zQ zS%fCcj1h#%a^U{Ekuz=k8R1QYwY&bIc3>^J@h8qXt2I=6tImocK`n;`Yn4A1^+{v* zRRR!9wOI}E69zTUv{hr0sf8}?br!`Is|kRwL_C%v;)BINOo8>wZ>#dnRE&ax24OPA z2910gWFUKceh4we&e|I5>LXRWy}fcq*UqJQllhVADtTMimKD~-fO(+<3&>DN+nvy! z7g-gdhO@G&z$72Ni*fafZFYj7Ed+$~$U&joNIt)F;2l0h0hC^@ZZFUvYpitQpajo1 zg`~|6R+1sH^R~IIZZ7eyrI!@GF*L4cO|QuzB{j&3E$w4M8=ipw4F_wyjSUZ2pYUGX zlp%FcuB%|V@qTz#jls;@pY#sQxb+p-u_zzX6xD~J5R!Xm(t1JE&=;1ga`xsF`@Q%# zjEdp#;ApB+Dj`G`Ynd@bHPO5t+|9_eE<8Uthl&O^sA%=|trM?gFjBIjl!pkd)(eV( zD2vh7@)t(|klSpZx3Z=4j+N+EZkm(GgW8!f-(Y2gsXQ{6x6R0flJQC=9N9y07x!xP zMSX+<-%WW$pdYjBl}$n>+^iC194=Lni!Pb3q6Pa=h8*4%Mo6VG*0-9)FQ0A&Uy2`2t2HL0GWCyRs%>mr*U~pneN9{WOTO;pz#K0J-q!nWOqfQS6lY{r zI_^hHM>r<6Z7cXq1!@1o+RBJ&&&1Dw`?K8dg*NVTE6~N}O|b+T5gl*t4tjyGL7V4? zwF?dUgo7@O`e~#_v3?EdME+2Q@=b|b294jPk>J6&Btuc#UX20utkT)NeroH1F*ViS z$P8*-V3^J@I=yT>IB#m#59@v6J`UVLLpRz>0QnX!_AO4UsWzU31s;kVEt%i7vPsoIczd4$}XRp(b>`iaw{U*NQs^=8Gre@nv z!_oqHida*hZ%@^2;T)%$0wUIJ2%664$y}KJC{*^<7HpJ(Uj`~*pdwdZtd@J$ls~nG zI4(2(L<}!2wsS)Qh(KLmx-$xjzmv7#|iF_n}s%lT)WHv4sq{E+`%%7ZDlK8X}=7fp;PNjSE z+;9%N61 yH%iooc)vcF^>#BuNRTQqqH=PP$0Lkz8RU6>@!H_j@cB>R1Zn)kleMfT=Kle&=ZH)I diff --git a/Simple AllTalk Manager/addons/sourcemod/plugins/simple-donatorbenefits.smx b/Simple AllTalk Manager/addons/sourcemod/plugins/simple-donatorbenefits.smx deleted file mode 100644 index 821d61d784607595ca400d273a941a42e40de640..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16600 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 diff --git a/Simple AllTalk Manager/addons/sourcemod/plugins/simple-messagesuppression.smx b/Simple AllTalk Manager/addons/sourcemod/plugins/simple-messagesuppression.smx deleted file mode 100644 index cc20dadd37d8ff23d0a64513cc09650f4bdbf24d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4845 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 Blh*(M diff --git a/Simple AllTalk Manager/addons/sourcemod/plugins/simple-spectate.smx b/Simple AllTalk Manager/addons/sourcemod/plugins/simple-spectate.smx deleted file mode 100644 index c6885b041145a73f664650e729a5dcf8b3b0813f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19129 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%0ACwUfid=y*oPG;MRqmWr)g0 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�XP zM5L)&uZne^XHs;_L+03=Xy3CiU1O76^S{TWu{zY}Jlq((BV?9EL=m4MC%~!W0MzeW zOjQv*a;A7AS@l%h9EbjzQ3d}e&j~R0VCoAN)q_>=)m=>e=ZX9w8jM3&o1RO^+0jJ) z

_|h)w;)ME+|h#gx@oo-|ZEuRI5d) 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 z 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 z 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 KvHt-#rc|>H2mv<$ diff --git a/Simple AllTalk Manager/addons/sourcemod/scripting/include/simple-plugins.inc b/Simple AllTalk Manager/addons/sourcemod/scripting/include/simple-plugins.inc deleted file mode 100644 index 8f21956..0000000 --- a/Simple AllTalk Manager/addons/sourcemod/scripting/include/simple-plugins.inc +++ /dev/null @@ -1,337 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Plugins -Description: - Included file for core plugin in the Simple Plugins project -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -*************************************************************************/ - -#if defined _simpleplugin_included - #endinput -#endif - -#define _simpleplugin_included - -#define CORE_INC_VERSION "1.1.$Rev$" - -#pragma semicolon 1 -#include -#undef REQUIRE_PLUGIN -#include -#define REQUIRE_PLUGIN -#undef REQUIRE_EXTENSIONS -#undef AUTOLOAD_EXTENSIONS -#tryinclude -#tryinclude -#tryinclude -#define AUTOLOAD_EXTENSIONS -#define REQUIRE_EXTENSIONS - -enum e_SupportedMods -{ - GameType_Unknown, - GameType_AOC, - GameType_CSS, - GameType_DOD, - GameType_FF, - GameType_HIDDEN, - GameType_HL2DM, - GameType_INS, - GameType_L4D, - GameType_NEO, - GameType_SGTLS, - GameType_TF, - GameType_ZPS -}; - -enum e_Teams -{ - Unknown, - Spectator, - Team1, - Team2 -}; - -new g_aCurrentTeams[e_Teams]; -new e_SupportedMods:g_CurrentMod; -new String:g_sGameName[e_SupportedMods][32] = { "Unknown", - "Age of Chivalry", - "Counter Strike", - "Day Of Defeat", - "Fortress Forever", - "Hidden: Source", - "Half Life 2: Deathmatch", - "Insurgency", - "Left 4 Dead", - "Neotokyo", - "Stargate TLS", - "Team Fortress 2", - "Zombie Panic: Source" - }; - -public SharedPlugin:_pl_simpleplugin = -{ - name = "simple-plugins", - file = "simple-plugins.smx", -#if defined REQUIRE_PLUGIN - required = 1 -#else - required = 0 -#endif -}; - -#if !defined REQUIRE_PLUGIN -public _pl_simpleplugin_SetNTVOptional() -{ - MarkNativeAsOptional("SM_MovePlayer"); - MarkNativeAsOptional("SM_SetForcedTeam"); - MarkNativeAsOptional("SM_GetForcedTeam"); - MarkNativeAsOptional("SM_ClearForcedTeam"); - MarkNativeAsOptional("SM_GetForcedPlayer"); - MarkNativeAsOptional("SM_AssignBuddy"); - MarkNativeAsOptional("SM_SearchBuddy"); - MarkNativeAsOptional("SM_LockBuddy"); - MarkNativeAsOptional("SM_IsBuddyLocked"); - MarkNativeAsOptional("SM_ClearBuddy"); - MarkNativeAsOptional("SM_IsValidAdmin"); - MarkNativeAsOptional("SM_IsValidTeam"); -} -#endif - -/********************************************************************** - * When a player has to moved - * - * @param plugin Plugin that initiated the move - * @param client The client index of the player that was moved - * @param team The team index the player was moved to - * @noreturn - **********************************************************************/ -forward SM_OnPlayerMoved(Handle:plugin, client, team); - -/********************************************************************** - * Move a player to the supplied team - * - * @param client The client index of the player to be moved - * @param team The team to move the player to - * @noreturn - * @error Invalid client or team index - **********************************************************************/ -native SM_MovePlayer(client, team); - -/********************************************************************** - * Move a player to the supplied team - * - * @param client The client index of the player to set - * @param team The team to move the to set - * @param override Whether or not to override another plugin - * @return True if successful, false if not - * @error Invalid client or team index - **********************************************************************/ -native SM_SetForcedTeam(client, team, bool:override = false); - -/********************************************************************** - * Gets the client's forced team index - * - * @param client The client index of the player to check - * @param plugin Optional: The plugin handle of the plugin - that set the team - * @return The team index of the forced team - Zero if no forced team - * @error Invalid client index - **********************************************************************/ -native SM_GetForcedTeam(client, &Handle:plugin = INVALID_HANDLE); - -/********************************************************************** - * Clears a client's forced team - * - * @param client The client index of the player to check - * @return True if successful, false if not - * @error Invalid client index - **********************************************************************/ -native SM_ClearForcedTeam(client); - -/********************************************************************** - * Gets a forced player on the wrong that is currently on the wrong team - * This will only return a player if the calling plugin assigned the team - * - * @param team The team index the player should be on - * @return The client index of the player - Zero if no player found - * @error Invalid client index - **********************************************************************/ -native SM_GetForcedPlayer(team); - -/********************************************************************** - * Assign a players buddy - * - * @param client The client index of the player to assign - * @param player The player index of the player to assign - * @param override Whether or not to override a player lock - * @return True if successful, false if not - * @error Invalid client or player index - **********************************************************************/ -native bool:SM_AssignBuddy(client, player, bool:override = false); - -/********************************************************************** - * Rturns the client's buddy - * - * @param client The client index of the player to assign - * @return The client index of the player's buddy - Zero if no buddy - * @error Invalid client index - **********************************************************************/ -native SM_GetClientBuddy(client); - -/********************************************************************** - * Set the buddy lock setting for a client - * - * @param client The client index of the player to assign - * @param setting Setting to set, True or False - * @return True if successful, false if not - * @error Invalid client index - **********************************************************************/ -native bool:SM_LockBuddy(client, bool:setting); - -/********************************************************************** - * Returns the buddy lock setting for a client - * - * @param client The client index of the player to assign - * @return True if locked, false if not - * @error Invalid client index - **********************************************************************/ -native bool:SM_IsBuddyLocked(client); - -/********************************************************************** - * Clear a players buddy - * - * @param client The client index of the player to clear - * @param override Whether or not to override a player lock - * @return True if successful, false if not - * @error Invalid client index - **********************************************************************/ -native bool:SM_ClearBuddy(client, bool:override = false); - -/********************************************************************** - * Determine if the player has the supplied flags - * ADMFLAG_ROOT will always return true - * - * @param client The client index of the player to assign - * @param flags The char flag(s) to check against - * @return True if valid, false if not - **********************************************************************/ -native bool:SM_IsValidAdmin(client, const String:flags[]); - - -/********************************************************************** - * Determine if the team is a valid team - * - * @param team The team index to determine if valid for - currently installed/supported mod - * @return True if valid, false if not - **********************************************************************/ -native bool:SM_IsValidTeam(team); - - -public e_SupportedMods:GetCurrentMod() -{ - new String:sGameType[64]; - GetGameFolderName(sGameType, sizeof(sGameType)); - - if (StrEqual(sGameType, "aoc", false)) - { - return GameType_AOC; - } - if (StrEqual(sGameType, "cstrike", false)) - { - return GameType_CSS; - } - if (StrEqual(sGameType, "dod", false)) - { - return GameType_DOD; - } - if (StrEqual(sGameType, "ff", false)) - { - return GameType_FF; - } - if (StrEqual(sGameType, "hidden", false)) - { - return GameType_HIDDEN; - } - if (StrEqual(sGameType, "hl2mp", false)) - { - return GameType_FF; - } - if (StrEqual(sGameType, "insurgency", false) || StrEqual(sGameType, "ins", false)) - { - return GameType_INS; - } - if (StrEqual(sGameType, "l4d", false)) - { - return GameType_L4D; - } - if (StrEqual(sGameType, "nts", false)) - { - return GameType_NEO; - } - if (StrEqual(sGameType, "sgtls", false)) - { - return GameType_SGTLS; - } - if (StrEqual(sGameType, "tf", false)) - { - return GameType_TF; - } - if (StrEqual(sGameType, "zps", false)) - { - return GameType_ZPS; - } - return GameType_Unknown; -} - -public LoadCurrentTeams() -{ - switch (g_CurrentMod) - { - case GameType_INS: - { - g_aCurrentTeams[Unknown] = 0; - g_aCurrentTeams[Spectator] = 3; - g_aCurrentTeams[Team1] = 1; - g_aCurrentTeams[Team2] = 2; - } - case default: - { - g_aCurrentTeams[Unknown] = 0; - g_aCurrentTeams[Spectator] = 1; - g_aCurrentTeams[Team1] = 2; - g_aCurrentTeams[Team2] = 3; - } - } -} diff --git a/Simple AllTalk Manager/addons/sourcemod/scripting/simple-alltalkmanager.sp b/Simple AllTalk Manager/addons/sourcemod/scripting/simple-alltalkmanager.sp index c848332..9d9ec82 100644 --- a/Simple AllTalk Manager/addons/sourcemod/scripting/simple-alltalkmanager.sp +++ b/Simple AllTalk Manager/addons/sourcemod/scripting/simple-alltalkmanager.sp @@ -97,7 +97,8 @@ public OnPluginStart() /** Remove the notify flag from all talk cvar since we do it */ - SetConVarFlags(satm_alltalk, GetConVarFlags(satm_alltalk)~FCVAR_NOTIFY); + new iCvarFlags = GetConVarFlags(satm_alltalk)^FCVAR_NOTIFY; + SetConVarFlags(satm_alltalk, iCvarFlags); /** Get the game type. We only care if it's TF2 diff --git a/Simple AllTalk Manager/addons/sourcemod/scripting/simple-autoscrambler.sp b/Simple AllTalk Manager/addons/sourcemod/scripting/simple-autoscrambler.sp deleted file mode 100644 index 6c6799e..0000000 --- a/Simple AllTalk Manager/addons/sourcemod/scripting/simple-autoscrambler.sp +++ /dev/null @@ -1,459 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple AutoScrambler -Description: - Automatically scrambles the teams based upon a number of events. -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include - -#define PLUGIN_VERSION "1.1.$Rev$" - -/** -Different scramble modes: - -1 = Full Scramble, dont restart round. -2 = Admins Immune, dont restart round. -3 = Full Scramble, restart round and reset scores. -4 = Admins Immune, restart round and reset scores. - -*/ - -/** -Different top player modes: - -1 = Divide Top 4 players on the two teams. -2 = Protect the Top 2 players on each team. - -*/ - -enum PlayerData -{ - Handle:hForcedTimer, - bool:bProtected; -}; - -/** -Cvars used for admins -*/ -new Handle: sas_admin_immunity_enabled = INVALID_HANDLE, - Handle: sas_admin_flag_scramblenow = INVALID_HANDLE, - Handle: sas_admin_flag_immunity = INVALID_HANDLE; - -/** -Cvars used for autoscramble -*/ -new Handle: sas_autoscramble_enabled = INVALID_HANDLE, - Handle: sas_autoscramble_minplayers = INVALID_HANDLE, - Handle: sas_autoscramble_mode = INVALID_HANDLE, - Handle: sas_autoscramble_winstreak = INVALID_HANDLE, - Handle: sas_autoscramble_steamroll = INVALID_HANDLE, - Handle: sas_autoscramble_frags = INVALID_HANDLE; - -/** -Cvars used for voting -*/ -new Handle: sas_vote_enabled = INVALID_HANDLE, - Handle: sas_vote_upcount = INVALID_HANDLE, - Handle: sas_vote_winpercent = INVALID_HANDLE, - Handle: sas_vote_mode = INVALID_HANDLE, - Handle: sas_vote_minplayers = INVALID_HANDLE; - -/** -Additional cvars -*/ -new Handle: sas_enabled = INVALID_HANDLE, - Handle: sas_timer_scrambledelay = INVALID_HANDLE, - Handle: TFGameModeArena = INVALID_HANDLE; - -/** -Timers -*/ -new Handle: g_hScrambleTimer = INVALID_HANDLE; - -/** - Player arrays - */ -new g_aPlayers[MAXPLAYERS + 1][PlayerData]; - -/** - Cvar variables - */ -new bool: g_bIsEnabled, - bool: g_bIsAutoScrambleEnabled, - bool: g_bIsVoteEnabled, - bool: g_bIsAdminImmunityEnabled; -new Float: g_fTimer_ScrambleDelay, - Float: g_fVote_UpCount, - Float: g_fVote_WinPercent; -new g_iAutoScramble_Minplayers, - g_iAutoScramble_Mode, - g_iAutoScramble_WinStreak, - g_iAutoScramble_SteamRoll, - g_iAutoScramble_Frags, - g_iVote_Mode, - g_iVote_MinPlayers; -new String: g_sScrambleNowFlag[5], - String: g_sAdminImmunityFlag[5]; - -/** -Other globals -*/ -new g_iMaxEntities, - g_iOwnerOffset; - -public Plugin:myinfo = -{ - name = "Simple AutoScrambler", - author = "Simple Plugins", - description = "Automatically scrambles the teams based upon a number of events.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -public OnPluginStart() -{ - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[SAS] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - switch (g_CurrentMod) - { - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_Post); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_Post); - } - } - - /** - Create console variables - */ - CreateConVar("sas_version", PLUGIN_VERSION, "Simple AutoScrambler Version",FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - sas_enabled = CreateConVar("sas_enabled", "1", "Enable/Disable Simple AutoScrambler"); - sas_timer_scrambledelay = CreateConVar("sas_timer_scrambledelay", "5.0", "Delay used after a scramble has been started", _, true, 1.0, true, 30.0); - - /** - Cvars used for admins - */ - sas_admin_immunity_enabled = CreateConVar("sas_admin_immunity_enabled", "1", "Enable/Disable admin immunity for scrambles"); - sas_admin_flag_scramblenow = CreateConVar("sas_admin_flag_scramblenow", "z", "Admin flag to use for scramblenow function/command"); - sas_admin_flag_immunity = CreateConVar("sas_admin_flag_immunity", "z", "Admin flag to use for scramble immunity"); - - /** - Cvars used for autoscramble - */ - sas_autoscramble_enabled = CreateConVar("sas_autoscramble_enabled", "1", "Enable/Disable the autoscramble function"); - sas_autoscramble_minplayers = CreateConVar("sas_autoscramble_minplayers", "16", "Min players needed to start an autoscramble"); - sas_autoscramble_mode = CreateConVar("sas_autoscramble_mode", "1", "Scramble mode used when autoscrambling"); - sas_autoscramble_winstreak = CreateConVar("sas_autoscramble_winstreak", "5", "Max amount of wins in a row a team can achieve before an autoscramble starts"); - sas_autoscramble_steamroll = CreateConVar("sas_autoscramble_steamroll", "120", "Shortest amount of time a team can win by before an autoscramble starts (seconds)"); - sas_autoscramble_frags = CreateConVar("sas_autoscramble_frags", "1", "Min players needed to start a vote and scramble"); - - /** - Cvars used for voting - */ - sas_vote_enabled = CreateConVar("sas_vote_enabled", "1", "Enable/Disable voting for scramble"); - sas_vote_upcount = CreateConVar("sas_vote_upcount", "5", "Amount of people wanting a scramble before a vote starts. If less than 1 it will be considered a percentage. (ie 0.5 = 50% | 1 = 1 Player | 5 = 5 Players)"); - sas_vote_winpercent = CreateConVar("sas_vote_winpercent", "0.6", "Percentage of votes needed to scramble", _, true, 0.0, true, 1.0); - sas_vote_mode = CreateConVar("sas_vote_mode", "1", "Scramble mode used when a vote results in a scramble"); - sas_vote_minplayers = CreateConVar("sas_vote_minplayers", "16", "Min players needed to start a vote and scramble"); - - /** - Hook the console variables if they change - */ - HookConVarChange(sas_enabled, ConVarSettingsChanged); - HookConVarChange(sas_timer_scrambledelay, ConVarSettingsChanged); - HookConVarChange(sas_admin_immunity_enabled, ConVarSettingsChanged); - HookConVarChange(sas_admin_flag_scramblenow, ConVarSettingsChanged); - HookConVarChange(sas_admin_flag_immunity, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_enabled, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_minplayers, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_mode, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_winstreak, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_steamroll, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_frags, ConVarSettingsChanged); - HookConVarChange(sas_vote_enabled, ConVarSettingsChanged); - HookConVarChange(sas_vote_upcount, ConVarSettingsChanged); - HookConVarChange(sas_vote_winpercent, ConVarSettingsChanged); - HookConVarChange(sas_vote_mode, ConVarSettingsChanged); - HookConVarChange(sas_vote_minplayers, ConVarSettingsChanged); - - /** - Register the command - */ - RegConsoleCmd("sm_scramblenow", Command_ScrambleNow, "sm_scramblenow (mode): Scrambles the teams"); - - /** - Load translations and .cfg file - */ - LoadTranslations ("simpleautoscrambler.phrases"); - AutoExecConfig(true, "plugin.simpleautoscrambler"); - LogAction(0, -1, "[SAS] Simple AutoScrambler is loaded."); -} - -public OnAllPluginsLoaded() -{ - //something -} - -public OnLibraryRemoved(const String:name[]) -{ - //something -} - -public OnConfigsExecuted() -{ - - /** - Load up all the variable defaults - */ - LoadUpVariables(); - - /** - Log our activity - */ - if (g_bIsEnabled) - LogAction(0, -1, "Simple AutoScrambler is ENABLED"); - else - LogAction(0, -1, "Simple AutoScrambler is DISABLED"); -} - -public Action:Command_ScrambleNow(client, args) -{ - - /** - Make sure we are enabled - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the client is authorized to run this command. - */ - if (!SM_IsValidAdmin(client, g_sScrambleNowFlag)) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure it's ok to scramble at this time - */ - if (!OkToScramble) - { - return Plugin_Handled; - } - - /** - Make sure it's ok to scramble at this time - */ - LogAction(0, -1, "[SAS] The scramblenow command was used"); - - /** - Scramble the teams - */ - StartAScramble(); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - -} - -public Action:Timer_ScrambleTeams(Handle:timer, any:mode) -{ - - /** - Make sure it's still ok to scramble - */ - if (!OkToScramble) - { - return Plugin_Handled; - } - - - switch (mode) - { - case - - - - } - - - /** - Reset the handle because the timer is over and the callback is done - */ - g_hScrambleTimer = INVALID_HANDLE; - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - -} - -stock StartAScramble(mode) -{ - - /** - See if we are already started a scramble - */ - if (g_hScrambleTimer == INVALID_HANDLE) - { - - /** - There is a scramble in progress - */ - return; - - } - - /** - Report that a scramble is about to start - */ - PrintCenterTextAll("%T", "Scramble", LANG_SERVER); - - /** - Start a timer and log the action - */ - g_hScrambleTimer = CreateTimer(g_fTimer_ScrambleDelay, Timer_ScrambleTeams, mode, TIMER_FLAG_NO_MAPCHANGE); - LogAction(0, -1, "[SAS] A scamble timer was started"); -} - -stock bool:OkToScramble() -{ - -} - -stock LoadUpVariables() -{ - g_bIsEnabled = GetConVarBool(sas_enabled); - g_bIsAutoScrambleEnabled = GetConVarBool(sas_autoscramble_enabled); - g_bIsVoteEnabled = GetConVarBool(sas_vote_enabled); - g_bIsAdminImmunityEnabled = GetConVarBool(sas_admin_immunity_enabled); - g_iAutoScramble_Minplayers = GetConVarInt(sas_autoscramble_minplayers); - g_iAutoScramble_Mode = GetConVarInt(sas_autoscramble_mode); - g_iAutoScramble_WinStreak = GetConVarInt(sas_autoscramble_winstreak); - g_iAutoScramble_SteamRoll = GetConVarInt(sas_autoscramble_steamroll); - g_iAutoScramble_Frags = GetConVarInt(sas_autoscramble_frags); - g_iVote_Mode = GetConVarInt(sas_vote_mode); - g_iVote_MinPlayers = GetConVarInt(sas_vote_minplayers); - GetConVarString(sas_admin_flag_scramblenow, g_sScrambleNowFlag, sizeof(g_sScrambleNowFlag)); - GetConVarString(sas_admin_flag_immunity, g_sAdminImmunityFlag, sizeof(g_sAdminImmunityFlag)); - g_fTimer_ScrambleDelay = GetConVarFloat(sas_timer_scrambledelay); - g_fVote_UpCount = GetConVarFloat(sas_vote_upcount); - g_fVote_WinPercent = GetConVarFloat(sas_vote_winpercent); - g_iMaxEntities = GetMaxEntities(); - g_iOwnerOffset = FindSendPropInfo("CBaseObject", "m_hBuilder"); -} - -stock TF2_DestroyBuildings(client) -{ - - /** - We have to start a loop to check the owner of all the valid entities - */ - for (new i = MaxClients + 1; i <= g_iMaxEntities; i++) - { - if (!IsValidEntity(i)) - { - - /** - Not valid, continue to next one - */ - continue; - } - - /** - Get the name of the current entity - */ - decl String:sNetClass[32]; - GetEntityNetClass(i, sNetClass, sizeof(sNetClass)); - - /** - See if its something that an engineer would build - */ - if (strcmp(sNetClass, "CObjectSentrygun") == 0 - || strcmp(sNetClass, "CObjectTeleporter") == 0 - || strcmp(sNetClass, "CObjectDispenser") == 0) - { - - /** - It is, so lets check the owner - */ - if (GetEntDataEnt2(i, g_iOwnerOffset) == client) - { - - /** - It's the clients building, so we blow it up. - */ - SetVariantInt(9999); - AcceptEntityInput(i, "RemoveHealth"); - } - } - } -} \ No newline at end of file diff --git a/Simple AllTalk Manager/addons/sourcemod/scripting/simple-chatcolors.sp b/Simple AllTalk Manager/addons/sourcemod/scripting/simple-chatcolors.sp deleted file mode 100644 index 539d057..0000000 --- a/Simple AllTalk Manager/addons/sourcemod/scripting/simple-chatcolors.sp +++ /dev/null @@ -1,496 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Chat Colors -Description: - Changes the colors of players chat based on config file -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#pragma semicolon 1 -#include -#include - -#define PLUGIN_VERSION "0.9.0.$Rev$" - -#define CHAT_SYMBOL '@' -#define TRIGGER_SYMBOL1 '!' -#define TRIGGER_SYMBOL2 '/' -#define CHAT_MAX_MESSAGE_LENGTH 1024 - -new Handle:g_hDebugCvar = INVALID_HANDLE; -new Handle:g_aGroupNames = INVALID_HANDLE; -new Handle:g_aGroupFlag = INVALID_HANDLE; -new Handle:g_aGroupNameColor = INVALID_HANDLE; -new Handle:g_aGroupTextColor = INVALID_HANDLE; - -new bool:g_bDebug = false; - -new g_iArraySize; - -new g_aPlayerColorIndex[MAXPLAYERS + 1] = { -1, ... }; - -public Plugin:myinfo = -{ - name = "Simple Chat Colors", - author = "Simple Plugins", - description = "Changes the colors of players chat based on config file.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -/** -Sourcemod callbacks -*/ -public OnPluginStart() -{ - - /** - Need to create all of our console variables. - */ - CreateConVar("sm_chatcolors_version", PLUGIN_VERSION, "Simple Chat Colors", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - g_hDebugCvar = CreateConVar("sm_chatcolors_debug", "1", "Enable/Disable debugging information"); - - /** - Hook console variables - */ - HookConVarChange(g_hDebugCvar, ConVarSettingsChanged); - - /** - Need to register the commands we are going to use - */ - RegConsoleCmd("say", Command_Say); - RegConsoleCmd("say_team", Command_SayTeam); - RegAdminCmd("sm_reloadcolorsconfig", Command_Reload, ADMFLAG_GENERIC, "Reloads settings from config file"); - - /** - Create the arrays - */ - g_aGroupNames = CreateArray(256, 1); - g_aGroupFlag = CreateArray(15, 1); - g_aGroupNameColor = CreateArray(15, 1); - g_aGroupTextColor = CreateArray(15, 1); - - /** - Load the admins and colors from the config - */ - LoadAdminsAndColorsFromConfig(); - g_iArraySize = GetArraySize(g_aGroupNames); -} - -public OnConfigsExecuted() -{ - g_bDebug = GetConVarBool(g_hDebugCvar); - ReloadConfigFile(); -} - -public OnClientPostAdminCheck(client) -{ - - /** - Check the client to see if they are a admin - */ - CheckAdmin(client); -} - -public OnClientDisconnect(client) -{ - g_aPlayerColorIndex[client] = -1; -} - -/** -Commands -*/ -public Action:Command_Say(client, args) -{ - - /** - Make sure we are enabled. - */ - if (client == 0 || IsChatTrigger()) - { - return Plugin_Continue; - } - - if (g_aPlayerColorIndex[client] != -1) - { - - /** - The client is, so get the chat message and strip it down. - */ - decl String:sArg[CHAT_MAX_MESSAGE_LENGTH], - String:sChatMsg[CHAT_MAX_MESSAGE_LENGTH]; - - new bool:bAlive = IsPlayerAlive(client); - - GetCmdArgString(sArg, sizeof(sArg)); - StripQuotes(sArg); - TrimString(sArg); - new startidx; - if (sArg[strlen(sArg)-1] == '"') - { - sArg[strlen(sArg)-1] = '\0'; - startidx = 1; - } - - /** - Bug out if they are using the admin chat symbol (admin chat). If we are in CSS it may not find all the triggers, so we double check. - */ - if (sArg[startidx] == CHAT_SYMBOL || sArg[startidx] == TRIGGER_SYMBOL1 || sArg[startidx] == TRIGGER_SYMBOL2) - { - return Plugin_Continue; - } - - /** - Log the message for hlstatsx and other things. - */ - new iUserID = GetClientUserId(client); - decl String:sAuthID[64]; - GetClientAuthString(client, sAuthID, sizeof(sAuthID)); - LogToGame("\"%N<%i><%s><>\" say \"%s\"", client, iUserID, sAuthID, sArg); - - /** - Format the message. - */ - FormatMessage(client, 0, bAlive, sChatMsg, sArg, g_aPlayerColorIndex[client]); - - /** - Send the message. - */ - //SayText2(0, client, sChatMsg); - CPrintToChatAll(sChatMsg); - - /** - We are done, bug out, and stop the original chat message. - */ - return Plugin_Stop; - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Command_SayTeam(client, args) -{ - - /** - Make sure we are enabled. - */ - if (client == 0 || IsChatTrigger()) - { - return Plugin_Continue; - } - - /** - Check the client to see if they are a admin - */ - if (g_aPlayerColorIndex[client] != -1) - { - - /** - The client is, so get the chat message and strip it down. - */ - decl String:sArg[CHAT_MAX_MESSAGE_LENGTH], - String:sChatMsg[CHAT_MAX_MESSAGE_LENGTH]; - - new bool:bAlive = IsPlayerAlive(client); - new iCurrentTeam = GetClientTeam(client); - - GetCmdArgString(sArg, sizeof(sArg)); - StripQuotes(sArg); - TrimString(sArg); - new startidx; - if (sArg[strlen(sArg)-1] == '"') - { - sArg[strlen(sArg)-1] = '\0'; - startidx = 1; - } - - /** - Bug out if they are using the admin chat symbol (admin chat). - */ - if (sArg[startidx] == CHAT_SYMBOL || sArg[startidx] == TRIGGER_SYMBOL1 || sArg[startidx] == TRIGGER_SYMBOL2) - { - return Plugin_Continue; - } - - /** - Log the message for hlstatsx and other things. - */ - new iUserID = GetClientUserId(client); - decl String:sAuthID[64]; - GetClientAuthString(client, sAuthID, sizeof(sAuthID)); - LogToGame("\"%N<%i><%s><>\" say_team \"%s\"", client, iUserID, sAuthID, sArg); - - /** - Format the message. - */ - FormatMessage(client, iCurrentTeam, bAlive, sChatMsg, sArg, g_aPlayerColorIndex[client]); - - /** - Send the message to the same team - */ - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == iCurrentTeam) - { - CPrintToChat(client, sChatMsg); - } - } - - /** - We are done, bug out, and stop the original chat message. - */ - return Plugin_Stop; - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Command_Reload(client, args) -{ - ReloadConfigFile(); - return Plugin_Handled; -} - -/** -Stock Functions -*/ -stock LoadAdminsAndColorsFromConfig() -{ - - /** - Make sure the config file is here and load it up - */ - new String:sConfigFile[256]; - BuildPath(Path_SM, sConfigFile, sizeof(sConfigFile), "configs/simple-chatcolors.cfg"); - if (!FileExists(sConfigFile)) - { - - /** - Config file doesn't exists, stop the plugin - */ - LogError("[SCC] Simple Chat Colors is not running! Could not find file %s", sConfigFile); - SetFailState("Could not find file %s", sConfigFile); - } - - /** - Create the arrays and variables - */ - new String:sGroupName[256]; - new String:sGroupFlag[15]; - new String:sGroupNameColor[15]; - new String:sGroupTextColor[15]; - - - /** - Load config file as a KeyValues file - */ - new Handle:kvChatColors = CreateKeyValues("admin_colors"); - FileToKeyValues(kvChatColors, sConfigFile); - - if (!KvGotoFirstSubKey(kvChatColors)) - { - return; - } - - /** - Load up all the groups in the file - */ - do - { - - /** - Get the section name; should be the "group" name - */ - KvGetSectionName(kvChatColors, sGroupName, sizeof(sGroupName)); - - - /** - Get the flags and colors - */ - KvGetString(kvChatColors, "flag", sGroupFlag, sizeof(sGroupFlag)); - KvGetString(kvChatColors, "namecolor", sGroupNameColor, sizeof(sGroupNameColor)); - KvGetString(kvChatColors, "textcolor", sGroupTextColor, sizeof(sGroupTextColor)); - - if (g_bDebug) - { - LogMessage("Group Name/SteamID: %s", sGroupName); - LogMessage("Flag String: %s", sGroupFlag); - LogMessage("Color on name: %s", sGroupNameColor); - LogMessage("Color of text: %s", sGroupTextColor); - } - - /** - Push the values to the arrays - */ - PushArrayString(g_aGroupNames, sGroupName); - PushArrayString(g_aGroupFlag, sGroupFlag); - PushArrayString(g_aGroupNameColor, sGroupNameColor); - PushArrayString(g_aGroupTextColor, sGroupTextColor); - } while (KvGotoNextKey(kvChatColors)); - - /** - Close our handle - */ - CloseHandle(kvChatColors); -} - -stock ReloadConfigFile() -{ - - /** - Clear the array - */ - ClearArray(g_aGroupNames); - ClearArray(g_aGroupFlag); - ClearArray(g_aGroupNameColor); - ClearArray(g_aGroupTextColor); - - /** - Load the admins, groups, and colors from the config - */ - LoadAdminsAndColorsFromConfig(); - g_iArraySize = GetArraySize(g_aGroupNames); - - /** - Recheck all the online players for assigned colors - */ - for (new index = 1; index <= MaxClients; index++) - { - if (IsClientConnected(index) && IsClientInGame(index)) - { - CheckAdmin(index); - } - } -} - -stock CheckAdmin(client) -{ - new String:sFlags[15]; - new String:sClientSteamID[64]; - new iGroupFlags; - new iFlags; - new iIndex = -1; - - /** - Look for a steamid first - */ - GetClientAuthString(client, sClientSteamID, sizeof(sClientSteamID)); - iIndex = FindStringInArray(g_aGroupNames, sClientSteamID); - if (iIndex != -1) - { - g_aPlayerColorIndex[client] = iIndex; - } - - /** - Didn't find one, check flags - */ - else - { - /** - Search for flag in groups - */ - - iFlags = GetUserFlagBits(client); - for (iIndex = 0; iIndex < g_iArraySize; iIndex++) - { - GetArrayString(g_aGroupFlag, iIndex, sFlags, sizeof(sFlags)); - iGroupFlags = ReadFlagString(sFlags); - if (iFlags & iGroupFlags) - { - g_aPlayerColorIndex[client] = iIndex; - break; - } - } - } - - if (g_bDebug) - { - PrintToChatAll("SteamID: %s", sClientSteamID); - PrintToChatAll("Array Index: %i", iIndex); - PrintToChatAll("Flag String: %s", sFlags); - PrintToChatAll("Flag Bits of Client: %i", iFlags); - PrintToChatAll("Flag Bits of Group: %i", iGroupFlags); - } -} - -stock FormatMessage(iClient, iTeam, bool:bAlive, String:sChatMsg[], const Sting:sMessage[], iArrayIndex) -{ - decl String:sDead[10], - String:sTeam[10], - String:sClientName[64]; - - GetClientName(iClient, sClientName, sizeof(sClientName)); - - if (iTeam != 0) - { - Format(sTeam, sizeof(sTeam), "(TEAM) "); - } - else - { - Format(sTeam, sizeof(sTeam), ""); - } - if (bAlive) - { - Format(sDead, sizeof(sDead), ""); - } - else - { - Format(sDead, sizeof(sDead), "*DEAD* "); - } - - new String:sNameColor[15]; - new String:sTextColor[15]; - GetArrayString(g_aGroupNameColor, iArrayIndex, sNameColor, sizeof(sNameColor)); - GetArrayString(g_aGroupTextColor, iArrayIndex, sTextColor, sizeof(sTextColor)); - - Format(sChatMsg, CHAT_MAX_MESSAGE_LENGTH, "{default}%s%s%s%s {default}: %s%s", sDead, sTeam, sNameColor, sClientName, sTextColor, sMessage); -} - -/** -Adjust the settings if a convar was changed -*/ -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (StringToInt(newValue) == 1) - { - g_bDebug = true; - } - else - { - g_bDebug = false; - } -} \ No newline at end of file diff --git a/Simple AllTalk Manager/addons/sourcemod/scripting/simple-donatorbenefits.sp b/Simple AllTalk Manager/addons/sourcemod/scripting/simple-donatorbenefits.sp deleted file mode 100644 index e3f6845..0000000 --- a/Simple AllTalk Manager/addons/sourcemod/scripting/simple-donatorbenefits.sp +++ /dev/null @@ -1,1312 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Donator Benefits -Description: - Provides donator benefits to players -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include -#include - -#define PLUGIN_VERSION "1.1.$Rev$" - -#define CHAT_SYMBOL '@' -#define CHAT_MAX_MESSAGE_LENGTH 1024 - -enum PlayerData -{ - bool:bIsDonator, - bool:bQueue, - bool:bImmune, - iHealthCount, - iNewTeam -}; - -/** - Public convar handles - */ -new Handle:sdb_enabled = INVALID_HANDLE; -new Handle:sdb_donationflag = INVALID_HANDLE; -new Handle:sdb_soundfile = INVALID_HANDLE; -new Handle:sdb_joinsound_enabled = INVALID_HANDLE; -new Handle:sdb_joinpubmsg_enabled = INVALID_HANDLE; -new Handle:sdb_joinprivmsg_enabled = INVALID_HANDLE; -new Handle:sdb_chatcolors_enabled = INVALID_HANDLE; -new Handle:sdb_immunity_enabled = INVALID_HANDLE; -new Handle:sdb_ubercharge_enabled = INVALID_HANDLE; -new Handle:sdb_givehealth_enabled = INVALID_HANDLE; -new Handle:sdb_nofalldmg_enabled = INVALID_HANDLE; -new Handle:sdb_fastheavy_enabled = INVALID_HANDLE; -new Handle:sdb_swapteam_enabled = INVALID_HANDLE; -new Handle:sdb_chatcolor = INVALID_HANDLE; -new Handle:sdb_uberlevel = INVALID_HANDLE; -new Handle:sdb_healthcount = INVALID_HANDLE; -new Handle:sdb_healthbonus = INVALID_HANDLE; -new Handle:sdb_heavymultiplier = INVALID_HANDLE; - -/** -Create global enable/disable bools so we don't have to check the console variable on every call -*/ -new bool:g_bIsEnabled = true; -new bool:g_bIsJoinSoundEnabled = true; -new bool:g_bIsJoinPubMsgEnabled = true; -new bool:g_bIsJoinPrivMsgEnabled = true; -new bool:g_bIsChatColorsEnabled = true; -new bool:g_bIsImmuntyEnabled = true; -new bool:g_bIsUberChargeEnabled = true; -new bool:g_bIsGiveHealthEnabled = true; -new bool:g_bIsNoFallDmgEnabled = true; -new bool:g_bIsFastHeayEnabled = true; -new bool:g_bIsSwapTeamEnabled = true; - -/** - Player arrays - */ -new g_aPlayers[MAXPLAYERS + 1][PlayerData]; - - -/** -Rest of the globals -*/ -new bool:g_bRoundEnd = false; -new String:g_sCharDonatorFlag[5]; -new String:g_sSoundFile[PLATFORM_MAX_PATH]; -new String:g_sChatColor[11]; -new g_iHealthBonus; -new g_iHealthCount; -new g_iClassMaxHealth[TFClassType] = {0, 125, 125, 200, 175, 150, 300, 175, 125, 125}; -new g_fClassMaxSpeed[TFClassType] = {0, 400, 300, 240, 280, 320, 230, 300, 300, 300}; -new Float:g_fHeavyMultiplier = 0.0; -new Float:g_fUberLevel = 0.0; - -public Plugin:myinfo = -{ - name = "Simple Donation Benefits", - author = "Simple Plugins", - description = "Gives donators benefits to players", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -} - -public OnPluginStart() -{ - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[SDB] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_connect", HookPlayerSpawn, EventHookMode_Pre); - HookEvent("player_spawn", HookPlayerSpawn, EventHookMode_Post); - HookEvent("player_death", HookPlayerDeath, EventHookMode_Post); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Post); - switch (g_CurrentMod) - { - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - HookEvent("player_changeclass", HookPlayerClass, EventHookMode_Post); - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_Post); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - - /** - Create console variables - */ - CreateConVar("sdb_version", PLUGIN_VERSION, "Simple Donation Benefits", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - sdb_enabled = CreateConVar("sdb_enabled", "1", "Enable/Disable Simple Donation Benefits"); - sdb_donationflag = CreateConVar("sdb_donationflag", "a", "Flag ALREADY given to donators. Must be in char format"); - - /** - Create the enable/disable donator console variables - */ - sdb_joinsound_enabled = CreateConVar("sdb_joinsound_enabled", "1", "Enable/Disable donator join sound"); - sdb_joinpubmsg_enabled = CreateConVar("sdb_joinpubmsg_enabled", "1", "Enable/Disable public donator join message (replaces: as connected)"); - sdb_joinprivmsg_enabled = CreateConVar("sdb_joinprivmsg_enabled", "1", "Enable/Disable private donator join message (sent only to donator)"); - sdb_chatcolors_enabled = CreateConVar("sdb_chatcolors_enabled", "1", "Enable/Disable donator chat colors"); - sdb_immunity_enabled = CreateConVar("sdb_immunity_enabled", "1", "Enable/Disable donator round end immunity"); - sdb_ubercharge_enabled = CreateConVar("sdb_ubercharge_enabled", "1", "Enable/Disable donator medics starting with ubercharge"); - sdb_givehealth_enabled = CreateConVar("sdb_givehealth_enabled", "1", "Enable/Disable donator instant health bonus"); - sdb_nofalldmg_enabled = CreateConVar("sdb_nofalldmg_enabled", "1", "Enable/Disable no fall damage for donators"); - sdb_fastheavy_enabled = CreateConVar("sdb_fastheavy_enabled", "1", "Enable/Disable donator heavies moving faster while spinning"); - sdb_swapteam_enabled = CreateConVar("sdb_swampteam_enabled", "1", "Enable/Disable donator swap team ability"); - - /** - Create the donator setting console variables - */ - sdb_soundfile = CreateConVar("sdb_soundfile", "custom/donatorjoin.mp3", "The location of sound file"); - sdb_chatcolor = CreateConVar("sdb_chatcolor", "green", "Color to use for donator chat. Valid colors are green and lightgreen"); - sdb_uberlevel = CreateConVar("sdb_uberlevel", "0.5", "Uberlevel to give donator medic at spawn. 1.0 = full uber", _, true, 0.0, true, 1.0); - sdb_healthcount = CreateConVar("sdb_healthcount", "1", "Number of times a donator can use use instant health per life"); - sdb_healthbonus = CreateConVar("sdb_healthbonus", "100", "The amount of health to heal the donator"); - sdb_heavymultiplier = CreateConVar("sdb_heavyspeed", "0.5", "The speed multiplier for the fast heavy. Based on running speed. 1.0 = running speed. (Game Default is 0.20)", _, true, 0.0, true, 1.0); - - /** - Hook dukehacks calls - */ - dhAddClientHook(CHK_TakeDamage, Hacks_TakeDamageHook); - dhAddClientHook(CHK_PreThink, Hacks_PreThinkHook); - - /** - Hook the console variables if they change - */ - HookConVarChange(sdb_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_donationflag, ConVarSettingsChanged); - HookConVarChange(sdb_joinsound_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_joinpubmsg_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_joinprivmsg_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_chatcolors_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_immunity_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_ubercharge_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_givehealth_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_nofalldmg_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_swapteam_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_fastheavy_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_soundfile, ConVarSettingsChanged); - HookConVarChange(sdb_chatcolor, ConVarSettingsChanged); - HookConVarChange(sdb_uberlevel, ConVarSettingsChanged); - HookConVarChange(sdb_healthcount, ConVarSettingsChanged); - HookConVarChange(sdb_healthbonus, ConVarSettingsChanged); - HookConVarChange(sdb_heavymultiplier, ConVarSettingsChanged); - - /** - Register the commands - */ - RegConsoleCmd("sm_swapteams", Command_SwapTeam, "sm_swapteams <[0]instant/[1]queued>: Swaps your team to the other team"); - RegConsoleCmd("sm_ihealth", Command_InstantHealth, "sm_ihealth: Gives you a instant health pack"); - RegAdminCmd("sm_teaser", Command_Teaser, ADMFLAG_GENERIC,"sm_teaser <[0]add/[1]remove>: Gives temporary donator privilages to a player"); - RegConsoleCmd("say", Command_Say); - - RegConsoleCmd("sm_test", Command_TEST); - - /** - Load the translations - */ - LoadTranslations("common.phrases"); - LoadTranslations("simpledonatorbenefits.phrases"); - - /** - Load or create the config file - */ - AutoExecConfig(true, "plugin.simpledonatorbenefits"); - LogAction(0, -1, "[SDB] Simple Donator Benefits is loaded."); -} - -public OnAllPluginsLoaded() -{ - //something -} - -public OnLibraryRemoved(const String:name[]) -{ - //something -} - -public OnConfigsExecuted() -{ - /** - Load up all the variable defaults - */ - LoadUpVariables(); - - /** - If the join sound is enabled, prep the sound files - */ - if (g_bIsJoinSoundEnabled) - PrepSoundFile(); - - /** - Log our activity - */ - if (g_bIsEnabled) - LogAction(0, -1, "Simple Donation Benefits is ENABLED"); - else - LogAction(0, -1, "Simple Donation Benefits is DISABLED"); -} - -public OnClientPostAdminCheck(client) -{ - - /** - Check if the client is a donator - */ - if (SM_IsValidAdmin(client, g_sCharDonatorFlag)) - { - - /** - They are, so we set the player array to true and start a timer for the sound or add - */ - g_aPlayers[client][bIsDonator] = true; - if (g_bIsJoinSoundEnabled || g_bIsJoinPrivMsgEnabled) - { - CreateTimer(10.0, Timer_DonatorJoined, client, TIMER_FLAG_NO_MAPCHANGE); - } - } - else - { - /** - They aren't, so we set the player array to false - */ - g_aPlayers[client][bIsDonator] = false; - } -} - -public OnClientDisconnect_Post(client) -{ - - /** - Clean up the player variables - */ - CleanUpPlayer(client); -} - -public Action:Command_SwapTeam(client, args) -{ - - /** - Make sure we are enabled - */ - if (!g_bIsEnabled || !g_bIsSwapTeamEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the command is not started by the server - */ - if (client == 0) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure the player is a donator - */ - if (!g_aPlayers[client][bIsDonator]) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Lets make sure the client is one a team we can swap. - If he is we set the global array to the opposite team. - */ - new iTeam = GetClientTeam(client); - if (iTeam == g_aCurrentTeams[Team1]) - { - g_aPlayers[client][iNewTeam] = g_aCurrentTeams[Team2]; - } - else if (iTeam == g_aCurrentTeams[Team2]) - { - g_aPlayers[client][iNewTeam] = g_aCurrentTeams[Team1]; - } - else - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "InValidTeam", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check to see if we have command arguments. - */ - if (GetCmdArgs()) - { - - /** - We do, so lets get it and see if the client wants to be switched instantly or queued for death. - */ - decl String:sArg[5]; - GetCmdArg(1, sArg, sizeof(sArg)); - new iWantsQue = StringToInt(sArg); - if (iWantsQue && !g_aPlayers[client][bQueue]) - { - - /** - He wants the que and isn't already in it, set the global array. - */ - g_aPlayers[client][bQueue] = true; - ReplyToCommand(client, "\x01\x04[STM]\x01 %T", "PlayerQueue", LANG_SERVER); - } - else if (!iWantsQue) - { - - /** - He wants to be switched right now, lets call the stock function. - */ - SM_MovePlayer(client, g_aPlayers[client][iNewTeam]); - } - } - else - { - - /** - There are no command arguments so we build and display the swap menu. - */ - new Handle:hPlayerMenu = BuildSwapModeMenu(); - DisplayMenu(hPlayerMenu, client, MENU_TIME_FOREVER); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_InstantHealth(client, args) -{ - - /** - Make sure we are enabled - */ - if (!g_bIsEnabled || !g_bIsGiveHealthEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the command is not started by the server - */ - if (client == 0) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure the player is a donator - */ - if (!g_aPlayers[client][bIsDonator]) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check health count to see if the player has reached the max - */ - if (g_aPlayers[client][iHealthCount] >= g_iHealthCount) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "ReachedCount", LANG_SERVER); - return Plugin_Handled; - } - - /** - Get the class of the player and the max health for that class - */ - new iHealth = GetClientHealth(client); - new TFClassType:PlayerClass = TF2_GetPlayerClass(client); - new iMaxHealth = g_iClassMaxHealth[PlayerClass]; - - /** - Check to see if the player is at the max health of the class - */ - if (iHealth >= iMaxHealth) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "AtMaxHealth", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check the current health - */ - if (iHealth + g_iHealthBonus >= iMaxHealth) - { - - /** - Raise them to max health if the current health + bonus would go above it - */ - SetEntityHealth(client, iMaxHealth); - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "ToMaxHealth", LANG_SERVER); - } - else - { - - /** - Give them the instant health bonus - */ - SetEntityHealth(client, iHealth + g_iHealthBonus); - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "HealthBonus", LANG_SERVER); - } - - /** - Increase the count - */ - g_aPlayers[client][iHealthCount] += 1; - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_Teaser(client, args) -{ - - /** - Make sure we are enabled - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Check to see if we have command arguments. - */ - new iCmdArgs = GetCmdArgs(); - if (iCmdArgs == 0) - { - - /** - We don't so display the player menu. - */ - new Handle:hPlayerMenu = BuildPlayerMenu(); - DisplayMenu(hPlayerMenu, client, MENU_TIME_FOREVER); - return Plugin_Handled; - } - - /** - We have some arguments, see if we can find the player - */ - decl String:sPlayer[64]; - GetCmdArg(1, sPlayer, sizeof(sPlayer)); - new iTarget = FindTarget(client, sPlayer, true, true); - if (iTarget == -1 || !IsClientInGame(iTarget)) - { - - /** - We don't know who this is, so display the player menu. - */ - new Handle:hPlayerMenu = BuildPlayerMenu(); - DisplayMenu(hPlayerMenu, client, MENU_TIME_FOREVER); - } - else - { - /** - We found the player, see if we are supposed to turn it on or off. - */ - if (iCmdArgs >= 2) - { - decl String:sOn[3]; - GetCmdArg(2, sOn, sizeof(sOn)); - if (StringToInt(sOn)) - { - - /** - Turn temp benefits on. - */ - g_aPlayers[iTarget][bIsDonator] = true; - } - else - { - - /** - Turn temp benefits on. - */ - g_aPlayers[iTarget][bIsDonator] = false; - } - } - else - { - - /** - We don't know what to do, so just turn it on. - */ - g_aPlayers[iTarget][bIsDonator] = true; - } - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_Say(client, args) -{ - - /** - Make sure we are enabled. - */ - if (client == 0 || IsChatTrigger() || !g_bIsChatColorsEnabled || !g_bIsEnabled) - { - return Plugin_Continue; - } - - /** - Check the client to see if they are a donator. - */ - if (g_aPlayers[client][bIsDonator]) - { - - /** - The client is, so get the chat message and strip it down. - */ - decl String:sArg[CHAT_MAX_MESSAGE_LENGTH], - String:sChatMsg[CHAT_MAX_MESSAGE_LENGTH]; - new bool:bAlive = IsPlayerAlive(client); - GetCmdArgString(sArg, sizeof(sArg)); - StripQuotes(sArg); - TrimString(sArg); - new startidx; - if (sArg[strlen(sArg)-1] == '"') - { - sArg[strlen(sArg)-1] = '\0'; - startidx = 1; - } - - /** - Bug out if they are using the admin chat symbol (admin chat). - */ - if (sArg[startidx] == CHAT_SYMBOL) - { - return Plugin_Continue; - } - - /** - Format the message. - */ - FormatMessage(client, 0, bAlive, sChatMsg, sArg); - - /** - Send the message. - */ - SayText2(0, client, sChatMsg); - - /** - We are done, bug out, and stop the original chat message. - */ - return Plugin_Stop; - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Hacks_TakeDamageHook(client, attacker, inflictor, Float:damage, &Float:multiplier, damagetype) -{ - - /** - Make sure we are enabled and the client is a donator. - */ - if (g_bIsEnabled && g_bIsNoFallDmgEnabled && g_aPlayers[client][bIsDonator]) - { - - /** - Check for fall damage. - */ - if (damagetype & DMG_FALL) - { - - /** - Cancel the fall damage and bug out. - */ - multiplier *= 0.0; - return Plugin_Changed; - } - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Hacks_PreThinkHook(client) -{ - - /** - Make sure we are enabled and the client is a donator. - */ - if (!g_bIsEnabled || !g_bIsFastHeayEnabled || !g_aPlayers[client][bIsDonator]) - { - return Plugin_Continue; - } - - /** - Check the players class. We are looking for the heavy. - */ - new TFClassType:PlayerClass = TF2_GetPlayerClass(client); - if (PlayerClass == TFClass_Heavy) - { - - /** - We have a heavy, lets check the weapon. - */ - decl String:sWeaponCurrent[64]; - GetClientWeapon(client, sWeaponCurrent, sizeof(sWeaponCurrent)); - if (StrEqual(sWeaponCurrent, "tf_weapon_minigun", false)) - { - - /** - We have a minigun, check the heavies current weapon state to see if it's spinning. - */ - new iWeapon = GetPlayerWeaponSlot(client, 0); - new iWeaponState = GetEntProp(iWeapon, Prop_Send, "m_iWeaponState"); - if (iWeaponState > 0) - { - - /** - He is spinning, so lets change the heavies speed. - */ - new Float:fMaxSpeed = FloatMul(g_fHeavyMultiplier, float(g_fClassMaxSpeed[PlayerClass])); - SetEntPropFloat(client, Prop_Send, "m_flMaxspeed", fMaxSpeed); - } - } - } - - /** - We are done, bug out. - */ - // use Plugin_Continue (other options are ignored on PreThink hook) - return Plugin_Continue; -} - -public Action:HookPlayerConnect(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (!g_bIsEnabled || !g_bIsJoinPubMsgEnabled || !dontBroadcast) - { - return Plugin_Continue; - } - - /** - Get our event variables and check the client. - */ - new iUserId = GetEventInt(event,"userid"); - new iClient = GetClientOfUserId(iUserId); - if (iClient != 0) - { - - /** - Get the info on the client and format the message. - */ - decl String:sClientName[255], - String:sAuthID[255], - String:sMsg[1024]; - - GetEventString(event, "name", sClientName, sizeof(sClientName)); - GetClientAuthString(iClient, sAuthID, sizeof(sAuthID)); - Format(sMsg, sizeof(sMsg), "%T", "PublicJoinMessage", LANG_SERVER, sClientName); - - /** - Print the message to the clients and do the normal functions. - */ - for (new i = 1; i <= MaxClients; i++) - { - if(IsClientConnected(i) && IsClientInGame(i)) - { - PrintToChat(i,"\x01\x05%s", sMsg); - PrintToConsole(i,"%s has connected.", sClientName); - } - } - LogToGame("\"%s<%d><%s><>\" entered the game", sClientName, iUserId, sAuthID); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public HookPlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled && g_bIsUberChargeEnabled) - { - - /** - Get the event variables and check the class for medic - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - if (TF2_GetPlayerClass(iClient) == TFClass_Medic) - { - - /** - Start a timer to get the medic the uber boost - */ - CreateTimer(0.25, Timer_PlayerUberDelay, iClient, TIMER_FLAG_NO_MAPCHANGE); - } - } -} - -public HookPlayerClass(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled && g_bIsUberChargeEnabled) - { - - /** - Get the event variables and check the class for medic - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - if (TF2_GetPlayerClass(iClient) == TFClass_Medic) - { - - /** - Start a timer to get the medic the uber boost - */ - CreateTimer(0.25, Timer_PlayerUberDelay, iClient, TIMER_FLAG_NO_MAPCHANGE); - } - } -} - -public HookPlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled || g_bIsSwapTeamEnabled) - { - - /** - Get the event variables - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - new String:sWeapon[256]; - GetEventString(event, "weapon", sWeapon, sizeof(sWeapon)); - - /** - Bug out if world killed him. Means he changed team or something - */ - if (StrEqual(sWeapon, "world", false)) - { - g_aPlayers[iClient][bQueue] = false; - return; - } - - /** - If he is queued up, swap him - */ - if (g_aPlayers[iClient][bQueue]) - { - SM_MovePlayer(iClient, g_aPlayers[iClient][iNewTeam]); - } - } -} - -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled || g_bIsSwapTeamEnabled) - { - - /** - Get the event variables - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - - /** - If he is queued up, clear the status - */ - if (g_aPlayers[iClient][bQueue]) - { - g_aPlayers[iClient][bQueue] = false; - } - } -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set our variables. - */ - g_bRoundEnd = false; - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled && g_bIsImmuntyEnabled) - { - - /** - Get rid of their immunity. - */ - ProcessRoundEndImmunity(false); - } -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set our variables. - */ - g_bRoundEnd = true; - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled && g_bIsImmuntyEnabled) - { - - /** - Give them their immunity. - */ - ProcessRoundEndImmunity(true); - } -} - -public Action:Timer_DonatorJoined(Handle:timer, any:client) -{ - - /** - Make sure sounds are enabled. - */ - if (g_bIsEnabled && g_bIsJoinSoundEnabled) - { - EmitSoundToClient(client, g_sSoundFile); - } - - /** - Make sure private messages are enabled. - */ - if (g_bIsJoinPrivMsgEnabled) - { - - /** - Send messages to the client. - */ - decl String:sMsg[1024]; - Format(sMsg, sizeof(sMsg), "%T", "PrivateJoinMessage", LANG_SERVER); - PrintToChat(client,"\x01\x05%s", sMsg); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Timer_PlayerUberDelay(Handle:timer, any:client) -{ - - /** - Make sure the client is still in game. - */ - if (IsClientInGame(client)) - { - - /** - Make sure the client is still a medic. - */ - if (TF2_GetPlayerClass(client) == TFClass_Medic) - { - - /** - Get the medgun weapon index - */ - new iIndex = GetPlayerWeaponSlot(client, 1); - if (iIndex > 0) - { - - /** - Set the uber level with the bonus. - */ - SetEntPropFloat(iIndex, Prop_Send, "m_flChargeLevel", g_fUberLevel); - } - } - } -} - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (convar == sdb_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsEnabled = false; - } - else - { - g_bIsEnabled = true; - } - } - else if (convar == sdb_donationflag) - { - Format(g_sCharDonatorFlag, sizeof(g_sCharDonatorFlag), "%s", newValue); - } - else if (convar == sdb_soundfile) - { - Format(g_sSoundFile, sizeof(g_sSoundFile), "%s", newValue); - } - else if (convar == sdb_joinsound_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsJoinSoundEnabled = false; - } - else - { - g_bIsJoinSoundEnabled = true; - } - } - else if (convar == sdb_joinpubmsg_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsJoinPubMsgEnabled = false; - } - else - { - g_bIsJoinPubMsgEnabled = true; - } - } - else if (convar == sdb_joinprivmsg_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsJoinPrivMsgEnabled = false; - } - else - { - g_bIsJoinPrivMsgEnabled = true; - } - } - else if (convar == sdb_chatcolors_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsChatColorsEnabled = false; - } - else - { - g_bIsChatColorsEnabled = true; - } - } - else if (convar == sdb_immunity_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsImmuntyEnabled = false; - } - else - { - g_bIsImmuntyEnabled = true; - } - } - else if (convar == sdb_ubercharge_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsUberChargeEnabled = false; - } - else - { - g_bIsUberChargeEnabled = true; - } - } - else if (convar == sdb_givehealth_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsGiveHealthEnabled = false; - } - else - { - g_bIsGiveHealthEnabled = true; - } - } - else if (convar == sdb_nofalldmg_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsNoFallDmgEnabled = false; - } - else - { - g_bIsNoFallDmgEnabled = true; - } - } - else if (convar == sdb_fastheavy_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsFastHeayEnabled = false; - } - else - { - g_bIsFastHeayEnabled = true; - } - } - else if (convar == sdb_swapteam_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsSwapTeamEnabled = false; - } - else - { - g_bIsSwapTeamEnabled = true; - } - } - else if (convar == sdb_chatcolor) - { - Format(g_sChatColor, sizeof(g_sChatColor), "%s", newValue); - } - else if (convar == sdb_uberlevel) - { - g_fUberLevel = StringToFloat(newValue); - } - else if (convar == sdb_healthcount) - { - g_iHealthCount = StringToInt(newValue); - } - else if (convar == sdb_healthbonus) - { - g_iHealthBonus = StringToInt(newValue); - } - else if (convar == sdb_heavymultiplier) - { - g_fHeavyMultiplier = StringToFloat(newValue); - } -} - -stock LoadUpVariables() -{ - g_bIsEnabled = GetConVarBool(sdb_enabled); - g_bIsJoinSoundEnabled = GetConVarBool(sdb_enabled); - g_bIsJoinPubMsgEnabled = GetConVarBool(sdb_enabled); - g_bIsJoinPrivMsgEnabled = GetConVarBool(sdb_enabled); - g_bIsChatColorsEnabled = GetConVarBool(sdb_enabled); - g_bIsImmuntyEnabled = GetConVarBool(sdb_enabled); - g_bIsUberChargeEnabled = GetConVarBool(sdb_enabled); - g_bIsGiveHealthEnabled = GetConVarBool(sdb_enabled); - g_bIsNoFallDmgEnabled = GetConVarBool(sdb_enabled); - g_bIsFastHeayEnabled = GetConVarBool(sdb_enabled); - g_bIsSwapTeamEnabled = GetConVarBool(sdb_enabled); - GetConVarString(sdb_donationflag, g_sCharDonatorFlag, sizeof(g_sCharDonatorFlag)); - GetConVarString(sdb_soundfile, g_sSoundFile, sizeof(g_sSoundFile)); - GetConVarString(sdb_chatcolor, g_sChatColor, sizeof(g_sChatColor)); - g_bRoundEnd = false; - g_iHealthBonus = GetConVarInt(sdb_healthbonus); - g_iHealthCount = GetConVarInt(sdb_healthcount); - g_fHeavyMultiplier = GetConVarFloat(sdb_heavymultiplier); - g_fUberLevel = GetConVarFloat(sdb_uberlevel); -} - -stock PrepSoundFile() -{ - decl String:buffer[PLATFORM_MAX_PATH]; - PrecacheSound(g_sSoundFile, true); - Format(buffer, sizeof(buffer), "sound/%s", g_sSoundFile); - AddFileToDownloadsTable(buffer); -} - -stock CleanUpPlayer(client) -{ - g_aPlayers[client][bIsDonator] = false; - g_aPlayers[client][bQueue] = false; - g_aPlayers[client][bImmune] = false; - g_aPlayers[client][iNewTeam] = 0; - g_aPlayers[client][iHealthCount] = 0; -} - -stock ProcessRoundEndImmunity(bool:give) -{ - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][bIsDonator]) - { - if (give) - { - SetEntProp(i, Prop_Data, "m_takedamage", 0, 1); - g_aPlayers[i][bImmune] = true; - } - else - { - SetEntProp(i, Prop_Data, "m_takedamage", 2, 1); - g_aPlayers[i][bImmune] = false; - } - } - } -} - -stock FormatMessage(iClient, iTeam, bool:bAlive, String:sChatMsg[], const Sting:sMessage[]) -{ - decl String:sDead[10], - String:sTeam[10], - String:sClientName[64]; - GetClientName(iClient, sClientName, sizeof(sClientName)); - if (iTeam != 0) - Format(sTeam, sizeof(sTeam), "(TEAM) "); - else - Format(sTeam, sizeof(sTeam), ""); - if (bAlive) - Format(sDead, sizeof(sDead), ""); - else - Format(sDead, sizeof(sDead), "*DEAD* "); - if (StrContains(g_sChatColor, "light", false) == -1) - Format(sChatMsg, CHAT_MAX_MESSAGE_LENGTH, "\x01%s%s\x03%s \x01: \x05%s", sDead, sTeam, sClientName, sMessage); - else - Format(sChatMsg, CHAT_MAX_MESSAGE_LENGTH, "\x01%s%s\x03%s \x01: \x04%s", sDead, sTeam, sClientName, sMessage); -} - -stock SayText2(target, author, const String:message[]) -{ - new Handle:hBf; - if (target == 0) - hBf = StartMessageAll("SayText2"); - else - hBf = StartMessageOne("SayText2", target); - if (hBf != INVALID_HANDLE) - { - BfWriteByte(hBf, author); - BfWriteByte(hBf, true); - BfWriteString(hBf, message); - EndMessage(); - } -} - -stock ProcessAdmins() -{ - for (new i = 1; i <= MaxClients; i++) - { - if (SM_IsValidAdmin(i, g_sCharDonatorFlag)) - { - g_aPlayers[i][bDonator] = true; - } - else - { - g_aPlayers[i][bDonator] = false; - } - } -} - -stock ProcessLate() -{ - if (g_bIsEnabled) - { - ProcessAdmins(); - PrepSoundFile(); - if (g_bRoundEnd && g_bIsImmuntyEnabled) - { - ProcessRoundEndImmunity(true); - } - if (!g_bIsImmuntyEnabled) - { - ProcessRoundEndImmunity(false); - } - } - else - { - ProcessRoundEndImmunity(false); - } -} - -public Menu_SwapMode(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, 64); - if (StringToInt(sSelection)) - g_aPlayers[param1][bQueue] = false; - else - g_aPlayers[param1][bQueue] = true; - if (!g_aPlayers[param1][bQueue]) - SM_MovePlayer(param1, g_aPlayers[param1][iNewTeam]); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -public Menu_SelectPlayer(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[256]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - new iTarget = GetClientOfUserId(StringToInt(sSelection)); - if (g_aPlayers[iTarget][bIsDonator]) - g_aPlayers[iTarget][bIsDonator] = false; - else - g_aPlayers[iTarget][bIsDonator] = true; - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -stock Handle:BuildSwapModeMenu() -{ - new Handle:menu = CreateMenu(Menu_SwapMode); - SetMenuTitle(menu, "Select When to Swap:"); - AddMenuItem(menu, "0", "Instantly (Kills)"); - AddMenuItem(menu, "1", "Queue on next death"); - SetMenuExitBackButton(menu, false); - return menu; -} - -stock Handle:BuildPlayerMenu() -{ - new Handle:menu = CreateMenu(Menu_SelectPlayer); - AddTargetsToMenu(menu, 0, true, false); - SetMenuTitle(menu, "Select A Player:"); - SetMenuExitBackButton(menu, true); - return menu; -} - -public Action:Command_TEST(client, args) -{ - -} \ No newline at end of file diff --git a/Simple AllTalk Manager/addons/sourcemod/scripting/simple-messagesuppression.sp b/Simple AllTalk Manager/addons/sourcemod/scripting/simple-messagesuppression.sp deleted file mode 100644 index f7725a4..0000000 --- a/Simple AllTalk Manager/addons/sourcemod/scripting/simple-messagesuppression.sp +++ /dev/null @@ -1,227 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Message Suppression -Description: - Blocks Specific Message Outputs -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include -#include - -#define SUPPRESS_VERSION "1.1.$Rev$" - -public Plugin:myinfo = -{ - name = "Simple Message Suppression", - author = "FlyingMongoose, psychonic", - description = "Blocks Specific Message Outputs", - version = SUPPRESS_VERSION, - url = "http://www.simple-plugins.com/" -} - -new Handle:cvarBlockSpectateMessage; -new Handle:cvarBlockDisconnectMessage; -new Handle:cvarBlockConnectMessage; -new Handle:cvarAdminShowMessages; -new iSpecTeam = 1; - - -public OnPluginStart() -{ - CreateConVar("suppress_version", SUPPRESS_VERSION, _, FCVAR_PLUGIN|FCVAR_NOTIFY|FCVAR_REPLICATED|FCVAR_SPONLY|FCVAR_DONTRECORD); - cvarBlockSpectateMessage = CreateConVar("sm_blockspectatemessage", "1", "If enabled it blocks the join team message if an administrator joins spectator", FCVAR_PLUGIN, true, 0.0, true, 1.0); - cvarBlockDisconnectMessage = CreateConVar("sm_blockdisconnectmessage", "1", "Blocks the disconnect message", FCVAR_PLUGIN, true, 0.0, true, 1.0); - cvarBlockConnectMessage = CreateConVar("sm_blockconnectmessage", "1", "If enabled it blocks the player connection message.", FCVAR_PLUGIN, true, 0.0, true, 1.0); - cvarAdminShowMessages = CreateConVar("sm_adminshowmessages", "1", "Shows disconnect/connect/team join messages for admins only (if disconnect message is set to be blocked)", FCVAR_PLUGIN, true, 0.0, true, 1.0); - HookEvent("player_team", ev_PlayerTeam, EventHookMode_Pre); - HookEvent("player_disconnect", ev_PlayerDisconnect, EventHookMode_Pre); - HookEvent("player_connect", ev_PlayerConnect, EventHookMode_Pre); - - new String:game_folder[64]; - GetGameFolderName(game_folder, sizeof(game_folder)) - - if (StrContains(game_folder, "insurgency", false) != -1) - { - iSpecTeam = 3; - } - else - { - new String:game_description[64]; - GetGameDescription(game_description, sizeof(game_description), true); - if (StrContains(game_description, "Insurgency", false) != -1) - { - iSpecTeam = 3; - } - } - - AutoExecConfig(true, "suppressmessage", "sourcemod"); -} - -public Action:ev_PlayerTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (GetConVarBool(cvarBlockSpectateMessage)) - { - if (!dontBroadcast && !GetEventBool(event, "silent")) - { - new iUserId = GetEventInt(event, "userid"); - new iClient = GetClientOfUserId(iUserId); - new iTeam = GetEventInt(event, "team"); - - if (iTeam == iSpecTeam && GetAdminFlag(GetUserAdmin(iClient), Admin_Kick)) - { - new iOldTeam = GetEventInt(event, "oldteam"); - new bool:bDisconnect = GetEventBool(event, "disconnect"); - new bool:bAutoteam = GetEventBool(event, "autoteam"); - decl String:strName[50]; - GetEventString(event, "name", strName, sizeof(strName)); - - if (iClient != 0) - { - if (GetConVarInt(cvarAdminShowMessages) == 1) - { - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i) && GetUserAdmin(i) != INVALID_ADMIN_ID) - { - PrintToChat(i,"%N joined team Spectator.", iClient); - PrintToConsole(i,"%N joined team Spectator.", iClient); - } - } - } - } - - new Handle:hEvent = CreateEvent("player_team"); - SetEventInt(hEvent, "userid", iUserId); - SetEventInt(hEvent, "team", iTeam); - SetEventInt(hEvent, "oldteam", iOldTeam); - SetEventBool(hEvent, "disconnect", bDisconnect); - SetEventBool(hEvent, "autoteam", bAutoteam); - SetEventBool(hEvent, "silent", true); - SetEventString(hEvent, "name", strName); - - FireEvent(hEvent, true); - - return Plugin_Handled; - } - } - } - return Plugin_Continue; -} -public Action:ev_PlayerConnect(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (GetConVarBool(cvarBlockConnectMessage)) - { - if (!dontBroadcast) - { - decl String:strName[50]; - GetEventString(event, "name", strName, sizeof(strName)); - new iIndex = GetEventInt(event, "index"); - new iUserId = GetEventInt(event, "userid"); - new iClient = GetClientOfUserId(iUserId); - decl String:strNetworkId[50]; - GetEventString(event, "networkid", strNetworkId, sizeof(strNetworkId)); - decl String:strAddress[50]; - GetEventString(event, "address", strAddress, sizeof(strAddress)); - - if (iClient != 0) - { - if (GetConVarInt(cvarAdminShowMessages) == 1) - { - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i) && GetUserAdmin(i) != INVALID_ADMIN_ID) - { - PrintToChat(i,"%N has connected.", iClient); - PrintToConsole(i,"%N has connected.", iClient); - } - } - } - } - - new Handle:hEvent = CreateEvent("player_connect"); - SetEventString(hEvent, "name", strName); - SetEventInt(hEvent, "index", iIndex); - SetEventInt(hEvent, "userid", iUserId); - SetEventString(hEvent, "networkid", strNetworkId); - SetEventString(hEvent, "address", strAddress); - - FireEvent(hEvent, true); - - return Plugin_Handled; - } - } - return Plugin_Continue; -} -public Action:ev_PlayerDisconnect(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (GetConVarBool(cvarBlockDisconnectMessage)) - { - if (!dontBroadcast) - { - new iUserId = GetEventInt(event, "userid"); - new iClient = GetClientOfUserId(iUserId); - decl String:strReason[50]; - GetEventString(event, "reason", strReason, sizeof(strReason)); - decl String:strName[50]; - GetEventString(event, "name", strName, sizeof(strName)); - decl String:strNetworkId[50]; - GetEventString(event, "networkid", strNetworkId, sizeof(strNetworkId)); - - if (iClient != 0) - { - if (GetConVarInt(cvarAdminShowMessages) == 1) - { - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i) && GetUserAdmin(i) != INVALID_ADMIN_ID) - { - PrintToChat(i, "%N has left the server.", iClient); - PrintToConsole(i, "Dropped %N from server (Disconnect by user.)", iClient); - } - } - } - } - - new Handle:hEvent = CreateEvent("player_disconnect"); - SetEventInt(hEvent, "userid", iUserId); - SetEventString(hEvent, "reason", strReason); - SetEventString(hEvent, "name", strName); - SetEventString(hEvent, "networkid", strNetworkId); - - FireEvent(hEvent, true); - - return Plugin_Handled; - } - } - - return Plugin_Continue; -} \ No newline at end of file diff --git a/Simple AllTalk Manager/addons/sourcemod/scripting/simple-plugins.sp b/Simple AllTalk Manager/addons/sourcemod/scripting/simple-plugins.sp deleted file mode 100644 index 4462b41..0000000 --- a/Simple AllTalk Manager/addons/sourcemod/scripting/simple-plugins.sp +++ /dev/null @@ -1,785 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Plugins -Description: - Core plugin for Simple Plugins project -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#define CORE_PLUGIN_VERSION "1.1.$Rev$" - -#include - -enum e_PlayerInfo -{ - Handle:hForcedTeamPlugin = INVALID_HANDLE, - iForcedTeam = 0, - iBuddy = 0, - bool:bBuddyLocked = false -}; - -new Handle:g_fwdPlayerMoved; -new g_aPlayers[MAXPLAYERS + 1][e_PlayerInfo]; -new bool:g_bTeamsSwitched = false; - -/** -Setting our plugin information. -*/ -public Plugin:myinfo = -{ - name = "Simple Plugins Core Plugin", - author = "Simple Plugins", - description = "Core plugin for Simple Plugins", - version = CORE_PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -public bool:AskPluginLoad(Handle:myself, bool:late, String:error[], err_max) -{ - - /** - Register natives for other plugins - */ - CreateNative("SM_MovePlayer", Native_SM_MovePlayer); - CreateNative("SM_SetForcedTeam", Native_SM_SetForcedTeam); - CreateNative("SM_GetForcedTeam", Native_SM_GetForcedTeam); - CreateNative("SM_ClearForcedTeam", Native_SM_ClearForcedTeam); - CreateNative("SM_GetForcedPlayer", Native_SM_GetForcedPlayer); - CreateNative("SM_AssignBuddy", Native_SM_AssignBuddy); - CreateNative("SM_GetClientBuddy", Native_SM_GetClientBuddy); - CreateNative("SM_LockBuddy", Native_SM_LockBuddy); - CreateNative("SM_IsBuddyLocked", Native_SM_IsBuddyLocked); - CreateNative("SM_ClearBuddy", Native_SM_ClearBuddy); - CreateNative("SM_IsValidAdmin", Native_SM_IsValidAdmin); - CreateNative("SM_IsValidTeam", Native_SM_IsValidTeam); - RegPluginLibrary("simpleplugins"); - return true; -} - -public OnPluginStart() -{ - - CreateConVar("ssm_core_pl_ver", CORE_PLUGIN_VERSION, "Simple SourceMod Plugins Core Plugin Version", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - CreateConVar("ssm_core_inc_ver", CORE_INC_VERSION, "Simple SourceMod Plugins Core Include Version", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook some events to control forced players and check extensions - */ - decl String:sExtError[256]; - LogAction(0, -1, "[SSM] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Pre); - switch (g_CurrentMod) - { - case GameType_CSS: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - new iExtStatus = GetExtensionFileStatus("game.cstrike.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SSM] Required extension was not found."); - LogAction(0, -1, "[SSM] Plugin FAILED TO LOAD."); - SetFailState("Required extension was not found."); - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SSM] Required extension is loaded with errors."); - LogAction(0, -1, "[SSM] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SSM] Plugin FAILED TO LOAD."); - SetFailState("Required extension is loaded with errors."); - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SSM] Required extension is loaded."); - } - } - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_PostNoCopy); - HookUserMessage(GetUserMessageId("TextMsg"), UserMessageHook_Class, true); - new iExtStatus = GetExtensionFileStatus("game.tf2.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SSM] Required extension was not found."); - LogAction(0, -1, "[SSM] Plugin FAILED TO LOAD."); - SetFailState("Required extension was not found."); - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SSM] Required extension is loaded with errors."); - LogAction(0, -1, "[SSM] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SSM] Plugin FAILED TO LOAD."); - SetFailState("Required extension is loaded with errors."); - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SSM] Required extension is loaded."); - } - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_PostNoCopy); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - - /** - Load common translations - */ - LoadTranslations ("common.phrases"); - - /** - Create the global forward - */ - g_fwdPlayerMoved = CreateGlobalForward("SM_OnPlayerMoved", ET_Event, Param_Cell, Param_Cell, Param_Cell); -} - -public OnClientDisconnect(client) -{ - - /** - Cleanup clients/players buddy list - */ - if (!IsFakeClient(client)) - { - SM_ClearBuddy(client, true); - SM_LockBuddy(client, false); - } - SM_ClearForcedTeam(client); -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - See if the teams have been switched - */ - if (g_bTeamsSwitched) - { - - /** - Switch the teams the players are forced to - */ - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][iForcedTeam] != 0) - { - if (g_aPlayers[i][iForcedTeam] == g_aCurrentTeams[Team1]) - { - g_aPlayers[i][iForcedTeam] = g_aCurrentTeams[Team2]; - } - else - { - g_aPlayers[i][iForcedTeam] = g_aCurrentTeams[Team1]; - } - } - } - } -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - g_bTeamsSwitched = false; -} - -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get our event variables - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - new iTeam = GetEventInt(event, "team"); - - /** - See if the player is on the wrong team - */ - if (g_aPlayers[iClient][iForcedTeam] != 0 && g_aPlayers[iClient][iForcedTeam] != iTeam) - { - - /** - Move the player back to the forced team - */ - CreateTimer(1.0, Timer_ForcePlayerMove, iClient, TIMER_FLAG_NO_MAPCHANGE); - - /** - If the event was going to be broadcasted, we refire it so it is not broadcasted and stop this one - */ - if (!dontBroadcast) - { - new Handle:hEvent = CreateEvent("player_team"); - SetEventInt(hEvent, "userid", GetEventInt(event, "userid")); - SetEventInt(hEvent, "team", GetEventInt(event, "team")); - SetEventInt(hEvent, "oldteam", GetEventInt(event, "oldteam")); - SetEventBool(hEvent, "disconnect", GetEventBool(event, "disconnect")); - - if (g_CurrentMod == GameType_DOD || g_CurrentMod == GameType_L4D || g_CurrentMod == GameType_TF) - { - new String:sClientName[MAX_NAME_LENGTH + 1]; - GetClientName(client, sClientName, sizeof(sClientName)); - SetEventBool(hEvent, "autoteam", GetEventBool(event, "autoteam")); - SetEventBool(hEvent, "silent", true); - SetEventString(hEvent, "name", sClientName); - FireEvent(hEvent, true); - } - else - { - FireEvent(hEvent, true); - } - return Plugin_Handled; - } - } - return Plugin_Continue; -} - -public Action:UserMessageHook_Class(UserMsg:msg_id, Handle:bf, const players[], playersNum, bool:reliable, bool:init) -{ - new String:sMessage[120]; - BfReadString(bf, sMessage, sizeof(sMessage), true); - if (StrContains(sMessage, "#TF_TeamsSwitched", false) != -1) - { - g_bTeamsSwitched = true; - } - return Plugin_Continue; -} - -public Native_SM_MovePlayer(Handle:plugin, numParams) -{ - - /** - Get and check the client and team - */ - new iClient = GetNativeCell(1); - new iTeam = GetNativeCell(2); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (iTeam != g_aCurrentTeams[Spectator] && iTeam != g_aCurrentTeams[Team1] && iTeam != g_aCurrentTeams[Team2]) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid team %d", iTeam); - } - - MovePlayer(iClient, iTeam); - if (!IsClientObserver(iClient)) - { - RespawnPlayer(iClient); - } - - new fResult; - - Call_StartForward(g_fwdPlayerMoved); - Call_PushCell(plugin); - Call_PushCell(iClient); - Call_PushCell(iTeam); - Call_Finish(fResult); - - if (fResult != SP_ERROR_NONE) - { - return ThrowNativeError(fResult, "Forward failed"); - } - - return fResult; -} - -public Native_SM_SetForcedTeam(Handle:plugin, numParams) -{ - - /** - Get and check the client and team - */ - new iClient = GetNativeCell(1); - new iTeam = GetNativeCell(2); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (iTeam != g_aCurrentTeams[Spectator] && iTeam != g_aCurrentTeams[Team1] && iTeam != g_aCurrentTeams[Team2] && iTeam != g_aCurrentTeams[Unknown]) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid team %d", iTeam); - } - - new bool:bOverRide = GetNativeCell(3) ? true : false; - - if (!bOverRide && g_aPlayers[iClient][hForcedTeamPlugin] != INVALID_HANDLE && plugin != g_aPlayers[iClient][hForcedTeamPlugin]) - { - return false; - } - - g_aPlayers[iClient][hForcedTeamPlugin] = plugin; - g_aPlayers[iClient][iForcedTeam] = iTeam; - return true; -} - -public Native_SM_GetForcedTeam(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - - /** - Get and set the plugin if they want it - */ - new Handle:hPlugin = GetNativeCell(2); - if (hPlugin != INVALID_HANDLE) - { - SetNativeCellRef(2, g_aPlayers[iClient][hForcedTeamPlugin]); - } - - /** - Return the forced team, this could be 0 - */ - return g_aPlayers[iClient][iForcedTeam]; -} - -public Native_SM_ClearForcedTeam(Handle:plugin, numParams) -{ - - /** - Get and check the client and team - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - - g_aPlayers[iClient][hForcedTeamPlugin] = INVALID_HANDLE; - g_aPlayers[iClient][iForcedTeam] = 0; - - return true; -} - -public Native_SM_GetForcedPlayer(Handle:plugin, numParams) -{ - - /** - Get and check the team - */ - new iTeam = GetNativeCell(1); - if (iTeam != g_aCurrentTeams[Spectator] && iTeam != g_aCurrentTeams[Team1] && iTeam != g_aCurrentTeams[Team2]) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid team %d", iTeam); - } - - /** - Start a loop to check for a player on the wrong team - Also make sure the plugin that set the forced team is the plugin that asked - */ - new iPlayer = 0; - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientInGame(i) - && GetClientTeam(i) != g_aPlayers[i][iForcedTeam] - && g_aPlayers[i][iForcedTeam] == iTeam - && g_aPlayers[i][hForcedTeamPlugin] == plugin) - { - iPlayer = i; - break; - } - } - - /** - Return the player we found, this could be 0 - */ - return iPlayer; -} - -public Native_SM_AssignBuddy(Handle:plugin, numParams) -{ - - /** - Get and check the client and player - */ - new iClient = GetNativeCell(1); - new iPlayer = GetNativeCell(2); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (iPlayer < 0 || iPlayer > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid player index (%d)", iPlayer); - } - if (!IsClientConnected(iPlayer)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Player %d is not connected", iPlayer); - } - if (!IsClientInGame(iPlayer)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Player %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Bots are not supported"); - } - - /** - See if we can override his setting - */ - new bool:bOverRide = GetNativeCell(3) ? true : false; - if (!bOverRide) - { - - /** - We can't override, so check if they are locked - */ - if (g_aPlayers[iClient][bBuddyLocked] || g_aPlayers[iPlayer][bBuddyLocked]) - { - - /** - We detected at least 1 lock, so we bug out - */ - return false; - } - } - - /** - Ready to set the buddies - */ - g_aPlayers[iClient][iBuddy] = iPlayer; - g_aPlayers[iPlayer][iBuddy] = iClient; - return true; -} - -public Native_SM_GetClientBuddy(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Bots are not supported"); - } - - /** - Return the players buddy, this could be 0 - */ - return g_aPlayers[iClient][iBuddy]; -} - -public Native_SM_LockBuddy(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - new bool:bSetting = GetNativeCell(2) ? true : false; - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Bots are not supported"); - } - - g_aPlayers[iClient][bBuddyLocked] = bSetting; - return true; -} - -public Native_SM_IsBuddyLocked(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Bots are not supported"); - } - - return g_aPlayers[iClient][bBuddyLocked]; -} - -public Native_SM_ClearBuddy(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Client (%d) is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Bots are not supported"); - } - - /** - Get the clients buddy and see if we can override his setting - */ - new bool:bOverRide = GetNativeCell(2) ? true : false; - new iPlayer = g_aPlayers[iClient][iBuddy]; - - /** - There is no buddy, we don't care about anything else so bug out - */ - if (iPlayer == 0) - { - return true; - } - - /** - We determined he had a buddy, check the override setting - */ - if (!bOverRide) - { - - /** - We can't override, so check if they are locked - */ - if (g_aPlayers[iClient][bBuddyLocked] || g_aPlayers[iPlayer][bBuddyLocked]) - { - - /** - We detected at least 1 lock, so we bug out - */ - return false; - } - } - - /** - Ready to clear the buddies - */ - g_aPlayers[iClient][iBuddy] = 0; - g_aPlayers[iPlayer][iBuddy] = 0; - return true; -} - -public Native_SM_IsValidTeam(Handle:plugin, numParams) -{ - - /** - Get the team - */ - new iTeam = GetNativeCell(1); - - /** - Check the team - */ - if (iTeam == g_aCurrentTeams[Spectator] || iTeam == g_aCurrentTeams[Team1] || iTeam == g_aCurrentTeams[Team2]) - { - return true; - } - return false; -} - -public Native_SM_IsValidAdmin(Handle:plugin, numParams) -{ - /** - Get the client and flags - */ - new iClient = GetNativeCell(1); - decl String:sFlags[15]; - GetNativeString(2, sFlags, sizeof(sFlags)); - new ibFlags = ReadFlagString(sFlags); - - /** - Check the flags - */ - if ((GetUserFlagBits(iClient) & ibFlags) == ibFlags) - { - return true; - } - if (GetUserFlagBits(iClient) & ADMFLAG_ROOT) - { - return true; - } - return false; -} - -public Action:Timer_ForcePlayerMove(Handle:timer, any:iClient) -{ - - MovePlayer(iClient, g_aPlayers[iClient][iForcedTeam]); - - if (g_aPlayers[iClient][iForcedTeam] != g_aCurrentTeams[Spectator]) - { - RespawnPlayer(iClient); - } - - PrintToChat(iClient, "\x01\x04----------------------------------"); - PrintToChat(iClient, "\x01\x04You have been forced to this team."); - PrintToChat(iClient, "\x01\x04----------------------------------"); - - return Plugin_Handled; -} - -stock MovePlayer(iClient, iTeam) -{ - - /** - Change the client's team based on the mod - */ - switch (g_CurrentMod) - { - case GameType_CSS: - { - CS_SwitchTeam(iClient, iTeam); - } - default: - { - ChangeClientTeam(iClient, iTeam); - } - } -} - -stock RespawnPlayer(iClient) -{ - - /** - Respawn the client based on the mod - */ - switch (g_CurrentMod) - { - case GameType_CSS: - { - CS_RespawnPlayer(iClient); - } - case GameType_TF: - { - TF2_RespawnPlayer(iClient); - } - case GameType_INS: - { - FakeClientCommand(iClient, "kill"); - } - default: - { - // - } - } -} diff --git a/Simple AllTalk Manager/addons/sourcemod/scripting/simple-roundimmunity.sp b/Simple AllTalk Manager/addons/sourcemod/scripting/simple-roundimmunity.sp deleted file mode 100644 index 5f0bca3..0000000 --- a/Simple AllTalk Manager/addons/sourcemod/scripting/simple-roundimmunity.sp +++ /dev/null @@ -1,947 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Round Immunity -Description: - Gives admins immunity during certain rounds -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or any later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#pragma semicolon 1 -#include -#include -#undef REQUIRE_EXTENSIONS -#undef AUTOLOAD_EXTENSIONS -#include -#include -#define REQUIRE_EXTENSIONS -#define AUTOLOAD_EXTENSIONS - -#define PLUGIN_VERSION "1.1.$Rev$" -#define SPECTATOR 1 -#define TEAM_RED 2 -#define TEAM_BLUE 3 - -#define COLOR_GREEN 0 -#define COLOR_BLACK 1 -#define COLOR_RED 2 -#define COLOR_BLUE 3 -#define COLOR_TEAM 4 -#define COLOR_RAINBOW 5 -#define COLOR_NONE 6 - -#define PLAYERCOND_SLOWED (1<<0) //1 -#define PLAYERCOND_ZOOMED (1<<1) //2 -#define PLAYERCOND_DISGUISING (1<<2) //4 -#define PLAYERCOND_DISGUISED (1<<3) //8 -#define PLAYERCOND_SPYCLOAK (1<<4) //16 -#define PLAYERCOND_UBERED (1<<5) //32 -#define PLAYERCOND_TELEPORTTRAIL (1<<6) //64 -#define PLAYERCOND_TAUNT (1<<7) //128 -// (1<<8) //256 -// (1<<9) //512 -#define PLAYERCOND_TELEPORTFLASH (1<<10) //1024 -#define PLAYERCOND_KRUBER (1<<11) //2048 -// (1<<12) //4096 -// (1<<13) //8192 -#define PLAYERCOND_BONKED (1<<14) //16384 (blame Neph if it doesn't work) -#define PLAYERCOND_BONKEDORDRINKSLOWDOWN (1<<15) //32768 -#define PLAYERCOND_HEALING (1<<16) //65536 -#define PLAYERCOND_BURNING (1<<17) //131072 -#define PLAYERCOND_FULLYCHARGEDBYMEDIC (1<<18) //262144 - -enum e_Cookies -{ - bEnabled, - iColor, - iMode -}; - -enum e_ColorNames -{ - Green, - Black, - Red, - Blue -}; - -enum e_ColorValues -{ - iRed, - iGreen, - iBlue -}; - -enum e_PlayerData -{ - Handle:hGodModeTimer, - Handle:hColorTimer, - bool:bIsAdmin, - bool:bIsImmune, - iCycleColor -}; - -/** - Global convar handles - */ -new Handle:sri_charadminflag = INVALID_HANDLE; -new Handle:sri_enabled = INVALID_HANDLE; -new Handle:sri_cookie_enabled = INVALID_HANDLE; -new Handle:sri_cookie_color = INVALID_HANDLE; -new Handle:sri_cookie_mode = INVALID_HANDLE; - -/** - Player arrays - */ -new g_aPlayers[MAXPLAYERS + 1][e_PlayerData]; -new g_aClientCookies[MAXPLAYERS + 1][e_Cookies]; - -/** - Global bools - */ -new bool:g_bLoadedLate = false; -new bool:g_bIsEnabled = true; -new bool:g_bRoundEnd = false; -new bool:g_bUseDukehacks = false; -new bool:g_bUseClientprefs = false; - -/** - Global strings/integers/floats - */ -new String:g_sCharAdminFlag[32]; -new g_iColors[e_ColorNames][e_ColorValues]; -new g_iClassMaxHealth[TFClassType] = {0, 125, 125, 200, 175, 150, 300, 175, 125, 125}; - -public Plugin:myinfo = -{ - name = "Simple Round Immunity", - author = "Simple Plugins", - description = "Gives admins immunity during certain rounds", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -} - -bool:AskPluginLoad(Handle:myself, bool:late, String:error[], err_max) -{ - g_bLoadedLate = late; - return true; -} - -public OnPluginStart() -{ - - /** - Create console variables - */ - CreateConVar("sri_version", PLUGIN_VERSION, "Simple Round Immunity", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - sri_enabled = CreateConVar("sri_enabled", "1", "Enable/Disable Admin immunity during certain round."); - sri_charadminflag = CreateConVar("sri_charadminflag", "a", "Admin flag to use for immunity (only one). Must be a in char format."); - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook some events and check extensions - */ - decl String:sExtError[256]; - LogAction(0, -1, "[SRI] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_spawn", HookPlayerSpawn, EventHookMode_Post); - HookEvent("player_hurt", HookPlayerHurt, EventHookMode_Pre); - switch (g_CurrentMod) - { - case GameType_CSS: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - new iExtStatus = GetExtensionFileStatus("game.cstrike.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SRI] Required extension was not found."); - LogAction(0, -1, "[SRI] Plugin FAILED TO LOAD."); - SetFailState("Required extension was not found."); - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SRI] Required extension is loaded with errors."); - LogAction(0, -1, "[SRI] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SRI] Plugin FAILED TO LOAD."); - SetFailState("Required extension is loaded with errors."); - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SRI] Required css extension is loaded."); - } - } - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_PostNoCopy); - HookUserMessage(GetUserMessageId("TextMsg"), UserMessageHook_Class, true); - new iExtStatus = GetExtensionFileStatus("game.tf2.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SRI] Required extension was not found."); - LogAction(0, -1, "[SRI] Plugin FAILED TO LOAD."); - SetFailState("Required extension was not found."); - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SRI] Required extension is loaded with errors."); - LogAction(0, -1, "[SRI] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SRI] Plugin FAILED TO LOAD."); - SetFailState("Required extension is loaded with errors."); - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SRI] Required tf2 extension is loaded."); - } - iExtStatus = GetExtensionFileStatus("dukehacks.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SRI] Dukehacks extension was not found."); - LogAction(0, -1, "[SRI] Plugin continued to load, but that feature will not be used."); - g_bUseDukehacks = false; - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SRI] Dukehacks extension is loaded with errors."); - LogAction(0, -1, "[SRI] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SRI] Plugin continued to load, but that feature will not be used."); - g_bUseDukehacks = false; - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SRI] Dukehacks extension is loaded and will be used."); - g_bUseDukehacks = true; - dhAddClientHook(CHK_TakeDamage, Hacks_TakeDamageHook); - } - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_PostNoCopy); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - /** - Now lets check for client prefs extension - */ - new iExtStatus = GetExtensionFileStatus("clientprefs.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SRI] Client Preferences extension was not found."); - LogAction(0, -1, "[SRI] Plugin continued to load, but that feature will not be used."); - g_bUseClientprefs = false; - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SRI] Client Preferences extension is loaded with errors."); - LogAction(0, -1, "[SRI] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SRI] Plugin continued to load, but that feature will not be used."); - g_bUseClientprefs = false; - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SRI] Client Preferences extension is loaded, checking database."); - if (!SQL_CheckConfig(clientprefs)) - { - LogAction(0, -1, "[SRI] No 'clientprefs' database found. Check your database.cfg file."); - LogAction(0, -1, "[SRI] Plugin continued to load, but Client Preferences will not be used."); - g_bUseClientprefs = false; - } - g_bUseClientprefs = true; - - /** - Deal with client cookies - */ - sri_cookie_enabled = RegClientCookie("bri_client_enabled", "Enable/Disable your immunity during the bonus round.", CookieAccess_Public); - sri_cookie_color = RegClientCookie("bri_client_color", "Color to render when immune.", CookieAccess_Public); - sri_cookie_mode = RegClientCookie("bri_client_mode", "God mode to select", CookieAccess_Public); - SetCookieMenuItem(CookieMenu_TopMenu, sri_cookie_enabled, "Bonus Round Immunity"); - } - - HookConVarChange(sri_enabled, EnabledChanged); - - RegAdminCmd("sm_immunity", Command_Immunity, ADMFLAG_ROOT, "sm_immunity: Gives you immunity"); - - LoadColors(); - - AutoExecConfig(true, "plugin.simpleroundimmunity"); -} - -public OnAllPluginsLoaded() -{ - //something - // need to deal with the unloading of dukehacks, clientprefs, and simpleplugins - // should move hooking the client prefs cookies to a function to make sure they are done post plugin start if ext is loaded late -} - -public OnLibraryRemoved(const String:name[]) -{ - //something - // need to deal with the loading of dukehacks, clientprefs, and simpleplugins -} - -public OnConfigsExecuted() -{ - GetConVarString(sri_charadminflag, g_sCharAdminFlag, sizeof(g_sCharAdminFlag)); - g_bIsEnabled = GetConVarBool(sri_enabled); - g_bRoundEnd = false; -} - -/** - Client events - */ - -public OnClientPostAdminCheck(client) -{ - if (SM_IsValidAdmin(client, g_sCharAdminFlag)) - g_aPlayers[client][bIsAdmin] = true; - else - g_aPlayers[client][bIsAdmin] = false; -} - -public OnClientCookiesCached(client) -{ - decl String:sEnabled[2], String:sColor[4], String:sMode[2]; - GetClientCookie(client, sri_cookie_enabled, sEnabled, sizeof(sEnabled)); - GetClientCookie(client, sri_cookie_color, sColor, sizeof(sColor)); - GetClientCookie(client, sri_cookie_mode, sMode, sizeof(sMode)); - g_aClientCookies[client][bEnabled] = StringToInt(sEnabled); - g_aClientCookies[client][iColor] = StringToInt(sColor); - g_aClientCookies[client][iMode] = StringToInt(sMode); -} - -public OnClientDisconnect(client) -{ - CleanUp(client); -} - -/** - Commands - */ - -public Action:Command_Immunity(client, args) -{ - if (g_aPlayers[client][IsImmune]) - { - DisableImmunity(client); - } - else - { - EnableImmunity(client); - } - return Plugin_Handled; -} - -/** - Event hooks - */ - -public Action:Hacks_TakeDamageHook(client, attacker, inflictor, Float:damage, &Float:multiplier, damagetype) -{ - if (attacker == 0 || attacker >= MaxClients) - { - return Plugin_Continue; - } - if (g_aPlayers[client][IsImmune]) - { - new TFClassType:PlayerClass = TF2_GetPlayerClass(attacker); - if (PlayerClass == TFClass_Spy) - { - multiplier *= 0.0; - return Plugin_Changed; - } - } - return Plugin_Continue; -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - g_bRoundEnd = false; - if (g_bIsEnabled) - { - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][IsImmune]) - { - DisableImmunity(i); - } - } - } -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - g_bRoundEnd = true; - if (g_bIsEnabled) - { - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][bIsAdmin]) - { - EnableImmunity(i); - } - } - } -} - -public HookPlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) -{ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - if (g_bIsEnabled && g_aPlayers[iClient][bIsAdmin] && g_bRoundEnd) - { - EnableImmunity(iClient); - } -} - -public Action:HookPlayerHurt(Handle:event, const String:name[], bool:dontBroadcast) -{ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - if (g_aPlayers[iClient][IsImmune]) - { - SetEntityHealth(iClient, 2000); - return Plugin_Continue; - } - return Plugin_Continue; -} - -/** - Cookie menus - */ - -public CookieMenu_TopMenu(client, CookieMenuAction:action, any:info, String:buffer[], maxlen) -{ - if (action == CookieMenuAction_DisplayOption) - { - //don't think we need to do anything - } - else - { - new Handle:hMenu = CreateMenu(Menu_CookieSettings); - SetMenuTitle(hMenu, "Options (Current Setting)"); - if (g_aClientCookies[client][bEnabled]) - { - AddMenuItem(hMenu, "enable", "Enabled/Disable (Enabled)"); - } - else - { - AddMenuItem(hMenu, "enable", "Enabled/Disable (Disabled)"); - } - if (g_aClientCookies[client][iMode]) - { - AddMenuItem(hMenu, "mode", "Immunity Mode Setting (God Mode)"); - } - else - { - AddMenuItem(hMenu, "mode", "Immunity Mode Setting (Health)"); - } - switch (g_aClientCookies[client][iColor]) - { - case COLOR_GREEN: - { - AddMenuItem(hMenu, "color", "Color (Green)"); - } - case COLOR_BLACK: - { - AddMenuItem(hMenu, "color", "Color (Black)"); - } - case COLOR_RED: - { - AddMenuItem(hMenu, "color", "Color (Red)"); - } - case COLOR_BLUE: - { - AddMenuItem(hMenu, "color", "Color (Blue)"); - } - case COLOR_TEAM: - { - AddMenuItem(hMenu, "color", "Color (Team)"); - } - case COLOR_RAINBOW: - { - AddMenuItem(hMenu, "color", "Color (Rainbow)"); - } - case COLOR_NONE: - { - AddMenuItem(hMenu, "color", "Color (None)"); - } - } - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, client, MENU_TIME_FOREVER); - } -} - -public Menu_CookieSettings(Handle:menu, MenuAction:action, param1, param2) -{ - new client = param1; - if (action == MenuAction_Select) - { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "enable", false)) - { - new Handle:hMenu = CreateMenu(Menu_CookieSettingsEnable); - SetMenuTitle(hMenu, "Enable/Disable Round End Immunity"); - - if (g_aClientCookies[client][bEnabled]) - { - AddMenuItem(hMenu, "enable", "Enable (Set)"); - AddMenuItem(hMenu, "disable", "Disable"); - } - else - { - AddMenuItem(hMenu, "enable", "Enabled"); - AddMenuItem(hMenu, "disable", "Disable (Set)"); - } - - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, client, MENU_TIME_FOREVER); - } - else if (StrEqual(sSelection, "mode", false)) - { - new Handle:hMenu = CreateMenu(Menu_CookieSettingsMode); - SetMenuTitle(hMenu, "Set Immunity Mode"); - - if (g_aClientCookies[client][iMode]) - { - AddMenuItem(hMenu, "god", "God Mode (Set)"); - AddMenuItem(hMenu, "health", "Health"); - } - else - { - AddMenuItem(hMenu, "god", "God Mode"); - AddMenuItem(hMenu, "health", "Health (Set)"); - } - - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, client, MENU_TIME_FOREVER); - } - else - { - new Handle:hMenu = CreateMenu(Menu_CookieSettingsColors); - SetMenuTitle(hMenu, "Select Immunity Color"); - switch (g_aClientCookies[client][iColor]) - { - case COLOR_GREEN: - { - AddMenuItem(hMenu, "Green", "Green (Set)"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_BLACK: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black (Set)"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_RED: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red (Set)"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_BLUE: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue (Set)"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_TEAM: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color (Set)"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_RAINBOW: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow (Set)"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_NONE: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None (Set)"); - } - } - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, client, MENU_TIME_FOREVER); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - ShowCookieMenu(client); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -public Menu_CookieSettingsEnable(Handle:menu, MenuAction:action, param1, param2) -{ - new client = param1; - if (action == MenuAction_Select) - { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "enable", false)) - { - SetClientCookie(client, sri_cookie_enabled, "1"); - g_aClientCookies[client][bEnabled] = 1; - PrintToChat(client, "[SM] Bonus Round Immunity is ENABLED"); - } - else - { - SetClientCookie(client, sri_cookie_enabled, "0"); - g_aClientCookies[client][bEnabled] = 0; - PrintToChat(client, "[SM] Bonus Round Immunity is DISABLED"); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - ShowCookieMenu(client); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -public Menu_CookieSettingsColors(Handle:menu, MenuAction:action, param1, param2) -{ - new client = param1; - if (action == MenuAction_Select) - { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "Green", false)) - { - SetClientCookie(client, sri_cookie_color, "0"); - g_aClientCookies[client][iColor] = COLOR_GREEN; - PrintToChat(client, "[SM] Bonus Round Immunity color set to GREEN"); - } - else if (StrEqual(sSelection, "Black", false)) - { - SetClientCookie(client, sri_cookie_color, "1"); - g_aClientCookies[client][iColor] = COLOR_BLACK; - PrintToChat(client, "[SM] Bonus Round Immunity color set to BLACK"); - } - else if (StrEqual(sSelection, "Red", false)) - { - SetClientCookie(client, sri_cookie_color, "2"); - g_aClientCookies[client][iColor] = COLOR_RED; - PrintToChat(client, "[SM] Bonus Round Immunity color set to RED"); - } - else if (StrEqual(sSelection, "Blue", false)) - { - SetClientCookie(client, sri_cookie_color, "3"); - g_aClientCookies[client][iColor] = COLOR_BLUE; - PrintToChat(client, "[SM] Bonus Round Immunity color set to BLUE"); - } - else if (StrEqual(sSelection, "Team", false)) - { - SetClientCookie(client, sri_cookie_color, "4"); - g_aClientCookies[client][iColor] = COLOR_TEAM; - PrintToChat(client, "[SM] Bonus Round Immunity color set to TEAM COLOR"); - } - else if (StrEqual(sSelection, "Rain", false)) - { - SetClientCookie(client, sri_cookie_color, "5"); - g_aClientCookies[client][iColor] = COLOR_RAINBOW; - PrintToChat(client, "[SM] Bonus Round Immunity color set to RAINBOW"); - } - else if (StrEqual(sSelection, "None", false)) - { - SetClientCookie(client, sri_cookie_color, "6"); - g_aClientCookies[client][iColor] = COLOR_NONE; - PrintToChat(client, "[SM] Bonus Round Immunity color set to NONE"); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - ShowCookieMenu(client); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -public Menu_CookieSettingsMode(Handle:menu, MenuAction:action, param1, param2) -{ - new client = param1; - if (action == MenuAction_Select) - { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "god", false)) - { - SetClientCookie(client, sri_cookie_mode, "1"); - g_aClientCookies[client][iMode] = 1; - PrintToChat(client, "[SM] Bonus Round Immunity set to GOD MODE"); - } - else - { - SetClientCookie(client, sri_cookie_mode, "0"); - g_aClientCookies[client][iMode] = 0; - PrintToChat(client, "[SM] Bonus Round Immunity set to HEALTH BONUS"); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - ShowCookieMenu(client); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -/** -Timer functions - */ - -public Action:Timer_ChangeColor(Handle:timer, any:client) -{ - if (g_aPlayers[client][CycleColor]++ == 3) - { - g_aPlayers[client][CycleColor] = 0; - } - SetEntityRenderMode(client, RENDER_TRANSCOLOR); - SetEntityRenderColor(client, g_iColors[g_aPlayers[client][CycleColor]][iRed], g_iColors[g_aPlayers[client][CycleColor]][iGreen], g_iColors[g_aPlayers[client][CycleColor]][iBlue], 255); - return Plugin_Continue; -} - -public Action:Timer_UndoGodMode(Handle:timer, any:client) -{ - if (IsClientInGame(client)) - { - SetEntProp(client, Prop_Data, "m_takedamage", 2, 1); - } - g_aPlayers[iClient][hGodModeTimer] = INVALID_HANDLE; - return Plugin_Handled; -} - -/** -Stock functions . - */ - -stock CleanUp(iClient) -{ - g_aPlayers[iClient][bIsAdmin] = false; - DisableImmunity(iClient); -} - -stock EnableImmunity(iClient) -{ - SetEntityRenderMode(iClient, RENDER_TRANSCOLOR); - switch (g_aClientCookies[iClient][iColor]) - { - case COLOR_TEAM: - { - new iTeam = GetClientTeam(iClient); - SetEntityRenderColor(iClient, g_iColors[e_ColorNames:iTeam][iRed], g_iColors[e_ColorNames:iTeam][iGreen], g_iColors[e_ColorNames:iTeam][iBlue], 255); - } - case COLOR_RAINBOW: - { - if (g_aPlayers[iClient][hColorTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hColorTimer]); - g_aPlayers[iClient][hColorTimer] = INVALID_HANDLE; - } - g_aPlayers[iClient][hColorTimer] = CreateTimer(0.2, Timer_ChangeColor, iClient, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); - } - case COLOR_NONE: - { - //We dont have to set a color - } - default: - { - SetEntityRenderColor(iClient, g_iColors[e_ColorNames:g_aClientCookies[iClient][iColor]][iRed], g_iColors[e_ColorNames:g_aClientCookies[iClient][iColor]][iGreen], g_iColors[e_ColorNames:g_aClientCookies[iClient][iColor]][iBlue], 255); - } - } - SetEntityHealth(iClient, 2000); - SetEntProp(iClient, Prop_Data, "m_takedamage", 0, 1); - g_aPlayers[iClient][hGodModeTimer] = CreateTimer(2.0, Timer_UndoGodMode, iClient); - g_aPlayers[iClient][IsImmune] = true; -} - -stock DisableImmunity(iClient) -{ - if (g_aPlayers[iClient][hGodModeTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hGodModeTimer]); - g_aPlayers[iClient][hGodModeTimer] = INVALID_HANDLE; - } - if (g_aPlayers[iClient][hColorTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hColorTimer]); - g_aPlayers[iClient][hColorTimer] = INVALID_HANDLE; - } - if (IsClientInGame(iClient)) - { - SetEntityRenderMode(iClient, RENDER_TRANSCOLOR); - SetEntityRenderColor(iClient, 255, 255, 255, 255); - new TFClassType:PlayerClass = TF2_GetPlayerClass(iClient); - new iMaxHealth = g_iClassMaxHealth[PlayerClass]; - SetEntityHealth(iClient, iMaxHealth); - } - g_aPlayers[iClient][CycleColor] = 0; - g_aPlayers[iClient][IsImmune] = false; -} - -stock LoadColors() -{ - g_iColors[Green][iRed] = 0; - g_iColors[Green][iGreen] = 255; - g_iColors[Green][iBlue] = 0; - - g_iColors[Black][iRed] = 10; - g_iColors[Black][iGreen] = 10; - g_iColors[Black][iBlue] = 0; - - g_iColors[Red][iRed] = 255; - g_iColors[Red][iGreen] = 0; - g_iColors[Red][iBlue] = 0; - - g_iColors[Blue][iRed] = 0; - g_iColors[Blue][iGreen] = 0; - g_iColors[Blue][iBlue] = 255; -} - -stock TF2_AddCond(client, cond) -{ - new Handle:cvar = FindConVar("sv_cheats"), bool:enabled = GetConVarBool(cvar), flags = GetConVarFlags(cvar); - if(!enabled) - { - SetConVarFlags(cvar, flags^FCVAR_NOTIFY); - SetConVarBool(cvar, true); - } - FakeClientCommand(client, "addcond %i", cond); - if(!enabled) - { - SetConVarBool(cvar, false); - SetConVarFlags(cvar, flags); - } -} - -stock TF2_RemoveCond(client, cond) -{ - new Handle:cvar = FindConVar("sv_cheats"), bool:enabled = GetConVarBool(cvar), flags = GetConVarFlags(cvar); - if(!enabled) - { - SetConVarFlags(cvar, flags^FCVAR_NOTIFY); - SetConVarBool(cvar, true); - } - FakeClientCommand(client, "removecond %i", cond); - if(!enabled) - { - SetConVarBool(cvar, false); - SetConVarFlags(cvar, flags); - } -} - -/** -Enabled hook - */ - -public EnabledChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (StringToInt(newValue) == 0) - { - UnhookEvent("player_spawn", HookPlayerSpawn, EventHookMode_Post); - UnhookEvent("teamplay_round_start", HookRoundStart, EventHookMode_Post); - UnhookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][bIsAdmin] && g_aPlayers[i][IsImmune]) - { - DisableImmunity(i); - } - } - g_bIsEnabled = false; - } - else - { - HookEvent("player_spawn", HookPlayerSpawn, EventHookMode_Post); - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_Post); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - g_bIsEnabled = true; - } -} diff --git a/Simple AllTalk Manager/addons/sourcemod/scripting/simple-spectate.sp b/Simple AllTalk Manager/addons/sourcemod/scripting/simple-spectate.sp deleted file mode 100644 index 4108f8f..0000000 --- a/Simple AllTalk Manager/addons/sourcemod/scripting/simple-spectate.sp +++ /dev/null @@ -1,2022 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Spectate -Description: - Spectate a player and follow them through death. -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include -#undef REQUIRE_EXTENSIONS -#undef AUTOLOAD_EXTENSIONS -#tryinclude -#define AUTOLOAD_EXTENSIONS -#define REQUIRE_EXTENSIONS - -#define PLUGIN_VERSION "1.2.1.$Rev$" - -#define SPECMODE_NONE 0 -#define SPECMODE_FIRSTPERSON 4 -#define SPECMODE_3RDPERSON 5 -#define SPECMODE_FREELOOK 6 -#define SPECMODE_CSS_FIRSTPERSON 3 -#define SPECMODE_CSS_3RDPERSON 4 -#define SPECMODE_CSS_FREELOOK 5 - -enum e_CvarHandles -{ - Handle:hHudMode, - Handle:hMenuType, - Handle:hRestrictHud, - Handle:hBan, - Handle:hBanPerm, - Handle:hBeacon, - Handle:hBlind, - Handle:hCheater, - Handle:hDrug, - Handle:hFreeze, - Handle:hFreezeBomb, - Handle:hKick, - Handle:hSlap, - Handle:hSlay, - Handle:hTimeBomb -}; - -enum e_CvarSettings -{ - bool:bHudMode, - bool:bMenuType, - bool:bRestrictHud, - bool:bBan, - bool:bBanPerm, - bool:bBeacon, - bool:bBlind, - bool:bCheater, - bool:bDrug, - bool:bFreeze, - bool:bFreezebomb, - bool:bKick, - bool:bSlap, - bool:bSlay, - bool:bTimeBomb -}; - -enum e_PluginSettings -{ - bool:bUseSteamBans, - bool:bUseSourceBans, - bool:bUseMySQLBans, - bool:bCanHUD, - bool:bUseDukehacks -}; - -enum e_Menus -{ - Handle:hSelectPlayer, - Handle:hBanTime, - Handle:hReason -}; - -enum e_Punishments -{ - Punish_None, - Punish_Ban, - Punish_Beacon, - Punish_Blind, - Punish_Cheater, - Punish_Drug, - Punish_Freeze, - Punish_FreezeBomb, - Punish_Kick, - Punish_Slap, - Punish_Slay, - Punish_TimeBomb -}; - -enum e_PlayerData -{ - bool:bIsDisplayingHud, - bool:bIsFlaggedCheater, - Handle:hHudTimer, - Handle:hTargetTimer, - iTargetIndex, - e_Punishments:TargetPunishment, - iBanTime -}; - -new Handle:sm_spectate_adminflag = INVALID_HANDLE; -new Handle:g_hAdminMenu = INVALID_HANDLE; -new Handle:g_hHud = INVALID_HANDLE; -new Handle:g_aPluginCvar[e_CvarHandles]; -new g_aPluginCvarSettings[e_CvarSettings]; -new g_aPluginSettings[e_PluginSettings]; -new g_aMenus[e_Menus]; -new g_aPlayers[MAXPLAYERS + 1][e_PlayerData]; -new String:g_sAdminFlags[16]; -new String:g_sPunishments[e_Punishments][15] = { "None", "Ban", "Beacon", "Blind", "Cheater", "Drug", "Freeze", "FreezeBomb", "Kick", "Slap", "Slay", "TimeBomb" }; - -public Plugin:myinfo = -{ - name = "Simple Spectate", - author = "Simple Plugins", - description = "Spectate a player and follow them through death.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -/** -Sourcemod callbacks -*/ -public OnPluginStart() -{ - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[SSPEC] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Pre); - - /** - Need to create all of our console variables. - */ - CreateConVar("sm_spectate_version", PLUGIN_VERSION, "Sourcemod Spectate", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - g_aPluginCvar[hHudMode] = CreateConVar("sm_spectate_hudmode", "1", "Hud Mode: 0 = Hud Text | 1 = Panel/Menu (NOTE: The panel/menu will override other menus until canceled)"); - g_aPluginCvar[hMenuType] = CreateConVar("sm_spectate_menutype", "0", "Menu Mode: 0 = Panel | 1 = Menu"); - g_aPluginCvar[hRestrictHud] = CreateConVar("sm_spectate_restricthud", "0", "Restrict the hud to the admin flag provided"); - g_aPluginCvar[hBan] = CreateConVar("sm_spectate_ban", "1", "Enable/Disable ban option"); - g_aPluginCvar[hBanPerm] = CreateConVar("sm_spectate_banperm", "1", "Enable/Disable permanent ban option"); - g_aPluginCvar[hBeacon] = CreateConVar("sm_spectate_beacon", "1", "Enable/Disable beacon option"); - g_aPluginCvar[hBlind] = CreateConVar("sm_spectate_blind", "1", "Enable/Disable blind option"); - g_aPluginCvar[hCheater] = CreateConVar("sm_spectate_cheater", "1", "Enable/Disable cheater option"); - g_aPluginCvar[hDrug] = CreateConVar("sm_spectate_drug", "1", "Enable/Disable drug option"); - g_aPluginCvar[hFreeze] = CreateConVar("sm_spectate_freeze", "1", "Enable/Disable freeze option"); - g_aPluginCvar[hFreezeBomb] = CreateConVar("sm_spectate_freezebomb", "1", "Enable/Disable freezebomb option"); - g_aPluginCvar[hKick] = CreateConVar("sm_spectate_kick", "1", "Enable/Disable kick option"); - g_aPluginCvar[hSlap] = CreateConVar("sm_spectate_slap", "1", "Enable/Disable slap option"); - g_aPluginCvar[hSlay] = CreateConVar("sm_spectate_slay", "1", "Enable/Disable slay option"); - g_aPluginCvar[hTimeBomb] = CreateConVar("sm_spectate_timebomb", "1", "Enable/Disable timebomb option"); - - sm_spectate_adminflag = CreateConVar("sm_spectate_adminflag", "d", "Admin Flag to use for admin hud"); - - /** - Hook console variables - */ - new e_CvarHandles:iCvar; - for ( ; _:iCvar < sizeof(g_aPluginCvar); iCvar++) - { - HookConVarChange(g_aPluginCvar[iCvar], ConVarSettingsChanged); - } - - /** - Need to register the commands we are going to create and use. - */ - RegConsoleCmd("sm_spectate", Command_Spectate, "Spectate a player"); - RegConsoleCmd("sm_spec", Command_Spectate, "Spectate a player"); - RegConsoleCmd("sm_observe", Command_Spectate, "Spectate a player"); - RegConsoleCmd("sm_stopspec", Command_StopSpectate, "Stop Spectating a player"); - RegConsoleCmd("sm_endobserve", Command_StopSpectate, "Stop Spectating a player"); - RegConsoleCmd("sm_specinfo", Command_ToggleHud, "Toggles the hud display if in spectator"); - - /** - Now we have to deal with the admin menu. If the admin library is loaded call the function to add our items. - */ - new Handle:gTopMenu; - if (LibraryExists("adminmenu") && ((gTopMenu = GetAdminTopMenu()) != INVALID_HANDLE)) - { - OnAdminMenuReady(gTopMenu); - } - - /** - Deal with the hud - Thanks to Spray Trace plugin (http://forums.alliedmods.net/showthread.php?p=665448) - */ - new String:sHudGames[32]; - GetGameFolderName(sHudGames, sizeof(sHudGames)); - g_aPluginSettings[bCanHUD] = StrEqual(sHudGames,"tf",false) - || StrEqual(sHudGames,"hl2mp",false) - || StrEqual(sHudGames,"sourceforts",false) - || StrEqual(sHudGames,"obsidian",false) - || StrEqual(sHudGames,"left4dead",false) - || StrEqual(sHudGames,"l4d",false); - - if (g_aPluginSettings[bCanHUD]) - { - g_hHud = CreateHudSynchronizer(); - } - - /** - Load translations - */ - LoadTranslations ("common.phrases"); - LoadTranslations ("simplespectate.phrases"); - - /** - Create the config file - */ - AutoExecConfig(true); -} - -public OnConfigsExecuted() -{ - new e_CvarHandles:iCvar; - for ( ; _:iCvar < sizeof(g_aPluginCvarSettings); iCvar++) - { - g_aPluginCvarSettings[iCvar] = GetConVarBool(g_aPluginCvar[iCvar]); - } - - /* - Build the global menus - */ - g_aMenus[hSelectPlayer] = BuildSelectPlayerMenu(); - g_aMenus[hBanTime] = BuildBanTimeMenu(); - g_aMenus[hReason] = BuildReasonMenu(); - - GetConVarString(sm_spectate_adminflag, g_sAdminFlags, sizeof(g_sAdminFlags)); -} - -public OnAllPluginsLoaded() -{ - - /* - Check for steambans - */ - if (FindConVar("sbsrc_version") != INVALID_HANDLE) - { - g_aPluginSettings[bUseSteamBans] = true; - } - else - { - g_aPluginSettings[bUseSteamBans] = false; - } - - /* - Check for sourcebans - */ - if (FindConVar("sb_version") != INVALID_HANDLE) - { - g_aPluginSettings[bUseSourceBans] = true; - } - else - { - g_aPluginSettings[bUseSourceBans] = false; - } - - /* - Check for mysql bans - */ - if (FindConVar("mysql_bans_version") != INVALID_HANDLE) - { - g_aPluginSettings[bUseMySQLBans] = true; - } - else - { - g_aPluginSettings[bUseMySQLBans] = false; - } - - /* - Check for dukehacks - */ - new String:sExtError[256]; - new iExtStatus = GetExtensionFileStatus("dukehacks.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SSPEC] Dukehacks extension was not found."); - LogAction(0, -1, "[SSPEC] Plugin continued to load, but that feature will not be used."); - g_aPluginSettings[bUseDukehacks] = false; - } - else if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SSPEC] Dukehacks extension is loaded with errors."); - LogAction(0, -1, "[SSPEC] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SSPEC] Plugin continued to load, but that feature will not be used."); - g_aPluginSettings[bUseDukehacks] = false; - } - else if (iExtStatus == 1) - { - LogAction(0, -1, "[SSPEC] Dukehacks extension is loaded and will be used."); - g_aPluginSettings[bUseDukehacks] = true; - dhAddClientHook(CHK_TakeDamage, Hacks_TakeDamageHook); - } - - /* - Deal with some known plugin conflicts - */ - new Handle:hObserveClient = FindConVar("observe_version"); - if (hObserveClient != INVALID_HANDLE) - { - new String:sNewFile[PLATFORM_MAX_PATH + 1], String:sOldFile[PLATFORM_MAX_PATH + 1]; - BuildPath(Path_SM, sNewFile, sizeof(sNewFile), "plugins/disabled/observe.smx"); - BuildPath(Path_SM, sOldFile, sizeof(sOldFile), "plugins/observe.smx"); - - /** - Check if plugins/observe.smx exists, and if not, ignore - */ - if(!FileExists(sOldFile)) - { - return; - } - - /** - Check if plugins/disabled/observe.smx already exists, and if so, delete it - */ - if(FileExists(sNewFile)) - { - DeleteFile(sNewFile); - } - - /** - Unload plugins/observe.smx and move it to plugins/disabled/observe.smx - */ - LogAction(0, -1, "Detected the plugin ObserveClient"); - LogAction(0, -1, "ObserveClient plugin conflicts with Simple Spectate"); - LogAction(0, -1, "Unloading plugin and disabling ObserveClient plugin"); - ServerCommand("sm plugins unload observe"); - RenameFile(sNewFile, sOldFile); - } -} - -public OnLibraryRemoved(const String:name[]) -{ - if (StrEqual(name, "adminmenu")) - { - - /** - Looks like the admin menu was removed. Set the global. - */ - g_hAdminMenu = INVALID_HANDLE; - } - else if (StrEqual(name, "simpleplugins")) - { - //something - } -} - -public OnClientDisconnect(client) -{ - - /** - Cleanup the clients variables. - */ - ResetClient(client); - - /** - Run a loop and see if we are supposed to spectate this person (is a target) - */ - for(new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][iTargetIndex] == client) - { - - /** - Cleanup the clients variables. - */ - StopFollowingPlayer(i); - g_aPlayers[i][TargetPunishment] = Punish_None; - g_aPlayers[i][iBanTime] = 0; - } - } -} - -/** -Thirdparty callbacks -*/ -public SM_OnPlayerMoved(Handle:plugin, client, team) -{ - - /** - Make sure we called the move function - */ - if (plugin != GetMyHandle()) - { - return; - } - - //Nothing -} - -public Action:Hacks_TakeDamageHook(client, attacker, inflictor, Float:damage, &Float:multiplier, damagetype) -{ - - /** - Check for a valid client - */ - if (client > 0 && client <= MaxClients) - { - - /** - Check if the client taking damage is flagged as a cheater - */ - if (g_aPlayers[client][bIsFlaggedCheater]) - { - - /** - Check for fall damage and increase it - */ - if (damagetype & DMG_FALL) - { - multiplier *= 1000.0; - return Plugin_Changed; - } - } - } - - /** - Check for a valid attacker - */ - if (attacker > 0 && attacker <= MaxClients) - { - - /** - Check if the attacker causing the damage is flagged as a cheater - */ - if (g_aPlayers[attacker][bIsFlaggedCheater]) - { - - /** - Make sure they are not hurting themselves - */ - if (client != attacker) - { - - /** - Stop the damage - */ - multiplier *= 0.0; - return Plugin_Changed; - } - } - } - return Plugin_Continue; -} - -/** -Events -*/ -public Action:HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get the client and team - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - new iTeam = GetEventInt(event, "team"); - - /** - Make sure it's a valid client - */ - if (iClient == 0) - { - return Plugin_Continue; - } - - /** - If it's a move to spectator start displaying the hud - */ - else if ((iTeam == g_aCurrentTeams[Spectator]) && (GetUserFlagBits(iClient) & ADMFLAG_GENERIC)) - { - StartDisplayingHud(iClient); - - /** - If the event was going to be broadcasted, we refire it so it is not broadcasted and stop this one - */ - if (!dontBroadcast) - { - new Handle:hEvent = CreateEvent("player_team"); - SetEventInt(hEvent, "userid", GetEventInt(event, "userid")); - SetEventInt(hEvent, "team", GetEventInt(event, "team")); - SetEventInt(hEvent, "oldteam", GetEventInt(event, "oldteam")); - SetEventBool(hEvent, "disconnect", GetEventBool(event, "disconnect")); - - if (g_CurrentMod == GameType_DOD || g_CurrentMod == GameType_L4D || g_CurrentMod == GameType_TF) - { - new String:sClientName[MAX_NAME_LENGTH + 1]; - GetClientName(client, sClientName, sizeof(sClientName)); - SetEventBool(hEvent, "autoteam", GetEventBool(event, "autoteam")); - SetEventBool(hEvent, "silent", true); - SetEventString(hEvent, "name", sClientName); - FireEvent(hEvent, true); - } - else - { - FireEvent(hEvent, true); - } - return Plugin_Handled; - } - } - - /** - Otherwise cleanup the client - */ - else - { - StopDisplayingHud(iClient); - StopFollowingPlayer(iClient); - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -/** -Commands -*/ -public Action:Command_Spectate(client, args) -{ - - /** - See if we already have a target (for toggling of command) - */ - if (g_aPlayers[client][iTargetIndex]) - { - - /** - We do, toggle it off - */ - StopFollowingPlayer(client); - - /** - We are done, bug out. - */ - return Plugin_Handled; - } - - /** - We don't... must want to enable it - See if we have some command arguments. - */ - new iCmdArgs = GetCmdArgs(); - if (iCmdArgs == 0) - { - - /** - We don't have any. Display the player menu. - */ - if (g_aPlayers[client][bIsDisplayingHud]) - { - StopDisplayingHud(client); - } - - DisplayMenu(BuildPlayerListMenu(), client, MENU_TIME_FOREVER); - return Plugin_Handled; - } - - /** - We have an argument. - Try to find the target. - */ - new String:sPlayer[128]; - GetCmdArg(1, sPlayer, sizeof(sPlayer)); - new iTarget = FindTarget(client, sPlayer, true, true); - if (iTarget == -1 || !IsClientInGame(iTarget)) - { - - /** - We couldn't find the target. Display the player menu. - */ - if (g_aPlayers[client][bIsDisplayingHud]) - { - StopDisplayingHud(client); - } - - DisplayMenu(BuildPlayerListMenu(), client, MENU_TIME_FOREVER); - return Plugin_Handled; - } - - /** - We found the target. - Call the stock function to spectate the target. - */ - StartFollowingPlayer(client, iTarget); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_StopSpectate(client, args) -{ - - /** - Cleanup the clients variables. - */ - StopFollowingPlayer(client); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_ToggleHud(client, args) -{ - - /** - Toggle the hud - */ - if (g_aPlayers[client][bIsDisplayingHud]) - { - StopDisplayingHud(client); - } - else - { - StartDisplayingHud(client); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -/** -Timers -*/ -public Action:Timer_ResetTarget(Handle:timer, any:client) -{ - - new iTargetID = GetEntPropEnt(client, Prop_Send, "m_hObserverTarget"); - - if (iTargetID != g_aPlayers[client][iTargetIndex] && IsPlayerAlive(g_aPlayers[client][iTargetIndex])) - { - - /** - Run the command to spectate the target from the clients prospectative. - */ - FakeClientCommandEx(client, "spec_player \"%N\"", g_aPlayers[client][iTargetIndex]); - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Timer_UpdateHud(Handle:timer, any:client) -{ - - /** - Make sure the client is still in game and a spectator - */ - if (!IsClientConnected(client) || !IsClientInGame(client) || GetClientTeam(client) != g_aCurrentTeams[Spectator] || !g_aPlayers[client][bIsDisplayingHud]) - { - - /** - We are done, bug out - */ - g_aPlayers[client][hHudTimer] = INVALID_HANDLE; - g_aPlayers[client][bIsDisplayingHud] = false; - return Plugin_Stop; - } - /** - Get the target - */ - new iTarget = GetEntPropEnt(client, Prop_Send, "m_hObserverTarget"); - - /** - Check to make sure the target is valid - */ - if (iTarget <= 0 || iTarget > MaxClients) - { - return Plugin_Continue; - } - - /** - Get the spectator mode - */ - new iSpecMode = GetEntProp(client, Prop_Send, "m_iObserverMode"); - - /** - This is a double check to make sure we are in spec - If we are on a regular team, specmod would = none or zero - */ - if (iSpecMode == SPECMODE_NONE) - { - - /** - We are done, bug out - */ - g_aPlayers[client][hHudTimer] = INVALID_HANDLE; - g_aPlayers[client][bIsDisplayingHud] = false; - return Plugin_Stop; - } - - /** - Check the spectator mode - CSS has different index's so we have to check game type first - */ - if (g_CurrentMod == GameType_CSS) - { - switch (iSpecMode) - { - case SPECMODE_CSS_FIRSTPERSON: - { - //Do Nothing - } - case SPECMODE_CSS_3RDPERSON: - { - //Do Nothing - } - case SPECMODE_CSS_FREELOOK: - { - return Plugin_Continue; - } - } - } - else - { - switch (iSpecMode) - { - case SPECMODE_FIRSTPERSON: - { - //Do Nothing - } - case SPECMODE_3RDPERSON: - { - //Do Nothing - } - case SPECMODE_FREELOOK: - { - return Plugin_Continue; - } - } - } - - - /** - Display with the hud - */ - if (g_aPluginSettings[bCanHUD] && !g_aPluginCvarSettings[bHudMode]) - { - new String:sSteamID[64]; - GetClientAuthString(iTarget, sSteamID, sizeof(sSteamID)); - SetHudTextParams(0.04, 0.6, 0.5, 255, 50, 50, 255); - ShowSyncHudText(client, g_hHud, "%N [%s]", iTarget, sSteamID); - } - else if (g_aPluginCvarSettings[bHudMode]) - { - if (g_aPluginCvarSettings[bMenuType]) - { - DisplayMenu(BuildPlayerHudMenu(client, iTarget), client, 1); - } - else - { - new Handle:hPanel = BuildPlayerHudPanel(client, iTarget); - SendPanelToClient(hPanel, client, Panel_PlayerHud, 1); - CloseHandle(hPanel); - } - } - - /** - We are done, keep going! - */ - return Plugin_Continue; -} - -/** -Admin Menu Callbacks -*/ -public OnAdminMenuReady(Handle:topmenu) -{ - if (topmenu == g_hAdminMenu) - { - return; - } - g_hAdminMenu = topmenu; - new TopMenuObject:player_commands = FindTopMenuCategory(g_hAdminMenu, ADMINMENU_PLAYERCOMMANDS); - if (player_commands == INVALID_TOPMENUOBJECT) - { - return; - } - AddToTopMenu(g_hAdminMenu, - "sm_spectate", - TopMenuObject_Item, - AdminMenu_SpecPlayer, - player_commands, - "sm_spectate", - ADMFLAG_GENERIC); -} - -public AdminMenu_SpecPlayer(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) -{ - if (action == TopMenuAction_DisplayOption) - { - - if (g_aPlayers[param][bIsDisplayingHud]) - { - StopDisplayingHud(param); - } - /** - See if we already have a target - */ - if (g_aPlayers[param][iTargetIndex]) - { - Format(buffer, maxlength, "Spectate(Disable)"); - } - else - { - Format(buffer, maxlength, "Spectate(Select Player)"); - } - } - else if (action == TopMenuAction_SelectOption) - { - - /** - See if we already have a target - */ - if (g_aPlayers[param][iTargetIndex]) - { - - /** - We do, toggle it off - */ - StopFollowingPlayer(param); - - /** - We are done, bug out. - */ - return; - } - else - { - DisplayMenu(BuildPlayerListMenu(), param, MENU_TIME_FOREVER); - } - } -} - -/** -Select Player Menu Callbacks -*/ -public Menu_PlayerList(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - /** - Get the selected player - */ - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - new iTarget = GetClientOfUserId(StringToInt(sSelection)); - - /** - Start following the player - */ - StartFollowingPlayer(param1, iTarget); - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_GENERIC) - { - - /** - Display the last admin menu - */ - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } - else if (param2 == MenuCancel_Exit && GetClientTeam(param1) == g_aCurrentTeams[Spectator]) - { - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_End) - { - - /** - Not a global menu, close it - */ - CloseHandle(menu); - } -} - -public Menu_SelectPlayer(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - - /** - Get the selected player - */ - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (strcmp(sSelection, "Current", false) == 0) - { - /** - Get the current target - */ - new iTarget = GetEntPropEnt(param1, Prop_Send, "m_hObserverTarget"); - - /** - Check to make sure the target is valid - */ - if (iTarget <= 0 || iTarget > MaxClients) - { - PrintToChat(param1, "\x03[SM-SPEC]\x01 %t", "Invalid Target"); - DisplayMenu(BuildPlayerListMenu(), param1, MENU_TIME_FOREVER); - } - - /** - Start following the player - */ - StartFollowingPlayer(param1, iTarget); - } - else - { - - /** - They want to select a player, show the player list - */ - DisplayMenu(BuildPlayerListMenu(), param1, MENU_TIME_FOREVER); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_End) - { - /** - Its a global menu, leave it alive - */ - } -} - -/** -Punishment Menu Callbacks -*/ -public Menu_Punishments(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - - /** - Get the menu selection - */ - new String:sSelection[15]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - - /** - Search for the correct index - */ - new e_Punishments:Index = Punish_None; - for ( ; _:Index <= sizeof(g_sPunishments); Index++) - { - if (StrEqual(sSelection, g_sPunishments[Index])) - { - break; - } - } - - /** - Display the next menu - */ - if (Index == Punish_Ban) - { - - /** - Set the punishment index and display ban time menu - */ - g_aPlayers[param1][TargetPunishment] = Index; - DisplayMenu(g_aMenus[hBanTime], param1, MENU_TIME_FOREVER); - } - else if (Index == Punish_Cheater) - { - - /** - Ask for confirmation before we set punishment index - */ - new Handle:hPanel = BuildAdminCheaterPanel(); - SendPanelToClient(hPanel, param1, Panel_AdminCheater, MENU_TIME_FOREVER); - CloseHandle(hPanel); - } - else - { - - /** - Set the punishment index and display reason menu - */ - g_aPlayers[param1][TargetPunishment] = Index; - DisplayMenu(g_aMenus[hReason], param1, MENU_TIME_FOREVER); - } - } - else if (action == MenuAction_Cancel) - { - - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - else if (action == MenuAction_End) - { - - /** - Not a global menu, close it - */ - CloseHandle(menu); - } -} - -public Menu_BanTime(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - - /** - Get the menu selection - */ - new String:sSelection[15]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - - /** - Set the ban time global - */ - g_aPlayers[param1][iBanTime] = StringToInt(sSelection); - - /** - Display the reason menu - */ - DisplayMenu(g_aMenus[hReason], param1, MENU_TIME_FOREVER); - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_End) - { - /** - Its a global menu, leave it alive - */ - } -} - -public Menu_Reason(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - - /** - Get the menu selection - */ - new String:sSelection[15]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - - /** - Perform the punishment - */ - PerformPunishment(param1, g_aPlayers[param1][iTargetIndex], g_aPlayers[param1][TargetPunishment], sSelection, g_aPlayers[param1][iBanTime]); - - /** - Reactivate the hud if still in spectator - */ - if (GetClientTeam(param1) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_End) - { - /** - Its a global menu, leave it alive - */ - } -} - -public Panel_AdminCheater(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - if (param2 == 1) - { - - /** - Set the punishment index and display reason menu - */ - g_aPlayers[param1][TargetPunishment] = Punish_Cheater; - DisplayMenu(g_aMenus[hReason], param1, MENU_TIME_FOREVER); - } - else - { - - /** - Reactivate the hud if still in spectator - */ - if (GetClientTeam(param1) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(param1); - } - } - } -} - -public Panel_PublicCheater(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - if (param2 == 1) - { - //Waiting for SB 2.0 and sb_submission to be published - } - else - { - - /** - Reactivate the hud if still in spectator - */ - if (GetClientTeam(param1) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(param1); - } - } - } -} - -/** -Hud Menu/Panel Callbacks -*/ -public Menu_PlayerHud(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "stop", false)) - { - StopFollowingPlayer(param1); - } - else if (StrEqual(sSelection, "start", false)) - { - StopDisplayingHud(param1); - DisplayMenu(g_aMenus[hSelectPlayer], param1, MENU_TIME_FOREVER); - } - else if (StrEqual(sSelection, "removecheater", false)) - { - g_aPlayers[g_aPlayers[param1][iTargetIndex]][bIsFlaggedCheater] = false; - } - else if (StrEqual(sSelection, "punish", false)) - { - if (g_aPlayers[param1][iTargetIndex]) - { - StopDisplayingHud(param1); - DisplayMenu(BuildPunishmentMenu(param1), param1, MENU_TIME_FOREVER); - } - else - { - StopDisplayingHud(param1); - PrintToChat(param1, "\x03[SM-SPEC]\x01 %t", "Must Have Target"); - DisplayMenu(g_aMenus[hSelectPlayer], param1, MENU_TIME_FOREVER); - } - } - else if (StrEqual(sSelection, "reportcheater", false)) - { - if (g_aPlayers[param1][iTargetIndex]) - { - StopDisplayingHud(param1); - new Handle:hPanel = BuildPublicCheaterPanel(); - SendPanelToClient(hPanel, param1, Panel_PublicCheater, MENU_TIME_FOREVER); - CloseHandle(hPanel); - } - else - { - StopDisplayingHud(param1); - PrintToChat(param1, "\x03[SM-SPEC]\x01 %t", "Must Have Target"); - DisplayMenu(g_aMenus[hSelectPlayer], param1, MENU_TIME_FOREVER); - } - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_Interrupted) - { - if (GetClientMenu(param1) == MenuSource_External) - { - StopDisplayingHud(param1); - } - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -public Panel_PlayerHud(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - switch (param2) - { - case 1: - { - if (g_aPlayers[param1][iTargetIndex]) - { - StopFollowingPlayer(param1); - } - else - { - StopDisplayingHud(param1); - DisplayMenu(BuildSelectPlayerMenu(), param1, MENU_TIME_FOREVER); - } - } - case 2: - { - if (!g_aPlayers[param1][iTargetIndex]) - { - StopDisplayingHud(param1); - PrintToChat(param1, "\x03[SM-SPEC]\x01 %t", "Must Have Target"); - DisplayMenu(g_aMenus[hSelectPlayer], param1, MENU_TIME_FOREVER); - return; - } - - if ((GetUserFlagBits(param1) & ADMFLAG_GENERIC) || (GetUserFlagBits(param1) & ADMFLAG_ROOT)) - { - if (g_aPlayers[g_aPlayers[param1][iTargetIndex]][bIsFlaggedCheater] && (GetUserFlagBits(param1) & ADMFLAG_ROOT)) - { - //Remove cheater flag - g_aPlayers[g_aPlayers[param1][iTargetIndex]][bIsFlaggedCheater] = false; - } - else - { - //Punish menu - StopDisplayingHud(param1); - DisplayMenu(BuildPunishmentMenu(param1), param1, MENU_TIME_FOREVER); - } - } - else - { - //Report Cheater - new Handle:hPanel = BuildPublicCheaterPanel(); - SendPanelToClient(hPanel, param1, Panel_PublicCheater, MENU_TIME_FOREVER); - CloseHandle(hPanel); - } - } - case 3: - { - StopDisplayingHud(param1); - } - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_Interrupted) - { - if (GetClientMenu(param1) == MenuSource_External) - { - StopDisplayingHud(param1); - } - } - } -} - - -/** -Stock functions -*/ -stock StartFollowingPlayer(client, target) -{ - - /** - If we have an open timer, close it. - */ - if (g_aPlayers[client][hTargetTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[client][hTargetTimer]); - g_aPlayers[client][hTargetTimer] = INVALID_HANDLE; - } - - /** - Make sure the target is on a non spectator team, and the client != target - */ - if (client == target) - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Yourself"); - return; - } - new iTargetTeam = GetClientTeam(target); - if (iTargetTeam == g_aCurrentTeams[Spectator] || iTargetTeam == g_aCurrentTeams[Unknown]) - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Spectator"); - return; - } - - /** - Check to see if client is already a spectator - */ - if (GetClientTeam(client) != g_aCurrentTeams[Spectator]) - { - - /** - Client is not a spectator, lets move them to spec. - */ - SM_MovePlayer(client, g_aCurrentTeams[Spectator]); - } - - /** - If we are using steambans call sb_status - */ - if (g_aPluginSettings[bUseSteamBans]) - { - FakeClientCommandEx(client, "sb_status"); - } - - - /** - Set the global and start to spectate the target. - Making sure it's long enough to deal with moving the client to spec if we had to. - */ - new String:sTargetName[MAX_NAME_LENGTH + 1]; - GetClientName(target, sTargetName, sizeof(sTargetName)); - g_aPlayers[client][iTargetIndex] = target; - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Spectating", sTargetName); - g_aPlayers[client][hTargetTimer] = CreateTimer(0.5, Timer_ResetTarget, client, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); - if (!g_aPlayers[client][bIsDisplayingHud] && GetClientTeam(client) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(client); - } -} - -stock StopFollowingPlayer(client) -{ - - /** - If we have an open timer, close it. - */ - if (g_aPlayers[client][hTargetTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[client][hTargetTimer]); - } - - /** - Tell the client we can't spec his target anymore... if they are in game. - */ - if (IsClientInGame(client) && g_aPlayers[client][iTargetIndex] != 0) - { - new String:sTargetName[MAX_NAME_LENGTH + 1]; - GetClientName(g_aPlayers[client][iTargetIndex], sTargetName, sizeof(sTargetName)); - if (!IsClientConnected(g_aPlayers[client][iTargetIndex]) || !IsClientInGame(g_aPlayers[client][iTargetIndex])) - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Target Left"); - } - else - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Stopped spectating", sTargetName); - } - } - - /** - Null the globals. - */ - g_aPlayers[client][iTargetIndex] = 0; - g_aPlayers[client][hTargetTimer] = INVALID_HANDLE; -} - -stock StartDisplayingHud(client) -{ - if (g_aPluginCvarSettings[bRestrictHud] && !SM_IsValidAdmin(client, g_sAdminFlags)) - { - return; - } - else - { - /** - Double check the hud timer - We should not have one, but if we do, lets cancel it for the current callback - */ - StopDisplayingHud(client); - - /** - Now we can safely display the hud and make sure the current stored handle is the current timer - */ - g_aPlayers[client][bIsDisplayingHud] = true; - g_aPlayers[client][hHudTimer] = CreateTimer(0.5, Timer_UpdateHud, client, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); - } -} - -stock StopDisplayingHud(client) -{ - if (g_aPlayers[client][hHudTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[client][hHudTimer]); - } - g_aPlayers[client][hHudTimer] = INVALID_HANDLE; - g_aPlayers[client][bIsDisplayingHud] = false; -} - -stock ResetClient(client) -{ - StopFollowingPlayer(client); - StopDisplayingHud(client); - - g_aPlayers[client][bIsFlaggedCheater] = false; - g_aPlayers[client][TargetPunishment] = Punish_None; - g_aPlayers[client][iBanTime] = -1; -} - -stock PerformPunishment(client, target, e_Punishments:punishment, const String:reason[], time = 300) -{ - new String:sTargetName[MAX_NAME_LENGTH + 1], - String:sTargetID[64]; - - /** - The target could have left the game by the time we get here - Check for a valid target - */ - if (!IsClientConnected(target) || !IsClientInGame(target)) - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Target Left"); - return; - } - - GetClientName(target, sTargetName, sizeof(sTargetName)); - GetClientAuthString(target, sTargetID, sizeof(sTargetID)); - - switch (punishment) - { - case Punish_Kick: - { - KickClient(g_aPlayers[client][iTargetIndex], "%s", reason); - } - case Punish_Ban: - { - if (g_aPluginSettings[bUseSourceBans]) - { - ClientCommand(client, "sm_ban #%d %d \"%s\"", GetClientUserId(target), time, reason); - } - else if (g_aPluginSettings[bUseMySQLBans]) - { - ClientCommand(client, "mysql_ban #%d %d \"%s\"", GetClientUserId(target), time, reason); - } - else - { - BanClient(target, time, BANFLAG_AUTHID, reason, reason); - } - } - case Punish_Cheater: - { - g_aPlayers[target][bIsFlaggedCheater] = true; - } - case Punish_Beacon: - { - ClientCommand(client, "sm_beacon \"%s\"", sTargetName); - } - case Punish_Blind: - { - ClientCommand(client, "sm_blind \"%s\"", sTargetName); - } - case Punish_Drug: - { - ClientCommand(client, "sm_drug \"%s\"", sTargetName); - } - case Punish_Freeze: - { - ClientCommand(client, "sm_freeze \"%s\"", sTargetName); - } - case Punish_FreezeBomb: - { - ClientCommand(client, "sm_freezebomb \"%s\"", sTargetName); - } - case Punish_Slap: - { - ClientCommand(client, "sm_slap \"%s\" 10", sTargetName); - } - case Punish_Slay: - { - ClientCommand(client, "sm_slay \"%s\"", sTargetName); - } - case Punish_TimeBomb: - { - ClientCommand(client, "sm_timebomb \"%s\"", sTargetName); - } - } - - if (punishment == Punish_Cheater) - { - LogAction(client, target, "[SM SPEC] %N marked %N(%s) with a %s flag for %s", client, target, sTargetID, g_sPunishments[punishment], reason); - } - else - { - ShowActivity(client, "%t", "Punished", sTargetName, g_sPunishments[punishment], reason); - LogAction(client, target, "[SM SPEC] %N punished %N(%s) with a %s for %s", client, target, sTargetID, g_sPunishments[punishment], reason); - } - - /** - Null the globals. - */ - g_aPlayers[client][TargetPunishment] = Punish_None; - g_aPlayers[client][iBanTime] = -1; -} - -/** -Build the menu of player names -*/ -stock Handle:BuildPlayerListMenu() -{ - new Handle:hMenu = CreateMenu(Menu_PlayerList); - AddTargetsToMenu(hMenu, 0, true, false); - SetMenuTitle(hMenu, "Select A Player:"); - SetMenuExitBackButton(hMenu, true); - return hMenu; -} - -/** -Build the select player menu (current or list of players) -*/ -stock Handle:BuildSelectPlayerMenu() -{ - new Handle:hMenu = CreateMenu(Menu_SelectPlayer); - SetMenuTitle(hMenu, "Select A Player:"); - AddMenuItem(hMenu, "Current", "Current Target"); - AddMenuItem(hMenu, "List", "Player List"); - SetMenuExitBackButton(hMenu, true); - return hMenu; -} - -/** -Build the punishmenu menu -*/ -stock Handle:BuildPunishmentMenu(iClient) -{ - new Handle:hMenu = CreateMenu(Menu_Punishments); - SetMenuTitle(hMenu, "Select A Punishment:"); - SetMenuExitBackButton(hMenu, true); - SetMenuExitButton(hMenu, true); - - if (g_aPluginCvarSettings[bKick] && ((GetUserFlagBits(iClient) & ADMFLAG_GENERIC) || (GetUserFlagBits(iClient) & ADMFLAG_ROOT))) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Kick], "Kick"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Kick], "Kick", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bBan] && ((GetUserFlagBits(iClient) & ADMFLAG_GENERIC) || (GetUserFlagBits(iClient) & ADMFLAG_ROOT))) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Ban], "Ban"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Ban], "Ban", ITEMDRAW_DISABLED); - } - - if (g_aPluginSettings[bUseDukehacks] && g_aPluginCvarSettings[bCheater] && (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Cheater], "Flag As Cheater"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Cheater], "Flag As Cheater", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bBeacon]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Beacon], "Beacon"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Beacon], "Beacon", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bBlind]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Blind], "Blind"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Blind], "Blind", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bDrug]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Drug], "Drug"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Drug], "Drug", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bFreeze]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Freeze], "Freeze"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Freeze], "Freeze", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bFreezebomb]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_FreezeBomb], "Freeze Bomb"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_FreezeBomb], "Freeze Bomb", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bSlap]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Slap], "Slap"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Slap], "Slap", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bSlay]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Slay], "Slay"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Slay], "Slay", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bTimeBomb]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_TimeBomb], "Time Bomb"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_TimeBomb], "Time Bomb", ITEMDRAW_DISABLED); - } - - return hMenu; -} - -/** -Build the punishmenu menu -*/ -stock Handle:BuildBanTimeMenu() -{ - new Handle:hMenu = CreateMenu(Menu_BanTime); - SetMenuTitle(hMenu, "Select Ban Type:"); - - if (g_aPluginCvarSettings[bBanPerm]) - { - AddMenuItem(hMenu, "permban", "Permanent"); - } - else - { - AddMenuItem(hMenu, "permban", "Permanent", ITEMDRAW_DISABLED); - } - - AddMenuItem(hMenu, "10", "10 Minutes"); - AddMenuItem(hMenu, "30", "30 Minutes"); - AddMenuItem(hMenu, "60", "1 Hour"); - AddMenuItem(hMenu, "240", "4 Hours"); - AddMenuItem(hMenu, "1440", "1 Day"); - AddMenuItem(hMenu, "10080", "1 Week"); - - SetMenuExitBackButton(hMenu, true); - return hMenu; -} - -/** -Build the punishmenu menu -*/ -stock Handle:BuildReasonMenu() -{ - new Handle:hMenu = CreateMenu(Menu_Reason); - SetMenuTitle(hMenu, "Select A Reason:"); - - AddMenuItem(hMenu, "Abusive", "Abusive"); - AddMenuItem(hMenu, "Racism", "Racism"); - AddMenuItem(hMenu, "General cheating/exploits", "General cheating/exploits"); - AddMenuItem(hMenu, "Wallhack", "Wallhack"); - AddMenuItem(hMenu, "Aimbot", "Aimbot"); - AddMenuItem(hMenu, "Speedhacking", "Speedhacking"); - AddMenuItem(hMenu, "Mic spamming", "Mic spamming"); - AddMenuItem(hMenu, "Admin disrepect", "Admin disrepect"); - AddMenuItem(hMenu, "Camping", "Camping"); - AddMenuItem(hMenu, "Team killing", "Team killing"); - AddMenuItem(hMenu, "Unacceptable Spray", "Unacceptable Spray"); - AddMenuItem(hMenu, "Breaking Server Rules", "Breaking Server Rules"); - AddMenuItem(hMenu, "Other", "Other"); - - SetMenuExitBackButton(hMenu, true); - return hMenu; -} - -/** -Build the cheater displays -*/ -stock Handle:BuildAdminCheaterPanel() -{ - - /** - Create the menu and set the menu options. - */ - new Handle:hPanel = CreatePanel(); - SetPanelTitle(hPanel, "Simple Spectator:"); - - DrawPanelText(hPanel, "Are you sure you want to"); - DrawPanelText(hPanel, "flag this player as a cheater?"); - DrawPanelText(hPanel, "They will not be able to damage"); - DrawPanelText(hPanel, "anyone and die on fall damage."); - DrawPanelItem(hPanel, "Yes"); - DrawPanelItem(hPanel, "No"); - - return hPanel; -} - -stock Handle:BuildPublicCheaterPanel() -{ - - /** - Create the menu and set the menu options. - */ - new Handle:hPanel = CreatePanel(); - SetPanelTitle(hPanel, "Simple Spectator:"); - - DrawPanelText(hPanel, "Are you sure you want to"); - DrawPanelText(hPanel, "submit this player as a cheater?"); - DrawPanelItem(hPanel, "Yes (Not Implemented Yet)", ITEMDRAW_DISABLED); - DrawPanelItem(hPanel, "No"); - return hPanel; -} - -/** -Build the hud displays -*/ -stock Handle:BuildPlayerHudMenu(iClient, iTarget) -{ - - /** - Create all the string variables we will need - */ - new String:sTargetName[MAX_NAME_LENGTH + 1], - String:sTargetID[64], - String:sTargetIP[16]; - - new String:sDisplayName[MAX_NAME_LENGTH + 1], - String:sDisplayID[64], - String:sDisplayIP[64], - String:sDisplayFrags[16], - String:sDisplayDeaths[16]; - - new iTargetFrags, - iTargetDeaths; - - /** - Get the targets information - */ - GetClientName(iTarget, sTargetName, sizeof(sTargetName)); - GetClientIP(iTarget, sTargetIP, sizeof(sTargetIP)); - GetClientAuthString(iTarget, sTargetID, sizeof(sTargetID)); - iTargetFrags = GetClientFrags(iTarget); - iTargetDeaths = GetClientDeaths(iTarget); - - /** - Format the strings for the menu - */ - Format(sDisplayName, sizeof(sDisplayName), "Player: %s", sTargetName); - Format(sDisplayID, sizeof(sDisplayID), "Steam ID: %s", sTargetID); - Format(sDisplayIP, sizeof(sDisplayIP), "IP Address: %s", sTargetIP); - Format(sDisplayFrags, sizeof(sDisplayFrags), "Kills: %i", iTargetFrags); - Format(sDisplayDeaths, sizeof(sDisplayDeaths), "Deaths: %i", iTargetDeaths); - - /** - Create the menu and set the menu options. - */ - new Handle:hMenu = CreateMenu(Menu_PlayerHud); - SetMenuExitBackButton(hMenu, false); - SetMenuTitle(hMenu, "Simple Spectator"); - - AddMenuItem(hMenu, "name", sDisplayName, ITEMDRAW_DISABLED); - AddMenuItem(hMenu, "steamid", sDisplayID, ITEMDRAW_DISABLED); - - if (SM_IsValidAdmin(iClient, g_sAdminFlags)) - { - AddMenuItem(hMenu, "ip", sDisplayIP, ITEMDRAW_DISABLED); - } - - AddMenuItem(hMenu, "kills", sDisplayFrags, ITEMDRAW_DISABLED); - AddMenuItem(hMenu, "deaths", sDisplayDeaths, ITEMDRAW_DISABLED); - - if (g_aPlayers[iClient][iTargetIndex]) - { - AddMenuItem(hMenu, "stop", "Stop Following"); - } - else - { - AddMenuItem(hMenu, "start", "Follow Player"); - } - - if ((GetUserFlagBits(iClient) & ADMFLAG_GENERIC) || (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - if (g_aPlayers[iTarget][bIsFlaggedCheater] && (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - AddMenuItem(hMenu, "removecheater", "Remove Cheater Flag"); - } - else - { - if (CanUserTarget(iClient, iTarget)) - { - AddMenuItem(hMenu, "punish", "Punish Player"); - } - else - { - AddMenuItem(hMenu, "punish", "Punish Player (Immune)", ITEMDRAW_DISABLED); - } - } - } - else - { - AddMenuItem(hMenu, "reportcheater", "Report Cheater"); - } - - SetMenuPagination(hMenu, MENU_NO_PAGINATION); - SetMenuExitButton(hMenu, true); - return hMenu; -} - -stock Handle:BuildPlayerHudPanel(iClient, iTarget) -{ - - /** - Create all the string variables we will need - */ - new String:sTargetName[MAX_NAME_LENGTH + 1], - String:sTargetID[64], - String:sTargetIP[16]; - - new String:sDisplayName[MAX_NAME_LENGTH + 1], - String:sDisplayID[64], - String:sDisplayIP[64], - String:sDisplayFrags[16], - String:sDisplayDeaths[16]; - - new iTargetFrags, - iTargetDeaths; - - /** - Get the targets information - */ - GetClientName(iTarget, sTargetName, sizeof(sTargetName)); - GetClientIP(iTarget, sTargetIP, sizeof(sTargetIP)); - GetClientAuthString(iTarget, sTargetID, sizeof(sTargetID)); - iTargetFrags = GetClientFrags(iTarget); - iTargetDeaths = GetClientDeaths(iTarget); - - /** - Format the strings for the menu - */ - Format(sDisplayName, sizeof(sDisplayName), "Player: %s", sTargetName); - Format(sDisplayID, sizeof(sDisplayID), "Steam ID: %s", sTargetID); - Format(sDisplayIP, sizeof(sDisplayIP), "IP Address: %s", sTargetIP); - Format(sDisplayFrags, sizeof(sDisplayFrags), "Kills: %i", iTargetFrags); - Format(sDisplayDeaths, sizeof(sDisplayDeaths), "Deaths: %i", iTargetDeaths); - - /** - Create the menu and set the menu options. - */ - new Handle:hPanel = CreatePanel(); - SetPanelTitle(hPanel, "Simple Spectator"); - - DrawPanelText(hPanel, "Player Information:"); - DrawPanelText(hPanel, sDisplayName); - DrawPanelText(hPanel, sDisplayID); - if (SM_IsValidAdmin(iClient, g_sAdminFlags)) - { - DrawPanelText(hPanel, sDisplayIP); - } - - DrawPanelText(hPanel, sDisplayFrags); - DrawPanelText(hPanel, sDisplayDeaths); - - if (g_aPlayers[iClient][iTargetIndex]) - { - DrawPanelItem(hPanel, "Stop Following"); - } - else - { - DrawPanelItem(hPanel, "Follow Player"); - } - - if ((GetUserFlagBits(iClient) & ADMFLAG_GENERIC) || (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - if (g_aPlayers[iTarget][bIsFlaggedCheater] && (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - DrawPanelItem(hPanel, "Remove Cheater Flag"); - } - else - { - if (CanUserTarget(iClient, iTarget)) - { - DrawPanelItem(hPanel, "Punish Player"); - } - else - { - DrawPanelItem(hPanel, "Punish Player (Immune)", ITEMDRAW_DISABLED); - } - } - } - else - { - DrawPanelItem(hPanel, "Report Cheater"); - } - - DrawPanelItem(hPanel, "Close Hud Panel"); - return hPanel; -} - -/** -Adjust the settings if a convar was changed -*/ -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - for (new iCvar = 0 ; _:iCvar < sizeof(g_aPluginCvarSettings); iCvar++) - { - if (g_aPluginCvar[_:iCvar] == convar) - { - if (StringToInt(newValue) == 1) - { - g_aPluginCvarSettings[_:iCvar] = true; - } - else - { - g_aPluginCvarSettings[_:iCvar] = false; - } - } - } - - /* - ReBuild the global menu that depends on cvars - */ - g_aMenus[hBanTime] = BuildBanTimeMenu(); - - /** - Run a loop to reset the hud - */ - for(new i = 1; i <= MaxClients; i++) - { - StopDisplayingHud(i); - if (IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(i); - } - } -} diff --git a/Simple AllTalk Manager/addons/sourcemod/scripting/simple-teambalancer.sp b/Simple AllTalk Manager/addons/sourcemod/scripting/simple-teambalancer.sp deleted file mode 100644 index 3302255..0000000 --- a/Simple AllTalk Manager/addons/sourcemod/scripting/simple-teambalancer.sp +++ /dev/null @@ -1,1797 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Team Balancer -Description: - Balances teams based upon player count - Player will not be balanced more than once in 5 (default) mins - Buddy system tries to keep buddies together - Ability to prioritize players - Ability to force players to accept the new team - Admins are immune -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include -#include - -#define PLUGIN_VERSION "2.1.$Rev$" - -enum PlayerData -{ - Handle:hBalanceTimer, - Handle:hForcedTimer, - bool:bSwitched, - bool:bFlagCarrier -}; - -/** - Global convar handles - */ -new Handle:stb_enabled = INVALID_HANDLE; -new Handle:stb_buddyenabled = INVALID_HANDLE; -new Handle:stb_logactivity = INVALID_HANDLE; -new Handle:stb_logactivity2 = INVALID_HANDLE; -new Handle:stb_unbalancelimit = INVALID_HANDLE; -new Handle:stb_deadonly = INVALID_HANDLE; -new Handle:stb_priorityenabled = INVALID_HANDLE; -new Handle:stb_uberlevel = INVALID_HANDLE; -new Handle:stb_balancedelay = INVALID_HANDLE; -new Handle:stb_livingplayerswitchdelay = INVALID_HANDLE; -new Handle:stb_livingplayercheckdelay = INVALID_HANDLE; -new Handle:stb_roundstartdelay = INVALID_HANDLE; -new Handle:stb_switchbackforced = INVALID_HANDLE; -new Handle:stb_adminflag = INVALID_HANDLE; -new Handle:stb_buddyrestriction = INVALID_HANDLE; -new Handle:stb_convarcontrol = INVALID_HANDLE; - -/** - Built-in cvars handles - */ -new Handle:stb_mp_autoteambalance = INVALID_HANDLE; -new Handle:stb_mp_teams_unbalance_limit = INVALID_HANDLE; -new Handle:TFGameModeArena = INVALID_HANDLE; - -/** - Timer handles - */ -new Handle:g_hBalanceTimer = INVALID_HANDLE; -new Handle:g_hLivingPlayerCheckTimer = INVALID_HANDLE; - -/** - Player arrays - */ -new g_aPlayers[MAXPLAYERS + 1][PlayerData]; - -/** -Global bools -*/ -new bool:g_bIsEnabled = true; -new bool:g_bPriorityPlayers = true; -new bool:g_bBuddyRestriction = false; -new bool:g_bLogActivity = false; -new bool:g_bLogActivity2 = false; -new bool:g_bDeadOnly = false; -new bool:g_bConVarControl = true; -new bool:g_bBuddyEnabled = true; -new bool:g_bBalanceInProgress = false; -new bool:g_bRoundStart = false; -new bool:g_bRoundEnd = false; -new bool:g_bSuddenDeath = false; -new bool:g_bIsArenaMode = false; - -/** - Global strings/integers/floats - */ -new g_iUnbalanceLimit, g_iLivingPlayerSwitchDelay, g_iLivingPlayerCheckDelay; -new g_iRoundStartDelay, g_iSwitchBackForced, g_iBalanceDelay; -new Float:g_fUberLevel; -new g_iOwnerOffset; -new String:g_sAdminFlag[5]; - -public Plugin:myinfo = -{ - name = "Simple Team Balancer", - author = "Simple Plugins", - description = "Balances teams based upon player count.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -} - -public OnPluginStart() -{ - - /** - Create console variables - */ - CreateConVar("stb_version", PLUGIN_VERSION, "Simple Team Balancer", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - stb_enabled = CreateConVar("stb_enabled", "1", "Enable or Disable Simple Team Balancer", _, true, 0.0, true, 1.0); - stb_priorityenabled = CreateConVar("stb_priorityenabled", "1", "Enable or Disable the prioritization of living players", _, true, 0.0, true, 1.0); - stb_buddyrestriction = CreateConVar("stb_buddyrestriction", "0", "Enable or Disable Admin Only buddy lists", _, true, 0.0, true, 1.0); - stb_logactivity = CreateConVar("stb_logactivity", "0", "Enable or Disable the disaplying of events in the log", _, true, 0.0, true, 1.0); - stb_logactivity2 = CreateConVar("stb_logactivity2", "0", "Enable or Disable the disaplying of detailed events in the log (WILL SPAM LOG)", _, true, 0.0, true, 1.0); - stb_deadonly = CreateConVar("stb_deadonly", "0", "Enable or Disable the switching of only dead players", _, true, 0.0, true, 1.0); - stb_convarcontrol = CreateConVar("stb_convarcontrol", "1", "Enable or Disable the control of builtin console variables", _, true, 0.0, true, 1.0); - stb_buddyenabled = CreateConVar("stb_buddyenabled", "1", "Enable or Disable the buddy system", _, true, 0.0, true, 1.0); - stb_unbalancelimit = CreateConVar("stb_unbalancelimit", "2", "Amount of players teams are ALLOWED to be unbalanced by", _, true, 1.0, true, 32.0); - stb_balancedelay = CreateConVar("stb_balancedelay", "10", "Delay in seconds to start an autobalance"); - stb_livingplayerswitchdelay = CreateConVar("stb_livingplayerswitchdelay", "20", "Delay in seconds to switch living players once selected"); - stb_livingplayercheckdelay = CreateConVar("stb_livingplayercheckdelay", "10", "Delay in seconds to start checking living players once teams become unbalanced"); - stb_roundstartdelay = CreateConVar("stb_roundstartdelay", "15", "Delay in seconds to start balancing teams after the start of a round"); - stb_switchbackforced = CreateConVar("stb_switchbackforced", "300", "Amount of time in seconds to not switch a player twice and force the team if enabled"); - stb_uberlevel = CreateConVar("stb_uberlevel", "1.0", "Min uber level medic must have to have priority over other living players. Setting to 0 will rarely switch a living medic", _, true, 0.0, true, 1.0); - stb_adminflag = CreateConVar("stb_adminflag", "a", "Admin flag to use for immunity. Must be a in char format."); - stb_mp_autoteambalance = FindConVar("mp_autoteambalance"); - stb_mp_teams_unbalance_limit = FindConVar("mp_teams_unbalance_limit"); - - /** - Removing the notify tags from the built in cvars. We dont want spam. - */ - if (stb_mp_autoteambalance != INVALID_HANDLE) - { - SetConVarFlags(stb_mp_autoteambalance, GetConVarFlags(stb_mp_autoteambalance)^FCVAR_NOTIFY); - } - if (stb_mp_teams_unbalance_limit != INVALID_HANDLE) - { - SetConVarFlags(stb_mp_teams_unbalance_limit, GetConVarFlags(stb_mp_teams_unbalance_limit)^FCVAR_NOTIFY); - } - - /** - Hook console variables - */ - HookConVarChange(stb_enabled, ConVarSettingsChanged); - HookConVarChange(stb_priorityenabled, ConVarSettingsChanged); - HookConVarChange(stb_buddyrestriction, ConVarSettingsChanged); - HookConVarChange(stb_logactivity, ConVarSettingsChanged); - HookConVarChange(stb_logactivity2, ConVarSettingsChanged); - HookConVarChange(stb_deadonly, ConVarSettingsChanged); - HookConVarChange(stb_convarcontrol, ConVarSettingsChanged); - HookConVarChange(stb_buddyenabled, ConVarSettingsChanged); - HookConVarChange(stb_unbalancelimit, ConVarSettingsChanged); - HookConVarChange(stb_balancedelay, ConVarSettingsChanged); - HookConVarChange(stb_livingplayerswitchdelay, ConVarSettingsChanged); - HookConVarChange(stb_livingplayercheckdelay, ConVarSettingsChanged); - HookConVarChange(stb_roundstartdelay, ConVarSettingsChanged); - HookConVarChange(stb_switchbackforced, ConVarSettingsChanged); - HookConVarChange(stb_uberlevel, ConVarSettingsChanged); - HookConVarChange(stb_mp_autoteambalance, ConVarSettingsChanged); - HookConVarChange(stb_mp_teams_unbalance_limit, ConVarSettingsChanged); - - /** - Create console commands - */ - RegConsoleCmd("sm_buddy", Command_AddBalanceBuddy, "Add a balance buddy"); - RegConsoleCmd("sm_lockbuddy", Command_LockBuddy, "Locks your balance buddy selection"); - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[STB] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_death", HookPlayerDeath, EventHookMode_Post); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Post); - switch (g_CurrentMod) - { - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - HookEvent("teamplay_suddendeath_begin", HookSuddenDeathBegin, EventHookMode_PostNoCopy); - HookEvent("teamplay_flag_event", HookFlagEvent, EventHookMode_Post); - TFGameModeArena = FindConVar("tf_gamemode_arena"); - g_iOwnerOffset = FindSendPropInfo("CBaseObject", "m_hBuilder"); - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_Post); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - - /** - Load translations and .cfg file - */ - LoadTranslations ("simpleteambalancer.phrases"); - AutoExecConfig(true, "plugin.simpleteambalancer"); - LogAction(0, -1, "[STB] Simple Team Balancer is loaded."); -} - -public OnAllPluginsLoaded() -{ - //something -} - -public OnLibraryRemoved(const String:name[]) -{ - //something -} - -public OnConfigsExecuted() -{ - - /** - Load up global variables - */ - g_bIsEnabled = GetConVarBool(stb_enabled); - g_bBuddyEnabled = GetConVarBool(stb_buddyenabled); - g_bLogActivity = GetConVarBool(stb_logactivity); - g_bLogActivity2 = GetConVarBool(stb_logactivity2); - g_bDeadOnly = GetConVarBool(stb_deadonly); - g_bPriorityPlayers = GetConVarBool(stb_priorityenabled); - g_bBuddyRestriction = GetConVarBool(stb_buddyrestriction); - g_bConVarControl = GetConVarBool(stb_convarcontrol); - g_fUberLevel = GetConVarFloat(stb_uberlevel); - g_iUnbalanceLimit = GetConVarInt(stb_unbalancelimit); - g_iBalanceDelay = GetConVarInt(stb_balancedelay); - g_iLivingPlayerSwitchDelay = GetConVarInt(stb_livingplayerswitchdelay); - g_iLivingPlayerCheckDelay = GetConVarInt(stb_livingplayercheckdelay); - g_iRoundStartDelay = GetConVarInt(stb_roundstartdelay); - g_iSwitchBackForced = GetConVarInt(stb_switchbackforced); - GetConVarString(stb_adminflag, g_sAdminFlag, sizeof(g_sAdminFlag)); - - /** - Report enabled - */ - if (g_bIsEnabled) - { - LogAction(0, -1, "[STB] Simple Team Balancer is ENABLED."); - } - else - { - LogAction(0, -1, "[STB] Simple Team Balancer is DISABLED."); - } - - - /** - Report log activity - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Log Activity ENABLED."); - } - else - { - LogAction(0, -1, "[STB] Log Activity DISABLED."); - } - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Detailed Log Activity ENABLED."); - } - else - { - LogAction(0, -1, "[STB] Detailed Log Activity DISABLED."); - } -} - -public OnMapStart() -{ - - /** - Check for arena mode - */ - if (g_CurrentMod == GameType_TF && GetConVarBool(TFGameModeArena)) - { - g_bIsArenaMode = true; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Simple Team Balancer detected arena mode and will be bypassed"); - } - } - else - { - g_bIsArenaMode = false; - } - - /** - Reset the globals - */ - g_bBalanceInProgress = false; - g_bRoundStart = false; - g_bRoundEnd = false; - g_bSuddenDeath = false; - - /** - Set the built-in convars - */ - SetGameCvars(); -} - -public OnClientPostAdminCheck(client) -{ - - /** - Make sure its a valid connected client and buddy system is enabled - */ - if (client == 0 || !g_bIsEnabled || !IsClientConnected(client) || !g_bBuddyEnabled) - { - return; - } - - /** - Make sure if its set for admins only they have the flags - */ - if (g_bBuddyRestriction && !SM_IsValidAdmin(client, g_sAdminFlag)) - { - return; - } - - /** - Start the advertisement timer - */ - CreateTimer (60.0, Timer_WelcomeAdvert, client); -} - -public OnClientDisconnect(client) -{ - - /** - Call stock function to cleaup - */ - CleanUp(client); -} - -public OnClientDisconnect_Post(client) -{ - - /** - Determine if we need a balance - */ - if (OkToBalance() && IsUnbalanced() && !g_bBalanceInProgress) - { - - /** - No balance in progress but balance is needed - */ - StartABalance(); - } -} - -public SM_OnPlayerMoved(Handle:plugin, client, team) -{ - - /** - Make sure we called the move function - */ - if (plugin != GetMyHandle()) - { - if (g_bLogActivity2) - { - LogAction(0, client, "[STB] Callback was not started with current plugin, bugging out."); - } - return; - } - - /** - Get the players name and report the event - */ - decl String:sPlayerName[64]; - GetClientName(client, sPlayerName, sizeof(sPlayerName)); - if (g_bLogActivity) - { - LogAction(0, client, "[STB] Changed %s to team %i.", sPlayerName, team); - } - - /** - If we are in TF2 fire the bult-in team balance event - */ - if(g_CurrentMod == GameType_TF) - { - new Handle:event = CreateEvent("teamplay_teambalanced_player"); - SetEventInt(event, "player", client); - SetEventInt(event, "team", team); - FireEvent(event); - } - - /** - Notify the players - */ - PrintToChatAll("[SM] %T", "BalanceMessage", LANG_SERVER, sPlayerName); - - /** - Set the players variables and start a timer - */ - g_aPlayers[client][bSwitched] = true; - g_aPlayers[client][hForcedTimer] = CreateTimer(float(g_iSwitchBackForced), Timer_ForcedExpired, client, TIMER_FLAG_NO_MAPCHANGE); - - /** - We are done, log the completion and end the balance - */ - if (g_bLogActivity) - { - LogAction(0, client, "[STB] Balance finished."); - } - g_bBalanceInProgress = false; -} - -/* HOOKED EVENTS */ - -public HookPlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get our event variables - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - decl String:sWeapon[64]; - GetEventString(event, "weapon", sWeapon, sizeof(sWeapon)); - - /** - Return if death was not caused by a player - This is the case when the player switches teams - */ - if (StrEqual(sWeapon, "world", false)) - { - return; - } - - - /** - Check if balance is needed - */ - if (IsClientInGame(iClient) && OkToBalance() && IsUnbalanced()) - { - new iSmallerTeam = GetSmallerTeam(); - - /** - Check if balance is in progress - */ - if (g_bBalanceInProgress) - { - - /** - There is a balance in progress - Check the player who died to see if he is supposed to be switched - */ - if (g_aPlayers[iClient][hBalanceTimer] != INVALID_HANDLE) - { - - /** - The player has a timer on him to switch him to other team - Stop the timer - */ - CloseHandle(g_aPlayers[iClient][hBalanceTimer]); - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] With a balance in progress the queued living player died and was switched."); - } - - /** - Call the stock change team function - */ - BalancePlayer(iClient, SM_GetForcedTeam(iClient)); - return; - } - - /** - Before we continue, lets make sure the client is switchable - */ - if (IsSwitchablePlayer(iClient, GetBiggerTeam())) - { - - /** - Now we check the buddy system - */ - if (g_bBuddyEnabled) - { - - /** - Buddy system is enabled, check to see if client has buddy - */ - new iBuddyIndex = SM_GetClientBuddy(iClient); - if (iBuddyIndex != 0 || !IsClientConnected(iBuddyIndex) || !IsClientInGame(iBuddyIndex)) - { - - /** - The client has a buddy, so we check to see if they are on same team - */ - if (GetClientTeam(iClient) == GetClientTeam(iBuddyIndex)) - { - - /** - They are, but we don't bug out, we still need to start a balance - */ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] With a balance in progress a buddy on the right team was found and skipped."); - } - } - else - { - - /** - They are not on the same team - The buddy could be in spec, and that would make it not matter where he is, or the buddy is on the smaller team - */ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] With a balance in progress a buddy on the wrong team was switched."); - } - BalancePlayer(iClient, iSmallerTeam); - return; - } - } - else - { - - /** - Client doesn't have a buddy, balance this player - */ - BalancePlayer(iClient, iSmallerTeam); - return; - } - } - else - { - - /** - Buddy system is not enabled, balance this player - */ - BalancePlayer(iClient, iSmallerTeam); - return; - } - } - } - else - { - - /** - If we get to here then we must need to start a balance - */ - StartABalance(); - } - } -} - -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get our event variables. - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - new iTeam = GetEventInt(event, "team"); - - /** - Make sure its ok to balance. - */ - if (OkToBalance()) - { - - /** - See if the client that changed teams was set to with a balance. - */ - if (g_aPlayers[iClient][hBalanceTimer] != INVALID_HANDLE - && SM_GetForcedTeam(iClient) == iTeam - && g_bBalanceInProgress) - { - - /** - The client was set to be balanced, so we close the timer. - */ - CloseHandle(g_aPlayers[iClient][hBalanceTimer]); - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - - /** - Stop the balance. - */ - g_bBalanceInProgress = false; - return; - } - - /** - It's not likely that this team change can cause us to need a balance. - If it does, start one with a small dealy to deal with forced switch backs. - */ - if (IsUnbalanced() && !g_bBalanceInProgress) - { - CreateTimer(2.0, Timer_ChangeTeamBalanceDelay, _, TIMER_FLAG_NO_MAPCHANGE); - } - } -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set the variables we need to start a round - */ - g_bRoundStart = true; - g_bRoundEnd = false; - g_bSuddenDeath = false; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Round Started"); - } - - /** - Start a delayed balance check at the start of the round - */ - CreateTimer(float(g_iRoundStartDelay), Timer_RoundStart); -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set the variables we need at round end - */ - g_bRoundEnd = true; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Round Ended"); - } -} - -public HookSuddenDeathBegin(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set the variables we need for sudden death - */ - g_bSuddenDeath = true; -} - -public HookFlagEvent(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get our event variables - */ - new iClient = GetEventInt(event, "player"); - new iFlagStatus = GetEventInt(event, "eventtype"); - - /** - Make sure we have a valid client - */ - if (!IsClientInGame(iClient)) - { - return; - } - - /** - Determine what kind of event this is - */ - switch (iFlagStatus) - { - case 1: - { - - /** - The flag was picked up - */ - g_aPlayers[iClient][bFlagCarrier] = true; - } - case 2: - { - - /** - The flag was capped - */ - g_aPlayers[iClient][bFlagCarrier] = false; - } - case 3: - { - - /** - The flag was defended, we don't have to do anything - */ - } - case 4: - { - - /** - The flag was dropped - */ - g_aPlayers[iClient][bFlagCarrier] = false; - } - } -} - -/* COMMAND EVENTS */ - -public Action:Command_AddBalanceBuddy(client, args) -{ - if (client == 0) - { - ReplyToCommand(client, "[SM] %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - if (!g_bIsEnabled || !g_bBuddyEnabled) - { - ReplyToCommand(client, "[SM] %T", "CmdDisabled", LANG_SERVER); - return Plugin_Handled; - } - if (g_bBuddyRestriction) - { - if (!SM_IsValidAdmin(client, g_sAdminFlag)) - { - ReplyToCommand(client, "[SM] %T", "RestrictedBuddy", LANG_SERVER); - return Plugin_Handled; - } - } - decl String:sPlayerUserId[24]; - GetCmdArg(1, sPlayerUserId, sizeof(sPlayerUserId)); - new iPlayer = GetClientOfUserId(StringToInt(sPlayerUserId)); - if (!iPlayer || !IsClientInGame(iPlayer) || client == iPlayer) - { - if (client == iPlayer) - { - PrintHintText(client, "%T", "SelectSelf", LANG_SERVER); - } - ReplyToCommand(client, "[SM] Usage: buddy "); - new Handle:playermenu = BuildPlayerMenu(); - DisplayMenu(playermenu, client, MENU_TIME_FOREVER); - } - else - { - decl String:cName[128]; - decl String:bName[128]; - GetClientName(client, cName, sizeof(cName)); - GetClientName(iPlayer, bName, sizeof(bName)); - if (SM_IsBuddyLocked(iPlayer)) - { - ReplyToCommand(client, "[SM] %T", "PlayerLockedBuddyMsg", LANG_SERVER, bName); - return Plugin_Handled; - } - SM_AssignBuddy(client, iPlayer); - PrintHintText(client, "%T", "BuddyMsg", LANG_SERVER, bName); - PrintHintText(iPlayer, "%T", "BuddyMsg", LANG_SERVER, cName); - } - return Plugin_Handled; -} - -public Action:Command_LockBuddy(client, args) -{ - if (client == 0) - { - ReplyToCommand(client, "[SM] %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - if (!g_bIsEnabled) - { - ReplyToCommand(client, "[SM] %T", "CmdDisabled", LANG_SERVER); - return Plugin_Handled; - } - if (g_bBuddyRestriction) - { - if (!SM_IsValidAdmin(client, g_sAdminFlag)) - { - ReplyToCommand(client, "[SM] %T", "RestrictedBuddy", LANG_SERVER); - return Plugin_Handled; - } - } - if (SM_IsBuddyLocked(client)) - { - SM_LockBuddy(client, false); - PrintHintText(client, "%T", "BuddyLockMsgDisabled", LANG_SERVER); - } - else - { - SM_LockBuddy(client, true); - PrintHintText(client, "%T", "BuddyLockMsgEnabled", LANG_SERVER); - } - return Plugin_Handled; -} - -/** -Stock functions . - */ - -stock bool:IsUnbalanced() -{ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Checking if teams are unbalanced"); - } - new Team1Count = GetTeamClientCount(g_aCurrentTeams[Team1]); - new Team2Count = GetTeamClientCount(g_aCurrentTeams[Team2]); - new ubCount = RoundFloat(FloatAbs(float(Team1Count - Team2Count))); - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Team1:%i Team2:%i Difference:%i", Team1Count, Team2Count, ubCount); - } - if (ubCount > g_iUnbalanceLimit) - { - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Teams are unbalanced"); - } - return true; - } - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Teams are not unbalanced"); - } - return false; -} - -stock bool:OkToBalance() -{ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Checking if OK to balance."); - } - new bool:bResult = false; - if (g_bIsEnabled && !g_bRoundStart && !g_bRoundEnd && !g_bIsArenaMode && !g_bSuddenDeath) - { - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Passed IF statement"); - LogAction(0, -1, "[STB] Now checking admins"); - } - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientInGame(i) && !SM_IsValidAdmin(i, g_sAdminFlag)) - { - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Found at least 1 non-admin"); - LogAction(0, -1, "[STB] OK to balance"); - } - bResult = true; - break; - } - } - if (!bResult && g_bLogActivity2) - { - LogAction(0, -1, "[STB] All admins online"); - } - } - if (!bResult && g_bLogActivity2) - { - LogAction(0, -1, "[STB] Not OK to balance"); - } - return bResult; -} - -stock bool:IsSwitchablePlayer(iClient, iBiggerTeam) -{ - - /** - Run the client thru some standard checks - */ - if (!IsClientInGame(iClient) - || SM_IsValidAdmin(iClient, g_sAdminFlag) - || g_aPlayers[iClient][bFlagCarrier] - || GetClientTeam(iClient) != iBiggerTeam - || g_aPlayers[iClient][bSwitched]) - { - - /** - The supplied client can't be switched - */ - return false; - } - - /** - The supplied client can be switched - */ - return true; -} - -stock bool:HasUber(iClient) -{ - - /** - First things first, make sure the client is a medic - */ - if(TF2_GetPlayerClass(iClient) == TFClass_Medic) - { - - /** - We can only check the active weapon, so make sure the client is holding the uber gun - */ - decl String:sWeaponName[32]; - GetClientWeapon(iClient, sWeaponName, sizeof(sWeaponName)); - if(StrEqual(sWeaponName, "tf_weapon_medigun")) - { - - /** - They are, so lets check the uber level of the gun - */ - new iEntityIndex = GetEntDataEnt2(iClient, FindSendPropInfo("CTFPlayer", "m_hActiveWeapon")); - new Float:fChargeLevel = GetEntDataFloat(iEntityIndex, FindSendPropInfo("CWeaponMedigun", "m_flChargeLevel")); - if (fChargeLevel >= g_fUberLevel) - { - - /** - The client supplied has an uber above the supplied level, return true - */ - if (g_bLogActivity2) - { - LogAction(0, iClient, "[STB] Found a medic with a uber and skipped him."); - } - return true; - } - } - } - - /** - The client supplied does not have an uber above the supplied level, return false - */ - return false; -} - -stock bool:HasBuildingsBuilt(iClient) -{ - - /** - We have to start a loop to check the owner of all the valid entities - */ - new iMaxEntities = GetMaxEntities(); - for (new i = MaxClients + 1; i <= iMaxEntities; i++) - { - if (!IsValidEntity(i)) - { - - /** - Not valid, continue to next one - */ - continue; - } - - /** - Get the name of the current entity - */ - decl String:sNetClass[32]; - GetEntityNetClass(i, sNetClass, sizeof(sNetClass)); - - /** - See if its something that an engineer would build - */ - if (strcmp(sNetClass, "CObjectSentrygun") == 0 - || strcmp(sNetClass, "CObjectTeleporter") == 0 - || strcmp(sNetClass, "CObjectDispenser") == 0) - { - - /** - It is, so lets check the owner - */ - if (GetEntDataEnt2(i, g_iOwnerOffset) == iClient) - { - - /** - The client supplied is the owner, return true - */ - if (g_bLogActivity2) - { - LogAction(0, iClient, "[STB] Found an engineer with buildings and skipped him."); - } - return true; - } - } - } - - /** - The client supplied didn't have any buildings, return false - */ - return false; -} - -stock StartABalance() -{ - - /** - See if we are already started a balance - */ - if (g_hBalanceTimer != INVALID_HANDLE) - { - - /** - We have, check if we still need to - */ - if (!IsUnbalanced() || !OkToBalance()) - { - - /** - We don't, stop the balance - It's almost impossible to reach this code, but we do it just in case - */ - CloseHandle(g_hBalanceTimer); - g_hBalanceTimer = INVALID_HANDLE; - g_bBalanceInProgress = false; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Balance delay timer was not needed and was killed before the callback."); - } - return; - } - else - { - - /** - We still need to balance - Bug out and wait for the current one to finish - */ - return; - } - } - - /** - Report that teams are unbalanced - */ - PrintToChatAll("[SM] %T", "UnBalanced", LANG_SERVER); - - /** - Check to see if we are supposed to delay the balance - */ - if (g_iBalanceDelay == 0) - { - - /** - Start the balance now - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Balance is now in progress."); - } - g_bBalanceInProgress = true; - g_hBalanceTimer = INVALID_HANDLE; - - /** - Check if we are allowed to scan living players - */ - if (!g_bDeadOnly) - { - - /** - We are allowed to, so we start a timer - */ - StartALivingPlayerTimer(); - - /** - Also report that we are now scanning dead players as well - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Now scanning dead players."); - } - } - else - { - - /** - We are not allowed to, so report that we are only scanning dead players - */ - if (g_bLogActivity) - LogAction(0, -1, "[STB] Only scanning dead players."); - } - - /** - We started the balance, bug out - */ - return; - } - - /** - We are supposed to delay the balance, start a balance timer - */ - g_hBalanceTimer = CreateTimer(float(g_iBalanceDelay), Timer_BalanceTeams, _, TIMER_FLAG_NO_MAPCHANGE); - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Teams are unbalanced. Balance delay timer started."); - } -} - -stock StartALivingPlayerTimer() -{ - - /** - Start a timer to check living players - */ - if (g_hLivingPlayerCheckTimer != INVALID_HANDLE) - { - - /** - If we for some reason already have one started, stop it. - */ - CloseHandle(g_hLivingPlayerCheckTimer); - g_hLivingPlayerCheckTimer = INVALID_HANDLE; - } - - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Living player balance delay timer started."); - } - g_hLivingPlayerCheckTimer = CreateTimer(float(g_iLivingPlayerCheckDelay), Timer_LivingPlayerCheck, _, TIMER_FLAG_NO_MAPCHANGE); -} - -stock FindSwitchablePlayer() -{ - - /** - Start a loop to find a switchable player - */ - new iPlayer; - new iBiggerTeam = GetBiggerTeam(); - for (new i = 1; i <= MaxClients; i++) - { - - /** - Check the stock function to see if we are allows to even switch the player - */ - if (!IsSwitchablePlayer(i, iBiggerTeam)) - { - continue; - } - - /** - If the mod is TF2 and they have Priority Players set check if the client has buildings or an uber - */ - if (g_CurrentMod == GameType_TF && g_bPriorityPlayers) - { - if (HasUber(i) || HasBuildingsBuilt(i)) - { - continue; - } - } - - /** - So far we are able we switch this player - Now we check the buddy system - */ - if (g_bBuddyEnabled) - { - - /** - Buddy system is enabled, check to see if client has buddy - */ - if (SM_GetClientBuddy(i) != 0) - { - - /** - The client has a buddy, so we check to see if they are on same team - */ - if (GetClientTeam(i) == GetClientTeam(SM_GetClientBuddy(i))) - { - - /** - They are, so we continue to next client - */ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] With a balance in progress a buddy on the right team was found and skipped."); - } - continue; - } - else - { - - /** - They are not on the same team, set this client - The buddy could be in spec, and that would make it not matter where he is, or the buddy is on the smaller team - */ - iPlayer = i; - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] With a balance in progress a buddy on the wrong team was found."); - } - break; - } - } - else - { - - /** - The client does not have a buddy, set this client - */ - iPlayer = i; - break; - } - } - else - { - - /** - Buddy system is not enabled, set this client - */ - iPlayer = i; - break; - } - } - - /** - Return the client we set, this could be 0, but very unlikely - */ - return iPlayer; -} - -stock BalancePlayer(iClient, iTeam) -{ - new Handle:hPack = CreateDataPack(); - WritePackCell(hPack, iClient); - WritePackCell(hPack, iTeam); - CreateTimer(0.1, Timer_BalancePlayer, hPack, TIMER_FLAG_NO_MAPCHANGE); -} - -stock CleanUp(iClient) -{ - g_aPlayers[iClient][bFlagCarrier] = false; - g_aPlayers[iClient][bSwitched] = false; - if (g_aPlayers[iClient][hForcedTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hForcedTimer]); - g_aPlayers[iClient][hForcedTimer] = INVALID_HANDLE; - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] Forced player disconnected, killing timer."); - } - } - if (g_aPlayers[iClient][hBalanceTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hBalanceTimer]); - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] Living player set to be balanced disconnected, killing timer."); - } - } -} - -stock GetSmallerTeam() -{ - - /** - Get the count of players on each team - */ - new iCountT1 = GetTeamClientCount(g_aCurrentTeams[Team1]); - new iCountT2 = GetTeamClientCount(g_aCurrentTeams[Team2]); - - /** - Return the smaller team - */ - if (iCountT1 < iCountT2) - { - return g_aCurrentTeams[Team1]; - } - else if (iCountT1 > iCountT2) - { - return g_aCurrentTeams[Team2]; - } - return 0; -} - -stock GetBiggerTeam() -{ - - /** - Get the count of players on each team - */ - new iCountT1 = GetTeamClientCount(g_aCurrentTeams[Team1]); - new iCountT2 = GetTeamClientCount(g_aCurrentTeams[Team2]); - - /** - Return the bigger team - */ - if (iCountT1 > iCountT2) - { - return g_aCurrentTeams[Team1]; - } - else if (iCountT1 < iCountT2) - { - return g_aCurrentTeams[Team2]; - } - return 0; -} - -stock SetGameCvars() -{ - if (g_bConVarControl && g_bIsEnabled) - { - if (stb_mp_autoteambalance != INVALID_HANDLE) - { - SetConVarInt(stb_mp_autoteambalance, 0); - } - if (stb_mp_teams_unbalance_limit != INVALID_HANDLE) - { - SetConVarInt(stb_mp_teams_unbalance_limit, g_iUnbalanceLimit); - } - } -} - -/* TIMER FUNCTIONS */ - -public Action:Timer_ChangeTeamBalanceDelay(Handle:timer, any:data) -{ - - /** - Finally start one if it's still unbalanced - */ - if (IsUnbalanced() && !g_bBalanceInProgress) - { - StartABalance(); - } -} - -public Action:Timer_BalanceTeams(Handle:timer, any:data) -{ - - /** - See if we still need to balance the teams - */ - if (!IsUnbalanced() || !OkToBalance()) - { - - /** - We don't, kill the balance - */ - g_bBalanceInProgress = false; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Balance delay timer was not needed and died."); - } - g_hBalanceTimer = INVALID_HANDLE; - return Plugin_Handled; - } - - /** - We still need to balance the teams - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Teams are still unbalanced. Balance is now in progress."); - } - g_bBalanceInProgress = true; - - - /** - Check if we are allowed to scan living players - */ - if (!g_bDeadOnly) - { - - /** - We are allowed to, so we start a timer - */ - StartALivingPlayerTimer(); - - /** - Also report that we are now scanning dead players as well - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Now scanning dead players."); - } - } - else - { - - /** - We are not allowed to, so report that we are only scanning dead players - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Only scanning dead players."); - } - } - - g_hBalanceTimer = INVALID_HANDLE; - return Plugin_Handled; -} - -public Action:Timer_LivingPlayerCheck(Handle:timer, any:data) -{ - - /** - Check to see if we still need to balance the teams - */ - if (!IsUnbalanced() || !OkToBalance()) - { - - /** - We don't, kill it and bug out - */ - g_bBalanceInProgress = false; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Living player balance delay timer was not needed and died."); - } - g_hLivingPlayerCheckTimer = INVALID_HANDLE; - return Plugin_Handled; - } - - /** - Call the stock function to find a player we can switch - */ - new iPlayer = FindSwitchablePlayer(); - - /** - Check to see if we found a player - */ - if (iPlayer == 0) - { - - /** - In the unlikely event that the stock function didn't return a player - Start a loop to find a random player - */ - new iBiggerTeam = GetBiggerTeam(); - do - { - iPlayer = GetRandomInt(1, MaxClients); - } while (!IsSwitchablePlayer(iPlayer, iBiggerTeam)); - - if (g_bLogActivity) - { - LogAction(0, iPlayer, "[STB] Found a random living player."); - } - } - else - { - if (g_bLogActivity) - { - LogAction(0, iPlayer, "[STB] Found a living player."); - } - } - - /** - Now that we have a player assigned them to the smaller team - */ - new iSmallerTeam = GetSmallerTeam(); - SM_SetForcedTeam(iPlayer, iSmallerTeam, true); - - /** - Let the player know we could be switching him soon - */ - PrintHintText(iPlayer, "%T", "PlayerMessage", LANG_SERVER, g_iLivingPlayerSwitchDelay); - if (g_bLogActivity) - { - LogAction(0, iPlayer, "[STB] Living player placed on a timer."); - } - - /** - Create a timer to switch the player - */ - g_aPlayers[iPlayer][hBalanceTimer] = CreateTimer(float(g_iLivingPlayerSwitchDelay), Timer_LivingPlayerBalance, iPlayer, TIMER_FLAG_NO_MAPCHANGE); - - /** - Reset the timer handle - */ - g_hLivingPlayerCheckTimer = INVALID_HANDLE; - - /** - We are done, bug out - */ - return Plugin_Handled; -} - -public Action:Timer_LivingPlayerBalance(Handle:timer, any:iClient) -{ - - /** - Check to make sure we still need to balance - */ - if (!IsUnbalanced() || !OkToBalance()) - { - - /** - We don't need to balance, bug out - */ - g_bBalanceInProgress = false; - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - SM_ClearForcedTeam(iClient); - return Plugin_Handled; - } - - /** - We still need to balance, lets make sure we can still balance this player - */ - if (!IsClientConnected(iClient) || g_aPlayers[iClient][bFlagCarrier]) - { - g_bBalanceInProgress = false; - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - SM_ClearForcedTeam(iClient); - if (g_bLogActivity) - { - if (g_aPlayers[iClient][bFlagCarrier]) - { - LogAction(0, iClient, "[STB] Living player became flag carrier, balance restarted."); - } - else - { - LogAction(0, iClient, "[STB] Living player timer was not needed and died."); - } - } - return Plugin_Handled; - } - - /** - Clear to balance this player, so do it - */ - BalancePlayer(iClient, SM_GetForcedTeam(iClient)); - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] Living player was switched."); - } - - /** - We are done, bug out - */ - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - return Plugin_Handled; -} - -public Action:Timer_BalancePlayer(Handle:timer, Handle:pack) -{ - - /** - Rest the datapack and load the variables - */ - ResetPack(pack); - new iClient = ReadPackCell(pack); - new iUnBalancedTeam = ReadPackCell(pack); - - /** - We are done with you now - */ - CloseHandle(pack); - - /** - Check the team and make sure its a valid team - */ - if(!SM_IsValidTeam(iUnBalancedTeam)) - { - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] Balance failed due to invalid team number %i", iUnBalancedTeam); - } - return Plugin_Handled; - } - - /** - Use our core function to change the clients team - */ - SM_MovePlayer(iClient, iUnBalancedTeam); - - return Plugin_Handled; -} - -public Action:Timer_RoundStart(Handle:timer, any:data) -{ - g_bRoundStart = false; - if (OkToBalance() && IsUnbalanced() && !g_bBalanceInProgress) - { - StartABalance(); - } - return Plugin_Handled; -} - -public Action:Timer_ForcedExpired(Handle:timer, any:iClient) -{ - SM_ClearForcedTeam(iClient); - g_aPlayers[iClient][bSwitched] = false; - g_aPlayers[iClient][hForcedTimer] = INVALID_HANDLE; - return Plugin_Handled; -} - -public Action:Timer_WelcomeAdvert(Handle:timer, any:iClient) -{ - if (IsClientConnected(iClient) && IsClientInGame(iClient)) - { - PrintToChat (iClient, "\x01\x04[STB]\x01 %T", "BuddyWelcomeMsg1", LANG_SERVER); - PrintToChat (iClient, "\x01\x04[STB]\x01 %T", "BuddyWelcomeMsg2", LANG_SERVER); - PrintToChat (iClient, "\x01\x04[STB]\x01 %T", "BuddyWelcomeMsg3", LANG_SERVER); - } - return Plugin_Handled; -} - -/* CONSOLE VARIABLE CHANGE EVENT */ - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (convar == stb_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsEnabled = false; - PrintToChatAll("[SM] %T", "Disabled", LANG_SERVER); - LogAction(0, -1, "[SimpleTeamBalancer] Disabled"); - } - else - { - g_bIsEnabled = true; - SetGameCvars(); - PrintToChatAll("[SM] %T", "Enabled", LANG_SERVER); - LogAction(0, -1, "[SimpleTeamBalancer] Enabled"); - } - } - else if (convar == stb_logactivity) - { - if (StringToInt(newValue) == 0) - { - g_bLogActivity = false; - LogAction(0, -1, "[STB] Log Activity DISABLED."); - } - else - { - g_bLogActivity = true; - LogAction(0, -1, "[STB] Log Activity ENABLED."); - } - } - else if (convar == stb_logactivity2) - { - if (StringToInt(newValue) == 0) - { - g_bLogActivity2 = false; - LogAction(0, -1, "[STB] Detailed Log Activity DISABLED."); - } - else - { - g_bLogActivity2 = true; - LogAction(0, -1, "[STB] Detailed Log Activity ENABLED."); - } - } - else if (convar == stb_convarcontrol) - { - if (StringToInt(newValue) == 0) - { - g_bConVarControl = false; - } - else - { - g_bConVarControl = true; - SetGameCvars(); - } - } - else if (convar == stb_deadonly) - { - if (StringToInt(newValue) == 0) - { - g_bDeadOnly = false; - } - else - { - g_bDeadOnly = true; - } - } - else if (convar == stb_priorityenabled) - { - if (StringToInt(newValue) == 0) - { - g_bPriorityPlayers = false; - } - else - { - g_bPriorityPlayers = true; - } - } - else if (convar == stb_buddyenabled) - { - if (StringToInt(newValue) == 0) - { - g_bBuddyEnabled = false; - } - else - { - g_bBuddyEnabled = true; - } - } - else if (convar == stb_buddyrestriction) - { - if (StringToInt(newValue) == 0) - { - g_bBuddyRestriction = false; - } - else - { - g_bBuddyRestriction = true; - } - } - else if (convar == stb_unbalancelimit) - { - g_iUnbalanceLimit = StringToInt(newValue); - SetGameCvars(); - } - else if (convar == stb_balancedelay) - { - g_iBalanceDelay = StringToInt(newValue); - } - else if (convar == stb_roundstartdelay) - { - g_iRoundStartDelay = StringToInt(newValue); - } - else if (convar == stb_livingplayerswitchdelay) - { - g_iLivingPlayerSwitchDelay = StringToInt(newValue); - } - else if (convar == stb_livingplayercheckdelay) - { - g_iLivingPlayerCheckDelay = StringToInt(newValue); - } - else if (convar == stb_uberlevel) - { - g_fUberLevel = StringToFloat(newValue); - } - else if (convar == stb_switchbackforced) - { - g_iSwitchBackForced = StringToInt(newValue); - } - else if (convar == stb_adminflag) - { - SetConVarString(stb_adminflag, newValue); - } - else if (convar == stb_mp_autoteambalance) - { - SetGameCvars(); - } - else if (convar == stb_mp_teams_unbalance_limit) - { - SetGameCvars(); - } -} - -/* MENU CODE */ - -stock Handle:BuildPlayerMenu() -{ - new Handle:menu = CreateMenu(Menu_SelectPlayer); - AddTargetsToMenu(menu, 0, true, false); - SetMenuTitle(menu, "Select A Player:"); - SetMenuExitButton(menu, true); - return menu; -} - -public Menu_SelectPlayer(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - new buddy = GetClientOfUserId(StringToInt(sSelection)); - if (param1 == buddy) { - PrintHintText(param1, "%T", "SelectSelf", LANG_SERVER); - } else if (!IsClientInGame(buddy)) { - PrintHintText(param1, "%T", "BuddyGone", LANG_SERVER); - } else { - decl String:cName[128]; - decl String:bName[128]; - GetClientName(param1, cName, sizeof(cName)); - GetClientName(buddy, bName, sizeof(bName)); - if (!SM_IsBuddyLocked(buddy)) { - SM_AssignBuddy(param1, buddy); - PrintHintText(param1, "%T", "BuddyMsg", LANG_SERVER, bName); - PrintHintText(buddy, "%T", "BuddyMsg", LANG_SERVER, cName); - } else - PrintHintText(param1, "%T", "PlayerLockedBuddyMsg", LANG_SERVER, bName); - } - } else if (action == MenuAction_End) { - CloseHandle(menu); - } -} \ No newline at end of file diff --git a/Simple AllTalk Manager/addons/sourcemod/scripting/simple-teammanager.sp b/Simple AllTalk Manager/addons/sourcemod/scripting/simple-teammanager.sp deleted file mode 100644 index 008f443..0000000 --- a/Simple AllTalk Manager/addons/sourcemod/scripting/simple-teammanager.sp +++ /dev/null @@ -1,1351 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Team Manager -Description: - Manges players and their team - Admin menu integration - Allows admins/donators to swap their teams (clears force)* - Allows admins to move players to a team (forced\unforced)* - Allows admins to scramble the teams* - *Works with Simple Team Balancer (if installed) -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include - -#define PLUGIN_VERSION "2.1.$Rev$" -#define VOTE_YES "##YES##" -#define VOTE_NO "##NO##" - -enum PlayerData -{ - iNewTeam, - bool:bQueue -}; - -new Handle:stm_enabled = INVALID_HANDLE; -new Handle:stm_logactivity = INVALID_HANDLE; -new Handle:stm_adminflag_swapteam = INVALID_HANDLE; -new Handle:stm_adminflag_moveplayer = INVALID_HANDLE; -new Handle:stm_adminflag_scramble = INVALID_HANDLE; -new Handle:stm_scrambledelay = INVALID_HANDLE; -new Handle:stm_voteenabled = INVALID_HANDLE; -new Handle:stm_votewin = INVALID_HANDLE; -new Handle:stm_votedelay = INVALID_HANDLE; -new Handle:stm_mp_bonusroundtime = INVALID_HANDLE; -new Handle:g_hAdminMenu = INVALID_HANDLE; -new Handle:g_hTimerPrepScramble = INVALID_HANDLE; -new Handle:g_hTimerClearScrambleForce = INVALID_HANDLE; - -new g_aPlayers[MAXPLAYERS + 1][PlayerData]; - -new bool:g_bIsEnabled = true; -new bool:g_bVoteEnabled = true; -new bool:g_bLogActivity = true; -new bool:g_bScrambleRoundEnd = false; -new g_iVoteDelay, g_iLastVoteTime, g_iTimeLeft; -new Float:g_fScrambleDelay, Float:g_fVoteWin; - -public Plugin:myinfo = -{ - name = "Simple Team Manager", - author = "Simple Plugins", - description = "Manages players and thier team.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -public OnPluginStart() -{ - - /** - Need to create all of our console variables. - */ - CreateConVar("stm_version", PLUGIN_VERSION, "Simple Team Manager Version",FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - stm_enabled = CreateConVar("stm_enabled", "1", "Enable or Disable Simple Team Manager", _, true, 0.0, true, 1.0); - stm_logactivity = CreateConVar("stm_logactivity", "0", "Enable or Disable the disaplying of events in the log", _, true, 0.0, true, 1.0); - stm_adminflag_swapteam = CreateConVar("stm_adminflag_swapteam", "a", "Admin flag to use for the swapteam command. Must be a in char format."); - stm_adminflag_moveplayer = CreateConVar("stm_adminflag_moveplayer", "c", "Admin flag to use for the moveplayer command. Must be a in char format."); - stm_adminflag_scramble = CreateConVar("stm_adminflag_scramble", "c", "Admin flag to use for the scrambleteam command. Must be a in char format."); - stm_scrambledelay = CreateConVar("stm_scrambledelay", "15", "Delay to scramble teams"); - stm_voteenabled = CreateConVar("stm_voteenabled", "1", "Enable or Disable voting to scramble the teams", _, true, 0.0, true, 1.0); - stm_votewin = CreateConVar("stm_votewin", "0.45", "Win percentage vote must win by", _, true, 0.0, true, 1.0); - stm_votedelay = CreateConVar("stm_votedelay", "600", "Delay before another vote can be cast"); - stm_mp_bonusroundtime = FindConVar("mp_bonusroundtime"); - - - /** - Need deal with changes to the console variables after the plugin is loaded. - We could not do this and just call the actual console variable each time we need it, but it's not efficent. - */ - HookConVarChange(stm_enabled, ConVarSettingsChanged); - HookConVarChange(stm_logactivity, ConVarSettingsChanged); - HookConVarChange(stm_scrambledelay, ConVarSettingsChanged); - HookConVarChange(stm_voteenabled, ConVarSettingsChanged); - HookConVarChange(stm_votewin, ConVarSettingsChanged); - HookConVarChange(stm_votedelay, ConVarSettingsChanged); - - /** - Need to register the commands we are going to create and use. - */ - RegConsoleCmd("sm_swapteam", Command_SwapTeam, "sm_swapteam <[0]instant/[1]queued>: Swaps your team to the other team"); - RegConsoleCmd("sm_moveplayer", Command_MovePlayer, "sm_moveplayer <[0]instant/[1]ondeath> <[0]unforced/[1]forced>: Moves a player to the specified team"); - RegConsoleCmd("sm_scrambleteams", Command_ScrambleTeams, "sm_scrambleteams: <[0]now/[1]roundend> <[0]dontrestart/[1]restartround> Scrambles the current teams"); - RegConsoleCmd("sm_votescramble", Command_VoteScramble, "sm_votescramble: Starts a vote to scramble the teams"); - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[STM] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_death", HookPlayerDeath, EventHookMode_Post); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Post); - switch (g_CurrentMod) - { - case GameType_TF: - { - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - } - case GameType_DOD: - { - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_Post); - } - default: - { - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - - /** - Now we have to deal with the admin menu. If the admin library is loaded call the function to add our items. - */ - new Handle:gTopMenu; - if (LibraryExists("adminmenu") && ((gTopMenu = GetAdminTopMenu()) != INVALID_HANDLE)) - { - OnAdminMenuReady(gTopMenu); - } - - /** - Load translations and .cfg file - */ - LoadTranslations ("simpleteammanager.phrases"); - AutoExecConfig(true, "plugin.simpleteammanager"); - LogAction(0, -1, "[STM] Simple Team Manager is loaded."); -} - -public OnAllPluginsLoaded() -{ - //something -} - -public OnLibraryRemoved(const String:name[]) -{ - if (StrEqual(name, "adminmenu")) - { - - /** - Looks like the admin menu was removed. Set the global. - */ - g_hAdminMenu = INVALID_HANDLE; - } - else if (StrEqual(name, "simpleplugins")) - { - SetFailState("Required plugin Simple SourceMod Plugins Core was removed."); - } -} - -public OnConfigsExecuted() -{ - - /** - Once we loaded up all the console variables from the config file, lets now set all the global variables we will use. - */ - g_bIsEnabled = GetConVarBool(stm_enabled); - g_bLogActivity = GetConVarBool(stm_logactivity); - g_fScrambleDelay = GetConVarFloat(stm_scrambledelay); - g_iVoteDelay = GetConVarInt(stm_votedelay); - g_fVoteWin = GetConVarFloat(stm_votewin); - g_iLastVoteTime = RoundFloat(GetEngineTime()); - g_bScrambleRoundEnd = false; - g_hTimerClearScrambleForce = INVALID_HANDLE; - - /** - Report enabled - */ - if (g_bIsEnabled) - { - LogAction(0, -1, "[STM] Simple Team Manager is ENABLED."); - } - else - { - LogAction(0, -1, "[STM] Simple Team Manager is DISABLED."); - } - - if (g_bLogActivity) - { - LogAction(0, -1, "[STM] Log Activity ENABLED."); - } - else - { - LogAction(0, -1, "[STM] Log Activity DISABLED."); - } -} - -/* COMMANDS */ - -public Action:Command_SwapTeam(client, args) -{ - - /** - Make sure we are enabled, if not bug out. - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - If this was ran from the console bug out. - */ - if (client == 0) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure the client is authorized to run this command. - */ - decl String:sFlags[5]; - GetConVarString(stm_adminflag_swapteam, sFlags, sizeof(sFlags)); - if (!SM_IsValidAdmin(client, sFlags)) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Lets make sure the client is one a team we can swap. - If he is we set the global array to the opposite team. - */ - new iTeam = GetClientTeam(client); - if (iTeam == g_aCurrentTeams[Team1]) - { - g_aPlayers[client][iNewTeam] = g_aCurrentTeams[Team2]; - } - else if (iTeam == g_aCurrentTeams[Team2]) - { - g_aPlayers[client][iNewTeam] = g_aCurrentTeams[Team1]; - } - else - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "InValidTeam", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check to see if we have command arguments. - */ - if (GetCmdArgs()) - { - - /** - We do, so lets get it and see if the client wants to be switched instantly or queued for death. - */ - decl String:sArg[5]; - GetCmdArg(1, sArg, sizeof(sArg)); - new iWantsQue = StringToInt(sArg); - if (iWantsQue && !g_aPlayers[client][bQueue]) - { - - /** - He wants the que and isn't already in it, set the global array. - */ - g_aPlayers[client][bQueue] = true; - ReplyToCommand(client, "\x01\x04[STM]\x01 %T", "PlayerQueue", LANG_SERVER); - } - else if (!iWantsQue) - { - - /** - He wants to be switched right now, lets call the stock function. - */ - SM_MovePlayer(client, g_aPlayers[client][iNewTeam]); - } - } - else - { - - /** - There are no command arguments so we build and display the swap menu. - */ - DisplaySwapModeMenu(client, client); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_MovePlayer(client, args) -{ - - /** - Make sure we are enabled, if not bug out. - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the client is authorized to run this command. - */ - decl String:sFlags[5]; - GetConVarString(stm_adminflag_moveplayer, sFlags, sizeof(sFlags)); - if (!SM_IsValidAdmin(client, sFlags)) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check to see if we have command arguments. - */ - new iCmdArgs = GetCmdArgs(); - if (iCmdArgs == 0) - { - - /** - We don't. Build the player menu, display it, and bug out. - */ - DisplayPlayerMenu(client); - return Plugin_Handled; - } - - /** - Check the first argument - If should be a players name or userid. - */ - decl String:sPlayer[64]; - GetCmdArg(1, sPlayer, sizeof(sPlayer)); - new iPlayerIndex = FindTarget(client, sPlayer, true, true); - if (iPlayerIndex == -1 || !IsClientInGame(iPlayerIndex)) - { - - /** - We don't know who this is. Build the player menu, display it, and bug out. - */ - DisplayPlayerMenu(client); - return Plugin_Handled; - } - - /** - We have figured out the first argument, lets check the second. - If should be the team the client wants to put the player on. - */ - if (iCmdArgs >= 2) - { - - /** - We have a command argument at least, lets see if we can identify the team. - */ - decl String:sTeam[24]; - GetCmdArg(2, sTeam, sizeof(sTeam)); - - new iTeam = StringToInt(sTeam); - if (SM_IsValidTeam(iTeam)) - { - - /** - It's a vaild team so lets set the global array to the new team. - */ - g_aPlayers[iPlayerIndex][iNewTeam] = iTeam; - } - else - { - - /** - It's not a vaild team so set the menu to display to the team menu. - */ - DisplayTeamMenu(client, iPlayerIndex); - return Plugin_Handled; - } - } - else - { - /** - We were not given a team, display the team menu. - */ - DisplayTeamMenu(client, iPlayerIndex); - return Plugin_Handled; - } - - /** - Check to see if we were given any more command arguments and found a team. - */ - if (iCmdArgs < 3) - { - - /** - No more command arguments and found a team. - Now lets check to see if the player is a spectator. If he is there is no reason to ask if it's instant or on death... he can't die. - */ - if (!IsClientObserver(iPlayerIndex)) - { - - /** - Not a spectator so display the swapmode menu. - */ - DisplaySwapModeMenu(client, iPlayerIndex); - } - else - { - - /** - The player is a spectator. - We make sure the player is not set to switch on death, since a spec can't die. - */ - g_aPlayers[iPlayerIndex][bQueue] = false; - } - } - - /** - We have figured out the second argument, lets check the third. - If should be the how the client wants to move the player: instant/on death. - */ - if (iCmdArgs >= 3) - { - - /** - The client gave us a command argument, lets check it. - */ - decl String:sSwapMode[5]; - GetCmdArg(3, sSwapMode, sizeof(sSwapMode)); - new iWantsQue = StringToInt(sSwapMode); - if (iWantsQue) - { - - /** - The client wants to que the player, set the global array. - */ - g_aPlayers[iPlayerIndex][bQueue] = true; - } - else - { - - /** - The client doesn't want to que the player, set the global array. - */ - g_aPlayers[iPlayerIndex][bQueue] = false; - } - } - else - { - /** - No swapmode argument, display the menu - */ - DisplaySwapModeMenu(client, iPlayerIndex); - } - - if (iCmdArgs >= 4) - { - - /** - Since we are compiling for Simple Team Balancer, and given a 4th argument, lets check it. - If should be the if the client wants to force the player to that team. - */ - decl String:sPlayerForced[5]; - GetCmdArg(4, sPlayerForced, sizeof(sPlayerForced)); - new iForceHim = StringToInt(sPlayerForced); - if (iForceHim) - { - - /** - The client wants to force the player - */ - SM_SetForcedTeam(iPlayerIndex, g_aPlayers[iPlayerIndex][iNewTeam]); - } - else - { - - /** - The client doesn't want to force the player - */ - SM_ClearForcedTeam(iPlayerIndex); - } - } - else - { - - } - - /** - We found and processed all the arguments. - */ - if (!IsPlayerAlive(iPlayerIndex)) - { - - /** - The player is not alive or died during this process so we just move him. - */ - SM_MovePlayer(iPlayerIndex, g_aPlayers[iPlayerIndex][iNewTeam]); - } - else - { - if (!g_aPlayers[iPlayerIndex][bQueue]) - { - - /** - The player is alive and is not set to be queued so we just move him. - */ - SM_MovePlayer(iPlayerIndex, g_aPlayers[iPlayerIndex][iNewTeam]); - } - } - - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_ScrambleTeams(client, args) -{ - - /** - Make sure we are enabled, if not bug out. - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the client is authorized to run this command. - */ - decl String:sFlags[5]; - GetConVarString(stm_adminflag_scramble, sFlags, sizeof(sFlags)); - if (!SM_IsValidAdmin(client, sFlags)) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check if a scramble timer was already called, if so close it down. - */ - if (g_hTimerPrepScramble != INVALID_HANDLE) - { - CloseHandle(g_hTimerPrepScramble); - g_hTimerPrepScramble = INVALID_HANDLE; - } - - /** - Check if we have any command arguments. - If we don't we display the scramble menu and bug out. - */ - new iCmdArgs = GetCmdArgs(); - if (iCmdArgs == 0) - { - DisplayScrambleMenu(client); - return Plugin_Handled; - } - - /** - We have a command argument. - It should be whether or not to scramble at round end. - */ - decl String:sRoundEnd[5]; - GetCmdArg(1, sRoundEnd, sizeof(sRoundEnd)); - if (StringToInt(sRoundEnd)) - { - /** - The client wants to scramble at round end so we set the global bool. - */ - g_bScrambleRoundEnd = true; - } - else - { - g_bScrambleRoundEnd = false; - } - - /** - Check for another command argument. - It should be whether or not to restart the round. - */ - decl String:sRestartRound[5]; - new bool:bRestartRound = false; - GetCmdArg(1, sRestartRound, sizeof(sRestartRound)); - if (StringToInt(sRestartRound)) - { - bRestartRound = true; - } - - /** - Now we start the scramble timer. - */ - StartScrambleTimer(_, bRestartRound); - - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_VoteScramble(client, args) -{ - - /** - Make sure we are enabled, if not bug out. - */ - if (!g_bVoteEnabled || !g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Make sure there is a vote in progress, if so bug out. - */ - if (IsVoteInProgress()) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "VoteInProgress", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure enough time has passed since the last vote. - */ - new iVoteTime = RoundFloat(GetEngineTime()); - if (iVoteTime - g_iLastVoteTime <= g_iVoteDelay) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "ScrambleTime", LANG_SERVER); - return Plugin_Handled; - } - - /** - Enough time has passed so reset the global vote time to now. - */ - g_iLastVoteTime = iVoteTime; - - /** - Build the vote menu and send it to everyone. - */ - new Handle:hMenu = CreateMenu(Menu_VoteScramble); - SetMenuTitle(hMenu, "Scramble Teams?"); - AddMenuItem(hMenu, VOTE_YES, "Yes"); - AddMenuItem(hMenu, VOTE_NO, "No"); - SetMenuExitButton(hMenu, false); - VoteMenuToAll(hMenu, 20); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -/* HOOKED EVENTS */ - -public HookPlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Find out who died. - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - - /** - Find out how the client died. - */ - new String:sWeapon[64]; - GetEventString(event, "weapon", sWeapon, sizeof(sWeapon)); - if (StrEqual(sWeapon, "world", false)) - { - - /** - He died because he changed teams so cleanup and bug out. - */ - s_CleanUp(iClient); - return; - } - - /** - Find out if this player was queued to change teams. - */ - if (g_aPlayers[iClient][bQueue]) - { - /** - Looks like he was, so call the stock function to move him. - */ - SM_MovePlayer(iClient, g_aPlayers[iClient][iNewTeam]); - } -} - -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Find out who changed teams. - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - - /** - If he was queued to switch teams we cleanup the variables. The client did it themself. - */ - if (g_aPlayers[iClient][bQueue]) - { - s_CleanUp(iClient); - } -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get the amount of time left in the map. - */ - new iTimeLeft; - GetMapTimeLeft(iTimeLeft); - - /** - Check to see if we are supposed to scramble at the end of the round and that there is enough time left in the map. - */ - if (g_bScrambleRoundEnd && iTimeLeft >= 60) - { - - /** - Check to see if there is a scramble timer in action and if so close it down. - */ - if (g_hTimerPrepScramble != INVALID_HANDLE) - { - CloseHandle(g_hTimerPrepScramble); - g_hTimerPrepScramble = INVALID_HANDLE; - } - - /** - Determine the round end chat time and run the scramble 1 second before it ends. - */ - new Float:fDelay = GetConVarFloat(stm_mp_bonusroundtime); - fDelay -= 1.0; - StartScrambleTimer(fDelay); - } -} - -public OnClientPostAdminCheck(client) -{ - - /** - Determine if the client has the flag to use the swapteam command. - */ - decl String:sFlags[5]; - GetConVarString(stm_adminflag_swapteam, sFlags, sizeof(sFlags)); - if (SM_IsValidAdmin(client, sFlags)) - { - /** - The client does so lets create a timer to run an advertise to tell him about it. - */ - CreateTimer (60.0, Timer_WelcomeAdvert, client); - } -} - -public OnClientDisconnect(client) -{ - - /** - Cleanup the clients variables. - */ - s_CleanUp(client); -} - -public SM_OnPlayerMoved(Handle:plugin, client, team) -{ - - /** - Make sure we called the move function - */ - if (plugin != GetMyHandle()) - { - if (g_bLogActivity) - { - LogAction(0, client, "[STM] Callback was not started with current plugin, bugging out."); - } - return; - } - - decl String:sPlayerName[64]; - GetClientName(client, sPlayerName, sizeof(sPlayerName)); - - PrintToChat(client, "\x01\x04[SM]\x01 %T", "PlayerSwitched", LANG_SERVER); - - s_CleanUp(client); -} - -/* TIMER FUNCTIONS */ - -public Action:Timer_PrepTeamScramble(Handle:timer, any:data) -{ - new bool:bRestartRound = data; - /** - Call the scramble the teams stock function. - */ - PrepTeamScramble(bRestartRound); - - /** - Reset the timer handle so we know the timer is done. - */ - g_hTimerPrepScramble = INVALID_HANDLE; - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Timer_ScrambleTheTeams(Handle:timer, any:data) -{ - new iPlayers[MAXPLAYERS + 1]; - new iCount, i, bool:bTeam, bool:bRestartRound = data; - - /** - Get all the client index numbers of valid players - */ - for(i = 1; i <= MaxClients; i++) - { - if(IsClientInGame(i)) // && !IsFakeClient(i)) - { - iPlayers[iCount++] = i; - } - } - - /** - Randomly sort the players - */ - SortIntegers(iPlayers, iCount, Sort_Random); - - /** - Loop through all the players and assign each one to a team, alternating each time - */ - for(i = 0; i < iCount; i++) - { - if (!bRestartRound) - { - /** - We didn't want to restart the round, so we move them to spec 1 at a time. - */ - SM_MovePlayer(iPlayers[i], g_aCurrentTeams[Spectator]); - } - SM_MovePlayer(iPlayers[i], bTeam ? g_aCurrentTeams[Team2] : g_aCurrentTeams[Team1]); - SM_SetForcedTeam(iPlayers[i], bTeam ? g_aCurrentTeams[Team2] : g_aCurrentTeams[Team1], true); - bTeam = !bTeam; - } - - /** - Reset this variable since we completed a scramble - */ - g_bScrambleRoundEnd = false; - - if (g_hTimerClearScrambleForce != INVALID_HANDLE) - { - CloseHandle(g_hTimerClearScrambleForce); - g_hTimerClearScrambleForce = INVALID_HANDLE; - } - - g_hTimerClearScrambleForce = CreateTimer(300.0, Timer_ClearScrambleForce, _, TIMER_FLAG_NO_MAPCHANGE); - - ServerCommand("mp_timelimit %i", g_iTimeLeft / 60); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Timer_ClearScrambleForce(Handle:timer, any:data) -{ - - for(new i = 1; i <= MaxClients; i++) - { - if(IsClientInGame(i)) // && !IsFakeClient(i)) - { - SM_ClearForcedTeam(i); - PrintToChat(i, "\x01\x04[SM]\x01 Your forced team status has been cleared"); - } - } - - g_hTimerClearScrambleForce = INVALID_HANDLE; - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Timer_WelcomeAdvert(Handle:timer, any:client) -{ - - /** - Lets make sure the client is connected and actually in the game. - */ - if (IsClientConnected(client) && IsClientInGame(client)) - { - - /** - We are good to go so lets tell him about the swapteam command. - */ - PrintToChat (client, "\x01\x04[STM]\x01 %T", "SwapTeamMsg", LANG_SERVER); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -/* STOCK FUNCTIONS */ - -stock s_CleanUp(iClient) -{ - - /** - Reset all the client variables - */ - g_aPlayers[iClient][bQueue] = false; - g_aPlayers[iClient][iNewTeam] = 0; -} - -stock StartScrambleTimer(Float:fdelay = 0.0, bool:bRestartRound = false) -{ - if (fdelay == 0.0) - { - fdelay = g_fScrambleDelay; - } - if (g_hTimerPrepScramble != INVALID_HANDLE) - { - CloseHandle(g_hTimerPrepScramble); - g_hTimerPrepScramble = INVALID_HANDLE; - } - PrintCenterTextAll("%T", "Scramble", LANG_SERVER); - g_hTimerPrepScramble = CreateTimer(fdelay, Timer_PrepTeamScramble, bRestartRound, TIMER_FLAG_NO_MAPCHANGE); -} - -stock PrepTeamScramble(bool:bRestartRound = false) -{ - new iPlayers[MAXPLAYERS + 1]; - new iCount; - - GetMapTimeLeft(g_iTimeLeft); - - if (bRestartRound) - { - - for(new i = 1; i <= MaxClients; i++) - { - if(IsClientInGame(i)) - // && !IsFakeClient(i)) - { - iPlayers[iCount++] = i; - SM_ClearForcedTeam(i); - SM_ClearBuddy(i); - SM_MovePlayer(i, g_aCurrentTeams[Spectator]); - } - } - } - else - { - //Can't move them all to spec at the same time - for(new i = 1; i <= MaxClients; i++) - { - if(IsClientInGame(i)) - // && !IsFakeClient(i)) - { - iPlayers[iCount++] = i; - SM_ClearForcedTeam(i); - SM_ClearBuddy(i); - //SM_MovePlayer(i, g_aCurrentTeams[Spectator]); - } - } - } - CreateTimer(4.0, Timer_ScrambleTheTeams, bRestartRound, TIMER_FLAG_NO_MAPCHANGE); -} - -/* CONSOLE VARIABLE CHANGE EVENT */ - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (convar == stm_enabled) { - if (StringToInt(newValue) == 0) { - g_bIsEnabled = false; - LogAction(0, -1, "[STM] Simple Team Manager is loaded and disabled."); - } else { - g_bIsEnabled = true; - LogAction(0, -1, "[STM] Simple Team Manager is loaded and enabled."); - } - } - else if (convar == stm_logactivity) { - if (StringToInt(newValue) == 0) { - g_bLogActivity = false; - LogAction(0, -1, "[STM] Log Activity DISABLED."); - } else { - g_bLogActivity = true; - LogAction(0, -1, "[STM] Log Activity ENABLED."); - } - } - else if (convar == stm_scrambledelay) - g_fScrambleDelay = StringToFloat(newValue); - else if (convar == stm_votewin) - g_fVoteWin = StringToFloat(newValue); - else if (convar == stm_votedelay) - g_iVoteDelay = StringToInt(newValue); - else if (convar == stm_voteenabled) { - if (StringToInt(newValue) == 0) - g_bVoteEnabled = false; - else - g_bVoteEnabled = true; - } -} - -/* MENU CODE */ - -public OnAdminMenuReady(Handle:topmenu) -{ - if (topmenu == g_hAdminMenu) - return; - g_hAdminMenu = topmenu; - new TopMenuObject:player_commands = FindTopMenuCategory(g_hAdminMenu, ADMINMENU_PLAYERCOMMANDS); - new TopMenuObject:server_commands = FindTopMenuCategory(g_hAdminMenu, ADMINMENU_SERVERCOMMANDS); - if (player_commands == INVALID_TOPMENUOBJECT) - return; - - AddToTopMenu(g_hAdminMenu, - "moveplayer", - TopMenuObject_Item, - AdminMenu_MovePlayer, - player_commands, - "moveplayer", - ADMFLAG_BAN); - - AddToTopMenu(g_hAdminMenu, - "scrambleteams", - TopMenuObject_Item, - AdminMenu_Scrambleteams, - server_commands, - "scrambleteams", - ADMFLAG_BAN); -} - -public AdminMenu_MovePlayer(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) -{ - if (action == TopMenuAction_DisplayOption) - Format(buffer, maxlength, "Move Player"); - else if (action == TopMenuAction_SelectOption){ - DisplayPlayerMenu(param); - } -} - -public AdminMenu_Scrambleteams(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) -{ - if (action == TopMenuAction_DisplayOption) - Format(buffer, maxlength, "Scramble Teams"); - else if (action == TopMenuAction_SelectOption) { - DisplayScrambleMenu(param); - } -} - -public Menu_SelectPlayer(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - DisplayTeamMenu(param1, GetClientOfUserId(StringToInt(sSelection))); - } else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -public Menu_SelectTeam(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new iTeam; - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - decl String:sIndex[64]; - if (SplitString(sSelection, "A", sIndex, sizeof(sIndex)) != -1) - iTeam = g_aCurrentTeams[Team1]; - else if (SplitString(sSelection, "B", sIndex, sizeof(sIndex)) != -1) - iTeam = g_aCurrentTeams[Team2]; - else { - SplitString(sSelection, "C", sIndex, sizeof(sIndex)); - iTeam = g_aCurrentTeams[Spectator]; - } - new iTarget = StringToInt(sIndex); - g_aPlayers[iTarget][iNewTeam] = iTeam; - DisplaySwapModeMenu(param1, iTarget); - } else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -public Menu_SwapMode(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - decl String:sIndex[64]; - - if (SplitString(sSelection, "A", sIndex, sizeof(sIndex)) == -1) - { - SplitString(sSelection, "B", sIndex, sizeof(sIndex)); - } - - new iTarget = StringToInt(sIndex); - - if (StrContains(sSelection, "A", true) != -1) - { - g_aPlayers[iTarget][bQueue] = false; - } - else if (StrContains(sSelection, "B", true) != -1) - { - g_aPlayers[iTarget][bQueue] = true; - } - - if (param1 == iTarget && !g_aPlayers[iTarget][bQueue]) - { - SM_MovePlayer(iTarget, g_aPlayers[iTarget][iNewTeam]); - } - else - { - DisplayForceModeMenu(param1, iTarget); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - { - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } - return; -} - -public Menu_ForceMode(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - decl String:sIndex[64]; - if (SplitString(sSelection, "A", sIndex, sizeof(sIndex)) == -1) - { - SplitString(sSelection, "B", sIndex, sizeof(sIndex)); - } - new iTarget = StringToInt(sIndex); - if (StrContains(sSelection, "A", true) != -1) - { - SM_ClearForcedTeam(iTarget); - } - else if (StrContains(sSelection, "B", true) != -1) - { - SM_SetForcedTeam(iTarget, g_aPlayers[iTarget][iNewTeam], true); - } - if (!g_aPlayers[iTarget][bQueue]) - { - SM_MovePlayer(iTarget, g_aPlayers[iTarget][iNewTeam]); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - { - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } - return; -} - -public Menu_VoteScramble(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_VoteEnd) { - new winning_votes, total_votes; - GetMenuVoteInfo(param2, winning_votes, total_votes); - if (param1 == 0) { - if (float(total_votes) / float(winning_votes) < g_fVoteWin) { - PrintToChatAll("\x01\x04[SM]\x01 %T", "VoteScramble2", LANG_SERVER, winning_votes, total_votes); - return; - } - PrintCenterTextAll("[SM] %T", "Scramble", LANG_SERVER); - PrintToChatAll("\x01\x04[SM]\x01 %T", "VoteScramble1", LANG_SERVER, winning_votes, total_votes); - StartScrambleTimer(); - } - if (param1 == 1) { - PrintToChatAll("\x01\x04[SM]\x01 %T", "VoteScramble2", LANG_SERVER, winning_votes, total_votes); - } - } - if (action == MenuAction_End) - CloseHandle(menu); -} - -public Menu_ScrambleTeams(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "NOW", false)) - g_bScrambleRoundEnd = false; - else - g_bScrambleRoundEnd = true; - DisplayScrambleMenu2(param1); - } else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -public Menu_ScrambleTeams2(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[64]; - new bool:bRestartRound; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "NO", false)) - { - bRestartRound = false; - } - else - { - bRestartRound = true; - } - StartScrambleTimer(_, bRestartRound); - } else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -stock DisplayScrambleMenu(iClient) -{ - new Handle:hMenu = CreateMenu(Menu_ScrambleTeams); - SetMenuTitle(hMenu, "Select When to Scramble:"); - AddMenuItem(hMenu, "NOW", "Instantly"); - AddMenuItem(hMenu, "END", "At Round End"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplayScrambleMenu2(iClient) -{ - new Handle:hMenu = CreateMenu(Menu_ScrambleTeams2); - SetMenuTitle(hMenu, "Select When to Scramble:"); - AddMenuItem(hMenu, "NO", "No Round Restart"); - AddMenuItem(hMenu, "YES", "Restart Round"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplaySwapModeMenu(iClient, iTarget) -{ - new Handle:hMenu = CreateMenu(Menu_SwapMode); - decl String:optionA[64]; - decl String:optionB[64]; - Format(optionA, sizeof(optionA), "%iA", iTarget); - Format(optionB, sizeof(optionB), "%iB", iTarget); - SetMenuTitle(hMenu, "Select When to Swap:"); - AddMenuItem(hMenu, optionA, "Instantly (Kills)"); - if (!IsClientObserver(iTarget)) - AddMenuItem(hMenu, optionB, "Queue on next death"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplayForceModeMenu(iClient, iTarget) -{ - new Handle:hMenu = CreateMenu(Menu_ForceMode); - decl String:optionA[64]; - decl String:optionB[64]; - Format(optionA, sizeof(optionA), "%iA", iTarget); - Format(optionB, sizeof(optionB), "%iB", iTarget); - SetMenuTitle(hMenu, "Select Force Mode:"); - AddMenuItem(hMenu, optionA, "UnForced"); - AddMenuItem(hMenu, optionB, "Forced"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplayTeamMenu(iClient, iTarget) -{ - new Handle:hMenu = CreateMenu(Menu_SelectTeam); - decl String:optionA[64]; - decl String:optionB[64]; - decl String:optionC[64]; - Format(optionA, sizeof(optionA), "%iA", iTarget); - Format(optionB, sizeof(optionB), "%iB", iTarget); - Format(optionC, sizeof(optionC), "%iC", iTarget); - SetMenuTitle(hMenu, "Select Team:"); - AddMenuItem(hMenu, optionA, "Team One"); - AddMenuItem(hMenu, optionB, "Team Two"); - AddMenuItem(hMenu, optionC, "Spectator"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplayPlayerMenu(iClient) -{ - new Handle:hMenu = CreateMenu(Menu_SelectPlayer); - AddTargetsToMenu(hMenu, 0, true, false); - SetMenuTitle(hMenu, "Select A Player:"); - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} diff --git a/Simple AllTalk Manager/addons/sourcemod/translations/simpledonatorbenefits.phrases.txt b/Simple AllTalk Manager/addons/sourcemod/translations/simpledonatorbenefits.phrases.txt deleted file mode 100644 index 3826846..0000000 --- a/Simple AllTalk Manager/addons/sourcemod/translations/simpledonatorbenefits.phrases.txt +++ /dev/null @@ -1,62 +0,0 @@ -"Phrases" -{ - "PlayerLevelCmd" - { - "en" "Command must be run at the player level" - "fr" "Cette commande doit être tapée en jeu" - "hu" "Ezt a parancsot jatekosi szinten kell futtatni!" - } - "RestrictedCmd" - { - "en" "You must be a donator or admin to run this command" - "fr" "Vous devez être un donateur ou un admin pour lancer cette commande" - "hu" "A parancs futtatasahoz admin, vagy tamogatoi szint szukseges!" - } - "InValidTeam" - { - "en" "You must be on red or blue to swap teams" - "fr" "Vous devez être RED ou BLU pour changer d'équipe" - "hu" "Jatekban kell lenned, hogy megcsereld a csapatokat!" - } - "PlayerQueue" - { - "en" "You have been queued to swap teams on next death" - "fr" "Vous avez été mis en attente pour changer d'équipe lors de votre prochaine mort" - "hu" "A kovetkezo halalnal csapatcsere lesz" - } - "PlayerSwitched" - { - "en" "Your team has been switched as requested" - "fr" "Vous avez changé d'équipe comme demandé" - "hu" "A keresnek eleget teve a csapatod meg lett csererlve" - } - "SwapTeamMsg" - { - "en" "Type /swapteam or !swapteam to swap your team!" - } - "ReachedCount" - { - "en" "You have reached your health limit. You must die before you can use it again" - } - "AtMaxHealth" - { - "en" "You are already at your maximum health!" - } - "ToMaxHealth" - { - "en" "Instant health bonus applied! You are not at your maximun health!" - } - "HealthBonus" - { - "en" "Instant health bonus applied!" - } - "PublicJoinMessage" - { - "#format" "{1:s}" - "en" "{1} a [donator] as joined the server" - } - "PrivateJoinMessage" - { - "en" "Thanks for donating!" - } -} \ No newline at end of file diff --git a/Simple AllTalk Manager/addons/sourcemod/translations/simplespectate.phrases.txt b/Simple AllTalk Manager/addons/sourcemod/translations/simplespectate.phrases.txt deleted file mode 100644 index 2d1a096..0000000 --- a/Simple AllTalk Manager/addons/sourcemod/translations/simplespectate.phrases.txt +++ /dev/null @@ -1,42 +0,0 @@ -"Phrases" -{ - "Stopped spectating" - { - "#format" "{1:s}" - "en" "Stopped tracking player: {1}" - } - "Yourself" - { - "en" "You can't spectate yourself" - } - "Spectator" - { - "en" "You can't spectate another spectator" - } - "Spectating" - { - "#format" "{1:s}" - "en" "Now spectating {1}. Type !stopspec or /stopspec to stop spectating this player" - } - "Invalid Target" - { - "en" "Invalid target" - } - "Cant Target" - { - "en" "Can't target this player" - } - "Must Have Target" - { - "en" "You must be following/tracking a player to punish" - } - "Target Left" - { - "en" "The player you were following/tracking has left" - } - "Punished" - { - "#format" "{1:s}{2:s}{3:s}" - "en" "{1} was punished with a {2} for {3}" - } -} \ No newline at end of file diff --git a/Simple AllTalk Manager/addons/sourcemod/translations/simpleteambalancer.phrases.txt b/Simple AllTalk Manager/addons/sourcemod/translations/simpleteambalancer.phrases.txt deleted file mode 100644 index 03595fd..0000000 --- a/Simple AllTalk Manager/addons/sourcemod/translations/simpleteambalancer.phrases.txt +++ /dev/null @@ -1,130 +0,0 @@ -"Phrases" -{ - "UnBalanced" - { - "en" "Teams are unbalanced and will be balanced shortly" - "fr" "Les équipes ne sont pas équilibrées et le seront bientôt" - "de" "Die Teams sind ungleich und werden in Kürze ausgeglichen" - "hu" "A csapatok nem kiegyenlitettek! Egyensuly beallitas kovetkezik!" - } - "Enabled" - { - "en" "Simple Team Balancer is ENABLED" - "fr" "Simple Team Balancer est ACTIVE" - "de" "Simple Team Balancer ist AKTIV" - "hu" "Az Egyszeru Csapat Egyensulytarto AKTIV!" - } - "Disabled" - { - "en" "Simple Team Balancer is DISABLED" - "fr" "Simple Team Balancer est DESACTIVE" - "de" "Simple Team Balancer ist INAKTIV" - "hu" "Az Egyszeru Csapat Egyensulytarto INAKTIV!" - } - "PlayerMessage" - { - "#format" "{1:i}" - "en" "You are going to be auto balanced in {1} seconds unless a dead player can be found" - "fr" "Vous passerez dans l'autre équipe dans {1} secondes si aucun joueur mort ne peut être trouvé dans cet intervalle" - "de" "Du wirst in {1} Sekunden zum automatischen Ausgleich herangezogen wenn kein toter Spieler gefunden werden kann" - "hu" "{1} masodpercen belul at leszel helyezve a masik csapatba, hacsak nem lesz addig egy halott jatekos!" - } - "BalanceMessage" - { - "#format" "{1:s}" - "en" "{1} was moved to the other team for game balance" - "fr" "{1} est passé dans l'autre équipe pour équilibrer la partie" - "de" "{1} wurde zum anderen Team verschoben um das Spiel auszugleichen" - "hu" "{1} at lett helyezve az egyensuly megtartasa erdekeben." - } - "PlayerLevelCmd" - { - "en" "Command must be run at the player level" - "fr" "La commande doit être lancée au niveau du joueur" - "de" "Das Kommando muss auf Spieler Ebene ausgeführt werden" - "hu" "Jatekosi szinten kell futtatni ezt a parancsot!" - } - "CmdDisabled" - { - "en" "Command is currently disabled" - "fr" "La commande est actuellement désactivée" - "de" "Das Kommando ist momentan inaktiv" - "hu" "A parancs jelenleg inaktiv" - } - "RestrictedBuddy" - { - "en" "You must be a donator or admin to add a balance buddy" - "fr" "Vous devez être un donateur ou un admin pour choisir un partenaire" - "de" "Du musst ein Spender oder Admin sein um einen Partner wählen zu können" - "hu" "Tamogato vagy admin kell hogy legyel, hogy 'Tarsat' jelolhess meg" - } - "SelectSelf" - { - "en" "You cannot be your own buddy" - "fr" "Vous ne pouvez pas être votre propre partenaire" - "de" "Du kannst nicht dein eigener Partner sein" - "hu" "Nem valaszthatod ki onmagad!" - } - "BuddyGone" - { - "en" "Your selected buddy has disconnected" - "fr" "Le partenaire que vous avez sélectionné s'est déconnecté" - "de" "Dein gewählter Partner hat die Verbindung getrennt" - "hu" "A valasztott 'Tarsad' kilepett" - } - "BuddyMsg" - { - "#format" "{1:s}" - "en" "You and {1} are now buddies" - "fr" "Vous et {1} êtes maintenant partenaires" - "de" "Du und {1} seid jetzt Partner" - "hu" "{1} es Te 'Tarsak' vagytok." - } - "BuddyLockMsgDisabled" - { - "en" "You can now be anyone's buddy" - "fr" "Vous pouvez à présent être le partenaire de n'importe qui" - "de" "Du kannst jetzt jedermanns Partner sein" - "hu" "Barkinek lehetsz a 'Tarsa'." - } - "BuddyLockMsgEnabled" - { - "en" "Buddy selection locked. Only you can change your buddy" - "fr" "Sélection de partenaire bloquée. Vous êtes le seul à pouvoir choisir votre partenaire" - "de" "Wahl des Partners gesperrt. Nur du kannst deinen Partner wechseln" - "hu" "Tars-lista lezarva. Csak Te tudod modositani a Tars-listadat." - } - "PlayerLockedBuddyMsg" - { - "#format" "{1:s}" - "en" "{1} has locked his buddy selection. Try again" - "fr" "{1} a bloqué sa sélection de partenaire. Essayez de nouveau." - "de" "{1} hat seine Wahl des Partners gesperrt. Versuche es erneut" - "hu" "{1} lezarta a Tars-listajat. Probald kesobb!" - } - "BuddyWelcomeMsg1" - { - "en" "Select a balance buddy and stay together during an autobalance!" - "fr" "Choisissez un partenaire et restez ensemble durant l'équilibrage automatique!" - "de" "Wähle einen Partner und bleibt zusammen während eines Ausgleichs" - "hu" "Valasz ki egy 'Tarsat' akivel egyuttmaradhatsz a csapatkiegyenlites alatt!" - } - "BuddyWelcomeMsg2" - { - "en" "/buddy or !buddy to select a balance buddy" - "fr" "/buddy or !buddy pour choisir un partenaire" - "de" "/buddy oder !buddy um einen Partner zu wählen" - "hu" "Hasznald a /buddy vagy !buddy parancsokat a 'Tars' kijelolesehez" - } - "BuddyWelcomeMsg3" - { - "en" "/lockbuddy or !lockbuddy to lock your selection" - "fr" "/lockbuddy or !lockbuddy pour bloquer votre sélection" - "de" "/lockbuddy oder !lockbuddy um deine Auswahl zu sperren" - "hu" "Hasznald a /lockbuddy vagy a !lockbuddy parancsokat a Tars-listad lezarasahoz" - } -} - - - - diff --git a/Simple AllTalk Manager/addons/sourcemod/translations/simpleteammanager.phrases.txt b/Simple AllTalk Manager/addons/sourcemod/translations/simpleteammanager.phrases.txt deleted file mode 100644 index f2093a7..0000000 --- a/Simple AllTalk Manager/addons/sourcemod/translations/simpleteammanager.phrases.txt +++ /dev/null @@ -1,92 +0,0 @@ -"Phrases" -{ - "PlayerLevelCmd" - { - "en" "Command must be run at the player level" - "fr" "Cette commande doit être tapée en jeu" - "hu" "Ezt a parancsot jatekosi szinten kell futtatni!" - } - "RestrictedCmd" - { - "en" "You must be a donator or admin to run this command" - "fr" "Vous devez être un donateur ou un admin pour lancer cette commande" - "hu" "A parancs futtatasahoz admin, vagy tamogatoi szint szukseges!" - } - "InValidTeam" - { - "en" "You must be on red or blue to swap teams" - "fr" "Vous devez être RED ou BLU pour changer d'équipe" - "hu" "Jatekban kell lenned, hogy megcsereld a csapatokat!" - } - "PlayerInValidTeam" - { - "en" "Player must be on red or blue to swap teams" - "fr" "Le joueur doit être RED ou BLU pour changer d'équipe" - "hu" "Valamelyik csapatban kell lenni, hogy csere legyen" - } - "PlayerQueue" - { - "en" "You have been queued to swap teams on next death" - "fr" "Vous avez été mis en attente pour changer d'équipe lors de votre prochaine mort" - "hu" "A kovetkezo halalnal csapatcsere lesz" - } - "PlayerSwitched" - { - "en" "Your team has been switched" - } - "PlayerSwitched1" - { - "en" "Your team has been switched as requested" - "fr" "Vous avez changé d'équipe comme demandé" - "hu" "A keresnek eleget teve a csapatod meg lett csererlve" - } - "PlayerSwitched2" - { - "en" "Your team has been switched by an Admin" - "fr" "Vous avez été changé d'équipe par un admin" - "hu" "Az Admin megcserelte a csapatodat!" - } - "SwapTeamMsg" - { - "en" "Type /swapteam or !swapteam to swap your team!" - } - "PlayerSwitched3" - { - "#format" "{1:s}" - "en" "{1}'s team has been switched" - "fr" "{1} a changé d'équipe" - "hu" "{1} csapata meg lett cserelve" - } - "Scramble" - { - "en" "Teams are about to be scrambled!" - "fr" "Les équipes vont être rééquilibrés" - "hu" "A csapatok hamarosan meg lesznek keverve!" - } - "VoteScramble1" - { - "#format" "{1:i}{2:i}" - "en" "Vote Scramble successful with {1} votes out of {2}" - "fr" "Le vote d'équilibrage des équipes a réussi avec {1} votes pour sur {2}" - "hu" "A szavazas sikeres volt, {1} szavazat a keveresre a {2} -bol" - } - "VoteScramble2" - { - "#format" "{1:i}{2:i}" - "en" "Vote Scramble failed with {1} votes out of {2}" - "fr" "Le vote d'équilibrage a échoué avec {1} votes pour sur {2}" - "hu" "A szavazas sikertelen volt, {1} szavazat a keveresre a {2} -bol" - } - "VoteInProgress" - { - "en" "A vote is currently in progress" - "fr" "Un vote est actuellement en cours" - "hu" "Egy szavazas mar fut!" - } - "ScrambleTime" - { - "en" "A vote was recently made, please wait" - "fr" "Un vote a déjà été fait récemment, réessayez plus tard" - "hu" "Nemreg volt szavazas, kerlek varj egy kicsit!" - } -} \ No newline at end of file diff --git a/Simple AutoScrambler/addons/sourcemod/configs/simple-alltalkmanager_events.cfg b/Simple AutoScrambler/addons/sourcemod/configs/simple-alltalkmanager_events.cfg deleted file mode 100644 index b739cf0..0000000 --- a/Simple AutoScrambler/addons/sourcemod/configs/simple-alltalkmanager_events.cfg +++ /dev/null @@ -1,43 +0,0 @@ -"game_events" -{ - "teamplay_round_start" - { - "reason" "Round Start" - "setting" "1" - } - "teamplay_setup_finished" - { - "reason" "Setup Period Ended" - "setting" "0" - } - "teamplay_overtime_begin" - { - "reason" "Overtime Began" - "setting" "1" - } - "teamplay_overtime_end" - { - "reason" "Overtime Ended" - "setting" "1" - } - "teamplay_round_win" - { - "reason" "Round Ended" - "setting" "1" - } - "teamplay_suddendeath_begin" - { - "reason" "Sudden Death Began" - "setting" "1" - } - "teamplay_suddendeath_end" - { - "reason" "Sudden Death Ended" - "setting" "1" - } - "teamplay_round_stalemate" - { - "reason" "Stalemate" - "setting" "1" - } -} \ No newline at end of file diff --git a/Simple AutoScrambler/addons/sourcemod/configs/simple-chatcolors.cfg b/Simple AutoScrambler/addons/sourcemod/configs/simple-chatcolors.cfg deleted file mode 100644 index 14b98c6..0000000 --- a/Simple AutoScrambler/addons/sourcemod/configs/simple-chatcolors.cfg +++ /dev/null @@ -1,15 +0,0 @@ -"admin_colors" -{ - "groupname2" - { - "flag" "z" - "namecolor" "{green}" - "textcolor" "{olive}" - } - "groupname1" - { - "flag" "a" - "namecolor" "{teamcolor}" - "textcolor" "{green}" - } -} \ No newline at end of file diff --git a/Simple AutoScrambler/addons/sourcemod/plugins/simple-alltalkmanager.smx b/Simple AutoScrambler/addons/sourcemod/plugins/simple-alltalkmanager.smx deleted file mode 100644 index 6122756af68998fb531abcd0d08698e24cff25af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7028 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 diff --git a/Simple AutoScrambler/addons/sourcemod/plugins/simple-donatorbenefits.smx b/Simple AutoScrambler/addons/sourcemod/plugins/simple-donatorbenefits.smx deleted file mode 100644 index 821d61d784607595ca400d273a941a42e40de640..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16600 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 diff --git a/Simple AutoScrambler/addons/sourcemod/plugins/simple-messagesuppression.smx b/Simple AutoScrambler/addons/sourcemod/plugins/simple-messagesuppression.smx deleted file mode 100644 index cc20dadd37d8ff23d0a64513cc09650f4bdbf24d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4845 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 Blh*(M diff --git a/Simple AutoScrambler/addons/sourcemod/plugins/simple-spectate.smx b/Simple AutoScrambler/addons/sourcemod/plugins/simple-spectate.smx deleted file mode 100644 index c6885b041145a73f664650e729a5dcf8b3b0813f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19129 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%0ACwUfid=y*oPG;MRqmWr)g0 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�XP zM5L)&uZne^XHs;_L+03=Xy3CiU1O76^S{TWu{zY}Jlq((BV?9EL=m4MC%~!W0MzeW zOjQv*a;A7AS@l%h9EbjzQ3d}e&j~R0VCoAN)q_>=)m=>e=ZX9w8jM3&o1RO^+0jJ) z

_|h)w;)ME+|h#gx@oo-|ZEuRI5d) zMl`=V%dcDbHEVwNSEv#n6n?du-$Pb&mH`?O1&-J0K*UD|BY z{LZ+vS*!Vd-=)n8&F`X1o7WSz-%nlIyrB7Ab7}Kj!p`*#OPe~?GfDMU_5HlICaTY( zra;;Mle{R_{R6uTA2Vec~@kN7Nro;@EuRFYy!gpC<8YqS#tf5cR(%@pG}YdLXKIGCvnv z>ja|SJeg%TES(W`(PUng+iP>8uAabOegu;&&;^;a^7Jv$+4T_vB^w0Gl(x~7sp&E*lb zmdmNo*jPy%ldX$a)E9i>Eo~-1z%Hs_0A)EIHmE21BFO{yStCf7cWt_3^oi;CBE$ zne0e}+44B&raPEiPgVrr=rPzwqKq_X(h-a9MvPWsP6H<$c{Uo99>W}Q7LLpQGyC)VDi z*@lRBn{AyAgDb+*X>~=_PR;sC)Z8N&kr{y*tg#63gnesG9Jh%UA#`VNw8LSnrM_1D zTY86jFk*2NZHoTZ*@j$nqHfehe4oPDW%j2r?;`C~XRz`jELy0_9p=g)&Ay=tveY6o>4!89X zSzTb|y6yca(S)aF{3nyhvRQX1Q%AZTC5V=6HWSTM{HvC2M=gqDG)ruk zbB1Ww_HeW#(i<|jlQpG<_>qH+`;0soWo6^JTr!UU-DV`7AE)&l-rTJAr*ZR;SbpC& z4*@#s@==xZTU5CN*x&ic%qt_cKB$t6yC&pfjxJ{FvI}tZKGvjJPOCfU)3fSFgp4uj z^X;&-2xUZLJ7Xy|7q`Ybnj8r0HA#$u^do6>sV+NA7Hs6-4or*=ml7Bh;l zOeGYHrdB2}@r4#;nmpAC%XTJbH3%T*R>6ebQZqfvz>N)h&kRKfi`k%db3YU&`<%j} zQrOk11-tzIScm#Jh#Cg%AzF^vahk;#F=17y4KqRRsx5viD{Mwnd@hGV)G;hp{G(@< z`Dl!W%)b0Wyn0My@saY5CU04!WKD^wg4CL*TCP^2adkLGYbPYFDx-%GBf4zJam&_| zD~WC%r?tPTb~}9J*e7AVR@ic!k-vB>O3FEy^iw~bo*3J##|G`*G zCh_|tk?g`~ZOF@cED-oXu4B{M;}wfn-DoW5OOT~KT%meia1XA*o!}0^-66O`aCZ+!@W2HRdI|2X3GVJ5T!Y`C2OQkve^PI& zdiv`g-PzinovBq&(9%UhL^P8_K%iVjK)`N7KtSL|d`tweqn-;PUXbc5$@v{%`QJ@_Gd~D<4NcyI1hBvj1<>^*@HKwf+C+{Kxq0=<CbE$`^|+5LZNdi!`ey1lj*uy!7b8<1v@elM1qHM)gqS$|M$`{8I5w(`-&)N|Y5gBxu`Dm}2 zoyBm~l$HG}c)b)7UvcYU!~61S^FGi2W#;bh^kv}0^?GjLbm#rL_oc-BI{e7bT@cG6 zYZ%J+tWOqQ-@o16zHiRGks5v5nrxca56AIJ=gn0Vwf`ZpU(w`Ye(aXYZ~vXbBd#^m zw3*&5&WHQ`@&Q3<#=8C(Zr>xr79pd?L(IXYQOXv|&&wSsx>v#|oD3cR67ex~!sfug zzUVR&a>?XBFepX)tZ!^y-2n~-tUHeijDU+%j+UJRzMlHdV2|-4Y$^TxH1tM1t1$ng zJ&2>97u5pQdmDJr0~(8v0=)@ejhG(XasdXz21UTt`MduvCh_5x$q?@SSgDLRG&jHZ zN{@QDry|_%i4QN;8!qkxjFxWi47r}y*GAA&7-uNB!`&7C%*^4al8L{!tC1PwhHcUQ zUHlkF^f@DK^kF~$yDQzr9+)TvZmiroC2e1ZkXJ}f!YTUHnIW0$v;qN+__)oF&2g$}VeU=hm*`;X()E7?-n^t| zlB8#*&;>x=^(NeNx0#xAK7E7@ZT0GCuQW3?2QxM?kMPa&2!$S9>9PbZU zf1e2*PKdp%+?Jv7jq5Irh336$%`=si_k(rH4@fCMl2XL}5rl{1Ln7bxD!MH&zQob( zx)-2Pj0os|9^P_IaOb!e{zv-~7GDQk=gNdWsd$a&#fQhynKJkfF~0QD?Q&Bp@+#E? znfk$GsxbOj_s2Jp8eZ6Yje9hl3NNgi=w6DZyHX}{ zk9qIv@=OC{{9rbWYbzR$z|`Y@c+p|_%phDZZjpqZLeG~a=@ z%zDBt5aE$1FkB+AlxYuK2@zh10t0bwhc|qIvy#9|?Se%lA`VWzrrpM^iR(m><@JO@ zP%=L>+LC_roX%9DI+(os`!g{ZH`vH;F~Co5?oYycqSwTiz;SZcJ%{Ky>L;*wLHScgQ@|$7t?=F zw>TSO`s|=_>GAN^gz&nFtF67=aQTGpmw=F9O+cD-!r>HXNS>ZafJuO9(g15;#))gP!TR zV#9lejk5uGROsH69877<6WPb&l`M)9`$3;u5Gp?>Sv4q<7jx&xxn7LaRI9Sqds-#j ztK9B5z0|j;&Q?Qp{3yiKPdjP0?3tDCH8kia!|SSd1J|nh-#plF$Sld zZ9YsT34MY5FiJcGdfl|MC$w^}zd+6^>N9}rXcMuQ;x3UlWBVe>wVdp}2!*b z#la!}8j(|8lJ3=%cB<6stEtla+;hF!!d0CTJ&J0cGycv7Q|@*5T5pi*#_6pkzZY5C ztf<*^VEem~#-E@U0L&h!2wb)wX+!8|7i8E2A* z6P#;?o?aIa&0rQWH@lH|ii#{lsm#ky_dH+t zLf%V|)`o=zX$?;A$8sMoW!Lzelw6QaYg#mI`kkL&2(l7x+t(NUI^_yEeXM&HRHaGU zyn}y|I<^UA#Oz=e_|%g|xkm+y zmJFQ*LJL~!y*Od1yw#@9Tk@`^U$-i#lcqm+asO_TJ%E3^sZA5b64v);w*Py2(L*&+ zN{#ybX_D$;91nBSfXYsIxfmrpY`?m00|)TP0`Ea7i_?J_W}pX942*l0F3 z43Z^wZub5*Z}xa7VJsoZI^Hv) z7aZ|WgRu4i)b)#VR1gn-v~#K*OB zfvM}bo*D8VopaDG)1M6QZSsY<|G0=9IR-N>A8?sG!<>r?H&~3PotliVXV(7xOs(8h z6bOQd-{_fmTzF$ILj2POQFYp!NY;Hw*7;F2KvH%mRS&wso#T%Rd4ixeF8KPPM+B^# zU-7hx@8vs+K(wNSe`>!7JmH#?%4^WBx-PiOthM}u#zwS9P+0Jh$%BNHlvp?Op~-`Y zK5cjAHMCo`gdAUG3n}}fN5fv`)d|t09xzRHaW_0-hH_A(*py)=L5?x#TGG6 zTcWq>MmCu{XS{jOZ)W)ypL5j`WhIFnoso~ILKiU)Y+@yUV}d=+Pf~+#8byt_qPQ(GOPGhLx=+T3Jk%^|yCqI=|j-}my4ce_MDT%YrX^G#*$;0vv zOUFzvBLzkKM2Gq8_XF1^2<~r$`ib=6SrkZU- z&%NgfDnZ#2obZ)uu3`7q=MytI=V5+TDbf2%i7QH?s{j{AK?@sli{LA;@5jS&&S~nv zCADS{m1^Uu)lTQCBQ9t2oFp&j{mX(CNf)lO=QOcVzWdzL=F!Nbsi9?JFn}J!_PiF% znQc&F_Lr=zQN{eSdH=)(r(N_kbJw+C`%-P4{mFW& zj!jECc7{21>fQ;@aNFa+^HM&Q!?*UcKWt=ww=9qUMMtmO>rM%N2;+AMJ+&G2#$GaP zxRtDQC!JpsOukz|a+CGFZ+~j#Zh)mz8-;+(fGm$1`HP#7m#6dN)8L_k&NisneM}z2 ziPA=;*}^n5yv1DTqILf>Ezp$p1rhb4bvlMw)CXA5sazP^f#5oVxVEznOZ|17(<99d}Jdym90}9Jf%*&MN3^~3ze##AwXun&n@vYfezwTHH z9KejboWIM69M2Dj$pm)|&W!pC%0u2hc2Qseo#WL_4nkd4n}>tn2To-!^KjNCVD1ZS z89s+Qae~RnaJNQIlMgQZ^~X)`tZv&3OaFANKjT!Im>zXqSg4TE(kN1ZEXaPs6euim zdBG#W2;a*+QbR-Wwt_7FF4*2SGv_p1E}y%NNhVkdUr2709=kttw}_Z$aiFS#5zT6sh4qrE4!@A!}M3(p)|hKQfC&utReCm)Vzj&hp4 zX@&ML!f!o0|57K3ytvK|T?oCCa`%`b!fAOYWFY*rSSU#LqP?#@*gnVk@uO;qQYbfz2;l)1}oCE#^<5(JHRu9hHj}mz6??-Qjf~RW-jEm6CMTZdaw6 z+8gUjdgn3LdR66Fv`PKp$o^!~F_^G@{;;I_D@=KMnm6-W;WzwB+-BZ%r$+eVQuv7J zG25%q#_YK#`^+oYI?-3*D1L!Exb$erN|L@6C$KZ&!gX%!=l9Lo%ZK*OTZeJavmuh1Z7>G?GyFJ4al(HsrBiBDy-!h?pHZMPCXS) zeTX$WF?#H`CY^cxp?w#qv!1|B8%E?C)RluVJnc`7>OT^?wmE*$oROR6?7wrvm-de^ z#F_I!-+#*coMeFjC?IsO$&I%+k>drd^{;Lox>XvtY1;~)9F`TD-O~CJ6Co}R6*RVM z8P@)sAQsQgSJ=d$iTWij1@L;)mNfA8Kl--p`) zX6_3PZdVG^6ow}H6A!z$&F?NVyQLF1;1JBQ-Soygo@UAds&p|LVoo-@*L)8reH47+*J-Jkl`N}f$lW)4(d zGvsV3pAs>v`!&c|QlLw}!L_UvI~`r;H)ozVwULTDCXn0bM^HeEk%NW5S7s$w)_FQ<%-aNlfMdmC}Sr_Yrjnv4(2WXwm; z$r4v4dDR81)pefY!v~b$>rT~zivYdxpz0ugxM4%mm2PmOS@gz~hk^T47v@d}O-tiP zV=I-?9rC%~8BbJ;+*i*y*J>|J_kTzhr}r-8#SS_b8R5%8_XRl)F26C$dk}yV$ zSmIcXtwq4;M)7UoaUfL6pg{P3LoU3hFx_5pdCeh+r9om=qe@YiV7Xo*)k_zy;5kAxst8qrr9=f;6X>I9wpiao$M|dQ7WtEUU+v-Pd49I=pf5Es>ej6UMhRb z6sAunp{AexkF0)PbNFq{?yQI`Waq_@?i}_R(O3=J#}0kGIVEz_wl?{=P%tO*BH{L^ zP_A-B{k~4(DQdrux<$V`!j!xHy_eYNIa4cey>TBW7@8Q7xRvU1n_VN81%WnsKFOT=j-Q6$Gx6`m| z2b*u!;N`33_c!56KJ?@C5T$~cC*!zFyw3d-TlX@vThi$F{l&6m@##3OaYcolzjl7v z((yAq{?)=2t#4O&UjN-L;9U6E`q+@Sp1;XfyKIPb#5Ou(Dn}?yrHg+pRe73<@>rAk zkg4F`{HHmXKXbdA7wRY#edd(Q@fxvu1c1HM6h?2(kH1O)yo=}YZ-i2*l*sUt<4JAU z&~0k5WvI>8(T2k&KJqij4p9SbV~e#KxZeR?6Br-uq>HjPGj=vN@lQbI%;(a=vPt%h zj`6>Y%Q*3A(BqWkxbl=MVFRhp_;hvH^clZ%#c$^>e?igOXu}Hr7R0HE%IWPWzH4w? zJUV2~F?Z)DjMM&QONcWWW~=Y)TviymdZOk0H(pFQZ_}YjNcmwDq+pCiXh(oXEhAp} zF6)yfZ#`#90X$2Om+MI9;>MO#>n|^5f_<#2OmXVI`a5g1(&fa8e;xeoGIR9DYChlh zaF|=_)(31N>#?@f%>~g`75h>GSC!~kD>jyvS`@Q$WU_1>RQYX(F0ft6tjzcQ)2uPf z%X+fG5jq-*tf-xiavJt@TTqR>PA;%MBa##T_27S`8nZ`-Vzd@YDvLQv z@S;bR{GGOZEbh9KajvnMJL_cUw}qBL>7oUbg3BtQDg$3d51q>L>zc#Doh;|Bghvnu zh|~H;4q`NrF>jI6^>h-F@jF@~tBe!%cprgohlw9=l~^8t#OC|109~Ce ztq55s=_;4vB=$2e-P5R+nL{uKHEyxeZW&e9*%&Du{wVN=(A^;Y3_3m!?$jw|D}gkwRUMXR zX}2J+7i9)JJU4qVkU6*|+sgQuo{Id}#R#>QO8HC$(9ef!i_$nt4I?=f1H&l5=W`Gr zWTY4+J*{`aEHqN_4IDfPSY{khn0Ppcp4WekRwYE8{rYpcnQ_hiT9(HTo!Vh@A?oXo9lA90pd z%tm-u8I9yjVO6nA-0BquUd%eQxf&mErx$L~LrDpINo9QF{kXF!n&Ua?Ws~`_qZks0 zl*DnK3D&5U8xKDg%i~M(;hm6a;HRs_o|a^MZSS_Y3GXLM+!~5dDgYHsygN}WOV6rr z7i?cRX>4^KF=f~8=IywVx%uRdGkK9 zg15GGXUpa`Izm4JShQ89nE6s;!6E$-E+I%s#Z=>}5$$t{qywI4>d}9rkkG1~q-{z)>6*H) zOj6g~5@Y0+a|EA_4Zrg76U1tfh=B~1Ch)B|)>`-(-N+oNnWD74Iq(JM$AtTIX$I8W zG3md&SmC*yx$rD&m*WyVet1L^f+|E;>TgS*%qUS5KNiZoJqsECHSXu;YOPc#Fg)|o zMJr94{@$NTkF6a4v-FOra&An@LW&MC&iMAMT=s1iXD4!Em6C}9D^)Vn5VTXT>iEp| z{89ZIO4 zbC$P@x8k`fJ{UHCd+eYvH9A3NWX`+Hp!@Ic@bj{XXry+e^LabQOai-9lpU?V2Bm8< z6M5X`{?E=v&?(v;I4ua24itIkd60;363Ou1da1yfx{M5kCH)nNLzgDjEcCi&CuF}f%?=AT>}eOMyf#f3M$6|B+ZoGrimNkAuDmy zGG!j!v#{t1kEp45^~jd5Z{EGQ zZUr;fjTDHu1U4~|<=fAiB5#q166%wTXpEx3-oq3g=NbLb6&)%`7pA<{1dVJ$h)7$U2@QLsnYG5}CV*s=*Io011BUwLQkJzt}b@nfJ5q%mMMHh8Ll(cUR_r1p%`AcYzNz^T0P9%MYgr zwGYp%Jx}=u#RF1NAQ=zls66d4$f@e8pSCRP<&%Wo*qw&C&e)SfC-QX0tZ?o&Gs~v3 zmj$DL#5!>FIU^U?XQp}a$;*3$lesn9l%!p_{e0hC@xpaq(y-6INs|43yG!|^bU#e9 zX2G6xIXOq#4YB>R*XfA-2zE*^Sv&J+XZre|kxtP1@JMLVI+@qe=yUEmXf(0#cdo{T zpV#ev-@fsvD-#K`kc=B{du#F&LVMx9M#>Xg`(^SI_GUzJLnWO*VY}GqhN>HOJNACT zKJUJ{x*K=9{b=Zqbx$t~hWm4b@k5P=nlpBl2k{wal|iy^7tE@It4ZKZ9Zz#QSdxxa zKR4_`$8(AW=3iW}*-yhsG%Ve(s5(ei2tHC7TrB|~>v$5=!)|pTk|t2G;$3k)=+syoLWFTQ2PV?ha+pXbn8@GvKA@Df;IM#buWSi`sCsbL1{(1GwO)useYpR=gmQ z8*V(aeP2%Gu35PUKg-l)3~J=Ai!#(s+Ow7o7X358f(dr_Q@EBeOjBz_8!9Uep;oys z1?+wcgI-H}a!XhI6t^wfI<|#S8KM4kvzRuh}O|BA#RUxi{iZSM54 z)8*wU$eqhUVsG6C%uHzX-C0gc;PcsOO-pEW*tyTdG%?!IBw)Cmdv5pob=qf-)*?+k zCjSQ){&ltx@?Z0S#_%CKeGBi;*`mwi@Gxz`#v|ZOtY5+6a zfYG-ZR=@)8*D1WBi}yZBw5<0tQ5c>>%s%BZx%wD8oST^hFp1u3)U|7qX}yeq2LYT+CN92?&X0bl{nP zYfPD~B6Jyhhh>jExwMj@#~{!b6a2-Hip+ZHFF~$kxNp^kQ>y*fPYK`iNOyfl2{KLp zdgKZy7!@;13=T!!>>n#!C;c)UD;k%TWnwREgL<@())I-*@6WgzUAD07{Qg}a#%m^= zqkxiUG~eFkil(}r+;+92D{_&a)%8e8eFZaaxzy?y7neJ{F{4o*d{po-ck5h_A)4@K zT9%_HHKgE#*fPjoiOGT9@+|QQBlDP1t@hq#3w|noSgshrATOFXqy(Y-UwW&M#9_wK$KaPQ>q{U1&}aWcp{XPYRhB%9 zfej3rd#o7><|@nh9L!3kMjnjXnjXbqOh1~Y&q#W_<(PHPFfYvhF4JL9ylkWKel0;X z08N^JQK}(DPg$IeC9ceP^}~}M!tO9za(ddp9qVT`sZ<%0t=~TU%@xZx=@SA&smEn% zNh@>~ZnQG@9{}ieI($-5@U?$hAzx3jeL-N#Gqa2np&tSE1RQ7)hUmX~AYy@nI+SMb z1}(X$z1lfcOKqOfHNHu5`l<{hm#~fPe0{fWXEH}@-~~yLuVPJ!!z){soLr;ZAy!1S z(N=0L!w5|K{${>b;DrBurdUC%q7tHbO5ZPq$3@b_VNT_=;?7SKB@pR#e__=|9t~Fw z+3LiSLNaMz&dF=ef|8K3*viTN@1Iw_%ta~th9-W~5Ea*b$*WfruaM04A1HI;BjXaV z{A3kw>I`#UYHsoK^{Fvy{)_@Q-&$W;ZTU3s=~v9uz3@v_wOpj>hpg*tsVFm&xVsK$h^Fx8>)#JORDJxCg+bX`;nttFr8ruz7_#rojfCXCj|bw)`r_;c8NhclN82 zw&0gLB{trbxTrAx5J==A$sM39Z&sXK7!pa&e!Cr;N``0Xz&ppU#k0-~4&&fYn^iDU z9Sjor{b(qrrd*Tqr%{bAoszmhkd2PlbZMSYy;NRhy;ULTt~LOPJ0(K?=JU%0okq|uyb=fj|z)$&e|9ioanh@18g#&m7pdFySYd(@!E z2Dn>cN&RIpS+2($MPoLgE?V*E`ViNPF1aMv>OXRB79#nM>U}+RQatdpgXOrpt8Fm* zr=Ic+?Pgb@w3a~;q`jRThxo_3{UyV+W*i!ql!&jj)|}1Qq9AdG55ZC95PS4hHA8koON5QQ};6@R-ORnvQRi16lc;5W|(k(oMxFA-g2g;xMtUIrOMS$pEQ8iT7QOjqFTSe^RY9m zcE6-i-a))%j?QPgp_fzZ4Hey%^UUDz!~GiCILB?)38`Q+rVE0PU;@H7XNoB-Yh=MuA9k=<#8CocU${przCi|sC zG)g{OEqrlnGw%~cKT>T|>iffJ%CRFsz?JOrtDq2RA?F9mNld(MEkUKh!l}O3EnD6L zf8zT4GeWUxM2(bgal^89eRJ53DvP;7JP86|uE;%(UpCT0l4j7kMZR;fn>`vqDYo2g~8hW8A$cp4T%as6QS`x}X=DasMzg-GH3 zSf&vnVFu&9$UL*rxI-8Z&(kltB2om&wH zK$*ruk>1+12f7Tde1@;vmVS96EC?W^HWKK^;4AoG$W0ORbV)~))hv|b^6%*u0*Xf(sOhwAt_J36HN0}Vy%1& z$dwLQq~3)s*|2or>9`y0lzxlKEtPh`naqkLQZC2j85&pp)t%MK8Q(w6;rwEgpv%13 zl(zGmX(fvbKWon!UWN?2w!rtw>ew%H11KmQH{|qJLotweg0PZ@I09m@$^K#p&?)-z z(~Xqn5m=V7!|llvU%MrHI&Fo2^hniEB5$rSovi<&{2!Yp!?!RXm5ZUcT*C@My6h$USN;?i!iK_1M_U zoCD+vJ~Ec4pD5;l?omXavl$ehL!g2e%M9msY-5$r4RaQkN8T-(PXZC)z^mt6%14XG zsZU+kNFnup$)?|8RGe`f$S%?9>|lwAoO>p3Qc{PJ1T_?pT-@#j5Z!WCJ_m~ajC*Wk z+rUL$Dcg%d$`%hdeh3q!RXrRH(7md@x^RN{m=!iyyzxNao@ZO7VAkFt28D7~5f6!yJ(MlTKGwo$;ld7khJ z+q!lg6wqVdmJ@Iu@8&ZH_mSC1@VJrQ7OVS{B)z*m+;kHSTHHYtXQsMdF!aN*wRdU8 zGdKv1m`V%K_8vnO9hsXnL>0_yn`jwp+T6h!kk`Q~tiOqut8h{E^+;U2go4qZ-cPZ! zV~>LP;*M!LVX_DL{_aQ>yW z0%W8N^FxopB@99J3-qMG3uNE%ibzlGPS4<=PR|hhurxH;V=;;Y7FvIZ_2dky*^-VV z=s+q~26tOg0k-wmOBkWd1J|DC=JKtPe^=%q4A{%+Y0u z@s(XySCMhO+-+SjcP4Q-S{K<1|GzCvI7Zm*nFq=;`~ah7dQBxGGJtXUbVr31HQlr} zlfC$slDwgt;v{Rk@w+?VGE$sS{A&O*oEm}_hW09?UVQoXa?Qw600?R?kWKt9QB}GN-2$yP_gs zNM9D5@I4qX-8+WY3&%dCL)N66fBcQy9q)slFaMkH;ifMTu=Ujr z0kDPitSs*6oIQ}*vVk1_bu(cb$fKDxP)fx`2qW9Yr<51vH-d6Pb2&7n)jkKhGeZ@d zN=G^FgCPZCYqPc)aK2O{|0In=KP`FsErJm%fz}v5K-h?ZKr3cPk156jGwBUjwb_BW z5PAHUbBTvoFMFN?&AD#CRBR^GFU|ZPeOJI`9QSK*!q@M?9kghH!>575&Glf>jMKqo zi29KPG6}x;M=*7frU&{BaqknlIl~IFB${BM8KDcJME2Jz1Pk4VlAFHrDn$}PQ&dr8 z8tFfDZDczRVRI;*iXSjSMP9#ra!Me!H|PMMbhyTzE`26?7bTxoc3%g^fg)IWh8Y^P zKGl`4nQn_FDepnj+e#<3e0_7n(%ULcgBOAdWrA}3dz1a#f%^FGZPy?bGt_+jgb6AM zRt4kr5yH@J#MHk?Vu<%@7MP=jVU${+g^}MlaQRTS4x@)rKfH&c7_$AC66(Jv48aM( z6HheRMebJdV4MVYMc<%@VZsPu)NW~81Fa*q>jS0Mme2d8+nL*TxF)?&0qA=u#lrlg zxNJ><2w}c;#ruDylE2a|5lU^`c5?oqy6xx+D7x*CUALPAG=w}5UnHXE3*ok8@Xc z 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 z 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 KvHt-#rc|>H2mv<$ diff --git a/Simple AutoScrambler/addons/sourcemod/scripting/include/simple-plugins.inc b/Simple AutoScrambler/addons/sourcemod/scripting/include/simple-plugins.inc deleted file mode 100644 index 8f21956..0000000 --- a/Simple AutoScrambler/addons/sourcemod/scripting/include/simple-plugins.inc +++ /dev/null @@ -1,337 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Plugins -Description: - Included file for core plugin in the Simple Plugins project -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -*************************************************************************/ - -#if defined _simpleplugin_included - #endinput -#endif - -#define _simpleplugin_included - -#define CORE_INC_VERSION "1.1.$Rev$" - -#pragma semicolon 1 -#include -#undef REQUIRE_PLUGIN -#include -#define REQUIRE_PLUGIN -#undef REQUIRE_EXTENSIONS -#undef AUTOLOAD_EXTENSIONS -#tryinclude -#tryinclude -#tryinclude -#define AUTOLOAD_EXTENSIONS -#define REQUIRE_EXTENSIONS - -enum e_SupportedMods -{ - GameType_Unknown, - GameType_AOC, - GameType_CSS, - GameType_DOD, - GameType_FF, - GameType_HIDDEN, - GameType_HL2DM, - GameType_INS, - GameType_L4D, - GameType_NEO, - GameType_SGTLS, - GameType_TF, - GameType_ZPS -}; - -enum e_Teams -{ - Unknown, - Spectator, - Team1, - Team2 -}; - -new g_aCurrentTeams[e_Teams]; -new e_SupportedMods:g_CurrentMod; -new String:g_sGameName[e_SupportedMods][32] = { "Unknown", - "Age of Chivalry", - "Counter Strike", - "Day Of Defeat", - "Fortress Forever", - "Hidden: Source", - "Half Life 2: Deathmatch", - "Insurgency", - "Left 4 Dead", - "Neotokyo", - "Stargate TLS", - "Team Fortress 2", - "Zombie Panic: Source" - }; - -public SharedPlugin:_pl_simpleplugin = -{ - name = "simple-plugins", - file = "simple-plugins.smx", -#if defined REQUIRE_PLUGIN - required = 1 -#else - required = 0 -#endif -}; - -#if !defined REQUIRE_PLUGIN -public _pl_simpleplugin_SetNTVOptional() -{ - MarkNativeAsOptional("SM_MovePlayer"); - MarkNativeAsOptional("SM_SetForcedTeam"); - MarkNativeAsOptional("SM_GetForcedTeam"); - MarkNativeAsOptional("SM_ClearForcedTeam"); - MarkNativeAsOptional("SM_GetForcedPlayer"); - MarkNativeAsOptional("SM_AssignBuddy"); - MarkNativeAsOptional("SM_SearchBuddy"); - MarkNativeAsOptional("SM_LockBuddy"); - MarkNativeAsOptional("SM_IsBuddyLocked"); - MarkNativeAsOptional("SM_ClearBuddy"); - MarkNativeAsOptional("SM_IsValidAdmin"); - MarkNativeAsOptional("SM_IsValidTeam"); -} -#endif - -/********************************************************************** - * When a player has to moved - * - * @param plugin Plugin that initiated the move - * @param client The client index of the player that was moved - * @param team The team index the player was moved to - * @noreturn - **********************************************************************/ -forward SM_OnPlayerMoved(Handle:plugin, client, team); - -/********************************************************************** - * Move a player to the supplied team - * - * @param client The client index of the player to be moved - * @param team The team to move the player to - * @noreturn - * @error Invalid client or team index - **********************************************************************/ -native SM_MovePlayer(client, team); - -/********************************************************************** - * Move a player to the supplied team - * - * @param client The client index of the player to set - * @param team The team to move the to set - * @param override Whether or not to override another plugin - * @return True if successful, false if not - * @error Invalid client or team index - **********************************************************************/ -native SM_SetForcedTeam(client, team, bool:override = false); - -/********************************************************************** - * Gets the client's forced team index - * - * @param client The client index of the player to check - * @param plugin Optional: The plugin handle of the plugin - that set the team - * @return The team index of the forced team - Zero if no forced team - * @error Invalid client index - **********************************************************************/ -native SM_GetForcedTeam(client, &Handle:plugin = INVALID_HANDLE); - -/********************************************************************** - * Clears a client's forced team - * - * @param client The client index of the player to check - * @return True if successful, false if not - * @error Invalid client index - **********************************************************************/ -native SM_ClearForcedTeam(client); - -/********************************************************************** - * Gets a forced player on the wrong that is currently on the wrong team - * This will only return a player if the calling plugin assigned the team - * - * @param team The team index the player should be on - * @return The client index of the player - Zero if no player found - * @error Invalid client index - **********************************************************************/ -native SM_GetForcedPlayer(team); - -/********************************************************************** - * Assign a players buddy - * - * @param client The client index of the player to assign - * @param player The player index of the player to assign - * @param override Whether or not to override a player lock - * @return True if successful, false if not - * @error Invalid client or player index - **********************************************************************/ -native bool:SM_AssignBuddy(client, player, bool:override = false); - -/********************************************************************** - * Rturns the client's buddy - * - * @param client The client index of the player to assign - * @return The client index of the player's buddy - Zero if no buddy - * @error Invalid client index - **********************************************************************/ -native SM_GetClientBuddy(client); - -/********************************************************************** - * Set the buddy lock setting for a client - * - * @param client The client index of the player to assign - * @param setting Setting to set, True or False - * @return True if successful, false if not - * @error Invalid client index - **********************************************************************/ -native bool:SM_LockBuddy(client, bool:setting); - -/********************************************************************** - * Returns the buddy lock setting for a client - * - * @param client The client index of the player to assign - * @return True if locked, false if not - * @error Invalid client index - **********************************************************************/ -native bool:SM_IsBuddyLocked(client); - -/********************************************************************** - * Clear a players buddy - * - * @param client The client index of the player to clear - * @param override Whether or not to override a player lock - * @return True if successful, false if not - * @error Invalid client index - **********************************************************************/ -native bool:SM_ClearBuddy(client, bool:override = false); - -/********************************************************************** - * Determine if the player has the supplied flags - * ADMFLAG_ROOT will always return true - * - * @param client The client index of the player to assign - * @param flags The char flag(s) to check against - * @return True if valid, false if not - **********************************************************************/ -native bool:SM_IsValidAdmin(client, const String:flags[]); - - -/********************************************************************** - * Determine if the team is a valid team - * - * @param team The team index to determine if valid for - currently installed/supported mod - * @return True if valid, false if not - **********************************************************************/ -native bool:SM_IsValidTeam(team); - - -public e_SupportedMods:GetCurrentMod() -{ - new String:sGameType[64]; - GetGameFolderName(sGameType, sizeof(sGameType)); - - if (StrEqual(sGameType, "aoc", false)) - { - return GameType_AOC; - } - if (StrEqual(sGameType, "cstrike", false)) - { - return GameType_CSS; - } - if (StrEqual(sGameType, "dod", false)) - { - return GameType_DOD; - } - if (StrEqual(sGameType, "ff", false)) - { - return GameType_FF; - } - if (StrEqual(sGameType, "hidden", false)) - { - return GameType_HIDDEN; - } - if (StrEqual(sGameType, "hl2mp", false)) - { - return GameType_FF; - } - if (StrEqual(sGameType, "insurgency", false) || StrEqual(sGameType, "ins", false)) - { - return GameType_INS; - } - if (StrEqual(sGameType, "l4d", false)) - { - return GameType_L4D; - } - if (StrEqual(sGameType, "nts", false)) - { - return GameType_NEO; - } - if (StrEqual(sGameType, "sgtls", false)) - { - return GameType_SGTLS; - } - if (StrEqual(sGameType, "tf", false)) - { - return GameType_TF; - } - if (StrEqual(sGameType, "zps", false)) - { - return GameType_ZPS; - } - return GameType_Unknown; -} - -public LoadCurrentTeams() -{ - switch (g_CurrentMod) - { - case GameType_INS: - { - g_aCurrentTeams[Unknown] = 0; - g_aCurrentTeams[Spectator] = 3; - g_aCurrentTeams[Team1] = 1; - g_aCurrentTeams[Team2] = 2; - } - case default: - { - g_aCurrentTeams[Unknown] = 0; - g_aCurrentTeams[Spectator] = 1; - g_aCurrentTeams[Team1] = 2; - g_aCurrentTeams[Team2] = 3; - } - } -} diff --git a/Simple AutoScrambler/addons/sourcemod/scripting/simple-alltalkmanager.sp b/Simple AutoScrambler/addons/sourcemod/scripting/simple-alltalkmanager.sp deleted file mode 100644 index c848332..0000000 --- a/Simple AutoScrambler/addons/sourcemod/scripting/simple-alltalkmanager.sp +++ /dev/null @@ -1,515 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple AllTalk Manager -Description: - Allows you to set alltalk at different times -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#pragma semicolon 1 -#include -#include - -#define PLUGIN_VERSION "1.4.$Rev$" - -new Handle:satm_enabled = INVALID_HANDLE; -new Handle:satm_threshold_enabled = INVALID_HANDLE; -new Handle:satm_player_threshold = INVALID_HANDLE; -new Handle:satm_threshold_setting = INVALID_HANDLE; -new Handle:satm_logactivity = INVALID_HANDLE; -new Handle:satm_alltalk = INVALID_HANDLE; - -new Handle:g_aEventNames = INVALID_HANDLE; -new Handle:g_aEventReasons = INVALID_HANDLE; -new Handle:g_aEventSettings = INVALID_HANDLE; - -new bool:g_bLastThreshold = false; -new bool:g_bEnabled = true; -new bool:g_bThresholdEnabled = true; -new bool:g_bIsSetupMap = false; -new bool:g_bIsGameTF2 = false; -new bool:g_bLogActivity = false; - -new g_iLastEventIndex; - -public Plugin:myinfo = -{ - name = "Simple AllTalk Manager", - author = "Simple Plugins", - description = "Allows you to set alltalk at different times", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -} - -/** -Sourcemod callbacks -*/ -public OnPluginStart() -{ - - /** - Need to create all of our console variables. - */ - CreateConVar("satm_version", PLUGIN_VERSION, "Simple AllTalk Manager", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - satm_enabled = CreateConVar("satm_enabled", "1", "Enables/Disables Simple AllTalk Manager", _, true, 0.0, true, 1.0); - satm_threshold_enabled = CreateConVar("satm_threshold_enabled", "1", "Enables/Disables player threshold", _, true, 0.0, true, 1.0); - satm_player_threshold = CreateConVar("satm_player_threshold", "8", "Amount of players for the threshold"); - satm_threshold_setting = CreateConVar("satm_threshold_setting", "1", "Enables/Disables all talk up to player threshold, with the opposite set after the threshold", _, true, 0.0, true, 1.0); - satm_logactivity = CreateConVar("satm_logactivity", "0", "Enables/Disables log activity", _, true, 0.0, true, 1.0); - satm_alltalk = FindConVar("sv_alltalk"); - - /** - Hook console variables - */ - HookConVarChange(satm_enabled, ConVarSettingsChanged); - HookConVarChange(satm_threshold_enabled, ConVarSettingsChanged); - HookConVarChange(satm_player_threshold, ConVarSettingsChanged); - HookConVarChange(satm_logactivity, ConVarSettingsChanged); - - /** - Remove the notify flag from all talk cvar since we do it - */ - SetConVarFlags(satm_alltalk, GetConVarFlags(satm_alltalk)~FCVAR_NOTIFY); - - /** - Get the game type. We only care if it's TF2 - */ - new String:sGameType[64]; - GetGameFolderName(sGameType, sizeof(sGameType)); - if (StrEqual(sGameType, "tf", false)) - { - g_bIsGameTF2 = true; - } - - /** - Create the arrays - */ - g_aEventNames = CreateArray(255, 1); - g_aEventReasons = CreateArray(255, 1); - g_aEventSettings = CreateArray(1, 1); - - /** - Need to register the commands we are going to create and use. - */ - RegAdminCmd("sm_reloadatconfig", Command_Reload, ADMFLAG_GENERIC, "Reloads settings from config file"); - - /** - Create the config file - */ - AutoExecConfig(true); - - /** - Load the events from the config - */ - LoadEventsFromConfig(); -} - -public OnConfigsExecuted() -{ - - /** - Load up the settings - */ - g_bEnabled = GetConVarBool(satm_enabled); - g_bLogActivity = GetConVarBool(satm_logactivity); - g_bThresholdEnabled = GetConVarBool(satm_threshold_enabled); -} - -public OnMapStart() -{ - - /** - Reset the globals - */ - g_iLastEventIndex = 0; - g_bLastThreshold = false; - - /** - Check the map type if we are in TF2 - */ - if (g_bIsGameTF2) - { - g_bIsSetupMap = IsSetupPeriodMap(); - } - - /** - Set AllTalk - */ - if (g_bEnabled) - { - SetConVarBool(satm_alltalk, true); - } -} - -public OnClientDisconnect_Post(client) -{ - if (g_bEnabled) - { - SetAllTalk(-1); - } -} - -public OnClientPostAdminCheck(client) -{ - if (g_bEnabled) - { - SetAllTalk(-1); - } - CreateTimer(2.0, Timer_ShowAllTalkStatus, client, TIMER_FLAG_NO_MAPCHANGE); -} - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (convar == satm_enabled) - { - if (StringToInt(newValue)) - { - g_bEnabled = true; - } - else - { - g_bEnabled = false; - } - } - else if (convar == satm_threshold_enabled) - { - if (StringToInt(newValue)) - { - g_bThresholdEnabled = true; - } - else - { - g_bThresholdEnabled = false; - } - } - else if (convar == satm_logactivity) - { - if (StringToInt(newValue)) - { - g_bLogActivity = true; - } - else - { - g_bLogActivity = false; - } - } - if (g_bEnabled) - { - SetAllTalk(-1); - } -} - -/** -Commands -*/ -public Action:Command_Reload(client, args) -{ - - /** - Clear the array - */ - ClearArray(g_aEventNames); - ClearArray(g_aEventReasons); - ClearArray(g_aEventSettings); - - /** - Load the events from the config - */ - LoadEventsFromConfig(); - - return Plugin_Handled; -} - -/** -Game Event Hooks -*/ -public Hook_All_Events(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (!g_bIsSetupMap) - { - if (StrEqual(name, "teamplay_round_start")) - { - if (FindStringInArray(g_aEventNames, "teamplay_setup_finished") != -1) - { - g_iLastEventIndex = FindStringInArray(g_aEventNames, "teamplay_setup_finished"); - if (g_bEnabled) - { - SetAllTalk(g_iLastEventIndex); - return; - } - } - } - } - g_iLastEventIndex = FindStringInArray(g_aEventNames, name); - if (g_bEnabled) - { - SetAllTalk(g_iLastEventIndex); - } -} - -/** -Timers -*/ -public Action:Timer_ShowAllTalkStatus(Handle:timer, any:client) -{ - if (IsClientConnected(client) && IsClientInGame(client)) - { - new bool:bSetting = GetConVarBool(satm_alltalk); - if (bSetting) - { - PrintToChat(client, "\x01\x04[SM] AllTalk is \x01[on]"); - } - else - { - PrintToChat(client, "\x01\x04[SM] AllTalk is \x01[off]"); - } - } -} - -/** -Stock Functions -*/ -stock LoadEventsFromConfig() -{ - - /** - Make sure the config file is here and load it up - */ - new String:sConfigFile[256]; - BuildPath(Path_SM, sConfigFile, sizeof(sConfigFile), "configs/simple-alltalkmanager_events.cfg"); - if (!FileExists(sConfigFile)) - { - - /** - Config file doesn't exists, stop the plugin - */ - LogError("[SATM] Simple AllTalk Manager is not running! Could not find file %s", sConfigFile); - SetFailState("Could not find file %s", sConfigFile); - } - - /** - Create the arrays and variables - */ - new String:sGameEventName[256]; - new String:sReason[256]; - new iSetting; - - /** - Load config file as a KeyValues file - */ - new Handle:kvGameEvents = CreateKeyValues("game_events"); - FileToKeyValues(kvGameEvents, sConfigFile); - - if (!KvGotoFirstSubKey(kvGameEvents)) - { - return; - } - - /** - Hook the game events and load the settings - */ - do - { - - /** - Get the section name; this should be the event name - */ - KvGetSectionName(kvGameEvents, sGameEventName, sizeof(sGameEventName)); - if (!HookEventEx(sGameEventName, Hook_All_Events, EventHookMode_PostNoCopy)) - { - - /** - Could not hook this event, stop the plugin - */ - SetFailState("Could not hook event %s", sGameEventName); - } - else - { - if (g_bLogActivity) - { - LogMessage("[SATM] Hooked event: %s", sGameEventName); - } - } - - /** - Get the reason string and setting - */ - KvGetString(kvGameEvents, "reason", sReason, sizeof(sReason)); - iSetting = KvGetNum(kvGameEvents, "setting"); - if (g_bLogActivity) - { - LogMessage("[SATM] Event reason string: %s", sReason); - LogMessage("[SATM] Event setting: %i", iSetting); - } - - /** - Push the values to the arrays - */ - PushArrayString(g_aEventNames, sGameEventName); - PushArrayString(g_aEventReasons, sReason); - PushArrayCell(g_aEventSettings, iSetting); - } while (KvGotoNextKey(kvGameEvents)); - - /** - Close our handle - */ - CloseHandle(kvGameEvents); -} - -stock SetAllTalk(index) -{ - new iPlayerThreshold = GetConVarInt(satm_player_threshold); - new bool:bThresholdMet = ((GetClientCount() >= iPlayerThreshold) ? true : false); - new bool:bSetting; - - if (g_bThresholdEnabled) - { - if (bThresholdMet) - { - if (index == -1) - { - if (bThresholdMet != g_bLastThreshold) - { - g_bLastThreshold = true; - bSetting = !GetConVarBool(satm_threshold_setting); - new bool:bLastSetting = GetArrayCell(g_aEventSettings, g_iLastEventIndex); - if (bLastSetting && !bSetting) - { - bSetting = GetArrayCell(g_aEventSettings, g_iLastEventIndex); - } - } - else - { - bSetting = GetArrayCell(g_aEventSettings, g_iLastEventIndex); - } - } - else - { - bSetting = GetArrayCell(g_aEventSettings, index); - } - } - else - { - g_bLastThreshold = false; - bSetting = GetConVarBool(satm_threshold_setting); - } - } - else - { - if (index != -1) - { - bSetting = GetArrayCell(g_aEventSettings, index); - } - } - - if (GetConVarBool(satm_alltalk) != bSetting) - { - - SetConVarBool(satm_alltalk, bSetting); - - new String:sReason[256]; - if (index == -1) - { - Format(sReason, sizeof(sReason), "Player Threshold"); - } - else - { - if (!g_bIsSetupMap) - { - new String:sCurrentEvent[256]; - GetArrayString(g_aEventNames, index, sCurrentEvent, sizeof(sCurrentEvent)); - if (StrEqual(sCurrentEvent, "teamplay_setup_finished")) - { - new iRoundStartIndex = FindStringInArray(g_aEventNames, "teamplay_round_start"); - if (iRoundStartIndex != -1) - { - GetArrayString(g_aEventReasons, iRoundStartIndex, sReason, sizeof(sReason)); - } - else - { - GetArrayString(g_aEventReasons, index, sReason, sizeof(sReason)); - } - } - else - { - GetArrayString(g_aEventReasons, index, sReason, sizeof(sReason)); - } - } - else - { - GetArrayString(g_aEventReasons, index, sReason, sizeof(sReason)); - } - } - - if (bSetting) - { - PrintToChatAll("\x01\x04[SM] AllTalk turned \x01[on] \x04due to:\x01 %s", sReason); - } - else - { - PrintToChatAll("\x01\x04[SM] AllTalk turned \x01[off] \x04due to:\x01 %s", sReason); - } - } -} - -stock bool:IsSetupPeriodMap() -{ - new iEnt = -1; - new String:sMapName[32]; - - GetCurrentMap(sMapName, sizeof(sMapName)); - - if (strncmp(sMapName, "cp_", 3, false) == 0) - { - new iTeam; - while ((iEnt = FindEntityByClassname(iEnt, "team_control_point")) != -1) - { - iTeam = GetEntProp(iEnt, Prop_Send, "m_iTeamNum"); - - /** - If there is a blu CP or a neutral CP, then it's not an attack/defend map - */ - if (iTeam != 2) - { - //this is a push map - return false; - } - } - //this is a attack/defend map - return true; - } - else if (strncmp(sMapName, "ctf_", 3, false) == 0) - { - //this is a ctf map - return false; - } - return false; -} diff --git a/Simple AutoScrambler/addons/sourcemod/scripting/simple-chatcolors.sp b/Simple AutoScrambler/addons/sourcemod/scripting/simple-chatcolors.sp deleted file mode 100644 index 539d057..0000000 --- a/Simple AutoScrambler/addons/sourcemod/scripting/simple-chatcolors.sp +++ /dev/null @@ -1,496 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Chat Colors -Description: - Changes the colors of players chat based on config file -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#pragma semicolon 1 -#include -#include - -#define PLUGIN_VERSION "0.9.0.$Rev$" - -#define CHAT_SYMBOL '@' -#define TRIGGER_SYMBOL1 '!' -#define TRIGGER_SYMBOL2 '/' -#define CHAT_MAX_MESSAGE_LENGTH 1024 - -new Handle:g_hDebugCvar = INVALID_HANDLE; -new Handle:g_aGroupNames = INVALID_HANDLE; -new Handle:g_aGroupFlag = INVALID_HANDLE; -new Handle:g_aGroupNameColor = INVALID_HANDLE; -new Handle:g_aGroupTextColor = INVALID_HANDLE; - -new bool:g_bDebug = false; - -new g_iArraySize; - -new g_aPlayerColorIndex[MAXPLAYERS + 1] = { -1, ... }; - -public Plugin:myinfo = -{ - name = "Simple Chat Colors", - author = "Simple Plugins", - description = "Changes the colors of players chat based on config file.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -/** -Sourcemod callbacks -*/ -public OnPluginStart() -{ - - /** - Need to create all of our console variables. - */ - CreateConVar("sm_chatcolors_version", PLUGIN_VERSION, "Simple Chat Colors", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - g_hDebugCvar = CreateConVar("sm_chatcolors_debug", "1", "Enable/Disable debugging information"); - - /** - Hook console variables - */ - HookConVarChange(g_hDebugCvar, ConVarSettingsChanged); - - /** - Need to register the commands we are going to use - */ - RegConsoleCmd("say", Command_Say); - RegConsoleCmd("say_team", Command_SayTeam); - RegAdminCmd("sm_reloadcolorsconfig", Command_Reload, ADMFLAG_GENERIC, "Reloads settings from config file"); - - /** - Create the arrays - */ - g_aGroupNames = CreateArray(256, 1); - g_aGroupFlag = CreateArray(15, 1); - g_aGroupNameColor = CreateArray(15, 1); - g_aGroupTextColor = CreateArray(15, 1); - - /** - Load the admins and colors from the config - */ - LoadAdminsAndColorsFromConfig(); - g_iArraySize = GetArraySize(g_aGroupNames); -} - -public OnConfigsExecuted() -{ - g_bDebug = GetConVarBool(g_hDebugCvar); - ReloadConfigFile(); -} - -public OnClientPostAdminCheck(client) -{ - - /** - Check the client to see if they are a admin - */ - CheckAdmin(client); -} - -public OnClientDisconnect(client) -{ - g_aPlayerColorIndex[client] = -1; -} - -/** -Commands -*/ -public Action:Command_Say(client, args) -{ - - /** - Make sure we are enabled. - */ - if (client == 0 || IsChatTrigger()) - { - return Plugin_Continue; - } - - if (g_aPlayerColorIndex[client] != -1) - { - - /** - The client is, so get the chat message and strip it down. - */ - decl String:sArg[CHAT_MAX_MESSAGE_LENGTH], - String:sChatMsg[CHAT_MAX_MESSAGE_LENGTH]; - - new bool:bAlive = IsPlayerAlive(client); - - GetCmdArgString(sArg, sizeof(sArg)); - StripQuotes(sArg); - TrimString(sArg); - new startidx; - if (sArg[strlen(sArg)-1] == '"') - { - sArg[strlen(sArg)-1] = '\0'; - startidx = 1; - } - - /** - Bug out if they are using the admin chat symbol (admin chat). If we are in CSS it may not find all the triggers, so we double check. - */ - if (sArg[startidx] == CHAT_SYMBOL || sArg[startidx] == TRIGGER_SYMBOL1 || sArg[startidx] == TRIGGER_SYMBOL2) - { - return Plugin_Continue; - } - - /** - Log the message for hlstatsx and other things. - */ - new iUserID = GetClientUserId(client); - decl String:sAuthID[64]; - GetClientAuthString(client, sAuthID, sizeof(sAuthID)); - LogToGame("\"%N<%i><%s><>\" say \"%s\"", client, iUserID, sAuthID, sArg); - - /** - Format the message. - */ - FormatMessage(client, 0, bAlive, sChatMsg, sArg, g_aPlayerColorIndex[client]); - - /** - Send the message. - */ - //SayText2(0, client, sChatMsg); - CPrintToChatAll(sChatMsg); - - /** - We are done, bug out, and stop the original chat message. - */ - return Plugin_Stop; - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Command_SayTeam(client, args) -{ - - /** - Make sure we are enabled. - */ - if (client == 0 || IsChatTrigger()) - { - return Plugin_Continue; - } - - /** - Check the client to see if they are a admin - */ - if (g_aPlayerColorIndex[client] != -1) - { - - /** - The client is, so get the chat message and strip it down. - */ - decl String:sArg[CHAT_MAX_MESSAGE_LENGTH], - String:sChatMsg[CHAT_MAX_MESSAGE_LENGTH]; - - new bool:bAlive = IsPlayerAlive(client); - new iCurrentTeam = GetClientTeam(client); - - GetCmdArgString(sArg, sizeof(sArg)); - StripQuotes(sArg); - TrimString(sArg); - new startidx; - if (sArg[strlen(sArg)-1] == '"') - { - sArg[strlen(sArg)-1] = '\0'; - startidx = 1; - } - - /** - Bug out if they are using the admin chat symbol (admin chat). - */ - if (sArg[startidx] == CHAT_SYMBOL || sArg[startidx] == TRIGGER_SYMBOL1 || sArg[startidx] == TRIGGER_SYMBOL2) - { - return Plugin_Continue; - } - - /** - Log the message for hlstatsx and other things. - */ - new iUserID = GetClientUserId(client); - decl String:sAuthID[64]; - GetClientAuthString(client, sAuthID, sizeof(sAuthID)); - LogToGame("\"%N<%i><%s><>\" say_team \"%s\"", client, iUserID, sAuthID, sArg); - - /** - Format the message. - */ - FormatMessage(client, iCurrentTeam, bAlive, sChatMsg, sArg, g_aPlayerColorIndex[client]); - - /** - Send the message to the same team - */ - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == iCurrentTeam) - { - CPrintToChat(client, sChatMsg); - } - } - - /** - We are done, bug out, and stop the original chat message. - */ - return Plugin_Stop; - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Command_Reload(client, args) -{ - ReloadConfigFile(); - return Plugin_Handled; -} - -/** -Stock Functions -*/ -stock LoadAdminsAndColorsFromConfig() -{ - - /** - Make sure the config file is here and load it up - */ - new String:sConfigFile[256]; - BuildPath(Path_SM, sConfigFile, sizeof(sConfigFile), "configs/simple-chatcolors.cfg"); - if (!FileExists(sConfigFile)) - { - - /** - Config file doesn't exists, stop the plugin - */ - LogError("[SCC] Simple Chat Colors is not running! Could not find file %s", sConfigFile); - SetFailState("Could not find file %s", sConfigFile); - } - - /** - Create the arrays and variables - */ - new String:sGroupName[256]; - new String:sGroupFlag[15]; - new String:sGroupNameColor[15]; - new String:sGroupTextColor[15]; - - - /** - Load config file as a KeyValues file - */ - new Handle:kvChatColors = CreateKeyValues("admin_colors"); - FileToKeyValues(kvChatColors, sConfigFile); - - if (!KvGotoFirstSubKey(kvChatColors)) - { - return; - } - - /** - Load up all the groups in the file - */ - do - { - - /** - Get the section name; should be the "group" name - */ - KvGetSectionName(kvChatColors, sGroupName, sizeof(sGroupName)); - - - /** - Get the flags and colors - */ - KvGetString(kvChatColors, "flag", sGroupFlag, sizeof(sGroupFlag)); - KvGetString(kvChatColors, "namecolor", sGroupNameColor, sizeof(sGroupNameColor)); - KvGetString(kvChatColors, "textcolor", sGroupTextColor, sizeof(sGroupTextColor)); - - if (g_bDebug) - { - LogMessage("Group Name/SteamID: %s", sGroupName); - LogMessage("Flag String: %s", sGroupFlag); - LogMessage("Color on name: %s", sGroupNameColor); - LogMessage("Color of text: %s", sGroupTextColor); - } - - /** - Push the values to the arrays - */ - PushArrayString(g_aGroupNames, sGroupName); - PushArrayString(g_aGroupFlag, sGroupFlag); - PushArrayString(g_aGroupNameColor, sGroupNameColor); - PushArrayString(g_aGroupTextColor, sGroupTextColor); - } while (KvGotoNextKey(kvChatColors)); - - /** - Close our handle - */ - CloseHandle(kvChatColors); -} - -stock ReloadConfigFile() -{ - - /** - Clear the array - */ - ClearArray(g_aGroupNames); - ClearArray(g_aGroupFlag); - ClearArray(g_aGroupNameColor); - ClearArray(g_aGroupTextColor); - - /** - Load the admins, groups, and colors from the config - */ - LoadAdminsAndColorsFromConfig(); - g_iArraySize = GetArraySize(g_aGroupNames); - - /** - Recheck all the online players for assigned colors - */ - for (new index = 1; index <= MaxClients; index++) - { - if (IsClientConnected(index) && IsClientInGame(index)) - { - CheckAdmin(index); - } - } -} - -stock CheckAdmin(client) -{ - new String:sFlags[15]; - new String:sClientSteamID[64]; - new iGroupFlags; - new iFlags; - new iIndex = -1; - - /** - Look for a steamid first - */ - GetClientAuthString(client, sClientSteamID, sizeof(sClientSteamID)); - iIndex = FindStringInArray(g_aGroupNames, sClientSteamID); - if (iIndex != -1) - { - g_aPlayerColorIndex[client] = iIndex; - } - - /** - Didn't find one, check flags - */ - else - { - /** - Search for flag in groups - */ - - iFlags = GetUserFlagBits(client); - for (iIndex = 0; iIndex < g_iArraySize; iIndex++) - { - GetArrayString(g_aGroupFlag, iIndex, sFlags, sizeof(sFlags)); - iGroupFlags = ReadFlagString(sFlags); - if (iFlags & iGroupFlags) - { - g_aPlayerColorIndex[client] = iIndex; - break; - } - } - } - - if (g_bDebug) - { - PrintToChatAll("SteamID: %s", sClientSteamID); - PrintToChatAll("Array Index: %i", iIndex); - PrintToChatAll("Flag String: %s", sFlags); - PrintToChatAll("Flag Bits of Client: %i", iFlags); - PrintToChatAll("Flag Bits of Group: %i", iGroupFlags); - } -} - -stock FormatMessage(iClient, iTeam, bool:bAlive, String:sChatMsg[], const Sting:sMessage[], iArrayIndex) -{ - decl String:sDead[10], - String:sTeam[10], - String:sClientName[64]; - - GetClientName(iClient, sClientName, sizeof(sClientName)); - - if (iTeam != 0) - { - Format(sTeam, sizeof(sTeam), "(TEAM) "); - } - else - { - Format(sTeam, sizeof(sTeam), ""); - } - if (bAlive) - { - Format(sDead, sizeof(sDead), ""); - } - else - { - Format(sDead, sizeof(sDead), "*DEAD* "); - } - - new String:sNameColor[15]; - new String:sTextColor[15]; - GetArrayString(g_aGroupNameColor, iArrayIndex, sNameColor, sizeof(sNameColor)); - GetArrayString(g_aGroupTextColor, iArrayIndex, sTextColor, sizeof(sTextColor)); - - Format(sChatMsg, CHAT_MAX_MESSAGE_LENGTH, "{default}%s%s%s%s {default}: %s%s", sDead, sTeam, sNameColor, sClientName, sTextColor, sMessage); -} - -/** -Adjust the settings if a convar was changed -*/ -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (StringToInt(newValue) == 1) - { - g_bDebug = true; - } - else - { - g_bDebug = false; - } -} \ No newline at end of file diff --git a/Simple AutoScrambler/addons/sourcemod/scripting/simple-donatorbenefits.sp b/Simple AutoScrambler/addons/sourcemod/scripting/simple-donatorbenefits.sp deleted file mode 100644 index e3f6845..0000000 --- a/Simple AutoScrambler/addons/sourcemod/scripting/simple-donatorbenefits.sp +++ /dev/null @@ -1,1312 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Donator Benefits -Description: - Provides donator benefits to players -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include -#include - -#define PLUGIN_VERSION "1.1.$Rev$" - -#define CHAT_SYMBOL '@' -#define CHAT_MAX_MESSAGE_LENGTH 1024 - -enum PlayerData -{ - bool:bIsDonator, - bool:bQueue, - bool:bImmune, - iHealthCount, - iNewTeam -}; - -/** - Public convar handles - */ -new Handle:sdb_enabled = INVALID_HANDLE; -new Handle:sdb_donationflag = INVALID_HANDLE; -new Handle:sdb_soundfile = INVALID_HANDLE; -new Handle:sdb_joinsound_enabled = INVALID_HANDLE; -new Handle:sdb_joinpubmsg_enabled = INVALID_HANDLE; -new Handle:sdb_joinprivmsg_enabled = INVALID_HANDLE; -new Handle:sdb_chatcolors_enabled = INVALID_HANDLE; -new Handle:sdb_immunity_enabled = INVALID_HANDLE; -new Handle:sdb_ubercharge_enabled = INVALID_HANDLE; -new Handle:sdb_givehealth_enabled = INVALID_HANDLE; -new Handle:sdb_nofalldmg_enabled = INVALID_HANDLE; -new Handle:sdb_fastheavy_enabled = INVALID_HANDLE; -new Handle:sdb_swapteam_enabled = INVALID_HANDLE; -new Handle:sdb_chatcolor = INVALID_HANDLE; -new Handle:sdb_uberlevel = INVALID_HANDLE; -new Handle:sdb_healthcount = INVALID_HANDLE; -new Handle:sdb_healthbonus = INVALID_HANDLE; -new Handle:sdb_heavymultiplier = INVALID_HANDLE; - -/** -Create global enable/disable bools so we don't have to check the console variable on every call -*/ -new bool:g_bIsEnabled = true; -new bool:g_bIsJoinSoundEnabled = true; -new bool:g_bIsJoinPubMsgEnabled = true; -new bool:g_bIsJoinPrivMsgEnabled = true; -new bool:g_bIsChatColorsEnabled = true; -new bool:g_bIsImmuntyEnabled = true; -new bool:g_bIsUberChargeEnabled = true; -new bool:g_bIsGiveHealthEnabled = true; -new bool:g_bIsNoFallDmgEnabled = true; -new bool:g_bIsFastHeayEnabled = true; -new bool:g_bIsSwapTeamEnabled = true; - -/** - Player arrays - */ -new g_aPlayers[MAXPLAYERS + 1][PlayerData]; - - -/** -Rest of the globals -*/ -new bool:g_bRoundEnd = false; -new String:g_sCharDonatorFlag[5]; -new String:g_sSoundFile[PLATFORM_MAX_PATH]; -new String:g_sChatColor[11]; -new g_iHealthBonus; -new g_iHealthCount; -new g_iClassMaxHealth[TFClassType] = {0, 125, 125, 200, 175, 150, 300, 175, 125, 125}; -new g_fClassMaxSpeed[TFClassType] = {0, 400, 300, 240, 280, 320, 230, 300, 300, 300}; -new Float:g_fHeavyMultiplier = 0.0; -new Float:g_fUberLevel = 0.0; - -public Plugin:myinfo = -{ - name = "Simple Donation Benefits", - author = "Simple Plugins", - description = "Gives donators benefits to players", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -} - -public OnPluginStart() -{ - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[SDB] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_connect", HookPlayerSpawn, EventHookMode_Pre); - HookEvent("player_spawn", HookPlayerSpawn, EventHookMode_Post); - HookEvent("player_death", HookPlayerDeath, EventHookMode_Post); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Post); - switch (g_CurrentMod) - { - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - HookEvent("player_changeclass", HookPlayerClass, EventHookMode_Post); - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_Post); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - - /** - Create console variables - */ - CreateConVar("sdb_version", PLUGIN_VERSION, "Simple Donation Benefits", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - sdb_enabled = CreateConVar("sdb_enabled", "1", "Enable/Disable Simple Donation Benefits"); - sdb_donationflag = CreateConVar("sdb_donationflag", "a", "Flag ALREADY given to donators. Must be in char format"); - - /** - Create the enable/disable donator console variables - */ - sdb_joinsound_enabled = CreateConVar("sdb_joinsound_enabled", "1", "Enable/Disable donator join sound"); - sdb_joinpubmsg_enabled = CreateConVar("sdb_joinpubmsg_enabled", "1", "Enable/Disable public donator join message (replaces: as connected)"); - sdb_joinprivmsg_enabled = CreateConVar("sdb_joinprivmsg_enabled", "1", "Enable/Disable private donator join message (sent only to donator)"); - sdb_chatcolors_enabled = CreateConVar("sdb_chatcolors_enabled", "1", "Enable/Disable donator chat colors"); - sdb_immunity_enabled = CreateConVar("sdb_immunity_enabled", "1", "Enable/Disable donator round end immunity"); - sdb_ubercharge_enabled = CreateConVar("sdb_ubercharge_enabled", "1", "Enable/Disable donator medics starting with ubercharge"); - sdb_givehealth_enabled = CreateConVar("sdb_givehealth_enabled", "1", "Enable/Disable donator instant health bonus"); - sdb_nofalldmg_enabled = CreateConVar("sdb_nofalldmg_enabled", "1", "Enable/Disable no fall damage for donators"); - sdb_fastheavy_enabled = CreateConVar("sdb_fastheavy_enabled", "1", "Enable/Disable donator heavies moving faster while spinning"); - sdb_swapteam_enabled = CreateConVar("sdb_swampteam_enabled", "1", "Enable/Disable donator swap team ability"); - - /** - Create the donator setting console variables - */ - sdb_soundfile = CreateConVar("sdb_soundfile", "custom/donatorjoin.mp3", "The location of sound file"); - sdb_chatcolor = CreateConVar("sdb_chatcolor", "green", "Color to use for donator chat. Valid colors are green and lightgreen"); - sdb_uberlevel = CreateConVar("sdb_uberlevel", "0.5", "Uberlevel to give donator medic at spawn. 1.0 = full uber", _, true, 0.0, true, 1.0); - sdb_healthcount = CreateConVar("sdb_healthcount", "1", "Number of times a donator can use use instant health per life"); - sdb_healthbonus = CreateConVar("sdb_healthbonus", "100", "The amount of health to heal the donator"); - sdb_heavymultiplier = CreateConVar("sdb_heavyspeed", "0.5", "The speed multiplier for the fast heavy. Based on running speed. 1.0 = running speed. (Game Default is 0.20)", _, true, 0.0, true, 1.0); - - /** - Hook dukehacks calls - */ - dhAddClientHook(CHK_TakeDamage, Hacks_TakeDamageHook); - dhAddClientHook(CHK_PreThink, Hacks_PreThinkHook); - - /** - Hook the console variables if they change - */ - HookConVarChange(sdb_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_donationflag, ConVarSettingsChanged); - HookConVarChange(sdb_joinsound_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_joinpubmsg_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_joinprivmsg_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_chatcolors_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_immunity_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_ubercharge_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_givehealth_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_nofalldmg_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_swapteam_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_fastheavy_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_soundfile, ConVarSettingsChanged); - HookConVarChange(sdb_chatcolor, ConVarSettingsChanged); - HookConVarChange(sdb_uberlevel, ConVarSettingsChanged); - HookConVarChange(sdb_healthcount, ConVarSettingsChanged); - HookConVarChange(sdb_healthbonus, ConVarSettingsChanged); - HookConVarChange(sdb_heavymultiplier, ConVarSettingsChanged); - - /** - Register the commands - */ - RegConsoleCmd("sm_swapteams", Command_SwapTeam, "sm_swapteams <[0]instant/[1]queued>: Swaps your team to the other team"); - RegConsoleCmd("sm_ihealth", Command_InstantHealth, "sm_ihealth: Gives you a instant health pack"); - RegAdminCmd("sm_teaser", Command_Teaser, ADMFLAG_GENERIC,"sm_teaser <[0]add/[1]remove>: Gives temporary donator privilages to a player"); - RegConsoleCmd("say", Command_Say); - - RegConsoleCmd("sm_test", Command_TEST); - - /** - Load the translations - */ - LoadTranslations("common.phrases"); - LoadTranslations("simpledonatorbenefits.phrases"); - - /** - Load or create the config file - */ - AutoExecConfig(true, "plugin.simpledonatorbenefits"); - LogAction(0, -1, "[SDB] Simple Donator Benefits is loaded."); -} - -public OnAllPluginsLoaded() -{ - //something -} - -public OnLibraryRemoved(const String:name[]) -{ - //something -} - -public OnConfigsExecuted() -{ - /** - Load up all the variable defaults - */ - LoadUpVariables(); - - /** - If the join sound is enabled, prep the sound files - */ - if (g_bIsJoinSoundEnabled) - PrepSoundFile(); - - /** - Log our activity - */ - if (g_bIsEnabled) - LogAction(0, -1, "Simple Donation Benefits is ENABLED"); - else - LogAction(0, -1, "Simple Donation Benefits is DISABLED"); -} - -public OnClientPostAdminCheck(client) -{ - - /** - Check if the client is a donator - */ - if (SM_IsValidAdmin(client, g_sCharDonatorFlag)) - { - - /** - They are, so we set the player array to true and start a timer for the sound or add - */ - g_aPlayers[client][bIsDonator] = true; - if (g_bIsJoinSoundEnabled || g_bIsJoinPrivMsgEnabled) - { - CreateTimer(10.0, Timer_DonatorJoined, client, TIMER_FLAG_NO_MAPCHANGE); - } - } - else - { - /** - They aren't, so we set the player array to false - */ - g_aPlayers[client][bIsDonator] = false; - } -} - -public OnClientDisconnect_Post(client) -{ - - /** - Clean up the player variables - */ - CleanUpPlayer(client); -} - -public Action:Command_SwapTeam(client, args) -{ - - /** - Make sure we are enabled - */ - if (!g_bIsEnabled || !g_bIsSwapTeamEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the command is not started by the server - */ - if (client == 0) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure the player is a donator - */ - if (!g_aPlayers[client][bIsDonator]) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Lets make sure the client is one a team we can swap. - If he is we set the global array to the opposite team. - */ - new iTeam = GetClientTeam(client); - if (iTeam == g_aCurrentTeams[Team1]) - { - g_aPlayers[client][iNewTeam] = g_aCurrentTeams[Team2]; - } - else if (iTeam == g_aCurrentTeams[Team2]) - { - g_aPlayers[client][iNewTeam] = g_aCurrentTeams[Team1]; - } - else - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "InValidTeam", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check to see if we have command arguments. - */ - if (GetCmdArgs()) - { - - /** - We do, so lets get it and see if the client wants to be switched instantly or queued for death. - */ - decl String:sArg[5]; - GetCmdArg(1, sArg, sizeof(sArg)); - new iWantsQue = StringToInt(sArg); - if (iWantsQue && !g_aPlayers[client][bQueue]) - { - - /** - He wants the que and isn't already in it, set the global array. - */ - g_aPlayers[client][bQueue] = true; - ReplyToCommand(client, "\x01\x04[STM]\x01 %T", "PlayerQueue", LANG_SERVER); - } - else if (!iWantsQue) - { - - /** - He wants to be switched right now, lets call the stock function. - */ - SM_MovePlayer(client, g_aPlayers[client][iNewTeam]); - } - } - else - { - - /** - There are no command arguments so we build and display the swap menu. - */ - new Handle:hPlayerMenu = BuildSwapModeMenu(); - DisplayMenu(hPlayerMenu, client, MENU_TIME_FOREVER); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_InstantHealth(client, args) -{ - - /** - Make sure we are enabled - */ - if (!g_bIsEnabled || !g_bIsGiveHealthEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the command is not started by the server - */ - if (client == 0) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure the player is a donator - */ - if (!g_aPlayers[client][bIsDonator]) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check health count to see if the player has reached the max - */ - if (g_aPlayers[client][iHealthCount] >= g_iHealthCount) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "ReachedCount", LANG_SERVER); - return Plugin_Handled; - } - - /** - Get the class of the player and the max health for that class - */ - new iHealth = GetClientHealth(client); - new TFClassType:PlayerClass = TF2_GetPlayerClass(client); - new iMaxHealth = g_iClassMaxHealth[PlayerClass]; - - /** - Check to see if the player is at the max health of the class - */ - if (iHealth >= iMaxHealth) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "AtMaxHealth", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check the current health - */ - if (iHealth + g_iHealthBonus >= iMaxHealth) - { - - /** - Raise them to max health if the current health + bonus would go above it - */ - SetEntityHealth(client, iMaxHealth); - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "ToMaxHealth", LANG_SERVER); - } - else - { - - /** - Give them the instant health bonus - */ - SetEntityHealth(client, iHealth + g_iHealthBonus); - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "HealthBonus", LANG_SERVER); - } - - /** - Increase the count - */ - g_aPlayers[client][iHealthCount] += 1; - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_Teaser(client, args) -{ - - /** - Make sure we are enabled - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Check to see if we have command arguments. - */ - new iCmdArgs = GetCmdArgs(); - if (iCmdArgs == 0) - { - - /** - We don't so display the player menu. - */ - new Handle:hPlayerMenu = BuildPlayerMenu(); - DisplayMenu(hPlayerMenu, client, MENU_TIME_FOREVER); - return Plugin_Handled; - } - - /** - We have some arguments, see if we can find the player - */ - decl String:sPlayer[64]; - GetCmdArg(1, sPlayer, sizeof(sPlayer)); - new iTarget = FindTarget(client, sPlayer, true, true); - if (iTarget == -1 || !IsClientInGame(iTarget)) - { - - /** - We don't know who this is, so display the player menu. - */ - new Handle:hPlayerMenu = BuildPlayerMenu(); - DisplayMenu(hPlayerMenu, client, MENU_TIME_FOREVER); - } - else - { - /** - We found the player, see if we are supposed to turn it on or off. - */ - if (iCmdArgs >= 2) - { - decl String:sOn[3]; - GetCmdArg(2, sOn, sizeof(sOn)); - if (StringToInt(sOn)) - { - - /** - Turn temp benefits on. - */ - g_aPlayers[iTarget][bIsDonator] = true; - } - else - { - - /** - Turn temp benefits on. - */ - g_aPlayers[iTarget][bIsDonator] = false; - } - } - else - { - - /** - We don't know what to do, so just turn it on. - */ - g_aPlayers[iTarget][bIsDonator] = true; - } - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_Say(client, args) -{ - - /** - Make sure we are enabled. - */ - if (client == 0 || IsChatTrigger() || !g_bIsChatColorsEnabled || !g_bIsEnabled) - { - return Plugin_Continue; - } - - /** - Check the client to see if they are a donator. - */ - if (g_aPlayers[client][bIsDonator]) - { - - /** - The client is, so get the chat message and strip it down. - */ - decl String:sArg[CHAT_MAX_MESSAGE_LENGTH], - String:sChatMsg[CHAT_MAX_MESSAGE_LENGTH]; - new bool:bAlive = IsPlayerAlive(client); - GetCmdArgString(sArg, sizeof(sArg)); - StripQuotes(sArg); - TrimString(sArg); - new startidx; - if (sArg[strlen(sArg)-1] == '"') - { - sArg[strlen(sArg)-1] = '\0'; - startidx = 1; - } - - /** - Bug out if they are using the admin chat symbol (admin chat). - */ - if (sArg[startidx] == CHAT_SYMBOL) - { - return Plugin_Continue; - } - - /** - Format the message. - */ - FormatMessage(client, 0, bAlive, sChatMsg, sArg); - - /** - Send the message. - */ - SayText2(0, client, sChatMsg); - - /** - We are done, bug out, and stop the original chat message. - */ - return Plugin_Stop; - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Hacks_TakeDamageHook(client, attacker, inflictor, Float:damage, &Float:multiplier, damagetype) -{ - - /** - Make sure we are enabled and the client is a donator. - */ - if (g_bIsEnabled && g_bIsNoFallDmgEnabled && g_aPlayers[client][bIsDonator]) - { - - /** - Check for fall damage. - */ - if (damagetype & DMG_FALL) - { - - /** - Cancel the fall damage and bug out. - */ - multiplier *= 0.0; - return Plugin_Changed; - } - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Hacks_PreThinkHook(client) -{ - - /** - Make sure we are enabled and the client is a donator. - */ - if (!g_bIsEnabled || !g_bIsFastHeayEnabled || !g_aPlayers[client][bIsDonator]) - { - return Plugin_Continue; - } - - /** - Check the players class. We are looking for the heavy. - */ - new TFClassType:PlayerClass = TF2_GetPlayerClass(client); - if (PlayerClass == TFClass_Heavy) - { - - /** - We have a heavy, lets check the weapon. - */ - decl String:sWeaponCurrent[64]; - GetClientWeapon(client, sWeaponCurrent, sizeof(sWeaponCurrent)); - if (StrEqual(sWeaponCurrent, "tf_weapon_minigun", false)) - { - - /** - We have a minigun, check the heavies current weapon state to see if it's spinning. - */ - new iWeapon = GetPlayerWeaponSlot(client, 0); - new iWeaponState = GetEntProp(iWeapon, Prop_Send, "m_iWeaponState"); - if (iWeaponState > 0) - { - - /** - He is spinning, so lets change the heavies speed. - */ - new Float:fMaxSpeed = FloatMul(g_fHeavyMultiplier, float(g_fClassMaxSpeed[PlayerClass])); - SetEntPropFloat(client, Prop_Send, "m_flMaxspeed", fMaxSpeed); - } - } - } - - /** - We are done, bug out. - */ - // use Plugin_Continue (other options are ignored on PreThink hook) - return Plugin_Continue; -} - -public Action:HookPlayerConnect(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (!g_bIsEnabled || !g_bIsJoinPubMsgEnabled || !dontBroadcast) - { - return Plugin_Continue; - } - - /** - Get our event variables and check the client. - */ - new iUserId = GetEventInt(event,"userid"); - new iClient = GetClientOfUserId(iUserId); - if (iClient != 0) - { - - /** - Get the info on the client and format the message. - */ - decl String:sClientName[255], - String:sAuthID[255], - String:sMsg[1024]; - - GetEventString(event, "name", sClientName, sizeof(sClientName)); - GetClientAuthString(iClient, sAuthID, sizeof(sAuthID)); - Format(sMsg, sizeof(sMsg), "%T", "PublicJoinMessage", LANG_SERVER, sClientName); - - /** - Print the message to the clients and do the normal functions. - */ - for (new i = 1; i <= MaxClients; i++) - { - if(IsClientConnected(i) && IsClientInGame(i)) - { - PrintToChat(i,"\x01\x05%s", sMsg); - PrintToConsole(i,"%s has connected.", sClientName); - } - } - LogToGame("\"%s<%d><%s><>\" entered the game", sClientName, iUserId, sAuthID); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public HookPlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled && g_bIsUberChargeEnabled) - { - - /** - Get the event variables and check the class for medic - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - if (TF2_GetPlayerClass(iClient) == TFClass_Medic) - { - - /** - Start a timer to get the medic the uber boost - */ - CreateTimer(0.25, Timer_PlayerUberDelay, iClient, TIMER_FLAG_NO_MAPCHANGE); - } - } -} - -public HookPlayerClass(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled && g_bIsUberChargeEnabled) - { - - /** - Get the event variables and check the class for medic - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - if (TF2_GetPlayerClass(iClient) == TFClass_Medic) - { - - /** - Start a timer to get the medic the uber boost - */ - CreateTimer(0.25, Timer_PlayerUberDelay, iClient, TIMER_FLAG_NO_MAPCHANGE); - } - } -} - -public HookPlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled || g_bIsSwapTeamEnabled) - { - - /** - Get the event variables - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - new String:sWeapon[256]; - GetEventString(event, "weapon", sWeapon, sizeof(sWeapon)); - - /** - Bug out if world killed him. Means he changed team or something - */ - if (StrEqual(sWeapon, "world", false)) - { - g_aPlayers[iClient][bQueue] = false; - return; - } - - /** - If he is queued up, swap him - */ - if (g_aPlayers[iClient][bQueue]) - { - SM_MovePlayer(iClient, g_aPlayers[iClient][iNewTeam]); - } - } -} - -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled || g_bIsSwapTeamEnabled) - { - - /** - Get the event variables - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - - /** - If he is queued up, clear the status - */ - if (g_aPlayers[iClient][bQueue]) - { - g_aPlayers[iClient][bQueue] = false; - } - } -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set our variables. - */ - g_bRoundEnd = false; - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled && g_bIsImmuntyEnabled) - { - - /** - Get rid of their immunity. - */ - ProcessRoundEndImmunity(false); - } -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set our variables. - */ - g_bRoundEnd = true; - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled && g_bIsImmuntyEnabled) - { - - /** - Give them their immunity. - */ - ProcessRoundEndImmunity(true); - } -} - -public Action:Timer_DonatorJoined(Handle:timer, any:client) -{ - - /** - Make sure sounds are enabled. - */ - if (g_bIsEnabled && g_bIsJoinSoundEnabled) - { - EmitSoundToClient(client, g_sSoundFile); - } - - /** - Make sure private messages are enabled. - */ - if (g_bIsJoinPrivMsgEnabled) - { - - /** - Send messages to the client. - */ - decl String:sMsg[1024]; - Format(sMsg, sizeof(sMsg), "%T", "PrivateJoinMessage", LANG_SERVER); - PrintToChat(client,"\x01\x05%s", sMsg); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Timer_PlayerUberDelay(Handle:timer, any:client) -{ - - /** - Make sure the client is still in game. - */ - if (IsClientInGame(client)) - { - - /** - Make sure the client is still a medic. - */ - if (TF2_GetPlayerClass(client) == TFClass_Medic) - { - - /** - Get the medgun weapon index - */ - new iIndex = GetPlayerWeaponSlot(client, 1); - if (iIndex > 0) - { - - /** - Set the uber level with the bonus. - */ - SetEntPropFloat(iIndex, Prop_Send, "m_flChargeLevel", g_fUberLevel); - } - } - } -} - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (convar == sdb_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsEnabled = false; - } - else - { - g_bIsEnabled = true; - } - } - else if (convar == sdb_donationflag) - { - Format(g_sCharDonatorFlag, sizeof(g_sCharDonatorFlag), "%s", newValue); - } - else if (convar == sdb_soundfile) - { - Format(g_sSoundFile, sizeof(g_sSoundFile), "%s", newValue); - } - else if (convar == sdb_joinsound_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsJoinSoundEnabled = false; - } - else - { - g_bIsJoinSoundEnabled = true; - } - } - else if (convar == sdb_joinpubmsg_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsJoinPubMsgEnabled = false; - } - else - { - g_bIsJoinPubMsgEnabled = true; - } - } - else if (convar == sdb_joinprivmsg_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsJoinPrivMsgEnabled = false; - } - else - { - g_bIsJoinPrivMsgEnabled = true; - } - } - else if (convar == sdb_chatcolors_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsChatColorsEnabled = false; - } - else - { - g_bIsChatColorsEnabled = true; - } - } - else if (convar == sdb_immunity_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsImmuntyEnabled = false; - } - else - { - g_bIsImmuntyEnabled = true; - } - } - else if (convar == sdb_ubercharge_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsUberChargeEnabled = false; - } - else - { - g_bIsUberChargeEnabled = true; - } - } - else if (convar == sdb_givehealth_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsGiveHealthEnabled = false; - } - else - { - g_bIsGiveHealthEnabled = true; - } - } - else if (convar == sdb_nofalldmg_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsNoFallDmgEnabled = false; - } - else - { - g_bIsNoFallDmgEnabled = true; - } - } - else if (convar == sdb_fastheavy_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsFastHeayEnabled = false; - } - else - { - g_bIsFastHeayEnabled = true; - } - } - else if (convar == sdb_swapteam_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsSwapTeamEnabled = false; - } - else - { - g_bIsSwapTeamEnabled = true; - } - } - else if (convar == sdb_chatcolor) - { - Format(g_sChatColor, sizeof(g_sChatColor), "%s", newValue); - } - else if (convar == sdb_uberlevel) - { - g_fUberLevel = StringToFloat(newValue); - } - else if (convar == sdb_healthcount) - { - g_iHealthCount = StringToInt(newValue); - } - else if (convar == sdb_healthbonus) - { - g_iHealthBonus = StringToInt(newValue); - } - else if (convar == sdb_heavymultiplier) - { - g_fHeavyMultiplier = StringToFloat(newValue); - } -} - -stock LoadUpVariables() -{ - g_bIsEnabled = GetConVarBool(sdb_enabled); - g_bIsJoinSoundEnabled = GetConVarBool(sdb_enabled); - g_bIsJoinPubMsgEnabled = GetConVarBool(sdb_enabled); - g_bIsJoinPrivMsgEnabled = GetConVarBool(sdb_enabled); - g_bIsChatColorsEnabled = GetConVarBool(sdb_enabled); - g_bIsImmuntyEnabled = GetConVarBool(sdb_enabled); - g_bIsUberChargeEnabled = GetConVarBool(sdb_enabled); - g_bIsGiveHealthEnabled = GetConVarBool(sdb_enabled); - g_bIsNoFallDmgEnabled = GetConVarBool(sdb_enabled); - g_bIsFastHeayEnabled = GetConVarBool(sdb_enabled); - g_bIsSwapTeamEnabled = GetConVarBool(sdb_enabled); - GetConVarString(sdb_donationflag, g_sCharDonatorFlag, sizeof(g_sCharDonatorFlag)); - GetConVarString(sdb_soundfile, g_sSoundFile, sizeof(g_sSoundFile)); - GetConVarString(sdb_chatcolor, g_sChatColor, sizeof(g_sChatColor)); - g_bRoundEnd = false; - g_iHealthBonus = GetConVarInt(sdb_healthbonus); - g_iHealthCount = GetConVarInt(sdb_healthcount); - g_fHeavyMultiplier = GetConVarFloat(sdb_heavymultiplier); - g_fUberLevel = GetConVarFloat(sdb_uberlevel); -} - -stock PrepSoundFile() -{ - decl String:buffer[PLATFORM_MAX_PATH]; - PrecacheSound(g_sSoundFile, true); - Format(buffer, sizeof(buffer), "sound/%s", g_sSoundFile); - AddFileToDownloadsTable(buffer); -} - -stock CleanUpPlayer(client) -{ - g_aPlayers[client][bIsDonator] = false; - g_aPlayers[client][bQueue] = false; - g_aPlayers[client][bImmune] = false; - g_aPlayers[client][iNewTeam] = 0; - g_aPlayers[client][iHealthCount] = 0; -} - -stock ProcessRoundEndImmunity(bool:give) -{ - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][bIsDonator]) - { - if (give) - { - SetEntProp(i, Prop_Data, "m_takedamage", 0, 1); - g_aPlayers[i][bImmune] = true; - } - else - { - SetEntProp(i, Prop_Data, "m_takedamage", 2, 1); - g_aPlayers[i][bImmune] = false; - } - } - } -} - -stock FormatMessage(iClient, iTeam, bool:bAlive, String:sChatMsg[], const Sting:sMessage[]) -{ - decl String:sDead[10], - String:sTeam[10], - String:sClientName[64]; - GetClientName(iClient, sClientName, sizeof(sClientName)); - if (iTeam != 0) - Format(sTeam, sizeof(sTeam), "(TEAM) "); - else - Format(sTeam, sizeof(sTeam), ""); - if (bAlive) - Format(sDead, sizeof(sDead), ""); - else - Format(sDead, sizeof(sDead), "*DEAD* "); - if (StrContains(g_sChatColor, "light", false) == -1) - Format(sChatMsg, CHAT_MAX_MESSAGE_LENGTH, "\x01%s%s\x03%s \x01: \x05%s", sDead, sTeam, sClientName, sMessage); - else - Format(sChatMsg, CHAT_MAX_MESSAGE_LENGTH, "\x01%s%s\x03%s \x01: \x04%s", sDead, sTeam, sClientName, sMessage); -} - -stock SayText2(target, author, const String:message[]) -{ - new Handle:hBf; - if (target == 0) - hBf = StartMessageAll("SayText2"); - else - hBf = StartMessageOne("SayText2", target); - if (hBf != INVALID_HANDLE) - { - BfWriteByte(hBf, author); - BfWriteByte(hBf, true); - BfWriteString(hBf, message); - EndMessage(); - } -} - -stock ProcessAdmins() -{ - for (new i = 1; i <= MaxClients; i++) - { - if (SM_IsValidAdmin(i, g_sCharDonatorFlag)) - { - g_aPlayers[i][bDonator] = true; - } - else - { - g_aPlayers[i][bDonator] = false; - } - } -} - -stock ProcessLate() -{ - if (g_bIsEnabled) - { - ProcessAdmins(); - PrepSoundFile(); - if (g_bRoundEnd && g_bIsImmuntyEnabled) - { - ProcessRoundEndImmunity(true); - } - if (!g_bIsImmuntyEnabled) - { - ProcessRoundEndImmunity(false); - } - } - else - { - ProcessRoundEndImmunity(false); - } -} - -public Menu_SwapMode(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, 64); - if (StringToInt(sSelection)) - g_aPlayers[param1][bQueue] = false; - else - g_aPlayers[param1][bQueue] = true; - if (!g_aPlayers[param1][bQueue]) - SM_MovePlayer(param1, g_aPlayers[param1][iNewTeam]); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -public Menu_SelectPlayer(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[256]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - new iTarget = GetClientOfUserId(StringToInt(sSelection)); - if (g_aPlayers[iTarget][bIsDonator]) - g_aPlayers[iTarget][bIsDonator] = false; - else - g_aPlayers[iTarget][bIsDonator] = true; - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -stock Handle:BuildSwapModeMenu() -{ - new Handle:menu = CreateMenu(Menu_SwapMode); - SetMenuTitle(menu, "Select When to Swap:"); - AddMenuItem(menu, "0", "Instantly (Kills)"); - AddMenuItem(menu, "1", "Queue on next death"); - SetMenuExitBackButton(menu, false); - return menu; -} - -stock Handle:BuildPlayerMenu() -{ - new Handle:menu = CreateMenu(Menu_SelectPlayer); - AddTargetsToMenu(menu, 0, true, false); - SetMenuTitle(menu, "Select A Player:"); - SetMenuExitBackButton(menu, true); - return menu; -} - -public Action:Command_TEST(client, args) -{ - -} \ No newline at end of file diff --git a/Simple AutoScrambler/addons/sourcemod/scripting/simple-messagesuppression.sp b/Simple AutoScrambler/addons/sourcemod/scripting/simple-messagesuppression.sp deleted file mode 100644 index f7725a4..0000000 --- a/Simple AutoScrambler/addons/sourcemod/scripting/simple-messagesuppression.sp +++ /dev/null @@ -1,227 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Message Suppression -Description: - Blocks Specific Message Outputs -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include -#include - -#define SUPPRESS_VERSION "1.1.$Rev$" - -public Plugin:myinfo = -{ - name = "Simple Message Suppression", - author = "FlyingMongoose, psychonic", - description = "Blocks Specific Message Outputs", - version = SUPPRESS_VERSION, - url = "http://www.simple-plugins.com/" -} - -new Handle:cvarBlockSpectateMessage; -new Handle:cvarBlockDisconnectMessage; -new Handle:cvarBlockConnectMessage; -new Handle:cvarAdminShowMessages; -new iSpecTeam = 1; - - -public OnPluginStart() -{ - CreateConVar("suppress_version", SUPPRESS_VERSION, _, FCVAR_PLUGIN|FCVAR_NOTIFY|FCVAR_REPLICATED|FCVAR_SPONLY|FCVAR_DONTRECORD); - cvarBlockSpectateMessage = CreateConVar("sm_blockspectatemessage", "1", "If enabled it blocks the join team message if an administrator joins spectator", FCVAR_PLUGIN, true, 0.0, true, 1.0); - cvarBlockDisconnectMessage = CreateConVar("sm_blockdisconnectmessage", "1", "Blocks the disconnect message", FCVAR_PLUGIN, true, 0.0, true, 1.0); - cvarBlockConnectMessage = CreateConVar("sm_blockconnectmessage", "1", "If enabled it blocks the player connection message.", FCVAR_PLUGIN, true, 0.0, true, 1.0); - cvarAdminShowMessages = CreateConVar("sm_adminshowmessages", "1", "Shows disconnect/connect/team join messages for admins only (if disconnect message is set to be blocked)", FCVAR_PLUGIN, true, 0.0, true, 1.0); - HookEvent("player_team", ev_PlayerTeam, EventHookMode_Pre); - HookEvent("player_disconnect", ev_PlayerDisconnect, EventHookMode_Pre); - HookEvent("player_connect", ev_PlayerConnect, EventHookMode_Pre); - - new String:game_folder[64]; - GetGameFolderName(game_folder, sizeof(game_folder)) - - if (StrContains(game_folder, "insurgency", false) != -1) - { - iSpecTeam = 3; - } - else - { - new String:game_description[64]; - GetGameDescription(game_description, sizeof(game_description), true); - if (StrContains(game_description, "Insurgency", false) != -1) - { - iSpecTeam = 3; - } - } - - AutoExecConfig(true, "suppressmessage", "sourcemod"); -} - -public Action:ev_PlayerTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (GetConVarBool(cvarBlockSpectateMessage)) - { - if (!dontBroadcast && !GetEventBool(event, "silent")) - { - new iUserId = GetEventInt(event, "userid"); - new iClient = GetClientOfUserId(iUserId); - new iTeam = GetEventInt(event, "team"); - - if (iTeam == iSpecTeam && GetAdminFlag(GetUserAdmin(iClient), Admin_Kick)) - { - new iOldTeam = GetEventInt(event, "oldteam"); - new bool:bDisconnect = GetEventBool(event, "disconnect"); - new bool:bAutoteam = GetEventBool(event, "autoteam"); - decl String:strName[50]; - GetEventString(event, "name", strName, sizeof(strName)); - - if (iClient != 0) - { - if (GetConVarInt(cvarAdminShowMessages) == 1) - { - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i) && GetUserAdmin(i) != INVALID_ADMIN_ID) - { - PrintToChat(i,"%N joined team Spectator.", iClient); - PrintToConsole(i,"%N joined team Spectator.", iClient); - } - } - } - } - - new Handle:hEvent = CreateEvent("player_team"); - SetEventInt(hEvent, "userid", iUserId); - SetEventInt(hEvent, "team", iTeam); - SetEventInt(hEvent, "oldteam", iOldTeam); - SetEventBool(hEvent, "disconnect", bDisconnect); - SetEventBool(hEvent, "autoteam", bAutoteam); - SetEventBool(hEvent, "silent", true); - SetEventString(hEvent, "name", strName); - - FireEvent(hEvent, true); - - return Plugin_Handled; - } - } - } - return Plugin_Continue; -} -public Action:ev_PlayerConnect(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (GetConVarBool(cvarBlockConnectMessage)) - { - if (!dontBroadcast) - { - decl String:strName[50]; - GetEventString(event, "name", strName, sizeof(strName)); - new iIndex = GetEventInt(event, "index"); - new iUserId = GetEventInt(event, "userid"); - new iClient = GetClientOfUserId(iUserId); - decl String:strNetworkId[50]; - GetEventString(event, "networkid", strNetworkId, sizeof(strNetworkId)); - decl String:strAddress[50]; - GetEventString(event, "address", strAddress, sizeof(strAddress)); - - if (iClient != 0) - { - if (GetConVarInt(cvarAdminShowMessages) == 1) - { - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i) && GetUserAdmin(i) != INVALID_ADMIN_ID) - { - PrintToChat(i,"%N has connected.", iClient); - PrintToConsole(i,"%N has connected.", iClient); - } - } - } - } - - new Handle:hEvent = CreateEvent("player_connect"); - SetEventString(hEvent, "name", strName); - SetEventInt(hEvent, "index", iIndex); - SetEventInt(hEvent, "userid", iUserId); - SetEventString(hEvent, "networkid", strNetworkId); - SetEventString(hEvent, "address", strAddress); - - FireEvent(hEvent, true); - - return Plugin_Handled; - } - } - return Plugin_Continue; -} -public Action:ev_PlayerDisconnect(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (GetConVarBool(cvarBlockDisconnectMessage)) - { - if (!dontBroadcast) - { - new iUserId = GetEventInt(event, "userid"); - new iClient = GetClientOfUserId(iUserId); - decl String:strReason[50]; - GetEventString(event, "reason", strReason, sizeof(strReason)); - decl String:strName[50]; - GetEventString(event, "name", strName, sizeof(strName)); - decl String:strNetworkId[50]; - GetEventString(event, "networkid", strNetworkId, sizeof(strNetworkId)); - - if (iClient != 0) - { - if (GetConVarInt(cvarAdminShowMessages) == 1) - { - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i) && GetUserAdmin(i) != INVALID_ADMIN_ID) - { - PrintToChat(i, "%N has left the server.", iClient); - PrintToConsole(i, "Dropped %N from server (Disconnect by user.)", iClient); - } - } - } - } - - new Handle:hEvent = CreateEvent("player_disconnect"); - SetEventInt(hEvent, "userid", iUserId); - SetEventString(hEvent, "reason", strReason); - SetEventString(hEvent, "name", strName); - SetEventString(hEvent, "networkid", strNetworkId); - - FireEvent(hEvent, true); - - return Plugin_Handled; - } - } - - return Plugin_Continue; -} \ No newline at end of file diff --git a/Simple AutoScrambler/addons/sourcemod/scripting/simple-plugins.sp b/Simple AutoScrambler/addons/sourcemod/scripting/simple-plugins.sp deleted file mode 100644 index 4462b41..0000000 --- a/Simple AutoScrambler/addons/sourcemod/scripting/simple-plugins.sp +++ /dev/null @@ -1,785 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Plugins -Description: - Core plugin for Simple Plugins project -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#define CORE_PLUGIN_VERSION "1.1.$Rev$" - -#include - -enum e_PlayerInfo -{ - Handle:hForcedTeamPlugin = INVALID_HANDLE, - iForcedTeam = 0, - iBuddy = 0, - bool:bBuddyLocked = false -}; - -new Handle:g_fwdPlayerMoved; -new g_aPlayers[MAXPLAYERS + 1][e_PlayerInfo]; -new bool:g_bTeamsSwitched = false; - -/** -Setting our plugin information. -*/ -public Plugin:myinfo = -{ - name = "Simple Plugins Core Plugin", - author = "Simple Plugins", - description = "Core plugin for Simple Plugins", - version = CORE_PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -public bool:AskPluginLoad(Handle:myself, bool:late, String:error[], err_max) -{ - - /** - Register natives for other plugins - */ - CreateNative("SM_MovePlayer", Native_SM_MovePlayer); - CreateNative("SM_SetForcedTeam", Native_SM_SetForcedTeam); - CreateNative("SM_GetForcedTeam", Native_SM_GetForcedTeam); - CreateNative("SM_ClearForcedTeam", Native_SM_ClearForcedTeam); - CreateNative("SM_GetForcedPlayer", Native_SM_GetForcedPlayer); - CreateNative("SM_AssignBuddy", Native_SM_AssignBuddy); - CreateNative("SM_GetClientBuddy", Native_SM_GetClientBuddy); - CreateNative("SM_LockBuddy", Native_SM_LockBuddy); - CreateNative("SM_IsBuddyLocked", Native_SM_IsBuddyLocked); - CreateNative("SM_ClearBuddy", Native_SM_ClearBuddy); - CreateNative("SM_IsValidAdmin", Native_SM_IsValidAdmin); - CreateNative("SM_IsValidTeam", Native_SM_IsValidTeam); - RegPluginLibrary("simpleplugins"); - return true; -} - -public OnPluginStart() -{ - - CreateConVar("ssm_core_pl_ver", CORE_PLUGIN_VERSION, "Simple SourceMod Plugins Core Plugin Version", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - CreateConVar("ssm_core_inc_ver", CORE_INC_VERSION, "Simple SourceMod Plugins Core Include Version", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook some events to control forced players and check extensions - */ - decl String:sExtError[256]; - LogAction(0, -1, "[SSM] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Pre); - switch (g_CurrentMod) - { - case GameType_CSS: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - new iExtStatus = GetExtensionFileStatus("game.cstrike.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SSM] Required extension was not found."); - LogAction(0, -1, "[SSM] Plugin FAILED TO LOAD."); - SetFailState("Required extension was not found."); - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SSM] Required extension is loaded with errors."); - LogAction(0, -1, "[SSM] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SSM] Plugin FAILED TO LOAD."); - SetFailState("Required extension is loaded with errors."); - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SSM] Required extension is loaded."); - } - } - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_PostNoCopy); - HookUserMessage(GetUserMessageId("TextMsg"), UserMessageHook_Class, true); - new iExtStatus = GetExtensionFileStatus("game.tf2.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SSM] Required extension was not found."); - LogAction(0, -1, "[SSM] Plugin FAILED TO LOAD."); - SetFailState("Required extension was not found."); - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SSM] Required extension is loaded with errors."); - LogAction(0, -1, "[SSM] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SSM] Plugin FAILED TO LOAD."); - SetFailState("Required extension is loaded with errors."); - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SSM] Required extension is loaded."); - } - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_PostNoCopy); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - - /** - Load common translations - */ - LoadTranslations ("common.phrases"); - - /** - Create the global forward - */ - g_fwdPlayerMoved = CreateGlobalForward("SM_OnPlayerMoved", ET_Event, Param_Cell, Param_Cell, Param_Cell); -} - -public OnClientDisconnect(client) -{ - - /** - Cleanup clients/players buddy list - */ - if (!IsFakeClient(client)) - { - SM_ClearBuddy(client, true); - SM_LockBuddy(client, false); - } - SM_ClearForcedTeam(client); -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - See if the teams have been switched - */ - if (g_bTeamsSwitched) - { - - /** - Switch the teams the players are forced to - */ - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][iForcedTeam] != 0) - { - if (g_aPlayers[i][iForcedTeam] == g_aCurrentTeams[Team1]) - { - g_aPlayers[i][iForcedTeam] = g_aCurrentTeams[Team2]; - } - else - { - g_aPlayers[i][iForcedTeam] = g_aCurrentTeams[Team1]; - } - } - } - } -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - g_bTeamsSwitched = false; -} - -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get our event variables - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - new iTeam = GetEventInt(event, "team"); - - /** - See if the player is on the wrong team - */ - if (g_aPlayers[iClient][iForcedTeam] != 0 && g_aPlayers[iClient][iForcedTeam] != iTeam) - { - - /** - Move the player back to the forced team - */ - CreateTimer(1.0, Timer_ForcePlayerMove, iClient, TIMER_FLAG_NO_MAPCHANGE); - - /** - If the event was going to be broadcasted, we refire it so it is not broadcasted and stop this one - */ - if (!dontBroadcast) - { - new Handle:hEvent = CreateEvent("player_team"); - SetEventInt(hEvent, "userid", GetEventInt(event, "userid")); - SetEventInt(hEvent, "team", GetEventInt(event, "team")); - SetEventInt(hEvent, "oldteam", GetEventInt(event, "oldteam")); - SetEventBool(hEvent, "disconnect", GetEventBool(event, "disconnect")); - - if (g_CurrentMod == GameType_DOD || g_CurrentMod == GameType_L4D || g_CurrentMod == GameType_TF) - { - new String:sClientName[MAX_NAME_LENGTH + 1]; - GetClientName(client, sClientName, sizeof(sClientName)); - SetEventBool(hEvent, "autoteam", GetEventBool(event, "autoteam")); - SetEventBool(hEvent, "silent", true); - SetEventString(hEvent, "name", sClientName); - FireEvent(hEvent, true); - } - else - { - FireEvent(hEvent, true); - } - return Plugin_Handled; - } - } - return Plugin_Continue; -} - -public Action:UserMessageHook_Class(UserMsg:msg_id, Handle:bf, const players[], playersNum, bool:reliable, bool:init) -{ - new String:sMessage[120]; - BfReadString(bf, sMessage, sizeof(sMessage), true); - if (StrContains(sMessage, "#TF_TeamsSwitched", false) != -1) - { - g_bTeamsSwitched = true; - } - return Plugin_Continue; -} - -public Native_SM_MovePlayer(Handle:plugin, numParams) -{ - - /** - Get and check the client and team - */ - new iClient = GetNativeCell(1); - new iTeam = GetNativeCell(2); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (iTeam != g_aCurrentTeams[Spectator] && iTeam != g_aCurrentTeams[Team1] && iTeam != g_aCurrentTeams[Team2]) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid team %d", iTeam); - } - - MovePlayer(iClient, iTeam); - if (!IsClientObserver(iClient)) - { - RespawnPlayer(iClient); - } - - new fResult; - - Call_StartForward(g_fwdPlayerMoved); - Call_PushCell(plugin); - Call_PushCell(iClient); - Call_PushCell(iTeam); - Call_Finish(fResult); - - if (fResult != SP_ERROR_NONE) - { - return ThrowNativeError(fResult, "Forward failed"); - } - - return fResult; -} - -public Native_SM_SetForcedTeam(Handle:plugin, numParams) -{ - - /** - Get and check the client and team - */ - new iClient = GetNativeCell(1); - new iTeam = GetNativeCell(2); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (iTeam != g_aCurrentTeams[Spectator] && iTeam != g_aCurrentTeams[Team1] && iTeam != g_aCurrentTeams[Team2] && iTeam != g_aCurrentTeams[Unknown]) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid team %d", iTeam); - } - - new bool:bOverRide = GetNativeCell(3) ? true : false; - - if (!bOverRide && g_aPlayers[iClient][hForcedTeamPlugin] != INVALID_HANDLE && plugin != g_aPlayers[iClient][hForcedTeamPlugin]) - { - return false; - } - - g_aPlayers[iClient][hForcedTeamPlugin] = plugin; - g_aPlayers[iClient][iForcedTeam] = iTeam; - return true; -} - -public Native_SM_GetForcedTeam(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - - /** - Get and set the plugin if they want it - */ - new Handle:hPlugin = GetNativeCell(2); - if (hPlugin != INVALID_HANDLE) - { - SetNativeCellRef(2, g_aPlayers[iClient][hForcedTeamPlugin]); - } - - /** - Return the forced team, this could be 0 - */ - return g_aPlayers[iClient][iForcedTeam]; -} - -public Native_SM_ClearForcedTeam(Handle:plugin, numParams) -{ - - /** - Get and check the client and team - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - - g_aPlayers[iClient][hForcedTeamPlugin] = INVALID_HANDLE; - g_aPlayers[iClient][iForcedTeam] = 0; - - return true; -} - -public Native_SM_GetForcedPlayer(Handle:plugin, numParams) -{ - - /** - Get and check the team - */ - new iTeam = GetNativeCell(1); - if (iTeam != g_aCurrentTeams[Spectator] && iTeam != g_aCurrentTeams[Team1] && iTeam != g_aCurrentTeams[Team2]) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid team %d", iTeam); - } - - /** - Start a loop to check for a player on the wrong team - Also make sure the plugin that set the forced team is the plugin that asked - */ - new iPlayer = 0; - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientInGame(i) - && GetClientTeam(i) != g_aPlayers[i][iForcedTeam] - && g_aPlayers[i][iForcedTeam] == iTeam - && g_aPlayers[i][hForcedTeamPlugin] == plugin) - { - iPlayer = i; - break; - } - } - - /** - Return the player we found, this could be 0 - */ - return iPlayer; -} - -public Native_SM_AssignBuddy(Handle:plugin, numParams) -{ - - /** - Get and check the client and player - */ - new iClient = GetNativeCell(1); - new iPlayer = GetNativeCell(2); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (iPlayer < 0 || iPlayer > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid player index (%d)", iPlayer); - } - if (!IsClientConnected(iPlayer)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Player %d is not connected", iPlayer); - } - if (!IsClientInGame(iPlayer)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Player %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Bots are not supported"); - } - - /** - See if we can override his setting - */ - new bool:bOverRide = GetNativeCell(3) ? true : false; - if (!bOverRide) - { - - /** - We can't override, so check if they are locked - */ - if (g_aPlayers[iClient][bBuddyLocked] || g_aPlayers[iPlayer][bBuddyLocked]) - { - - /** - We detected at least 1 lock, so we bug out - */ - return false; - } - } - - /** - Ready to set the buddies - */ - g_aPlayers[iClient][iBuddy] = iPlayer; - g_aPlayers[iPlayer][iBuddy] = iClient; - return true; -} - -public Native_SM_GetClientBuddy(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Bots are not supported"); - } - - /** - Return the players buddy, this could be 0 - */ - return g_aPlayers[iClient][iBuddy]; -} - -public Native_SM_LockBuddy(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - new bool:bSetting = GetNativeCell(2) ? true : false; - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Bots are not supported"); - } - - g_aPlayers[iClient][bBuddyLocked] = bSetting; - return true; -} - -public Native_SM_IsBuddyLocked(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Bots are not supported"); - } - - return g_aPlayers[iClient][bBuddyLocked]; -} - -public Native_SM_ClearBuddy(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Client (%d) is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Bots are not supported"); - } - - /** - Get the clients buddy and see if we can override his setting - */ - new bool:bOverRide = GetNativeCell(2) ? true : false; - new iPlayer = g_aPlayers[iClient][iBuddy]; - - /** - There is no buddy, we don't care about anything else so bug out - */ - if (iPlayer == 0) - { - return true; - } - - /** - We determined he had a buddy, check the override setting - */ - if (!bOverRide) - { - - /** - We can't override, so check if they are locked - */ - if (g_aPlayers[iClient][bBuddyLocked] || g_aPlayers[iPlayer][bBuddyLocked]) - { - - /** - We detected at least 1 lock, so we bug out - */ - return false; - } - } - - /** - Ready to clear the buddies - */ - g_aPlayers[iClient][iBuddy] = 0; - g_aPlayers[iPlayer][iBuddy] = 0; - return true; -} - -public Native_SM_IsValidTeam(Handle:plugin, numParams) -{ - - /** - Get the team - */ - new iTeam = GetNativeCell(1); - - /** - Check the team - */ - if (iTeam == g_aCurrentTeams[Spectator] || iTeam == g_aCurrentTeams[Team1] || iTeam == g_aCurrentTeams[Team2]) - { - return true; - } - return false; -} - -public Native_SM_IsValidAdmin(Handle:plugin, numParams) -{ - /** - Get the client and flags - */ - new iClient = GetNativeCell(1); - decl String:sFlags[15]; - GetNativeString(2, sFlags, sizeof(sFlags)); - new ibFlags = ReadFlagString(sFlags); - - /** - Check the flags - */ - if ((GetUserFlagBits(iClient) & ibFlags) == ibFlags) - { - return true; - } - if (GetUserFlagBits(iClient) & ADMFLAG_ROOT) - { - return true; - } - return false; -} - -public Action:Timer_ForcePlayerMove(Handle:timer, any:iClient) -{ - - MovePlayer(iClient, g_aPlayers[iClient][iForcedTeam]); - - if (g_aPlayers[iClient][iForcedTeam] != g_aCurrentTeams[Spectator]) - { - RespawnPlayer(iClient); - } - - PrintToChat(iClient, "\x01\x04----------------------------------"); - PrintToChat(iClient, "\x01\x04You have been forced to this team."); - PrintToChat(iClient, "\x01\x04----------------------------------"); - - return Plugin_Handled; -} - -stock MovePlayer(iClient, iTeam) -{ - - /** - Change the client's team based on the mod - */ - switch (g_CurrentMod) - { - case GameType_CSS: - { - CS_SwitchTeam(iClient, iTeam); - } - default: - { - ChangeClientTeam(iClient, iTeam); - } - } -} - -stock RespawnPlayer(iClient) -{ - - /** - Respawn the client based on the mod - */ - switch (g_CurrentMod) - { - case GameType_CSS: - { - CS_RespawnPlayer(iClient); - } - case GameType_TF: - { - TF2_RespawnPlayer(iClient); - } - case GameType_INS: - { - FakeClientCommand(iClient, "kill"); - } - default: - { - // - } - } -} diff --git a/Simple AutoScrambler/addons/sourcemod/scripting/simple-roundimmunity.sp b/Simple AutoScrambler/addons/sourcemod/scripting/simple-roundimmunity.sp deleted file mode 100644 index 5f0bca3..0000000 --- a/Simple AutoScrambler/addons/sourcemod/scripting/simple-roundimmunity.sp +++ /dev/null @@ -1,947 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Round Immunity -Description: - Gives admins immunity during certain rounds -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or any later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#pragma semicolon 1 -#include -#include -#undef REQUIRE_EXTENSIONS -#undef AUTOLOAD_EXTENSIONS -#include -#include -#define REQUIRE_EXTENSIONS -#define AUTOLOAD_EXTENSIONS - -#define PLUGIN_VERSION "1.1.$Rev$" -#define SPECTATOR 1 -#define TEAM_RED 2 -#define TEAM_BLUE 3 - -#define COLOR_GREEN 0 -#define COLOR_BLACK 1 -#define COLOR_RED 2 -#define COLOR_BLUE 3 -#define COLOR_TEAM 4 -#define COLOR_RAINBOW 5 -#define COLOR_NONE 6 - -#define PLAYERCOND_SLOWED (1<<0) //1 -#define PLAYERCOND_ZOOMED (1<<1) //2 -#define PLAYERCOND_DISGUISING (1<<2) //4 -#define PLAYERCOND_DISGUISED (1<<3) //8 -#define PLAYERCOND_SPYCLOAK (1<<4) //16 -#define PLAYERCOND_UBERED (1<<5) //32 -#define PLAYERCOND_TELEPORTTRAIL (1<<6) //64 -#define PLAYERCOND_TAUNT (1<<7) //128 -// (1<<8) //256 -// (1<<9) //512 -#define PLAYERCOND_TELEPORTFLASH (1<<10) //1024 -#define PLAYERCOND_KRUBER (1<<11) //2048 -// (1<<12) //4096 -// (1<<13) //8192 -#define PLAYERCOND_BONKED (1<<14) //16384 (blame Neph if it doesn't work) -#define PLAYERCOND_BONKEDORDRINKSLOWDOWN (1<<15) //32768 -#define PLAYERCOND_HEALING (1<<16) //65536 -#define PLAYERCOND_BURNING (1<<17) //131072 -#define PLAYERCOND_FULLYCHARGEDBYMEDIC (1<<18) //262144 - -enum e_Cookies -{ - bEnabled, - iColor, - iMode -}; - -enum e_ColorNames -{ - Green, - Black, - Red, - Blue -}; - -enum e_ColorValues -{ - iRed, - iGreen, - iBlue -}; - -enum e_PlayerData -{ - Handle:hGodModeTimer, - Handle:hColorTimer, - bool:bIsAdmin, - bool:bIsImmune, - iCycleColor -}; - -/** - Global convar handles - */ -new Handle:sri_charadminflag = INVALID_HANDLE; -new Handle:sri_enabled = INVALID_HANDLE; -new Handle:sri_cookie_enabled = INVALID_HANDLE; -new Handle:sri_cookie_color = INVALID_HANDLE; -new Handle:sri_cookie_mode = INVALID_HANDLE; - -/** - Player arrays - */ -new g_aPlayers[MAXPLAYERS + 1][e_PlayerData]; -new g_aClientCookies[MAXPLAYERS + 1][e_Cookies]; - -/** - Global bools - */ -new bool:g_bLoadedLate = false; -new bool:g_bIsEnabled = true; -new bool:g_bRoundEnd = false; -new bool:g_bUseDukehacks = false; -new bool:g_bUseClientprefs = false; - -/** - Global strings/integers/floats - */ -new String:g_sCharAdminFlag[32]; -new g_iColors[e_ColorNames][e_ColorValues]; -new g_iClassMaxHealth[TFClassType] = {0, 125, 125, 200, 175, 150, 300, 175, 125, 125}; - -public Plugin:myinfo = -{ - name = "Simple Round Immunity", - author = "Simple Plugins", - description = "Gives admins immunity during certain rounds", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -} - -bool:AskPluginLoad(Handle:myself, bool:late, String:error[], err_max) -{ - g_bLoadedLate = late; - return true; -} - -public OnPluginStart() -{ - - /** - Create console variables - */ - CreateConVar("sri_version", PLUGIN_VERSION, "Simple Round Immunity", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - sri_enabled = CreateConVar("sri_enabled", "1", "Enable/Disable Admin immunity during certain round."); - sri_charadminflag = CreateConVar("sri_charadminflag", "a", "Admin flag to use for immunity (only one). Must be a in char format."); - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook some events and check extensions - */ - decl String:sExtError[256]; - LogAction(0, -1, "[SRI] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_spawn", HookPlayerSpawn, EventHookMode_Post); - HookEvent("player_hurt", HookPlayerHurt, EventHookMode_Pre); - switch (g_CurrentMod) - { - case GameType_CSS: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - new iExtStatus = GetExtensionFileStatus("game.cstrike.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SRI] Required extension was not found."); - LogAction(0, -1, "[SRI] Plugin FAILED TO LOAD."); - SetFailState("Required extension was not found."); - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SRI] Required extension is loaded with errors."); - LogAction(0, -1, "[SRI] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SRI] Plugin FAILED TO LOAD."); - SetFailState("Required extension is loaded with errors."); - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SRI] Required css extension is loaded."); - } - } - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_PostNoCopy); - HookUserMessage(GetUserMessageId("TextMsg"), UserMessageHook_Class, true); - new iExtStatus = GetExtensionFileStatus("game.tf2.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SRI] Required extension was not found."); - LogAction(0, -1, "[SRI] Plugin FAILED TO LOAD."); - SetFailState("Required extension was not found."); - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SRI] Required extension is loaded with errors."); - LogAction(0, -1, "[SRI] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SRI] Plugin FAILED TO LOAD."); - SetFailState("Required extension is loaded with errors."); - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SRI] Required tf2 extension is loaded."); - } - iExtStatus = GetExtensionFileStatus("dukehacks.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SRI] Dukehacks extension was not found."); - LogAction(0, -1, "[SRI] Plugin continued to load, but that feature will not be used."); - g_bUseDukehacks = false; - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SRI] Dukehacks extension is loaded with errors."); - LogAction(0, -1, "[SRI] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SRI] Plugin continued to load, but that feature will not be used."); - g_bUseDukehacks = false; - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SRI] Dukehacks extension is loaded and will be used."); - g_bUseDukehacks = true; - dhAddClientHook(CHK_TakeDamage, Hacks_TakeDamageHook); - } - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_PostNoCopy); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - /** - Now lets check for client prefs extension - */ - new iExtStatus = GetExtensionFileStatus("clientprefs.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SRI] Client Preferences extension was not found."); - LogAction(0, -1, "[SRI] Plugin continued to load, but that feature will not be used."); - g_bUseClientprefs = false; - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SRI] Client Preferences extension is loaded with errors."); - LogAction(0, -1, "[SRI] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SRI] Plugin continued to load, but that feature will not be used."); - g_bUseClientprefs = false; - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SRI] Client Preferences extension is loaded, checking database."); - if (!SQL_CheckConfig(clientprefs)) - { - LogAction(0, -1, "[SRI] No 'clientprefs' database found. Check your database.cfg file."); - LogAction(0, -1, "[SRI] Plugin continued to load, but Client Preferences will not be used."); - g_bUseClientprefs = false; - } - g_bUseClientprefs = true; - - /** - Deal with client cookies - */ - sri_cookie_enabled = RegClientCookie("bri_client_enabled", "Enable/Disable your immunity during the bonus round.", CookieAccess_Public); - sri_cookie_color = RegClientCookie("bri_client_color", "Color to render when immune.", CookieAccess_Public); - sri_cookie_mode = RegClientCookie("bri_client_mode", "God mode to select", CookieAccess_Public); - SetCookieMenuItem(CookieMenu_TopMenu, sri_cookie_enabled, "Bonus Round Immunity"); - } - - HookConVarChange(sri_enabled, EnabledChanged); - - RegAdminCmd("sm_immunity", Command_Immunity, ADMFLAG_ROOT, "sm_immunity: Gives you immunity"); - - LoadColors(); - - AutoExecConfig(true, "plugin.simpleroundimmunity"); -} - -public OnAllPluginsLoaded() -{ - //something - // need to deal with the unloading of dukehacks, clientprefs, and simpleplugins - // should move hooking the client prefs cookies to a function to make sure they are done post plugin start if ext is loaded late -} - -public OnLibraryRemoved(const String:name[]) -{ - //something - // need to deal with the loading of dukehacks, clientprefs, and simpleplugins -} - -public OnConfigsExecuted() -{ - GetConVarString(sri_charadminflag, g_sCharAdminFlag, sizeof(g_sCharAdminFlag)); - g_bIsEnabled = GetConVarBool(sri_enabled); - g_bRoundEnd = false; -} - -/** - Client events - */ - -public OnClientPostAdminCheck(client) -{ - if (SM_IsValidAdmin(client, g_sCharAdminFlag)) - g_aPlayers[client][bIsAdmin] = true; - else - g_aPlayers[client][bIsAdmin] = false; -} - -public OnClientCookiesCached(client) -{ - decl String:sEnabled[2], String:sColor[4], String:sMode[2]; - GetClientCookie(client, sri_cookie_enabled, sEnabled, sizeof(sEnabled)); - GetClientCookie(client, sri_cookie_color, sColor, sizeof(sColor)); - GetClientCookie(client, sri_cookie_mode, sMode, sizeof(sMode)); - g_aClientCookies[client][bEnabled] = StringToInt(sEnabled); - g_aClientCookies[client][iColor] = StringToInt(sColor); - g_aClientCookies[client][iMode] = StringToInt(sMode); -} - -public OnClientDisconnect(client) -{ - CleanUp(client); -} - -/** - Commands - */ - -public Action:Command_Immunity(client, args) -{ - if (g_aPlayers[client][IsImmune]) - { - DisableImmunity(client); - } - else - { - EnableImmunity(client); - } - return Plugin_Handled; -} - -/** - Event hooks - */ - -public Action:Hacks_TakeDamageHook(client, attacker, inflictor, Float:damage, &Float:multiplier, damagetype) -{ - if (attacker == 0 || attacker >= MaxClients) - { - return Plugin_Continue; - } - if (g_aPlayers[client][IsImmune]) - { - new TFClassType:PlayerClass = TF2_GetPlayerClass(attacker); - if (PlayerClass == TFClass_Spy) - { - multiplier *= 0.0; - return Plugin_Changed; - } - } - return Plugin_Continue; -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - g_bRoundEnd = false; - if (g_bIsEnabled) - { - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][IsImmune]) - { - DisableImmunity(i); - } - } - } -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - g_bRoundEnd = true; - if (g_bIsEnabled) - { - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][bIsAdmin]) - { - EnableImmunity(i); - } - } - } -} - -public HookPlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) -{ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - if (g_bIsEnabled && g_aPlayers[iClient][bIsAdmin] && g_bRoundEnd) - { - EnableImmunity(iClient); - } -} - -public Action:HookPlayerHurt(Handle:event, const String:name[], bool:dontBroadcast) -{ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - if (g_aPlayers[iClient][IsImmune]) - { - SetEntityHealth(iClient, 2000); - return Plugin_Continue; - } - return Plugin_Continue; -} - -/** - Cookie menus - */ - -public CookieMenu_TopMenu(client, CookieMenuAction:action, any:info, String:buffer[], maxlen) -{ - if (action == CookieMenuAction_DisplayOption) - { - //don't think we need to do anything - } - else - { - new Handle:hMenu = CreateMenu(Menu_CookieSettings); - SetMenuTitle(hMenu, "Options (Current Setting)"); - if (g_aClientCookies[client][bEnabled]) - { - AddMenuItem(hMenu, "enable", "Enabled/Disable (Enabled)"); - } - else - { - AddMenuItem(hMenu, "enable", "Enabled/Disable (Disabled)"); - } - if (g_aClientCookies[client][iMode]) - { - AddMenuItem(hMenu, "mode", "Immunity Mode Setting (God Mode)"); - } - else - { - AddMenuItem(hMenu, "mode", "Immunity Mode Setting (Health)"); - } - switch (g_aClientCookies[client][iColor]) - { - case COLOR_GREEN: - { - AddMenuItem(hMenu, "color", "Color (Green)"); - } - case COLOR_BLACK: - { - AddMenuItem(hMenu, "color", "Color (Black)"); - } - case COLOR_RED: - { - AddMenuItem(hMenu, "color", "Color (Red)"); - } - case COLOR_BLUE: - { - AddMenuItem(hMenu, "color", "Color (Blue)"); - } - case COLOR_TEAM: - { - AddMenuItem(hMenu, "color", "Color (Team)"); - } - case COLOR_RAINBOW: - { - AddMenuItem(hMenu, "color", "Color (Rainbow)"); - } - case COLOR_NONE: - { - AddMenuItem(hMenu, "color", "Color (None)"); - } - } - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, client, MENU_TIME_FOREVER); - } -} - -public Menu_CookieSettings(Handle:menu, MenuAction:action, param1, param2) -{ - new client = param1; - if (action == MenuAction_Select) - { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "enable", false)) - { - new Handle:hMenu = CreateMenu(Menu_CookieSettingsEnable); - SetMenuTitle(hMenu, "Enable/Disable Round End Immunity"); - - if (g_aClientCookies[client][bEnabled]) - { - AddMenuItem(hMenu, "enable", "Enable (Set)"); - AddMenuItem(hMenu, "disable", "Disable"); - } - else - { - AddMenuItem(hMenu, "enable", "Enabled"); - AddMenuItem(hMenu, "disable", "Disable (Set)"); - } - - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, client, MENU_TIME_FOREVER); - } - else if (StrEqual(sSelection, "mode", false)) - { - new Handle:hMenu = CreateMenu(Menu_CookieSettingsMode); - SetMenuTitle(hMenu, "Set Immunity Mode"); - - if (g_aClientCookies[client][iMode]) - { - AddMenuItem(hMenu, "god", "God Mode (Set)"); - AddMenuItem(hMenu, "health", "Health"); - } - else - { - AddMenuItem(hMenu, "god", "God Mode"); - AddMenuItem(hMenu, "health", "Health (Set)"); - } - - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, client, MENU_TIME_FOREVER); - } - else - { - new Handle:hMenu = CreateMenu(Menu_CookieSettingsColors); - SetMenuTitle(hMenu, "Select Immunity Color"); - switch (g_aClientCookies[client][iColor]) - { - case COLOR_GREEN: - { - AddMenuItem(hMenu, "Green", "Green (Set)"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_BLACK: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black (Set)"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_RED: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red (Set)"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_BLUE: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue (Set)"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_TEAM: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color (Set)"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_RAINBOW: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow (Set)"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_NONE: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None (Set)"); - } - } - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, client, MENU_TIME_FOREVER); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - ShowCookieMenu(client); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -public Menu_CookieSettingsEnable(Handle:menu, MenuAction:action, param1, param2) -{ - new client = param1; - if (action == MenuAction_Select) - { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "enable", false)) - { - SetClientCookie(client, sri_cookie_enabled, "1"); - g_aClientCookies[client][bEnabled] = 1; - PrintToChat(client, "[SM] Bonus Round Immunity is ENABLED"); - } - else - { - SetClientCookie(client, sri_cookie_enabled, "0"); - g_aClientCookies[client][bEnabled] = 0; - PrintToChat(client, "[SM] Bonus Round Immunity is DISABLED"); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - ShowCookieMenu(client); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -public Menu_CookieSettingsColors(Handle:menu, MenuAction:action, param1, param2) -{ - new client = param1; - if (action == MenuAction_Select) - { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "Green", false)) - { - SetClientCookie(client, sri_cookie_color, "0"); - g_aClientCookies[client][iColor] = COLOR_GREEN; - PrintToChat(client, "[SM] Bonus Round Immunity color set to GREEN"); - } - else if (StrEqual(sSelection, "Black", false)) - { - SetClientCookie(client, sri_cookie_color, "1"); - g_aClientCookies[client][iColor] = COLOR_BLACK; - PrintToChat(client, "[SM] Bonus Round Immunity color set to BLACK"); - } - else if (StrEqual(sSelection, "Red", false)) - { - SetClientCookie(client, sri_cookie_color, "2"); - g_aClientCookies[client][iColor] = COLOR_RED; - PrintToChat(client, "[SM] Bonus Round Immunity color set to RED"); - } - else if (StrEqual(sSelection, "Blue", false)) - { - SetClientCookie(client, sri_cookie_color, "3"); - g_aClientCookies[client][iColor] = COLOR_BLUE; - PrintToChat(client, "[SM] Bonus Round Immunity color set to BLUE"); - } - else if (StrEqual(sSelection, "Team", false)) - { - SetClientCookie(client, sri_cookie_color, "4"); - g_aClientCookies[client][iColor] = COLOR_TEAM; - PrintToChat(client, "[SM] Bonus Round Immunity color set to TEAM COLOR"); - } - else if (StrEqual(sSelection, "Rain", false)) - { - SetClientCookie(client, sri_cookie_color, "5"); - g_aClientCookies[client][iColor] = COLOR_RAINBOW; - PrintToChat(client, "[SM] Bonus Round Immunity color set to RAINBOW"); - } - else if (StrEqual(sSelection, "None", false)) - { - SetClientCookie(client, sri_cookie_color, "6"); - g_aClientCookies[client][iColor] = COLOR_NONE; - PrintToChat(client, "[SM] Bonus Round Immunity color set to NONE"); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - ShowCookieMenu(client); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -public Menu_CookieSettingsMode(Handle:menu, MenuAction:action, param1, param2) -{ - new client = param1; - if (action == MenuAction_Select) - { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "god", false)) - { - SetClientCookie(client, sri_cookie_mode, "1"); - g_aClientCookies[client][iMode] = 1; - PrintToChat(client, "[SM] Bonus Round Immunity set to GOD MODE"); - } - else - { - SetClientCookie(client, sri_cookie_mode, "0"); - g_aClientCookies[client][iMode] = 0; - PrintToChat(client, "[SM] Bonus Round Immunity set to HEALTH BONUS"); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - ShowCookieMenu(client); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -/** -Timer functions - */ - -public Action:Timer_ChangeColor(Handle:timer, any:client) -{ - if (g_aPlayers[client][CycleColor]++ == 3) - { - g_aPlayers[client][CycleColor] = 0; - } - SetEntityRenderMode(client, RENDER_TRANSCOLOR); - SetEntityRenderColor(client, g_iColors[g_aPlayers[client][CycleColor]][iRed], g_iColors[g_aPlayers[client][CycleColor]][iGreen], g_iColors[g_aPlayers[client][CycleColor]][iBlue], 255); - return Plugin_Continue; -} - -public Action:Timer_UndoGodMode(Handle:timer, any:client) -{ - if (IsClientInGame(client)) - { - SetEntProp(client, Prop_Data, "m_takedamage", 2, 1); - } - g_aPlayers[iClient][hGodModeTimer] = INVALID_HANDLE; - return Plugin_Handled; -} - -/** -Stock functions . - */ - -stock CleanUp(iClient) -{ - g_aPlayers[iClient][bIsAdmin] = false; - DisableImmunity(iClient); -} - -stock EnableImmunity(iClient) -{ - SetEntityRenderMode(iClient, RENDER_TRANSCOLOR); - switch (g_aClientCookies[iClient][iColor]) - { - case COLOR_TEAM: - { - new iTeam = GetClientTeam(iClient); - SetEntityRenderColor(iClient, g_iColors[e_ColorNames:iTeam][iRed], g_iColors[e_ColorNames:iTeam][iGreen], g_iColors[e_ColorNames:iTeam][iBlue], 255); - } - case COLOR_RAINBOW: - { - if (g_aPlayers[iClient][hColorTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hColorTimer]); - g_aPlayers[iClient][hColorTimer] = INVALID_HANDLE; - } - g_aPlayers[iClient][hColorTimer] = CreateTimer(0.2, Timer_ChangeColor, iClient, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); - } - case COLOR_NONE: - { - //We dont have to set a color - } - default: - { - SetEntityRenderColor(iClient, g_iColors[e_ColorNames:g_aClientCookies[iClient][iColor]][iRed], g_iColors[e_ColorNames:g_aClientCookies[iClient][iColor]][iGreen], g_iColors[e_ColorNames:g_aClientCookies[iClient][iColor]][iBlue], 255); - } - } - SetEntityHealth(iClient, 2000); - SetEntProp(iClient, Prop_Data, "m_takedamage", 0, 1); - g_aPlayers[iClient][hGodModeTimer] = CreateTimer(2.0, Timer_UndoGodMode, iClient); - g_aPlayers[iClient][IsImmune] = true; -} - -stock DisableImmunity(iClient) -{ - if (g_aPlayers[iClient][hGodModeTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hGodModeTimer]); - g_aPlayers[iClient][hGodModeTimer] = INVALID_HANDLE; - } - if (g_aPlayers[iClient][hColorTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hColorTimer]); - g_aPlayers[iClient][hColorTimer] = INVALID_HANDLE; - } - if (IsClientInGame(iClient)) - { - SetEntityRenderMode(iClient, RENDER_TRANSCOLOR); - SetEntityRenderColor(iClient, 255, 255, 255, 255); - new TFClassType:PlayerClass = TF2_GetPlayerClass(iClient); - new iMaxHealth = g_iClassMaxHealth[PlayerClass]; - SetEntityHealth(iClient, iMaxHealth); - } - g_aPlayers[iClient][CycleColor] = 0; - g_aPlayers[iClient][IsImmune] = false; -} - -stock LoadColors() -{ - g_iColors[Green][iRed] = 0; - g_iColors[Green][iGreen] = 255; - g_iColors[Green][iBlue] = 0; - - g_iColors[Black][iRed] = 10; - g_iColors[Black][iGreen] = 10; - g_iColors[Black][iBlue] = 0; - - g_iColors[Red][iRed] = 255; - g_iColors[Red][iGreen] = 0; - g_iColors[Red][iBlue] = 0; - - g_iColors[Blue][iRed] = 0; - g_iColors[Blue][iGreen] = 0; - g_iColors[Blue][iBlue] = 255; -} - -stock TF2_AddCond(client, cond) -{ - new Handle:cvar = FindConVar("sv_cheats"), bool:enabled = GetConVarBool(cvar), flags = GetConVarFlags(cvar); - if(!enabled) - { - SetConVarFlags(cvar, flags^FCVAR_NOTIFY); - SetConVarBool(cvar, true); - } - FakeClientCommand(client, "addcond %i", cond); - if(!enabled) - { - SetConVarBool(cvar, false); - SetConVarFlags(cvar, flags); - } -} - -stock TF2_RemoveCond(client, cond) -{ - new Handle:cvar = FindConVar("sv_cheats"), bool:enabled = GetConVarBool(cvar), flags = GetConVarFlags(cvar); - if(!enabled) - { - SetConVarFlags(cvar, flags^FCVAR_NOTIFY); - SetConVarBool(cvar, true); - } - FakeClientCommand(client, "removecond %i", cond); - if(!enabled) - { - SetConVarBool(cvar, false); - SetConVarFlags(cvar, flags); - } -} - -/** -Enabled hook - */ - -public EnabledChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (StringToInt(newValue) == 0) - { - UnhookEvent("player_spawn", HookPlayerSpawn, EventHookMode_Post); - UnhookEvent("teamplay_round_start", HookRoundStart, EventHookMode_Post); - UnhookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][bIsAdmin] && g_aPlayers[i][IsImmune]) - { - DisableImmunity(i); - } - } - g_bIsEnabled = false; - } - else - { - HookEvent("player_spawn", HookPlayerSpawn, EventHookMode_Post); - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_Post); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - g_bIsEnabled = true; - } -} diff --git a/Simple AutoScrambler/addons/sourcemod/scripting/simple-spectate.sp b/Simple AutoScrambler/addons/sourcemod/scripting/simple-spectate.sp deleted file mode 100644 index 4108f8f..0000000 --- a/Simple AutoScrambler/addons/sourcemod/scripting/simple-spectate.sp +++ /dev/null @@ -1,2022 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Spectate -Description: - Spectate a player and follow them through death. -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include -#undef REQUIRE_EXTENSIONS -#undef AUTOLOAD_EXTENSIONS -#tryinclude -#define AUTOLOAD_EXTENSIONS -#define REQUIRE_EXTENSIONS - -#define PLUGIN_VERSION "1.2.1.$Rev$" - -#define SPECMODE_NONE 0 -#define SPECMODE_FIRSTPERSON 4 -#define SPECMODE_3RDPERSON 5 -#define SPECMODE_FREELOOK 6 -#define SPECMODE_CSS_FIRSTPERSON 3 -#define SPECMODE_CSS_3RDPERSON 4 -#define SPECMODE_CSS_FREELOOK 5 - -enum e_CvarHandles -{ - Handle:hHudMode, - Handle:hMenuType, - Handle:hRestrictHud, - Handle:hBan, - Handle:hBanPerm, - Handle:hBeacon, - Handle:hBlind, - Handle:hCheater, - Handle:hDrug, - Handle:hFreeze, - Handle:hFreezeBomb, - Handle:hKick, - Handle:hSlap, - Handle:hSlay, - Handle:hTimeBomb -}; - -enum e_CvarSettings -{ - bool:bHudMode, - bool:bMenuType, - bool:bRestrictHud, - bool:bBan, - bool:bBanPerm, - bool:bBeacon, - bool:bBlind, - bool:bCheater, - bool:bDrug, - bool:bFreeze, - bool:bFreezebomb, - bool:bKick, - bool:bSlap, - bool:bSlay, - bool:bTimeBomb -}; - -enum e_PluginSettings -{ - bool:bUseSteamBans, - bool:bUseSourceBans, - bool:bUseMySQLBans, - bool:bCanHUD, - bool:bUseDukehacks -}; - -enum e_Menus -{ - Handle:hSelectPlayer, - Handle:hBanTime, - Handle:hReason -}; - -enum e_Punishments -{ - Punish_None, - Punish_Ban, - Punish_Beacon, - Punish_Blind, - Punish_Cheater, - Punish_Drug, - Punish_Freeze, - Punish_FreezeBomb, - Punish_Kick, - Punish_Slap, - Punish_Slay, - Punish_TimeBomb -}; - -enum e_PlayerData -{ - bool:bIsDisplayingHud, - bool:bIsFlaggedCheater, - Handle:hHudTimer, - Handle:hTargetTimer, - iTargetIndex, - e_Punishments:TargetPunishment, - iBanTime -}; - -new Handle:sm_spectate_adminflag = INVALID_HANDLE; -new Handle:g_hAdminMenu = INVALID_HANDLE; -new Handle:g_hHud = INVALID_HANDLE; -new Handle:g_aPluginCvar[e_CvarHandles]; -new g_aPluginCvarSettings[e_CvarSettings]; -new g_aPluginSettings[e_PluginSettings]; -new g_aMenus[e_Menus]; -new g_aPlayers[MAXPLAYERS + 1][e_PlayerData]; -new String:g_sAdminFlags[16]; -new String:g_sPunishments[e_Punishments][15] = { "None", "Ban", "Beacon", "Blind", "Cheater", "Drug", "Freeze", "FreezeBomb", "Kick", "Slap", "Slay", "TimeBomb" }; - -public Plugin:myinfo = -{ - name = "Simple Spectate", - author = "Simple Plugins", - description = "Spectate a player and follow them through death.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -/** -Sourcemod callbacks -*/ -public OnPluginStart() -{ - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[SSPEC] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Pre); - - /** - Need to create all of our console variables. - */ - CreateConVar("sm_spectate_version", PLUGIN_VERSION, "Sourcemod Spectate", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - g_aPluginCvar[hHudMode] = CreateConVar("sm_spectate_hudmode", "1", "Hud Mode: 0 = Hud Text | 1 = Panel/Menu (NOTE: The panel/menu will override other menus until canceled)"); - g_aPluginCvar[hMenuType] = CreateConVar("sm_spectate_menutype", "0", "Menu Mode: 0 = Panel | 1 = Menu"); - g_aPluginCvar[hRestrictHud] = CreateConVar("sm_spectate_restricthud", "0", "Restrict the hud to the admin flag provided"); - g_aPluginCvar[hBan] = CreateConVar("sm_spectate_ban", "1", "Enable/Disable ban option"); - g_aPluginCvar[hBanPerm] = CreateConVar("sm_spectate_banperm", "1", "Enable/Disable permanent ban option"); - g_aPluginCvar[hBeacon] = CreateConVar("sm_spectate_beacon", "1", "Enable/Disable beacon option"); - g_aPluginCvar[hBlind] = CreateConVar("sm_spectate_blind", "1", "Enable/Disable blind option"); - g_aPluginCvar[hCheater] = CreateConVar("sm_spectate_cheater", "1", "Enable/Disable cheater option"); - g_aPluginCvar[hDrug] = CreateConVar("sm_spectate_drug", "1", "Enable/Disable drug option"); - g_aPluginCvar[hFreeze] = CreateConVar("sm_spectate_freeze", "1", "Enable/Disable freeze option"); - g_aPluginCvar[hFreezeBomb] = CreateConVar("sm_spectate_freezebomb", "1", "Enable/Disable freezebomb option"); - g_aPluginCvar[hKick] = CreateConVar("sm_spectate_kick", "1", "Enable/Disable kick option"); - g_aPluginCvar[hSlap] = CreateConVar("sm_spectate_slap", "1", "Enable/Disable slap option"); - g_aPluginCvar[hSlay] = CreateConVar("sm_spectate_slay", "1", "Enable/Disable slay option"); - g_aPluginCvar[hTimeBomb] = CreateConVar("sm_spectate_timebomb", "1", "Enable/Disable timebomb option"); - - sm_spectate_adminflag = CreateConVar("sm_spectate_adminflag", "d", "Admin Flag to use for admin hud"); - - /** - Hook console variables - */ - new e_CvarHandles:iCvar; - for ( ; _:iCvar < sizeof(g_aPluginCvar); iCvar++) - { - HookConVarChange(g_aPluginCvar[iCvar], ConVarSettingsChanged); - } - - /** - Need to register the commands we are going to create and use. - */ - RegConsoleCmd("sm_spectate", Command_Spectate, "Spectate a player"); - RegConsoleCmd("sm_spec", Command_Spectate, "Spectate a player"); - RegConsoleCmd("sm_observe", Command_Spectate, "Spectate a player"); - RegConsoleCmd("sm_stopspec", Command_StopSpectate, "Stop Spectating a player"); - RegConsoleCmd("sm_endobserve", Command_StopSpectate, "Stop Spectating a player"); - RegConsoleCmd("sm_specinfo", Command_ToggleHud, "Toggles the hud display if in spectator"); - - /** - Now we have to deal with the admin menu. If the admin library is loaded call the function to add our items. - */ - new Handle:gTopMenu; - if (LibraryExists("adminmenu") && ((gTopMenu = GetAdminTopMenu()) != INVALID_HANDLE)) - { - OnAdminMenuReady(gTopMenu); - } - - /** - Deal with the hud - Thanks to Spray Trace plugin (http://forums.alliedmods.net/showthread.php?p=665448) - */ - new String:sHudGames[32]; - GetGameFolderName(sHudGames, sizeof(sHudGames)); - g_aPluginSettings[bCanHUD] = StrEqual(sHudGames,"tf",false) - || StrEqual(sHudGames,"hl2mp",false) - || StrEqual(sHudGames,"sourceforts",false) - || StrEqual(sHudGames,"obsidian",false) - || StrEqual(sHudGames,"left4dead",false) - || StrEqual(sHudGames,"l4d",false); - - if (g_aPluginSettings[bCanHUD]) - { - g_hHud = CreateHudSynchronizer(); - } - - /** - Load translations - */ - LoadTranslations ("common.phrases"); - LoadTranslations ("simplespectate.phrases"); - - /** - Create the config file - */ - AutoExecConfig(true); -} - -public OnConfigsExecuted() -{ - new e_CvarHandles:iCvar; - for ( ; _:iCvar < sizeof(g_aPluginCvarSettings); iCvar++) - { - g_aPluginCvarSettings[iCvar] = GetConVarBool(g_aPluginCvar[iCvar]); - } - - /* - Build the global menus - */ - g_aMenus[hSelectPlayer] = BuildSelectPlayerMenu(); - g_aMenus[hBanTime] = BuildBanTimeMenu(); - g_aMenus[hReason] = BuildReasonMenu(); - - GetConVarString(sm_spectate_adminflag, g_sAdminFlags, sizeof(g_sAdminFlags)); -} - -public OnAllPluginsLoaded() -{ - - /* - Check for steambans - */ - if (FindConVar("sbsrc_version") != INVALID_HANDLE) - { - g_aPluginSettings[bUseSteamBans] = true; - } - else - { - g_aPluginSettings[bUseSteamBans] = false; - } - - /* - Check for sourcebans - */ - if (FindConVar("sb_version") != INVALID_HANDLE) - { - g_aPluginSettings[bUseSourceBans] = true; - } - else - { - g_aPluginSettings[bUseSourceBans] = false; - } - - /* - Check for mysql bans - */ - if (FindConVar("mysql_bans_version") != INVALID_HANDLE) - { - g_aPluginSettings[bUseMySQLBans] = true; - } - else - { - g_aPluginSettings[bUseMySQLBans] = false; - } - - /* - Check for dukehacks - */ - new String:sExtError[256]; - new iExtStatus = GetExtensionFileStatus("dukehacks.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SSPEC] Dukehacks extension was not found."); - LogAction(0, -1, "[SSPEC] Plugin continued to load, but that feature will not be used."); - g_aPluginSettings[bUseDukehacks] = false; - } - else if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SSPEC] Dukehacks extension is loaded with errors."); - LogAction(0, -1, "[SSPEC] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SSPEC] Plugin continued to load, but that feature will not be used."); - g_aPluginSettings[bUseDukehacks] = false; - } - else if (iExtStatus == 1) - { - LogAction(0, -1, "[SSPEC] Dukehacks extension is loaded and will be used."); - g_aPluginSettings[bUseDukehacks] = true; - dhAddClientHook(CHK_TakeDamage, Hacks_TakeDamageHook); - } - - /* - Deal with some known plugin conflicts - */ - new Handle:hObserveClient = FindConVar("observe_version"); - if (hObserveClient != INVALID_HANDLE) - { - new String:sNewFile[PLATFORM_MAX_PATH + 1], String:sOldFile[PLATFORM_MAX_PATH + 1]; - BuildPath(Path_SM, sNewFile, sizeof(sNewFile), "plugins/disabled/observe.smx"); - BuildPath(Path_SM, sOldFile, sizeof(sOldFile), "plugins/observe.smx"); - - /** - Check if plugins/observe.smx exists, and if not, ignore - */ - if(!FileExists(sOldFile)) - { - return; - } - - /** - Check if plugins/disabled/observe.smx already exists, and if so, delete it - */ - if(FileExists(sNewFile)) - { - DeleteFile(sNewFile); - } - - /** - Unload plugins/observe.smx and move it to plugins/disabled/observe.smx - */ - LogAction(0, -1, "Detected the plugin ObserveClient"); - LogAction(0, -1, "ObserveClient plugin conflicts with Simple Spectate"); - LogAction(0, -1, "Unloading plugin and disabling ObserveClient plugin"); - ServerCommand("sm plugins unload observe"); - RenameFile(sNewFile, sOldFile); - } -} - -public OnLibraryRemoved(const String:name[]) -{ - if (StrEqual(name, "adminmenu")) - { - - /** - Looks like the admin menu was removed. Set the global. - */ - g_hAdminMenu = INVALID_HANDLE; - } - else if (StrEqual(name, "simpleplugins")) - { - //something - } -} - -public OnClientDisconnect(client) -{ - - /** - Cleanup the clients variables. - */ - ResetClient(client); - - /** - Run a loop and see if we are supposed to spectate this person (is a target) - */ - for(new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][iTargetIndex] == client) - { - - /** - Cleanup the clients variables. - */ - StopFollowingPlayer(i); - g_aPlayers[i][TargetPunishment] = Punish_None; - g_aPlayers[i][iBanTime] = 0; - } - } -} - -/** -Thirdparty callbacks -*/ -public SM_OnPlayerMoved(Handle:plugin, client, team) -{ - - /** - Make sure we called the move function - */ - if (plugin != GetMyHandle()) - { - return; - } - - //Nothing -} - -public Action:Hacks_TakeDamageHook(client, attacker, inflictor, Float:damage, &Float:multiplier, damagetype) -{ - - /** - Check for a valid client - */ - if (client > 0 && client <= MaxClients) - { - - /** - Check if the client taking damage is flagged as a cheater - */ - if (g_aPlayers[client][bIsFlaggedCheater]) - { - - /** - Check for fall damage and increase it - */ - if (damagetype & DMG_FALL) - { - multiplier *= 1000.0; - return Plugin_Changed; - } - } - } - - /** - Check for a valid attacker - */ - if (attacker > 0 && attacker <= MaxClients) - { - - /** - Check if the attacker causing the damage is flagged as a cheater - */ - if (g_aPlayers[attacker][bIsFlaggedCheater]) - { - - /** - Make sure they are not hurting themselves - */ - if (client != attacker) - { - - /** - Stop the damage - */ - multiplier *= 0.0; - return Plugin_Changed; - } - } - } - return Plugin_Continue; -} - -/** -Events -*/ -public Action:HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get the client and team - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - new iTeam = GetEventInt(event, "team"); - - /** - Make sure it's a valid client - */ - if (iClient == 0) - { - return Plugin_Continue; - } - - /** - If it's a move to spectator start displaying the hud - */ - else if ((iTeam == g_aCurrentTeams[Spectator]) && (GetUserFlagBits(iClient) & ADMFLAG_GENERIC)) - { - StartDisplayingHud(iClient); - - /** - If the event was going to be broadcasted, we refire it so it is not broadcasted and stop this one - */ - if (!dontBroadcast) - { - new Handle:hEvent = CreateEvent("player_team"); - SetEventInt(hEvent, "userid", GetEventInt(event, "userid")); - SetEventInt(hEvent, "team", GetEventInt(event, "team")); - SetEventInt(hEvent, "oldteam", GetEventInt(event, "oldteam")); - SetEventBool(hEvent, "disconnect", GetEventBool(event, "disconnect")); - - if (g_CurrentMod == GameType_DOD || g_CurrentMod == GameType_L4D || g_CurrentMod == GameType_TF) - { - new String:sClientName[MAX_NAME_LENGTH + 1]; - GetClientName(client, sClientName, sizeof(sClientName)); - SetEventBool(hEvent, "autoteam", GetEventBool(event, "autoteam")); - SetEventBool(hEvent, "silent", true); - SetEventString(hEvent, "name", sClientName); - FireEvent(hEvent, true); - } - else - { - FireEvent(hEvent, true); - } - return Plugin_Handled; - } - } - - /** - Otherwise cleanup the client - */ - else - { - StopDisplayingHud(iClient); - StopFollowingPlayer(iClient); - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -/** -Commands -*/ -public Action:Command_Spectate(client, args) -{ - - /** - See if we already have a target (for toggling of command) - */ - if (g_aPlayers[client][iTargetIndex]) - { - - /** - We do, toggle it off - */ - StopFollowingPlayer(client); - - /** - We are done, bug out. - */ - return Plugin_Handled; - } - - /** - We don't... must want to enable it - See if we have some command arguments. - */ - new iCmdArgs = GetCmdArgs(); - if (iCmdArgs == 0) - { - - /** - We don't have any. Display the player menu. - */ - if (g_aPlayers[client][bIsDisplayingHud]) - { - StopDisplayingHud(client); - } - - DisplayMenu(BuildPlayerListMenu(), client, MENU_TIME_FOREVER); - return Plugin_Handled; - } - - /** - We have an argument. - Try to find the target. - */ - new String:sPlayer[128]; - GetCmdArg(1, sPlayer, sizeof(sPlayer)); - new iTarget = FindTarget(client, sPlayer, true, true); - if (iTarget == -1 || !IsClientInGame(iTarget)) - { - - /** - We couldn't find the target. Display the player menu. - */ - if (g_aPlayers[client][bIsDisplayingHud]) - { - StopDisplayingHud(client); - } - - DisplayMenu(BuildPlayerListMenu(), client, MENU_TIME_FOREVER); - return Plugin_Handled; - } - - /** - We found the target. - Call the stock function to spectate the target. - */ - StartFollowingPlayer(client, iTarget); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_StopSpectate(client, args) -{ - - /** - Cleanup the clients variables. - */ - StopFollowingPlayer(client); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_ToggleHud(client, args) -{ - - /** - Toggle the hud - */ - if (g_aPlayers[client][bIsDisplayingHud]) - { - StopDisplayingHud(client); - } - else - { - StartDisplayingHud(client); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -/** -Timers -*/ -public Action:Timer_ResetTarget(Handle:timer, any:client) -{ - - new iTargetID = GetEntPropEnt(client, Prop_Send, "m_hObserverTarget"); - - if (iTargetID != g_aPlayers[client][iTargetIndex] && IsPlayerAlive(g_aPlayers[client][iTargetIndex])) - { - - /** - Run the command to spectate the target from the clients prospectative. - */ - FakeClientCommandEx(client, "spec_player \"%N\"", g_aPlayers[client][iTargetIndex]); - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Timer_UpdateHud(Handle:timer, any:client) -{ - - /** - Make sure the client is still in game and a spectator - */ - if (!IsClientConnected(client) || !IsClientInGame(client) || GetClientTeam(client) != g_aCurrentTeams[Spectator] || !g_aPlayers[client][bIsDisplayingHud]) - { - - /** - We are done, bug out - */ - g_aPlayers[client][hHudTimer] = INVALID_HANDLE; - g_aPlayers[client][bIsDisplayingHud] = false; - return Plugin_Stop; - } - /** - Get the target - */ - new iTarget = GetEntPropEnt(client, Prop_Send, "m_hObserverTarget"); - - /** - Check to make sure the target is valid - */ - if (iTarget <= 0 || iTarget > MaxClients) - { - return Plugin_Continue; - } - - /** - Get the spectator mode - */ - new iSpecMode = GetEntProp(client, Prop_Send, "m_iObserverMode"); - - /** - This is a double check to make sure we are in spec - If we are on a regular team, specmod would = none or zero - */ - if (iSpecMode == SPECMODE_NONE) - { - - /** - We are done, bug out - */ - g_aPlayers[client][hHudTimer] = INVALID_HANDLE; - g_aPlayers[client][bIsDisplayingHud] = false; - return Plugin_Stop; - } - - /** - Check the spectator mode - CSS has different index's so we have to check game type first - */ - if (g_CurrentMod == GameType_CSS) - { - switch (iSpecMode) - { - case SPECMODE_CSS_FIRSTPERSON: - { - //Do Nothing - } - case SPECMODE_CSS_3RDPERSON: - { - //Do Nothing - } - case SPECMODE_CSS_FREELOOK: - { - return Plugin_Continue; - } - } - } - else - { - switch (iSpecMode) - { - case SPECMODE_FIRSTPERSON: - { - //Do Nothing - } - case SPECMODE_3RDPERSON: - { - //Do Nothing - } - case SPECMODE_FREELOOK: - { - return Plugin_Continue; - } - } - } - - - /** - Display with the hud - */ - if (g_aPluginSettings[bCanHUD] && !g_aPluginCvarSettings[bHudMode]) - { - new String:sSteamID[64]; - GetClientAuthString(iTarget, sSteamID, sizeof(sSteamID)); - SetHudTextParams(0.04, 0.6, 0.5, 255, 50, 50, 255); - ShowSyncHudText(client, g_hHud, "%N [%s]", iTarget, sSteamID); - } - else if (g_aPluginCvarSettings[bHudMode]) - { - if (g_aPluginCvarSettings[bMenuType]) - { - DisplayMenu(BuildPlayerHudMenu(client, iTarget), client, 1); - } - else - { - new Handle:hPanel = BuildPlayerHudPanel(client, iTarget); - SendPanelToClient(hPanel, client, Panel_PlayerHud, 1); - CloseHandle(hPanel); - } - } - - /** - We are done, keep going! - */ - return Plugin_Continue; -} - -/** -Admin Menu Callbacks -*/ -public OnAdminMenuReady(Handle:topmenu) -{ - if (topmenu == g_hAdminMenu) - { - return; - } - g_hAdminMenu = topmenu; - new TopMenuObject:player_commands = FindTopMenuCategory(g_hAdminMenu, ADMINMENU_PLAYERCOMMANDS); - if (player_commands == INVALID_TOPMENUOBJECT) - { - return; - } - AddToTopMenu(g_hAdminMenu, - "sm_spectate", - TopMenuObject_Item, - AdminMenu_SpecPlayer, - player_commands, - "sm_spectate", - ADMFLAG_GENERIC); -} - -public AdminMenu_SpecPlayer(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) -{ - if (action == TopMenuAction_DisplayOption) - { - - if (g_aPlayers[param][bIsDisplayingHud]) - { - StopDisplayingHud(param); - } - /** - See if we already have a target - */ - if (g_aPlayers[param][iTargetIndex]) - { - Format(buffer, maxlength, "Spectate(Disable)"); - } - else - { - Format(buffer, maxlength, "Spectate(Select Player)"); - } - } - else if (action == TopMenuAction_SelectOption) - { - - /** - See if we already have a target - */ - if (g_aPlayers[param][iTargetIndex]) - { - - /** - We do, toggle it off - */ - StopFollowingPlayer(param); - - /** - We are done, bug out. - */ - return; - } - else - { - DisplayMenu(BuildPlayerListMenu(), param, MENU_TIME_FOREVER); - } - } -} - -/** -Select Player Menu Callbacks -*/ -public Menu_PlayerList(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - /** - Get the selected player - */ - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - new iTarget = GetClientOfUserId(StringToInt(sSelection)); - - /** - Start following the player - */ - StartFollowingPlayer(param1, iTarget); - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_GENERIC) - { - - /** - Display the last admin menu - */ - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } - else if (param2 == MenuCancel_Exit && GetClientTeam(param1) == g_aCurrentTeams[Spectator]) - { - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_End) - { - - /** - Not a global menu, close it - */ - CloseHandle(menu); - } -} - -public Menu_SelectPlayer(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - - /** - Get the selected player - */ - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (strcmp(sSelection, "Current", false) == 0) - { - /** - Get the current target - */ - new iTarget = GetEntPropEnt(param1, Prop_Send, "m_hObserverTarget"); - - /** - Check to make sure the target is valid - */ - if (iTarget <= 0 || iTarget > MaxClients) - { - PrintToChat(param1, "\x03[SM-SPEC]\x01 %t", "Invalid Target"); - DisplayMenu(BuildPlayerListMenu(), param1, MENU_TIME_FOREVER); - } - - /** - Start following the player - */ - StartFollowingPlayer(param1, iTarget); - } - else - { - - /** - They want to select a player, show the player list - */ - DisplayMenu(BuildPlayerListMenu(), param1, MENU_TIME_FOREVER); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_End) - { - /** - Its a global menu, leave it alive - */ - } -} - -/** -Punishment Menu Callbacks -*/ -public Menu_Punishments(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - - /** - Get the menu selection - */ - new String:sSelection[15]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - - /** - Search for the correct index - */ - new e_Punishments:Index = Punish_None; - for ( ; _:Index <= sizeof(g_sPunishments); Index++) - { - if (StrEqual(sSelection, g_sPunishments[Index])) - { - break; - } - } - - /** - Display the next menu - */ - if (Index == Punish_Ban) - { - - /** - Set the punishment index and display ban time menu - */ - g_aPlayers[param1][TargetPunishment] = Index; - DisplayMenu(g_aMenus[hBanTime], param1, MENU_TIME_FOREVER); - } - else if (Index == Punish_Cheater) - { - - /** - Ask for confirmation before we set punishment index - */ - new Handle:hPanel = BuildAdminCheaterPanel(); - SendPanelToClient(hPanel, param1, Panel_AdminCheater, MENU_TIME_FOREVER); - CloseHandle(hPanel); - } - else - { - - /** - Set the punishment index and display reason menu - */ - g_aPlayers[param1][TargetPunishment] = Index; - DisplayMenu(g_aMenus[hReason], param1, MENU_TIME_FOREVER); - } - } - else if (action == MenuAction_Cancel) - { - - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - else if (action == MenuAction_End) - { - - /** - Not a global menu, close it - */ - CloseHandle(menu); - } -} - -public Menu_BanTime(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - - /** - Get the menu selection - */ - new String:sSelection[15]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - - /** - Set the ban time global - */ - g_aPlayers[param1][iBanTime] = StringToInt(sSelection); - - /** - Display the reason menu - */ - DisplayMenu(g_aMenus[hReason], param1, MENU_TIME_FOREVER); - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_End) - { - /** - Its a global menu, leave it alive - */ - } -} - -public Menu_Reason(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - - /** - Get the menu selection - */ - new String:sSelection[15]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - - /** - Perform the punishment - */ - PerformPunishment(param1, g_aPlayers[param1][iTargetIndex], g_aPlayers[param1][TargetPunishment], sSelection, g_aPlayers[param1][iBanTime]); - - /** - Reactivate the hud if still in spectator - */ - if (GetClientTeam(param1) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_End) - { - /** - Its a global menu, leave it alive - */ - } -} - -public Panel_AdminCheater(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - if (param2 == 1) - { - - /** - Set the punishment index and display reason menu - */ - g_aPlayers[param1][TargetPunishment] = Punish_Cheater; - DisplayMenu(g_aMenus[hReason], param1, MENU_TIME_FOREVER); - } - else - { - - /** - Reactivate the hud if still in spectator - */ - if (GetClientTeam(param1) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(param1); - } - } - } -} - -public Panel_PublicCheater(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - if (param2 == 1) - { - //Waiting for SB 2.0 and sb_submission to be published - } - else - { - - /** - Reactivate the hud if still in spectator - */ - if (GetClientTeam(param1) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(param1); - } - } - } -} - -/** -Hud Menu/Panel Callbacks -*/ -public Menu_PlayerHud(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "stop", false)) - { - StopFollowingPlayer(param1); - } - else if (StrEqual(sSelection, "start", false)) - { - StopDisplayingHud(param1); - DisplayMenu(g_aMenus[hSelectPlayer], param1, MENU_TIME_FOREVER); - } - else if (StrEqual(sSelection, "removecheater", false)) - { - g_aPlayers[g_aPlayers[param1][iTargetIndex]][bIsFlaggedCheater] = false; - } - else if (StrEqual(sSelection, "punish", false)) - { - if (g_aPlayers[param1][iTargetIndex]) - { - StopDisplayingHud(param1); - DisplayMenu(BuildPunishmentMenu(param1), param1, MENU_TIME_FOREVER); - } - else - { - StopDisplayingHud(param1); - PrintToChat(param1, "\x03[SM-SPEC]\x01 %t", "Must Have Target"); - DisplayMenu(g_aMenus[hSelectPlayer], param1, MENU_TIME_FOREVER); - } - } - else if (StrEqual(sSelection, "reportcheater", false)) - { - if (g_aPlayers[param1][iTargetIndex]) - { - StopDisplayingHud(param1); - new Handle:hPanel = BuildPublicCheaterPanel(); - SendPanelToClient(hPanel, param1, Panel_PublicCheater, MENU_TIME_FOREVER); - CloseHandle(hPanel); - } - else - { - StopDisplayingHud(param1); - PrintToChat(param1, "\x03[SM-SPEC]\x01 %t", "Must Have Target"); - DisplayMenu(g_aMenus[hSelectPlayer], param1, MENU_TIME_FOREVER); - } - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_Interrupted) - { - if (GetClientMenu(param1) == MenuSource_External) - { - StopDisplayingHud(param1); - } - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -public Panel_PlayerHud(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - switch (param2) - { - case 1: - { - if (g_aPlayers[param1][iTargetIndex]) - { - StopFollowingPlayer(param1); - } - else - { - StopDisplayingHud(param1); - DisplayMenu(BuildSelectPlayerMenu(), param1, MENU_TIME_FOREVER); - } - } - case 2: - { - if (!g_aPlayers[param1][iTargetIndex]) - { - StopDisplayingHud(param1); - PrintToChat(param1, "\x03[SM-SPEC]\x01 %t", "Must Have Target"); - DisplayMenu(g_aMenus[hSelectPlayer], param1, MENU_TIME_FOREVER); - return; - } - - if ((GetUserFlagBits(param1) & ADMFLAG_GENERIC) || (GetUserFlagBits(param1) & ADMFLAG_ROOT)) - { - if (g_aPlayers[g_aPlayers[param1][iTargetIndex]][bIsFlaggedCheater] && (GetUserFlagBits(param1) & ADMFLAG_ROOT)) - { - //Remove cheater flag - g_aPlayers[g_aPlayers[param1][iTargetIndex]][bIsFlaggedCheater] = false; - } - else - { - //Punish menu - StopDisplayingHud(param1); - DisplayMenu(BuildPunishmentMenu(param1), param1, MENU_TIME_FOREVER); - } - } - else - { - //Report Cheater - new Handle:hPanel = BuildPublicCheaterPanel(); - SendPanelToClient(hPanel, param1, Panel_PublicCheater, MENU_TIME_FOREVER); - CloseHandle(hPanel); - } - } - case 3: - { - StopDisplayingHud(param1); - } - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_Interrupted) - { - if (GetClientMenu(param1) == MenuSource_External) - { - StopDisplayingHud(param1); - } - } - } -} - - -/** -Stock functions -*/ -stock StartFollowingPlayer(client, target) -{ - - /** - If we have an open timer, close it. - */ - if (g_aPlayers[client][hTargetTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[client][hTargetTimer]); - g_aPlayers[client][hTargetTimer] = INVALID_HANDLE; - } - - /** - Make sure the target is on a non spectator team, and the client != target - */ - if (client == target) - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Yourself"); - return; - } - new iTargetTeam = GetClientTeam(target); - if (iTargetTeam == g_aCurrentTeams[Spectator] || iTargetTeam == g_aCurrentTeams[Unknown]) - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Spectator"); - return; - } - - /** - Check to see if client is already a spectator - */ - if (GetClientTeam(client) != g_aCurrentTeams[Spectator]) - { - - /** - Client is not a spectator, lets move them to spec. - */ - SM_MovePlayer(client, g_aCurrentTeams[Spectator]); - } - - /** - If we are using steambans call sb_status - */ - if (g_aPluginSettings[bUseSteamBans]) - { - FakeClientCommandEx(client, "sb_status"); - } - - - /** - Set the global and start to spectate the target. - Making sure it's long enough to deal with moving the client to spec if we had to. - */ - new String:sTargetName[MAX_NAME_LENGTH + 1]; - GetClientName(target, sTargetName, sizeof(sTargetName)); - g_aPlayers[client][iTargetIndex] = target; - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Spectating", sTargetName); - g_aPlayers[client][hTargetTimer] = CreateTimer(0.5, Timer_ResetTarget, client, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); - if (!g_aPlayers[client][bIsDisplayingHud] && GetClientTeam(client) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(client); - } -} - -stock StopFollowingPlayer(client) -{ - - /** - If we have an open timer, close it. - */ - if (g_aPlayers[client][hTargetTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[client][hTargetTimer]); - } - - /** - Tell the client we can't spec his target anymore... if they are in game. - */ - if (IsClientInGame(client) && g_aPlayers[client][iTargetIndex] != 0) - { - new String:sTargetName[MAX_NAME_LENGTH + 1]; - GetClientName(g_aPlayers[client][iTargetIndex], sTargetName, sizeof(sTargetName)); - if (!IsClientConnected(g_aPlayers[client][iTargetIndex]) || !IsClientInGame(g_aPlayers[client][iTargetIndex])) - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Target Left"); - } - else - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Stopped spectating", sTargetName); - } - } - - /** - Null the globals. - */ - g_aPlayers[client][iTargetIndex] = 0; - g_aPlayers[client][hTargetTimer] = INVALID_HANDLE; -} - -stock StartDisplayingHud(client) -{ - if (g_aPluginCvarSettings[bRestrictHud] && !SM_IsValidAdmin(client, g_sAdminFlags)) - { - return; - } - else - { - /** - Double check the hud timer - We should not have one, but if we do, lets cancel it for the current callback - */ - StopDisplayingHud(client); - - /** - Now we can safely display the hud and make sure the current stored handle is the current timer - */ - g_aPlayers[client][bIsDisplayingHud] = true; - g_aPlayers[client][hHudTimer] = CreateTimer(0.5, Timer_UpdateHud, client, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); - } -} - -stock StopDisplayingHud(client) -{ - if (g_aPlayers[client][hHudTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[client][hHudTimer]); - } - g_aPlayers[client][hHudTimer] = INVALID_HANDLE; - g_aPlayers[client][bIsDisplayingHud] = false; -} - -stock ResetClient(client) -{ - StopFollowingPlayer(client); - StopDisplayingHud(client); - - g_aPlayers[client][bIsFlaggedCheater] = false; - g_aPlayers[client][TargetPunishment] = Punish_None; - g_aPlayers[client][iBanTime] = -1; -} - -stock PerformPunishment(client, target, e_Punishments:punishment, const String:reason[], time = 300) -{ - new String:sTargetName[MAX_NAME_LENGTH + 1], - String:sTargetID[64]; - - /** - The target could have left the game by the time we get here - Check for a valid target - */ - if (!IsClientConnected(target) || !IsClientInGame(target)) - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Target Left"); - return; - } - - GetClientName(target, sTargetName, sizeof(sTargetName)); - GetClientAuthString(target, sTargetID, sizeof(sTargetID)); - - switch (punishment) - { - case Punish_Kick: - { - KickClient(g_aPlayers[client][iTargetIndex], "%s", reason); - } - case Punish_Ban: - { - if (g_aPluginSettings[bUseSourceBans]) - { - ClientCommand(client, "sm_ban #%d %d \"%s\"", GetClientUserId(target), time, reason); - } - else if (g_aPluginSettings[bUseMySQLBans]) - { - ClientCommand(client, "mysql_ban #%d %d \"%s\"", GetClientUserId(target), time, reason); - } - else - { - BanClient(target, time, BANFLAG_AUTHID, reason, reason); - } - } - case Punish_Cheater: - { - g_aPlayers[target][bIsFlaggedCheater] = true; - } - case Punish_Beacon: - { - ClientCommand(client, "sm_beacon \"%s\"", sTargetName); - } - case Punish_Blind: - { - ClientCommand(client, "sm_blind \"%s\"", sTargetName); - } - case Punish_Drug: - { - ClientCommand(client, "sm_drug \"%s\"", sTargetName); - } - case Punish_Freeze: - { - ClientCommand(client, "sm_freeze \"%s\"", sTargetName); - } - case Punish_FreezeBomb: - { - ClientCommand(client, "sm_freezebomb \"%s\"", sTargetName); - } - case Punish_Slap: - { - ClientCommand(client, "sm_slap \"%s\" 10", sTargetName); - } - case Punish_Slay: - { - ClientCommand(client, "sm_slay \"%s\"", sTargetName); - } - case Punish_TimeBomb: - { - ClientCommand(client, "sm_timebomb \"%s\"", sTargetName); - } - } - - if (punishment == Punish_Cheater) - { - LogAction(client, target, "[SM SPEC] %N marked %N(%s) with a %s flag for %s", client, target, sTargetID, g_sPunishments[punishment], reason); - } - else - { - ShowActivity(client, "%t", "Punished", sTargetName, g_sPunishments[punishment], reason); - LogAction(client, target, "[SM SPEC] %N punished %N(%s) with a %s for %s", client, target, sTargetID, g_sPunishments[punishment], reason); - } - - /** - Null the globals. - */ - g_aPlayers[client][TargetPunishment] = Punish_None; - g_aPlayers[client][iBanTime] = -1; -} - -/** -Build the menu of player names -*/ -stock Handle:BuildPlayerListMenu() -{ - new Handle:hMenu = CreateMenu(Menu_PlayerList); - AddTargetsToMenu(hMenu, 0, true, false); - SetMenuTitle(hMenu, "Select A Player:"); - SetMenuExitBackButton(hMenu, true); - return hMenu; -} - -/** -Build the select player menu (current or list of players) -*/ -stock Handle:BuildSelectPlayerMenu() -{ - new Handle:hMenu = CreateMenu(Menu_SelectPlayer); - SetMenuTitle(hMenu, "Select A Player:"); - AddMenuItem(hMenu, "Current", "Current Target"); - AddMenuItem(hMenu, "List", "Player List"); - SetMenuExitBackButton(hMenu, true); - return hMenu; -} - -/** -Build the punishmenu menu -*/ -stock Handle:BuildPunishmentMenu(iClient) -{ - new Handle:hMenu = CreateMenu(Menu_Punishments); - SetMenuTitle(hMenu, "Select A Punishment:"); - SetMenuExitBackButton(hMenu, true); - SetMenuExitButton(hMenu, true); - - if (g_aPluginCvarSettings[bKick] && ((GetUserFlagBits(iClient) & ADMFLAG_GENERIC) || (GetUserFlagBits(iClient) & ADMFLAG_ROOT))) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Kick], "Kick"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Kick], "Kick", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bBan] && ((GetUserFlagBits(iClient) & ADMFLAG_GENERIC) || (GetUserFlagBits(iClient) & ADMFLAG_ROOT))) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Ban], "Ban"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Ban], "Ban", ITEMDRAW_DISABLED); - } - - if (g_aPluginSettings[bUseDukehacks] && g_aPluginCvarSettings[bCheater] && (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Cheater], "Flag As Cheater"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Cheater], "Flag As Cheater", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bBeacon]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Beacon], "Beacon"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Beacon], "Beacon", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bBlind]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Blind], "Blind"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Blind], "Blind", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bDrug]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Drug], "Drug"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Drug], "Drug", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bFreeze]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Freeze], "Freeze"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Freeze], "Freeze", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bFreezebomb]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_FreezeBomb], "Freeze Bomb"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_FreezeBomb], "Freeze Bomb", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bSlap]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Slap], "Slap"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Slap], "Slap", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bSlay]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Slay], "Slay"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Slay], "Slay", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bTimeBomb]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_TimeBomb], "Time Bomb"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_TimeBomb], "Time Bomb", ITEMDRAW_DISABLED); - } - - return hMenu; -} - -/** -Build the punishmenu menu -*/ -stock Handle:BuildBanTimeMenu() -{ - new Handle:hMenu = CreateMenu(Menu_BanTime); - SetMenuTitle(hMenu, "Select Ban Type:"); - - if (g_aPluginCvarSettings[bBanPerm]) - { - AddMenuItem(hMenu, "permban", "Permanent"); - } - else - { - AddMenuItem(hMenu, "permban", "Permanent", ITEMDRAW_DISABLED); - } - - AddMenuItem(hMenu, "10", "10 Minutes"); - AddMenuItem(hMenu, "30", "30 Minutes"); - AddMenuItem(hMenu, "60", "1 Hour"); - AddMenuItem(hMenu, "240", "4 Hours"); - AddMenuItem(hMenu, "1440", "1 Day"); - AddMenuItem(hMenu, "10080", "1 Week"); - - SetMenuExitBackButton(hMenu, true); - return hMenu; -} - -/** -Build the punishmenu menu -*/ -stock Handle:BuildReasonMenu() -{ - new Handle:hMenu = CreateMenu(Menu_Reason); - SetMenuTitle(hMenu, "Select A Reason:"); - - AddMenuItem(hMenu, "Abusive", "Abusive"); - AddMenuItem(hMenu, "Racism", "Racism"); - AddMenuItem(hMenu, "General cheating/exploits", "General cheating/exploits"); - AddMenuItem(hMenu, "Wallhack", "Wallhack"); - AddMenuItem(hMenu, "Aimbot", "Aimbot"); - AddMenuItem(hMenu, "Speedhacking", "Speedhacking"); - AddMenuItem(hMenu, "Mic spamming", "Mic spamming"); - AddMenuItem(hMenu, "Admin disrepect", "Admin disrepect"); - AddMenuItem(hMenu, "Camping", "Camping"); - AddMenuItem(hMenu, "Team killing", "Team killing"); - AddMenuItem(hMenu, "Unacceptable Spray", "Unacceptable Spray"); - AddMenuItem(hMenu, "Breaking Server Rules", "Breaking Server Rules"); - AddMenuItem(hMenu, "Other", "Other"); - - SetMenuExitBackButton(hMenu, true); - return hMenu; -} - -/** -Build the cheater displays -*/ -stock Handle:BuildAdminCheaterPanel() -{ - - /** - Create the menu and set the menu options. - */ - new Handle:hPanel = CreatePanel(); - SetPanelTitle(hPanel, "Simple Spectator:"); - - DrawPanelText(hPanel, "Are you sure you want to"); - DrawPanelText(hPanel, "flag this player as a cheater?"); - DrawPanelText(hPanel, "They will not be able to damage"); - DrawPanelText(hPanel, "anyone and die on fall damage."); - DrawPanelItem(hPanel, "Yes"); - DrawPanelItem(hPanel, "No"); - - return hPanel; -} - -stock Handle:BuildPublicCheaterPanel() -{ - - /** - Create the menu and set the menu options. - */ - new Handle:hPanel = CreatePanel(); - SetPanelTitle(hPanel, "Simple Spectator:"); - - DrawPanelText(hPanel, "Are you sure you want to"); - DrawPanelText(hPanel, "submit this player as a cheater?"); - DrawPanelItem(hPanel, "Yes (Not Implemented Yet)", ITEMDRAW_DISABLED); - DrawPanelItem(hPanel, "No"); - return hPanel; -} - -/** -Build the hud displays -*/ -stock Handle:BuildPlayerHudMenu(iClient, iTarget) -{ - - /** - Create all the string variables we will need - */ - new String:sTargetName[MAX_NAME_LENGTH + 1], - String:sTargetID[64], - String:sTargetIP[16]; - - new String:sDisplayName[MAX_NAME_LENGTH + 1], - String:sDisplayID[64], - String:sDisplayIP[64], - String:sDisplayFrags[16], - String:sDisplayDeaths[16]; - - new iTargetFrags, - iTargetDeaths; - - /** - Get the targets information - */ - GetClientName(iTarget, sTargetName, sizeof(sTargetName)); - GetClientIP(iTarget, sTargetIP, sizeof(sTargetIP)); - GetClientAuthString(iTarget, sTargetID, sizeof(sTargetID)); - iTargetFrags = GetClientFrags(iTarget); - iTargetDeaths = GetClientDeaths(iTarget); - - /** - Format the strings for the menu - */ - Format(sDisplayName, sizeof(sDisplayName), "Player: %s", sTargetName); - Format(sDisplayID, sizeof(sDisplayID), "Steam ID: %s", sTargetID); - Format(sDisplayIP, sizeof(sDisplayIP), "IP Address: %s", sTargetIP); - Format(sDisplayFrags, sizeof(sDisplayFrags), "Kills: %i", iTargetFrags); - Format(sDisplayDeaths, sizeof(sDisplayDeaths), "Deaths: %i", iTargetDeaths); - - /** - Create the menu and set the menu options. - */ - new Handle:hMenu = CreateMenu(Menu_PlayerHud); - SetMenuExitBackButton(hMenu, false); - SetMenuTitle(hMenu, "Simple Spectator"); - - AddMenuItem(hMenu, "name", sDisplayName, ITEMDRAW_DISABLED); - AddMenuItem(hMenu, "steamid", sDisplayID, ITEMDRAW_DISABLED); - - if (SM_IsValidAdmin(iClient, g_sAdminFlags)) - { - AddMenuItem(hMenu, "ip", sDisplayIP, ITEMDRAW_DISABLED); - } - - AddMenuItem(hMenu, "kills", sDisplayFrags, ITEMDRAW_DISABLED); - AddMenuItem(hMenu, "deaths", sDisplayDeaths, ITEMDRAW_DISABLED); - - if (g_aPlayers[iClient][iTargetIndex]) - { - AddMenuItem(hMenu, "stop", "Stop Following"); - } - else - { - AddMenuItem(hMenu, "start", "Follow Player"); - } - - if ((GetUserFlagBits(iClient) & ADMFLAG_GENERIC) || (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - if (g_aPlayers[iTarget][bIsFlaggedCheater] && (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - AddMenuItem(hMenu, "removecheater", "Remove Cheater Flag"); - } - else - { - if (CanUserTarget(iClient, iTarget)) - { - AddMenuItem(hMenu, "punish", "Punish Player"); - } - else - { - AddMenuItem(hMenu, "punish", "Punish Player (Immune)", ITEMDRAW_DISABLED); - } - } - } - else - { - AddMenuItem(hMenu, "reportcheater", "Report Cheater"); - } - - SetMenuPagination(hMenu, MENU_NO_PAGINATION); - SetMenuExitButton(hMenu, true); - return hMenu; -} - -stock Handle:BuildPlayerHudPanel(iClient, iTarget) -{ - - /** - Create all the string variables we will need - */ - new String:sTargetName[MAX_NAME_LENGTH + 1], - String:sTargetID[64], - String:sTargetIP[16]; - - new String:sDisplayName[MAX_NAME_LENGTH + 1], - String:sDisplayID[64], - String:sDisplayIP[64], - String:sDisplayFrags[16], - String:sDisplayDeaths[16]; - - new iTargetFrags, - iTargetDeaths; - - /** - Get the targets information - */ - GetClientName(iTarget, sTargetName, sizeof(sTargetName)); - GetClientIP(iTarget, sTargetIP, sizeof(sTargetIP)); - GetClientAuthString(iTarget, sTargetID, sizeof(sTargetID)); - iTargetFrags = GetClientFrags(iTarget); - iTargetDeaths = GetClientDeaths(iTarget); - - /** - Format the strings for the menu - */ - Format(sDisplayName, sizeof(sDisplayName), "Player: %s", sTargetName); - Format(sDisplayID, sizeof(sDisplayID), "Steam ID: %s", sTargetID); - Format(sDisplayIP, sizeof(sDisplayIP), "IP Address: %s", sTargetIP); - Format(sDisplayFrags, sizeof(sDisplayFrags), "Kills: %i", iTargetFrags); - Format(sDisplayDeaths, sizeof(sDisplayDeaths), "Deaths: %i", iTargetDeaths); - - /** - Create the menu and set the menu options. - */ - new Handle:hPanel = CreatePanel(); - SetPanelTitle(hPanel, "Simple Spectator"); - - DrawPanelText(hPanel, "Player Information:"); - DrawPanelText(hPanel, sDisplayName); - DrawPanelText(hPanel, sDisplayID); - if (SM_IsValidAdmin(iClient, g_sAdminFlags)) - { - DrawPanelText(hPanel, sDisplayIP); - } - - DrawPanelText(hPanel, sDisplayFrags); - DrawPanelText(hPanel, sDisplayDeaths); - - if (g_aPlayers[iClient][iTargetIndex]) - { - DrawPanelItem(hPanel, "Stop Following"); - } - else - { - DrawPanelItem(hPanel, "Follow Player"); - } - - if ((GetUserFlagBits(iClient) & ADMFLAG_GENERIC) || (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - if (g_aPlayers[iTarget][bIsFlaggedCheater] && (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - DrawPanelItem(hPanel, "Remove Cheater Flag"); - } - else - { - if (CanUserTarget(iClient, iTarget)) - { - DrawPanelItem(hPanel, "Punish Player"); - } - else - { - DrawPanelItem(hPanel, "Punish Player (Immune)", ITEMDRAW_DISABLED); - } - } - } - else - { - DrawPanelItem(hPanel, "Report Cheater"); - } - - DrawPanelItem(hPanel, "Close Hud Panel"); - return hPanel; -} - -/** -Adjust the settings if a convar was changed -*/ -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - for (new iCvar = 0 ; _:iCvar < sizeof(g_aPluginCvarSettings); iCvar++) - { - if (g_aPluginCvar[_:iCvar] == convar) - { - if (StringToInt(newValue) == 1) - { - g_aPluginCvarSettings[_:iCvar] = true; - } - else - { - g_aPluginCvarSettings[_:iCvar] = false; - } - } - } - - /* - ReBuild the global menu that depends on cvars - */ - g_aMenus[hBanTime] = BuildBanTimeMenu(); - - /** - Run a loop to reset the hud - */ - for(new i = 1; i <= MaxClients; i++) - { - StopDisplayingHud(i); - if (IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(i); - } - } -} diff --git a/Simple AutoScrambler/addons/sourcemod/scripting/simple-teambalancer.sp b/Simple AutoScrambler/addons/sourcemod/scripting/simple-teambalancer.sp deleted file mode 100644 index 3302255..0000000 --- a/Simple AutoScrambler/addons/sourcemod/scripting/simple-teambalancer.sp +++ /dev/null @@ -1,1797 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Team Balancer -Description: - Balances teams based upon player count - Player will not be balanced more than once in 5 (default) mins - Buddy system tries to keep buddies together - Ability to prioritize players - Ability to force players to accept the new team - Admins are immune -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include -#include - -#define PLUGIN_VERSION "2.1.$Rev$" - -enum PlayerData -{ - Handle:hBalanceTimer, - Handle:hForcedTimer, - bool:bSwitched, - bool:bFlagCarrier -}; - -/** - Global convar handles - */ -new Handle:stb_enabled = INVALID_HANDLE; -new Handle:stb_buddyenabled = INVALID_HANDLE; -new Handle:stb_logactivity = INVALID_HANDLE; -new Handle:stb_logactivity2 = INVALID_HANDLE; -new Handle:stb_unbalancelimit = INVALID_HANDLE; -new Handle:stb_deadonly = INVALID_HANDLE; -new Handle:stb_priorityenabled = INVALID_HANDLE; -new Handle:stb_uberlevel = INVALID_HANDLE; -new Handle:stb_balancedelay = INVALID_HANDLE; -new Handle:stb_livingplayerswitchdelay = INVALID_HANDLE; -new Handle:stb_livingplayercheckdelay = INVALID_HANDLE; -new Handle:stb_roundstartdelay = INVALID_HANDLE; -new Handle:stb_switchbackforced = INVALID_HANDLE; -new Handle:stb_adminflag = INVALID_HANDLE; -new Handle:stb_buddyrestriction = INVALID_HANDLE; -new Handle:stb_convarcontrol = INVALID_HANDLE; - -/** - Built-in cvars handles - */ -new Handle:stb_mp_autoteambalance = INVALID_HANDLE; -new Handle:stb_mp_teams_unbalance_limit = INVALID_HANDLE; -new Handle:TFGameModeArena = INVALID_HANDLE; - -/** - Timer handles - */ -new Handle:g_hBalanceTimer = INVALID_HANDLE; -new Handle:g_hLivingPlayerCheckTimer = INVALID_HANDLE; - -/** - Player arrays - */ -new g_aPlayers[MAXPLAYERS + 1][PlayerData]; - -/** -Global bools -*/ -new bool:g_bIsEnabled = true; -new bool:g_bPriorityPlayers = true; -new bool:g_bBuddyRestriction = false; -new bool:g_bLogActivity = false; -new bool:g_bLogActivity2 = false; -new bool:g_bDeadOnly = false; -new bool:g_bConVarControl = true; -new bool:g_bBuddyEnabled = true; -new bool:g_bBalanceInProgress = false; -new bool:g_bRoundStart = false; -new bool:g_bRoundEnd = false; -new bool:g_bSuddenDeath = false; -new bool:g_bIsArenaMode = false; - -/** - Global strings/integers/floats - */ -new g_iUnbalanceLimit, g_iLivingPlayerSwitchDelay, g_iLivingPlayerCheckDelay; -new g_iRoundStartDelay, g_iSwitchBackForced, g_iBalanceDelay; -new Float:g_fUberLevel; -new g_iOwnerOffset; -new String:g_sAdminFlag[5]; - -public Plugin:myinfo = -{ - name = "Simple Team Balancer", - author = "Simple Plugins", - description = "Balances teams based upon player count.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -} - -public OnPluginStart() -{ - - /** - Create console variables - */ - CreateConVar("stb_version", PLUGIN_VERSION, "Simple Team Balancer", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - stb_enabled = CreateConVar("stb_enabled", "1", "Enable or Disable Simple Team Balancer", _, true, 0.0, true, 1.0); - stb_priorityenabled = CreateConVar("stb_priorityenabled", "1", "Enable or Disable the prioritization of living players", _, true, 0.0, true, 1.0); - stb_buddyrestriction = CreateConVar("stb_buddyrestriction", "0", "Enable or Disable Admin Only buddy lists", _, true, 0.0, true, 1.0); - stb_logactivity = CreateConVar("stb_logactivity", "0", "Enable or Disable the disaplying of events in the log", _, true, 0.0, true, 1.0); - stb_logactivity2 = CreateConVar("stb_logactivity2", "0", "Enable or Disable the disaplying of detailed events in the log (WILL SPAM LOG)", _, true, 0.0, true, 1.0); - stb_deadonly = CreateConVar("stb_deadonly", "0", "Enable or Disable the switching of only dead players", _, true, 0.0, true, 1.0); - stb_convarcontrol = CreateConVar("stb_convarcontrol", "1", "Enable or Disable the control of builtin console variables", _, true, 0.0, true, 1.0); - stb_buddyenabled = CreateConVar("stb_buddyenabled", "1", "Enable or Disable the buddy system", _, true, 0.0, true, 1.0); - stb_unbalancelimit = CreateConVar("stb_unbalancelimit", "2", "Amount of players teams are ALLOWED to be unbalanced by", _, true, 1.0, true, 32.0); - stb_balancedelay = CreateConVar("stb_balancedelay", "10", "Delay in seconds to start an autobalance"); - stb_livingplayerswitchdelay = CreateConVar("stb_livingplayerswitchdelay", "20", "Delay in seconds to switch living players once selected"); - stb_livingplayercheckdelay = CreateConVar("stb_livingplayercheckdelay", "10", "Delay in seconds to start checking living players once teams become unbalanced"); - stb_roundstartdelay = CreateConVar("stb_roundstartdelay", "15", "Delay in seconds to start balancing teams after the start of a round"); - stb_switchbackforced = CreateConVar("stb_switchbackforced", "300", "Amount of time in seconds to not switch a player twice and force the team if enabled"); - stb_uberlevel = CreateConVar("stb_uberlevel", "1.0", "Min uber level medic must have to have priority over other living players. Setting to 0 will rarely switch a living medic", _, true, 0.0, true, 1.0); - stb_adminflag = CreateConVar("stb_adminflag", "a", "Admin flag to use for immunity. Must be a in char format."); - stb_mp_autoteambalance = FindConVar("mp_autoteambalance"); - stb_mp_teams_unbalance_limit = FindConVar("mp_teams_unbalance_limit"); - - /** - Removing the notify tags from the built in cvars. We dont want spam. - */ - if (stb_mp_autoteambalance != INVALID_HANDLE) - { - SetConVarFlags(stb_mp_autoteambalance, GetConVarFlags(stb_mp_autoteambalance)^FCVAR_NOTIFY); - } - if (stb_mp_teams_unbalance_limit != INVALID_HANDLE) - { - SetConVarFlags(stb_mp_teams_unbalance_limit, GetConVarFlags(stb_mp_teams_unbalance_limit)^FCVAR_NOTIFY); - } - - /** - Hook console variables - */ - HookConVarChange(stb_enabled, ConVarSettingsChanged); - HookConVarChange(stb_priorityenabled, ConVarSettingsChanged); - HookConVarChange(stb_buddyrestriction, ConVarSettingsChanged); - HookConVarChange(stb_logactivity, ConVarSettingsChanged); - HookConVarChange(stb_logactivity2, ConVarSettingsChanged); - HookConVarChange(stb_deadonly, ConVarSettingsChanged); - HookConVarChange(stb_convarcontrol, ConVarSettingsChanged); - HookConVarChange(stb_buddyenabled, ConVarSettingsChanged); - HookConVarChange(stb_unbalancelimit, ConVarSettingsChanged); - HookConVarChange(stb_balancedelay, ConVarSettingsChanged); - HookConVarChange(stb_livingplayerswitchdelay, ConVarSettingsChanged); - HookConVarChange(stb_livingplayercheckdelay, ConVarSettingsChanged); - HookConVarChange(stb_roundstartdelay, ConVarSettingsChanged); - HookConVarChange(stb_switchbackforced, ConVarSettingsChanged); - HookConVarChange(stb_uberlevel, ConVarSettingsChanged); - HookConVarChange(stb_mp_autoteambalance, ConVarSettingsChanged); - HookConVarChange(stb_mp_teams_unbalance_limit, ConVarSettingsChanged); - - /** - Create console commands - */ - RegConsoleCmd("sm_buddy", Command_AddBalanceBuddy, "Add a balance buddy"); - RegConsoleCmd("sm_lockbuddy", Command_LockBuddy, "Locks your balance buddy selection"); - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[STB] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_death", HookPlayerDeath, EventHookMode_Post); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Post); - switch (g_CurrentMod) - { - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - HookEvent("teamplay_suddendeath_begin", HookSuddenDeathBegin, EventHookMode_PostNoCopy); - HookEvent("teamplay_flag_event", HookFlagEvent, EventHookMode_Post); - TFGameModeArena = FindConVar("tf_gamemode_arena"); - g_iOwnerOffset = FindSendPropInfo("CBaseObject", "m_hBuilder"); - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_Post); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - - /** - Load translations and .cfg file - */ - LoadTranslations ("simpleteambalancer.phrases"); - AutoExecConfig(true, "plugin.simpleteambalancer"); - LogAction(0, -1, "[STB] Simple Team Balancer is loaded."); -} - -public OnAllPluginsLoaded() -{ - //something -} - -public OnLibraryRemoved(const String:name[]) -{ - //something -} - -public OnConfigsExecuted() -{ - - /** - Load up global variables - */ - g_bIsEnabled = GetConVarBool(stb_enabled); - g_bBuddyEnabled = GetConVarBool(stb_buddyenabled); - g_bLogActivity = GetConVarBool(stb_logactivity); - g_bLogActivity2 = GetConVarBool(stb_logactivity2); - g_bDeadOnly = GetConVarBool(stb_deadonly); - g_bPriorityPlayers = GetConVarBool(stb_priorityenabled); - g_bBuddyRestriction = GetConVarBool(stb_buddyrestriction); - g_bConVarControl = GetConVarBool(stb_convarcontrol); - g_fUberLevel = GetConVarFloat(stb_uberlevel); - g_iUnbalanceLimit = GetConVarInt(stb_unbalancelimit); - g_iBalanceDelay = GetConVarInt(stb_balancedelay); - g_iLivingPlayerSwitchDelay = GetConVarInt(stb_livingplayerswitchdelay); - g_iLivingPlayerCheckDelay = GetConVarInt(stb_livingplayercheckdelay); - g_iRoundStartDelay = GetConVarInt(stb_roundstartdelay); - g_iSwitchBackForced = GetConVarInt(stb_switchbackforced); - GetConVarString(stb_adminflag, g_sAdminFlag, sizeof(g_sAdminFlag)); - - /** - Report enabled - */ - if (g_bIsEnabled) - { - LogAction(0, -1, "[STB] Simple Team Balancer is ENABLED."); - } - else - { - LogAction(0, -1, "[STB] Simple Team Balancer is DISABLED."); - } - - - /** - Report log activity - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Log Activity ENABLED."); - } - else - { - LogAction(0, -1, "[STB] Log Activity DISABLED."); - } - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Detailed Log Activity ENABLED."); - } - else - { - LogAction(0, -1, "[STB] Detailed Log Activity DISABLED."); - } -} - -public OnMapStart() -{ - - /** - Check for arena mode - */ - if (g_CurrentMod == GameType_TF && GetConVarBool(TFGameModeArena)) - { - g_bIsArenaMode = true; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Simple Team Balancer detected arena mode and will be bypassed"); - } - } - else - { - g_bIsArenaMode = false; - } - - /** - Reset the globals - */ - g_bBalanceInProgress = false; - g_bRoundStart = false; - g_bRoundEnd = false; - g_bSuddenDeath = false; - - /** - Set the built-in convars - */ - SetGameCvars(); -} - -public OnClientPostAdminCheck(client) -{ - - /** - Make sure its a valid connected client and buddy system is enabled - */ - if (client == 0 || !g_bIsEnabled || !IsClientConnected(client) || !g_bBuddyEnabled) - { - return; - } - - /** - Make sure if its set for admins only they have the flags - */ - if (g_bBuddyRestriction && !SM_IsValidAdmin(client, g_sAdminFlag)) - { - return; - } - - /** - Start the advertisement timer - */ - CreateTimer (60.0, Timer_WelcomeAdvert, client); -} - -public OnClientDisconnect(client) -{ - - /** - Call stock function to cleaup - */ - CleanUp(client); -} - -public OnClientDisconnect_Post(client) -{ - - /** - Determine if we need a balance - */ - if (OkToBalance() && IsUnbalanced() && !g_bBalanceInProgress) - { - - /** - No balance in progress but balance is needed - */ - StartABalance(); - } -} - -public SM_OnPlayerMoved(Handle:plugin, client, team) -{ - - /** - Make sure we called the move function - */ - if (plugin != GetMyHandle()) - { - if (g_bLogActivity2) - { - LogAction(0, client, "[STB] Callback was not started with current plugin, bugging out."); - } - return; - } - - /** - Get the players name and report the event - */ - decl String:sPlayerName[64]; - GetClientName(client, sPlayerName, sizeof(sPlayerName)); - if (g_bLogActivity) - { - LogAction(0, client, "[STB] Changed %s to team %i.", sPlayerName, team); - } - - /** - If we are in TF2 fire the bult-in team balance event - */ - if(g_CurrentMod == GameType_TF) - { - new Handle:event = CreateEvent("teamplay_teambalanced_player"); - SetEventInt(event, "player", client); - SetEventInt(event, "team", team); - FireEvent(event); - } - - /** - Notify the players - */ - PrintToChatAll("[SM] %T", "BalanceMessage", LANG_SERVER, sPlayerName); - - /** - Set the players variables and start a timer - */ - g_aPlayers[client][bSwitched] = true; - g_aPlayers[client][hForcedTimer] = CreateTimer(float(g_iSwitchBackForced), Timer_ForcedExpired, client, TIMER_FLAG_NO_MAPCHANGE); - - /** - We are done, log the completion and end the balance - */ - if (g_bLogActivity) - { - LogAction(0, client, "[STB] Balance finished."); - } - g_bBalanceInProgress = false; -} - -/* HOOKED EVENTS */ - -public HookPlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get our event variables - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - decl String:sWeapon[64]; - GetEventString(event, "weapon", sWeapon, sizeof(sWeapon)); - - /** - Return if death was not caused by a player - This is the case when the player switches teams - */ - if (StrEqual(sWeapon, "world", false)) - { - return; - } - - - /** - Check if balance is needed - */ - if (IsClientInGame(iClient) && OkToBalance() && IsUnbalanced()) - { - new iSmallerTeam = GetSmallerTeam(); - - /** - Check if balance is in progress - */ - if (g_bBalanceInProgress) - { - - /** - There is a balance in progress - Check the player who died to see if he is supposed to be switched - */ - if (g_aPlayers[iClient][hBalanceTimer] != INVALID_HANDLE) - { - - /** - The player has a timer on him to switch him to other team - Stop the timer - */ - CloseHandle(g_aPlayers[iClient][hBalanceTimer]); - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] With a balance in progress the queued living player died and was switched."); - } - - /** - Call the stock change team function - */ - BalancePlayer(iClient, SM_GetForcedTeam(iClient)); - return; - } - - /** - Before we continue, lets make sure the client is switchable - */ - if (IsSwitchablePlayer(iClient, GetBiggerTeam())) - { - - /** - Now we check the buddy system - */ - if (g_bBuddyEnabled) - { - - /** - Buddy system is enabled, check to see if client has buddy - */ - new iBuddyIndex = SM_GetClientBuddy(iClient); - if (iBuddyIndex != 0 || !IsClientConnected(iBuddyIndex) || !IsClientInGame(iBuddyIndex)) - { - - /** - The client has a buddy, so we check to see if they are on same team - */ - if (GetClientTeam(iClient) == GetClientTeam(iBuddyIndex)) - { - - /** - They are, but we don't bug out, we still need to start a balance - */ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] With a balance in progress a buddy on the right team was found and skipped."); - } - } - else - { - - /** - They are not on the same team - The buddy could be in spec, and that would make it not matter where he is, or the buddy is on the smaller team - */ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] With a balance in progress a buddy on the wrong team was switched."); - } - BalancePlayer(iClient, iSmallerTeam); - return; - } - } - else - { - - /** - Client doesn't have a buddy, balance this player - */ - BalancePlayer(iClient, iSmallerTeam); - return; - } - } - else - { - - /** - Buddy system is not enabled, balance this player - */ - BalancePlayer(iClient, iSmallerTeam); - return; - } - } - } - else - { - - /** - If we get to here then we must need to start a balance - */ - StartABalance(); - } - } -} - -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get our event variables. - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - new iTeam = GetEventInt(event, "team"); - - /** - Make sure its ok to balance. - */ - if (OkToBalance()) - { - - /** - See if the client that changed teams was set to with a balance. - */ - if (g_aPlayers[iClient][hBalanceTimer] != INVALID_HANDLE - && SM_GetForcedTeam(iClient) == iTeam - && g_bBalanceInProgress) - { - - /** - The client was set to be balanced, so we close the timer. - */ - CloseHandle(g_aPlayers[iClient][hBalanceTimer]); - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - - /** - Stop the balance. - */ - g_bBalanceInProgress = false; - return; - } - - /** - It's not likely that this team change can cause us to need a balance. - If it does, start one with a small dealy to deal with forced switch backs. - */ - if (IsUnbalanced() && !g_bBalanceInProgress) - { - CreateTimer(2.0, Timer_ChangeTeamBalanceDelay, _, TIMER_FLAG_NO_MAPCHANGE); - } - } -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set the variables we need to start a round - */ - g_bRoundStart = true; - g_bRoundEnd = false; - g_bSuddenDeath = false; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Round Started"); - } - - /** - Start a delayed balance check at the start of the round - */ - CreateTimer(float(g_iRoundStartDelay), Timer_RoundStart); -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set the variables we need at round end - */ - g_bRoundEnd = true; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Round Ended"); - } -} - -public HookSuddenDeathBegin(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set the variables we need for sudden death - */ - g_bSuddenDeath = true; -} - -public HookFlagEvent(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get our event variables - */ - new iClient = GetEventInt(event, "player"); - new iFlagStatus = GetEventInt(event, "eventtype"); - - /** - Make sure we have a valid client - */ - if (!IsClientInGame(iClient)) - { - return; - } - - /** - Determine what kind of event this is - */ - switch (iFlagStatus) - { - case 1: - { - - /** - The flag was picked up - */ - g_aPlayers[iClient][bFlagCarrier] = true; - } - case 2: - { - - /** - The flag was capped - */ - g_aPlayers[iClient][bFlagCarrier] = false; - } - case 3: - { - - /** - The flag was defended, we don't have to do anything - */ - } - case 4: - { - - /** - The flag was dropped - */ - g_aPlayers[iClient][bFlagCarrier] = false; - } - } -} - -/* COMMAND EVENTS */ - -public Action:Command_AddBalanceBuddy(client, args) -{ - if (client == 0) - { - ReplyToCommand(client, "[SM] %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - if (!g_bIsEnabled || !g_bBuddyEnabled) - { - ReplyToCommand(client, "[SM] %T", "CmdDisabled", LANG_SERVER); - return Plugin_Handled; - } - if (g_bBuddyRestriction) - { - if (!SM_IsValidAdmin(client, g_sAdminFlag)) - { - ReplyToCommand(client, "[SM] %T", "RestrictedBuddy", LANG_SERVER); - return Plugin_Handled; - } - } - decl String:sPlayerUserId[24]; - GetCmdArg(1, sPlayerUserId, sizeof(sPlayerUserId)); - new iPlayer = GetClientOfUserId(StringToInt(sPlayerUserId)); - if (!iPlayer || !IsClientInGame(iPlayer) || client == iPlayer) - { - if (client == iPlayer) - { - PrintHintText(client, "%T", "SelectSelf", LANG_SERVER); - } - ReplyToCommand(client, "[SM] Usage: buddy "); - new Handle:playermenu = BuildPlayerMenu(); - DisplayMenu(playermenu, client, MENU_TIME_FOREVER); - } - else - { - decl String:cName[128]; - decl String:bName[128]; - GetClientName(client, cName, sizeof(cName)); - GetClientName(iPlayer, bName, sizeof(bName)); - if (SM_IsBuddyLocked(iPlayer)) - { - ReplyToCommand(client, "[SM] %T", "PlayerLockedBuddyMsg", LANG_SERVER, bName); - return Plugin_Handled; - } - SM_AssignBuddy(client, iPlayer); - PrintHintText(client, "%T", "BuddyMsg", LANG_SERVER, bName); - PrintHintText(iPlayer, "%T", "BuddyMsg", LANG_SERVER, cName); - } - return Plugin_Handled; -} - -public Action:Command_LockBuddy(client, args) -{ - if (client == 0) - { - ReplyToCommand(client, "[SM] %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - if (!g_bIsEnabled) - { - ReplyToCommand(client, "[SM] %T", "CmdDisabled", LANG_SERVER); - return Plugin_Handled; - } - if (g_bBuddyRestriction) - { - if (!SM_IsValidAdmin(client, g_sAdminFlag)) - { - ReplyToCommand(client, "[SM] %T", "RestrictedBuddy", LANG_SERVER); - return Plugin_Handled; - } - } - if (SM_IsBuddyLocked(client)) - { - SM_LockBuddy(client, false); - PrintHintText(client, "%T", "BuddyLockMsgDisabled", LANG_SERVER); - } - else - { - SM_LockBuddy(client, true); - PrintHintText(client, "%T", "BuddyLockMsgEnabled", LANG_SERVER); - } - return Plugin_Handled; -} - -/** -Stock functions . - */ - -stock bool:IsUnbalanced() -{ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Checking if teams are unbalanced"); - } - new Team1Count = GetTeamClientCount(g_aCurrentTeams[Team1]); - new Team2Count = GetTeamClientCount(g_aCurrentTeams[Team2]); - new ubCount = RoundFloat(FloatAbs(float(Team1Count - Team2Count))); - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Team1:%i Team2:%i Difference:%i", Team1Count, Team2Count, ubCount); - } - if (ubCount > g_iUnbalanceLimit) - { - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Teams are unbalanced"); - } - return true; - } - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Teams are not unbalanced"); - } - return false; -} - -stock bool:OkToBalance() -{ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Checking if OK to balance."); - } - new bool:bResult = false; - if (g_bIsEnabled && !g_bRoundStart && !g_bRoundEnd && !g_bIsArenaMode && !g_bSuddenDeath) - { - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Passed IF statement"); - LogAction(0, -1, "[STB] Now checking admins"); - } - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientInGame(i) && !SM_IsValidAdmin(i, g_sAdminFlag)) - { - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Found at least 1 non-admin"); - LogAction(0, -1, "[STB] OK to balance"); - } - bResult = true; - break; - } - } - if (!bResult && g_bLogActivity2) - { - LogAction(0, -1, "[STB] All admins online"); - } - } - if (!bResult && g_bLogActivity2) - { - LogAction(0, -1, "[STB] Not OK to balance"); - } - return bResult; -} - -stock bool:IsSwitchablePlayer(iClient, iBiggerTeam) -{ - - /** - Run the client thru some standard checks - */ - if (!IsClientInGame(iClient) - || SM_IsValidAdmin(iClient, g_sAdminFlag) - || g_aPlayers[iClient][bFlagCarrier] - || GetClientTeam(iClient) != iBiggerTeam - || g_aPlayers[iClient][bSwitched]) - { - - /** - The supplied client can't be switched - */ - return false; - } - - /** - The supplied client can be switched - */ - return true; -} - -stock bool:HasUber(iClient) -{ - - /** - First things first, make sure the client is a medic - */ - if(TF2_GetPlayerClass(iClient) == TFClass_Medic) - { - - /** - We can only check the active weapon, so make sure the client is holding the uber gun - */ - decl String:sWeaponName[32]; - GetClientWeapon(iClient, sWeaponName, sizeof(sWeaponName)); - if(StrEqual(sWeaponName, "tf_weapon_medigun")) - { - - /** - They are, so lets check the uber level of the gun - */ - new iEntityIndex = GetEntDataEnt2(iClient, FindSendPropInfo("CTFPlayer", "m_hActiveWeapon")); - new Float:fChargeLevel = GetEntDataFloat(iEntityIndex, FindSendPropInfo("CWeaponMedigun", "m_flChargeLevel")); - if (fChargeLevel >= g_fUberLevel) - { - - /** - The client supplied has an uber above the supplied level, return true - */ - if (g_bLogActivity2) - { - LogAction(0, iClient, "[STB] Found a medic with a uber and skipped him."); - } - return true; - } - } - } - - /** - The client supplied does not have an uber above the supplied level, return false - */ - return false; -} - -stock bool:HasBuildingsBuilt(iClient) -{ - - /** - We have to start a loop to check the owner of all the valid entities - */ - new iMaxEntities = GetMaxEntities(); - for (new i = MaxClients + 1; i <= iMaxEntities; i++) - { - if (!IsValidEntity(i)) - { - - /** - Not valid, continue to next one - */ - continue; - } - - /** - Get the name of the current entity - */ - decl String:sNetClass[32]; - GetEntityNetClass(i, sNetClass, sizeof(sNetClass)); - - /** - See if its something that an engineer would build - */ - if (strcmp(sNetClass, "CObjectSentrygun") == 0 - || strcmp(sNetClass, "CObjectTeleporter") == 0 - || strcmp(sNetClass, "CObjectDispenser") == 0) - { - - /** - It is, so lets check the owner - */ - if (GetEntDataEnt2(i, g_iOwnerOffset) == iClient) - { - - /** - The client supplied is the owner, return true - */ - if (g_bLogActivity2) - { - LogAction(0, iClient, "[STB] Found an engineer with buildings and skipped him."); - } - return true; - } - } - } - - /** - The client supplied didn't have any buildings, return false - */ - return false; -} - -stock StartABalance() -{ - - /** - See if we are already started a balance - */ - if (g_hBalanceTimer != INVALID_HANDLE) - { - - /** - We have, check if we still need to - */ - if (!IsUnbalanced() || !OkToBalance()) - { - - /** - We don't, stop the balance - It's almost impossible to reach this code, but we do it just in case - */ - CloseHandle(g_hBalanceTimer); - g_hBalanceTimer = INVALID_HANDLE; - g_bBalanceInProgress = false; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Balance delay timer was not needed and was killed before the callback."); - } - return; - } - else - { - - /** - We still need to balance - Bug out and wait for the current one to finish - */ - return; - } - } - - /** - Report that teams are unbalanced - */ - PrintToChatAll("[SM] %T", "UnBalanced", LANG_SERVER); - - /** - Check to see if we are supposed to delay the balance - */ - if (g_iBalanceDelay == 0) - { - - /** - Start the balance now - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Balance is now in progress."); - } - g_bBalanceInProgress = true; - g_hBalanceTimer = INVALID_HANDLE; - - /** - Check if we are allowed to scan living players - */ - if (!g_bDeadOnly) - { - - /** - We are allowed to, so we start a timer - */ - StartALivingPlayerTimer(); - - /** - Also report that we are now scanning dead players as well - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Now scanning dead players."); - } - } - else - { - - /** - We are not allowed to, so report that we are only scanning dead players - */ - if (g_bLogActivity) - LogAction(0, -1, "[STB] Only scanning dead players."); - } - - /** - We started the balance, bug out - */ - return; - } - - /** - We are supposed to delay the balance, start a balance timer - */ - g_hBalanceTimer = CreateTimer(float(g_iBalanceDelay), Timer_BalanceTeams, _, TIMER_FLAG_NO_MAPCHANGE); - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Teams are unbalanced. Balance delay timer started."); - } -} - -stock StartALivingPlayerTimer() -{ - - /** - Start a timer to check living players - */ - if (g_hLivingPlayerCheckTimer != INVALID_HANDLE) - { - - /** - If we for some reason already have one started, stop it. - */ - CloseHandle(g_hLivingPlayerCheckTimer); - g_hLivingPlayerCheckTimer = INVALID_HANDLE; - } - - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Living player balance delay timer started."); - } - g_hLivingPlayerCheckTimer = CreateTimer(float(g_iLivingPlayerCheckDelay), Timer_LivingPlayerCheck, _, TIMER_FLAG_NO_MAPCHANGE); -} - -stock FindSwitchablePlayer() -{ - - /** - Start a loop to find a switchable player - */ - new iPlayer; - new iBiggerTeam = GetBiggerTeam(); - for (new i = 1; i <= MaxClients; i++) - { - - /** - Check the stock function to see if we are allows to even switch the player - */ - if (!IsSwitchablePlayer(i, iBiggerTeam)) - { - continue; - } - - /** - If the mod is TF2 and they have Priority Players set check if the client has buildings or an uber - */ - if (g_CurrentMod == GameType_TF && g_bPriorityPlayers) - { - if (HasUber(i) || HasBuildingsBuilt(i)) - { - continue; - } - } - - /** - So far we are able we switch this player - Now we check the buddy system - */ - if (g_bBuddyEnabled) - { - - /** - Buddy system is enabled, check to see if client has buddy - */ - if (SM_GetClientBuddy(i) != 0) - { - - /** - The client has a buddy, so we check to see if they are on same team - */ - if (GetClientTeam(i) == GetClientTeam(SM_GetClientBuddy(i))) - { - - /** - They are, so we continue to next client - */ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] With a balance in progress a buddy on the right team was found and skipped."); - } - continue; - } - else - { - - /** - They are not on the same team, set this client - The buddy could be in spec, and that would make it not matter where he is, or the buddy is on the smaller team - */ - iPlayer = i; - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] With a balance in progress a buddy on the wrong team was found."); - } - break; - } - } - else - { - - /** - The client does not have a buddy, set this client - */ - iPlayer = i; - break; - } - } - else - { - - /** - Buddy system is not enabled, set this client - */ - iPlayer = i; - break; - } - } - - /** - Return the client we set, this could be 0, but very unlikely - */ - return iPlayer; -} - -stock BalancePlayer(iClient, iTeam) -{ - new Handle:hPack = CreateDataPack(); - WritePackCell(hPack, iClient); - WritePackCell(hPack, iTeam); - CreateTimer(0.1, Timer_BalancePlayer, hPack, TIMER_FLAG_NO_MAPCHANGE); -} - -stock CleanUp(iClient) -{ - g_aPlayers[iClient][bFlagCarrier] = false; - g_aPlayers[iClient][bSwitched] = false; - if (g_aPlayers[iClient][hForcedTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hForcedTimer]); - g_aPlayers[iClient][hForcedTimer] = INVALID_HANDLE; - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] Forced player disconnected, killing timer."); - } - } - if (g_aPlayers[iClient][hBalanceTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hBalanceTimer]); - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] Living player set to be balanced disconnected, killing timer."); - } - } -} - -stock GetSmallerTeam() -{ - - /** - Get the count of players on each team - */ - new iCountT1 = GetTeamClientCount(g_aCurrentTeams[Team1]); - new iCountT2 = GetTeamClientCount(g_aCurrentTeams[Team2]); - - /** - Return the smaller team - */ - if (iCountT1 < iCountT2) - { - return g_aCurrentTeams[Team1]; - } - else if (iCountT1 > iCountT2) - { - return g_aCurrentTeams[Team2]; - } - return 0; -} - -stock GetBiggerTeam() -{ - - /** - Get the count of players on each team - */ - new iCountT1 = GetTeamClientCount(g_aCurrentTeams[Team1]); - new iCountT2 = GetTeamClientCount(g_aCurrentTeams[Team2]); - - /** - Return the bigger team - */ - if (iCountT1 > iCountT2) - { - return g_aCurrentTeams[Team1]; - } - else if (iCountT1 < iCountT2) - { - return g_aCurrentTeams[Team2]; - } - return 0; -} - -stock SetGameCvars() -{ - if (g_bConVarControl && g_bIsEnabled) - { - if (stb_mp_autoteambalance != INVALID_HANDLE) - { - SetConVarInt(stb_mp_autoteambalance, 0); - } - if (stb_mp_teams_unbalance_limit != INVALID_HANDLE) - { - SetConVarInt(stb_mp_teams_unbalance_limit, g_iUnbalanceLimit); - } - } -} - -/* TIMER FUNCTIONS */ - -public Action:Timer_ChangeTeamBalanceDelay(Handle:timer, any:data) -{ - - /** - Finally start one if it's still unbalanced - */ - if (IsUnbalanced() && !g_bBalanceInProgress) - { - StartABalance(); - } -} - -public Action:Timer_BalanceTeams(Handle:timer, any:data) -{ - - /** - See if we still need to balance the teams - */ - if (!IsUnbalanced() || !OkToBalance()) - { - - /** - We don't, kill the balance - */ - g_bBalanceInProgress = false; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Balance delay timer was not needed and died."); - } - g_hBalanceTimer = INVALID_HANDLE; - return Plugin_Handled; - } - - /** - We still need to balance the teams - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Teams are still unbalanced. Balance is now in progress."); - } - g_bBalanceInProgress = true; - - - /** - Check if we are allowed to scan living players - */ - if (!g_bDeadOnly) - { - - /** - We are allowed to, so we start a timer - */ - StartALivingPlayerTimer(); - - /** - Also report that we are now scanning dead players as well - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Now scanning dead players."); - } - } - else - { - - /** - We are not allowed to, so report that we are only scanning dead players - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Only scanning dead players."); - } - } - - g_hBalanceTimer = INVALID_HANDLE; - return Plugin_Handled; -} - -public Action:Timer_LivingPlayerCheck(Handle:timer, any:data) -{ - - /** - Check to see if we still need to balance the teams - */ - if (!IsUnbalanced() || !OkToBalance()) - { - - /** - We don't, kill it and bug out - */ - g_bBalanceInProgress = false; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Living player balance delay timer was not needed and died."); - } - g_hLivingPlayerCheckTimer = INVALID_HANDLE; - return Plugin_Handled; - } - - /** - Call the stock function to find a player we can switch - */ - new iPlayer = FindSwitchablePlayer(); - - /** - Check to see if we found a player - */ - if (iPlayer == 0) - { - - /** - In the unlikely event that the stock function didn't return a player - Start a loop to find a random player - */ - new iBiggerTeam = GetBiggerTeam(); - do - { - iPlayer = GetRandomInt(1, MaxClients); - } while (!IsSwitchablePlayer(iPlayer, iBiggerTeam)); - - if (g_bLogActivity) - { - LogAction(0, iPlayer, "[STB] Found a random living player."); - } - } - else - { - if (g_bLogActivity) - { - LogAction(0, iPlayer, "[STB] Found a living player."); - } - } - - /** - Now that we have a player assigned them to the smaller team - */ - new iSmallerTeam = GetSmallerTeam(); - SM_SetForcedTeam(iPlayer, iSmallerTeam, true); - - /** - Let the player know we could be switching him soon - */ - PrintHintText(iPlayer, "%T", "PlayerMessage", LANG_SERVER, g_iLivingPlayerSwitchDelay); - if (g_bLogActivity) - { - LogAction(0, iPlayer, "[STB] Living player placed on a timer."); - } - - /** - Create a timer to switch the player - */ - g_aPlayers[iPlayer][hBalanceTimer] = CreateTimer(float(g_iLivingPlayerSwitchDelay), Timer_LivingPlayerBalance, iPlayer, TIMER_FLAG_NO_MAPCHANGE); - - /** - Reset the timer handle - */ - g_hLivingPlayerCheckTimer = INVALID_HANDLE; - - /** - We are done, bug out - */ - return Plugin_Handled; -} - -public Action:Timer_LivingPlayerBalance(Handle:timer, any:iClient) -{ - - /** - Check to make sure we still need to balance - */ - if (!IsUnbalanced() || !OkToBalance()) - { - - /** - We don't need to balance, bug out - */ - g_bBalanceInProgress = false; - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - SM_ClearForcedTeam(iClient); - return Plugin_Handled; - } - - /** - We still need to balance, lets make sure we can still balance this player - */ - if (!IsClientConnected(iClient) || g_aPlayers[iClient][bFlagCarrier]) - { - g_bBalanceInProgress = false; - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - SM_ClearForcedTeam(iClient); - if (g_bLogActivity) - { - if (g_aPlayers[iClient][bFlagCarrier]) - { - LogAction(0, iClient, "[STB] Living player became flag carrier, balance restarted."); - } - else - { - LogAction(0, iClient, "[STB] Living player timer was not needed and died."); - } - } - return Plugin_Handled; - } - - /** - Clear to balance this player, so do it - */ - BalancePlayer(iClient, SM_GetForcedTeam(iClient)); - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] Living player was switched."); - } - - /** - We are done, bug out - */ - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - return Plugin_Handled; -} - -public Action:Timer_BalancePlayer(Handle:timer, Handle:pack) -{ - - /** - Rest the datapack and load the variables - */ - ResetPack(pack); - new iClient = ReadPackCell(pack); - new iUnBalancedTeam = ReadPackCell(pack); - - /** - We are done with you now - */ - CloseHandle(pack); - - /** - Check the team and make sure its a valid team - */ - if(!SM_IsValidTeam(iUnBalancedTeam)) - { - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] Balance failed due to invalid team number %i", iUnBalancedTeam); - } - return Plugin_Handled; - } - - /** - Use our core function to change the clients team - */ - SM_MovePlayer(iClient, iUnBalancedTeam); - - return Plugin_Handled; -} - -public Action:Timer_RoundStart(Handle:timer, any:data) -{ - g_bRoundStart = false; - if (OkToBalance() && IsUnbalanced() && !g_bBalanceInProgress) - { - StartABalance(); - } - return Plugin_Handled; -} - -public Action:Timer_ForcedExpired(Handle:timer, any:iClient) -{ - SM_ClearForcedTeam(iClient); - g_aPlayers[iClient][bSwitched] = false; - g_aPlayers[iClient][hForcedTimer] = INVALID_HANDLE; - return Plugin_Handled; -} - -public Action:Timer_WelcomeAdvert(Handle:timer, any:iClient) -{ - if (IsClientConnected(iClient) && IsClientInGame(iClient)) - { - PrintToChat (iClient, "\x01\x04[STB]\x01 %T", "BuddyWelcomeMsg1", LANG_SERVER); - PrintToChat (iClient, "\x01\x04[STB]\x01 %T", "BuddyWelcomeMsg2", LANG_SERVER); - PrintToChat (iClient, "\x01\x04[STB]\x01 %T", "BuddyWelcomeMsg3", LANG_SERVER); - } - return Plugin_Handled; -} - -/* CONSOLE VARIABLE CHANGE EVENT */ - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (convar == stb_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsEnabled = false; - PrintToChatAll("[SM] %T", "Disabled", LANG_SERVER); - LogAction(0, -1, "[SimpleTeamBalancer] Disabled"); - } - else - { - g_bIsEnabled = true; - SetGameCvars(); - PrintToChatAll("[SM] %T", "Enabled", LANG_SERVER); - LogAction(0, -1, "[SimpleTeamBalancer] Enabled"); - } - } - else if (convar == stb_logactivity) - { - if (StringToInt(newValue) == 0) - { - g_bLogActivity = false; - LogAction(0, -1, "[STB] Log Activity DISABLED."); - } - else - { - g_bLogActivity = true; - LogAction(0, -1, "[STB] Log Activity ENABLED."); - } - } - else if (convar == stb_logactivity2) - { - if (StringToInt(newValue) == 0) - { - g_bLogActivity2 = false; - LogAction(0, -1, "[STB] Detailed Log Activity DISABLED."); - } - else - { - g_bLogActivity2 = true; - LogAction(0, -1, "[STB] Detailed Log Activity ENABLED."); - } - } - else if (convar == stb_convarcontrol) - { - if (StringToInt(newValue) == 0) - { - g_bConVarControl = false; - } - else - { - g_bConVarControl = true; - SetGameCvars(); - } - } - else if (convar == stb_deadonly) - { - if (StringToInt(newValue) == 0) - { - g_bDeadOnly = false; - } - else - { - g_bDeadOnly = true; - } - } - else if (convar == stb_priorityenabled) - { - if (StringToInt(newValue) == 0) - { - g_bPriorityPlayers = false; - } - else - { - g_bPriorityPlayers = true; - } - } - else if (convar == stb_buddyenabled) - { - if (StringToInt(newValue) == 0) - { - g_bBuddyEnabled = false; - } - else - { - g_bBuddyEnabled = true; - } - } - else if (convar == stb_buddyrestriction) - { - if (StringToInt(newValue) == 0) - { - g_bBuddyRestriction = false; - } - else - { - g_bBuddyRestriction = true; - } - } - else if (convar == stb_unbalancelimit) - { - g_iUnbalanceLimit = StringToInt(newValue); - SetGameCvars(); - } - else if (convar == stb_balancedelay) - { - g_iBalanceDelay = StringToInt(newValue); - } - else if (convar == stb_roundstartdelay) - { - g_iRoundStartDelay = StringToInt(newValue); - } - else if (convar == stb_livingplayerswitchdelay) - { - g_iLivingPlayerSwitchDelay = StringToInt(newValue); - } - else if (convar == stb_livingplayercheckdelay) - { - g_iLivingPlayerCheckDelay = StringToInt(newValue); - } - else if (convar == stb_uberlevel) - { - g_fUberLevel = StringToFloat(newValue); - } - else if (convar == stb_switchbackforced) - { - g_iSwitchBackForced = StringToInt(newValue); - } - else if (convar == stb_adminflag) - { - SetConVarString(stb_adminflag, newValue); - } - else if (convar == stb_mp_autoteambalance) - { - SetGameCvars(); - } - else if (convar == stb_mp_teams_unbalance_limit) - { - SetGameCvars(); - } -} - -/* MENU CODE */ - -stock Handle:BuildPlayerMenu() -{ - new Handle:menu = CreateMenu(Menu_SelectPlayer); - AddTargetsToMenu(menu, 0, true, false); - SetMenuTitle(menu, "Select A Player:"); - SetMenuExitButton(menu, true); - return menu; -} - -public Menu_SelectPlayer(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - new buddy = GetClientOfUserId(StringToInt(sSelection)); - if (param1 == buddy) { - PrintHintText(param1, "%T", "SelectSelf", LANG_SERVER); - } else if (!IsClientInGame(buddy)) { - PrintHintText(param1, "%T", "BuddyGone", LANG_SERVER); - } else { - decl String:cName[128]; - decl String:bName[128]; - GetClientName(param1, cName, sizeof(cName)); - GetClientName(buddy, bName, sizeof(bName)); - if (!SM_IsBuddyLocked(buddy)) { - SM_AssignBuddy(param1, buddy); - PrintHintText(param1, "%T", "BuddyMsg", LANG_SERVER, bName); - PrintHintText(buddy, "%T", "BuddyMsg", LANG_SERVER, cName); - } else - PrintHintText(param1, "%T", "PlayerLockedBuddyMsg", LANG_SERVER, bName); - } - } else if (action == MenuAction_End) { - CloseHandle(menu); - } -} \ No newline at end of file diff --git a/Simple AutoScrambler/addons/sourcemod/scripting/simple-teammanager.sp b/Simple AutoScrambler/addons/sourcemod/scripting/simple-teammanager.sp deleted file mode 100644 index 008f443..0000000 --- a/Simple AutoScrambler/addons/sourcemod/scripting/simple-teammanager.sp +++ /dev/null @@ -1,1351 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Team Manager -Description: - Manges players and their team - Admin menu integration - Allows admins/donators to swap their teams (clears force)* - Allows admins to move players to a team (forced\unforced)* - Allows admins to scramble the teams* - *Works with Simple Team Balancer (if installed) -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include - -#define PLUGIN_VERSION "2.1.$Rev$" -#define VOTE_YES "##YES##" -#define VOTE_NO "##NO##" - -enum PlayerData -{ - iNewTeam, - bool:bQueue -}; - -new Handle:stm_enabled = INVALID_HANDLE; -new Handle:stm_logactivity = INVALID_HANDLE; -new Handle:stm_adminflag_swapteam = INVALID_HANDLE; -new Handle:stm_adminflag_moveplayer = INVALID_HANDLE; -new Handle:stm_adminflag_scramble = INVALID_HANDLE; -new Handle:stm_scrambledelay = INVALID_HANDLE; -new Handle:stm_voteenabled = INVALID_HANDLE; -new Handle:stm_votewin = INVALID_HANDLE; -new Handle:stm_votedelay = INVALID_HANDLE; -new Handle:stm_mp_bonusroundtime = INVALID_HANDLE; -new Handle:g_hAdminMenu = INVALID_HANDLE; -new Handle:g_hTimerPrepScramble = INVALID_HANDLE; -new Handle:g_hTimerClearScrambleForce = INVALID_HANDLE; - -new g_aPlayers[MAXPLAYERS + 1][PlayerData]; - -new bool:g_bIsEnabled = true; -new bool:g_bVoteEnabled = true; -new bool:g_bLogActivity = true; -new bool:g_bScrambleRoundEnd = false; -new g_iVoteDelay, g_iLastVoteTime, g_iTimeLeft; -new Float:g_fScrambleDelay, Float:g_fVoteWin; - -public Plugin:myinfo = -{ - name = "Simple Team Manager", - author = "Simple Plugins", - description = "Manages players and thier team.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -public OnPluginStart() -{ - - /** - Need to create all of our console variables. - */ - CreateConVar("stm_version", PLUGIN_VERSION, "Simple Team Manager Version",FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - stm_enabled = CreateConVar("stm_enabled", "1", "Enable or Disable Simple Team Manager", _, true, 0.0, true, 1.0); - stm_logactivity = CreateConVar("stm_logactivity", "0", "Enable or Disable the disaplying of events in the log", _, true, 0.0, true, 1.0); - stm_adminflag_swapteam = CreateConVar("stm_adminflag_swapteam", "a", "Admin flag to use for the swapteam command. Must be a in char format."); - stm_adminflag_moveplayer = CreateConVar("stm_adminflag_moveplayer", "c", "Admin flag to use for the moveplayer command. Must be a in char format."); - stm_adminflag_scramble = CreateConVar("stm_adminflag_scramble", "c", "Admin flag to use for the scrambleteam command. Must be a in char format."); - stm_scrambledelay = CreateConVar("stm_scrambledelay", "15", "Delay to scramble teams"); - stm_voteenabled = CreateConVar("stm_voteenabled", "1", "Enable or Disable voting to scramble the teams", _, true, 0.0, true, 1.0); - stm_votewin = CreateConVar("stm_votewin", "0.45", "Win percentage vote must win by", _, true, 0.0, true, 1.0); - stm_votedelay = CreateConVar("stm_votedelay", "600", "Delay before another vote can be cast"); - stm_mp_bonusroundtime = FindConVar("mp_bonusroundtime"); - - - /** - Need deal with changes to the console variables after the plugin is loaded. - We could not do this and just call the actual console variable each time we need it, but it's not efficent. - */ - HookConVarChange(stm_enabled, ConVarSettingsChanged); - HookConVarChange(stm_logactivity, ConVarSettingsChanged); - HookConVarChange(stm_scrambledelay, ConVarSettingsChanged); - HookConVarChange(stm_voteenabled, ConVarSettingsChanged); - HookConVarChange(stm_votewin, ConVarSettingsChanged); - HookConVarChange(stm_votedelay, ConVarSettingsChanged); - - /** - Need to register the commands we are going to create and use. - */ - RegConsoleCmd("sm_swapteam", Command_SwapTeam, "sm_swapteam <[0]instant/[1]queued>: Swaps your team to the other team"); - RegConsoleCmd("sm_moveplayer", Command_MovePlayer, "sm_moveplayer <[0]instant/[1]ondeath> <[0]unforced/[1]forced>: Moves a player to the specified team"); - RegConsoleCmd("sm_scrambleteams", Command_ScrambleTeams, "sm_scrambleteams: <[0]now/[1]roundend> <[0]dontrestart/[1]restartround> Scrambles the current teams"); - RegConsoleCmd("sm_votescramble", Command_VoteScramble, "sm_votescramble: Starts a vote to scramble the teams"); - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[STM] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_death", HookPlayerDeath, EventHookMode_Post); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Post); - switch (g_CurrentMod) - { - case GameType_TF: - { - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - } - case GameType_DOD: - { - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_Post); - } - default: - { - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - - /** - Now we have to deal with the admin menu. If the admin library is loaded call the function to add our items. - */ - new Handle:gTopMenu; - if (LibraryExists("adminmenu") && ((gTopMenu = GetAdminTopMenu()) != INVALID_HANDLE)) - { - OnAdminMenuReady(gTopMenu); - } - - /** - Load translations and .cfg file - */ - LoadTranslations ("simpleteammanager.phrases"); - AutoExecConfig(true, "plugin.simpleteammanager"); - LogAction(0, -1, "[STM] Simple Team Manager is loaded."); -} - -public OnAllPluginsLoaded() -{ - //something -} - -public OnLibraryRemoved(const String:name[]) -{ - if (StrEqual(name, "adminmenu")) - { - - /** - Looks like the admin menu was removed. Set the global. - */ - g_hAdminMenu = INVALID_HANDLE; - } - else if (StrEqual(name, "simpleplugins")) - { - SetFailState("Required plugin Simple SourceMod Plugins Core was removed."); - } -} - -public OnConfigsExecuted() -{ - - /** - Once we loaded up all the console variables from the config file, lets now set all the global variables we will use. - */ - g_bIsEnabled = GetConVarBool(stm_enabled); - g_bLogActivity = GetConVarBool(stm_logactivity); - g_fScrambleDelay = GetConVarFloat(stm_scrambledelay); - g_iVoteDelay = GetConVarInt(stm_votedelay); - g_fVoteWin = GetConVarFloat(stm_votewin); - g_iLastVoteTime = RoundFloat(GetEngineTime()); - g_bScrambleRoundEnd = false; - g_hTimerClearScrambleForce = INVALID_HANDLE; - - /** - Report enabled - */ - if (g_bIsEnabled) - { - LogAction(0, -1, "[STM] Simple Team Manager is ENABLED."); - } - else - { - LogAction(0, -1, "[STM] Simple Team Manager is DISABLED."); - } - - if (g_bLogActivity) - { - LogAction(0, -1, "[STM] Log Activity ENABLED."); - } - else - { - LogAction(0, -1, "[STM] Log Activity DISABLED."); - } -} - -/* COMMANDS */ - -public Action:Command_SwapTeam(client, args) -{ - - /** - Make sure we are enabled, if not bug out. - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - If this was ran from the console bug out. - */ - if (client == 0) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure the client is authorized to run this command. - */ - decl String:sFlags[5]; - GetConVarString(stm_adminflag_swapteam, sFlags, sizeof(sFlags)); - if (!SM_IsValidAdmin(client, sFlags)) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Lets make sure the client is one a team we can swap. - If he is we set the global array to the opposite team. - */ - new iTeam = GetClientTeam(client); - if (iTeam == g_aCurrentTeams[Team1]) - { - g_aPlayers[client][iNewTeam] = g_aCurrentTeams[Team2]; - } - else if (iTeam == g_aCurrentTeams[Team2]) - { - g_aPlayers[client][iNewTeam] = g_aCurrentTeams[Team1]; - } - else - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "InValidTeam", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check to see if we have command arguments. - */ - if (GetCmdArgs()) - { - - /** - We do, so lets get it and see if the client wants to be switched instantly or queued for death. - */ - decl String:sArg[5]; - GetCmdArg(1, sArg, sizeof(sArg)); - new iWantsQue = StringToInt(sArg); - if (iWantsQue && !g_aPlayers[client][bQueue]) - { - - /** - He wants the que and isn't already in it, set the global array. - */ - g_aPlayers[client][bQueue] = true; - ReplyToCommand(client, "\x01\x04[STM]\x01 %T", "PlayerQueue", LANG_SERVER); - } - else if (!iWantsQue) - { - - /** - He wants to be switched right now, lets call the stock function. - */ - SM_MovePlayer(client, g_aPlayers[client][iNewTeam]); - } - } - else - { - - /** - There are no command arguments so we build and display the swap menu. - */ - DisplaySwapModeMenu(client, client); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_MovePlayer(client, args) -{ - - /** - Make sure we are enabled, if not bug out. - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the client is authorized to run this command. - */ - decl String:sFlags[5]; - GetConVarString(stm_adminflag_moveplayer, sFlags, sizeof(sFlags)); - if (!SM_IsValidAdmin(client, sFlags)) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check to see if we have command arguments. - */ - new iCmdArgs = GetCmdArgs(); - if (iCmdArgs == 0) - { - - /** - We don't. Build the player menu, display it, and bug out. - */ - DisplayPlayerMenu(client); - return Plugin_Handled; - } - - /** - Check the first argument - If should be a players name or userid. - */ - decl String:sPlayer[64]; - GetCmdArg(1, sPlayer, sizeof(sPlayer)); - new iPlayerIndex = FindTarget(client, sPlayer, true, true); - if (iPlayerIndex == -1 || !IsClientInGame(iPlayerIndex)) - { - - /** - We don't know who this is. Build the player menu, display it, and bug out. - */ - DisplayPlayerMenu(client); - return Plugin_Handled; - } - - /** - We have figured out the first argument, lets check the second. - If should be the team the client wants to put the player on. - */ - if (iCmdArgs >= 2) - { - - /** - We have a command argument at least, lets see if we can identify the team. - */ - decl String:sTeam[24]; - GetCmdArg(2, sTeam, sizeof(sTeam)); - - new iTeam = StringToInt(sTeam); - if (SM_IsValidTeam(iTeam)) - { - - /** - It's a vaild team so lets set the global array to the new team. - */ - g_aPlayers[iPlayerIndex][iNewTeam] = iTeam; - } - else - { - - /** - It's not a vaild team so set the menu to display to the team menu. - */ - DisplayTeamMenu(client, iPlayerIndex); - return Plugin_Handled; - } - } - else - { - /** - We were not given a team, display the team menu. - */ - DisplayTeamMenu(client, iPlayerIndex); - return Plugin_Handled; - } - - /** - Check to see if we were given any more command arguments and found a team. - */ - if (iCmdArgs < 3) - { - - /** - No more command arguments and found a team. - Now lets check to see if the player is a spectator. If he is there is no reason to ask if it's instant or on death... he can't die. - */ - if (!IsClientObserver(iPlayerIndex)) - { - - /** - Not a spectator so display the swapmode menu. - */ - DisplaySwapModeMenu(client, iPlayerIndex); - } - else - { - - /** - The player is a spectator. - We make sure the player is not set to switch on death, since a spec can't die. - */ - g_aPlayers[iPlayerIndex][bQueue] = false; - } - } - - /** - We have figured out the second argument, lets check the third. - If should be the how the client wants to move the player: instant/on death. - */ - if (iCmdArgs >= 3) - { - - /** - The client gave us a command argument, lets check it. - */ - decl String:sSwapMode[5]; - GetCmdArg(3, sSwapMode, sizeof(sSwapMode)); - new iWantsQue = StringToInt(sSwapMode); - if (iWantsQue) - { - - /** - The client wants to que the player, set the global array. - */ - g_aPlayers[iPlayerIndex][bQueue] = true; - } - else - { - - /** - The client doesn't want to que the player, set the global array. - */ - g_aPlayers[iPlayerIndex][bQueue] = false; - } - } - else - { - /** - No swapmode argument, display the menu - */ - DisplaySwapModeMenu(client, iPlayerIndex); - } - - if (iCmdArgs >= 4) - { - - /** - Since we are compiling for Simple Team Balancer, and given a 4th argument, lets check it. - If should be the if the client wants to force the player to that team. - */ - decl String:sPlayerForced[5]; - GetCmdArg(4, sPlayerForced, sizeof(sPlayerForced)); - new iForceHim = StringToInt(sPlayerForced); - if (iForceHim) - { - - /** - The client wants to force the player - */ - SM_SetForcedTeam(iPlayerIndex, g_aPlayers[iPlayerIndex][iNewTeam]); - } - else - { - - /** - The client doesn't want to force the player - */ - SM_ClearForcedTeam(iPlayerIndex); - } - } - else - { - - } - - /** - We found and processed all the arguments. - */ - if (!IsPlayerAlive(iPlayerIndex)) - { - - /** - The player is not alive or died during this process so we just move him. - */ - SM_MovePlayer(iPlayerIndex, g_aPlayers[iPlayerIndex][iNewTeam]); - } - else - { - if (!g_aPlayers[iPlayerIndex][bQueue]) - { - - /** - The player is alive and is not set to be queued so we just move him. - */ - SM_MovePlayer(iPlayerIndex, g_aPlayers[iPlayerIndex][iNewTeam]); - } - } - - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_ScrambleTeams(client, args) -{ - - /** - Make sure we are enabled, if not bug out. - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the client is authorized to run this command. - */ - decl String:sFlags[5]; - GetConVarString(stm_adminflag_scramble, sFlags, sizeof(sFlags)); - if (!SM_IsValidAdmin(client, sFlags)) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check if a scramble timer was already called, if so close it down. - */ - if (g_hTimerPrepScramble != INVALID_HANDLE) - { - CloseHandle(g_hTimerPrepScramble); - g_hTimerPrepScramble = INVALID_HANDLE; - } - - /** - Check if we have any command arguments. - If we don't we display the scramble menu and bug out. - */ - new iCmdArgs = GetCmdArgs(); - if (iCmdArgs == 0) - { - DisplayScrambleMenu(client); - return Plugin_Handled; - } - - /** - We have a command argument. - It should be whether or not to scramble at round end. - */ - decl String:sRoundEnd[5]; - GetCmdArg(1, sRoundEnd, sizeof(sRoundEnd)); - if (StringToInt(sRoundEnd)) - { - /** - The client wants to scramble at round end so we set the global bool. - */ - g_bScrambleRoundEnd = true; - } - else - { - g_bScrambleRoundEnd = false; - } - - /** - Check for another command argument. - It should be whether or not to restart the round. - */ - decl String:sRestartRound[5]; - new bool:bRestartRound = false; - GetCmdArg(1, sRestartRound, sizeof(sRestartRound)); - if (StringToInt(sRestartRound)) - { - bRestartRound = true; - } - - /** - Now we start the scramble timer. - */ - StartScrambleTimer(_, bRestartRound); - - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_VoteScramble(client, args) -{ - - /** - Make sure we are enabled, if not bug out. - */ - if (!g_bVoteEnabled || !g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Make sure there is a vote in progress, if so bug out. - */ - if (IsVoteInProgress()) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "VoteInProgress", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure enough time has passed since the last vote. - */ - new iVoteTime = RoundFloat(GetEngineTime()); - if (iVoteTime - g_iLastVoteTime <= g_iVoteDelay) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "ScrambleTime", LANG_SERVER); - return Plugin_Handled; - } - - /** - Enough time has passed so reset the global vote time to now. - */ - g_iLastVoteTime = iVoteTime; - - /** - Build the vote menu and send it to everyone. - */ - new Handle:hMenu = CreateMenu(Menu_VoteScramble); - SetMenuTitle(hMenu, "Scramble Teams?"); - AddMenuItem(hMenu, VOTE_YES, "Yes"); - AddMenuItem(hMenu, VOTE_NO, "No"); - SetMenuExitButton(hMenu, false); - VoteMenuToAll(hMenu, 20); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -/* HOOKED EVENTS */ - -public HookPlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Find out who died. - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - - /** - Find out how the client died. - */ - new String:sWeapon[64]; - GetEventString(event, "weapon", sWeapon, sizeof(sWeapon)); - if (StrEqual(sWeapon, "world", false)) - { - - /** - He died because he changed teams so cleanup and bug out. - */ - s_CleanUp(iClient); - return; - } - - /** - Find out if this player was queued to change teams. - */ - if (g_aPlayers[iClient][bQueue]) - { - /** - Looks like he was, so call the stock function to move him. - */ - SM_MovePlayer(iClient, g_aPlayers[iClient][iNewTeam]); - } -} - -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Find out who changed teams. - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - - /** - If he was queued to switch teams we cleanup the variables. The client did it themself. - */ - if (g_aPlayers[iClient][bQueue]) - { - s_CleanUp(iClient); - } -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get the amount of time left in the map. - */ - new iTimeLeft; - GetMapTimeLeft(iTimeLeft); - - /** - Check to see if we are supposed to scramble at the end of the round and that there is enough time left in the map. - */ - if (g_bScrambleRoundEnd && iTimeLeft >= 60) - { - - /** - Check to see if there is a scramble timer in action and if so close it down. - */ - if (g_hTimerPrepScramble != INVALID_HANDLE) - { - CloseHandle(g_hTimerPrepScramble); - g_hTimerPrepScramble = INVALID_HANDLE; - } - - /** - Determine the round end chat time and run the scramble 1 second before it ends. - */ - new Float:fDelay = GetConVarFloat(stm_mp_bonusroundtime); - fDelay -= 1.0; - StartScrambleTimer(fDelay); - } -} - -public OnClientPostAdminCheck(client) -{ - - /** - Determine if the client has the flag to use the swapteam command. - */ - decl String:sFlags[5]; - GetConVarString(stm_adminflag_swapteam, sFlags, sizeof(sFlags)); - if (SM_IsValidAdmin(client, sFlags)) - { - /** - The client does so lets create a timer to run an advertise to tell him about it. - */ - CreateTimer (60.0, Timer_WelcomeAdvert, client); - } -} - -public OnClientDisconnect(client) -{ - - /** - Cleanup the clients variables. - */ - s_CleanUp(client); -} - -public SM_OnPlayerMoved(Handle:plugin, client, team) -{ - - /** - Make sure we called the move function - */ - if (plugin != GetMyHandle()) - { - if (g_bLogActivity) - { - LogAction(0, client, "[STM] Callback was not started with current plugin, bugging out."); - } - return; - } - - decl String:sPlayerName[64]; - GetClientName(client, sPlayerName, sizeof(sPlayerName)); - - PrintToChat(client, "\x01\x04[SM]\x01 %T", "PlayerSwitched", LANG_SERVER); - - s_CleanUp(client); -} - -/* TIMER FUNCTIONS */ - -public Action:Timer_PrepTeamScramble(Handle:timer, any:data) -{ - new bool:bRestartRound = data; - /** - Call the scramble the teams stock function. - */ - PrepTeamScramble(bRestartRound); - - /** - Reset the timer handle so we know the timer is done. - */ - g_hTimerPrepScramble = INVALID_HANDLE; - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Timer_ScrambleTheTeams(Handle:timer, any:data) -{ - new iPlayers[MAXPLAYERS + 1]; - new iCount, i, bool:bTeam, bool:bRestartRound = data; - - /** - Get all the client index numbers of valid players - */ - for(i = 1; i <= MaxClients; i++) - { - if(IsClientInGame(i)) // && !IsFakeClient(i)) - { - iPlayers[iCount++] = i; - } - } - - /** - Randomly sort the players - */ - SortIntegers(iPlayers, iCount, Sort_Random); - - /** - Loop through all the players and assign each one to a team, alternating each time - */ - for(i = 0; i < iCount; i++) - { - if (!bRestartRound) - { - /** - We didn't want to restart the round, so we move them to spec 1 at a time. - */ - SM_MovePlayer(iPlayers[i], g_aCurrentTeams[Spectator]); - } - SM_MovePlayer(iPlayers[i], bTeam ? g_aCurrentTeams[Team2] : g_aCurrentTeams[Team1]); - SM_SetForcedTeam(iPlayers[i], bTeam ? g_aCurrentTeams[Team2] : g_aCurrentTeams[Team1], true); - bTeam = !bTeam; - } - - /** - Reset this variable since we completed a scramble - */ - g_bScrambleRoundEnd = false; - - if (g_hTimerClearScrambleForce != INVALID_HANDLE) - { - CloseHandle(g_hTimerClearScrambleForce); - g_hTimerClearScrambleForce = INVALID_HANDLE; - } - - g_hTimerClearScrambleForce = CreateTimer(300.0, Timer_ClearScrambleForce, _, TIMER_FLAG_NO_MAPCHANGE); - - ServerCommand("mp_timelimit %i", g_iTimeLeft / 60); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Timer_ClearScrambleForce(Handle:timer, any:data) -{ - - for(new i = 1; i <= MaxClients; i++) - { - if(IsClientInGame(i)) // && !IsFakeClient(i)) - { - SM_ClearForcedTeam(i); - PrintToChat(i, "\x01\x04[SM]\x01 Your forced team status has been cleared"); - } - } - - g_hTimerClearScrambleForce = INVALID_HANDLE; - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Timer_WelcomeAdvert(Handle:timer, any:client) -{ - - /** - Lets make sure the client is connected and actually in the game. - */ - if (IsClientConnected(client) && IsClientInGame(client)) - { - - /** - We are good to go so lets tell him about the swapteam command. - */ - PrintToChat (client, "\x01\x04[STM]\x01 %T", "SwapTeamMsg", LANG_SERVER); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -/* STOCK FUNCTIONS */ - -stock s_CleanUp(iClient) -{ - - /** - Reset all the client variables - */ - g_aPlayers[iClient][bQueue] = false; - g_aPlayers[iClient][iNewTeam] = 0; -} - -stock StartScrambleTimer(Float:fdelay = 0.0, bool:bRestartRound = false) -{ - if (fdelay == 0.0) - { - fdelay = g_fScrambleDelay; - } - if (g_hTimerPrepScramble != INVALID_HANDLE) - { - CloseHandle(g_hTimerPrepScramble); - g_hTimerPrepScramble = INVALID_HANDLE; - } - PrintCenterTextAll("%T", "Scramble", LANG_SERVER); - g_hTimerPrepScramble = CreateTimer(fdelay, Timer_PrepTeamScramble, bRestartRound, TIMER_FLAG_NO_MAPCHANGE); -} - -stock PrepTeamScramble(bool:bRestartRound = false) -{ - new iPlayers[MAXPLAYERS + 1]; - new iCount; - - GetMapTimeLeft(g_iTimeLeft); - - if (bRestartRound) - { - - for(new i = 1; i <= MaxClients; i++) - { - if(IsClientInGame(i)) - // && !IsFakeClient(i)) - { - iPlayers[iCount++] = i; - SM_ClearForcedTeam(i); - SM_ClearBuddy(i); - SM_MovePlayer(i, g_aCurrentTeams[Spectator]); - } - } - } - else - { - //Can't move them all to spec at the same time - for(new i = 1; i <= MaxClients; i++) - { - if(IsClientInGame(i)) - // && !IsFakeClient(i)) - { - iPlayers[iCount++] = i; - SM_ClearForcedTeam(i); - SM_ClearBuddy(i); - //SM_MovePlayer(i, g_aCurrentTeams[Spectator]); - } - } - } - CreateTimer(4.0, Timer_ScrambleTheTeams, bRestartRound, TIMER_FLAG_NO_MAPCHANGE); -} - -/* CONSOLE VARIABLE CHANGE EVENT */ - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (convar == stm_enabled) { - if (StringToInt(newValue) == 0) { - g_bIsEnabled = false; - LogAction(0, -1, "[STM] Simple Team Manager is loaded and disabled."); - } else { - g_bIsEnabled = true; - LogAction(0, -1, "[STM] Simple Team Manager is loaded and enabled."); - } - } - else if (convar == stm_logactivity) { - if (StringToInt(newValue) == 0) { - g_bLogActivity = false; - LogAction(0, -1, "[STM] Log Activity DISABLED."); - } else { - g_bLogActivity = true; - LogAction(0, -1, "[STM] Log Activity ENABLED."); - } - } - else if (convar == stm_scrambledelay) - g_fScrambleDelay = StringToFloat(newValue); - else if (convar == stm_votewin) - g_fVoteWin = StringToFloat(newValue); - else if (convar == stm_votedelay) - g_iVoteDelay = StringToInt(newValue); - else if (convar == stm_voteenabled) { - if (StringToInt(newValue) == 0) - g_bVoteEnabled = false; - else - g_bVoteEnabled = true; - } -} - -/* MENU CODE */ - -public OnAdminMenuReady(Handle:topmenu) -{ - if (topmenu == g_hAdminMenu) - return; - g_hAdminMenu = topmenu; - new TopMenuObject:player_commands = FindTopMenuCategory(g_hAdminMenu, ADMINMENU_PLAYERCOMMANDS); - new TopMenuObject:server_commands = FindTopMenuCategory(g_hAdminMenu, ADMINMENU_SERVERCOMMANDS); - if (player_commands == INVALID_TOPMENUOBJECT) - return; - - AddToTopMenu(g_hAdminMenu, - "moveplayer", - TopMenuObject_Item, - AdminMenu_MovePlayer, - player_commands, - "moveplayer", - ADMFLAG_BAN); - - AddToTopMenu(g_hAdminMenu, - "scrambleteams", - TopMenuObject_Item, - AdminMenu_Scrambleteams, - server_commands, - "scrambleteams", - ADMFLAG_BAN); -} - -public AdminMenu_MovePlayer(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) -{ - if (action == TopMenuAction_DisplayOption) - Format(buffer, maxlength, "Move Player"); - else if (action == TopMenuAction_SelectOption){ - DisplayPlayerMenu(param); - } -} - -public AdminMenu_Scrambleteams(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) -{ - if (action == TopMenuAction_DisplayOption) - Format(buffer, maxlength, "Scramble Teams"); - else if (action == TopMenuAction_SelectOption) { - DisplayScrambleMenu(param); - } -} - -public Menu_SelectPlayer(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - DisplayTeamMenu(param1, GetClientOfUserId(StringToInt(sSelection))); - } else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -public Menu_SelectTeam(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new iTeam; - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - decl String:sIndex[64]; - if (SplitString(sSelection, "A", sIndex, sizeof(sIndex)) != -1) - iTeam = g_aCurrentTeams[Team1]; - else if (SplitString(sSelection, "B", sIndex, sizeof(sIndex)) != -1) - iTeam = g_aCurrentTeams[Team2]; - else { - SplitString(sSelection, "C", sIndex, sizeof(sIndex)); - iTeam = g_aCurrentTeams[Spectator]; - } - new iTarget = StringToInt(sIndex); - g_aPlayers[iTarget][iNewTeam] = iTeam; - DisplaySwapModeMenu(param1, iTarget); - } else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -public Menu_SwapMode(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - decl String:sIndex[64]; - - if (SplitString(sSelection, "A", sIndex, sizeof(sIndex)) == -1) - { - SplitString(sSelection, "B", sIndex, sizeof(sIndex)); - } - - new iTarget = StringToInt(sIndex); - - if (StrContains(sSelection, "A", true) != -1) - { - g_aPlayers[iTarget][bQueue] = false; - } - else if (StrContains(sSelection, "B", true) != -1) - { - g_aPlayers[iTarget][bQueue] = true; - } - - if (param1 == iTarget && !g_aPlayers[iTarget][bQueue]) - { - SM_MovePlayer(iTarget, g_aPlayers[iTarget][iNewTeam]); - } - else - { - DisplayForceModeMenu(param1, iTarget); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - { - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } - return; -} - -public Menu_ForceMode(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - decl String:sIndex[64]; - if (SplitString(sSelection, "A", sIndex, sizeof(sIndex)) == -1) - { - SplitString(sSelection, "B", sIndex, sizeof(sIndex)); - } - new iTarget = StringToInt(sIndex); - if (StrContains(sSelection, "A", true) != -1) - { - SM_ClearForcedTeam(iTarget); - } - else if (StrContains(sSelection, "B", true) != -1) - { - SM_SetForcedTeam(iTarget, g_aPlayers[iTarget][iNewTeam], true); - } - if (!g_aPlayers[iTarget][bQueue]) - { - SM_MovePlayer(iTarget, g_aPlayers[iTarget][iNewTeam]); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - { - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } - return; -} - -public Menu_VoteScramble(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_VoteEnd) { - new winning_votes, total_votes; - GetMenuVoteInfo(param2, winning_votes, total_votes); - if (param1 == 0) { - if (float(total_votes) / float(winning_votes) < g_fVoteWin) { - PrintToChatAll("\x01\x04[SM]\x01 %T", "VoteScramble2", LANG_SERVER, winning_votes, total_votes); - return; - } - PrintCenterTextAll("[SM] %T", "Scramble", LANG_SERVER); - PrintToChatAll("\x01\x04[SM]\x01 %T", "VoteScramble1", LANG_SERVER, winning_votes, total_votes); - StartScrambleTimer(); - } - if (param1 == 1) { - PrintToChatAll("\x01\x04[SM]\x01 %T", "VoteScramble2", LANG_SERVER, winning_votes, total_votes); - } - } - if (action == MenuAction_End) - CloseHandle(menu); -} - -public Menu_ScrambleTeams(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "NOW", false)) - g_bScrambleRoundEnd = false; - else - g_bScrambleRoundEnd = true; - DisplayScrambleMenu2(param1); - } else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -public Menu_ScrambleTeams2(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[64]; - new bool:bRestartRound; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "NO", false)) - { - bRestartRound = false; - } - else - { - bRestartRound = true; - } - StartScrambleTimer(_, bRestartRound); - } else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -stock DisplayScrambleMenu(iClient) -{ - new Handle:hMenu = CreateMenu(Menu_ScrambleTeams); - SetMenuTitle(hMenu, "Select When to Scramble:"); - AddMenuItem(hMenu, "NOW", "Instantly"); - AddMenuItem(hMenu, "END", "At Round End"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplayScrambleMenu2(iClient) -{ - new Handle:hMenu = CreateMenu(Menu_ScrambleTeams2); - SetMenuTitle(hMenu, "Select When to Scramble:"); - AddMenuItem(hMenu, "NO", "No Round Restart"); - AddMenuItem(hMenu, "YES", "Restart Round"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplaySwapModeMenu(iClient, iTarget) -{ - new Handle:hMenu = CreateMenu(Menu_SwapMode); - decl String:optionA[64]; - decl String:optionB[64]; - Format(optionA, sizeof(optionA), "%iA", iTarget); - Format(optionB, sizeof(optionB), "%iB", iTarget); - SetMenuTitle(hMenu, "Select When to Swap:"); - AddMenuItem(hMenu, optionA, "Instantly (Kills)"); - if (!IsClientObserver(iTarget)) - AddMenuItem(hMenu, optionB, "Queue on next death"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplayForceModeMenu(iClient, iTarget) -{ - new Handle:hMenu = CreateMenu(Menu_ForceMode); - decl String:optionA[64]; - decl String:optionB[64]; - Format(optionA, sizeof(optionA), "%iA", iTarget); - Format(optionB, sizeof(optionB), "%iB", iTarget); - SetMenuTitle(hMenu, "Select Force Mode:"); - AddMenuItem(hMenu, optionA, "UnForced"); - AddMenuItem(hMenu, optionB, "Forced"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplayTeamMenu(iClient, iTarget) -{ - new Handle:hMenu = CreateMenu(Menu_SelectTeam); - decl String:optionA[64]; - decl String:optionB[64]; - decl String:optionC[64]; - Format(optionA, sizeof(optionA), "%iA", iTarget); - Format(optionB, sizeof(optionB), "%iB", iTarget); - Format(optionC, sizeof(optionC), "%iC", iTarget); - SetMenuTitle(hMenu, "Select Team:"); - AddMenuItem(hMenu, optionA, "Team One"); - AddMenuItem(hMenu, optionB, "Team Two"); - AddMenuItem(hMenu, optionC, "Spectator"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplayPlayerMenu(iClient) -{ - new Handle:hMenu = CreateMenu(Menu_SelectPlayer); - AddTargetsToMenu(hMenu, 0, true, false); - SetMenuTitle(hMenu, "Select A Player:"); - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} diff --git a/Simple AutoScrambler/addons/sourcemod/translations/simpledonatorbenefits.phrases.txt b/Simple AutoScrambler/addons/sourcemod/translations/simpledonatorbenefits.phrases.txt deleted file mode 100644 index 3826846..0000000 --- a/Simple AutoScrambler/addons/sourcemod/translations/simpledonatorbenefits.phrases.txt +++ /dev/null @@ -1,62 +0,0 @@ -"Phrases" -{ - "PlayerLevelCmd" - { - "en" "Command must be run at the player level" - "fr" "Cette commande doit être tapée en jeu" - "hu" "Ezt a parancsot jatekosi szinten kell futtatni!" - } - "RestrictedCmd" - { - "en" "You must be a donator or admin to run this command" - "fr" "Vous devez être un donateur ou un admin pour lancer cette commande" - "hu" "A parancs futtatasahoz admin, vagy tamogatoi szint szukseges!" - } - "InValidTeam" - { - "en" "You must be on red or blue to swap teams" - "fr" "Vous devez être RED ou BLU pour changer d'équipe" - "hu" "Jatekban kell lenned, hogy megcsereld a csapatokat!" - } - "PlayerQueue" - { - "en" "You have been queued to swap teams on next death" - "fr" "Vous avez été mis en attente pour changer d'équipe lors de votre prochaine mort" - "hu" "A kovetkezo halalnal csapatcsere lesz" - } - "PlayerSwitched" - { - "en" "Your team has been switched as requested" - "fr" "Vous avez changé d'équipe comme demandé" - "hu" "A keresnek eleget teve a csapatod meg lett csererlve" - } - "SwapTeamMsg" - { - "en" "Type /swapteam or !swapteam to swap your team!" - } - "ReachedCount" - { - "en" "You have reached your health limit. You must die before you can use it again" - } - "AtMaxHealth" - { - "en" "You are already at your maximum health!" - } - "ToMaxHealth" - { - "en" "Instant health bonus applied! You are not at your maximun health!" - } - "HealthBonus" - { - "en" "Instant health bonus applied!" - } - "PublicJoinMessage" - { - "#format" "{1:s}" - "en" "{1} a [donator] as joined the server" - } - "PrivateJoinMessage" - { - "en" "Thanks for donating!" - } -} \ No newline at end of file diff --git a/Simple AutoScrambler/addons/sourcemod/translations/simplespectate.phrases.txt b/Simple AutoScrambler/addons/sourcemod/translations/simplespectate.phrases.txt deleted file mode 100644 index 2d1a096..0000000 --- a/Simple AutoScrambler/addons/sourcemod/translations/simplespectate.phrases.txt +++ /dev/null @@ -1,42 +0,0 @@ -"Phrases" -{ - "Stopped spectating" - { - "#format" "{1:s}" - "en" "Stopped tracking player: {1}" - } - "Yourself" - { - "en" "You can't spectate yourself" - } - "Spectator" - { - "en" "You can't spectate another spectator" - } - "Spectating" - { - "#format" "{1:s}" - "en" "Now spectating {1}. Type !stopspec or /stopspec to stop spectating this player" - } - "Invalid Target" - { - "en" "Invalid target" - } - "Cant Target" - { - "en" "Can't target this player" - } - "Must Have Target" - { - "en" "You must be following/tracking a player to punish" - } - "Target Left" - { - "en" "The player you were following/tracking has left" - } - "Punished" - { - "#format" "{1:s}{2:s}{3:s}" - "en" "{1} was punished with a {2} for {3}" - } -} \ No newline at end of file diff --git a/Simple AutoScrambler/addons/sourcemod/translations/simpleteambalancer.phrases.txt b/Simple AutoScrambler/addons/sourcemod/translations/simpleteambalancer.phrases.txt deleted file mode 100644 index 03595fd..0000000 --- a/Simple AutoScrambler/addons/sourcemod/translations/simpleteambalancer.phrases.txt +++ /dev/null @@ -1,130 +0,0 @@ -"Phrases" -{ - "UnBalanced" - { - "en" "Teams are unbalanced and will be balanced shortly" - "fr" "Les équipes ne sont pas équilibrées et le seront bientôt" - "de" "Die Teams sind ungleich und werden in Kürze ausgeglichen" - "hu" "A csapatok nem kiegyenlitettek! Egyensuly beallitas kovetkezik!" - } - "Enabled" - { - "en" "Simple Team Balancer is ENABLED" - "fr" "Simple Team Balancer est ACTIVE" - "de" "Simple Team Balancer ist AKTIV" - "hu" "Az Egyszeru Csapat Egyensulytarto AKTIV!" - } - "Disabled" - { - "en" "Simple Team Balancer is DISABLED" - "fr" "Simple Team Balancer est DESACTIVE" - "de" "Simple Team Balancer ist INAKTIV" - "hu" "Az Egyszeru Csapat Egyensulytarto INAKTIV!" - } - "PlayerMessage" - { - "#format" "{1:i}" - "en" "You are going to be auto balanced in {1} seconds unless a dead player can be found" - "fr" "Vous passerez dans l'autre équipe dans {1} secondes si aucun joueur mort ne peut être trouvé dans cet intervalle" - "de" "Du wirst in {1} Sekunden zum automatischen Ausgleich herangezogen wenn kein toter Spieler gefunden werden kann" - "hu" "{1} masodpercen belul at leszel helyezve a masik csapatba, hacsak nem lesz addig egy halott jatekos!" - } - "BalanceMessage" - { - "#format" "{1:s}" - "en" "{1} was moved to the other team for game balance" - "fr" "{1} est passé dans l'autre équipe pour équilibrer la partie" - "de" "{1} wurde zum anderen Team verschoben um das Spiel auszugleichen" - "hu" "{1} at lett helyezve az egyensuly megtartasa erdekeben." - } - "PlayerLevelCmd" - { - "en" "Command must be run at the player level" - "fr" "La commande doit être lancée au niveau du joueur" - "de" "Das Kommando muss auf Spieler Ebene ausgeführt werden" - "hu" "Jatekosi szinten kell futtatni ezt a parancsot!" - } - "CmdDisabled" - { - "en" "Command is currently disabled" - "fr" "La commande est actuellement désactivée" - "de" "Das Kommando ist momentan inaktiv" - "hu" "A parancs jelenleg inaktiv" - } - "RestrictedBuddy" - { - "en" "You must be a donator or admin to add a balance buddy" - "fr" "Vous devez être un donateur ou un admin pour choisir un partenaire" - "de" "Du musst ein Spender oder Admin sein um einen Partner wählen zu können" - "hu" "Tamogato vagy admin kell hogy legyel, hogy 'Tarsat' jelolhess meg" - } - "SelectSelf" - { - "en" "You cannot be your own buddy" - "fr" "Vous ne pouvez pas être votre propre partenaire" - "de" "Du kannst nicht dein eigener Partner sein" - "hu" "Nem valaszthatod ki onmagad!" - } - "BuddyGone" - { - "en" "Your selected buddy has disconnected" - "fr" "Le partenaire que vous avez sélectionné s'est déconnecté" - "de" "Dein gewählter Partner hat die Verbindung getrennt" - "hu" "A valasztott 'Tarsad' kilepett" - } - "BuddyMsg" - { - "#format" "{1:s}" - "en" "You and {1} are now buddies" - "fr" "Vous et {1} êtes maintenant partenaires" - "de" "Du und {1} seid jetzt Partner" - "hu" "{1} es Te 'Tarsak' vagytok." - } - "BuddyLockMsgDisabled" - { - "en" "You can now be anyone's buddy" - "fr" "Vous pouvez à présent être le partenaire de n'importe qui" - "de" "Du kannst jetzt jedermanns Partner sein" - "hu" "Barkinek lehetsz a 'Tarsa'." - } - "BuddyLockMsgEnabled" - { - "en" "Buddy selection locked. Only you can change your buddy" - "fr" "Sélection de partenaire bloquée. Vous êtes le seul à pouvoir choisir votre partenaire" - "de" "Wahl des Partners gesperrt. Nur du kannst deinen Partner wechseln" - "hu" "Tars-lista lezarva. Csak Te tudod modositani a Tars-listadat." - } - "PlayerLockedBuddyMsg" - { - "#format" "{1:s}" - "en" "{1} has locked his buddy selection. Try again" - "fr" "{1} a bloqué sa sélection de partenaire. Essayez de nouveau." - "de" "{1} hat seine Wahl des Partners gesperrt. Versuche es erneut" - "hu" "{1} lezarta a Tars-listajat. Probald kesobb!" - } - "BuddyWelcomeMsg1" - { - "en" "Select a balance buddy and stay together during an autobalance!" - "fr" "Choisissez un partenaire et restez ensemble durant l'équilibrage automatique!" - "de" "Wähle einen Partner und bleibt zusammen während eines Ausgleichs" - "hu" "Valasz ki egy 'Tarsat' akivel egyuttmaradhatsz a csapatkiegyenlites alatt!" - } - "BuddyWelcomeMsg2" - { - "en" "/buddy or !buddy to select a balance buddy" - "fr" "/buddy or !buddy pour choisir un partenaire" - "de" "/buddy oder !buddy um einen Partner zu wählen" - "hu" "Hasznald a /buddy vagy !buddy parancsokat a 'Tars' kijelolesehez" - } - "BuddyWelcomeMsg3" - { - "en" "/lockbuddy or !lockbuddy to lock your selection" - "fr" "/lockbuddy or !lockbuddy pour bloquer votre sélection" - "de" "/lockbuddy oder !lockbuddy um deine Auswahl zu sperren" - "hu" "Hasznald a /lockbuddy vagy a !lockbuddy parancsokat a Tars-listad lezarasahoz" - } -} - - - - diff --git a/Simple AutoScrambler/addons/sourcemod/translations/simpleteammanager.phrases.txt b/Simple AutoScrambler/addons/sourcemod/translations/simpleteammanager.phrases.txt deleted file mode 100644 index f2093a7..0000000 --- a/Simple AutoScrambler/addons/sourcemod/translations/simpleteammanager.phrases.txt +++ /dev/null @@ -1,92 +0,0 @@ -"Phrases" -{ - "PlayerLevelCmd" - { - "en" "Command must be run at the player level" - "fr" "Cette commande doit être tapée en jeu" - "hu" "Ezt a parancsot jatekosi szinten kell futtatni!" - } - "RestrictedCmd" - { - "en" "You must be a donator or admin to run this command" - "fr" "Vous devez être un donateur ou un admin pour lancer cette commande" - "hu" "A parancs futtatasahoz admin, vagy tamogatoi szint szukseges!" - } - "InValidTeam" - { - "en" "You must be on red or blue to swap teams" - "fr" "Vous devez être RED ou BLU pour changer d'équipe" - "hu" "Jatekban kell lenned, hogy megcsereld a csapatokat!" - } - "PlayerInValidTeam" - { - "en" "Player must be on red or blue to swap teams" - "fr" "Le joueur doit être RED ou BLU pour changer d'équipe" - "hu" "Valamelyik csapatban kell lenni, hogy csere legyen" - } - "PlayerQueue" - { - "en" "You have been queued to swap teams on next death" - "fr" "Vous avez été mis en attente pour changer d'équipe lors de votre prochaine mort" - "hu" "A kovetkezo halalnal csapatcsere lesz" - } - "PlayerSwitched" - { - "en" "Your team has been switched" - } - "PlayerSwitched1" - { - "en" "Your team has been switched as requested" - "fr" "Vous avez changé d'équipe comme demandé" - "hu" "A keresnek eleget teve a csapatod meg lett csererlve" - } - "PlayerSwitched2" - { - "en" "Your team has been switched by an Admin" - "fr" "Vous avez été changé d'équipe par un admin" - "hu" "Az Admin megcserelte a csapatodat!" - } - "SwapTeamMsg" - { - "en" "Type /swapteam or !swapteam to swap your team!" - } - "PlayerSwitched3" - { - "#format" "{1:s}" - "en" "{1}'s team has been switched" - "fr" "{1} a changé d'équipe" - "hu" "{1} csapata meg lett cserelve" - } - "Scramble" - { - "en" "Teams are about to be scrambled!" - "fr" "Les équipes vont être rééquilibrés" - "hu" "A csapatok hamarosan meg lesznek keverve!" - } - "VoteScramble1" - { - "#format" "{1:i}{2:i}" - "en" "Vote Scramble successful with {1} votes out of {2}" - "fr" "Le vote d'équilibrage des équipes a réussi avec {1} votes pour sur {2}" - "hu" "A szavazas sikeres volt, {1} szavazat a keveresre a {2} -bol" - } - "VoteScramble2" - { - "#format" "{1:i}{2:i}" - "en" "Vote Scramble failed with {1} votes out of {2}" - "fr" "Le vote d'équilibrage a échoué avec {1} votes pour sur {2}" - "hu" "A szavazas sikertelen volt, {1} szavazat a keveresre a {2} -bol" - } - "VoteInProgress" - { - "en" "A vote is currently in progress" - "fr" "Un vote est actuellement en cours" - "hu" "Egy szavazas mar fut!" - } - "ScrambleTime" - { - "en" "A vote was recently made, please wait" - "fr" "Un vote a déjà été fait récemment, réessayez plus tard" - "hu" "Nemreg volt szavazas, kerlek varj egy kicsit!" - } -} \ No newline at end of file diff --git a/Simple Chat Colors/addons/sourcemod/configs/simple-alltalkmanager_events.cfg b/Simple Chat Colors/addons/sourcemod/configs/simple-alltalkmanager_events.cfg deleted file mode 100644 index b739cf0..0000000 --- a/Simple Chat Colors/addons/sourcemod/configs/simple-alltalkmanager_events.cfg +++ /dev/null @@ -1,43 +0,0 @@ -"game_events" -{ - "teamplay_round_start" - { - "reason" "Round Start" - "setting" "1" - } - "teamplay_setup_finished" - { - "reason" "Setup Period Ended" - "setting" "0" - } - "teamplay_overtime_begin" - { - "reason" "Overtime Began" - "setting" "1" - } - "teamplay_overtime_end" - { - "reason" "Overtime Ended" - "setting" "1" - } - "teamplay_round_win" - { - "reason" "Round Ended" - "setting" "1" - } - "teamplay_suddendeath_begin" - { - "reason" "Sudden Death Began" - "setting" "1" - } - "teamplay_suddendeath_end" - { - "reason" "Sudden Death Ended" - "setting" "1" - } - "teamplay_round_stalemate" - { - "reason" "Stalemate" - "setting" "1" - } -} \ No newline at end of file diff --git a/Simple Chat Colors/addons/sourcemod/plugins/simple-alltalkmanager.smx b/Simple Chat Colors/addons/sourcemod/plugins/simple-alltalkmanager.smx deleted file mode 100644 index 6122756af68998fb531abcd0d08698e24cff25af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7028 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 diff --git a/Simple Chat Colors/addons/sourcemod/plugins/simple-chatcolors.smx b/Simple Chat Colors/addons/sourcemod/plugins/simple-chatcolors.smx new file mode 100644 index 0000000000000000000000000000000000000000..4ffa03cd125582025db390707da36562a6868850 GIT binary patch literal 9097 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 UVUpuGq0YDRpI>l4cz-?mFB3D^;s5{u literal 0 HcmV?d00001 diff --git a/Simple Chat Colors/addons/sourcemod/plugins/simple-donatorbenefits.smx b/Simple Chat Colors/addons/sourcemod/plugins/simple-donatorbenefits.smx deleted file mode 100644 index 821d61d784607595ca400d273a941a42e40de640..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16600 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 diff --git a/Simple Chat Colors/addons/sourcemod/plugins/simple-messagesuppression.smx b/Simple Chat Colors/addons/sourcemod/plugins/simple-messagesuppression.smx deleted file mode 100644 index cc20dadd37d8ff23d0a64513cc09650f4bdbf24d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4845 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 Blh*(M diff --git a/Simple Chat Colors/addons/sourcemod/plugins/simple-spectate.smx b/Simple Chat Colors/addons/sourcemod/plugins/simple-spectate.smx deleted file mode 100644 index c6885b041145a73f664650e729a5dcf8b3b0813f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19129 zcmYIvbyyrf)Gkhomf~K#cyWgocP(zk-DPnp1&S9hUL1<+;=84|ZE=Ui9Tta$h0E`| z-+k^M=RI$dlgvyeC(p@DA}_D0gMy6Qu8f5A6&V=`w;2fui5vL^{#XADL_)%N;e$a) zNG5bhNH{N?As-3p)r$@B3uiAtLb89+G%u3+!o^?mSzb8g7ZTDwDiRXs3kQ}UA+5Yr zj&+2D^yWpoz6iw& zw|~j!vU0PwLE^Hu@U}qWa`&-xcChmLAL47_`9fSRyd8XPUWm7a-Tx$A{!3U}+Wr5M z{}Q$i&i^mp*}?VyQ7?ZNOE>5LwRdo}b^E_Hy}UggTwhxATRI8G4f?E~b*sj!#B33U zge+ZXqx>f-MOslth1CV~6|Dnm3FEuwf7U}Qj5^GG(^;<>iA-ngtK>;LD=I3EW4YKm z_KS+-Nlibm^b-SD0fuqxopD?}aqK;#9a;_#PX(8`UT5t>m+8%?M?Ij6t?ke~5s1i( z+)Li(?nz#zS@?}$#b=(^^?rz#jCkh!7TD>nL3smmac|*zMs-hjCt72<$A-p2X(F9e z2+I^NK(9}wk*C*?NyD-KjL&bfr9A@vjB_^o7lbbtu$=Lr$---%%KgIN@3s;GTN z06pjv`2>s4$DJlJ*Ul?imh0;1>1!1W3@ihZq%_@0eA{2NqaUTx!$Y`G5k+x5oDo5~ zkq3YE?S64{k8!Ud$a`tW_#W?ZHn{D6;oJRsh~?epMwQS^GnSln9di2`w8n6hPMoA? z&e~&X7+M{I{+ul?2svr&(MJ5vIN1(pFoj@QcOch<{Pr{Q>TBxiODzAOB5v%}$M>sW zCygopL}XK>ynjoH5F$vbHZO5tQU87LmyV6E_`^q?lfaIR5|CLLpTe|_C{5jf&d>0{ z@^d03n!~!f9_G<1HWe+JMxt#xm5s9ovo($f^nkKZ0h`>pgtv)jS=u6N0fzYuYh#EV z3k~?wu^$Fp69X=y5rSxekQNl~xy_1w0q#(7Cq+uC#YL?kBvt`l3un#Q38>xbS4k zf^jU8da2#}8^F5w@40jfJo^nJVpIf7ZMfeXG zCM)EU{_#dWRn7O%+a<6gW)4YD^+Wlok*n+9w;11+4b9jk->Vkir21&`utD!XZ~$SL zpzHI&I6f6aQc44wh}46RXtHYp@Bhb(!c$pO_>(dG9`@l8=o02@R&bC;kTfCZ;$t1{diBk4i5Ky{zh$=#?d=-&6ZId{vnS`5bu zNgNTdN|r6aQMhblC-z<7U4&@%5V?VJRUkk7gN!bSNBA+U@9b=r&RMAh8Fx752Qd2i z-uq)T!l*LE6&hi=IlWs~2OQ#mQ}&ceXhNBiw9?ZV{Jrz0E=7lncWL?EYEx_uQ@dtb zaAg1^8s{lJwraZ#Igco*B5U_4<~2DE@sf>TvuTs5IeyaZ?18%B?M$a^Y==4iG~d7m zFPw%smULg?+W@GmA;uhqHBr||F*G6mE6|Oo3)LUynrh?e8EYzkDp-3|t6KA1wh-vQ z)p9>!Q$sDua5RiIFMg^?A=+}5`m3PAdTE+hvL&Nxf@fXlBskRO^hT1yU)J2@x%+zOU?Foi0!z9uj z@qm;va}5$ie#VY~q0`v_za7H8PC*f0*TL^fAYnm8i4b7FG}MvlI?e!Jz4+|s>5`;6`9tCslBe>ew-6Ag-z zN1sZ~&MM4kP`975O+5m4VYFkL+=uYbWg62{!I@*g6o-yh{T4us&v2^<6miyp_bxV6<(B5@>BZxZdAikJRfvT@S9YZ2MJI*w) z&y~TE2H;~0Z^*bZ`UI9HmrI5}RP)~=z10#** zA4~!Hm~IV-D{(?o$Yr?kvH1KLP1atl*0y2f^N*WEI88$B1-yb|Z*rS&T8vtE-MCzA zeRPdu>+|(N2LC0F#N!Rl#%zFEL8hius70%j2_XG-WLA!CXou>YgCkG{k+po1oRGDp zF&J7Y0-%K^s?6`$ANoh??f!il3ocgHKPjH?7)iJiH#R0+S1jK10w$_UGR;33^Np5z zm+qR1CK<77GU@sZo>8n{wS?!FBbLPN3QXe8=GW^+8iES+B#EADj2@MR9IM&>_3nEH zl;jFTR(DFO0j{bcN_dbB@f)Q)Nb-5>$Tin}mB`4X$b^XUw2Rd=$Yc4;>>1Lw_HbM3 ze`emm<<(|l71#k6%MdK~=5=!Q&HM3`X}h5nEY0kH)j^o;dZd?E)25cA(7C*{qIL5? zY-BDU9CXsv5UFn?u3zOvlqo4c3uzjxK)sZglGn8lL=K+L6U{20t#PUKJ*lN-8#^*N zVYv`3f6k?P`mO4ffKSA=9+c5OrE?;3Eov8dvmzOQ@b?L#l?U_rp<@hBkCOjfq z1@RZPS;KS%B4)eFRW5Y`$h%f6Gp&H-b*LTjXBk%v4%^ikA*c7f^~VvIzeA<2PV-eN z0G)6nh|s!7QlS@R=5Ir{{CmN&9G&+dp;6eCs$XOFH0|$QiG4oa9>477?A_%MQH_q~ zO(UZ#RfoGhFN)bqe-|S$sfYZN%KKx5zz3BeQ);;_eUrnBR|0&gX~a({jJlAO1RlylIKq zsQEu9d{S=;uHhXYd$2X_d}VVCz8onXSSnF;1g@F4gWEAA-%YpEK{^h%&Sy;-27M%4 zX6G>YzDZ?51$|9hc?2{%bS9A5O4g^1#PkrrqV>wW@e8u{y#aJj?mxvf?GSGFT9vEo zJ=x(iGppPb8xN&ZKJJ-0vV+~8Q77J8r5RGw?1_zn0$0exdd)Z`q+`mM@iNni+KldD zGy;%#?DhNN=iW+1gO6Fd#c8Hn?&-DsZQfFQ?}5o~NV{v0(eB`H9f~t|ytT5(iO1*` zg#M0@URD)}?Ob$^pw}7Z(c|K7|KbP_$7uGpBIn36M+x0>pd2xfG`3iOQ#`AzNF$T~ zmVD$BE67NPJ0lPY;AmB{COKld$9>dTy%BAF_vzjw%XUq}LulxNx|X_ zj*vfPH8-~ghF%ButS|%`4VeBq;jBbZZ%z*;Zphs%Xc;>lwGY*AO)ook>j_0q4c!){ zoqeg%$q(AgAX3jf)2!hvP}b-_GK;XDvWr|ItnjI|xRMlF@94OyT?cjiUZd656FI8v zi1-w|d)<+Ixn!v88(6E#S4TYse=5YeTsrY-1qGU^ggBZ}{`Q)1g3K%it|Jd=8SkW7 z#T-c_ZLr;%9G#n-Kp1v@_c%E_>|dr50&HCWVxEnxM7@A%!E}GkA>aLuu^VL7CG%OJ zX3Z@1x^+{x0!V1n-JN0A?NfkGRt;R&FiAgSsU7JiELdTwHQ3CZCP4K0OKTC1_ z713le?f|f_F||^qMG5C{J*j9}#m0WZ(Yeh1m73^whP%lh7MiKP!X0y=K|TcYk+?gPijG`1VWWFH$(d19^c; z>k{qDrX8@~tLUfxJ6l5=rJ&Fg5B?p!(i78kr-S{=V)WWeDl1k9)-~SU+Srar7rz&6 zpo_z4qdF;&&FNwksG9Kbw3q3SRaHmjV$3x?VYx%8zV0tw59&H7Van2IOW6gK_M4n z7sI#ODbj6b`#Z^%e93F5{`pg&hDYf6!UJ!A)4S1ov|B?WVD&jwWB%*-p6;UuDYfv& z>zdt2*B;a)o1Zzm1i-exN#ZvNmM20>7m~R$(XpY`qT)^T0Lkg`KhXv5wGHWAar~zE zHa{cqZL%V&9=E3+-duS;>P~g`kla*{h)3m{i!_?+*)c+DRSQn1J-G}2%_bF$Cqq;l zD|qzpyHi9S!A5o=`_z+jEp^qB)W+$Z=G0~a@Q|tCd6$Vu1^+w z=B4nxwepD;eC6w5kSHImjozM4puucaUZ6qw{Nrr`@$V3mF&WqX^0Q(yBbT${sJTZF z<(7KQ{c3`UfRooPP^j?=D8&0BFZ%bm^-=V9g>LLJJC8X4@w`F+!N)6j%h-`=X8ZFD zVg*tD@`wA2Lm)H82=YA`|7iy?UZu0Bpfit_hdZ1b7N#We#YCGY3?$UxXbb4aJ76FhM1w;EhX zY&x_`T%&xn$3!gkV2wrUU}^_(ftb$ol;oQGmovT2qR&ee9LbwY9f{+J2ynotGq2+B z4&2W6&B!=K^{g|034P9{OIyh6XGQX3FOwWDw9+D<;qUJygc1@#o@tL>3d11pw8ta) zVUPgkbB;~>Kfd(w4LzE@BcNiZpmEz{t@AG2+a0?=N~$UHsPCH7Bqm+$Z*y z>+Wpx{iiDa&=#qb1IaYw-JGT&4tPFCV}-cx$E>w1^&SkX5(L;0cGm>!Uh>aLW^lXa z8?4>)eyTEk5OO@xDozM52Z}9!E<@Zh7~WkW0Gm3Og;vX^4`<7HN11%fE!U%XnZYYr zV=69&i``zpb?+VdbJz8a=IMW;18pk-)3;nvfbDW1w%ElqC(m$%gV;gasqYh zS~e|UaouNUmJh3&I%uU5c*8T0J`ob#vNydubHI^l&SiSw@jm!&$vL)TD$Ur7^)2s0t>y13{sC-RWj%wEZF!Cwm)??c`Qvv?!4jm+H2$%k zZSV~2WX#vqAtKcMlRBmy0gnT{myQHors z9>DGPCN3`)>o_1*{_7h(N4)zTN1KU2F_o^_T0b8UJGYJcWv_~FwkxQKyA%|-)ta0K z2_(=ZAx;7O>woxBwYqzWCs!_2J=?%Hm0xkXUUFX$GW=AVzBG+9)_OU~dGxV{IW;BH zFUNNILe~yToz}H1u*S|^y2s?-f4gkE3~&Dte%ri#GVKQ`+we&$*O`tlm*EyUOPR=Q z_I@x#ZOVH(xcQrQ`fb&TG_)hc@Ia%>4f3bpAXt2SCvi}IAW&{8MKuQ z{FG{VHyAKsW4qyhqL0s%M5UfchmwGWZ#Hy8o@UUJr$l^DkSNe zHN4ZQy#sy)T$#06&pB?ALzwh_9%KvfNT7FL2G6qULpL6a&LW3w_ds02r zSO3BJo=}fXw%zXrwehpW&ZVTleE+4LItWAhMB}}_-8n=c#AV%OP)2ktV7Z^01Wx{)ZNH8>NW}2*LIP7`<4SP)Ds9zvQ^N*W%Gnds2q-z}w4E6& zH1`zYFf#yZrj2*U9iAF~);A919tk>cTnfyXjX6T<|BVw)?U$s=$Wkeb*ZxbI)M$TGDSD~(0GuxF^pH1=gAjjkfz>d%kI7B-R- zoYe6uV!9vBBvz@5gv&0qN__#&mNLTRNoWt8z1i+Fv6!#D``;quKg~X zLOshjNY;x*nt#8lN+`EkI4kLDglMO3Gfe%BTD8!mMQvhPZ)HeM58GSS*hW_eKZ6)Y zMww3St7>Z(dCGM&YimTg^CssW!`0^F%K%>DA4HkT0Ba zOnrtupsycGFqjKY}MR`Ob{JO9Dcc)Bf#Xa)uT zyp8Tnp}~-%kLB3EO_%*u8(&N@UnWG=gSIU{d7@mxk0K>>ABOy38Zm^XkmCZ|Wb<6V zWhX2LtSu4ZmUx(^32<`HTzqr<+Ba+9`A6tgcbTF4wYyrQ`GP)p-Bbz>P!eRoj$~|9ut0lA!5qPrh^lbKUy9Anl+PTwb--~JK-ilgp*i=BXdXyUQMKM+_k9 zPYCxmtIUb@x333GLDWqXbM8qb6i=2D2W~Mr)U21j0-zSES8;gWHOf( zo1$-InA#YsNEp?{8+ibsDwA^gNd(WzYb;PARQE5(Wk2N5HEfq8rDS>%_#CZO6_{GK zkJo0agP8A4Jg#%jv$=>nQO$n6ggZ(kNF3+oCtgwe4bGg9a5rW@6w5}+-5)JJ5I<+2 zuivL?G%nZ|sQTp2;?g|q-2XN)n91k?pl}#a@y@>!4X((9TS9{u>5mlqGp{nBAuf6k z{v(_Q$UITj7Mj%?0B!GcM;R!iFFDbUFZfC4R8f=4}1>fd6M|FCUFvfEiZ%ZvSzE| z`8m~0=W01kH6hfF+h_L^+9$wl&IkV=g~GnsGq0qv6Q~@bQt8=b*=E8gSu+$J9e^L% z$%@|EQq4xUy(^}$eh%Cz{`%%m&98vqy$(m0RB|X-IL;TmoGGti4CLsPty&5z%U)%+ z^eNp{P_;T3f0 zKQW)9sL83$qA_X3d2~j^#{SF2y_ly%jO?|QAU$~n-&+@cV%0aH(#Pe#22DeLZv45& zG~|$gr3G`+6&E8OEdw?`F=t7Of!-!ugwj;JciE*=LxAukkWnsuY%JPWbV{SAz+O62 zh?nY$SOHgMmpp_fQ(*jyYYyqf)^o1^u!xcQ9wTL=ROTfq^OPG8ce3~$=Pn-GtB_Iu z@cz1lYZA5i!K+bFo8Hsu{8s&drkqUcN%XZXP@Rx{-O>t{a zd~#XmDMv1Eo!t7mNJqmGYRk*;xeuhLrQUKv}+(uN#-A68_vGCF^_E^Aj|Z&I`UKpuycrFVR+HsvH8ne&x;gE7D)(rLUR>y^Bp zbV5eU&~coC<;Lf!q0?LV7e;BT@Qna7f>Q!+Wa6Un9J&jl8sF`+>kYi-qc0j7QS0Jv zeMm`(cv+O^fx7i9>eX2N4>_h}QPzI9XXBG!6r#yBV#u9U#6QKVDi~*dh_F0gqKErF zm#uyOX=GF6R&rewHQ}$K%KwX)?8}2y_mg#9&;p?>yK=uG*JO##Dw+E1TZtGwwufuX zhPJZYEC1u8NPgTPrh@Pk@(?!*v%&IiD?Ov%TD!K+!*wD z0ZFfU+h{eFTYaIMt1Ed2=?$7Hp_p|&(p$0VRH70BCt`2uW<6s;X2 zV*a-x&XL4Y62UUvz!%)4cJI@qi8TC`0Xtds)d9ii-w*e>+7$~QMD5M@Z2$VDOazPx z#seqGQ{T4Ib)3@t6;`)HJ{5}R)-hI)kWx8cu^}Vfk3Z>-I_GQmLuf2j8GRuuMUV1$ z8>5GuG|nH74xUr~>xU#v3d%V^ShicBg+I`##;>u~^2Q6HCUFVH+lA8%UA~5Pv`3vY z6+!so&q!eRNufx1emGlF`@z;(7N3bO9{$KhKDv6C(t)r~Iktm`3o>A4JKQRM&-?vv zL&{C{V&Sr9@53XY1*q}wf~aBq`|M$?CFky}pv$1A?OZ9GIs4S3?P2>KHmU7_@g5eVZDGs|%hI-(XMy!= zYq6l1vlH*7ql6l=O(ddEWX4`9hm$Jz-xq;3!nVToRr<;6z;(*~hAlUlD*cPyAKUeF z6>wFN)iL1Ro03isL3P5|lRbUxOIlD#C_mJ(PI#GkVVfAxi|S(LQO5ZOc@0g~zh9&g zELqn!Pv94=zu@pX2+ZD7N_Hpwqc%5aj{Wd6bkxk_6o`n|&z;A5d@1`x>i36z!nVcy z28+_@1O$uqU3sFc6YeA?(`TM=Kr73Lxzs-arp35TwXPd7Pq?;lvlH&sE>VttOQ^Zw zwAnNH>rF^DVE3t>6a}W_Xq_8%}e#uUmWl0Z|19sc#1gFfGo@HT-^O zvsy1OxV^q`n&v$zKo3Q2XVX;$dcCuW6AV4~^dOP^r^_{gj~Ou9zX%0Wj`oXv2QQEI z`wxJdUQ7T`#dhI1>bszJVK3@C+xGplB}ismQ*k&gs*rZ@d(z-fU)oG^@m)g6+g|U> z>^KxcZW0L3gq9HCaj+I8(7!FZrFP+zEVxY+&} zJIq6r8_gLNaVI>ffZl_Jvw2<@CRX{BxD|3A>Cpwe<$H(Q_jl{A^P7$26UGMPyC@l} zR*l?*t9hgXBrasj#{Ez*%i8GOJPHr-wa`OfyUerTmv~hcBp$y9z`gAAnFb0^?%gdi z4;maZjO;HWLh_uG9Nv6Ium+ds|YcgnQlymhixE8E|>nI?5^PQ-a0>pF?y{ zLX^5l-*8QYpwsOz{g*4MPungZalC%X0?`OLZDVc6hjmx~*puqndZWeas~=g>Sy8)` zG%rSb^c_&c833HJ?>yS#5<7;&uEbc^c$zJCJ{=J}{jqrOa8hm%eeULj%Zz%75?M^WOG+N$eJANC46lE>vB#xYyr9*rPnk{e-yZ=!CjDa7MJjwc zB)RE1+nds*{e33S?4^GlHpL4yc=BoZv_r~g4kvhJx9UD~Hn1P%q;+7-^X2(-9|PGVxTFgJLaCnovQ2@Q*z&{cgUJm7E)!Jh2?jN{KI>wh4Kh+_5>Y zmG?)Tk=8~bs@DQmwb+(@X}tWu;AN`xWL=CpMoZRH@Q;4))Q@DT3H+wL`xZs&YtGE0 z>tDV7FehvIX9jLYm#q1j!J8?OM>{MbFDKQuDB0LY!(Oh4y>cQ0OV_}GW>OwC#0YSsi`a`eL4#OZo|B z(-OBp@%E3zW9mpBoN2S+VsgP*s!j>5Gv!9Z3}wo}d8GOns}yPclXqv)L1E^;F%!PK z+rrAs%-mE*rN>{RkhR7D-J=0DqtJuncdHUbk2Mo#OA)B1g4>!U#_m= z<{exH)DK^MoeZ&3b4v?kH_WkFpC#kH7k2Xc7NG3ZH8_3om{65lB^6YLBqB_W+7z2DpFtB(|>D_d1 z$CFur+@)e&78r?anOM;O-_{mwiqak1%2AxN^68aEqxCAGY(^|iyE0QeXG2itEfRq42)Ta3eLhQ}_}As-UdHqpr>-%nl*bF*K=9Vi2J&ew?Yj?1xz zT52{dM2vqa{I=jM(VEMtbRCN^p0DUc?IlcYToVS(e{)Q^8^1IU9NLxV zV5|?Bl9_@!(ia=Hi2eMc#<;^RAT+44=(2#;lWHkyJ6@LiQ`?w-SKAiFCvH|IFQ7sn zUuFC6rqQ)~W`Jg42HRJx;JUs*#@|EL){MV@o@P{}ROrz7jM(vz)BMGXgQZ(0R);Y{O87e5}Qz6u$gWfrVEvZV`y; zW6eb=k!(dHiozT-aee#lFnac(t)V#j)o_II!N}WHrB0bsOs*n?OlkBEI-W$G`_qah z^v%U2O69X}z^}FrBAd)2MyxyL6<3m#_iyIKhci!`dOE|-*m^)=O|07YZFyL$Ne?9> z$9s8|q1|C;GkFAn`jV*Uxy?fFr=Bnmafi>6)5QIx*v-;eUslD6mNRv*Y>4SIL?U?) z#IUIYDw;y3`ey^N4Uv*tS|Wq^0wZFhzb94sjY-=Hux~rA87np_`QI3eTN9ktM4Fgl zeLut3701jw4^o_zGTX1fFW}g&QY?7;b|m{IQd(j8UYX9#BeYyozqp?-VaA|Bccwr% zwasV<$RAqE!gKsN(_%G){vm0NzQ%Kc%hP>=({uYMk-q29$efW~Bj*pm0_*ElZ=s?y z2?b?roAtrwL9yKDO6>O2$%zm8z4U_k)8!96O81hcee%E7bxU5heG(}pOFG8L=1mO7 z8VJ*^k;e9Mm9)h$a1G>qO#_&YEY2(0s5fEotCYY5B}TVz{lc0;`#O&Y)YeWKOp|N%TPNA zv&Aq1b^FjVdSH(9(sUJ<9vz<#ShX#B5FS-VBX_{LdnR$R9C0c z>aspnrqc)K!rGwcypT*{h!96UO5@16OKhH*Awodn2X(?8(H?#rwepjl97wyGRv%V`{uIQ7r~8i`mm>9m!Vp=WnXV8d8=L?8=gl%B;*Ut^tH+*wz zmNF{3R>@P(XHmY}_3o0bDtb^^m^qkcGGYiWNO}3V`jJFY(yUjgNy@lL;78qii=K_K zt;M&3%%0ACwUfid=y*oPG;MRqmWr)g0 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�XP zM5L)&uZne^XHs;_L+03=Xy3CiU1O76^S{TWu{zY}Jlq((BV?9EL=m4MC%~!W0MzeW zOjQv*a;A7AS@l%h9EbjzQ3d}e&j~R0VCoAN)q_>=)m=>e=ZX9w8jM3&o1RO^+0jJ) z

_|h)w;)ME+|h#gx@oo-|ZEuRI5d) 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 z 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 z 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 KvHt-#rc|>H2mv<$ diff --git a/Simple Chat Colors/addons/sourcemod/scripting/include/simple-plugins.inc b/Simple Chat Colors/addons/sourcemod/scripting/include/simple-plugins.inc deleted file mode 100644 index 8f21956..0000000 --- a/Simple Chat Colors/addons/sourcemod/scripting/include/simple-plugins.inc +++ /dev/null @@ -1,337 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Plugins -Description: - Included file for core plugin in the Simple Plugins project -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -*************************************************************************/ - -#if defined _simpleplugin_included - #endinput -#endif - -#define _simpleplugin_included - -#define CORE_INC_VERSION "1.1.$Rev$" - -#pragma semicolon 1 -#include -#undef REQUIRE_PLUGIN -#include -#define REQUIRE_PLUGIN -#undef REQUIRE_EXTENSIONS -#undef AUTOLOAD_EXTENSIONS -#tryinclude -#tryinclude -#tryinclude -#define AUTOLOAD_EXTENSIONS -#define REQUIRE_EXTENSIONS - -enum e_SupportedMods -{ - GameType_Unknown, - GameType_AOC, - GameType_CSS, - GameType_DOD, - GameType_FF, - GameType_HIDDEN, - GameType_HL2DM, - GameType_INS, - GameType_L4D, - GameType_NEO, - GameType_SGTLS, - GameType_TF, - GameType_ZPS -}; - -enum e_Teams -{ - Unknown, - Spectator, - Team1, - Team2 -}; - -new g_aCurrentTeams[e_Teams]; -new e_SupportedMods:g_CurrentMod; -new String:g_sGameName[e_SupportedMods][32] = { "Unknown", - "Age of Chivalry", - "Counter Strike", - "Day Of Defeat", - "Fortress Forever", - "Hidden: Source", - "Half Life 2: Deathmatch", - "Insurgency", - "Left 4 Dead", - "Neotokyo", - "Stargate TLS", - "Team Fortress 2", - "Zombie Panic: Source" - }; - -public SharedPlugin:_pl_simpleplugin = -{ - name = "simple-plugins", - file = "simple-plugins.smx", -#if defined REQUIRE_PLUGIN - required = 1 -#else - required = 0 -#endif -}; - -#if !defined REQUIRE_PLUGIN -public _pl_simpleplugin_SetNTVOptional() -{ - MarkNativeAsOptional("SM_MovePlayer"); - MarkNativeAsOptional("SM_SetForcedTeam"); - MarkNativeAsOptional("SM_GetForcedTeam"); - MarkNativeAsOptional("SM_ClearForcedTeam"); - MarkNativeAsOptional("SM_GetForcedPlayer"); - MarkNativeAsOptional("SM_AssignBuddy"); - MarkNativeAsOptional("SM_SearchBuddy"); - MarkNativeAsOptional("SM_LockBuddy"); - MarkNativeAsOptional("SM_IsBuddyLocked"); - MarkNativeAsOptional("SM_ClearBuddy"); - MarkNativeAsOptional("SM_IsValidAdmin"); - MarkNativeAsOptional("SM_IsValidTeam"); -} -#endif - -/********************************************************************** - * When a player has to moved - * - * @param plugin Plugin that initiated the move - * @param client The client index of the player that was moved - * @param team The team index the player was moved to - * @noreturn - **********************************************************************/ -forward SM_OnPlayerMoved(Handle:plugin, client, team); - -/********************************************************************** - * Move a player to the supplied team - * - * @param client The client index of the player to be moved - * @param team The team to move the player to - * @noreturn - * @error Invalid client or team index - **********************************************************************/ -native SM_MovePlayer(client, team); - -/********************************************************************** - * Move a player to the supplied team - * - * @param client The client index of the player to set - * @param team The team to move the to set - * @param override Whether or not to override another plugin - * @return True if successful, false if not - * @error Invalid client or team index - **********************************************************************/ -native SM_SetForcedTeam(client, team, bool:override = false); - -/********************************************************************** - * Gets the client's forced team index - * - * @param client The client index of the player to check - * @param plugin Optional: The plugin handle of the plugin - that set the team - * @return The team index of the forced team - Zero if no forced team - * @error Invalid client index - **********************************************************************/ -native SM_GetForcedTeam(client, &Handle:plugin = INVALID_HANDLE); - -/********************************************************************** - * Clears a client's forced team - * - * @param client The client index of the player to check - * @return True if successful, false if not - * @error Invalid client index - **********************************************************************/ -native SM_ClearForcedTeam(client); - -/********************************************************************** - * Gets a forced player on the wrong that is currently on the wrong team - * This will only return a player if the calling plugin assigned the team - * - * @param team The team index the player should be on - * @return The client index of the player - Zero if no player found - * @error Invalid client index - **********************************************************************/ -native SM_GetForcedPlayer(team); - -/********************************************************************** - * Assign a players buddy - * - * @param client The client index of the player to assign - * @param player The player index of the player to assign - * @param override Whether or not to override a player lock - * @return True if successful, false if not - * @error Invalid client or player index - **********************************************************************/ -native bool:SM_AssignBuddy(client, player, bool:override = false); - -/********************************************************************** - * Rturns the client's buddy - * - * @param client The client index of the player to assign - * @return The client index of the player's buddy - Zero if no buddy - * @error Invalid client index - **********************************************************************/ -native SM_GetClientBuddy(client); - -/********************************************************************** - * Set the buddy lock setting for a client - * - * @param client The client index of the player to assign - * @param setting Setting to set, True or False - * @return True if successful, false if not - * @error Invalid client index - **********************************************************************/ -native bool:SM_LockBuddy(client, bool:setting); - -/********************************************************************** - * Returns the buddy lock setting for a client - * - * @param client The client index of the player to assign - * @return True if locked, false if not - * @error Invalid client index - **********************************************************************/ -native bool:SM_IsBuddyLocked(client); - -/********************************************************************** - * Clear a players buddy - * - * @param client The client index of the player to clear - * @param override Whether or not to override a player lock - * @return True if successful, false if not - * @error Invalid client index - **********************************************************************/ -native bool:SM_ClearBuddy(client, bool:override = false); - -/********************************************************************** - * Determine if the player has the supplied flags - * ADMFLAG_ROOT will always return true - * - * @param client The client index of the player to assign - * @param flags The char flag(s) to check against - * @return True if valid, false if not - **********************************************************************/ -native bool:SM_IsValidAdmin(client, const String:flags[]); - - -/********************************************************************** - * Determine if the team is a valid team - * - * @param team The team index to determine if valid for - currently installed/supported mod - * @return True if valid, false if not - **********************************************************************/ -native bool:SM_IsValidTeam(team); - - -public e_SupportedMods:GetCurrentMod() -{ - new String:sGameType[64]; - GetGameFolderName(sGameType, sizeof(sGameType)); - - if (StrEqual(sGameType, "aoc", false)) - { - return GameType_AOC; - } - if (StrEqual(sGameType, "cstrike", false)) - { - return GameType_CSS; - } - if (StrEqual(sGameType, "dod", false)) - { - return GameType_DOD; - } - if (StrEqual(sGameType, "ff", false)) - { - return GameType_FF; - } - if (StrEqual(sGameType, "hidden", false)) - { - return GameType_HIDDEN; - } - if (StrEqual(sGameType, "hl2mp", false)) - { - return GameType_FF; - } - if (StrEqual(sGameType, "insurgency", false) || StrEqual(sGameType, "ins", false)) - { - return GameType_INS; - } - if (StrEqual(sGameType, "l4d", false)) - { - return GameType_L4D; - } - if (StrEqual(sGameType, "nts", false)) - { - return GameType_NEO; - } - if (StrEqual(sGameType, "sgtls", false)) - { - return GameType_SGTLS; - } - if (StrEqual(sGameType, "tf", false)) - { - return GameType_TF; - } - if (StrEqual(sGameType, "zps", false)) - { - return GameType_ZPS; - } - return GameType_Unknown; -} - -public LoadCurrentTeams() -{ - switch (g_CurrentMod) - { - case GameType_INS: - { - g_aCurrentTeams[Unknown] = 0; - g_aCurrentTeams[Spectator] = 3; - g_aCurrentTeams[Team1] = 1; - g_aCurrentTeams[Team2] = 2; - } - case default: - { - g_aCurrentTeams[Unknown] = 0; - g_aCurrentTeams[Spectator] = 1; - g_aCurrentTeams[Team1] = 2; - g_aCurrentTeams[Team2] = 3; - } - } -} diff --git a/Simple Chat Colors/addons/sourcemod/scripting/simple-alltalkmanager.sp b/Simple Chat Colors/addons/sourcemod/scripting/simple-alltalkmanager.sp deleted file mode 100644 index c848332..0000000 --- a/Simple Chat Colors/addons/sourcemod/scripting/simple-alltalkmanager.sp +++ /dev/null @@ -1,515 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple AllTalk Manager -Description: - Allows you to set alltalk at different times -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#pragma semicolon 1 -#include -#include - -#define PLUGIN_VERSION "1.4.$Rev$" - -new Handle:satm_enabled = INVALID_HANDLE; -new Handle:satm_threshold_enabled = INVALID_HANDLE; -new Handle:satm_player_threshold = INVALID_HANDLE; -new Handle:satm_threshold_setting = INVALID_HANDLE; -new Handle:satm_logactivity = INVALID_HANDLE; -new Handle:satm_alltalk = INVALID_HANDLE; - -new Handle:g_aEventNames = INVALID_HANDLE; -new Handle:g_aEventReasons = INVALID_HANDLE; -new Handle:g_aEventSettings = INVALID_HANDLE; - -new bool:g_bLastThreshold = false; -new bool:g_bEnabled = true; -new bool:g_bThresholdEnabled = true; -new bool:g_bIsSetupMap = false; -new bool:g_bIsGameTF2 = false; -new bool:g_bLogActivity = false; - -new g_iLastEventIndex; - -public Plugin:myinfo = -{ - name = "Simple AllTalk Manager", - author = "Simple Plugins", - description = "Allows you to set alltalk at different times", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -} - -/** -Sourcemod callbacks -*/ -public OnPluginStart() -{ - - /** - Need to create all of our console variables. - */ - CreateConVar("satm_version", PLUGIN_VERSION, "Simple AllTalk Manager", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - satm_enabled = CreateConVar("satm_enabled", "1", "Enables/Disables Simple AllTalk Manager", _, true, 0.0, true, 1.0); - satm_threshold_enabled = CreateConVar("satm_threshold_enabled", "1", "Enables/Disables player threshold", _, true, 0.0, true, 1.0); - satm_player_threshold = CreateConVar("satm_player_threshold", "8", "Amount of players for the threshold"); - satm_threshold_setting = CreateConVar("satm_threshold_setting", "1", "Enables/Disables all talk up to player threshold, with the opposite set after the threshold", _, true, 0.0, true, 1.0); - satm_logactivity = CreateConVar("satm_logactivity", "0", "Enables/Disables log activity", _, true, 0.0, true, 1.0); - satm_alltalk = FindConVar("sv_alltalk"); - - /** - Hook console variables - */ - HookConVarChange(satm_enabled, ConVarSettingsChanged); - HookConVarChange(satm_threshold_enabled, ConVarSettingsChanged); - HookConVarChange(satm_player_threshold, ConVarSettingsChanged); - HookConVarChange(satm_logactivity, ConVarSettingsChanged); - - /** - Remove the notify flag from all talk cvar since we do it - */ - SetConVarFlags(satm_alltalk, GetConVarFlags(satm_alltalk)~FCVAR_NOTIFY); - - /** - Get the game type. We only care if it's TF2 - */ - new String:sGameType[64]; - GetGameFolderName(sGameType, sizeof(sGameType)); - if (StrEqual(sGameType, "tf", false)) - { - g_bIsGameTF2 = true; - } - - /** - Create the arrays - */ - g_aEventNames = CreateArray(255, 1); - g_aEventReasons = CreateArray(255, 1); - g_aEventSettings = CreateArray(1, 1); - - /** - Need to register the commands we are going to create and use. - */ - RegAdminCmd("sm_reloadatconfig", Command_Reload, ADMFLAG_GENERIC, "Reloads settings from config file"); - - /** - Create the config file - */ - AutoExecConfig(true); - - /** - Load the events from the config - */ - LoadEventsFromConfig(); -} - -public OnConfigsExecuted() -{ - - /** - Load up the settings - */ - g_bEnabled = GetConVarBool(satm_enabled); - g_bLogActivity = GetConVarBool(satm_logactivity); - g_bThresholdEnabled = GetConVarBool(satm_threshold_enabled); -} - -public OnMapStart() -{ - - /** - Reset the globals - */ - g_iLastEventIndex = 0; - g_bLastThreshold = false; - - /** - Check the map type if we are in TF2 - */ - if (g_bIsGameTF2) - { - g_bIsSetupMap = IsSetupPeriodMap(); - } - - /** - Set AllTalk - */ - if (g_bEnabled) - { - SetConVarBool(satm_alltalk, true); - } -} - -public OnClientDisconnect_Post(client) -{ - if (g_bEnabled) - { - SetAllTalk(-1); - } -} - -public OnClientPostAdminCheck(client) -{ - if (g_bEnabled) - { - SetAllTalk(-1); - } - CreateTimer(2.0, Timer_ShowAllTalkStatus, client, TIMER_FLAG_NO_MAPCHANGE); -} - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (convar == satm_enabled) - { - if (StringToInt(newValue)) - { - g_bEnabled = true; - } - else - { - g_bEnabled = false; - } - } - else if (convar == satm_threshold_enabled) - { - if (StringToInt(newValue)) - { - g_bThresholdEnabled = true; - } - else - { - g_bThresholdEnabled = false; - } - } - else if (convar == satm_logactivity) - { - if (StringToInt(newValue)) - { - g_bLogActivity = true; - } - else - { - g_bLogActivity = false; - } - } - if (g_bEnabled) - { - SetAllTalk(-1); - } -} - -/** -Commands -*/ -public Action:Command_Reload(client, args) -{ - - /** - Clear the array - */ - ClearArray(g_aEventNames); - ClearArray(g_aEventReasons); - ClearArray(g_aEventSettings); - - /** - Load the events from the config - */ - LoadEventsFromConfig(); - - return Plugin_Handled; -} - -/** -Game Event Hooks -*/ -public Hook_All_Events(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (!g_bIsSetupMap) - { - if (StrEqual(name, "teamplay_round_start")) - { - if (FindStringInArray(g_aEventNames, "teamplay_setup_finished") != -1) - { - g_iLastEventIndex = FindStringInArray(g_aEventNames, "teamplay_setup_finished"); - if (g_bEnabled) - { - SetAllTalk(g_iLastEventIndex); - return; - } - } - } - } - g_iLastEventIndex = FindStringInArray(g_aEventNames, name); - if (g_bEnabled) - { - SetAllTalk(g_iLastEventIndex); - } -} - -/** -Timers -*/ -public Action:Timer_ShowAllTalkStatus(Handle:timer, any:client) -{ - if (IsClientConnected(client) && IsClientInGame(client)) - { - new bool:bSetting = GetConVarBool(satm_alltalk); - if (bSetting) - { - PrintToChat(client, "\x01\x04[SM] AllTalk is \x01[on]"); - } - else - { - PrintToChat(client, "\x01\x04[SM] AllTalk is \x01[off]"); - } - } -} - -/** -Stock Functions -*/ -stock LoadEventsFromConfig() -{ - - /** - Make sure the config file is here and load it up - */ - new String:sConfigFile[256]; - BuildPath(Path_SM, sConfigFile, sizeof(sConfigFile), "configs/simple-alltalkmanager_events.cfg"); - if (!FileExists(sConfigFile)) - { - - /** - Config file doesn't exists, stop the plugin - */ - LogError("[SATM] Simple AllTalk Manager is not running! Could not find file %s", sConfigFile); - SetFailState("Could not find file %s", sConfigFile); - } - - /** - Create the arrays and variables - */ - new String:sGameEventName[256]; - new String:sReason[256]; - new iSetting; - - /** - Load config file as a KeyValues file - */ - new Handle:kvGameEvents = CreateKeyValues("game_events"); - FileToKeyValues(kvGameEvents, sConfigFile); - - if (!KvGotoFirstSubKey(kvGameEvents)) - { - return; - } - - /** - Hook the game events and load the settings - */ - do - { - - /** - Get the section name; this should be the event name - */ - KvGetSectionName(kvGameEvents, sGameEventName, sizeof(sGameEventName)); - if (!HookEventEx(sGameEventName, Hook_All_Events, EventHookMode_PostNoCopy)) - { - - /** - Could not hook this event, stop the plugin - */ - SetFailState("Could not hook event %s", sGameEventName); - } - else - { - if (g_bLogActivity) - { - LogMessage("[SATM] Hooked event: %s", sGameEventName); - } - } - - /** - Get the reason string and setting - */ - KvGetString(kvGameEvents, "reason", sReason, sizeof(sReason)); - iSetting = KvGetNum(kvGameEvents, "setting"); - if (g_bLogActivity) - { - LogMessage("[SATM] Event reason string: %s", sReason); - LogMessage("[SATM] Event setting: %i", iSetting); - } - - /** - Push the values to the arrays - */ - PushArrayString(g_aEventNames, sGameEventName); - PushArrayString(g_aEventReasons, sReason); - PushArrayCell(g_aEventSettings, iSetting); - } while (KvGotoNextKey(kvGameEvents)); - - /** - Close our handle - */ - CloseHandle(kvGameEvents); -} - -stock SetAllTalk(index) -{ - new iPlayerThreshold = GetConVarInt(satm_player_threshold); - new bool:bThresholdMet = ((GetClientCount() >= iPlayerThreshold) ? true : false); - new bool:bSetting; - - if (g_bThresholdEnabled) - { - if (bThresholdMet) - { - if (index == -1) - { - if (bThresholdMet != g_bLastThreshold) - { - g_bLastThreshold = true; - bSetting = !GetConVarBool(satm_threshold_setting); - new bool:bLastSetting = GetArrayCell(g_aEventSettings, g_iLastEventIndex); - if (bLastSetting && !bSetting) - { - bSetting = GetArrayCell(g_aEventSettings, g_iLastEventIndex); - } - } - else - { - bSetting = GetArrayCell(g_aEventSettings, g_iLastEventIndex); - } - } - else - { - bSetting = GetArrayCell(g_aEventSettings, index); - } - } - else - { - g_bLastThreshold = false; - bSetting = GetConVarBool(satm_threshold_setting); - } - } - else - { - if (index != -1) - { - bSetting = GetArrayCell(g_aEventSettings, index); - } - } - - if (GetConVarBool(satm_alltalk) != bSetting) - { - - SetConVarBool(satm_alltalk, bSetting); - - new String:sReason[256]; - if (index == -1) - { - Format(sReason, sizeof(sReason), "Player Threshold"); - } - else - { - if (!g_bIsSetupMap) - { - new String:sCurrentEvent[256]; - GetArrayString(g_aEventNames, index, sCurrentEvent, sizeof(sCurrentEvent)); - if (StrEqual(sCurrentEvent, "teamplay_setup_finished")) - { - new iRoundStartIndex = FindStringInArray(g_aEventNames, "teamplay_round_start"); - if (iRoundStartIndex != -1) - { - GetArrayString(g_aEventReasons, iRoundStartIndex, sReason, sizeof(sReason)); - } - else - { - GetArrayString(g_aEventReasons, index, sReason, sizeof(sReason)); - } - } - else - { - GetArrayString(g_aEventReasons, index, sReason, sizeof(sReason)); - } - } - else - { - GetArrayString(g_aEventReasons, index, sReason, sizeof(sReason)); - } - } - - if (bSetting) - { - PrintToChatAll("\x01\x04[SM] AllTalk turned \x01[on] \x04due to:\x01 %s", sReason); - } - else - { - PrintToChatAll("\x01\x04[SM] AllTalk turned \x01[off] \x04due to:\x01 %s", sReason); - } - } -} - -stock bool:IsSetupPeriodMap() -{ - new iEnt = -1; - new String:sMapName[32]; - - GetCurrentMap(sMapName, sizeof(sMapName)); - - if (strncmp(sMapName, "cp_", 3, false) == 0) - { - new iTeam; - while ((iEnt = FindEntityByClassname(iEnt, "team_control_point")) != -1) - { - iTeam = GetEntProp(iEnt, Prop_Send, "m_iTeamNum"); - - /** - If there is a blu CP or a neutral CP, then it's not an attack/defend map - */ - if (iTeam != 2) - { - //this is a push map - return false; - } - } - //this is a attack/defend map - return true; - } - else if (strncmp(sMapName, "ctf_", 3, false) == 0) - { - //this is a ctf map - return false; - } - return false; -} diff --git a/Simple Chat Colors/addons/sourcemod/scripting/simple-autoscrambler.sp b/Simple Chat Colors/addons/sourcemod/scripting/simple-autoscrambler.sp deleted file mode 100644 index 6c6799e..0000000 --- a/Simple Chat Colors/addons/sourcemod/scripting/simple-autoscrambler.sp +++ /dev/null @@ -1,459 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple AutoScrambler -Description: - Automatically scrambles the teams based upon a number of events. -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include - -#define PLUGIN_VERSION "1.1.$Rev$" - -/** -Different scramble modes: - -1 = Full Scramble, dont restart round. -2 = Admins Immune, dont restart round. -3 = Full Scramble, restart round and reset scores. -4 = Admins Immune, restart round and reset scores. - -*/ - -/** -Different top player modes: - -1 = Divide Top 4 players on the two teams. -2 = Protect the Top 2 players on each team. - -*/ - -enum PlayerData -{ - Handle:hForcedTimer, - bool:bProtected; -}; - -/** -Cvars used for admins -*/ -new Handle: sas_admin_immunity_enabled = INVALID_HANDLE, - Handle: sas_admin_flag_scramblenow = INVALID_HANDLE, - Handle: sas_admin_flag_immunity = INVALID_HANDLE; - -/** -Cvars used for autoscramble -*/ -new Handle: sas_autoscramble_enabled = INVALID_HANDLE, - Handle: sas_autoscramble_minplayers = INVALID_HANDLE, - Handle: sas_autoscramble_mode = INVALID_HANDLE, - Handle: sas_autoscramble_winstreak = INVALID_HANDLE, - Handle: sas_autoscramble_steamroll = INVALID_HANDLE, - Handle: sas_autoscramble_frags = INVALID_HANDLE; - -/** -Cvars used for voting -*/ -new Handle: sas_vote_enabled = INVALID_HANDLE, - Handle: sas_vote_upcount = INVALID_HANDLE, - Handle: sas_vote_winpercent = INVALID_HANDLE, - Handle: sas_vote_mode = INVALID_HANDLE, - Handle: sas_vote_minplayers = INVALID_HANDLE; - -/** -Additional cvars -*/ -new Handle: sas_enabled = INVALID_HANDLE, - Handle: sas_timer_scrambledelay = INVALID_HANDLE, - Handle: TFGameModeArena = INVALID_HANDLE; - -/** -Timers -*/ -new Handle: g_hScrambleTimer = INVALID_HANDLE; - -/** - Player arrays - */ -new g_aPlayers[MAXPLAYERS + 1][PlayerData]; - -/** - Cvar variables - */ -new bool: g_bIsEnabled, - bool: g_bIsAutoScrambleEnabled, - bool: g_bIsVoteEnabled, - bool: g_bIsAdminImmunityEnabled; -new Float: g_fTimer_ScrambleDelay, - Float: g_fVote_UpCount, - Float: g_fVote_WinPercent; -new g_iAutoScramble_Minplayers, - g_iAutoScramble_Mode, - g_iAutoScramble_WinStreak, - g_iAutoScramble_SteamRoll, - g_iAutoScramble_Frags, - g_iVote_Mode, - g_iVote_MinPlayers; -new String: g_sScrambleNowFlag[5], - String: g_sAdminImmunityFlag[5]; - -/** -Other globals -*/ -new g_iMaxEntities, - g_iOwnerOffset; - -public Plugin:myinfo = -{ - name = "Simple AutoScrambler", - author = "Simple Plugins", - description = "Automatically scrambles the teams based upon a number of events.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -public OnPluginStart() -{ - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[SAS] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - switch (g_CurrentMod) - { - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_Post); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_Post); - } - } - - /** - Create console variables - */ - CreateConVar("sas_version", PLUGIN_VERSION, "Simple AutoScrambler Version",FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - sas_enabled = CreateConVar("sas_enabled", "1", "Enable/Disable Simple AutoScrambler"); - sas_timer_scrambledelay = CreateConVar("sas_timer_scrambledelay", "5.0", "Delay used after a scramble has been started", _, true, 1.0, true, 30.0); - - /** - Cvars used for admins - */ - sas_admin_immunity_enabled = CreateConVar("sas_admin_immunity_enabled", "1", "Enable/Disable admin immunity for scrambles"); - sas_admin_flag_scramblenow = CreateConVar("sas_admin_flag_scramblenow", "z", "Admin flag to use for scramblenow function/command"); - sas_admin_flag_immunity = CreateConVar("sas_admin_flag_immunity", "z", "Admin flag to use for scramble immunity"); - - /** - Cvars used for autoscramble - */ - sas_autoscramble_enabled = CreateConVar("sas_autoscramble_enabled", "1", "Enable/Disable the autoscramble function"); - sas_autoscramble_minplayers = CreateConVar("sas_autoscramble_minplayers", "16", "Min players needed to start an autoscramble"); - sas_autoscramble_mode = CreateConVar("sas_autoscramble_mode", "1", "Scramble mode used when autoscrambling"); - sas_autoscramble_winstreak = CreateConVar("sas_autoscramble_winstreak", "5", "Max amount of wins in a row a team can achieve before an autoscramble starts"); - sas_autoscramble_steamroll = CreateConVar("sas_autoscramble_steamroll", "120", "Shortest amount of time a team can win by before an autoscramble starts (seconds)"); - sas_autoscramble_frags = CreateConVar("sas_autoscramble_frags", "1", "Min players needed to start a vote and scramble"); - - /** - Cvars used for voting - */ - sas_vote_enabled = CreateConVar("sas_vote_enabled", "1", "Enable/Disable voting for scramble"); - sas_vote_upcount = CreateConVar("sas_vote_upcount", "5", "Amount of people wanting a scramble before a vote starts. If less than 1 it will be considered a percentage. (ie 0.5 = 50% | 1 = 1 Player | 5 = 5 Players)"); - sas_vote_winpercent = CreateConVar("sas_vote_winpercent", "0.6", "Percentage of votes needed to scramble", _, true, 0.0, true, 1.0); - sas_vote_mode = CreateConVar("sas_vote_mode", "1", "Scramble mode used when a vote results in a scramble"); - sas_vote_minplayers = CreateConVar("sas_vote_minplayers", "16", "Min players needed to start a vote and scramble"); - - /** - Hook the console variables if they change - */ - HookConVarChange(sas_enabled, ConVarSettingsChanged); - HookConVarChange(sas_timer_scrambledelay, ConVarSettingsChanged); - HookConVarChange(sas_admin_immunity_enabled, ConVarSettingsChanged); - HookConVarChange(sas_admin_flag_scramblenow, ConVarSettingsChanged); - HookConVarChange(sas_admin_flag_immunity, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_enabled, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_minplayers, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_mode, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_winstreak, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_steamroll, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_frags, ConVarSettingsChanged); - HookConVarChange(sas_vote_enabled, ConVarSettingsChanged); - HookConVarChange(sas_vote_upcount, ConVarSettingsChanged); - HookConVarChange(sas_vote_winpercent, ConVarSettingsChanged); - HookConVarChange(sas_vote_mode, ConVarSettingsChanged); - HookConVarChange(sas_vote_minplayers, ConVarSettingsChanged); - - /** - Register the command - */ - RegConsoleCmd("sm_scramblenow", Command_ScrambleNow, "sm_scramblenow (mode): Scrambles the teams"); - - /** - Load translations and .cfg file - */ - LoadTranslations ("simpleautoscrambler.phrases"); - AutoExecConfig(true, "plugin.simpleautoscrambler"); - LogAction(0, -1, "[SAS] Simple AutoScrambler is loaded."); -} - -public OnAllPluginsLoaded() -{ - //something -} - -public OnLibraryRemoved(const String:name[]) -{ - //something -} - -public OnConfigsExecuted() -{ - - /** - Load up all the variable defaults - */ - LoadUpVariables(); - - /** - Log our activity - */ - if (g_bIsEnabled) - LogAction(0, -1, "Simple AutoScrambler is ENABLED"); - else - LogAction(0, -1, "Simple AutoScrambler is DISABLED"); -} - -public Action:Command_ScrambleNow(client, args) -{ - - /** - Make sure we are enabled - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the client is authorized to run this command. - */ - if (!SM_IsValidAdmin(client, g_sScrambleNowFlag)) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure it's ok to scramble at this time - */ - if (!OkToScramble) - { - return Plugin_Handled; - } - - /** - Make sure it's ok to scramble at this time - */ - LogAction(0, -1, "[SAS] The scramblenow command was used"); - - /** - Scramble the teams - */ - StartAScramble(); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - -} - -public Action:Timer_ScrambleTeams(Handle:timer, any:mode) -{ - - /** - Make sure it's still ok to scramble - */ - if (!OkToScramble) - { - return Plugin_Handled; - } - - - switch (mode) - { - case - - - - } - - - /** - Reset the handle because the timer is over and the callback is done - */ - g_hScrambleTimer = INVALID_HANDLE; - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - -} - -stock StartAScramble(mode) -{ - - /** - See if we are already started a scramble - */ - if (g_hScrambleTimer == INVALID_HANDLE) - { - - /** - There is a scramble in progress - */ - return; - - } - - /** - Report that a scramble is about to start - */ - PrintCenterTextAll("%T", "Scramble", LANG_SERVER); - - /** - Start a timer and log the action - */ - g_hScrambleTimer = CreateTimer(g_fTimer_ScrambleDelay, Timer_ScrambleTeams, mode, TIMER_FLAG_NO_MAPCHANGE); - LogAction(0, -1, "[SAS] A scamble timer was started"); -} - -stock bool:OkToScramble() -{ - -} - -stock LoadUpVariables() -{ - g_bIsEnabled = GetConVarBool(sas_enabled); - g_bIsAutoScrambleEnabled = GetConVarBool(sas_autoscramble_enabled); - g_bIsVoteEnabled = GetConVarBool(sas_vote_enabled); - g_bIsAdminImmunityEnabled = GetConVarBool(sas_admin_immunity_enabled); - g_iAutoScramble_Minplayers = GetConVarInt(sas_autoscramble_minplayers); - g_iAutoScramble_Mode = GetConVarInt(sas_autoscramble_mode); - g_iAutoScramble_WinStreak = GetConVarInt(sas_autoscramble_winstreak); - g_iAutoScramble_SteamRoll = GetConVarInt(sas_autoscramble_steamroll); - g_iAutoScramble_Frags = GetConVarInt(sas_autoscramble_frags); - g_iVote_Mode = GetConVarInt(sas_vote_mode); - g_iVote_MinPlayers = GetConVarInt(sas_vote_minplayers); - GetConVarString(sas_admin_flag_scramblenow, g_sScrambleNowFlag, sizeof(g_sScrambleNowFlag)); - GetConVarString(sas_admin_flag_immunity, g_sAdminImmunityFlag, sizeof(g_sAdminImmunityFlag)); - g_fTimer_ScrambleDelay = GetConVarFloat(sas_timer_scrambledelay); - g_fVote_UpCount = GetConVarFloat(sas_vote_upcount); - g_fVote_WinPercent = GetConVarFloat(sas_vote_winpercent); - g_iMaxEntities = GetMaxEntities(); - g_iOwnerOffset = FindSendPropInfo("CBaseObject", "m_hBuilder"); -} - -stock TF2_DestroyBuildings(client) -{ - - /** - We have to start a loop to check the owner of all the valid entities - */ - for (new i = MaxClients + 1; i <= g_iMaxEntities; i++) - { - if (!IsValidEntity(i)) - { - - /** - Not valid, continue to next one - */ - continue; - } - - /** - Get the name of the current entity - */ - decl String:sNetClass[32]; - GetEntityNetClass(i, sNetClass, sizeof(sNetClass)); - - /** - See if its something that an engineer would build - */ - if (strcmp(sNetClass, "CObjectSentrygun") == 0 - || strcmp(sNetClass, "CObjectTeleporter") == 0 - || strcmp(sNetClass, "CObjectDispenser") == 0) - { - - /** - It is, so lets check the owner - */ - if (GetEntDataEnt2(i, g_iOwnerOffset) == client) - { - - /** - It's the clients building, so we blow it up. - */ - SetVariantInt(9999); - AcceptEntityInput(i, "RemoveHealth"); - } - } - } -} \ No newline at end of file diff --git a/Simple Chat Colors/addons/sourcemod/scripting/simple-donatorbenefits.sp b/Simple Chat Colors/addons/sourcemod/scripting/simple-donatorbenefits.sp deleted file mode 100644 index e3f6845..0000000 --- a/Simple Chat Colors/addons/sourcemod/scripting/simple-donatorbenefits.sp +++ /dev/null @@ -1,1312 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Donator Benefits -Description: - Provides donator benefits to players -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include -#include - -#define PLUGIN_VERSION "1.1.$Rev$" - -#define CHAT_SYMBOL '@' -#define CHAT_MAX_MESSAGE_LENGTH 1024 - -enum PlayerData -{ - bool:bIsDonator, - bool:bQueue, - bool:bImmune, - iHealthCount, - iNewTeam -}; - -/** - Public convar handles - */ -new Handle:sdb_enabled = INVALID_HANDLE; -new Handle:sdb_donationflag = INVALID_HANDLE; -new Handle:sdb_soundfile = INVALID_HANDLE; -new Handle:sdb_joinsound_enabled = INVALID_HANDLE; -new Handle:sdb_joinpubmsg_enabled = INVALID_HANDLE; -new Handle:sdb_joinprivmsg_enabled = INVALID_HANDLE; -new Handle:sdb_chatcolors_enabled = INVALID_HANDLE; -new Handle:sdb_immunity_enabled = INVALID_HANDLE; -new Handle:sdb_ubercharge_enabled = INVALID_HANDLE; -new Handle:sdb_givehealth_enabled = INVALID_HANDLE; -new Handle:sdb_nofalldmg_enabled = INVALID_HANDLE; -new Handle:sdb_fastheavy_enabled = INVALID_HANDLE; -new Handle:sdb_swapteam_enabled = INVALID_HANDLE; -new Handle:sdb_chatcolor = INVALID_HANDLE; -new Handle:sdb_uberlevel = INVALID_HANDLE; -new Handle:sdb_healthcount = INVALID_HANDLE; -new Handle:sdb_healthbonus = INVALID_HANDLE; -new Handle:sdb_heavymultiplier = INVALID_HANDLE; - -/** -Create global enable/disable bools so we don't have to check the console variable on every call -*/ -new bool:g_bIsEnabled = true; -new bool:g_bIsJoinSoundEnabled = true; -new bool:g_bIsJoinPubMsgEnabled = true; -new bool:g_bIsJoinPrivMsgEnabled = true; -new bool:g_bIsChatColorsEnabled = true; -new bool:g_bIsImmuntyEnabled = true; -new bool:g_bIsUberChargeEnabled = true; -new bool:g_bIsGiveHealthEnabled = true; -new bool:g_bIsNoFallDmgEnabled = true; -new bool:g_bIsFastHeayEnabled = true; -new bool:g_bIsSwapTeamEnabled = true; - -/** - Player arrays - */ -new g_aPlayers[MAXPLAYERS + 1][PlayerData]; - - -/** -Rest of the globals -*/ -new bool:g_bRoundEnd = false; -new String:g_sCharDonatorFlag[5]; -new String:g_sSoundFile[PLATFORM_MAX_PATH]; -new String:g_sChatColor[11]; -new g_iHealthBonus; -new g_iHealthCount; -new g_iClassMaxHealth[TFClassType] = {0, 125, 125, 200, 175, 150, 300, 175, 125, 125}; -new g_fClassMaxSpeed[TFClassType] = {0, 400, 300, 240, 280, 320, 230, 300, 300, 300}; -new Float:g_fHeavyMultiplier = 0.0; -new Float:g_fUberLevel = 0.0; - -public Plugin:myinfo = -{ - name = "Simple Donation Benefits", - author = "Simple Plugins", - description = "Gives donators benefits to players", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -} - -public OnPluginStart() -{ - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[SDB] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_connect", HookPlayerSpawn, EventHookMode_Pre); - HookEvent("player_spawn", HookPlayerSpawn, EventHookMode_Post); - HookEvent("player_death", HookPlayerDeath, EventHookMode_Post); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Post); - switch (g_CurrentMod) - { - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - HookEvent("player_changeclass", HookPlayerClass, EventHookMode_Post); - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_Post); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - - /** - Create console variables - */ - CreateConVar("sdb_version", PLUGIN_VERSION, "Simple Donation Benefits", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - sdb_enabled = CreateConVar("sdb_enabled", "1", "Enable/Disable Simple Donation Benefits"); - sdb_donationflag = CreateConVar("sdb_donationflag", "a", "Flag ALREADY given to donators. Must be in char format"); - - /** - Create the enable/disable donator console variables - */ - sdb_joinsound_enabled = CreateConVar("sdb_joinsound_enabled", "1", "Enable/Disable donator join sound"); - sdb_joinpubmsg_enabled = CreateConVar("sdb_joinpubmsg_enabled", "1", "Enable/Disable public donator join message (replaces: as connected)"); - sdb_joinprivmsg_enabled = CreateConVar("sdb_joinprivmsg_enabled", "1", "Enable/Disable private donator join message (sent only to donator)"); - sdb_chatcolors_enabled = CreateConVar("sdb_chatcolors_enabled", "1", "Enable/Disable donator chat colors"); - sdb_immunity_enabled = CreateConVar("sdb_immunity_enabled", "1", "Enable/Disable donator round end immunity"); - sdb_ubercharge_enabled = CreateConVar("sdb_ubercharge_enabled", "1", "Enable/Disable donator medics starting with ubercharge"); - sdb_givehealth_enabled = CreateConVar("sdb_givehealth_enabled", "1", "Enable/Disable donator instant health bonus"); - sdb_nofalldmg_enabled = CreateConVar("sdb_nofalldmg_enabled", "1", "Enable/Disable no fall damage for donators"); - sdb_fastheavy_enabled = CreateConVar("sdb_fastheavy_enabled", "1", "Enable/Disable donator heavies moving faster while spinning"); - sdb_swapteam_enabled = CreateConVar("sdb_swampteam_enabled", "1", "Enable/Disable donator swap team ability"); - - /** - Create the donator setting console variables - */ - sdb_soundfile = CreateConVar("sdb_soundfile", "custom/donatorjoin.mp3", "The location of sound file"); - sdb_chatcolor = CreateConVar("sdb_chatcolor", "green", "Color to use for donator chat. Valid colors are green and lightgreen"); - sdb_uberlevel = CreateConVar("sdb_uberlevel", "0.5", "Uberlevel to give donator medic at spawn. 1.0 = full uber", _, true, 0.0, true, 1.0); - sdb_healthcount = CreateConVar("sdb_healthcount", "1", "Number of times a donator can use use instant health per life"); - sdb_healthbonus = CreateConVar("sdb_healthbonus", "100", "The amount of health to heal the donator"); - sdb_heavymultiplier = CreateConVar("sdb_heavyspeed", "0.5", "The speed multiplier for the fast heavy. Based on running speed. 1.0 = running speed. (Game Default is 0.20)", _, true, 0.0, true, 1.0); - - /** - Hook dukehacks calls - */ - dhAddClientHook(CHK_TakeDamage, Hacks_TakeDamageHook); - dhAddClientHook(CHK_PreThink, Hacks_PreThinkHook); - - /** - Hook the console variables if they change - */ - HookConVarChange(sdb_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_donationflag, ConVarSettingsChanged); - HookConVarChange(sdb_joinsound_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_joinpubmsg_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_joinprivmsg_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_chatcolors_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_immunity_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_ubercharge_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_givehealth_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_nofalldmg_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_swapteam_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_fastheavy_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_soundfile, ConVarSettingsChanged); - HookConVarChange(sdb_chatcolor, ConVarSettingsChanged); - HookConVarChange(sdb_uberlevel, ConVarSettingsChanged); - HookConVarChange(sdb_healthcount, ConVarSettingsChanged); - HookConVarChange(sdb_healthbonus, ConVarSettingsChanged); - HookConVarChange(sdb_heavymultiplier, ConVarSettingsChanged); - - /** - Register the commands - */ - RegConsoleCmd("sm_swapteams", Command_SwapTeam, "sm_swapteams <[0]instant/[1]queued>: Swaps your team to the other team"); - RegConsoleCmd("sm_ihealth", Command_InstantHealth, "sm_ihealth: Gives you a instant health pack"); - RegAdminCmd("sm_teaser", Command_Teaser, ADMFLAG_GENERIC,"sm_teaser <[0]add/[1]remove>: Gives temporary donator privilages to a player"); - RegConsoleCmd("say", Command_Say); - - RegConsoleCmd("sm_test", Command_TEST); - - /** - Load the translations - */ - LoadTranslations("common.phrases"); - LoadTranslations("simpledonatorbenefits.phrases"); - - /** - Load or create the config file - */ - AutoExecConfig(true, "plugin.simpledonatorbenefits"); - LogAction(0, -1, "[SDB] Simple Donator Benefits is loaded."); -} - -public OnAllPluginsLoaded() -{ - //something -} - -public OnLibraryRemoved(const String:name[]) -{ - //something -} - -public OnConfigsExecuted() -{ - /** - Load up all the variable defaults - */ - LoadUpVariables(); - - /** - If the join sound is enabled, prep the sound files - */ - if (g_bIsJoinSoundEnabled) - PrepSoundFile(); - - /** - Log our activity - */ - if (g_bIsEnabled) - LogAction(0, -1, "Simple Donation Benefits is ENABLED"); - else - LogAction(0, -1, "Simple Donation Benefits is DISABLED"); -} - -public OnClientPostAdminCheck(client) -{ - - /** - Check if the client is a donator - */ - if (SM_IsValidAdmin(client, g_sCharDonatorFlag)) - { - - /** - They are, so we set the player array to true and start a timer for the sound or add - */ - g_aPlayers[client][bIsDonator] = true; - if (g_bIsJoinSoundEnabled || g_bIsJoinPrivMsgEnabled) - { - CreateTimer(10.0, Timer_DonatorJoined, client, TIMER_FLAG_NO_MAPCHANGE); - } - } - else - { - /** - They aren't, so we set the player array to false - */ - g_aPlayers[client][bIsDonator] = false; - } -} - -public OnClientDisconnect_Post(client) -{ - - /** - Clean up the player variables - */ - CleanUpPlayer(client); -} - -public Action:Command_SwapTeam(client, args) -{ - - /** - Make sure we are enabled - */ - if (!g_bIsEnabled || !g_bIsSwapTeamEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the command is not started by the server - */ - if (client == 0) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure the player is a donator - */ - if (!g_aPlayers[client][bIsDonator]) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Lets make sure the client is one a team we can swap. - If he is we set the global array to the opposite team. - */ - new iTeam = GetClientTeam(client); - if (iTeam == g_aCurrentTeams[Team1]) - { - g_aPlayers[client][iNewTeam] = g_aCurrentTeams[Team2]; - } - else if (iTeam == g_aCurrentTeams[Team2]) - { - g_aPlayers[client][iNewTeam] = g_aCurrentTeams[Team1]; - } - else - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "InValidTeam", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check to see if we have command arguments. - */ - if (GetCmdArgs()) - { - - /** - We do, so lets get it and see if the client wants to be switched instantly or queued for death. - */ - decl String:sArg[5]; - GetCmdArg(1, sArg, sizeof(sArg)); - new iWantsQue = StringToInt(sArg); - if (iWantsQue && !g_aPlayers[client][bQueue]) - { - - /** - He wants the que and isn't already in it, set the global array. - */ - g_aPlayers[client][bQueue] = true; - ReplyToCommand(client, "\x01\x04[STM]\x01 %T", "PlayerQueue", LANG_SERVER); - } - else if (!iWantsQue) - { - - /** - He wants to be switched right now, lets call the stock function. - */ - SM_MovePlayer(client, g_aPlayers[client][iNewTeam]); - } - } - else - { - - /** - There are no command arguments so we build and display the swap menu. - */ - new Handle:hPlayerMenu = BuildSwapModeMenu(); - DisplayMenu(hPlayerMenu, client, MENU_TIME_FOREVER); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_InstantHealth(client, args) -{ - - /** - Make sure we are enabled - */ - if (!g_bIsEnabled || !g_bIsGiveHealthEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the command is not started by the server - */ - if (client == 0) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure the player is a donator - */ - if (!g_aPlayers[client][bIsDonator]) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check health count to see if the player has reached the max - */ - if (g_aPlayers[client][iHealthCount] >= g_iHealthCount) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "ReachedCount", LANG_SERVER); - return Plugin_Handled; - } - - /** - Get the class of the player and the max health for that class - */ - new iHealth = GetClientHealth(client); - new TFClassType:PlayerClass = TF2_GetPlayerClass(client); - new iMaxHealth = g_iClassMaxHealth[PlayerClass]; - - /** - Check to see if the player is at the max health of the class - */ - if (iHealth >= iMaxHealth) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "AtMaxHealth", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check the current health - */ - if (iHealth + g_iHealthBonus >= iMaxHealth) - { - - /** - Raise them to max health if the current health + bonus would go above it - */ - SetEntityHealth(client, iMaxHealth); - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "ToMaxHealth", LANG_SERVER); - } - else - { - - /** - Give them the instant health bonus - */ - SetEntityHealth(client, iHealth + g_iHealthBonus); - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "HealthBonus", LANG_SERVER); - } - - /** - Increase the count - */ - g_aPlayers[client][iHealthCount] += 1; - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_Teaser(client, args) -{ - - /** - Make sure we are enabled - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Check to see if we have command arguments. - */ - new iCmdArgs = GetCmdArgs(); - if (iCmdArgs == 0) - { - - /** - We don't so display the player menu. - */ - new Handle:hPlayerMenu = BuildPlayerMenu(); - DisplayMenu(hPlayerMenu, client, MENU_TIME_FOREVER); - return Plugin_Handled; - } - - /** - We have some arguments, see if we can find the player - */ - decl String:sPlayer[64]; - GetCmdArg(1, sPlayer, sizeof(sPlayer)); - new iTarget = FindTarget(client, sPlayer, true, true); - if (iTarget == -1 || !IsClientInGame(iTarget)) - { - - /** - We don't know who this is, so display the player menu. - */ - new Handle:hPlayerMenu = BuildPlayerMenu(); - DisplayMenu(hPlayerMenu, client, MENU_TIME_FOREVER); - } - else - { - /** - We found the player, see if we are supposed to turn it on or off. - */ - if (iCmdArgs >= 2) - { - decl String:sOn[3]; - GetCmdArg(2, sOn, sizeof(sOn)); - if (StringToInt(sOn)) - { - - /** - Turn temp benefits on. - */ - g_aPlayers[iTarget][bIsDonator] = true; - } - else - { - - /** - Turn temp benefits on. - */ - g_aPlayers[iTarget][bIsDonator] = false; - } - } - else - { - - /** - We don't know what to do, so just turn it on. - */ - g_aPlayers[iTarget][bIsDonator] = true; - } - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_Say(client, args) -{ - - /** - Make sure we are enabled. - */ - if (client == 0 || IsChatTrigger() || !g_bIsChatColorsEnabled || !g_bIsEnabled) - { - return Plugin_Continue; - } - - /** - Check the client to see if they are a donator. - */ - if (g_aPlayers[client][bIsDonator]) - { - - /** - The client is, so get the chat message and strip it down. - */ - decl String:sArg[CHAT_MAX_MESSAGE_LENGTH], - String:sChatMsg[CHAT_MAX_MESSAGE_LENGTH]; - new bool:bAlive = IsPlayerAlive(client); - GetCmdArgString(sArg, sizeof(sArg)); - StripQuotes(sArg); - TrimString(sArg); - new startidx; - if (sArg[strlen(sArg)-1] == '"') - { - sArg[strlen(sArg)-1] = '\0'; - startidx = 1; - } - - /** - Bug out if they are using the admin chat symbol (admin chat). - */ - if (sArg[startidx] == CHAT_SYMBOL) - { - return Plugin_Continue; - } - - /** - Format the message. - */ - FormatMessage(client, 0, bAlive, sChatMsg, sArg); - - /** - Send the message. - */ - SayText2(0, client, sChatMsg); - - /** - We are done, bug out, and stop the original chat message. - */ - return Plugin_Stop; - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Hacks_TakeDamageHook(client, attacker, inflictor, Float:damage, &Float:multiplier, damagetype) -{ - - /** - Make sure we are enabled and the client is a donator. - */ - if (g_bIsEnabled && g_bIsNoFallDmgEnabled && g_aPlayers[client][bIsDonator]) - { - - /** - Check for fall damage. - */ - if (damagetype & DMG_FALL) - { - - /** - Cancel the fall damage and bug out. - */ - multiplier *= 0.0; - return Plugin_Changed; - } - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Hacks_PreThinkHook(client) -{ - - /** - Make sure we are enabled and the client is a donator. - */ - if (!g_bIsEnabled || !g_bIsFastHeayEnabled || !g_aPlayers[client][bIsDonator]) - { - return Plugin_Continue; - } - - /** - Check the players class. We are looking for the heavy. - */ - new TFClassType:PlayerClass = TF2_GetPlayerClass(client); - if (PlayerClass == TFClass_Heavy) - { - - /** - We have a heavy, lets check the weapon. - */ - decl String:sWeaponCurrent[64]; - GetClientWeapon(client, sWeaponCurrent, sizeof(sWeaponCurrent)); - if (StrEqual(sWeaponCurrent, "tf_weapon_minigun", false)) - { - - /** - We have a minigun, check the heavies current weapon state to see if it's spinning. - */ - new iWeapon = GetPlayerWeaponSlot(client, 0); - new iWeaponState = GetEntProp(iWeapon, Prop_Send, "m_iWeaponState"); - if (iWeaponState > 0) - { - - /** - He is spinning, so lets change the heavies speed. - */ - new Float:fMaxSpeed = FloatMul(g_fHeavyMultiplier, float(g_fClassMaxSpeed[PlayerClass])); - SetEntPropFloat(client, Prop_Send, "m_flMaxspeed", fMaxSpeed); - } - } - } - - /** - We are done, bug out. - */ - // use Plugin_Continue (other options are ignored on PreThink hook) - return Plugin_Continue; -} - -public Action:HookPlayerConnect(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (!g_bIsEnabled || !g_bIsJoinPubMsgEnabled || !dontBroadcast) - { - return Plugin_Continue; - } - - /** - Get our event variables and check the client. - */ - new iUserId = GetEventInt(event,"userid"); - new iClient = GetClientOfUserId(iUserId); - if (iClient != 0) - { - - /** - Get the info on the client and format the message. - */ - decl String:sClientName[255], - String:sAuthID[255], - String:sMsg[1024]; - - GetEventString(event, "name", sClientName, sizeof(sClientName)); - GetClientAuthString(iClient, sAuthID, sizeof(sAuthID)); - Format(sMsg, sizeof(sMsg), "%T", "PublicJoinMessage", LANG_SERVER, sClientName); - - /** - Print the message to the clients and do the normal functions. - */ - for (new i = 1; i <= MaxClients; i++) - { - if(IsClientConnected(i) && IsClientInGame(i)) - { - PrintToChat(i,"\x01\x05%s", sMsg); - PrintToConsole(i,"%s has connected.", sClientName); - } - } - LogToGame("\"%s<%d><%s><>\" entered the game", sClientName, iUserId, sAuthID); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public HookPlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled && g_bIsUberChargeEnabled) - { - - /** - Get the event variables and check the class for medic - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - if (TF2_GetPlayerClass(iClient) == TFClass_Medic) - { - - /** - Start a timer to get the medic the uber boost - */ - CreateTimer(0.25, Timer_PlayerUberDelay, iClient, TIMER_FLAG_NO_MAPCHANGE); - } - } -} - -public HookPlayerClass(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled && g_bIsUberChargeEnabled) - { - - /** - Get the event variables and check the class for medic - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - if (TF2_GetPlayerClass(iClient) == TFClass_Medic) - { - - /** - Start a timer to get the medic the uber boost - */ - CreateTimer(0.25, Timer_PlayerUberDelay, iClient, TIMER_FLAG_NO_MAPCHANGE); - } - } -} - -public HookPlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled || g_bIsSwapTeamEnabled) - { - - /** - Get the event variables - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - new String:sWeapon[256]; - GetEventString(event, "weapon", sWeapon, sizeof(sWeapon)); - - /** - Bug out if world killed him. Means he changed team or something - */ - if (StrEqual(sWeapon, "world", false)) - { - g_aPlayers[iClient][bQueue] = false; - return; - } - - /** - If he is queued up, swap him - */ - if (g_aPlayers[iClient][bQueue]) - { - SM_MovePlayer(iClient, g_aPlayers[iClient][iNewTeam]); - } - } -} - -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled || g_bIsSwapTeamEnabled) - { - - /** - Get the event variables - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - - /** - If he is queued up, clear the status - */ - if (g_aPlayers[iClient][bQueue]) - { - g_aPlayers[iClient][bQueue] = false; - } - } -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set our variables. - */ - g_bRoundEnd = false; - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled && g_bIsImmuntyEnabled) - { - - /** - Get rid of their immunity. - */ - ProcessRoundEndImmunity(false); - } -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set our variables. - */ - g_bRoundEnd = true; - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled && g_bIsImmuntyEnabled) - { - - /** - Give them their immunity. - */ - ProcessRoundEndImmunity(true); - } -} - -public Action:Timer_DonatorJoined(Handle:timer, any:client) -{ - - /** - Make sure sounds are enabled. - */ - if (g_bIsEnabled && g_bIsJoinSoundEnabled) - { - EmitSoundToClient(client, g_sSoundFile); - } - - /** - Make sure private messages are enabled. - */ - if (g_bIsJoinPrivMsgEnabled) - { - - /** - Send messages to the client. - */ - decl String:sMsg[1024]; - Format(sMsg, sizeof(sMsg), "%T", "PrivateJoinMessage", LANG_SERVER); - PrintToChat(client,"\x01\x05%s", sMsg); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Timer_PlayerUberDelay(Handle:timer, any:client) -{ - - /** - Make sure the client is still in game. - */ - if (IsClientInGame(client)) - { - - /** - Make sure the client is still a medic. - */ - if (TF2_GetPlayerClass(client) == TFClass_Medic) - { - - /** - Get the medgun weapon index - */ - new iIndex = GetPlayerWeaponSlot(client, 1); - if (iIndex > 0) - { - - /** - Set the uber level with the bonus. - */ - SetEntPropFloat(iIndex, Prop_Send, "m_flChargeLevel", g_fUberLevel); - } - } - } -} - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (convar == sdb_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsEnabled = false; - } - else - { - g_bIsEnabled = true; - } - } - else if (convar == sdb_donationflag) - { - Format(g_sCharDonatorFlag, sizeof(g_sCharDonatorFlag), "%s", newValue); - } - else if (convar == sdb_soundfile) - { - Format(g_sSoundFile, sizeof(g_sSoundFile), "%s", newValue); - } - else if (convar == sdb_joinsound_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsJoinSoundEnabled = false; - } - else - { - g_bIsJoinSoundEnabled = true; - } - } - else if (convar == sdb_joinpubmsg_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsJoinPubMsgEnabled = false; - } - else - { - g_bIsJoinPubMsgEnabled = true; - } - } - else if (convar == sdb_joinprivmsg_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsJoinPrivMsgEnabled = false; - } - else - { - g_bIsJoinPrivMsgEnabled = true; - } - } - else if (convar == sdb_chatcolors_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsChatColorsEnabled = false; - } - else - { - g_bIsChatColorsEnabled = true; - } - } - else if (convar == sdb_immunity_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsImmuntyEnabled = false; - } - else - { - g_bIsImmuntyEnabled = true; - } - } - else if (convar == sdb_ubercharge_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsUberChargeEnabled = false; - } - else - { - g_bIsUberChargeEnabled = true; - } - } - else if (convar == sdb_givehealth_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsGiveHealthEnabled = false; - } - else - { - g_bIsGiveHealthEnabled = true; - } - } - else if (convar == sdb_nofalldmg_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsNoFallDmgEnabled = false; - } - else - { - g_bIsNoFallDmgEnabled = true; - } - } - else if (convar == sdb_fastheavy_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsFastHeayEnabled = false; - } - else - { - g_bIsFastHeayEnabled = true; - } - } - else if (convar == sdb_swapteam_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsSwapTeamEnabled = false; - } - else - { - g_bIsSwapTeamEnabled = true; - } - } - else if (convar == sdb_chatcolor) - { - Format(g_sChatColor, sizeof(g_sChatColor), "%s", newValue); - } - else if (convar == sdb_uberlevel) - { - g_fUberLevel = StringToFloat(newValue); - } - else if (convar == sdb_healthcount) - { - g_iHealthCount = StringToInt(newValue); - } - else if (convar == sdb_healthbonus) - { - g_iHealthBonus = StringToInt(newValue); - } - else if (convar == sdb_heavymultiplier) - { - g_fHeavyMultiplier = StringToFloat(newValue); - } -} - -stock LoadUpVariables() -{ - g_bIsEnabled = GetConVarBool(sdb_enabled); - g_bIsJoinSoundEnabled = GetConVarBool(sdb_enabled); - g_bIsJoinPubMsgEnabled = GetConVarBool(sdb_enabled); - g_bIsJoinPrivMsgEnabled = GetConVarBool(sdb_enabled); - g_bIsChatColorsEnabled = GetConVarBool(sdb_enabled); - g_bIsImmuntyEnabled = GetConVarBool(sdb_enabled); - g_bIsUberChargeEnabled = GetConVarBool(sdb_enabled); - g_bIsGiveHealthEnabled = GetConVarBool(sdb_enabled); - g_bIsNoFallDmgEnabled = GetConVarBool(sdb_enabled); - g_bIsFastHeayEnabled = GetConVarBool(sdb_enabled); - g_bIsSwapTeamEnabled = GetConVarBool(sdb_enabled); - GetConVarString(sdb_donationflag, g_sCharDonatorFlag, sizeof(g_sCharDonatorFlag)); - GetConVarString(sdb_soundfile, g_sSoundFile, sizeof(g_sSoundFile)); - GetConVarString(sdb_chatcolor, g_sChatColor, sizeof(g_sChatColor)); - g_bRoundEnd = false; - g_iHealthBonus = GetConVarInt(sdb_healthbonus); - g_iHealthCount = GetConVarInt(sdb_healthcount); - g_fHeavyMultiplier = GetConVarFloat(sdb_heavymultiplier); - g_fUberLevel = GetConVarFloat(sdb_uberlevel); -} - -stock PrepSoundFile() -{ - decl String:buffer[PLATFORM_MAX_PATH]; - PrecacheSound(g_sSoundFile, true); - Format(buffer, sizeof(buffer), "sound/%s", g_sSoundFile); - AddFileToDownloadsTable(buffer); -} - -stock CleanUpPlayer(client) -{ - g_aPlayers[client][bIsDonator] = false; - g_aPlayers[client][bQueue] = false; - g_aPlayers[client][bImmune] = false; - g_aPlayers[client][iNewTeam] = 0; - g_aPlayers[client][iHealthCount] = 0; -} - -stock ProcessRoundEndImmunity(bool:give) -{ - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][bIsDonator]) - { - if (give) - { - SetEntProp(i, Prop_Data, "m_takedamage", 0, 1); - g_aPlayers[i][bImmune] = true; - } - else - { - SetEntProp(i, Prop_Data, "m_takedamage", 2, 1); - g_aPlayers[i][bImmune] = false; - } - } - } -} - -stock FormatMessage(iClient, iTeam, bool:bAlive, String:sChatMsg[], const Sting:sMessage[]) -{ - decl String:sDead[10], - String:sTeam[10], - String:sClientName[64]; - GetClientName(iClient, sClientName, sizeof(sClientName)); - if (iTeam != 0) - Format(sTeam, sizeof(sTeam), "(TEAM) "); - else - Format(sTeam, sizeof(sTeam), ""); - if (bAlive) - Format(sDead, sizeof(sDead), ""); - else - Format(sDead, sizeof(sDead), "*DEAD* "); - if (StrContains(g_sChatColor, "light", false) == -1) - Format(sChatMsg, CHAT_MAX_MESSAGE_LENGTH, "\x01%s%s\x03%s \x01: \x05%s", sDead, sTeam, sClientName, sMessage); - else - Format(sChatMsg, CHAT_MAX_MESSAGE_LENGTH, "\x01%s%s\x03%s \x01: \x04%s", sDead, sTeam, sClientName, sMessage); -} - -stock SayText2(target, author, const String:message[]) -{ - new Handle:hBf; - if (target == 0) - hBf = StartMessageAll("SayText2"); - else - hBf = StartMessageOne("SayText2", target); - if (hBf != INVALID_HANDLE) - { - BfWriteByte(hBf, author); - BfWriteByte(hBf, true); - BfWriteString(hBf, message); - EndMessage(); - } -} - -stock ProcessAdmins() -{ - for (new i = 1; i <= MaxClients; i++) - { - if (SM_IsValidAdmin(i, g_sCharDonatorFlag)) - { - g_aPlayers[i][bDonator] = true; - } - else - { - g_aPlayers[i][bDonator] = false; - } - } -} - -stock ProcessLate() -{ - if (g_bIsEnabled) - { - ProcessAdmins(); - PrepSoundFile(); - if (g_bRoundEnd && g_bIsImmuntyEnabled) - { - ProcessRoundEndImmunity(true); - } - if (!g_bIsImmuntyEnabled) - { - ProcessRoundEndImmunity(false); - } - } - else - { - ProcessRoundEndImmunity(false); - } -} - -public Menu_SwapMode(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, 64); - if (StringToInt(sSelection)) - g_aPlayers[param1][bQueue] = false; - else - g_aPlayers[param1][bQueue] = true; - if (!g_aPlayers[param1][bQueue]) - SM_MovePlayer(param1, g_aPlayers[param1][iNewTeam]); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -public Menu_SelectPlayer(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[256]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - new iTarget = GetClientOfUserId(StringToInt(sSelection)); - if (g_aPlayers[iTarget][bIsDonator]) - g_aPlayers[iTarget][bIsDonator] = false; - else - g_aPlayers[iTarget][bIsDonator] = true; - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -stock Handle:BuildSwapModeMenu() -{ - new Handle:menu = CreateMenu(Menu_SwapMode); - SetMenuTitle(menu, "Select When to Swap:"); - AddMenuItem(menu, "0", "Instantly (Kills)"); - AddMenuItem(menu, "1", "Queue on next death"); - SetMenuExitBackButton(menu, false); - return menu; -} - -stock Handle:BuildPlayerMenu() -{ - new Handle:menu = CreateMenu(Menu_SelectPlayer); - AddTargetsToMenu(menu, 0, true, false); - SetMenuTitle(menu, "Select A Player:"); - SetMenuExitBackButton(menu, true); - return menu; -} - -public Action:Command_TEST(client, args) -{ - -} \ No newline at end of file diff --git a/Simple Chat Colors/addons/sourcemod/scripting/simple-messagesuppression.sp b/Simple Chat Colors/addons/sourcemod/scripting/simple-messagesuppression.sp deleted file mode 100644 index f7725a4..0000000 --- a/Simple Chat Colors/addons/sourcemod/scripting/simple-messagesuppression.sp +++ /dev/null @@ -1,227 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Message Suppression -Description: - Blocks Specific Message Outputs -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include -#include - -#define SUPPRESS_VERSION "1.1.$Rev$" - -public Plugin:myinfo = -{ - name = "Simple Message Suppression", - author = "FlyingMongoose, psychonic", - description = "Blocks Specific Message Outputs", - version = SUPPRESS_VERSION, - url = "http://www.simple-plugins.com/" -} - -new Handle:cvarBlockSpectateMessage; -new Handle:cvarBlockDisconnectMessage; -new Handle:cvarBlockConnectMessage; -new Handle:cvarAdminShowMessages; -new iSpecTeam = 1; - - -public OnPluginStart() -{ - CreateConVar("suppress_version", SUPPRESS_VERSION, _, FCVAR_PLUGIN|FCVAR_NOTIFY|FCVAR_REPLICATED|FCVAR_SPONLY|FCVAR_DONTRECORD); - cvarBlockSpectateMessage = CreateConVar("sm_blockspectatemessage", "1", "If enabled it blocks the join team message if an administrator joins spectator", FCVAR_PLUGIN, true, 0.0, true, 1.0); - cvarBlockDisconnectMessage = CreateConVar("sm_blockdisconnectmessage", "1", "Blocks the disconnect message", FCVAR_PLUGIN, true, 0.0, true, 1.0); - cvarBlockConnectMessage = CreateConVar("sm_blockconnectmessage", "1", "If enabled it blocks the player connection message.", FCVAR_PLUGIN, true, 0.0, true, 1.0); - cvarAdminShowMessages = CreateConVar("sm_adminshowmessages", "1", "Shows disconnect/connect/team join messages for admins only (if disconnect message is set to be blocked)", FCVAR_PLUGIN, true, 0.0, true, 1.0); - HookEvent("player_team", ev_PlayerTeam, EventHookMode_Pre); - HookEvent("player_disconnect", ev_PlayerDisconnect, EventHookMode_Pre); - HookEvent("player_connect", ev_PlayerConnect, EventHookMode_Pre); - - new String:game_folder[64]; - GetGameFolderName(game_folder, sizeof(game_folder)) - - if (StrContains(game_folder, "insurgency", false) != -1) - { - iSpecTeam = 3; - } - else - { - new String:game_description[64]; - GetGameDescription(game_description, sizeof(game_description), true); - if (StrContains(game_description, "Insurgency", false) != -1) - { - iSpecTeam = 3; - } - } - - AutoExecConfig(true, "suppressmessage", "sourcemod"); -} - -public Action:ev_PlayerTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (GetConVarBool(cvarBlockSpectateMessage)) - { - if (!dontBroadcast && !GetEventBool(event, "silent")) - { - new iUserId = GetEventInt(event, "userid"); - new iClient = GetClientOfUserId(iUserId); - new iTeam = GetEventInt(event, "team"); - - if (iTeam == iSpecTeam && GetAdminFlag(GetUserAdmin(iClient), Admin_Kick)) - { - new iOldTeam = GetEventInt(event, "oldteam"); - new bool:bDisconnect = GetEventBool(event, "disconnect"); - new bool:bAutoteam = GetEventBool(event, "autoteam"); - decl String:strName[50]; - GetEventString(event, "name", strName, sizeof(strName)); - - if (iClient != 0) - { - if (GetConVarInt(cvarAdminShowMessages) == 1) - { - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i) && GetUserAdmin(i) != INVALID_ADMIN_ID) - { - PrintToChat(i,"%N joined team Spectator.", iClient); - PrintToConsole(i,"%N joined team Spectator.", iClient); - } - } - } - } - - new Handle:hEvent = CreateEvent("player_team"); - SetEventInt(hEvent, "userid", iUserId); - SetEventInt(hEvent, "team", iTeam); - SetEventInt(hEvent, "oldteam", iOldTeam); - SetEventBool(hEvent, "disconnect", bDisconnect); - SetEventBool(hEvent, "autoteam", bAutoteam); - SetEventBool(hEvent, "silent", true); - SetEventString(hEvent, "name", strName); - - FireEvent(hEvent, true); - - return Plugin_Handled; - } - } - } - return Plugin_Continue; -} -public Action:ev_PlayerConnect(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (GetConVarBool(cvarBlockConnectMessage)) - { - if (!dontBroadcast) - { - decl String:strName[50]; - GetEventString(event, "name", strName, sizeof(strName)); - new iIndex = GetEventInt(event, "index"); - new iUserId = GetEventInt(event, "userid"); - new iClient = GetClientOfUserId(iUserId); - decl String:strNetworkId[50]; - GetEventString(event, "networkid", strNetworkId, sizeof(strNetworkId)); - decl String:strAddress[50]; - GetEventString(event, "address", strAddress, sizeof(strAddress)); - - if (iClient != 0) - { - if (GetConVarInt(cvarAdminShowMessages) == 1) - { - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i) && GetUserAdmin(i) != INVALID_ADMIN_ID) - { - PrintToChat(i,"%N has connected.", iClient); - PrintToConsole(i,"%N has connected.", iClient); - } - } - } - } - - new Handle:hEvent = CreateEvent("player_connect"); - SetEventString(hEvent, "name", strName); - SetEventInt(hEvent, "index", iIndex); - SetEventInt(hEvent, "userid", iUserId); - SetEventString(hEvent, "networkid", strNetworkId); - SetEventString(hEvent, "address", strAddress); - - FireEvent(hEvent, true); - - return Plugin_Handled; - } - } - return Plugin_Continue; -} -public Action:ev_PlayerDisconnect(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (GetConVarBool(cvarBlockDisconnectMessage)) - { - if (!dontBroadcast) - { - new iUserId = GetEventInt(event, "userid"); - new iClient = GetClientOfUserId(iUserId); - decl String:strReason[50]; - GetEventString(event, "reason", strReason, sizeof(strReason)); - decl String:strName[50]; - GetEventString(event, "name", strName, sizeof(strName)); - decl String:strNetworkId[50]; - GetEventString(event, "networkid", strNetworkId, sizeof(strNetworkId)); - - if (iClient != 0) - { - if (GetConVarInt(cvarAdminShowMessages) == 1) - { - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i) && GetUserAdmin(i) != INVALID_ADMIN_ID) - { - PrintToChat(i, "%N has left the server.", iClient); - PrintToConsole(i, "Dropped %N from server (Disconnect by user.)", iClient); - } - } - } - } - - new Handle:hEvent = CreateEvent("player_disconnect"); - SetEventInt(hEvent, "userid", iUserId); - SetEventString(hEvent, "reason", strReason); - SetEventString(hEvent, "name", strName); - SetEventString(hEvent, "networkid", strNetworkId); - - FireEvent(hEvent, true); - - return Plugin_Handled; - } - } - - return Plugin_Continue; -} \ No newline at end of file diff --git a/Simple Chat Colors/addons/sourcemod/scripting/simple-plugins.sp b/Simple Chat Colors/addons/sourcemod/scripting/simple-plugins.sp deleted file mode 100644 index 4462b41..0000000 --- a/Simple Chat Colors/addons/sourcemod/scripting/simple-plugins.sp +++ /dev/null @@ -1,785 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Plugins -Description: - Core plugin for Simple Plugins project -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#define CORE_PLUGIN_VERSION "1.1.$Rev$" - -#include - -enum e_PlayerInfo -{ - Handle:hForcedTeamPlugin = INVALID_HANDLE, - iForcedTeam = 0, - iBuddy = 0, - bool:bBuddyLocked = false -}; - -new Handle:g_fwdPlayerMoved; -new g_aPlayers[MAXPLAYERS + 1][e_PlayerInfo]; -new bool:g_bTeamsSwitched = false; - -/** -Setting our plugin information. -*/ -public Plugin:myinfo = -{ - name = "Simple Plugins Core Plugin", - author = "Simple Plugins", - description = "Core plugin for Simple Plugins", - version = CORE_PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -public bool:AskPluginLoad(Handle:myself, bool:late, String:error[], err_max) -{ - - /** - Register natives for other plugins - */ - CreateNative("SM_MovePlayer", Native_SM_MovePlayer); - CreateNative("SM_SetForcedTeam", Native_SM_SetForcedTeam); - CreateNative("SM_GetForcedTeam", Native_SM_GetForcedTeam); - CreateNative("SM_ClearForcedTeam", Native_SM_ClearForcedTeam); - CreateNative("SM_GetForcedPlayer", Native_SM_GetForcedPlayer); - CreateNative("SM_AssignBuddy", Native_SM_AssignBuddy); - CreateNative("SM_GetClientBuddy", Native_SM_GetClientBuddy); - CreateNative("SM_LockBuddy", Native_SM_LockBuddy); - CreateNative("SM_IsBuddyLocked", Native_SM_IsBuddyLocked); - CreateNative("SM_ClearBuddy", Native_SM_ClearBuddy); - CreateNative("SM_IsValidAdmin", Native_SM_IsValidAdmin); - CreateNative("SM_IsValidTeam", Native_SM_IsValidTeam); - RegPluginLibrary("simpleplugins"); - return true; -} - -public OnPluginStart() -{ - - CreateConVar("ssm_core_pl_ver", CORE_PLUGIN_VERSION, "Simple SourceMod Plugins Core Plugin Version", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - CreateConVar("ssm_core_inc_ver", CORE_INC_VERSION, "Simple SourceMod Plugins Core Include Version", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook some events to control forced players and check extensions - */ - decl String:sExtError[256]; - LogAction(0, -1, "[SSM] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Pre); - switch (g_CurrentMod) - { - case GameType_CSS: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - new iExtStatus = GetExtensionFileStatus("game.cstrike.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SSM] Required extension was not found."); - LogAction(0, -1, "[SSM] Plugin FAILED TO LOAD."); - SetFailState("Required extension was not found."); - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SSM] Required extension is loaded with errors."); - LogAction(0, -1, "[SSM] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SSM] Plugin FAILED TO LOAD."); - SetFailState("Required extension is loaded with errors."); - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SSM] Required extension is loaded."); - } - } - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_PostNoCopy); - HookUserMessage(GetUserMessageId("TextMsg"), UserMessageHook_Class, true); - new iExtStatus = GetExtensionFileStatus("game.tf2.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SSM] Required extension was not found."); - LogAction(0, -1, "[SSM] Plugin FAILED TO LOAD."); - SetFailState("Required extension was not found."); - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SSM] Required extension is loaded with errors."); - LogAction(0, -1, "[SSM] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SSM] Plugin FAILED TO LOAD."); - SetFailState("Required extension is loaded with errors."); - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SSM] Required extension is loaded."); - } - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_PostNoCopy); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - - /** - Load common translations - */ - LoadTranslations ("common.phrases"); - - /** - Create the global forward - */ - g_fwdPlayerMoved = CreateGlobalForward("SM_OnPlayerMoved", ET_Event, Param_Cell, Param_Cell, Param_Cell); -} - -public OnClientDisconnect(client) -{ - - /** - Cleanup clients/players buddy list - */ - if (!IsFakeClient(client)) - { - SM_ClearBuddy(client, true); - SM_LockBuddy(client, false); - } - SM_ClearForcedTeam(client); -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - See if the teams have been switched - */ - if (g_bTeamsSwitched) - { - - /** - Switch the teams the players are forced to - */ - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][iForcedTeam] != 0) - { - if (g_aPlayers[i][iForcedTeam] == g_aCurrentTeams[Team1]) - { - g_aPlayers[i][iForcedTeam] = g_aCurrentTeams[Team2]; - } - else - { - g_aPlayers[i][iForcedTeam] = g_aCurrentTeams[Team1]; - } - } - } - } -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - g_bTeamsSwitched = false; -} - -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get our event variables - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - new iTeam = GetEventInt(event, "team"); - - /** - See if the player is on the wrong team - */ - if (g_aPlayers[iClient][iForcedTeam] != 0 && g_aPlayers[iClient][iForcedTeam] != iTeam) - { - - /** - Move the player back to the forced team - */ - CreateTimer(1.0, Timer_ForcePlayerMove, iClient, TIMER_FLAG_NO_MAPCHANGE); - - /** - If the event was going to be broadcasted, we refire it so it is not broadcasted and stop this one - */ - if (!dontBroadcast) - { - new Handle:hEvent = CreateEvent("player_team"); - SetEventInt(hEvent, "userid", GetEventInt(event, "userid")); - SetEventInt(hEvent, "team", GetEventInt(event, "team")); - SetEventInt(hEvent, "oldteam", GetEventInt(event, "oldteam")); - SetEventBool(hEvent, "disconnect", GetEventBool(event, "disconnect")); - - if (g_CurrentMod == GameType_DOD || g_CurrentMod == GameType_L4D || g_CurrentMod == GameType_TF) - { - new String:sClientName[MAX_NAME_LENGTH + 1]; - GetClientName(client, sClientName, sizeof(sClientName)); - SetEventBool(hEvent, "autoteam", GetEventBool(event, "autoteam")); - SetEventBool(hEvent, "silent", true); - SetEventString(hEvent, "name", sClientName); - FireEvent(hEvent, true); - } - else - { - FireEvent(hEvent, true); - } - return Plugin_Handled; - } - } - return Plugin_Continue; -} - -public Action:UserMessageHook_Class(UserMsg:msg_id, Handle:bf, const players[], playersNum, bool:reliable, bool:init) -{ - new String:sMessage[120]; - BfReadString(bf, sMessage, sizeof(sMessage), true); - if (StrContains(sMessage, "#TF_TeamsSwitched", false) != -1) - { - g_bTeamsSwitched = true; - } - return Plugin_Continue; -} - -public Native_SM_MovePlayer(Handle:plugin, numParams) -{ - - /** - Get and check the client and team - */ - new iClient = GetNativeCell(1); - new iTeam = GetNativeCell(2); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (iTeam != g_aCurrentTeams[Spectator] && iTeam != g_aCurrentTeams[Team1] && iTeam != g_aCurrentTeams[Team2]) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid team %d", iTeam); - } - - MovePlayer(iClient, iTeam); - if (!IsClientObserver(iClient)) - { - RespawnPlayer(iClient); - } - - new fResult; - - Call_StartForward(g_fwdPlayerMoved); - Call_PushCell(plugin); - Call_PushCell(iClient); - Call_PushCell(iTeam); - Call_Finish(fResult); - - if (fResult != SP_ERROR_NONE) - { - return ThrowNativeError(fResult, "Forward failed"); - } - - return fResult; -} - -public Native_SM_SetForcedTeam(Handle:plugin, numParams) -{ - - /** - Get and check the client and team - */ - new iClient = GetNativeCell(1); - new iTeam = GetNativeCell(2); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (iTeam != g_aCurrentTeams[Spectator] && iTeam != g_aCurrentTeams[Team1] && iTeam != g_aCurrentTeams[Team2] && iTeam != g_aCurrentTeams[Unknown]) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid team %d", iTeam); - } - - new bool:bOverRide = GetNativeCell(3) ? true : false; - - if (!bOverRide && g_aPlayers[iClient][hForcedTeamPlugin] != INVALID_HANDLE && plugin != g_aPlayers[iClient][hForcedTeamPlugin]) - { - return false; - } - - g_aPlayers[iClient][hForcedTeamPlugin] = plugin; - g_aPlayers[iClient][iForcedTeam] = iTeam; - return true; -} - -public Native_SM_GetForcedTeam(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - - /** - Get and set the plugin if they want it - */ - new Handle:hPlugin = GetNativeCell(2); - if (hPlugin != INVALID_HANDLE) - { - SetNativeCellRef(2, g_aPlayers[iClient][hForcedTeamPlugin]); - } - - /** - Return the forced team, this could be 0 - */ - return g_aPlayers[iClient][iForcedTeam]; -} - -public Native_SM_ClearForcedTeam(Handle:plugin, numParams) -{ - - /** - Get and check the client and team - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - - g_aPlayers[iClient][hForcedTeamPlugin] = INVALID_HANDLE; - g_aPlayers[iClient][iForcedTeam] = 0; - - return true; -} - -public Native_SM_GetForcedPlayer(Handle:plugin, numParams) -{ - - /** - Get and check the team - */ - new iTeam = GetNativeCell(1); - if (iTeam != g_aCurrentTeams[Spectator] && iTeam != g_aCurrentTeams[Team1] && iTeam != g_aCurrentTeams[Team2]) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid team %d", iTeam); - } - - /** - Start a loop to check for a player on the wrong team - Also make sure the plugin that set the forced team is the plugin that asked - */ - new iPlayer = 0; - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientInGame(i) - && GetClientTeam(i) != g_aPlayers[i][iForcedTeam] - && g_aPlayers[i][iForcedTeam] == iTeam - && g_aPlayers[i][hForcedTeamPlugin] == plugin) - { - iPlayer = i; - break; - } - } - - /** - Return the player we found, this could be 0 - */ - return iPlayer; -} - -public Native_SM_AssignBuddy(Handle:plugin, numParams) -{ - - /** - Get and check the client and player - */ - new iClient = GetNativeCell(1); - new iPlayer = GetNativeCell(2); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (iPlayer < 0 || iPlayer > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid player index (%d)", iPlayer); - } - if (!IsClientConnected(iPlayer)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Player %d is not connected", iPlayer); - } - if (!IsClientInGame(iPlayer)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Player %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Bots are not supported"); - } - - /** - See if we can override his setting - */ - new bool:bOverRide = GetNativeCell(3) ? true : false; - if (!bOverRide) - { - - /** - We can't override, so check if they are locked - */ - if (g_aPlayers[iClient][bBuddyLocked] || g_aPlayers[iPlayer][bBuddyLocked]) - { - - /** - We detected at least 1 lock, so we bug out - */ - return false; - } - } - - /** - Ready to set the buddies - */ - g_aPlayers[iClient][iBuddy] = iPlayer; - g_aPlayers[iPlayer][iBuddy] = iClient; - return true; -} - -public Native_SM_GetClientBuddy(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Bots are not supported"); - } - - /** - Return the players buddy, this could be 0 - */ - return g_aPlayers[iClient][iBuddy]; -} - -public Native_SM_LockBuddy(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - new bool:bSetting = GetNativeCell(2) ? true : false; - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Bots are not supported"); - } - - g_aPlayers[iClient][bBuddyLocked] = bSetting; - return true; -} - -public Native_SM_IsBuddyLocked(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Bots are not supported"); - } - - return g_aPlayers[iClient][bBuddyLocked]; -} - -public Native_SM_ClearBuddy(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Client (%d) is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Bots are not supported"); - } - - /** - Get the clients buddy and see if we can override his setting - */ - new bool:bOverRide = GetNativeCell(2) ? true : false; - new iPlayer = g_aPlayers[iClient][iBuddy]; - - /** - There is no buddy, we don't care about anything else so bug out - */ - if (iPlayer == 0) - { - return true; - } - - /** - We determined he had a buddy, check the override setting - */ - if (!bOverRide) - { - - /** - We can't override, so check if they are locked - */ - if (g_aPlayers[iClient][bBuddyLocked] || g_aPlayers[iPlayer][bBuddyLocked]) - { - - /** - We detected at least 1 lock, so we bug out - */ - return false; - } - } - - /** - Ready to clear the buddies - */ - g_aPlayers[iClient][iBuddy] = 0; - g_aPlayers[iPlayer][iBuddy] = 0; - return true; -} - -public Native_SM_IsValidTeam(Handle:plugin, numParams) -{ - - /** - Get the team - */ - new iTeam = GetNativeCell(1); - - /** - Check the team - */ - if (iTeam == g_aCurrentTeams[Spectator] || iTeam == g_aCurrentTeams[Team1] || iTeam == g_aCurrentTeams[Team2]) - { - return true; - } - return false; -} - -public Native_SM_IsValidAdmin(Handle:plugin, numParams) -{ - /** - Get the client and flags - */ - new iClient = GetNativeCell(1); - decl String:sFlags[15]; - GetNativeString(2, sFlags, sizeof(sFlags)); - new ibFlags = ReadFlagString(sFlags); - - /** - Check the flags - */ - if ((GetUserFlagBits(iClient) & ibFlags) == ibFlags) - { - return true; - } - if (GetUserFlagBits(iClient) & ADMFLAG_ROOT) - { - return true; - } - return false; -} - -public Action:Timer_ForcePlayerMove(Handle:timer, any:iClient) -{ - - MovePlayer(iClient, g_aPlayers[iClient][iForcedTeam]); - - if (g_aPlayers[iClient][iForcedTeam] != g_aCurrentTeams[Spectator]) - { - RespawnPlayer(iClient); - } - - PrintToChat(iClient, "\x01\x04----------------------------------"); - PrintToChat(iClient, "\x01\x04You have been forced to this team."); - PrintToChat(iClient, "\x01\x04----------------------------------"); - - return Plugin_Handled; -} - -stock MovePlayer(iClient, iTeam) -{ - - /** - Change the client's team based on the mod - */ - switch (g_CurrentMod) - { - case GameType_CSS: - { - CS_SwitchTeam(iClient, iTeam); - } - default: - { - ChangeClientTeam(iClient, iTeam); - } - } -} - -stock RespawnPlayer(iClient) -{ - - /** - Respawn the client based on the mod - */ - switch (g_CurrentMod) - { - case GameType_CSS: - { - CS_RespawnPlayer(iClient); - } - case GameType_TF: - { - TF2_RespawnPlayer(iClient); - } - case GameType_INS: - { - FakeClientCommand(iClient, "kill"); - } - default: - { - // - } - } -} diff --git a/Simple Chat Colors/addons/sourcemod/scripting/simple-roundimmunity.sp b/Simple Chat Colors/addons/sourcemod/scripting/simple-roundimmunity.sp deleted file mode 100644 index 5f0bca3..0000000 --- a/Simple Chat Colors/addons/sourcemod/scripting/simple-roundimmunity.sp +++ /dev/null @@ -1,947 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Round Immunity -Description: - Gives admins immunity during certain rounds -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or any later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#pragma semicolon 1 -#include -#include -#undef REQUIRE_EXTENSIONS -#undef AUTOLOAD_EXTENSIONS -#include -#include -#define REQUIRE_EXTENSIONS -#define AUTOLOAD_EXTENSIONS - -#define PLUGIN_VERSION "1.1.$Rev$" -#define SPECTATOR 1 -#define TEAM_RED 2 -#define TEAM_BLUE 3 - -#define COLOR_GREEN 0 -#define COLOR_BLACK 1 -#define COLOR_RED 2 -#define COLOR_BLUE 3 -#define COLOR_TEAM 4 -#define COLOR_RAINBOW 5 -#define COLOR_NONE 6 - -#define PLAYERCOND_SLOWED (1<<0) //1 -#define PLAYERCOND_ZOOMED (1<<1) //2 -#define PLAYERCOND_DISGUISING (1<<2) //4 -#define PLAYERCOND_DISGUISED (1<<3) //8 -#define PLAYERCOND_SPYCLOAK (1<<4) //16 -#define PLAYERCOND_UBERED (1<<5) //32 -#define PLAYERCOND_TELEPORTTRAIL (1<<6) //64 -#define PLAYERCOND_TAUNT (1<<7) //128 -// (1<<8) //256 -// (1<<9) //512 -#define PLAYERCOND_TELEPORTFLASH (1<<10) //1024 -#define PLAYERCOND_KRUBER (1<<11) //2048 -// (1<<12) //4096 -// (1<<13) //8192 -#define PLAYERCOND_BONKED (1<<14) //16384 (blame Neph if it doesn't work) -#define PLAYERCOND_BONKEDORDRINKSLOWDOWN (1<<15) //32768 -#define PLAYERCOND_HEALING (1<<16) //65536 -#define PLAYERCOND_BURNING (1<<17) //131072 -#define PLAYERCOND_FULLYCHARGEDBYMEDIC (1<<18) //262144 - -enum e_Cookies -{ - bEnabled, - iColor, - iMode -}; - -enum e_ColorNames -{ - Green, - Black, - Red, - Blue -}; - -enum e_ColorValues -{ - iRed, - iGreen, - iBlue -}; - -enum e_PlayerData -{ - Handle:hGodModeTimer, - Handle:hColorTimer, - bool:bIsAdmin, - bool:bIsImmune, - iCycleColor -}; - -/** - Global convar handles - */ -new Handle:sri_charadminflag = INVALID_HANDLE; -new Handle:sri_enabled = INVALID_HANDLE; -new Handle:sri_cookie_enabled = INVALID_HANDLE; -new Handle:sri_cookie_color = INVALID_HANDLE; -new Handle:sri_cookie_mode = INVALID_HANDLE; - -/** - Player arrays - */ -new g_aPlayers[MAXPLAYERS + 1][e_PlayerData]; -new g_aClientCookies[MAXPLAYERS + 1][e_Cookies]; - -/** - Global bools - */ -new bool:g_bLoadedLate = false; -new bool:g_bIsEnabled = true; -new bool:g_bRoundEnd = false; -new bool:g_bUseDukehacks = false; -new bool:g_bUseClientprefs = false; - -/** - Global strings/integers/floats - */ -new String:g_sCharAdminFlag[32]; -new g_iColors[e_ColorNames][e_ColorValues]; -new g_iClassMaxHealth[TFClassType] = {0, 125, 125, 200, 175, 150, 300, 175, 125, 125}; - -public Plugin:myinfo = -{ - name = "Simple Round Immunity", - author = "Simple Plugins", - description = "Gives admins immunity during certain rounds", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -} - -bool:AskPluginLoad(Handle:myself, bool:late, String:error[], err_max) -{ - g_bLoadedLate = late; - return true; -} - -public OnPluginStart() -{ - - /** - Create console variables - */ - CreateConVar("sri_version", PLUGIN_VERSION, "Simple Round Immunity", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - sri_enabled = CreateConVar("sri_enabled", "1", "Enable/Disable Admin immunity during certain round."); - sri_charadminflag = CreateConVar("sri_charadminflag", "a", "Admin flag to use for immunity (only one). Must be a in char format."); - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook some events and check extensions - */ - decl String:sExtError[256]; - LogAction(0, -1, "[SRI] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_spawn", HookPlayerSpawn, EventHookMode_Post); - HookEvent("player_hurt", HookPlayerHurt, EventHookMode_Pre); - switch (g_CurrentMod) - { - case GameType_CSS: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - new iExtStatus = GetExtensionFileStatus("game.cstrike.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SRI] Required extension was not found."); - LogAction(0, -1, "[SRI] Plugin FAILED TO LOAD."); - SetFailState("Required extension was not found."); - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SRI] Required extension is loaded with errors."); - LogAction(0, -1, "[SRI] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SRI] Plugin FAILED TO LOAD."); - SetFailState("Required extension is loaded with errors."); - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SRI] Required css extension is loaded."); - } - } - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_PostNoCopy); - HookUserMessage(GetUserMessageId("TextMsg"), UserMessageHook_Class, true); - new iExtStatus = GetExtensionFileStatus("game.tf2.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SRI] Required extension was not found."); - LogAction(0, -1, "[SRI] Plugin FAILED TO LOAD."); - SetFailState("Required extension was not found."); - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SRI] Required extension is loaded with errors."); - LogAction(0, -1, "[SRI] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SRI] Plugin FAILED TO LOAD."); - SetFailState("Required extension is loaded with errors."); - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SRI] Required tf2 extension is loaded."); - } - iExtStatus = GetExtensionFileStatus("dukehacks.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SRI] Dukehacks extension was not found."); - LogAction(0, -1, "[SRI] Plugin continued to load, but that feature will not be used."); - g_bUseDukehacks = false; - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SRI] Dukehacks extension is loaded with errors."); - LogAction(0, -1, "[SRI] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SRI] Plugin continued to load, but that feature will not be used."); - g_bUseDukehacks = false; - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SRI] Dukehacks extension is loaded and will be used."); - g_bUseDukehacks = true; - dhAddClientHook(CHK_TakeDamage, Hacks_TakeDamageHook); - } - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_PostNoCopy); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - /** - Now lets check for client prefs extension - */ - new iExtStatus = GetExtensionFileStatus("clientprefs.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SRI] Client Preferences extension was not found."); - LogAction(0, -1, "[SRI] Plugin continued to load, but that feature will not be used."); - g_bUseClientprefs = false; - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SRI] Client Preferences extension is loaded with errors."); - LogAction(0, -1, "[SRI] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SRI] Plugin continued to load, but that feature will not be used."); - g_bUseClientprefs = false; - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SRI] Client Preferences extension is loaded, checking database."); - if (!SQL_CheckConfig(clientprefs)) - { - LogAction(0, -1, "[SRI] No 'clientprefs' database found. Check your database.cfg file."); - LogAction(0, -1, "[SRI] Plugin continued to load, but Client Preferences will not be used."); - g_bUseClientprefs = false; - } - g_bUseClientprefs = true; - - /** - Deal with client cookies - */ - sri_cookie_enabled = RegClientCookie("bri_client_enabled", "Enable/Disable your immunity during the bonus round.", CookieAccess_Public); - sri_cookie_color = RegClientCookie("bri_client_color", "Color to render when immune.", CookieAccess_Public); - sri_cookie_mode = RegClientCookie("bri_client_mode", "God mode to select", CookieAccess_Public); - SetCookieMenuItem(CookieMenu_TopMenu, sri_cookie_enabled, "Bonus Round Immunity"); - } - - HookConVarChange(sri_enabled, EnabledChanged); - - RegAdminCmd("sm_immunity", Command_Immunity, ADMFLAG_ROOT, "sm_immunity: Gives you immunity"); - - LoadColors(); - - AutoExecConfig(true, "plugin.simpleroundimmunity"); -} - -public OnAllPluginsLoaded() -{ - //something - // need to deal with the unloading of dukehacks, clientprefs, and simpleplugins - // should move hooking the client prefs cookies to a function to make sure they are done post plugin start if ext is loaded late -} - -public OnLibraryRemoved(const String:name[]) -{ - //something - // need to deal with the loading of dukehacks, clientprefs, and simpleplugins -} - -public OnConfigsExecuted() -{ - GetConVarString(sri_charadminflag, g_sCharAdminFlag, sizeof(g_sCharAdminFlag)); - g_bIsEnabled = GetConVarBool(sri_enabled); - g_bRoundEnd = false; -} - -/** - Client events - */ - -public OnClientPostAdminCheck(client) -{ - if (SM_IsValidAdmin(client, g_sCharAdminFlag)) - g_aPlayers[client][bIsAdmin] = true; - else - g_aPlayers[client][bIsAdmin] = false; -} - -public OnClientCookiesCached(client) -{ - decl String:sEnabled[2], String:sColor[4], String:sMode[2]; - GetClientCookie(client, sri_cookie_enabled, sEnabled, sizeof(sEnabled)); - GetClientCookie(client, sri_cookie_color, sColor, sizeof(sColor)); - GetClientCookie(client, sri_cookie_mode, sMode, sizeof(sMode)); - g_aClientCookies[client][bEnabled] = StringToInt(sEnabled); - g_aClientCookies[client][iColor] = StringToInt(sColor); - g_aClientCookies[client][iMode] = StringToInt(sMode); -} - -public OnClientDisconnect(client) -{ - CleanUp(client); -} - -/** - Commands - */ - -public Action:Command_Immunity(client, args) -{ - if (g_aPlayers[client][IsImmune]) - { - DisableImmunity(client); - } - else - { - EnableImmunity(client); - } - return Plugin_Handled; -} - -/** - Event hooks - */ - -public Action:Hacks_TakeDamageHook(client, attacker, inflictor, Float:damage, &Float:multiplier, damagetype) -{ - if (attacker == 0 || attacker >= MaxClients) - { - return Plugin_Continue; - } - if (g_aPlayers[client][IsImmune]) - { - new TFClassType:PlayerClass = TF2_GetPlayerClass(attacker); - if (PlayerClass == TFClass_Spy) - { - multiplier *= 0.0; - return Plugin_Changed; - } - } - return Plugin_Continue; -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - g_bRoundEnd = false; - if (g_bIsEnabled) - { - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][IsImmune]) - { - DisableImmunity(i); - } - } - } -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - g_bRoundEnd = true; - if (g_bIsEnabled) - { - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][bIsAdmin]) - { - EnableImmunity(i); - } - } - } -} - -public HookPlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) -{ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - if (g_bIsEnabled && g_aPlayers[iClient][bIsAdmin] && g_bRoundEnd) - { - EnableImmunity(iClient); - } -} - -public Action:HookPlayerHurt(Handle:event, const String:name[], bool:dontBroadcast) -{ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - if (g_aPlayers[iClient][IsImmune]) - { - SetEntityHealth(iClient, 2000); - return Plugin_Continue; - } - return Plugin_Continue; -} - -/** - Cookie menus - */ - -public CookieMenu_TopMenu(client, CookieMenuAction:action, any:info, String:buffer[], maxlen) -{ - if (action == CookieMenuAction_DisplayOption) - { - //don't think we need to do anything - } - else - { - new Handle:hMenu = CreateMenu(Menu_CookieSettings); - SetMenuTitle(hMenu, "Options (Current Setting)"); - if (g_aClientCookies[client][bEnabled]) - { - AddMenuItem(hMenu, "enable", "Enabled/Disable (Enabled)"); - } - else - { - AddMenuItem(hMenu, "enable", "Enabled/Disable (Disabled)"); - } - if (g_aClientCookies[client][iMode]) - { - AddMenuItem(hMenu, "mode", "Immunity Mode Setting (God Mode)"); - } - else - { - AddMenuItem(hMenu, "mode", "Immunity Mode Setting (Health)"); - } - switch (g_aClientCookies[client][iColor]) - { - case COLOR_GREEN: - { - AddMenuItem(hMenu, "color", "Color (Green)"); - } - case COLOR_BLACK: - { - AddMenuItem(hMenu, "color", "Color (Black)"); - } - case COLOR_RED: - { - AddMenuItem(hMenu, "color", "Color (Red)"); - } - case COLOR_BLUE: - { - AddMenuItem(hMenu, "color", "Color (Blue)"); - } - case COLOR_TEAM: - { - AddMenuItem(hMenu, "color", "Color (Team)"); - } - case COLOR_RAINBOW: - { - AddMenuItem(hMenu, "color", "Color (Rainbow)"); - } - case COLOR_NONE: - { - AddMenuItem(hMenu, "color", "Color (None)"); - } - } - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, client, MENU_TIME_FOREVER); - } -} - -public Menu_CookieSettings(Handle:menu, MenuAction:action, param1, param2) -{ - new client = param1; - if (action == MenuAction_Select) - { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "enable", false)) - { - new Handle:hMenu = CreateMenu(Menu_CookieSettingsEnable); - SetMenuTitle(hMenu, "Enable/Disable Round End Immunity"); - - if (g_aClientCookies[client][bEnabled]) - { - AddMenuItem(hMenu, "enable", "Enable (Set)"); - AddMenuItem(hMenu, "disable", "Disable"); - } - else - { - AddMenuItem(hMenu, "enable", "Enabled"); - AddMenuItem(hMenu, "disable", "Disable (Set)"); - } - - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, client, MENU_TIME_FOREVER); - } - else if (StrEqual(sSelection, "mode", false)) - { - new Handle:hMenu = CreateMenu(Menu_CookieSettingsMode); - SetMenuTitle(hMenu, "Set Immunity Mode"); - - if (g_aClientCookies[client][iMode]) - { - AddMenuItem(hMenu, "god", "God Mode (Set)"); - AddMenuItem(hMenu, "health", "Health"); - } - else - { - AddMenuItem(hMenu, "god", "God Mode"); - AddMenuItem(hMenu, "health", "Health (Set)"); - } - - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, client, MENU_TIME_FOREVER); - } - else - { - new Handle:hMenu = CreateMenu(Menu_CookieSettingsColors); - SetMenuTitle(hMenu, "Select Immunity Color"); - switch (g_aClientCookies[client][iColor]) - { - case COLOR_GREEN: - { - AddMenuItem(hMenu, "Green", "Green (Set)"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_BLACK: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black (Set)"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_RED: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red (Set)"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_BLUE: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue (Set)"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_TEAM: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color (Set)"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_RAINBOW: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow (Set)"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_NONE: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None (Set)"); - } - } - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, client, MENU_TIME_FOREVER); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - ShowCookieMenu(client); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -public Menu_CookieSettingsEnable(Handle:menu, MenuAction:action, param1, param2) -{ - new client = param1; - if (action == MenuAction_Select) - { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "enable", false)) - { - SetClientCookie(client, sri_cookie_enabled, "1"); - g_aClientCookies[client][bEnabled] = 1; - PrintToChat(client, "[SM] Bonus Round Immunity is ENABLED"); - } - else - { - SetClientCookie(client, sri_cookie_enabled, "0"); - g_aClientCookies[client][bEnabled] = 0; - PrintToChat(client, "[SM] Bonus Round Immunity is DISABLED"); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - ShowCookieMenu(client); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -public Menu_CookieSettingsColors(Handle:menu, MenuAction:action, param1, param2) -{ - new client = param1; - if (action == MenuAction_Select) - { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "Green", false)) - { - SetClientCookie(client, sri_cookie_color, "0"); - g_aClientCookies[client][iColor] = COLOR_GREEN; - PrintToChat(client, "[SM] Bonus Round Immunity color set to GREEN"); - } - else if (StrEqual(sSelection, "Black", false)) - { - SetClientCookie(client, sri_cookie_color, "1"); - g_aClientCookies[client][iColor] = COLOR_BLACK; - PrintToChat(client, "[SM] Bonus Round Immunity color set to BLACK"); - } - else if (StrEqual(sSelection, "Red", false)) - { - SetClientCookie(client, sri_cookie_color, "2"); - g_aClientCookies[client][iColor] = COLOR_RED; - PrintToChat(client, "[SM] Bonus Round Immunity color set to RED"); - } - else if (StrEqual(sSelection, "Blue", false)) - { - SetClientCookie(client, sri_cookie_color, "3"); - g_aClientCookies[client][iColor] = COLOR_BLUE; - PrintToChat(client, "[SM] Bonus Round Immunity color set to BLUE"); - } - else if (StrEqual(sSelection, "Team", false)) - { - SetClientCookie(client, sri_cookie_color, "4"); - g_aClientCookies[client][iColor] = COLOR_TEAM; - PrintToChat(client, "[SM] Bonus Round Immunity color set to TEAM COLOR"); - } - else if (StrEqual(sSelection, "Rain", false)) - { - SetClientCookie(client, sri_cookie_color, "5"); - g_aClientCookies[client][iColor] = COLOR_RAINBOW; - PrintToChat(client, "[SM] Bonus Round Immunity color set to RAINBOW"); - } - else if (StrEqual(sSelection, "None", false)) - { - SetClientCookie(client, sri_cookie_color, "6"); - g_aClientCookies[client][iColor] = COLOR_NONE; - PrintToChat(client, "[SM] Bonus Round Immunity color set to NONE"); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - ShowCookieMenu(client); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -public Menu_CookieSettingsMode(Handle:menu, MenuAction:action, param1, param2) -{ - new client = param1; - if (action == MenuAction_Select) - { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "god", false)) - { - SetClientCookie(client, sri_cookie_mode, "1"); - g_aClientCookies[client][iMode] = 1; - PrintToChat(client, "[SM] Bonus Round Immunity set to GOD MODE"); - } - else - { - SetClientCookie(client, sri_cookie_mode, "0"); - g_aClientCookies[client][iMode] = 0; - PrintToChat(client, "[SM] Bonus Round Immunity set to HEALTH BONUS"); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - ShowCookieMenu(client); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -/** -Timer functions - */ - -public Action:Timer_ChangeColor(Handle:timer, any:client) -{ - if (g_aPlayers[client][CycleColor]++ == 3) - { - g_aPlayers[client][CycleColor] = 0; - } - SetEntityRenderMode(client, RENDER_TRANSCOLOR); - SetEntityRenderColor(client, g_iColors[g_aPlayers[client][CycleColor]][iRed], g_iColors[g_aPlayers[client][CycleColor]][iGreen], g_iColors[g_aPlayers[client][CycleColor]][iBlue], 255); - return Plugin_Continue; -} - -public Action:Timer_UndoGodMode(Handle:timer, any:client) -{ - if (IsClientInGame(client)) - { - SetEntProp(client, Prop_Data, "m_takedamage", 2, 1); - } - g_aPlayers[iClient][hGodModeTimer] = INVALID_HANDLE; - return Plugin_Handled; -} - -/** -Stock functions . - */ - -stock CleanUp(iClient) -{ - g_aPlayers[iClient][bIsAdmin] = false; - DisableImmunity(iClient); -} - -stock EnableImmunity(iClient) -{ - SetEntityRenderMode(iClient, RENDER_TRANSCOLOR); - switch (g_aClientCookies[iClient][iColor]) - { - case COLOR_TEAM: - { - new iTeam = GetClientTeam(iClient); - SetEntityRenderColor(iClient, g_iColors[e_ColorNames:iTeam][iRed], g_iColors[e_ColorNames:iTeam][iGreen], g_iColors[e_ColorNames:iTeam][iBlue], 255); - } - case COLOR_RAINBOW: - { - if (g_aPlayers[iClient][hColorTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hColorTimer]); - g_aPlayers[iClient][hColorTimer] = INVALID_HANDLE; - } - g_aPlayers[iClient][hColorTimer] = CreateTimer(0.2, Timer_ChangeColor, iClient, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); - } - case COLOR_NONE: - { - //We dont have to set a color - } - default: - { - SetEntityRenderColor(iClient, g_iColors[e_ColorNames:g_aClientCookies[iClient][iColor]][iRed], g_iColors[e_ColorNames:g_aClientCookies[iClient][iColor]][iGreen], g_iColors[e_ColorNames:g_aClientCookies[iClient][iColor]][iBlue], 255); - } - } - SetEntityHealth(iClient, 2000); - SetEntProp(iClient, Prop_Data, "m_takedamage", 0, 1); - g_aPlayers[iClient][hGodModeTimer] = CreateTimer(2.0, Timer_UndoGodMode, iClient); - g_aPlayers[iClient][IsImmune] = true; -} - -stock DisableImmunity(iClient) -{ - if (g_aPlayers[iClient][hGodModeTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hGodModeTimer]); - g_aPlayers[iClient][hGodModeTimer] = INVALID_HANDLE; - } - if (g_aPlayers[iClient][hColorTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hColorTimer]); - g_aPlayers[iClient][hColorTimer] = INVALID_HANDLE; - } - if (IsClientInGame(iClient)) - { - SetEntityRenderMode(iClient, RENDER_TRANSCOLOR); - SetEntityRenderColor(iClient, 255, 255, 255, 255); - new TFClassType:PlayerClass = TF2_GetPlayerClass(iClient); - new iMaxHealth = g_iClassMaxHealth[PlayerClass]; - SetEntityHealth(iClient, iMaxHealth); - } - g_aPlayers[iClient][CycleColor] = 0; - g_aPlayers[iClient][IsImmune] = false; -} - -stock LoadColors() -{ - g_iColors[Green][iRed] = 0; - g_iColors[Green][iGreen] = 255; - g_iColors[Green][iBlue] = 0; - - g_iColors[Black][iRed] = 10; - g_iColors[Black][iGreen] = 10; - g_iColors[Black][iBlue] = 0; - - g_iColors[Red][iRed] = 255; - g_iColors[Red][iGreen] = 0; - g_iColors[Red][iBlue] = 0; - - g_iColors[Blue][iRed] = 0; - g_iColors[Blue][iGreen] = 0; - g_iColors[Blue][iBlue] = 255; -} - -stock TF2_AddCond(client, cond) -{ - new Handle:cvar = FindConVar("sv_cheats"), bool:enabled = GetConVarBool(cvar), flags = GetConVarFlags(cvar); - if(!enabled) - { - SetConVarFlags(cvar, flags^FCVAR_NOTIFY); - SetConVarBool(cvar, true); - } - FakeClientCommand(client, "addcond %i", cond); - if(!enabled) - { - SetConVarBool(cvar, false); - SetConVarFlags(cvar, flags); - } -} - -stock TF2_RemoveCond(client, cond) -{ - new Handle:cvar = FindConVar("sv_cheats"), bool:enabled = GetConVarBool(cvar), flags = GetConVarFlags(cvar); - if(!enabled) - { - SetConVarFlags(cvar, flags^FCVAR_NOTIFY); - SetConVarBool(cvar, true); - } - FakeClientCommand(client, "removecond %i", cond); - if(!enabled) - { - SetConVarBool(cvar, false); - SetConVarFlags(cvar, flags); - } -} - -/** -Enabled hook - */ - -public EnabledChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (StringToInt(newValue) == 0) - { - UnhookEvent("player_spawn", HookPlayerSpawn, EventHookMode_Post); - UnhookEvent("teamplay_round_start", HookRoundStart, EventHookMode_Post); - UnhookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][bIsAdmin] && g_aPlayers[i][IsImmune]) - { - DisableImmunity(i); - } - } - g_bIsEnabled = false; - } - else - { - HookEvent("player_spawn", HookPlayerSpawn, EventHookMode_Post); - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_Post); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - g_bIsEnabled = true; - } -} diff --git a/Simple Chat Colors/addons/sourcemod/scripting/simple-spectate.sp b/Simple Chat Colors/addons/sourcemod/scripting/simple-spectate.sp deleted file mode 100644 index 4108f8f..0000000 --- a/Simple Chat Colors/addons/sourcemod/scripting/simple-spectate.sp +++ /dev/null @@ -1,2022 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Spectate -Description: - Spectate a player and follow them through death. -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include -#undef REQUIRE_EXTENSIONS -#undef AUTOLOAD_EXTENSIONS -#tryinclude -#define AUTOLOAD_EXTENSIONS -#define REQUIRE_EXTENSIONS - -#define PLUGIN_VERSION "1.2.1.$Rev$" - -#define SPECMODE_NONE 0 -#define SPECMODE_FIRSTPERSON 4 -#define SPECMODE_3RDPERSON 5 -#define SPECMODE_FREELOOK 6 -#define SPECMODE_CSS_FIRSTPERSON 3 -#define SPECMODE_CSS_3RDPERSON 4 -#define SPECMODE_CSS_FREELOOK 5 - -enum e_CvarHandles -{ - Handle:hHudMode, - Handle:hMenuType, - Handle:hRestrictHud, - Handle:hBan, - Handle:hBanPerm, - Handle:hBeacon, - Handle:hBlind, - Handle:hCheater, - Handle:hDrug, - Handle:hFreeze, - Handle:hFreezeBomb, - Handle:hKick, - Handle:hSlap, - Handle:hSlay, - Handle:hTimeBomb -}; - -enum e_CvarSettings -{ - bool:bHudMode, - bool:bMenuType, - bool:bRestrictHud, - bool:bBan, - bool:bBanPerm, - bool:bBeacon, - bool:bBlind, - bool:bCheater, - bool:bDrug, - bool:bFreeze, - bool:bFreezebomb, - bool:bKick, - bool:bSlap, - bool:bSlay, - bool:bTimeBomb -}; - -enum e_PluginSettings -{ - bool:bUseSteamBans, - bool:bUseSourceBans, - bool:bUseMySQLBans, - bool:bCanHUD, - bool:bUseDukehacks -}; - -enum e_Menus -{ - Handle:hSelectPlayer, - Handle:hBanTime, - Handle:hReason -}; - -enum e_Punishments -{ - Punish_None, - Punish_Ban, - Punish_Beacon, - Punish_Blind, - Punish_Cheater, - Punish_Drug, - Punish_Freeze, - Punish_FreezeBomb, - Punish_Kick, - Punish_Slap, - Punish_Slay, - Punish_TimeBomb -}; - -enum e_PlayerData -{ - bool:bIsDisplayingHud, - bool:bIsFlaggedCheater, - Handle:hHudTimer, - Handle:hTargetTimer, - iTargetIndex, - e_Punishments:TargetPunishment, - iBanTime -}; - -new Handle:sm_spectate_adminflag = INVALID_HANDLE; -new Handle:g_hAdminMenu = INVALID_HANDLE; -new Handle:g_hHud = INVALID_HANDLE; -new Handle:g_aPluginCvar[e_CvarHandles]; -new g_aPluginCvarSettings[e_CvarSettings]; -new g_aPluginSettings[e_PluginSettings]; -new g_aMenus[e_Menus]; -new g_aPlayers[MAXPLAYERS + 1][e_PlayerData]; -new String:g_sAdminFlags[16]; -new String:g_sPunishments[e_Punishments][15] = { "None", "Ban", "Beacon", "Blind", "Cheater", "Drug", "Freeze", "FreezeBomb", "Kick", "Slap", "Slay", "TimeBomb" }; - -public Plugin:myinfo = -{ - name = "Simple Spectate", - author = "Simple Plugins", - description = "Spectate a player and follow them through death.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -/** -Sourcemod callbacks -*/ -public OnPluginStart() -{ - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[SSPEC] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Pre); - - /** - Need to create all of our console variables. - */ - CreateConVar("sm_spectate_version", PLUGIN_VERSION, "Sourcemod Spectate", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - g_aPluginCvar[hHudMode] = CreateConVar("sm_spectate_hudmode", "1", "Hud Mode: 0 = Hud Text | 1 = Panel/Menu (NOTE: The panel/menu will override other menus until canceled)"); - g_aPluginCvar[hMenuType] = CreateConVar("sm_spectate_menutype", "0", "Menu Mode: 0 = Panel | 1 = Menu"); - g_aPluginCvar[hRestrictHud] = CreateConVar("sm_spectate_restricthud", "0", "Restrict the hud to the admin flag provided"); - g_aPluginCvar[hBan] = CreateConVar("sm_spectate_ban", "1", "Enable/Disable ban option"); - g_aPluginCvar[hBanPerm] = CreateConVar("sm_spectate_banperm", "1", "Enable/Disable permanent ban option"); - g_aPluginCvar[hBeacon] = CreateConVar("sm_spectate_beacon", "1", "Enable/Disable beacon option"); - g_aPluginCvar[hBlind] = CreateConVar("sm_spectate_blind", "1", "Enable/Disable blind option"); - g_aPluginCvar[hCheater] = CreateConVar("sm_spectate_cheater", "1", "Enable/Disable cheater option"); - g_aPluginCvar[hDrug] = CreateConVar("sm_spectate_drug", "1", "Enable/Disable drug option"); - g_aPluginCvar[hFreeze] = CreateConVar("sm_spectate_freeze", "1", "Enable/Disable freeze option"); - g_aPluginCvar[hFreezeBomb] = CreateConVar("sm_spectate_freezebomb", "1", "Enable/Disable freezebomb option"); - g_aPluginCvar[hKick] = CreateConVar("sm_spectate_kick", "1", "Enable/Disable kick option"); - g_aPluginCvar[hSlap] = CreateConVar("sm_spectate_slap", "1", "Enable/Disable slap option"); - g_aPluginCvar[hSlay] = CreateConVar("sm_spectate_slay", "1", "Enable/Disable slay option"); - g_aPluginCvar[hTimeBomb] = CreateConVar("sm_spectate_timebomb", "1", "Enable/Disable timebomb option"); - - sm_spectate_adminflag = CreateConVar("sm_spectate_adminflag", "d", "Admin Flag to use for admin hud"); - - /** - Hook console variables - */ - new e_CvarHandles:iCvar; - for ( ; _:iCvar < sizeof(g_aPluginCvar); iCvar++) - { - HookConVarChange(g_aPluginCvar[iCvar], ConVarSettingsChanged); - } - - /** - Need to register the commands we are going to create and use. - */ - RegConsoleCmd("sm_spectate", Command_Spectate, "Spectate a player"); - RegConsoleCmd("sm_spec", Command_Spectate, "Spectate a player"); - RegConsoleCmd("sm_observe", Command_Spectate, "Spectate a player"); - RegConsoleCmd("sm_stopspec", Command_StopSpectate, "Stop Spectating a player"); - RegConsoleCmd("sm_endobserve", Command_StopSpectate, "Stop Spectating a player"); - RegConsoleCmd("sm_specinfo", Command_ToggleHud, "Toggles the hud display if in spectator"); - - /** - Now we have to deal with the admin menu. If the admin library is loaded call the function to add our items. - */ - new Handle:gTopMenu; - if (LibraryExists("adminmenu") && ((gTopMenu = GetAdminTopMenu()) != INVALID_HANDLE)) - { - OnAdminMenuReady(gTopMenu); - } - - /** - Deal with the hud - Thanks to Spray Trace plugin (http://forums.alliedmods.net/showthread.php?p=665448) - */ - new String:sHudGames[32]; - GetGameFolderName(sHudGames, sizeof(sHudGames)); - g_aPluginSettings[bCanHUD] = StrEqual(sHudGames,"tf",false) - || StrEqual(sHudGames,"hl2mp",false) - || StrEqual(sHudGames,"sourceforts",false) - || StrEqual(sHudGames,"obsidian",false) - || StrEqual(sHudGames,"left4dead",false) - || StrEqual(sHudGames,"l4d",false); - - if (g_aPluginSettings[bCanHUD]) - { - g_hHud = CreateHudSynchronizer(); - } - - /** - Load translations - */ - LoadTranslations ("common.phrases"); - LoadTranslations ("simplespectate.phrases"); - - /** - Create the config file - */ - AutoExecConfig(true); -} - -public OnConfigsExecuted() -{ - new e_CvarHandles:iCvar; - for ( ; _:iCvar < sizeof(g_aPluginCvarSettings); iCvar++) - { - g_aPluginCvarSettings[iCvar] = GetConVarBool(g_aPluginCvar[iCvar]); - } - - /* - Build the global menus - */ - g_aMenus[hSelectPlayer] = BuildSelectPlayerMenu(); - g_aMenus[hBanTime] = BuildBanTimeMenu(); - g_aMenus[hReason] = BuildReasonMenu(); - - GetConVarString(sm_spectate_adminflag, g_sAdminFlags, sizeof(g_sAdminFlags)); -} - -public OnAllPluginsLoaded() -{ - - /* - Check for steambans - */ - if (FindConVar("sbsrc_version") != INVALID_HANDLE) - { - g_aPluginSettings[bUseSteamBans] = true; - } - else - { - g_aPluginSettings[bUseSteamBans] = false; - } - - /* - Check for sourcebans - */ - if (FindConVar("sb_version") != INVALID_HANDLE) - { - g_aPluginSettings[bUseSourceBans] = true; - } - else - { - g_aPluginSettings[bUseSourceBans] = false; - } - - /* - Check for mysql bans - */ - if (FindConVar("mysql_bans_version") != INVALID_HANDLE) - { - g_aPluginSettings[bUseMySQLBans] = true; - } - else - { - g_aPluginSettings[bUseMySQLBans] = false; - } - - /* - Check for dukehacks - */ - new String:sExtError[256]; - new iExtStatus = GetExtensionFileStatus("dukehacks.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SSPEC] Dukehacks extension was not found."); - LogAction(0, -1, "[SSPEC] Plugin continued to load, but that feature will not be used."); - g_aPluginSettings[bUseDukehacks] = false; - } - else if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SSPEC] Dukehacks extension is loaded with errors."); - LogAction(0, -1, "[SSPEC] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SSPEC] Plugin continued to load, but that feature will not be used."); - g_aPluginSettings[bUseDukehacks] = false; - } - else if (iExtStatus == 1) - { - LogAction(0, -1, "[SSPEC] Dukehacks extension is loaded and will be used."); - g_aPluginSettings[bUseDukehacks] = true; - dhAddClientHook(CHK_TakeDamage, Hacks_TakeDamageHook); - } - - /* - Deal with some known plugin conflicts - */ - new Handle:hObserveClient = FindConVar("observe_version"); - if (hObserveClient != INVALID_HANDLE) - { - new String:sNewFile[PLATFORM_MAX_PATH + 1], String:sOldFile[PLATFORM_MAX_PATH + 1]; - BuildPath(Path_SM, sNewFile, sizeof(sNewFile), "plugins/disabled/observe.smx"); - BuildPath(Path_SM, sOldFile, sizeof(sOldFile), "plugins/observe.smx"); - - /** - Check if plugins/observe.smx exists, and if not, ignore - */ - if(!FileExists(sOldFile)) - { - return; - } - - /** - Check if plugins/disabled/observe.smx already exists, and if so, delete it - */ - if(FileExists(sNewFile)) - { - DeleteFile(sNewFile); - } - - /** - Unload plugins/observe.smx and move it to plugins/disabled/observe.smx - */ - LogAction(0, -1, "Detected the plugin ObserveClient"); - LogAction(0, -1, "ObserveClient plugin conflicts with Simple Spectate"); - LogAction(0, -1, "Unloading plugin and disabling ObserveClient plugin"); - ServerCommand("sm plugins unload observe"); - RenameFile(sNewFile, sOldFile); - } -} - -public OnLibraryRemoved(const String:name[]) -{ - if (StrEqual(name, "adminmenu")) - { - - /** - Looks like the admin menu was removed. Set the global. - */ - g_hAdminMenu = INVALID_HANDLE; - } - else if (StrEqual(name, "simpleplugins")) - { - //something - } -} - -public OnClientDisconnect(client) -{ - - /** - Cleanup the clients variables. - */ - ResetClient(client); - - /** - Run a loop and see if we are supposed to spectate this person (is a target) - */ - for(new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][iTargetIndex] == client) - { - - /** - Cleanup the clients variables. - */ - StopFollowingPlayer(i); - g_aPlayers[i][TargetPunishment] = Punish_None; - g_aPlayers[i][iBanTime] = 0; - } - } -} - -/** -Thirdparty callbacks -*/ -public SM_OnPlayerMoved(Handle:plugin, client, team) -{ - - /** - Make sure we called the move function - */ - if (plugin != GetMyHandle()) - { - return; - } - - //Nothing -} - -public Action:Hacks_TakeDamageHook(client, attacker, inflictor, Float:damage, &Float:multiplier, damagetype) -{ - - /** - Check for a valid client - */ - if (client > 0 && client <= MaxClients) - { - - /** - Check if the client taking damage is flagged as a cheater - */ - if (g_aPlayers[client][bIsFlaggedCheater]) - { - - /** - Check for fall damage and increase it - */ - if (damagetype & DMG_FALL) - { - multiplier *= 1000.0; - return Plugin_Changed; - } - } - } - - /** - Check for a valid attacker - */ - if (attacker > 0 && attacker <= MaxClients) - { - - /** - Check if the attacker causing the damage is flagged as a cheater - */ - if (g_aPlayers[attacker][bIsFlaggedCheater]) - { - - /** - Make sure they are not hurting themselves - */ - if (client != attacker) - { - - /** - Stop the damage - */ - multiplier *= 0.0; - return Plugin_Changed; - } - } - } - return Plugin_Continue; -} - -/** -Events -*/ -public Action:HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get the client and team - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - new iTeam = GetEventInt(event, "team"); - - /** - Make sure it's a valid client - */ - if (iClient == 0) - { - return Plugin_Continue; - } - - /** - If it's a move to spectator start displaying the hud - */ - else if ((iTeam == g_aCurrentTeams[Spectator]) && (GetUserFlagBits(iClient) & ADMFLAG_GENERIC)) - { - StartDisplayingHud(iClient); - - /** - If the event was going to be broadcasted, we refire it so it is not broadcasted and stop this one - */ - if (!dontBroadcast) - { - new Handle:hEvent = CreateEvent("player_team"); - SetEventInt(hEvent, "userid", GetEventInt(event, "userid")); - SetEventInt(hEvent, "team", GetEventInt(event, "team")); - SetEventInt(hEvent, "oldteam", GetEventInt(event, "oldteam")); - SetEventBool(hEvent, "disconnect", GetEventBool(event, "disconnect")); - - if (g_CurrentMod == GameType_DOD || g_CurrentMod == GameType_L4D || g_CurrentMod == GameType_TF) - { - new String:sClientName[MAX_NAME_LENGTH + 1]; - GetClientName(client, sClientName, sizeof(sClientName)); - SetEventBool(hEvent, "autoteam", GetEventBool(event, "autoteam")); - SetEventBool(hEvent, "silent", true); - SetEventString(hEvent, "name", sClientName); - FireEvent(hEvent, true); - } - else - { - FireEvent(hEvent, true); - } - return Plugin_Handled; - } - } - - /** - Otherwise cleanup the client - */ - else - { - StopDisplayingHud(iClient); - StopFollowingPlayer(iClient); - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -/** -Commands -*/ -public Action:Command_Spectate(client, args) -{ - - /** - See if we already have a target (for toggling of command) - */ - if (g_aPlayers[client][iTargetIndex]) - { - - /** - We do, toggle it off - */ - StopFollowingPlayer(client); - - /** - We are done, bug out. - */ - return Plugin_Handled; - } - - /** - We don't... must want to enable it - See if we have some command arguments. - */ - new iCmdArgs = GetCmdArgs(); - if (iCmdArgs == 0) - { - - /** - We don't have any. Display the player menu. - */ - if (g_aPlayers[client][bIsDisplayingHud]) - { - StopDisplayingHud(client); - } - - DisplayMenu(BuildPlayerListMenu(), client, MENU_TIME_FOREVER); - return Plugin_Handled; - } - - /** - We have an argument. - Try to find the target. - */ - new String:sPlayer[128]; - GetCmdArg(1, sPlayer, sizeof(sPlayer)); - new iTarget = FindTarget(client, sPlayer, true, true); - if (iTarget == -1 || !IsClientInGame(iTarget)) - { - - /** - We couldn't find the target. Display the player menu. - */ - if (g_aPlayers[client][bIsDisplayingHud]) - { - StopDisplayingHud(client); - } - - DisplayMenu(BuildPlayerListMenu(), client, MENU_TIME_FOREVER); - return Plugin_Handled; - } - - /** - We found the target. - Call the stock function to spectate the target. - */ - StartFollowingPlayer(client, iTarget); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_StopSpectate(client, args) -{ - - /** - Cleanup the clients variables. - */ - StopFollowingPlayer(client); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_ToggleHud(client, args) -{ - - /** - Toggle the hud - */ - if (g_aPlayers[client][bIsDisplayingHud]) - { - StopDisplayingHud(client); - } - else - { - StartDisplayingHud(client); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -/** -Timers -*/ -public Action:Timer_ResetTarget(Handle:timer, any:client) -{ - - new iTargetID = GetEntPropEnt(client, Prop_Send, "m_hObserverTarget"); - - if (iTargetID != g_aPlayers[client][iTargetIndex] && IsPlayerAlive(g_aPlayers[client][iTargetIndex])) - { - - /** - Run the command to spectate the target from the clients prospectative. - */ - FakeClientCommandEx(client, "spec_player \"%N\"", g_aPlayers[client][iTargetIndex]); - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Timer_UpdateHud(Handle:timer, any:client) -{ - - /** - Make sure the client is still in game and a spectator - */ - if (!IsClientConnected(client) || !IsClientInGame(client) || GetClientTeam(client) != g_aCurrentTeams[Spectator] || !g_aPlayers[client][bIsDisplayingHud]) - { - - /** - We are done, bug out - */ - g_aPlayers[client][hHudTimer] = INVALID_HANDLE; - g_aPlayers[client][bIsDisplayingHud] = false; - return Plugin_Stop; - } - /** - Get the target - */ - new iTarget = GetEntPropEnt(client, Prop_Send, "m_hObserverTarget"); - - /** - Check to make sure the target is valid - */ - if (iTarget <= 0 || iTarget > MaxClients) - { - return Plugin_Continue; - } - - /** - Get the spectator mode - */ - new iSpecMode = GetEntProp(client, Prop_Send, "m_iObserverMode"); - - /** - This is a double check to make sure we are in spec - If we are on a regular team, specmod would = none or zero - */ - if (iSpecMode == SPECMODE_NONE) - { - - /** - We are done, bug out - */ - g_aPlayers[client][hHudTimer] = INVALID_HANDLE; - g_aPlayers[client][bIsDisplayingHud] = false; - return Plugin_Stop; - } - - /** - Check the spectator mode - CSS has different index's so we have to check game type first - */ - if (g_CurrentMod == GameType_CSS) - { - switch (iSpecMode) - { - case SPECMODE_CSS_FIRSTPERSON: - { - //Do Nothing - } - case SPECMODE_CSS_3RDPERSON: - { - //Do Nothing - } - case SPECMODE_CSS_FREELOOK: - { - return Plugin_Continue; - } - } - } - else - { - switch (iSpecMode) - { - case SPECMODE_FIRSTPERSON: - { - //Do Nothing - } - case SPECMODE_3RDPERSON: - { - //Do Nothing - } - case SPECMODE_FREELOOK: - { - return Plugin_Continue; - } - } - } - - - /** - Display with the hud - */ - if (g_aPluginSettings[bCanHUD] && !g_aPluginCvarSettings[bHudMode]) - { - new String:sSteamID[64]; - GetClientAuthString(iTarget, sSteamID, sizeof(sSteamID)); - SetHudTextParams(0.04, 0.6, 0.5, 255, 50, 50, 255); - ShowSyncHudText(client, g_hHud, "%N [%s]", iTarget, sSteamID); - } - else if (g_aPluginCvarSettings[bHudMode]) - { - if (g_aPluginCvarSettings[bMenuType]) - { - DisplayMenu(BuildPlayerHudMenu(client, iTarget), client, 1); - } - else - { - new Handle:hPanel = BuildPlayerHudPanel(client, iTarget); - SendPanelToClient(hPanel, client, Panel_PlayerHud, 1); - CloseHandle(hPanel); - } - } - - /** - We are done, keep going! - */ - return Plugin_Continue; -} - -/** -Admin Menu Callbacks -*/ -public OnAdminMenuReady(Handle:topmenu) -{ - if (topmenu == g_hAdminMenu) - { - return; - } - g_hAdminMenu = topmenu; - new TopMenuObject:player_commands = FindTopMenuCategory(g_hAdminMenu, ADMINMENU_PLAYERCOMMANDS); - if (player_commands == INVALID_TOPMENUOBJECT) - { - return; - } - AddToTopMenu(g_hAdminMenu, - "sm_spectate", - TopMenuObject_Item, - AdminMenu_SpecPlayer, - player_commands, - "sm_spectate", - ADMFLAG_GENERIC); -} - -public AdminMenu_SpecPlayer(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) -{ - if (action == TopMenuAction_DisplayOption) - { - - if (g_aPlayers[param][bIsDisplayingHud]) - { - StopDisplayingHud(param); - } - /** - See if we already have a target - */ - if (g_aPlayers[param][iTargetIndex]) - { - Format(buffer, maxlength, "Spectate(Disable)"); - } - else - { - Format(buffer, maxlength, "Spectate(Select Player)"); - } - } - else if (action == TopMenuAction_SelectOption) - { - - /** - See if we already have a target - */ - if (g_aPlayers[param][iTargetIndex]) - { - - /** - We do, toggle it off - */ - StopFollowingPlayer(param); - - /** - We are done, bug out. - */ - return; - } - else - { - DisplayMenu(BuildPlayerListMenu(), param, MENU_TIME_FOREVER); - } - } -} - -/** -Select Player Menu Callbacks -*/ -public Menu_PlayerList(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - /** - Get the selected player - */ - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - new iTarget = GetClientOfUserId(StringToInt(sSelection)); - - /** - Start following the player - */ - StartFollowingPlayer(param1, iTarget); - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_GENERIC) - { - - /** - Display the last admin menu - */ - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } - else if (param2 == MenuCancel_Exit && GetClientTeam(param1) == g_aCurrentTeams[Spectator]) - { - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_End) - { - - /** - Not a global menu, close it - */ - CloseHandle(menu); - } -} - -public Menu_SelectPlayer(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - - /** - Get the selected player - */ - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (strcmp(sSelection, "Current", false) == 0) - { - /** - Get the current target - */ - new iTarget = GetEntPropEnt(param1, Prop_Send, "m_hObserverTarget"); - - /** - Check to make sure the target is valid - */ - if (iTarget <= 0 || iTarget > MaxClients) - { - PrintToChat(param1, "\x03[SM-SPEC]\x01 %t", "Invalid Target"); - DisplayMenu(BuildPlayerListMenu(), param1, MENU_TIME_FOREVER); - } - - /** - Start following the player - */ - StartFollowingPlayer(param1, iTarget); - } - else - { - - /** - They want to select a player, show the player list - */ - DisplayMenu(BuildPlayerListMenu(), param1, MENU_TIME_FOREVER); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_End) - { - /** - Its a global menu, leave it alive - */ - } -} - -/** -Punishment Menu Callbacks -*/ -public Menu_Punishments(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - - /** - Get the menu selection - */ - new String:sSelection[15]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - - /** - Search for the correct index - */ - new e_Punishments:Index = Punish_None; - for ( ; _:Index <= sizeof(g_sPunishments); Index++) - { - if (StrEqual(sSelection, g_sPunishments[Index])) - { - break; - } - } - - /** - Display the next menu - */ - if (Index == Punish_Ban) - { - - /** - Set the punishment index and display ban time menu - */ - g_aPlayers[param1][TargetPunishment] = Index; - DisplayMenu(g_aMenus[hBanTime], param1, MENU_TIME_FOREVER); - } - else if (Index == Punish_Cheater) - { - - /** - Ask for confirmation before we set punishment index - */ - new Handle:hPanel = BuildAdminCheaterPanel(); - SendPanelToClient(hPanel, param1, Panel_AdminCheater, MENU_TIME_FOREVER); - CloseHandle(hPanel); - } - else - { - - /** - Set the punishment index and display reason menu - */ - g_aPlayers[param1][TargetPunishment] = Index; - DisplayMenu(g_aMenus[hReason], param1, MENU_TIME_FOREVER); - } - } - else if (action == MenuAction_Cancel) - { - - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - else if (action == MenuAction_End) - { - - /** - Not a global menu, close it - */ - CloseHandle(menu); - } -} - -public Menu_BanTime(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - - /** - Get the menu selection - */ - new String:sSelection[15]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - - /** - Set the ban time global - */ - g_aPlayers[param1][iBanTime] = StringToInt(sSelection); - - /** - Display the reason menu - */ - DisplayMenu(g_aMenus[hReason], param1, MENU_TIME_FOREVER); - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_End) - { - /** - Its a global menu, leave it alive - */ - } -} - -public Menu_Reason(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - - /** - Get the menu selection - */ - new String:sSelection[15]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - - /** - Perform the punishment - */ - PerformPunishment(param1, g_aPlayers[param1][iTargetIndex], g_aPlayers[param1][TargetPunishment], sSelection, g_aPlayers[param1][iBanTime]); - - /** - Reactivate the hud if still in spectator - */ - if (GetClientTeam(param1) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_End) - { - /** - Its a global menu, leave it alive - */ - } -} - -public Panel_AdminCheater(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - if (param2 == 1) - { - - /** - Set the punishment index and display reason menu - */ - g_aPlayers[param1][TargetPunishment] = Punish_Cheater; - DisplayMenu(g_aMenus[hReason], param1, MENU_TIME_FOREVER); - } - else - { - - /** - Reactivate the hud if still in spectator - */ - if (GetClientTeam(param1) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(param1); - } - } - } -} - -public Panel_PublicCheater(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - if (param2 == 1) - { - //Waiting for SB 2.0 and sb_submission to be published - } - else - { - - /** - Reactivate the hud if still in spectator - */ - if (GetClientTeam(param1) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(param1); - } - } - } -} - -/** -Hud Menu/Panel Callbacks -*/ -public Menu_PlayerHud(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "stop", false)) - { - StopFollowingPlayer(param1); - } - else if (StrEqual(sSelection, "start", false)) - { - StopDisplayingHud(param1); - DisplayMenu(g_aMenus[hSelectPlayer], param1, MENU_TIME_FOREVER); - } - else if (StrEqual(sSelection, "removecheater", false)) - { - g_aPlayers[g_aPlayers[param1][iTargetIndex]][bIsFlaggedCheater] = false; - } - else if (StrEqual(sSelection, "punish", false)) - { - if (g_aPlayers[param1][iTargetIndex]) - { - StopDisplayingHud(param1); - DisplayMenu(BuildPunishmentMenu(param1), param1, MENU_TIME_FOREVER); - } - else - { - StopDisplayingHud(param1); - PrintToChat(param1, "\x03[SM-SPEC]\x01 %t", "Must Have Target"); - DisplayMenu(g_aMenus[hSelectPlayer], param1, MENU_TIME_FOREVER); - } - } - else if (StrEqual(sSelection, "reportcheater", false)) - { - if (g_aPlayers[param1][iTargetIndex]) - { - StopDisplayingHud(param1); - new Handle:hPanel = BuildPublicCheaterPanel(); - SendPanelToClient(hPanel, param1, Panel_PublicCheater, MENU_TIME_FOREVER); - CloseHandle(hPanel); - } - else - { - StopDisplayingHud(param1); - PrintToChat(param1, "\x03[SM-SPEC]\x01 %t", "Must Have Target"); - DisplayMenu(g_aMenus[hSelectPlayer], param1, MENU_TIME_FOREVER); - } - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_Interrupted) - { - if (GetClientMenu(param1) == MenuSource_External) - { - StopDisplayingHud(param1); - } - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -public Panel_PlayerHud(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - switch (param2) - { - case 1: - { - if (g_aPlayers[param1][iTargetIndex]) - { - StopFollowingPlayer(param1); - } - else - { - StopDisplayingHud(param1); - DisplayMenu(BuildSelectPlayerMenu(), param1, MENU_TIME_FOREVER); - } - } - case 2: - { - if (!g_aPlayers[param1][iTargetIndex]) - { - StopDisplayingHud(param1); - PrintToChat(param1, "\x03[SM-SPEC]\x01 %t", "Must Have Target"); - DisplayMenu(g_aMenus[hSelectPlayer], param1, MENU_TIME_FOREVER); - return; - } - - if ((GetUserFlagBits(param1) & ADMFLAG_GENERIC) || (GetUserFlagBits(param1) & ADMFLAG_ROOT)) - { - if (g_aPlayers[g_aPlayers[param1][iTargetIndex]][bIsFlaggedCheater] && (GetUserFlagBits(param1) & ADMFLAG_ROOT)) - { - //Remove cheater flag - g_aPlayers[g_aPlayers[param1][iTargetIndex]][bIsFlaggedCheater] = false; - } - else - { - //Punish menu - StopDisplayingHud(param1); - DisplayMenu(BuildPunishmentMenu(param1), param1, MENU_TIME_FOREVER); - } - } - else - { - //Report Cheater - new Handle:hPanel = BuildPublicCheaterPanel(); - SendPanelToClient(hPanel, param1, Panel_PublicCheater, MENU_TIME_FOREVER); - CloseHandle(hPanel); - } - } - case 3: - { - StopDisplayingHud(param1); - } - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_Interrupted) - { - if (GetClientMenu(param1) == MenuSource_External) - { - StopDisplayingHud(param1); - } - } - } -} - - -/** -Stock functions -*/ -stock StartFollowingPlayer(client, target) -{ - - /** - If we have an open timer, close it. - */ - if (g_aPlayers[client][hTargetTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[client][hTargetTimer]); - g_aPlayers[client][hTargetTimer] = INVALID_HANDLE; - } - - /** - Make sure the target is on a non spectator team, and the client != target - */ - if (client == target) - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Yourself"); - return; - } - new iTargetTeam = GetClientTeam(target); - if (iTargetTeam == g_aCurrentTeams[Spectator] || iTargetTeam == g_aCurrentTeams[Unknown]) - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Spectator"); - return; - } - - /** - Check to see if client is already a spectator - */ - if (GetClientTeam(client) != g_aCurrentTeams[Spectator]) - { - - /** - Client is not a spectator, lets move them to spec. - */ - SM_MovePlayer(client, g_aCurrentTeams[Spectator]); - } - - /** - If we are using steambans call sb_status - */ - if (g_aPluginSettings[bUseSteamBans]) - { - FakeClientCommandEx(client, "sb_status"); - } - - - /** - Set the global and start to spectate the target. - Making sure it's long enough to deal with moving the client to spec if we had to. - */ - new String:sTargetName[MAX_NAME_LENGTH + 1]; - GetClientName(target, sTargetName, sizeof(sTargetName)); - g_aPlayers[client][iTargetIndex] = target; - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Spectating", sTargetName); - g_aPlayers[client][hTargetTimer] = CreateTimer(0.5, Timer_ResetTarget, client, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); - if (!g_aPlayers[client][bIsDisplayingHud] && GetClientTeam(client) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(client); - } -} - -stock StopFollowingPlayer(client) -{ - - /** - If we have an open timer, close it. - */ - if (g_aPlayers[client][hTargetTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[client][hTargetTimer]); - } - - /** - Tell the client we can't spec his target anymore... if they are in game. - */ - if (IsClientInGame(client) && g_aPlayers[client][iTargetIndex] != 0) - { - new String:sTargetName[MAX_NAME_LENGTH + 1]; - GetClientName(g_aPlayers[client][iTargetIndex], sTargetName, sizeof(sTargetName)); - if (!IsClientConnected(g_aPlayers[client][iTargetIndex]) || !IsClientInGame(g_aPlayers[client][iTargetIndex])) - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Target Left"); - } - else - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Stopped spectating", sTargetName); - } - } - - /** - Null the globals. - */ - g_aPlayers[client][iTargetIndex] = 0; - g_aPlayers[client][hTargetTimer] = INVALID_HANDLE; -} - -stock StartDisplayingHud(client) -{ - if (g_aPluginCvarSettings[bRestrictHud] && !SM_IsValidAdmin(client, g_sAdminFlags)) - { - return; - } - else - { - /** - Double check the hud timer - We should not have one, but if we do, lets cancel it for the current callback - */ - StopDisplayingHud(client); - - /** - Now we can safely display the hud and make sure the current stored handle is the current timer - */ - g_aPlayers[client][bIsDisplayingHud] = true; - g_aPlayers[client][hHudTimer] = CreateTimer(0.5, Timer_UpdateHud, client, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); - } -} - -stock StopDisplayingHud(client) -{ - if (g_aPlayers[client][hHudTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[client][hHudTimer]); - } - g_aPlayers[client][hHudTimer] = INVALID_HANDLE; - g_aPlayers[client][bIsDisplayingHud] = false; -} - -stock ResetClient(client) -{ - StopFollowingPlayer(client); - StopDisplayingHud(client); - - g_aPlayers[client][bIsFlaggedCheater] = false; - g_aPlayers[client][TargetPunishment] = Punish_None; - g_aPlayers[client][iBanTime] = -1; -} - -stock PerformPunishment(client, target, e_Punishments:punishment, const String:reason[], time = 300) -{ - new String:sTargetName[MAX_NAME_LENGTH + 1], - String:sTargetID[64]; - - /** - The target could have left the game by the time we get here - Check for a valid target - */ - if (!IsClientConnected(target) || !IsClientInGame(target)) - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Target Left"); - return; - } - - GetClientName(target, sTargetName, sizeof(sTargetName)); - GetClientAuthString(target, sTargetID, sizeof(sTargetID)); - - switch (punishment) - { - case Punish_Kick: - { - KickClient(g_aPlayers[client][iTargetIndex], "%s", reason); - } - case Punish_Ban: - { - if (g_aPluginSettings[bUseSourceBans]) - { - ClientCommand(client, "sm_ban #%d %d \"%s\"", GetClientUserId(target), time, reason); - } - else if (g_aPluginSettings[bUseMySQLBans]) - { - ClientCommand(client, "mysql_ban #%d %d \"%s\"", GetClientUserId(target), time, reason); - } - else - { - BanClient(target, time, BANFLAG_AUTHID, reason, reason); - } - } - case Punish_Cheater: - { - g_aPlayers[target][bIsFlaggedCheater] = true; - } - case Punish_Beacon: - { - ClientCommand(client, "sm_beacon \"%s\"", sTargetName); - } - case Punish_Blind: - { - ClientCommand(client, "sm_blind \"%s\"", sTargetName); - } - case Punish_Drug: - { - ClientCommand(client, "sm_drug \"%s\"", sTargetName); - } - case Punish_Freeze: - { - ClientCommand(client, "sm_freeze \"%s\"", sTargetName); - } - case Punish_FreezeBomb: - { - ClientCommand(client, "sm_freezebomb \"%s\"", sTargetName); - } - case Punish_Slap: - { - ClientCommand(client, "sm_slap \"%s\" 10", sTargetName); - } - case Punish_Slay: - { - ClientCommand(client, "sm_slay \"%s\"", sTargetName); - } - case Punish_TimeBomb: - { - ClientCommand(client, "sm_timebomb \"%s\"", sTargetName); - } - } - - if (punishment == Punish_Cheater) - { - LogAction(client, target, "[SM SPEC] %N marked %N(%s) with a %s flag for %s", client, target, sTargetID, g_sPunishments[punishment], reason); - } - else - { - ShowActivity(client, "%t", "Punished", sTargetName, g_sPunishments[punishment], reason); - LogAction(client, target, "[SM SPEC] %N punished %N(%s) with a %s for %s", client, target, sTargetID, g_sPunishments[punishment], reason); - } - - /** - Null the globals. - */ - g_aPlayers[client][TargetPunishment] = Punish_None; - g_aPlayers[client][iBanTime] = -1; -} - -/** -Build the menu of player names -*/ -stock Handle:BuildPlayerListMenu() -{ - new Handle:hMenu = CreateMenu(Menu_PlayerList); - AddTargetsToMenu(hMenu, 0, true, false); - SetMenuTitle(hMenu, "Select A Player:"); - SetMenuExitBackButton(hMenu, true); - return hMenu; -} - -/** -Build the select player menu (current or list of players) -*/ -stock Handle:BuildSelectPlayerMenu() -{ - new Handle:hMenu = CreateMenu(Menu_SelectPlayer); - SetMenuTitle(hMenu, "Select A Player:"); - AddMenuItem(hMenu, "Current", "Current Target"); - AddMenuItem(hMenu, "List", "Player List"); - SetMenuExitBackButton(hMenu, true); - return hMenu; -} - -/** -Build the punishmenu menu -*/ -stock Handle:BuildPunishmentMenu(iClient) -{ - new Handle:hMenu = CreateMenu(Menu_Punishments); - SetMenuTitle(hMenu, "Select A Punishment:"); - SetMenuExitBackButton(hMenu, true); - SetMenuExitButton(hMenu, true); - - if (g_aPluginCvarSettings[bKick] && ((GetUserFlagBits(iClient) & ADMFLAG_GENERIC) || (GetUserFlagBits(iClient) & ADMFLAG_ROOT))) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Kick], "Kick"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Kick], "Kick", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bBan] && ((GetUserFlagBits(iClient) & ADMFLAG_GENERIC) || (GetUserFlagBits(iClient) & ADMFLAG_ROOT))) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Ban], "Ban"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Ban], "Ban", ITEMDRAW_DISABLED); - } - - if (g_aPluginSettings[bUseDukehacks] && g_aPluginCvarSettings[bCheater] && (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Cheater], "Flag As Cheater"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Cheater], "Flag As Cheater", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bBeacon]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Beacon], "Beacon"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Beacon], "Beacon", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bBlind]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Blind], "Blind"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Blind], "Blind", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bDrug]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Drug], "Drug"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Drug], "Drug", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bFreeze]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Freeze], "Freeze"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Freeze], "Freeze", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bFreezebomb]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_FreezeBomb], "Freeze Bomb"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_FreezeBomb], "Freeze Bomb", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bSlap]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Slap], "Slap"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Slap], "Slap", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bSlay]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Slay], "Slay"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Slay], "Slay", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bTimeBomb]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_TimeBomb], "Time Bomb"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_TimeBomb], "Time Bomb", ITEMDRAW_DISABLED); - } - - return hMenu; -} - -/** -Build the punishmenu menu -*/ -stock Handle:BuildBanTimeMenu() -{ - new Handle:hMenu = CreateMenu(Menu_BanTime); - SetMenuTitle(hMenu, "Select Ban Type:"); - - if (g_aPluginCvarSettings[bBanPerm]) - { - AddMenuItem(hMenu, "permban", "Permanent"); - } - else - { - AddMenuItem(hMenu, "permban", "Permanent", ITEMDRAW_DISABLED); - } - - AddMenuItem(hMenu, "10", "10 Minutes"); - AddMenuItem(hMenu, "30", "30 Minutes"); - AddMenuItem(hMenu, "60", "1 Hour"); - AddMenuItem(hMenu, "240", "4 Hours"); - AddMenuItem(hMenu, "1440", "1 Day"); - AddMenuItem(hMenu, "10080", "1 Week"); - - SetMenuExitBackButton(hMenu, true); - return hMenu; -} - -/** -Build the punishmenu menu -*/ -stock Handle:BuildReasonMenu() -{ - new Handle:hMenu = CreateMenu(Menu_Reason); - SetMenuTitle(hMenu, "Select A Reason:"); - - AddMenuItem(hMenu, "Abusive", "Abusive"); - AddMenuItem(hMenu, "Racism", "Racism"); - AddMenuItem(hMenu, "General cheating/exploits", "General cheating/exploits"); - AddMenuItem(hMenu, "Wallhack", "Wallhack"); - AddMenuItem(hMenu, "Aimbot", "Aimbot"); - AddMenuItem(hMenu, "Speedhacking", "Speedhacking"); - AddMenuItem(hMenu, "Mic spamming", "Mic spamming"); - AddMenuItem(hMenu, "Admin disrepect", "Admin disrepect"); - AddMenuItem(hMenu, "Camping", "Camping"); - AddMenuItem(hMenu, "Team killing", "Team killing"); - AddMenuItem(hMenu, "Unacceptable Spray", "Unacceptable Spray"); - AddMenuItem(hMenu, "Breaking Server Rules", "Breaking Server Rules"); - AddMenuItem(hMenu, "Other", "Other"); - - SetMenuExitBackButton(hMenu, true); - return hMenu; -} - -/** -Build the cheater displays -*/ -stock Handle:BuildAdminCheaterPanel() -{ - - /** - Create the menu and set the menu options. - */ - new Handle:hPanel = CreatePanel(); - SetPanelTitle(hPanel, "Simple Spectator:"); - - DrawPanelText(hPanel, "Are you sure you want to"); - DrawPanelText(hPanel, "flag this player as a cheater?"); - DrawPanelText(hPanel, "They will not be able to damage"); - DrawPanelText(hPanel, "anyone and die on fall damage."); - DrawPanelItem(hPanel, "Yes"); - DrawPanelItem(hPanel, "No"); - - return hPanel; -} - -stock Handle:BuildPublicCheaterPanel() -{ - - /** - Create the menu and set the menu options. - */ - new Handle:hPanel = CreatePanel(); - SetPanelTitle(hPanel, "Simple Spectator:"); - - DrawPanelText(hPanel, "Are you sure you want to"); - DrawPanelText(hPanel, "submit this player as a cheater?"); - DrawPanelItem(hPanel, "Yes (Not Implemented Yet)", ITEMDRAW_DISABLED); - DrawPanelItem(hPanel, "No"); - return hPanel; -} - -/** -Build the hud displays -*/ -stock Handle:BuildPlayerHudMenu(iClient, iTarget) -{ - - /** - Create all the string variables we will need - */ - new String:sTargetName[MAX_NAME_LENGTH + 1], - String:sTargetID[64], - String:sTargetIP[16]; - - new String:sDisplayName[MAX_NAME_LENGTH + 1], - String:sDisplayID[64], - String:sDisplayIP[64], - String:sDisplayFrags[16], - String:sDisplayDeaths[16]; - - new iTargetFrags, - iTargetDeaths; - - /** - Get the targets information - */ - GetClientName(iTarget, sTargetName, sizeof(sTargetName)); - GetClientIP(iTarget, sTargetIP, sizeof(sTargetIP)); - GetClientAuthString(iTarget, sTargetID, sizeof(sTargetID)); - iTargetFrags = GetClientFrags(iTarget); - iTargetDeaths = GetClientDeaths(iTarget); - - /** - Format the strings for the menu - */ - Format(sDisplayName, sizeof(sDisplayName), "Player: %s", sTargetName); - Format(sDisplayID, sizeof(sDisplayID), "Steam ID: %s", sTargetID); - Format(sDisplayIP, sizeof(sDisplayIP), "IP Address: %s", sTargetIP); - Format(sDisplayFrags, sizeof(sDisplayFrags), "Kills: %i", iTargetFrags); - Format(sDisplayDeaths, sizeof(sDisplayDeaths), "Deaths: %i", iTargetDeaths); - - /** - Create the menu and set the menu options. - */ - new Handle:hMenu = CreateMenu(Menu_PlayerHud); - SetMenuExitBackButton(hMenu, false); - SetMenuTitle(hMenu, "Simple Spectator"); - - AddMenuItem(hMenu, "name", sDisplayName, ITEMDRAW_DISABLED); - AddMenuItem(hMenu, "steamid", sDisplayID, ITEMDRAW_DISABLED); - - if (SM_IsValidAdmin(iClient, g_sAdminFlags)) - { - AddMenuItem(hMenu, "ip", sDisplayIP, ITEMDRAW_DISABLED); - } - - AddMenuItem(hMenu, "kills", sDisplayFrags, ITEMDRAW_DISABLED); - AddMenuItem(hMenu, "deaths", sDisplayDeaths, ITEMDRAW_DISABLED); - - if (g_aPlayers[iClient][iTargetIndex]) - { - AddMenuItem(hMenu, "stop", "Stop Following"); - } - else - { - AddMenuItem(hMenu, "start", "Follow Player"); - } - - if ((GetUserFlagBits(iClient) & ADMFLAG_GENERIC) || (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - if (g_aPlayers[iTarget][bIsFlaggedCheater] && (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - AddMenuItem(hMenu, "removecheater", "Remove Cheater Flag"); - } - else - { - if (CanUserTarget(iClient, iTarget)) - { - AddMenuItem(hMenu, "punish", "Punish Player"); - } - else - { - AddMenuItem(hMenu, "punish", "Punish Player (Immune)", ITEMDRAW_DISABLED); - } - } - } - else - { - AddMenuItem(hMenu, "reportcheater", "Report Cheater"); - } - - SetMenuPagination(hMenu, MENU_NO_PAGINATION); - SetMenuExitButton(hMenu, true); - return hMenu; -} - -stock Handle:BuildPlayerHudPanel(iClient, iTarget) -{ - - /** - Create all the string variables we will need - */ - new String:sTargetName[MAX_NAME_LENGTH + 1], - String:sTargetID[64], - String:sTargetIP[16]; - - new String:sDisplayName[MAX_NAME_LENGTH + 1], - String:sDisplayID[64], - String:sDisplayIP[64], - String:sDisplayFrags[16], - String:sDisplayDeaths[16]; - - new iTargetFrags, - iTargetDeaths; - - /** - Get the targets information - */ - GetClientName(iTarget, sTargetName, sizeof(sTargetName)); - GetClientIP(iTarget, sTargetIP, sizeof(sTargetIP)); - GetClientAuthString(iTarget, sTargetID, sizeof(sTargetID)); - iTargetFrags = GetClientFrags(iTarget); - iTargetDeaths = GetClientDeaths(iTarget); - - /** - Format the strings for the menu - */ - Format(sDisplayName, sizeof(sDisplayName), "Player: %s", sTargetName); - Format(sDisplayID, sizeof(sDisplayID), "Steam ID: %s", sTargetID); - Format(sDisplayIP, sizeof(sDisplayIP), "IP Address: %s", sTargetIP); - Format(sDisplayFrags, sizeof(sDisplayFrags), "Kills: %i", iTargetFrags); - Format(sDisplayDeaths, sizeof(sDisplayDeaths), "Deaths: %i", iTargetDeaths); - - /** - Create the menu and set the menu options. - */ - new Handle:hPanel = CreatePanel(); - SetPanelTitle(hPanel, "Simple Spectator"); - - DrawPanelText(hPanel, "Player Information:"); - DrawPanelText(hPanel, sDisplayName); - DrawPanelText(hPanel, sDisplayID); - if (SM_IsValidAdmin(iClient, g_sAdminFlags)) - { - DrawPanelText(hPanel, sDisplayIP); - } - - DrawPanelText(hPanel, sDisplayFrags); - DrawPanelText(hPanel, sDisplayDeaths); - - if (g_aPlayers[iClient][iTargetIndex]) - { - DrawPanelItem(hPanel, "Stop Following"); - } - else - { - DrawPanelItem(hPanel, "Follow Player"); - } - - if ((GetUserFlagBits(iClient) & ADMFLAG_GENERIC) || (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - if (g_aPlayers[iTarget][bIsFlaggedCheater] && (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - DrawPanelItem(hPanel, "Remove Cheater Flag"); - } - else - { - if (CanUserTarget(iClient, iTarget)) - { - DrawPanelItem(hPanel, "Punish Player"); - } - else - { - DrawPanelItem(hPanel, "Punish Player (Immune)", ITEMDRAW_DISABLED); - } - } - } - else - { - DrawPanelItem(hPanel, "Report Cheater"); - } - - DrawPanelItem(hPanel, "Close Hud Panel"); - return hPanel; -} - -/** -Adjust the settings if a convar was changed -*/ -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - for (new iCvar = 0 ; _:iCvar < sizeof(g_aPluginCvarSettings); iCvar++) - { - if (g_aPluginCvar[_:iCvar] == convar) - { - if (StringToInt(newValue) == 1) - { - g_aPluginCvarSettings[_:iCvar] = true; - } - else - { - g_aPluginCvarSettings[_:iCvar] = false; - } - } - } - - /* - ReBuild the global menu that depends on cvars - */ - g_aMenus[hBanTime] = BuildBanTimeMenu(); - - /** - Run a loop to reset the hud - */ - for(new i = 1; i <= MaxClients; i++) - { - StopDisplayingHud(i); - if (IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(i); - } - } -} diff --git a/Simple Chat Colors/addons/sourcemod/scripting/simple-teambalancer.sp b/Simple Chat Colors/addons/sourcemod/scripting/simple-teambalancer.sp deleted file mode 100644 index 3302255..0000000 --- a/Simple Chat Colors/addons/sourcemod/scripting/simple-teambalancer.sp +++ /dev/null @@ -1,1797 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Team Balancer -Description: - Balances teams based upon player count - Player will not be balanced more than once in 5 (default) mins - Buddy system tries to keep buddies together - Ability to prioritize players - Ability to force players to accept the new team - Admins are immune -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include -#include - -#define PLUGIN_VERSION "2.1.$Rev$" - -enum PlayerData -{ - Handle:hBalanceTimer, - Handle:hForcedTimer, - bool:bSwitched, - bool:bFlagCarrier -}; - -/** - Global convar handles - */ -new Handle:stb_enabled = INVALID_HANDLE; -new Handle:stb_buddyenabled = INVALID_HANDLE; -new Handle:stb_logactivity = INVALID_HANDLE; -new Handle:stb_logactivity2 = INVALID_HANDLE; -new Handle:stb_unbalancelimit = INVALID_HANDLE; -new Handle:stb_deadonly = INVALID_HANDLE; -new Handle:stb_priorityenabled = INVALID_HANDLE; -new Handle:stb_uberlevel = INVALID_HANDLE; -new Handle:stb_balancedelay = INVALID_HANDLE; -new Handle:stb_livingplayerswitchdelay = INVALID_HANDLE; -new Handle:stb_livingplayercheckdelay = INVALID_HANDLE; -new Handle:stb_roundstartdelay = INVALID_HANDLE; -new Handle:stb_switchbackforced = INVALID_HANDLE; -new Handle:stb_adminflag = INVALID_HANDLE; -new Handle:stb_buddyrestriction = INVALID_HANDLE; -new Handle:stb_convarcontrol = INVALID_HANDLE; - -/** - Built-in cvars handles - */ -new Handle:stb_mp_autoteambalance = INVALID_HANDLE; -new Handle:stb_mp_teams_unbalance_limit = INVALID_HANDLE; -new Handle:TFGameModeArena = INVALID_HANDLE; - -/** - Timer handles - */ -new Handle:g_hBalanceTimer = INVALID_HANDLE; -new Handle:g_hLivingPlayerCheckTimer = INVALID_HANDLE; - -/** - Player arrays - */ -new g_aPlayers[MAXPLAYERS + 1][PlayerData]; - -/** -Global bools -*/ -new bool:g_bIsEnabled = true; -new bool:g_bPriorityPlayers = true; -new bool:g_bBuddyRestriction = false; -new bool:g_bLogActivity = false; -new bool:g_bLogActivity2 = false; -new bool:g_bDeadOnly = false; -new bool:g_bConVarControl = true; -new bool:g_bBuddyEnabled = true; -new bool:g_bBalanceInProgress = false; -new bool:g_bRoundStart = false; -new bool:g_bRoundEnd = false; -new bool:g_bSuddenDeath = false; -new bool:g_bIsArenaMode = false; - -/** - Global strings/integers/floats - */ -new g_iUnbalanceLimit, g_iLivingPlayerSwitchDelay, g_iLivingPlayerCheckDelay; -new g_iRoundStartDelay, g_iSwitchBackForced, g_iBalanceDelay; -new Float:g_fUberLevel; -new g_iOwnerOffset; -new String:g_sAdminFlag[5]; - -public Plugin:myinfo = -{ - name = "Simple Team Balancer", - author = "Simple Plugins", - description = "Balances teams based upon player count.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -} - -public OnPluginStart() -{ - - /** - Create console variables - */ - CreateConVar("stb_version", PLUGIN_VERSION, "Simple Team Balancer", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - stb_enabled = CreateConVar("stb_enabled", "1", "Enable or Disable Simple Team Balancer", _, true, 0.0, true, 1.0); - stb_priorityenabled = CreateConVar("stb_priorityenabled", "1", "Enable or Disable the prioritization of living players", _, true, 0.0, true, 1.0); - stb_buddyrestriction = CreateConVar("stb_buddyrestriction", "0", "Enable or Disable Admin Only buddy lists", _, true, 0.0, true, 1.0); - stb_logactivity = CreateConVar("stb_logactivity", "0", "Enable or Disable the disaplying of events in the log", _, true, 0.0, true, 1.0); - stb_logactivity2 = CreateConVar("stb_logactivity2", "0", "Enable or Disable the disaplying of detailed events in the log (WILL SPAM LOG)", _, true, 0.0, true, 1.0); - stb_deadonly = CreateConVar("stb_deadonly", "0", "Enable or Disable the switching of only dead players", _, true, 0.0, true, 1.0); - stb_convarcontrol = CreateConVar("stb_convarcontrol", "1", "Enable or Disable the control of builtin console variables", _, true, 0.0, true, 1.0); - stb_buddyenabled = CreateConVar("stb_buddyenabled", "1", "Enable or Disable the buddy system", _, true, 0.0, true, 1.0); - stb_unbalancelimit = CreateConVar("stb_unbalancelimit", "2", "Amount of players teams are ALLOWED to be unbalanced by", _, true, 1.0, true, 32.0); - stb_balancedelay = CreateConVar("stb_balancedelay", "10", "Delay in seconds to start an autobalance"); - stb_livingplayerswitchdelay = CreateConVar("stb_livingplayerswitchdelay", "20", "Delay in seconds to switch living players once selected"); - stb_livingplayercheckdelay = CreateConVar("stb_livingplayercheckdelay", "10", "Delay in seconds to start checking living players once teams become unbalanced"); - stb_roundstartdelay = CreateConVar("stb_roundstartdelay", "15", "Delay in seconds to start balancing teams after the start of a round"); - stb_switchbackforced = CreateConVar("stb_switchbackforced", "300", "Amount of time in seconds to not switch a player twice and force the team if enabled"); - stb_uberlevel = CreateConVar("stb_uberlevel", "1.0", "Min uber level medic must have to have priority over other living players. Setting to 0 will rarely switch a living medic", _, true, 0.0, true, 1.0); - stb_adminflag = CreateConVar("stb_adminflag", "a", "Admin flag to use for immunity. Must be a in char format."); - stb_mp_autoteambalance = FindConVar("mp_autoteambalance"); - stb_mp_teams_unbalance_limit = FindConVar("mp_teams_unbalance_limit"); - - /** - Removing the notify tags from the built in cvars. We dont want spam. - */ - if (stb_mp_autoteambalance != INVALID_HANDLE) - { - SetConVarFlags(stb_mp_autoteambalance, GetConVarFlags(stb_mp_autoteambalance)^FCVAR_NOTIFY); - } - if (stb_mp_teams_unbalance_limit != INVALID_HANDLE) - { - SetConVarFlags(stb_mp_teams_unbalance_limit, GetConVarFlags(stb_mp_teams_unbalance_limit)^FCVAR_NOTIFY); - } - - /** - Hook console variables - */ - HookConVarChange(stb_enabled, ConVarSettingsChanged); - HookConVarChange(stb_priorityenabled, ConVarSettingsChanged); - HookConVarChange(stb_buddyrestriction, ConVarSettingsChanged); - HookConVarChange(stb_logactivity, ConVarSettingsChanged); - HookConVarChange(stb_logactivity2, ConVarSettingsChanged); - HookConVarChange(stb_deadonly, ConVarSettingsChanged); - HookConVarChange(stb_convarcontrol, ConVarSettingsChanged); - HookConVarChange(stb_buddyenabled, ConVarSettingsChanged); - HookConVarChange(stb_unbalancelimit, ConVarSettingsChanged); - HookConVarChange(stb_balancedelay, ConVarSettingsChanged); - HookConVarChange(stb_livingplayerswitchdelay, ConVarSettingsChanged); - HookConVarChange(stb_livingplayercheckdelay, ConVarSettingsChanged); - HookConVarChange(stb_roundstartdelay, ConVarSettingsChanged); - HookConVarChange(stb_switchbackforced, ConVarSettingsChanged); - HookConVarChange(stb_uberlevel, ConVarSettingsChanged); - HookConVarChange(stb_mp_autoteambalance, ConVarSettingsChanged); - HookConVarChange(stb_mp_teams_unbalance_limit, ConVarSettingsChanged); - - /** - Create console commands - */ - RegConsoleCmd("sm_buddy", Command_AddBalanceBuddy, "Add a balance buddy"); - RegConsoleCmd("sm_lockbuddy", Command_LockBuddy, "Locks your balance buddy selection"); - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[STB] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_death", HookPlayerDeath, EventHookMode_Post); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Post); - switch (g_CurrentMod) - { - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - HookEvent("teamplay_suddendeath_begin", HookSuddenDeathBegin, EventHookMode_PostNoCopy); - HookEvent("teamplay_flag_event", HookFlagEvent, EventHookMode_Post); - TFGameModeArena = FindConVar("tf_gamemode_arena"); - g_iOwnerOffset = FindSendPropInfo("CBaseObject", "m_hBuilder"); - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_Post); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - - /** - Load translations and .cfg file - */ - LoadTranslations ("simpleteambalancer.phrases"); - AutoExecConfig(true, "plugin.simpleteambalancer"); - LogAction(0, -1, "[STB] Simple Team Balancer is loaded."); -} - -public OnAllPluginsLoaded() -{ - //something -} - -public OnLibraryRemoved(const String:name[]) -{ - //something -} - -public OnConfigsExecuted() -{ - - /** - Load up global variables - */ - g_bIsEnabled = GetConVarBool(stb_enabled); - g_bBuddyEnabled = GetConVarBool(stb_buddyenabled); - g_bLogActivity = GetConVarBool(stb_logactivity); - g_bLogActivity2 = GetConVarBool(stb_logactivity2); - g_bDeadOnly = GetConVarBool(stb_deadonly); - g_bPriorityPlayers = GetConVarBool(stb_priorityenabled); - g_bBuddyRestriction = GetConVarBool(stb_buddyrestriction); - g_bConVarControl = GetConVarBool(stb_convarcontrol); - g_fUberLevel = GetConVarFloat(stb_uberlevel); - g_iUnbalanceLimit = GetConVarInt(stb_unbalancelimit); - g_iBalanceDelay = GetConVarInt(stb_balancedelay); - g_iLivingPlayerSwitchDelay = GetConVarInt(stb_livingplayerswitchdelay); - g_iLivingPlayerCheckDelay = GetConVarInt(stb_livingplayercheckdelay); - g_iRoundStartDelay = GetConVarInt(stb_roundstartdelay); - g_iSwitchBackForced = GetConVarInt(stb_switchbackforced); - GetConVarString(stb_adminflag, g_sAdminFlag, sizeof(g_sAdminFlag)); - - /** - Report enabled - */ - if (g_bIsEnabled) - { - LogAction(0, -1, "[STB] Simple Team Balancer is ENABLED."); - } - else - { - LogAction(0, -1, "[STB] Simple Team Balancer is DISABLED."); - } - - - /** - Report log activity - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Log Activity ENABLED."); - } - else - { - LogAction(0, -1, "[STB] Log Activity DISABLED."); - } - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Detailed Log Activity ENABLED."); - } - else - { - LogAction(0, -1, "[STB] Detailed Log Activity DISABLED."); - } -} - -public OnMapStart() -{ - - /** - Check for arena mode - */ - if (g_CurrentMod == GameType_TF && GetConVarBool(TFGameModeArena)) - { - g_bIsArenaMode = true; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Simple Team Balancer detected arena mode and will be bypassed"); - } - } - else - { - g_bIsArenaMode = false; - } - - /** - Reset the globals - */ - g_bBalanceInProgress = false; - g_bRoundStart = false; - g_bRoundEnd = false; - g_bSuddenDeath = false; - - /** - Set the built-in convars - */ - SetGameCvars(); -} - -public OnClientPostAdminCheck(client) -{ - - /** - Make sure its a valid connected client and buddy system is enabled - */ - if (client == 0 || !g_bIsEnabled || !IsClientConnected(client) || !g_bBuddyEnabled) - { - return; - } - - /** - Make sure if its set for admins only they have the flags - */ - if (g_bBuddyRestriction && !SM_IsValidAdmin(client, g_sAdminFlag)) - { - return; - } - - /** - Start the advertisement timer - */ - CreateTimer (60.0, Timer_WelcomeAdvert, client); -} - -public OnClientDisconnect(client) -{ - - /** - Call stock function to cleaup - */ - CleanUp(client); -} - -public OnClientDisconnect_Post(client) -{ - - /** - Determine if we need a balance - */ - if (OkToBalance() && IsUnbalanced() && !g_bBalanceInProgress) - { - - /** - No balance in progress but balance is needed - */ - StartABalance(); - } -} - -public SM_OnPlayerMoved(Handle:plugin, client, team) -{ - - /** - Make sure we called the move function - */ - if (plugin != GetMyHandle()) - { - if (g_bLogActivity2) - { - LogAction(0, client, "[STB] Callback was not started with current plugin, bugging out."); - } - return; - } - - /** - Get the players name and report the event - */ - decl String:sPlayerName[64]; - GetClientName(client, sPlayerName, sizeof(sPlayerName)); - if (g_bLogActivity) - { - LogAction(0, client, "[STB] Changed %s to team %i.", sPlayerName, team); - } - - /** - If we are in TF2 fire the bult-in team balance event - */ - if(g_CurrentMod == GameType_TF) - { - new Handle:event = CreateEvent("teamplay_teambalanced_player"); - SetEventInt(event, "player", client); - SetEventInt(event, "team", team); - FireEvent(event); - } - - /** - Notify the players - */ - PrintToChatAll("[SM] %T", "BalanceMessage", LANG_SERVER, sPlayerName); - - /** - Set the players variables and start a timer - */ - g_aPlayers[client][bSwitched] = true; - g_aPlayers[client][hForcedTimer] = CreateTimer(float(g_iSwitchBackForced), Timer_ForcedExpired, client, TIMER_FLAG_NO_MAPCHANGE); - - /** - We are done, log the completion and end the balance - */ - if (g_bLogActivity) - { - LogAction(0, client, "[STB] Balance finished."); - } - g_bBalanceInProgress = false; -} - -/* HOOKED EVENTS */ - -public HookPlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get our event variables - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - decl String:sWeapon[64]; - GetEventString(event, "weapon", sWeapon, sizeof(sWeapon)); - - /** - Return if death was not caused by a player - This is the case when the player switches teams - */ - if (StrEqual(sWeapon, "world", false)) - { - return; - } - - - /** - Check if balance is needed - */ - if (IsClientInGame(iClient) && OkToBalance() && IsUnbalanced()) - { - new iSmallerTeam = GetSmallerTeam(); - - /** - Check if balance is in progress - */ - if (g_bBalanceInProgress) - { - - /** - There is a balance in progress - Check the player who died to see if he is supposed to be switched - */ - if (g_aPlayers[iClient][hBalanceTimer] != INVALID_HANDLE) - { - - /** - The player has a timer on him to switch him to other team - Stop the timer - */ - CloseHandle(g_aPlayers[iClient][hBalanceTimer]); - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] With a balance in progress the queued living player died and was switched."); - } - - /** - Call the stock change team function - */ - BalancePlayer(iClient, SM_GetForcedTeam(iClient)); - return; - } - - /** - Before we continue, lets make sure the client is switchable - */ - if (IsSwitchablePlayer(iClient, GetBiggerTeam())) - { - - /** - Now we check the buddy system - */ - if (g_bBuddyEnabled) - { - - /** - Buddy system is enabled, check to see if client has buddy - */ - new iBuddyIndex = SM_GetClientBuddy(iClient); - if (iBuddyIndex != 0 || !IsClientConnected(iBuddyIndex) || !IsClientInGame(iBuddyIndex)) - { - - /** - The client has a buddy, so we check to see if they are on same team - */ - if (GetClientTeam(iClient) == GetClientTeam(iBuddyIndex)) - { - - /** - They are, but we don't bug out, we still need to start a balance - */ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] With a balance in progress a buddy on the right team was found and skipped."); - } - } - else - { - - /** - They are not on the same team - The buddy could be in spec, and that would make it not matter where he is, or the buddy is on the smaller team - */ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] With a balance in progress a buddy on the wrong team was switched."); - } - BalancePlayer(iClient, iSmallerTeam); - return; - } - } - else - { - - /** - Client doesn't have a buddy, balance this player - */ - BalancePlayer(iClient, iSmallerTeam); - return; - } - } - else - { - - /** - Buddy system is not enabled, balance this player - */ - BalancePlayer(iClient, iSmallerTeam); - return; - } - } - } - else - { - - /** - If we get to here then we must need to start a balance - */ - StartABalance(); - } - } -} - -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get our event variables. - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - new iTeam = GetEventInt(event, "team"); - - /** - Make sure its ok to balance. - */ - if (OkToBalance()) - { - - /** - See if the client that changed teams was set to with a balance. - */ - if (g_aPlayers[iClient][hBalanceTimer] != INVALID_HANDLE - && SM_GetForcedTeam(iClient) == iTeam - && g_bBalanceInProgress) - { - - /** - The client was set to be balanced, so we close the timer. - */ - CloseHandle(g_aPlayers[iClient][hBalanceTimer]); - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - - /** - Stop the balance. - */ - g_bBalanceInProgress = false; - return; - } - - /** - It's not likely that this team change can cause us to need a balance. - If it does, start one with a small dealy to deal with forced switch backs. - */ - if (IsUnbalanced() && !g_bBalanceInProgress) - { - CreateTimer(2.0, Timer_ChangeTeamBalanceDelay, _, TIMER_FLAG_NO_MAPCHANGE); - } - } -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set the variables we need to start a round - */ - g_bRoundStart = true; - g_bRoundEnd = false; - g_bSuddenDeath = false; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Round Started"); - } - - /** - Start a delayed balance check at the start of the round - */ - CreateTimer(float(g_iRoundStartDelay), Timer_RoundStart); -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set the variables we need at round end - */ - g_bRoundEnd = true; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Round Ended"); - } -} - -public HookSuddenDeathBegin(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set the variables we need for sudden death - */ - g_bSuddenDeath = true; -} - -public HookFlagEvent(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get our event variables - */ - new iClient = GetEventInt(event, "player"); - new iFlagStatus = GetEventInt(event, "eventtype"); - - /** - Make sure we have a valid client - */ - if (!IsClientInGame(iClient)) - { - return; - } - - /** - Determine what kind of event this is - */ - switch (iFlagStatus) - { - case 1: - { - - /** - The flag was picked up - */ - g_aPlayers[iClient][bFlagCarrier] = true; - } - case 2: - { - - /** - The flag was capped - */ - g_aPlayers[iClient][bFlagCarrier] = false; - } - case 3: - { - - /** - The flag was defended, we don't have to do anything - */ - } - case 4: - { - - /** - The flag was dropped - */ - g_aPlayers[iClient][bFlagCarrier] = false; - } - } -} - -/* COMMAND EVENTS */ - -public Action:Command_AddBalanceBuddy(client, args) -{ - if (client == 0) - { - ReplyToCommand(client, "[SM] %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - if (!g_bIsEnabled || !g_bBuddyEnabled) - { - ReplyToCommand(client, "[SM] %T", "CmdDisabled", LANG_SERVER); - return Plugin_Handled; - } - if (g_bBuddyRestriction) - { - if (!SM_IsValidAdmin(client, g_sAdminFlag)) - { - ReplyToCommand(client, "[SM] %T", "RestrictedBuddy", LANG_SERVER); - return Plugin_Handled; - } - } - decl String:sPlayerUserId[24]; - GetCmdArg(1, sPlayerUserId, sizeof(sPlayerUserId)); - new iPlayer = GetClientOfUserId(StringToInt(sPlayerUserId)); - if (!iPlayer || !IsClientInGame(iPlayer) || client == iPlayer) - { - if (client == iPlayer) - { - PrintHintText(client, "%T", "SelectSelf", LANG_SERVER); - } - ReplyToCommand(client, "[SM] Usage: buddy "); - new Handle:playermenu = BuildPlayerMenu(); - DisplayMenu(playermenu, client, MENU_TIME_FOREVER); - } - else - { - decl String:cName[128]; - decl String:bName[128]; - GetClientName(client, cName, sizeof(cName)); - GetClientName(iPlayer, bName, sizeof(bName)); - if (SM_IsBuddyLocked(iPlayer)) - { - ReplyToCommand(client, "[SM] %T", "PlayerLockedBuddyMsg", LANG_SERVER, bName); - return Plugin_Handled; - } - SM_AssignBuddy(client, iPlayer); - PrintHintText(client, "%T", "BuddyMsg", LANG_SERVER, bName); - PrintHintText(iPlayer, "%T", "BuddyMsg", LANG_SERVER, cName); - } - return Plugin_Handled; -} - -public Action:Command_LockBuddy(client, args) -{ - if (client == 0) - { - ReplyToCommand(client, "[SM] %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - if (!g_bIsEnabled) - { - ReplyToCommand(client, "[SM] %T", "CmdDisabled", LANG_SERVER); - return Plugin_Handled; - } - if (g_bBuddyRestriction) - { - if (!SM_IsValidAdmin(client, g_sAdminFlag)) - { - ReplyToCommand(client, "[SM] %T", "RestrictedBuddy", LANG_SERVER); - return Plugin_Handled; - } - } - if (SM_IsBuddyLocked(client)) - { - SM_LockBuddy(client, false); - PrintHintText(client, "%T", "BuddyLockMsgDisabled", LANG_SERVER); - } - else - { - SM_LockBuddy(client, true); - PrintHintText(client, "%T", "BuddyLockMsgEnabled", LANG_SERVER); - } - return Plugin_Handled; -} - -/** -Stock functions . - */ - -stock bool:IsUnbalanced() -{ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Checking if teams are unbalanced"); - } - new Team1Count = GetTeamClientCount(g_aCurrentTeams[Team1]); - new Team2Count = GetTeamClientCount(g_aCurrentTeams[Team2]); - new ubCount = RoundFloat(FloatAbs(float(Team1Count - Team2Count))); - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Team1:%i Team2:%i Difference:%i", Team1Count, Team2Count, ubCount); - } - if (ubCount > g_iUnbalanceLimit) - { - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Teams are unbalanced"); - } - return true; - } - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Teams are not unbalanced"); - } - return false; -} - -stock bool:OkToBalance() -{ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Checking if OK to balance."); - } - new bool:bResult = false; - if (g_bIsEnabled && !g_bRoundStart && !g_bRoundEnd && !g_bIsArenaMode && !g_bSuddenDeath) - { - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Passed IF statement"); - LogAction(0, -1, "[STB] Now checking admins"); - } - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientInGame(i) && !SM_IsValidAdmin(i, g_sAdminFlag)) - { - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Found at least 1 non-admin"); - LogAction(0, -1, "[STB] OK to balance"); - } - bResult = true; - break; - } - } - if (!bResult && g_bLogActivity2) - { - LogAction(0, -1, "[STB] All admins online"); - } - } - if (!bResult && g_bLogActivity2) - { - LogAction(0, -1, "[STB] Not OK to balance"); - } - return bResult; -} - -stock bool:IsSwitchablePlayer(iClient, iBiggerTeam) -{ - - /** - Run the client thru some standard checks - */ - if (!IsClientInGame(iClient) - || SM_IsValidAdmin(iClient, g_sAdminFlag) - || g_aPlayers[iClient][bFlagCarrier] - || GetClientTeam(iClient) != iBiggerTeam - || g_aPlayers[iClient][bSwitched]) - { - - /** - The supplied client can't be switched - */ - return false; - } - - /** - The supplied client can be switched - */ - return true; -} - -stock bool:HasUber(iClient) -{ - - /** - First things first, make sure the client is a medic - */ - if(TF2_GetPlayerClass(iClient) == TFClass_Medic) - { - - /** - We can only check the active weapon, so make sure the client is holding the uber gun - */ - decl String:sWeaponName[32]; - GetClientWeapon(iClient, sWeaponName, sizeof(sWeaponName)); - if(StrEqual(sWeaponName, "tf_weapon_medigun")) - { - - /** - They are, so lets check the uber level of the gun - */ - new iEntityIndex = GetEntDataEnt2(iClient, FindSendPropInfo("CTFPlayer", "m_hActiveWeapon")); - new Float:fChargeLevel = GetEntDataFloat(iEntityIndex, FindSendPropInfo("CWeaponMedigun", "m_flChargeLevel")); - if (fChargeLevel >= g_fUberLevel) - { - - /** - The client supplied has an uber above the supplied level, return true - */ - if (g_bLogActivity2) - { - LogAction(0, iClient, "[STB] Found a medic with a uber and skipped him."); - } - return true; - } - } - } - - /** - The client supplied does not have an uber above the supplied level, return false - */ - return false; -} - -stock bool:HasBuildingsBuilt(iClient) -{ - - /** - We have to start a loop to check the owner of all the valid entities - */ - new iMaxEntities = GetMaxEntities(); - for (new i = MaxClients + 1; i <= iMaxEntities; i++) - { - if (!IsValidEntity(i)) - { - - /** - Not valid, continue to next one - */ - continue; - } - - /** - Get the name of the current entity - */ - decl String:sNetClass[32]; - GetEntityNetClass(i, sNetClass, sizeof(sNetClass)); - - /** - See if its something that an engineer would build - */ - if (strcmp(sNetClass, "CObjectSentrygun") == 0 - || strcmp(sNetClass, "CObjectTeleporter") == 0 - || strcmp(sNetClass, "CObjectDispenser") == 0) - { - - /** - It is, so lets check the owner - */ - if (GetEntDataEnt2(i, g_iOwnerOffset) == iClient) - { - - /** - The client supplied is the owner, return true - */ - if (g_bLogActivity2) - { - LogAction(0, iClient, "[STB] Found an engineer with buildings and skipped him."); - } - return true; - } - } - } - - /** - The client supplied didn't have any buildings, return false - */ - return false; -} - -stock StartABalance() -{ - - /** - See if we are already started a balance - */ - if (g_hBalanceTimer != INVALID_HANDLE) - { - - /** - We have, check if we still need to - */ - if (!IsUnbalanced() || !OkToBalance()) - { - - /** - We don't, stop the balance - It's almost impossible to reach this code, but we do it just in case - */ - CloseHandle(g_hBalanceTimer); - g_hBalanceTimer = INVALID_HANDLE; - g_bBalanceInProgress = false; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Balance delay timer was not needed and was killed before the callback."); - } - return; - } - else - { - - /** - We still need to balance - Bug out and wait for the current one to finish - */ - return; - } - } - - /** - Report that teams are unbalanced - */ - PrintToChatAll("[SM] %T", "UnBalanced", LANG_SERVER); - - /** - Check to see if we are supposed to delay the balance - */ - if (g_iBalanceDelay == 0) - { - - /** - Start the balance now - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Balance is now in progress."); - } - g_bBalanceInProgress = true; - g_hBalanceTimer = INVALID_HANDLE; - - /** - Check if we are allowed to scan living players - */ - if (!g_bDeadOnly) - { - - /** - We are allowed to, so we start a timer - */ - StartALivingPlayerTimer(); - - /** - Also report that we are now scanning dead players as well - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Now scanning dead players."); - } - } - else - { - - /** - We are not allowed to, so report that we are only scanning dead players - */ - if (g_bLogActivity) - LogAction(0, -1, "[STB] Only scanning dead players."); - } - - /** - We started the balance, bug out - */ - return; - } - - /** - We are supposed to delay the balance, start a balance timer - */ - g_hBalanceTimer = CreateTimer(float(g_iBalanceDelay), Timer_BalanceTeams, _, TIMER_FLAG_NO_MAPCHANGE); - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Teams are unbalanced. Balance delay timer started."); - } -} - -stock StartALivingPlayerTimer() -{ - - /** - Start a timer to check living players - */ - if (g_hLivingPlayerCheckTimer != INVALID_HANDLE) - { - - /** - If we for some reason already have one started, stop it. - */ - CloseHandle(g_hLivingPlayerCheckTimer); - g_hLivingPlayerCheckTimer = INVALID_HANDLE; - } - - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Living player balance delay timer started."); - } - g_hLivingPlayerCheckTimer = CreateTimer(float(g_iLivingPlayerCheckDelay), Timer_LivingPlayerCheck, _, TIMER_FLAG_NO_MAPCHANGE); -} - -stock FindSwitchablePlayer() -{ - - /** - Start a loop to find a switchable player - */ - new iPlayer; - new iBiggerTeam = GetBiggerTeam(); - for (new i = 1; i <= MaxClients; i++) - { - - /** - Check the stock function to see if we are allows to even switch the player - */ - if (!IsSwitchablePlayer(i, iBiggerTeam)) - { - continue; - } - - /** - If the mod is TF2 and they have Priority Players set check if the client has buildings or an uber - */ - if (g_CurrentMod == GameType_TF && g_bPriorityPlayers) - { - if (HasUber(i) || HasBuildingsBuilt(i)) - { - continue; - } - } - - /** - So far we are able we switch this player - Now we check the buddy system - */ - if (g_bBuddyEnabled) - { - - /** - Buddy system is enabled, check to see if client has buddy - */ - if (SM_GetClientBuddy(i) != 0) - { - - /** - The client has a buddy, so we check to see if they are on same team - */ - if (GetClientTeam(i) == GetClientTeam(SM_GetClientBuddy(i))) - { - - /** - They are, so we continue to next client - */ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] With a balance in progress a buddy on the right team was found and skipped."); - } - continue; - } - else - { - - /** - They are not on the same team, set this client - The buddy could be in spec, and that would make it not matter where he is, or the buddy is on the smaller team - */ - iPlayer = i; - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] With a balance in progress a buddy on the wrong team was found."); - } - break; - } - } - else - { - - /** - The client does not have a buddy, set this client - */ - iPlayer = i; - break; - } - } - else - { - - /** - Buddy system is not enabled, set this client - */ - iPlayer = i; - break; - } - } - - /** - Return the client we set, this could be 0, but very unlikely - */ - return iPlayer; -} - -stock BalancePlayer(iClient, iTeam) -{ - new Handle:hPack = CreateDataPack(); - WritePackCell(hPack, iClient); - WritePackCell(hPack, iTeam); - CreateTimer(0.1, Timer_BalancePlayer, hPack, TIMER_FLAG_NO_MAPCHANGE); -} - -stock CleanUp(iClient) -{ - g_aPlayers[iClient][bFlagCarrier] = false; - g_aPlayers[iClient][bSwitched] = false; - if (g_aPlayers[iClient][hForcedTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hForcedTimer]); - g_aPlayers[iClient][hForcedTimer] = INVALID_HANDLE; - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] Forced player disconnected, killing timer."); - } - } - if (g_aPlayers[iClient][hBalanceTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hBalanceTimer]); - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] Living player set to be balanced disconnected, killing timer."); - } - } -} - -stock GetSmallerTeam() -{ - - /** - Get the count of players on each team - */ - new iCountT1 = GetTeamClientCount(g_aCurrentTeams[Team1]); - new iCountT2 = GetTeamClientCount(g_aCurrentTeams[Team2]); - - /** - Return the smaller team - */ - if (iCountT1 < iCountT2) - { - return g_aCurrentTeams[Team1]; - } - else if (iCountT1 > iCountT2) - { - return g_aCurrentTeams[Team2]; - } - return 0; -} - -stock GetBiggerTeam() -{ - - /** - Get the count of players on each team - */ - new iCountT1 = GetTeamClientCount(g_aCurrentTeams[Team1]); - new iCountT2 = GetTeamClientCount(g_aCurrentTeams[Team2]); - - /** - Return the bigger team - */ - if (iCountT1 > iCountT2) - { - return g_aCurrentTeams[Team1]; - } - else if (iCountT1 < iCountT2) - { - return g_aCurrentTeams[Team2]; - } - return 0; -} - -stock SetGameCvars() -{ - if (g_bConVarControl && g_bIsEnabled) - { - if (stb_mp_autoteambalance != INVALID_HANDLE) - { - SetConVarInt(stb_mp_autoteambalance, 0); - } - if (stb_mp_teams_unbalance_limit != INVALID_HANDLE) - { - SetConVarInt(stb_mp_teams_unbalance_limit, g_iUnbalanceLimit); - } - } -} - -/* TIMER FUNCTIONS */ - -public Action:Timer_ChangeTeamBalanceDelay(Handle:timer, any:data) -{ - - /** - Finally start one if it's still unbalanced - */ - if (IsUnbalanced() && !g_bBalanceInProgress) - { - StartABalance(); - } -} - -public Action:Timer_BalanceTeams(Handle:timer, any:data) -{ - - /** - See if we still need to balance the teams - */ - if (!IsUnbalanced() || !OkToBalance()) - { - - /** - We don't, kill the balance - */ - g_bBalanceInProgress = false; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Balance delay timer was not needed and died."); - } - g_hBalanceTimer = INVALID_HANDLE; - return Plugin_Handled; - } - - /** - We still need to balance the teams - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Teams are still unbalanced. Balance is now in progress."); - } - g_bBalanceInProgress = true; - - - /** - Check if we are allowed to scan living players - */ - if (!g_bDeadOnly) - { - - /** - We are allowed to, so we start a timer - */ - StartALivingPlayerTimer(); - - /** - Also report that we are now scanning dead players as well - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Now scanning dead players."); - } - } - else - { - - /** - We are not allowed to, so report that we are only scanning dead players - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Only scanning dead players."); - } - } - - g_hBalanceTimer = INVALID_HANDLE; - return Plugin_Handled; -} - -public Action:Timer_LivingPlayerCheck(Handle:timer, any:data) -{ - - /** - Check to see if we still need to balance the teams - */ - if (!IsUnbalanced() || !OkToBalance()) - { - - /** - We don't, kill it and bug out - */ - g_bBalanceInProgress = false; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Living player balance delay timer was not needed and died."); - } - g_hLivingPlayerCheckTimer = INVALID_HANDLE; - return Plugin_Handled; - } - - /** - Call the stock function to find a player we can switch - */ - new iPlayer = FindSwitchablePlayer(); - - /** - Check to see if we found a player - */ - if (iPlayer == 0) - { - - /** - In the unlikely event that the stock function didn't return a player - Start a loop to find a random player - */ - new iBiggerTeam = GetBiggerTeam(); - do - { - iPlayer = GetRandomInt(1, MaxClients); - } while (!IsSwitchablePlayer(iPlayer, iBiggerTeam)); - - if (g_bLogActivity) - { - LogAction(0, iPlayer, "[STB] Found a random living player."); - } - } - else - { - if (g_bLogActivity) - { - LogAction(0, iPlayer, "[STB] Found a living player."); - } - } - - /** - Now that we have a player assigned them to the smaller team - */ - new iSmallerTeam = GetSmallerTeam(); - SM_SetForcedTeam(iPlayer, iSmallerTeam, true); - - /** - Let the player know we could be switching him soon - */ - PrintHintText(iPlayer, "%T", "PlayerMessage", LANG_SERVER, g_iLivingPlayerSwitchDelay); - if (g_bLogActivity) - { - LogAction(0, iPlayer, "[STB] Living player placed on a timer."); - } - - /** - Create a timer to switch the player - */ - g_aPlayers[iPlayer][hBalanceTimer] = CreateTimer(float(g_iLivingPlayerSwitchDelay), Timer_LivingPlayerBalance, iPlayer, TIMER_FLAG_NO_MAPCHANGE); - - /** - Reset the timer handle - */ - g_hLivingPlayerCheckTimer = INVALID_HANDLE; - - /** - We are done, bug out - */ - return Plugin_Handled; -} - -public Action:Timer_LivingPlayerBalance(Handle:timer, any:iClient) -{ - - /** - Check to make sure we still need to balance - */ - if (!IsUnbalanced() || !OkToBalance()) - { - - /** - We don't need to balance, bug out - */ - g_bBalanceInProgress = false; - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - SM_ClearForcedTeam(iClient); - return Plugin_Handled; - } - - /** - We still need to balance, lets make sure we can still balance this player - */ - if (!IsClientConnected(iClient) || g_aPlayers[iClient][bFlagCarrier]) - { - g_bBalanceInProgress = false; - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - SM_ClearForcedTeam(iClient); - if (g_bLogActivity) - { - if (g_aPlayers[iClient][bFlagCarrier]) - { - LogAction(0, iClient, "[STB] Living player became flag carrier, balance restarted."); - } - else - { - LogAction(0, iClient, "[STB] Living player timer was not needed and died."); - } - } - return Plugin_Handled; - } - - /** - Clear to balance this player, so do it - */ - BalancePlayer(iClient, SM_GetForcedTeam(iClient)); - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] Living player was switched."); - } - - /** - We are done, bug out - */ - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - return Plugin_Handled; -} - -public Action:Timer_BalancePlayer(Handle:timer, Handle:pack) -{ - - /** - Rest the datapack and load the variables - */ - ResetPack(pack); - new iClient = ReadPackCell(pack); - new iUnBalancedTeam = ReadPackCell(pack); - - /** - We are done with you now - */ - CloseHandle(pack); - - /** - Check the team and make sure its a valid team - */ - if(!SM_IsValidTeam(iUnBalancedTeam)) - { - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] Balance failed due to invalid team number %i", iUnBalancedTeam); - } - return Plugin_Handled; - } - - /** - Use our core function to change the clients team - */ - SM_MovePlayer(iClient, iUnBalancedTeam); - - return Plugin_Handled; -} - -public Action:Timer_RoundStart(Handle:timer, any:data) -{ - g_bRoundStart = false; - if (OkToBalance() && IsUnbalanced() && !g_bBalanceInProgress) - { - StartABalance(); - } - return Plugin_Handled; -} - -public Action:Timer_ForcedExpired(Handle:timer, any:iClient) -{ - SM_ClearForcedTeam(iClient); - g_aPlayers[iClient][bSwitched] = false; - g_aPlayers[iClient][hForcedTimer] = INVALID_HANDLE; - return Plugin_Handled; -} - -public Action:Timer_WelcomeAdvert(Handle:timer, any:iClient) -{ - if (IsClientConnected(iClient) && IsClientInGame(iClient)) - { - PrintToChat (iClient, "\x01\x04[STB]\x01 %T", "BuddyWelcomeMsg1", LANG_SERVER); - PrintToChat (iClient, "\x01\x04[STB]\x01 %T", "BuddyWelcomeMsg2", LANG_SERVER); - PrintToChat (iClient, "\x01\x04[STB]\x01 %T", "BuddyWelcomeMsg3", LANG_SERVER); - } - return Plugin_Handled; -} - -/* CONSOLE VARIABLE CHANGE EVENT */ - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (convar == stb_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsEnabled = false; - PrintToChatAll("[SM] %T", "Disabled", LANG_SERVER); - LogAction(0, -1, "[SimpleTeamBalancer] Disabled"); - } - else - { - g_bIsEnabled = true; - SetGameCvars(); - PrintToChatAll("[SM] %T", "Enabled", LANG_SERVER); - LogAction(0, -1, "[SimpleTeamBalancer] Enabled"); - } - } - else if (convar == stb_logactivity) - { - if (StringToInt(newValue) == 0) - { - g_bLogActivity = false; - LogAction(0, -1, "[STB] Log Activity DISABLED."); - } - else - { - g_bLogActivity = true; - LogAction(0, -1, "[STB] Log Activity ENABLED."); - } - } - else if (convar == stb_logactivity2) - { - if (StringToInt(newValue) == 0) - { - g_bLogActivity2 = false; - LogAction(0, -1, "[STB] Detailed Log Activity DISABLED."); - } - else - { - g_bLogActivity2 = true; - LogAction(0, -1, "[STB] Detailed Log Activity ENABLED."); - } - } - else if (convar == stb_convarcontrol) - { - if (StringToInt(newValue) == 0) - { - g_bConVarControl = false; - } - else - { - g_bConVarControl = true; - SetGameCvars(); - } - } - else if (convar == stb_deadonly) - { - if (StringToInt(newValue) == 0) - { - g_bDeadOnly = false; - } - else - { - g_bDeadOnly = true; - } - } - else if (convar == stb_priorityenabled) - { - if (StringToInt(newValue) == 0) - { - g_bPriorityPlayers = false; - } - else - { - g_bPriorityPlayers = true; - } - } - else if (convar == stb_buddyenabled) - { - if (StringToInt(newValue) == 0) - { - g_bBuddyEnabled = false; - } - else - { - g_bBuddyEnabled = true; - } - } - else if (convar == stb_buddyrestriction) - { - if (StringToInt(newValue) == 0) - { - g_bBuddyRestriction = false; - } - else - { - g_bBuddyRestriction = true; - } - } - else if (convar == stb_unbalancelimit) - { - g_iUnbalanceLimit = StringToInt(newValue); - SetGameCvars(); - } - else if (convar == stb_balancedelay) - { - g_iBalanceDelay = StringToInt(newValue); - } - else if (convar == stb_roundstartdelay) - { - g_iRoundStartDelay = StringToInt(newValue); - } - else if (convar == stb_livingplayerswitchdelay) - { - g_iLivingPlayerSwitchDelay = StringToInt(newValue); - } - else if (convar == stb_livingplayercheckdelay) - { - g_iLivingPlayerCheckDelay = StringToInt(newValue); - } - else if (convar == stb_uberlevel) - { - g_fUberLevel = StringToFloat(newValue); - } - else if (convar == stb_switchbackforced) - { - g_iSwitchBackForced = StringToInt(newValue); - } - else if (convar == stb_adminflag) - { - SetConVarString(stb_adminflag, newValue); - } - else if (convar == stb_mp_autoteambalance) - { - SetGameCvars(); - } - else if (convar == stb_mp_teams_unbalance_limit) - { - SetGameCvars(); - } -} - -/* MENU CODE */ - -stock Handle:BuildPlayerMenu() -{ - new Handle:menu = CreateMenu(Menu_SelectPlayer); - AddTargetsToMenu(menu, 0, true, false); - SetMenuTitle(menu, "Select A Player:"); - SetMenuExitButton(menu, true); - return menu; -} - -public Menu_SelectPlayer(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - new buddy = GetClientOfUserId(StringToInt(sSelection)); - if (param1 == buddy) { - PrintHintText(param1, "%T", "SelectSelf", LANG_SERVER); - } else if (!IsClientInGame(buddy)) { - PrintHintText(param1, "%T", "BuddyGone", LANG_SERVER); - } else { - decl String:cName[128]; - decl String:bName[128]; - GetClientName(param1, cName, sizeof(cName)); - GetClientName(buddy, bName, sizeof(bName)); - if (!SM_IsBuddyLocked(buddy)) { - SM_AssignBuddy(param1, buddy); - PrintHintText(param1, "%T", "BuddyMsg", LANG_SERVER, bName); - PrintHintText(buddy, "%T", "BuddyMsg", LANG_SERVER, cName); - } else - PrintHintText(param1, "%T", "PlayerLockedBuddyMsg", LANG_SERVER, bName); - } - } else if (action == MenuAction_End) { - CloseHandle(menu); - } -} \ No newline at end of file diff --git a/Simple Chat Colors/addons/sourcemod/scripting/simple-teammanager.sp b/Simple Chat Colors/addons/sourcemod/scripting/simple-teammanager.sp deleted file mode 100644 index 008f443..0000000 --- a/Simple Chat Colors/addons/sourcemod/scripting/simple-teammanager.sp +++ /dev/null @@ -1,1351 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Team Manager -Description: - Manges players and their team - Admin menu integration - Allows admins/donators to swap their teams (clears force)* - Allows admins to move players to a team (forced\unforced)* - Allows admins to scramble the teams* - *Works with Simple Team Balancer (if installed) -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include - -#define PLUGIN_VERSION "2.1.$Rev$" -#define VOTE_YES "##YES##" -#define VOTE_NO "##NO##" - -enum PlayerData -{ - iNewTeam, - bool:bQueue -}; - -new Handle:stm_enabled = INVALID_HANDLE; -new Handle:stm_logactivity = INVALID_HANDLE; -new Handle:stm_adminflag_swapteam = INVALID_HANDLE; -new Handle:stm_adminflag_moveplayer = INVALID_HANDLE; -new Handle:stm_adminflag_scramble = INVALID_HANDLE; -new Handle:stm_scrambledelay = INVALID_HANDLE; -new Handle:stm_voteenabled = INVALID_HANDLE; -new Handle:stm_votewin = INVALID_HANDLE; -new Handle:stm_votedelay = INVALID_HANDLE; -new Handle:stm_mp_bonusroundtime = INVALID_HANDLE; -new Handle:g_hAdminMenu = INVALID_HANDLE; -new Handle:g_hTimerPrepScramble = INVALID_HANDLE; -new Handle:g_hTimerClearScrambleForce = INVALID_HANDLE; - -new g_aPlayers[MAXPLAYERS + 1][PlayerData]; - -new bool:g_bIsEnabled = true; -new bool:g_bVoteEnabled = true; -new bool:g_bLogActivity = true; -new bool:g_bScrambleRoundEnd = false; -new g_iVoteDelay, g_iLastVoteTime, g_iTimeLeft; -new Float:g_fScrambleDelay, Float:g_fVoteWin; - -public Plugin:myinfo = -{ - name = "Simple Team Manager", - author = "Simple Plugins", - description = "Manages players and thier team.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -public OnPluginStart() -{ - - /** - Need to create all of our console variables. - */ - CreateConVar("stm_version", PLUGIN_VERSION, "Simple Team Manager Version",FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - stm_enabled = CreateConVar("stm_enabled", "1", "Enable or Disable Simple Team Manager", _, true, 0.0, true, 1.0); - stm_logactivity = CreateConVar("stm_logactivity", "0", "Enable or Disable the disaplying of events in the log", _, true, 0.0, true, 1.0); - stm_adminflag_swapteam = CreateConVar("stm_adminflag_swapteam", "a", "Admin flag to use for the swapteam command. Must be a in char format."); - stm_adminflag_moveplayer = CreateConVar("stm_adminflag_moveplayer", "c", "Admin flag to use for the moveplayer command. Must be a in char format."); - stm_adminflag_scramble = CreateConVar("stm_adminflag_scramble", "c", "Admin flag to use for the scrambleteam command. Must be a in char format."); - stm_scrambledelay = CreateConVar("stm_scrambledelay", "15", "Delay to scramble teams"); - stm_voteenabled = CreateConVar("stm_voteenabled", "1", "Enable or Disable voting to scramble the teams", _, true, 0.0, true, 1.0); - stm_votewin = CreateConVar("stm_votewin", "0.45", "Win percentage vote must win by", _, true, 0.0, true, 1.0); - stm_votedelay = CreateConVar("stm_votedelay", "600", "Delay before another vote can be cast"); - stm_mp_bonusroundtime = FindConVar("mp_bonusroundtime"); - - - /** - Need deal with changes to the console variables after the plugin is loaded. - We could not do this and just call the actual console variable each time we need it, but it's not efficent. - */ - HookConVarChange(stm_enabled, ConVarSettingsChanged); - HookConVarChange(stm_logactivity, ConVarSettingsChanged); - HookConVarChange(stm_scrambledelay, ConVarSettingsChanged); - HookConVarChange(stm_voteenabled, ConVarSettingsChanged); - HookConVarChange(stm_votewin, ConVarSettingsChanged); - HookConVarChange(stm_votedelay, ConVarSettingsChanged); - - /** - Need to register the commands we are going to create and use. - */ - RegConsoleCmd("sm_swapteam", Command_SwapTeam, "sm_swapteam <[0]instant/[1]queued>: Swaps your team to the other team"); - RegConsoleCmd("sm_moveplayer", Command_MovePlayer, "sm_moveplayer <[0]instant/[1]ondeath> <[0]unforced/[1]forced>: Moves a player to the specified team"); - RegConsoleCmd("sm_scrambleteams", Command_ScrambleTeams, "sm_scrambleteams: <[0]now/[1]roundend> <[0]dontrestart/[1]restartround> Scrambles the current teams"); - RegConsoleCmd("sm_votescramble", Command_VoteScramble, "sm_votescramble: Starts a vote to scramble the teams"); - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[STM] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_death", HookPlayerDeath, EventHookMode_Post); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Post); - switch (g_CurrentMod) - { - case GameType_TF: - { - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - } - case GameType_DOD: - { - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_Post); - } - default: - { - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - - /** - Now we have to deal with the admin menu. If the admin library is loaded call the function to add our items. - */ - new Handle:gTopMenu; - if (LibraryExists("adminmenu") && ((gTopMenu = GetAdminTopMenu()) != INVALID_HANDLE)) - { - OnAdminMenuReady(gTopMenu); - } - - /** - Load translations and .cfg file - */ - LoadTranslations ("simpleteammanager.phrases"); - AutoExecConfig(true, "plugin.simpleteammanager"); - LogAction(0, -1, "[STM] Simple Team Manager is loaded."); -} - -public OnAllPluginsLoaded() -{ - //something -} - -public OnLibraryRemoved(const String:name[]) -{ - if (StrEqual(name, "adminmenu")) - { - - /** - Looks like the admin menu was removed. Set the global. - */ - g_hAdminMenu = INVALID_HANDLE; - } - else if (StrEqual(name, "simpleplugins")) - { - SetFailState("Required plugin Simple SourceMod Plugins Core was removed."); - } -} - -public OnConfigsExecuted() -{ - - /** - Once we loaded up all the console variables from the config file, lets now set all the global variables we will use. - */ - g_bIsEnabled = GetConVarBool(stm_enabled); - g_bLogActivity = GetConVarBool(stm_logactivity); - g_fScrambleDelay = GetConVarFloat(stm_scrambledelay); - g_iVoteDelay = GetConVarInt(stm_votedelay); - g_fVoteWin = GetConVarFloat(stm_votewin); - g_iLastVoteTime = RoundFloat(GetEngineTime()); - g_bScrambleRoundEnd = false; - g_hTimerClearScrambleForce = INVALID_HANDLE; - - /** - Report enabled - */ - if (g_bIsEnabled) - { - LogAction(0, -1, "[STM] Simple Team Manager is ENABLED."); - } - else - { - LogAction(0, -1, "[STM] Simple Team Manager is DISABLED."); - } - - if (g_bLogActivity) - { - LogAction(0, -1, "[STM] Log Activity ENABLED."); - } - else - { - LogAction(0, -1, "[STM] Log Activity DISABLED."); - } -} - -/* COMMANDS */ - -public Action:Command_SwapTeam(client, args) -{ - - /** - Make sure we are enabled, if not bug out. - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - If this was ran from the console bug out. - */ - if (client == 0) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure the client is authorized to run this command. - */ - decl String:sFlags[5]; - GetConVarString(stm_adminflag_swapteam, sFlags, sizeof(sFlags)); - if (!SM_IsValidAdmin(client, sFlags)) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Lets make sure the client is one a team we can swap. - If he is we set the global array to the opposite team. - */ - new iTeam = GetClientTeam(client); - if (iTeam == g_aCurrentTeams[Team1]) - { - g_aPlayers[client][iNewTeam] = g_aCurrentTeams[Team2]; - } - else if (iTeam == g_aCurrentTeams[Team2]) - { - g_aPlayers[client][iNewTeam] = g_aCurrentTeams[Team1]; - } - else - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "InValidTeam", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check to see if we have command arguments. - */ - if (GetCmdArgs()) - { - - /** - We do, so lets get it and see if the client wants to be switched instantly or queued for death. - */ - decl String:sArg[5]; - GetCmdArg(1, sArg, sizeof(sArg)); - new iWantsQue = StringToInt(sArg); - if (iWantsQue && !g_aPlayers[client][bQueue]) - { - - /** - He wants the que and isn't already in it, set the global array. - */ - g_aPlayers[client][bQueue] = true; - ReplyToCommand(client, "\x01\x04[STM]\x01 %T", "PlayerQueue", LANG_SERVER); - } - else if (!iWantsQue) - { - - /** - He wants to be switched right now, lets call the stock function. - */ - SM_MovePlayer(client, g_aPlayers[client][iNewTeam]); - } - } - else - { - - /** - There are no command arguments so we build and display the swap menu. - */ - DisplaySwapModeMenu(client, client); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_MovePlayer(client, args) -{ - - /** - Make sure we are enabled, if not bug out. - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the client is authorized to run this command. - */ - decl String:sFlags[5]; - GetConVarString(stm_adminflag_moveplayer, sFlags, sizeof(sFlags)); - if (!SM_IsValidAdmin(client, sFlags)) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check to see if we have command arguments. - */ - new iCmdArgs = GetCmdArgs(); - if (iCmdArgs == 0) - { - - /** - We don't. Build the player menu, display it, and bug out. - */ - DisplayPlayerMenu(client); - return Plugin_Handled; - } - - /** - Check the first argument - If should be a players name or userid. - */ - decl String:sPlayer[64]; - GetCmdArg(1, sPlayer, sizeof(sPlayer)); - new iPlayerIndex = FindTarget(client, sPlayer, true, true); - if (iPlayerIndex == -1 || !IsClientInGame(iPlayerIndex)) - { - - /** - We don't know who this is. Build the player menu, display it, and bug out. - */ - DisplayPlayerMenu(client); - return Plugin_Handled; - } - - /** - We have figured out the first argument, lets check the second. - If should be the team the client wants to put the player on. - */ - if (iCmdArgs >= 2) - { - - /** - We have a command argument at least, lets see if we can identify the team. - */ - decl String:sTeam[24]; - GetCmdArg(2, sTeam, sizeof(sTeam)); - - new iTeam = StringToInt(sTeam); - if (SM_IsValidTeam(iTeam)) - { - - /** - It's a vaild team so lets set the global array to the new team. - */ - g_aPlayers[iPlayerIndex][iNewTeam] = iTeam; - } - else - { - - /** - It's not a vaild team so set the menu to display to the team menu. - */ - DisplayTeamMenu(client, iPlayerIndex); - return Plugin_Handled; - } - } - else - { - /** - We were not given a team, display the team menu. - */ - DisplayTeamMenu(client, iPlayerIndex); - return Plugin_Handled; - } - - /** - Check to see if we were given any more command arguments and found a team. - */ - if (iCmdArgs < 3) - { - - /** - No more command arguments and found a team. - Now lets check to see if the player is a spectator. If he is there is no reason to ask if it's instant or on death... he can't die. - */ - if (!IsClientObserver(iPlayerIndex)) - { - - /** - Not a spectator so display the swapmode menu. - */ - DisplaySwapModeMenu(client, iPlayerIndex); - } - else - { - - /** - The player is a spectator. - We make sure the player is not set to switch on death, since a spec can't die. - */ - g_aPlayers[iPlayerIndex][bQueue] = false; - } - } - - /** - We have figured out the second argument, lets check the third. - If should be the how the client wants to move the player: instant/on death. - */ - if (iCmdArgs >= 3) - { - - /** - The client gave us a command argument, lets check it. - */ - decl String:sSwapMode[5]; - GetCmdArg(3, sSwapMode, sizeof(sSwapMode)); - new iWantsQue = StringToInt(sSwapMode); - if (iWantsQue) - { - - /** - The client wants to que the player, set the global array. - */ - g_aPlayers[iPlayerIndex][bQueue] = true; - } - else - { - - /** - The client doesn't want to que the player, set the global array. - */ - g_aPlayers[iPlayerIndex][bQueue] = false; - } - } - else - { - /** - No swapmode argument, display the menu - */ - DisplaySwapModeMenu(client, iPlayerIndex); - } - - if (iCmdArgs >= 4) - { - - /** - Since we are compiling for Simple Team Balancer, and given a 4th argument, lets check it. - If should be the if the client wants to force the player to that team. - */ - decl String:sPlayerForced[5]; - GetCmdArg(4, sPlayerForced, sizeof(sPlayerForced)); - new iForceHim = StringToInt(sPlayerForced); - if (iForceHim) - { - - /** - The client wants to force the player - */ - SM_SetForcedTeam(iPlayerIndex, g_aPlayers[iPlayerIndex][iNewTeam]); - } - else - { - - /** - The client doesn't want to force the player - */ - SM_ClearForcedTeam(iPlayerIndex); - } - } - else - { - - } - - /** - We found and processed all the arguments. - */ - if (!IsPlayerAlive(iPlayerIndex)) - { - - /** - The player is not alive or died during this process so we just move him. - */ - SM_MovePlayer(iPlayerIndex, g_aPlayers[iPlayerIndex][iNewTeam]); - } - else - { - if (!g_aPlayers[iPlayerIndex][bQueue]) - { - - /** - The player is alive and is not set to be queued so we just move him. - */ - SM_MovePlayer(iPlayerIndex, g_aPlayers[iPlayerIndex][iNewTeam]); - } - } - - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_ScrambleTeams(client, args) -{ - - /** - Make sure we are enabled, if not bug out. - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the client is authorized to run this command. - */ - decl String:sFlags[5]; - GetConVarString(stm_adminflag_scramble, sFlags, sizeof(sFlags)); - if (!SM_IsValidAdmin(client, sFlags)) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check if a scramble timer was already called, if so close it down. - */ - if (g_hTimerPrepScramble != INVALID_HANDLE) - { - CloseHandle(g_hTimerPrepScramble); - g_hTimerPrepScramble = INVALID_HANDLE; - } - - /** - Check if we have any command arguments. - If we don't we display the scramble menu and bug out. - */ - new iCmdArgs = GetCmdArgs(); - if (iCmdArgs == 0) - { - DisplayScrambleMenu(client); - return Plugin_Handled; - } - - /** - We have a command argument. - It should be whether or not to scramble at round end. - */ - decl String:sRoundEnd[5]; - GetCmdArg(1, sRoundEnd, sizeof(sRoundEnd)); - if (StringToInt(sRoundEnd)) - { - /** - The client wants to scramble at round end so we set the global bool. - */ - g_bScrambleRoundEnd = true; - } - else - { - g_bScrambleRoundEnd = false; - } - - /** - Check for another command argument. - It should be whether or not to restart the round. - */ - decl String:sRestartRound[5]; - new bool:bRestartRound = false; - GetCmdArg(1, sRestartRound, sizeof(sRestartRound)); - if (StringToInt(sRestartRound)) - { - bRestartRound = true; - } - - /** - Now we start the scramble timer. - */ - StartScrambleTimer(_, bRestartRound); - - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_VoteScramble(client, args) -{ - - /** - Make sure we are enabled, if not bug out. - */ - if (!g_bVoteEnabled || !g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Make sure there is a vote in progress, if so bug out. - */ - if (IsVoteInProgress()) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "VoteInProgress", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure enough time has passed since the last vote. - */ - new iVoteTime = RoundFloat(GetEngineTime()); - if (iVoteTime - g_iLastVoteTime <= g_iVoteDelay) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "ScrambleTime", LANG_SERVER); - return Plugin_Handled; - } - - /** - Enough time has passed so reset the global vote time to now. - */ - g_iLastVoteTime = iVoteTime; - - /** - Build the vote menu and send it to everyone. - */ - new Handle:hMenu = CreateMenu(Menu_VoteScramble); - SetMenuTitle(hMenu, "Scramble Teams?"); - AddMenuItem(hMenu, VOTE_YES, "Yes"); - AddMenuItem(hMenu, VOTE_NO, "No"); - SetMenuExitButton(hMenu, false); - VoteMenuToAll(hMenu, 20); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -/* HOOKED EVENTS */ - -public HookPlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Find out who died. - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - - /** - Find out how the client died. - */ - new String:sWeapon[64]; - GetEventString(event, "weapon", sWeapon, sizeof(sWeapon)); - if (StrEqual(sWeapon, "world", false)) - { - - /** - He died because he changed teams so cleanup and bug out. - */ - s_CleanUp(iClient); - return; - } - - /** - Find out if this player was queued to change teams. - */ - if (g_aPlayers[iClient][bQueue]) - { - /** - Looks like he was, so call the stock function to move him. - */ - SM_MovePlayer(iClient, g_aPlayers[iClient][iNewTeam]); - } -} - -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Find out who changed teams. - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - - /** - If he was queued to switch teams we cleanup the variables. The client did it themself. - */ - if (g_aPlayers[iClient][bQueue]) - { - s_CleanUp(iClient); - } -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get the amount of time left in the map. - */ - new iTimeLeft; - GetMapTimeLeft(iTimeLeft); - - /** - Check to see if we are supposed to scramble at the end of the round and that there is enough time left in the map. - */ - if (g_bScrambleRoundEnd && iTimeLeft >= 60) - { - - /** - Check to see if there is a scramble timer in action and if so close it down. - */ - if (g_hTimerPrepScramble != INVALID_HANDLE) - { - CloseHandle(g_hTimerPrepScramble); - g_hTimerPrepScramble = INVALID_HANDLE; - } - - /** - Determine the round end chat time and run the scramble 1 second before it ends. - */ - new Float:fDelay = GetConVarFloat(stm_mp_bonusroundtime); - fDelay -= 1.0; - StartScrambleTimer(fDelay); - } -} - -public OnClientPostAdminCheck(client) -{ - - /** - Determine if the client has the flag to use the swapteam command. - */ - decl String:sFlags[5]; - GetConVarString(stm_adminflag_swapteam, sFlags, sizeof(sFlags)); - if (SM_IsValidAdmin(client, sFlags)) - { - /** - The client does so lets create a timer to run an advertise to tell him about it. - */ - CreateTimer (60.0, Timer_WelcomeAdvert, client); - } -} - -public OnClientDisconnect(client) -{ - - /** - Cleanup the clients variables. - */ - s_CleanUp(client); -} - -public SM_OnPlayerMoved(Handle:plugin, client, team) -{ - - /** - Make sure we called the move function - */ - if (plugin != GetMyHandle()) - { - if (g_bLogActivity) - { - LogAction(0, client, "[STM] Callback was not started with current plugin, bugging out."); - } - return; - } - - decl String:sPlayerName[64]; - GetClientName(client, sPlayerName, sizeof(sPlayerName)); - - PrintToChat(client, "\x01\x04[SM]\x01 %T", "PlayerSwitched", LANG_SERVER); - - s_CleanUp(client); -} - -/* TIMER FUNCTIONS */ - -public Action:Timer_PrepTeamScramble(Handle:timer, any:data) -{ - new bool:bRestartRound = data; - /** - Call the scramble the teams stock function. - */ - PrepTeamScramble(bRestartRound); - - /** - Reset the timer handle so we know the timer is done. - */ - g_hTimerPrepScramble = INVALID_HANDLE; - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Timer_ScrambleTheTeams(Handle:timer, any:data) -{ - new iPlayers[MAXPLAYERS + 1]; - new iCount, i, bool:bTeam, bool:bRestartRound = data; - - /** - Get all the client index numbers of valid players - */ - for(i = 1; i <= MaxClients; i++) - { - if(IsClientInGame(i)) // && !IsFakeClient(i)) - { - iPlayers[iCount++] = i; - } - } - - /** - Randomly sort the players - */ - SortIntegers(iPlayers, iCount, Sort_Random); - - /** - Loop through all the players and assign each one to a team, alternating each time - */ - for(i = 0; i < iCount; i++) - { - if (!bRestartRound) - { - /** - We didn't want to restart the round, so we move them to spec 1 at a time. - */ - SM_MovePlayer(iPlayers[i], g_aCurrentTeams[Spectator]); - } - SM_MovePlayer(iPlayers[i], bTeam ? g_aCurrentTeams[Team2] : g_aCurrentTeams[Team1]); - SM_SetForcedTeam(iPlayers[i], bTeam ? g_aCurrentTeams[Team2] : g_aCurrentTeams[Team1], true); - bTeam = !bTeam; - } - - /** - Reset this variable since we completed a scramble - */ - g_bScrambleRoundEnd = false; - - if (g_hTimerClearScrambleForce != INVALID_HANDLE) - { - CloseHandle(g_hTimerClearScrambleForce); - g_hTimerClearScrambleForce = INVALID_HANDLE; - } - - g_hTimerClearScrambleForce = CreateTimer(300.0, Timer_ClearScrambleForce, _, TIMER_FLAG_NO_MAPCHANGE); - - ServerCommand("mp_timelimit %i", g_iTimeLeft / 60); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Timer_ClearScrambleForce(Handle:timer, any:data) -{ - - for(new i = 1; i <= MaxClients; i++) - { - if(IsClientInGame(i)) // && !IsFakeClient(i)) - { - SM_ClearForcedTeam(i); - PrintToChat(i, "\x01\x04[SM]\x01 Your forced team status has been cleared"); - } - } - - g_hTimerClearScrambleForce = INVALID_HANDLE; - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Timer_WelcomeAdvert(Handle:timer, any:client) -{ - - /** - Lets make sure the client is connected and actually in the game. - */ - if (IsClientConnected(client) && IsClientInGame(client)) - { - - /** - We are good to go so lets tell him about the swapteam command. - */ - PrintToChat (client, "\x01\x04[STM]\x01 %T", "SwapTeamMsg", LANG_SERVER); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -/* STOCK FUNCTIONS */ - -stock s_CleanUp(iClient) -{ - - /** - Reset all the client variables - */ - g_aPlayers[iClient][bQueue] = false; - g_aPlayers[iClient][iNewTeam] = 0; -} - -stock StartScrambleTimer(Float:fdelay = 0.0, bool:bRestartRound = false) -{ - if (fdelay == 0.0) - { - fdelay = g_fScrambleDelay; - } - if (g_hTimerPrepScramble != INVALID_HANDLE) - { - CloseHandle(g_hTimerPrepScramble); - g_hTimerPrepScramble = INVALID_HANDLE; - } - PrintCenterTextAll("%T", "Scramble", LANG_SERVER); - g_hTimerPrepScramble = CreateTimer(fdelay, Timer_PrepTeamScramble, bRestartRound, TIMER_FLAG_NO_MAPCHANGE); -} - -stock PrepTeamScramble(bool:bRestartRound = false) -{ - new iPlayers[MAXPLAYERS + 1]; - new iCount; - - GetMapTimeLeft(g_iTimeLeft); - - if (bRestartRound) - { - - for(new i = 1; i <= MaxClients; i++) - { - if(IsClientInGame(i)) - // && !IsFakeClient(i)) - { - iPlayers[iCount++] = i; - SM_ClearForcedTeam(i); - SM_ClearBuddy(i); - SM_MovePlayer(i, g_aCurrentTeams[Spectator]); - } - } - } - else - { - //Can't move them all to spec at the same time - for(new i = 1; i <= MaxClients; i++) - { - if(IsClientInGame(i)) - // && !IsFakeClient(i)) - { - iPlayers[iCount++] = i; - SM_ClearForcedTeam(i); - SM_ClearBuddy(i); - //SM_MovePlayer(i, g_aCurrentTeams[Spectator]); - } - } - } - CreateTimer(4.0, Timer_ScrambleTheTeams, bRestartRound, TIMER_FLAG_NO_MAPCHANGE); -} - -/* CONSOLE VARIABLE CHANGE EVENT */ - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (convar == stm_enabled) { - if (StringToInt(newValue) == 0) { - g_bIsEnabled = false; - LogAction(0, -1, "[STM] Simple Team Manager is loaded and disabled."); - } else { - g_bIsEnabled = true; - LogAction(0, -1, "[STM] Simple Team Manager is loaded and enabled."); - } - } - else if (convar == stm_logactivity) { - if (StringToInt(newValue) == 0) { - g_bLogActivity = false; - LogAction(0, -1, "[STM] Log Activity DISABLED."); - } else { - g_bLogActivity = true; - LogAction(0, -1, "[STM] Log Activity ENABLED."); - } - } - else if (convar == stm_scrambledelay) - g_fScrambleDelay = StringToFloat(newValue); - else if (convar == stm_votewin) - g_fVoteWin = StringToFloat(newValue); - else if (convar == stm_votedelay) - g_iVoteDelay = StringToInt(newValue); - else if (convar == stm_voteenabled) { - if (StringToInt(newValue) == 0) - g_bVoteEnabled = false; - else - g_bVoteEnabled = true; - } -} - -/* MENU CODE */ - -public OnAdminMenuReady(Handle:topmenu) -{ - if (topmenu == g_hAdminMenu) - return; - g_hAdminMenu = topmenu; - new TopMenuObject:player_commands = FindTopMenuCategory(g_hAdminMenu, ADMINMENU_PLAYERCOMMANDS); - new TopMenuObject:server_commands = FindTopMenuCategory(g_hAdminMenu, ADMINMENU_SERVERCOMMANDS); - if (player_commands == INVALID_TOPMENUOBJECT) - return; - - AddToTopMenu(g_hAdminMenu, - "moveplayer", - TopMenuObject_Item, - AdminMenu_MovePlayer, - player_commands, - "moveplayer", - ADMFLAG_BAN); - - AddToTopMenu(g_hAdminMenu, - "scrambleteams", - TopMenuObject_Item, - AdminMenu_Scrambleteams, - server_commands, - "scrambleteams", - ADMFLAG_BAN); -} - -public AdminMenu_MovePlayer(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) -{ - if (action == TopMenuAction_DisplayOption) - Format(buffer, maxlength, "Move Player"); - else if (action == TopMenuAction_SelectOption){ - DisplayPlayerMenu(param); - } -} - -public AdminMenu_Scrambleteams(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) -{ - if (action == TopMenuAction_DisplayOption) - Format(buffer, maxlength, "Scramble Teams"); - else if (action == TopMenuAction_SelectOption) { - DisplayScrambleMenu(param); - } -} - -public Menu_SelectPlayer(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - DisplayTeamMenu(param1, GetClientOfUserId(StringToInt(sSelection))); - } else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -public Menu_SelectTeam(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new iTeam; - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - decl String:sIndex[64]; - if (SplitString(sSelection, "A", sIndex, sizeof(sIndex)) != -1) - iTeam = g_aCurrentTeams[Team1]; - else if (SplitString(sSelection, "B", sIndex, sizeof(sIndex)) != -1) - iTeam = g_aCurrentTeams[Team2]; - else { - SplitString(sSelection, "C", sIndex, sizeof(sIndex)); - iTeam = g_aCurrentTeams[Spectator]; - } - new iTarget = StringToInt(sIndex); - g_aPlayers[iTarget][iNewTeam] = iTeam; - DisplaySwapModeMenu(param1, iTarget); - } else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -public Menu_SwapMode(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - decl String:sIndex[64]; - - if (SplitString(sSelection, "A", sIndex, sizeof(sIndex)) == -1) - { - SplitString(sSelection, "B", sIndex, sizeof(sIndex)); - } - - new iTarget = StringToInt(sIndex); - - if (StrContains(sSelection, "A", true) != -1) - { - g_aPlayers[iTarget][bQueue] = false; - } - else if (StrContains(sSelection, "B", true) != -1) - { - g_aPlayers[iTarget][bQueue] = true; - } - - if (param1 == iTarget && !g_aPlayers[iTarget][bQueue]) - { - SM_MovePlayer(iTarget, g_aPlayers[iTarget][iNewTeam]); - } - else - { - DisplayForceModeMenu(param1, iTarget); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - { - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } - return; -} - -public Menu_ForceMode(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - decl String:sIndex[64]; - if (SplitString(sSelection, "A", sIndex, sizeof(sIndex)) == -1) - { - SplitString(sSelection, "B", sIndex, sizeof(sIndex)); - } - new iTarget = StringToInt(sIndex); - if (StrContains(sSelection, "A", true) != -1) - { - SM_ClearForcedTeam(iTarget); - } - else if (StrContains(sSelection, "B", true) != -1) - { - SM_SetForcedTeam(iTarget, g_aPlayers[iTarget][iNewTeam], true); - } - if (!g_aPlayers[iTarget][bQueue]) - { - SM_MovePlayer(iTarget, g_aPlayers[iTarget][iNewTeam]); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - { - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } - return; -} - -public Menu_VoteScramble(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_VoteEnd) { - new winning_votes, total_votes; - GetMenuVoteInfo(param2, winning_votes, total_votes); - if (param1 == 0) { - if (float(total_votes) / float(winning_votes) < g_fVoteWin) { - PrintToChatAll("\x01\x04[SM]\x01 %T", "VoteScramble2", LANG_SERVER, winning_votes, total_votes); - return; - } - PrintCenterTextAll("[SM] %T", "Scramble", LANG_SERVER); - PrintToChatAll("\x01\x04[SM]\x01 %T", "VoteScramble1", LANG_SERVER, winning_votes, total_votes); - StartScrambleTimer(); - } - if (param1 == 1) { - PrintToChatAll("\x01\x04[SM]\x01 %T", "VoteScramble2", LANG_SERVER, winning_votes, total_votes); - } - } - if (action == MenuAction_End) - CloseHandle(menu); -} - -public Menu_ScrambleTeams(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "NOW", false)) - g_bScrambleRoundEnd = false; - else - g_bScrambleRoundEnd = true; - DisplayScrambleMenu2(param1); - } else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -public Menu_ScrambleTeams2(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[64]; - new bool:bRestartRound; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "NO", false)) - { - bRestartRound = false; - } - else - { - bRestartRound = true; - } - StartScrambleTimer(_, bRestartRound); - } else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -stock DisplayScrambleMenu(iClient) -{ - new Handle:hMenu = CreateMenu(Menu_ScrambleTeams); - SetMenuTitle(hMenu, "Select When to Scramble:"); - AddMenuItem(hMenu, "NOW", "Instantly"); - AddMenuItem(hMenu, "END", "At Round End"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplayScrambleMenu2(iClient) -{ - new Handle:hMenu = CreateMenu(Menu_ScrambleTeams2); - SetMenuTitle(hMenu, "Select When to Scramble:"); - AddMenuItem(hMenu, "NO", "No Round Restart"); - AddMenuItem(hMenu, "YES", "Restart Round"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplaySwapModeMenu(iClient, iTarget) -{ - new Handle:hMenu = CreateMenu(Menu_SwapMode); - decl String:optionA[64]; - decl String:optionB[64]; - Format(optionA, sizeof(optionA), "%iA", iTarget); - Format(optionB, sizeof(optionB), "%iB", iTarget); - SetMenuTitle(hMenu, "Select When to Swap:"); - AddMenuItem(hMenu, optionA, "Instantly (Kills)"); - if (!IsClientObserver(iTarget)) - AddMenuItem(hMenu, optionB, "Queue on next death"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplayForceModeMenu(iClient, iTarget) -{ - new Handle:hMenu = CreateMenu(Menu_ForceMode); - decl String:optionA[64]; - decl String:optionB[64]; - Format(optionA, sizeof(optionA), "%iA", iTarget); - Format(optionB, sizeof(optionB), "%iB", iTarget); - SetMenuTitle(hMenu, "Select Force Mode:"); - AddMenuItem(hMenu, optionA, "UnForced"); - AddMenuItem(hMenu, optionB, "Forced"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplayTeamMenu(iClient, iTarget) -{ - new Handle:hMenu = CreateMenu(Menu_SelectTeam); - decl String:optionA[64]; - decl String:optionB[64]; - decl String:optionC[64]; - Format(optionA, sizeof(optionA), "%iA", iTarget); - Format(optionB, sizeof(optionB), "%iB", iTarget); - Format(optionC, sizeof(optionC), "%iC", iTarget); - SetMenuTitle(hMenu, "Select Team:"); - AddMenuItem(hMenu, optionA, "Team One"); - AddMenuItem(hMenu, optionB, "Team Two"); - AddMenuItem(hMenu, optionC, "Spectator"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplayPlayerMenu(iClient) -{ - new Handle:hMenu = CreateMenu(Menu_SelectPlayer); - AddTargetsToMenu(hMenu, 0, true, false); - SetMenuTitle(hMenu, "Select A Player:"); - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} diff --git a/Simple Chat Colors/addons/sourcemod/translations/simpledonatorbenefits.phrases.txt b/Simple Chat Colors/addons/sourcemod/translations/simpledonatorbenefits.phrases.txt deleted file mode 100644 index 3826846..0000000 --- a/Simple Chat Colors/addons/sourcemod/translations/simpledonatorbenefits.phrases.txt +++ /dev/null @@ -1,62 +0,0 @@ -"Phrases" -{ - "PlayerLevelCmd" - { - "en" "Command must be run at the player level" - "fr" "Cette commande doit être tapée en jeu" - "hu" "Ezt a parancsot jatekosi szinten kell futtatni!" - } - "RestrictedCmd" - { - "en" "You must be a donator or admin to run this command" - "fr" "Vous devez être un donateur ou un admin pour lancer cette commande" - "hu" "A parancs futtatasahoz admin, vagy tamogatoi szint szukseges!" - } - "InValidTeam" - { - "en" "You must be on red or blue to swap teams" - "fr" "Vous devez être RED ou BLU pour changer d'équipe" - "hu" "Jatekban kell lenned, hogy megcsereld a csapatokat!" - } - "PlayerQueue" - { - "en" "You have been queued to swap teams on next death" - "fr" "Vous avez été mis en attente pour changer d'équipe lors de votre prochaine mort" - "hu" "A kovetkezo halalnal csapatcsere lesz" - } - "PlayerSwitched" - { - "en" "Your team has been switched as requested" - "fr" "Vous avez changé d'équipe comme demandé" - "hu" "A keresnek eleget teve a csapatod meg lett csererlve" - } - "SwapTeamMsg" - { - "en" "Type /swapteam or !swapteam to swap your team!" - } - "ReachedCount" - { - "en" "You have reached your health limit. You must die before you can use it again" - } - "AtMaxHealth" - { - "en" "You are already at your maximum health!" - } - "ToMaxHealth" - { - "en" "Instant health bonus applied! You are not at your maximun health!" - } - "HealthBonus" - { - "en" "Instant health bonus applied!" - } - "PublicJoinMessage" - { - "#format" "{1:s}" - "en" "{1} a [donator] as joined the server" - } - "PrivateJoinMessage" - { - "en" "Thanks for donating!" - } -} \ No newline at end of file diff --git a/Simple Chat Colors/addons/sourcemod/translations/simplespectate.phrases.txt b/Simple Chat Colors/addons/sourcemod/translations/simplespectate.phrases.txt deleted file mode 100644 index 2d1a096..0000000 --- a/Simple Chat Colors/addons/sourcemod/translations/simplespectate.phrases.txt +++ /dev/null @@ -1,42 +0,0 @@ -"Phrases" -{ - "Stopped spectating" - { - "#format" "{1:s}" - "en" "Stopped tracking player: {1}" - } - "Yourself" - { - "en" "You can't spectate yourself" - } - "Spectator" - { - "en" "You can't spectate another spectator" - } - "Spectating" - { - "#format" "{1:s}" - "en" "Now spectating {1}. Type !stopspec or /stopspec to stop spectating this player" - } - "Invalid Target" - { - "en" "Invalid target" - } - "Cant Target" - { - "en" "Can't target this player" - } - "Must Have Target" - { - "en" "You must be following/tracking a player to punish" - } - "Target Left" - { - "en" "The player you were following/tracking has left" - } - "Punished" - { - "#format" "{1:s}{2:s}{3:s}" - "en" "{1} was punished with a {2} for {3}" - } -} \ No newline at end of file diff --git a/Simple Chat Colors/addons/sourcemod/translations/simpleteambalancer.phrases.txt b/Simple Chat Colors/addons/sourcemod/translations/simpleteambalancer.phrases.txt deleted file mode 100644 index 03595fd..0000000 --- a/Simple Chat Colors/addons/sourcemod/translations/simpleteambalancer.phrases.txt +++ /dev/null @@ -1,130 +0,0 @@ -"Phrases" -{ - "UnBalanced" - { - "en" "Teams are unbalanced and will be balanced shortly" - "fr" "Les équipes ne sont pas équilibrées et le seront bientôt" - "de" "Die Teams sind ungleich und werden in Kürze ausgeglichen" - "hu" "A csapatok nem kiegyenlitettek! Egyensuly beallitas kovetkezik!" - } - "Enabled" - { - "en" "Simple Team Balancer is ENABLED" - "fr" "Simple Team Balancer est ACTIVE" - "de" "Simple Team Balancer ist AKTIV" - "hu" "Az Egyszeru Csapat Egyensulytarto AKTIV!" - } - "Disabled" - { - "en" "Simple Team Balancer is DISABLED" - "fr" "Simple Team Balancer est DESACTIVE" - "de" "Simple Team Balancer ist INAKTIV" - "hu" "Az Egyszeru Csapat Egyensulytarto INAKTIV!" - } - "PlayerMessage" - { - "#format" "{1:i}" - "en" "You are going to be auto balanced in {1} seconds unless a dead player can be found" - "fr" "Vous passerez dans l'autre équipe dans {1} secondes si aucun joueur mort ne peut être trouvé dans cet intervalle" - "de" "Du wirst in {1} Sekunden zum automatischen Ausgleich herangezogen wenn kein toter Spieler gefunden werden kann" - "hu" "{1} masodpercen belul at leszel helyezve a masik csapatba, hacsak nem lesz addig egy halott jatekos!" - } - "BalanceMessage" - { - "#format" "{1:s}" - "en" "{1} was moved to the other team for game balance" - "fr" "{1} est passé dans l'autre équipe pour équilibrer la partie" - "de" "{1} wurde zum anderen Team verschoben um das Spiel auszugleichen" - "hu" "{1} at lett helyezve az egyensuly megtartasa erdekeben." - } - "PlayerLevelCmd" - { - "en" "Command must be run at the player level" - "fr" "La commande doit être lancée au niveau du joueur" - "de" "Das Kommando muss auf Spieler Ebene ausgeführt werden" - "hu" "Jatekosi szinten kell futtatni ezt a parancsot!" - } - "CmdDisabled" - { - "en" "Command is currently disabled" - "fr" "La commande est actuellement désactivée" - "de" "Das Kommando ist momentan inaktiv" - "hu" "A parancs jelenleg inaktiv" - } - "RestrictedBuddy" - { - "en" "You must be a donator or admin to add a balance buddy" - "fr" "Vous devez être un donateur ou un admin pour choisir un partenaire" - "de" "Du musst ein Spender oder Admin sein um einen Partner wählen zu können" - "hu" "Tamogato vagy admin kell hogy legyel, hogy 'Tarsat' jelolhess meg" - } - "SelectSelf" - { - "en" "You cannot be your own buddy" - "fr" "Vous ne pouvez pas être votre propre partenaire" - "de" "Du kannst nicht dein eigener Partner sein" - "hu" "Nem valaszthatod ki onmagad!" - } - "BuddyGone" - { - "en" "Your selected buddy has disconnected" - "fr" "Le partenaire que vous avez sélectionné s'est déconnecté" - "de" "Dein gewählter Partner hat die Verbindung getrennt" - "hu" "A valasztott 'Tarsad' kilepett" - } - "BuddyMsg" - { - "#format" "{1:s}" - "en" "You and {1} are now buddies" - "fr" "Vous et {1} êtes maintenant partenaires" - "de" "Du und {1} seid jetzt Partner" - "hu" "{1} es Te 'Tarsak' vagytok." - } - "BuddyLockMsgDisabled" - { - "en" "You can now be anyone's buddy" - "fr" "Vous pouvez à présent être le partenaire de n'importe qui" - "de" "Du kannst jetzt jedermanns Partner sein" - "hu" "Barkinek lehetsz a 'Tarsa'." - } - "BuddyLockMsgEnabled" - { - "en" "Buddy selection locked. Only you can change your buddy" - "fr" "Sélection de partenaire bloquée. Vous êtes le seul à pouvoir choisir votre partenaire" - "de" "Wahl des Partners gesperrt. Nur du kannst deinen Partner wechseln" - "hu" "Tars-lista lezarva. Csak Te tudod modositani a Tars-listadat." - } - "PlayerLockedBuddyMsg" - { - "#format" "{1:s}" - "en" "{1} has locked his buddy selection. Try again" - "fr" "{1} a bloqué sa sélection de partenaire. Essayez de nouveau." - "de" "{1} hat seine Wahl des Partners gesperrt. Versuche es erneut" - "hu" "{1} lezarta a Tars-listajat. Probald kesobb!" - } - "BuddyWelcomeMsg1" - { - "en" "Select a balance buddy and stay together during an autobalance!" - "fr" "Choisissez un partenaire et restez ensemble durant l'équilibrage automatique!" - "de" "Wähle einen Partner und bleibt zusammen während eines Ausgleichs" - "hu" "Valasz ki egy 'Tarsat' akivel egyuttmaradhatsz a csapatkiegyenlites alatt!" - } - "BuddyWelcomeMsg2" - { - "en" "/buddy or !buddy to select a balance buddy" - "fr" "/buddy or !buddy pour choisir un partenaire" - "de" "/buddy oder !buddy um einen Partner zu wählen" - "hu" "Hasznald a /buddy vagy !buddy parancsokat a 'Tars' kijelolesehez" - } - "BuddyWelcomeMsg3" - { - "en" "/lockbuddy or !lockbuddy to lock your selection" - "fr" "/lockbuddy or !lockbuddy pour bloquer votre sélection" - "de" "/lockbuddy oder !lockbuddy um deine Auswahl zu sperren" - "hu" "Hasznald a /lockbuddy vagy a !lockbuddy parancsokat a Tars-listad lezarasahoz" - } -} - - - - diff --git a/Simple Chat Colors/addons/sourcemod/translations/simpleteammanager.phrases.txt b/Simple Chat Colors/addons/sourcemod/translations/simpleteammanager.phrases.txt deleted file mode 100644 index f2093a7..0000000 --- a/Simple Chat Colors/addons/sourcemod/translations/simpleteammanager.phrases.txt +++ /dev/null @@ -1,92 +0,0 @@ -"Phrases" -{ - "PlayerLevelCmd" - { - "en" "Command must be run at the player level" - "fr" "Cette commande doit être tapée en jeu" - "hu" "Ezt a parancsot jatekosi szinten kell futtatni!" - } - "RestrictedCmd" - { - "en" "You must be a donator or admin to run this command" - "fr" "Vous devez être un donateur ou un admin pour lancer cette commande" - "hu" "A parancs futtatasahoz admin, vagy tamogatoi szint szukseges!" - } - "InValidTeam" - { - "en" "You must be on red or blue to swap teams" - "fr" "Vous devez être RED ou BLU pour changer d'équipe" - "hu" "Jatekban kell lenned, hogy megcsereld a csapatokat!" - } - "PlayerInValidTeam" - { - "en" "Player must be on red or blue to swap teams" - "fr" "Le joueur doit être RED ou BLU pour changer d'équipe" - "hu" "Valamelyik csapatban kell lenni, hogy csere legyen" - } - "PlayerQueue" - { - "en" "You have been queued to swap teams on next death" - "fr" "Vous avez été mis en attente pour changer d'équipe lors de votre prochaine mort" - "hu" "A kovetkezo halalnal csapatcsere lesz" - } - "PlayerSwitched" - { - "en" "Your team has been switched" - } - "PlayerSwitched1" - { - "en" "Your team has been switched as requested" - "fr" "Vous avez changé d'équipe comme demandé" - "hu" "A keresnek eleget teve a csapatod meg lett csererlve" - } - "PlayerSwitched2" - { - "en" "Your team has been switched by an Admin" - "fr" "Vous avez été changé d'équipe par un admin" - "hu" "Az Admin megcserelte a csapatodat!" - } - "SwapTeamMsg" - { - "en" "Type /swapteam or !swapteam to swap your team!" - } - "PlayerSwitched3" - { - "#format" "{1:s}" - "en" "{1}'s team has been switched" - "fr" "{1} a changé d'équipe" - "hu" "{1} csapata meg lett cserelve" - } - "Scramble" - { - "en" "Teams are about to be scrambled!" - "fr" "Les équipes vont être rééquilibrés" - "hu" "A csapatok hamarosan meg lesznek keverve!" - } - "VoteScramble1" - { - "#format" "{1:i}{2:i}" - "en" "Vote Scramble successful with {1} votes out of {2}" - "fr" "Le vote d'équilibrage des équipes a réussi avec {1} votes pour sur {2}" - "hu" "A szavazas sikeres volt, {1} szavazat a keveresre a {2} -bol" - } - "VoteScramble2" - { - "#format" "{1:i}{2:i}" - "en" "Vote Scramble failed with {1} votes out of {2}" - "fr" "Le vote d'équilibrage a échoué avec {1} votes pour sur {2}" - "hu" "A szavazas sikertelen volt, {1} szavazat a keveresre a {2} -bol" - } - "VoteInProgress" - { - "en" "A vote is currently in progress" - "fr" "Un vote est actuellement en cours" - "hu" "Egy szavazas mar fut!" - } - "ScrambleTime" - { - "en" "A vote was recently made, please wait" - "fr" "Un vote a déjà été fait récemment, réessayez plus tard" - "hu" "Nemreg volt szavazas, kerlek varj egy kicsit!" - } -} \ No newline at end of file diff --git a/Simple Donator Benefits/addons/sourcemod/configs/simple-alltalkmanager_events.cfg b/Simple Donator Benefits/addons/sourcemod/configs/simple-alltalkmanager_events.cfg deleted file mode 100644 index b739cf0..0000000 --- a/Simple Donator Benefits/addons/sourcemod/configs/simple-alltalkmanager_events.cfg +++ /dev/null @@ -1,43 +0,0 @@ -"game_events" -{ - "teamplay_round_start" - { - "reason" "Round Start" - "setting" "1" - } - "teamplay_setup_finished" - { - "reason" "Setup Period Ended" - "setting" "0" - } - "teamplay_overtime_begin" - { - "reason" "Overtime Began" - "setting" "1" - } - "teamplay_overtime_end" - { - "reason" "Overtime Ended" - "setting" "1" - } - "teamplay_round_win" - { - "reason" "Round Ended" - "setting" "1" - } - "teamplay_suddendeath_begin" - { - "reason" "Sudden Death Began" - "setting" "1" - } - "teamplay_suddendeath_end" - { - "reason" "Sudden Death Ended" - "setting" "1" - } - "teamplay_round_stalemate" - { - "reason" "Stalemate" - "setting" "1" - } -} \ No newline at end of file diff --git a/Simple Donator Benefits/addons/sourcemod/configs/simple-chatcolors.cfg b/Simple Donator Benefits/addons/sourcemod/configs/simple-chatcolors.cfg deleted file mode 100644 index 14b98c6..0000000 --- a/Simple Donator Benefits/addons/sourcemod/configs/simple-chatcolors.cfg +++ /dev/null @@ -1,15 +0,0 @@ -"admin_colors" -{ - "groupname2" - { - "flag" "z" - "namecolor" "{green}" - "textcolor" "{olive}" - } - "groupname1" - { - "flag" "a" - "namecolor" "{teamcolor}" - "textcolor" "{green}" - } -} \ No newline at end of file diff --git a/Simple Donator Benefits/addons/sourcemod/plugins/simple-alltalkmanager.smx b/Simple Donator Benefits/addons/sourcemod/plugins/simple-alltalkmanager.smx deleted file mode 100644 index 6122756af68998fb531abcd0d08698e24cff25af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7028 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 diff --git a/Simple Donator Benefits/addons/sourcemod/plugins/simple-messagesuppression.smx b/Simple Donator Benefits/addons/sourcemod/plugins/simple-messagesuppression.smx deleted file mode 100644 index cc20dadd37d8ff23d0a64513cc09650f4bdbf24d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4845 zcmYM%XE>XE`v>q?RccnPDsHu@J!_@5qNo_HEkw+yU7HS6t5l5=V$`0kQN)U>y^0V! z?ph7C#R%fb{XGBs_`f)>@8|rD^W}9MKRrD&5IGsy_Dulbi!=a0-v9srq{v90f0GFS zxb}~k0RSB;0Dz9<05$+Xgp{nLf|IOFN*+>8lI%oEVN%Jl0|3qB0DuI^Tbuwu5$Ucx z$;rF`Kotc5ph>bSKL9`)4=^T`5y>K?b!(CXgaCkHN&vu>WT5!}&cH}ECE1xYN7BXD z6#|fSbq;g}NInY!dwaM9{1?H_{v^Ph13iKvBm_D`|J(Zf)3}16|G)E3|X|i`hb1C|L?p9%+2?IHv33u^2@U}_z&+M_NBc!#;a zUbU$3Ma6a|X(dn<5a&MdtOQ!Tir&@UEEB(C`FbH0FfX>RES<>&26*^t4Ui>dJZUdJ zziFpmAi70$TJ~2GW=cDxXZ^<@-m$x{(g4bZ_HB(LcxWfsrWm_~Uix6nI$wn87TLWd zaNAw^)imA4sU4E(nEx26)kgj-QhOa(ta+wbB=^MHrXHV@SK9dZfvWPANGA6h@>*u} zr?n=b6*Zy5#=9Su76j4C<)f1Ztt=H0?A0&Fo286`BG079KJ1L$Y)Vgjr+>0h;+j+X zIC@m+_t-asaQTo{&4nC`?bIC0yQ3Hb%>0w9_XkL`MRkEn-E`39BY9q9AYwK28f;C2 z2VyV1c{*LEmfghia4O0|5x+&-tAD_N9?LdVNJJA4R#DzS~9bM zT>+l5K2m$ka(3Fku!9E=<9IM`8MA|j4e?vLeUZa-eeKm<&3*8rUGtaw#tx9BH&vo+6nd2ixrZKj(x*~^f4Tm;_vE6&tW@Pm>GYwUGV|g@M2OBhF3@m% z(4h1$sR4t?Tpc7MP5?7M2+^MIm?$;$f8a%qKd&04=gQ`ikOG>#C1@smPY1tm$c;^6)~E)JA2jKX#xyd+XS!zw zgCB43dV$586uzW~+j7ktKI)t!s`RbMj8yK{{&s*V)WXCaJinYMDf|tbN0lIaoIqn$ zPW3Q}M45*L2QL5T2dp^@Ipe1r(-$pkm z@LNq1*Vgfw(Xe&-N@Wul6rVNmN~*%z=+Ru#=Ffehh{y00+b$usvGa~BdUr1;3Wxch zGuPb10v$D+iJpvtDk3g(>$EVOFcma% zB5yCdd2;leBF`BlwxoB-gH{PN;&vn@p)Qn4qnc|zdr$Xd^OQCmKYJ}aNXj)Y+N^r~ z{c-NLyd(Gdx7~%-NT`0F#^5ft5qhOVgv6B-dQ`A@Y%?4G94aZFw=Q?~xW^mq(=KCojb|TLl{l-Pd=#Xoi82q*m zF0u1dUeJ&U4<4BaBPQgHTK#F0+g|k|kE_%yzJ1EE@jm$Wxi^!=u`gBw2*mCTmF!gA zs+2RC^&M+1-hLunH|f11nNo{!8b+JusVd4q!z)4xr{nHGJ-~*+G~BdRD9LhS0=LLk zp2eQ689K;2%rrT$Fn<>=P8l+O- zWT-W6HD9LPpS&*2a^70x?fdOaAKR0sCz_u@k~6n%pbrLvrFX;hMZ~MLVoPEO@?K|Q zv)kk+0i4xQu;?tsz$~b(#&(qrkiTugZ5+W+q*6#53~v3szhFou7kA(>CLyD~IL)#- zf(B>XxF>HK7)#X@Uw%ulFRE9bEOb|wt~l?v`VL?`;5^smc-M-vGZHyB+85MT# z@sdxXt|(zT$ahEcrzJfEK#!5~&MDnQX1T@$@b0DRglWpsU!BxJOK}ZU9_;46T0PFf zAMA?a2Yerdk>l#`v|WU1&DJU1-25X=7YZ}3kzH-cnsqWb&ubY^@v9rIjyu|rwWYhi zGn^ZDG$h+fhYNwo#;JwNQqzZib7kP1C>^+?xOxXtLXWdHM#dfS$?{6Cw!qJ{wGoS1 zEOBbd!g;c*Pvy?;YcKiAjd31a3`NYQY}l>CQScZn*%Dn*Gq#pYbmug9SvPToJo;K2 zYxC`wVbpu1e-}CSL)u~PENvV8wwduBW`B{UEtim&=2tmzXU`r*v&^=vEmo5msw|38 zIV?lEm})Rw&@Y$9>|TrF6CGO`V2=qQ?@Ui4?ysK2DuZQ#hKB0>ZHP2QnZwS9I4(Cj z5J55vk6K(dg-_^bw^5wJQNe#*ln=DVhIc7}4ej9(OwGL5z^mts9k?j6NO;kCw|YLP zZQEgarR3;D)->xN2O)rMWO+_ILp6bkT|{-tt+fLWeVnBBSeZ2e1^4 zYig8gWOpbu9^!}i586hrWw0l_p=oAjSq(RK-F6aDQnV}h+%HBO4g>4JwqZ-t3R>5ldr!8~e{qjY{ES@wIcej6nwMIKeUA>T4+#Fa93-NmyfXtkKA zu;8@a2#M3i)jTTX?4sVWt4HUC#!cVG6bz%Y!o>8#fX&S|M18IW-E;nOOsD z-M9&KCF$fo4~C$GflK>h%irVuwEkAA38&~9OBxuqL0ss^ ztwy(Wc3sEDdyx!XkAf>|iR5$sFLY(hiv(YF|DH%`_)ck=2P8an*wu2%giugd`IEim z{;F1)W?MD$g3ZV+t_qb^-&zf3?iQO%6_PU<;0e58A^a)bB71-=B(6cntX%l}6lbr& zv%<1Xf=ff9(792uC#SmAU9~2gF4>_(TGhkQoP;{Thuhx{>W{CN6T4b?#J`jwq{5JT zKAkpnDY)-s;;-?6&Z73oZv5w{2k+ygA#2GARa;cuJh!aZ1;ioldLc*XI@NA(sA01C1t7pt zpKg{c!^hz_x48s+#QuY+<1ccH{O=|7whjGc#O=L?40KF0PR-4A|Ty_m0B8VEthwXP1-lzU@e{J!^SJY#UMhOWh7K&;}T ztQak_@iepw;6qvF850-Ko~k*HPD+r36tNhRg)uNFgAi*H<{50c_gItTV7|lhU`_UI zCpN^c+pobtZVNrlpbjA{dbuO;r^6K> z1|Ww0?UTql8}osIc>jKWcrl&2?InX_@`h_x!KdUNuFLE342VS93%joH=}iUk8b(B zklpM0(Z?c&zz@6%8*P4Rr3+8RS_TWI=y3gZvhLH&CoHK{D{KWI3mqXbBKNHHk68s%{ zKCv0(=1q`8lV%Lw4tBFTq@8JJpN%)K_N8&%)3^yCHn?ec{3tn^ofFoL>u}Y{AU1T7 zcNSbc_Zu|}$-J_PYPATYU%X?DjCT<@@o&onzp1BTrBKO8=_r1# z$QNm}Z?4rYXm4PUXWqauk$EeGYa%|aQ!xMB+^NjxvWPEIceaW8REaA7Gz746%a@`f zZ#;KvAm_n z)|IU*H}_a97*7SJD56q(8*MHfewCt3Csn#>BjS1+^%j*nsW0wzvVZ8Bzi~mn=oLFQ zu2O6HwGM=mnot9D3RnO>-2>k~Wxp8J55Z8NYA4jl9rL*X7q=JvVxu4JW>ycrKu{Cu zaX0qps#V_&V9hUXoj#giUw(^D4%*a+AU~Bz?5hRsw+5g(OGg0O{_lGkFBEb7d#ZQD zuQY;K6xZ@RmSSsv5`4|92+Yf!Kh*%y1_v=$y}qo#U)X|A;03entRGQxTF}G=C8+Cc z%PRsaefpxM_~#R=;pc`P3_jgEMTOrIL6zuT-h?^0g>OsAI}VogRXT(FTc;z+e3Ecy zdStaj8oHi&^W{UlL$!m2d^)TyQ!st$V~E_8X~hgOj0}VBDN2m1R0?}^d08YIK*Nda zm&SiBx?TMAbM{}+cguYqR~nDs7LXGzc6?gh@UCo3y3x|xt}-ybO!%YNl24+(mAKf* zKtSXD`;tQpI)feN;;Q`f2DJ>u?Vl{h!-q|c3@+n~!b-K1uH*AkHwCFBnqEy@H452} zP$refdtEduvSb^|`IWPGpx_13}{zMCMdJKuc};r-9%1f z-91SI^wcAWXdpIwjkPl-hpl9y<-)c^Ls8XrLBb|OiApudN5P{AvU=QHlK8DUT@abX zn7#Q2bk+3rtxl(oO==s?g>P4`Byr51{o~$7Nm!Cs68_Swgm9^yL$C+sruc1cl@RQo z=6IH%cMPT)UWNsG8LojE&-gvV4U^<7=RrE#hUHk#9%zt2apBv=UvF~x@Ry=%_b0QO z;VxO?lv=LJ4Nj)E&A#PZc6>LtKJ~uFu-9h*6VB;-L`A$L5^kDvXnl}9Aeh(`-WWY7 z8?*=tyWPZ&zBjj)<)p~wwohStIwks|?ez^2`!!t6k_fTRm}#e{IqGQ-p`T87VCsn_ zV<`l>Nv;^$qy`P$Z%&fX5BlNoPWKrYjeNpDo#n!p+vfU4KNzJAvVnhgFA_`x3S;>0 zINbyM;CA4l{&l?hUDG&8@AW77M@=IS(9~}>4L{59BXmQPy_IDuR%UwxIHlSK^ShsY z6cc@*ja0*kJ&+(DZ@+rhWLu%!9L?+YT4d}_@ZcG^(TTUD8KkOF^SxK<6+u%h;;r|I zIQW`2Ji)U=;7hME*a}ZWC=YA_0a3=fyootR3cY2gCQ%9n z8E6VB&uJrn!dmOwoe>2ZhGLv2>M>r(e?+}Kj%j&H3;C$9)ta7lz2LY1?oZW~{HSn& miU>-`)W(Yx9?5~ayHP>)L0$0c_f!S6*OgPxt^$4?8TvJ(C!HUD0Kh;FoWLQ|7s2!0KmWT1UmqHLIZ#gZ@m8n02ba9 z`^`GV0Ko7~iQkMw901DSl;+Jw-Z&f<02tp`MH&EjkN|+=jibH+z&IQLh`zCwCIE=M zsoa~TzVX6)0MK}2MQ#V3%Xt zyRk_QTk(7Y!C(llKoM`}GdjM&IStupfd4&3hJM&a*ck{>P~xI|&->RLYU5+FEmQQB zysVp5o7|2o7+1D$b-axh$Bp2kP<+K1F-5kIv4=NbdQLIfaS*Z~!J@pAb3>1E{* z4Yr*xksWcB&)E7j@r+&Tay8hNNWZ!TLr!0F$ z70j}tc&-Joi4Dxg!yx6;fOd*AvP+3%Q4_rAZW7^lL$bQ58!WeL848DHsuJ;XuH zgY7c#TcdfIoxGWT{2|93?q>A85aO0LRo8XO6r4+w0&HTD1&2k>T%U zH@C{VOa0mwnaw%A_Vuhba5#3{IVGm8bMSiTO!J1l@4F}2N|cw-c-U^tU2`_+80{%t zo0IOZWxj2ki&-2k%up>F+X2Cq=%J}{##-N>S366Nwbz7Iu|M`kpqZ>1DtKk}g|A$F{8W{)tIy35tGC%?q`@=p8uHO}tn~6RpRh9&LYB;`I5q#B zxuauA=JC^QW46Z~S7Vhc*RDtMqvq|uUMcDWr_2!p7SZ*G$bv+l&-X=tNm(Idu1lC@ zMGwLQkD%vBgL!BJt8IAR@5vy*K1Hf zY~_XH>HK$*oTGxx;%n+#=^9Dfc#nU4><;U4WeQ@jWXfWLVw=Z#c!cIHp(u9HA+{yw zKxi3TpjV1dOo+Gc&gS-P^9jc{9M;!D$=kLop5<%@CUNbkq-M=oZdn0$tp;4be8d;! zET@m1Gk@Umw_UamJt7%@x@3;#4?FikPk%}Fze+{-_j#K$WTp0K3J7*yY4-8(;!KRY z#r0cXB16VP=wka90>7kbtaaD8JBi*KJGRv&ut7bcCEM5p6p*96Wh4ka4x4hT8s3GM ziS$1Nd#4mj$5eK$P&JQapKABboqgv~iv5};nacN+e(|B&^9NtTgl`#~Cj$PuGc=a( z4(sy2;#?Z7kIo}?!pcdY4c3MbGJFuJKC+p3CMNAe3y3&6NKcwycRa?x~oI8rLx2?)ec5JQfO#49OBDWs- z^fQelmeJ89&kc#q(NV@SwTp)i)1JX`MBKy@{2C*tOzjypDWC>FHWYpN+*m@=w$9|N zC|Hz7K%F)}zM{`(Yk^@&Au(ObcmMA=R-wby3v7@GQCfO2hu%-O;y*^=T~k8O zzYVu6Rp^p=3M3_-_NAWYrAPBiyRp8Wixk|6TAfA7DRYXSXs#3MS1Pg;m+W!vd}>%{5sG;x z&KR~=i#^vl66fN(mv30OEgzc3SG23*;yKRFUEpe4?^KX;nid#%E_|@f$RvFkbKEL4 zICA%0+9$}g_xXDtp(cj_fgDjym){h4h)>&5T5u-cP$cZqq#<=)&eA#coRgnhNA^WI z!9!OM=RRNeI%9l&&4HB{H!n|E+viXgwzK;Fmk5+rulR9n;GxK~=C#SoxL1!L9UuQB zbU&0)-p#%lR;}smcuJFbjBZPKDPwH&s`8p$d~xYe2AWBUlEu^!!$ssgPK#|M? z>)+sG*P4^UzLng~>+qT#LvvTbn~o>Fp4FBWLs`PM!`O+GTqqz-mAx`$ekIG{#R(}D@>3@^ zTp^=aSQP=(LnG`WM{Qrwrf=#{%zh+qPKsqTqW6J1;V)&N3NnZBRly18Kj6>a4Vqjw z`x<)X-wSYRrV|50$5zSe-gSZTTi60XOP?ZKuVR zj+u|A^W^A^`3FLFh#^K3u*nh3ikM3}W2!O1q{C~m)jm>fC~{5kUR^DGS^3?32HO@d zc3Dy4J5b{+M`BQ_?Y+2>YLTS^RZMh0ZC}0lBigWrw>^75L0(L-cGi#LF>lhWuhhX` zHP(JJaa10ID^tx{5cV6gHdQCcN;Fy5lAwN52+@RQQ>tl0a-F2wd5QzY%gKj|yO^P0 z?t=96T8X1iM$OQu*@Kj~(W{5Cdd|9&_JXQ4@o?IXYpQd3CsQJbp^^IxzFchYd5fFO z=wuq9?zGvXcoDRQF&}X71PQtGQ_JB@fdEeh$g%C}(p*P7)lxgnQir*$h$w>IFwLWC+2qsx@eZknp6zA~IXmBIP}pC}Q~vbtiN`7JK9J5!-Awnv`rr3$~@ z0*Mihrf4Cc{l|uYym#()uP4+A_I0UQ^1x+aqT7F7bmmL{O+q}}FW-yh2}Y|5SE_oy zn!p{S%O>hWBjn@Kc$1UNVktq5VLQ_EDXP~&yfW<`Y=l@zftvd*;s!YeJ7l()6{A8Y zwX0shvgTm;9oM_dYjbwI$rdXi2F!03IoN0rr-%a)fz+P6Y&VZnj^|ga>!f>Wjh4#< z_ov6Y%U5I1JN01l@^n}N>L=xv=S6R4THnF&8@y1>)2?AME7SZr^ht@SlI#!dK|`uY zoAlmHI1@a1!rmit7t0mtGF-8V)%Lz5*-k4VM|q}cH)J!%)pSz*L}0&y+@!RdbPHxJ zq({~|8pfGA`%O2vh0&)^$0SOvq~(4SUk+t~HBGojcmH(rUVY3B`b!J@a4$b(L*%S; zSWV>gTSXWFR#~V}6*TK94&*9!XN_1Kj}r`Qk#adj?3y3<@1GxLj?WAltO@L$mj8{a zkmdwYfB+{TMS4u`kGtu^*p)ws?2o+B-W>R(#0P2+dqe}u;d~20CxPCA=2{=O%LtPMZsrT%WTI~S?8P(YW= zhN_*U620Na!Z{N7He67PY`l9wNR6xm+UJ}9tBrouX3H5b&2YV&&`EbEcST}9IK4M+qvj_Dk3fxF5-GxAeK4Nuv z)hHrJkPKv@A$8`iF~18zVYw;Hsm>ixda(w*S}858crwF_<(;I6&q zej9W@RRmtRyIyq)KULKX$DdV1jv>8&R6WJ;*8x?6noyM702}yEunRB_2wlejKhOa4 zgx*C2Ac*xeV2^-odOcyig}Wf2HH0%f|6@Ry1mhw1Hi`_a6Qc(-A?%V-4(R^#A_LQ$ zv?EnxZYY9WLHcM>rz-7We=iUd%pK6R3kJu<*uHB*+a+bN@u-=rZbGJRU}hMX?f2|8 z`UhbHNZvKS?6Mpd$Auks{89`JVG0*QV?jN;1RjAbxCOK`dN9~H!k3YuV^P8YmIpY~ z0iS0wJ?Qz10k6b{7#lABorq`fT|t1$rw=*O`Dy^T8!J=}3eo2Khmj7pI#GS@(#_l@pY<1i;^YX5XXsT0skm;VPPbF7 zC+4cxQOakzaq3t#dP zq<12(4Ng^Pr9eqVD|7W`XNl>7aAAPq#6nMW1&oWfq}O(g+zM)a&aqBm>bU-J`cCHP zU;X0JHBuH&tNEe1%vH)VwZQJL=D$?ENc3p1%r$A*hiM@__Q49s*;Oa3Ad8Q2pRwr* z{Ov`XA}Dvd>^K6SM3Faklcr#Fb0tb=abOW!{7vx7oJrKXA_{xd_i0-doT)NtVuM1( zbqdB^MRUpBCrw5 zHrkYGvw}=d=MRmF;OzMe<&^ZZ=WAOFiG3S=0;k%^eli(7mEM$|)&{5BS~f(A{4Pr2 zDlkWGZ@^s2V5^IDXUaMuCgLI;KEOp=37M?IM@0$1L?gAzIbx0Dq^w@}&C=qa8&5tR z%+|*Qy%B*L(km?P%9;~L+Q=4P;+3!__!GUbNdFm>cChvn{=lOAql*gy-d+nBKIsr+ zbfk~Hm#Z)(aJCRK?e67zQVQ2^XTgININZ8H4A35U}(Mp3d+Qn}*kW(U$Opt*Ln9TF4k{FQ|=7 zpEL%49#42BYZQQp9v9SxalTznhh&cW$4g06ER!2U4D1yLtDn)48Pa{jrMsw{#h9PE zfh|ip%9$AsX%Nj%B-gZ!nrF#Bp}Zxc=%)aGEp`7ULM@XuRts9T=FPhwRv~ee-*}G$ z%1sCNlT8GYh_D#U%iN`y_~lN|Cet{+&A9Q{M}#TBa^>(Ub9&kkC1g`HYx*uj!(8nX z!dR7-O~6R^)MYcA@6tEk%@?(*jmC%gBDr{%Lj=keJAH{Gl~@e}Rb~ zjf{Lf;+o*^;B_(Qu-2n!N$XE(%XmBV`#rI8&)Ep=AJoof$2`=MVWwXEKx{R)vL{U% zaH$6@iM2$AKeDSsC}y~+oXhS zwh&Ukbd0={udOSBcVzR<++U6uzvbURWkUC#U;amX-ZCTeo4%4fCPS;hvL3pDd->Rx z7?(%vj7`}g0)O`|EOQS`gW}mpxLdUsS1Q4y!JHejiFYn4EUwJlLjMGJdz7+*eW$V* zA9d#s?{6YX%r8-ZlnMossWU+~1twQIE#9*2VDs|PlVc}`O3B)~(d;`1D2 zm>y!MET!&{b(?)6URAra<b7s<-1g6 zaxC(a%OQFTyqmm2<+$N$EkGgs{ z!ls#i^HQ-I``%yOI=7r$ZsD@6bDo>yywf|jF^|atg)b6}cNKr3Mg(Tl1wS!?yL2e0 ztp5yDIlQ9vIRT#!`xnB;ig zkf~Yl8!_H#uFn74$~531S@D5()aHYOV>&F8*%|@qZLy|^<@O1nVP@~25hIi{K>V|& z8E6I*s>=!!lXe!+sO^};?&MtMX%{jNeSWTK{c3<5-*c}*{ptr}(ww0onmkg0ZL%ni zOrgystS6ehSfv_Ycmpx9g$nf&>rPZl>4mmugf8}esz@nm#Dx*)X*t3|756XZtnJ#e zZIlIdM35J$kO=ncqZJ8{98TpuSk?is z-uUfN&ZW16bwBeoIJ>fQilgGNI6NWIn};9#g~iZZ{JHN!)n}HCZC3kPFL3rQRWg+q zloLoURaVdURKS+-pWxk54eJ%Sg%l9n;Wj>Gmj7l4RiefJfTWY|g9zbyNIcL-J93x2YS*fz-CqxamQJah-&o}}0DRuW}(FQ_q55JE#B zG{T*-`LIVTqPq}m_*t-*IJ`6N3X~=G0Ca{M*?nb6G8Y$B%dkxF%)meB;SJo?Pu&mDCw~QQngT!@fDUr|Yh~K;4jK!B_eeya zVa_zFi2>p02e=I>=N8_L{E}0UP$^W#_o-*jzxdRJFC>mTQn>x+TyhnxH^zPS&*We8 zDL*O=fTPd}(riE|9~yDKU(*5jVIFo5Z~7VDS8KYzH-xY~d{2Q1kDA&B{LnfNKu>HJ z=6D_s9q-TR2XX!V3ZODZPt$JiHZ)xL79Tmwal3@Kea7Z%d;mwPC>mn}3Ep>i`+S*J z{Yf^qj1?xQzY7T_3_y22nF{VNuou=;j8<=#5Ao>z8DxP3fW(skevy|zm*4c^&mCdo z*WRTq0~fyfJA2KS&)V?Y5xqzmW$IJkKWX4WfjLkHDhr$gd>1BQet!^5JRb2;6Mgh@ zDuTC7xgB@o3rVJ{PM`rMhzZUedxOn?9;k%pK}e=_0k}cBNBM~+M+r<_o+O$7tbk8} zYF`uM6iin^4knCa-BNSY_)l>DZzln_p-z(NZw0>qvpjJu#FtP9y8#83y`9r6(B=qm zNSn0n5t?w1P|k3@oxkpjmJ4_J>f+f?))mAlbbo-A1H2J8{s2yQvsi}28}}$z64yvw z`9Rz}G>=%(iLlrCx~@UkKvDLQ{`%_rny*Wdl!PmA#poVTBqITQhoxu;Cv~0&Bp<#- z6=R=q_{wW~eRVn?yRS$!*&&=LCg)j2iZS`mxAqehbtjyA7ZT>MRKnqvN z3CgOY^*^3AT%nwP@2lN4G{tZ1zsJyBRGjMIe?NsI zdl|&rk;DCEIf_%oY=91|0i%cbJzKcC@-r8FI~}|+R=ik0iLXB{nak6VycIvCR@z!5!Xo``=tKT>KW%?;!imP;U?A z>300J%`fU9oF4h?tMoN2@>y9aD=1#Gd}2a(`lI8ndsLxu6mpryG#=+9qtnnfY)$Uh zp{f}hgebQl%ua1A249zKvf-6-!xZ(eStSd6O!D(5%`s2P=&e&s#{&WgUX6N7M@TpN zt#uk$|4>^wu)Tz#F&0EoL-g=9k2WnSID8BG=_e9!{3cMf8s7AtK&l-*3X`=WbmeN2 z8oH7N8k@@XwoEf{pOES0=EL#MEJeX8lda9~AfGv=g= z{EegCzWq$c1%c0LdP}TukEMEPkTE zzuH51EQXVuaHhTF1tsZewVDGrQLM`OghnhQ`#*HL%GDz_NS|Hxq;Hm^uXngZ7K-A_ zPy1a^U8D4trs`1}`kBVQRUf-re!c;v_lyt>>c}2gr1xmSE!(Ro)f}Q{QU}*GCp3E?%8u9IuZZ;NE{ggk z8|_0!X^xNWH84QFXMzcy2(g%RHtS(ohl%4#L+Cfiu>JU`9d7n+Yz`Xk!!CXqV>a7ZCH zafV6~2M!(zs?o-#>*z;AA>I&T58bw z^D|9QTb}N~o_qeEDrbeoXFbN3Osk9Om5TPepFx5K@?|dww)zw|vsQmW@`oV3$13=K*Jfsm{9twlL;CH&FoXKF&^}k0hbYYUBN+kS(M3g+eXBYs* z*zo-E-WIV_gXa9nw3F4wvR4cG`N|yMUmMHC3d5!LthH{r^LOX3bWDmr|6sRVy|$#G z)eM`hst0iWbgJgGjtXD-EuwK8qqZwU>LxC0HYAzJQxvSOqY6^>@JA) z9sQEPF1RA5VGLW3lu8P6ZnpWD3e#{MqaAv9y-%KOesTDc>psrlaJq$|%FHZ@l7k$& zE2zOJrKya-qERr97fpfe)5DWD$tkD)j=$1l1SEpiJ2*&WSP_pW5dZcAjWEewPOMKY zElJT39elI+7?H>a*`!gRS42)$4hSgvzO*f*t;ZL1`{AbA{8NOM{~j!swVE0ok}TNh=ZAzz!3}-vVi8(%UhQjK8T2pX^2gJcFh+Z-1cD;U!>w|7p^$&X!6y z`}qSmvZT&uyi?dr8L5QP)%!Yc@#~&aH~-a!6^X7c^bYr;0b+lj1CIF!B&Wb&v46v= zY@&yVj6->f644q6sSeX2S1vVnogoj7xnDWIQZugkn;4WS@lyx9FEgA9-ZW|o7B+Zw z>wi|gMrPiOc&KcAV)Phky%v;{TP7LqZRt9%@2xNJh*G%TeV9+#wl!Evawq40lJVG8 z+$a!^^}8^PBYzGObWCCB^+G6X@6Hmsy(c17?CF2yZ#zwvzW`+kzT{a=LB Blh*(M diff --git a/Simple Donator Benefits/addons/sourcemod/plugins/simple-spectate.smx b/Simple Donator Benefits/addons/sourcemod/plugins/simple-spectate.smx deleted file mode 100644 index c6885b041145a73f664650e729a5dcf8b3b0813f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19129 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%0ACwUfid=y*oPG;MRqmWr)g0 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�XP zM5L)&uZne^XHs;_L+03=Xy3CiU1O76^S{TWu{zY}Jlq((BV?9EL=m4MC%~!W0MzeW zOjQv*a;A7AS@l%h9EbjzQ3d}e&j~R0VCoAN)q_>=)m=>e=ZX9w8jM3&o1RO^+0jJ) z

_|h)w;)ME+|h#gx@oo-|ZEuRI5d) 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 z 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 z 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 KvHt-#rc|>H2mv<$ diff --git a/Simple Donator Benefits/addons/sourcemod/scripting/include/simple-plugins.inc b/Simple Donator Benefits/addons/sourcemod/scripting/include/simple-plugins.inc deleted file mode 100644 index 8f21956..0000000 --- a/Simple Donator Benefits/addons/sourcemod/scripting/include/simple-plugins.inc +++ /dev/null @@ -1,337 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Plugins -Description: - Included file for core plugin in the Simple Plugins project -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -*************************************************************************/ - -#if defined _simpleplugin_included - #endinput -#endif - -#define _simpleplugin_included - -#define CORE_INC_VERSION "1.1.$Rev$" - -#pragma semicolon 1 -#include -#undef REQUIRE_PLUGIN -#include -#define REQUIRE_PLUGIN -#undef REQUIRE_EXTENSIONS -#undef AUTOLOAD_EXTENSIONS -#tryinclude -#tryinclude -#tryinclude -#define AUTOLOAD_EXTENSIONS -#define REQUIRE_EXTENSIONS - -enum e_SupportedMods -{ - GameType_Unknown, - GameType_AOC, - GameType_CSS, - GameType_DOD, - GameType_FF, - GameType_HIDDEN, - GameType_HL2DM, - GameType_INS, - GameType_L4D, - GameType_NEO, - GameType_SGTLS, - GameType_TF, - GameType_ZPS -}; - -enum e_Teams -{ - Unknown, - Spectator, - Team1, - Team2 -}; - -new g_aCurrentTeams[e_Teams]; -new e_SupportedMods:g_CurrentMod; -new String:g_sGameName[e_SupportedMods][32] = { "Unknown", - "Age of Chivalry", - "Counter Strike", - "Day Of Defeat", - "Fortress Forever", - "Hidden: Source", - "Half Life 2: Deathmatch", - "Insurgency", - "Left 4 Dead", - "Neotokyo", - "Stargate TLS", - "Team Fortress 2", - "Zombie Panic: Source" - }; - -public SharedPlugin:_pl_simpleplugin = -{ - name = "simple-plugins", - file = "simple-plugins.smx", -#if defined REQUIRE_PLUGIN - required = 1 -#else - required = 0 -#endif -}; - -#if !defined REQUIRE_PLUGIN -public _pl_simpleplugin_SetNTVOptional() -{ - MarkNativeAsOptional("SM_MovePlayer"); - MarkNativeAsOptional("SM_SetForcedTeam"); - MarkNativeAsOptional("SM_GetForcedTeam"); - MarkNativeAsOptional("SM_ClearForcedTeam"); - MarkNativeAsOptional("SM_GetForcedPlayer"); - MarkNativeAsOptional("SM_AssignBuddy"); - MarkNativeAsOptional("SM_SearchBuddy"); - MarkNativeAsOptional("SM_LockBuddy"); - MarkNativeAsOptional("SM_IsBuddyLocked"); - MarkNativeAsOptional("SM_ClearBuddy"); - MarkNativeAsOptional("SM_IsValidAdmin"); - MarkNativeAsOptional("SM_IsValidTeam"); -} -#endif - -/********************************************************************** - * When a player has to moved - * - * @param plugin Plugin that initiated the move - * @param client The client index of the player that was moved - * @param team The team index the player was moved to - * @noreturn - **********************************************************************/ -forward SM_OnPlayerMoved(Handle:plugin, client, team); - -/********************************************************************** - * Move a player to the supplied team - * - * @param client The client index of the player to be moved - * @param team The team to move the player to - * @noreturn - * @error Invalid client or team index - **********************************************************************/ -native SM_MovePlayer(client, team); - -/********************************************************************** - * Move a player to the supplied team - * - * @param client The client index of the player to set - * @param team The team to move the to set - * @param override Whether or not to override another plugin - * @return True if successful, false if not - * @error Invalid client or team index - **********************************************************************/ -native SM_SetForcedTeam(client, team, bool:override = false); - -/********************************************************************** - * Gets the client's forced team index - * - * @param client The client index of the player to check - * @param plugin Optional: The plugin handle of the plugin - that set the team - * @return The team index of the forced team - Zero if no forced team - * @error Invalid client index - **********************************************************************/ -native SM_GetForcedTeam(client, &Handle:plugin = INVALID_HANDLE); - -/********************************************************************** - * Clears a client's forced team - * - * @param client The client index of the player to check - * @return True if successful, false if not - * @error Invalid client index - **********************************************************************/ -native SM_ClearForcedTeam(client); - -/********************************************************************** - * Gets a forced player on the wrong that is currently on the wrong team - * This will only return a player if the calling plugin assigned the team - * - * @param team The team index the player should be on - * @return The client index of the player - Zero if no player found - * @error Invalid client index - **********************************************************************/ -native SM_GetForcedPlayer(team); - -/********************************************************************** - * Assign a players buddy - * - * @param client The client index of the player to assign - * @param player The player index of the player to assign - * @param override Whether or not to override a player lock - * @return True if successful, false if not - * @error Invalid client or player index - **********************************************************************/ -native bool:SM_AssignBuddy(client, player, bool:override = false); - -/********************************************************************** - * Rturns the client's buddy - * - * @param client The client index of the player to assign - * @return The client index of the player's buddy - Zero if no buddy - * @error Invalid client index - **********************************************************************/ -native SM_GetClientBuddy(client); - -/********************************************************************** - * Set the buddy lock setting for a client - * - * @param client The client index of the player to assign - * @param setting Setting to set, True or False - * @return True if successful, false if not - * @error Invalid client index - **********************************************************************/ -native bool:SM_LockBuddy(client, bool:setting); - -/********************************************************************** - * Returns the buddy lock setting for a client - * - * @param client The client index of the player to assign - * @return True if locked, false if not - * @error Invalid client index - **********************************************************************/ -native bool:SM_IsBuddyLocked(client); - -/********************************************************************** - * Clear a players buddy - * - * @param client The client index of the player to clear - * @param override Whether or not to override a player lock - * @return True if successful, false if not - * @error Invalid client index - **********************************************************************/ -native bool:SM_ClearBuddy(client, bool:override = false); - -/********************************************************************** - * Determine if the player has the supplied flags - * ADMFLAG_ROOT will always return true - * - * @param client The client index of the player to assign - * @param flags The char flag(s) to check against - * @return True if valid, false if not - **********************************************************************/ -native bool:SM_IsValidAdmin(client, const String:flags[]); - - -/********************************************************************** - * Determine if the team is a valid team - * - * @param team The team index to determine if valid for - currently installed/supported mod - * @return True if valid, false if not - **********************************************************************/ -native bool:SM_IsValidTeam(team); - - -public e_SupportedMods:GetCurrentMod() -{ - new String:sGameType[64]; - GetGameFolderName(sGameType, sizeof(sGameType)); - - if (StrEqual(sGameType, "aoc", false)) - { - return GameType_AOC; - } - if (StrEqual(sGameType, "cstrike", false)) - { - return GameType_CSS; - } - if (StrEqual(sGameType, "dod", false)) - { - return GameType_DOD; - } - if (StrEqual(sGameType, "ff", false)) - { - return GameType_FF; - } - if (StrEqual(sGameType, "hidden", false)) - { - return GameType_HIDDEN; - } - if (StrEqual(sGameType, "hl2mp", false)) - { - return GameType_FF; - } - if (StrEqual(sGameType, "insurgency", false) || StrEqual(sGameType, "ins", false)) - { - return GameType_INS; - } - if (StrEqual(sGameType, "l4d", false)) - { - return GameType_L4D; - } - if (StrEqual(sGameType, "nts", false)) - { - return GameType_NEO; - } - if (StrEqual(sGameType, "sgtls", false)) - { - return GameType_SGTLS; - } - if (StrEqual(sGameType, "tf", false)) - { - return GameType_TF; - } - if (StrEqual(sGameType, "zps", false)) - { - return GameType_ZPS; - } - return GameType_Unknown; -} - -public LoadCurrentTeams() -{ - switch (g_CurrentMod) - { - case GameType_INS: - { - g_aCurrentTeams[Unknown] = 0; - g_aCurrentTeams[Spectator] = 3; - g_aCurrentTeams[Team1] = 1; - g_aCurrentTeams[Team2] = 2; - } - case default: - { - g_aCurrentTeams[Unknown] = 0; - g_aCurrentTeams[Spectator] = 1; - g_aCurrentTeams[Team1] = 2; - g_aCurrentTeams[Team2] = 3; - } - } -} diff --git a/Simple Donator Benefits/addons/sourcemod/scripting/simple-alltalkmanager.sp b/Simple Donator Benefits/addons/sourcemod/scripting/simple-alltalkmanager.sp deleted file mode 100644 index c848332..0000000 --- a/Simple Donator Benefits/addons/sourcemod/scripting/simple-alltalkmanager.sp +++ /dev/null @@ -1,515 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple AllTalk Manager -Description: - Allows you to set alltalk at different times -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#pragma semicolon 1 -#include -#include - -#define PLUGIN_VERSION "1.4.$Rev$" - -new Handle:satm_enabled = INVALID_HANDLE; -new Handle:satm_threshold_enabled = INVALID_HANDLE; -new Handle:satm_player_threshold = INVALID_HANDLE; -new Handle:satm_threshold_setting = INVALID_HANDLE; -new Handle:satm_logactivity = INVALID_HANDLE; -new Handle:satm_alltalk = INVALID_HANDLE; - -new Handle:g_aEventNames = INVALID_HANDLE; -new Handle:g_aEventReasons = INVALID_HANDLE; -new Handle:g_aEventSettings = INVALID_HANDLE; - -new bool:g_bLastThreshold = false; -new bool:g_bEnabled = true; -new bool:g_bThresholdEnabled = true; -new bool:g_bIsSetupMap = false; -new bool:g_bIsGameTF2 = false; -new bool:g_bLogActivity = false; - -new g_iLastEventIndex; - -public Plugin:myinfo = -{ - name = "Simple AllTalk Manager", - author = "Simple Plugins", - description = "Allows you to set alltalk at different times", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -} - -/** -Sourcemod callbacks -*/ -public OnPluginStart() -{ - - /** - Need to create all of our console variables. - */ - CreateConVar("satm_version", PLUGIN_VERSION, "Simple AllTalk Manager", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - satm_enabled = CreateConVar("satm_enabled", "1", "Enables/Disables Simple AllTalk Manager", _, true, 0.0, true, 1.0); - satm_threshold_enabled = CreateConVar("satm_threshold_enabled", "1", "Enables/Disables player threshold", _, true, 0.0, true, 1.0); - satm_player_threshold = CreateConVar("satm_player_threshold", "8", "Amount of players for the threshold"); - satm_threshold_setting = CreateConVar("satm_threshold_setting", "1", "Enables/Disables all talk up to player threshold, with the opposite set after the threshold", _, true, 0.0, true, 1.0); - satm_logactivity = CreateConVar("satm_logactivity", "0", "Enables/Disables log activity", _, true, 0.0, true, 1.0); - satm_alltalk = FindConVar("sv_alltalk"); - - /** - Hook console variables - */ - HookConVarChange(satm_enabled, ConVarSettingsChanged); - HookConVarChange(satm_threshold_enabled, ConVarSettingsChanged); - HookConVarChange(satm_player_threshold, ConVarSettingsChanged); - HookConVarChange(satm_logactivity, ConVarSettingsChanged); - - /** - Remove the notify flag from all talk cvar since we do it - */ - SetConVarFlags(satm_alltalk, GetConVarFlags(satm_alltalk)~FCVAR_NOTIFY); - - /** - Get the game type. We only care if it's TF2 - */ - new String:sGameType[64]; - GetGameFolderName(sGameType, sizeof(sGameType)); - if (StrEqual(sGameType, "tf", false)) - { - g_bIsGameTF2 = true; - } - - /** - Create the arrays - */ - g_aEventNames = CreateArray(255, 1); - g_aEventReasons = CreateArray(255, 1); - g_aEventSettings = CreateArray(1, 1); - - /** - Need to register the commands we are going to create and use. - */ - RegAdminCmd("sm_reloadatconfig", Command_Reload, ADMFLAG_GENERIC, "Reloads settings from config file"); - - /** - Create the config file - */ - AutoExecConfig(true); - - /** - Load the events from the config - */ - LoadEventsFromConfig(); -} - -public OnConfigsExecuted() -{ - - /** - Load up the settings - */ - g_bEnabled = GetConVarBool(satm_enabled); - g_bLogActivity = GetConVarBool(satm_logactivity); - g_bThresholdEnabled = GetConVarBool(satm_threshold_enabled); -} - -public OnMapStart() -{ - - /** - Reset the globals - */ - g_iLastEventIndex = 0; - g_bLastThreshold = false; - - /** - Check the map type if we are in TF2 - */ - if (g_bIsGameTF2) - { - g_bIsSetupMap = IsSetupPeriodMap(); - } - - /** - Set AllTalk - */ - if (g_bEnabled) - { - SetConVarBool(satm_alltalk, true); - } -} - -public OnClientDisconnect_Post(client) -{ - if (g_bEnabled) - { - SetAllTalk(-1); - } -} - -public OnClientPostAdminCheck(client) -{ - if (g_bEnabled) - { - SetAllTalk(-1); - } - CreateTimer(2.0, Timer_ShowAllTalkStatus, client, TIMER_FLAG_NO_MAPCHANGE); -} - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (convar == satm_enabled) - { - if (StringToInt(newValue)) - { - g_bEnabled = true; - } - else - { - g_bEnabled = false; - } - } - else if (convar == satm_threshold_enabled) - { - if (StringToInt(newValue)) - { - g_bThresholdEnabled = true; - } - else - { - g_bThresholdEnabled = false; - } - } - else if (convar == satm_logactivity) - { - if (StringToInt(newValue)) - { - g_bLogActivity = true; - } - else - { - g_bLogActivity = false; - } - } - if (g_bEnabled) - { - SetAllTalk(-1); - } -} - -/** -Commands -*/ -public Action:Command_Reload(client, args) -{ - - /** - Clear the array - */ - ClearArray(g_aEventNames); - ClearArray(g_aEventReasons); - ClearArray(g_aEventSettings); - - /** - Load the events from the config - */ - LoadEventsFromConfig(); - - return Plugin_Handled; -} - -/** -Game Event Hooks -*/ -public Hook_All_Events(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (!g_bIsSetupMap) - { - if (StrEqual(name, "teamplay_round_start")) - { - if (FindStringInArray(g_aEventNames, "teamplay_setup_finished") != -1) - { - g_iLastEventIndex = FindStringInArray(g_aEventNames, "teamplay_setup_finished"); - if (g_bEnabled) - { - SetAllTalk(g_iLastEventIndex); - return; - } - } - } - } - g_iLastEventIndex = FindStringInArray(g_aEventNames, name); - if (g_bEnabled) - { - SetAllTalk(g_iLastEventIndex); - } -} - -/** -Timers -*/ -public Action:Timer_ShowAllTalkStatus(Handle:timer, any:client) -{ - if (IsClientConnected(client) && IsClientInGame(client)) - { - new bool:bSetting = GetConVarBool(satm_alltalk); - if (bSetting) - { - PrintToChat(client, "\x01\x04[SM] AllTalk is \x01[on]"); - } - else - { - PrintToChat(client, "\x01\x04[SM] AllTalk is \x01[off]"); - } - } -} - -/** -Stock Functions -*/ -stock LoadEventsFromConfig() -{ - - /** - Make sure the config file is here and load it up - */ - new String:sConfigFile[256]; - BuildPath(Path_SM, sConfigFile, sizeof(sConfigFile), "configs/simple-alltalkmanager_events.cfg"); - if (!FileExists(sConfigFile)) - { - - /** - Config file doesn't exists, stop the plugin - */ - LogError("[SATM] Simple AllTalk Manager is not running! Could not find file %s", sConfigFile); - SetFailState("Could not find file %s", sConfigFile); - } - - /** - Create the arrays and variables - */ - new String:sGameEventName[256]; - new String:sReason[256]; - new iSetting; - - /** - Load config file as a KeyValues file - */ - new Handle:kvGameEvents = CreateKeyValues("game_events"); - FileToKeyValues(kvGameEvents, sConfigFile); - - if (!KvGotoFirstSubKey(kvGameEvents)) - { - return; - } - - /** - Hook the game events and load the settings - */ - do - { - - /** - Get the section name; this should be the event name - */ - KvGetSectionName(kvGameEvents, sGameEventName, sizeof(sGameEventName)); - if (!HookEventEx(sGameEventName, Hook_All_Events, EventHookMode_PostNoCopy)) - { - - /** - Could not hook this event, stop the plugin - */ - SetFailState("Could not hook event %s", sGameEventName); - } - else - { - if (g_bLogActivity) - { - LogMessage("[SATM] Hooked event: %s", sGameEventName); - } - } - - /** - Get the reason string and setting - */ - KvGetString(kvGameEvents, "reason", sReason, sizeof(sReason)); - iSetting = KvGetNum(kvGameEvents, "setting"); - if (g_bLogActivity) - { - LogMessage("[SATM] Event reason string: %s", sReason); - LogMessage("[SATM] Event setting: %i", iSetting); - } - - /** - Push the values to the arrays - */ - PushArrayString(g_aEventNames, sGameEventName); - PushArrayString(g_aEventReasons, sReason); - PushArrayCell(g_aEventSettings, iSetting); - } while (KvGotoNextKey(kvGameEvents)); - - /** - Close our handle - */ - CloseHandle(kvGameEvents); -} - -stock SetAllTalk(index) -{ - new iPlayerThreshold = GetConVarInt(satm_player_threshold); - new bool:bThresholdMet = ((GetClientCount() >= iPlayerThreshold) ? true : false); - new bool:bSetting; - - if (g_bThresholdEnabled) - { - if (bThresholdMet) - { - if (index == -1) - { - if (bThresholdMet != g_bLastThreshold) - { - g_bLastThreshold = true; - bSetting = !GetConVarBool(satm_threshold_setting); - new bool:bLastSetting = GetArrayCell(g_aEventSettings, g_iLastEventIndex); - if (bLastSetting && !bSetting) - { - bSetting = GetArrayCell(g_aEventSettings, g_iLastEventIndex); - } - } - else - { - bSetting = GetArrayCell(g_aEventSettings, g_iLastEventIndex); - } - } - else - { - bSetting = GetArrayCell(g_aEventSettings, index); - } - } - else - { - g_bLastThreshold = false; - bSetting = GetConVarBool(satm_threshold_setting); - } - } - else - { - if (index != -1) - { - bSetting = GetArrayCell(g_aEventSettings, index); - } - } - - if (GetConVarBool(satm_alltalk) != bSetting) - { - - SetConVarBool(satm_alltalk, bSetting); - - new String:sReason[256]; - if (index == -1) - { - Format(sReason, sizeof(sReason), "Player Threshold"); - } - else - { - if (!g_bIsSetupMap) - { - new String:sCurrentEvent[256]; - GetArrayString(g_aEventNames, index, sCurrentEvent, sizeof(sCurrentEvent)); - if (StrEqual(sCurrentEvent, "teamplay_setup_finished")) - { - new iRoundStartIndex = FindStringInArray(g_aEventNames, "teamplay_round_start"); - if (iRoundStartIndex != -1) - { - GetArrayString(g_aEventReasons, iRoundStartIndex, sReason, sizeof(sReason)); - } - else - { - GetArrayString(g_aEventReasons, index, sReason, sizeof(sReason)); - } - } - else - { - GetArrayString(g_aEventReasons, index, sReason, sizeof(sReason)); - } - } - else - { - GetArrayString(g_aEventReasons, index, sReason, sizeof(sReason)); - } - } - - if (bSetting) - { - PrintToChatAll("\x01\x04[SM] AllTalk turned \x01[on] \x04due to:\x01 %s", sReason); - } - else - { - PrintToChatAll("\x01\x04[SM] AllTalk turned \x01[off] \x04due to:\x01 %s", sReason); - } - } -} - -stock bool:IsSetupPeriodMap() -{ - new iEnt = -1; - new String:sMapName[32]; - - GetCurrentMap(sMapName, sizeof(sMapName)); - - if (strncmp(sMapName, "cp_", 3, false) == 0) - { - new iTeam; - while ((iEnt = FindEntityByClassname(iEnt, "team_control_point")) != -1) - { - iTeam = GetEntProp(iEnt, Prop_Send, "m_iTeamNum"); - - /** - If there is a blu CP or a neutral CP, then it's not an attack/defend map - */ - if (iTeam != 2) - { - //this is a push map - return false; - } - } - //this is a attack/defend map - return true; - } - else if (strncmp(sMapName, "ctf_", 3, false) == 0) - { - //this is a ctf map - return false; - } - return false; -} diff --git a/Simple Donator Benefits/addons/sourcemod/scripting/simple-autoscrambler.sp b/Simple Donator Benefits/addons/sourcemod/scripting/simple-autoscrambler.sp deleted file mode 100644 index 6c6799e..0000000 --- a/Simple Donator Benefits/addons/sourcemod/scripting/simple-autoscrambler.sp +++ /dev/null @@ -1,459 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple AutoScrambler -Description: - Automatically scrambles the teams based upon a number of events. -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include - -#define PLUGIN_VERSION "1.1.$Rev$" - -/** -Different scramble modes: - -1 = Full Scramble, dont restart round. -2 = Admins Immune, dont restart round. -3 = Full Scramble, restart round and reset scores. -4 = Admins Immune, restart round and reset scores. - -*/ - -/** -Different top player modes: - -1 = Divide Top 4 players on the two teams. -2 = Protect the Top 2 players on each team. - -*/ - -enum PlayerData -{ - Handle:hForcedTimer, - bool:bProtected; -}; - -/** -Cvars used for admins -*/ -new Handle: sas_admin_immunity_enabled = INVALID_HANDLE, - Handle: sas_admin_flag_scramblenow = INVALID_HANDLE, - Handle: sas_admin_flag_immunity = INVALID_HANDLE; - -/** -Cvars used for autoscramble -*/ -new Handle: sas_autoscramble_enabled = INVALID_HANDLE, - Handle: sas_autoscramble_minplayers = INVALID_HANDLE, - Handle: sas_autoscramble_mode = INVALID_HANDLE, - Handle: sas_autoscramble_winstreak = INVALID_HANDLE, - Handle: sas_autoscramble_steamroll = INVALID_HANDLE, - Handle: sas_autoscramble_frags = INVALID_HANDLE; - -/** -Cvars used for voting -*/ -new Handle: sas_vote_enabled = INVALID_HANDLE, - Handle: sas_vote_upcount = INVALID_HANDLE, - Handle: sas_vote_winpercent = INVALID_HANDLE, - Handle: sas_vote_mode = INVALID_HANDLE, - Handle: sas_vote_minplayers = INVALID_HANDLE; - -/** -Additional cvars -*/ -new Handle: sas_enabled = INVALID_HANDLE, - Handle: sas_timer_scrambledelay = INVALID_HANDLE, - Handle: TFGameModeArena = INVALID_HANDLE; - -/** -Timers -*/ -new Handle: g_hScrambleTimer = INVALID_HANDLE; - -/** - Player arrays - */ -new g_aPlayers[MAXPLAYERS + 1][PlayerData]; - -/** - Cvar variables - */ -new bool: g_bIsEnabled, - bool: g_bIsAutoScrambleEnabled, - bool: g_bIsVoteEnabled, - bool: g_bIsAdminImmunityEnabled; -new Float: g_fTimer_ScrambleDelay, - Float: g_fVote_UpCount, - Float: g_fVote_WinPercent; -new g_iAutoScramble_Minplayers, - g_iAutoScramble_Mode, - g_iAutoScramble_WinStreak, - g_iAutoScramble_SteamRoll, - g_iAutoScramble_Frags, - g_iVote_Mode, - g_iVote_MinPlayers; -new String: g_sScrambleNowFlag[5], - String: g_sAdminImmunityFlag[5]; - -/** -Other globals -*/ -new g_iMaxEntities, - g_iOwnerOffset; - -public Plugin:myinfo = -{ - name = "Simple AutoScrambler", - author = "Simple Plugins", - description = "Automatically scrambles the teams based upon a number of events.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -public OnPluginStart() -{ - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[SAS] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - switch (g_CurrentMod) - { - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_Post); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_Post); - } - } - - /** - Create console variables - */ - CreateConVar("sas_version", PLUGIN_VERSION, "Simple AutoScrambler Version",FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - sas_enabled = CreateConVar("sas_enabled", "1", "Enable/Disable Simple AutoScrambler"); - sas_timer_scrambledelay = CreateConVar("sas_timer_scrambledelay", "5.0", "Delay used after a scramble has been started", _, true, 1.0, true, 30.0); - - /** - Cvars used for admins - */ - sas_admin_immunity_enabled = CreateConVar("sas_admin_immunity_enabled", "1", "Enable/Disable admin immunity for scrambles"); - sas_admin_flag_scramblenow = CreateConVar("sas_admin_flag_scramblenow", "z", "Admin flag to use for scramblenow function/command"); - sas_admin_flag_immunity = CreateConVar("sas_admin_flag_immunity", "z", "Admin flag to use for scramble immunity"); - - /** - Cvars used for autoscramble - */ - sas_autoscramble_enabled = CreateConVar("sas_autoscramble_enabled", "1", "Enable/Disable the autoscramble function"); - sas_autoscramble_minplayers = CreateConVar("sas_autoscramble_minplayers", "16", "Min players needed to start an autoscramble"); - sas_autoscramble_mode = CreateConVar("sas_autoscramble_mode", "1", "Scramble mode used when autoscrambling"); - sas_autoscramble_winstreak = CreateConVar("sas_autoscramble_winstreak", "5", "Max amount of wins in a row a team can achieve before an autoscramble starts"); - sas_autoscramble_steamroll = CreateConVar("sas_autoscramble_steamroll", "120", "Shortest amount of time a team can win by before an autoscramble starts (seconds)"); - sas_autoscramble_frags = CreateConVar("sas_autoscramble_frags", "1", "Min players needed to start a vote and scramble"); - - /** - Cvars used for voting - */ - sas_vote_enabled = CreateConVar("sas_vote_enabled", "1", "Enable/Disable voting for scramble"); - sas_vote_upcount = CreateConVar("sas_vote_upcount", "5", "Amount of people wanting a scramble before a vote starts. If less than 1 it will be considered a percentage. (ie 0.5 = 50% | 1 = 1 Player | 5 = 5 Players)"); - sas_vote_winpercent = CreateConVar("sas_vote_winpercent", "0.6", "Percentage of votes needed to scramble", _, true, 0.0, true, 1.0); - sas_vote_mode = CreateConVar("sas_vote_mode", "1", "Scramble mode used when a vote results in a scramble"); - sas_vote_minplayers = CreateConVar("sas_vote_minplayers", "16", "Min players needed to start a vote and scramble"); - - /** - Hook the console variables if they change - */ - HookConVarChange(sas_enabled, ConVarSettingsChanged); - HookConVarChange(sas_timer_scrambledelay, ConVarSettingsChanged); - HookConVarChange(sas_admin_immunity_enabled, ConVarSettingsChanged); - HookConVarChange(sas_admin_flag_scramblenow, ConVarSettingsChanged); - HookConVarChange(sas_admin_flag_immunity, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_enabled, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_minplayers, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_mode, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_winstreak, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_steamroll, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_frags, ConVarSettingsChanged); - HookConVarChange(sas_vote_enabled, ConVarSettingsChanged); - HookConVarChange(sas_vote_upcount, ConVarSettingsChanged); - HookConVarChange(sas_vote_winpercent, ConVarSettingsChanged); - HookConVarChange(sas_vote_mode, ConVarSettingsChanged); - HookConVarChange(sas_vote_minplayers, ConVarSettingsChanged); - - /** - Register the command - */ - RegConsoleCmd("sm_scramblenow", Command_ScrambleNow, "sm_scramblenow (mode): Scrambles the teams"); - - /** - Load translations and .cfg file - */ - LoadTranslations ("simpleautoscrambler.phrases"); - AutoExecConfig(true, "plugin.simpleautoscrambler"); - LogAction(0, -1, "[SAS] Simple AutoScrambler is loaded."); -} - -public OnAllPluginsLoaded() -{ - //something -} - -public OnLibraryRemoved(const String:name[]) -{ - //something -} - -public OnConfigsExecuted() -{ - - /** - Load up all the variable defaults - */ - LoadUpVariables(); - - /** - Log our activity - */ - if (g_bIsEnabled) - LogAction(0, -1, "Simple AutoScrambler is ENABLED"); - else - LogAction(0, -1, "Simple AutoScrambler is DISABLED"); -} - -public Action:Command_ScrambleNow(client, args) -{ - - /** - Make sure we are enabled - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the client is authorized to run this command. - */ - if (!SM_IsValidAdmin(client, g_sScrambleNowFlag)) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure it's ok to scramble at this time - */ - if (!OkToScramble) - { - return Plugin_Handled; - } - - /** - Make sure it's ok to scramble at this time - */ - LogAction(0, -1, "[SAS] The scramblenow command was used"); - - /** - Scramble the teams - */ - StartAScramble(); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - -} - -public Action:Timer_ScrambleTeams(Handle:timer, any:mode) -{ - - /** - Make sure it's still ok to scramble - */ - if (!OkToScramble) - { - return Plugin_Handled; - } - - - switch (mode) - { - case - - - - } - - - /** - Reset the handle because the timer is over and the callback is done - */ - g_hScrambleTimer = INVALID_HANDLE; - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - -} - -stock StartAScramble(mode) -{ - - /** - See if we are already started a scramble - */ - if (g_hScrambleTimer == INVALID_HANDLE) - { - - /** - There is a scramble in progress - */ - return; - - } - - /** - Report that a scramble is about to start - */ - PrintCenterTextAll("%T", "Scramble", LANG_SERVER); - - /** - Start a timer and log the action - */ - g_hScrambleTimer = CreateTimer(g_fTimer_ScrambleDelay, Timer_ScrambleTeams, mode, TIMER_FLAG_NO_MAPCHANGE); - LogAction(0, -1, "[SAS] A scamble timer was started"); -} - -stock bool:OkToScramble() -{ - -} - -stock LoadUpVariables() -{ - g_bIsEnabled = GetConVarBool(sas_enabled); - g_bIsAutoScrambleEnabled = GetConVarBool(sas_autoscramble_enabled); - g_bIsVoteEnabled = GetConVarBool(sas_vote_enabled); - g_bIsAdminImmunityEnabled = GetConVarBool(sas_admin_immunity_enabled); - g_iAutoScramble_Minplayers = GetConVarInt(sas_autoscramble_minplayers); - g_iAutoScramble_Mode = GetConVarInt(sas_autoscramble_mode); - g_iAutoScramble_WinStreak = GetConVarInt(sas_autoscramble_winstreak); - g_iAutoScramble_SteamRoll = GetConVarInt(sas_autoscramble_steamroll); - g_iAutoScramble_Frags = GetConVarInt(sas_autoscramble_frags); - g_iVote_Mode = GetConVarInt(sas_vote_mode); - g_iVote_MinPlayers = GetConVarInt(sas_vote_minplayers); - GetConVarString(sas_admin_flag_scramblenow, g_sScrambleNowFlag, sizeof(g_sScrambleNowFlag)); - GetConVarString(sas_admin_flag_immunity, g_sAdminImmunityFlag, sizeof(g_sAdminImmunityFlag)); - g_fTimer_ScrambleDelay = GetConVarFloat(sas_timer_scrambledelay); - g_fVote_UpCount = GetConVarFloat(sas_vote_upcount); - g_fVote_WinPercent = GetConVarFloat(sas_vote_winpercent); - g_iMaxEntities = GetMaxEntities(); - g_iOwnerOffset = FindSendPropInfo("CBaseObject", "m_hBuilder"); -} - -stock TF2_DestroyBuildings(client) -{ - - /** - We have to start a loop to check the owner of all the valid entities - */ - for (new i = MaxClients + 1; i <= g_iMaxEntities; i++) - { - if (!IsValidEntity(i)) - { - - /** - Not valid, continue to next one - */ - continue; - } - - /** - Get the name of the current entity - */ - decl String:sNetClass[32]; - GetEntityNetClass(i, sNetClass, sizeof(sNetClass)); - - /** - See if its something that an engineer would build - */ - if (strcmp(sNetClass, "CObjectSentrygun") == 0 - || strcmp(sNetClass, "CObjectTeleporter") == 0 - || strcmp(sNetClass, "CObjectDispenser") == 0) - { - - /** - It is, so lets check the owner - */ - if (GetEntDataEnt2(i, g_iOwnerOffset) == client) - { - - /** - It's the clients building, so we blow it up. - */ - SetVariantInt(9999); - AcceptEntityInput(i, "RemoveHealth"); - } - } - } -} \ No newline at end of file diff --git a/Simple Donator Benefits/addons/sourcemod/scripting/simple-chatcolors.sp b/Simple Donator Benefits/addons/sourcemod/scripting/simple-chatcolors.sp deleted file mode 100644 index 539d057..0000000 --- a/Simple Donator Benefits/addons/sourcemod/scripting/simple-chatcolors.sp +++ /dev/null @@ -1,496 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Chat Colors -Description: - Changes the colors of players chat based on config file -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#pragma semicolon 1 -#include -#include - -#define PLUGIN_VERSION "0.9.0.$Rev$" - -#define CHAT_SYMBOL '@' -#define TRIGGER_SYMBOL1 '!' -#define TRIGGER_SYMBOL2 '/' -#define CHAT_MAX_MESSAGE_LENGTH 1024 - -new Handle:g_hDebugCvar = INVALID_HANDLE; -new Handle:g_aGroupNames = INVALID_HANDLE; -new Handle:g_aGroupFlag = INVALID_HANDLE; -new Handle:g_aGroupNameColor = INVALID_HANDLE; -new Handle:g_aGroupTextColor = INVALID_HANDLE; - -new bool:g_bDebug = false; - -new g_iArraySize; - -new g_aPlayerColorIndex[MAXPLAYERS + 1] = { -1, ... }; - -public Plugin:myinfo = -{ - name = "Simple Chat Colors", - author = "Simple Plugins", - description = "Changes the colors of players chat based on config file.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -/** -Sourcemod callbacks -*/ -public OnPluginStart() -{ - - /** - Need to create all of our console variables. - */ - CreateConVar("sm_chatcolors_version", PLUGIN_VERSION, "Simple Chat Colors", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - g_hDebugCvar = CreateConVar("sm_chatcolors_debug", "1", "Enable/Disable debugging information"); - - /** - Hook console variables - */ - HookConVarChange(g_hDebugCvar, ConVarSettingsChanged); - - /** - Need to register the commands we are going to use - */ - RegConsoleCmd("say", Command_Say); - RegConsoleCmd("say_team", Command_SayTeam); - RegAdminCmd("sm_reloadcolorsconfig", Command_Reload, ADMFLAG_GENERIC, "Reloads settings from config file"); - - /** - Create the arrays - */ - g_aGroupNames = CreateArray(256, 1); - g_aGroupFlag = CreateArray(15, 1); - g_aGroupNameColor = CreateArray(15, 1); - g_aGroupTextColor = CreateArray(15, 1); - - /** - Load the admins and colors from the config - */ - LoadAdminsAndColorsFromConfig(); - g_iArraySize = GetArraySize(g_aGroupNames); -} - -public OnConfigsExecuted() -{ - g_bDebug = GetConVarBool(g_hDebugCvar); - ReloadConfigFile(); -} - -public OnClientPostAdminCheck(client) -{ - - /** - Check the client to see if they are a admin - */ - CheckAdmin(client); -} - -public OnClientDisconnect(client) -{ - g_aPlayerColorIndex[client] = -1; -} - -/** -Commands -*/ -public Action:Command_Say(client, args) -{ - - /** - Make sure we are enabled. - */ - if (client == 0 || IsChatTrigger()) - { - return Plugin_Continue; - } - - if (g_aPlayerColorIndex[client] != -1) - { - - /** - The client is, so get the chat message and strip it down. - */ - decl String:sArg[CHAT_MAX_MESSAGE_LENGTH], - String:sChatMsg[CHAT_MAX_MESSAGE_LENGTH]; - - new bool:bAlive = IsPlayerAlive(client); - - GetCmdArgString(sArg, sizeof(sArg)); - StripQuotes(sArg); - TrimString(sArg); - new startidx; - if (sArg[strlen(sArg)-1] == '"') - { - sArg[strlen(sArg)-1] = '\0'; - startidx = 1; - } - - /** - Bug out if they are using the admin chat symbol (admin chat). If we are in CSS it may not find all the triggers, so we double check. - */ - if (sArg[startidx] == CHAT_SYMBOL || sArg[startidx] == TRIGGER_SYMBOL1 || sArg[startidx] == TRIGGER_SYMBOL2) - { - return Plugin_Continue; - } - - /** - Log the message for hlstatsx and other things. - */ - new iUserID = GetClientUserId(client); - decl String:sAuthID[64]; - GetClientAuthString(client, sAuthID, sizeof(sAuthID)); - LogToGame("\"%N<%i><%s><>\" say \"%s\"", client, iUserID, sAuthID, sArg); - - /** - Format the message. - */ - FormatMessage(client, 0, bAlive, sChatMsg, sArg, g_aPlayerColorIndex[client]); - - /** - Send the message. - */ - //SayText2(0, client, sChatMsg); - CPrintToChatAll(sChatMsg); - - /** - We are done, bug out, and stop the original chat message. - */ - return Plugin_Stop; - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Command_SayTeam(client, args) -{ - - /** - Make sure we are enabled. - */ - if (client == 0 || IsChatTrigger()) - { - return Plugin_Continue; - } - - /** - Check the client to see if they are a admin - */ - if (g_aPlayerColorIndex[client] != -1) - { - - /** - The client is, so get the chat message and strip it down. - */ - decl String:sArg[CHAT_MAX_MESSAGE_LENGTH], - String:sChatMsg[CHAT_MAX_MESSAGE_LENGTH]; - - new bool:bAlive = IsPlayerAlive(client); - new iCurrentTeam = GetClientTeam(client); - - GetCmdArgString(sArg, sizeof(sArg)); - StripQuotes(sArg); - TrimString(sArg); - new startidx; - if (sArg[strlen(sArg)-1] == '"') - { - sArg[strlen(sArg)-1] = '\0'; - startidx = 1; - } - - /** - Bug out if they are using the admin chat symbol (admin chat). - */ - if (sArg[startidx] == CHAT_SYMBOL || sArg[startidx] == TRIGGER_SYMBOL1 || sArg[startidx] == TRIGGER_SYMBOL2) - { - return Plugin_Continue; - } - - /** - Log the message for hlstatsx and other things. - */ - new iUserID = GetClientUserId(client); - decl String:sAuthID[64]; - GetClientAuthString(client, sAuthID, sizeof(sAuthID)); - LogToGame("\"%N<%i><%s><>\" say_team \"%s\"", client, iUserID, sAuthID, sArg); - - /** - Format the message. - */ - FormatMessage(client, iCurrentTeam, bAlive, sChatMsg, sArg, g_aPlayerColorIndex[client]); - - /** - Send the message to the same team - */ - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == iCurrentTeam) - { - CPrintToChat(client, sChatMsg); - } - } - - /** - We are done, bug out, and stop the original chat message. - */ - return Plugin_Stop; - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Command_Reload(client, args) -{ - ReloadConfigFile(); - return Plugin_Handled; -} - -/** -Stock Functions -*/ -stock LoadAdminsAndColorsFromConfig() -{ - - /** - Make sure the config file is here and load it up - */ - new String:sConfigFile[256]; - BuildPath(Path_SM, sConfigFile, sizeof(sConfigFile), "configs/simple-chatcolors.cfg"); - if (!FileExists(sConfigFile)) - { - - /** - Config file doesn't exists, stop the plugin - */ - LogError("[SCC] Simple Chat Colors is not running! Could not find file %s", sConfigFile); - SetFailState("Could not find file %s", sConfigFile); - } - - /** - Create the arrays and variables - */ - new String:sGroupName[256]; - new String:sGroupFlag[15]; - new String:sGroupNameColor[15]; - new String:sGroupTextColor[15]; - - - /** - Load config file as a KeyValues file - */ - new Handle:kvChatColors = CreateKeyValues("admin_colors"); - FileToKeyValues(kvChatColors, sConfigFile); - - if (!KvGotoFirstSubKey(kvChatColors)) - { - return; - } - - /** - Load up all the groups in the file - */ - do - { - - /** - Get the section name; should be the "group" name - */ - KvGetSectionName(kvChatColors, sGroupName, sizeof(sGroupName)); - - - /** - Get the flags and colors - */ - KvGetString(kvChatColors, "flag", sGroupFlag, sizeof(sGroupFlag)); - KvGetString(kvChatColors, "namecolor", sGroupNameColor, sizeof(sGroupNameColor)); - KvGetString(kvChatColors, "textcolor", sGroupTextColor, sizeof(sGroupTextColor)); - - if (g_bDebug) - { - LogMessage("Group Name/SteamID: %s", sGroupName); - LogMessage("Flag String: %s", sGroupFlag); - LogMessage("Color on name: %s", sGroupNameColor); - LogMessage("Color of text: %s", sGroupTextColor); - } - - /** - Push the values to the arrays - */ - PushArrayString(g_aGroupNames, sGroupName); - PushArrayString(g_aGroupFlag, sGroupFlag); - PushArrayString(g_aGroupNameColor, sGroupNameColor); - PushArrayString(g_aGroupTextColor, sGroupTextColor); - } while (KvGotoNextKey(kvChatColors)); - - /** - Close our handle - */ - CloseHandle(kvChatColors); -} - -stock ReloadConfigFile() -{ - - /** - Clear the array - */ - ClearArray(g_aGroupNames); - ClearArray(g_aGroupFlag); - ClearArray(g_aGroupNameColor); - ClearArray(g_aGroupTextColor); - - /** - Load the admins, groups, and colors from the config - */ - LoadAdminsAndColorsFromConfig(); - g_iArraySize = GetArraySize(g_aGroupNames); - - /** - Recheck all the online players for assigned colors - */ - for (new index = 1; index <= MaxClients; index++) - { - if (IsClientConnected(index) && IsClientInGame(index)) - { - CheckAdmin(index); - } - } -} - -stock CheckAdmin(client) -{ - new String:sFlags[15]; - new String:sClientSteamID[64]; - new iGroupFlags; - new iFlags; - new iIndex = -1; - - /** - Look for a steamid first - */ - GetClientAuthString(client, sClientSteamID, sizeof(sClientSteamID)); - iIndex = FindStringInArray(g_aGroupNames, sClientSteamID); - if (iIndex != -1) - { - g_aPlayerColorIndex[client] = iIndex; - } - - /** - Didn't find one, check flags - */ - else - { - /** - Search for flag in groups - */ - - iFlags = GetUserFlagBits(client); - for (iIndex = 0; iIndex < g_iArraySize; iIndex++) - { - GetArrayString(g_aGroupFlag, iIndex, sFlags, sizeof(sFlags)); - iGroupFlags = ReadFlagString(sFlags); - if (iFlags & iGroupFlags) - { - g_aPlayerColorIndex[client] = iIndex; - break; - } - } - } - - if (g_bDebug) - { - PrintToChatAll("SteamID: %s", sClientSteamID); - PrintToChatAll("Array Index: %i", iIndex); - PrintToChatAll("Flag String: %s", sFlags); - PrintToChatAll("Flag Bits of Client: %i", iFlags); - PrintToChatAll("Flag Bits of Group: %i", iGroupFlags); - } -} - -stock FormatMessage(iClient, iTeam, bool:bAlive, String:sChatMsg[], const Sting:sMessage[], iArrayIndex) -{ - decl String:sDead[10], - String:sTeam[10], - String:sClientName[64]; - - GetClientName(iClient, sClientName, sizeof(sClientName)); - - if (iTeam != 0) - { - Format(sTeam, sizeof(sTeam), "(TEAM) "); - } - else - { - Format(sTeam, sizeof(sTeam), ""); - } - if (bAlive) - { - Format(sDead, sizeof(sDead), ""); - } - else - { - Format(sDead, sizeof(sDead), "*DEAD* "); - } - - new String:sNameColor[15]; - new String:sTextColor[15]; - GetArrayString(g_aGroupNameColor, iArrayIndex, sNameColor, sizeof(sNameColor)); - GetArrayString(g_aGroupTextColor, iArrayIndex, sTextColor, sizeof(sTextColor)); - - Format(sChatMsg, CHAT_MAX_MESSAGE_LENGTH, "{default}%s%s%s%s {default}: %s%s", sDead, sTeam, sNameColor, sClientName, sTextColor, sMessage); -} - -/** -Adjust the settings if a convar was changed -*/ -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (StringToInt(newValue) == 1) - { - g_bDebug = true; - } - else - { - g_bDebug = false; - } -} \ No newline at end of file diff --git a/Simple Donator Benefits/addons/sourcemod/scripting/simple-messagesuppression.sp b/Simple Donator Benefits/addons/sourcemod/scripting/simple-messagesuppression.sp deleted file mode 100644 index f7725a4..0000000 --- a/Simple Donator Benefits/addons/sourcemod/scripting/simple-messagesuppression.sp +++ /dev/null @@ -1,227 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Message Suppression -Description: - Blocks Specific Message Outputs -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include -#include - -#define SUPPRESS_VERSION "1.1.$Rev$" - -public Plugin:myinfo = -{ - name = "Simple Message Suppression", - author = "FlyingMongoose, psychonic", - description = "Blocks Specific Message Outputs", - version = SUPPRESS_VERSION, - url = "http://www.simple-plugins.com/" -} - -new Handle:cvarBlockSpectateMessage; -new Handle:cvarBlockDisconnectMessage; -new Handle:cvarBlockConnectMessage; -new Handle:cvarAdminShowMessages; -new iSpecTeam = 1; - - -public OnPluginStart() -{ - CreateConVar("suppress_version", SUPPRESS_VERSION, _, FCVAR_PLUGIN|FCVAR_NOTIFY|FCVAR_REPLICATED|FCVAR_SPONLY|FCVAR_DONTRECORD); - cvarBlockSpectateMessage = CreateConVar("sm_blockspectatemessage", "1", "If enabled it blocks the join team message if an administrator joins spectator", FCVAR_PLUGIN, true, 0.0, true, 1.0); - cvarBlockDisconnectMessage = CreateConVar("sm_blockdisconnectmessage", "1", "Blocks the disconnect message", FCVAR_PLUGIN, true, 0.0, true, 1.0); - cvarBlockConnectMessage = CreateConVar("sm_blockconnectmessage", "1", "If enabled it blocks the player connection message.", FCVAR_PLUGIN, true, 0.0, true, 1.0); - cvarAdminShowMessages = CreateConVar("sm_adminshowmessages", "1", "Shows disconnect/connect/team join messages for admins only (if disconnect message is set to be blocked)", FCVAR_PLUGIN, true, 0.0, true, 1.0); - HookEvent("player_team", ev_PlayerTeam, EventHookMode_Pre); - HookEvent("player_disconnect", ev_PlayerDisconnect, EventHookMode_Pre); - HookEvent("player_connect", ev_PlayerConnect, EventHookMode_Pre); - - new String:game_folder[64]; - GetGameFolderName(game_folder, sizeof(game_folder)) - - if (StrContains(game_folder, "insurgency", false) != -1) - { - iSpecTeam = 3; - } - else - { - new String:game_description[64]; - GetGameDescription(game_description, sizeof(game_description), true); - if (StrContains(game_description, "Insurgency", false) != -1) - { - iSpecTeam = 3; - } - } - - AutoExecConfig(true, "suppressmessage", "sourcemod"); -} - -public Action:ev_PlayerTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (GetConVarBool(cvarBlockSpectateMessage)) - { - if (!dontBroadcast && !GetEventBool(event, "silent")) - { - new iUserId = GetEventInt(event, "userid"); - new iClient = GetClientOfUserId(iUserId); - new iTeam = GetEventInt(event, "team"); - - if (iTeam == iSpecTeam && GetAdminFlag(GetUserAdmin(iClient), Admin_Kick)) - { - new iOldTeam = GetEventInt(event, "oldteam"); - new bool:bDisconnect = GetEventBool(event, "disconnect"); - new bool:bAutoteam = GetEventBool(event, "autoteam"); - decl String:strName[50]; - GetEventString(event, "name", strName, sizeof(strName)); - - if (iClient != 0) - { - if (GetConVarInt(cvarAdminShowMessages) == 1) - { - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i) && GetUserAdmin(i) != INVALID_ADMIN_ID) - { - PrintToChat(i,"%N joined team Spectator.", iClient); - PrintToConsole(i,"%N joined team Spectator.", iClient); - } - } - } - } - - new Handle:hEvent = CreateEvent("player_team"); - SetEventInt(hEvent, "userid", iUserId); - SetEventInt(hEvent, "team", iTeam); - SetEventInt(hEvent, "oldteam", iOldTeam); - SetEventBool(hEvent, "disconnect", bDisconnect); - SetEventBool(hEvent, "autoteam", bAutoteam); - SetEventBool(hEvent, "silent", true); - SetEventString(hEvent, "name", strName); - - FireEvent(hEvent, true); - - return Plugin_Handled; - } - } - } - return Plugin_Continue; -} -public Action:ev_PlayerConnect(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (GetConVarBool(cvarBlockConnectMessage)) - { - if (!dontBroadcast) - { - decl String:strName[50]; - GetEventString(event, "name", strName, sizeof(strName)); - new iIndex = GetEventInt(event, "index"); - new iUserId = GetEventInt(event, "userid"); - new iClient = GetClientOfUserId(iUserId); - decl String:strNetworkId[50]; - GetEventString(event, "networkid", strNetworkId, sizeof(strNetworkId)); - decl String:strAddress[50]; - GetEventString(event, "address", strAddress, sizeof(strAddress)); - - if (iClient != 0) - { - if (GetConVarInt(cvarAdminShowMessages) == 1) - { - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i) && GetUserAdmin(i) != INVALID_ADMIN_ID) - { - PrintToChat(i,"%N has connected.", iClient); - PrintToConsole(i,"%N has connected.", iClient); - } - } - } - } - - new Handle:hEvent = CreateEvent("player_connect"); - SetEventString(hEvent, "name", strName); - SetEventInt(hEvent, "index", iIndex); - SetEventInt(hEvent, "userid", iUserId); - SetEventString(hEvent, "networkid", strNetworkId); - SetEventString(hEvent, "address", strAddress); - - FireEvent(hEvent, true); - - return Plugin_Handled; - } - } - return Plugin_Continue; -} -public Action:ev_PlayerDisconnect(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (GetConVarBool(cvarBlockDisconnectMessage)) - { - if (!dontBroadcast) - { - new iUserId = GetEventInt(event, "userid"); - new iClient = GetClientOfUserId(iUserId); - decl String:strReason[50]; - GetEventString(event, "reason", strReason, sizeof(strReason)); - decl String:strName[50]; - GetEventString(event, "name", strName, sizeof(strName)); - decl String:strNetworkId[50]; - GetEventString(event, "networkid", strNetworkId, sizeof(strNetworkId)); - - if (iClient != 0) - { - if (GetConVarInt(cvarAdminShowMessages) == 1) - { - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i) && GetUserAdmin(i) != INVALID_ADMIN_ID) - { - PrintToChat(i, "%N has left the server.", iClient); - PrintToConsole(i, "Dropped %N from server (Disconnect by user.)", iClient); - } - } - } - } - - new Handle:hEvent = CreateEvent("player_disconnect"); - SetEventInt(hEvent, "userid", iUserId); - SetEventString(hEvent, "reason", strReason); - SetEventString(hEvent, "name", strName); - SetEventString(hEvent, "networkid", strNetworkId); - - FireEvent(hEvent, true); - - return Plugin_Handled; - } - } - - return Plugin_Continue; -} \ No newline at end of file diff --git a/Simple Donator Benefits/addons/sourcemod/scripting/simple-plugins.sp b/Simple Donator Benefits/addons/sourcemod/scripting/simple-plugins.sp deleted file mode 100644 index 4462b41..0000000 --- a/Simple Donator Benefits/addons/sourcemod/scripting/simple-plugins.sp +++ /dev/null @@ -1,785 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Plugins -Description: - Core plugin for Simple Plugins project -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#define CORE_PLUGIN_VERSION "1.1.$Rev$" - -#include - -enum e_PlayerInfo -{ - Handle:hForcedTeamPlugin = INVALID_HANDLE, - iForcedTeam = 0, - iBuddy = 0, - bool:bBuddyLocked = false -}; - -new Handle:g_fwdPlayerMoved; -new g_aPlayers[MAXPLAYERS + 1][e_PlayerInfo]; -new bool:g_bTeamsSwitched = false; - -/** -Setting our plugin information. -*/ -public Plugin:myinfo = -{ - name = "Simple Plugins Core Plugin", - author = "Simple Plugins", - description = "Core plugin for Simple Plugins", - version = CORE_PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -public bool:AskPluginLoad(Handle:myself, bool:late, String:error[], err_max) -{ - - /** - Register natives for other plugins - */ - CreateNative("SM_MovePlayer", Native_SM_MovePlayer); - CreateNative("SM_SetForcedTeam", Native_SM_SetForcedTeam); - CreateNative("SM_GetForcedTeam", Native_SM_GetForcedTeam); - CreateNative("SM_ClearForcedTeam", Native_SM_ClearForcedTeam); - CreateNative("SM_GetForcedPlayer", Native_SM_GetForcedPlayer); - CreateNative("SM_AssignBuddy", Native_SM_AssignBuddy); - CreateNative("SM_GetClientBuddy", Native_SM_GetClientBuddy); - CreateNative("SM_LockBuddy", Native_SM_LockBuddy); - CreateNative("SM_IsBuddyLocked", Native_SM_IsBuddyLocked); - CreateNative("SM_ClearBuddy", Native_SM_ClearBuddy); - CreateNative("SM_IsValidAdmin", Native_SM_IsValidAdmin); - CreateNative("SM_IsValidTeam", Native_SM_IsValidTeam); - RegPluginLibrary("simpleplugins"); - return true; -} - -public OnPluginStart() -{ - - CreateConVar("ssm_core_pl_ver", CORE_PLUGIN_VERSION, "Simple SourceMod Plugins Core Plugin Version", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - CreateConVar("ssm_core_inc_ver", CORE_INC_VERSION, "Simple SourceMod Plugins Core Include Version", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook some events to control forced players and check extensions - */ - decl String:sExtError[256]; - LogAction(0, -1, "[SSM] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Pre); - switch (g_CurrentMod) - { - case GameType_CSS: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - new iExtStatus = GetExtensionFileStatus("game.cstrike.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SSM] Required extension was not found."); - LogAction(0, -1, "[SSM] Plugin FAILED TO LOAD."); - SetFailState("Required extension was not found."); - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SSM] Required extension is loaded with errors."); - LogAction(0, -1, "[SSM] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SSM] Plugin FAILED TO LOAD."); - SetFailState("Required extension is loaded with errors."); - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SSM] Required extension is loaded."); - } - } - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_PostNoCopy); - HookUserMessage(GetUserMessageId("TextMsg"), UserMessageHook_Class, true); - new iExtStatus = GetExtensionFileStatus("game.tf2.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SSM] Required extension was not found."); - LogAction(0, -1, "[SSM] Plugin FAILED TO LOAD."); - SetFailState("Required extension was not found."); - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SSM] Required extension is loaded with errors."); - LogAction(0, -1, "[SSM] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SSM] Plugin FAILED TO LOAD."); - SetFailState("Required extension is loaded with errors."); - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SSM] Required extension is loaded."); - } - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_PostNoCopy); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - - /** - Load common translations - */ - LoadTranslations ("common.phrases"); - - /** - Create the global forward - */ - g_fwdPlayerMoved = CreateGlobalForward("SM_OnPlayerMoved", ET_Event, Param_Cell, Param_Cell, Param_Cell); -} - -public OnClientDisconnect(client) -{ - - /** - Cleanup clients/players buddy list - */ - if (!IsFakeClient(client)) - { - SM_ClearBuddy(client, true); - SM_LockBuddy(client, false); - } - SM_ClearForcedTeam(client); -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - See if the teams have been switched - */ - if (g_bTeamsSwitched) - { - - /** - Switch the teams the players are forced to - */ - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][iForcedTeam] != 0) - { - if (g_aPlayers[i][iForcedTeam] == g_aCurrentTeams[Team1]) - { - g_aPlayers[i][iForcedTeam] = g_aCurrentTeams[Team2]; - } - else - { - g_aPlayers[i][iForcedTeam] = g_aCurrentTeams[Team1]; - } - } - } - } -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - g_bTeamsSwitched = false; -} - -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get our event variables - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - new iTeam = GetEventInt(event, "team"); - - /** - See if the player is on the wrong team - */ - if (g_aPlayers[iClient][iForcedTeam] != 0 && g_aPlayers[iClient][iForcedTeam] != iTeam) - { - - /** - Move the player back to the forced team - */ - CreateTimer(1.0, Timer_ForcePlayerMove, iClient, TIMER_FLAG_NO_MAPCHANGE); - - /** - If the event was going to be broadcasted, we refire it so it is not broadcasted and stop this one - */ - if (!dontBroadcast) - { - new Handle:hEvent = CreateEvent("player_team"); - SetEventInt(hEvent, "userid", GetEventInt(event, "userid")); - SetEventInt(hEvent, "team", GetEventInt(event, "team")); - SetEventInt(hEvent, "oldteam", GetEventInt(event, "oldteam")); - SetEventBool(hEvent, "disconnect", GetEventBool(event, "disconnect")); - - if (g_CurrentMod == GameType_DOD || g_CurrentMod == GameType_L4D || g_CurrentMod == GameType_TF) - { - new String:sClientName[MAX_NAME_LENGTH + 1]; - GetClientName(client, sClientName, sizeof(sClientName)); - SetEventBool(hEvent, "autoteam", GetEventBool(event, "autoteam")); - SetEventBool(hEvent, "silent", true); - SetEventString(hEvent, "name", sClientName); - FireEvent(hEvent, true); - } - else - { - FireEvent(hEvent, true); - } - return Plugin_Handled; - } - } - return Plugin_Continue; -} - -public Action:UserMessageHook_Class(UserMsg:msg_id, Handle:bf, const players[], playersNum, bool:reliable, bool:init) -{ - new String:sMessage[120]; - BfReadString(bf, sMessage, sizeof(sMessage), true); - if (StrContains(sMessage, "#TF_TeamsSwitched", false) != -1) - { - g_bTeamsSwitched = true; - } - return Plugin_Continue; -} - -public Native_SM_MovePlayer(Handle:plugin, numParams) -{ - - /** - Get and check the client and team - */ - new iClient = GetNativeCell(1); - new iTeam = GetNativeCell(2); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (iTeam != g_aCurrentTeams[Spectator] && iTeam != g_aCurrentTeams[Team1] && iTeam != g_aCurrentTeams[Team2]) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid team %d", iTeam); - } - - MovePlayer(iClient, iTeam); - if (!IsClientObserver(iClient)) - { - RespawnPlayer(iClient); - } - - new fResult; - - Call_StartForward(g_fwdPlayerMoved); - Call_PushCell(plugin); - Call_PushCell(iClient); - Call_PushCell(iTeam); - Call_Finish(fResult); - - if (fResult != SP_ERROR_NONE) - { - return ThrowNativeError(fResult, "Forward failed"); - } - - return fResult; -} - -public Native_SM_SetForcedTeam(Handle:plugin, numParams) -{ - - /** - Get and check the client and team - */ - new iClient = GetNativeCell(1); - new iTeam = GetNativeCell(2); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (iTeam != g_aCurrentTeams[Spectator] && iTeam != g_aCurrentTeams[Team1] && iTeam != g_aCurrentTeams[Team2] && iTeam != g_aCurrentTeams[Unknown]) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid team %d", iTeam); - } - - new bool:bOverRide = GetNativeCell(3) ? true : false; - - if (!bOverRide && g_aPlayers[iClient][hForcedTeamPlugin] != INVALID_HANDLE && plugin != g_aPlayers[iClient][hForcedTeamPlugin]) - { - return false; - } - - g_aPlayers[iClient][hForcedTeamPlugin] = plugin; - g_aPlayers[iClient][iForcedTeam] = iTeam; - return true; -} - -public Native_SM_GetForcedTeam(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - - /** - Get and set the plugin if they want it - */ - new Handle:hPlugin = GetNativeCell(2); - if (hPlugin != INVALID_HANDLE) - { - SetNativeCellRef(2, g_aPlayers[iClient][hForcedTeamPlugin]); - } - - /** - Return the forced team, this could be 0 - */ - return g_aPlayers[iClient][iForcedTeam]; -} - -public Native_SM_ClearForcedTeam(Handle:plugin, numParams) -{ - - /** - Get and check the client and team - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - - g_aPlayers[iClient][hForcedTeamPlugin] = INVALID_HANDLE; - g_aPlayers[iClient][iForcedTeam] = 0; - - return true; -} - -public Native_SM_GetForcedPlayer(Handle:plugin, numParams) -{ - - /** - Get and check the team - */ - new iTeam = GetNativeCell(1); - if (iTeam != g_aCurrentTeams[Spectator] && iTeam != g_aCurrentTeams[Team1] && iTeam != g_aCurrentTeams[Team2]) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid team %d", iTeam); - } - - /** - Start a loop to check for a player on the wrong team - Also make sure the plugin that set the forced team is the plugin that asked - */ - new iPlayer = 0; - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientInGame(i) - && GetClientTeam(i) != g_aPlayers[i][iForcedTeam] - && g_aPlayers[i][iForcedTeam] == iTeam - && g_aPlayers[i][hForcedTeamPlugin] == plugin) - { - iPlayer = i; - break; - } - } - - /** - Return the player we found, this could be 0 - */ - return iPlayer; -} - -public Native_SM_AssignBuddy(Handle:plugin, numParams) -{ - - /** - Get and check the client and player - */ - new iClient = GetNativeCell(1); - new iPlayer = GetNativeCell(2); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (iPlayer < 0 || iPlayer > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid player index (%d)", iPlayer); - } - if (!IsClientConnected(iPlayer)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Player %d is not connected", iPlayer); - } - if (!IsClientInGame(iPlayer)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Player %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Bots are not supported"); - } - - /** - See if we can override his setting - */ - new bool:bOverRide = GetNativeCell(3) ? true : false; - if (!bOverRide) - { - - /** - We can't override, so check if they are locked - */ - if (g_aPlayers[iClient][bBuddyLocked] || g_aPlayers[iPlayer][bBuddyLocked]) - { - - /** - We detected at least 1 lock, so we bug out - */ - return false; - } - } - - /** - Ready to set the buddies - */ - g_aPlayers[iClient][iBuddy] = iPlayer; - g_aPlayers[iPlayer][iBuddy] = iClient; - return true; -} - -public Native_SM_GetClientBuddy(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Bots are not supported"); - } - - /** - Return the players buddy, this could be 0 - */ - return g_aPlayers[iClient][iBuddy]; -} - -public Native_SM_LockBuddy(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - new bool:bSetting = GetNativeCell(2) ? true : false; - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Bots are not supported"); - } - - g_aPlayers[iClient][bBuddyLocked] = bSetting; - return true; -} - -public Native_SM_IsBuddyLocked(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Bots are not supported"); - } - - return g_aPlayers[iClient][bBuddyLocked]; -} - -public Native_SM_ClearBuddy(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Client (%d) is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Bots are not supported"); - } - - /** - Get the clients buddy and see if we can override his setting - */ - new bool:bOverRide = GetNativeCell(2) ? true : false; - new iPlayer = g_aPlayers[iClient][iBuddy]; - - /** - There is no buddy, we don't care about anything else so bug out - */ - if (iPlayer == 0) - { - return true; - } - - /** - We determined he had a buddy, check the override setting - */ - if (!bOverRide) - { - - /** - We can't override, so check if they are locked - */ - if (g_aPlayers[iClient][bBuddyLocked] || g_aPlayers[iPlayer][bBuddyLocked]) - { - - /** - We detected at least 1 lock, so we bug out - */ - return false; - } - } - - /** - Ready to clear the buddies - */ - g_aPlayers[iClient][iBuddy] = 0; - g_aPlayers[iPlayer][iBuddy] = 0; - return true; -} - -public Native_SM_IsValidTeam(Handle:plugin, numParams) -{ - - /** - Get the team - */ - new iTeam = GetNativeCell(1); - - /** - Check the team - */ - if (iTeam == g_aCurrentTeams[Spectator] || iTeam == g_aCurrentTeams[Team1] || iTeam == g_aCurrentTeams[Team2]) - { - return true; - } - return false; -} - -public Native_SM_IsValidAdmin(Handle:plugin, numParams) -{ - /** - Get the client and flags - */ - new iClient = GetNativeCell(1); - decl String:sFlags[15]; - GetNativeString(2, sFlags, sizeof(sFlags)); - new ibFlags = ReadFlagString(sFlags); - - /** - Check the flags - */ - if ((GetUserFlagBits(iClient) & ibFlags) == ibFlags) - { - return true; - } - if (GetUserFlagBits(iClient) & ADMFLAG_ROOT) - { - return true; - } - return false; -} - -public Action:Timer_ForcePlayerMove(Handle:timer, any:iClient) -{ - - MovePlayer(iClient, g_aPlayers[iClient][iForcedTeam]); - - if (g_aPlayers[iClient][iForcedTeam] != g_aCurrentTeams[Spectator]) - { - RespawnPlayer(iClient); - } - - PrintToChat(iClient, "\x01\x04----------------------------------"); - PrintToChat(iClient, "\x01\x04You have been forced to this team."); - PrintToChat(iClient, "\x01\x04----------------------------------"); - - return Plugin_Handled; -} - -stock MovePlayer(iClient, iTeam) -{ - - /** - Change the client's team based on the mod - */ - switch (g_CurrentMod) - { - case GameType_CSS: - { - CS_SwitchTeam(iClient, iTeam); - } - default: - { - ChangeClientTeam(iClient, iTeam); - } - } -} - -stock RespawnPlayer(iClient) -{ - - /** - Respawn the client based on the mod - */ - switch (g_CurrentMod) - { - case GameType_CSS: - { - CS_RespawnPlayer(iClient); - } - case GameType_TF: - { - TF2_RespawnPlayer(iClient); - } - case GameType_INS: - { - FakeClientCommand(iClient, "kill"); - } - default: - { - // - } - } -} diff --git a/Simple Donator Benefits/addons/sourcemod/scripting/simple-roundimmunity.sp b/Simple Donator Benefits/addons/sourcemod/scripting/simple-roundimmunity.sp deleted file mode 100644 index 5f0bca3..0000000 --- a/Simple Donator Benefits/addons/sourcemod/scripting/simple-roundimmunity.sp +++ /dev/null @@ -1,947 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Round Immunity -Description: - Gives admins immunity during certain rounds -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or any later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#pragma semicolon 1 -#include -#include -#undef REQUIRE_EXTENSIONS -#undef AUTOLOAD_EXTENSIONS -#include -#include -#define REQUIRE_EXTENSIONS -#define AUTOLOAD_EXTENSIONS - -#define PLUGIN_VERSION "1.1.$Rev$" -#define SPECTATOR 1 -#define TEAM_RED 2 -#define TEAM_BLUE 3 - -#define COLOR_GREEN 0 -#define COLOR_BLACK 1 -#define COLOR_RED 2 -#define COLOR_BLUE 3 -#define COLOR_TEAM 4 -#define COLOR_RAINBOW 5 -#define COLOR_NONE 6 - -#define PLAYERCOND_SLOWED (1<<0) //1 -#define PLAYERCOND_ZOOMED (1<<1) //2 -#define PLAYERCOND_DISGUISING (1<<2) //4 -#define PLAYERCOND_DISGUISED (1<<3) //8 -#define PLAYERCOND_SPYCLOAK (1<<4) //16 -#define PLAYERCOND_UBERED (1<<5) //32 -#define PLAYERCOND_TELEPORTTRAIL (1<<6) //64 -#define PLAYERCOND_TAUNT (1<<7) //128 -// (1<<8) //256 -// (1<<9) //512 -#define PLAYERCOND_TELEPORTFLASH (1<<10) //1024 -#define PLAYERCOND_KRUBER (1<<11) //2048 -// (1<<12) //4096 -// (1<<13) //8192 -#define PLAYERCOND_BONKED (1<<14) //16384 (blame Neph if it doesn't work) -#define PLAYERCOND_BONKEDORDRINKSLOWDOWN (1<<15) //32768 -#define PLAYERCOND_HEALING (1<<16) //65536 -#define PLAYERCOND_BURNING (1<<17) //131072 -#define PLAYERCOND_FULLYCHARGEDBYMEDIC (1<<18) //262144 - -enum e_Cookies -{ - bEnabled, - iColor, - iMode -}; - -enum e_ColorNames -{ - Green, - Black, - Red, - Blue -}; - -enum e_ColorValues -{ - iRed, - iGreen, - iBlue -}; - -enum e_PlayerData -{ - Handle:hGodModeTimer, - Handle:hColorTimer, - bool:bIsAdmin, - bool:bIsImmune, - iCycleColor -}; - -/** - Global convar handles - */ -new Handle:sri_charadminflag = INVALID_HANDLE; -new Handle:sri_enabled = INVALID_HANDLE; -new Handle:sri_cookie_enabled = INVALID_HANDLE; -new Handle:sri_cookie_color = INVALID_HANDLE; -new Handle:sri_cookie_mode = INVALID_HANDLE; - -/** - Player arrays - */ -new g_aPlayers[MAXPLAYERS + 1][e_PlayerData]; -new g_aClientCookies[MAXPLAYERS + 1][e_Cookies]; - -/** - Global bools - */ -new bool:g_bLoadedLate = false; -new bool:g_bIsEnabled = true; -new bool:g_bRoundEnd = false; -new bool:g_bUseDukehacks = false; -new bool:g_bUseClientprefs = false; - -/** - Global strings/integers/floats - */ -new String:g_sCharAdminFlag[32]; -new g_iColors[e_ColorNames][e_ColorValues]; -new g_iClassMaxHealth[TFClassType] = {0, 125, 125, 200, 175, 150, 300, 175, 125, 125}; - -public Plugin:myinfo = -{ - name = "Simple Round Immunity", - author = "Simple Plugins", - description = "Gives admins immunity during certain rounds", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -} - -bool:AskPluginLoad(Handle:myself, bool:late, String:error[], err_max) -{ - g_bLoadedLate = late; - return true; -} - -public OnPluginStart() -{ - - /** - Create console variables - */ - CreateConVar("sri_version", PLUGIN_VERSION, "Simple Round Immunity", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - sri_enabled = CreateConVar("sri_enabled", "1", "Enable/Disable Admin immunity during certain round."); - sri_charadminflag = CreateConVar("sri_charadminflag", "a", "Admin flag to use for immunity (only one). Must be a in char format."); - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook some events and check extensions - */ - decl String:sExtError[256]; - LogAction(0, -1, "[SRI] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_spawn", HookPlayerSpawn, EventHookMode_Post); - HookEvent("player_hurt", HookPlayerHurt, EventHookMode_Pre); - switch (g_CurrentMod) - { - case GameType_CSS: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - new iExtStatus = GetExtensionFileStatus("game.cstrike.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SRI] Required extension was not found."); - LogAction(0, -1, "[SRI] Plugin FAILED TO LOAD."); - SetFailState("Required extension was not found."); - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SRI] Required extension is loaded with errors."); - LogAction(0, -1, "[SRI] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SRI] Plugin FAILED TO LOAD."); - SetFailState("Required extension is loaded with errors."); - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SRI] Required css extension is loaded."); - } - } - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_PostNoCopy); - HookUserMessage(GetUserMessageId("TextMsg"), UserMessageHook_Class, true); - new iExtStatus = GetExtensionFileStatus("game.tf2.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SRI] Required extension was not found."); - LogAction(0, -1, "[SRI] Plugin FAILED TO LOAD."); - SetFailState("Required extension was not found."); - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SRI] Required extension is loaded with errors."); - LogAction(0, -1, "[SRI] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SRI] Plugin FAILED TO LOAD."); - SetFailState("Required extension is loaded with errors."); - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SRI] Required tf2 extension is loaded."); - } - iExtStatus = GetExtensionFileStatus("dukehacks.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SRI] Dukehacks extension was not found."); - LogAction(0, -1, "[SRI] Plugin continued to load, but that feature will not be used."); - g_bUseDukehacks = false; - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SRI] Dukehacks extension is loaded with errors."); - LogAction(0, -1, "[SRI] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SRI] Plugin continued to load, but that feature will not be used."); - g_bUseDukehacks = false; - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SRI] Dukehacks extension is loaded and will be used."); - g_bUseDukehacks = true; - dhAddClientHook(CHK_TakeDamage, Hacks_TakeDamageHook); - } - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_PostNoCopy); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - /** - Now lets check for client prefs extension - */ - new iExtStatus = GetExtensionFileStatus("clientprefs.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SRI] Client Preferences extension was not found."); - LogAction(0, -1, "[SRI] Plugin continued to load, but that feature will not be used."); - g_bUseClientprefs = false; - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SRI] Client Preferences extension is loaded with errors."); - LogAction(0, -1, "[SRI] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SRI] Plugin continued to load, but that feature will not be used."); - g_bUseClientprefs = false; - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SRI] Client Preferences extension is loaded, checking database."); - if (!SQL_CheckConfig(clientprefs)) - { - LogAction(0, -1, "[SRI] No 'clientprefs' database found. Check your database.cfg file."); - LogAction(0, -1, "[SRI] Plugin continued to load, but Client Preferences will not be used."); - g_bUseClientprefs = false; - } - g_bUseClientprefs = true; - - /** - Deal with client cookies - */ - sri_cookie_enabled = RegClientCookie("bri_client_enabled", "Enable/Disable your immunity during the bonus round.", CookieAccess_Public); - sri_cookie_color = RegClientCookie("bri_client_color", "Color to render when immune.", CookieAccess_Public); - sri_cookie_mode = RegClientCookie("bri_client_mode", "God mode to select", CookieAccess_Public); - SetCookieMenuItem(CookieMenu_TopMenu, sri_cookie_enabled, "Bonus Round Immunity"); - } - - HookConVarChange(sri_enabled, EnabledChanged); - - RegAdminCmd("sm_immunity", Command_Immunity, ADMFLAG_ROOT, "sm_immunity: Gives you immunity"); - - LoadColors(); - - AutoExecConfig(true, "plugin.simpleroundimmunity"); -} - -public OnAllPluginsLoaded() -{ - //something - // need to deal with the unloading of dukehacks, clientprefs, and simpleplugins - // should move hooking the client prefs cookies to a function to make sure they are done post plugin start if ext is loaded late -} - -public OnLibraryRemoved(const String:name[]) -{ - //something - // need to deal with the loading of dukehacks, clientprefs, and simpleplugins -} - -public OnConfigsExecuted() -{ - GetConVarString(sri_charadminflag, g_sCharAdminFlag, sizeof(g_sCharAdminFlag)); - g_bIsEnabled = GetConVarBool(sri_enabled); - g_bRoundEnd = false; -} - -/** - Client events - */ - -public OnClientPostAdminCheck(client) -{ - if (SM_IsValidAdmin(client, g_sCharAdminFlag)) - g_aPlayers[client][bIsAdmin] = true; - else - g_aPlayers[client][bIsAdmin] = false; -} - -public OnClientCookiesCached(client) -{ - decl String:sEnabled[2], String:sColor[4], String:sMode[2]; - GetClientCookie(client, sri_cookie_enabled, sEnabled, sizeof(sEnabled)); - GetClientCookie(client, sri_cookie_color, sColor, sizeof(sColor)); - GetClientCookie(client, sri_cookie_mode, sMode, sizeof(sMode)); - g_aClientCookies[client][bEnabled] = StringToInt(sEnabled); - g_aClientCookies[client][iColor] = StringToInt(sColor); - g_aClientCookies[client][iMode] = StringToInt(sMode); -} - -public OnClientDisconnect(client) -{ - CleanUp(client); -} - -/** - Commands - */ - -public Action:Command_Immunity(client, args) -{ - if (g_aPlayers[client][IsImmune]) - { - DisableImmunity(client); - } - else - { - EnableImmunity(client); - } - return Plugin_Handled; -} - -/** - Event hooks - */ - -public Action:Hacks_TakeDamageHook(client, attacker, inflictor, Float:damage, &Float:multiplier, damagetype) -{ - if (attacker == 0 || attacker >= MaxClients) - { - return Plugin_Continue; - } - if (g_aPlayers[client][IsImmune]) - { - new TFClassType:PlayerClass = TF2_GetPlayerClass(attacker); - if (PlayerClass == TFClass_Spy) - { - multiplier *= 0.0; - return Plugin_Changed; - } - } - return Plugin_Continue; -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - g_bRoundEnd = false; - if (g_bIsEnabled) - { - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][IsImmune]) - { - DisableImmunity(i); - } - } - } -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - g_bRoundEnd = true; - if (g_bIsEnabled) - { - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][bIsAdmin]) - { - EnableImmunity(i); - } - } - } -} - -public HookPlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) -{ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - if (g_bIsEnabled && g_aPlayers[iClient][bIsAdmin] && g_bRoundEnd) - { - EnableImmunity(iClient); - } -} - -public Action:HookPlayerHurt(Handle:event, const String:name[], bool:dontBroadcast) -{ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - if (g_aPlayers[iClient][IsImmune]) - { - SetEntityHealth(iClient, 2000); - return Plugin_Continue; - } - return Plugin_Continue; -} - -/** - Cookie menus - */ - -public CookieMenu_TopMenu(client, CookieMenuAction:action, any:info, String:buffer[], maxlen) -{ - if (action == CookieMenuAction_DisplayOption) - { - //don't think we need to do anything - } - else - { - new Handle:hMenu = CreateMenu(Menu_CookieSettings); - SetMenuTitle(hMenu, "Options (Current Setting)"); - if (g_aClientCookies[client][bEnabled]) - { - AddMenuItem(hMenu, "enable", "Enabled/Disable (Enabled)"); - } - else - { - AddMenuItem(hMenu, "enable", "Enabled/Disable (Disabled)"); - } - if (g_aClientCookies[client][iMode]) - { - AddMenuItem(hMenu, "mode", "Immunity Mode Setting (God Mode)"); - } - else - { - AddMenuItem(hMenu, "mode", "Immunity Mode Setting (Health)"); - } - switch (g_aClientCookies[client][iColor]) - { - case COLOR_GREEN: - { - AddMenuItem(hMenu, "color", "Color (Green)"); - } - case COLOR_BLACK: - { - AddMenuItem(hMenu, "color", "Color (Black)"); - } - case COLOR_RED: - { - AddMenuItem(hMenu, "color", "Color (Red)"); - } - case COLOR_BLUE: - { - AddMenuItem(hMenu, "color", "Color (Blue)"); - } - case COLOR_TEAM: - { - AddMenuItem(hMenu, "color", "Color (Team)"); - } - case COLOR_RAINBOW: - { - AddMenuItem(hMenu, "color", "Color (Rainbow)"); - } - case COLOR_NONE: - { - AddMenuItem(hMenu, "color", "Color (None)"); - } - } - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, client, MENU_TIME_FOREVER); - } -} - -public Menu_CookieSettings(Handle:menu, MenuAction:action, param1, param2) -{ - new client = param1; - if (action == MenuAction_Select) - { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "enable", false)) - { - new Handle:hMenu = CreateMenu(Menu_CookieSettingsEnable); - SetMenuTitle(hMenu, "Enable/Disable Round End Immunity"); - - if (g_aClientCookies[client][bEnabled]) - { - AddMenuItem(hMenu, "enable", "Enable (Set)"); - AddMenuItem(hMenu, "disable", "Disable"); - } - else - { - AddMenuItem(hMenu, "enable", "Enabled"); - AddMenuItem(hMenu, "disable", "Disable (Set)"); - } - - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, client, MENU_TIME_FOREVER); - } - else if (StrEqual(sSelection, "mode", false)) - { - new Handle:hMenu = CreateMenu(Menu_CookieSettingsMode); - SetMenuTitle(hMenu, "Set Immunity Mode"); - - if (g_aClientCookies[client][iMode]) - { - AddMenuItem(hMenu, "god", "God Mode (Set)"); - AddMenuItem(hMenu, "health", "Health"); - } - else - { - AddMenuItem(hMenu, "god", "God Mode"); - AddMenuItem(hMenu, "health", "Health (Set)"); - } - - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, client, MENU_TIME_FOREVER); - } - else - { - new Handle:hMenu = CreateMenu(Menu_CookieSettingsColors); - SetMenuTitle(hMenu, "Select Immunity Color"); - switch (g_aClientCookies[client][iColor]) - { - case COLOR_GREEN: - { - AddMenuItem(hMenu, "Green", "Green (Set)"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_BLACK: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black (Set)"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_RED: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red (Set)"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_BLUE: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue (Set)"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_TEAM: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color (Set)"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_RAINBOW: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow (Set)"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_NONE: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None (Set)"); - } - } - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, client, MENU_TIME_FOREVER); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - ShowCookieMenu(client); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -public Menu_CookieSettingsEnable(Handle:menu, MenuAction:action, param1, param2) -{ - new client = param1; - if (action == MenuAction_Select) - { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "enable", false)) - { - SetClientCookie(client, sri_cookie_enabled, "1"); - g_aClientCookies[client][bEnabled] = 1; - PrintToChat(client, "[SM] Bonus Round Immunity is ENABLED"); - } - else - { - SetClientCookie(client, sri_cookie_enabled, "0"); - g_aClientCookies[client][bEnabled] = 0; - PrintToChat(client, "[SM] Bonus Round Immunity is DISABLED"); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - ShowCookieMenu(client); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -public Menu_CookieSettingsColors(Handle:menu, MenuAction:action, param1, param2) -{ - new client = param1; - if (action == MenuAction_Select) - { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "Green", false)) - { - SetClientCookie(client, sri_cookie_color, "0"); - g_aClientCookies[client][iColor] = COLOR_GREEN; - PrintToChat(client, "[SM] Bonus Round Immunity color set to GREEN"); - } - else if (StrEqual(sSelection, "Black", false)) - { - SetClientCookie(client, sri_cookie_color, "1"); - g_aClientCookies[client][iColor] = COLOR_BLACK; - PrintToChat(client, "[SM] Bonus Round Immunity color set to BLACK"); - } - else if (StrEqual(sSelection, "Red", false)) - { - SetClientCookie(client, sri_cookie_color, "2"); - g_aClientCookies[client][iColor] = COLOR_RED; - PrintToChat(client, "[SM] Bonus Round Immunity color set to RED"); - } - else if (StrEqual(sSelection, "Blue", false)) - { - SetClientCookie(client, sri_cookie_color, "3"); - g_aClientCookies[client][iColor] = COLOR_BLUE; - PrintToChat(client, "[SM] Bonus Round Immunity color set to BLUE"); - } - else if (StrEqual(sSelection, "Team", false)) - { - SetClientCookie(client, sri_cookie_color, "4"); - g_aClientCookies[client][iColor] = COLOR_TEAM; - PrintToChat(client, "[SM] Bonus Round Immunity color set to TEAM COLOR"); - } - else if (StrEqual(sSelection, "Rain", false)) - { - SetClientCookie(client, sri_cookie_color, "5"); - g_aClientCookies[client][iColor] = COLOR_RAINBOW; - PrintToChat(client, "[SM] Bonus Round Immunity color set to RAINBOW"); - } - else if (StrEqual(sSelection, "None", false)) - { - SetClientCookie(client, sri_cookie_color, "6"); - g_aClientCookies[client][iColor] = COLOR_NONE; - PrintToChat(client, "[SM] Bonus Round Immunity color set to NONE"); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - ShowCookieMenu(client); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -public Menu_CookieSettingsMode(Handle:menu, MenuAction:action, param1, param2) -{ - new client = param1; - if (action == MenuAction_Select) - { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "god", false)) - { - SetClientCookie(client, sri_cookie_mode, "1"); - g_aClientCookies[client][iMode] = 1; - PrintToChat(client, "[SM] Bonus Round Immunity set to GOD MODE"); - } - else - { - SetClientCookie(client, sri_cookie_mode, "0"); - g_aClientCookies[client][iMode] = 0; - PrintToChat(client, "[SM] Bonus Round Immunity set to HEALTH BONUS"); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - ShowCookieMenu(client); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -/** -Timer functions - */ - -public Action:Timer_ChangeColor(Handle:timer, any:client) -{ - if (g_aPlayers[client][CycleColor]++ == 3) - { - g_aPlayers[client][CycleColor] = 0; - } - SetEntityRenderMode(client, RENDER_TRANSCOLOR); - SetEntityRenderColor(client, g_iColors[g_aPlayers[client][CycleColor]][iRed], g_iColors[g_aPlayers[client][CycleColor]][iGreen], g_iColors[g_aPlayers[client][CycleColor]][iBlue], 255); - return Plugin_Continue; -} - -public Action:Timer_UndoGodMode(Handle:timer, any:client) -{ - if (IsClientInGame(client)) - { - SetEntProp(client, Prop_Data, "m_takedamage", 2, 1); - } - g_aPlayers[iClient][hGodModeTimer] = INVALID_HANDLE; - return Plugin_Handled; -} - -/** -Stock functions . - */ - -stock CleanUp(iClient) -{ - g_aPlayers[iClient][bIsAdmin] = false; - DisableImmunity(iClient); -} - -stock EnableImmunity(iClient) -{ - SetEntityRenderMode(iClient, RENDER_TRANSCOLOR); - switch (g_aClientCookies[iClient][iColor]) - { - case COLOR_TEAM: - { - new iTeam = GetClientTeam(iClient); - SetEntityRenderColor(iClient, g_iColors[e_ColorNames:iTeam][iRed], g_iColors[e_ColorNames:iTeam][iGreen], g_iColors[e_ColorNames:iTeam][iBlue], 255); - } - case COLOR_RAINBOW: - { - if (g_aPlayers[iClient][hColorTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hColorTimer]); - g_aPlayers[iClient][hColorTimer] = INVALID_HANDLE; - } - g_aPlayers[iClient][hColorTimer] = CreateTimer(0.2, Timer_ChangeColor, iClient, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); - } - case COLOR_NONE: - { - //We dont have to set a color - } - default: - { - SetEntityRenderColor(iClient, g_iColors[e_ColorNames:g_aClientCookies[iClient][iColor]][iRed], g_iColors[e_ColorNames:g_aClientCookies[iClient][iColor]][iGreen], g_iColors[e_ColorNames:g_aClientCookies[iClient][iColor]][iBlue], 255); - } - } - SetEntityHealth(iClient, 2000); - SetEntProp(iClient, Prop_Data, "m_takedamage", 0, 1); - g_aPlayers[iClient][hGodModeTimer] = CreateTimer(2.0, Timer_UndoGodMode, iClient); - g_aPlayers[iClient][IsImmune] = true; -} - -stock DisableImmunity(iClient) -{ - if (g_aPlayers[iClient][hGodModeTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hGodModeTimer]); - g_aPlayers[iClient][hGodModeTimer] = INVALID_HANDLE; - } - if (g_aPlayers[iClient][hColorTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hColorTimer]); - g_aPlayers[iClient][hColorTimer] = INVALID_HANDLE; - } - if (IsClientInGame(iClient)) - { - SetEntityRenderMode(iClient, RENDER_TRANSCOLOR); - SetEntityRenderColor(iClient, 255, 255, 255, 255); - new TFClassType:PlayerClass = TF2_GetPlayerClass(iClient); - new iMaxHealth = g_iClassMaxHealth[PlayerClass]; - SetEntityHealth(iClient, iMaxHealth); - } - g_aPlayers[iClient][CycleColor] = 0; - g_aPlayers[iClient][IsImmune] = false; -} - -stock LoadColors() -{ - g_iColors[Green][iRed] = 0; - g_iColors[Green][iGreen] = 255; - g_iColors[Green][iBlue] = 0; - - g_iColors[Black][iRed] = 10; - g_iColors[Black][iGreen] = 10; - g_iColors[Black][iBlue] = 0; - - g_iColors[Red][iRed] = 255; - g_iColors[Red][iGreen] = 0; - g_iColors[Red][iBlue] = 0; - - g_iColors[Blue][iRed] = 0; - g_iColors[Blue][iGreen] = 0; - g_iColors[Blue][iBlue] = 255; -} - -stock TF2_AddCond(client, cond) -{ - new Handle:cvar = FindConVar("sv_cheats"), bool:enabled = GetConVarBool(cvar), flags = GetConVarFlags(cvar); - if(!enabled) - { - SetConVarFlags(cvar, flags^FCVAR_NOTIFY); - SetConVarBool(cvar, true); - } - FakeClientCommand(client, "addcond %i", cond); - if(!enabled) - { - SetConVarBool(cvar, false); - SetConVarFlags(cvar, flags); - } -} - -stock TF2_RemoveCond(client, cond) -{ - new Handle:cvar = FindConVar("sv_cheats"), bool:enabled = GetConVarBool(cvar), flags = GetConVarFlags(cvar); - if(!enabled) - { - SetConVarFlags(cvar, flags^FCVAR_NOTIFY); - SetConVarBool(cvar, true); - } - FakeClientCommand(client, "removecond %i", cond); - if(!enabled) - { - SetConVarBool(cvar, false); - SetConVarFlags(cvar, flags); - } -} - -/** -Enabled hook - */ - -public EnabledChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (StringToInt(newValue) == 0) - { - UnhookEvent("player_spawn", HookPlayerSpawn, EventHookMode_Post); - UnhookEvent("teamplay_round_start", HookRoundStart, EventHookMode_Post); - UnhookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][bIsAdmin] && g_aPlayers[i][IsImmune]) - { - DisableImmunity(i); - } - } - g_bIsEnabled = false; - } - else - { - HookEvent("player_spawn", HookPlayerSpawn, EventHookMode_Post); - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_Post); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - g_bIsEnabled = true; - } -} diff --git a/Simple Donator Benefits/addons/sourcemod/scripting/simple-spectate.sp b/Simple Donator Benefits/addons/sourcemod/scripting/simple-spectate.sp deleted file mode 100644 index 4108f8f..0000000 --- a/Simple Donator Benefits/addons/sourcemod/scripting/simple-spectate.sp +++ /dev/null @@ -1,2022 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Spectate -Description: - Spectate a player and follow them through death. -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include -#undef REQUIRE_EXTENSIONS -#undef AUTOLOAD_EXTENSIONS -#tryinclude -#define AUTOLOAD_EXTENSIONS -#define REQUIRE_EXTENSIONS - -#define PLUGIN_VERSION "1.2.1.$Rev$" - -#define SPECMODE_NONE 0 -#define SPECMODE_FIRSTPERSON 4 -#define SPECMODE_3RDPERSON 5 -#define SPECMODE_FREELOOK 6 -#define SPECMODE_CSS_FIRSTPERSON 3 -#define SPECMODE_CSS_3RDPERSON 4 -#define SPECMODE_CSS_FREELOOK 5 - -enum e_CvarHandles -{ - Handle:hHudMode, - Handle:hMenuType, - Handle:hRestrictHud, - Handle:hBan, - Handle:hBanPerm, - Handle:hBeacon, - Handle:hBlind, - Handle:hCheater, - Handle:hDrug, - Handle:hFreeze, - Handle:hFreezeBomb, - Handle:hKick, - Handle:hSlap, - Handle:hSlay, - Handle:hTimeBomb -}; - -enum e_CvarSettings -{ - bool:bHudMode, - bool:bMenuType, - bool:bRestrictHud, - bool:bBan, - bool:bBanPerm, - bool:bBeacon, - bool:bBlind, - bool:bCheater, - bool:bDrug, - bool:bFreeze, - bool:bFreezebomb, - bool:bKick, - bool:bSlap, - bool:bSlay, - bool:bTimeBomb -}; - -enum e_PluginSettings -{ - bool:bUseSteamBans, - bool:bUseSourceBans, - bool:bUseMySQLBans, - bool:bCanHUD, - bool:bUseDukehacks -}; - -enum e_Menus -{ - Handle:hSelectPlayer, - Handle:hBanTime, - Handle:hReason -}; - -enum e_Punishments -{ - Punish_None, - Punish_Ban, - Punish_Beacon, - Punish_Blind, - Punish_Cheater, - Punish_Drug, - Punish_Freeze, - Punish_FreezeBomb, - Punish_Kick, - Punish_Slap, - Punish_Slay, - Punish_TimeBomb -}; - -enum e_PlayerData -{ - bool:bIsDisplayingHud, - bool:bIsFlaggedCheater, - Handle:hHudTimer, - Handle:hTargetTimer, - iTargetIndex, - e_Punishments:TargetPunishment, - iBanTime -}; - -new Handle:sm_spectate_adminflag = INVALID_HANDLE; -new Handle:g_hAdminMenu = INVALID_HANDLE; -new Handle:g_hHud = INVALID_HANDLE; -new Handle:g_aPluginCvar[e_CvarHandles]; -new g_aPluginCvarSettings[e_CvarSettings]; -new g_aPluginSettings[e_PluginSettings]; -new g_aMenus[e_Menus]; -new g_aPlayers[MAXPLAYERS + 1][e_PlayerData]; -new String:g_sAdminFlags[16]; -new String:g_sPunishments[e_Punishments][15] = { "None", "Ban", "Beacon", "Blind", "Cheater", "Drug", "Freeze", "FreezeBomb", "Kick", "Slap", "Slay", "TimeBomb" }; - -public Plugin:myinfo = -{ - name = "Simple Spectate", - author = "Simple Plugins", - description = "Spectate a player and follow them through death.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -/** -Sourcemod callbacks -*/ -public OnPluginStart() -{ - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[SSPEC] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Pre); - - /** - Need to create all of our console variables. - */ - CreateConVar("sm_spectate_version", PLUGIN_VERSION, "Sourcemod Spectate", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - g_aPluginCvar[hHudMode] = CreateConVar("sm_spectate_hudmode", "1", "Hud Mode: 0 = Hud Text | 1 = Panel/Menu (NOTE: The panel/menu will override other menus until canceled)"); - g_aPluginCvar[hMenuType] = CreateConVar("sm_spectate_menutype", "0", "Menu Mode: 0 = Panel | 1 = Menu"); - g_aPluginCvar[hRestrictHud] = CreateConVar("sm_spectate_restricthud", "0", "Restrict the hud to the admin flag provided"); - g_aPluginCvar[hBan] = CreateConVar("sm_spectate_ban", "1", "Enable/Disable ban option"); - g_aPluginCvar[hBanPerm] = CreateConVar("sm_spectate_banperm", "1", "Enable/Disable permanent ban option"); - g_aPluginCvar[hBeacon] = CreateConVar("sm_spectate_beacon", "1", "Enable/Disable beacon option"); - g_aPluginCvar[hBlind] = CreateConVar("sm_spectate_blind", "1", "Enable/Disable blind option"); - g_aPluginCvar[hCheater] = CreateConVar("sm_spectate_cheater", "1", "Enable/Disable cheater option"); - g_aPluginCvar[hDrug] = CreateConVar("sm_spectate_drug", "1", "Enable/Disable drug option"); - g_aPluginCvar[hFreeze] = CreateConVar("sm_spectate_freeze", "1", "Enable/Disable freeze option"); - g_aPluginCvar[hFreezeBomb] = CreateConVar("sm_spectate_freezebomb", "1", "Enable/Disable freezebomb option"); - g_aPluginCvar[hKick] = CreateConVar("sm_spectate_kick", "1", "Enable/Disable kick option"); - g_aPluginCvar[hSlap] = CreateConVar("sm_spectate_slap", "1", "Enable/Disable slap option"); - g_aPluginCvar[hSlay] = CreateConVar("sm_spectate_slay", "1", "Enable/Disable slay option"); - g_aPluginCvar[hTimeBomb] = CreateConVar("sm_spectate_timebomb", "1", "Enable/Disable timebomb option"); - - sm_spectate_adminflag = CreateConVar("sm_spectate_adminflag", "d", "Admin Flag to use for admin hud"); - - /** - Hook console variables - */ - new e_CvarHandles:iCvar; - for ( ; _:iCvar < sizeof(g_aPluginCvar); iCvar++) - { - HookConVarChange(g_aPluginCvar[iCvar], ConVarSettingsChanged); - } - - /** - Need to register the commands we are going to create and use. - */ - RegConsoleCmd("sm_spectate", Command_Spectate, "Spectate a player"); - RegConsoleCmd("sm_spec", Command_Spectate, "Spectate a player"); - RegConsoleCmd("sm_observe", Command_Spectate, "Spectate a player"); - RegConsoleCmd("sm_stopspec", Command_StopSpectate, "Stop Spectating a player"); - RegConsoleCmd("sm_endobserve", Command_StopSpectate, "Stop Spectating a player"); - RegConsoleCmd("sm_specinfo", Command_ToggleHud, "Toggles the hud display if in spectator"); - - /** - Now we have to deal with the admin menu. If the admin library is loaded call the function to add our items. - */ - new Handle:gTopMenu; - if (LibraryExists("adminmenu") && ((gTopMenu = GetAdminTopMenu()) != INVALID_HANDLE)) - { - OnAdminMenuReady(gTopMenu); - } - - /** - Deal with the hud - Thanks to Spray Trace plugin (http://forums.alliedmods.net/showthread.php?p=665448) - */ - new String:sHudGames[32]; - GetGameFolderName(sHudGames, sizeof(sHudGames)); - g_aPluginSettings[bCanHUD] = StrEqual(sHudGames,"tf",false) - || StrEqual(sHudGames,"hl2mp",false) - || StrEqual(sHudGames,"sourceforts",false) - || StrEqual(sHudGames,"obsidian",false) - || StrEqual(sHudGames,"left4dead",false) - || StrEqual(sHudGames,"l4d",false); - - if (g_aPluginSettings[bCanHUD]) - { - g_hHud = CreateHudSynchronizer(); - } - - /** - Load translations - */ - LoadTranslations ("common.phrases"); - LoadTranslations ("simplespectate.phrases"); - - /** - Create the config file - */ - AutoExecConfig(true); -} - -public OnConfigsExecuted() -{ - new e_CvarHandles:iCvar; - for ( ; _:iCvar < sizeof(g_aPluginCvarSettings); iCvar++) - { - g_aPluginCvarSettings[iCvar] = GetConVarBool(g_aPluginCvar[iCvar]); - } - - /* - Build the global menus - */ - g_aMenus[hSelectPlayer] = BuildSelectPlayerMenu(); - g_aMenus[hBanTime] = BuildBanTimeMenu(); - g_aMenus[hReason] = BuildReasonMenu(); - - GetConVarString(sm_spectate_adminflag, g_sAdminFlags, sizeof(g_sAdminFlags)); -} - -public OnAllPluginsLoaded() -{ - - /* - Check for steambans - */ - if (FindConVar("sbsrc_version") != INVALID_HANDLE) - { - g_aPluginSettings[bUseSteamBans] = true; - } - else - { - g_aPluginSettings[bUseSteamBans] = false; - } - - /* - Check for sourcebans - */ - if (FindConVar("sb_version") != INVALID_HANDLE) - { - g_aPluginSettings[bUseSourceBans] = true; - } - else - { - g_aPluginSettings[bUseSourceBans] = false; - } - - /* - Check for mysql bans - */ - if (FindConVar("mysql_bans_version") != INVALID_HANDLE) - { - g_aPluginSettings[bUseMySQLBans] = true; - } - else - { - g_aPluginSettings[bUseMySQLBans] = false; - } - - /* - Check for dukehacks - */ - new String:sExtError[256]; - new iExtStatus = GetExtensionFileStatus("dukehacks.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SSPEC] Dukehacks extension was not found."); - LogAction(0, -1, "[SSPEC] Plugin continued to load, but that feature will not be used."); - g_aPluginSettings[bUseDukehacks] = false; - } - else if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SSPEC] Dukehacks extension is loaded with errors."); - LogAction(0, -1, "[SSPEC] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SSPEC] Plugin continued to load, but that feature will not be used."); - g_aPluginSettings[bUseDukehacks] = false; - } - else if (iExtStatus == 1) - { - LogAction(0, -1, "[SSPEC] Dukehacks extension is loaded and will be used."); - g_aPluginSettings[bUseDukehacks] = true; - dhAddClientHook(CHK_TakeDamage, Hacks_TakeDamageHook); - } - - /* - Deal with some known plugin conflicts - */ - new Handle:hObserveClient = FindConVar("observe_version"); - if (hObserveClient != INVALID_HANDLE) - { - new String:sNewFile[PLATFORM_MAX_PATH + 1], String:sOldFile[PLATFORM_MAX_PATH + 1]; - BuildPath(Path_SM, sNewFile, sizeof(sNewFile), "plugins/disabled/observe.smx"); - BuildPath(Path_SM, sOldFile, sizeof(sOldFile), "plugins/observe.smx"); - - /** - Check if plugins/observe.smx exists, and if not, ignore - */ - if(!FileExists(sOldFile)) - { - return; - } - - /** - Check if plugins/disabled/observe.smx already exists, and if so, delete it - */ - if(FileExists(sNewFile)) - { - DeleteFile(sNewFile); - } - - /** - Unload plugins/observe.smx and move it to plugins/disabled/observe.smx - */ - LogAction(0, -1, "Detected the plugin ObserveClient"); - LogAction(0, -1, "ObserveClient plugin conflicts with Simple Spectate"); - LogAction(0, -1, "Unloading plugin and disabling ObserveClient plugin"); - ServerCommand("sm plugins unload observe"); - RenameFile(sNewFile, sOldFile); - } -} - -public OnLibraryRemoved(const String:name[]) -{ - if (StrEqual(name, "adminmenu")) - { - - /** - Looks like the admin menu was removed. Set the global. - */ - g_hAdminMenu = INVALID_HANDLE; - } - else if (StrEqual(name, "simpleplugins")) - { - //something - } -} - -public OnClientDisconnect(client) -{ - - /** - Cleanup the clients variables. - */ - ResetClient(client); - - /** - Run a loop and see if we are supposed to spectate this person (is a target) - */ - for(new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][iTargetIndex] == client) - { - - /** - Cleanup the clients variables. - */ - StopFollowingPlayer(i); - g_aPlayers[i][TargetPunishment] = Punish_None; - g_aPlayers[i][iBanTime] = 0; - } - } -} - -/** -Thirdparty callbacks -*/ -public SM_OnPlayerMoved(Handle:plugin, client, team) -{ - - /** - Make sure we called the move function - */ - if (plugin != GetMyHandle()) - { - return; - } - - //Nothing -} - -public Action:Hacks_TakeDamageHook(client, attacker, inflictor, Float:damage, &Float:multiplier, damagetype) -{ - - /** - Check for a valid client - */ - if (client > 0 && client <= MaxClients) - { - - /** - Check if the client taking damage is flagged as a cheater - */ - if (g_aPlayers[client][bIsFlaggedCheater]) - { - - /** - Check for fall damage and increase it - */ - if (damagetype & DMG_FALL) - { - multiplier *= 1000.0; - return Plugin_Changed; - } - } - } - - /** - Check for a valid attacker - */ - if (attacker > 0 && attacker <= MaxClients) - { - - /** - Check if the attacker causing the damage is flagged as a cheater - */ - if (g_aPlayers[attacker][bIsFlaggedCheater]) - { - - /** - Make sure they are not hurting themselves - */ - if (client != attacker) - { - - /** - Stop the damage - */ - multiplier *= 0.0; - return Plugin_Changed; - } - } - } - return Plugin_Continue; -} - -/** -Events -*/ -public Action:HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get the client and team - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - new iTeam = GetEventInt(event, "team"); - - /** - Make sure it's a valid client - */ - if (iClient == 0) - { - return Plugin_Continue; - } - - /** - If it's a move to spectator start displaying the hud - */ - else if ((iTeam == g_aCurrentTeams[Spectator]) && (GetUserFlagBits(iClient) & ADMFLAG_GENERIC)) - { - StartDisplayingHud(iClient); - - /** - If the event was going to be broadcasted, we refire it so it is not broadcasted and stop this one - */ - if (!dontBroadcast) - { - new Handle:hEvent = CreateEvent("player_team"); - SetEventInt(hEvent, "userid", GetEventInt(event, "userid")); - SetEventInt(hEvent, "team", GetEventInt(event, "team")); - SetEventInt(hEvent, "oldteam", GetEventInt(event, "oldteam")); - SetEventBool(hEvent, "disconnect", GetEventBool(event, "disconnect")); - - if (g_CurrentMod == GameType_DOD || g_CurrentMod == GameType_L4D || g_CurrentMod == GameType_TF) - { - new String:sClientName[MAX_NAME_LENGTH + 1]; - GetClientName(client, sClientName, sizeof(sClientName)); - SetEventBool(hEvent, "autoteam", GetEventBool(event, "autoteam")); - SetEventBool(hEvent, "silent", true); - SetEventString(hEvent, "name", sClientName); - FireEvent(hEvent, true); - } - else - { - FireEvent(hEvent, true); - } - return Plugin_Handled; - } - } - - /** - Otherwise cleanup the client - */ - else - { - StopDisplayingHud(iClient); - StopFollowingPlayer(iClient); - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -/** -Commands -*/ -public Action:Command_Spectate(client, args) -{ - - /** - See if we already have a target (for toggling of command) - */ - if (g_aPlayers[client][iTargetIndex]) - { - - /** - We do, toggle it off - */ - StopFollowingPlayer(client); - - /** - We are done, bug out. - */ - return Plugin_Handled; - } - - /** - We don't... must want to enable it - See if we have some command arguments. - */ - new iCmdArgs = GetCmdArgs(); - if (iCmdArgs == 0) - { - - /** - We don't have any. Display the player menu. - */ - if (g_aPlayers[client][bIsDisplayingHud]) - { - StopDisplayingHud(client); - } - - DisplayMenu(BuildPlayerListMenu(), client, MENU_TIME_FOREVER); - return Plugin_Handled; - } - - /** - We have an argument. - Try to find the target. - */ - new String:sPlayer[128]; - GetCmdArg(1, sPlayer, sizeof(sPlayer)); - new iTarget = FindTarget(client, sPlayer, true, true); - if (iTarget == -1 || !IsClientInGame(iTarget)) - { - - /** - We couldn't find the target. Display the player menu. - */ - if (g_aPlayers[client][bIsDisplayingHud]) - { - StopDisplayingHud(client); - } - - DisplayMenu(BuildPlayerListMenu(), client, MENU_TIME_FOREVER); - return Plugin_Handled; - } - - /** - We found the target. - Call the stock function to spectate the target. - */ - StartFollowingPlayer(client, iTarget); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_StopSpectate(client, args) -{ - - /** - Cleanup the clients variables. - */ - StopFollowingPlayer(client); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_ToggleHud(client, args) -{ - - /** - Toggle the hud - */ - if (g_aPlayers[client][bIsDisplayingHud]) - { - StopDisplayingHud(client); - } - else - { - StartDisplayingHud(client); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -/** -Timers -*/ -public Action:Timer_ResetTarget(Handle:timer, any:client) -{ - - new iTargetID = GetEntPropEnt(client, Prop_Send, "m_hObserverTarget"); - - if (iTargetID != g_aPlayers[client][iTargetIndex] && IsPlayerAlive(g_aPlayers[client][iTargetIndex])) - { - - /** - Run the command to spectate the target from the clients prospectative. - */ - FakeClientCommandEx(client, "spec_player \"%N\"", g_aPlayers[client][iTargetIndex]); - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Timer_UpdateHud(Handle:timer, any:client) -{ - - /** - Make sure the client is still in game and a spectator - */ - if (!IsClientConnected(client) || !IsClientInGame(client) || GetClientTeam(client) != g_aCurrentTeams[Spectator] || !g_aPlayers[client][bIsDisplayingHud]) - { - - /** - We are done, bug out - */ - g_aPlayers[client][hHudTimer] = INVALID_HANDLE; - g_aPlayers[client][bIsDisplayingHud] = false; - return Plugin_Stop; - } - /** - Get the target - */ - new iTarget = GetEntPropEnt(client, Prop_Send, "m_hObserverTarget"); - - /** - Check to make sure the target is valid - */ - if (iTarget <= 0 || iTarget > MaxClients) - { - return Plugin_Continue; - } - - /** - Get the spectator mode - */ - new iSpecMode = GetEntProp(client, Prop_Send, "m_iObserverMode"); - - /** - This is a double check to make sure we are in spec - If we are on a regular team, specmod would = none or zero - */ - if (iSpecMode == SPECMODE_NONE) - { - - /** - We are done, bug out - */ - g_aPlayers[client][hHudTimer] = INVALID_HANDLE; - g_aPlayers[client][bIsDisplayingHud] = false; - return Plugin_Stop; - } - - /** - Check the spectator mode - CSS has different index's so we have to check game type first - */ - if (g_CurrentMod == GameType_CSS) - { - switch (iSpecMode) - { - case SPECMODE_CSS_FIRSTPERSON: - { - //Do Nothing - } - case SPECMODE_CSS_3RDPERSON: - { - //Do Nothing - } - case SPECMODE_CSS_FREELOOK: - { - return Plugin_Continue; - } - } - } - else - { - switch (iSpecMode) - { - case SPECMODE_FIRSTPERSON: - { - //Do Nothing - } - case SPECMODE_3RDPERSON: - { - //Do Nothing - } - case SPECMODE_FREELOOK: - { - return Plugin_Continue; - } - } - } - - - /** - Display with the hud - */ - if (g_aPluginSettings[bCanHUD] && !g_aPluginCvarSettings[bHudMode]) - { - new String:sSteamID[64]; - GetClientAuthString(iTarget, sSteamID, sizeof(sSteamID)); - SetHudTextParams(0.04, 0.6, 0.5, 255, 50, 50, 255); - ShowSyncHudText(client, g_hHud, "%N [%s]", iTarget, sSteamID); - } - else if (g_aPluginCvarSettings[bHudMode]) - { - if (g_aPluginCvarSettings[bMenuType]) - { - DisplayMenu(BuildPlayerHudMenu(client, iTarget), client, 1); - } - else - { - new Handle:hPanel = BuildPlayerHudPanel(client, iTarget); - SendPanelToClient(hPanel, client, Panel_PlayerHud, 1); - CloseHandle(hPanel); - } - } - - /** - We are done, keep going! - */ - return Plugin_Continue; -} - -/** -Admin Menu Callbacks -*/ -public OnAdminMenuReady(Handle:topmenu) -{ - if (topmenu == g_hAdminMenu) - { - return; - } - g_hAdminMenu = topmenu; - new TopMenuObject:player_commands = FindTopMenuCategory(g_hAdminMenu, ADMINMENU_PLAYERCOMMANDS); - if (player_commands == INVALID_TOPMENUOBJECT) - { - return; - } - AddToTopMenu(g_hAdminMenu, - "sm_spectate", - TopMenuObject_Item, - AdminMenu_SpecPlayer, - player_commands, - "sm_spectate", - ADMFLAG_GENERIC); -} - -public AdminMenu_SpecPlayer(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) -{ - if (action == TopMenuAction_DisplayOption) - { - - if (g_aPlayers[param][bIsDisplayingHud]) - { - StopDisplayingHud(param); - } - /** - See if we already have a target - */ - if (g_aPlayers[param][iTargetIndex]) - { - Format(buffer, maxlength, "Spectate(Disable)"); - } - else - { - Format(buffer, maxlength, "Spectate(Select Player)"); - } - } - else if (action == TopMenuAction_SelectOption) - { - - /** - See if we already have a target - */ - if (g_aPlayers[param][iTargetIndex]) - { - - /** - We do, toggle it off - */ - StopFollowingPlayer(param); - - /** - We are done, bug out. - */ - return; - } - else - { - DisplayMenu(BuildPlayerListMenu(), param, MENU_TIME_FOREVER); - } - } -} - -/** -Select Player Menu Callbacks -*/ -public Menu_PlayerList(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - /** - Get the selected player - */ - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - new iTarget = GetClientOfUserId(StringToInt(sSelection)); - - /** - Start following the player - */ - StartFollowingPlayer(param1, iTarget); - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_GENERIC) - { - - /** - Display the last admin menu - */ - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } - else if (param2 == MenuCancel_Exit && GetClientTeam(param1) == g_aCurrentTeams[Spectator]) - { - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_End) - { - - /** - Not a global menu, close it - */ - CloseHandle(menu); - } -} - -public Menu_SelectPlayer(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - - /** - Get the selected player - */ - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (strcmp(sSelection, "Current", false) == 0) - { - /** - Get the current target - */ - new iTarget = GetEntPropEnt(param1, Prop_Send, "m_hObserverTarget"); - - /** - Check to make sure the target is valid - */ - if (iTarget <= 0 || iTarget > MaxClients) - { - PrintToChat(param1, "\x03[SM-SPEC]\x01 %t", "Invalid Target"); - DisplayMenu(BuildPlayerListMenu(), param1, MENU_TIME_FOREVER); - } - - /** - Start following the player - */ - StartFollowingPlayer(param1, iTarget); - } - else - { - - /** - They want to select a player, show the player list - */ - DisplayMenu(BuildPlayerListMenu(), param1, MENU_TIME_FOREVER); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_End) - { - /** - Its a global menu, leave it alive - */ - } -} - -/** -Punishment Menu Callbacks -*/ -public Menu_Punishments(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - - /** - Get the menu selection - */ - new String:sSelection[15]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - - /** - Search for the correct index - */ - new e_Punishments:Index = Punish_None; - for ( ; _:Index <= sizeof(g_sPunishments); Index++) - { - if (StrEqual(sSelection, g_sPunishments[Index])) - { - break; - } - } - - /** - Display the next menu - */ - if (Index == Punish_Ban) - { - - /** - Set the punishment index and display ban time menu - */ - g_aPlayers[param1][TargetPunishment] = Index; - DisplayMenu(g_aMenus[hBanTime], param1, MENU_TIME_FOREVER); - } - else if (Index == Punish_Cheater) - { - - /** - Ask for confirmation before we set punishment index - */ - new Handle:hPanel = BuildAdminCheaterPanel(); - SendPanelToClient(hPanel, param1, Panel_AdminCheater, MENU_TIME_FOREVER); - CloseHandle(hPanel); - } - else - { - - /** - Set the punishment index and display reason menu - */ - g_aPlayers[param1][TargetPunishment] = Index; - DisplayMenu(g_aMenus[hReason], param1, MENU_TIME_FOREVER); - } - } - else if (action == MenuAction_Cancel) - { - - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - else if (action == MenuAction_End) - { - - /** - Not a global menu, close it - */ - CloseHandle(menu); - } -} - -public Menu_BanTime(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - - /** - Get the menu selection - */ - new String:sSelection[15]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - - /** - Set the ban time global - */ - g_aPlayers[param1][iBanTime] = StringToInt(sSelection); - - /** - Display the reason menu - */ - DisplayMenu(g_aMenus[hReason], param1, MENU_TIME_FOREVER); - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_End) - { - /** - Its a global menu, leave it alive - */ - } -} - -public Menu_Reason(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - - /** - Get the menu selection - */ - new String:sSelection[15]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - - /** - Perform the punishment - */ - PerformPunishment(param1, g_aPlayers[param1][iTargetIndex], g_aPlayers[param1][TargetPunishment], sSelection, g_aPlayers[param1][iBanTime]); - - /** - Reactivate the hud if still in spectator - */ - if (GetClientTeam(param1) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_End) - { - /** - Its a global menu, leave it alive - */ - } -} - -public Panel_AdminCheater(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - if (param2 == 1) - { - - /** - Set the punishment index and display reason menu - */ - g_aPlayers[param1][TargetPunishment] = Punish_Cheater; - DisplayMenu(g_aMenus[hReason], param1, MENU_TIME_FOREVER); - } - else - { - - /** - Reactivate the hud if still in spectator - */ - if (GetClientTeam(param1) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(param1); - } - } - } -} - -public Panel_PublicCheater(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - if (param2 == 1) - { - //Waiting for SB 2.0 and sb_submission to be published - } - else - { - - /** - Reactivate the hud if still in spectator - */ - if (GetClientTeam(param1) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(param1); - } - } - } -} - -/** -Hud Menu/Panel Callbacks -*/ -public Menu_PlayerHud(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "stop", false)) - { - StopFollowingPlayer(param1); - } - else if (StrEqual(sSelection, "start", false)) - { - StopDisplayingHud(param1); - DisplayMenu(g_aMenus[hSelectPlayer], param1, MENU_TIME_FOREVER); - } - else if (StrEqual(sSelection, "removecheater", false)) - { - g_aPlayers[g_aPlayers[param1][iTargetIndex]][bIsFlaggedCheater] = false; - } - else if (StrEqual(sSelection, "punish", false)) - { - if (g_aPlayers[param1][iTargetIndex]) - { - StopDisplayingHud(param1); - DisplayMenu(BuildPunishmentMenu(param1), param1, MENU_TIME_FOREVER); - } - else - { - StopDisplayingHud(param1); - PrintToChat(param1, "\x03[SM-SPEC]\x01 %t", "Must Have Target"); - DisplayMenu(g_aMenus[hSelectPlayer], param1, MENU_TIME_FOREVER); - } - } - else if (StrEqual(sSelection, "reportcheater", false)) - { - if (g_aPlayers[param1][iTargetIndex]) - { - StopDisplayingHud(param1); - new Handle:hPanel = BuildPublicCheaterPanel(); - SendPanelToClient(hPanel, param1, Panel_PublicCheater, MENU_TIME_FOREVER); - CloseHandle(hPanel); - } - else - { - StopDisplayingHud(param1); - PrintToChat(param1, "\x03[SM-SPEC]\x01 %t", "Must Have Target"); - DisplayMenu(g_aMenus[hSelectPlayer], param1, MENU_TIME_FOREVER); - } - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_Interrupted) - { - if (GetClientMenu(param1) == MenuSource_External) - { - StopDisplayingHud(param1); - } - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -public Panel_PlayerHud(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - switch (param2) - { - case 1: - { - if (g_aPlayers[param1][iTargetIndex]) - { - StopFollowingPlayer(param1); - } - else - { - StopDisplayingHud(param1); - DisplayMenu(BuildSelectPlayerMenu(), param1, MENU_TIME_FOREVER); - } - } - case 2: - { - if (!g_aPlayers[param1][iTargetIndex]) - { - StopDisplayingHud(param1); - PrintToChat(param1, "\x03[SM-SPEC]\x01 %t", "Must Have Target"); - DisplayMenu(g_aMenus[hSelectPlayer], param1, MENU_TIME_FOREVER); - return; - } - - if ((GetUserFlagBits(param1) & ADMFLAG_GENERIC) || (GetUserFlagBits(param1) & ADMFLAG_ROOT)) - { - if (g_aPlayers[g_aPlayers[param1][iTargetIndex]][bIsFlaggedCheater] && (GetUserFlagBits(param1) & ADMFLAG_ROOT)) - { - //Remove cheater flag - g_aPlayers[g_aPlayers[param1][iTargetIndex]][bIsFlaggedCheater] = false; - } - else - { - //Punish menu - StopDisplayingHud(param1); - DisplayMenu(BuildPunishmentMenu(param1), param1, MENU_TIME_FOREVER); - } - } - else - { - //Report Cheater - new Handle:hPanel = BuildPublicCheaterPanel(); - SendPanelToClient(hPanel, param1, Panel_PublicCheater, MENU_TIME_FOREVER); - CloseHandle(hPanel); - } - } - case 3: - { - StopDisplayingHud(param1); - } - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_Interrupted) - { - if (GetClientMenu(param1) == MenuSource_External) - { - StopDisplayingHud(param1); - } - } - } -} - - -/** -Stock functions -*/ -stock StartFollowingPlayer(client, target) -{ - - /** - If we have an open timer, close it. - */ - if (g_aPlayers[client][hTargetTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[client][hTargetTimer]); - g_aPlayers[client][hTargetTimer] = INVALID_HANDLE; - } - - /** - Make sure the target is on a non spectator team, and the client != target - */ - if (client == target) - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Yourself"); - return; - } - new iTargetTeam = GetClientTeam(target); - if (iTargetTeam == g_aCurrentTeams[Spectator] || iTargetTeam == g_aCurrentTeams[Unknown]) - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Spectator"); - return; - } - - /** - Check to see if client is already a spectator - */ - if (GetClientTeam(client) != g_aCurrentTeams[Spectator]) - { - - /** - Client is not a spectator, lets move them to spec. - */ - SM_MovePlayer(client, g_aCurrentTeams[Spectator]); - } - - /** - If we are using steambans call sb_status - */ - if (g_aPluginSettings[bUseSteamBans]) - { - FakeClientCommandEx(client, "sb_status"); - } - - - /** - Set the global and start to spectate the target. - Making sure it's long enough to deal with moving the client to spec if we had to. - */ - new String:sTargetName[MAX_NAME_LENGTH + 1]; - GetClientName(target, sTargetName, sizeof(sTargetName)); - g_aPlayers[client][iTargetIndex] = target; - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Spectating", sTargetName); - g_aPlayers[client][hTargetTimer] = CreateTimer(0.5, Timer_ResetTarget, client, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); - if (!g_aPlayers[client][bIsDisplayingHud] && GetClientTeam(client) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(client); - } -} - -stock StopFollowingPlayer(client) -{ - - /** - If we have an open timer, close it. - */ - if (g_aPlayers[client][hTargetTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[client][hTargetTimer]); - } - - /** - Tell the client we can't spec his target anymore... if they are in game. - */ - if (IsClientInGame(client) && g_aPlayers[client][iTargetIndex] != 0) - { - new String:sTargetName[MAX_NAME_LENGTH + 1]; - GetClientName(g_aPlayers[client][iTargetIndex], sTargetName, sizeof(sTargetName)); - if (!IsClientConnected(g_aPlayers[client][iTargetIndex]) || !IsClientInGame(g_aPlayers[client][iTargetIndex])) - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Target Left"); - } - else - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Stopped spectating", sTargetName); - } - } - - /** - Null the globals. - */ - g_aPlayers[client][iTargetIndex] = 0; - g_aPlayers[client][hTargetTimer] = INVALID_HANDLE; -} - -stock StartDisplayingHud(client) -{ - if (g_aPluginCvarSettings[bRestrictHud] && !SM_IsValidAdmin(client, g_sAdminFlags)) - { - return; - } - else - { - /** - Double check the hud timer - We should not have one, but if we do, lets cancel it for the current callback - */ - StopDisplayingHud(client); - - /** - Now we can safely display the hud and make sure the current stored handle is the current timer - */ - g_aPlayers[client][bIsDisplayingHud] = true; - g_aPlayers[client][hHudTimer] = CreateTimer(0.5, Timer_UpdateHud, client, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); - } -} - -stock StopDisplayingHud(client) -{ - if (g_aPlayers[client][hHudTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[client][hHudTimer]); - } - g_aPlayers[client][hHudTimer] = INVALID_HANDLE; - g_aPlayers[client][bIsDisplayingHud] = false; -} - -stock ResetClient(client) -{ - StopFollowingPlayer(client); - StopDisplayingHud(client); - - g_aPlayers[client][bIsFlaggedCheater] = false; - g_aPlayers[client][TargetPunishment] = Punish_None; - g_aPlayers[client][iBanTime] = -1; -} - -stock PerformPunishment(client, target, e_Punishments:punishment, const String:reason[], time = 300) -{ - new String:sTargetName[MAX_NAME_LENGTH + 1], - String:sTargetID[64]; - - /** - The target could have left the game by the time we get here - Check for a valid target - */ - if (!IsClientConnected(target) || !IsClientInGame(target)) - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Target Left"); - return; - } - - GetClientName(target, sTargetName, sizeof(sTargetName)); - GetClientAuthString(target, sTargetID, sizeof(sTargetID)); - - switch (punishment) - { - case Punish_Kick: - { - KickClient(g_aPlayers[client][iTargetIndex], "%s", reason); - } - case Punish_Ban: - { - if (g_aPluginSettings[bUseSourceBans]) - { - ClientCommand(client, "sm_ban #%d %d \"%s\"", GetClientUserId(target), time, reason); - } - else if (g_aPluginSettings[bUseMySQLBans]) - { - ClientCommand(client, "mysql_ban #%d %d \"%s\"", GetClientUserId(target), time, reason); - } - else - { - BanClient(target, time, BANFLAG_AUTHID, reason, reason); - } - } - case Punish_Cheater: - { - g_aPlayers[target][bIsFlaggedCheater] = true; - } - case Punish_Beacon: - { - ClientCommand(client, "sm_beacon \"%s\"", sTargetName); - } - case Punish_Blind: - { - ClientCommand(client, "sm_blind \"%s\"", sTargetName); - } - case Punish_Drug: - { - ClientCommand(client, "sm_drug \"%s\"", sTargetName); - } - case Punish_Freeze: - { - ClientCommand(client, "sm_freeze \"%s\"", sTargetName); - } - case Punish_FreezeBomb: - { - ClientCommand(client, "sm_freezebomb \"%s\"", sTargetName); - } - case Punish_Slap: - { - ClientCommand(client, "sm_slap \"%s\" 10", sTargetName); - } - case Punish_Slay: - { - ClientCommand(client, "sm_slay \"%s\"", sTargetName); - } - case Punish_TimeBomb: - { - ClientCommand(client, "sm_timebomb \"%s\"", sTargetName); - } - } - - if (punishment == Punish_Cheater) - { - LogAction(client, target, "[SM SPEC] %N marked %N(%s) with a %s flag for %s", client, target, sTargetID, g_sPunishments[punishment], reason); - } - else - { - ShowActivity(client, "%t", "Punished", sTargetName, g_sPunishments[punishment], reason); - LogAction(client, target, "[SM SPEC] %N punished %N(%s) with a %s for %s", client, target, sTargetID, g_sPunishments[punishment], reason); - } - - /** - Null the globals. - */ - g_aPlayers[client][TargetPunishment] = Punish_None; - g_aPlayers[client][iBanTime] = -1; -} - -/** -Build the menu of player names -*/ -stock Handle:BuildPlayerListMenu() -{ - new Handle:hMenu = CreateMenu(Menu_PlayerList); - AddTargetsToMenu(hMenu, 0, true, false); - SetMenuTitle(hMenu, "Select A Player:"); - SetMenuExitBackButton(hMenu, true); - return hMenu; -} - -/** -Build the select player menu (current or list of players) -*/ -stock Handle:BuildSelectPlayerMenu() -{ - new Handle:hMenu = CreateMenu(Menu_SelectPlayer); - SetMenuTitle(hMenu, "Select A Player:"); - AddMenuItem(hMenu, "Current", "Current Target"); - AddMenuItem(hMenu, "List", "Player List"); - SetMenuExitBackButton(hMenu, true); - return hMenu; -} - -/** -Build the punishmenu menu -*/ -stock Handle:BuildPunishmentMenu(iClient) -{ - new Handle:hMenu = CreateMenu(Menu_Punishments); - SetMenuTitle(hMenu, "Select A Punishment:"); - SetMenuExitBackButton(hMenu, true); - SetMenuExitButton(hMenu, true); - - if (g_aPluginCvarSettings[bKick] && ((GetUserFlagBits(iClient) & ADMFLAG_GENERIC) || (GetUserFlagBits(iClient) & ADMFLAG_ROOT))) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Kick], "Kick"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Kick], "Kick", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bBan] && ((GetUserFlagBits(iClient) & ADMFLAG_GENERIC) || (GetUserFlagBits(iClient) & ADMFLAG_ROOT))) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Ban], "Ban"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Ban], "Ban", ITEMDRAW_DISABLED); - } - - if (g_aPluginSettings[bUseDukehacks] && g_aPluginCvarSettings[bCheater] && (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Cheater], "Flag As Cheater"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Cheater], "Flag As Cheater", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bBeacon]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Beacon], "Beacon"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Beacon], "Beacon", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bBlind]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Blind], "Blind"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Blind], "Blind", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bDrug]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Drug], "Drug"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Drug], "Drug", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bFreeze]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Freeze], "Freeze"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Freeze], "Freeze", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bFreezebomb]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_FreezeBomb], "Freeze Bomb"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_FreezeBomb], "Freeze Bomb", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bSlap]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Slap], "Slap"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Slap], "Slap", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bSlay]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Slay], "Slay"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Slay], "Slay", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bTimeBomb]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_TimeBomb], "Time Bomb"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_TimeBomb], "Time Bomb", ITEMDRAW_DISABLED); - } - - return hMenu; -} - -/** -Build the punishmenu menu -*/ -stock Handle:BuildBanTimeMenu() -{ - new Handle:hMenu = CreateMenu(Menu_BanTime); - SetMenuTitle(hMenu, "Select Ban Type:"); - - if (g_aPluginCvarSettings[bBanPerm]) - { - AddMenuItem(hMenu, "permban", "Permanent"); - } - else - { - AddMenuItem(hMenu, "permban", "Permanent", ITEMDRAW_DISABLED); - } - - AddMenuItem(hMenu, "10", "10 Minutes"); - AddMenuItem(hMenu, "30", "30 Minutes"); - AddMenuItem(hMenu, "60", "1 Hour"); - AddMenuItem(hMenu, "240", "4 Hours"); - AddMenuItem(hMenu, "1440", "1 Day"); - AddMenuItem(hMenu, "10080", "1 Week"); - - SetMenuExitBackButton(hMenu, true); - return hMenu; -} - -/** -Build the punishmenu menu -*/ -stock Handle:BuildReasonMenu() -{ - new Handle:hMenu = CreateMenu(Menu_Reason); - SetMenuTitle(hMenu, "Select A Reason:"); - - AddMenuItem(hMenu, "Abusive", "Abusive"); - AddMenuItem(hMenu, "Racism", "Racism"); - AddMenuItem(hMenu, "General cheating/exploits", "General cheating/exploits"); - AddMenuItem(hMenu, "Wallhack", "Wallhack"); - AddMenuItem(hMenu, "Aimbot", "Aimbot"); - AddMenuItem(hMenu, "Speedhacking", "Speedhacking"); - AddMenuItem(hMenu, "Mic spamming", "Mic spamming"); - AddMenuItem(hMenu, "Admin disrepect", "Admin disrepect"); - AddMenuItem(hMenu, "Camping", "Camping"); - AddMenuItem(hMenu, "Team killing", "Team killing"); - AddMenuItem(hMenu, "Unacceptable Spray", "Unacceptable Spray"); - AddMenuItem(hMenu, "Breaking Server Rules", "Breaking Server Rules"); - AddMenuItem(hMenu, "Other", "Other"); - - SetMenuExitBackButton(hMenu, true); - return hMenu; -} - -/** -Build the cheater displays -*/ -stock Handle:BuildAdminCheaterPanel() -{ - - /** - Create the menu and set the menu options. - */ - new Handle:hPanel = CreatePanel(); - SetPanelTitle(hPanel, "Simple Spectator:"); - - DrawPanelText(hPanel, "Are you sure you want to"); - DrawPanelText(hPanel, "flag this player as a cheater?"); - DrawPanelText(hPanel, "They will not be able to damage"); - DrawPanelText(hPanel, "anyone and die on fall damage."); - DrawPanelItem(hPanel, "Yes"); - DrawPanelItem(hPanel, "No"); - - return hPanel; -} - -stock Handle:BuildPublicCheaterPanel() -{ - - /** - Create the menu and set the menu options. - */ - new Handle:hPanel = CreatePanel(); - SetPanelTitle(hPanel, "Simple Spectator:"); - - DrawPanelText(hPanel, "Are you sure you want to"); - DrawPanelText(hPanel, "submit this player as a cheater?"); - DrawPanelItem(hPanel, "Yes (Not Implemented Yet)", ITEMDRAW_DISABLED); - DrawPanelItem(hPanel, "No"); - return hPanel; -} - -/** -Build the hud displays -*/ -stock Handle:BuildPlayerHudMenu(iClient, iTarget) -{ - - /** - Create all the string variables we will need - */ - new String:sTargetName[MAX_NAME_LENGTH + 1], - String:sTargetID[64], - String:sTargetIP[16]; - - new String:sDisplayName[MAX_NAME_LENGTH + 1], - String:sDisplayID[64], - String:sDisplayIP[64], - String:sDisplayFrags[16], - String:sDisplayDeaths[16]; - - new iTargetFrags, - iTargetDeaths; - - /** - Get the targets information - */ - GetClientName(iTarget, sTargetName, sizeof(sTargetName)); - GetClientIP(iTarget, sTargetIP, sizeof(sTargetIP)); - GetClientAuthString(iTarget, sTargetID, sizeof(sTargetID)); - iTargetFrags = GetClientFrags(iTarget); - iTargetDeaths = GetClientDeaths(iTarget); - - /** - Format the strings for the menu - */ - Format(sDisplayName, sizeof(sDisplayName), "Player: %s", sTargetName); - Format(sDisplayID, sizeof(sDisplayID), "Steam ID: %s", sTargetID); - Format(sDisplayIP, sizeof(sDisplayIP), "IP Address: %s", sTargetIP); - Format(sDisplayFrags, sizeof(sDisplayFrags), "Kills: %i", iTargetFrags); - Format(sDisplayDeaths, sizeof(sDisplayDeaths), "Deaths: %i", iTargetDeaths); - - /** - Create the menu and set the menu options. - */ - new Handle:hMenu = CreateMenu(Menu_PlayerHud); - SetMenuExitBackButton(hMenu, false); - SetMenuTitle(hMenu, "Simple Spectator"); - - AddMenuItem(hMenu, "name", sDisplayName, ITEMDRAW_DISABLED); - AddMenuItem(hMenu, "steamid", sDisplayID, ITEMDRAW_DISABLED); - - if (SM_IsValidAdmin(iClient, g_sAdminFlags)) - { - AddMenuItem(hMenu, "ip", sDisplayIP, ITEMDRAW_DISABLED); - } - - AddMenuItem(hMenu, "kills", sDisplayFrags, ITEMDRAW_DISABLED); - AddMenuItem(hMenu, "deaths", sDisplayDeaths, ITEMDRAW_DISABLED); - - if (g_aPlayers[iClient][iTargetIndex]) - { - AddMenuItem(hMenu, "stop", "Stop Following"); - } - else - { - AddMenuItem(hMenu, "start", "Follow Player"); - } - - if ((GetUserFlagBits(iClient) & ADMFLAG_GENERIC) || (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - if (g_aPlayers[iTarget][bIsFlaggedCheater] && (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - AddMenuItem(hMenu, "removecheater", "Remove Cheater Flag"); - } - else - { - if (CanUserTarget(iClient, iTarget)) - { - AddMenuItem(hMenu, "punish", "Punish Player"); - } - else - { - AddMenuItem(hMenu, "punish", "Punish Player (Immune)", ITEMDRAW_DISABLED); - } - } - } - else - { - AddMenuItem(hMenu, "reportcheater", "Report Cheater"); - } - - SetMenuPagination(hMenu, MENU_NO_PAGINATION); - SetMenuExitButton(hMenu, true); - return hMenu; -} - -stock Handle:BuildPlayerHudPanel(iClient, iTarget) -{ - - /** - Create all the string variables we will need - */ - new String:sTargetName[MAX_NAME_LENGTH + 1], - String:sTargetID[64], - String:sTargetIP[16]; - - new String:sDisplayName[MAX_NAME_LENGTH + 1], - String:sDisplayID[64], - String:sDisplayIP[64], - String:sDisplayFrags[16], - String:sDisplayDeaths[16]; - - new iTargetFrags, - iTargetDeaths; - - /** - Get the targets information - */ - GetClientName(iTarget, sTargetName, sizeof(sTargetName)); - GetClientIP(iTarget, sTargetIP, sizeof(sTargetIP)); - GetClientAuthString(iTarget, sTargetID, sizeof(sTargetID)); - iTargetFrags = GetClientFrags(iTarget); - iTargetDeaths = GetClientDeaths(iTarget); - - /** - Format the strings for the menu - */ - Format(sDisplayName, sizeof(sDisplayName), "Player: %s", sTargetName); - Format(sDisplayID, sizeof(sDisplayID), "Steam ID: %s", sTargetID); - Format(sDisplayIP, sizeof(sDisplayIP), "IP Address: %s", sTargetIP); - Format(sDisplayFrags, sizeof(sDisplayFrags), "Kills: %i", iTargetFrags); - Format(sDisplayDeaths, sizeof(sDisplayDeaths), "Deaths: %i", iTargetDeaths); - - /** - Create the menu and set the menu options. - */ - new Handle:hPanel = CreatePanel(); - SetPanelTitle(hPanel, "Simple Spectator"); - - DrawPanelText(hPanel, "Player Information:"); - DrawPanelText(hPanel, sDisplayName); - DrawPanelText(hPanel, sDisplayID); - if (SM_IsValidAdmin(iClient, g_sAdminFlags)) - { - DrawPanelText(hPanel, sDisplayIP); - } - - DrawPanelText(hPanel, sDisplayFrags); - DrawPanelText(hPanel, sDisplayDeaths); - - if (g_aPlayers[iClient][iTargetIndex]) - { - DrawPanelItem(hPanel, "Stop Following"); - } - else - { - DrawPanelItem(hPanel, "Follow Player"); - } - - if ((GetUserFlagBits(iClient) & ADMFLAG_GENERIC) || (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - if (g_aPlayers[iTarget][bIsFlaggedCheater] && (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - DrawPanelItem(hPanel, "Remove Cheater Flag"); - } - else - { - if (CanUserTarget(iClient, iTarget)) - { - DrawPanelItem(hPanel, "Punish Player"); - } - else - { - DrawPanelItem(hPanel, "Punish Player (Immune)", ITEMDRAW_DISABLED); - } - } - } - else - { - DrawPanelItem(hPanel, "Report Cheater"); - } - - DrawPanelItem(hPanel, "Close Hud Panel"); - return hPanel; -} - -/** -Adjust the settings if a convar was changed -*/ -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - for (new iCvar = 0 ; _:iCvar < sizeof(g_aPluginCvarSettings); iCvar++) - { - if (g_aPluginCvar[_:iCvar] == convar) - { - if (StringToInt(newValue) == 1) - { - g_aPluginCvarSettings[_:iCvar] = true; - } - else - { - g_aPluginCvarSettings[_:iCvar] = false; - } - } - } - - /* - ReBuild the global menu that depends on cvars - */ - g_aMenus[hBanTime] = BuildBanTimeMenu(); - - /** - Run a loop to reset the hud - */ - for(new i = 1; i <= MaxClients; i++) - { - StopDisplayingHud(i); - if (IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(i); - } - } -} diff --git a/Simple Donator Benefits/addons/sourcemod/scripting/simple-teambalancer.sp b/Simple Donator Benefits/addons/sourcemod/scripting/simple-teambalancer.sp deleted file mode 100644 index 3302255..0000000 --- a/Simple Donator Benefits/addons/sourcemod/scripting/simple-teambalancer.sp +++ /dev/null @@ -1,1797 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Team Balancer -Description: - Balances teams based upon player count - Player will not be balanced more than once in 5 (default) mins - Buddy system tries to keep buddies together - Ability to prioritize players - Ability to force players to accept the new team - Admins are immune -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include -#include - -#define PLUGIN_VERSION "2.1.$Rev$" - -enum PlayerData -{ - Handle:hBalanceTimer, - Handle:hForcedTimer, - bool:bSwitched, - bool:bFlagCarrier -}; - -/** - Global convar handles - */ -new Handle:stb_enabled = INVALID_HANDLE; -new Handle:stb_buddyenabled = INVALID_HANDLE; -new Handle:stb_logactivity = INVALID_HANDLE; -new Handle:stb_logactivity2 = INVALID_HANDLE; -new Handle:stb_unbalancelimit = INVALID_HANDLE; -new Handle:stb_deadonly = INVALID_HANDLE; -new Handle:stb_priorityenabled = INVALID_HANDLE; -new Handle:stb_uberlevel = INVALID_HANDLE; -new Handle:stb_balancedelay = INVALID_HANDLE; -new Handle:stb_livingplayerswitchdelay = INVALID_HANDLE; -new Handle:stb_livingplayercheckdelay = INVALID_HANDLE; -new Handle:stb_roundstartdelay = INVALID_HANDLE; -new Handle:stb_switchbackforced = INVALID_HANDLE; -new Handle:stb_adminflag = INVALID_HANDLE; -new Handle:stb_buddyrestriction = INVALID_HANDLE; -new Handle:stb_convarcontrol = INVALID_HANDLE; - -/** - Built-in cvars handles - */ -new Handle:stb_mp_autoteambalance = INVALID_HANDLE; -new Handle:stb_mp_teams_unbalance_limit = INVALID_HANDLE; -new Handle:TFGameModeArena = INVALID_HANDLE; - -/** - Timer handles - */ -new Handle:g_hBalanceTimer = INVALID_HANDLE; -new Handle:g_hLivingPlayerCheckTimer = INVALID_HANDLE; - -/** - Player arrays - */ -new g_aPlayers[MAXPLAYERS + 1][PlayerData]; - -/** -Global bools -*/ -new bool:g_bIsEnabled = true; -new bool:g_bPriorityPlayers = true; -new bool:g_bBuddyRestriction = false; -new bool:g_bLogActivity = false; -new bool:g_bLogActivity2 = false; -new bool:g_bDeadOnly = false; -new bool:g_bConVarControl = true; -new bool:g_bBuddyEnabled = true; -new bool:g_bBalanceInProgress = false; -new bool:g_bRoundStart = false; -new bool:g_bRoundEnd = false; -new bool:g_bSuddenDeath = false; -new bool:g_bIsArenaMode = false; - -/** - Global strings/integers/floats - */ -new g_iUnbalanceLimit, g_iLivingPlayerSwitchDelay, g_iLivingPlayerCheckDelay; -new g_iRoundStartDelay, g_iSwitchBackForced, g_iBalanceDelay; -new Float:g_fUberLevel; -new g_iOwnerOffset; -new String:g_sAdminFlag[5]; - -public Plugin:myinfo = -{ - name = "Simple Team Balancer", - author = "Simple Plugins", - description = "Balances teams based upon player count.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -} - -public OnPluginStart() -{ - - /** - Create console variables - */ - CreateConVar("stb_version", PLUGIN_VERSION, "Simple Team Balancer", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - stb_enabled = CreateConVar("stb_enabled", "1", "Enable or Disable Simple Team Balancer", _, true, 0.0, true, 1.0); - stb_priorityenabled = CreateConVar("stb_priorityenabled", "1", "Enable or Disable the prioritization of living players", _, true, 0.0, true, 1.0); - stb_buddyrestriction = CreateConVar("stb_buddyrestriction", "0", "Enable or Disable Admin Only buddy lists", _, true, 0.0, true, 1.0); - stb_logactivity = CreateConVar("stb_logactivity", "0", "Enable or Disable the disaplying of events in the log", _, true, 0.0, true, 1.0); - stb_logactivity2 = CreateConVar("stb_logactivity2", "0", "Enable or Disable the disaplying of detailed events in the log (WILL SPAM LOG)", _, true, 0.0, true, 1.0); - stb_deadonly = CreateConVar("stb_deadonly", "0", "Enable or Disable the switching of only dead players", _, true, 0.0, true, 1.0); - stb_convarcontrol = CreateConVar("stb_convarcontrol", "1", "Enable or Disable the control of builtin console variables", _, true, 0.0, true, 1.0); - stb_buddyenabled = CreateConVar("stb_buddyenabled", "1", "Enable or Disable the buddy system", _, true, 0.0, true, 1.0); - stb_unbalancelimit = CreateConVar("stb_unbalancelimit", "2", "Amount of players teams are ALLOWED to be unbalanced by", _, true, 1.0, true, 32.0); - stb_balancedelay = CreateConVar("stb_balancedelay", "10", "Delay in seconds to start an autobalance"); - stb_livingplayerswitchdelay = CreateConVar("stb_livingplayerswitchdelay", "20", "Delay in seconds to switch living players once selected"); - stb_livingplayercheckdelay = CreateConVar("stb_livingplayercheckdelay", "10", "Delay in seconds to start checking living players once teams become unbalanced"); - stb_roundstartdelay = CreateConVar("stb_roundstartdelay", "15", "Delay in seconds to start balancing teams after the start of a round"); - stb_switchbackforced = CreateConVar("stb_switchbackforced", "300", "Amount of time in seconds to not switch a player twice and force the team if enabled"); - stb_uberlevel = CreateConVar("stb_uberlevel", "1.0", "Min uber level medic must have to have priority over other living players. Setting to 0 will rarely switch a living medic", _, true, 0.0, true, 1.0); - stb_adminflag = CreateConVar("stb_adminflag", "a", "Admin flag to use for immunity. Must be a in char format."); - stb_mp_autoteambalance = FindConVar("mp_autoteambalance"); - stb_mp_teams_unbalance_limit = FindConVar("mp_teams_unbalance_limit"); - - /** - Removing the notify tags from the built in cvars. We dont want spam. - */ - if (stb_mp_autoteambalance != INVALID_HANDLE) - { - SetConVarFlags(stb_mp_autoteambalance, GetConVarFlags(stb_mp_autoteambalance)^FCVAR_NOTIFY); - } - if (stb_mp_teams_unbalance_limit != INVALID_HANDLE) - { - SetConVarFlags(stb_mp_teams_unbalance_limit, GetConVarFlags(stb_mp_teams_unbalance_limit)^FCVAR_NOTIFY); - } - - /** - Hook console variables - */ - HookConVarChange(stb_enabled, ConVarSettingsChanged); - HookConVarChange(stb_priorityenabled, ConVarSettingsChanged); - HookConVarChange(stb_buddyrestriction, ConVarSettingsChanged); - HookConVarChange(stb_logactivity, ConVarSettingsChanged); - HookConVarChange(stb_logactivity2, ConVarSettingsChanged); - HookConVarChange(stb_deadonly, ConVarSettingsChanged); - HookConVarChange(stb_convarcontrol, ConVarSettingsChanged); - HookConVarChange(stb_buddyenabled, ConVarSettingsChanged); - HookConVarChange(stb_unbalancelimit, ConVarSettingsChanged); - HookConVarChange(stb_balancedelay, ConVarSettingsChanged); - HookConVarChange(stb_livingplayerswitchdelay, ConVarSettingsChanged); - HookConVarChange(stb_livingplayercheckdelay, ConVarSettingsChanged); - HookConVarChange(stb_roundstartdelay, ConVarSettingsChanged); - HookConVarChange(stb_switchbackforced, ConVarSettingsChanged); - HookConVarChange(stb_uberlevel, ConVarSettingsChanged); - HookConVarChange(stb_mp_autoteambalance, ConVarSettingsChanged); - HookConVarChange(stb_mp_teams_unbalance_limit, ConVarSettingsChanged); - - /** - Create console commands - */ - RegConsoleCmd("sm_buddy", Command_AddBalanceBuddy, "Add a balance buddy"); - RegConsoleCmd("sm_lockbuddy", Command_LockBuddy, "Locks your balance buddy selection"); - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[STB] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_death", HookPlayerDeath, EventHookMode_Post); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Post); - switch (g_CurrentMod) - { - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - HookEvent("teamplay_suddendeath_begin", HookSuddenDeathBegin, EventHookMode_PostNoCopy); - HookEvent("teamplay_flag_event", HookFlagEvent, EventHookMode_Post); - TFGameModeArena = FindConVar("tf_gamemode_arena"); - g_iOwnerOffset = FindSendPropInfo("CBaseObject", "m_hBuilder"); - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_Post); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - - /** - Load translations and .cfg file - */ - LoadTranslations ("simpleteambalancer.phrases"); - AutoExecConfig(true, "plugin.simpleteambalancer"); - LogAction(0, -1, "[STB] Simple Team Balancer is loaded."); -} - -public OnAllPluginsLoaded() -{ - //something -} - -public OnLibraryRemoved(const String:name[]) -{ - //something -} - -public OnConfigsExecuted() -{ - - /** - Load up global variables - */ - g_bIsEnabled = GetConVarBool(stb_enabled); - g_bBuddyEnabled = GetConVarBool(stb_buddyenabled); - g_bLogActivity = GetConVarBool(stb_logactivity); - g_bLogActivity2 = GetConVarBool(stb_logactivity2); - g_bDeadOnly = GetConVarBool(stb_deadonly); - g_bPriorityPlayers = GetConVarBool(stb_priorityenabled); - g_bBuddyRestriction = GetConVarBool(stb_buddyrestriction); - g_bConVarControl = GetConVarBool(stb_convarcontrol); - g_fUberLevel = GetConVarFloat(stb_uberlevel); - g_iUnbalanceLimit = GetConVarInt(stb_unbalancelimit); - g_iBalanceDelay = GetConVarInt(stb_balancedelay); - g_iLivingPlayerSwitchDelay = GetConVarInt(stb_livingplayerswitchdelay); - g_iLivingPlayerCheckDelay = GetConVarInt(stb_livingplayercheckdelay); - g_iRoundStartDelay = GetConVarInt(stb_roundstartdelay); - g_iSwitchBackForced = GetConVarInt(stb_switchbackforced); - GetConVarString(stb_adminflag, g_sAdminFlag, sizeof(g_sAdminFlag)); - - /** - Report enabled - */ - if (g_bIsEnabled) - { - LogAction(0, -1, "[STB] Simple Team Balancer is ENABLED."); - } - else - { - LogAction(0, -1, "[STB] Simple Team Balancer is DISABLED."); - } - - - /** - Report log activity - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Log Activity ENABLED."); - } - else - { - LogAction(0, -1, "[STB] Log Activity DISABLED."); - } - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Detailed Log Activity ENABLED."); - } - else - { - LogAction(0, -1, "[STB] Detailed Log Activity DISABLED."); - } -} - -public OnMapStart() -{ - - /** - Check for arena mode - */ - if (g_CurrentMod == GameType_TF && GetConVarBool(TFGameModeArena)) - { - g_bIsArenaMode = true; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Simple Team Balancer detected arena mode and will be bypassed"); - } - } - else - { - g_bIsArenaMode = false; - } - - /** - Reset the globals - */ - g_bBalanceInProgress = false; - g_bRoundStart = false; - g_bRoundEnd = false; - g_bSuddenDeath = false; - - /** - Set the built-in convars - */ - SetGameCvars(); -} - -public OnClientPostAdminCheck(client) -{ - - /** - Make sure its a valid connected client and buddy system is enabled - */ - if (client == 0 || !g_bIsEnabled || !IsClientConnected(client) || !g_bBuddyEnabled) - { - return; - } - - /** - Make sure if its set for admins only they have the flags - */ - if (g_bBuddyRestriction && !SM_IsValidAdmin(client, g_sAdminFlag)) - { - return; - } - - /** - Start the advertisement timer - */ - CreateTimer (60.0, Timer_WelcomeAdvert, client); -} - -public OnClientDisconnect(client) -{ - - /** - Call stock function to cleaup - */ - CleanUp(client); -} - -public OnClientDisconnect_Post(client) -{ - - /** - Determine if we need a balance - */ - if (OkToBalance() && IsUnbalanced() && !g_bBalanceInProgress) - { - - /** - No balance in progress but balance is needed - */ - StartABalance(); - } -} - -public SM_OnPlayerMoved(Handle:plugin, client, team) -{ - - /** - Make sure we called the move function - */ - if (plugin != GetMyHandle()) - { - if (g_bLogActivity2) - { - LogAction(0, client, "[STB] Callback was not started with current plugin, bugging out."); - } - return; - } - - /** - Get the players name and report the event - */ - decl String:sPlayerName[64]; - GetClientName(client, sPlayerName, sizeof(sPlayerName)); - if (g_bLogActivity) - { - LogAction(0, client, "[STB] Changed %s to team %i.", sPlayerName, team); - } - - /** - If we are in TF2 fire the bult-in team balance event - */ - if(g_CurrentMod == GameType_TF) - { - new Handle:event = CreateEvent("teamplay_teambalanced_player"); - SetEventInt(event, "player", client); - SetEventInt(event, "team", team); - FireEvent(event); - } - - /** - Notify the players - */ - PrintToChatAll("[SM] %T", "BalanceMessage", LANG_SERVER, sPlayerName); - - /** - Set the players variables and start a timer - */ - g_aPlayers[client][bSwitched] = true; - g_aPlayers[client][hForcedTimer] = CreateTimer(float(g_iSwitchBackForced), Timer_ForcedExpired, client, TIMER_FLAG_NO_MAPCHANGE); - - /** - We are done, log the completion and end the balance - */ - if (g_bLogActivity) - { - LogAction(0, client, "[STB] Balance finished."); - } - g_bBalanceInProgress = false; -} - -/* HOOKED EVENTS */ - -public HookPlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get our event variables - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - decl String:sWeapon[64]; - GetEventString(event, "weapon", sWeapon, sizeof(sWeapon)); - - /** - Return if death was not caused by a player - This is the case when the player switches teams - */ - if (StrEqual(sWeapon, "world", false)) - { - return; - } - - - /** - Check if balance is needed - */ - if (IsClientInGame(iClient) && OkToBalance() && IsUnbalanced()) - { - new iSmallerTeam = GetSmallerTeam(); - - /** - Check if balance is in progress - */ - if (g_bBalanceInProgress) - { - - /** - There is a balance in progress - Check the player who died to see if he is supposed to be switched - */ - if (g_aPlayers[iClient][hBalanceTimer] != INVALID_HANDLE) - { - - /** - The player has a timer on him to switch him to other team - Stop the timer - */ - CloseHandle(g_aPlayers[iClient][hBalanceTimer]); - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] With a balance in progress the queued living player died and was switched."); - } - - /** - Call the stock change team function - */ - BalancePlayer(iClient, SM_GetForcedTeam(iClient)); - return; - } - - /** - Before we continue, lets make sure the client is switchable - */ - if (IsSwitchablePlayer(iClient, GetBiggerTeam())) - { - - /** - Now we check the buddy system - */ - if (g_bBuddyEnabled) - { - - /** - Buddy system is enabled, check to see if client has buddy - */ - new iBuddyIndex = SM_GetClientBuddy(iClient); - if (iBuddyIndex != 0 || !IsClientConnected(iBuddyIndex) || !IsClientInGame(iBuddyIndex)) - { - - /** - The client has a buddy, so we check to see if they are on same team - */ - if (GetClientTeam(iClient) == GetClientTeam(iBuddyIndex)) - { - - /** - They are, but we don't bug out, we still need to start a balance - */ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] With a balance in progress a buddy on the right team was found and skipped."); - } - } - else - { - - /** - They are not on the same team - The buddy could be in spec, and that would make it not matter where he is, or the buddy is on the smaller team - */ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] With a balance in progress a buddy on the wrong team was switched."); - } - BalancePlayer(iClient, iSmallerTeam); - return; - } - } - else - { - - /** - Client doesn't have a buddy, balance this player - */ - BalancePlayer(iClient, iSmallerTeam); - return; - } - } - else - { - - /** - Buddy system is not enabled, balance this player - */ - BalancePlayer(iClient, iSmallerTeam); - return; - } - } - } - else - { - - /** - If we get to here then we must need to start a balance - */ - StartABalance(); - } - } -} - -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get our event variables. - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - new iTeam = GetEventInt(event, "team"); - - /** - Make sure its ok to balance. - */ - if (OkToBalance()) - { - - /** - See if the client that changed teams was set to with a balance. - */ - if (g_aPlayers[iClient][hBalanceTimer] != INVALID_HANDLE - && SM_GetForcedTeam(iClient) == iTeam - && g_bBalanceInProgress) - { - - /** - The client was set to be balanced, so we close the timer. - */ - CloseHandle(g_aPlayers[iClient][hBalanceTimer]); - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - - /** - Stop the balance. - */ - g_bBalanceInProgress = false; - return; - } - - /** - It's not likely that this team change can cause us to need a balance. - If it does, start one with a small dealy to deal with forced switch backs. - */ - if (IsUnbalanced() && !g_bBalanceInProgress) - { - CreateTimer(2.0, Timer_ChangeTeamBalanceDelay, _, TIMER_FLAG_NO_MAPCHANGE); - } - } -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set the variables we need to start a round - */ - g_bRoundStart = true; - g_bRoundEnd = false; - g_bSuddenDeath = false; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Round Started"); - } - - /** - Start a delayed balance check at the start of the round - */ - CreateTimer(float(g_iRoundStartDelay), Timer_RoundStart); -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set the variables we need at round end - */ - g_bRoundEnd = true; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Round Ended"); - } -} - -public HookSuddenDeathBegin(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set the variables we need for sudden death - */ - g_bSuddenDeath = true; -} - -public HookFlagEvent(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get our event variables - */ - new iClient = GetEventInt(event, "player"); - new iFlagStatus = GetEventInt(event, "eventtype"); - - /** - Make sure we have a valid client - */ - if (!IsClientInGame(iClient)) - { - return; - } - - /** - Determine what kind of event this is - */ - switch (iFlagStatus) - { - case 1: - { - - /** - The flag was picked up - */ - g_aPlayers[iClient][bFlagCarrier] = true; - } - case 2: - { - - /** - The flag was capped - */ - g_aPlayers[iClient][bFlagCarrier] = false; - } - case 3: - { - - /** - The flag was defended, we don't have to do anything - */ - } - case 4: - { - - /** - The flag was dropped - */ - g_aPlayers[iClient][bFlagCarrier] = false; - } - } -} - -/* COMMAND EVENTS */ - -public Action:Command_AddBalanceBuddy(client, args) -{ - if (client == 0) - { - ReplyToCommand(client, "[SM] %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - if (!g_bIsEnabled || !g_bBuddyEnabled) - { - ReplyToCommand(client, "[SM] %T", "CmdDisabled", LANG_SERVER); - return Plugin_Handled; - } - if (g_bBuddyRestriction) - { - if (!SM_IsValidAdmin(client, g_sAdminFlag)) - { - ReplyToCommand(client, "[SM] %T", "RestrictedBuddy", LANG_SERVER); - return Plugin_Handled; - } - } - decl String:sPlayerUserId[24]; - GetCmdArg(1, sPlayerUserId, sizeof(sPlayerUserId)); - new iPlayer = GetClientOfUserId(StringToInt(sPlayerUserId)); - if (!iPlayer || !IsClientInGame(iPlayer) || client == iPlayer) - { - if (client == iPlayer) - { - PrintHintText(client, "%T", "SelectSelf", LANG_SERVER); - } - ReplyToCommand(client, "[SM] Usage: buddy "); - new Handle:playermenu = BuildPlayerMenu(); - DisplayMenu(playermenu, client, MENU_TIME_FOREVER); - } - else - { - decl String:cName[128]; - decl String:bName[128]; - GetClientName(client, cName, sizeof(cName)); - GetClientName(iPlayer, bName, sizeof(bName)); - if (SM_IsBuddyLocked(iPlayer)) - { - ReplyToCommand(client, "[SM] %T", "PlayerLockedBuddyMsg", LANG_SERVER, bName); - return Plugin_Handled; - } - SM_AssignBuddy(client, iPlayer); - PrintHintText(client, "%T", "BuddyMsg", LANG_SERVER, bName); - PrintHintText(iPlayer, "%T", "BuddyMsg", LANG_SERVER, cName); - } - return Plugin_Handled; -} - -public Action:Command_LockBuddy(client, args) -{ - if (client == 0) - { - ReplyToCommand(client, "[SM] %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - if (!g_bIsEnabled) - { - ReplyToCommand(client, "[SM] %T", "CmdDisabled", LANG_SERVER); - return Plugin_Handled; - } - if (g_bBuddyRestriction) - { - if (!SM_IsValidAdmin(client, g_sAdminFlag)) - { - ReplyToCommand(client, "[SM] %T", "RestrictedBuddy", LANG_SERVER); - return Plugin_Handled; - } - } - if (SM_IsBuddyLocked(client)) - { - SM_LockBuddy(client, false); - PrintHintText(client, "%T", "BuddyLockMsgDisabled", LANG_SERVER); - } - else - { - SM_LockBuddy(client, true); - PrintHintText(client, "%T", "BuddyLockMsgEnabled", LANG_SERVER); - } - return Plugin_Handled; -} - -/** -Stock functions . - */ - -stock bool:IsUnbalanced() -{ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Checking if teams are unbalanced"); - } - new Team1Count = GetTeamClientCount(g_aCurrentTeams[Team1]); - new Team2Count = GetTeamClientCount(g_aCurrentTeams[Team2]); - new ubCount = RoundFloat(FloatAbs(float(Team1Count - Team2Count))); - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Team1:%i Team2:%i Difference:%i", Team1Count, Team2Count, ubCount); - } - if (ubCount > g_iUnbalanceLimit) - { - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Teams are unbalanced"); - } - return true; - } - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Teams are not unbalanced"); - } - return false; -} - -stock bool:OkToBalance() -{ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Checking if OK to balance."); - } - new bool:bResult = false; - if (g_bIsEnabled && !g_bRoundStart && !g_bRoundEnd && !g_bIsArenaMode && !g_bSuddenDeath) - { - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Passed IF statement"); - LogAction(0, -1, "[STB] Now checking admins"); - } - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientInGame(i) && !SM_IsValidAdmin(i, g_sAdminFlag)) - { - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Found at least 1 non-admin"); - LogAction(0, -1, "[STB] OK to balance"); - } - bResult = true; - break; - } - } - if (!bResult && g_bLogActivity2) - { - LogAction(0, -1, "[STB] All admins online"); - } - } - if (!bResult && g_bLogActivity2) - { - LogAction(0, -1, "[STB] Not OK to balance"); - } - return bResult; -} - -stock bool:IsSwitchablePlayer(iClient, iBiggerTeam) -{ - - /** - Run the client thru some standard checks - */ - if (!IsClientInGame(iClient) - || SM_IsValidAdmin(iClient, g_sAdminFlag) - || g_aPlayers[iClient][bFlagCarrier] - || GetClientTeam(iClient) != iBiggerTeam - || g_aPlayers[iClient][bSwitched]) - { - - /** - The supplied client can't be switched - */ - return false; - } - - /** - The supplied client can be switched - */ - return true; -} - -stock bool:HasUber(iClient) -{ - - /** - First things first, make sure the client is a medic - */ - if(TF2_GetPlayerClass(iClient) == TFClass_Medic) - { - - /** - We can only check the active weapon, so make sure the client is holding the uber gun - */ - decl String:sWeaponName[32]; - GetClientWeapon(iClient, sWeaponName, sizeof(sWeaponName)); - if(StrEqual(sWeaponName, "tf_weapon_medigun")) - { - - /** - They are, so lets check the uber level of the gun - */ - new iEntityIndex = GetEntDataEnt2(iClient, FindSendPropInfo("CTFPlayer", "m_hActiveWeapon")); - new Float:fChargeLevel = GetEntDataFloat(iEntityIndex, FindSendPropInfo("CWeaponMedigun", "m_flChargeLevel")); - if (fChargeLevel >= g_fUberLevel) - { - - /** - The client supplied has an uber above the supplied level, return true - */ - if (g_bLogActivity2) - { - LogAction(0, iClient, "[STB] Found a medic with a uber and skipped him."); - } - return true; - } - } - } - - /** - The client supplied does not have an uber above the supplied level, return false - */ - return false; -} - -stock bool:HasBuildingsBuilt(iClient) -{ - - /** - We have to start a loop to check the owner of all the valid entities - */ - new iMaxEntities = GetMaxEntities(); - for (new i = MaxClients + 1; i <= iMaxEntities; i++) - { - if (!IsValidEntity(i)) - { - - /** - Not valid, continue to next one - */ - continue; - } - - /** - Get the name of the current entity - */ - decl String:sNetClass[32]; - GetEntityNetClass(i, sNetClass, sizeof(sNetClass)); - - /** - See if its something that an engineer would build - */ - if (strcmp(sNetClass, "CObjectSentrygun") == 0 - || strcmp(sNetClass, "CObjectTeleporter") == 0 - || strcmp(sNetClass, "CObjectDispenser") == 0) - { - - /** - It is, so lets check the owner - */ - if (GetEntDataEnt2(i, g_iOwnerOffset) == iClient) - { - - /** - The client supplied is the owner, return true - */ - if (g_bLogActivity2) - { - LogAction(0, iClient, "[STB] Found an engineer with buildings and skipped him."); - } - return true; - } - } - } - - /** - The client supplied didn't have any buildings, return false - */ - return false; -} - -stock StartABalance() -{ - - /** - See if we are already started a balance - */ - if (g_hBalanceTimer != INVALID_HANDLE) - { - - /** - We have, check if we still need to - */ - if (!IsUnbalanced() || !OkToBalance()) - { - - /** - We don't, stop the balance - It's almost impossible to reach this code, but we do it just in case - */ - CloseHandle(g_hBalanceTimer); - g_hBalanceTimer = INVALID_HANDLE; - g_bBalanceInProgress = false; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Balance delay timer was not needed and was killed before the callback."); - } - return; - } - else - { - - /** - We still need to balance - Bug out and wait for the current one to finish - */ - return; - } - } - - /** - Report that teams are unbalanced - */ - PrintToChatAll("[SM] %T", "UnBalanced", LANG_SERVER); - - /** - Check to see if we are supposed to delay the balance - */ - if (g_iBalanceDelay == 0) - { - - /** - Start the balance now - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Balance is now in progress."); - } - g_bBalanceInProgress = true; - g_hBalanceTimer = INVALID_HANDLE; - - /** - Check if we are allowed to scan living players - */ - if (!g_bDeadOnly) - { - - /** - We are allowed to, so we start a timer - */ - StartALivingPlayerTimer(); - - /** - Also report that we are now scanning dead players as well - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Now scanning dead players."); - } - } - else - { - - /** - We are not allowed to, so report that we are only scanning dead players - */ - if (g_bLogActivity) - LogAction(0, -1, "[STB] Only scanning dead players."); - } - - /** - We started the balance, bug out - */ - return; - } - - /** - We are supposed to delay the balance, start a balance timer - */ - g_hBalanceTimer = CreateTimer(float(g_iBalanceDelay), Timer_BalanceTeams, _, TIMER_FLAG_NO_MAPCHANGE); - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Teams are unbalanced. Balance delay timer started."); - } -} - -stock StartALivingPlayerTimer() -{ - - /** - Start a timer to check living players - */ - if (g_hLivingPlayerCheckTimer != INVALID_HANDLE) - { - - /** - If we for some reason already have one started, stop it. - */ - CloseHandle(g_hLivingPlayerCheckTimer); - g_hLivingPlayerCheckTimer = INVALID_HANDLE; - } - - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Living player balance delay timer started."); - } - g_hLivingPlayerCheckTimer = CreateTimer(float(g_iLivingPlayerCheckDelay), Timer_LivingPlayerCheck, _, TIMER_FLAG_NO_MAPCHANGE); -} - -stock FindSwitchablePlayer() -{ - - /** - Start a loop to find a switchable player - */ - new iPlayer; - new iBiggerTeam = GetBiggerTeam(); - for (new i = 1; i <= MaxClients; i++) - { - - /** - Check the stock function to see if we are allows to even switch the player - */ - if (!IsSwitchablePlayer(i, iBiggerTeam)) - { - continue; - } - - /** - If the mod is TF2 and they have Priority Players set check if the client has buildings or an uber - */ - if (g_CurrentMod == GameType_TF && g_bPriorityPlayers) - { - if (HasUber(i) || HasBuildingsBuilt(i)) - { - continue; - } - } - - /** - So far we are able we switch this player - Now we check the buddy system - */ - if (g_bBuddyEnabled) - { - - /** - Buddy system is enabled, check to see if client has buddy - */ - if (SM_GetClientBuddy(i) != 0) - { - - /** - The client has a buddy, so we check to see if they are on same team - */ - if (GetClientTeam(i) == GetClientTeam(SM_GetClientBuddy(i))) - { - - /** - They are, so we continue to next client - */ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] With a balance in progress a buddy on the right team was found and skipped."); - } - continue; - } - else - { - - /** - They are not on the same team, set this client - The buddy could be in spec, and that would make it not matter where he is, or the buddy is on the smaller team - */ - iPlayer = i; - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] With a balance in progress a buddy on the wrong team was found."); - } - break; - } - } - else - { - - /** - The client does not have a buddy, set this client - */ - iPlayer = i; - break; - } - } - else - { - - /** - Buddy system is not enabled, set this client - */ - iPlayer = i; - break; - } - } - - /** - Return the client we set, this could be 0, but very unlikely - */ - return iPlayer; -} - -stock BalancePlayer(iClient, iTeam) -{ - new Handle:hPack = CreateDataPack(); - WritePackCell(hPack, iClient); - WritePackCell(hPack, iTeam); - CreateTimer(0.1, Timer_BalancePlayer, hPack, TIMER_FLAG_NO_MAPCHANGE); -} - -stock CleanUp(iClient) -{ - g_aPlayers[iClient][bFlagCarrier] = false; - g_aPlayers[iClient][bSwitched] = false; - if (g_aPlayers[iClient][hForcedTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hForcedTimer]); - g_aPlayers[iClient][hForcedTimer] = INVALID_HANDLE; - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] Forced player disconnected, killing timer."); - } - } - if (g_aPlayers[iClient][hBalanceTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hBalanceTimer]); - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] Living player set to be balanced disconnected, killing timer."); - } - } -} - -stock GetSmallerTeam() -{ - - /** - Get the count of players on each team - */ - new iCountT1 = GetTeamClientCount(g_aCurrentTeams[Team1]); - new iCountT2 = GetTeamClientCount(g_aCurrentTeams[Team2]); - - /** - Return the smaller team - */ - if (iCountT1 < iCountT2) - { - return g_aCurrentTeams[Team1]; - } - else if (iCountT1 > iCountT2) - { - return g_aCurrentTeams[Team2]; - } - return 0; -} - -stock GetBiggerTeam() -{ - - /** - Get the count of players on each team - */ - new iCountT1 = GetTeamClientCount(g_aCurrentTeams[Team1]); - new iCountT2 = GetTeamClientCount(g_aCurrentTeams[Team2]); - - /** - Return the bigger team - */ - if (iCountT1 > iCountT2) - { - return g_aCurrentTeams[Team1]; - } - else if (iCountT1 < iCountT2) - { - return g_aCurrentTeams[Team2]; - } - return 0; -} - -stock SetGameCvars() -{ - if (g_bConVarControl && g_bIsEnabled) - { - if (stb_mp_autoteambalance != INVALID_HANDLE) - { - SetConVarInt(stb_mp_autoteambalance, 0); - } - if (stb_mp_teams_unbalance_limit != INVALID_HANDLE) - { - SetConVarInt(stb_mp_teams_unbalance_limit, g_iUnbalanceLimit); - } - } -} - -/* TIMER FUNCTIONS */ - -public Action:Timer_ChangeTeamBalanceDelay(Handle:timer, any:data) -{ - - /** - Finally start one if it's still unbalanced - */ - if (IsUnbalanced() && !g_bBalanceInProgress) - { - StartABalance(); - } -} - -public Action:Timer_BalanceTeams(Handle:timer, any:data) -{ - - /** - See if we still need to balance the teams - */ - if (!IsUnbalanced() || !OkToBalance()) - { - - /** - We don't, kill the balance - */ - g_bBalanceInProgress = false; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Balance delay timer was not needed and died."); - } - g_hBalanceTimer = INVALID_HANDLE; - return Plugin_Handled; - } - - /** - We still need to balance the teams - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Teams are still unbalanced. Balance is now in progress."); - } - g_bBalanceInProgress = true; - - - /** - Check if we are allowed to scan living players - */ - if (!g_bDeadOnly) - { - - /** - We are allowed to, so we start a timer - */ - StartALivingPlayerTimer(); - - /** - Also report that we are now scanning dead players as well - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Now scanning dead players."); - } - } - else - { - - /** - We are not allowed to, so report that we are only scanning dead players - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Only scanning dead players."); - } - } - - g_hBalanceTimer = INVALID_HANDLE; - return Plugin_Handled; -} - -public Action:Timer_LivingPlayerCheck(Handle:timer, any:data) -{ - - /** - Check to see if we still need to balance the teams - */ - if (!IsUnbalanced() || !OkToBalance()) - { - - /** - We don't, kill it and bug out - */ - g_bBalanceInProgress = false; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Living player balance delay timer was not needed and died."); - } - g_hLivingPlayerCheckTimer = INVALID_HANDLE; - return Plugin_Handled; - } - - /** - Call the stock function to find a player we can switch - */ - new iPlayer = FindSwitchablePlayer(); - - /** - Check to see if we found a player - */ - if (iPlayer == 0) - { - - /** - In the unlikely event that the stock function didn't return a player - Start a loop to find a random player - */ - new iBiggerTeam = GetBiggerTeam(); - do - { - iPlayer = GetRandomInt(1, MaxClients); - } while (!IsSwitchablePlayer(iPlayer, iBiggerTeam)); - - if (g_bLogActivity) - { - LogAction(0, iPlayer, "[STB] Found a random living player."); - } - } - else - { - if (g_bLogActivity) - { - LogAction(0, iPlayer, "[STB] Found a living player."); - } - } - - /** - Now that we have a player assigned them to the smaller team - */ - new iSmallerTeam = GetSmallerTeam(); - SM_SetForcedTeam(iPlayer, iSmallerTeam, true); - - /** - Let the player know we could be switching him soon - */ - PrintHintText(iPlayer, "%T", "PlayerMessage", LANG_SERVER, g_iLivingPlayerSwitchDelay); - if (g_bLogActivity) - { - LogAction(0, iPlayer, "[STB] Living player placed on a timer."); - } - - /** - Create a timer to switch the player - */ - g_aPlayers[iPlayer][hBalanceTimer] = CreateTimer(float(g_iLivingPlayerSwitchDelay), Timer_LivingPlayerBalance, iPlayer, TIMER_FLAG_NO_MAPCHANGE); - - /** - Reset the timer handle - */ - g_hLivingPlayerCheckTimer = INVALID_HANDLE; - - /** - We are done, bug out - */ - return Plugin_Handled; -} - -public Action:Timer_LivingPlayerBalance(Handle:timer, any:iClient) -{ - - /** - Check to make sure we still need to balance - */ - if (!IsUnbalanced() || !OkToBalance()) - { - - /** - We don't need to balance, bug out - */ - g_bBalanceInProgress = false; - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - SM_ClearForcedTeam(iClient); - return Plugin_Handled; - } - - /** - We still need to balance, lets make sure we can still balance this player - */ - if (!IsClientConnected(iClient) || g_aPlayers[iClient][bFlagCarrier]) - { - g_bBalanceInProgress = false; - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - SM_ClearForcedTeam(iClient); - if (g_bLogActivity) - { - if (g_aPlayers[iClient][bFlagCarrier]) - { - LogAction(0, iClient, "[STB] Living player became flag carrier, balance restarted."); - } - else - { - LogAction(0, iClient, "[STB] Living player timer was not needed and died."); - } - } - return Plugin_Handled; - } - - /** - Clear to balance this player, so do it - */ - BalancePlayer(iClient, SM_GetForcedTeam(iClient)); - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] Living player was switched."); - } - - /** - We are done, bug out - */ - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - return Plugin_Handled; -} - -public Action:Timer_BalancePlayer(Handle:timer, Handle:pack) -{ - - /** - Rest the datapack and load the variables - */ - ResetPack(pack); - new iClient = ReadPackCell(pack); - new iUnBalancedTeam = ReadPackCell(pack); - - /** - We are done with you now - */ - CloseHandle(pack); - - /** - Check the team and make sure its a valid team - */ - if(!SM_IsValidTeam(iUnBalancedTeam)) - { - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] Balance failed due to invalid team number %i", iUnBalancedTeam); - } - return Plugin_Handled; - } - - /** - Use our core function to change the clients team - */ - SM_MovePlayer(iClient, iUnBalancedTeam); - - return Plugin_Handled; -} - -public Action:Timer_RoundStart(Handle:timer, any:data) -{ - g_bRoundStart = false; - if (OkToBalance() && IsUnbalanced() && !g_bBalanceInProgress) - { - StartABalance(); - } - return Plugin_Handled; -} - -public Action:Timer_ForcedExpired(Handle:timer, any:iClient) -{ - SM_ClearForcedTeam(iClient); - g_aPlayers[iClient][bSwitched] = false; - g_aPlayers[iClient][hForcedTimer] = INVALID_HANDLE; - return Plugin_Handled; -} - -public Action:Timer_WelcomeAdvert(Handle:timer, any:iClient) -{ - if (IsClientConnected(iClient) && IsClientInGame(iClient)) - { - PrintToChat (iClient, "\x01\x04[STB]\x01 %T", "BuddyWelcomeMsg1", LANG_SERVER); - PrintToChat (iClient, "\x01\x04[STB]\x01 %T", "BuddyWelcomeMsg2", LANG_SERVER); - PrintToChat (iClient, "\x01\x04[STB]\x01 %T", "BuddyWelcomeMsg3", LANG_SERVER); - } - return Plugin_Handled; -} - -/* CONSOLE VARIABLE CHANGE EVENT */ - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (convar == stb_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsEnabled = false; - PrintToChatAll("[SM] %T", "Disabled", LANG_SERVER); - LogAction(0, -1, "[SimpleTeamBalancer] Disabled"); - } - else - { - g_bIsEnabled = true; - SetGameCvars(); - PrintToChatAll("[SM] %T", "Enabled", LANG_SERVER); - LogAction(0, -1, "[SimpleTeamBalancer] Enabled"); - } - } - else if (convar == stb_logactivity) - { - if (StringToInt(newValue) == 0) - { - g_bLogActivity = false; - LogAction(0, -1, "[STB] Log Activity DISABLED."); - } - else - { - g_bLogActivity = true; - LogAction(0, -1, "[STB] Log Activity ENABLED."); - } - } - else if (convar == stb_logactivity2) - { - if (StringToInt(newValue) == 0) - { - g_bLogActivity2 = false; - LogAction(0, -1, "[STB] Detailed Log Activity DISABLED."); - } - else - { - g_bLogActivity2 = true; - LogAction(0, -1, "[STB] Detailed Log Activity ENABLED."); - } - } - else if (convar == stb_convarcontrol) - { - if (StringToInt(newValue) == 0) - { - g_bConVarControl = false; - } - else - { - g_bConVarControl = true; - SetGameCvars(); - } - } - else if (convar == stb_deadonly) - { - if (StringToInt(newValue) == 0) - { - g_bDeadOnly = false; - } - else - { - g_bDeadOnly = true; - } - } - else if (convar == stb_priorityenabled) - { - if (StringToInt(newValue) == 0) - { - g_bPriorityPlayers = false; - } - else - { - g_bPriorityPlayers = true; - } - } - else if (convar == stb_buddyenabled) - { - if (StringToInt(newValue) == 0) - { - g_bBuddyEnabled = false; - } - else - { - g_bBuddyEnabled = true; - } - } - else if (convar == stb_buddyrestriction) - { - if (StringToInt(newValue) == 0) - { - g_bBuddyRestriction = false; - } - else - { - g_bBuddyRestriction = true; - } - } - else if (convar == stb_unbalancelimit) - { - g_iUnbalanceLimit = StringToInt(newValue); - SetGameCvars(); - } - else if (convar == stb_balancedelay) - { - g_iBalanceDelay = StringToInt(newValue); - } - else if (convar == stb_roundstartdelay) - { - g_iRoundStartDelay = StringToInt(newValue); - } - else if (convar == stb_livingplayerswitchdelay) - { - g_iLivingPlayerSwitchDelay = StringToInt(newValue); - } - else if (convar == stb_livingplayercheckdelay) - { - g_iLivingPlayerCheckDelay = StringToInt(newValue); - } - else if (convar == stb_uberlevel) - { - g_fUberLevel = StringToFloat(newValue); - } - else if (convar == stb_switchbackforced) - { - g_iSwitchBackForced = StringToInt(newValue); - } - else if (convar == stb_adminflag) - { - SetConVarString(stb_adminflag, newValue); - } - else if (convar == stb_mp_autoteambalance) - { - SetGameCvars(); - } - else if (convar == stb_mp_teams_unbalance_limit) - { - SetGameCvars(); - } -} - -/* MENU CODE */ - -stock Handle:BuildPlayerMenu() -{ - new Handle:menu = CreateMenu(Menu_SelectPlayer); - AddTargetsToMenu(menu, 0, true, false); - SetMenuTitle(menu, "Select A Player:"); - SetMenuExitButton(menu, true); - return menu; -} - -public Menu_SelectPlayer(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - new buddy = GetClientOfUserId(StringToInt(sSelection)); - if (param1 == buddy) { - PrintHintText(param1, "%T", "SelectSelf", LANG_SERVER); - } else if (!IsClientInGame(buddy)) { - PrintHintText(param1, "%T", "BuddyGone", LANG_SERVER); - } else { - decl String:cName[128]; - decl String:bName[128]; - GetClientName(param1, cName, sizeof(cName)); - GetClientName(buddy, bName, sizeof(bName)); - if (!SM_IsBuddyLocked(buddy)) { - SM_AssignBuddy(param1, buddy); - PrintHintText(param1, "%T", "BuddyMsg", LANG_SERVER, bName); - PrintHintText(buddy, "%T", "BuddyMsg", LANG_SERVER, cName); - } else - PrintHintText(param1, "%T", "PlayerLockedBuddyMsg", LANG_SERVER, bName); - } - } else if (action == MenuAction_End) { - CloseHandle(menu); - } -} \ No newline at end of file diff --git a/Simple Donator Benefits/addons/sourcemod/scripting/simple-teammanager.sp b/Simple Donator Benefits/addons/sourcemod/scripting/simple-teammanager.sp deleted file mode 100644 index 008f443..0000000 --- a/Simple Donator Benefits/addons/sourcemod/scripting/simple-teammanager.sp +++ /dev/null @@ -1,1351 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Team Manager -Description: - Manges players and their team - Admin menu integration - Allows admins/donators to swap their teams (clears force)* - Allows admins to move players to a team (forced\unforced)* - Allows admins to scramble the teams* - *Works with Simple Team Balancer (if installed) -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include - -#define PLUGIN_VERSION "2.1.$Rev$" -#define VOTE_YES "##YES##" -#define VOTE_NO "##NO##" - -enum PlayerData -{ - iNewTeam, - bool:bQueue -}; - -new Handle:stm_enabled = INVALID_HANDLE; -new Handle:stm_logactivity = INVALID_HANDLE; -new Handle:stm_adminflag_swapteam = INVALID_HANDLE; -new Handle:stm_adminflag_moveplayer = INVALID_HANDLE; -new Handle:stm_adminflag_scramble = INVALID_HANDLE; -new Handle:stm_scrambledelay = INVALID_HANDLE; -new Handle:stm_voteenabled = INVALID_HANDLE; -new Handle:stm_votewin = INVALID_HANDLE; -new Handle:stm_votedelay = INVALID_HANDLE; -new Handle:stm_mp_bonusroundtime = INVALID_HANDLE; -new Handle:g_hAdminMenu = INVALID_HANDLE; -new Handle:g_hTimerPrepScramble = INVALID_HANDLE; -new Handle:g_hTimerClearScrambleForce = INVALID_HANDLE; - -new g_aPlayers[MAXPLAYERS + 1][PlayerData]; - -new bool:g_bIsEnabled = true; -new bool:g_bVoteEnabled = true; -new bool:g_bLogActivity = true; -new bool:g_bScrambleRoundEnd = false; -new g_iVoteDelay, g_iLastVoteTime, g_iTimeLeft; -new Float:g_fScrambleDelay, Float:g_fVoteWin; - -public Plugin:myinfo = -{ - name = "Simple Team Manager", - author = "Simple Plugins", - description = "Manages players and thier team.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -public OnPluginStart() -{ - - /** - Need to create all of our console variables. - */ - CreateConVar("stm_version", PLUGIN_VERSION, "Simple Team Manager Version",FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - stm_enabled = CreateConVar("stm_enabled", "1", "Enable or Disable Simple Team Manager", _, true, 0.0, true, 1.0); - stm_logactivity = CreateConVar("stm_logactivity", "0", "Enable or Disable the disaplying of events in the log", _, true, 0.0, true, 1.0); - stm_adminflag_swapteam = CreateConVar("stm_adminflag_swapteam", "a", "Admin flag to use for the swapteam command. Must be a in char format."); - stm_adminflag_moveplayer = CreateConVar("stm_adminflag_moveplayer", "c", "Admin flag to use for the moveplayer command. Must be a in char format."); - stm_adminflag_scramble = CreateConVar("stm_adminflag_scramble", "c", "Admin flag to use for the scrambleteam command. Must be a in char format."); - stm_scrambledelay = CreateConVar("stm_scrambledelay", "15", "Delay to scramble teams"); - stm_voteenabled = CreateConVar("stm_voteenabled", "1", "Enable or Disable voting to scramble the teams", _, true, 0.0, true, 1.0); - stm_votewin = CreateConVar("stm_votewin", "0.45", "Win percentage vote must win by", _, true, 0.0, true, 1.0); - stm_votedelay = CreateConVar("stm_votedelay", "600", "Delay before another vote can be cast"); - stm_mp_bonusroundtime = FindConVar("mp_bonusroundtime"); - - - /** - Need deal with changes to the console variables after the plugin is loaded. - We could not do this and just call the actual console variable each time we need it, but it's not efficent. - */ - HookConVarChange(stm_enabled, ConVarSettingsChanged); - HookConVarChange(stm_logactivity, ConVarSettingsChanged); - HookConVarChange(stm_scrambledelay, ConVarSettingsChanged); - HookConVarChange(stm_voteenabled, ConVarSettingsChanged); - HookConVarChange(stm_votewin, ConVarSettingsChanged); - HookConVarChange(stm_votedelay, ConVarSettingsChanged); - - /** - Need to register the commands we are going to create and use. - */ - RegConsoleCmd("sm_swapteam", Command_SwapTeam, "sm_swapteam <[0]instant/[1]queued>: Swaps your team to the other team"); - RegConsoleCmd("sm_moveplayer", Command_MovePlayer, "sm_moveplayer <[0]instant/[1]ondeath> <[0]unforced/[1]forced>: Moves a player to the specified team"); - RegConsoleCmd("sm_scrambleteams", Command_ScrambleTeams, "sm_scrambleteams: <[0]now/[1]roundend> <[0]dontrestart/[1]restartround> Scrambles the current teams"); - RegConsoleCmd("sm_votescramble", Command_VoteScramble, "sm_votescramble: Starts a vote to scramble the teams"); - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[STM] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_death", HookPlayerDeath, EventHookMode_Post); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Post); - switch (g_CurrentMod) - { - case GameType_TF: - { - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - } - case GameType_DOD: - { - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_Post); - } - default: - { - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - - /** - Now we have to deal with the admin menu. If the admin library is loaded call the function to add our items. - */ - new Handle:gTopMenu; - if (LibraryExists("adminmenu") && ((gTopMenu = GetAdminTopMenu()) != INVALID_HANDLE)) - { - OnAdminMenuReady(gTopMenu); - } - - /** - Load translations and .cfg file - */ - LoadTranslations ("simpleteammanager.phrases"); - AutoExecConfig(true, "plugin.simpleteammanager"); - LogAction(0, -1, "[STM] Simple Team Manager is loaded."); -} - -public OnAllPluginsLoaded() -{ - //something -} - -public OnLibraryRemoved(const String:name[]) -{ - if (StrEqual(name, "adminmenu")) - { - - /** - Looks like the admin menu was removed. Set the global. - */ - g_hAdminMenu = INVALID_HANDLE; - } - else if (StrEqual(name, "simpleplugins")) - { - SetFailState("Required plugin Simple SourceMod Plugins Core was removed."); - } -} - -public OnConfigsExecuted() -{ - - /** - Once we loaded up all the console variables from the config file, lets now set all the global variables we will use. - */ - g_bIsEnabled = GetConVarBool(stm_enabled); - g_bLogActivity = GetConVarBool(stm_logactivity); - g_fScrambleDelay = GetConVarFloat(stm_scrambledelay); - g_iVoteDelay = GetConVarInt(stm_votedelay); - g_fVoteWin = GetConVarFloat(stm_votewin); - g_iLastVoteTime = RoundFloat(GetEngineTime()); - g_bScrambleRoundEnd = false; - g_hTimerClearScrambleForce = INVALID_HANDLE; - - /** - Report enabled - */ - if (g_bIsEnabled) - { - LogAction(0, -1, "[STM] Simple Team Manager is ENABLED."); - } - else - { - LogAction(0, -1, "[STM] Simple Team Manager is DISABLED."); - } - - if (g_bLogActivity) - { - LogAction(0, -1, "[STM] Log Activity ENABLED."); - } - else - { - LogAction(0, -1, "[STM] Log Activity DISABLED."); - } -} - -/* COMMANDS */ - -public Action:Command_SwapTeam(client, args) -{ - - /** - Make sure we are enabled, if not bug out. - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - If this was ran from the console bug out. - */ - if (client == 0) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure the client is authorized to run this command. - */ - decl String:sFlags[5]; - GetConVarString(stm_adminflag_swapteam, sFlags, sizeof(sFlags)); - if (!SM_IsValidAdmin(client, sFlags)) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Lets make sure the client is one a team we can swap. - If he is we set the global array to the opposite team. - */ - new iTeam = GetClientTeam(client); - if (iTeam == g_aCurrentTeams[Team1]) - { - g_aPlayers[client][iNewTeam] = g_aCurrentTeams[Team2]; - } - else if (iTeam == g_aCurrentTeams[Team2]) - { - g_aPlayers[client][iNewTeam] = g_aCurrentTeams[Team1]; - } - else - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "InValidTeam", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check to see if we have command arguments. - */ - if (GetCmdArgs()) - { - - /** - We do, so lets get it and see if the client wants to be switched instantly or queued for death. - */ - decl String:sArg[5]; - GetCmdArg(1, sArg, sizeof(sArg)); - new iWantsQue = StringToInt(sArg); - if (iWantsQue && !g_aPlayers[client][bQueue]) - { - - /** - He wants the que and isn't already in it, set the global array. - */ - g_aPlayers[client][bQueue] = true; - ReplyToCommand(client, "\x01\x04[STM]\x01 %T", "PlayerQueue", LANG_SERVER); - } - else if (!iWantsQue) - { - - /** - He wants to be switched right now, lets call the stock function. - */ - SM_MovePlayer(client, g_aPlayers[client][iNewTeam]); - } - } - else - { - - /** - There are no command arguments so we build and display the swap menu. - */ - DisplaySwapModeMenu(client, client); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_MovePlayer(client, args) -{ - - /** - Make sure we are enabled, if not bug out. - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the client is authorized to run this command. - */ - decl String:sFlags[5]; - GetConVarString(stm_adminflag_moveplayer, sFlags, sizeof(sFlags)); - if (!SM_IsValidAdmin(client, sFlags)) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check to see if we have command arguments. - */ - new iCmdArgs = GetCmdArgs(); - if (iCmdArgs == 0) - { - - /** - We don't. Build the player menu, display it, and bug out. - */ - DisplayPlayerMenu(client); - return Plugin_Handled; - } - - /** - Check the first argument - If should be a players name or userid. - */ - decl String:sPlayer[64]; - GetCmdArg(1, sPlayer, sizeof(sPlayer)); - new iPlayerIndex = FindTarget(client, sPlayer, true, true); - if (iPlayerIndex == -1 || !IsClientInGame(iPlayerIndex)) - { - - /** - We don't know who this is. Build the player menu, display it, and bug out. - */ - DisplayPlayerMenu(client); - return Plugin_Handled; - } - - /** - We have figured out the first argument, lets check the second. - If should be the team the client wants to put the player on. - */ - if (iCmdArgs >= 2) - { - - /** - We have a command argument at least, lets see if we can identify the team. - */ - decl String:sTeam[24]; - GetCmdArg(2, sTeam, sizeof(sTeam)); - - new iTeam = StringToInt(sTeam); - if (SM_IsValidTeam(iTeam)) - { - - /** - It's a vaild team so lets set the global array to the new team. - */ - g_aPlayers[iPlayerIndex][iNewTeam] = iTeam; - } - else - { - - /** - It's not a vaild team so set the menu to display to the team menu. - */ - DisplayTeamMenu(client, iPlayerIndex); - return Plugin_Handled; - } - } - else - { - /** - We were not given a team, display the team menu. - */ - DisplayTeamMenu(client, iPlayerIndex); - return Plugin_Handled; - } - - /** - Check to see if we were given any more command arguments and found a team. - */ - if (iCmdArgs < 3) - { - - /** - No more command arguments and found a team. - Now lets check to see if the player is a spectator. If he is there is no reason to ask if it's instant or on death... he can't die. - */ - if (!IsClientObserver(iPlayerIndex)) - { - - /** - Not a spectator so display the swapmode menu. - */ - DisplaySwapModeMenu(client, iPlayerIndex); - } - else - { - - /** - The player is a spectator. - We make sure the player is not set to switch on death, since a spec can't die. - */ - g_aPlayers[iPlayerIndex][bQueue] = false; - } - } - - /** - We have figured out the second argument, lets check the third. - If should be the how the client wants to move the player: instant/on death. - */ - if (iCmdArgs >= 3) - { - - /** - The client gave us a command argument, lets check it. - */ - decl String:sSwapMode[5]; - GetCmdArg(3, sSwapMode, sizeof(sSwapMode)); - new iWantsQue = StringToInt(sSwapMode); - if (iWantsQue) - { - - /** - The client wants to que the player, set the global array. - */ - g_aPlayers[iPlayerIndex][bQueue] = true; - } - else - { - - /** - The client doesn't want to que the player, set the global array. - */ - g_aPlayers[iPlayerIndex][bQueue] = false; - } - } - else - { - /** - No swapmode argument, display the menu - */ - DisplaySwapModeMenu(client, iPlayerIndex); - } - - if (iCmdArgs >= 4) - { - - /** - Since we are compiling for Simple Team Balancer, and given a 4th argument, lets check it. - If should be the if the client wants to force the player to that team. - */ - decl String:sPlayerForced[5]; - GetCmdArg(4, sPlayerForced, sizeof(sPlayerForced)); - new iForceHim = StringToInt(sPlayerForced); - if (iForceHim) - { - - /** - The client wants to force the player - */ - SM_SetForcedTeam(iPlayerIndex, g_aPlayers[iPlayerIndex][iNewTeam]); - } - else - { - - /** - The client doesn't want to force the player - */ - SM_ClearForcedTeam(iPlayerIndex); - } - } - else - { - - } - - /** - We found and processed all the arguments. - */ - if (!IsPlayerAlive(iPlayerIndex)) - { - - /** - The player is not alive or died during this process so we just move him. - */ - SM_MovePlayer(iPlayerIndex, g_aPlayers[iPlayerIndex][iNewTeam]); - } - else - { - if (!g_aPlayers[iPlayerIndex][bQueue]) - { - - /** - The player is alive and is not set to be queued so we just move him. - */ - SM_MovePlayer(iPlayerIndex, g_aPlayers[iPlayerIndex][iNewTeam]); - } - } - - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_ScrambleTeams(client, args) -{ - - /** - Make sure we are enabled, if not bug out. - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the client is authorized to run this command. - */ - decl String:sFlags[5]; - GetConVarString(stm_adminflag_scramble, sFlags, sizeof(sFlags)); - if (!SM_IsValidAdmin(client, sFlags)) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check if a scramble timer was already called, if so close it down. - */ - if (g_hTimerPrepScramble != INVALID_HANDLE) - { - CloseHandle(g_hTimerPrepScramble); - g_hTimerPrepScramble = INVALID_HANDLE; - } - - /** - Check if we have any command arguments. - If we don't we display the scramble menu and bug out. - */ - new iCmdArgs = GetCmdArgs(); - if (iCmdArgs == 0) - { - DisplayScrambleMenu(client); - return Plugin_Handled; - } - - /** - We have a command argument. - It should be whether or not to scramble at round end. - */ - decl String:sRoundEnd[5]; - GetCmdArg(1, sRoundEnd, sizeof(sRoundEnd)); - if (StringToInt(sRoundEnd)) - { - /** - The client wants to scramble at round end so we set the global bool. - */ - g_bScrambleRoundEnd = true; - } - else - { - g_bScrambleRoundEnd = false; - } - - /** - Check for another command argument. - It should be whether or not to restart the round. - */ - decl String:sRestartRound[5]; - new bool:bRestartRound = false; - GetCmdArg(1, sRestartRound, sizeof(sRestartRound)); - if (StringToInt(sRestartRound)) - { - bRestartRound = true; - } - - /** - Now we start the scramble timer. - */ - StartScrambleTimer(_, bRestartRound); - - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_VoteScramble(client, args) -{ - - /** - Make sure we are enabled, if not bug out. - */ - if (!g_bVoteEnabled || !g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Make sure there is a vote in progress, if so bug out. - */ - if (IsVoteInProgress()) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "VoteInProgress", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure enough time has passed since the last vote. - */ - new iVoteTime = RoundFloat(GetEngineTime()); - if (iVoteTime - g_iLastVoteTime <= g_iVoteDelay) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "ScrambleTime", LANG_SERVER); - return Plugin_Handled; - } - - /** - Enough time has passed so reset the global vote time to now. - */ - g_iLastVoteTime = iVoteTime; - - /** - Build the vote menu and send it to everyone. - */ - new Handle:hMenu = CreateMenu(Menu_VoteScramble); - SetMenuTitle(hMenu, "Scramble Teams?"); - AddMenuItem(hMenu, VOTE_YES, "Yes"); - AddMenuItem(hMenu, VOTE_NO, "No"); - SetMenuExitButton(hMenu, false); - VoteMenuToAll(hMenu, 20); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -/* HOOKED EVENTS */ - -public HookPlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Find out who died. - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - - /** - Find out how the client died. - */ - new String:sWeapon[64]; - GetEventString(event, "weapon", sWeapon, sizeof(sWeapon)); - if (StrEqual(sWeapon, "world", false)) - { - - /** - He died because he changed teams so cleanup and bug out. - */ - s_CleanUp(iClient); - return; - } - - /** - Find out if this player was queued to change teams. - */ - if (g_aPlayers[iClient][bQueue]) - { - /** - Looks like he was, so call the stock function to move him. - */ - SM_MovePlayer(iClient, g_aPlayers[iClient][iNewTeam]); - } -} - -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Find out who changed teams. - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - - /** - If he was queued to switch teams we cleanup the variables. The client did it themself. - */ - if (g_aPlayers[iClient][bQueue]) - { - s_CleanUp(iClient); - } -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get the amount of time left in the map. - */ - new iTimeLeft; - GetMapTimeLeft(iTimeLeft); - - /** - Check to see if we are supposed to scramble at the end of the round and that there is enough time left in the map. - */ - if (g_bScrambleRoundEnd && iTimeLeft >= 60) - { - - /** - Check to see if there is a scramble timer in action and if so close it down. - */ - if (g_hTimerPrepScramble != INVALID_HANDLE) - { - CloseHandle(g_hTimerPrepScramble); - g_hTimerPrepScramble = INVALID_HANDLE; - } - - /** - Determine the round end chat time and run the scramble 1 second before it ends. - */ - new Float:fDelay = GetConVarFloat(stm_mp_bonusroundtime); - fDelay -= 1.0; - StartScrambleTimer(fDelay); - } -} - -public OnClientPostAdminCheck(client) -{ - - /** - Determine if the client has the flag to use the swapteam command. - */ - decl String:sFlags[5]; - GetConVarString(stm_adminflag_swapteam, sFlags, sizeof(sFlags)); - if (SM_IsValidAdmin(client, sFlags)) - { - /** - The client does so lets create a timer to run an advertise to tell him about it. - */ - CreateTimer (60.0, Timer_WelcomeAdvert, client); - } -} - -public OnClientDisconnect(client) -{ - - /** - Cleanup the clients variables. - */ - s_CleanUp(client); -} - -public SM_OnPlayerMoved(Handle:plugin, client, team) -{ - - /** - Make sure we called the move function - */ - if (plugin != GetMyHandle()) - { - if (g_bLogActivity) - { - LogAction(0, client, "[STM] Callback was not started with current plugin, bugging out."); - } - return; - } - - decl String:sPlayerName[64]; - GetClientName(client, sPlayerName, sizeof(sPlayerName)); - - PrintToChat(client, "\x01\x04[SM]\x01 %T", "PlayerSwitched", LANG_SERVER); - - s_CleanUp(client); -} - -/* TIMER FUNCTIONS */ - -public Action:Timer_PrepTeamScramble(Handle:timer, any:data) -{ - new bool:bRestartRound = data; - /** - Call the scramble the teams stock function. - */ - PrepTeamScramble(bRestartRound); - - /** - Reset the timer handle so we know the timer is done. - */ - g_hTimerPrepScramble = INVALID_HANDLE; - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Timer_ScrambleTheTeams(Handle:timer, any:data) -{ - new iPlayers[MAXPLAYERS + 1]; - new iCount, i, bool:bTeam, bool:bRestartRound = data; - - /** - Get all the client index numbers of valid players - */ - for(i = 1; i <= MaxClients; i++) - { - if(IsClientInGame(i)) // && !IsFakeClient(i)) - { - iPlayers[iCount++] = i; - } - } - - /** - Randomly sort the players - */ - SortIntegers(iPlayers, iCount, Sort_Random); - - /** - Loop through all the players and assign each one to a team, alternating each time - */ - for(i = 0; i < iCount; i++) - { - if (!bRestartRound) - { - /** - We didn't want to restart the round, so we move them to spec 1 at a time. - */ - SM_MovePlayer(iPlayers[i], g_aCurrentTeams[Spectator]); - } - SM_MovePlayer(iPlayers[i], bTeam ? g_aCurrentTeams[Team2] : g_aCurrentTeams[Team1]); - SM_SetForcedTeam(iPlayers[i], bTeam ? g_aCurrentTeams[Team2] : g_aCurrentTeams[Team1], true); - bTeam = !bTeam; - } - - /** - Reset this variable since we completed a scramble - */ - g_bScrambleRoundEnd = false; - - if (g_hTimerClearScrambleForce != INVALID_HANDLE) - { - CloseHandle(g_hTimerClearScrambleForce); - g_hTimerClearScrambleForce = INVALID_HANDLE; - } - - g_hTimerClearScrambleForce = CreateTimer(300.0, Timer_ClearScrambleForce, _, TIMER_FLAG_NO_MAPCHANGE); - - ServerCommand("mp_timelimit %i", g_iTimeLeft / 60); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Timer_ClearScrambleForce(Handle:timer, any:data) -{ - - for(new i = 1; i <= MaxClients; i++) - { - if(IsClientInGame(i)) // && !IsFakeClient(i)) - { - SM_ClearForcedTeam(i); - PrintToChat(i, "\x01\x04[SM]\x01 Your forced team status has been cleared"); - } - } - - g_hTimerClearScrambleForce = INVALID_HANDLE; - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Timer_WelcomeAdvert(Handle:timer, any:client) -{ - - /** - Lets make sure the client is connected and actually in the game. - */ - if (IsClientConnected(client) && IsClientInGame(client)) - { - - /** - We are good to go so lets tell him about the swapteam command. - */ - PrintToChat (client, "\x01\x04[STM]\x01 %T", "SwapTeamMsg", LANG_SERVER); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -/* STOCK FUNCTIONS */ - -stock s_CleanUp(iClient) -{ - - /** - Reset all the client variables - */ - g_aPlayers[iClient][bQueue] = false; - g_aPlayers[iClient][iNewTeam] = 0; -} - -stock StartScrambleTimer(Float:fdelay = 0.0, bool:bRestartRound = false) -{ - if (fdelay == 0.0) - { - fdelay = g_fScrambleDelay; - } - if (g_hTimerPrepScramble != INVALID_HANDLE) - { - CloseHandle(g_hTimerPrepScramble); - g_hTimerPrepScramble = INVALID_HANDLE; - } - PrintCenterTextAll("%T", "Scramble", LANG_SERVER); - g_hTimerPrepScramble = CreateTimer(fdelay, Timer_PrepTeamScramble, bRestartRound, TIMER_FLAG_NO_MAPCHANGE); -} - -stock PrepTeamScramble(bool:bRestartRound = false) -{ - new iPlayers[MAXPLAYERS + 1]; - new iCount; - - GetMapTimeLeft(g_iTimeLeft); - - if (bRestartRound) - { - - for(new i = 1; i <= MaxClients; i++) - { - if(IsClientInGame(i)) - // && !IsFakeClient(i)) - { - iPlayers[iCount++] = i; - SM_ClearForcedTeam(i); - SM_ClearBuddy(i); - SM_MovePlayer(i, g_aCurrentTeams[Spectator]); - } - } - } - else - { - //Can't move them all to spec at the same time - for(new i = 1; i <= MaxClients; i++) - { - if(IsClientInGame(i)) - // && !IsFakeClient(i)) - { - iPlayers[iCount++] = i; - SM_ClearForcedTeam(i); - SM_ClearBuddy(i); - //SM_MovePlayer(i, g_aCurrentTeams[Spectator]); - } - } - } - CreateTimer(4.0, Timer_ScrambleTheTeams, bRestartRound, TIMER_FLAG_NO_MAPCHANGE); -} - -/* CONSOLE VARIABLE CHANGE EVENT */ - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (convar == stm_enabled) { - if (StringToInt(newValue) == 0) { - g_bIsEnabled = false; - LogAction(0, -1, "[STM] Simple Team Manager is loaded and disabled."); - } else { - g_bIsEnabled = true; - LogAction(0, -1, "[STM] Simple Team Manager is loaded and enabled."); - } - } - else if (convar == stm_logactivity) { - if (StringToInt(newValue) == 0) { - g_bLogActivity = false; - LogAction(0, -1, "[STM] Log Activity DISABLED."); - } else { - g_bLogActivity = true; - LogAction(0, -1, "[STM] Log Activity ENABLED."); - } - } - else if (convar == stm_scrambledelay) - g_fScrambleDelay = StringToFloat(newValue); - else if (convar == stm_votewin) - g_fVoteWin = StringToFloat(newValue); - else if (convar == stm_votedelay) - g_iVoteDelay = StringToInt(newValue); - else if (convar == stm_voteenabled) { - if (StringToInt(newValue) == 0) - g_bVoteEnabled = false; - else - g_bVoteEnabled = true; - } -} - -/* MENU CODE */ - -public OnAdminMenuReady(Handle:topmenu) -{ - if (topmenu == g_hAdminMenu) - return; - g_hAdminMenu = topmenu; - new TopMenuObject:player_commands = FindTopMenuCategory(g_hAdminMenu, ADMINMENU_PLAYERCOMMANDS); - new TopMenuObject:server_commands = FindTopMenuCategory(g_hAdminMenu, ADMINMENU_SERVERCOMMANDS); - if (player_commands == INVALID_TOPMENUOBJECT) - return; - - AddToTopMenu(g_hAdminMenu, - "moveplayer", - TopMenuObject_Item, - AdminMenu_MovePlayer, - player_commands, - "moveplayer", - ADMFLAG_BAN); - - AddToTopMenu(g_hAdminMenu, - "scrambleteams", - TopMenuObject_Item, - AdminMenu_Scrambleteams, - server_commands, - "scrambleteams", - ADMFLAG_BAN); -} - -public AdminMenu_MovePlayer(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) -{ - if (action == TopMenuAction_DisplayOption) - Format(buffer, maxlength, "Move Player"); - else if (action == TopMenuAction_SelectOption){ - DisplayPlayerMenu(param); - } -} - -public AdminMenu_Scrambleteams(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) -{ - if (action == TopMenuAction_DisplayOption) - Format(buffer, maxlength, "Scramble Teams"); - else if (action == TopMenuAction_SelectOption) { - DisplayScrambleMenu(param); - } -} - -public Menu_SelectPlayer(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - DisplayTeamMenu(param1, GetClientOfUserId(StringToInt(sSelection))); - } else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -public Menu_SelectTeam(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new iTeam; - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - decl String:sIndex[64]; - if (SplitString(sSelection, "A", sIndex, sizeof(sIndex)) != -1) - iTeam = g_aCurrentTeams[Team1]; - else if (SplitString(sSelection, "B", sIndex, sizeof(sIndex)) != -1) - iTeam = g_aCurrentTeams[Team2]; - else { - SplitString(sSelection, "C", sIndex, sizeof(sIndex)); - iTeam = g_aCurrentTeams[Spectator]; - } - new iTarget = StringToInt(sIndex); - g_aPlayers[iTarget][iNewTeam] = iTeam; - DisplaySwapModeMenu(param1, iTarget); - } else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -public Menu_SwapMode(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - decl String:sIndex[64]; - - if (SplitString(sSelection, "A", sIndex, sizeof(sIndex)) == -1) - { - SplitString(sSelection, "B", sIndex, sizeof(sIndex)); - } - - new iTarget = StringToInt(sIndex); - - if (StrContains(sSelection, "A", true) != -1) - { - g_aPlayers[iTarget][bQueue] = false; - } - else if (StrContains(sSelection, "B", true) != -1) - { - g_aPlayers[iTarget][bQueue] = true; - } - - if (param1 == iTarget && !g_aPlayers[iTarget][bQueue]) - { - SM_MovePlayer(iTarget, g_aPlayers[iTarget][iNewTeam]); - } - else - { - DisplayForceModeMenu(param1, iTarget); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - { - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } - return; -} - -public Menu_ForceMode(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - decl String:sIndex[64]; - if (SplitString(sSelection, "A", sIndex, sizeof(sIndex)) == -1) - { - SplitString(sSelection, "B", sIndex, sizeof(sIndex)); - } - new iTarget = StringToInt(sIndex); - if (StrContains(sSelection, "A", true) != -1) - { - SM_ClearForcedTeam(iTarget); - } - else if (StrContains(sSelection, "B", true) != -1) - { - SM_SetForcedTeam(iTarget, g_aPlayers[iTarget][iNewTeam], true); - } - if (!g_aPlayers[iTarget][bQueue]) - { - SM_MovePlayer(iTarget, g_aPlayers[iTarget][iNewTeam]); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - { - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } - return; -} - -public Menu_VoteScramble(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_VoteEnd) { - new winning_votes, total_votes; - GetMenuVoteInfo(param2, winning_votes, total_votes); - if (param1 == 0) { - if (float(total_votes) / float(winning_votes) < g_fVoteWin) { - PrintToChatAll("\x01\x04[SM]\x01 %T", "VoteScramble2", LANG_SERVER, winning_votes, total_votes); - return; - } - PrintCenterTextAll("[SM] %T", "Scramble", LANG_SERVER); - PrintToChatAll("\x01\x04[SM]\x01 %T", "VoteScramble1", LANG_SERVER, winning_votes, total_votes); - StartScrambleTimer(); - } - if (param1 == 1) { - PrintToChatAll("\x01\x04[SM]\x01 %T", "VoteScramble2", LANG_SERVER, winning_votes, total_votes); - } - } - if (action == MenuAction_End) - CloseHandle(menu); -} - -public Menu_ScrambleTeams(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "NOW", false)) - g_bScrambleRoundEnd = false; - else - g_bScrambleRoundEnd = true; - DisplayScrambleMenu2(param1); - } else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -public Menu_ScrambleTeams2(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[64]; - new bool:bRestartRound; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "NO", false)) - { - bRestartRound = false; - } - else - { - bRestartRound = true; - } - StartScrambleTimer(_, bRestartRound); - } else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -stock DisplayScrambleMenu(iClient) -{ - new Handle:hMenu = CreateMenu(Menu_ScrambleTeams); - SetMenuTitle(hMenu, "Select When to Scramble:"); - AddMenuItem(hMenu, "NOW", "Instantly"); - AddMenuItem(hMenu, "END", "At Round End"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplayScrambleMenu2(iClient) -{ - new Handle:hMenu = CreateMenu(Menu_ScrambleTeams2); - SetMenuTitle(hMenu, "Select When to Scramble:"); - AddMenuItem(hMenu, "NO", "No Round Restart"); - AddMenuItem(hMenu, "YES", "Restart Round"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplaySwapModeMenu(iClient, iTarget) -{ - new Handle:hMenu = CreateMenu(Menu_SwapMode); - decl String:optionA[64]; - decl String:optionB[64]; - Format(optionA, sizeof(optionA), "%iA", iTarget); - Format(optionB, sizeof(optionB), "%iB", iTarget); - SetMenuTitle(hMenu, "Select When to Swap:"); - AddMenuItem(hMenu, optionA, "Instantly (Kills)"); - if (!IsClientObserver(iTarget)) - AddMenuItem(hMenu, optionB, "Queue on next death"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplayForceModeMenu(iClient, iTarget) -{ - new Handle:hMenu = CreateMenu(Menu_ForceMode); - decl String:optionA[64]; - decl String:optionB[64]; - Format(optionA, sizeof(optionA), "%iA", iTarget); - Format(optionB, sizeof(optionB), "%iB", iTarget); - SetMenuTitle(hMenu, "Select Force Mode:"); - AddMenuItem(hMenu, optionA, "UnForced"); - AddMenuItem(hMenu, optionB, "Forced"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplayTeamMenu(iClient, iTarget) -{ - new Handle:hMenu = CreateMenu(Menu_SelectTeam); - decl String:optionA[64]; - decl String:optionB[64]; - decl String:optionC[64]; - Format(optionA, sizeof(optionA), "%iA", iTarget); - Format(optionB, sizeof(optionB), "%iB", iTarget); - Format(optionC, sizeof(optionC), "%iC", iTarget); - SetMenuTitle(hMenu, "Select Team:"); - AddMenuItem(hMenu, optionA, "Team One"); - AddMenuItem(hMenu, optionB, "Team Two"); - AddMenuItem(hMenu, optionC, "Spectator"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplayPlayerMenu(iClient) -{ - new Handle:hMenu = CreateMenu(Menu_SelectPlayer); - AddTargetsToMenu(hMenu, 0, true, false); - SetMenuTitle(hMenu, "Select A Player:"); - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} diff --git a/Simple Donator Benefits/addons/sourcemod/translations/simplespectate.phrases.txt b/Simple Donator Benefits/addons/sourcemod/translations/simplespectate.phrases.txt deleted file mode 100644 index 2d1a096..0000000 --- a/Simple Donator Benefits/addons/sourcemod/translations/simplespectate.phrases.txt +++ /dev/null @@ -1,42 +0,0 @@ -"Phrases" -{ - "Stopped spectating" - { - "#format" "{1:s}" - "en" "Stopped tracking player: {1}" - } - "Yourself" - { - "en" "You can't spectate yourself" - } - "Spectator" - { - "en" "You can't spectate another spectator" - } - "Spectating" - { - "#format" "{1:s}" - "en" "Now spectating {1}. Type !stopspec or /stopspec to stop spectating this player" - } - "Invalid Target" - { - "en" "Invalid target" - } - "Cant Target" - { - "en" "Can't target this player" - } - "Must Have Target" - { - "en" "You must be following/tracking a player to punish" - } - "Target Left" - { - "en" "The player you were following/tracking has left" - } - "Punished" - { - "#format" "{1:s}{2:s}{3:s}" - "en" "{1} was punished with a {2} for {3}" - } -} \ No newline at end of file diff --git a/Simple Donator Benefits/addons/sourcemod/translations/simpleteambalancer.phrases.txt b/Simple Donator Benefits/addons/sourcemod/translations/simpleteambalancer.phrases.txt deleted file mode 100644 index 03595fd..0000000 --- a/Simple Donator Benefits/addons/sourcemod/translations/simpleteambalancer.phrases.txt +++ /dev/null @@ -1,130 +0,0 @@ -"Phrases" -{ - "UnBalanced" - { - "en" "Teams are unbalanced and will be balanced shortly" - "fr" "Les équipes ne sont pas équilibrées et le seront bientôt" - "de" "Die Teams sind ungleich und werden in Kürze ausgeglichen" - "hu" "A csapatok nem kiegyenlitettek! Egyensuly beallitas kovetkezik!" - } - "Enabled" - { - "en" "Simple Team Balancer is ENABLED" - "fr" "Simple Team Balancer est ACTIVE" - "de" "Simple Team Balancer ist AKTIV" - "hu" "Az Egyszeru Csapat Egyensulytarto AKTIV!" - } - "Disabled" - { - "en" "Simple Team Balancer is DISABLED" - "fr" "Simple Team Balancer est DESACTIVE" - "de" "Simple Team Balancer ist INAKTIV" - "hu" "Az Egyszeru Csapat Egyensulytarto INAKTIV!" - } - "PlayerMessage" - { - "#format" "{1:i}" - "en" "You are going to be auto balanced in {1} seconds unless a dead player can be found" - "fr" "Vous passerez dans l'autre équipe dans {1} secondes si aucun joueur mort ne peut être trouvé dans cet intervalle" - "de" "Du wirst in {1} Sekunden zum automatischen Ausgleich herangezogen wenn kein toter Spieler gefunden werden kann" - "hu" "{1} masodpercen belul at leszel helyezve a masik csapatba, hacsak nem lesz addig egy halott jatekos!" - } - "BalanceMessage" - { - "#format" "{1:s}" - "en" "{1} was moved to the other team for game balance" - "fr" "{1} est passé dans l'autre équipe pour équilibrer la partie" - "de" "{1} wurde zum anderen Team verschoben um das Spiel auszugleichen" - "hu" "{1} at lett helyezve az egyensuly megtartasa erdekeben." - } - "PlayerLevelCmd" - { - "en" "Command must be run at the player level" - "fr" "La commande doit être lancée au niveau du joueur" - "de" "Das Kommando muss auf Spieler Ebene ausgeführt werden" - "hu" "Jatekosi szinten kell futtatni ezt a parancsot!" - } - "CmdDisabled" - { - "en" "Command is currently disabled" - "fr" "La commande est actuellement désactivée" - "de" "Das Kommando ist momentan inaktiv" - "hu" "A parancs jelenleg inaktiv" - } - "RestrictedBuddy" - { - "en" "You must be a donator or admin to add a balance buddy" - "fr" "Vous devez être un donateur ou un admin pour choisir un partenaire" - "de" "Du musst ein Spender oder Admin sein um einen Partner wählen zu können" - "hu" "Tamogato vagy admin kell hogy legyel, hogy 'Tarsat' jelolhess meg" - } - "SelectSelf" - { - "en" "You cannot be your own buddy" - "fr" "Vous ne pouvez pas être votre propre partenaire" - "de" "Du kannst nicht dein eigener Partner sein" - "hu" "Nem valaszthatod ki onmagad!" - } - "BuddyGone" - { - "en" "Your selected buddy has disconnected" - "fr" "Le partenaire que vous avez sélectionné s'est déconnecté" - "de" "Dein gewählter Partner hat die Verbindung getrennt" - "hu" "A valasztott 'Tarsad' kilepett" - } - "BuddyMsg" - { - "#format" "{1:s}" - "en" "You and {1} are now buddies" - "fr" "Vous et {1} êtes maintenant partenaires" - "de" "Du und {1} seid jetzt Partner" - "hu" "{1} es Te 'Tarsak' vagytok." - } - "BuddyLockMsgDisabled" - { - "en" "You can now be anyone's buddy" - "fr" "Vous pouvez à présent être le partenaire de n'importe qui" - "de" "Du kannst jetzt jedermanns Partner sein" - "hu" "Barkinek lehetsz a 'Tarsa'." - } - "BuddyLockMsgEnabled" - { - "en" "Buddy selection locked. Only you can change your buddy" - "fr" "Sélection de partenaire bloquée. Vous êtes le seul à pouvoir choisir votre partenaire" - "de" "Wahl des Partners gesperrt. Nur du kannst deinen Partner wechseln" - "hu" "Tars-lista lezarva. Csak Te tudod modositani a Tars-listadat." - } - "PlayerLockedBuddyMsg" - { - "#format" "{1:s}" - "en" "{1} has locked his buddy selection. Try again" - "fr" "{1} a bloqué sa sélection de partenaire. Essayez de nouveau." - "de" "{1} hat seine Wahl des Partners gesperrt. Versuche es erneut" - "hu" "{1} lezarta a Tars-listajat. Probald kesobb!" - } - "BuddyWelcomeMsg1" - { - "en" "Select a balance buddy and stay together during an autobalance!" - "fr" "Choisissez un partenaire et restez ensemble durant l'équilibrage automatique!" - "de" "Wähle einen Partner und bleibt zusammen während eines Ausgleichs" - "hu" "Valasz ki egy 'Tarsat' akivel egyuttmaradhatsz a csapatkiegyenlites alatt!" - } - "BuddyWelcomeMsg2" - { - "en" "/buddy or !buddy to select a balance buddy" - "fr" "/buddy or !buddy pour choisir un partenaire" - "de" "/buddy oder !buddy um einen Partner zu wählen" - "hu" "Hasznald a /buddy vagy !buddy parancsokat a 'Tars' kijelolesehez" - } - "BuddyWelcomeMsg3" - { - "en" "/lockbuddy or !lockbuddy to lock your selection" - "fr" "/lockbuddy or !lockbuddy pour bloquer votre sélection" - "de" "/lockbuddy oder !lockbuddy um deine Auswahl zu sperren" - "hu" "Hasznald a /lockbuddy vagy a !lockbuddy parancsokat a Tars-listad lezarasahoz" - } -} - - - - diff --git a/Simple Donator Benefits/addons/sourcemod/translations/simpleteammanager.phrases.txt b/Simple Donator Benefits/addons/sourcemod/translations/simpleteammanager.phrases.txt deleted file mode 100644 index f2093a7..0000000 --- a/Simple Donator Benefits/addons/sourcemod/translations/simpleteammanager.phrases.txt +++ /dev/null @@ -1,92 +0,0 @@ -"Phrases" -{ - "PlayerLevelCmd" - { - "en" "Command must be run at the player level" - "fr" "Cette commande doit être tapée en jeu" - "hu" "Ezt a parancsot jatekosi szinten kell futtatni!" - } - "RestrictedCmd" - { - "en" "You must be a donator or admin to run this command" - "fr" "Vous devez être un donateur ou un admin pour lancer cette commande" - "hu" "A parancs futtatasahoz admin, vagy tamogatoi szint szukseges!" - } - "InValidTeam" - { - "en" "You must be on red or blue to swap teams" - "fr" "Vous devez être RED ou BLU pour changer d'équipe" - "hu" "Jatekban kell lenned, hogy megcsereld a csapatokat!" - } - "PlayerInValidTeam" - { - "en" "Player must be on red or blue to swap teams" - "fr" "Le joueur doit être RED ou BLU pour changer d'équipe" - "hu" "Valamelyik csapatban kell lenni, hogy csere legyen" - } - "PlayerQueue" - { - "en" "You have been queued to swap teams on next death" - "fr" "Vous avez été mis en attente pour changer d'équipe lors de votre prochaine mort" - "hu" "A kovetkezo halalnal csapatcsere lesz" - } - "PlayerSwitched" - { - "en" "Your team has been switched" - } - "PlayerSwitched1" - { - "en" "Your team has been switched as requested" - "fr" "Vous avez changé d'équipe comme demandé" - "hu" "A keresnek eleget teve a csapatod meg lett csererlve" - } - "PlayerSwitched2" - { - "en" "Your team has been switched by an Admin" - "fr" "Vous avez été changé d'équipe par un admin" - "hu" "Az Admin megcserelte a csapatodat!" - } - "SwapTeamMsg" - { - "en" "Type /swapteam or !swapteam to swap your team!" - } - "PlayerSwitched3" - { - "#format" "{1:s}" - "en" "{1}'s team has been switched" - "fr" "{1} a changé d'équipe" - "hu" "{1} csapata meg lett cserelve" - } - "Scramble" - { - "en" "Teams are about to be scrambled!" - "fr" "Les équipes vont être rééquilibrés" - "hu" "A csapatok hamarosan meg lesznek keverve!" - } - "VoteScramble1" - { - "#format" "{1:i}{2:i}" - "en" "Vote Scramble successful with {1} votes out of {2}" - "fr" "Le vote d'équilibrage des équipes a réussi avec {1} votes pour sur {2}" - "hu" "A szavazas sikeres volt, {1} szavazat a keveresre a {2} -bol" - } - "VoteScramble2" - { - "#format" "{1:i}{2:i}" - "en" "Vote Scramble failed with {1} votes out of {2}" - "fr" "Le vote d'équilibrage a échoué avec {1} votes pour sur {2}" - "hu" "A szavazas sikertelen volt, {1} szavazat a keveresre a {2} -bol" - } - "VoteInProgress" - { - "en" "A vote is currently in progress" - "fr" "Un vote est actuellement en cours" - "hu" "Egy szavazas mar fut!" - } - "ScrambleTime" - { - "en" "A vote was recently made, please wait" - "fr" "Un vote a déjà été fait récemment, réessayez plus tard" - "hu" "Nemreg volt szavazas, kerlek varj egy kicsit!" - } -} \ No newline at end of file diff --git a/Simple Message Suppression/addons/sourcemod/configs/simple-alltalkmanager_events.cfg b/Simple Message Suppression/addons/sourcemod/configs/simple-alltalkmanager_events.cfg deleted file mode 100644 index b739cf0..0000000 --- a/Simple Message Suppression/addons/sourcemod/configs/simple-alltalkmanager_events.cfg +++ /dev/null @@ -1,43 +0,0 @@ -"game_events" -{ - "teamplay_round_start" - { - "reason" "Round Start" - "setting" "1" - } - "teamplay_setup_finished" - { - "reason" "Setup Period Ended" - "setting" "0" - } - "teamplay_overtime_begin" - { - "reason" "Overtime Began" - "setting" "1" - } - "teamplay_overtime_end" - { - "reason" "Overtime Ended" - "setting" "1" - } - "teamplay_round_win" - { - "reason" "Round Ended" - "setting" "1" - } - "teamplay_suddendeath_begin" - { - "reason" "Sudden Death Began" - "setting" "1" - } - "teamplay_suddendeath_end" - { - "reason" "Sudden Death Ended" - "setting" "1" - } - "teamplay_round_stalemate" - { - "reason" "Stalemate" - "setting" "1" - } -} \ No newline at end of file diff --git a/Simple Message Suppression/addons/sourcemod/configs/simple-chatcolors.cfg b/Simple Message Suppression/addons/sourcemod/configs/simple-chatcolors.cfg deleted file mode 100644 index 14b98c6..0000000 --- a/Simple Message Suppression/addons/sourcemod/configs/simple-chatcolors.cfg +++ /dev/null @@ -1,15 +0,0 @@ -"admin_colors" -{ - "groupname2" - { - "flag" "z" - "namecolor" "{green}" - "textcolor" "{olive}" - } - "groupname1" - { - "flag" "a" - "namecolor" "{teamcolor}" - "textcolor" "{green}" - } -} \ No newline at end of file diff --git a/Simple Message Suppression/addons/sourcemod/plugins/simple-alltalkmanager.smx b/Simple Message Suppression/addons/sourcemod/plugins/simple-alltalkmanager.smx deleted file mode 100644 index 6122756af68998fb531abcd0d08698e24cff25af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7028 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 diff --git a/Simple Message Suppression/addons/sourcemod/plugins/simple-donatorbenefits.smx b/Simple Message Suppression/addons/sourcemod/plugins/simple-donatorbenefits.smx deleted file mode 100644 index 821d61d784607595ca400d273a941a42e40de640..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16600 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 diff --git a/Simple Message Suppression/addons/sourcemod/plugins/simple-plugins.smx b/Simple Message Suppression/addons/sourcemod/plugins/simple-plugins.smx deleted file mode 100644 index ac307a3862c6de083db599bdb3741567fc1d86bc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9599 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 Blh*(M diff --git a/Simple Message Suppression/addons/sourcemod/plugins/simple-spectate.smx b/Simple Message Suppression/addons/sourcemod/plugins/simple-spectate.smx deleted file mode 100644 index c6885b041145a73f664650e729a5dcf8b3b0813f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19129 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%0ACwUfid=y*oPG;MRqmWr)g0 zUrrQAHD1dkPm8eyEQac4ZqKu^@ys?bv0h)GO&&4Xka(t+0QJ!s*HyVgQ=o!%&Uc^F zuFY82y3ItqYjyE!%mj(&c4sky12UOXLZ-63>oQLgPi`Flj{k~1lrU=z@K)4-SHvEs znnhzs9{J4t;0{>aocy7mAsmUIB);@AYo)%F;nooRcBawo%(%Pv^*z&bjdJa;F&^Fb ztXq`qsiXYE2%D699}+&p0Rzpl%1yKW%P(0n&?sI(@+-}(W44$!Ii53jUSOsYPshlD zre?KjRkRz2)zL?{*_boVt@*3y(Pm~?B`^8L-iRNM`)^g9d2`nFvrLb?_My602}Pdg zY$FxObHAtnX_rSA<)imLBHe7o^M}s{6LqoOTX%loUXRD@ZWk(0Yv`VEeofHF2^uNJ z@kd!3Day?G@THxGtGo-NH{GqGj^F2X2K;TFdf(LL#2=!Z8x7lYzNt%!M}UPWg06o` zBDAsnrId8revmSUOG{?dQ{NeONTWXTIWB@Blk#?@8=bCFJC${umP+(D}3G$2LX2YLpQ4Q0(!)g$0Y&%;<{P?>kz9{z0oo z&(c$qZ;=bmzt6{P`XQU9iXIZw5hOH$rBL!yA2XSraiI?mUEyo^$!2ke5L__6wq*D` zPS3?-=zBA0=nz3#qPYp$Qzq3>hzsn<&&Zn-vqy0wjCFuVf-~&JluCj*^5_p4<~Q%^Jjd)HF2;uR3ph%I>a~3Xo8T zi%HkDhnMdQ2pwdZd6CwiB)@E<<~7^Z5-YZ1T)h&d6jrQj3ct#}N1vjEDU=A!Ktj`e z9tTT=-f^mShSQckqDsl{XixZ@yNk?MIe|5_f@ub??Wtkkf=pGe53pdDB?`3jRj86? zWac*>2%}i^CDKaqF!Q1`y@UG5HfvWs6IDSKW?p(nHiv!~{~&E%4of$wYt{2yUd0QFxiTKUKGbBI zui8+S#MmwvxvnHvR6!uX9-r5A+Rbp0*(+DdJrRYo6fGdOUj>Jh?s(Ls*#p-WUnnx4 zwV={a|1Z=q3U}7Xzsjd(zlFdL6+K7}3eb135U2xG89IC5ygL+ky&^M{ShaBcM-adq!IHMO?gQULl zpic8CyqwjHgB4^5W=?-jSz?9NvC@KRk+@fS1IgyYr059=4P2fWhVdWwPz3h^OT)%H zp2TMHq1=j3i_VT;RUMyVH?zi>ExHT}dt?WP!nk!1NEs>QSieZgFsFQn_`u4dcoxoUhHEIz6dy?&GS1T`y^6=Lwgg;Rx zdMVoQ+lcPuW8JuDMVv4s)pmu#+*nenF8z{rkYL?J+^{#pn2)dA*N+xHkH7iRYE+9V z^(m0s04Fqi6O=c;K!p~P-;1h&%#93Ee+2WTajU-Xk-J9@$(h0o!S_SE3l>ep3<|&b zR?qvy^5rCG?Mn=5sNB=XC98IvM}cz-tw+kKJ?fy(r*B|#yp^bood$d1=wyNH4cVN` zUi9F%qM{0exWgr{+)=3WjKRzbiOA)X=OSN-Vd5}ms0~y#7Lzc;5bOx$1n+#5f+4v} z!rr+f_oJG;>O!kVU#r+C4jgS*>&9Hb?Mk`}$4Amw8D18f55u3V#mfLwI=CV`BfFXo zDLl2J0+1fU#KNP)sGDQH?zn%yz{E*yCxUXNU@z$O5mqzSlPqA1qpYahqxFPuqxD2? z8jf{Juk{C2yK}+tS=ai-=S7f%@L}|@U@%s-yp${)E#&7EYRI?Enyszx^GAN_%|z@| zQmCycQke0mAlZA&kVw@IBoMlIFsU1(DOyO<6~;?X=u4cjmL4u%jcP%k>7N7EEPosH zim3{K3p5|W1u0!G1HwziujzmSMp~lJVN!>T3bueE!RGq_LT-|#$RsJlKLhXftp)0H zRmYH6{v{6w-U-{F3F8XC%EhDViM}m2YG~^w_9OG7gb}&Z!2F>oo2Xo9@P^t_+^TkP zska%yU0C!)jD-@WIDngWQoK1HP?wJ>dA!kbguxr^MSEt;iSCN*is_1qhZF&}3!?@X ze2y-*H!Mj3V@)^ z+souhR4_h@8I&3{S-oI6ZI)~3iV0s95obK{B@W74*Da0ENRv9GnyGPUTPLYwVgR* zFtRy)k3iQRfZPD*s%EDK1aAp40U!wz_@N2E7H-Y}B5F~}Q`#A-UF}e-!Y;#%!-0fS z^%Q=u+ujJ{RHIMyDg$_4lBD(I2KeH*T{+uGYch}E2PHfXU;P)KmxuO5-wnYmzF-eu zzR9ufz*$i}x6JB{9OIW58;p$(Gj;&tv#%gidn4vsSW5uL#0|U}a7SOufJ(47LJnHlJ zP2?V0KlD4~lm~*D2g@g%o9J*Bnhl13^WmYYo=8&i@PW8h2zD+d&%Ygs$F%2aAOxRvVVj9dYO;Y|G&{)}A zlh;+*MSJ%e+Mq5u5K7~RBaHJ%bkL4{owtnLUq^ z16Efli4=;|h4*Nja{IdHYdz5&AWZ}MTm-*Ca|@?MG5ZyO^@urz4?}+`UL!BRJ#Mzs z?v4Wt<%B(B#UF1Er5p*U;D5H8_1+CsfVPGfL?cY-NA1Vw z?uv6#oi-MEar4+iW*%LrAvlI=hSrnVda^adUjN!pfi)Dx!h$t)=?hQ&g;G2NSVrR_ zN;2yjMCwQEXU>|lUG5SL-$rsdN_~y+0Y`x4Q}FNJz{K4phF?1)&oT0ZAVr6X4bd(j zQ(;6YJ`wH85pmb2UZEY+OCU3Vby!2#-O0&HC92KhS*`?;$S{3T1H&=HI+gIg(3avK zvq&J{YCrjo0$+iJ(i)Xuh!RX_PFQrf8(lE+x)Gb2XJ%u&OTeT%*_~^L{7iJS^5V+X zr;aGJk}581E_g(#Ggi*c%+T27pyFD{{?AS1kk}Dm!MdC`s+7t`7)#h*SOK@q^pLjz zbA9Hza^LNRN{kiQ4f!R|RNFxiO|k6&j?pbM{W@3Jr9=_|011*=)C-}(gL1;$kahC% z0@fda32YShLt3)exA3HfKA_fkGY`(mIedSk|NEyh-P@7;4t{uWa5nYV z+64FUUvVMc_etK@>MHs|vWAliY;I$lZ!m+DBfdV^mPsDz*yhJHs%uL@b$nFHLu3b_ zUYb&;TU$7)g-!{wrA};3-^z&7)#-zWS@3;@{Xh=GzjQ!OFHq3rS*XJeZxg?7689!f zt$2Rbx zl;%V;>%!jp)WjER!dMR(w$cT?59iKToc!XOF16-QfB1xSImXP(;no^~#T1JslJsqS zAANf!lxHfKV)Tn|3{x}%VmsDTWXmNvt?YSg!+16S&HxO%`h?zB($dr&a%t_4)KpAv zwVwuXu+2tFQP$C_c}CrB`qk>F;T`@+>zMq6Xl05~N38kHf&xe_7)|?TK$LZGU@&%; zvJqm^uiI`%cpruq`Ld2`VakJJvks%;9oBIuc^}4QFlK&iHyWJjeXX40sOfZOsWieO z%v316-^&~MQ}hq-yE-j9HO-X$nPukpFZR^G%m}V`AKx}#ciOmMUb9u0%9qe=Rh6ts zgiG0M@o=s7e@=0`N0XtcwZ4CE+hNb?2xKZyU;Q#%t|Mf8aWHeDm+hg6$F;*BQOh5b z!{w&){d;QFK;HtF%nVt)RkIT!E%nwOMH*YQOrou)!$8QH|k2>w78TEZHZI zD<#LjvI6q^Gtn#;gQ?;J;D9yEq6Hzt2Cr9}Wg1$V-v?{_zDv_izx(Z=72|nAu*l27 zrse9K!f8bx`t5a7E{S~zWqCWGh>b5}u<9Py;9_jk{|z;k-{*<2mwqNmhhN{S�XP zM5L)&uZne^XHs;_L+03=Xy3CiU1O76^S{TWu{zY}Jlq((BV?9EL=m4MC%~!W0MzeW zOjQv*a;A7AS@l%h9EbjzQ3d}e&j~R0VCoAN)q_>=)m=>e=ZX9w8jM3&o1RO^+0jJ) z

_|h)w;)ME+|h#gx@oo-|ZEuRI5d) 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 z zz<>ukh-T0O%6a(J73SKH$i0Iz_(zd>wTqk)sb2R;cfi*BfN$IWoiHas4P5=%s`Dr0 zzvwSL(+FkDP<{Leh%}FzA5w@p7P1(m@r|D0-!S!O(YCNw)Gj6b!tXxp4;2Gt$7AePM=p zw4`4K5dg)Eus%;R4V8^S8z3TJ5B;JeVVHIpU4vsM(~Fs~L&*c<-~7k3-vnW+e&qk~ zIuJi$qG=4XvI2zC!K#gQULMKYu0N{gn>-cJyV1ljVUs&NIIkPW)NORYH9l|~323a!?Y#i!$%MFK0;FrXEbCA73jh2Q+@Ua;IJCz5rhEM94jgcrGse=X&mEv zMF+(k9`b#=J}~6uRJd0VV2>tg+E*Lshu48oIl@9h9#F&F)|xbItq9KkjNYC7z|u=Q zDJMjq_t4?ekYI^?jJK}SSF3(UC*I3aB{X60jO)uU5bB8DeIcymLDOrC-aP;%?OVPE zj2i)fg{H({UQBbckT+v7+q&DS+a~B!C4r}6$>D%-%t``ePy{7j2zQm{%)7f#WL&%u zsekyeV6ZH>pAn|Bp{N2~?A81QBd(9C!%l$S{KWylzXj1jMF5#-FDB^SS9gpYzh^q` z#x8>`+Xu7!sSBGmet?-XN^qQdM(+a0<8vzfGh6g|6Zt{L= zdQkr(=%DaH=VDyZsOufB_1Ll9q6TnEhVfuJO9Y@`sY)22`QcS{WNN}WncDDu(EK8B zdRd@6!ywYYOv0x`k^ubev3OI9I?2=)X(`le@C6s}Cj{m-e~M=A zuw7j6VRCzGdv7^8Um*bSgnmH>bpw>5Q_BSaXl@|clElei!0d1`POs*d%cnq%FPYIV zuj65S=Idof%LhYFRV?I0@IsQdSpgRB1Cn2FBoi%+YTN~vbV#VKPXSB`rH876uMt2Y zA%Jav^n3;=XoPz*iyO}c<2q%58X$$RWtE>}N(-fbotA6D8G0z+jLA^tr{N5UM!Pk{c(i5TNj`@*xw1y|c$%=qf zvR@w!UuY&8@L^y+3=}mzgf6L&tv5EU@zpy zHWz>fa?Oqb`uI?@uUi}7xeY?oFp&>b4EqFW*dRof()56{Ns?hYzf4<+;FhLqC*fYL z`w;fJf3W~;A%+5^dK`@bB+1+WDF(x5JnpOBlV`jA$ZhV|XbV+ML+#c6$_!-(Z;h3D zyoRl%=})WSm-f!52G1_~)XYASmCCjFxf(MxmI+5h$o>RX1IMNSLbMBd;izqG!18PO z^!;w*uT(X3d2xpOB8=DP4J0?_%*us&-@66fu_`>ee(!z?=ngeqs7d7sKTr0eW^a|V(j_kcaPs813qVI^-ViM zFlm>-v#e~pd@uYF+*uY5xWui~U+c!KBQoKb$fpk=eK6L%&PFgvewO=EJr#y=+m^rV z5`#vKS?9YF&Jf@r0lJD7FyJ^y!WYN4OsE1WhEeaNn;Ggq8w>=0UADF)yA>Ir4-oBH zQm+S#Ovkya(VrE z=%*&Qd!`1>T>1s=h1v)GMQH7S>4ZirAGucMMF>(MP{scu(nBmEVc5v@?_mB+L8~gP zW$bo4!ppoF3uA(iAcw`k%GaeNSBOOd$y?2uCi7hg(~{!9jRPl0Gw=8%>%4n?os0yV zznk>Af=m=j!ap;H4$ktS?CVNrF% ztOqJKkJ#c*sCT)e(}eG8yhN|B%~EMvF44%_%pysp((T-aUvx^09Q$9A>J;V6CreiE zd+}^M6`p_ew9Kt{Uwsai}m!5NKdN0$eBlV-Q0U}a1Z_ZFsV}3?I$C0&^Cs#+ld2;4+DUN=Q+@D}~W7^H2 ztLyTt;5=Sw@O+(uwtBQPWWK7TYU5Gs}{< z*%-mKS=mY0IaU$9d8(Es6Lq3~iKG2di&tHYegkUMNscRilSMwmV~JHXTM`<_!xbFe z-4yoAd1IPNP+`XLdBLkmLrbaGoGA%l1GYy~&)(kIZ|}^*`v*_IjjUg@2RD;y=L^Ec zV%)B_9M&O$xpR5*$nHviOopI`!U9(_^(3~e8}9utD;$hePYIr0xsFM6p0N<2y*4W2 zYWx+?y>@Z7!Ei0ayCDc=pHpGara=B}`_{rq4;Sfl_jAe1+q+*7Q|D---5xjU=~~*W za4@1vP)A6c3QTbv#qU0VTEvYQ&SQ*xcfOZJ^U$4Kk2bQVt5e57Mu?ShxLnXwO zV?x_4n>&u4DG=?G6olrPv`(E+_#Q^XO!Fl)0BI}kaJI87kkT%z$Jb#Lrw>PC`;CO; zY$QTLq+o6C&m@P1xGwqo;5}qn>O-Q=awx8b^f?tF^iCK)>_D}0uet5nCP0pQN5cem zcjm`ABVh(BZIVyFdFn(Lzc_-ox#OIrqvu9jO<{iFtlh0f0g?0HpytFvPPrtqh65avAaOsE-zlLkag?6Y+ z9Zo!u)@d3*U}clJjEGNIcYTA(iu*E)XNu^5P{oAlIF?hFp)N#j6&k#n46+ta>ebjz z7B#yslkRusJz?GP*E>Q_QkLN+gXHV(C-#=i>ic0M?svQedd$26-K(026!{~pPm`Mn zE7*it*;@+-Jwr@a50upF6(LCA9M$fDDr+P- zmS|{7$k?izKl!w)Z>4FlZx{AaixO!NE}PN^Wb$%_2v`u^O{XBihc6iWl0XAu*UsO* z4H=y?;Pk>ZN9*o2cFhYGGWHTvSIB$G_h#maTkHuyZ>`Tu>#~%i#q~nE2AryEv%fx# zN~qQp|780E%_D+HCUY5~GL;)7_?!(hm$ydwoE^PdMLuWCOy&N0K4(BJ zUZWKYO&#|i$A;6kx4$!!sHBWKe-+!fXIGi~&eeOPndGG#2k>@tISjWD_!$%5F{VB& z=KaK`$eFk#{A;q;G8)phk`%gO8@4r4X9dce;6_@l7nasZjS5Yw!!}x>(KsYj@;h6x z4O<;f;;cRt$~{}5sPyEdUh7Z62J)1yeJ2qeaP(0x=@^=G8lk2!7!*eF<0T*LDlAyl znG6oQ<25v!Z25P-qFDLBkxfNW`#Jd5?`*vC0fk@e?%1it+kKe2>eKM3YlF!o^XA#g zw4OI+tIf22BX+2mUsX1+~~hd8uE5JX+u2fJbI-b zsJ>%RNXaW0wRP8EbFXeC@hF&!|D9WbxWl4TeLbLYqv66?b*6jjT-kRkyC(!zDHKF^ z?0{OsxVvff61*a@+y5-ua--YY(2CWco6keKiVtLZzlT% z9Sz#RbGp_JUse|e9K_@#32NW=&Ah?r^RCvPYZT`RSi^iF>UBcd7s`Wj6$+rX6A3)! z+Mz@(FDTh6qV=P?=U{f2R4%rrn0unC3+Rc+>$vjUut-hXeGhA`3s*J8Q3F4pDSPDD zrwm_wGq7_CKzr`&&#?rApQMsydjM>?oIx5VE3ORroe~=ANSEgu-pNf26y>h(AK)et zDgDb_G3425cDU|2xDhulB0IB5&Mk}RuSAd$#_r)SKiB;87q`TuvLR>ldVA2OEnTCyJflXnzS*Cn z@9d`Kwif-Fg345_ki26jZ23Q>QXk=s+^6HYW9;**2KU9?&u?G%`CM0GdS85NK}A1` zxc`uy-ajiRkf9qY`mMwK@fNWWW1qGviU-~nu4W)|D9>Ue|1csZ*-O1LZ{BeGf|dGN zjKl3Sa#^#yzu^$_L{L-KyYIF|B4(`0IAU*fFvs2=H;H~f$ocygvC8waDF^a>>V&y2xT{YAn*?R2bpXm2zt79g9s46j(iF!E3cZ#gaLUgI?^L;fH+Mk2ubCe z$X$|$SVC9_?-H*h5YOA>Pn)#`5wCABW4PE|5Pn;-Z7>M@kh;YU3kb`H`xI;?@k@&< z=)KgC;2|MA8kcUuNP{|n)F#n-ldI7Bn2KwrY3)Pj*z_NWYC%bQH&#Fnu1nCN2zv|HpIA0T%}KFounObUzFwsC;HM%b~h6fN_Lgdps|iY z8pcFZqRpnI-i$E=jviB_$_d0o@Pff!M2{GTf6^LA!F0KA;U>xh3h_TC^^hzc*{PGN zNUH+Ue-Cfro<>-=wtmi+{g1Il+OCK#kM;M<0#uy!=~kO#+#zsz%OYleWazZnSHz5% z-odB4N(dz!`%QDYw<4N=m z+3DEh+P)Ie?L3vBkuLv`ok3QW%6BU|%=ajUU=608!F<^za5OZ(NG6%O|GwFx(^*=} z;10uXp-j9Ap{(RmJoJi*bwe-Mh@6-p2;;S|<0=!Qu0tztyPY}u(#wBkB)wdj+{TX# zFzdDuk^c#UbgR-?yst{Hv+T8J8?3X`ShnrDT;_?|wst0!Ew{fo`*zxVn>gbI18L96 zY5A^$C((^0vuQ)bUZ%3eU%H7po+i<#r}?pAnkLCdF=Z7Bwb0oDYA`6XOuS@bSyn+K zNdNz9Xs=kCd&OAb%Wb==kZHbaveZ|=a9W@*qRG{x66mO`n$HsVqTSK zm&V8i63RtcfmYvZwHM9^Cs#w{Yh8q(Cfp0-a|w!a#DX++Oi5pA83rC_mL*f?9V!7Jt~&<;+gC7blGpM z*K91J9uWwL_*n=Dq(%q`2u8?H^}m)#8v+9MlNEI!AU4n;AijMv ztvv(;(Ps|EC(AlOKp1^mf={XVWTwwJswol#;gn;;h z2mvAd$-B`I5SE`-?o*^=ARx3p>uY{;ejWsb8P2DCGE6%J#P?78c}ob4Pxi)wfM76n zFf)f>Ff(>FhG1}XGqJTYb@?A~H+KF6dt+BCck@qhHMaO4*X}>Z%*5jVU-{4ZWo7&S z;`WYN|2N;t{+Gl59qHogY-Rsh&2#O-56LrGGv$MqP?};48VyZArxgEd zW4>=F+dm;yp5O6kI7Gi2L;cg`Sdz@lSkNsfzHd}UM**VfKNx82XT`BFKK}l#AGcO> zRjvzguUcDdpP;E|t&fUgprKjf@A0|x+Xi*BCVguZcn!!s+&$`axm<2L&IP$$b{(fW zuzz!?n|OwLqviZ&I=B-MJ=Ue%&L8#=55Q$d{&+b6vt-NiSfu+Mj5j&jpArx+yW#IT zB(Y5rV~wFX2)5Bk>czXZ-RekP;-nB7chzTOpuv6cl3m8K;O`ux`Nq>#d=0+p7v||qJP;-1ADgwTM(SWJ%tNm4^seC%`+7Oc5sRU)RBK? zmLl&EE}V(pye6;jxpf`5bqxd4M?NWddB=q-Iv}CIU^6pj|B2eUhH{x`0K~RM!`B~* ze~KyF9e9auU!ee@*fZ$swZ$r6=XC@7Fja79&*p9ohx_(Dx(ZMqGulf60~7&x{6Um-67z|R?^mnv%gG|RpDWX z%;mj6vCKHIO$5xCu8+NU>u z_R3FZyG7C;WR^)eW*BQK1q>|Amm8)}<+DulRoUN_md>;GksZTNyl7l75&+(~zLQJ~ zV9l!>S&oD|@5CSX=8XphFu=V7pnBNh{2)CZpV_&u06)hWZINCh8iC;t`_5_05I@g$N2L11>~)pNOMvjS zd$pHVsVI9ZLnUth)WUlj)bJ$fz{>IgV}XUEXw)q(7WX^)rPVNt?zDODqJ4&Z zpDM!B^v4NVn`xY9py*cQzF|?X=BWNCn&8Ehd`r}}1k|mLGy71+jpS`a0ALTF(t}7A zJj=H?^S9ex0zol3=f>j@H9!;LsRK%T?`k?YV1#N**%_{3a63y9Jn`d-q|N0sJ`w!h zM&<+Qd{~rm^W;yO*L400K_zjfx?+#Ms|W#@sS=C%8&a^Q#ONQV-abLDyh zIl2kRKHAn=+f<87fDB5_NU-6eo1h6#1DjDV*CL4lbQby@%+$Jol=F4hfa^Nq=pF(8 z650!=KNVWQh~RGLfK+V$j;zwPJt$`2GDKS|` z|4^xVROC4w%MwBM&ncSPK(Ngk53E~@Ls81Hea5k?T^!BpuYST*(;xHxTZ)Y1Lza&2KJGLhh15gk(af|79-DIhSR3@h{QiL%!APratL&GSt-OuO z2i}orx(`>(kEG0=GsR!l?-uL7Kyn@bup<9%|6NbDM_@0 z>DrTV&7y)5!F7pUrh1DFrFo6+HGgp^?l`JKk)KMjpIWqwV|L?=<*vd3d<*-CFaDvD zO#pmDcUY;@2}7Fc8`Eaugt*GDS=b}#3?9W7K~8E_kG+)Ll&$`Z5s@+<^?D7WWy@am z2``vA?~GyE!JOvv}&|@ zo?(1@@;ylvsX_D;?_nnGdh1U1eEI!?@8hU^#_O$~laT1TJYyW}HW%ALdHBzTYj9Fc z4FOn(p9pNbTCIEq`W45hnbz3t7vHS-XZaLg1*@X}Dgi`iuib*x)ZRrklDf%xJj2

yusGpqQ>6ExBn@EdnBPfZ8~n=Zw)h+;v&k@ieNHd; zaYF|R8xN>hgK8hLh7(zSs|V5sbePJifkH~ReUv>~bPhX9Z+?Z*9Se`)dgS^|_tE)H zLuOq1zH~{B$I;9$rkOVjUQ=j-RN3(UJxT%{n%35C=y)DiL^C=w4tEmziM#YUe;Y6u z_?U5*LuqW5wfAh+S@=2ud}l2-ii%PgXYT#gmzB9sL*#5T`27Q%)#e9|NYN!5Mh8)= z{O}U?e>*(Jrb!dh4*I{GW6cnDF%o9*J9TlroTh*`JaqlR_uYfwZ`;2NeU2s&{d`rO zy~8;?2)pQ2<0_i?VTKy~wEL$#MtQ&93}Z=W;rNK>y4Y84J-keIr~NM0^BeTs2f4V| z+xl+11@D8p+xFwHjB(amIwNj2$)C7}a%c2xrhKI4d`gPrJ=NAxx^lhx`n}plh7#n_ zXArABy7{;Ga1Z(DPPxgJ_pR-HZ4HiiHZyvvDODQvMw3zzwJkGzc*A`tm)Z}m=B9mf z(p+#wffH*$mKTgs;ugxNO0S9h^^5vSM{5R`19y<#uk*)q=W5Sd$?6fc=TMIr#*z*x ziTNZ4Tl|^>TR#41|6e2IZVU#IHfi8s1vm?rX+GWw)aVaV;4A<&IpY6BMg7?A5CglP;XHc_yOo zT!4-<8|K?1_Hze9gay@y+|$H8`MfoZ-2%ha(a@zmH(aUC$Gjon}galjl!1B6HMbYfrP`n z!1LrtJ&PZ2nK4`RcZNhgiVWimL4@;`T_on+8_d~5Gd{)N`M6_q9X)A0R%JK#_DOUXLkAs~F~=H1 zS8t;+vg;vCE>yle2VLFt%9pEz@6OA1*IEM2gNeA$+%v1WS|&MfP_aj=mskg%Qt3b8 zHH>>&#%?o}IO);$HDw{~9rI}8z-5zen5&Bww}D z`9Ymr(H-+?j@PywWvf@8?-y7L7Br=9lySh7w&c+^J=U$P`ZJi{)VOCCd`nw@i*927 zP^x;fA1pxj_jHbdELZH5EFgDJ+pOu`Er~xC_0Zmb8S5CnijG$Tz}=lhyUhBKf+*W_ z8MmLkJ8y;uB+Y!%kN*WXN&DlKH<%HCb}(3SU8e8!^xs`_Z96eQBZL3;50|oWF1!== zJKNTor>h*#w@>U&|8X6!-~EhV;9Sdd*(!aebS0i(U7ueyM~|1JOpO;Lz}J1>8zHrL zoqn|B0^{PnR@<6J5*RG6=IH!tGR&uJ!Xp6ZMFnNrUqEIDIC0bWU9dQ6Il$ zagKFI90B`c+A3+Eyx_C-Z^qe}82PjumJz4YfY$nqA&nitDvsjm_CNeNG&6qorU6|= z%RB~Vf|9Q0*`6JmI`_r+_tp9dgk6WUbl!^A_Zpf9)10mSf1e72x0*0sW;@n}uevc( z@u+yN+_FJV#dR|Y!wu+#H@2y4kGyl~P0l9WWiArajgLHYYh5foJW@4{XFDOJo1$pP zILGJH!jj#lw5-cQ;ppCDZND23AZjruLLe)8VNo;Lz|}kMdpZ(BDnYBTZ+|f@c$Xk|Jl4N z+u^SWTtK)?c*{z>3xf3lmo^`1_}?A+*Sgerk?<&3yJqJE#!c-1bMnID`Lj+KA6I%V z8j5VJ{{Ce5jXN%v->#M*0TavUt)sNc;+bft=ht3&j#p<&%r|Jb9V#8V z-(4SA2_kA*GQxgUOyOB}3$#BxTv(>EQd4GDy_>ShemGSnnH#ly-A?TISXum3mezGo zgwHvOA3=^hj7!a0o!C}w-S4Eh7v&#HpO5;nvi)&@e++wd*}p0-Z{M(M z^Udj^-}ex(`?-7Htk*PcJs}UQuA#Rm&~Gw7^eC|7{xjX)WWGHCbxB|ESJpwpiucs@ ztL=hAtoA6TN!zu|g@QirVV)h%Kd5*D*1yVlwai&se{uuw^-}q#Ve(;+T)WF@rG*mj zjiT{eq1Hg#1rN}+JzURfQHf_!)fw1xmv2Eo}v*(`l;6t!~zQa{qXv@D(zOgg(54(x3WK@`z7<5zhC`r zNn%z4!a;HVCXXl+#qx>W#S-@{^9c8B9p16n;wqz)p{uI>YT0(Ou6uRUx;b3WT>^f{ zy!ptA*_gsqF)%6Tv)rn(|1v4>bVE98L-x?Z6QyLy%1E)T1v83rdT^ZM>a+<#0h8ni zLdlgX^@qlY*H_Vwmg4@(teq{7X6J1d;kJ=msweKRcfJIN-6F;e9~sF$(_Dw{Ytp<$ ztCX~9b}PD8%eXXtZT8WMp%3b7Zr0Padj!7b_5u~|NLes6J$if#GmKnU4EPs~C7Om- zv-cyFNt<3vWAcpk3TxE`3TtEk%*S5?et~oSpup2ZpjqI~TQ!1bP55S2 zsNJZtqR(AvN$|3=qU3EUCB~y?k@z}cgM#9*c1cT|YKbD(Iqc~@-_9QoTfE%zms8nA zML}6FecmDCG=^$@x}zxC)P<#gADI{-6^7a!CWk6cjnzWM7fE+8$34ShXcW=01_;5< zU8NscX(msWBd;S+cXPvGVn$5Km-rFGAgHc7OS0T%FpuciyA%%-SGEkCH%X8ZUAul^ z)_@=$LTHZvtQt`+(RY;la9C2E4Y>XMTrINS3ea;Tg}L?=^3?M+%s(Unc+~%rq-<`M zRNJ6VgOvDwM@X8kUo(ZKWs*p95;%6 zVu+q!3tmi*coGLOk07Cse>Jg<`$o|$sgoEfjJWzk9%)E~S6)n(&AwRl=RIX2Z>*9h z6At0Q_0iMb0+Fq`AvvJ)Ht_H*;ojP_V(@p*j%Yb+zNO=y<8}dOih@Lo_%}6SYlL@( zR4RryOqrhbsxf8BzNw@u<^oouLWS z{>@);3}DN3 ze*cx9A&W1UlV+~H=*NZ1G3VFlKAK?P{o$DV{kRK!Fs|k-xngXdVMzhk`uHL|Mb z>^Ar45FC90!P&NA;ECJjj)zZh*2DyqEK3X&u`x}?MC3?f&*+<{j#$B)t zilNyY8Mh&P44>E|d4m~iJ&j-ZlC13$QuyUBzqK_SlQ zJ8SA~z}B?2COx&se!M;Pd`z~5$Y!aUftHEaEQHwZ9`Zd)^LW@Jf#189Ud6cnRqHeu zJEp4{N!`1b2~iOg6VuD^%VZ{M*)A|tYx8-ynE9|_$Pa45rY>#Zr_&zoo! z{Mnt&94UJ#61}-kluQ$NAKx8yB?$ ze+UT;`;XJuM{!bPX|3^c6K$xB))W%-%wZzGzEUZ^N$zlTr%5TxO#0HqJd(+Bp>R1e za_38Y1q$Zb)cSt)UteqXIhipKg8Y@OxC>!iUKKJIYUIh9g-gwV;iG~)j1OF6OljS+ zOtKrb2it$IpM$sc0b2|act?V-iorc)ov+#J*@ncS!j}!0C`e?YWl}N+LH6EG65soD zXERVJ`YA3}y%lwkhb)Ov5uzV+Gitc23YrFK!waO#6(nGsV}C-@y?)^pDHBqeOiZ|K zec^P_>ME{kv$_#;~!@=#+%4z#@$79t^c~%-r!@9(U z-3*!~%cUsqT3889o2p@d|6avEU~&lQTXMg1&ynADl(XdNkCGtPJiMM1=`S~Y;V*N< z+eXVAfY@Dh$$B)oy0*b=5m%Q&WCL+pai^GdHhJCBut&#;e5kUtR|7R3;4tZ8NB8#&%{T`1U}J{Qb9+w8vR8VS5sF=5MI%eh2YD&8 zo@?A&Z+?JI@t|{>lZ9 zIfy)mDn*($XS_UioiiBzr_fe*E6+^a*TfQc!@UDgY7Yz46-2E7>i)*t?-&DI8=d)M zS~#&r^KK5Q_A}zXey(U&~Icoo!g=Nb7W|mxtse|GWlS(xn0j z6z(B{#Q46Ki2DVGLre0||8~XU8TfP3*ZNF-qG3n_?zAk33eMEEs-EQ>COz^vjtik; zjcr@7Mw6}pSD3#=dt$xxCo?bfHYY32nCb5&a93vexZ^CsJ#ss6ew(zI*`BiCFuKBd zvi8`Nw$aI+spN?1q10;WW$L!9odVW~Vr`mWZ-;k#b{T`eydvzmKrU4zZ_6`uXV*ah zf1#E7)c!J%1iRF29!l0#SMRyGW1v20YS}Or`qqU}ng|BEal8cJ*gQ*j8X&8*1`K89 zKp&52wJ;t%Tx0iTKwE5>V>j6^DK>xSyD;raOdG#Tv+wq~=ippF9s#Mf;ywk7ELG?+ znE9PFi7eGUQ=P+ymXW1DVh`H_EKWS+QGs7H&?^6KSBd)?SRnQ_84R2dx55B%0fv+x zhzIZMQ{&4d&Z@?wcos^dRm3fE8=?oVqeuhYTx}i+yb71B2h+bn9BqV&Anvy91lnR> zdlC=IHjD$EPH?w$P1;pQSLO!#!It1BD|6uRHJz-t)QvX0e%sytrV$3gNgLBj`ZA0-|0gapR=Hi$0;z4TCXR@&~BjwXq z=bCtYb;w999fW+sjbNp3X!;pN&EC#bq0mLp2aNDf0@Db^wj0z#(d0ry9 zN!7hpN?18Y>28r)@VVAX;0nM5f9fkNuwKFn9EyM{nd^pdrT7H=yKVwk)_1UQLaXfJ z+dN6#6)G5MdjzT7Z%@nEv0ib*516})?%ir%X(-JX?C}~xe`}PZm@N%o{TSH=+JVhm zkwp|ZLw~Fd?h>f$!QVJS_kr%q5vaSu-2kF<2ms)GO}2@i74m);>?r50;GVs=DrVPx z&Ap9$o7-U(a2hTL;R-mt=Yx0!>PA-H3FMTxRfRlTrH4 z8#J8kpn<4kq1bsiw4o}=BOgF9HR3I0r$ct|4Y(tTpyILk)`sS!!TdY}%_%}4Bi4cP zUMq%|a`J8!=}B4v@_^=rH&ml}bnc);_x-(dt}^T4u9+6an$%|w-6Di6Gqff1-GQA? zdj;;QYn|V5EFrF4~(K-kC4@EBLjuM(qUU3nB4}=(SmyRsfuU zA-qZ5n2OSa}K;Gup&oYiwbdk76{Pv9+ic zX8T(w7qTB)2x4>;%Q|)@JTj#cbxjLD}-y}4`t%kEW+S@Ig7ec#4Oq9Guk416A=VrzDey9p`y8PZ`-PFt)5WTE0 ze?=Z@pM&ymccY%npfThxb7GULSfh5rOQsmfuQ#;pX8-2lq4*=NF)BuXdB!p5#MPx_tv`r5 zAw8uCvpd%|Or1QddG!KFajO|Zdq4DnnU#ZLw(4cLJ}M?TumL|rks%iNUa9?1okV-nGOr!6zTR3nGq6tLs}R3jL?z0cfr(9n;ScazNB@*p4OycuV@vwcKc65)QUFgMsrtBB zK9(bK8Cu$*w4ud{SKKXImr=pCKHXpkr`sF}YU})aejlsSG$`_B^OwvqZu2}YUrQ|| z31T(@S=eupk|kN(F3P^;hH0Tg{#Lm-)sIovW(}9X)&_WXva!*=>;LXw+E(YX|EmhF z!9)8tZSAb7olcVQ@Fe-9WDOP4V0rXsFmJ(4H}upG?|)h%H#rg$j@h^+bUn7^RlD#G zqAer;QkW6HHN-2bR)Y&LPTAuNNu3f3DnXCmA2xD$!%1K>tDbj|VR1;xMb74f&27mJmB;cY`B(MI{bYaO5ivPDFzEDVF4V@y$T-6(o zlz@+qs;zo|7c{DHW)McY2Nyc~#u4t`sLW_#`-gxcb;Y>!(g`~=Uw$BgELJJfZWbN| zsWK`hD5Qpjz72nq(@V<8{o0tHt!c#aD-X}C?w>j6_$fnJ9fAehgFy#Cy5TkFn2n^j zMa(gi$|H1QSwCg8n##A(vkq#UDDqdB3GHvp)krrEua=P#CVCzxNkbz?QhYJ1Qd)k^ zF{Qz5EV?f?rYPX2n?Q9e$4VJyqAbdF6XLwL95wKny zaek7`?pShRmdrhw|;p+Zn@{LH0j#5t7wXE zec@YmYFQEzFfWRMz2_z)A*gX~*n7^~plc<$?#T$c!QA%Zl!d%J)N{9SJ77U++Le*b zmy}8NRQ*S4h3ILUooDerXmuY-P^F{kX8m z__Q9s=6?eKlX|XCE;PyaZq}UXZf^Y|X=;XJ1NpyAukZFw=CH&FElogq!cOAu5340< z0_S-;eZ`HV<6^wqbn$PkL%Jl2penTfzHaRu?ngM>S;K$>HM?*AP(Euj8p6K*)vPG4 z@p{oX;dDDd>GEZJL0g!k`tnHWAN&1e>|^IJHu~?Es<`s6WFz)8wPVBdFupP%bC`O4 zqU#)*>%=cvql*|TT&qgGsmsehMqkA@roU)kSHW~j{?q@{beJx~ZAB5vUvmM2I(6hqqgLG`^uuU)9Ec2oPmdN~bBzM_yy>g41W%r&ZQrP2MH z;L!RC$nFt>Ul0iS%!OZ9x6Yr)Ka0K+!Yj(i~hS2>63_d@RmE z+++Rm0^s+EkB=oyer*)CZlA$4FP`Cu?wA_!ShDf0zYCvn&RfCz4u?Dy7Ko2?GkdxZ zM2J7>?i$C+3Tf3!c(jUrlNZR?OcLl;x#7qgj(U1tNLKXoT^VWN6}X(odAB+QVWh0J zER4VqqDTquZ{nHiFmKD~t54SO-DBM$T~kJ{q5(^yUeucivF&I4JtOu008ly7@(k^n)PQgeeWgb6$WpFsN4dPU%=Jrm~ ziQSQ7WSuiZtxn0kctDi5W{--8(&rPmt`Cd{2xqjn_xCjir^nknKR8nyc-*BCw!~^9 zcc!43>1kYUd@WfN3_7?`CS8kn$eOYggAIwfkmmWLSn(-)_f5rn>FV^J2#23z@G=d<)T~%Bk0YiNVvE+23JN*$ z(jEP{M%(+*ry0x%117os?k+@Z1T7db2H$6D=?yJN$J-bm*aIyX^-KJEzjaJ|wBtry zTn~;^yfa$}@jbDT<;C181M+YmU%npjM70Zmr}Cj}xfAjXyr_m`BJ!}D|}cX6Y<)I)NHgDtg&=sY?Q z-jT+oua8@sgs*!N82V^;(EAL3f_cE|G2GAr(d^;~HSX7YAVk=nt++?m_K>u1nljI+ zfq5D%p$z`|UDz#OWV|pIl*Vu8wa0H+MQXoLKFeyyO()lbvl-1_ZeBCu7yShm|D9TN z4}m9J-u#c&5d^n|xUPxd`X%Wx|rjH(c@c_e{I9KwB2WF)nE> zbSx>^OiFZ)kZ}SgrBnrtmOYSWP~p$4cHhO%RAEDewsIqG0cpqZ<mQs>>a==?!YS zWnn--=(B2TJQt0_Y98@3?4(Tb^#xbw>)S7{f=6jDmmki-Y5l|~;WTZ6?J8p}7dL>X zZR2<0Yxt!s=H<~O(c4k@T^zD}PbsB8XD46#iWnOz41r5v}h6G?50p|4G z#-;s^b}TT5-Hwo+*;y1Yz#G0uuYjg(dwwt+eGmYoF!;A&IrF)rPh4bVY1uQPXUD#$ zVQTzCJnzYHnB((crG>rLp+9K0r+CWqOu%|0F>nsG-uc!iF?u5>aOe`W1I6H<;Fc6! zBV{kaOR^H=E_N+^zYk65d?Q2c?@ed^hGr?hep#Abbayz}Uz6XR|wIgru`Ea-EOWGU!PItLObi zAx0B=`*2T_F+Y||>^iu0O7yyb!9V3zmBHT)Eh@4YV*A>P@)_fv5jszpm-6|e*8^ba zauXf*Ph&@X?8EVfHmdc_#fT%%o`)}MWR|tT3$KeOYef0Oj?aD%MzoaSI?)I<)@uYI zwe7{*52lX-Fuw^l*{*_)pEh0`Vg@X7;fr4@aQ2jHie7{9G>o2)ZmG+80B+Fp&}nTi z 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 KvHt-#rc|>H2mv<$ diff --git a/Simple Message Suppression/addons/sourcemod/scripting/include/simple-plugins.inc b/Simple Message Suppression/addons/sourcemod/scripting/include/simple-plugins.inc deleted file mode 100644 index 8f21956..0000000 --- a/Simple Message Suppression/addons/sourcemod/scripting/include/simple-plugins.inc +++ /dev/null @@ -1,337 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Plugins -Description: - Included file for core plugin in the Simple Plugins project -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -*************************************************************************/ - -#if defined _simpleplugin_included - #endinput -#endif - -#define _simpleplugin_included - -#define CORE_INC_VERSION "1.1.$Rev$" - -#pragma semicolon 1 -#include -#undef REQUIRE_PLUGIN -#include -#define REQUIRE_PLUGIN -#undef REQUIRE_EXTENSIONS -#undef AUTOLOAD_EXTENSIONS -#tryinclude -#tryinclude -#tryinclude -#define AUTOLOAD_EXTENSIONS -#define REQUIRE_EXTENSIONS - -enum e_SupportedMods -{ - GameType_Unknown, - GameType_AOC, - GameType_CSS, - GameType_DOD, - GameType_FF, - GameType_HIDDEN, - GameType_HL2DM, - GameType_INS, - GameType_L4D, - GameType_NEO, - GameType_SGTLS, - GameType_TF, - GameType_ZPS -}; - -enum e_Teams -{ - Unknown, - Spectator, - Team1, - Team2 -}; - -new g_aCurrentTeams[e_Teams]; -new e_SupportedMods:g_CurrentMod; -new String:g_sGameName[e_SupportedMods][32] = { "Unknown", - "Age of Chivalry", - "Counter Strike", - "Day Of Defeat", - "Fortress Forever", - "Hidden: Source", - "Half Life 2: Deathmatch", - "Insurgency", - "Left 4 Dead", - "Neotokyo", - "Stargate TLS", - "Team Fortress 2", - "Zombie Panic: Source" - }; - -public SharedPlugin:_pl_simpleplugin = -{ - name = "simple-plugins", - file = "simple-plugins.smx", -#if defined REQUIRE_PLUGIN - required = 1 -#else - required = 0 -#endif -}; - -#if !defined REQUIRE_PLUGIN -public _pl_simpleplugin_SetNTVOptional() -{ - MarkNativeAsOptional("SM_MovePlayer"); - MarkNativeAsOptional("SM_SetForcedTeam"); - MarkNativeAsOptional("SM_GetForcedTeam"); - MarkNativeAsOptional("SM_ClearForcedTeam"); - MarkNativeAsOptional("SM_GetForcedPlayer"); - MarkNativeAsOptional("SM_AssignBuddy"); - MarkNativeAsOptional("SM_SearchBuddy"); - MarkNativeAsOptional("SM_LockBuddy"); - MarkNativeAsOptional("SM_IsBuddyLocked"); - MarkNativeAsOptional("SM_ClearBuddy"); - MarkNativeAsOptional("SM_IsValidAdmin"); - MarkNativeAsOptional("SM_IsValidTeam"); -} -#endif - -/********************************************************************** - * When a player has to moved - * - * @param plugin Plugin that initiated the move - * @param client The client index of the player that was moved - * @param team The team index the player was moved to - * @noreturn - **********************************************************************/ -forward SM_OnPlayerMoved(Handle:plugin, client, team); - -/********************************************************************** - * Move a player to the supplied team - * - * @param client The client index of the player to be moved - * @param team The team to move the player to - * @noreturn - * @error Invalid client or team index - **********************************************************************/ -native SM_MovePlayer(client, team); - -/********************************************************************** - * Move a player to the supplied team - * - * @param client The client index of the player to set - * @param team The team to move the to set - * @param override Whether or not to override another plugin - * @return True if successful, false if not - * @error Invalid client or team index - **********************************************************************/ -native SM_SetForcedTeam(client, team, bool:override = false); - -/********************************************************************** - * Gets the client's forced team index - * - * @param client The client index of the player to check - * @param plugin Optional: The plugin handle of the plugin - that set the team - * @return The team index of the forced team - Zero if no forced team - * @error Invalid client index - **********************************************************************/ -native SM_GetForcedTeam(client, &Handle:plugin = INVALID_HANDLE); - -/********************************************************************** - * Clears a client's forced team - * - * @param client The client index of the player to check - * @return True if successful, false if not - * @error Invalid client index - **********************************************************************/ -native SM_ClearForcedTeam(client); - -/********************************************************************** - * Gets a forced player on the wrong that is currently on the wrong team - * This will only return a player if the calling plugin assigned the team - * - * @param team The team index the player should be on - * @return The client index of the player - Zero if no player found - * @error Invalid client index - **********************************************************************/ -native SM_GetForcedPlayer(team); - -/********************************************************************** - * Assign a players buddy - * - * @param client The client index of the player to assign - * @param player The player index of the player to assign - * @param override Whether or not to override a player lock - * @return True if successful, false if not - * @error Invalid client or player index - **********************************************************************/ -native bool:SM_AssignBuddy(client, player, bool:override = false); - -/********************************************************************** - * Rturns the client's buddy - * - * @param client The client index of the player to assign - * @return The client index of the player's buddy - Zero if no buddy - * @error Invalid client index - **********************************************************************/ -native SM_GetClientBuddy(client); - -/********************************************************************** - * Set the buddy lock setting for a client - * - * @param client The client index of the player to assign - * @param setting Setting to set, True or False - * @return True if successful, false if not - * @error Invalid client index - **********************************************************************/ -native bool:SM_LockBuddy(client, bool:setting); - -/********************************************************************** - * Returns the buddy lock setting for a client - * - * @param client The client index of the player to assign - * @return True if locked, false if not - * @error Invalid client index - **********************************************************************/ -native bool:SM_IsBuddyLocked(client); - -/********************************************************************** - * Clear a players buddy - * - * @param client The client index of the player to clear - * @param override Whether or not to override a player lock - * @return True if successful, false if not - * @error Invalid client index - **********************************************************************/ -native bool:SM_ClearBuddy(client, bool:override = false); - -/********************************************************************** - * Determine if the player has the supplied flags - * ADMFLAG_ROOT will always return true - * - * @param client The client index of the player to assign - * @param flags The char flag(s) to check against - * @return True if valid, false if not - **********************************************************************/ -native bool:SM_IsValidAdmin(client, const String:flags[]); - - -/********************************************************************** - * Determine if the team is a valid team - * - * @param team The team index to determine if valid for - currently installed/supported mod - * @return True if valid, false if not - **********************************************************************/ -native bool:SM_IsValidTeam(team); - - -public e_SupportedMods:GetCurrentMod() -{ - new String:sGameType[64]; - GetGameFolderName(sGameType, sizeof(sGameType)); - - if (StrEqual(sGameType, "aoc", false)) - { - return GameType_AOC; - } - if (StrEqual(sGameType, "cstrike", false)) - { - return GameType_CSS; - } - if (StrEqual(sGameType, "dod", false)) - { - return GameType_DOD; - } - if (StrEqual(sGameType, "ff", false)) - { - return GameType_FF; - } - if (StrEqual(sGameType, "hidden", false)) - { - return GameType_HIDDEN; - } - if (StrEqual(sGameType, "hl2mp", false)) - { - return GameType_FF; - } - if (StrEqual(sGameType, "insurgency", false) || StrEqual(sGameType, "ins", false)) - { - return GameType_INS; - } - if (StrEqual(sGameType, "l4d", false)) - { - return GameType_L4D; - } - if (StrEqual(sGameType, "nts", false)) - { - return GameType_NEO; - } - if (StrEqual(sGameType, "sgtls", false)) - { - return GameType_SGTLS; - } - if (StrEqual(sGameType, "tf", false)) - { - return GameType_TF; - } - if (StrEqual(sGameType, "zps", false)) - { - return GameType_ZPS; - } - return GameType_Unknown; -} - -public LoadCurrentTeams() -{ - switch (g_CurrentMod) - { - case GameType_INS: - { - g_aCurrentTeams[Unknown] = 0; - g_aCurrentTeams[Spectator] = 3; - g_aCurrentTeams[Team1] = 1; - g_aCurrentTeams[Team2] = 2; - } - case default: - { - g_aCurrentTeams[Unknown] = 0; - g_aCurrentTeams[Spectator] = 1; - g_aCurrentTeams[Team1] = 2; - g_aCurrentTeams[Team2] = 3; - } - } -} diff --git a/Simple Message Suppression/addons/sourcemod/scripting/simple-alltalkmanager.sp b/Simple Message Suppression/addons/sourcemod/scripting/simple-alltalkmanager.sp deleted file mode 100644 index c848332..0000000 --- a/Simple Message Suppression/addons/sourcemod/scripting/simple-alltalkmanager.sp +++ /dev/null @@ -1,515 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple AllTalk Manager -Description: - Allows you to set alltalk at different times -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#pragma semicolon 1 -#include -#include - -#define PLUGIN_VERSION "1.4.$Rev$" - -new Handle:satm_enabled = INVALID_HANDLE; -new Handle:satm_threshold_enabled = INVALID_HANDLE; -new Handle:satm_player_threshold = INVALID_HANDLE; -new Handle:satm_threshold_setting = INVALID_HANDLE; -new Handle:satm_logactivity = INVALID_HANDLE; -new Handle:satm_alltalk = INVALID_HANDLE; - -new Handle:g_aEventNames = INVALID_HANDLE; -new Handle:g_aEventReasons = INVALID_HANDLE; -new Handle:g_aEventSettings = INVALID_HANDLE; - -new bool:g_bLastThreshold = false; -new bool:g_bEnabled = true; -new bool:g_bThresholdEnabled = true; -new bool:g_bIsSetupMap = false; -new bool:g_bIsGameTF2 = false; -new bool:g_bLogActivity = false; - -new g_iLastEventIndex; - -public Plugin:myinfo = -{ - name = "Simple AllTalk Manager", - author = "Simple Plugins", - description = "Allows you to set alltalk at different times", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -} - -/** -Sourcemod callbacks -*/ -public OnPluginStart() -{ - - /** - Need to create all of our console variables. - */ - CreateConVar("satm_version", PLUGIN_VERSION, "Simple AllTalk Manager", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - satm_enabled = CreateConVar("satm_enabled", "1", "Enables/Disables Simple AllTalk Manager", _, true, 0.0, true, 1.0); - satm_threshold_enabled = CreateConVar("satm_threshold_enabled", "1", "Enables/Disables player threshold", _, true, 0.0, true, 1.0); - satm_player_threshold = CreateConVar("satm_player_threshold", "8", "Amount of players for the threshold"); - satm_threshold_setting = CreateConVar("satm_threshold_setting", "1", "Enables/Disables all talk up to player threshold, with the opposite set after the threshold", _, true, 0.0, true, 1.0); - satm_logactivity = CreateConVar("satm_logactivity", "0", "Enables/Disables log activity", _, true, 0.0, true, 1.0); - satm_alltalk = FindConVar("sv_alltalk"); - - /** - Hook console variables - */ - HookConVarChange(satm_enabled, ConVarSettingsChanged); - HookConVarChange(satm_threshold_enabled, ConVarSettingsChanged); - HookConVarChange(satm_player_threshold, ConVarSettingsChanged); - HookConVarChange(satm_logactivity, ConVarSettingsChanged); - - /** - Remove the notify flag from all talk cvar since we do it - */ - SetConVarFlags(satm_alltalk, GetConVarFlags(satm_alltalk)~FCVAR_NOTIFY); - - /** - Get the game type. We only care if it's TF2 - */ - new String:sGameType[64]; - GetGameFolderName(sGameType, sizeof(sGameType)); - if (StrEqual(sGameType, "tf", false)) - { - g_bIsGameTF2 = true; - } - - /** - Create the arrays - */ - g_aEventNames = CreateArray(255, 1); - g_aEventReasons = CreateArray(255, 1); - g_aEventSettings = CreateArray(1, 1); - - /** - Need to register the commands we are going to create and use. - */ - RegAdminCmd("sm_reloadatconfig", Command_Reload, ADMFLAG_GENERIC, "Reloads settings from config file"); - - /** - Create the config file - */ - AutoExecConfig(true); - - /** - Load the events from the config - */ - LoadEventsFromConfig(); -} - -public OnConfigsExecuted() -{ - - /** - Load up the settings - */ - g_bEnabled = GetConVarBool(satm_enabled); - g_bLogActivity = GetConVarBool(satm_logactivity); - g_bThresholdEnabled = GetConVarBool(satm_threshold_enabled); -} - -public OnMapStart() -{ - - /** - Reset the globals - */ - g_iLastEventIndex = 0; - g_bLastThreshold = false; - - /** - Check the map type if we are in TF2 - */ - if (g_bIsGameTF2) - { - g_bIsSetupMap = IsSetupPeriodMap(); - } - - /** - Set AllTalk - */ - if (g_bEnabled) - { - SetConVarBool(satm_alltalk, true); - } -} - -public OnClientDisconnect_Post(client) -{ - if (g_bEnabled) - { - SetAllTalk(-1); - } -} - -public OnClientPostAdminCheck(client) -{ - if (g_bEnabled) - { - SetAllTalk(-1); - } - CreateTimer(2.0, Timer_ShowAllTalkStatus, client, TIMER_FLAG_NO_MAPCHANGE); -} - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (convar == satm_enabled) - { - if (StringToInt(newValue)) - { - g_bEnabled = true; - } - else - { - g_bEnabled = false; - } - } - else if (convar == satm_threshold_enabled) - { - if (StringToInt(newValue)) - { - g_bThresholdEnabled = true; - } - else - { - g_bThresholdEnabled = false; - } - } - else if (convar == satm_logactivity) - { - if (StringToInt(newValue)) - { - g_bLogActivity = true; - } - else - { - g_bLogActivity = false; - } - } - if (g_bEnabled) - { - SetAllTalk(-1); - } -} - -/** -Commands -*/ -public Action:Command_Reload(client, args) -{ - - /** - Clear the array - */ - ClearArray(g_aEventNames); - ClearArray(g_aEventReasons); - ClearArray(g_aEventSettings); - - /** - Load the events from the config - */ - LoadEventsFromConfig(); - - return Plugin_Handled; -} - -/** -Game Event Hooks -*/ -public Hook_All_Events(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (!g_bIsSetupMap) - { - if (StrEqual(name, "teamplay_round_start")) - { - if (FindStringInArray(g_aEventNames, "teamplay_setup_finished") != -1) - { - g_iLastEventIndex = FindStringInArray(g_aEventNames, "teamplay_setup_finished"); - if (g_bEnabled) - { - SetAllTalk(g_iLastEventIndex); - return; - } - } - } - } - g_iLastEventIndex = FindStringInArray(g_aEventNames, name); - if (g_bEnabled) - { - SetAllTalk(g_iLastEventIndex); - } -} - -/** -Timers -*/ -public Action:Timer_ShowAllTalkStatus(Handle:timer, any:client) -{ - if (IsClientConnected(client) && IsClientInGame(client)) - { - new bool:bSetting = GetConVarBool(satm_alltalk); - if (bSetting) - { - PrintToChat(client, "\x01\x04[SM] AllTalk is \x01[on]"); - } - else - { - PrintToChat(client, "\x01\x04[SM] AllTalk is \x01[off]"); - } - } -} - -/** -Stock Functions -*/ -stock LoadEventsFromConfig() -{ - - /** - Make sure the config file is here and load it up - */ - new String:sConfigFile[256]; - BuildPath(Path_SM, sConfigFile, sizeof(sConfigFile), "configs/simple-alltalkmanager_events.cfg"); - if (!FileExists(sConfigFile)) - { - - /** - Config file doesn't exists, stop the plugin - */ - LogError("[SATM] Simple AllTalk Manager is not running! Could not find file %s", sConfigFile); - SetFailState("Could not find file %s", sConfigFile); - } - - /** - Create the arrays and variables - */ - new String:sGameEventName[256]; - new String:sReason[256]; - new iSetting; - - /** - Load config file as a KeyValues file - */ - new Handle:kvGameEvents = CreateKeyValues("game_events"); - FileToKeyValues(kvGameEvents, sConfigFile); - - if (!KvGotoFirstSubKey(kvGameEvents)) - { - return; - } - - /** - Hook the game events and load the settings - */ - do - { - - /** - Get the section name; this should be the event name - */ - KvGetSectionName(kvGameEvents, sGameEventName, sizeof(sGameEventName)); - if (!HookEventEx(sGameEventName, Hook_All_Events, EventHookMode_PostNoCopy)) - { - - /** - Could not hook this event, stop the plugin - */ - SetFailState("Could not hook event %s", sGameEventName); - } - else - { - if (g_bLogActivity) - { - LogMessage("[SATM] Hooked event: %s", sGameEventName); - } - } - - /** - Get the reason string and setting - */ - KvGetString(kvGameEvents, "reason", sReason, sizeof(sReason)); - iSetting = KvGetNum(kvGameEvents, "setting"); - if (g_bLogActivity) - { - LogMessage("[SATM] Event reason string: %s", sReason); - LogMessage("[SATM] Event setting: %i", iSetting); - } - - /** - Push the values to the arrays - */ - PushArrayString(g_aEventNames, sGameEventName); - PushArrayString(g_aEventReasons, sReason); - PushArrayCell(g_aEventSettings, iSetting); - } while (KvGotoNextKey(kvGameEvents)); - - /** - Close our handle - */ - CloseHandle(kvGameEvents); -} - -stock SetAllTalk(index) -{ - new iPlayerThreshold = GetConVarInt(satm_player_threshold); - new bool:bThresholdMet = ((GetClientCount() >= iPlayerThreshold) ? true : false); - new bool:bSetting; - - if (g_bThresholdEnabled) - { - if (bThresholdMet) - { - if (index == -1) - { - if (bThresholdMet != g_bLastThreshold) - { - g_bLastThreshold = true; - bSetting = !GetConVarBool(satm_threshold_setting); - new bool:bLastSetting = GetArrayCell(g_aEventSettings, g_iLastEventIndex); - if (bLastSetting && !bSetting) - { - bSetting = GetArrayCell(g_aEventSettings, g_iLastEventIndex); - } - } - else - { - bSetting = GetArrayCell(g_aEventSettings, g_iLastEventIndex); - } - } - else - { - bSetting = GetArrayCell(g_aEventSettings, index); - } - } - else - { - g_bLastThreshold = false; - bSetting = GetConVarBool(satm_threshold_setting); - } - } - else - { - if (index != -1) - { - bSetting = GetArrayCell(g_aEventSettings, index); - } - } - - if (GetConVarBool(satm_alltalk) != bSetting) - { - - SetConVarBool(satm_alltalk, bSetting); - - new String:sReason[256]; - if (index == -1) - { - Format(sReason, sizeof(sReason), "Player Threshold"); - } - else - { - if (!g_bIsSetupMap) - { - new String:sCurrentEvent[256]; - GetArrayString(g_aEventNames, index, sCurrentEvent, sizeof(sCurrentEvent)); - if (StrEqual(sCurrentEvent, "teamplay_setup_finished")) - { - new iRoundStartIndex = FindStringInArray(g_aEventNames, "teamplay_round_start"); - if (iRoundStartIndex != -1) - { - GetArrayString(g_aEventReasons, iRoundStartIndex, sReason, sizeof(sReason)); - } - else - { - GetArrayString(g_aEventReasons, index, sReason, sizeof(sReason)); - } - } - else - { - GetArrayString(g_aEventReasons, index, sReason, sizeof(sReason)); - } - } - else - { - GetArrayString(g_aEventReasons, index, sReason, sizeof(sReason)); - } - } - - if (bSetting) - { - PrintToChatAll("\x01\x04[SM] AllTalk turned \x01[on] \x04due to:\x01 %s", sReason); - } - else - { - PrintToChatAll("\x01\x04[SM] AllTalk turned \x01[off] \x04due to:\x01 %s", sReason); - } - } -} - -stock bool:IsSetupPeriodMap() -{ - new iEnt = -1; - new String:sMapName[32]; - - GetCurrentMap(sMapName, sizeof(sMapName)); - - if (strncmp(sMapName, "cp_", 3, false) == 0) - { - new iTeam; - while ((iEnt = FindEntityByClassname(iEnt, "team_control_point")) != -1) - { - iTeam = GetEntProp(iEnt, Prop_Send, "m_iTeamNum"); - - /** - If there is a blu CP or a neutral CP, then it's not an attack/defend map - */ - if (iTeam != 2) - { - //this is a push map - return false; - } - } - //this is a attack/defend map - return true; - } - else if (strncmp(sMapName, "ctf_", 3, false) == 0) - { - //this is a ctf map - return false; - } - return false; -} diff --git a/Simple Message Suppression/addons/sourcemod/scripting/simple-autoscrambler.sp b/Simple Message Suppression/addons/sourcemod/scripting/simple-autoscrambler.sp deleted file mode 100644 index 6c6799e..0000000 --- a/Simple Message Suppression/addons/sourcemod/scripting/simple-autoscrambler.sp +++ /dev/null @@ -1,459 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple AutoScrambler -Description: - Automatically scrambles the teams based upon a number of events. -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include - -#define PLUGIN_VERSION "1.1.$Rev$" - -/** -Different scramble modes: - -1 = Full Scramble, dont restart round. -2 = Admins Immune, dont restart round. -3 = Full Scramble, restart round and reset scores. -4 = Admins Immune, restart round and reset scores. - -*/ - -/** -Different top player modes: - -1 = Divide Top 4 players on the two teams. -2 = Protect the Top 2 players on each team. - -*/ - -enum PlayerData -{ - Handle:hForcedTimer, - bool:bProtected; -}; - -/** -Cvars used for admins -*/ -new Handle: sas_admin_immunity_enabled = INVALID_HANDLE, - Handle: sas_admin_flag_scramblenow = INVALID_HANDLE, - Handle: sas_admin_flag_immunity = INVALID_HANDLE; - -/** -Cvars used for autoscramble -*/ -new Handle: sas_autoscramble_enabled = INVALID_HANDLE, - Handle: sas_autoscramble_minplayers = INVALID_HANDLE, - Handle: sas_autoscramble_mode = INVALID_HANDLE, - Handle: sas_autoscramble_winstreak = INVALID_HANDLE, - Handle: sas_autoscramble_steamroll = INVALID_HANDLE, - Handle: sas_autoscramble_frags = INVALID_HANDLE; - -/** -Cvars used for voting -*/ -new Handle: sas_vote_enabled = INVALID_HANDLE, - Handle: sas_vote_upcount = INVALID_HANDLE, - Handle: sas_vote_winpercent = INVALID_HANDLE, - Handle: sas_vote_mode = INVALID_HANDLE, - Handle: sas_vote_minplayers = INVALID_HANDLE; - -/** -Additional cvars -*/ -new Handle: sas_enabled = INVALID_HANDLE, - Handle: sas_timer_scrambledelay = INVALID_HANDLE, - Handle: TFGameModeArena = INVALID_HANDLE; - -/** -Timers -*/ -new Handle: g_hScrambleTimer = INVALID_HANDLE; - -/** - Player arrays - */ -new g_aPlayers[MAXPLAYERS + 1][PlayerData]; - -/** - Cvar variables - */ -new bool: g_bIsEnabled, - bool: g_bIsAutoScrambleEnabled, - bool: g_bIsVoteEnabled, - bool: g_bIsAdminImmunityEnabled; -new Float: g_fTimer_ScrambleDelay, - Float: g_fVote_UpCount, - Float: g_fVote_WinPercent; -new g_iAutoScramble_Minplayers, - g_iAutoScramble_Mode, - g_iAutoScramble_WinStreak, - g_iAutoScramble_SteamRoll, - g_iAutoScramble_Frags, - g_iVote_Mode, - g_iVote_MinPlayers; -new String: g_sScrambleNowFlag[5], - String: g_sAdminImmunityFlag[5]; - -/** -Other globals -*/ -new g_iMaxEntities, - g_iOwnerOffset; - -public Plugin:myinfo = -{ - name = "Simple AutoScrambler", - author = "Simple Plugins", - description = "Automatically scrambles the teams based upon a number of events.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -public OnPluginStart() -{ - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[SAS] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - switch (g_CurrentMod) - { - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_Post); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_Post); - } - } - - /** - Create console variables - */ - CreateConVar("sas_version", PLUGIN_VERSION, "Simple AutoScrambler Version",FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - sas_enabled = CreateConVar("sas_enabled", "1", "Enable/Disable Simple AutoScrambler"); - sas_timer_scrambledelay = CreateConVar("sas_timer_scrambledelay", "5.0", "Delay used after a scramble has been started", _, true, 1.0, true, 30.0); - - /** - Cvars used for admins - */ - sas_admin_immunity_enabled = CreateConVar("sas_admin_immunity_enabled", "1", "Enable/Disable admin immunity for scrambles"); - sas_admin_flag_scramblenow = CreateConVar("sas_admin_flag_scramblenow", "z", "Admin flag to use for scramblenow function/command"); - sas_admin_flag_immunity = CreateConVar("sas_admin_flag_immunity", "z", "Admin flag to use for scramble immunity"); - - /** - Cvars used for autoscramble - */ - sas_autoscramble_enabled = CreateConVar("sas_autoscramble_enabled", "1", "Enable/Disable the autoscramble function"); - sas_autoscramble_minplayers = CreateConVar("sas_autoscramble_minplayers", "16", "Min players needed to start an autoscramble"); - sas_autoscramble_mode = CreateConVar("sas_autoscramble_mode", "1", "Scramble mode used when autoscrambling"); - sas_autoscramble_winstreak = CreateConVar("sas_autoscramble_winstreak", "5", "Max amount of wins in a row a team can achieve before an autoscramble starts"); - sas_autoscramble_steamroll = CreateConVar("sas_autoscramble_steamroll", "120", "Shortest amount of time a team can win by before an autoscramble starts (seconds)"); - sas_autoscramble_frags = CreateConVar("sas_autoscramble_frags", "1", "Min players needed to start a vote and scramble"); - - /** - Cvars used for voting - */ - sas_vote_enabled = CreateConVar("sas_vote_enabled", "1", "Enable/Disable voting for scramble"); - sas_vote_upcount = CreateConVar("sas_vote_upcount", "5", "Amount of people wanting a scramble before a vote starts. If less than 1 it will be considered a percentage. (ie 0.5 = 50% | 1 = 1 Player | 5 = 5 Players)"); - sas_vote_winpercent = CreateConVar("sas_vote_winpercent", "0.6", "Percentage of votes needed to scramble", _, true, 0.0, true, 1.0); - sas_vote_mode = CreateConVar("sas_vote_mode", "1", "Scramble mode used when a vote results in a scramble"); - sas_vote_minplayers = CreateConVar("sas_vote_minplayers", "16", "Min players needed to start a vote and scramble"); - - /** - Hook the console variables if they change - */ - HookConVarChange(sas_enabled, ConVarSettingsChanged); - HookConVarChange(sas_timer_scrambledelay, ConVarSettingsChanged); - HookConVarChange(sas_admin_immunity_enabled, ConVarSettingsChanged); - HookConVarChange(sas_admin_flag_scramblenow, ConVarSettingsChanged); - HookConVarChange(sas_admin_flag_immunity, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_enabled, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_minplayers, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_mode, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_winstreak, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_steamroll, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_frags, ConVarSettingsChanged); - HookConVarChange(sas_vote_enabled, ConVarSettingsChanged); - HookConVarChange(sas_vote_upcount, ConVarSettingsChanged); - HookConVarChange(sas_vote_winpercent, ConVarSettingsChanged); - HookConVarChange(sas_vote_mode, ConVarSettingsChanged); - HookConVarChange(sas_vote_minplayers, ConVarSettingsChanged); - - /** - Register the command - */ - RegConsoleCmd("sm_scramblenow", Command_ScrambleNow, "sm_scramblenow (mode): Scrambles the teams"); - - /** - Load translations and .cfg file - */ - LoadTranslations ("simpleautoscrambler.phrases"); - AutoExecConfig(true, "plugin.simpleautoscrambler"); - LogAction(0, -1, "[SAS] Simple AutoScrambler is loaded."); -} - -public OnAllPluginsLoaded() -{ - //something -} - -public OnLibraryRemoved(const String:name[]) -{ - //something -} - -public OnConfigsExecuted() -{ - - /** - Load up all the variable defaults - */ - LoadUpVariables(); - - /** - Log our activity - */ - if (g_bIsEnabled) - LogAction(0, -1, "Simple AutoScrambler is ENABLED"); - else - LogAction(0, -1, "Simple AutoScrambler is DISABLED"); -} - -public Action:Command_ScrambleNow(client, args) -{ - - /** - Make sure we are enabled - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the client is authorized to run this command. - */ - if (!SM_IsValidAdmin(client, g_sScrambleNowFlag)) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure it's ok to scramble at this time - */ - if (!OkToScramble) - { - return Plugin_Handled; - } - - /** - Make sure it's ok to scramble at this time - */ - LogAction(0, -1, "[SAS] The scramblenow command was used"); - - /** - Scramble the teams - */ - StartAScramble(); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - -} - -public Action:Timer_ScrambleTeams(Handle:timer, any:mode) -{ - - /** - Make sure it's still ok to scramble - */ - if (!OkToScramble) - { - return Plugin_Handled; - } - - - switch (mode) - { - case - - - - } - - - /** - Reset the handle because the timer is over and the callback is done - */ - g_hScrambleTimer = INVALID_HANDLE; - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - -} - -stock StartAScramble(mode) -{ - - /** - See if we are already started a scramble - */ - if (g_hScrambleTimer == INVALID_HANDLE) - { - - /** - There is a scramble in progress - */ - return; - - } - - /** - Report that a scramble is about to start - */ - PrintCenterTextAll("%T", "Scramble", LANG_SERVER); - - /** - Start a timer and log the action - */ - g_hScrambleTimer = CreateTimer(g_fTimer_ScrambleDelay, Timer_ScrambleTeams, mode, TIMER_FLAG_NO_MAPCHANGE); - LogAction(0, -1, "[SAS] A scamble timer was started"); -} - -stock bool:OkToScramble() -{ - -} - -stock LoadUpVariables() -{ - g_bIsEnabled = GetConVarBool(sas_enabled); - g_bIsAutoScrambleEnabled = GetConVarBool(sas_autoscramble_enabled); - g_bIsVoteEnabled = GetConVarBool(sas_vote_enabled); - g_bIsAdminImmunityEnabled = GetConVarBool(sas_admin_immunity_enabled); - g_iAutoScramble_Minplayers = GetConVarInt(sas_autoscramble_minplayers); - g_iAutoScramble_Mode = GetConVarInt(sas_autoscramble_mode); - g_iAutoScramble_WinStreak = GetConVarInt(sas_autoscramble_winstreak); - g_iAutoScramble_SteamRoll = GetConVarInt(sas_autoscramble_steamroll); - g_iAutoScramble_Frags = GetConVarInt(sas_autoscramble_frags); - g_iVote_Mode = GetConVarInt(sas_vote_mode); - g_iVote_MinPlayers = GetConVarInt(sas_vote_minplayers); - GetConVarString(sas_admin_flag_scramblenow, g_sScrambleNowFlag, sizeof(g_sScrambleNowFlag)); - GetConVarString(sas_admin_flag_immunity, g_sAdminImmunityFlag, sizeof(g_sAdminImmunityFlag)); - g_fTimer_ScrambleDelay = GetConVarFloat(sas_timer_scrambledelay); - g_fVote_UpCount = GetConVarFloat(sas_vote_upcount); - g_fVote_WinPercent = GetConVarFloat(sas_vote_winpercent); - g_iMaxEntities = GetMaxEntities(); - g_iOwnerOffset = FindSendPropInfo("CBaseObject", "m_hBuilder"); -} - -stock TF2_DestroyBuildings(client) -{ - - /** - We have to start a loop to check the owner of all the valid entities - */ - for (new i = MaxClients + 1; i <= g_iMaxEntities; i++) - { - if (!IsValidEntity(i)) - { - - /** - Not valid, continue to next one - */ - continue; - } - - /** - Get the name of the current entity - */ - decl String:sNetClass[32]; - GetEntityNetClass(i, sNetClass, sizeof(sNetClass)); - - /** - See if its something that an engineer would build - */ - if (strcmp(sNetClass, "CObjectSentrygun") == 0 - || strcmp(sNetClass, "CObjectTeleporter") == 0 - || strcmp(sNetClass, "CObjectDispenser") == 0) - { - - /** - It is, so lets check the owner - */ - if (GetEntDataEnt2(i, g_iOwnerOffset) == client) - { - - /** - It's the clients building, so we blow it up. - */ - SetVariantInt(9999); - AcceptEntityInput(i, "RemoveHealth"); - } - } - } -} \ No newline at end of file diff --git a/Simple Message Suppression/addons/sourcemod/scripting/simple-chatcolors.sp b/Simple Message Suppression/addons/sourcemod/scripting/simple-chatcolors.sp deleted file mode 100644 index 539d057..0000000 --- a/Simple Message Suppression/addons/sourcemod/scripting/simple-chatcolors.sp +++ /dev/null @@ -1,496 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Chat Colors -Description: - Changes the colors of players chat based on config file -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#pragma semicolon 1 -#include -#include - -#define PLUGIN_VERSION "0.9.0.$Rev$" - -#define CHAT_SYMBOL '@' -#define TRIGGER_SYMBOL1 '!' -#define TRIGGER_SYMBOL2 '/' -#define CHAT_MAX_MESSAGE_LENGTH 1024 - -new Handle:g_hDebugCvar = INVALID_HANDLE; -new Handle:g_aGroupNames = INVALID_HANDLE; -new Handle:g_aGroupFlag = INVALID_HANDLE; -new Handle:g_aGroupNameColor = INVALID_HANDLE; -new Handle:g_aGroupTextColor = INVALID_HANDLE; - -new bool:g_bDebug = false; - -new g_iArraySize; - -new g_aPlayerColorIndex[MAXPLAYERS + 1] = { -1, ... }; - -public Plugin:myinfo = -{ - name = "Simple Chat Colors", - author = "Simple Plugins", - description = "Changes the colors of players chat based on config file.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -/** -Sourcemod callbacks -*/ -public OnPluginStart() -{ - - /** - Need to create all of our console variables. - */ - CreateConVar("sm_chatcolors_version", PLUGIN_VERSION, "Simple Chat Colors", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - g_hDebugCvar = CreateConVar("sm_chatcolors_debug", "1", "Enable/Disable debugging information"); - - /** - Hook console variables - */ - HookConVarChange(g_hDebugCvar, ConVarSettingsChanged); - - /** - Need to register the commands we are going to use - */ - RegConsoleCmd("say", Command_Say); - RegConsoleCmd("say_team", Command_SayTeam); - RegAdminCmd("sm_reloadcolorsconfig", Command_Reload, ADMFLAG_GENERIC, "Reloads settings from config file"); - - /** - Create the arrays - */ - g_aGroupNames = CreateArray(256, 1); - g_aGroupFlag = CreateArray(15, 1); - g_aGroupNameColor = CreateArray(15, 1); - g_aGroupTextColor = CreateArray(15, 1); - - /** - Load the admins and colors from the config - */ - LoadAdminsAndColorsFromConfig(); - g_iArraySize = GetArraySize(g_aGroupNames); -} - -public OnConfigsExecuted() -{ - g_bDebug = GetConVarBool(g_hDebugCvar); - ReloadConfigFile(); -} - -public OnClientPostAdminCheck(client) -{ - - /** - Check the client to see if they are a admin - */ - CheckAdmin(client); -} - -public OnClientDisconnect(client) -{ - g_aPlayerColorIndex[client] = -1; -} - -/** -Commands -*/ -public Action:Command_Say(client, args) -{ - - /** - Make sure we are enabled. - */ - if (client == 0 || IsChatTrigger()) - { - return Plugin_Continue; - } - - if (g_aPlayerColorIndex[client] != -1) - { - - /** - The client is, so get the chat message and strip it down. - */ - decl String:sArg[CHAT_MAX_MESSAGE_LENGTH], - String:sChatMsg[CHAT_MAX_MESSAGE_LENGTH]; - - new bool:bAlive = IsPlayerAlive(client); - - GetCmdArgString(sArg, sizeof(sArg)); - StripQuotes(sArg); - TrimString(sArg); - new startidx; - if (sArg[strlen(sArg)-1] == '"') - { - sArg[strlen(sArg)-1] = '\0'; - startidx = 1; - } - - /** - Bug out if they are using the admin chat symbol (admin chat). If we are in CSS it may not find all the triggers, so we double check. - */ - if (sArg[startidx] == CHAT_SYMBOL || sArg[startidx] == TRIGGER_SYMBOL1 || sArg[startidx] == TRIGGER_SYMBOL2) - { - return Plugin_Continue; - } - - /** - Log the message for hlstatsx and other things. - */ - new iUserID = GetClientUserId(client); - decl String:sAuthID[64]; - GetClientAuthString(client, sAuthID, sizeof(sAuthID)); - LogToGame("\"%N<%i><%s><>\" say \"%s\"", client, iUserID, sAuthID, sArg); - - /** - Format the message. - */ - FormatMessage(client, 0, bAlive, sChatMsg, sArg, g_aPlayerColorIndex[client]); - - /** - Send the message. - */ - //SayText2(0, client, sChatMsg); - CPrintToChatAll(sChatMsg); - - /** - We are done, bug out, and stop the original chat message. - */ - return Plugin_Stop; - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Command_SayTeam(client, args) -{ - - /** - Make sure we are enabled. - */ - if (client == 0 || IsChatTrigger()) - { - return Plugin_Continue; - } - - /** - Check the client to see if they are a admin - */ - if (g_aPlayerColorIndex[client] != -1) - { - - /** - The client is, so get the chat message and strip it down. - */ - decl String:sArg[CHAT_MAX_MESSAGE_LENGTH], - String:sChatMsg[CHAT_MAX_MESSAGE_LENGTH]; - - new bool:bAlive = IsPlayerAlive(client); - new iCurrentTeam = GetClientTeam(client); - - GetCmdArgString(sArg, sizeof(sArg)); - StripQuotes(sArg); - TrimString(sArg); - new startidx; - if (sArg[strlen(sArg)-1] == '"') - { - sArg[strlen(sArg)-1] = '\0'; - startidx = 1; - } - - /** - Bug out if they are using the admin chat symbol (admin chat). - */ - if (sArg[startidx] == CHAT_SYMBOL || sArg[startidx] == TRIGGER_SYMBOL1 || sArg[startidx] == TRIGGER_SYMBOL2) - { - return Plugin_Continue; - } - - /** - Log the message for hlstatsx and other things. - */ - new iUserID = GetClientUserId(client); - decl String:sAuthID[64]; - GetClientAuthString(client, sAuthID, sizeof(sAuthID)); - LogToGame("\"%N<%i><%s><>\" say_team \"%s\"", client, iUserID, sAuthID, sArg); - - /** - Format the message. - */ - FormatMessage(client, iCurrentTeam, bAlive, sChatMsg, sArg, g_aPlayerColorIndex[client]); - - /** - Send the message to the same team - */ - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == iCurrentTeam) - { - CPrintToChat(client, sChatMsg); - } - } - - /** - We are done, bug out, and stop the original chat message. - */ - return Plugin_Stop; - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Command_Reload(client, args) -{ - ReloadConfigFile(); - return Plugin_Handled; -} - -/** -Stock Functions -*/ -stock LoadAdminsAndColorsFromConfig() -{ - - /** - Make sure the config file is here and load it up - */ - new String:sConfigFile[256]; - BuildPath(Path_SM, sConfigFile, sizeof(sConfigFile), "configs/simple-chatcolors.cfg"); - if (!FileExists(sConfigFile)) - { - - /** - Config file doesn't exists, stop the plugin - */ - LogError("[SCC] Simple Chat Colors is not running! Could not find file %s", sConfigFile); - SetFailState("Could not find file %s", sConfigFile); - } - - /** - Create the arrays and variables - */ - new String:sGroupName[256]; - new String:sGroupFlag[15]; - new String:sGroupNameColor[15]; - new String:sGroupTextColor[15]; - - - /** - Load config file as a KeyValues file - */ - new Handle:kvChatColors = CreateKeyValues("admin_colors"); - FileToKeyValues(kvChatColors, sConfigFile); - - if (!KvGotoFirstSubKey(kvChatColors)) - { - return; - } - - /** - Load up all the groups in the file - */ - do - { - - /** - Get the section name; should be the "group" name - */ - KvGetSectionName(kvChatColors, sGroupName, sizeof(sGroupName)); - - - /** - Get the flags and colors - */ - KvGetString(kvChatColors, "flag", sGroupFlag, sizeof(sGroupFlag)); - KvGetString(kvChatColors, "namecolor", sGroupNameColor, sizeof(sGroupNameColor)); - KvGetString(kvChatColors, "textcolor", sGroupTextColor, sizeof(sGroupTextColor)); - - if (g_bDebug) - { - LogMessage("Group Name/SteamID: %s", sGroupName); - LogMessage("Flag String: %s", sGroupFlag); - LogMessage("Color on name: %s", sGroupNameColor); - LogMessage("Color of text: %s", sGroupTextColor); - } - - /** - Push the values to the arrays - */ - PushArrayString(g_aGroupNames, sGroupName); - PushArrayString(g_aGroupFlag, sGroupFlag); - PushArrayString(g_aGroupNameColor, sGroupNameColor); - PushArrayString(g_aGroupTextColor, sGroupTextColor); - } while (KvGotoNextKey(kvChatColors)); - - /** - Close our handle - */ - CloseHandle(kvChatColors); -} - -stock ReloadConfigFile() -{ - - /** - Clear the array - */ - ClearArray(g_aGroupNames); - ClearArray(g_aGroupFlag); - ClearArray(g_aGroupNameColor); - ClearArray(g_aGroupTextColor); - - /** - Load the admins, groups, and colors from the config - */ - LoadAdminsAndColorsFromConfig(); - g_iArraySize = GetArraySize(g_aGroupNames); - - /** - Recheck all the online players for assigned colors - */ - for (new index = 1; index <= MaxClients; index++) - { - if (IsClientConnected(index) && IsClientInGame(index)) - { - CheckAdmin(index); - } - } -} - -stock CheckAdmin(client) -{ - new String:sFlags[15]; - new String:sClientSteamID[64]; - new iGroupFlags; - new iFlags; - new iIndex = -1; - - /** - Look for a steamid first - */ - GetClientAuthString(client, sClientSteamID, sizeof(sClientSteamID)); - iIndex = FindStringInArray(g_aGroupNames, sClientSteamID); - if (iIndex != -1) - { - g_aPlayerColorIndex[client] = iIndex; - } - - /** - Didn't find one, check flags - */ - else - { - /** - Search for flag in groups - */ - - iFlags = GetUserFlagBits(client); - for (iIndex = 0; iIndex < g_iArraySize; iIndex++) - { - GetArrayString(g_aGroupFlag, iIndex, sFlags, sizeof(sFlags)); - iGroupFlags = ReadFlagString(sFlags); - if (iFlags & iGroupFlags) - { - g_aPlayerColorIndex[client] = iIndex; - break; - } - } - } - - if (g_bDebug) - { - PrintToChatAll("SteamID: %s", sClientSteamID); - PrintToChatAll("Array Index: %i", iIndex); - PrintToChatAll("Flag String: %s", sFlags); - PrintToChatAll("Flag Bits of Client: %i", iFlags); - PrintToChatAll("Flag Bits of Group: %i", iGroupFlags); - } -} - -stock FormatMessage(iClient, iTeam, bool:bAlive, String:sChatMsg[], const Sting:sMessage[], iArrayIndex) -{ - decl String:sDead[10], - String:sTeam[10], - String:sClientName[64]; - - GetClientName(iClient, sClientName, sizeof(sClientName)); - - if (iTeam != 0) - { - Format(sTeam, sizeof(sTeam), "(TEAM) "); - } - else - { - Format(sTeam, sizeof(sTeam), ""); - } - if (bAlive) - { - Format(sDead, sizeof(sDead), ""); - } - else - { - Format(sDead, sizeof(sDead), "*DEAD* "); - } - - new String:sNameColor[15]; - new String:sTextColor[15]; - GetArrayString(g_aGroupNameColor, iArrayIndex, sNameColor, sizeof(sNameColor)); - GetArrayString(g_aGroupTextColor, iArrayIndex, sTextColor, sizeof(sTextColor)); - - Format(sChatMsg, CHAT_MAX_MESSAGE_LENGTH, "{default}%s%s%s%s {default}: %s%s", sDead, sTeam, sNameColor, sClientName, sTextColor, sMessage); -} - -/** -Adjust the settings if a convar was changed -*/ -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (StringToInt(newValue) == 1) - { - g_bDebug = true; - } - else - { - g_bDebug = false; - } -} \ No newline at end of file diff --git a/Simple Message Suppression/addons/sourcemod/scripting/simple-donatorbenefits.sp b/Simple Message Suppression/addons/sourcemod/scripting/simple-donatorbenefits.sp deleted file mode 100644 index e3f6845..0000000 --- a/Simple Message Suppression/addons/sourcemod/scripting/simple-donatorbenefits.sp +++ /dev/null @@ -1,1312 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Donator Benefits -Description: - Provides donator benefits to players -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include -#include - -#define PLUGIN_VERSION "1.1.$Rev$" - -#define CHAT_SYMBOL '@' -#define CHAT_MAX_MESSAGE_LENGTH 1024 - -enum PlayerData -{ - bool:bIsDonator, - bool:bQueue, - bool:bImmune, - iHealthCount, - iNewTeam -}; - -/** - Public convar handles - */ -new Handle:sdb_enabled = INVALID_HANDLE; -new Handle:sdb_donationflag = INVALID_HANDLE; -new Handle:sdb_soundfile = INVALID_HANDLE; -new Handle:sdb_joinsound_enabled = INVALID_HANDLE; -new Handle:sdb_joinpubmsg_enabled = INVALID_HANDLE; -new Handle:sdb_joinprivmsg_enabled = INVALID_HANDLE; -new Handle:sdb_chatcolors_enabled = INVALID_HANDLE; -new Handle:sdb_immunity_enabled = INVALID_HANDLE; -new Handle:sdb_ubercharge_enabled = INVALID_HANDLE; -new Handle:sdb_givehealth_enabled = INVALID_HANDLE; -new Handle:sdb_nofalldmg_enabled = INVALID_HANDLE; -new Handle:sdb_fastheavy_enabled = INVALID_HANDLE; -new Handle:sdb_swapteam_enabled = INVALID_HANDLE; -new Handle:sdb_chatcolor = INVALID_HANDLE; -new Handle:sdb_uberlevel = INVALID_HANDLE; -new Handle:sdb_healthcount = INVALID_HANDLE; -new Handle:sdb_healthbonus = INVALID_HANDLE; -new Handle:sdb_heavymultiplier = INVALID_HANDLE; - -/** -Create global enable/disable bools so we don't have to check the console variable on every call -*/ -new bool:g_bIsEnabled = true; -new bool:g_bIsJoinSoundEnabled = true; -new bool:g_bIsJoinPubMsgEnabled = true; -new bool:g_bIsJoinPrivMsgEnabled = true; -new bool:g_bIsChatColorsEnabled = true; -new bool:g_bIsImmuntyEnabled = true; -new bool:g_bIsUberChargeEnabled = true; -new bool:g_bIsGiveHealthEnabled = true; -new bool:g_bIsNoFallDmgEnabled = true; -new bool:g_bIsFastHeayEnabled = true; -new bool:g_bIsSwapTeamEnabled = true; - -/** - Player arrays - */ -new g_aPlayers[MAXPLAYERS + 1][PlayerData]; - - -/** -Rest of the globals -*/ -new bool:g_bRoundEnd = false; -new String:g_sCharDonatorFlag[5]; -new String:g_sSoundFile[PLATFORM_MAX_PATH]; -new String:g_sChatColor[11]; -new g_iHealthBonus; -new g_iHealthCount; -new g_iClassMaxHealth[TFClassType] = {0, 125, 125, 200, 175, 150, 300, 175, 125, 125}; -new g_fClassMaxSpeed[TFClassType] = {0, 400, 300, 240, 280, 320, 230, 300, 300, 300}; -new Float:g_fHeavyMultiplier = 0.0; -new Float:g_fUberLevel = 0.0; - -public Plugin:myinfo = -{ - name = "Simple Donation Benefits", - author = "Simple Plugins", - description = "Gives donators benefits to players", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -} - -public OnPluginStart() -{ - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[SDB] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_connect", HookPlayerSpawn, EventHookMode_Pre); - HookEvent("player_spawn", HookPlayerSpawn, EventHookMode_Post); - HookEvent("player_death", HookPlayerDeath, EventHookMode_Post); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Post); - switch (g_CurrentMod) - { - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - HookEvent("player_changeclass", HookPlayerClass, EventHookMode_Post); - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_Post); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - - /** - Create console variables - */ - CreateConVar("sdb_version", PLUGIN_VERSION, "Simple Donation Benefits", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - sdb_enabled = CreateConVar("sdb_enabled", "1", "Enable/Disable Simple Donation Benefits"); - sdb_donationflag = CreateConVar("sdb_donationflag", "a", "Flag ALREADY given to donators. Must be in char format"); - - /** - Create the enable/disable donator console variables - */ - sdb_joinsound_enabled = CreateConVar("sdb_joinsound_enabled", "1", "Enable/Disable donator join sound"); - sdb_joinpubmsg_enabled = CreateConVar("sdb_joinpubmsg_enabled", "1", "Enable/Disable public donator join message (replaces: as connected)"); - sdb_joinprivmsg_enabled = CreateConVar("sdb_joinprivmsg_enabled", "1", "Enable/Disable private donator join message (sent only to donator)"); - sdb_chatcolors_enabled = CreateConVar("sdb_chatcolors_enabled", "1", "Enable/Disable donator chat colors"); - sdb_immunity_enabled = CreateConVar("sdb_immunity_enabled", "1", "Enable/Disable donator round end immunity"); - sdb_ubercharge_enabled = CreateConVar("sdb_ubercharge_enabled", "1", "Enable/Disable donator medics starting with ubercharge"); - sdb_givehealth_enabled = CreateConVar("sdb_givehealth_enabled", "1", "Enable/Disable donator instant health bonus"); - sdb_nofalldmg_enabled = CreateConVar("sdb_nofalldmg_enabled", "1", "Enable/Disable no fall damage for donators"); - sdb_fastheavy_enabled = CreateConVar("sdb_fastheavy_enabled", "1", "Enable/Disable donator heavies moving faster while spinning"); - sdb_swapteam_enabled = CreateConVar("sdb_swampteam_enabled", "1", "Enable/Disable donator swap team ability"); - - /** - Create the donator setting console variables - */ - sdb_soundfile = CreateConVar("sdb_soundfile", "custom/donatorjoin.mp3", "The location of sound file"); - sdb_chatcolor = CreateConVar("sdb_chatcolor", "green", "Color to use for donator chat. Valid colors are green and lightgreen"); - sdb_uberlevel = CreateConVar("sdb_uberlevel", "0.5", "Uberlevel to give donator medic at spawn. 1.0 = full uber", _, true, 0.0, true, 1.0); - sdb_healthcount = CreateConVar("sdb_healthcount", "1", "Number of times a donator can use use instant health per life"); - sdb_healthbonus = CreateConVar("sdb_healthbonus", "100", "The amount of health to heal the donator"); - sdb_heavymultiplier = CreateConVar("sdb_heavyspeed", "0.5", "The speed multiplier for the fast heavy. Based on running speed. 1.0 = running speed. (Game Default is 0.20)", _, true, 0.0, true, 1.0); - - /** - Hook dukehacks calls - */ - dhAddClientHook(CHK_TakeDamage, Hacks_TakeDamageHook); - dhAddClientHook(CHK_PreThink, Hacks_PreThinkHook); - - /** - Hook the console variables if they change - */ - HookConVarChange(sdb_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_donationflag, ConVarSettingsChanged); - HookConVarChange(sdb_joinsound_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_joinpubmsg_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_joinprivmsg_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_chatcolors_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_immunity_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_ubercharge_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_givehealth_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_nofalldmg_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_swapteam_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_fastheavy_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_soundfile, ConVarSettingsChanged); - HookConVarChange(sdb_chatcolor, ConVarSettingsChanged); - HookConVarChange(sdb_uberlevel, ConVarSettingsChanged); - HookConVarChange(sdb_healthcount, ConVarSettingsChanged); - HookConVarChange(sdb_healthbonus, ConVarSettingsChanged); - HookConVarChange(sdb_heavymultiplier, ConVarSettingsChanged); - - /** - Register the commands - */ - RegConsoleCmd("sm_swapteams", Command_SwapTeam, "sm_swapteams <[0]instant/[1]queued>: Swaps your team to the other team"); - RegConsoleCmd("sm_ihealth", Command_InstantHealth, "sm_ihealth: Gives you a instant health pack"); - RegAdminCmd("sm_teaser", Command_Teaser, ADMFLAG_GENERIC,"sm_teaser <[0]add/[1]remove>: Gives temporary donator privilages to a player"); - RegConsoleCmd("say", Command_Say); - - RegConsoleCmd("sm_test", Command_TEST); - - /** - Load the translations - */ - LoadTranslations("common.phrases"); - LoadTranslations("simpledonatorbenefits.phrases"); - - /** - Load or create the config file - */ - AutoExecConfig(true, "plugin.simpledonatorbenefits"); - LogAction(0, -1, "[SDB] Simple Donator Benefits is loaded."); -} - -public OnAllPluginsLoaded() -{ - //something -} - -public OnLibraryRemoved(const String:name[]) -{ - //something -} - -public OnConfigsExecuted() -{ - /** - Load up all the variable defaults - */ - LoadUpVariables(); - - /** - If the join sound is enabled, prep the sound files - */ - if (g_bIsJoinSoundEnabled) - PrepSoundFile(); - - /** - Log our activity - */ - if (g_bIsEnabled) - LogAction(0, -1, "Simple Donation Benefits is ENABLED"); - else - LogAction(0, -1, "Simple Donation Benefits is DISABLED"); -} - -public OnClientPostAdminCheck(client) -{ - - /** - Check if the client is a donator - */ - if (SM_IsValidAdmin(client, g_sCharDonatorFlag)) - { - - /** - They are, so we set the player array to true and start a timer for the sound or add - */ - g_aPlayers[client][bIsDonator] = true; - if (g_bIsJoinSoundEnabled || g_bIsJoinPrivMsgEnabled) - { - CreateTimer(10.0, Timer_DonatorJoined, client, TIMER_FLAG_NO_MAPCHANGE); - } - } - else - { - /** - They aren't, so we set the player array to false - */ - g_aPlayers[client][bIsDonator] = false; - } -} - -public OnClientDisconnect_Post(client) -{ - - /** - Clean up the player variables - */ - CleanUpPlayer(client); -} - -public Action:Command_SwapTeam(client, args) -{ - - /** - Make sure we are enabled - */ - if (!g_bIsEnabled || !g_bIsSwapTeamEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the command is not started by the server - */ - if (client == 0) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure the player is a donator - */ - if (!g_aPlayers[client][bIsDonator]) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Lets make sure the client is one a team we can swap. - If he is we set the global array to the opposite team. - */ - new iTeam = GetClientTeam(client); - if (iTeam == g_aCurrentTeams[Team1]) - { - g_aPlayers[client][iNewTeam] = g_aCurrentTeams[Team2]; - } - else if (iTeam == g_aCurrentTeams[Team2]) - { - g_aPlayers[client][iNewTeam] = g_aCurrentTeams[Team1]; - } - else - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "InValidTeam", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check to see if we have command arguments. - */ - if (GetCmdArgs()) - { - - /** - We do, so lets get it and see if the client wants to be switched instantly or queued for death. - */ - decl String:sArg[5]; - GetCmdArg(1, sArg, sizeof(sArg)); - new iWantsQue = StringToInt(sArg); - if (iWantsQue && !g_aPlayers[client][bQueue]) - { - - /** - He wants the que and isn't already in it, set the global array. - */ - g_aPlayers[client][bQueue] = true; - ReplyToCommand(client, "\x01\x04[STM]\x01 %T", "PlayerQueue", LANG_SERVER); - } - else if (!iWantsQue) - { - - /** - He wants to be switched right now, lets call the stock function. - */ - SM_MovePlayer(client, g_aPlayers[client][iNewTeam]); - } - } - else - { - - /** - There are no command arguments so we build and display the swap menu. - */ - new Handle:hPlayerMenu = BuildSwapModeMenu(); - DisplayMenu(hPlayerMenu, client, MENU_TIME_FOREVER); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_InstantHealth(client, args) -{ - - /** - Make sure we are enabled - */ - if (!g_bIsEnabled || !g_bIsGiveHealthEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the command is not started by the server - */ - if (client == 0) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure the player is a donator - */ - if (!g_aPlayers[client][bIsDonator]) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check health count to see if the player has reached the max - */ - if (g_aPlayers[client][iHealthCount] >= g_iHealthCount) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "ReachedCount", LANG_SERVER); - return Plugin_Handled; - } - - /** - Get the class of the player and the max health for that class - */ - new iHealth = GetClientHealth(client); - new TFClassType:PlayerClass = TF2_GetPlayerClass(client); - new iMaxHealth = g_iClassMaxHealth[PlayerClass]; - - /** - Check to see if the player is at the max health of the class - */ - if (iHealth >= iMaxHealth) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "AtMaxHealth", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check the current health - */ - if (iHealth + g_iHealthBonus >= iMaxHealth) - { - - /** - Raise them to max health if the current health + bonus would go above it - */ - SetEntityHealth(client, iMaxHealth); - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "ToMaxHealth", LANG_SERVER); - } - else - { - - /** - Give them the instant health bonus - */ - SetEntityHealth(client, iHealth + g_iHealthBonus); - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "HealthBonus", LANG_SERVER); - } - - /** - Increase the count - */ - g_aPlayers[client][iHealthCount] += 1; - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_Teaser(client, args) -{ - - /** - Make sure we are enabled - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Check to see if we have command arguments. - */ - new iCmdArgs = GetCmdArgs(); - if (iCmdArgs == 0) - { - - /** - We don't so display the player menu. - */ - new Handle:hPlayerMenu = BuildPlayerMenu(); - DisplayMenu(hPlayerMenu, client, MENU_TIME_FOREVER); - return Plugin_Handled; - } - - /** - We have some arguments, see if we can find the player - */ - decl String:sPlayer[64]; - GetCmdArg(1, sPlayer, sizeof(sPlayer)); - new iTarget = FindTarget(client, sPlayer, true, true); - if (iTarget == -1 || !IsClientInGame(iTarget)) - { - - /** - We don't know who this is, so display the player menu. - */ - new Handle:hPlayerMenu = BuildPlayerMenu(); - DisplayMenu(hPlayerMenu, client, MENU_TIME_FOREVER); - } - else - { - /** - We found the player, see if we are supposed to turn it on or off. - */ - if (iCmdArgs >= 2) - { - decl String:sOn[3]; - GetCmdArg(2, sOn, sizeof(sOn)); - if (StringToInt(sOn)) - { - - /** - Turn temp benefits on. - */ - g_aPlayers[iTarget][bIsDonator] = true; - } - else - { - - /** - Turn temp benefits on. - */ - g_aPlayers[iTarget][bIsDonator] = false; - } - } - else - { - - /** - We don't know what to do, so just turn it on. - */ - g_aPlayers[iTarget][bIsDonator] = true; - } - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_Say(client, args) -{ - - /** - Make sure we are enabled. - */ - if (client == 0 || IsChatTrigger() || !g_bIsChatColorsEnabled || !g_bIsEnabled) - { - return Plugin_Continue; - } - - /** - Check the client to see if they are a donator. - */ - if (g_aPlayers[client][bIsDonator]) - { - - /** - The client is, so get the chat message and strip it down. - */ - decl String:sArg[CHAT_MAX_MESSAGE_LENGTH], - String:sChatMsg[CHAT_MAX_MESSAGE_LENGTH]; - new bool:bAlive = IsPlayerAlive(client); - GetCmdArgString(sArg, sizeof(sArg)); - StripQuotes(sArg); - TrimString(sArg); - new startidx; - if (sArg[strlen(sArg)-1] == '"') - { - sArg[strlen(sArg)-1] = '\0'; - startidx = 1; - } - - /** - Bug out if they are using the admin chat symbol (admin chat). - */ - if (sArg[startidx] == CHAT_SYMBOL) - { - return Plugin_Continue; - } - - /** - Format the message. - */ - FormatMessage(client, 0, bAlive, sChatMsg, sArg); - - /** - Send the message. - */ - SayText2(0, client, sChatMsg); - - /** - We are done, bug out, and stop the original chat message. - */ - return Plugin_Stop; - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Hacks_TakeDamageHook(client, attacker, inflictor, Float:damage, &Float:multiplier, damagetype) -{ - - /** - Make sure we are enabled and the client is a donator. - */ - if (g_bIsEnabled && g_bIsNoFallDmgEnabled && g_aPlayers[client][bIsDonator]) - { - - /** - Check for fall damage. - */ - if (damagetype & DMG_FALL) - { - - /** - Cancel the fall damage and bug out. - */ - multiplier *= 0.0; - return Plugin_Changed; - } - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Hacks_PreThinkHook(client) -{ - - /** - Make sure we are enabled and the client is a donator. - */ - if (!g_bIsEnabled || !g_bIsFastHeayEnabled || !g_aPlayers[client][bIsDonator]) - { - return Plugin_Continue; - } - - /** - Check the players class. We are looking for the heavy. - */ - new TFClassType:PlayerClass = TF2_GetPlayerClass(client); - if (PlayerClass == TFClass_Heavy) - { - - /** - We have a heavy, lets check the weapon. - */ - decl String:sWeaponCurrent[64]; - GetClientWeapon(client, sWeaponCurrent, sizeof(sWeaponCurrent)); - if (StrEqual(sWeaponCurrent, "tf_weapon_minigun", false)) - { - - /** - We have a minigun, check the heavies current weapon state to see if it's spinning. - */ - new iWeapon = GetPlayerWeaponSlot(client, 0); - new iWeaponState = GetEntProp(iWeapon, Prop_Send, "m_iWeaponState"); - if (iWeaponState > 0) - { - - /** - He is spinning, so lets change the heavies speed. - */ - new Float:fMaxSpeed = FloatMul(g_fHeavyMultiplier, float(g_fClassMaxSpeed[PlayerClass])); - SetEntPropFloat(client, Prop_Send, "m_flMaxspeed", fMaxSpeed); - } - } - } - - /** - We are done, bug out. - */ - // use Plugin_Continue (other options are ignored on PreThink hook) - return Plugin_Continue; -} - -public Action:HookPlayerConnect(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (!g_bIsEnabled || !g_bIsJoinPubMsgEnabled || !dontBroadcast) - { - return Plugin_Continue; - } - - /** - Get our event variables and check the client. - */ - new iUserId = GetEventInt(event,"userid"); - new iClient = GetClientOfUserId(iUserId); - if (iClient != 0) - { - - /** - Get the info on the client and format the message. - */ - decl String:sClientName[255], - String:sAuthID[255], - String:sMsg[1024]; - - GetEventString(event, "name", sClientName, sizeof(sClientName)); - GetClientAuthString(iClient, sAuthID, sizeof(sAuthID)); - Format(sMsg, sizeof(sMsg), "%T", "PublicJoinMessage", LANG_SERVER, sClientName); - - /** - Print the message to the clients and do the normal functions. - */ - for (new i = 1; i <= MaxClients; i++) - { - if(IsClientConnected(i) && IsClientInGame(i)) - { - PrintToChat(i,"\x01\x05%s", sMsg); - PrintToConsole(i,"%s has connected.", sClientName); - } - } - LogToGame("\"%s<%d><%s><>\" entered the game", sClientName, iUserId, sAuthID); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public HookPlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled && g_bIsUberChargeEnabled) - { - - /** - Get the event variables and check the class for medic - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - if (TF2_GetPlayerClass(iClient) == TFClass_Medic) - { - - /** - Start a timer to get the medic the uber boost - */ - CreateTimer(0.25, Timer_PlayerUberDelay, iClient, TIMER_FLAG_NO_MAPCHANGE); - } - } -} - -public HookPlayerClass(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled && g_bIsUberChargeEnabled) - { - - /** - Get the event variables and check the class for medic - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - if (TF2_GetPlayerClass(iClient) == TFClass_Medic) - { - - /** - Start a timer to get the medic the uber boost - */ - CreateTimer(0.25, Timer_PlayerUberDelay, iClient, TIMER_FLAG_NO_MAPCHANGE); - } - } -} - -public HookPlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled || g_bIsSwapTeamEnabled) - { - - /** - Get the event variables - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - new String:sWeapon[256]; - GetEventString(event, "weapon", sWeapon, sizeof(sWeapon)); - - /** - Bug out if world killed him. Means he changed team or something - */ - if (StrEqual(sWeapon, "world", false)) - { - g_aPlayers[iClient][bQueue] = false; - return; - } - - /** - If he is queued up, swap him - */ - if (g_aPlayers[iClient][bQueue]) - { - SM_MovePlayer(iClient, g_aPlayers[iClient][iNewTeam]); - } - } -} - -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled || g_bIsSwapTeamEnabled) - { - - /** - Get the event variables - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - - /** - If he is queued up, clear the status - */ - if (g_aPlayers[iClient][bQueue]) - { - g_aPlayers[iClient][bQueue] = false; - } - } -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set our variables. - */ - g_bRoundEnd = false; - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled && g_bIsImmuntyEnabled) - { - - /** - Get rid of their immunity. - */ - ProcessRoundEndImmunity(false); - } -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set our variables. - */ - g_bRoundEnd = true; - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled && g_bIsImmuntyEnabled) - { - - /** - Give them their immunity. - */ - ProcessRoundEndImmunity(true); - } -} - -public Action:Timer_DonatorJoined(Handle:timer, any:client) -{ - - /** - Make sure sounds are enabled. - */ - if (g_bIsEnabled && g_bIsJoinSoundEnabled) - { - EmitSoundToClient(client, g_sSoundFile); - } - - /** - Make sure private messages are enabled. - */ - if (g_bIsJoinPrivMsgEnabled) - { - - /** - Send messages to the client. - */ - decl String:sMsg[1024]; - Format(sMsg, sizeof(sMsg), "%T", "PrivateJoinMessage", LANG_SERVER); - PrintToChat(client,"\x01\x05%s", sMsg); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Timer_PlayerUberDelay(Handle:timer, any:client) -{ - - /** - Make sure the client is still in game. - */ - if (IsClientInGame(client)) - { - - /** - Make sure the client is still a medic. - */ - if (TF2_GetPlayerClass(client) == TFClass_Medic) - { - - /** - Get the medgun weapon index - */ - new iIndex = GetPlayerWeaponSlot(client, 1); - if (iIndex > 0) - { - - /** - Set the uber level with the bonus. - */ - SetEntPropFloat(iIndex, Prop_Send, "m_flChargeLevel", g_fUberLevel); - } - } - } -} - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (convar == sdb_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsEnabled = false; - } - else - { - g_bIsEnabled = true; - } - } - else if (convar == sdb_donationflag) - { - Format(g_sCharDonatorFlag, sizeof(g_sCharDonatorFlag), "%s", newValue); - } - else if (convar == sdb_soundfile) - { - Format(g_sSoundFile, sizeof(g_sSoundFile), "%s", newValue); - } - else if (convar == sdb_joinsound_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsJoinSoundEnabled = false; - } - else - { - g_bIsJoinSoundEnabled = true; - } - } - else if (convar == sdb_joinpubmsg_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsJoinPubMsgEnabled = false; - } - else - { - g_bIsJoinPubMsgEnabled = true; - } - } - else if (convar == sdb_joinprivmsg_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsJoinPrivMsgEnabled = false; - } - else - { - g_bIsJoinPrivMsgEnabled = true; - } - } - else if (convar == sdb_chatcolors_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsChatColorsEnabled = false; - } - else - { - g_bIsChatColorsEnabled = true; - } - } - else if (convar == sdb_immunity_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsImmuntyEnabled = false; - } - else - { - g_bIsImmuntyEnabled = true; - } - } - else if (convar == sdb_ubercharge_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsUberChargeEnabled = false; - } - else - { - g_bIsUberChargeEnabled = true; - } - } - else if (convar == sdb_givehealth_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsGiveHealthEnabled = false; - } - else - { - g_bIsGiveHealthEnabled = true; - } - } - else if (convar == sdb_nofalldmg_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsNoFallDmgEnabled = false; - } - else - { - g_bIsNoFallDmgEnabled = true; - } - } - else if (convar == sdb_fastheavy_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsFastHeayEnabled = false; - } - else - { - g_bIsFastHeayEnabled = true; - } - } - else if (convar == sdb_swapteam_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsSwapTeamEnabled = false; - } - else - { - g_bIsSwapTeamEnabled = true; - } - } - else if (convar == sdb_chatcolor) - { - Format(g_sChatColor, sizeof(g_sChatColor), "%s", newValue); - } - else if (convar == sdb_uberlevel) - { - g_fUberLevel = StringToFloat(newValue); - } - else if (convar == sdb_healthcount) - { - g_iHealthCount = StringToInt(newValue); - } - else if (convar == sdb_healthbonus) - { - g_iHealthBonus = StringToInt(newValue); - } - else if (convar == sdb_heavymultiplier) - { - g_fHeavyMultiplier = StringToFloat(newValue); - } -} - -stock LoadUpVariables() -{ - g_bIsEnabled = GetConVarBool(sdb_enabled); - g_bIsJoinSoundEnabled = GetConVarBool(sdb_enabled); - g_bIsJoinPubMsgEnabled = GetConVarBool(sdb_enabled); - g_bIsJoinPrivMsgEnabled = GetConVarBool(sdb_enabled); - g_bIsChatColorsEnabled = GetConVarBool(sdb_enabled); - g_bIsImmuntyEnabled = GetConVarBool(sdb_enabled); - g_bIsUberChargeEnabled = GetConVarBool(sdb_enabled); - g_bIsGiveHealthEnabled = GetConVarBool(sdb_enabled); - g_bIsNoFallDmgEnabled = GetConVarBool(sdb_enabled); - g_bIsFastHeayEnabled = GetConVarBool(sdb_enabled); - g_bIsSwapTeamEnabled = GetConVarBool(sdb_enabled); - GetConVarString(sdb_donationflag, g_sCharDonatorFlag, sizeof(g_sCharDonatorFlag)); - GetConVarString(sdb_soundfile, g_sSoundFile, sizeof(g_sSoundFile)); - GetConVarString(sdb_chatcolor, g_sChatColor, sizeof(g_sChatColor)); - g_bRoundEnd = false; - g_iHealthBonus = GetConVarInt(sdb_healthbonus); - g_iHealthCount = GetConVarInt(sdb_healthcount); - g_fHeavyMultiplier = GetConVarFloat(sdb_heavymultiplier); - g_fUberLevel = GetConVarFloat(sdb_uberlevel); -} - -stock PrepSoundFile() -{ - decl String:buffer[PLATFORM_MAX_PATH]; - PrecacheSound(g_sSoundFile, true); - Format(buffer, sizeof(buffer), "sound/%s", g_sSoundFile); - AddFileToDownloadsTable(buffer); -} - -stock CleanUpPlayer(client) -{ - g_aPlayers[client][bIsDonator] = false; - g_aPlayers[client][bQueue] = false; - g_aPlayers[client][bImmune] = false; - g_aPlayers[client][iNewTeam] = 0; - g_aPlayers[client][iHealthCount] = 0; -} - -stock ProcessRoundEndImmunity(bool:give) -{ - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][bIsDonator]) - { - if (give) - { - SetEntProp(i, Prop_Data, "m_takedamage", 0, 1); - g_aPlayers[i][bImmune] = true; - } - else - { - SetEntProp(i, Prop_Data, "m_takedamage", 2, 1); - g_aPlayers[i][bImmune] = false; - } - } - } -} - -stock FormatMessage(iClient, iTeam, bool:bAlive, String:sChatMsg[], const Sting:sMessage[]) -{ - decl String:sDead[10], - String:sTeam[10], - String:sClientName[64]; - GetClientName(iClient, sClientName, sizeof(sClientName)); - if (iTeam != 0) - Format(sTeam, sizeof(sTeam), "(TEAM) "); - else - Format(sTeam, sizeof(sTeam), ""); - if (bAlive) - Format(sDead, sizeof(sDead), ""); - else - Format(sDead, sizeof(sDead), "*DEAD* "); - if (StrContains(g_sChatColor, "light", false) == -1) - Format(sChatMsg, CHAT_MAX_MESSAGE_LENGTH, "\x01%s%s\x03%s \x01: \x05%s", sDead, sTeam, sClientName, sMessage); - else - Format(sChatMsg, CHAT_MAX_MESSAGE_LENGTH, "\x01%s%s\x03%s \x01: \x04%s", sDead, sTeam, sClientName, sMessage); -} - -stock SayText2(target, author, const String:message[]) -{ - new Handle:hBf; - if (target == 0) - hBf = StartMessageAll("SayText2"); - else - hBf = StartMessageOne("SayText2", target); - if (hBf != INVALID_HANDLE) - { - BfWriteByte(hBf, author); - BfWriteByte(hBf, true); - BfWriteString(hBf, message); - EndMessage(); - } -} - -stock ProcessAdmins() -{ - for (new i = 1; i <= MaxClients; i++) - { - if (SM_IsValidAdmin(i, g_sCharDonatorFlag)) - { - g_aPlayers[i][bDonator] = true; - } - else - { - g_aPlayers[i][bDonator] = false; - } - } -} - -stock ProcessLate() -{ - if (g_bIsEnabled) - { - ProcessAdmins(); - PrepSoundFile(); - if (g_bRoundEnd && g_bIsImmuntyEnabled) - { - ProcessRoundEndImmunity(true); - } - if (!g_bIsImmuntyEnabled) - { - ProcessRoundEndImmunity(false); - } - } - else - { - ProcessRoundEndImmunity(false); - } -} - -public Menu_SwapMode(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, 64); - if (StringToInt(sSelection)) - g_aPlayers[param1][bQueue] = false; - else - g_aPlayers[param1][bQueue] = true; - if (!g_aPlayers[param1][bQueue]) - SM_MovePlayer(param1, g_aPlayers[param1][iNewTeam]); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -public Menu_SelectPlayer(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[256]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - new iTarget = GetClientOfUserId(StringToInt(sSelection)); - if (g_aPlayers[iTarget][bIsDonator]) - g_aPlayers[iTarget][bIsDonator] = false; - else - g_aPlayers[iTarget][bIsDonator] = true; - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -stock Handle:BuildSwapModeMenu() -{ - new Handle:menu = CreateMenu(Menu_SwapMode); - SetMenuTitle(menu, "Select When to Swap:"); - AddMenuItem(menu, "0", "Instantly (Kills)"); - AddMenuItem(menu, "1", "Queue on next death"); - SetMenuExitBackButton(menu, false); - return menu; -} - -stock Handle:BuildPlayerMenu() -{ - new Handle:menu = CreateMenu(Menu_SelectPlayer); - AddTargetsToMenu(menu, 0, true, false); - SetMenuTitle(menu, "Select A Player:"); - SetMenuExitBackButton(menu, true); - return menu; -} - -public Action:Command_TEST(client, args) -{ - -} \ No newline at end of file diff --git a/Simple Message Suppression/addons/sourcemod/scripting/simple-plugins.sp b/Simple Message Suppression/addons/sourcemod/scripting/simple-plugins.sp deleted file mode 100644 index 4462b41..0000000 --- a/Simple Message Suppression/addons/sourcemod/scripting/simple-plugins.sp +++ /dev/null @@ -1,785 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Plugins -Description: - Core plugin for Simple Plugins project -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#define CORE_PLUGIN_VERSION "1.1.$Rev$" - -#include - -enum e_PlayerInfo -{ - Handle:hForcedTeamPlugin = INVALID_HANDLE, - iForcedTeam = 0, - iBuddy = 0, - bool:bBuddyLocked = false -}; - -new Handle:g_fwdPlayerMoved; -new g_aPlayers[MAXPLAYERS + 1][e_PlayerInfo]; -new bool:g_bTeamsSwitched = false; - -/** -Setting our plugin information. -*/ -public Plugin:myinfo = -{ - name = "Simple Plugins Core Plugin", - author = "Simple Plugins", - description = "Core plugin for Simple Plugins", - version = CORE_PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -public bool:AskPluginLoad(Handle:myself, bool:late, String:error[], err_max) -{ - - /** - Register natives for other plugins - */ - CreateNative("SM_MovePlayer", Native_SM_MovePlayer); - CreateNative("SM_SetForcedTeam", Native_SM_SetForcedTeam); - CreateNative("SM_GetForcedTeam", Native_SM_GetForcedTeam); - CreateNative("SM_ClearForcedTeam", Native_SM_ClearForcedTeam); - CreateNative("SM_GetForcedPlayer", Native_SM_GetForcedPlayer); - CreateNative("SM_AssignBuddy", Native_SM_AssignBuddy); - CreateNative("SM_GetClientBuddy", Native_SM_GetClientBuddy); - CreateNative("SM_LockBuddy", Native_SM_LockBuddy); - CreateNative("SM_IsBuddyLocked", Native_SM_IsBuddyLocked); - CreateNative("SM_ClearBuddy", Native_SM_ClearBuddy); - CreateNative("SM_IsValidAdmin", Native_SM_IsValidAdmin); - CreateNative("SM_IsValidTeam", Native_SM_IsValidTeam); - RegPluginLibrary("simpleplugins"); - return true; -} - -public OnPluginStart() -{ - - CreateConVar("ssm_core_pl_ver", CORE_PLUGIN_VERSION, "Simple SourceMod Plugins Core Plugin Version", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - CreateConVar("ssm_core_inc_ver", CORE_INC_VERSION, "Simple SourceMod Plugins Core Include Version", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook some events to control forced players and check extensions - */ - decl String:sExtError[256]; - LogAction(0, -1, "[SSM] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Pre); - switch (g_CurrentMod) - { - case GameType_CSS: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - new iExtStatus = GetExtensionFileStatus("game.cstrike.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SSM] Required extension was not found."); - LogAction(0, -1, "[SSM] Plugin FAILED TO LOAD."); - SetFailState("Required extension was not found."); - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SSM] Required extension is loaded with errors."); - LogAction(0, -1, "[SSM] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SSM] Plugin FAILED TO LOAD."); - SetFailState("Required extension is loaded with errors."); - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SSM] Required extension is loaded."); - } - } - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_PostNoCopy); - HookUserMessage(GetUserMessageId("TextMsg"), UserMessageHook_Class, true); - new iExtStatus = GetExtensionFileStatus("game.tf2.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SSM] Required extension was not found."); - LogAction(0, -1, "[SSM] Plugin FAILED TO LOAD."); - SetFailState("Required extension was not found."); - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SSM] Required extension is loaded with errors."); - LogAction(0, -1, "[SSM] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SSM] Plugin FAILED TO LOAD."); - SetFailState("Required extension is loaded with errors."); - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SSM] Required extension is loaded."); - } - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_PostNoCopy); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - - /** - Load common translations - */ - LoadTranslations ("common.phrases"); - - /** - Create the global forward - */ - g_fwdPlayerMoved = CreateGlobalForward("SM_OnPlayerMoved", ET_Event, Param_Cell, Param_Cell, Param_Cell); -} - -public OnClientDisconnect(client) -{ - - /** - Cleanup clients/players buddy list - */ - if (!IsFakeClient(client)) - { - SM_ClearBuddy(client, true); - SM_LockBuddy(client, false); - } - SM_ClearForcedTeam(client); -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - See if the teams have been switched - */ - if (g_bTeamsSwitched) - { - - /** - Switch the teams the players are forced to - */ - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][iForcedTeam] != 0) - { - if (g_aPlayers[i][iForcedTeam] == g_aCurrentTeams[Team1]) - { - g_aPlayers[i][iForcedTeam] = g_aCurrentTeams[Team2]; - } - else - { - g_aPlayers[i][iForcedTeam] = g_aCurrentTeams[Team1]; - } - } - } - } -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - g_bTeamsSwitched = false; -} - -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get our event variables - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - new iTeam = GetEventInt(event, "team"); - - /** - See if the player is on the wrong team - */ - if (g_aPlayers[iClient][iForcedTeam] != 0 && g_aPlayers[iClient][iForcedTeam] != iTeam) - { - - /** - Move the player back to the forced team - */ - CreateTimer(1.0, Timer_ForcePlayerMove, iClient, TIMER_FLAG_NO_MAPCHANGE); - - /** - If the event was going to be broadcasted, we refire it so it is not broadcasted and stop this one - */ - if (!dontBroadcast) - { - new Handle:hEvent = CreateEvent("player_team"); - SetEventInt(hEvent, "userid", GetEventInt(event, "userid")); - SetEventInt(hEvent, "team", GetEventInt(event, "team")); - SetEventInt(hEvent, "oldteam", GetEventInt(event, "oldteam")); - SetEventBool(hEvent, "disconnect", GetEventBool(event, "disconnect")); - - if (g_CurrentMod == GameType_DOD || g_CurrentMod == GameType_L4D || g_CurrentMod == GameType_TF) - { - new String:sClientName[MAX_NAME_LENGTH + 1]; - GetClientName(client, sClientName, sizeof(sClientName)); - SetEventBool(hEvent, "autoteam", GetEventBool(event, "autoteam")); - SetEventBool(hEvent, "silent", true); - SetEventString(hEvent, "name", sClientName); - FireEvent(hEvent, true); - } - else - { - FireEvent(hEvent, true); - } - return Plugin_Handled; - } - } - return Plugin_Continue; -} - -public Action:UserMessageHook_Class(UserMsg:msg_id, Handle:bf, const players[], playersNum, bool:reliable, bool:init) -{ - new String:sMessage[120]; - BfReadString(bf, sMessage, sizeof(sMessage), true); - if (StrContains(sMessage, "#TF_TeamsSwitched", false) != -1) - { - g_bTeamsSwitched = true; - } - return Plugin_Continue; -} - -public Native_SM_MovePlayer(Handle:plugin, numParams) -{ - - /** - Get and check the client and team - */ - new iClient = GetNativeCell(1); - new iTeam = GetNativeCell(2); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (iTeam != g_aCurrentTeams[Spectator] && iTeam != g_aCurrentTeams[Team1] && iTeam != g_aCurrentTeams[Team2]) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid team %d", iTeam); - } - - MovePlayer(iClient, iTeam); - if (!IsClientObserver(iClient)) - { - RespawnPlayer(iClient); - } - - new fResult; - - Call_StartForward(g_fwdPlayerMoved); - Call_PushCell(plugin); - Call_PushCell(iClient); - Call_PushCell(iTeam); - Call_Finish(fResult); - - if (fResult != SP_ERROR_NONE) - { - return ThrowNativeError(fResult, "Forward failed"); - } - - return fResult; -} - -public Native_SM_SetForcedTeam(Handle:plugin, numParams) -{ - - /** - Get and check the client and team - */ - new iClient = GetNativeCell(1); - new iTeam = GetNativeCell(2); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (iTeam != g_aCurrentTeams[Spectator] && iTeam != g_aCurrentTeams[Team1] && iTeam != g_aCurrentTeams[Team2] && iTeam != g_aCurrentTeams[Unknown]) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid team %d", iTeam); - } - - new bool:bOverRide = GetNativeCell(3) ? true : false; - - if (!bOverRide && g_aPlayers[iClient][hForcedTeamPlugin] != INVALID_HANDLE && plugin != g_aPlayers[iClient][hForcedTeamPlugin]) - { - return false; - } - - g_aPlayers[iClient][hForcedTeamPlugin] = plugin; - g_aPlayers[iClient][iForcedTeam] = iTeam; - return true; -} - -public Native_SM_GetForcedTeam(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - - /** - Get and set the plugin if they want it - */ - new Handle:hPlugin = GetNativeCell(2); - if (hPlugin != INVALID_HANDLE) - { - SetNativeCellRef(2, g_aPlayers[iClient][hForcedTeamPlugin]); - } - - /** - Return the forced team, this could be 0 - */ - return g_aPlayers[iClient][iForcedTeam]; -} - -public Native_SM_ClearForcedTeam(Handle:plugin, numParams) -{ - - /** - Get and check the client and team - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - - g_aPlayers[iClient][hForcedTeamPlugin] = INVALID_HANDLE; - g_aPlayers[iClient][iForcedTeam] = 0; - - return true; -} - -public Native_SM_GetForcedPlayer(Handle:plugin, numParams) -{ - - /** - Get and check the team - */ - new iTeam = GetNativeCell(1); - if (iTeam != g_aCurrentTeams[Spectator] && iTeam != g_aCurrentTeams[Team1] && iTeam != g_aCurrentTeams[Team2]) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid team %d", iTeam); - } - - /** - Start a loop to check for a player on the wrong team - Also make sure the plugin that set the forced team is the plugin that asked - */ - new iPlayer = 0; - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientInGame(i) - && GetClientTeam(i) != g_aPlayers[i][iForcedTeam] - && g_aPlayers[i][iForcedTeam] == iTeam - && g_aPlayers[i][hForcedTeamPlugin] == plugin) - { - iPlayer = i; - break; - } - } - - /** - Return the player we found, this could be 0 - */ - return iPlayer; -} - -public Native_SM_AssignBuddy(Handle:plugin, numParams) -{ - - /** - Get and check the client and player - */ - new iClient = GetNativeCell(1); - new iPlayer = GetNativeCell(2); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (iPlayer < 0 || iPlayer > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid player index (%d)", iPlayer); - } - if (!IsClientConnected(iPlayer)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Player %d is not connected", iPlayer); - } - if (!IsClientInGame(iPlayer)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Player %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Bots are not supported"); - } - - /** - See if we can override his setting - */ - new bool:bOverRide = GetNativeCell(3) ? true : false; - if (!bOverRide) - { - - /** - We can't override, so check if they are locked - */ - if (g_aPlayers[iClient][bBuddyLocked] || g_aPlayers[iPlayer][bBuddyLocked]) - { - - /** - We detected at least 1 lock, so we bug out - */ - return false; - } - } - - /** - Ready to set the buddies - */ - g_aPlayers[iClient][iBuddy] = iPlayer; - g_aPlayers[iPlayer][iBuddy] = iClient; - return true; -} - -public Native_SM_GetClientBuddy(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Bots are not supported"); - } - - /** - Return the players buddy, this could be 0 - */ - return g_aPlayers[iClient][iBuddy]; -} - -public Native_SM_LockBuddy(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - new bool:bSetting = GetNativeCell(2) ? true : false; - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Bots are not supported"); - } - - g_aPlayers[iClient][bBuddyLocked] = bSetting; - return true; -} - -public Native_SM_IsBuddyLocked(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Bots are not supported"); - } - - return g_aPlayers[iClient][bBuddyLocked]; -} - -public Native_SM_ClearBuddy(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Client (%d) is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Bots are not supported"); - } - - /** - Get the clients buddy and see if we can override his setting - */ - new bool:bOverRide = GetNativeCell(2) ? true : false; - new iPlayer = g_aPlayers[iClient][iBuddy]; - - /** - There is no buddy, we don't care about anything else so bug out - */ - if (iPlayer == 0) - { - return true; - } - - /** - We determined he had a buddy, check the override setting - */ - if (!bOverRide) - { - - /** - We can't override, so check if they are locked - */ - if (g_aPlayers[iClient][bBuddyLocked] || g_aPlayers[iPlayer][bBuddyLocked]) - { - - /** - We detected at least 1 lock, so we bug out - */ - return false; - } - } - - /** - Ready to clear the buddies - */ - g_aPlayers[iClient][iBuddy] = 0; - g_aPlayers[iPlayer][iBuddy] = 0; - return true; -} - -public Native_SM_IsValidTeam(Handle:plugin, numParams) -{ - - /** - Get the team - */ - new iTeam = GetNativeCell(1); - - /** - Check the team - */ - if (iTeam == g_aCurrentTeams[Spectator] || iTeam == g_aCurrentTeams[Team1] || iTeam == g_aCurrentTeams[Team2]) - { - return true; - } - return false; -} - -public Native_SM_IsValidAdmin(Handle:plugin, numParams) -{ - /** - Get the client and flags - */ - new iClient = GetNativeCell(1); - decl String:sFlags[15]; - GetNativeString(2, sFlags, sizeof(sFlags)); - new ibFlags = ReadFlagString(sFlags); - - /** - Check the flags - */ - if ((GetUserFlagBits(iClient) & ibFlags) == ibFlags) - { - return true; - } - if (GetUserFlagBits(iClient) & ADMFLAG_ROOT) - { - return true; - } - return false; -} - -public Action:Timer_ForcePlayerMove(Handle:timer, any:iClient) -{ - - MovePlayer(iClient, g_aPlayers[iClient][iForcedTeam]); - - if (g_aPlayers[iClient][iForcedTeam] != g_aCurrentTeams[Spectator]) - { - RespawnPlayer(iClient); - } - - PrintToChat(iClient, "\x01\x04----------------------------------"); - PrintToChat(iClient, "\x01\x04You have been forced to this team."); - PrintToChat(iClient, "\x01\x04----------------------------------"); - - return Plugin_Handled; -} - -stock MovePlayer(iClient, iTeam) -{ - - /** - Change the client's team based on the mod - */ - switch (g_CurrentMod) - { - case GameType_CSS: - { - CS_SwitchTeam(iClient, iTeam); - } - default: - { - ChangeClientTeam(iClient, iTeam); - } - } -} - -stock RespawnPlayer(iClient) -{ - - /** - Respawn the client based on the mod - */ - switch (g_CurrentMod) - { - case GameType_CSS: - { - CS_RespawnPlayer(iClient); - } - case GameType_TF: - { - TF2_RespawnPlayer(iClient); - } - case GameType_INS: - { - FakeClientCommand(iClient, "kill"); - } - default: - { - // - } - } -} diff --git a/Simple Message Suppression/addons/sourcemod/scripting/simple-roundimmunity.sp b/Simple Message Suppression/addons/sourcemod/scripting/simple-roundimmunity.sp deleted file mode 100644 index 5f0bca3..0000000 --- a/Simple Message Suppression/addons/sourcemod/scripting/simple-roundimmunity.sp +++ /dev/null @@ -1,947 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Round Immunity -Description: - Gives admins immunity during certain rounds -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or any later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#pragma semicolon 1 -#include -#include -#undef REQUIRE_EXTENSIONS -#undef AUTOLOAD_EXTENSIONS -#include -#include -#define REQUIRE_EXTENSIONS -#define AUTOLOAD_EXTENSIONS - -#define PLUGIN_VERSION "1.1.$Rev$" -#define SPECTATOR 1 -#define TEAM_RED 2 -#define TEAM_BLUE 3 - -#define COLOR_GREEN 0 -#define COLOR_BLACK 1 -#define COLOR_RED 2 -#define COLOR_BLUE 3 -#define COLOR_TEAM 4 -#define COLOR_RAINBOW 5 -#define COLOR_NONE 6 - -#define PLAYERCOND_SLOWED (1<<0) //1 -#define PLAYERCOND_ZOOMED (1<<1) //2 -#define PLAYERCOND_DISGUISING (1<<2) //4 -#define PLAYERCOND_DISGUISED (1<<3) //8 -#define PLAYERCOND_SPYCLOAK (1<<4) //16 -#define PLAYERCOND_UBERED (1<<5) //32 -#define PLAYERCOND_TELEPORTTRAIL (1<<6) //64 -#define PLAYERCOND_TAUNT (1<<7) //128 -// (1<<8) //256 -// (1<<9) //512 -#define PLAYERCOND_TELEPORTFLASH (1<<10) //1024 -#define PLAYERCOND_KRUBER (1<<11) //2048 -// (1<<12) //4096 -// (1<<13) //8192 -#define PLAYERCOND_BONKED (1<<14) //16384 (blame Neph if it doesn't work) -#define PLAYERCOND_BONKEDORDRINKSLOWDOWN (1<<15) //32768 -#define PLAYERCOND_HEALING (1<<16) //65536 -#define PLAYERCOND_BURNING (1<<17) //131072 -#define PLAYERCOND_FULLYCHARGEDBYMEDIC (1<<18) //262144 - -enum e_Cookies -{ - bEnabled, - iColor, - iMode -}; - -enum e_ColorNames -{ - Green, - Black, - Red, - Blue -}; - -enum e_ColorValues -{ - iRed, - iGreen, - iBlue -}; - -enum e_PlayerData -{ - Handle:hGodModeTimer, - Handle:hColorTimer, - bool:bIsAdmin, - bool:bIsImmune, - iCycleColor -}; - -/** - Global convar handles - */ -new Handle:sri_charadminflag = INVALID_HANDLE; -new Handle:sri_enabled = INVALID_HANDLE; -new Handle:sri_cookie_enabled = INVALID_HANDLE; -new Handle:sri_cookie_color = INVALID_HANDLE; -new Handle:sri_cookie_mode = INVALID_HANDLE; - -/** - Player arrays - */ -new g_aPlayers[MAXPLAYERS + 1][e_PlayerData]; -new g_aClientCookies[MAXPLAYERS + 1][e_Cookies]; - -/** - Global bools - */ -new bool:g_bLoadedLate = false; -new bool:g_bIsEnabled = true; -new bool:g_bRoundEnd = false; -new bool:g_bUseDukehacks = false; -new bool:g_bUseClientprefs = false; - -/** - Global strings/integers/floats - */ -new String:g_sCharAdminFlag[32]; -new g_iColors[e_ColorNames][e_ColorValues]; -new g_iClassMaxHealth[TFClassType] = {0, 125, 125, 200, 175, 150, 300, 175, 125, 125}; - -public Plugin:myinfo = -{ - name = "Simple Round Immunity", - author = "Simple Plugins", - description = "Gives admins immunity during certain rounds", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -} - -bool:AskPluginLoad(Handle:myself, bool:late, String:error[], err_max) -{ - g_bLoadedLate = late; - return true; -} - -public OnPluginStart() -{ - - /** - Create console variables - */ - CreateConVar("sri_version", PLUGIN_VERSION, "Simple Round Immunity", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - sri_enabled = CreateConVar("sri_enabled", "1", "Enable/Disable Admin immunity during certain round."); - sri_charadminflag = CreateConVar("sri_charadminflag", "a", "Admin flag to use for immunity (only one). Must be a in char format."); - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook some events and check extensions - */ - decl String:sExtError[256]; - LogAction(0, -1, "[SRI] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_spawn", HookPlayerSpawn, EventHookMode_Post); - HookEvent("player_hurt", HookPlayerHurt, EventHookMode_Pre); - switch (g_CurrentMod) - { - case GameType_CSS: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - new iExtStatus = GetExtensionFileStatus("game.cstrike.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SRI] Required extension was not found."); - LogAction(0, -1, "[SRI] Plugin FAILED TO LOAD."); - SetFailState("Required extension was not found."); - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SRI] Required extension is loaded with errors."); - LogAction(0, -1, "[SRI] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SRI] Plugin FAILED TO LOAD."); - SetFailState("Required extension is loaded with errors."); - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SRI] Required css extension is loaded."); - } - } - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_PostNoCopy); - HookUserMessage(GetUserMessageId("TextMsg"), UserMessageHook_Class, true); - new iExtStatus = GetExtensionFileStatus("game.tf2.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SRI] Required extension was not found."); - LogAction(0, -1, "[SRI] Plugin FAILED TO LOAD."); - SetFailState("Required extension was not found."); - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SRI] Required extension is loaded with errors."); - LogAction(0, -1, "[SRI] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SRI] Plugin FAILED TO LOAD."); - SetFailState("Required extension is loaded with errors."); - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SRI] Required tf2 extension is loaded."); - } - iExtStatus = GetExtensionFileStatus("dukehacks.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SRI] Dukehacks extension was not found."); - LogAction(0, -1, "[SRI] Plugin continued to load, but that feature will not be used."); - g_bUseDukehacks = false; - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SRI] Dukehacks extension is loaded with errors."); - LogAction(0, -1, "[SRI] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SRI] Plugin continued to load, but that feature will not be used."); - g_bUseDukehacks = false; - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SRI] Dukehacks extension is loaded and will be used."); - g_bUseDukehacks = true; - dhAddClientHook(CHK_TakeDamage, Hacks_TakeDamageHook); - } - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_PostNoCopy); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - /** - Now lets check for client prefs extension - */ - new iExtStatus = GetExtensionFileStatus("clientprefs.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SRI] Client Preferences extension was not found."); - LogAction(0, -1, "[SRI] Plugin continued to load, but that feature will not be used."); - g_bUseClientprefs = false; - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SRI] Client Preferences extension is loaded with errors."); - LogAction(0, -1, "[SRI] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SRI] Plugin continued to load, but that feature will not be used."); - g_bUseClientprefs = false; - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SRI] Client Preferences extension is loaded, checking database."); - if (!SQL_CheckConfig(clientprefs)) - { - LogAction(0, -1, "[SRI] No 'clientprefs' database found. Check your database.cfg file."); - LogAction(0, -1, "[SRI] Plugin continued to load, but Client Preferences will not be used."); - g_bUseClientprefs = false; - } - g_bUseClientprefs = true; - - /** - Deal with client cookies - */ - sri_cookie_enabled = RegClientCookie("bri_client_enabled", "Enable/Disable your immunity during the bonus round.", CookieAccess_Public); - sri_cookie_color = RegClientCookie("bri_client_color", "Color to render when immune.", CookieAccess_Public); - sri_cookie_mode = RegClientCookie("bri_client_mode", "God mode to select", CookieAccess_Public); - SetCookieMenuItem(CookieMenu_TopMenu, sri_cookie_enabled, "Bonus Round Immunity"); - } - - HookConVarChange(sri_enabled, EnabledChanged); - - RegAdminCmd("sm_immunity", Command_Immunity, ADMFLAG_ROOT, "sm_immunity: Gives you immunity"); - - LoadColors(); - - AutoExecConfig(true, "plugin.simpleroundimmunity"); -} - -public OnAllPluginsLoaded() -{ - //something - // need to deal with the unloading of dukehacks, clientprefs, and simpleplugins - // should move hooking the client prefs cookies to a function to make sure they are done post plugin start if ext is loaded late -} - -public OnLibraryRemoved(const String:name[]) -{ - //something - // need to deal with the loading of dukehacks, clientprefs, and simpleplugins -} - -public OnConfigsExecuted() -{ - GetConVarString(sri_charadminflag, g_sCharAdminFlag, sizeof(g_sCharAdminFlag)); - g_bIsEnabled = GetConVarBool(sri_enabled); - g_bRoundEnd = false; -} - -/** - Client events - */ - -public OnClientPostAdminCheck(client) -{ - if (SM_IsValidAdmin(client, g_sCharAdminFlag)) - g_aPlayers[client][bIsAdmin] = true; - else - g_aPlayers[client][bIsAdmin] = false; -} - -public OnClientCookiesCached(client) -{ - decl String:sEnabled[2], String:sColor[4], String:sMode[2]; - GetClientCookie(client, sri_cookie_enabled, sEnabled, sizeof(sEnabled)); - GetClientCookie(client, sri_cookie_color, sColor, sizeof(sColor)); - GetClientCookie(client, sri_cookie_mode, sMode, sizeof(sMode)); - g_aClientCookies[client][bEnabled] = StringToInt(sEnabled); - g_aClientCookies[client][iColor] = StringToInt(sColor); - g_aClientCookies[client][iMode] = StringToInt(sMode); -} - -public OnClientDisconnect(client) -{ - CleanUp(client); -} - -/** - Commands - */ - -public Action:Command_Immunity(client, args) -{ - if (g_aPlayers[client][IsImmune]) - { - DisableImmunity(client); - } - else - { - EnableImmunity(client); - } - return Plugin_Handled; -} - -/** - Event hooks - */ - -public Action:Hacks_TakeDamageHook(client, attacker, inflictor, Float:damage, &Float:multiplier, damagetype) -{ - if (attacker == 0 || attacker >= MaxClients) - { - return Plugin_Continue; - } - if (g_aPlayers[client][IsImmune]) - { - new TFClassType:PlayerClass = TF2_GetPlayerClass(attacker); - if (PlayerClass == TFClass_Spy) - { - multiplier *= 0.0; - return Plugin_Changed; - } - } - return Plugin_Continue; -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - g_bRoundEnd = false; - if (g_bIsEnabled) - { - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][IsImmune]) - { - DisableImmunity(i); - } - } - } -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - g_bRoundEnd = true; - if (g_bIsEnabled) - { - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][bIsAdmin]) - { - EnableImmunity(i); - } - } - } -} - -public HookPlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) -{ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - if (g_bIsEnabled && g_aPlayers[iClient][bIsAdmin] && g_bRoundEnd) - { - EnableImmunity(iClient); - } -} - -public Action:HookPlayerHurt(Handle:event, const String:name[], bool:dontBroadcast) -{ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - if (g_aPlayers[iClient][IsImmune]) - { - SetEntityHealth(iClient, 2000); - return Plugin_Continue; - } - return Plugin_Continue; -} - -/** - Cookie menus - */ - -public CookieMenu_TopMenu(client, CookieMenuAction:action, any:info, String:buffer[], maxlen) -{ - if (action == CookieMenuAction_DisplayOption) - { - //don't think we need to do anything - } - else - { - new Handle:hMenu = CreateMenu(Menu_CookieSettings); - SetMenuTitle(hMenu, "Options (Current Setting)"); - if (g_aClientCookies[client][bEnabled]) - { - AddMenuItem(hMenu, "enable", "Enabled/Disable (Enabled)"); - } - else - { - AddMenuItem(hMenu, "enable", "Enabled/Disable (Disabled)"); - } - if (g_aClientCookies[client][iMode]) - { - AddMenuItem(hMenu, "mode", "Immunity Mode Setting (God Mode)"); - } - else - { - AddMenuItem(hMenu, "mode", "Immunity Mode Setting (Health)"); - } - switch (g_aClientCookies[client][iColor]) - { - case COLOR_GREEN: - { - AddMenuItem(hMenu, "color", "Color (Green)"); - } - case COLOR_BLACK: - { - AddMenuItem(hMenu, "color", "Color (Black)"); - } - case COLOR_RED: - { - AddMenuItem(hMenu, "color", "Color (Red)"); - } - case COLOR_BLUE: - { - AddMenuItem(hMenu, "color", "Color (Blue)"); - } - case COLOR_TEAM: - { - AddMenuItem(hMenu, "color", "Color (Team)"); - } - case COLOR_RAINBOW: - { - AddMenuItem(hMenu, "color", "Color (Rainbow)"); - } - case COLOR_NONE: - { - AddMenuItem(hMenu, "color", "Color (None)"); - } - } - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, client, MENU_TIME_FOREVER); - } -} - -public Menu_CookieSettings(Handle:menu, MenuAction:action, param1, param2) -{ - new client = param1; - if (action == MenuAction_Select) - { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "enable", false)) - { - new Handle:hMenu = CreateMenu(Menu_CookieSettingsEnable); - SetMenuTitle(hMenu, "Enable/Disable Round End Immunity"); - - if (g_aClientCookies[client][bEnabled]) - { - AddMenuItem(hMenu, "enable", "Enable (Set)"); - AddMenuItem(hMenu, "disable", "Disable"); - } - else - { - AddMenuItem(hMenu, "enable", "Enabled"); - AddMenuItem(hMenu, "disable", "Disable (Set)"); - } - - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, client, MENU_TIME_FOREVER); - } - else if (StrEqual(sSelection, "mode", false)) - { - new Handle:hMenu = CreateMenu(Menu_CookieSettingsMode); - SetMenuTitle(hMenu, "Set Immunity Mode"); - - if (g_aClientCookies[client][iMode]) - { - AddMenuItem(hMenu, "god", "God Mode (Set)"); - AddMenuItem(hMenu, "health", "Health"); - } - else - { - AddMenuItem(hMenu, "god", "God Mode"); - AddMenuItem(hMenu, "health", "Health (Set)"); - } - - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, client, MENU_TIME_FOREVER); - } - else - { - new Handle:hMenu = CreateMenu(Menu_CookieSettingsColors); - SetMenuTitle(hMenu, "Select Immunity Color"); - switch (g_aClientCookies[client][iColor]) - { - case COLOR_GREEN: - { - AddMenuItem(hMenu, "Green", "Green (Set)"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_BLACK: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black (Set)"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_RED: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red (Set)"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_BLUE: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue (Set)"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_TEAM: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color (Set)"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_RAINBOW: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow (Set)"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_NONE: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None (Set)"); - } - } - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, client, MENU_TIME_FOREVER); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - ShowCookieMenu(client); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -public Menu_CookieSettingsEnable(Handle:menu, MenuAction:action, param1, param2) -{ - new client = param1; - if (action == MenuAction_Select) - { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "enable", false)) - { - SetClientCookie(client, sri_cookie_enabled, "1"); - g_aClientCookies[client][bEnabled] = 1; - PrintToChat(client, "[SM] Bonus Round Immunity is ENABLED"); - } - else - { - SetClientCookie(client, sri_cookie_enabled, "0"); - g_aClientCookies[client][bEnabled] = 0; - PrintToChat(client, "[SM] Bonus Round Immunity is DISABLED"); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - ShowCookieMenu(client); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -public Menu_CookieSettingsColors(Handle:menu, MenuAction:action, param1, param2) -{ - new client = param1; - if (action == MenuAction_Select) - { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "Green", false)) - { - SetClientCookie(client, sri_cookie_color, "0"); - g_aClientCookies[client][iColor] = COLOR_GREEN; - PrintToChat(client, "[SM] Bonus Round Immunity color set to GREEN"); - } - else if (StrEqual(sSelection, "Black", false)) - { - SetClientCookie(client, sri_cookie_color, "1"); - g_aClientCookies[client][iColor] = COLOR_BLACK; - PrintToChat(client, "[SM] Bonus Round Immunity color set to BLACK"); - } - else if (StrEqual(sSelection, "Red", false)) - { - SetClientCookie(client, sri_cookie_color, "2"); - g_aClientCookies[client][iColor] = COLOR_RED; - PrintToChat(client, "[SM] Bonus Round Immunity color set to RED"); - } - else if (StrEqual(sSelection, "Blue", false)) - { - SetClientCookie(client, sri_cookie_color, "3"); - g_aClientCookies[client][iColor] = COLOR_BLUE; - PrintToChat(client, "[SM] Bonus Round Immunity color set to BLUE"); - } - else if (StrEqual(sSelection, "Team", false)) - { - SetClientCookie(client, sri_cookie_color, "4"); - g_aClientCookies[client][iColor] = COLOR_TEAM; - PrintToChat(client, "[SM] Bonus Round Immunity color set to TEAM COLOR"); - } - else if (StrEqual(sSelection, "Rain", false)) - { - SetClientCookie(client, sri_cookie_color, "5"); - g_aClientCookies[client][iColor] = COLOR_RAINBOW; - PrintToChat(client, "[SM] Bonus Round Immunity color set to RAINBOW"); - } - else if (StrEqual(sSelection, "None", false)) - { - SetClientCookie(client, sri_cookie_color, "6"); - g_aClientCookies[client][iColor] = COLOR_NONE; - PrintToChat(client, "[SM] Bonus Round Immunity color set to NONE"); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - ShowCookieMenu(client); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -public Menu_CookieSettingsMode(Handle:menu, MenuAction:action, param1, param2) -{ - new client = param1; - if (action == MenuAction_Select) - { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "god", false)) - { - SetClientCookie(client, sri_cookie_mode, "1"); - g_aClientCookies[client][iMode] = 1; - PrintToChat(client, "[SM] Bonus Round Immunity set to GOD MODE"); - } - else - { - SetClientCookie(client, sri_cookie_mode, "0"); - g_aClientCookies[client][iMode] = 0; - PrintToChat(client, "[SM] Bonus Round Immunity set to HEALTH BONUS"); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - ShowCookieMenu(client); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -/** -Timer functions - */ - -public Action:Timer_ChangeColor(Handle:timer, any:client) -{ - if (g_aPlayers[client][CycleColor]++ == 3) - { - g_aPlayers[client][CycleColor] = 0; - } - SetEntityRenderMode(client, RENDER_TRANSCOLOR); - SetEntityRenderColor(client, g_iColors[g_aPlayers[client][CycleColor]][iRed], g_iColors[g_aPlayers[client][CycleColor]][iGreen], g_iColors[g_aPlayers[client][CycleColor]][iBlue], 255); - return Plugin_Continue; -} - -public Action:Timer_UndoGodMode(Handle:timer, any:client) -{ - if (IsClientInGame(client)) - { - SetEntProp(client, Prop_Data, "m_takedamage", 2, 1); - } - g_aPlayers[iClient][hGodModeTimer] = INVALID_HANDLE; - return Plugin_Handled; -} - -/** -Stock functions . - */ - -stock CleanUp(iClient) -{ - g_aPlayers[iClient][bIsAdmin] = false; - DisableImmunity(iClient); -} - -stock EnableImmunity(iClient) -{ - SetEntityRenderMode(iClient, RENDER_TRANSCOLOR); - switch (g_aClientCookies[iClient][iColor]) - { - case COLOR_TEAM: - { - new iTeam = GetClientTeam(iClient); - SetEntityRenderColor(iClient, g_iColors[e_ColorNames:iTeam][iRed], g_iColors[e_ColorNames:iTeam][iGreen], g_iColors[e_ColorNames:iTeam][iBlue], 255); - } - case COLOR_RAINBOW: - { - if (g_aPlayers[iClient][hColorTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hColorTimer]); - g_aPlayers[iClient][hColorTimer] = INVALID_HANDLE; - } - g_aPlayers[iClient][hColorTimer] = CreateTimer(0.2, Timer_ChangeColor, iClient, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); - } - case COLOR_NONE: - { - //We dont have to set a color - } - default: - { - SetEntityRenderColor(iClient, g_iColors[e_ColorNames:g_aClientCookies[iClient][iColor]][iRed], g_iColors[e_ColorNames:g_aClientCookies[iClient][iColor]][iGreen], g_iColors[e_ColorNames:g_aClientCookies[iClient][iColor]][iBlue], 255); - } - } - SetEntityHealth(iClient, 2000); - SetEntProp(iClient, Prop_Data, "m_takedamage", 0, 1); - g_aPlayers[iClient][hGodModeTimer] = CreateTimer(2.0, Timer_UndoGodMode, iClient); - g_aPlayers[iClient][IsImmune] = true; -} - -stock DisableImmunity(iClient) -{ - if (g_aPlayers[iClient][hGodModeTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hGodModeTimer]); - g_aPlayers[iClient][hGodModeTimer] = INVALID_HANDLE; - } - if (g_aPlayers[iClient][hColorTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hColorTimer]); - g_aPlayers[iClient][hColorTimer] = INVALID_HANDLE; - } - if (IsClientInGame(iClient)) - { - SetEntityRenderMode(iClient, RENDER_TRANSCOLOR); - SetEntityRenderColor(iClient, 255, 255, 255, 255); - new TFClassType:PlayerClass = TF2_GetPlayerClass(iClient); - new iMaxHealth = g_iClassMaxHealth[PlayerClass]; - SetEntityHealth(iClient, iMaxHealth); - } - g_aPlayers[iClient][CycleColor] = 0; - g_aPlayers[iClient][IsImmune] = false; -} - -stock LoadColors() -{ - g_iColors[Green][iRed] = 0; - g_iColors[Green][iGreen] = 255; - g_iColors[Green][iBlue] = 0; - - g_iColors[Black][iRed] = 10; - g_iColors[Black][iGreen] = 10; - g_iColors[Black][iBlue] = 0; - - g_iColors[Red][iRed] = 255; - g_iColors[Red][iGreen] = 0; - g_iColors[Red][iBlue] = 0; - - g_iColors[Blue][iRed] = 0; - g_iColors[Blue][iGreen] = 0; - g_iColors[Blue][iBlue] = 255; -} - -stock TF2_AddCond(client, cond) -{ - new Handle:cvar = FindConVar("sv_cheats"), bool:enabled = GetConVarBool(cvar), flags = GetConVarFlags(cvar); - if(!enabled) - { - SetConVarFlags(cvar, flags^FCVAR_NOTIFY); - SetConVarBool(cvar, true); - } - FakeClientCommand(client, "addcond %i", cond); - if(!enabled) - { - SetConVarBool(cvar, false); - SetConVarFlags(cvar, flags); - } -} - -stock TF2_RemoveCond(client, cond) -{ - new Handle:cvar = FindConVar("sv_cheats"), bool:enabled = GetConVarBool(cvar), flags = GetConVarFlags(cvar); - if(!enabled) - { - SetConVarFlags(cvar, flags^FCVAR_NOTIFY); - SetConVarBool(cvar, true); - } - FakeClientCommand(client, "removecond %i", cond); - if(!enabled) - { - SetConVarBool(cvar, false); - SetConVarFlags(cvar, flags); - } -} - -/** -Enabled hook - */ - -public EnabledChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (StringToInt(newValue) == 0) - { - UnhookEvent("player_spawn", HookPlayerSpawn, EventHookMode_Post); - UnhookEvent("teamplay_round_start", HookRoundStart, EventHookMode_Post); - UnhookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][bIsAdmin] && g_aPlayers[i][IsImmune]) - { - DisableImmunity(i); - } - } - g_bIsEnabled = false; - } - else - { - HookEvent("player_spawn", HookPlayerSpawn, EventHookMode_Post); - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_Post); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - g_bIsEnabled = true; - } -} diff --git a/Simple Message Suppression/addons/sourcemod/scripting/simple-spectate.sp b/Simple Message Suppression/addons/sourcemod/scripting/simple-spectate.sp deleted file mode 100644 index 4108f8f..0000000 --- a/Simple Message Suppression/addons/sourcemod/scripting/simple-spectate.sp +++ /dev/null @@ -1,2022 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Spectate -Description: - Spectate a player and follow them through death. -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include -#undef REQUIRE_EXTENSIONS -#undef AUTOLOAD_EXTENSIONS -#tryinclude -#define AUTOLOAD_EXTENSIONS -#define REQUIRE_EXTENSIONS - -#define PLUGIN_VERSION "1.2.1.$Rev$" - -#define SPECMODE_NONE 0 -#define SPECMODE_FIRSTPERSON 4 -#define SPECMODE_3RDPERSON 5 -#define SPECMODE_FREELOOK 6 -#define SPECMODE_CSS_FIRSTPERSON 3 -#define SPECMODE_CSS_3RDPERSON 4 -#define SPECMODE_CSS_FREELOOK 5 - -enum e_CvarHandles -{ - Handle:hHudMode, - Handle:hMenuType, - Handle:hRestrictHud, - Handle:hBan, - Handle:hBanPerm, - Handle:hBeacon, - Handle:hBlind, - Handle:hCheater, - Handle:hDrug, - Handle:hFreeze, - Handle:hFreezeBomb, - Handle:hKick, - Handle:hSlap, - Handle:hSlay, - Handle:hTimeBomb -}; - -enum e_CvarSettings -{ - bool:bHudMode, - bool:bMenuType, - bool:bRestrictHud, - bool:bBan, - bool:bBanPerm, - bool:bBeacon, - bool:bBlind, - bool:bCheater, - bool:bDrug, - bool:bFreeze, - bool:bFreezebomb, - bool:bKick, - bool:bSlap, - bool:bSlay, - bool:bTimeBomb -}; - -enum e_PluginSettings -{ - bool:bUseSteamBans, - bool:bUseSourceBans, - bool:bUseMySQLBans, - bool:bCanHUD, - bool:bUseDukehacks -}; - -enum e_Menus -{ - Handle:hSelectPlayer, - Handle:hBanTime, - Handle:hReason -}; - -enum e_Punishments -{ - Punish_None, - Punish_Ban, - Punish_Beacon, - Punish_Blind, - Punish_Cheater, - Punish_Drug, - Punish_Freeze, - Punish_FreezeBomb, - Punish_Kick, - Punish_Slap, - Punish_Slay, - Punish_TimeBomb -}; - -enum e_PlayerData -{ - bool:bIsDisplayingHud, - bool:bIsFlaggedCheater, - Handle:hHudTimer, - Handle:hTargetTimer, - iTargetIndex, - e_Punishments:TargetPunishment, - iBanTime -}; - -new Handle:sm_spectate_adminflag = INVALID_HANDLE; -new Handle:g_hAdminMenu = INVALID_HANDLE; -new Handle:g_hHud = INVALID_HANDLE; -new Handle:g_aPluginCvar[e_CvarHandles]; -new g_aPluginCvarSettings[e_CvarSettings]; -new g_aPluginSettings[e_PluginSettings]; -new g_aMenus[e_Menus]; -new g_aPlayers[MAXPLAYERS + 1][e_PlayerData]; -new String:g_sAdminFlags[16]; -new String:g_sPunishments[e_Punishments][15] = { "None", "Ban", "Beacon", "Blind", "Cheater", "Drug", "Freeze", "FreezeBomb", "Kick", "Slap", "Slay", "TimeBomb" }; - -public Plugin:myinfo = -{ - name = "Simple Spectate", - author = "Simple Plugins", - description = "Spectate a player and follow them through death.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -/** -Sourcemod callbacks -*/ -public OnPluginStart() -{ - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[SSPEC] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Pre); - - /** - Need to create all of our console variables. - */ - CreateConVar("sm_spectate_version", PLUGIN_VERSION, "Sourcemod Spectate", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - g_aPluginCvar[hHudMode] = CreateConVar("sm_spectate_hudmode", "1", "Hud Mode: 0 = Hud Text | 1 = Panel/Menu (NOTE: The panel/menu will override other menus until canceled)"); - g_aPluginCvar[hMenuType] = CreateConVar("sm_spectate_menutype", "0", "Menu Mode: 0 = Panel | 1 = Menu"); - g_aPluginCvar[hRestrictHud] = CreateConVar("sm_spectate_restricthud", "0", "Restrict the hud to the admin flag provided"); - g_aPluginCvar[hBan] = CreateConVar("sm_spectate_ban", "1", "Enable/Disable ban option"); - g_aPluginCvar[hBanPerm] = CreateConVar("sm_spectate_banperm", "1", "Enable/Disable permanent ban option"); - g_aPluginCvar[hBeacon] = CreateConVar("sm_spectate_beacon", "1", "Enable/Disable beacon option"); - g_aPluginCvar[hBlind] = CreateConVar("sm_spectate_blind", "1", "Enable/Disable blind option"); - g_aPluginCvar[hCheater] = CreateConVar("sm_spectate_cheater", "1", "Enable/Disable cheater option"); - g_aPluginCvar[hDrug] = CreateConVar("sm_spectate_drug", "1", "Enable/Disable drug option"); - g_aPluginCvar[hFreeze] = CreateConVar("sm_spectate_freeze", "1", "Enable/Disable freeze option"); - g_aPluginCvar[hFreezeBomb] = CreateConVar("sm_spectate_freezebomb", "1", "Enable/Disable freezebomb option"); - g_aPluginCvar[hKick] = CreateConVar("sm_spectate_kick", "1", "Enable/Disable kick option"); - g_aPluginCvar[hSlap] = CreateConVar("sm_spectate_slap", "1", "Enable/Disable slap option"); - g_aPluginCvar[hSlay] = CreateConVar("sm_spectate_slay", "1", "Enable/Disable slay option"); - g_aPluginCvar[hTimeBomb] = CreateConVar("sm_spectate_timebomb", "1", "Enable/Disable timebomb option"); - - sm_spectate_adminflag = CreateConVar("sm_spectate_adminflag", "d", "Admin Flag to use for admin hud"); - - /** - Hook console variables - */ - new e_CvarHandles:iCvar; - for ( ; _:iCvar < sizeof(g_aPluginCvar); iCvar++) - { - HookConVarChange(g_aPluginCvar[iCvar], ConVarSettingsChanged); - } - - /** - Need to register the commands we are going to create and use. - */ - RegConsoleCmd("sm_spectate", Command_Spectate, "Spectate a player"); - RegConsoleCmd("sm_spec", Command_Spectate, "Spectate a player"); - RegConsoleCmd("sm_observe", Command_Spectate, "Spectate a player"); - RegConsoleCmd("sm_stopspec", Command_StopSpectate, "Stop Spectating a player"); - RegConsoleCmd("sm_endobserve", Command_StopSpectate, "Stop Spectating a player"); - RegConsoleCmd("sm_specinfo", Command_ToggleHud, "Toggles the hud display if in spectator"); - - /** - Now we have to deal with the admin menu. If the admin library is loaded call the function to add our items. - */ - new Handle:gTopMenu; - if (LibraryExists("adminmenu") && ((gTopMenu = GetAdminTopMenu()) != INVALID_HANDLE)) - { - OnAdminMenuReady(gTopMenu); - } - - /** - Deal with the hud - Thanks to Spray Trace plugin (http://forums.alliedmods.net/showthread.php?p=665448) - */ - new String:sHudGames[32]; - GetGameFolderName(sHudGames, sizeof(sHudGames)); - g_aPluginSettings[bCanHUD] = StrEqual(sHudGames,"tf",false) - || StrEqual(sHudGames,"hl2mp",false) - || StrEqual(sHudGames,"sourceforts",false) - || StrEqual(sHudGames,"obsidian",false) - || StrEqual(sHudGames,"left4dead",false) - || StrEqual(sHudGames,"l4d",false); - - if (g_aPluginSettings[bCanHUD]) - { - g_hHud = CreateHudSynchronizer(); - } - - /** - Load translations - */ - LoadTranslations ("common.phrases"); - LoadTranslations ("simplespectate.phrases"); - - /** - Create the config file - */ - AutoExecConfig(true); -} - -public OnConfigsExecuted() -{ - new e_CvarHandles:iCvar; - for ( ; _:iCvar < sizeof(g_aPluginCvarSettings); iCvar++) - { - g_aPluginCvarSettings[iCvar] = GetConVarBool(g_aPluginCvar[iCvar]); - } - - /* - Build the global menus - */ - g_aMenus[hSelectPlayer] = BuildSelectPlayerMenu(); - g_aMenus[hBanTime] = BuildBanTimeMenu(); - g_aMenus[hReason] = BuildReasonMenu(); - - GetConVarString(sm_spectate_adminflag, g_sAdminFlags, sizeof(g_sAdminFlags)); -} - -public OnAllPluginsLoaded() -{ - - /* - Check for steambans - */ - if (FindConVar("sbsrc_version") != INVALID_HANDLE) - { - g_aPluginSettings[bUseSteamBans] = true; - } - else - { - g_aPluginSettings[bUseSteamBans] = false; - } - - /* - Check for sourcebans - */ - if (FindConVar("sb_version") != INVALID_HANDLE) - { - g_aPluginSettings[bUseSourceBans] = true; - } - else - { - g_aPluginSettings[bUseSourceBans] = false; - } - - /* - Check for mysql bans - */ - if (FindConVar("mysql_bans_version") != INVALID_HANDLE) - { - g_aPluginSettings[bUseMySQLBans] = true; - } - else - { - g_aPluginSettings[bUseMySQLBans] = false; - } - - /* - Check for dukehacks - */ - new String:sExtError[256]; - new iExtStatus = GetExtensionFileStatus("dukehacks.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SSPEC] Dukehacks extension was not found."); - LogAction(0, -1, "[SSPEC] Plugin continued to load, but that feature will not be used."); - g_aPluginSettings[bUseDukehacks] = false; - } - else if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SSPEC] Dukehacks extension is loaded with errors."); - LogAction(0, -1, "[SSPEC] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SSPEC] Plugin continued to load, but that feature will not be used."); - g_aPluginSettings[bUseDukehacks] = false; - } - else if (iExtStatus == 1) - { - LogAction(0, -1, "[SSPEC] Dukehacks extension is loaded and will be used."); - g_aPluginSettings[bUseDukehacks] = true; - dhAddClientHook(CHK_TakeDamage, Hacks_TakeDamageHook); - } - - /* - Deal with some known plugin conflicts - */ - new Handle:hObserveClient = FindConVar("observe_version"); - if (hObserveClient != INVALID_HANDLE) - { - new String:sNewFile[PLATFORM_MAX_PATH + 1], String:sOldFile[PLATFORM_MAX_PATH + 1]; - BuildPath(Path_SM, sNewFile, sizeof(sNewFile), "plugins/disabled/observe.smx"); - BuildPath(Path_SM, sOldFile, sizeof(sOldFile), "plugins/observe.smx"); - - /** - Check if plugins/observe.smx exists, and if not, ignore - */ - if(!FileExists(sOldFile)) - { - return; - } - - /** - Check if plugins/disabled/observe.smx already exists, and if so, delete it - */ - if(FileExists(sNewFile)) - { - DeleteFile(sNewFile); - } - - /** - Unload plugins/observe.smx and move it to plugins/disabled/observe.smx - */ - LogAction(0, -1, "Detected the plugin ObserveClient"); - LogAction(0, -1, "ObserveClient plugin conflicts with Simple Spectate"); - LogAction(0, -1, "Unloading plugin and disabling ObserveClient plugin"); - ServerCommand("sm plugins unload observe"); - RenameFile(sNewFile, sOldFile); - } -} - -public OnLibraryRemoved(const String:name[]) -{ - if (StrEqual(name, "adminmenu")) - { - - /** - Looks like the admin menu was removed. Set the global. - */ - g_hAdminMenu = INVALID_HANDLE; - } - else if (StrEqual(name, "simpleplugins")) - { - //something - } -} - -public OnClientDisconnect(client) -{ - - /** - Cleanup the clients variables. - */ - ResetClient(client); - - /** - Run a loop and see if we are supposed to spectate this person (is a target) - */ - for(new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][iTargetIndex] == client) - { - - /** - Cleanup the clients variables. - */ - StopFollowingPlayer(i); - g_aPlayers[i][TargetPunishment] = Punish_None; - g_aPlayers[i][iBanTime] = 0; - } - } -} - -/** -Thirdparty callbacks -*/ -public SM_OnPlayerMoved(Handle:plugin, client, team) -{ - - /** - Make sure we called the move function - */ - if (plugin != GetMyHandle()) - { - return; - } - - //Nothing -} - -public Action:Hacks_TakeDamageHook(client, attacker, inflictor, Float:damage, &Float:multiplier, damagetype) -{ - - /** - Check for a valid client - */ - if (client > 0 && client <= MaxClients) - { - - /** - Check if the client taking damage is flagged as a cheater - */ - if (g_aPlayers[client][bIsFlaggedCheater]) - { - - /** - Check for fall damage and increase it - */ - if (damagetype & DMG_FALL) - { - multiplier *= 1000.0; - return Plugin_Changed; - } - } - } - - /** - Check for a valid attacker - */ - if (attacker > 0 && attacker <= MaxClients) - { - - /** - Check if the attacker causing the damage is flagged as a cheater - */ - if (g_aPlayers[attacker][bIsFlaggedCheater]) - { - - /** - Make sure they are not hurting themselves - */ - if (client != attacker) - { - - /** - Stop the damage - */ - multiplier *= 0.0; - return Plugin_Changed; - } - } - } - return Plugin_Continue; -} - -/** -Events -*/ -public Action:HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get the client and team - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - new iTeam = GetEventInt(event, "team"); - - /** - Make sure it's a valid client - */ - if (iClient == 0) - { - return Plugin_Continue; - } - - /** - If it's a move to spectator start displaying the hud - */ - else if ((iTeam == g_aCurrentTeams[Spectator]) && (GetUserFlagBits(iClient) & ADMFLAG_GENERIC)) - { - StartDisplayingHud(iClient); - - /** - If the event was going to be broadcasted, we refire it so it is not broadcasted and stop this one - */ - if (!dontBroadcast) - { - new Handle:hEvent = CreateEvent("player_team"); - SetEventInt(hEvent, "userid", GetEventInt(event, "userid")); - SetEventInt(hEvent, "team", GetEventInt(event, "team")); - SetEventInt(hEvent, "oldteam", GetEventInt(event, "oldteam")); - SetEventBool(hEvent, "disconnect", GetEventBool(event, "disconnect")); - - if (g_CurrentMod == GameType_DOD || g_CurrentMod == GameType_L4D || g_CurrentMod == GameType_TF) - { - new String:sClientName[MAX_NAME_LENGTH + 1]; - GetClientName(client, sClientName, sizeof(sClientName)); - SetEventBool(hEvent, "autoteam", GetEventBool(event, "autoteam")); - SetEventBool(hEvent, "silent", true); - SetEventString(hEvent, "name", sClientName); - FireEvent(hEvent, true); - } - else - { - FireEvent(hEvent, true); - } - return Plugin_Handled; - } - } - - /** - Otherwise cleanup the client - */ - else - { - StopDisplayingHud(iClient); - StopFollowingPlayer(iClient); - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -/** -Commands -*/ -public Action:Command_Spectate(client, args) -{ - - /** - See if we already have a target (for toggling of command) - */ - if (g_aPlayers[client][iTargetIndex]) - { - - /** - We do, toggle it off - */ - StopFollowingPlayer(client); - - /** - We are done, bug out. - */ - return Plugin_Handled; - } - - /** - We don't... must want to enable it - See if we have some command arguments. - */ - new iCmdArgs = GetCmdArgs(); - if (iCmdArgs == 0) - { - - /** - We don't have any. Display the player menu. - */ - if (g_aPlayers[client][bIsDisplayingHud]) - { - StopDisplayingHud(client); - } - - DisplayMenu(BuildPlayerListMenu(), client, MENU_TIME_FOREVER); - return Plugin_Handled; - } - - /** - We have an argument. - Try to find the target. - */ - new String:sPlayer[128]; - GetCmdArg(1, sPlayer, sizeof(sPlayer)); - new iTarget = FindTarget(client, sPlayer, true, true); - if (iTarget == -1 || !IsClientInGame(iTarget)) - { - - /** - We couldn't find the target. Display the player menu. - */ - if (g_aPlayers[client][bIsDisplayingHud]) - { - StopDisplayingHud(client); - } - - DisplayMenu(BuildPlayerListMenu(), client, MENU_TIME_FOREVER); - return Plugin_Handled; - } - - /** - We found the target. - Call the stock function to spectate the target. - */ - StartFollowingPlayer(client, iTarget); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_StopSpectate(client, args) -{ - - /** - Cleanup the clients variables. - */ - StopFollowingPlayer(client); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_ToggleHud(client, args) -{ - - /** - Toggle the hud - */ - if (g_aPlayers[client][bIsDisplayingHud]) - { - StopDisplayingHud(client); - } - else - { - StartDisplayingHud(client); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -/** -Timers -*/ -public Action:Timer_ResetTarget(Handle:timer, any:client) -{ - - new iTargetID = GetEntPropEnt(client, Prop_Send, "m_hObserverTarget"); - - if (iTargetID != g_aPlayers[client][iTargetIndex] && IsPlayerAlive(g_aPlayers[client][iTargetIndex])) - { - - /** - Run the command to spectate the target from the clients prospectative. - */ - FakeClientCommandEx(client, "spec_player \"%N\"", g_aPlayers[client][iTargetIndex]); - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Timer_UpdateHud(Handle:timer, any:client) -{ - - /** - Make sure the client is still in game and a spectator - */ - if (!IsClientConnected(client) || !IsClientInGame(client) || GetClientTeam(client) != g_aCurrentTeams[Spectator] || !g_aPlayers[client][bIsDisplayingHud]) - { - - /** - We are done, bug out - */ - g_aPlayers[client][hHudTimer] = INVALID_HANDLE; - g_aPlayers[client][bIsDisplayingHud] = false; - return Plugin_Stop; - } - /** - Get the target - */ - new iTarget = GetEntPropEnt(client, Prop_Send, "m_hObserverTarget"); - - /** - Check to make sure the target is valid - */ - if (iTarget <= 0 || iTarget > MaxClients) - { - return Plugin_Continue; - } - - /** - Get the spectator mode - */ - new iSpecMode = GetEntProp(client, Prop_Send, "m_iObserverMode"); - - /** - This is a double check to make sure we are in spec - If we are on a regular team, specmod would = none or zero - */ - if (iSpecMode == SPECMODE_NONE) - { - - /** - We are done, bug out - */ - g_aPlayers[client][hHudTimer] = INVALID_HANDLE; - g_aPlayers[client][bIsDisplayingHud] = false; - return Plugin_Stop; - } - - /** - Check the spectator mode - CSS has different index's so we have to check game type first - */ - if (g_CurrentMod == GameType_CSS) - { - switch (iSpecMode) - { - case SPECMODE_CSS_FIRSTPERSON: - { - //Do Nothing - } - case SPECMODE_CSS_3RDPERSON: - { - //Do Nothing - } - case SPECMODE_CSS_FREELOOK: - { - return Plugin_Continue; - } - } - } - else - { - switch (iSpecMode) - { - case SPECMODE_FIRSTPERSON: - { - //Do Nothing - } - case SPECMODE_3RDPERSON: - { - //Do Nothing - } - case SPECMODE_FREELOOK: - { - return Plugin_Continue; - } - } - } - - - /** - Display with the hud - */ - if (g_aPluginSettings[bCanHUD] && !g_aPluginCvarSettings[bHudMode]) - { - new String:sSteamID[64]; - GetClientAuthString(iTarget, sSteamID, sizeof(sSteamID)); - SetHudTextParams(0.04, 0.6, 0.5, 255, 50, 50, 255); - ShowSyncHudText(client, g_hHud, "%N [%s]", iTarget, sSteamID); - } - else if (g_aPluginCvarSettings[bHudMode]) - { - if (g_aPluginCvarSettings[bMenuType]) - { - DisplayMenu(BuildPlayerHudMenu(client, iTarget), client, 1); - } - else - { - new Handle:hPanel = BuildPlayerHudPanel(client, iTarget); - SendPanelToClient(hPanel, client, Panel_PlayerHud, 1); - CloseHandle(hPanel); - } - } - - /** - We are done, keep going! - */ - return Plugin_Continue; -} - -/** -Admin Menu Callbacks -*/ -public OnAdminMenuReady(Handle:topmenu) -{ - if (topmenu == g_hAdminMenu) - { - return; - } - g_hAdminMenu = topmenu; - new TopMenuObject:player_commands = FindTopMenuCategory(g_hAdminMenu, ADMINMENU_PLAYERCOMMANDS); - if (player_commands == INVALID_TOPMENUOBJECT) - { - return; - } - AddToTopMenu(g_hAdminMenu, - "sm_spectate", - TopMenuObject_Item, - AdminMenu_SpecPlayer, - player_commands, - "sm_spectate", - ADMFLAG_GENERIC); -} - -public AdminMenu_SpecPlayer(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) -{ - if (action == TopMenuAction_DisplayOption) - { - - if (g_aPlayers[param][bIsDisplayingHud]) - { - StopDisplayingHud(param); - } - /** - See if we already have a target - */ - if (g_aPlayers[param][iTargetIndex]) - { - Format(buffer, maxlength, "Spectate(Disable)"); - } - else - { - Format(buffer, maxlength, "Spectate(Select Player)"); - } - } - else if (action == TopMenuAction_SelectOption) - { - - /** - See if we already have a target - */ - if (g_aPlayers[param][iTargetIndex]) - { - - /** - We do, toggle it off - */ - StopFollowingPlayer(param); - - /** - We are done, bug out. - */ - return; - } - else - { - DisplayMenu(BuildPlayerListMenu(), param, MENU_TIME_FOREVER); - } - } -} - -/** -Select Player Menu Callbacks -*/ -public Menu_PlayerList(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - /** - Get the selected player - */ - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - new iTarget = GetClientOfUserId(StringToInt(sSelection)); - - /** - Start following the player - */ - StartFollowingPlayer(param1, iTarget); - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_GENERIC) - { - - /** - Display the last admin menu - */ - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } - else if (param2 == MenuCancel_Exit && GetClientTeam(param1) == g_aCurrentTeams[Spectator]) - { - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_End) - { - - /** - Not a global menu, close it - */ - CloseHandle(menu); - } -} - -public Menu_SelectPlayer(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - - /** - Get the selected player - */ - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (strcmp(sSelection, "Current", false) == 0) - { - /** - Get the current target - */ - new iTarget = GetEntPropEnt(param1, Prop_Send, "m_hObserverTarget"); - - /** - Check to make sure the target is valid - */ - if (iTarget <= 0 || iTarget > MaxClients) - { - PrintToChat(param1, "\x03[SM-SPEC]\x01 %t", "Invalid Target"); - DisplayMenu(BuildPlayerListMenu(), param1, MENU_TIME_FOREVER); - } - - /** - Start following the player - */ - StartFollowingPlayer(param1, iTarget); - } - else - { - - /** - They want to select a player, show the player list - */ - DisplayMenu(BuildPlayerListMenu(), param1, MENU_TIME_FOREVER); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_End) - { - /** - Its a global menu, leave it alive - */ - } -} - -/** -Punishment Menu Callbacks -*/ -public Menu_Punishments(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - - /** - Get the menu selection - */ - new String:sSelection[15]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - - /** - Search for the correct index - */ - new e_Punishments:Index = Punish_None; - for ( ; _:Index <= sizeof(g_sPunishments); Index++) - { - if (StrEqual(sSelection, g_sPunishments[Index])) - { - break; - } - } - - /** - Display the next menu - */ - if (Index == Punish_Ban) - { - - /** - Set the punishment index and display ban time menu - */ - g_aPlayers[param1][TargetPunishment] = Index; - DisplayMenu(g_aMenus[hBanTime], param1, MENU_TIME_FOREVER); - } - else if (Index == Punish_Cheater) - { - - /** - Ask for confirmation before we set punishment index - */ - new Handle:hPanel = BuildAdminCheaterPanel(); - SendPanelToClient(hPanel, param1, Panel_AdminCheater, MENU_TIME_FOREVER); - CloseHandle(hPanel); - } - else - { - - /** - Set the punishment index and display reason menu - */ - g_aPlayers[param1][TargetPunishment] = Index; - DisplayMenu(g_aMenus[hReason], param1, MENU_TIME_FOREVER); - } - } - else if (action == MenuAction_Cancel) - { - - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - else if (action == MenuAction_End) - { - - /** - Not a global menu, close it - */ - CloseHandle(menu); - } -} - -public Menu_BanTime(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - - /** - Get the menu selection - */ - new String:sSelection[15]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - - /** - Set the ban time global - */ - g_aPlayers[param1][iBanTime] = StringToInt(sSelection); - - /** - Display the reason menu - */ - DisplayMenu(g_aMenus[hReason], param1, MENU_TIME_FOREVER); - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_End) - { - /** - Its a global menu, leave it alive - */ - } -} - -public Menu_Reason(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - - /** - Get the menu selection - */ - new String:sSelection[15]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - - /** - Perform the punishment - */ - PerformPunishment(param1, g_aPlayers[param1][iTargetIndex], g_aPlayers[param1][TargetPunishment], sSelection, g_aPlayers[param1][iBanTime]); - - /** - Reactivate the hud if still in spectator - */ - if (GetClientTeam(param1) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_End) - { - /** - Its a global menu, leave it alive - */ - } -} - -public Panel_AdminCheater(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - if (param2 == 1) - { - - /** - Set the punishment index and display reason menu - */ - g_aPlayers[param1][TargetPunishment] = Punish_Cheater; - DisplayMenu(g_aMenus[hReason], param1, MENU_TIME_FOREVER); - } - else - { - - /** - Reactivate the hud if still in spectator - */ - if (GetClientTeam(param1) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(param1); - } - } - } -} - -public Panel_PublicCheater(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - if (param2 == 1) - { - //Waiting for SB 2.0 and sb_submission to be published - } - else - { - - /** - Reactivate the hud if still in spectator - */ - if (GetClientTeam(param1) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(param1); - } - } - } -} - -/** -Hud Menu/Panel Callbacks -*/ -public Menu_PlayerHud(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "stop", false)) - { - StopFollowingPlayer(param1); - } - else if (StrEqual(sSelection, "start", false)) - { - StopDisplayingHud(param1); - DisplayMenu(g_aMenus[hSelectPlayer], param1, MENU_TIME_FOREVER); - } - else if (StrEqual(sSelection, "removecheater", false)) - { - g_aPlayers[g_aPlayers[param1][iTargetIndex]][bIsFlaggedCheater] = false; - } - else if (StrEqual(sSelection, "punish", false)) - { - if (g_aPlayers[param1][iTargetIndex]) - { - StopDisplayingHud(param1); - DisplayMenu(BuildPunishmentMenu(param1), param1, MENU_TIME_FOREVER); - } - else - { - StopDisplayingHud(param1); - PrintToChat(param1, "\x03[SM-SPEC]\x01 %t", "Must Have Target"); - DisplayMenu(g_aMenus[hSelectPlayer], param1, MENU_TIME_FOREVER); - } - } - else if (StrEqual(sSelection, "reportcheater", false)) - { - if (g_aPlayers[param1][iTargetIndex]) - { - StopDisplayingHud(param1); - new Handle:hPanel = BuildPublicCheaterPanel(); - SendPanelToClient(hPanel, param1, Panel_PublicCheater, MENU_TIME_FOREVER); - CloseHandle(hPanel); - } - else - { - StopDisplayingHud(param1); - PrintToChat(param1, "\x03[SM-SPEC]\x01 %t", "Must Have Target"); - DisplayMenu(g_aMenus[hSelectPlayer], param1, MENU_TIME_FOREVER); - } - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_Interrupted) - { - if (GetClientMenu(param1) == MenuSource_External) - { - StopDisplayingHud(param1); - } - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -public Panel_PlayerHud(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - switch (param2) - { - case 1: - { - if (g_aPlayers[param1][iTargetIndex]) - { - StopFollowingPlayer(param1); - } - else - { - StopDisplayingHud(param1); - DisplayMenu(BuildSelectPlayerMenu(), param1, MENU_TIME_FOREVER); - } - } - case 2: - { - if (!g_aPlayers[param1][iTargetIndex]) - { - StopDisplayingHud(param1); - PrintToChat(param1, "\x03[SM-SPEC]\x01 %t", "Must Have Target"); - DisplayMenu(g_aMenus[hSelectPlayer], param1, MENU_TIME_FOREVER); - return; - } - - if ((GetUserFlagBits(param1) & ADMFLAG_GENERIC) || (GetUserFlagBits(param1) & ADMFLAG_ROOT)) - { - if (g_aPlayers[g_aPlayers[param1][iTargetIndex]][bIsFlaggedCheater] && (GetUserFlagBits(param1) & ADMFLAG_ROOT)) - { - //Remove cheater flag - g_aPlayers[g_aPlayers[param1][iTargetIndex]][bIsFlaggedCheater] = false; - } - else - { - //Punish menu - StopDisplayingHud(param1); - DisplayMenu(BuildPunishmentMenu(param1), param1, MENU_TIME_FOREVER); - } - } - else - { - //Report Cheater - new Handle:hPanel = BuildPublicCheaterPanel(); - SendPanelToClient(hPanel, param1, Panel_PublicCheater, MENU_TIME_FOREVER); - CloseHandle(hPanel); - } - } - case 3: - { - StopDisplayingHud(param1); - } - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_Interrupted) - { - if (GetClientMenu(param1) == MenuSource_External) - { - StopDisplayingHud(param1); - } - } - } -} - - -/** -Stock functions -*/ -stock StartFollowingPlayer(client, target) -{ - - /** - If we have an open timer, close it. - */ - if (g_aPlayers[client][hTargetTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[client][hTargetTimer]); - g_aPlayers[client][hTargetTimer] = INVALID_HANDLE; - } - - /** - Make sure the target is on a non spectator team, and the client != target - */ - if (client == target) - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Yourself"); - return; - } - new iTargetTeam = GetClientTeam(target); - if (iTargetTeam == g_aCurrentTeams[Spectator] || iTargetTeam == g_aCurrentTeams[Unknown]) - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Spectator"); - return; - } - - /** - Check to see if client is already a spectator - */ - if (GetClientTeam(client) != g_aCurrentTeams[Spectator]) - { - - /** - Client is not a spectator, lets move them to spec. - */ - SM_MovePlayer(client, g_aCurrentTeams[Spectator]); - } - - /** - If we are using steambans call sb_status - */ - if (g_aPluginSettings[bUseSteamBans]) - { - FakeClientCommandEx(client, "sb_status"); - } - - - /** - Set the global and start to spectate the target. - Making sure it's long enough to deal with moving the client to spec if we had to. - */ - new String:sTargetName[MAX_NAME_LENGTH + 1]; - GetClientName(target, sTargetName, sizeof(sTargetName)); - g_aPlayers[client][iTargetIndex] = target; - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Spectating", sTargetName); - g_aPlayers[client][hTargetTimer] = CreateTimer(0.5, Timer_ResetTarget, client, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); - if (!g_aPlayers[client][bIsDisplayingHud] && GetClientTeam(client) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(client); - } -} - -stock StopFollowingPlayer(client) -{ - - /** - If we have an open timer, close it. - */ - if (g_aPlayers[client][hTargetTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[client][hTargetTimer]); - } - - /** - Tell the client we can't spec his target anymore... if they are in game. - */ - if (IsClientInGame(client) && g_aPlayers[client][iTargetIndex] != 0) - { - new String:sTargetName[MAX_NAME_LENGTH + 1]; - GetClientName(g_aPlayers[client][iTargetIndex], sTargetName, sizeof(sTargetName)); - if (!IsClientConnected(g_aPlayers[client][iTargetIndex]) || !IsClientInGame(g_aPlayers[client][iTargetIndex])) - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Target Left"); - } - else - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Stopped spectating", sTargetName); - } - } - - /** - Null the globals. - */ - g_aPlayers[client][iTargetIndex] = 0; - g_aPlayers[client][hTargetTimer] = INVALID_HANDLE; -} - -stock StartDisplayingHud(client) -{ - if (g_aPluginCvarSettings[bRestrictHud] && !SM_IsValidAdmin(client, g_sAdminFlags)) - { - return; - } - else - { - /** - Double check the hud timer - We should not have one, but if we do, lets cancel it for the current callback - */ - StopDisplayingHud(client); - - /** - Now we can safely display the hud and make sure the current stored handle is the current timer - */ - g_aPlayers[client][bIsDisplayingHud] = true; - g_aPlayers[client][hHudTimer] = CreateTimer(0.5, Timer_UpdateHud, client, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); - } -} - -stock StopDisplayingHud(client) -{ - if (g_aPlayers[client][hHudTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[client][hHudTimer]); - } - g_aPlayers[client][hHudTimer] = INVALID_HANDLE; - g_aPlayers[client][bIsDisplayingHud] = false; -} - -stock ResetClient(client) -{ - StopFollowingPlayer(client); - StopDisplayingHud(client); - - g_aPlayers[client][bIsFlaggedCheater] = false; - g_aPlayers[client][TargetPunishment] = Punish_None; - g_aPlayers[client][iBanTime] = -1; -} - -stock PerformPunishment(client, target, e_Punishments:punishment, const String:reason[], time = 300) -{ - new String:sTargetName[MAX_NAME_LENGTH + 1], - String:sTargetID[64]; - - /** - The target could have left the game by the time we get here - Check for a valid target - */ - if (!IsClientConnected(target) || !IsClientInGame(target)) - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Target Left"); - return; - } - - GetClientName(target, sTargetName, sizeof(sTargetName)); - GetClientAuthString(target, sTargetID, sizeof(sTargetID)); - - switch (punishment) - { - case Punish_Kick: - { - KickClient(g_aPlayers[client][iTargetIndex], "%s", reason); - } - case Punish_Ban: - { - if (g_aPluginSettings[bUseSourceBans]) - { - ClientCommand(client, "sm_ban #%d %d \"%s\"", GetClientUserId(target), time, reason); - } - else if (g_aPluginSettings[bUseMySQLBans]) - { - ClientCommand(client, "mysql_ban #%d %d \"%s\"", GetClientUserId(target), time, reason); - } - else - { - BanClient(target, time, BANFLAG_AUTHID, reason, reason); - } - } - case Punish_Cheater: - { - g_aPlayers[target][bIsFlaggedCheater] = true; - } - case Punish_Beacon: - { - ClientCommand(client, "sm_beacon \"%s\"", sTargetName); - } - case Punish_Blind: - { - ClientCommand(client, "sm_blind \"%s\"", sTargetName); - } - case Punish_Drug: - { - ClientCommand(client, "sm_drug \"%s\"", sTargetName); - } - case Punish_Freeze: - { - ClientCommand(client, "sm_freeze \"%s\"", sTargetName); - } - case Punish_FreezeBomb: - { - ClientCommand(client, "sm_freezebomb \"%s\"", sTargetName); - } - case Punish_Slap: - { - ClientCommand(client, "sm_slap \"%s\" 10", sTargetName); - } - case Punish_Slay: - { - ClientCommand(client, "sm_slay \"%s\"", sTargetName); - } - case Punish_TimeBomb: - { - ClientCommand(client, "sm_timebomb \"%s\"", sTargetName); - } - } - - if (punishment == Punish_Cheater) - { - LogAction(client, target, "[SM SPEC] %N marked %N(%s) with a %s flag for %s", client, target, sTargetID, g_sPunishments[punishment], reason); - } - else - { - ShowActivity(client, "%t", "Punished", sTargetName, g_sPunishments[punishment], reason); - LogAction(client, target, "[SM SPEC] %N punished %N(%s) with a %s for %s", client, target, sTargetID, g_sPunishments[punishment], reason); - } - - /** - Null the globals. - */ - g_aPlayers[client][TargetPunishment] = Punish_None; - g_aPlayers[client][iBanTime] = -1; -} - -/** -Build the menu of player names -*/ -stock Handle:BuildPlayerListMenu() -{ - new Handle:hMenu = CreateMenu(Menu_PlayerList); - AddTargetsToMenu(hMenu, 0, true, false); - SetMenuTitle(hMenu, "Select A Player:"); - SetMenuExitBackButton(hMenu, true); - return hMenu; -} - -/** -Build the select player menu (current or list of players) -*/ -stock Handle:BuildSelectPlayerMenu() -{ - new Handle:hMenu = CreateMenu(Menu_SelectPlayer); - SetMenuTitle(hMenu, "Select A Player:"); - AddMenuItem(hMenu, "Current", "Current Target"); - AddMenuItem(hMenu, "List", "Player List"); - SetMenuExitBackButton(hMenu, true); - return hMenu; -} - -/** -Build the punishmenu menu -*/ -stock Handle:BuildPunishmentMenu(iClient) -{ - new Handle:hMenu = CreateMenu(Menu_Punishments); - SetMenuTitle(hMenu, "Select A Punishment:"); - SetMenuExitBackButton(hMenu, true); - SetMenuExitButton(hMenu, true); - - if (g_aPluginCvarSettings[bKick] && ((GetUserFlagBits(iClient) & ADMFLAG_GENERIC) || (GetUserFlagBits(iClient) & ADMFLAG_ROOT))) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Kick], "Kick"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Kick], "Kick", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bBan] && ((GetUserFlagBits(iClient) & ADMFLAG_GENERIC) || (GetUserFlagBits(iClient) & ADMFLAG_ROOT))) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Ban], "Ban"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Ban], "Ban", ITEMDRAW_DISABLED); - } - - if (g_aPluginSettings[bUseDukehacks] && g_aPluginCvarSettings[bCheater] && (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Cheater], "Flag As Cheater"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Cheater], "Flag As Cheater", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bBeacon]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Beacon], "Beacon"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Beacon], "Beacon", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bBlind]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Blind], "Blind"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Blind], "Blind", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bDrug]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Drug], "Drug"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Drug], "Drug", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bFreeze]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Freeze], "Freeze"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Freeze], "Freeze", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bFreezebomb]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_FreezeBomb], "Freeze Bomb"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_FreezeBomb], "Freeze Bomb", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bSlap]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Slap], "Slap"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Slap], "Slap", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bSlay]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Slay], "Slay"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Slay], "Slay", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bTimeBomb]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_TimeBomb], "Time Bomb"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_TimeBomb], "Time Bomb", ITEMDRAW_DISABLED); - } - - return hMenu; -} - -/** -Build the punishmenu menu -*/ -stock Handle:BuildBanTimeMenu() -{ - new Handle:hMenu = CreateMenu(Menu_BanTime); - SetMenuTitle(hMenu, "Select Ban Type:"); - - if (g_aPluginCvarSettings[bBanPerm]) - { - AddMenuItem(hMenu, "permban", "Permanent"); - } - else - { - AddMenuItem(hMenu, "permban", "Permanent", ITEMDRAW_DISABLED); - } - - AddMenuItem(hMenu, "10", "10 Minutes"); - AddMenuItem(hMenu, "30", "30 Minutes"); - AddMenuItem(hMenu, "60", "1 Hour"); - AddMenuItem(hMenu, "240", "4 Hours"); - AddMenuItem(hMenu, "1440", "1 Day"); - AddMenuItem(hMenu, "10080", "1 Week"); - - SetMenuExitBackButton(hMenu, true); - return hMenu; -} - -/** -Build the punishmenu menu -*/ -stock Handle:BuildReasonMenu() -{ - new Handle:hMenu = CreateMenu(Menu_Reason); - SetMenuTitle(hMenu, "Select A Reason:"); - - AddMenuItem(hMenu, "Abusive", "Abusive"); - AddMenuItem(hMenu, "Racism", "Racism"); - AddMenuItem(hMenu, "General cheating/exploits", "General cheating/exploits"); - AddMenuItem(hMenu, "Wallhack", "Wallhack"); - AddMenuItem(hMenu, "Aimbot", "Aimbot"); - AddMenuItem(hMenu, "Speedhacking", "Speedhacking"); - AddMenuItem(hMenu, "Mic spamming", "Mic spamming"); - AddMenuItem(hMenu, "Admin disrepect", "Admin disrepect"); - AddMenuItem(hMenu, "Camping", "Camping"); - AddMenuItem(hMenu, "Team killing", "Team killing"); - AddMenuItem(hMenu, "Unacceptable Spray", "Unacceptable Spray"); - AddMenuItem(hMenu, "Breaking Server Rules", "Breaking Server Rules"); - AddMenuItem(hMenu, "Other", "Other"); - - SetMenuExitBackButton(hMenu, true); - return hMenu; -} - -/** -Build the cheater displays -*/ -stock Handle:BuildAdminCheaterPanel() -{ - - /** - Create the menu and set the menu options. - */ - new Handle:hPanel = CreatePanel(); - SetPanelTitle(hPanel, "Simple Spectator:"); - - DrawPanelText(hPanel, "Are you sure you want to"); - DrawPanelText(hPanel, "flag this player as a cheater?"); - DrawPanelText(hPanel, "They will not be able to damage"); - DrawPanelText(hPanel, "anyone and die on fall damage."); - DrawPanelItem(hPanel, "Yes"); - DrawPanelItem(hPanel, "No"); - - return hPanel; -} - -stock Handle:BuildPublicCheaterPanel() -{ - - /** - Create the menu and set the menu options. - */ - new Handle:hPanel = CreatePanel(); - SetPanelTitle(hPanel, "Simple Spectator:"); - - DrawPanelText(hPanel, "Are you sure you want to"); - DrawPanelText(hPanel, "submit this player as a cheater?"); - DrawPanelItem(hPanel, "Yes (Not Implemented Yet)", ITEMDRAW_DISABLED); - DrawPanelItem(hPanel, "No"); - return hPanel; -} - -/** -Build the hud displays -*/ -stock Handle:BuildPlayerHudMenu(iClient, iTarget) -{ - - /** - Create all the string variables we will need - */ - new String:sTargetName[MAX_NAME_LENGTH + 1], - String:sTargetID[64], - String:sTargetIP[16]; - - new String:sDisplayName[MAX_NAME_LENGTH + 1], - String:sDisplayID[64], - String:sDisplayIP[64], - String:sDisplayFrags[16], - String:sDisplayDeaths[16]; - - new iTargetFrags, - iTargetDeaths; - - /** - Get the targets information - */ - GetClientName(iTarget, sTargetName, sizeof(sTargetName)); - GetClientIP(iTarget, sTargetIP, sizeof(sTargetIP)); - GetClientAuthString(iTarget, sTargetID, sizeof(sTargetID)); - iTargetFrags = GetClientFrags(iTarget); - iTargetDeaths = GetClientDeaths(iTarget); - - /** - Format the strings for the menu - */ - Format(sDisplayName, sizeof(sDisplayName), "Player: %s", sTargetName); - Format(sDisplayID, sizeof(sDisplayID), "Steam ID: %s", sTargetID); - Format(sDisplayIP, sizeof(sDisplayIP), "IP Address: %s", sTargetIP); - Format(sDisplayFrags, sizeof(sDisplayFrags), "Kills: %i", iTargetFrags); - Format(sDisplayDeaths, sizeof(sDisplayDeaths), "Deaths: %i", iTargetDeaths); - - /** - Create the menu and set the menu options. - */ - new Handle:hMenu = CreateMenu(Menu_PlayerHud); - SetMenuExitBackButton(hMenu, false); - SetMenuTitle(hMenu, "Simple Spectator"); - - AddMenuItem(hMenu, "name", sDisplayName, ITEMDRAW_DISABLED); - AddMenuItem(hMenu, "steamid", sDisplayID, ITEMDRAW_DISABLED); - - if (SM_IsValidAdmin(iClient, g_sAdminFlags)) - { - AddMenuItem(hMenu, "ip", sDisplayIP, ITEMDRAW_DISABLED); - } - - AddMenuItem(hMenu, "kills", sDisplayFrags, ITEMDRAW_DISABLED); - AddMenuItem(hMenu, "deaths", sDisplayDeaths, ITEMDRAW_DISABLED); - - if (g_aPlayers[iClient][iTargetIndex]) - { - AddMenuItem(hMenu, "stop", "Stop Following"); - } - else - { - AddMenuItem(hMenu, "start", "Follow Player"); - } - - if ((GetUserFlagBits(iClient) & ADMFLAG_GENERIC) || (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - if (g_aPlayers[iTarget][bIsFlaggedCheater] && (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - AddMenuItem(hMenu, "removecheater", "Remove Cheater Flag"); - } - else - { - if (CanUserTarget(iClient, iTarget)) - { - AddMenuItem(hMenu, "punish", "Punish Player"); - } - else - { - AddMenuItem(hMenu, "punish", "Punish Player (Immune)", ITEMDRAW_DISABLED); - } - } - } - else - { - AddMenuItem(hMenu, "reportcheater", "Report Cheater"); - } - - SetMenuPagination(hMenu, MENU_NO_PAGINATION); - SetMenuExitButton(hMenu, true); - return hMenu; -} - -stock Handle:BuildPlayerHudPanel(iClient, iTarget) -{ - - /** - Create all the string variables we will need - */ - new String:sTargetName[MAX_NAME_LENGTH + 1], - String:sTargetID[64], - String:sTargetIP[16]; - - new String:sDisplayName[MAX_NAME_LENGTH + 1], - String:sDisplayID[64], - String:sDisplayIP[64], - String:sDisplayFrags[16], - String:sDisplayDeaths[16]; - - new iTargetFrags, - iTargetDeaths; - - /** - Get the targets information - */ - GetClientName(iTarget, sTargetName, sizeof(sTargetName)); - GetClientIP(iTarget, sTargetIP, sizeof(sTargetIP)); - GetClientAuthString(iTarget, sTargetID, sizeof(sTargetID)); - iTargetFrags = GetClientFrags(iTarget); - iTargetDeaths = GetClientDeaths(iTarget); - - /** - Format the strings for the menu - */ - Format(sDisplayName, sizeof(sDisplayName), "Player: %s", sTargetName); - Format(sDisplayID, sizeof(sDisplayID), "Steam ID: %s", sTargetID); - Format(sDisplayIP, sizeof(sDisplayIP), "IP Address: %s", sTargetIP); - Format(sDisplayFrags, sizeof(sDisplayFrags), "Kills: %i", iTargetFrags); - Format(sDisplayDeaths, sizeof(sDisplayDeaths), "Deaths: %i", iTargetDeaths); - - /** - Create the menu and set the menu options. - */ - new Handle:hPanel = CreatePanel(); - SetPanelTitle(hPanel, "Simple Spectator"); - - DrawPanelText(hPanel, "Player Information:"); - DrawPanelText(hPanel, sDisplayName); - DrawPanelText(hPanel, sDisplayID); - if (SM_IsValidAdmin(iClient, g_sAdminFlags)) - { - DrawPanelText(hPanel, sDisplayIP); - } - - DrawPanelText(hPanel, sDisplayFrags); - DrawPanelText(hPanel, sDisplayDeaths); - - if (g_aPlayers[iClient][iTargetIndex]) - { - DrawPanelItem(hPanel, "Stop Following"); - } - else - { - DrawPanelItem(hPanel, "Follow Player"); - } - - if ((GetUserFlagBits(iClient) & ADMFLAG_GENERIC) || (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - if (g_aPlayers[iTarget][bIsFlaggedCheater] && (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - DrawPanelItem(hPanel, "Remove Cheater Flag"); - } - else - { - if (CanUserTarget(iClient, iTarget)) - { - DrawPanelItem(hPanel, "Punish Player"); - } - else - { - DrawPanelItem(hPanel, "Punish Player (Immune)", ITEMDRAW_DISABLED); - } - } - } - else - { - DrawPanelItem(hPanel, "Report Cheater"); - } - - DrawPanelItem(hPanel, "Close Hud Panel"); - return hPanel; -} - -/** -Adjust the settings if a convar was changed -*/ -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - for (new iCvar = 0 ; _:iCvar < sizeof(g_aPluginCvarSettings); iCvar++) - { - if (g_aPluginCvar[_:iCvar] == convar) - { - if (StringToInt(newValue) == 1) - { - g_aPluginCvarSettings[_:iCvar] = true; - } - else - { - g_aPluginCvarSettings[_:iCvar] = false; - } - } - } - - /* - ReBuild the global menu that depends on cvars - */ - g_aMenus[hBanTime] = BuildBanTimeMenu(); - - /** - Run a loop to reset the hud - */ - for(new i = 1; i <= MaxClients; i++) - { - StopDisplayingHud(i); - if (IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(i); - } - } -} diff --git a/Simple Message Suppression/addons/sourcemod/scripting/simple-teambalancer.sp b/Simple Message Suppression/addons/sourcemod/scripting/simple-teambalancer.sp deleted file mode 100644 index 3302255..0000000 --- a/Simple Message Suppression/addons/sourcemod/scripting/simple-teambalancer.sp +++ /dev/null @@ -1,1797 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Team Balancer -Description: - Balances teams based upon player count - Player will not be balanced more than once in 5 (default) mins - Buddy system tries to keep buddies together - Ability to prioritize players - Ability to force players to accept the new team - Admins are immune -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include -#include - -#define PLUGIN_VERSION "2.1.$Rev$" - -enum PlayerData -{ - Handle:hBalanceTimer, - Handle:hForcedTimer, - bool:bSwitched, - bool:bFlagCarrier -}; - -/** - Global convar handles - */ -new Handle:stb_enabled = INVALID_HANDLE; -new Handle:stb_buddyenabled = INVALID_HANDLE; -new Handle:stb_logactivity = INVALID_HANDLE; -new Handle:stb_logactivity2 = INVALID_HANDLE; -new Handle:stb_unbalancelimit = INVALID_HANDLE; -new Handle:stb_deadonly = INVALID_HANDLE; -new Handle:stb_priorityenabled = INVALID_HANDLE; -new Handle:stb_uberlevel = INVALID_HANDLE; -new Handle:stb_balancedelay = INVALID_HANDLE; -new Handle:stb_livingplayerswitchdelay = INVALID_HANDLE; -new Handle:stb_livingplayercheckdelay = INVALID_HANDLE; -new Handle:stb_roundstartdelay = INVALID_HANDLE; -new Handle:stb_switchbackforced = INVALID_HANDLE; -new Handle:stb_adminflag = INVALID_HANDLE; -new Handle:stb_buddyrestriction = INVALID_HANDLE; -new Handle:stb_convarcontrol = INVALID_HANDLE; - -/** - Built-in cvars handles - */ -new Handle:stb_mp_autoteambalance = INVALID_HANDLE; -new Handle:stb_mp_teams_unbalance_limit = INVALID_HANDLE; -new Handle:TFGameModeArena = INVALID_HANDLE; - -/** - Timer handles - */ -new Handle:g_hBalanceTimer = INVALID_HANDLE; -new Handle:g_hLivingPlayerCheckTimer = INVALID_HANDLE; - -/** - Player arrays - */ -new g_aPlayers[MAXPLAYERS + 1][PlayerData]; - -/** -Global bools -*/ -new bool:g_bIsEnabled = true; -new bool:g_bPriorityPlayers = true; -new bool:g_bBuddyRestriction = false; -new bool:g_bLogActivity = false; -new bool:g_bLogActivity2 = false; -new bool:g_bDeadOnly = false; -new bool:g_bConVarControl = true; -new bool:g_bBuddyEnabled = true; -new bool:g_bBalanceInProgress = false; -new bool:g_bRoundStart = false; -new bool:g_bRoundEnd = false; -new bool:g_bSuddenDeath = false; -new bool:g_bIsArenaMode = false; - -/** - Global strings/integers/floats - */ -new g_iUnbalanceLimit, g_iLivingPlayerSwitchDelay, g_iLivingPlayerCheckDelay; -new g_iRoundStartDelay, g_iSwitchBackForced, g_iBalanceDelay; -new Float:g_fUberLevel; -new g_iOwnerOffset; -new String:g_sAdminFlag[5]; - -public Plugin:myinfo = -{ - name = "Simple Team Balancer", - author = "Simple Plugins", - description = "Balances teams based upon player count.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -} - -public OnPluginStart() -{ - - /** - Create console variables - */ - CreateConVar("stb_version", PLUGIN_VERSION, "Simple Team Balancer", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - stb_enabled = CreateConVar("stb_enabled", "1", "Enable or Disable Simple Team Balancer", _, true, 0.0, true, 1.0); - stb_priorityenabled = CreateConVar("stb_priorityenabled", "1", "Enable or Disable the prioritization of living players", _, true, 0.0, true, 1.0); - stb_buddyrestriction = CreateConVar("stb_buddyrestriction", "0", "Enable or Disable Admin Only buddy lists", _, true, 0.0, true, 1.0); - stb_logactivity = CreateConVar("stb_logactivity", "0", "Enable or Disable the disaplying of events in the log", _, true, 0.0, true, 1.0); - stb_logactivity2 = CreateConVar("stb_logactivity2", "0", "Enable or Disable the disaplying of detailed events in the log (WILL SPAM LOG)", _, true, 0.0, true, 1.0); - stb_deadonly = CreateConVar("stb_deadonly", "0", "Enable or Disable the switching of only dead players", _, true, 0.0, true, 1.0); - stb_convarcontrol = CreateConVar("stb_convarcontrol", "1", "Enable or Disable the control of builtin console variables", _, true, 0.0, true, 1.0); - stb_buddyenabled = CreateConVar("stb_buddyenabled", "1", "Enable or Disable the buddy system", _, true, 0.0, true, 1.0); - stb_unbalancelimit = CreateConVar("stb_unbalancelimit", "2", "Amount of players teams are ALLOWED to be unbalanced by", _, true, 1.0, true, 32.0); - stb_balancedelay = CreateConVar("stb_balancedelay", "10", "Delay in seconds to start an autobalance"); - stb_livingplayerswitchdelay = CreateConVar("stb_livingplayerswitchdelay", "20", "Delay in seconds to switch living players once selected"); - stb_livingplayercheckdelay = CreateConVar("stb_livingplayercheckdelay", "10", "Delay in seconds to start checking living players once teams become unbalanced"); - stb_roundstartdelay = CreateConVar("stb_roundstartdelay", "15", "Delay in seconds to start balancing teams after the start of a round"); - stb_switchbackforced = CreateConVar("stb_switchbackforced", "300", "Amount of time in seconds to not switch a player twice and force the team if enabled"); - stb_uberlevel = CreateConVar("stb_uberlevel", "1.0", "Min uber level medic must have to have priority over other living players. Setting to 0 will rarely switch a living medic", _, true, 0.0, true, 1.0); - stb_adminflag = CreateConVar("stb_adminflag", "a", "Admin flag to use for immunity. Must be a in char format."); - stb_mp_autoteambalance = FindConVar("mp_autoteambalance"); - stb_mp_teams_unbalance_limit = FindConVar("mp_teams_unbalance_limit"); - - /** - Removing the notify tags from the built in cvars. We dont want spam. - */ - if (stb_mp_autoteambalance != INVALID_HANDLE) - { - SetConVarFlags(stb_mp_autoteambalance, GetConVarFlags(stb_mp_autoteambalance)^FCVAR_NOTIFY); - } - if (stb_mp_teams_unbalance_limit != INVALID_HANDLE) - { - SetConVarFlags(stb_mp_teams_unbalance_limit, GetConVarFlags(stb_mp_teams_unbalance_limit)^FCVAR_NOTIFY); - } - - /** - Hook console variables - */ - HookConVarChange(stb_enabled, ConVarSettingsChanged); - HookConVarChange(stb_priorityenabled, ConVarSettingsChanged); - HookConVarChange(stb_buddyrestriction, ConVarSettingsChanged); - HookConVarChange(stb_logactivity, ConVarSettingsChanged); - HookConVarChange(stb_logactivity2, ConVarSettingsChanged); - HookConVarChange(stb_deadonly, ConVarSettingsChanged); - HookConVarChange(stb_convarcontrol, ConVarSettingsChanged); - HookConVarChange(stb_buddyenabled, ConVarSettingsChanged); - HookConVarChange(stb_unbalancelimit, ConVarSettingsChanged); - HookConVarChange(stb_balancedelay, ConVarSettingsChanged); - HookConVarChange(stb_livingplayerswitchdelay, ConVarSettingsChanged); - HookConVarChange(stb_livingplayercheckdelay, ConVarSettingsChanged); - HookConVarChange(stb_roundstartdelay, ConVarSettingsChanged); - HookConVarChange(stb_switchbackforced, ConVarSettingsChanged); - HookConVarChange(stb_uberlevel, ConVarSettingsChanged); - HookConVarChange(stb_mp_autoteambalance, ConVarSettingsChanged); - HookConVarChange(stb_mp_teams_unbalance_limit, ConVarSettingsChanged); - - /** - Create console commands - */ - RegConsoleCmd("sm_buddy", Command_AddBalanceBuddy, "Add a balance buddy"); - RegConsoleCmd("sm_lockbuddy", Command_LockBuddy, "Locks your balance buddy selection"); - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[STB] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_death", HookPlayerDeath, EventHookMode_Post); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Post); - switch (g_CurrentMod) - { - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - HookEvent("teamplay_suddendeath_begin", HookSuddenDeathBegin, EventHookMode_PostNoCopy); - HookEvent("teamplay_flag_event", HookFlagEvent, EventHookMode_Post); - TFGameModeArena = FindConVar("tf_gamemode_arena"); - g_iOwnerOffset = FindSendPropInfo("CBaseObject", "m_hBuilder"); - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_Post); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - - /** - Load translations and .cfg file - */ - LoadTranslations ("simpleteambalancer.phrases"); - AutoExecConfig(true, "plugin.simpleteambalancer"); - LogAction(0, -1, "[STB] Simple Team Balancer is loaded."); -} - -public OnAllPluginsLoaded() -{ - //something -} - -public OnLibraryRemoved(const String:name[]) -{ - //something -} - -public OnConfigsExecuted() -{ - - /** - Load up global variables - */ - g_bIsEnabled = GetConVarBool(stb_enabled); - g_bBuddyEnabled = GetConVarBool(stb_buddyenabled); - g_bLogActivity = GetConVarBool(stb_logactivity); - g_bLogActivity2 = GetConVarBool(stb_logactivity2); - g_bDeadOnly = GetConVarBool(stb_deadonly); - g_bPriorityPlayers = GetConVarBool(stb_priorityenabled); - g_bBuddyRestriction = GetConVarBool(stb_buddyrestriction); - g_bConVarControl = GetConVarBool(stb_convarcontrol); - g_fUberLevel = GetConVarFloat(stb_uberlevel); - g_iUnbalanceLimit = GetConVarInt(stb_unbalancelimit); - g_iBalanceDelay = GetConVarInt(stb_balancedelay); - g_iLivingPlayerSwitchDelay = GetConVarInt(stb_livingplayerswitchdelay); - g_iLivingPlayerCheckDelay = GetConVarInt(stb_livingplayercheckdelay); - g_iRoundStartDelay = GetConVarInt(stb_roundstartdelay); - g_iSwitchBackForced = GetConVarInt(stb_switchbackforced); - GetConVarString(stb_adminflag, g_sAdminFlag, sizeof(g_sAdminFlag)); - - /** - Report enabled - */ - if (g_bIsEnabled) - { - LogAction(0, -1, "[STB] Simple Team Balancer is ENABLED."); - } - else - { - LogAction(0, -1, "[STB] Simple Team Balancer is DISABLED."); - } - - - /** - Report log activity - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Log Activity ENABLED."); - } - else - { - LogAction(0, -1, "[STB] Log Activity DISABLED."); - } - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Detailed Log Activity ENABLED."); - } - else - { - LogAction(0, -1, "[STB] Detailed Log Activity DISABLED."); - } -} - -public OnMapStart() -{ - - /** - Check for arena mode - */ - if (g_CurrentMod == GameType_TF && GetConVarBool(TFGameModeArena)) - { - g_bIsArenaMode = true; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Simple Team Balancer detected arena mode and will be bypassed"); - } - } - else - { - g_bIsArenaMode = false; - } - - /** - Reset the globals - */ - g_bBalanceInProgress = false; - g_bRoundStart = false; - g_bRoundEnd = false; - g_bSuddenDeath = false; - - /** - Set the built-in convars - */ - SetGameCvars(); -} - -public OnClientPostAdminCheck(client) -{ - - /** - Make sure its a valid connected client and buddy system is enabled - */ - if (client == 0 || !g_bIsEnabled || !IsClientConnected(client) || !g_bBuddyEnabled) - { - return; - } - - /** - Make sure if its set for admins only they have the flags - */ - if (g_bBuddyRestriction && !SM_IsValidAdmin(client, g_sAdminFlag)) - { - return; - } - - /** - Start the advertisement timer - */ - CreateTimer (60.0, Timer_WelcomeAdvert, client); -} - -public OnClientDisconnect(client) -{ - - /** - Call stock function to cleaup - */ - CleanUp(client); -} - -public OnClientDisconnect_Post(client) -{ - - /** - Determine if we need a balance - */ - if (OkToBalance() && IsUnbalanced() && !g_bBalanceInProgress) - { - - /** - No balance in progress but balance is needed - */ - StartABalance(); - } -} - -public SM_OnPlayerMoved(Handle:plugin, client, team) -{ - - /** - Make sure we called the move function - */ - if (plugin != GetMyHandle()) - { - if (g_bLogActivity2) - { - LogAction(0, client, "[STB] Callback was not started with current plugin, bugging out."); - } - return; - } - - /** - Get the players name and report the event - */ - decl String:sPlayerName[64]; - GetClientName(client, sPlayerName, sizeof(sPlayerName)); - if (g_bLogActivity) - { - LogAction(0, client, "[STB] Changed %s to team %i.", sPlayerName, team); - } - - /** - If we are in TF2 fire the bult-in team balance event - */ - if(g_CurrentMod == GameType_TF) - { - new Handle:event = CreateEvent("teamplay_teambalanced_player"); - SetEventInt(event, "player", client); - SetEventInt(event, "team", team); - FireEvent(event); - } - - /** - Notify the players - */ - PrintToChatAll("[SM] %T", "BalanceMessage", LANG_SERVER, sPlayerName); - - /** - Set the players variables and start a timer - */ - g_aPlayers[client][bSwitched] = true; - g_aPlayers[client][hForcedTimer] = CreateTimer(float(g_iSwitchBackForced), Timer_ForcedExpired, client, TIMER_FLAG_NO_MAPCHANGE); - - /** - We are done, log the completion and end the balance - */ - if (g_bLogActivity) - { - LogAction(0, client, "[STB] Balance finished."); - } - g_bBalanceInProgress = false; -} - -/* HOOKED EVENTS */ - -public HookPlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get our event variables - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - decl String:sWeapon[64]; - GetEventString(event, "weapon", sWeapon, sizeof(sWeapon)); - - /** - Return if death was not caused by a player - This is the case when the player switches teams - */ - if (StrEqual(sWeapon, "world", false)) - { - return; - } - - - /** - Check if balance is needed - */ - if (IsClientInGame(iClient) && OkToBalance() && IsUnbalanced()) - { - new iSmallerTeam = GetSmallerTeam(); - - /** - Check if balance is in progress - */ - if (g_bBalanceInProgress) - { - - /** - There is a balance in progress - Check the player who died to see if he is supposed to be switched - */ - if (g_aPlayers[iClient][hBalanceTimer] != INVALID_HANDLE) - { - - /** - The player has a timer on him to switch him to other team - Stop the timer - */ - CloseHandle(g_aPlayers[iClient][hBalanceTimer]); - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] With a balance in progress the queued living player died and was switched."); - } - - /** - Call the stock change team function - */ - BalancePlayer(iClient, SM_GetForcedTeam(iClient)); - return; - } - - /** - Before we continue, lets make sure the client is switchable - */ - if (IsSwitchablePlayer(iClient, GetBiggerTeam())) - { - - /** - Now we check the buddy system - */ - if (g_bBuddyEnabled) - { - - /** - Buddy system is enabled, check to see if client has buddy - */ - new iBuddyIndex = SM_GetClientBuddy(iClient); - if (iBuddyIndex != 0 || !IsClientConnected(iBuddyIndex) || !IsClientInGame(iBuddyIndex)) - { - - /** - The client has a buddy, so we check to see if they are on same team - */ - if (GetClientTeam(iClient) == GetClientTeam(iBuddyIndex)) - { - - /** - They are, but we don't bug out, we still need to start a balance - */ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] With a balance in progress a buddy on the right team was found and skipped."); - } - } - else - { - - /** - They are not on the same team - The buddy could be in spec, and that would make it not matter where he is, or the buddy is on the smaller team - */ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] With a balance in progress a buddy on the wrong team was switched."); - } - BalancePlayer(iClient, iSmallerTeam); - return; - } - } - else - { - - /** - Client doesn't have a buddy, balance this player - */ - BalancePlayer(iClient, iSmallerTeam); - return; - } - } - else - { - - /** - Buddy system is not enabled, balance this player - */ - BalancePlayer(iClient, iSmallerTeam); - return; - } - } - } - else - { - - /** - If we get to here then we must need to start a balance - */ - StartABalance(); - } - } -} - -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get our event variables. - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - new iTeam = GetEventInt(event, "team"); - - /** - Make sure its ok to balance. - */ - if (OkToBalance()) - { - - /** - See if the client that changed teams was set to with a balance. - */ - if (g_aPlayers[iClient][hBalanceTimer] != INVALID_HANDLE - && SM_GetForcedTeam(iClient) == iTeam - && g_bBalanceInProgress) - { - - /** - The client was set to be balanced, so we close the timer. - */ - CloseHandle(g_aPlayers[iClient][hBalanceTimer]); - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - - /** - Stop the balance. - */ - g_bBalanceInProgress = false; - return; - } - - /** - It's not likely that this team change can cause us to need a balance. - If it does, start one with a small dealy to deal with forced switch backs. - */ - if (IsUnbalanced() && !g_bBalanceInProgress) - { - CreateTimer(2.0, Timer_ChangeTeamBalanceDelay, _, TIMER_FLAG_NO_MAPCHANGE); - } - } -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set the variables we need to start a round - */ - g_bRoundStart = true; - g_bRoundEnd = false; - g_bSuddenDeath = false; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Round Started"); - } - - /** - Start a delayed balance check at the start of the round - */ - CreateTimer(float(g_iRoundStartDelay), Timer_RoundStart); -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set the variables we need at round end - */ - g_bRoundEnd = true; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Round Ended"); - } -} - -public HookSuddenDeathBegin(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set the variables we need for sudden death - */ - g_bSuddenDeath = true; -} - -public HookFlagEvent(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get our event variables - */ - new iClient = GetEventInt(event, "player"); - new iFlagStatus = GetEventInt(event, "eventtype"); - - /** - Make sure we have a valid client - */ - if (!IsClientInGame(iClient)) - { - return; - } - - /** - Determine what kind of event this is - */ - switch (iFlagStatus) - { - case 1: - { - - /** - The flag was picked up - */ - g_aPlayers[iClient][bFlagCarrier] = true; - } - case 2: - { - - /** - The flag was capped - */ - g_aPlayers[iClient][bFlagCarrier] = false; - } - case 3: - { - - /** - The flag was defended, we don't have to do anything - */ - } - case 4: - { - - /** - The flag was dropped - */ - g_aPlayers[iClient][bFlagCarrier] = false; - } - } -} - -/* COMMAND EVENTS */ - -public Action:Command_AddBalanceBuddy(client, args) -{ - if (client == 0) - { - ReplyToCommand(client, "[SM] %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - if (!g_bIsEnabled || !g_bBuddyEnabled) - { - ReplyToCommand(client, "[SM] %T", "CmdDisabled", LANG_SERVER); - return Plugin_Handled; - } - if (g_bBuddyRestriction) - { - if (!SM_IsValidAdmin(client, g_sAdminFlag)) - { - ReplyToCommand(client, "[SM] %T", "RestrictedBuddy", LANG_SERVER); - return Plugin_Handled; - } - } - decl String:sPlayerUserId[24]; - GetCmdArg(1, sPlayerUserId, sizeof(sPlayerUserId)); - new iPlayer = GetClientOfUserId(StringToInt(sPlayerUserId)); - if (!iPlayer || !IsClientInGame(iPlayer) || client == iPlayer) - { - if (client == iPlayer) - { - PrintHintText(client, "%T", "SelectSelf", LANG_SERVER); - } - ReplyToCommand(client, "[SM] Usage: buddy "); - new Handle:playermenu = BuildPlayerMenu(); - DisplayMenu(playermenu, client, MENU_TIME_FOREVER); - } - else - { - decl String:cName[128]; - decl String:bName[128]; - GetClientName(client, cName, sizeof(cName)); - GetClientName(iPlayer, bName, sizeof(bName)); - if (SM_IsBuddyLocked(iPlayer)) - { - ReplyToCommand(client, "[SM] %T", "PlayerLockedBuddyMsg", LANG_SERVER, bName); - return Plugin_Handled; - } - SM_AssignBuddy(client, iPlayer); - PrintHintText(client, "%T", "BuddyMsg", LANG_SERVER, bName); - PrintHintText(iPlayer, "%T", "BuddyMsg", LANG_SERVER, cName); - } - return Plugin_Handled; -} - -public Action:Command_LockBuddy(client, args) -{ - if (client == 0) - { - ReplyToCommand(client, "[SM] %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - if (!g_bIsEnabled) - { - ReplyToCommand(client, "[SM] %T", "CmdDisabled", LANG_SERVER); - return Plugin_Handled; - } - if (g_bBuddyRestriction) - { - if (!SM_IsValidAdmin(client, g_sAdminFlag)) - { - ReplyToCommand(client, "[SM] %T", "RestrictedBuddy", LANG_SERVER); - return Plugin_Handled; - } - } - if (SM_IsBuddyLocked(client)) - { - SM_LockBuddy(client, false); - PrintHintText(client, "%T", "BuddyLockMsgDisabled", LANG_SERVER); - } - else - { - SM_LockBuddy(client, true); - PrintHintText(client, "%T", "BuddyLockMsgEnabled", LANG_SERVER); - } - return Plugin_Handled; -} - -/** -Stock functions . - */ - -stock bool:IsUnbalanced() -{ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Checking if teams are unbalanced"); - } - new Team1Count = GetTeamClientCount(g_aCurrentTeams[Team1]); - new Team2Count = GetTeamClientCount(g_aCurrentTeams[Team2]); - new ubCount = RoundFloat(FloatAbs(float(Team1Count - Team2Count))); - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Team1:%i Team2:%i Difference:%i", Team1Count, Team2Count, ubCount); - } - if (ubCount > g_iUnbalanceLimit) - { - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Teams are unbalanced"); - } - return true; - } - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Teams are not unbalanced"); - } - return false; -} - -stock bool:OkToBalance() -{ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Checking if OK to balance."); - } - new bool:bResult = false; - if (g_bIsEnabled && !g_bRoundStart && !g_bRoundEnd && !g_bIsArenaMode && !g_bSuddenDeath) - { - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Passed IF statement"); - LogAction(0, -1, "[STB] Now checking admins"); - } - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientInGame(i) && !SM_IsValidAdmin(i, g_sAdminFlag)) - { - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Found at least 1 non-admin"); - LogAction(0, -1, "[STB] OK to balance"); - } - bResult = true; - break; - } - } - if (!bResult && g_bLogActivity2) - { - LogAction(0, -1, "[STB] All admins online"); - } - } - if (!bResult && g_bLogActivity2) - { - LogAction(0, -1, "[STB] Not OK to balance"); - } - return bResult; -} - -stock bool:IsSwitchablePlayer(iClient, iBiggerTeam) -{ - - /** - Run the client thru some standard checks - */ - if (!IsClientInGame(iClient) - || SM_IsValidAdmin(iClient, g_sAdminFlag) - || g_aPlayers[iClient][bFlagCarrier] - || GetClientTeam(iClient) != iBiggerTeam - || g_aPlayers[iClient][bSwitched]) - { - - /** - The supplied client can't be switched - */ - return false; - } - - /** - The supplied client can be switched - */ - return true; -} - -stock bool:HasUber(iClient) -{ - - /** - First things first, make sure the client is a medic - */ - if(TF2_GetPlayerClass(iClient) == TFClass_Medic) - { - - /** - We can only check the active weapon, so make sure the client is holding the uber gun - */ - decl String:sWeaponName[32]; - GetClientWeapon(iClient, sWeaponName, sizeof(sWeaponName)); - if(StrEqual(sWeaponName, "tf_weapon_medigun")) - { - - /** - They are, so lets check the uber level of the gun - */ - new iEntityIndex = GetEntDataEnt2(iClient, FindSendPropInfo("CTFPlayer", "m_hActiveWeapon")); - new Float:fChargeLevel = GetEntDataFloat(iEntityIndex, FindSendPropInfo("CWeaponMedigun", "m_flChargeLevel")); - if (fChargeLevel >= g_fUberLevel) - { - - /** - The client supplied has an uber above the supplied level, return true - */ - if (g_bLogActivity2) - { - LogAction(0, iClient, "[STB] Found a medic with a uber and skipped him."); - } - return true; - } - } - } - - /** - The client supplied does not have an uber above the supplied level, return false - */ - return false; -} - -stock bool:HasBuildingsBuilt(iClient) -{ - - /** - We have to start a loop to check the owner of all the valid entities - */ - new iMaxEntities = GetMaxEntities(); - for (new i = MaxClients + 1; i <= iMaxEntities; i++) - { - if (!IsValidEntity(i)) - { - - /** - Not valid, continue to next one - */ - continue; - } - - /** - Get the name of the current entity - */ - decl String:sNetClass[32]; - GetEntityNetClass(i, sNetClass, sizeof(sNetClass)); - - /** - See if its something that an engineer would build - */ - if (strcmp(sNetClass, "CObjectSentrygun") == 0 - || strcmp(sNetClass, "CObjectTeleporter") == 0 - || strcmp(sNetClass, "CObjectDispenser") == 0) - { - - /** - It is, so lets check the owner - */ - if (GetEntDataEnt2(i, g_iOwnerOffset) == iClient) - { - - /** - The client supplied is the owner, return true - */ - if (g_bLogActivity2) - { - LogAction(0, iClient, "[STB] Found an engineer with buildings and skipped him."); - } - return true; - } - } - } - - /** - The client supplied didn't have any buildings, return false - */ - return false; -} - -stock StartABalance() -{ - - /** - See if we are already started a balance - */ - if (g_hBalanceTimer != INVALID_HANDLE) - { - - /** - We have, check if we still need to - */ - if (!IsUnbalanced() || !OkToBalance()) - { - - /** - We don't, stop the balance - It's almost impossible to reach this code, but we do it just in case - */ - CloseHandle(g_hBalanceTimer); - g_hBalanceTimer = INVALID_HANDLE; - g_bBalanceInProgress = false; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Balance delay timer was not needed and was killed before the callback."); - } - return; - } - else - { - - /** - We still need to balance - Bug out and wait for the current one to finish - */ - return; - } - } - - /** - Report that teams are unbalanced - */ - PrintToChatAll("[SM] %T", "UnBalanced", LANG_SERVER); - - /** - Check to see if we are supposed to delay the balance - */ - if (g_iBalanceDelay == 0) - { - - /** - Start the balance now - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Balance is now in progress."); - } - g_bBalanceInProgress = true; - g_hBalanceTimer = INVALID_HANDLE; - - /** - Check if we are allowed to scan living players - */ - if (!g_bDeadOnly) - { - - /** - We are allowed to, so we start a timer - */ - StartALivingPlayerTimer(); - - /** - Also report that we are now scanning dead players as well - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Now scanning dead players."); - } - } - else - { - - /** - We are not allowed to, so report that we are only scanning dead players - */ - if (g_bLogActivity) - LogAction(0, -1, "[STB] Only scanning dead players."); - } - - /** - We started the balance, bug out - */ - return; - } - - /** - We are supposed to delay the balance, start a balance timer - */ - g_hBalanceTimer = CreateTimer(float(g_iBalanceDelay), Timer_BalanceTeams, _, TIMER_FLAG_NO_MAPCHANGE); - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Teams are unbalanced. Balance delay timer started."); - } -} - -stock StartALivingPlayerTimer() -{ - - /** - Start a timer to check living players - */ - if (g_hLivingPlayerCheckTimer != INVALID_HANDLE) - { - - /** - If we for some reason already have one started, stop it. - */ - CloseHandle(g_hLivingPlayerCheckTimer); - g_hLivingPlayerCheckTimer = INVALID_HANDLE; - } - - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Living player balance delay timer started."); - } - g_hLivingPlayerCheckTimer = CreateTimer(float(g_iLivingPlayerCheckDelay), Timer_LivingPlayerCheck, _, TIMER_FLAG_NO_MAPCHANGE); -} - -stock FindSwitchablePlayer() -{ - - /** - Start a loop to find a switchable player - */ - new iPlayer; - new iBiggerTeam = GetBiggerTeam(); - for (new i = 1; i <= MaxClients; i++) - { - - /** - Check the stock function to see if we are allows to even switch the player - */ - if (!IsSwitchablePlayer(i, iBiggerTeam)) - { - continue; - } - - /** - If the mod is TF2 and they have Priority Players set check if the client has buildings or an uber - */ - if (g_CurrentMod == GameType_TF && g_bPriorityPlayers) - { - if (HasUber(i) || HasBuildingsBuilt(i)) - { - continue; - } - } - - /** - So far we are able we switch this player - Now we check the buddy system - */ - if (g_bBuddyEnabled) - { - - /** - Buddy system is enabled, check to see if client has buddy - */ - if (SM_GetClientBuddy(i) != 0) - { - - /** - The client has a buddy, so we check to see if they are on same team - */ - if (GetClientTeam(i) == GetClientTeam(SM_GetClientBuddy(i))) - { - - /** - They are, so we continue to next client - */ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] With a balance in progress a buddy on the right team was found and skipped."); - } - continue; - } - else - { - - /** - They are not on the same team, set this client - The buddy could be in spec, and that would make it not matter where he is, or the buddy is on the smaller team - */ - iPlayer = i; - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] With a balance in progress a buddy on the wrong team was found."); - } - break; - } - } - else - { - - /** - The client does not have a buddy, set this client - */ - iPlayer = i; - break; - } - } - else - { - - /** - Buddy system is not enabled, set this client - */ - iPlayer = i; - break; - } - } - - /** - Return the client we set, this could be 0, but very unlikely - */ - return iPlayer; -} - -stock BalancePlayer(iClient, iTeam) -{ - new Handle:hPack = CreateDataPack(); - WritePackCell(hPack, iClient); - WritePackCell(hPack, iTeam); - CreateTimer(0.1, Timer_BalancePlayer, hPack, TIMER_FLAG_NO_MAPCHANGE); -} - -stock CleanUp(iClient) -{ - g_aPlayers[iClient][bFlagCarrier] = false; - g_aPlayers[iClient][bSwitched] = false; - if (g_aPlayers[iClient][hForcedTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hForcedTimer]); - g_aPlayers[iClient][hForcedTimer] = INVALID_HANDLE; - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] Forced player disconnected, killing timer."); - } - } - if (g_aPlayers[iClient][hBalanceTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hBalanceTimer]); - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] Living player set to be balanced disconnected, killing timer."); - } - } -} - -stock GetSmallerTeam() -{ - - /** - Get the count of players on each team - */ - new iCountT1 = GetTeamClientCount(g_aCurrentTeams[Team1]); - new iCountT2 = GetTeamClientCount(g_aCurrentTeams[Team2]); - - /** - Return the smaller team - */ - if (iCountT1 < iCountT2) - { - return g_aCurrentTeams[Team1]; - } - else if (iCountT1 > iCountT2) - { - return g_aCurrentTeams[Team2]; - } - return 0; -} - -stock GetBiggerTeam() -{ - - /** - Get the count of players on each team - */ - new iCountT1 = GetTeamClientCount(g_aCurrentTeams[Team1]); - new iCountT2 = GetTeamClientCount(g_aCurrentTeams[Team2]); - - /** - Return the bigger team - */ - if (iCountT1 > iCountT2) - { - return g_aCurrentTeams[Team1]; - } - else if (iCountT1 < iCountT2) - { - return g_aCurrentTeams[Team2]; - } - return 0; -} - -stock SetGameCvars() -{ - if (g_bConVarControl && g_bIsEnabled) - { - if (stb_mp_autoteambalance != INVALID_HANDLE) - { - SetConVarInt(stb_mp_autoteambalance, 0); - } - if (stb_mp_teams_unbalance_limit != INVALID_HANDLE) - { - SetConVarInt(stb_mp_teams_unbalance_limit, g_iUnbalanceLimit); - } - } -} - -/* TIMER FUNCTIONS */ - -public Action:Timer_ChangeTeamBalanceDelay(Handle:timer, any:data) -{ - - /** - Finally start one if it's still unbalanced - */ - if (IsUnbalanced() && !g_bBalanceInProgress) - { - StartABalance(); - } -} - -public Action:Timer_BalanceTeams(Handle:timer, any:data) -{ - - /** - See if we still need to balance the teams - */ - if (!IsUnbalanced() || !OkToBalance()) - { - - /** - We don't, kill the balance - */ - g_bBalanceInProgress = false; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Balance delay timer was not needed and died."); - } - g_hBalanceTimer = INVALID_HANDLE; - return Plugin_Handled; - } - - /** - We still need to balance the teams - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Teams are still unbalanced. Balance is now in progress."); - } - g_bBalanceInProgress = true; - - - /** - Check if we are allowed to scan living players - */ - if (!g_bDeadOnly) - { - - /** - We are allowed to, so we start a timer - */ - StartALivingPlayerTimer(); - - /** - Also report that we are now scanning dead players as well - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Now scanning dead players."); - } - } - else - { - - /** - We are not allowed to, so report that we are only scanning dead players - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Only scanning dead players."); - } - } - - g_hBalanceTimer = INVALID_HANDLE; - return Plugin_Handled; -} - -public Action:Timer_LivingPlayerCheck(Handle:timer, any:data) -{ - - /** - Check to see if we still need to balance the teams - */ - if (!IsUnbalanced() || !OkToBalance()) - { - - /** - We don't, kill it and bug out - */ - g_bBalanceInProgress = false; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Living player balance delay timer was not needed and died."); - } - g_hLivingPlayerCheckTimer = INVALID_HANDLE; - return Plugin_Handled; - } - - /** - Call the stock function to find a player we can switch - */ - new iPlayer = FindSwitchablePlayer(); - - /** - Check to see if we found a player - */ - if (iPlayer == 0) - { - - /** - In the unlikely event that the stock function didn't return a player - Start a loop to find a random player - */ - new iBiggerTeam = GetBiggerTeam(); - do - { - iPlayer = GetRandomInt(1, MaxClients); - } while (!IsSwitchablePlayer(iPlayer, iBiggerTeam)); - - if (g_bLogActivity) - { - LogAction(0, iPlayer, "[STB] Found a random living player."); - } - } - else - { - if (g_bLogActivity) - { - LogAction(0, iPlayer, "[STB] Found a living player."); - } - } - - /** - Now that we have a player assigned them to the smaller team - */ - new iSmallerTeam = GetSmallerTeam(); - SM_SetForcedTeam(iPlayer, iSmallerTeam, true); - - /** - Let the player know we could be switching him soon - */ - PrintHintText(iPlayer, "%T", "PlayerMessage", LANG_SERVER, g_iLivingPlayerSwitchDelay); - if (g_bLogActivity) - { - LogAction(0, iPlayer, "[STB] Living player placed on a timer."); - } - - /** - Create a timer to switch the player - */ - g_aPlayers[iPlayer][hBalanceTimer] = CreateTimer(float(g_iLivingPlayerSwitchDelay), Timer_LivingPlayerBalance, iPlayer, TIMER_FLAG_NO_MAPCHANGE); - - /** - Reset the timer handle - */ - g_hLivingPlayerCheckTimer = INVALID_HANDLE; - - /** - We are done, bug out - */ - return Plugin_Handled; -} - -public Action:Timer_LivingPlayerBalance(Handle:timer, any:iClient) -{ - - /** - Check to make sure we still need to balance - */ - if (!IsUnbalanced() || !OkToBalance()) - { - - /** - We don't need to balance, bug out - */ - g_bBalanceInProgress = false; - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - SM_ClearForcedTeam(iClient); - return Plugin_Handled; - } - - /** - We still need to balance, lets make sure we can still balance this player - */ - if (!IsClientConnected(iClient) || g_aPlayers[iClient][bFlagCarrier]) - { - g_bBalanceInProgress = false; - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - SM_ClearForcedTeam(iClient); - if (g_bLogActivity) - { - if (g_aPlayers[iClient][bFlagCarrier]) - { - LogAction(0, iClient, "[STB] Living player became flag carrier, balance restarted."); - } - else - { - LogAction(0, iClient, "[STB] Living player timer was not needed and died."); - } - } - return Plugin_Handled; - } - - /** - Clear to balance this player, so do it - */ - BalancePlayer(iClient, SM_GetForcedTeam(iClient)); - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] Living player was switched."); - } - - /** - We are done, bug out - */ - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - return Plugin_Handled; -} - -public Action:Timer_BalancePlayer(Handle:timer, Handle:pack) -{ - - /** - Rest the datapack and load the variables - */ - ResetPack(pack); - new iClient = ReadPackCell(pack); - new iUnBalancedTeam = ReadPackCell(pack); - - /** - We are done with you now - */ - CloseHandle(pack); - - /** - Check the team and make sure its a valid team - */ - if(!SM_IsValidTeam(iUnBalancedTeam)) - { - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] Balance failed due to invalid team number %i", iUnBalancedTeam); - } - return Plugin_Handled; - } - - /** - Use our core function to change the clients team - */ - SM_MovePlayer(iClient, iUnBalancedTeam); - - return Plugin_Handled; -} - -public Action:Timer_RoundStart(Handle:timer, any:data) -{ - g_bRoundStart = false; - if (OkToBalance() && IsUnbalanced() && !g_bBalanceInProgress) - { - StartABalance(); - } - return Plugin_Handled; -} - -public Action:Timer_ForcedExpired(Handle:timer, any:iClient) -{ - SM_ClearForcedTeam(iClient); - g_aPlayers[iClient][bSwitched] = false; - g_aPlayers[iClient][hForcedTimer] = INVALID_HANDLE; - return Plugin_Handled; -} - -public Action:Timer_WelcomeAdvert(Handle:timer, any:iClient) -{ - if (IsClientConnected(iClient) && IsClientInGame(iClient)) - { - PrintToChat (iClient, "\x01\x04[STB]\x01 %T", "BuddyWelcomeMsg1", LANG_SERVER); - PrintToChat (iClient, "\x01\x04[STB]\x01 %T", "BuddyWelcomeMsg2", LANG_SERVER); - PrintToChat (iClient, "\x01\x04[STB]\x01 %T", "BuddyWelcomeMsg3", LANG_SERVER); - } - return Plugin_Handled; -} - -/* CONSOLE VARIABLE CHANGE EVENT */ - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (convar == stb_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsEnabled = false; - PrintToChatAll("[SM] %T", "Disabled", LANG_SERVER); - LogAction(0, -1, "[SimpleTeamBalancer] Disabled"); - } - else - { - g_bIsEnabled = true; - SetGameCvars(); - PrintToChatAll("[SM] %T", "Enabled", LANG_SERVER); - LogAction(0, -1, "[SimpleTeamBalancer] Enabled"); - } - } - else if (convar == stb_logactivity) - { - if (StringToInt(newValue) == 0) - { - g_bLogActivity = false; - LogAction(0, -1, "[STB] Log Activity DISABLED."); - } - else - { - g_bLogActivity = true; - LogAction(0, -1, "[STB] Log Activity ENABLED."); - } - } - else if (convar == stb_logactivity2) - { - if (StringToInt(newValue) == 0) - { - g_bLogActivity2 = false; - LogAction(0, -1, "[STB] Detailed Log Activity DISABLED."); - } - else - { - g_bLogActivity2 = true; - LogAction(0, -1, "[STB] Detailed Log Activity ENABLED."); - } - } - else if (convar == stb_convarcontrol) - { - if (StringToInt(newValue) == 0) - { - g_bConVarControl = false; - } - else - { - g_bConVarControl = true; - SetGameCvars(); - } - } - else if (convar == stb_deadonly) - { - if (StringToInt(newValue) == 0) - { - g_bDeadOnly = false; - } - else - { - g_bDeadOnly = true; - } - } - else if (convar == stb_priorityenabled) - { - if (StringToInt(newValue) == 0) - { - g_bPriorityPlayers = false; - } - else - { - g_bPriorityPlayers = true; - } - } - else if (convar == stb_buddyenabled) - { - if (StringToInt(newValue) == 0) - { - g_bBuddyEnabled = false; - } - else - { - g_bBuddyEnabled = true; - } - } - else if (convar == stb_buddyrestriction) - { - if (StringToInt(newValue) == 0) - { - g_bBuddyRestriction = false; - } - else - { - g_bBuddyRestriction = true; - } - } - else if (convar == stb_unbalancelimit) - { - g_iUnbalanceLimit = StringToInt(newValue); - SetGameCvars(); - } - else if (convar == stb_balancedelay) - { - g_iBalanceDelay = StringToInt(newValue); - } - else if (convar == stb_roundstartdelay) - { - g_iRoundStartDelay = StringToInt(newValue); - } - else if (convar == stb_livingplayerswitchdelay) - { - g_iLivingPlayerSwitchDelay = StringToInt(newValue); - } - else if (convar == stb_livingplayercheckdelay) - { - g_iLivingPlayerCheckDelay = StringToInt(newValue); - } - else if (convar == stb_uberlevel) - { - g_fUberLevel = StringToFloat(newValue); - } - else if (convar == stb_switchbackforced) - { - g_iSwitchBackForced = StringToInt(newValue); - } - else if (convar == stb_adminflag) - { - SetConVarString(stb_adminflag, newValue); - } - else if (convar == stb_mp_autoteambalance) - { - SetGameCvars(); - } - else if (convar == stb_mp_teams_unbalance_limit) - { - SetGameCvars(); - } -} - -/* MENU CODE */ - -stock Handle:BuildPlayerMenu() -{ - new Handle:menu = CreateMenu(Menu_SelectPlayer); - AddTargetsToMenu(menu, 0, true, false); - SetMenuTitle(menu, "Select A Player:"); - SetMenuExitButton(menu, true); - return menu; -} - -public Menu_SelectPlayer(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - new buddy = GetClientOfUserId(StringToInt(sSelection)); - if (param1 == buddy) { - PrintHintText(param1, "%T", "SelectSelf", LANG_SERVER); - } else if (!IsClientInGame(buddy)) { - PrintHintText(param1, "%T", "BuddyGone", LANG_SERVER); - } else { - decl String:cName[128]; - decl String:bName[128]; - GetClientName(param1, cName, sizeof(cName)); - GetClientName(buddy, bName, sizeof(bName)); - if (!SM_IsBuddyLocked(buddy)) { - SM_AssignBuddy(param1, buddy); - PrintHintText(param1, "%T", "BuddyMsg", LANG_SERVER, bName); - PrintHintText(buddy, "%T", "BuddyMsg", LANG_SERVER, cName); - } else - PrintHintText(param1, "%T", "PlayerLockedBuddyMsg", LANG_SERVER, bName); - } - } else if (action == MenuAction_End) { - CloseHandle(menu); - } -} \ No newline at end of file diff --git a/Simple Message Suppression/addons/sourcemod/scripting/simple-teammanager.sp b/Simple Message Suppression/addons/sourcemod/scripting/simple-teammanager.sp deleted file mode 100644 index 008f443..0000000 --- a/Simple Message Suppression/addons/sourcemod/scripting/simple-teammanager.sp +++ /dev/null @@ -1,1351 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Team Manager -Description: - Manges players and their team - Admin menu integration - Allows admins/donators to swap their teams (clears force)* - Allows admins to move players to a team (forced\unforced)* - Allows admins to scramble the teams* - *Works with Simple Team Balancer (if installed) -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include - -#define PLUGIN_VERSION "2.1.$Rev$" -#define VOTE_YES "##YES##" -#define VOTE_NO "##NO##" - -enum PlayerData -{ - iNewTeam, - bool:bQueue -}; - -new Handle:stm_enabled = INVALID_HANDLE; -new Handle:stm_logactivity = INVALID_HANDLE; -new Handle:stm_adminflag_swapteam = INVALID_HANDLE; -new Handle:stm_adminflag_moveplayer = INVALID_HANDLE; -new Handle:stm_adminflag_scramble = INVALID_HANDLE; -new Handle:stm_scrambledelay = INVALID_HANDLE; -new Handle:stm_voteenabled = INVALID_HANDLE; -new Handle:stm_votewin = INVALID_HANDLE; -new Handle:stm_votedelay = INVALID_HANDLE; -new Handle:stm_mp_bonusroundtime = INVALID_HANDLE; -new Handle:g_hAdminMenu = INVALID_HANDLE; -new Handle:g_hTimerPrepScramble = INVALID_HANDLE; -new Handle:g_hTimerClearScrambleForce = INVALID_HANDLE; - -new g_aPlayers[MAXPLAYERS + 1][PlayerData]; - -new bool:g_bIsEnabled = true; -new bool:g_bVoteEnabled = true; -new bool:g_bLogActivity = true; -new bool:g_bScrambleRoundEnd = false; -new g_iVoteDelay, g_iLastVoteTime, g_iTimeLeft; -new Float:g_fScrambleDelay, Float:g_fVoteWin; - -public Plugin:myinfo = -{ - name = "Simple Team Manager", - author = "Simple Plugins", - description = "Manages players and thier team.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -public OnPluginStart() -{ - - /** - Need to create all of our console variables. - */ - CreateConVar("stm_version", PLUGIN_VERSION, "Simple Team Manager Version",FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - stm_enabled = CreateConVar("stm_enabled", "1", "Enable or Disable Simple Team Manager", _, true, 0.0, true, 1.0); - stm_logactivity = CreateConVar("stm_logactivity", "0", "Enable or Disable the disaplying of events in the log", _, true, 0.0, true, 1.0); - stm_adminflag_swapteam = CreateConVar("stm_adminflag_swapteam", "a", "Admin flag to use for the swapteam command. Must be a in char format."); - stm_adminflag_moveplayer = CreateConVar("stm_adminflag_moveplayer", "c", "Admin flag to use for the moveplayer command. Must be a in char format."); - stm_adminflag_scramble = CreateConVar("stm_adminflag_scramble", "c", "Admin flag to use for the scrambleteam command. Must be a in char format."); - stm_scrambledelay = CreateConVar("stm_scrambledelay", "15", "Delay to scramble teams"); - stm_voteenabled = CreateConVar("stm_voteenabled", "1", "Enable or Disable voting to scramble the teams", _, true, 0.0, true, 1.0); - stm_votewin = CreateConVar("stm_votewin", "0.45", "Win percentage vote must win by", _, true, 0.0, true, 1.0); - stm_votedelay = CreateConVar("stm_votedelay", "600", "Delay before another vote can be cast"); - stm_mp_bonusroundtime = FindConVar("mp_bonusroundtime"); - - - /** - Need deal with changes to the console variables after the plugin is loaded. - We could not do this and just call the actual console variable each time we need it, but it's not efficent. - */ - HookConVarChange(stm_enabled, ConVarSettingsChanged); - HookConVarChange(stm_logactivity, ConVarSettingsChanged); - HookConVarChange(stm_scrambledelay, ConVarSettingsChanged); - HookConVarChange(stm_voteenabled, ConVarSettingsChanged); - HookConVarChange(stm_votewin, ConVarSettingsChanged); - HookConVarChange(stm_votedelay, ConVarSettingsChanged); - - /** - Need to register the commands we are going to create and use. - */ - RegConsoleCmd("sm_swapteam", Command_SwapTeam, "sm_swapteam <[0]instant/[1]queued>: Swaps your team to the other team"); - RegConsoleCmd("sm_moveplayer", Command_MovePlayer, "sm_moveplayer <[0]instant/[1]ondeath> <[0]unforced/[1]forced>: Moves a player to the specified team"); - RegConsoleCmd("sm_scrambleteams", Command_ScrambleTeams, "sm_scrambleteams: <[0]now/[1]roundend> <[0]dontrestart/[1]restartround> Scrambles the current teams"); - RegConsoleCmd("sm_votescramble", Command_VoteScramble, "sm_votescramble: Starts a vote to scramble the teams"); - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[STM] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_death", HookPlayerDeath, EventHookMode_Post); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Post); - switch (g_CurrentMod) - { - case GameType_TF: - { - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - } - case GameType_DOD: - { - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_Post); - } - default: - { - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - - /** - Now we have to deal with the admin menu. If the admin library is loaded call the function to add our items. - */ - new Handle:gTopMenu; - if (LibraryExists("adminmenu") && ((gTopMenu = GetAdminTopMenu()) != INVALID_HANDLE)) - { - OnAdminMenuReady(gTopMenu); - } - - /** - Load translations and .cfg file - */ - LoadTranslations ("simpleteammanager.phrases"); - AutoExecConfig(true, "plugin.simpleteammanager"); - LogAction(0, -1, "[STM] Simple Team Manager is loaded."); -} - -public OnAllPluginsLoaded() -{ - //something -} - -public OnLibraryRemoved(const String:name[]) -{ - if (StrEqual(name, "adminmenu")) - { - - /** - Looks like the admin menu was removed. Set the global. - */ - g_hAdminMenu = INVALID_HANDLE; - } - else if (StrEqual(name, "simpleplugins")) - { - SetFailState("Required plugin Simple SourceMod Plugins Core was removed."); - } -} - -public OnConfigsExecuted() -{ - - /** - Once we loaded up all the console variables from the config file, lets now set all the global variables we will use. - */ - g_bIsEnabled = GetConVarBool(stm_enabled); - g_bLogActivity = GetConVarBool(stm_logactivity); - g_fScrambleDelay = GetConVarFloat(stm_scrambledelay); - g_iVoteDelay = GetConVarInt(stm_votedelay); - g_fVoteWin = GetConVarFloat(stm_votewin); - g_iLastVoteTime = RoundFloat(GetEngineTime()); - g_bScrambleRoundEnd = false; - g_hTimerClearScrambleForce = INVALID_HANDLE; - - /** - Report enabled - */ - if (g_bIsEnabled) - { - LogAction(0, -1, "[STM] Simple Team Manager is ENABLED."); - } - else - { - LogAction(0, -1, "[STM] Simple Team Manager is DISABLED."); - } - - if (g_bLogActivity) - { - LogAction(0, -1, "[STM] Log Activity ENABLED."); - } - else - { - LogAction(0, -1, "[STM] Log Activity DISABLED."); - } -} - -/* COMMANDS */ - -public Action:Command_SwapTeam(client, args) -{ - - /** - Make sure we are enabled, if not bug out. - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - If this was ran from the console bug out. - */ - if (client == 0) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure the client is authorized to run this command. - */ - decl String:sFlags[5]; - GetConVarString(stm_adminflag_swapteam, sFlags, sizeof(sFlags)); - if (!SM_IsValidAdmin(client, sFlags)) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Lets make sure the client is one a team we can swap. - If he is we set the global array to the opposite team. - */ - new iTeam = GetClientTeam(client); - if (iTeam == g_aCurrentTeams[Team1]) - { - g_aPlayers[client][iNewTeam] = g_aCurrentTeams[Team2]; - } - else if (iTeam == g_aCurrentTeams[Team2]) - { - g_aPlayers[client][iNewTeam] = g_aCurrentTeams[Team1]; - } - else - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "InValidTeam", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check to see if we have command arguments. - */ - if (GetCmdArgs()) - { - - /** - We do, so lets get it and see if the client wants to be switched instantly or queued for death. - */ - decl String:sArg[5]; - GetCmdArg(1, sArg, sizeof(sArg)); - new iWantsQue = StringToInt(sArg); - if (iWantsQue && !g_aPlayers[client][bQueue]) - { - - /** - He wants the que and isn't already in it, set the global array. - */ - g_aPlayers[client][bQueue] = true; - ReplyToCommand(client, "\x01\x04[STM]\x01 %T", "PlayerQueue", LANG_SERVER); - } - else if (!iWantsQue) - { - - /** - He wants to be switched right now, lets call the stock function. - */ - SM_MovePlayer(client, g_aPlayers[client][iNewTeam]); - } - } - else - { - - /** - There are no command arguments so we build and display the swap menu. - */ - DisplaySwapModeMenu(client, client); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_MovePlayer(client, args) -{ - - /** - Make sure we are enabled, if not bug out. - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the client is authorized to run this command. - */ - decl String:sFlags[5]; - GetConVarString(stm_adminflag_moveplayer, sFlags, sizeof(sFlags)); - if (!SM_IsValidAdmin(client, sFlags)) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check to see if we have command arguments. - */ - new iCmdArgs = GetCmdArgs(); - if (iCmdArgs == 0) - { - - /** - We don't. Build the player menu, display it, and bug out. - */ - DisplayPlayerMenu(client); - return Plugin_Handled; - } - - /** - Check the first argument - If should be a players name or userid. - */ - decl String:sPlayer[64]; - GetCmdArg(1, sPlayer, sizeof(sPlayer)); - new iPlayerIndex = FindTarget(client, sPlayer, true, true); - if (iPlayerIndex == -1 || !IsClientInGame(iPlayerIndex)) - { - - /** - We don't know who this is. Build the player menu, display it, and bug out. - */ - DisplayPlayerMenu(client); - return Plugin_Handled; - } - - /** - We have figured out the first argument, lets check the second. - If should be the team the client wants to put the player on. - */ - if (iCmdArgs >= 2) - { - - /** - We have a command argument at least, lets see if we can identify the team. - */ - decl String:sTeam[24]; - GetCmdArg(2, sTeam, sizeof(sTeam)); - - new iTeam = StringToInt(sTeam); - if (SM_IsValidTeam(iTeam)) - { - - /** - It's a vaild team so lets set the global array to the new team. - */ - g_aPlayers[iPlayerIndex][iNewTeam] = iTeam; - } - else - { - - /** - It's not a vaild team so set the menu to display to the team menu. - */ - DisplayTeamMenu(client, iPlayerIndex); - return Plugin_Handled; - } - } - else - { - /** - We were not given a team, display the team menu. - */ - DisplayTeamMenu(client, iPlayerIndex); - return Plugin_Handled; - } - - /** - Check to see if we were given any more command arguments and found a team. - */ - if (iCmdArgs < 3) - { - - /** - No more command arguments and found a team. - Now lets check to see if the player is a spectator. If he is there is no reason to ask if it's instant or on death... he can't die. - */ - if (!IsClientObserver(iPlayerIndex)) - { - - /** - Not a spectator so display the swapmode menu. - */ - DisplaySwapModeMenu(client, iPlayerIndex); - } - else - { - - /** - The player is a spectator. - We make sure the player is not set to switch on death, since a spec can't die. - */ - g_aPlayers[iPlayerIndex][bQueue] = false; - } - } - - /** - We have figured out the second argument, lets check the third. - If should be the how the client wants to move the player: instant/on death. - */ - if (iCmdArgs >= 3) - { - - /** - The client gave us a command argument, lets check it. - */ - decl String:sSwapMode[5]; - GetCmdArg(3, sSwapMode, sizeof(sSwapMode)); - new iWantsQue = StringToInt(sSwapMode); - if (iWantsQue) - { - - /** - The client wants to que the player, set the global array. - */ - g_aPlayers[iPlayerIndex][bQueue] = true; - } - else - { - - /** - The client doesn't want to que the player, set the global array. - */ - g_aPlayers[iPlayerIndex][bQueue] = false; - } - } - else - { - /** - No swapmode argument, display the menu - */ - DisplaySwapModeMenu(client, iPlayerIndex); - } - - if (iCmdArgs >= 4) - { - - /** - Since we are compiling for Simple Team Balancer, and given a 4th argument, lets check it. - If should be the if the client wants to force the player to that team. - */ - decl String:sPlayerForced[5]; - GetCmdArg(4, sPlayerForced, sizeof(sPlayerForced)); - new iForceHim = StringToInt(sPlayerForced); - if (iForceHim) - { - - /** - The client wants to force the player - */ - SM_SetForcedTeam(iPlayerIndex, g_aPlayers[iPlayerIndex][iNewTeam]); - } - else - { - - /** - The client doesn't want to force the player - */ - SM_ClearForcedTeam(iPlayerIndex); - } - } - else - { - - } - - /** - We found and processed all the arguments. - */ - if (!IsPlayerAlive(iPlayerIndex)) - { - - /** - The player is not alive or died during this process so we just move him. - */ - SM_MovePlayer(iPlayerIndex, g_aPlayers[iPlayerIndex][iNewTeam]); - } - else - { - if (!g_aPlayers[iPlayerIndex][bQueue]) - { - - /** - The player is alive and is not set to be queued so we just move him. - */ - SM_MovePlayer(iPlayerIndex, g_aPlayers[iPlayerIndex][iNewTeam]); - } - } - - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_ScrambleTeams(client, args) -{ - - /** - Make sure we are enabled, if not bug out. - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the client is authorized to run this command. - */ - decl String:sFlags[5]; - GetConVarString(stm_adminflag_scramble, sFlags, sizeof(sFlags)); - if (!SM_IsValidAdmin(client, sFlags)) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check if a scramble timer was already called, if so close it down. - */ - if (g_hTimerPrepScramble != INVALID_HANDLE) - { - CloseHandle(g_hTimerPrepScramble); - g_hTimerPrepScramble = INVALID_HANDLE; - } - - /** - Check if we have any command arguments. - If we don't we display the scramble menu and bug out. - */ - new iCmdArgs = GetCmdArgs(); - if (iCmdArgs == 0) - { - DisplayScrambleMenu(client); - return Plugin_Handled; - } - - /** - We have a command argument. - It should be whether or not to scramble at round end. - */ - decl String:sRoundEnd[5]; - GetCmdArg(1, sRoundEnd, sizeof(sRoundEnd)); - if (StringToInt(sRoundEnd)) - { - /** - The client wants to scramble at round end so we set the global bool. - */ - g_bScrambleRoundEnd = true; - } - else - { - g_bScrambleRoundEnd = false; - } - - /** - Check for another command argument. - It should be whether or not to restart the round. - */ - decl String:sRestartRound[5]; - new bool:bRestartRound = false; - GetCmdArg(1, sRestartRound, sizeof(sRestartRound)); - if (StringToInt(sRestartRound)) - { - bRestartRound = true; - } - - /** - Now we start the scramble timer. - */ - StartScrambleTimer(_, bRestartRound); - - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_VoteScramble(client, args) -{ - - /** - Make sure we are enabled, if not bug out. - */ - if (!g_bVoteEnabled || !g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Make sure there is a vote in progress, if so bug out. - */ - if (IsVoteInProgress()) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "VoteInProgress", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure enough time has passed since the last vote. - */ - new iVoteTime = RoundFloat(GetEngineTime()); - if (iVoteTime - g_iLastVoteTime <= g_iVoteDelay) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "ScrambleTime", LANG_SERVER); - return Plugin_Handled; - } - - /** - Enough time has passed so reset the global vote time to now. - */ - g_iLastVoteTime = iVoteTime; - - /** - Build the vote menu and send it to everyone. - */ - new Handle:hMenu = CreateMenu(Menu_VoteScramble); - SetMenuTitle(hMenu, "Scramble Teams?"); - AddMenuItem(hMenu, VOTE_YES, "Yes"); - AddMenuItem(hMenu, VOTE_NO, "No"); - SetMenuExitButton(hMenu, false); - VoteMenuToAll(hMenu, 20); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -/* HOOKED EVENTS */ - -public HookPlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Find out who died. - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - - /** - Find out how the client died. - */ - new String:sWeapon[64]; - GetEventString(event, "weapon", sWeapon, sizeof(sWeapon)); - if (StrEqual(sWeapon, "world", false)) - { - - /** - He died because he changed teams so cleanup and bug out. - */ - s_CleanUp(iClient); - return; - } - - /** - Find out if this player was queued to change teams. - */ - if (g_aPlayers[iClient][bQueue]) - { - /** - Looks like he was, so call the stock function to move him. - */ - SM_MovePlayer(iClient, g_aPlayers[iClient][iNewTeam]); - } -} - -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Find out who changed teams. - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - - /** - If he was queued to switch teams we cleanup the variables. The client did it themself. - */ - if (g_aPlayers[iClient][bQueue]) - { - s_CleanUp(iClient); - } -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get the amount of time left in the map. - */ - new iTimeLeft; - GetMapTimeLeft(iTimeLeft); - - /** - Check to see if we are supposed to scramble at the end of the round and that there is enough time left in the map. - */ - if (g_bScrambleRoundEnd && iTimeLeft >= 60) - { - - /** - Check to see if there is a scramble timer in action and if so close it down. - */ - if (g_hTimerPrepScramble != INVALID_HANDLE) - { - CloseHandle(g_hTimerPrepScramble); - g_hTimerPrepScramble = INVALID_HANDLE; - } - - /** - Determine the round end chat time and run the scramble 1 second before it ends. - */ - new Float:fDelay = GetConVarFloat(stm_mp_bonusroundtime); - fDelay -= 1.0; - StartScrambleTimer(fDelay); - } -} - -public OnClientPostAdminCheck(client) -{ - - /** - Determine if the client has the flag to use the swapteam command. - */ - decl String:sFlags[5]; - GetConVarString(stm_adminflag_swapteam, sFlags, sizeof(sFlags)); - if (SM_IsValidAdmin(client, sFlags)) - { - /** - The client does so lets create a timer to run an advertise to tell him about it. - */ - CreateTimer (60.0, Timer_WelcomeAdvert, client); - } -} - -public OnClientDisconnect(client) -{ - - /** - Cleanup the clients variables. - */ - s_CleanUp(client); -} - -public SM_OnPlayerMoved(Handle:plugin, client, team) -{ - - /** - Make sure we called the move function - */ - if (plugin != GetMyHandle()) - { - if (g_bLogActivity) - { - LogAction(0, client, "[STM] Callback was not started with current plugin, bugging out."); - } - return; - } - - decl String:sPlayerName[64]; - GetClientName(client, sPlayerName, sizeof(sPlayerName)); - - PrintToChat(client, "\x01\x04[SM]\x01 %T", "PlayerSwitched", LANG_SERVER); - - s_CleanUp(client); -} - -/* TIMER FUNCTIONS */ - -public Action:Timer_PrepTeamScramble(Handle:timer, any:data) -{ - new bool:bRestartRound = data; - /** - Call the scramble the teams stock function. - */ - PrepTeamScramble(bRestartRound); - - /** - Reset the timer handle so we know the timer is done. - */ - g_hTimerPrepScramble = INVALID_HANDLE; - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Timer_ScrambleTheTeams(Handle:timer, any:data) -{ - new iPlayers[MAXPLAYERS + 1]; - new iCount, i, bool:bTeam, bool:bRestartRound = data; - - /** - Get all the client index numbers of valid players - */ - for(i = 1; i <= MaxClients; i++) - { - if(IsClientInGame(i)) // && !IsFakeClient(i)) - { - iPlayers[iCount++] = i; - } - } - - /** - Randomly sort the players - */ - SortIntegers(iPlayers, iCount, Sort_Random); - - /** - Loop through all the players and assign each one to a team, alternating each time - */ - for(i = 0; i < iCount; i++) - { - if (!bRestartRound) - { - /** - We didn't want to restart the round, so we move them to spec 1 at a time. - */ - SM_MovePlayer(iPlayers[i], g_aCurrentTeams[Spectator]); - } - SM_MovePlayer(iPlayers[i], bTeam ? g_aCurrentTeams[Team2] : g_aCurrentTeams[Team1]); - SM_SetForcedTeam(iPlayers[i], bTeam ? g_aCurrentTeams[Team2] : g_aCurrentTeams[Team1], true); - bTeam = !bTeam; - } - - /** - Reset this variable since we completed a scramble - */ - g_bScrambleRoundEnd = false; - - if (g_hTimerClearScrambleForce != INVALID_HANDLE) - { - CloseHandle(g_hTimerClearScrambleForce); - g_hTimerClearScrambleForce = INVALID_HANDLE; - } - - g_hTimerClearScrambleForce = CreateTimer(300.0, Timer_ClearScrambleForce, _, TIMER_FLAG_NO_MAPCHANGE); - - ServerCommand("mp_timelimit %i", g_iTimeLeft / 60); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Timer_ClearScrambleForce(Handle:timer, any:data) -{ - - for(new i = 1; i <= MaxClients; i++) - { - if(IsClientInGame(i)) // && !IsFakeClient(i)) - { - SM_ClearForcedTeam(i); - PrintToChat(i, "\x01\x04[SM]\x01 Your forced team status has been cleared"); - } - } - - g_hTimerClearScrambleForce = INVALID_HANDLE; - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Timer_WelcomeAdvert(Handle:timer, any:client) -{ - - /** - Lets make sure the client is connected and actually in the game. - */ - if (IsClientConnected(client) && IsClientInGame(client)) - { - - /** - We are good to go so lets tell him about the swapteam command. - */ - PrintToChat (client, "\x01\x04[STM]\x01 %T", "SwapTeamMsg", LANG_SERVER); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -/* STOCK FUNCTIONS */ - -stock s_CleanUp(iClient) -{ - - /** - Reset all the client variables - */ - g_aPlayers[iClient][bQueue] = false; - g_aPlayers[iClient][iNewTeam] = 0; -} - -stock StartScrambleTimer(Float:fdelay = 0.0, bool:bRestartRound = false) -{ - if (fdelay == 0.0) - { - fdelay = g_fScrambleDelay; - } - if (g_hTimerPrepScramble != INVALID_HANDLE) - { - CloseHandle(g_hTimerPrepScramble); - g_hTimerPrepScramble = INVALID_HANDLE; - } - PrintCenterTextAll("%T", "Scramble", LANG_SERVER); - g_hTimerPrepScramble = CreateTimer(fdelay, Timer_PrepTeamScramble, bRestartRound, TIMER_FLAG_NO_MAPCHANGE); -} - -stock PrepTeamScramble(bool:bRestartRound = false) -{ - new iPlayers[MAXPLAYERS + 1]; - new iCount; - - GetMapTimeLeft(g_iTimeLeft); - - if (bRestartRound) - { - - for(new i = 1; i <= MaxClients; i++) - { - if(IsClientInGame(i)) - // && !IsFakeClient(i)) - { - iPlayers[iCount++] = i; - SM_ClearForcedTeam(i); - SM_ClearBuddy(i); - SM_MovePlayer(i, g_aCurrentTeams[Spectator]); - } - } - } - else - { - //Can't move them all to spec at the same time - for(new i = 1; i <= MaxClients; i++) - { - if(IsClientInGame(i)) - // && !IsFakeClient(i)) - { - iPlayers[iCount++] = i; - SM_ClearForcedTeam(i); - SM_ClearBuddy(i); - //SM_MovePlayer(i, g_aCurrentTeams[Spectator]); - } - } - } - CreateTimer(4.0, Timer_ScrambleTheTeams, bRestartRound, TIMER_FLAG_NO_MAPCHANGE); -} - -/* CONSOLE VARIABLE CHANGE EVENT */ - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (convar == stm_enabled) { - if (StringToInt(newValue) == 0) { - g_bIsEnabled = false; - LogAction(0, -1, "[STM] Simple Team Manager is loaded and disabled."); - } else { - g_bIsEnabled = true; - LogAction(0, -1, "[STM] Simple Team Manager is loaded and enabled."); - } - } - else if (convar == stm_logactivity) { - if (StringToInt(newValue) == 0) { - g_bLogActivity = false; - LogAction(0, -1, "[STM] Log Activity DISABLED."); - } else { - g_bLogActivity = true; - LogAction(0, -1, "[STM] Log Activity ENABLED."); - } - } - else if (convar == stm_scrambledelay) - g_fScrambleDelay = StringToFloat(newValue); - else if (convar == stm_votewin) - g_fVoteWin = StringToFloat(newValue); - else if (convar == stm_votedelay) - g_iVoteDelay = StringToInt(newValue); - else if (convar == stm_voteenabled) { - if (StringToInt(newValue) == 0) - g_bVoteEnabled = false; - else - g_bVoteEnabled = true; - } -} - -/* MENU CODE */ - -public OnAdminMenuReady(Handle:topmenu) -{ - if (topmenu == g_hAdminMenu) - return; - g_hAdminMenu = topmenu; - new TopMenuObject:player_commands = FindTopMenuCategory(g_hAdminMenu, ADMINMENU_PLAYERCOMMANDS); - new TopMenuObject:server_commands = FindTopMenuCategory(g_hAdminMenu, ADMINMENU_SERVERCOMMANDS); - if (player_commands == INVALID_TOPMENUOBJECT) - return; - - AddToTopMenu(g_hAdminMenu, - "moveplayer", - TopMenuObject_Item, - AdminMenu_MovePlayer, - player_commands, - "moveplayer", - ADMFLAG_BAN); - - AddToTopMenu(g_hAdminMenu, - "scrambleteams", - TopMenuObject_Item, - AdminMenu_Scrambleteams, - server_commands, - "scrambleteams", - ADMFLAG_BAN); -} - -public AdminMenu_MovePlayer(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) -{ - if (action == TopMenuAction_DisplayOption) - Format(buffer, maxlength, "Move Player"); - else if (action == TopMenuAction_SelectOption){ - DisplayPlayerMenu(param); - } -} - -public AdminMenu_Scrambleteams(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) -{ - if (action == TopMenuAction_DisplayOption) - Format(buffer, maxlength, "Scramble Teams"); - else if (action == TopMenuAction_SelectOption) { - DisplayScrambleMenu(param); - } -} - -public Menu_SelectPlayer(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - DisplayTeamMenu(param1, GetClientOfUserId(StringToInt(sSelection))); - } else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -public Menu_SelectTeam(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new iTeam; - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - decl String:sIndex[64]; - if (SplitString(sSelection, "A", sIndex, sizeof(sIndex)) != -1) - iTeam = g_aCurrentTeams[Team1]; - else if (SplitString(sSelection, "B", sIndex, sizeof(sIndex)) != -1) - iTeam = g_aCurrentTeams[Team2]; - else { - SplitString(sSelection, "C", sIndex, sizeof(sIndex)); - iTeam = g_aCurrentTeams[Spectator]; - } - new iTarget = StringToInt(sIndex); - g_aPlayers[iTarget][iNewTeam] = iTeam; - DisplaySwapModeMenu(param1, iTarget); - } else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -public Menu_SwapMode(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - decl String:sIndex[64]; - - if (SplitString(sSelection, "A", sIndex, sizeof(sIndex)) == -1) - { - SplitString(sSelection, "B", sIndex, sizeof(sIndex)); - } - - new iTarget = StringToInt(sIndex); - - if (StrContains(sSelection, "A", true) != -1) - { - g_aPlayers[iTarget][bQueue] = false; - } - else if (StrContains(sSelection, "B", true) != -1) - { - g_aPlayers[iTarget][bQueue] = true; - } - - if (param1 == iTarget && !g_aPlayers[iTarget][bQueue]) - { - SM_MovePlayer(iTarget, g_aPlayers[iTarget][iNewTeam]); - } - else - { - DisplayForceModeMenu(param1, iTarget); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - { - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } - return; -} - -public Menu_ForceMode(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - decl String:sIndex[64]; - if (SplitString(sSelection, "A", sIndex, sizeof(sIndex)) == -1) - { - SplitString(sSelection, "B", sIndex, sizeof(sIndex)); - } - new iTarget = StringToInt(sIndex); - if (StrContains(sSelection, "A", true) != -1) - { - SM_ClearForcedTeam(iTarget); - } - else if (StrContains(sSelection, "B", true) != -1) - { - SM_SetForcedTeam(iTarget, g_aPlayers[iTarget][iNewTeam], true); - } - if (!g_aPlayers[iTarget][bQueue]) - { - SM_MovePlayer(iTarget, g_aPlayers[iTarget][iNewTeam]); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - { - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } - return; -} - -public Menu_VoteScramble(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_VoteEnd) { - new winning_votes, total_votes; - GetMenuVoteInfo(param2, winning_votes, total_votes); - if (param1 == 0) { - if (float(total_votes) / float(winning_votes) < g_fVoteWin) { - PrintToChatAll("\x01\x04[SM]\x01 %T", "VoteScramble2", LANG_SERVER, winning_votes, total_votes); - return; - } - PrintCenterTextAll("[SM] %T", "Scramble", LANG_SERVER); - PrintToChatAll("\x01\x04[SM]\x01 %T", "VoteScramble1", LANG_SERVER, winning_votes, total_votes); - StartScrambleTimer(); - } - if (param1 == 1) { - PrintToChatAll("\x01\x04[SM]\x01 %T", "VoteScramble2", LANG_SERVER, winning_votes, total_votes); - } - } - if (action == MenuAction_End) - CloseHandle(menu); -} - -public Menu_ScrambleTeams(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "NOW", false)) - g_bScrambleRoundEnd = false; - else - g_bScrambleRoundEnd = true; - DisplayScrambleMenu2(param1); - } else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -public Menu_ScrambleTeams2(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[64]; - new bool:bRestartRound; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "NO", false)) - { - bRestartRound = false; - } - else - { - bRestartRound = true; - } - StartScrambleTimer(_, bRestartRound); - } else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -stock DisplayScrambleMenu(iClient) -{ - new Handle:hMenu = CreateMenu(Menu_ScrambleTeams); - SetMenuTitle(hMenu, "Select When to Scramble:"); - AddMenuItem(hMenu, "NOW", "Instantly"); - AddMenuItem(hMenu, "END", "At Round End"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplayScrambleMenu2(iClient) -{ - new Handle:hMenu = CreateMenu(Menu_ScrambleTeams2); - SetMenuTitle(hMenu, "Select When to Scramble:"); - AddMenuItem(hMenu, "NO", "No Round Restart"); - AddMenuItem(hMenu, "YES", "Restart Round"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplaySwapModeMenu(iClient, iTarget) -{ - new Handle:hMenu = CreateMenu(Menu_SwapMode); - decl String:optionA[64]; - decl String:optionB[64]; - Format(optionA, sizeof(optionA), "%iA", iTarget); - Format(optionB, sizeof(optionB), "%iB", iTarget); - SetMenuTitle(hMenu, "Select When to Swap:"); - AddMenuItem(hMenu, optionA, "Instantly (Kills)"); - if (!IsClientObserver(iTarget)) - AddMenuItem(hMenu, optionB, "Queue on next death"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplayForceModeMenu(iClient, iTarget) -{ - new Handle:hMenu = CreateMenu(Menu_ForceMode); - decl String:optionA[64]; - decl String:optionB[64]; - Format(optionA, sizeof(optionA), "%iA", iTarget); - Format(optionB, sizeof(optionB), "%iB", iTarget); - SetMenuTitle(hMenu, "Select Force Mode:"); - AddMenuItem(hMenu, optionA, "UnForced"); - AddMenuItem(hMenu, optionB, "Forced"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplayTeamMenu(iClient, iTarget) -{ - new Handle:hMenu = CreateMenu(Menu_SelectTeam); - decl String:optionA[64]; - decl String:optionB[64]; - decl String:optionC[64]; - Format(optionA, sizeof(optionA), "%iA", iTarget); - Format(optionB, sizeof(optionB), "%iB", iTarget); - Format(optionC, sizeof(optionC), "%iC", iTarget); - SetMenuTitle(hMenu, "Select Team:"); - AddMenuItem(hMenu, optionA, "Team One"); - AddMenuItem(hMenu, optionB, "Team Two"); - AddMenuItem(hMenu, optionC, "Spectator"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplayPlayerMenu(iClient) -{ - new Handle:hMenu = CreateMenu(Menu_SelectPlayer); - AddTargetsToMenu(hMenu, 0, true, false); - SetMenuTitle(hMenu, "Select A Player:"); - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} diff --git a/Simple Message Suppression/addons/sourcemod/translations/simpledonatorbenefits.phrases.txt b/Simple Message Suppression/addons/sourcemod/translations/simpledonatorbenefits.phrases.txt deleted file mode 100644 index 3826846..0000000 --- a/Simple Message Suppression/addons/sourcemod/translations/simpledonatorbenefits.phrases.txt +++ /dev/null @@ -1,62 +0,0 @@ -"Phrases" -{ - "PlayerLevelCmd" - { - "en" "Command must be run at the player level" - "fr" "Cette commande doit être tapée en jeu" - "hu" "Ezt a parancsot jatekosi szinten kell futtatni!" - } - "RestrictedCmd" - { - "en" "You must be a donator or admin to run this command" - "fr" "Vous devez être un donateur ou un admin pour lancer cette commande" - "hu" "A parancs futtatasahoz admin, vagy tamogatoi szint szukseges!" - } - "InValidTeam" - { - "en" "You must be on red or blue to swap teams" - "fr" "Vous devez être RED ou BLU pour changer d'équipe" - "hu" "Jatekban kell lenned, hogy megcsereld a csapatokat!" - } - "PlayerQueue" - { - "en" "You have been queued to swap teams on next death" - "fr" "Vous avez été mis en attente pour changer d'équipe lors de votre prochaine mort" - "hu" "A kovetkezo halalnal csapatcsere lesz" - } - "PlayerSwitched" - { - "en" "Your team has been switched as requested" - "fr" "Vous avez changé d'équipe comme demandé" - "hu" "A keresnek eleget teve a csapatod meg lett csererlve" - } - "SwapTeamMsg" - { - "en" "Type /swapteam or !swapteam to swap your team!" - } - "ReachedCount" - { - "en" "You have reached your health limit. You must die before you can use it again" - } - "AtMaxHealth" - { - "en" "You are already at your maximum health!" - } - "ToMaxHealth" - { - "en" "Instant health bonus applied! You are not at your maximun health!" - } - "HealthBonus" - { - "en" "Instant health bonus applied!" - } - "PublicJoinMessage" - { - "#format" "{1:s}" - "en" "{1} a [donator] as joined the server" - } - "PrivateJoinMessage" - { - "en" "Thanks for donating!" - } -} \ No newline at end of file diff --git a/Simple Message Suppression/addons/sourcemod/translations/simplespectate.phrases.txt b/Simple Message Suppression/addons/sourcemod/translations/simplespectate.phrases.txt deleted file mode 100644 index 2d1a096..0000000 --- a/Simple Message Suppression/addons/sourcemod/translations/simplespectate.phrases.txt +++ /dev/null @@ -1,42 +0,0 @@ -"Phrases" -{ - "Stopped spectating" - { - "#format" "{1:s}" - "en" "Stopped tracking player: {1}" - } - "Yourself" - { - "en" "You can't spectate yourself" - } - "Spectator" - { - "en" "You can't spectate another spectator" - } - "Spectating" - { - "#format" "{1:s}" - "en" "Now spectating {1}. Type !stopspec or /stopspec to stop spectating this player" - } - "Invalid Target" - { - "en" "Invalid target" - } - "Cant Target" - { - "en" "Can't target this player" - } - "Must Have Target" - { - "en" "You must be following/tracking a player to punish" - } - "Target Left" - { - "en" "The player you were following/tracking has left" - } - "Punished" - { - "#format" "{1:s}{2:s}{3:s}" - "en" "{1} was punished with a {2} for {3}" - } -} \ No newline at end of file diff --git a/Simple Message Suppression/addons/sourcemod/translations/simpleteambalancer.phrases.txt b/Simple Message Suppression/addons/sourcemod/translations/simpleteambalancer.phrases.txt deleted file mode 100644 index 03595fd..0000000 --- a/Simple Message Suppression/addons/sourcemod/translations/simpleteambalancer.phrases.txt +++ /dev/null @@ -1,130 +0,0 @@ -"Phrases" -{ - "UnBalanced" - { - "en" "Teams are unbalanced and will be balanced shortly" - "fr" "Les équipes ne sont pas équilibrées et le seront bientôt" - "de" "Die Teams sind ungleich und werden in Kürze ausgeglichen" - "hu" "A csapatok nem kiegyenlitettek! Egyensuly beallitas kovetkezik!" - } - "Enabled" - { - "en" "Simple Team Balancer is ENABLED" - "fr" "Simple Team Balancer est ACTIVE" - "de" "Simple Team Balancer ist AKTIV" - "hu" "Az Egyszeru Csapat Egyensulytarto AKTIV!" - } - "Disabled" - { - "en" "Simple Team Balancer is DISABLED" - "fr" "Simple Team Balancer est DESACTIVE" - "de" "Simple Team Balancer ist INAKTIV" - "hu" "Az Egyszeru Csapat Egyensulytarto INAKTIV!" - } - "PlayerMessage" - { - "#format" "{1:i}" - "en" "You are going to be auto balanced in {1} seconds unless a dead player can be found" - "fr" "Vous passerez dans l'autre équipe dans {1} secondes si aucun joueur mort ne peut être trouvé dans cet intervalle" - "de" "Du wirst in {1} Sekunden zum automatischen Ausgleich herangezogen wenn kein toter Spieler gefunden werden kann" - "hu" "{1} masodpercen belul at leszel helyezve a masik csapatba, hacsak nem lesz addig egy halott jatekos!" - } - "BalanceMessage" - { - "#format" "{1:s}" - "en" "{1} was moved to the other team for game balance" - "fr" "{1} est passé dans l'autre équipe pour équilibrer la partie" - "de" "{1} wurde zum anderen Team verschoben um das Spiel auszugleichen" - "hu" "{1} at lett helyezve az egyensuly megtartasa erdekeben." - } - "PlayerLevelCmd" - { - "en" "Command must be run at the player level" - "fr" "La commande doit être lancée au niveau du joueur" - "de" "Das Kommando muss auf Spieler Ebene ausgeführt werden" - "hu" "Jatekosi szinten kell futtatni ezt a parancsot!" - } - "CmdDisabled" - { - "en" "Command is currently disabled" - "fr" "La commande est actuellement désactivée" - "de" "Das Kommando ist momentan inaktiv" - "hu" "A parancs jelenleg inaktiv" - } - "RestrictedBuddy" - { - "en" "You must be a donator or admin to add a balance buddy" - "fr" "Vous devez être un donateur ou un admin pour choisir un partenaire" - "de" "Du musst ein Spender oder Admin sein um einen Partner wählen zu können" - "hu" "Tamogato vagy admin kell hogy legyel, hogy 'Tarsat' jelolhess meg" - } - "SelectSelf" - { - "en" "You cannot be your own buddy" - "fr" "Vous ne pouvez pas être votre propre partenaire" - "de" "Du kannst nicht dein eigener Partner sein" - "hu" "Nem valaszthatod ki onmagad!" - } - "BuddyGone" - { - "en" "Your selected buddy has disconnected" - "fr" "Le partenaire que vous avez sélectionné s'est déconnecté" - "de" "Dein gewählter Partner hat die Verbindung getrennt" - "hu" "A valasztott 'Tarsad' kilepett" - } - "BuddyMsg" - { - "#format" "{1:s}" - "en" "You and {1} are now buddies" - "fr" "Vous et {1} êtes maintenant partenaires" - "de" "Du und {1} seid jetzt Partner" - "hu" "{1} es Te 'Tarsak' vagytok." - } - "BuddyLockMsgDisabled" - { - "en" "You can now be anyone's buddy" - "fr" "Vous pouvez à présent être le partenaire de n'importe qui" - "de" "Du kannst jetzt jedermanns Partner sein" - "hu" "Barkinek lehetsz a 'Tarsa'." - } - "BuddyLockMsgEnabled" - { - "en" "Buddy selection locked. Only you can change your buddy" - "fr" "Sélection de partenaire bloquée. Vous êtes le seul à pouvoir choisir votre partenaire" - "de" "Wahl des Partners gesperrt. Nur du kannst deinen Partner wechseln" - "hu" "Tars-lista lezarva. Csak Te tudod modositani a Tars-listadat." - } - "PlayerLockedBuddyMsg" - { - "#format" "{1:s}" - "en" "{1} has locked his buddy selection. Try again" - "fr" "{1} a bloqué sa sélection de partenaire. Essayez de nouveau." - "de" "{1} hat seine Wahl des Partners gesperrt. Versuche es erneut" - "hu" "{1} lezarta a Tars-listajat. Probald kesobb!" - } - "BuddyWelcomeMsg1" - { - "en" "Select a balance buddy and stay together during an autobalance!" - "fr" "Choisissez un partenaire et restez ensemble durant l'équilibrage automatique!" - "de" "Wähle einen Partner und bleibt zusammen während eines Ausgleichs" - "hu" "Valasz ki egy 'Tarsat' akivel egyuttmaradhatsz a csapatkiegyenlites alatt!" - } - "BuddyWelcomeMsg2" - { - "en" "/buddy or !buddy to select a balance buddy" - "fr" "/buddy or !buddy pour choisir un partenaire" - "de" "/buddy oder !buddy um einen Partner zu wählen" - "hu" "Hasznald a /buddy vagy !buddy parancsokat a 'Tars' kijelolesehez" - } - "BuddyWelcomeMsg3" - { - "en" "/lockbuddy or !lockbuddy to lock your selection" - "fr" "/lockbuddy or !lockbuddy pour bloquer votre sélection" - "de" "/lockbuddy oder !lockbuddy um deine Auswahl zu sperren" - "hu" "Hasznald a /lockbuddy vagy a !lockbuddy parancsokat a Tars-listad lezarasahoz" - } -} - - - - diff --git a/Simple Message Suppression/addons/sourcemod/translations/simpleteammanager.phrases.txt b/Simple Message Suppression/addons/sourcemod/translations/simpleteammanager.phrases.txt deleted file mode 100644 index f2093a7..0000000 --- a/Simple Message Suppression/addons/sourcemod/translations/simpleteammanager.phrases.txt +++ /dev/null @@ -1,92 +0,0 @@ -"Phrases" -{ - "PlayerLevelCmd" - { - "en" "Command must be run at the player level" - "fr" "Cette commande doit être tapée en jeu" - "hu" "Ezt a parancsot jatekosi szinten kell futtatni!" - } - "RestrictedCmd" - { - "en" "You must be a donator or admin to run this command" - "fr" "Vous devez être un donateur ou un admin pour lancer cette commande" - "hu" "A parancs futtatasahoz admin, vagy tamogatoi szint szukseges!" - } - "InValidTeam" - { - "en" "You must be on red or blue to swap teams" - "fr" "Vous devez être RED ou BLU pour changer d'équipe" - "hu" "Jatekban kell lenned, hogy megcsereld a csapatokat!" - } - "PlayerInValidTeam" - { - "en" "Player must be on red or blue to swap teams" - "fr" "Le joueur doit être RED ou BLU pour changer d'équipe" - "hu" "Valamelyik csapatban kell lenni, hogy csere legyen" - } - "PlayerQueue" - { - "en" "You have been queued to swap teams on next death" - "fr" "Vous avez été mis en attente pour changer d'équipe lors de votre prochaine mort" - "hu" "A kovetkezo halalnal csapatcsere lesz" - } - "PlayerSwitched" - { - "en" "Your team has been switched" - } - "PlayerSwitched1" - { - "en" "Your team has been switched as requested" - "fr" "Vous avez changé d'équipe comme demandé" - "hu" "A keresnek eleget teve a csapatod meg lett csererlve" - } - "PlayerSwitched2" - { - "en" "Your team has been switched by an Admin" - "fr" "Vous avez été changé d'équipe par un admin" - "hu" "Az Admin megcserelte a csapatodat!" - } - "SwapTeamMsg" - { - "en" "Type /swapteam or !swapteam to swap your team!" - } - "PlayerSwitched3" - { - "#format" "{1:s}" - "en" "{1}'s team has been switched" - "fr" "{1} a changé d'équipe" - "hu" "{1} csapata meg lett cserelve" - } - "Scramble" - { - "en" "Teams are about to be scrambled!" - "fr" "Les équipes vont être rééquilibrés" - "hu" "A csapatok hamarosan meg lesznek keverve!" - } - "VoteScramble1" - { - "#format" "{1:i}{2:i}" - "en" "Vote Scramble successful with {1} votes out of {2}" - "fr" "Le vote d'équilibrage des équipes a réussi avec {1} votes pour sur {2}" - "hu" "A szavazas sikeres volt, {1} szavazat a keveresre a {2} -bol" - } - "VoteScramble2" - { - "#format" "{1:i}{2:i}" - "en" "Vote Scramble failed with {1} votes out of {2}" - "fr" "Le vote d'équilibrage a échoué avec {1} votes pour sur {2}" - "hu" "A szavazas sikertelen volt, {1} szavazat a keveresre a {2} -bol" - } - "VoteInProgress" - { - "en" "A vote is currently in progress" - "fr" "Un vote est actuellement en cours" - "hu" "Egy szavazas mar fut!" - } - "ScrambleTime" - { - "en" "A vote was recently made, please wait" - "fr" "Un vote a déjà été fait récemment, réessayez plus tard" - "hu" "Nemreg volt szavazas, kerlek varj egy kicsit!" - } -} \ No newline at end of file diff --git a/Simple Plugins Core/addons/sourcemod/configs/simple-alltalkmanager_events.cfg b/Simple Plugins Core/addons/sourcemod/configs/simple-alltalkmanager_events.cfg deleted file mode 100644 index b739cf0..0000000 --- a/Simple Plugins Core/addons/sourcemod/configs/simple-alltalkmanager_events.cfg +++ /dev/null @@ -1,43 +0,0 @@ -"game_events" -{ - "teamplay_round_start" - { - "reason" "Round Start" - "setting" "1" - } - "teamplay_setup_finished" - { - "reason" "Setup Period Ended" - "setting" "0" - } - "teamplay_overtime_begin" - { - "reason" "Overtime Began" - "setting" "1" - } - "teamplay_overtime_end" - { - "reason" "Overtime Ended" - "setting" "1" - } - "teamplay_round_win" - { - "reason" "Round Ended" - "setting" "1" - } - "teamplay_suddendeath_begin" - { - "reason" "Sudden Death Began" - "setting" "1" - } - "teamplay_suddendeath_end" - { - "reason" "Sudden Death Ended" - "setting" "1" - } - "teamplay_round_stalemate" - { - "reason" "Stalemate" - "setting" "1" - } -} \ No newline at end of file diff --git a/Simple Plugins Core/addons/sourcemod/configs/simple-chatcolors.cfg b/Simple Plugins Core/addons/sourcemod/configs/simple-chatcolors.cfg deleted file mode 100644 index 14b98c6..0000000 --- a/Simple Plugins Core/addons/sourcemod/configs/simple-chatcolors.cfg +++ /dev/null @@ -1,15 +0,0 @@ -"admin_colors" -{ - "groupname2" - { - "flag" "z" - "namecolor" "{green}" - "textcolor" "{olive}" - } - "groupname1" - { - "flag" "a" - "namecolor" "{teamcolor}" - "textcolor" "{green}" - } -} \ No newline at end of file diff --git a/Simple Plugins Core/addons/sourcemod/plugins/simple-alltalkmanager.smx b/Simple Plugins Core/addons/sourcemod/plugins/simple-alltalkmanager.smx deleted file mode 100644 index 6122756af68998fb531abcd0d08698e24cff25af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7028 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 diff --git a/Simple Plugins Core/addons/sourcemod/plugins/simple-donatorbenefits.smx b/Simple Plugins Core/addons/sourcemod/plugins/simple-donatorbenefits.smx deleted file mode 100644 index 821d61d784607595ca400d273a941a42e40de640..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16600 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 diff --git a/Simple Plugins Core/addons/sourcemod/plugins/simple-messagesuppression.smx b/Simple Plugins Core/addons/sourcemod/plugins/simple-messagesuppression.smx deleted file mode 100644 index cc20dadd37d8ff23d0a64513cc09650f4bdbf24d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4845 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 Ee?(+yN&o-= delta 9546 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 diff --git a/Simple Plugins Core/addons/sourcemod/plugins/simple-spectate.smx b/Simple Plugins Core/addons/sourcemod/plugins/simple-spectate.smx deleted file mode 100644 index c6885b041145a73f664650e729a5dcf8b3b0813f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19129 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%0ACwUfid=y*oPG;MRqmWr)g0 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�XP zM5L)&uZne^XHs;_L+03=Xy3CiU1O76^S{TWu{zY}Jlq((BV?9EL=m4MC%~!W0MzeW zOjQv*a;A7AS@l%h9EbjzQ3d}e&j~R0VCoAN)q_>=)m=>e=ZX9w8jM3&o1RO^+0jJ) z

_|h)w;)ME+|h#gx@oo-|ZEuRI5d) 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 z zz<>ukh-T0O%6a(J73SKH$i0Iz_(zd>wTqk)sb2R;cfi*BfN$IWoiHas4P5=%s`Dr0 zzvwSL(+FkDP<{Leh%}FzA5w@p7P1(m@r|D0-!S!O(YCNw)Gj6b!tXxp4;2Gt$7AePM=p zw4`4K5dg)Eus%;R4V8^S8z3TJ5B;JeVVHIpU4vsM(~Fs~L&*c<-~7k3-vnW+e&qk~ zIuJi$qG=4XvI2zC!K#gQULMKYu0N{gn>-cJyV1ljVUs&NIIkPW)NORYH9l|~323a!?Y#i!$%MFK0;FrXEbCA73jh2Q+@Ua;IJCz5rhEM94jgcrGse=X&mEv zMF+(k9`b#=J}~6uRJd0VV2>tg+E*Lshu48oIl@9h9#F&F)|xbItq9KkjNYC7z|u=Q zDJMjq_t4?ekYI^?jJK}SSF3(UC*I3aB{X60jO)uU5bB8DeIcymLDOrC-aP;%?OVPE zj2i)fg{H({UQBbckT+v7+q&DS+a~B!C4r}6$>D%-%t``ePy{7j2zQm{%)7f#WL&%u zsekyeV6ZH>pAn|Bp{N2~?A81QBd(9C!%l$S{KWylzXj1jMF5#-FDB^SS9gpYzh^q` z#x8>`+Xu7!sSBGmet?-XN^qQdM(+a0<8vzfGh6g|6Zt{L= zdQkr(=%DaH=VDyZsOufB_1Ll9q6TnEhVfuJO9Y@`sY)22`QcS{WNN}WncDDu(EK8B zdRd@6!ywYYOv0x`k^ubev3OI9I?2=)X(`le@C6s}Cj{m-e~M=A zuw7j6VRCzGdv7^8Um*bSgnmH>bpw>5Q_BSaXl@|clElei!0d1`POs*d%cnq%FPYIV zuj65S=Idof%LhYFRV?I0@IsQdSpgRB1Cn2FBoi%+YTN~vbV#VKPXSB`rH876uMt2Y zA%Jav^n3;=XoPz*iyO}c<2q%58X$$RWtE>}N(-fbotA6D8G0z+jLA^tr{N5UM!Pk{c(i5TNj`@*xw1y|c$%=qf zvR@w!UuY&8@L^y+3=}mzgf6L&tv5EU@zpy zHWz>fa?Oqb`uI?@uUi}7xeY?oFp&>b4EqFW*dRof()56{Ns?hYzf4<+;FhLqC*fYL z`w;fJf3W~;A%+5^dK`@bB+1+WDF(x5JnpOBlV`jA$ZhV|XbV+ML+#c6$_!-(Z;h3D zyoRl%=})WSm-f!52G1_~)XYASmCCjFxf(MxmI+5h$o>RX1IMNSLbMBd;izqG!18PO z^!;w*uT(X3d2xpOB8=DP4J0?_%*us&-@66fu_`>ee(!z?=ngeqs7d7sKTr0eW^a|V(j_kcaPs813qVI^-ViM zFlm>-v#e~pd@uYF+*uY5xWui~U+c!KBQoKb$fpk=eK6L%&PFgvewO=EJr#y=+m^rV z5`#vKS?9YF&Jf@r0lJD7FyJ^y!WYN4OsE1WhEeaNn;Ggq8w>=0UADF)yA>Ir4-oBH zQm+S#Ovkya(VrE z=%*&Qd!`1>T>1s=h1v)GMQH7S>4ZirAGucMMF>(MP{scu(nBmEVc5v@?_mB+L8~gP zW$bo4!ppoF3uA(iAcw`k%GaeNSBOOd$y?2uCi7hg(~{!9jRPl0Gw=8%>%4n?os0yV zznk>Af=m=j!ap;H4$ktS?CVNrF% ztOqJKkJ#c*sCT)e(}eG8yhN|B%~EMvF44%_%pysp((T-aUvx^09Q$9A>J;V6CreiE zd+}^M6`p_ew9Kt{Uwsai}m!5NKdN0$eBlV-Q0U}a1Z_ZFsV}3?I$C0&^Cs#+ld2;4+DUN=Q+@D}~W7^H2 ztLyTt;5=Sw@O+(uwtBQPWWK7TYU5Gs}{< z*%-mKS=mY0IaU$9d8(Es6Lq3~iKG2di&tHYegkUMNscRilSMwmV~JHXTM`<_!xbFe z-4yoAd1IPNP+`XLdBLkmLrbaGoGA%l1GYy~&)(kIZ|}^*`v*_IjjUg@2RD;y=L^Ec zV%)B_9M&O$xpR5*$nHviOopI`!U9(_^(3~e8}9utD;$hePYIr0xsFM6p0N<2y*4W2 zYWx+?y>@Z7!Ei0ayCDc=pHpGara=B}`_{rq4;Sfl_jAe1+q+*7Q|D---5xjU=~~*W za4@1vP)A6c3QTbv#qU0VTEvYQ&SQ*xcfOZJ^U$4Kk2bQVt5e57Mu?ShxLnXwO zV?x_4n>&u4DG=?G6olrPv`(E+_#Q^XO!Fl)0BI}kaJI87kkT%z$Jb#Lrw>PC`;CO; zY$QTLq+o6C&m@P1xGwqo;5}qn>O-Q=awx8b^f?tF^iCK)>_D}0uet5nCP0pQN5cem zcjm`ABVh(BZIVyFdFn(Lzc_-ox#OIrqvu9jO<{iFtlh0f0g?0HpytFvPPrtqh65avAaOsE-zlLkag?6Y+ z9Zo!u)@d3*U}clJjEGNIcYTA(iu*E)XNu^5P{oAlIF?hFp)N#j6&k#n46+ta>ebjz z7B#yslkRusJz?GP*E>Q_QkLN+gXHV(C-#=i>ic0M?svQedd$26-K(026!{~pPm`Mn zE7*it*;@+-Jwr@a50upF6(LCA9M$fDDr+P- zmS|{7$k?izKl!w)Z>4FlZx{AaixO!NE}PN^Wb$%_2v`u^O{XBihc6iWl0XAu*UsO* z4H=y?;Pk>ZN9*o2cFhYGGWHTvSIB$G_h#maTkHuyZ>`Tu>#~%i#q~nE2AryEv%fx# zN~qQp|780E%_D+HCUY5~GL;)7_?!(hm$ydwoE^PdMLuWCOy&N0K4(BJ zUZWKYO&#|i$A;6kx4$!!sHBWKe-+!fXIGi~&eeOPndGG#2k>@tISjWD_!$%5F{VB& z=KaK`$eFk#{A;q;G8)phk`%gO8@4r4X9dce;6_@l7nasZjS5Yw!!}x>(KsYj@;h6x z4O<;f;;cRt$~{}5sPyEdUh7Z62J)1yeJ2qeaP(0x=@^=G8lk2!7!*eF<0T*LDlAyl znG6oQ<25v!Z25P-qFDLBkxfNW`#Jd5?`*vC0fk@e?%1it+kKe2>eKM3YlF!o^XA#g zw4OI+tIf22BX+2mUsX1+~~hd8uE5JX+u2fJbI-b zsJ>%RNXaW0wRP8EbFXeC@hF&!|D9WbxWl4TeLbLYqv66?b*6jjT-kRkyC(!zDHKF^ z?0{OsxVvff61*a@+y5-ua--YY(2CWco6keKiVtLZzlT% z9Sz#RbGp_JUse|e9K_@#32NW=&Ah?r^RCvPYZT`RSi^iF>UBcd7s`Wj6$+rX6A3)! z+Mz@(FDTh6qV=P?=U{f2R4%rrn0unC3+Rc+>$vjUut-hXeGhA`3s*J8Q3F4pDSPDD zrwm_wGq7_CKzr`&&#?rApQMsydjM>?oIx5VE3ORroe~=ANSEgu-pNf26y>h(AK)et zDgDb_G3425cDU|2xDhulB0IB5&Mk}RuSAd$#_r)SKiB;87q`TuvLR>ldVA2OEnTCyJflXnzS*Cn z@9d`Kwif-Fg345_ki26jZ23Q>QXk=s+^6HYW9;**2KU9?&u?G%`CM0GdS85NK}A1` zxc`uy-ajiRkf9qY`mMwK@fNWWW1qGviU-~nu4W)|D9>Ue|1csZ*-O1LZ{BeGf|dGN zjKl3Sa#^#yzu^$_L{L-KyYIF|B4(`0IAU*fFvs2=H;H~f$ocygvC8waDF^a>>V&y2xT{YAn*?R2bpXm2zt79g9s46j(iF!E3cZ#gaLUgI?^L;fH+Mk2ubCe z$X$|$SVC9_?-H*h5YOA>Pn)#`5wCABW4PE|5Pn;-Z7>M@kh;YU3kb`H`xI;?@k@&< z=)KgC;2|MA8kcUuNP{|n)F#n-ldI7Bn2KwrY3)Pj*z_NWYC%bQH&#Fnu1nCN2zv|HpIA0T%}KFounObUzFwsC;HM%b~h6fN_Lgdps|iY z8pcFZqRpnI-i$E=jviB_$_d0o@Pff!M2{GTf6^LA!F0KA;U>xh3h_TC^^hzc*{PGN zNUH+Ue-Cfro<>-=wtmi+{g1Il+OCK#kM;M<0#uy!=~kO#+#zsz%OYleWazZnSHz5% z-odB4N(dz!`%QDYw<4N=m z+3DEh+P)Ie?L3vBkuLv`ok3QW%6BU|%=ajUU=608!F<^za5OZ(NG6%O|GwFx(^*=} z;10uXp-j9Ap{(RmJoJi*bwe-Mh@6-p2;;S|<0=!Qu0tztyPY}u(#wBkB)wdj+{TX# zFzdDuk^c#UbgR-?yst{Hv+T8J8?3X`ShnrDT;_?|wst0!Ew{fo`*zxVn>gbI18L96 zY5A^$C((^0vuQ)bUZ%3eU%H7po+i<#r}?pAnkLCdF=Z7Bwb0oDYA`6XOuS@bSyn+K zNdNz9Xs=kCd&OAb%Wb==kZHbaveZ|=a9W@*qRG{x66mO`n$HsVqTSK zm&V8i63RtcfmYvZwHM9^Cs#w{Yh8q(Cfp0-a|w!a#DX++Oi5pA83rC_mL*f?9V!7Jt~&<;+gC7blGpM z*K91J9uWwL_*n=Dq(%q`2u8?H^}m)#8v+9MlNEI!AU4n;AijMv ztvv(;(Ps|EC(AlOKp1^mf={XVWTwwJswol#;gn;;h z2mvAd$-B`I5SE`-?o*^=ARx3p>uY{;ejWsb8P2DCGE6%J#P?78c}ob4Pxi)wfM76n zFf)f>Ff(>FhG1}XGqJTYb@?A~H+KF6dt+BCck@qhHMaO4*X}>Z%*5jVU-{4ZWo7&S z;`WYN|2N;t{+Gl59qHogY-Rsh&2#O-56LrGGv$MqP?};48VyZArxgEd zW4>=F+dm;yp5O6kI7Gi2L;cg`Sdz@lSkNsfzHd}UM**VfKNx82XT`BFKK}l#AGcO> zRjvzguUcDdpP;E|t&fUgprKjf@A0|x+Xi*BCVguZcn!!s+&$`axm<2L&IP$$b{(fW zuzz!?n|OwLqviZ&I=B-MJ=Ue%&L8#=55Q$d{&+b6vt-NiSfu+Mj5j&jpArx+yW#IT zB(Y5rV~wFX2)5Bk>czXZ-RekP;-nB7chzTOpuv6cl3m8K;O`ux`Nq>#d=0+p7v||qJP;-1ADgwTM(SWJ%tNm4^seC%`+7Oc5sRU)RBK? zmLl&EE}V(pye6;jxpf`5bqxd4M?NWddB=q-Iv}CIU^6pj|B2eUhH{x`0K~RM!`B~* ze~KyF9e9auU!ee@*fZ$swZ$r6=XC@7Fja79&*p9ohx_(Dx(ZMqGulf60~7&x{6Um-67z|R?^mnv%gG|RpDWX z%;mj6vCKHIO$5xCu8+NU>u z_R3FZyG7C;WR^)eW*BQK1q>|Amm8)}<+DulRoUN_md>;GksZTNyl7l75&+(~zLQJ~ zV9l!>S&oD|@5CSX=8XphFu=V7pnBNh{2)CZpV_&u06)hWZINCh8iC;t`_5_05I@g$N2L11>~)pNOMvjS zd$pHVsVI9ZLnUth)WUlj)bJ$fz{>IgV}XUEXw)q(7WX^)rPVNt?zDODqJ4&Z zpDM!B^v4NVn`xY9py*cQzF|?X=BWNCn&8Ehd`r}}1k|mLGy71+jpS`a0ALTF(t}7A zJj=H?^S9ex0zol3=f>j@H9!;LsRK%T?`k?YV1#N**%_{3a63y9Jn`d-q|N0sJ`w!h zM&<+Qd{~rm^W;yO*L400K_zjfx?+#Ms|W#@sS=C%8&a^Q#ONQV-abLDyh zIl2kRKHAn=+f<87fDB5_NU-6eo1h6#1DjDV*CL4lbQby@%+$Jol=F4hfa^Nq=pF(8 z650!=KNVWQh~RGLfK+V$j;zwPJt$`2GDKS|` z|4^xVROC4w%MwBM&ncSPK(Ngk53E~@Ls81Hea5k?T^!BpuYST*(;xHxTZ)Y1Lza&2KJGLhh15gk(af|79-DIhSR3@h{QiL%!APratL&GSt-OuO z2i}orx(`>(kEG0=GsR!l?-uL7Kyn@bup<9%|6NbDM_@0 z>DrTV&7y)5!F7pUrh1DFrFo6+HGgp^?l`JKk)KMjpIWqwV|L?=<*vd3d<*-CFaDvD zO#pmDcUY;@2}7Fc8`Eaugt*GDS=b}#3?9W7K~8E_kG+)Ll&$`Z5s@+<^?D7WWy@am z2``vA?~GyE!JOvv}&|@ zo?(1@@;ylvsX_D;?_nnGdh1U1eEI!?@8hU^#_O$~laT1TJYyW}HW%ALdHBzTYj9Fc z4FOn(p9pNbTCIEq`W45hnbz3t7vHS-XZaLg1*@X}Dgi`iuib*x)ZRrklDf%xJj2

yusGpqQ>6ExBn@EdnBPfZ8~n=Zw)h+;v&k@ieNHd; zaYF|R8xN>hgK8hLh7(zSs|V5sbePJifkH~ReUv>~bPhX9Z+?Z*9Se`)dgS^|_tE)H zLuOq1zH~{B$I;9$rkOVjUQ=j-RN3(UJxT%{n%35C=y)DiL^C=w4tEmziM#YUe;Y6u z_?U5*LuqW5wfAh+S@=2ud}l2-ii%PgXYT#gmzB9sL*#5T`27Q%)#e9|NYN!5Mh8)= z{O}U?e>*(Jrb!dh4*I{GW6cnDF%o9*J9TlroTh*`JaqlR_uYfwZ`;2NeU2s&{d`rO zy~8;?2)pQ2<0_i?VTKy~wEL$#MtQ&93}Z=W;rNK>y4Y84J-keIr~NM0^BeTs2f4V| z+xl+11@D8p+xFwHjB(amIwNj2$)C7}a%c2xrhKI4d`gPrJ=NAxx^lhx`n}plh7#n_ zXArABy7{;Ga1Z(DPPxgJ_pR-HZ4HiiHZyvvDODQvMw3zzwJkGzc*A`tm)Z}m=B9mf z(p+#wffH*$mKTgs;ugxNO0S9h^^5vSM{5R`19y<#uk*)q=W5Sd$?6fc=TMIr#*z*x ziTNZ4Tl|^>TR#41|6e2IZVU#IHfi8s1vm?rX+GWw)aVaV;4A<&IpY6BMg7?A5CglP;XHc_yOo zT!4-<8|K?1_Hze9gay@y+|$H8`MfoZ-2%ha(a@zmH(aUC$Gjon}galjl!1B6HMbYfrP`n z!1LrtJ&PZ2nK4`RcZNhgiVWimL4@;`T_on+8_d~5Gd{)N`M6_q9X)A0R%JK#_DOUXLkAs~F~=H1 zS8t;+vg;vCE>yle2VLFt%9pEz@6OA1*IEM2gNeA$+%v1WS|&MfP_aj=mskg%Qt3b8 zHH>>&#%?o}IO);$HDw{~9rI}8z-5zen5&Bww}D z`9Ymr(H-+?j@PywWvf@8?-y7L7Br=9lySh7w&c+^J=U$P`ZJi{)VOCCd`nw@i*927 zP^x;fA1pxj_jHbdELZH5EFgDJ+pOu`Er~xC_0Zmb8S5CnijG$Tz}=lhyUhBKf+*W_ z8MmLkJ8y;uB+Y!%kN*WXN&DlKH<%HCb}(3SU8e8!^xs`_Z96eQBZL3;50|oWF1!== zJKNTor>h*#w@>U&|8X6!-~EhV;9Sdd*(!aebS0i(U7ueyM~|1JOpO;Lz}J1>8zHrL zoqn|B0^{PnR@<6J5*RG6=IH!tGR&uJ!Xp6ZMFnNrUqEIDIC0bWU9dQ6Il$ zagKFI90B`c+A3+Eyx_C-Z^qe}82PjumJz4YfY$nqA&nitDvsjm_CNeNG&6qorU6|= z%RB~Vf|9Q0*`6JmI`_r+_tp9dgk6WUbl!^A_Zpf9)10mSf1e72x0*0sW;@n}uevc( z@u+yN+_FJV#dR|Y!wu+#H@2y4kGyl~P0l9WWiArajgLHYYh5foJW@4{XFDOJo1$pP zILGJH!jj#lw5-cQ;ppCDZND23AZjruLLe)8VNo;Lz|}kMdpZ(BDnYBTZ+|f@c$Xk|Jl4N z+u^SWTtK)?c*{z>3xf3lmo^`1_}?A+*Sgerk?<&3yJqJE#!c-1bMnID`Lj+KA6I%V z8j5VJ{{Ce5jXN%v->#M*0TavUt)sNc;+bft=ht3&j#p<&%r|Jb9V#8V z-(4SA2_kA*GQxgUOyOB}3$#BxTv(>EQd4GDy_>ShemGSnnH#ly-A?TISXum3mezGo zgwHvOA3=^hj7!a0o!C}w-S4Eh7v&#HpO5;nvi)&@e++wd*}p0-Z{M(M z^Udj^-}ex(`?-7Htk*PcJs}UQuA#Rm&~Gw7^eC|7{xjX)WWGHCbxB|ESJpwpiucs@ ztL=hAtoA6TN!zu|g@QirVV)h%Kd5*D*1yVlwai&se{uuw^-}q#Ve(;+T)WF@rG*mj zjiT{eq1Hg#1rN}+JzURfQHf_!)fw1xmv2Eo}v*(`l;6t!~zQa{qXv@D(zOgg(54(x3WK@`z7<5zhC`r zNn%z4!a;HVCXXl+#qx>W#S-@{^9c8B9p16n;wqz)p{uI>YT0(Ou6uRUx;b3WT>^f{ zy!ptA*_gsqF)%6Tv)rn(|1v4>bVE98L-x?Z6QyLy%1E)T1v83rdT^ZM>a+<#0h8ni zLdlgX^@qlY*H_Vwmg4@(teq{7X6J1d;kJ=msweKRcfJIN-6F;e9~sF$(_Dw{Ytp<$ ztCX~9b}PD8%eXXtZT8WMp%3b7Zr0Padj!7b_5u~|NLes6J$if#GmKnU4EPs~C7Om- zv-cyFNt<3vWAcpk3TxE`3TtEk%*S5?et~oSpup2ZpjqI~TQ!1bP55S2 zsNJZtqR(AvN$|3=qU3EUCB~y?k@z}cgM#9*c1cT|YKbD(Iqc~@-_9QoTfE%zms8nA zML}6FecmDCG=^$@x}zxC)P<#gADI{-6^7a!CWk6cjnzWM7fE+8$34ShXcW=01_;5< zU8NscX(msWBd;S+cXPvGVn$5Km-rFGAgHc7OS0T%FpuciyA%%-SGEkCH%X8ZUAul^ z)_@=$LTHZvtQt`+(RY;la9C2E4Y>XMTrINS3ea;Tg}L?=^3?M+%s(Unc+~%rq-<`M zRNJ6VgOvDwM@X8kUo(ZKWs*p95;%6 zVu+q!3tmi*coGLOk07Cse>Jg<`$o|$sgoEfjJWzk9%)E~S6)n(&AwRl=RIX2Z>*9h z6At0Q_0iMb0+Fq`AvvJ)Ht_H*;ojP_V(@p*j%Yb+zNO=y<8}dOih@Lo_%}6SYlL@( zR4RryOqrhbsxf8BzNw@u<^oouLWS z{>@);3}DN3 ze*cx9A&W1UlV+~H=*NZ1G3VFlKAK?P{o$DV{kRK!Fs|k-xngXdVMzhk`uHL|Mb z>^Ar45FC90!P&NA;ECJjj)zZh*2DyqEK3X&u`x}?MC3?f&*+<{j#$B)t zilNyY8Mh&P44>E|d4m~iJ&j-ZlC13$QuyUBzqK_SlQ zJ8SA~z}B?2COx&se!M;Pd`z~5$Y!aUftHEaEQHwZ9`Zd)^LW@Jf#189Ud6cnRqHeu zJEp4{N!`1b2~iOg6VuD^%VZ{M*)A|tYx8-ynE9|_$Pa45rY>#Zr_&zoo! z{Mnt&94UJ#61}-kluQ$NAKx8yB?$ ze+UT;`;XJuM{!bPX|3^c6K$xB))W%-%wZzGzEUZ^N$zlTr%5TxO#0HqJd(+Bp>R1e za_38Y1q$Zb)cSt)UteqXIhipKg8Y@OxC>!iUKKJIYUIh9g-gwV;iG~)j1OF6OljS+ zOtKrb2it$IpM$sc0b2|act?V-iorc)ov+#J*@ncS!j}!0C`e?YWl}N+LH6EG65soD zXERVJ`YA3}y%lwkhb)Ov5uzV+Gitc23YrFK!waO#6(nGsV}C-@y?)^pDHBqeOiZ|K zec^P_>ME{kv$_#;~!@=#+%4z#@$79t^c~%-r!@9(U z-3*!~%cUsqT3889o2p@d|6avEU~&lQTXMg1&ynADl(XdNkCGtPJiMM1=`S~Y;V*N< z+eXVAfY@Dh$$B)oy0*b=5m%Q&WCL+pai^GdHhJCBut&#;e5kUtR|7R3;4tZ8NB8#&%{T`1U}J{Qb9+w8vR8VS5sF=5MI%eh2YD&8 zo@?A&Z+?JI@t|{>lZ9 zIfy)mDn*($XS_UioiiBzr_fe*E6+^a*TfQc!@UDgY7Yz46-2E7>i)*t?-&DI8=d)M zS~#&r^KK5Q_A}zXey(U&~Icoo!g=Nb7W|mxtse|GWlS(xn0j z6z(B{#Q46Ki2DVGLre0||8~XU8TfP3*ZNF-qG3n_?zAk33eMEEs-EQ>COz^vjtik; zjcr@7Mw6}pSD3#=dt$xxCo?bfHYY32nCb5&a93vexZ^CsJ#ss6ew(zI*`BiCFuKBd zvi8`Nw$aI+spN?1q10;WW$L!9odVW~Vr`mWZ-;k#b{T`eydvzmKrU4zZ_6`uXV*ah zf1#E7)c!J%1iRF29!l0#SMRyGW1v20YS}Or`qqU}ng|BEal8cJ*gQ*j8X&8*1`K89 zKp&52wJ;t%Tx0iTKwE5>V>j6^DK>xSyD;raOdG#Tv+wq~=ippF9s#Mf;ywk7ELG?+ znE9PFi7eGUQ=P+ymXW1DVh`H_EKWS+QGs7H&?^6KSBd)?SRnQ_84R2dx55B%0fv+x zhzIZMQ{&4d&Z@?wcos^dRm3fE8=?oVqeuhYTx}i+yb71B2h+bn9BqV&Anvy91lnR> zdlC=IHjD$EPH?w$P1;pQSLO!#!It1BD|6uRHJz-t)QvX0e%sytrV$3gNgLBj`ZA0-|0gapR=Hi$0;z4TCXR@&~BjwXq z=bCtYb;w999fW+sjbNp3X!;pN&EC#bq0mLp2aNDf0@Db^wj0z#(d0ry9 zN!7hpN?18Y>28r)@VVAX;0nM5f9fkNuwKFn9EyM{nd^pdrT7H=yKVwk)_1UQLaXfJ z+dN6#6)G5MdjzT7Z%@nEv0ib*516})?%ir%X(-JX?C}~xe`}PZm@N%o{TSH=+JVhm zkwp|ZLw~Fd?h>f$!QVJS_kr%q5vaSu-2kF<2ms)GO}2@i74m);>?r50;GVs=DrVPx z&Ap9$o7-U(a2hTL;R-mt=Yx0!>PA-H3FMTxRfRlTrH4 z8#J8kpn<4kq1bsiw4o}=BOgF9HR3I0r$ct|4Y(tTpyILk)`sS!!TdY}%_%}4Bi4cP zUMq%|a`J8!=}B4v@_^=rH&ml}bnc);_x-(dt}^T4u9+6an$%|w-6Di6Gqff1-GQA? zdj;;QYn|V5EFrF4~(K-kC4@EBLjuM(qUU3nB4}=(SmyRsfuU zA-qZ5n2OSa}K;Gup&oYiwbdk76{Pv9+ic zX8T(w7qTB)2x4>;%Q|)@JTj#cbxjLD}-y}4`t%kEW+S@Ig7ec#4Oq9Guk416A=VrzDey9p`y8PZ`-PFt)5WTE0 ze?=Z@pM&ymccY%npfThxb7GULSfh5rOQsmfuQ#;pX8-2lq4*=NF)BuXdB!p5#MPx_tv`r5 zAw8uCvpd%|Or1QddG!KFajO|Zdq4DnnU#ZLw(4cLJ}M?TumL|rks%iNUa9?1okV-nGOr!6zTR3nGq6tLs}R3jL?z0cfr(9n;ScazNB@*p4OycuV@vwcKc65)QUFgMsrtBB zK9(bK8Cu$*w4ud{SKKXImr=pCKHXpkr`sF}YU})aejlsSG$`_B^OwvqZu2}YUrQ|| z31T(@S=eupk|kN(F3P^;hH0Tg{#Lm-)sIovW(}9X)&_WXva!*=>;LXw+E(YX|EmhF z!9)8tZSAb7olcVQ@Fe-9WDOP4V0rXsFmJ(4H}upG?|)h%H#rg$j@h^+bUn7^RlD#G zqAer;QkW6HHN-2bR)Y&LPTAuNNu3f3DnXCmA2xD$!%1K>tDbj|VR1;xMb74f&27mJmB;cY`B(MI{bYaO5ivPDFzEDVF4V@y$T-6(o zlz@+qs;zo|7c{DHW)McY2Nyc~#u4t`sLW_#`-gxcb;Y>!(g`~=Uw$BgELJJfZWbN| zsWK`hD5Qpjz72nq(@V<8{o0tHt!c#aD-X}C?w>j6_$fnJ9fAehgFy#Cy5TkFn2n^j zMa(gi$|H1QSwCg8n##A(vkq#UDDqdB3GHvp)krrEua=P#CVCzxNkbz?QhYJ1Qd)k^ zF{Qz5EV?f?rYPX2n?Q9e$4VJyqAbdF6XLwL95wKny zaek7`?pShRmdrhw|;p+Zn@{LH0j#5t7wXE zec@YmYFQEzFfWRMz2_z)A*gX~*n7^~plc<$?#T$c!QA%Zl!d%J)N{9SJ77U++Le*b zmy}8NRQ*S4h3ILUooDerXmuY-P^F{kX8m z__Q9s=6?eKlX|XCE;PyaZq}UXZf^Y|X=;XJ1NpyAukZFw=CH&FElogq!cOAu5340< z0_S-;eZ`HV<6^wqbn$PkL%Jl2penTfzHaRu?ngM>S;K$>HM?*AP(Euj8p6K*)vPG4 z@p{oX;dDDd>GEZJL0g!k`tnHWAN&1e>|^IJHu~?Es<`s6WFz)8wPVBdFupP%bC`O4 zqU#)*>%=cvql*|TT&qgGsmsehMqkA@roU)kSHW~j{?q@{beJx~ZAB5vUvmM2I(6hqqgLG`^uuU)9Ec2oPmdN~bBzM_yy>g41W%r&ZQrP2MH z;L!RC$nFt>Ul0iS%!OZ9x6Yr)Ka0K+!Yj(i~hS2>63_d@RmE z+++Rm0^s+EkB=oyer*)CZlA$4FP`Cu?wA_!ShDf0zYCvn&RfCz4u?Dy7Ko2?GkdxZ zM2J7>?i$C+3Tf3!c(jUrlNZR?OcLl;x#7qgj(U1tNLKXoT^VWN6}X(odAB+QVWh0J zER4VqqDTquZ{nHiFmKD~t54SO-DBM$T~kJ{q5(^yUeucivF&I4JtOu008ly7@(k^n)PQgeeWgb6$WpFsN4dPU%=Jrm~ ziQSQ7WSuiZtxn0kctDi5W{--8(&rPmt`Cd{2xqjn_xCjir^nknKR8nyc-*BCw!~^9 zcc!43>1kYUd@WfN3_7?`CS8kn$eOYggAIwfkmmWLSn(-)_f5rn>FV^J2#23z@G=d<)T~%Bk0YiNVvE+23JN*$ z(jEP{M%(+*ry0x%117os?k+@Z1T7db2H$6D=?yJN$J-bm*aIyX^-KJEzjaJ|wBtry zTn~;^yfa$}@jbDT<;C181M+YmU%npjM70Zmr}Cj}xfAjXyr_m`BJ!}D|}cX6Y<)I)NHgDtg&=sY?Q z-jT+oua8@sgs*!N82V^;(EAL3f_cE|G2GAr(d^;~HSX7YAVk=nt++?m_K>u1nljI+ zfq5D%p$z`|UDz#OWV|pIl*Vu8wa0H+MQXoLKFeyyO()lbvl-1_ZeBCu7yShm|D9TN z4}m9J-u#c&5d^n|xUPxd`X%Wx|rjH(c@c_e{I9KwB2WF)nE> zbSx>^OiFZ)kZ}SgrBnrtmOYSWP~p$4cHhO%RAEDewsIqG0cpqZ<mQs>>a==?!YS zWnn--=(B2TJQt0_Y98@3?4(Tb^#xbw>)S7{f=6jDmmki-Y5l|~;WTZ6?J8p}7dL>X zZR2<0Yxt!s=H<~O(c4k@T^zD}PbsB8XD46#iWnOz41r5v}h6G?50p|4G z#-;s^b}TT5-Hwo+*;y1Yz#G0uuYjg(dwwt+eGmYoF!;A&IrF)rPh4bVY1uQPXUD#$ zVQTzCJnzYHnB((crG>rLp+9K0r+CWqOu%|0F>nsG-uc!iF?u5>aOe`W1I6H<;Fc6! zBV{kaOR^H=E_N+^zYk65d?Q2c?@ed^hGr?hep#Abbayz}Uz6XR|wIgru`Ea-EOWGU!PItLObi zAx0B=`*2T_F+Y||>^iu0O7yyb!9V3zmBHT)Eh@4YV*A>P@)_fv5jszpm-6|e*8^ba zauXf*Ph&@X?8EVfHmdc_#fT%%o`)}MWR|tT3$KeOYef0Oj?aD%MzoaSI?)I<)@uYI zwe7{*52lX-Fuw^l*{*_)pEh0`Vg@X7;fr4@aQ2jHie7{9G>o2)ZmG+80B+Fp&}nTi z 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 KvHt-#rc|>H2mv<$ diff --git a/Simple Plugins Core/addons/sourcemod/scripting/include/simple-plugins.inc b/Simple Plugins Core/addons/sourcemod/scripting/include/simple-plugins.inc index 8f21956..3a9cf4b 100644 --- a/Simple Plugins Core/addons/sourcemod/scripting/include/simple-plugins.inc +++ b/Simple Plugins Core/addons/sourcemod/scripting/include/simple-plugins.inc @@ -326,7 +326,7 @@ public LoadCurrentTeams() g_aCurrentTeams[Team1] = 1; g_aCurrentTeams[Team2] = 2; } - case default: + default: { g_aCurrentTeams[Unknown] = 0; g_aCurrentTeams[Spectator] = 1; diff --git a/Simple Plugins Core/addons/sourcemod/scripting/simple-alltalkmanager.sp b/Simple Plugins Core/addons/sourcemod/scripting/simple-alltalkmanager.sp deleted file mode 100644 index c848332..0000000 --- a/Simple Plugins Core/addons/sourcemod/scripting/simple-alltalkmanager.sp +++ /dev/null @@ -1,515 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple AllTalk Manager -Description: - Allows you to set alltalk at different times -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#pragma semicolon 1 -#include -#include - -#define PLUGIN_VERSION "1.4.$Rev$" - -new Handle:satm_enabled = INVALID_HANDLE; -new Handle:satm_threshold_enabled = INVALID_HANDLE; -new Handle:satm_player_threshold = INVALID_HANDLE; -new Handle:satm_threshold_setting = INVALID_HANDLE; -new Handle:satm_logactivity = INVALID_HANDLE; -new Handle:satm_alltalk = INVALID_HANDLE; - -new Handle:g_aEventNames = INVALID_HANDLE; -new Handle:g_aEventReasons = INVALID_HANDLE; -new Handle:g_aEventSettings = INVALID_HANDLE; - -new bool:g_bLastThreshold = false; -new bool:g_bEnabled = true; -new bool:g_bThresholdEnabled = true; -new bool:g_bIsSetupMap = false; -new bool:g_bIsGameTF2 = false; -new bool:g_bLogActivity = false; - -new g_iLastEventIndex; - -public Plugin:myinfo = -{ - name = "Simple AllTalk Manager", - author = "Simple Plugins", - description = "Allows you to set alltalk at different times", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -} - -/** -Sourcemod callbacks -*/ -public OnPluginStart() -{ - - /** - Need to create all of our console variables. - */ - CreateConVar("satm_version", PLUGIN_VERSION, "Simple AllTalk Manager", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - satm_enabled = CreateConVar("satm_enabled", "1", "Enables/Disables Simple AllTalk Manager", _, true, 0.0, true, 1.0); - satm_threshold_enabled = CreateConVar("satm_threshold_enabled", "1", "Enables/Disables player threshold", _, true, 0.0, true, 1.0); - satm_player_threshold = CreateConVar("satm_player_threshold", "8", "Amount of players for the threshold"); - satm_threshold_setting = CreateConVar("satm_threshold_setting", "1", "Enables/Disables all talk up to player threshold, with the opposite set after the threshold", _, true, 0.0, true, 1.0); - satm_logactivity = CreateConVar("satm_logactivity", "0", "Enables/Disables log activity", _, true, 0.0, true, 1.0); - satm_alltalk = FindConVar("sv_alltalk"); - - /** - Hook console variables - */ - HookConVarChange(satm_enabled, ConVarSettingsChanged); - HookConVarChange(satm_threshold_enabled, ConVarSettingsChanged); - HookConVarChange(satm_player_threshold, ConVarSettingsChanged); - HookConVarChange(satm_logactivity, ConVarSettingsChanged); - - /** - Remove the notify flag from all talk cvar since we do it - */ - SetConVarFlags(satm_alltalk, GetConVarFlags(satm_alltalk)~FCVAR_NOTIFY); - - /** - Get the game type. We only care if it's TF2 - */ - new String:sGameType[64]; - GetGameFolderName(sGameType, sizeof(sGameType)); - if (StrEqual(sGameType, "tf", false)) - { - g_bIsGameTF2 = true; - } - - /** - Create the arrays - */ - g_aEventNames = CreateArray(255, 1); - g_aEventReasons = CreateArray(255, 1); - g_aEventSettings = CreateArray(1, 1); - - /** - Need to register the commands we are going to create and use. - */ - RegAdminCmd("sm_reloadatconfig", Command_Reload, ADMFLAG_GENERIC, "Reloads settings from config file"); - - /** - Create the config file - */ - AutoExecConfig(true); - - /** - Load the events from the config - */ - LoadEventsFromConfig(); -} - -public OnConfigsExecuted() -{ - - /** - Load up the settings - */ - g_bEnabled = GetConVarBool(satm_enabled); - g_bLogActivity = GetConVarBool(satm_logactivity); - g_bThresholdEnabled = GetConVarBool(satm_threshold_enabled); -} - -public OnMapStart() -{ - - /** - Reset the globals - */ - g_iLastEventIndex = 0; - g_bLastThreshold = false; - - /** - Check the map type if we are in TF2 - */ - if (g_bIsGameTF2) - { - g_bIsSetupMap = IsSetupPeriodMap(); - } - - /** - Set AllTalk - */ - if (g_bEnabled) - { - SetConVarBool(satm_alltalk, true); - } -} - -public OnClientDisconnect_Post(client) -{ - if (g_bEnabled) - { - SetAllTalk(-1); - } -} - -public OnClientPostAdminCheck(client) -{ - if (g_bEnabled) - { - SetAllTalk(-1); - } - CreateTimer(2.0, Timer_ShowAllTalkStatus, client, TIMER_FLAG_NO_MAPCHANGE); -} - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (convar == satm_enabled) - { - if (StringToInt(newValue)) - { - g_bEnabled = true; - } - else - { - g_bEnabled = false; - } - } - else if (convar == satm_threshold_enabled) - { - if (StringToInt(newValue)) - { - g_bThresholdEnabled = true; - } - else - { - g_bThresholdEnabled = false; - } - } - else if (convar == satm_logactivity) - { - if (StringToInt(newValue)) - { - g_bLogActivity = true; - } - else - { - g_bLogActivity = false; - } - } - if (g_bEnabled) - { - SetAllTalk(-1); - } -} - -/** -Commands -*/ -public Action:Command_Reload(client, args) -{ - - /** - Clear the array - */ - ClearArray(g_aEventNames); - ClearArray(g_aEventReasons); - ClearArray(g_aEventSettings); - - /** - Load the events from the config - */ - LoadEventsFromConfig(); - - return Plugin_Handled; -} - -/** -Game Event Hooks -*/ -public Hook_All_Events(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (!g_bIsSetupMap) - { - if (StrEqual(name, "teamplay_round_start")) - { - if (FindStringInArray(g_aEventNames, "teamplay_setup_finished") != -1) - { - g_iLastEventIndex = FindStringInArray(g_aEventNames, "teamplay_setup_finished"); - if (g_bEnabled) - { - SetAllTalk(g_iLastEventIndex); - return; - } - } - } - } - g_iLastEventIndex = FindStringInArray(g_aEventNames, name); - if (g_bEnabled) - { - SetAllTalk(g_iLastEventIndex); - } -} - -/** -Timers -*/ -public Action:Timer_ShowAllTalkStatus(Handle:timer, any:client) -{ - if (IsClientConnected(client) && IsClientInGame(client)) - { - new bool:bSetting = GetConVarBool(satm_alltalk); - if (bSetting) - { - PrintToChat(client, "\x01\x04[SM] AllTalk is \x01[on]"); - } - else - { - PrintToChat(client, "\x01\x04[SM] AllTalk is \x01[off]"); - } - } -} - -/** -Stock Functions -*/ -stock LoadEventsFromConfig() -{ - - /** - Make sure the config file is here and load it up - */ - new String:sConfigFile[256]; - BuildPath(Path_SM, sConfigFile, sizeof(sConfigFile), "configs/simple-alltalkmanager_events.cfg"); - if (!FileExists(sConfigFile)) - { - - /** - Config file doesn't exists, stop the plugin - */ - LogError("[SATM] Simple AllTalk Manager is not running! Could not find file %s", sConfigFile); - SetFailState("Could not find file %s", sConfigFile); - } - - /** - Create the arrays and variables - */ - new String:sGameEventName[256]; - new String:sReason[256]; - new iSetting; - - /** - Load config file as a KeyValues file - */ - new Handle:kvGameEvents = CreateKeyValues("game_events"); - FileToKeyValues(kvGameEvents, sConfigFile); - - if (!KvGotoFirstSubKey(kvGameEvents)) - { - return; - } - - /** - Hook the game events and load the settings - */ - do - { - - /** - Get the section name; this should be the event name - */ - KvGetSectionName(kvGameEvents, sGameEventName, sizeof(sGameEventName)); - if (!HookEventEx(sGameEventName, Hook_All_Events, EventHookMode_PostNoCopy)) - { - - /** - Could not hook this event, stop the plugin - */ - SetFailState("Could not hook event %s", sGameEventName); - } - else - { - if (g_bLogActivity) - { - LogMessage("[SATM] Hooked event: %s", sGameEventName); - } - } - - /** - Get the reason string and setting - */ - KvGetString(kvGameEvents, "reason", sReason, sizeof(sReason)); - iSetting = KvGetNum(kvGameEvents, "setting"); - if (g_bLogActivity) - { - LogMessage("[SATM] Event reason string: %s", sReason); - LogMessage("[SATM] Event setting: %i", iSetting); - } - - /** - Push the values to the arrays - */ - PushArrayString(g_aEventNames, sGameEventName); - PushArrayString(g_aEventReasons, sReason); - PushArrayCell(g_aEventSettings, iSetting); - } while (KvGotoNextKey(kvGameEvents)); - - /** - Close our handle - */ - CloseHandle(kvGameEvents); -} - -stock SetAllTalk(index) -{ - new iPlayerThreshold = GetConVarInt(satm_player_threshold); - new bool:bThresholdMet = ((GetClientCount() >= iPlayerThreshold) ? true : false); - new bool:bSetting; - - if (g_bThresholdEnabled) - { - if (bThresholdMet) - { - if (index == -1) - { - if (bThresholdMet != g_bLastThreshold) - { - g_bLastThreshold = true; - bSetting = !GetConVarBool(satm_threshold_setting); - new bool:bLastSetting = GetArrayCell(g_aEventSettings, g_iLastEventIndex); - if (bLastSetting && !bSetting) - { - bSetting = GetArrayCell(g_aEventSettings, g_iLastEventIndex); - } - } - else - { - bSetting = GetArrayCell(g_aEventSettings, g_iLastEventIndex); - } - } - else - { - bSetting = GetArrayCell(g_aEventSettings, index); - } - } - else - { - g_bLastThreshold = false; - bSetting = GetConVarBool(satm_threshold_setting); - } - } - else - { - if (index != -1) - { - bSetting = GetArrayCell(g_aEventSettings, index); - } - } - - if (GetConVarBool(satm_alltalk) != bSetting) - { - - SetConVarBool(satm_alltalk, bSetting); - - new String:sReason[256]; - if (index == -1) - { - Format(sReason, sizeof(sReason), "Player Threshold"); - } - else - { - if (!g_bIsSetupMap) - { - new String:sCurrentEvent[256]; - GetArrayString(g_aEventNames, index, sCurrentEvent, sizeof(sCurrentEvent)); - if (StrEqual(sCurrentEvent, "teamplay_setup_finished")) - { - new iRoundStartIndex = FindStringInArray(g_aEventNames, "teamplay_round_start"); - if (iRoundStartIndex != -1) - { - GetArrayString(g_aEventReasons, iRoundStartIndex, sReason, sizeof(sReason)); - } - else - { - GetArrayString(g_aEventReasons, index, sReason, sizeof(sReason)); - } - } - else - { - GetArrayString(g_aEventReasons, index, sReason, sizeof(sReason)); - } - } - else - { - GetArrayString(g_aEventReasons, index, sReason, sizeof(sReason)); - } - } - - if (bSetting) - { - PrintToChatAll("\x01\x04[SM] AllTalk turned \x01[on] \x04due to:\x01 %s", sReason); - } - else - { - PrintToChatAll("\x01\x04[SM] AllTalk turned \x01[off] \x04due to:\x01 %s", sReason); - } - } -} - -stock bool:IsSetupPeriodMap() -{ - new iEnt = -1; - new String:sMapName[32]; - - GetCurrentMap(sMapName, sizeof(sMapName)); - - if (strncmp(sMapName, "cp_", 3, false) == 0) - { - new iTeam; - while ((iEnt = FindEntityByClassname(iEnt, "team_control_point")) != -1) - { - iTeam = GetEntProp(iEnt, Prop_Send, "m_iTeamNum"); - - /** - If there is a blu CP or a neutral CP, then it's not an attack/defend map - */ - if (iTeam != 2) - { - //this is a push map - return false; - } - } - //this is a attack/defend map - return true; - } - else if (strncmp(sMapName, "ctf_", 3, false) == 0) - { - //this is a ctf map - return false; - } - return false; -} diff --git a/Simple Plugins Core/addons/sourcemod/scripting/simple-autoscrambler.sp b/Simple Plugins Core/addons/sourcemod/scripting/simple-autoscrambler.sp deleted file mode 100644 index 6c6799e..0000000 --- a/Simple Plugins Core/addons/sourcemod/scripting/simple-autoscrambler.sp +++ /dev/null @@ -1,459 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple AutoScrambler -Description: - Automatically scrambles the teams based upon a number of events. -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include - -#define PLUGIN_VERSION "1.1.$Rev$" - -/** -Different scramble modes: - -1 = Full Scramble, dont restart round. -2 = Admins Immune, dont restart round. -3 = Full Scramble, restart round and reset scores. -4 = Admins Immune, restart round and reset scores. - -*/ - -/** -Different top player modes: - -1 = Divide Top 4 players on the two teams. -2 = Protect the Top 2 players on each team. - -*/ - -enum PlayerData -{ - Handle:hForcedTimer, - bool:bProtected; -}; - -/** -Cvars used for admins -*/ -new Handle: sas_admin_immunity_enabled = INVALID_HANDLE, - Handle: sas_admin_flag_scramblenow = INVALID_HANDLE, - Handle: sas_admin_flag_immunity = INVALID_HANDLE; - -/** -Cvars used for autoscramble -*/ -new Handle: sas_autoscramble_enabled = INVALID_HANDLE, - Handle: sas_autoscramble_minplayers = INVALID_HANDLE, - Handle: sas_autoscramble_mode = INVALID_HANDLE, - Handle: sas_autoscramble_winstreak = INVALID_HANDLE, - Handle: sas_autoscramble_steamroll = INVALID_HANDLE, - Handle: sas_autoscramble_frags = INVALID_HANDLE; - -/** -Cvars used for voting -*/ -new Handle: sas_vote_enabled = INVALID_HANDLE, - Handle: sas_vote_upcount = INVALID_HANDLE, - Handle: sas_vote_winpercent = INVALID_HANDLE, - Handle: sas_vote_mode = INVALID_HANDLE, - Handle: sas_vote_minplayers = INVALID_HANDLE; - -/** -Additional cvars -*/ -new Handle: sas_enabled = INVALID_HANDLE, - Handle: sas_timer_scrambledelay = INVALID_HANDLE, - Handle: TFGameModeArena = INVALID_HANDLE; - -/** -Timers -*/ -new Handle: g_hScrambleTimer = INVALID_HANDLE; - -/** - Player arrays - */ -new g_aPlayers[MAXPLAYERS + 1][PlayerData]; - -/** - Cvar variables - */ -new bool: g_bIsEnabled, - bool: g_bIsAutoScrambleEnabled, - bool: g_bIsVoteEnabled, - bool: g_bIsAdminImmunityEnabled; -new Float: g_fTimer_ScrambleDelay, - Float: g_fVote_UpCount, - Float: g_fVote_WinPercent; -new g_iAutoScramble_Minplayers, - g_iAutoScramble_Mode, - g_iAutoScramble_WinStreak, - g_iAutoScramble_SteamRoll, - g_iAutoScramble_Frags, - g_iVote_Mode, - g_iVote_MinPlayers; -new String: g_sScrambleNowFlag[5], - String: g_sAdminImmunityFlag[5]; - -/** -Other globals -*/ -new g_iMaxEntities, - g_iOwnerOffset; - -public Plugin:myinfo = -{ - name = "Simple AutoScrambler", - author = "Simple Plugins", - description = "Automatically scrambles the teams based upon a number of events.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -public OnPluginStart() -{ - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[SAS] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - switch (g_CurrentMod) - { - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_Post); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_Post); - } - } - - /** - Create console variables - */ - CreateConVar("sas_version", PLUGIN_VERSION, "Simple AutoScrambler Version",FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - sas_enabled = CreateConVar("sas_enabled", "1", "Enable/Disable Simple AutoScrambler"); - sas_timer_scrambledelay = CreateConVar("sas_timer_scrambledelay", "5.0", "Delay used after a scramble has been started", _, true, 1.0, true, 30.0); - - /** - Cvars used for admins - */ - sas_admin_immunity_enabled = CreateConVar("sas_admin_immunity_enabled", "1", "Enable/Disable admin immunity for scrambles"); - sas_admin_flag_scramblenow = CreateConVar("sas_admin_flag_scramblenow", "z", "Admin flag to use for scramblenow function/command"); - sas_admin_flag_immunity = CreateConVar("sas_admin_flag_immunity", "z", "Admin flag to use for scramble immunity"); - - /** - Cvars used for autoscramble - */ - sas_autoscramble_enabled = CreateConVar("sas_autoscramble_enabled", "1", "Enable/Disable the autoscramble function"); - sas_autoscramble_minplayers = CreateConVar("sas_autoscramble_minplayers", "16", "Min players needed to start an autoscramble"); - sas_autoscramble_mode = CreateConVar("sas_autoscramble_mode", "1", "Scramble mode used when autoscrambling"); - sas_autoscramble_winstreak = CreateConVar("sas_autoscramble_winstreak", "5", "Max amount of wins in a row a team can achieve before an autoscramble starts"); - sas_autoscramble_steamroll = CreateConVar("sas_autoscramble_steamroll", "120", "Shortest amount of time a team can win by before an autoscramble starts (seconds)"); - sas_autoscramble_frags = CreateConVar("sas_autoscramble_frags", "1", "Min players needed to start a vote and scramble"); - - /** - Cvars used for voting - */ - sas_vote_enabled = CreateConVar("sas_vote_enabled", "1", "Enable/Disable voting for scramble"); - sas_vote_upcount = CreateConVar("sas_vote_upcount", "5", "Amount of people wanting a scramble before a vote starts. If less than 1 it will be considered a percentage. (ie 0.5 = 50% | 1 = 1 Player | 5 = 5 Players)"); - sas_vote_winpercent = CreateConVar("sas_vote_winpercent", "0.6", "Percentage of votes needed to scramble", _, true, 0.0, true, 1.0); - sas_vote_mode = CreateConVar("sas_vote_mode", "1", "Scramble mode used when a vote results in a scramble"); - sas_vote_minplayers = CreateConVar("sas_vote_minplayers", "16", "Min players needed to start a vote and scramble"); - - /** - Hook the console variables if they change - */ - HookConVarChange(sas_enabled, ConVarSettingsChanged); - HookConVarChange(sas_timer_scrambledelay, ConVarSettingsChanged); - HookConVarChange(sas_admin_immunity_enabled, ConVarSettingsChanged); - HookConVarChange(sas_admin_flag_scramblenow, ConVarSettingsChanged); - HookConVarChange(sas_admin_flag_immunity, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_enabled, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_minplayers, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_mode, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_winstreak, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_steamroll, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_frags, ConVarSettingsChanged); - HookConVarChange(sas_vote_enabled, ConVarSettingsChanged); - HookConVarChange(sas_vote_upcount, ConVarSettingsChanged); - HookConVarChange(sas_vote_winpercent, ConVarSettingsChanged); - HookConVarChange(sas_vote_mode, ConVarSettingsChanged); - HookConVarChange(sas_vote_minplayers, ConVarSettingsChanged); - - /** - Register the command - */ - RegConsoleCmd("sm_scramblenow", Command_ScrambleNow, "sm_scramblenow (mode): Scrambles the teams"); - - /** - Load translations and .cfg file - */ - LoadTranslations ("simpleautoscrambler.phrases"); - AutoExecConfig(true, "plugin.simpleautoscrambler"); - LogAction(0, -1, "[SAS] Simple AutoScrambler is loaded."); -} - -public OnAllPluginsLoaded() -{ - //something -} - -public OnLibraryRemoved(const String:name[]) -{ - //something -} - -public OnConfigsExecuted() -{ - - /** - Load up all the variable defaults - */ - LoadUpVariables(); - - /** - Log our activity - */ - if (g_bIsEnabled) - LogAction(0, -1, "Simple AutoScrambler is ENABLED"); - else - LogAction(0, -1, "Simple AutoScrambler is DISABLED"); -} - -public Action:Command_ScrambleNow(client, args) -{ - - /** - Make sure we are enabled - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the client is authorized to run this command. - */ - if (!SM_IsValidAdmin(client, g_sScrambleNowFlag)) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure it's ok to scramble at this time - */ - if (!OkToScramble) - { - return Plugin_Handled; - } - - /** - Make sure it's ok to scramble at this time - */ - LogAction(0, -1, "[SAS] The scramblenow command was used"); - - /** - Scramble the teams - */ - StartAScramble(); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - -} - -public Action:Timer_ScrambleTeams(Handle:timer, any:mode) -{ - - /** - Make sure it's still ok to scramble - */ - if (!OkToScramble) - { - return Plugin_Handled; - } - - - switch (mode) - { - case - - - - } - - - /** - Reset the handle because the timer is over and the callback is done - */ - g_hScrambleTimer = INVALID_HANDLE; - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - -} - -stock StartAScramble(mode) -{ - - /** - See if we are already started a scramble - */ - if (g_hScrambleTimer == INVALID_HANDLE) - { - - /** - There is a scramble in progress - */ - return; - - } - - /** - Report that a scramble is about to start - */ - PrintCenterTextAll("%T", "Scramble", LANG_SERVER); - - /** - Start a timer and log the action - */ - g_hScrambleTimer = CreateTimer(g_fTimer_ScrambleDelay, Timer_ScrambleTeams, mode, TIMER_FLAG_NO_MAPCHANGE); - LogAction(0, -1, "[SAS] A scamble timer was started"); -} - -stock bool:OkToScramble() -{ - -} - -stock LoadUpVariables() -{ - g_bIsEnabled = GetConVarBool(sas_enabled); - g_bIsAutoScrambleEnabled = GetConVarBool(sas_autoscramble_enabled); - g_bIsVoteEnabled = GetConVarBool(sas_vote_enabled); - g_bIsAdminImmunityEnabled = GetConVarBool(sas_admin_immunity_enabled); - g_iAutoScramble_Minplayers = GetConVarInt(sas_autoscramble_minplayers); - g_iAutoScramble_Mode = GetConVarInt(sas_autoscramble_mode); - g_iAutoScramble_WinStreak = GetConVarInt(sas_autoscramble_winstreak); - g_iAutoScramble_SteamRoll = GetConVarInt(sas_autoscramble_steamroll); - g_iAutoScramble_Frags = GetConVarInt(sas_autoscramble_frags); - g_iVote_Mode = GetConVarInt(sas_vote_mode); - g_iVote_MinPlayers = GetConVarInt(sas_vote_minplayers); - GetConVarString(sas_admin_flag_scramblenow, g_sScrambleNowFlag, sizeof(g_sScrambleNowFlag)); - GetConVarString(sas_admin_flag_immunity, g_sAdminImmunityFlag, sizeof(g_sAdminImmunityFlag)); - g_fTimer_ScrambleDelay = GetConVarFloat(sas_timer_scrambledelay); - g_fVote_UpCount = GetConVarFloat(sas_vote_upcount); - g_fVote_WinPercent = GetConVarFloat(sas_vote_winpercent); - g_iMaxEntities = GetMaxEntities(); - g_iOwnerOffset = FindSendPropInfo("CBaseObject", "m_hBuilder"); -} - -stock TF2_DestroyBuildings(client) -{ - - /** - We have to start a loop to check the owner of all the valid entities - */ - for (new i = MaxClients + 1; i <= g_iMaxEntities; i++) - { - if (!IsValidEntity(i)) - { - - /** - Not valid, continue to next one - */ - continue; - } - - /** - Get the name of the current entity - */ - decl String:sNetClass[32]; - GetEntityNetClass(i, sNetClass, sizeof(sNetClass)); - - /** - See if its something that an engineer would build - */ - if (strcmp(sNetClass, "CObjectSentrygun") == 0 - || strcmp(sNetClass, "CObjectTeleporter") == 0 - || strcmp(sNetClass, "CObjectDispenser") == 0) - { - - /** - It is, so lets check the owner - */ - if (GetEntDataEnt2(i, g_iOwnerOffset) == client) - { - - /** - It's the clients building, so we blow it up. - */ - SetVariantInt(9999); - AcceptEntityInput(i, "RemoveHealth"); - } - } - } -} \ No newline at end of file diff --git a/Simple Plugins Core/addons/sourcemod/scripting/simple-chatcolors.sp b/Simple Plugins Core/addons/sourcemod/scripting/simple-chatcolors.sp deleted file mode 100644 index 539d057..0000000 --- a/Simple Plugins Core/addons/sourcemod/scripting/simple-chatcolors.sp +++ /dev/null @@ -1,496 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Chat Colors -Description: - Changes the colors of players chat based on config file -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#pragma semicolon 1 -#include -#include - -#define PLUGIN_VERSION "0.9.0.$Rev$" - -#define CHAT_SYMBOL '@' -#define TRIGGER_SYMBOL1 '!' -#define TRIGGER_SYMBOL2 '/' -#define CHAT_MAX_MESSAGE_LENGTH 1024 - -new Handle:g_hDebugCvar = INVALID_HANDLE; -new Handle:g_aGroupNames = INVALID_HANDLE; -new Handle:g_aGroupFlag = INVALID_HANDLE; -new Handle:g_aGroupNameColor = INVALID_HANDLE; -new Handle:g_aGroupTextColor = INVALID_HANDLE; - -new bool:g_bDebug = false; - -new g_iArraySize; - -new g_aPlayerColorIndex[MAXPLAYERS + 1] = { -1, ... }; - -public Plugin:myinfo = -{ - name = "Simple Chat Colors", - author = "Simple Plugins", - description = "Changes the colors of players chat based on config file.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -/** -Sourcemod callbacks -*/ -public OnPluginStart() -{ - - /** - Need to create all of our console variables. - */ - CreateConVar("sm_chatcolors_version", PLUGIN_VERSION, "Simple Chat Colors", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - g_hDebugCvar = CreateConVar("sm_chatcolors_debug", "1", "Enable/Disable debugging information"); - - /** - Hook console variables - */ - HookConVarChange(g_hDebugCvar, ConVarSettingsChanged); - - /** - Need to register the commands we are going to use - */ - RegConsoleCmd("say", Command_Say); - RegConsoleCmd("say_team", Command_SayTeam); - RegAdminCmd("sm_reloadcolorsconfig", Command_Reload, ADMFLAG_GENERIC, "Reloads settings from config file"); - - /** - Create the arrays - */ - g_aGroupNames = CreateArray(256, 1); - g_aGroupFlag = CreateArray(15, 1); - g_aGroupNameColor = CreateArray(15, 1); - g_aGroupTextColor = CreateArray(15, 1); - - /** - Load the admins and colors from the config - */ - LoadAdminsAndColorsFromConfig(); - g_iArraySize = GetArraySize(g_aGroupNames); -} - -public OnConfigsExecuted() -{ - g_bDebug = GetConVarBool(g_hDebugCvar); - ReloadConfigFile(); -} - -public OnClientPostAdminCheck(client) -{ - - /** - Check the client to see if they are a admin - */ - CheckAdmin(client); -} - -public OnClientDisconnect(client) -{ - g_aPlayerColorIndex[client] = -1; -} - -/** -Commands -*/ -public Action:Command_Say(client, args) -{ - - /** - Make sure we are enabled. - */ - if (client == 0 || IsChatTrigger()) - { - return Plugin_Continue; - } - - if (g_aPlayerColorIndex[client] != -1) - { - - /** - The client is, so get the chat message and strip it down. - */ - decl String:sArg[CHAT_MAX_MESSAGE_LENGTH], - String:sChatMsg[CHAT_MAX_MESSAGE_LENGTH]; - - new bool:bAlive = IsPlayerAlive(client); - - GetCmdArgString(sArg, sizeof(sArg)); - StripQuotes(sArg); - TrimString(sArg); - new startidx; - if (sArg[strlen(sArg)-1] == '"') - { - sArg[strlen(sArg)-1] = '\0'; - startidx = 1; - } - - /** - Bug out if they are using the admin chat symbol (admin chat). If we are in CSS it may not find all the triggers, so we double check. - */ - if (sArg[startidx] == CHAT_SYMBOL || sArg[startidx] == TRIGGER_SYMBOL1 || sArg[startidx] == TRIGGER_SYMBOL2) - { - return Plugin_Continue; - } - - /** - Log the message for hlstatsx and other things. - */ - new iUserID = GetClientUserId(client); - decl String:sAuthID[64]; - GetClientAuthString(client, sAuthID, sizeof(sAuthID)); - LogToGame("\"%N<%i><%s><>\" say \"%s\"", client, iUserID, sAuthID, sArg); - - /** - Format the message. - */ - FormatMessage(client, 0, bAlive, sChatMsg, sArg, g_aPlayerColorIndex[client]); - - /** - Send the message. - */ - //SayText2(0, client, sChatMsg); - CPrintToChatAll(sChatMsg); - - /** - We are done, bug out, and stop the original chat message. - */ - return Plugin_Stop; - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Command_SayTeam(client, args) -{ - - /** - Make sure we are enabled. - */ - if (client == 0 || IsChatTrigger()) - { - return Plugin_Continue; - } - - /** - Check the client to see if they are a admin - */ - if (g_aPlayerColorIndex[client] != -1) - { - - /** - The client is, so get the chat message and strip it down. - */ - decl String:sArg[CHAT_MAX_MESSAGE_LENGTH], - String:sChatMsg[CHAT_MAX_MESSAGE_LENGTH]; - - new bool:bAlive = IsPlayerAlive(client); - new iCurrentTeam = GetClientTeam(client); - - GetCmdArgString(sArg, sizeof(sArg)); - StripQuotes(sArg); - TrimString(sArg); - new startidx; - if (sArg[strlen(sArg)-1] == '"') - { - sArg[strlen(sArg)-1] = '\0'; - startidx = 1; - } - - /** - Bug out if they are using the admin chat symbol (admin chat). - */ - if (sArg[startidx] == CHAT_SYMBOL || sArg[startidx] == TRIGGER_SYMBOL1 || sArg[startidx] == TRIGGER_SYMBOL2) - { - return Plugin_Continue; - } - - /** - Log the message for hlstatsx and other things. - */ - new iUserID = GetClientUserId(client); - decl String:sAuthID[64]; - GetClientAuthString(client, sAuthID, sizeof(sAuthID)); - LogToGame("\"%N<%i><%s><>\" say_team \"%s\"", client, iUserID, sAuthID, sArg); - - /** - Format the message. - */ - FormatMessage(client, iCurrentTeam, bAlive, sChatMsg, sArg, g_aPlayerColorIndex[client]); - - /** - Send the message to the same team - */ - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == iCurrentTeam) - { - CPrintToChat(client, sChatMsg); - } - } - - /** - We are done, bug out, and stop the original chat message. - */ - return Plugin_Stop; - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Command_Reload(client, args) -{ - ReloadConfigFile(); - return Plugin_Handled; -} - -/** -Stock Functions -*/ -stock LoadAdminsAndColorsFromConfig() -{ - - /** - Make sure the config file is here and load it up - */ - new String:sConfigFile[256]; - BuildPath(Path_SM, sConfigFile, sizeof(sConfigFile), "configs/simple-chatcolors.cfg"); - if (!FileExists(sConfigFile)) - { - - /** - Config file doesn't exists, stop the plugin - */ - LogError("[SCC] Simple Chat Colors is not running! Could not find file %s", sConfigFile); - SetFailState("Could not find file %s", sConfigFile); - } - - /** - Create the arrays and variables - */ - new String:sGroupName[256]; - new String:sGroupFlag[15]; - new String:sGroupNameColor[15]; - new String:sGroupTextColor[15]; - - - /** - Load config file as a KeyValues file - */ - new Handle:kvChatColors = CreateKeyValues("admin_colors"); - FileToKeyValues(kvChatColors, sConfigFile); - - if (!KvGotoFirstSubKey(kvChatColors)) - { - return; - } - - /** - Load up all the groups in the file - */ - do - { - - /** - Get the section name; should be the "group" name - */ - KvGetSectionName(kvChatColors, sGroupName, sizeof(sGroupName)); - - - /** - Get the flags and colors - */ - KvGetString(kvChatColors, "flag", sGroupFlag, sizeof(sGroupFlag)); - KvGetString(kvChatColors, "namecolor", sGroupNameColor, sizeof(sGroupNameColor)); - KvGetString(kvChatColors, "textcolor", sGroupTextColor, sizeof(sGroupTextColor)); - - if (g_bDebug) - { - LogMessage("Group Name/SteamID: %s", sGroupName); - LogMessage("Flag String: %s", sGroupFlag); - LogMessage("Color on name: %s", sGroupNameColor); - LogMessage("Color of text: %s", sGroupTextColor); - } - - /** - Push the values to the arrays - */ - PushArrayString(g_aGroupNames, sGroupName); - PushArrayString(g_aGroupFlag, sGroupFlag); - PushArrayString(g_aGroupNameColor, sGroupNameColor); - PushArrayString(g_aGroupTextColor, sGroupTextColor); - } while (KvGotoNextKey(kvChatColors)); - - /** - Close our handle - */ - CloseHandle(kvChatColors); -} - -stock ReloadConfigFile() -{ - - /** - Clear the array - */ - ClearArray(g_aGroupNames); - ClearArray(g_aGroupFlag); - ClearArray(g_aGroupNameColor); - ClearArray(g_aGroupTextColor); - - /** - Load the admins, groups, and colors from the config - */ - LoadAdminsAndColorsFromConfig(); - g_iArraySize = GetArraySize(g_aGroupNames); - - /** - Recheck all the online players for assigned colors - */ - for (new index = 1; index <= MaxClients; index++) - { - if (IsClientConnected(index) && IsClientInGame(index)) - { - CheckAdmin(index); - } - } -} - -stock CheckAdmin(client) -{ - new String:sFlags[15]; - new String:sClientSteamID[64]; - new iGroupFlags; - new iFlags; - new iIndex = -1; - - /** - Look for a steamid first - */ - GetClientAuthString(client, sClientSteamID, sizeof(sClientSteamID)); - iIndex = FindStringInArray(g_aGroupNames, sClientSteamID); - if (iIndex != -1) - { - g_aPlayerColorIndex[client] = iIndex; - } - - /** - Didn't find one, check flags - */ - else - { - /** - Search for flag in groups - */ - - iFlags = GetUserFlagBits(client); - for (iIndex = 0; iIndex < g_iArraySize; iIndex++) - { - GetArrayString(g_aGroupFlag, iIndex, sFlags, sizeof(sFlags)); - iGroupFlags = ReadFlagString(sFlags); - if (iFlags & iGroupFlags) - { - g_aPlayerColorIndex[client] = iIndex; - break; - } - } - } - - if (g_bDebug) - { - PrintToChatAll("SteamID: %s", sClientSteamID); - PrintToChatAll("Array Index: %i", iIndex); - PrintToChatAll("Flag String: %s", sFlags); - PrintToChatAll("Flag Bits of Client: %i", iFlags); - PrintToChatAll("Flag Bits of Group: %i", iGroupFlags); - } -} - -stock FormatMessage(iClient, iTeam, bool:bAlive, String:sChatMsg[], const Sting:sMessage[], iArrayIndex) -{ - decl String:sDead[10], - String:sTeam[10], - String:sClientName[64]; - - GetClientName(iClient, sClientName, sizeof(sClientName)); - - if (iTeam != 0) - { - Format(sTeam, sizeof(sTeam), "(TEAM) "); - } - else - { - Format(sTeam, sizeof(sTeam), ""); - } - if (bAlive) - { - Format(sDead, sizeof(sDead), ""); - } - else - { - Format(sDead, sizeof(sDead), "*DEAD* "); - } - - new String:sNameColor[15]; - new String:sTextColor[15]; - GetArrayString(g_aGroupNameColor, iArrayIndex, sNameColor, sizeof(sNameColor)); - GetArrayString(g_aGroupTextColor, iArrayIndex, sTextColor, sizeof(sTextColor)); - - Format(sChatMsg, CHAT_MAX_MESSAGE_LENGTH, "{default}%s%s%s%s {default}: %s%s", sDead, sTeam, sNameColor, sClientName, sTextColor, sMessage); -} - -/** -Adjust the settings if a convar was changed -*/ -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (StringToInt(newValue) == 1) - { - g_bDebug = true; - } - else - { - g_bDebug = false; - } -} \ No newline at end of file diff --git a/Simple Plugins Core/addons/sourcemod/scripting/simple-donatorbenefits.sp b/Simple Plugins Core/addons/sourcemod/scripting/simple-donatorbenefits.sp deleted file mode 100644 index e3f6845..0000000 --- a/Simple Plugins Core/addons/sourcemod/scripting/simple-donatorbenefits.sp +++ /dev/null @@ -1,1312 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Donator Benefits -Description: - Provides donator benefits to players -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include -#include - -#define PLUGIN_VERSION "1.1.$Rev$" - -#define CHAT_SYMBOL '@' -#define CHAT_MAX_MESSAGE_LENGTH 1024 - -enum PlayerData -{ - bool:bIsDonator, - bool:bQueue, - bool:bImmune, - iHealthCount, - iNewTeam -}; - -/** - Public convar handles - */ -new Handle:sdb_enabled = INVALID_HANDLE; -new Handle:sdb_donationflag = INVALID_HANDLE; -new Handle:sdb_soundfile = INVALID_HANDLE; -new Handle:sdb_joinsound_enabled = INVALID_HANDLE; -new Handle:sdb_joinpubmsg_enabled = INVALID_HANDLE; -new Handle:sdb_joinprivmsg_enabled = INVALID_HANDLE; -new Handle:sdb_chatcolors_enabled = INVALID_HANDLE; -new Handle:sdb_immunity_enabled = INVALID_HANDLE; -new Handle:sdb_ubercharge_enabled = INVALID_HANDLE; -new Handle:sdb_givehealth_enabled = INVALID_HANDLE; -new Handle:sdb_nofalldmg_enabled = INVALID_HANDLE; -new Handle:sdb_fastheavy_enabled = INVALID_HANDLE; -new Handle:sdb_swapteam_enabled = INVALID_HANDLE; -new Handle:sdb_chatcolor = INVALID_HANDLE; -new Handle:sdb_uberlevel = INVALID_HANDLE; -new Handle:sdb_healthcount = INVALID_HANDLE; -new Handle:sdb_healthbonus = INVALID_HANDLE; -new Handle:sdb_heavymultiplier = INVALID_HANDLE; - -/** -Create global enable/disable bools so we don't have to check the console variable on every call -*/ -new bool:g_bIsEnabled = true; -new bool:g_bIsJoinSoundEnabled = true; -new bool:g_bIsJoinPubMsgEnabled = true; -new bool:g_bIsJoinPrivMsgEnabled = true; -new bool:g_bIsChatColorsEnabled = true; -new bool:g_bIsImmuntyEnabled = true; -new bool:g_bIsUberChargeEnabled = true; -new bool:g_bIsGiveHealthEnabled = true; -new bool:g_bIsNoFallDmgEnabled = true; -new bool:g_bIsFastHeayEnabled = true; -new bool:g_bIsSwapTeamEnabled = true; - -/** - Player arrays - */ -new g_aPlayers[MAXPLAYERS + 1][PlayerData]; - - -/** -Rest of the globals -*/ -new bool:g_bRoundEnd = false; -new String:g_sCharDonatorFlag[5]; -new String:g_sSoundFile[PLATFORM_MAX_PATH]; -new String:g_sChatColor[11]; -new g_iHealthBonus; -new g_iHealthCount; -new g_iClassMaxHealth[TFClassType] = {0, 125, 125, 200, 175, 150, 300, 175, 125, 125}; -new g_fClassMaxSpeed[TFClassType] = {0, 400, 300, 240, 280, 320, 230, 300, 300, 300}; -new Float:g_fHeavyMultiplier = 0.0; -new Float:g_fUberLevel = 0.0; - -public Plugin:myinfo = -{ - name = "Simple Donation Benefits", - author = "Simple Plugins", - description = "Gives donators benefits to players", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -} - -public OnPluginStart() -{ - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[SDB] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_connect", HookPlayerSpawn, EventHookMode_Pre); - HookEvent("player_spawn", HookPlayerSpawn, EventHookMode_Post); - HookEvent("player_death", HookPlayerDeath, EventHookMode_Post); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Post); - switch (g_CurrentMod) - { - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - HookEvent("player_changeclass", HookPlayerClass, EventHookMode_Post); - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_Post); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - - /** - Create console variables - */ - CreateConVar("sdb_version", PLUGIN_VERSION, "Simple Donation Benefits", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - sdb_enabled = CreateConVar("sdb_enabled", "1", "Enable/Disable Simple Donation Benefits"); - sdb_donationflag = CreateConVar("sdb_donationflag", "a", "Flag ALREADY given to donators. Must be in char format"); - - /** - Create the enable/disable donator console variables - */ - sdb_joinsound_enabled = CreateConVar("sdb_joinsound_enabled", "1", "Enable/Disable donator join sound"); - sdb_joinpubmsg_enabled = CreateConVar("sdb_joinpubmsg_enabled", "1", "Enable/Disable public donator join message (replaces: as connected)"); - sdb_joinprivmsg_enabled = CreateConVar("sdb_joinprivmsg_enabled", "1", "Enable/Disable private donator join message (sent only to donator)"); - sdb_chatcolors_enabled = CreateConVar("sdb_chatcolors_enabled", "1", "Enable/Disable donator chat colors"); - sdb_immunity_enabled = CreateConVar("sdb_immunity_enabled", "1", "Enable/Disable donator round end immunity"); - sdb_ubercharge_enabled = CreateConVar("sdb_ubercharge_enabled", "1", "Enable/Disable donator medics starting with ubercharge"); - sdb_givehealth_enabled = CreateConVar("sdb_givehealth_enabled", "1", "Enable/Disable donator instant health bonus"); - sdb_nofalldmg_enabled = CreateConVar("sdb_nofalldmg_enabled", "1", "Enable/Disable no fall damage for donators"); - sdb_fastheavy_enabled = CreateConVar("sdb_fastheavy_enabled", "1", "Enable/Disable donator heavies moving faster while spinning"); - sdb_swapteam_enabled = CreateConVar("sdb_swampteam_enabled", "1", "Enable/Disable donator swap team ability"); - - /** - Create the donator setting console variables - */ - sdb_soundfile = CreateConVar("sdb_soundfile", "custom/donatorjoin.mp3", "The location of sound file"); - sdb_chatcolor = CreateConVar("sdb_chatcolor", "green", "Color to use for donator chat. Valid colors are green and lightgreen"); - sdb_uberlevel = CreateConVar("sdb_uberlevel", "0.5", "Uberlevel to give donator medic at spawn. 1.0 = full uber", _, true, 0.0, true, 1.0); - sdb_healthcount = CreateConVar("sdb_healthcount", "1", "Number of times a donator can use use instant health per life"); - sdb_healthbonus = CreateConVar("sdb_healthbonus", "100", "The amount of health to heal the donator"); - sdb_heavymultiplier = CreateConVar("sdb_heavyspeed", "0.5", "The speed multiplier for the fast heavy. Based on running speed. 1.0 = running speed. (Game Default is 0.20)", _, true, 0.0, true, 1.0); - - /** - Hook dukehacks calls - */ - dhAddClientHook(CHK_TakeDamage, Hacks_TakeDamageHook); - dhAddClientHook(CHK_PreThink, Hacks_PreThinkHook); - - /** - Hook the console variables if they change - */ - HookConVarChange(sdb_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_donationflag, ConVarSettingsChanged); - HookConVarChange(sdb_joinsound_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_joinpubmsg_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_joinprivmsg_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_chatcolors_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_immunity_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_ubercharge_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_givehealth_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_nofalldmg_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_swapteam_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_fastheavy_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_soundfile, ConVarSettingsChanged); - HookConVarChange(sdb_chatcolor, ConVarSettingsChanged); - HookConVarChange(sdb_uberlevel, ConVarSettingsChanged); - HookConVarChange(sdb_healthcount, ConVarSettingsChanged); - HookConVarChange(sdb_healthbonus, ConVarSettingsChanged); - HookConVarChange(sdb_heavymultiplier, ConVarSettingsChanged); - - /** - Register the commands - */ - RegConsoleCmd("sm_swapteams", Command_SwapTeam, "sm_swapteams <[0]instant/[1]queued>: Swaps your team to the other team"); - RegConsoleCmd("sm_ihealth", Command_InstantHealth, "sm_ihealth: Gives you a instant health pack"); - RegAdminCmd("sm_teaser", Command_Teaser, ADMFLAG_GENERIC,"sm_teaser <[0]add/[1]remove>: Gives temporary donator privilages to a player"); - RegConsoleCmd("say", Command_Say); - - RegConsoleCmd("sm_test", Command_TEST); - - /** - Load the translations - */ - LoadTranslations("common.phrases"); - LoadTranslations("simpledonatorbenefits.phrases"); - - /** - Load or create the config file - */ - AutoExecConfig(true, "plugin.simpledonatorbenefits"); - LogAction(0, -1, "[SDB] Simple Donator Benefits is loaded."); -} - -public OnAllPluginsLoaded() -{ - //something -} - -public OnLibraryRemoved(const String:name[]) -{ - //something -} - -public OnConfigsExecuted() -{ - /** - Load up all the variable defaults - */ - LoadUpVariables(); - - /** - If the join sound is enabled, prep the sound files - */ - if (g_bIsJoinSoundEnabled) - PrepSoundFile(); - - /** - Log our activity - */ - if (g_bIsEnabled) - LogAction(0, -1, "Simple Donation Benefits is ENABLED"); - else - LogAction(0, -1, "Simple Donation Benefits is DISABLED"); -} - -public OnClientPostAdminCheck(client) -{ - - /** - Check if the client is a donator - */ - if (SM_IsValidAdmin(client, g_sCharDonatorFlag)) - { - - /** - They are, so we set the player array to true and start a timer for the sound or add - */ - g_aPlayers[client][bIsDonator] = true; - if (g_bIsJoinSoundEnabled || g_bIsJoinPrivMsgEnabled) - { - CreateTimer(10.0, Timer_DonatorJoined, client, TIMER_FLAG_NO_MAPCHANGE); - } - } - else - { - /** - They aren't, so we set the player array to false - */ - g_aPlayers[client][bIsDonator] = false; - } -} - -public OnClientDisconnect_Post(client) -{ - - /** - Clean up the player variables - */ - CleanUpPlayer(client); -} - -public Action:Command_SwapTeam(client, args) -{ - - /** - Make sure we are enabled - */ - if (!g_bIsEnabled || !g_bIsSwapTeamEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the command is not started by the server - */ - if (client == 0) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure the player is a donator - */ - if (!g_aPlayers[client][bIsDonator]) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Lets make sure the client is one a team we can swap. - If he is we set the global array to the opposite team. - */ - new iTeam = GetClientTeam(client); - if (iTeam == g_aCurrentTeams[Team1]) - { - g_aPlayers[client][iNewTeam] = g_aCurrentTeams[Team2]; - } - else if (iTeam == g_aCurrentTeams[Team2]) - { - g_aPlayers[client][iNewTeam] = g_aCurrentTeams[Team1]; - } - else - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "InValidTeam", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check to see if we have command arguments. - */ - if (GetCmdArgs()) - { - - /** - We do, so lets get it and see if the client wants to be switched instantly or queued for death. - */ - decl String:sArg[5]; - GetCmdArg(1, sArg, sizeof(sArg)); - new iWantsQue = StringToInt(sArg); - if (iWantsQue && !g_aPlayers[client][bQueue]) - { - - /** - He wants the que and isn't already in it, set the global array. - */ - g_aPlayers[client][bQueue] = true; - ReplyToCommand(client, "\x01\x04[STM]\x01 %T", "PlayerQueue", LANG_SERVER); - } - else if (!iWantsQue) - { - - /** - He wants to be switched right now, lets call the stock function. - */ - SM_MovePlayer(client, g_aPlayers[client][iNewTeam]); - } - } - else - { - - /** - There are no command arguments so we build and display the swap menu. - */ - new Handle:hPlayerMenu = BuildSwapModeMenu(); - DisplayMenu(hPlayerMenu, client, MENU_TIME_FOREVER); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_InstantHealth(client, args) -{ - - /** - Make sure we are enabled - */ - if (!g_bIsEnabled || !g_bIsGiveHealthEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the command is not started by the server - */ - if (client == 0) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure the player is a donator - */ - if (!g_aPlayers[client][bIsDonator]) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check health count to see if the player has reached the max - */ - if (g_aPlayers[client][iHealthCount] >= g_iHealthCount) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "ReachedCount", LANG_SERVER); - return Plugin_Handled; - } - - /** - Get the class of the player and the max health for that class - */ - new iHealth = GetClientHealth(client); - new TFClassType:PlayerClass = TF2_GetPlayerClass(client); - new iMaxHealth = g_iClassMaxHealth[PlayerClass]; - - /** - Check to see if the player is at the max health of the class - */ - if (iHealth >= iMaxHealth) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "AtMaxHealth", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check the current health - */ - if (iHealth + g_iHealthBonus >= iMaxHealth) - { - - /** - Raise them to max health if the current health + bonus would go above it - */ - SetEntityHealth(client, iMaxHealth); - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "ToMaxHealth", LANG_SERVER); - } - else - { - - /** - Give them the instant health bonus - */ - SetEntityHealth(client, iHealth + g_iHealthBonus); - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "HealthBonus", LANG_SERVER); - } - - /** - Increase the count - */ - g_aPlayers[client][iHealthCount] += 1; - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_Teaser(client, args) -{ - - /** - Make sure we are enabled - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Check to see if we have command arguments. - */ - new iCmdArgs = GetCmdArgs(); - if (iCmdArgs == 0) - { - - /** - We don't so display the player menu. - */ - new Handle:hPlayerMenu = BuildPlayerMenu(); - DisplayMenu(hPlayerMenu, client, MENU_TIME_FOREVER); - return Plugin_Handled; - } - - /** - We have some arguments, see if we can find the player - */ - decl String:sPlayer[64]; - GetCmdArg(1, sPlayer, sizeof(sPlayer)); - new iTarget = FindTarget(client, sPlayer, true, true); - if (iTarget == -1 || !IsClientInGame(iTarget)) - { - - /** - We don't know who this is, so display the player menu. - */ - new Handle:hPlayerMenu = BuildPlayerMenu(); - DisplayMenu(hPlayerMenu, client, MENU_TIME_FOREVER); - } - else - { - /** - We found the player, see if we are supposed to turn it on or off. - */ - if (iCmdArgs >= 2) - { - decl String:sOn[3]; - GetCmdArg(2, sOn, sizeof(sOn)); - if (StringToInt(sOn)) - { - - /** - Turn temp benefits on. - */ - g_aPlayers[iTarget][bIsDonator] = true; - } - else - { - - /** - Turn temp benefits on. - */ - g_aPlayers[iTarget][bIsDonator] = false; - } - } - else - { - - /** - We don't know what to do, so just turn it on. - */ - g_aPlayers[iTarget][bIsDonator] = true; - } - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_Say(client, args) -{ - - /** - Make sure we are enabled. - */ - if (client == 0 || IsChatTrigger() || !g_bIsChatColorsEnabled || !g_bIsEnabled) - { - return Plugin_Continue; - } - - /** - Check the client to see if they are a donator. - */ - if (g_aPlayers[client][bIsDonator]) - { - - /** - The client is, so get the chat message and strip it down. - */ - decl String:sArg[CHAT_MAX_MESSAGE_LENGTH], - String:sChatMsg[CHAT_MAX_MESSAGE_LENGTH]; - new bool:bAlive = IsPlayerAlive(client); - GetCmdArgString(sArg, sizeof(sArg)); - StripQuotes(sArg); - TrimString(sArg); - new startidx; - if (sArg[strlen(sArg)-1] == '"') - { - sArg[strlen(sArg)-1] = '\0'; - startidx = 1; - } - - /** - Bug out if they are using the admin chat symbol (admin chat). - */ - if (sArg[startidx] == CHAT_SYMBOL) - { - return Plugin_Continue; - } - - /** - Format the message. - */ - FormatMessage(client, 0, bAlive, sChatMsg, sArg); - - /** - Send the message. - */ - SayText2(0, client, sChatMsg); - - /** - We are done, bug out, and stop the original chat message. - */ - return Plugin_Stop; - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Hacks_TakeDamageHook(client, attacker, inflictor, Float:damage, &Float:multiplier, damagetype) -{ - - /** - Make sure we are enabled and the client is a donator. - */ - if (g_bIsEnabled && g_bIsNoFallDmgEnabled && g_aPlayers[client][bIsDonator]) - { - - /** - Check for fall damage. - */ - if (damagetype & DMG_FALL) - { - - /** - Cancel the fall damage and bug out. - */ - multiplier *= 0.0; - return Plugin_Changed; - } - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Hacks_PreThinkHook(client) -{ - - /** - Make sure we are enabled and the client is a donator. - */ - if (!g_bIsEnabled || !g_bIsFastHeayEnabled || !g_aPlayers[client][bIsDonator]) - { - return Plugin_Continue; - } - - /** - Check the players class. We are looking for the heavy. - */ - new TFClassType:PlayerClass = TF2_GetPlayerClass(client); - if (PlayerClass == TFClass_Heavy) - { - - /** - We have a heavy, lets check the weapon. - */ - decl String:sWeaponCurrent[64]; - GetClientWeapon(client, sWeaponCurrent, sizeof(sWeaponCurrent)); - if (StrEqual(sWeaponCurrent, "tf_weapon_minigun", false)) - { - - /** - We have a minigun, check the heavies current weapon state to see if it's spinning. - */ - new iWeapon = GetPlayerWeaponSlot(client, 0); - new iWeaponState = GetEntProp(iWeapon, Prop_Send, "m_iWeaponState"); - if (iWeaponState > 0) - { - - /** - He is spinning, so lets change the heavies speed. - */ - new Float:fMaxSpeed = FloatMul(g_fHeavyMultiplier, float(g_fClassMaxSpeed[PlayerClass])); - SetEntPropFloat(client, Prop_Send, "m_flMaxspeed", fMaxSpeed); - } - } - } - - /** - We are done, bug out. - */ - // use Plugin_Continue (other options are ignored on PreThink hook) - return Plugin_Continue; -} - -public Action:HookPlayerConnect(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (!g_bIsEnabled || !g_bIsJoinPubMsgEnabled || !dontBroadcast) - { - return Plugin_Continue; - } - - /** - Get our event variables and check the client. - */ - new iUserId = GetEventInt(event,"userid"); - new iClient = GetClientOfUserId(iUserId); - if (iClient != 0) - { - - /** - Get the info on the client and format the message. - */ - decl String:sClientName[255], - String:sAuthID[255], - String:sMsg[1024]; - - GetEventString(event, "name", sClientName, sizeof(sClientName)); - GetClientAuthString(iClient, sAuthID, sizeof(sAuthID)); - Format(sMsg, sizeof(sMsg), "%T", "PublicJoinMessage", LANG_SERVER, sClientName); - - /** - Print the message to the clients and do the normal functions. - */ - for (new i = 1; i <= MaxClients; i++) - { - if(IsClientConnected(i) && IsClientInGame(i)) - { - PrintToChat(i,"\x01\x05%s", sMsg); - PrintToConsole(i,"%s has connected.", sClientName); - } - } - LogToGame("\"%s<%d><%s><>\" entered the game", sClientName, iUserId, sAuthID); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public HookPlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled && g_bIsUberChargeEnabled) - { - - /** - Get the event variables and check the class for medic - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - if (TF2_GetPlayerClass(iClient) == TFClass_Medic) - { - - /** - Start a timer to get the medic the uber boost - */ - CreateTimer(0.25, Timer_PlayerUberDelay, iClient, TIMER_FLAG_NO_MAPCHANGE); - } - } -} - -public HookPlayerClass(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled && g_bIsUberChargeEnabled) - { - - /** - Get the event variables and check the class for medic - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - if (TF2_GetPlayerClass(iClient) == TFClass_Medic) - { - - /** - Start a timer to get the medic the uber boost - */ - CreateTimer(0.25, Timer_PlayerUberDelay, iClient, TIMER_FLAG_NO_MAPCHANGE); - } - } -} - -public HookPlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled || g_bIsSwapTeamEnabled) - { - - /** - Get the event variables - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - new String:sWeapon[256]; - GetEventString(event, "weapon", sWeapon, sizeof(sWeapon)); - - /** - Bug out if world killed him. Means he changed team or something - */ - if (StrEqual(sWeapon, "world", false)) - { - g_aPlayers[iClient][bQueue] = false; - return; - } - - /** - If he is queued up, swap him - */ - if (g_aPlayers[iClient][bQueue]) - { - SM_MovePlayer(iClient, g_aPlayers[iClient][iNewTeam]); - } - } -} - -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled || g_bIsSwapTeamEnabled) - { - - /** - Get the event variables - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - - /** - If he is queued up, clear the status - */ - if (g_aPlayers[iClient][bQueue]) - { - g_aPlayers[iClient][bQueue] = false; - } - } -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set our variables. - */ - g_bRoundEnd = false; - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled && g_bIsImmuntyEnabled) - { - - /** - Get rid of their immunity. - */ - ProcessRoundEndImmunity(false); - } -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set our variables. - */ - g_bRoundEnd = true; - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled && g_bIsImmuntyEnabled) - { - - /** - Give them their immunity. - */ - ProcessRoundEndImmunity(true); - } -} - -public Action:Timer_DonatorJoined(Handle:timer, any:client) -{ - - /** - Make sure sounds are enabled. - */ - if (g_bIsEnabled && g_bIsJoinSoundEnabled) - { - EmitSoundToClient(client, g_sSoundFile); - } - - /** - Make sure private messages are enabled. - */ - if (g_bIsJoinPrivMsgEnabled) - { - - /** - Send messages to the client. - */ - decl String:sMsg[1024]; - Format(sMsg, sizeof(sMsg), "%T", "PrivateJoinMessage", LANG_SERVER); - PrintToChat(client,"\x01\x05%s", sMsg); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Timer_PlayerUberDelay(Handle:timer, any:client) -{ - - /** - Make sure the client is still in game. - */ - if (IsClientInGame(client)) - { - - /** - Make sure the client is still a medic. - */ - if (TF2_GetPlayerClass(client) == TFClass_Medic) - { - - /** - Get the medgun weapon index - */ - new iIndex = GetPlayerWeaponSlot(client, 1); - if (iIndex > 0) - { - - /** - Set the uber level with the bonus. - */ - SetEntPropFloat(iIndex, Prop_Send, "m_flChargeLevel", g_fUberLevel); - } - } - } -} - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (convar == sdb_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsEnabled = false; - } - else - { - g_bIsEnabled = true; - } - } - else if (convar == sdb_donationflag) - { - Format(g_sCharDonatorFlag, sizeof(g_sCharDonatorFlag), "%s", newValue); - } - else if (convar == sdb_soundfile) - { - Format(g_sSoundFile, sizeof(g_sSoundFile), "%s", newValue); - } - else if (convar == sdb_joinsound_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsJoinSoundEnabled = false; - } - else - { - g_bIsJoinSoundEnabled = true; - } - } - else if (convar == sdb_joinpubmsg_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsJoinPubMsgEnabled = false; - } - else - { - g_bIsJoinPubMsgEnabled = true; - } - } - else if (convar == sdb_joinprivmsg_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsJoinPrivMsgEnabled = false; - } - else - { - g_bIsJoinPrivMsgEnabled = true; - } - } - else if (convar == sdb_chatcolors_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsChatColorsEnabled = false; - } - else - { - g_bIsChatColorsEnabled = true; - } - } - else if (convar == sdb_immunity_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsImmuntyEnabled = false; - } - else - { - g_bIsImmuntyEnabled = true; - } - } - else if (convar == sdb_ubercharge_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsUberChargeEnabled = false; - } - else - { - g_bIsUberChargeEnabled = true; - } - } - else if (convar == sdb_givehealth_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsGiveHealthEnabled = false; - } - else - { - g_bIsGiveHealthEnabled = true; - } - } - else if (convar == sdb_nofalldmg_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsNoFallDmgEnabled = false; - } - else - { - g_bIsNoFallDmgEnabled = true; - } - } - else if (convar == sdb_fastheavy_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsFastHeayEnabled = false; - } - else - { - g_bIsFastHeayEnabled = true; - } - } - else if (convar == sdb_swapteam_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsSwapTeamEnabled = false; - } - else - { - g_bIsSwapTeamEnabled = true; - } - } - else if (convar == sdb_chatcolor) - { - Format(g_sChatColor, sizeof(g_sChatColor), "%s", newValue); - } - else if (convar == sdb_uberlevel) - { - g_fUberLevel = StringToFloat(newValue); - } - else if (convar == sdb_healthcount) - { - g_iHealthCount = StringToInt(newValue); - } - else if (convar == sdb_healthbonus) - { - g_iHealthBonus = StringToInt(newValue); - } - else if (convar == sdb_heavymultiplier) - { - g_fHeavyMultiplier = StringToFloat(newValue); - } -} - -stock LoadUpVariables() -{ - g_bIsEnabled = GetConVarBool(sdb_enabled); - g_bIsJoinSoundEnabled = GetConVarBool(sdb_enabled); - g_bIsJoinPubMsgEnabled = GetConVarBool(sdb_enabled); - g_bIsJoinPrivMsgEnabled = GetConVarBool(sdb_enabled); - g_bIsChatColorsEnabled = GetConVarBool(sdb_enabled); - g_bIsImmuntyEnabled = GetConVarBool(sdb_enabled); - g_bIsUberChargeEnabled = GetConVarBool(sdb_enabled); - g_bIsGiveHealthEnabled = GetConVarBool(sdb_enabled); - g_bIsNoFallDmgEnabled = GetConVarBool(sdb_enabled); - g_bIsFastHeayEnabled = GetConVarBool(sdb_enabled); - g_bIsSwapTeamEnabled = GetConVarBool(sdb_enabled); - GetConVarString(sdb_donationflag, g_sCharDonatorFlag, sizeof(g_sCharDonatorFlag)); - GetConVarString(sdb_soundfile, g_sSoundFile, sizeof(g_sSoundFile)); - GetConVarString(sdb_chatcolor, g_sChatColor, sizeof(g_sChatColor)); - g_bRoundEnd = false; - g_iHealthBonus = GetConVarInt(sdb_healthbonus); - g_iHealthCount = GetConVarInt(sdb_healthcount); - g_fHeavyMultiplier = GetConVarFloat(sdb_heavymultiplier); - g_fUberLevel = GetConVarFloat(sdb_uberlevel); -} - -stock PrepSoundFile() -{ - decl String:buffer[PLATFORM_MAX_PATH]; - PrecacheSound(g_sSoundFile, true); - Format(buffer, sizeof(buffer), "sound/%s", g_sSoundFile); - AddFileToDownloadsTable(buffer); -} - -stock CleanUpPlayer(client) -{ - g_aPlayers[client][bIsDonator] = false; - g_aPlayers[client][bQueue] = false; - g_aPlayers[client][bImmune] = false; - g_aPlayers[client][iNewTeam] = 0; - g_aPlayers[client][iHealthCount] = 0; -} - -stock ProcessRoundEndImmunity(bool:give) -{ - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][bIsDonator]) - { - if (give) - { - SetEntProp(i, Prop_Data, "m_takedamage", 0, 1); - g_aPlayers[i][bImmune] = true; - } - else - { - SetEntProp(i, Prop_Data, "m_takedamage", 2, 1); - g_aPlayers[i][bImmune] = false; - } - } - } -} - -stock FormatMessage(iClient, iTeam, bool:bAlive, String:sChatMsg[], const Sting:sMessage[]) -{ - decl String:sDead[10], - String:sTeam[10], - String:sClientName[64]; - GetClientName(iClient, sClientName, sizeof(sClientName)); - if (iTeam != 0) - Format(sTeam, sizeof(sTeam), "(TEAM) "); - else - Format(sTeam, sizeof(sTeam), ""); - if (bAlive) - Format(sDead, sizeof(sDead), ""); - else - Format(sDead, sizeof(sDead), "*DEAD* "); - if (StrContains(g_sChatColor, "light", false) == -1) - Format(sChatMsg, CHAT_MAX_MESSAGE_LENGTH, "\x01%s%s\x03%s \x01: \x05%s", sDead, sTeam, sClientName, sMessage); - else - Format(sChatMsg, CHAT_MAX_MESSAGE_LENGTH, "\x01%s%s\x03%s \x01: \x04%s", sDead, sTeam, sClientName, sMessage); -} - -stock SayText2(target, author, const String:message[]) -{ - new Handle:hBf; - if (target == 0) - hBf = StartMessageAll("SayText2"); - else - hBf = StartMessageOne("SayText2", target); - if (hBf != INVALID_HANDLE) - { - BfWriteByte(hBf, author); - BfWriteByte(hBf, true); - BfWriteString(hBf, message); - EndMessage(); - } -} - -stock ProcessAdmins() -{ - for (new i = 1; i <= MaxClients; i++) - { - if (SM_IsValidAdmin(i, g_sCharDonatorFlag)) - { - g_aPlayers[i][bDonator] = true; - } - else - { - g_aPlayers[i][bDonator] = false; - } - } -} - -stock ProcessLate() -{ - if (g_bIsEnabled) - { - ProcessAdmins(); - PrepSoundFile(); - if (g_bRoundEnd && g_bIsImmuntyEnabled) - { - ProcessRoundEndImmunity(true); - } - if (!g_bIsImmuntyEnabled) - { - ProcessRoundEndImmunity(false); - } - } - else - { - ProcessRoundEndImmunity(false); - } -} - -public Menu_SwapMode(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, 64); - if (StringToInt(sSelection)) - g_aPlayers[param1][bQueue] = false; - else - g_aPlayers[param1][bQueue] = true; - if (!g_aPlayers[param1][bQueue]) - SM_MovePlayer(param1, g_aPlayers[param1][iNewTeam]); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -public Menu_SelectPlayer(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[256]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - new iTarget = GetClientOfUserId(StringToInt(sSelection)); - if (g_aPlayers[iTarget][bIsDonator]) - g_aPlayers[iTarget][bIsDonator] = false; - else - g_aPlayers[iTarget][bIsDonator] = true; - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -stock Handle:BuildSwapModeMenu() -{ - new Handle:menu = CreateMenu(Menu_SwapMode); - SetMenuTitle(menu, "Select When to Swap:"); - AddMenuItem(menu, "0", "Instantly (Kills)"); - AddMenuItem(menu, "1", "Queue on next death"); - SetMenuExitBackButton(menu, false); - return menu; -} - -stock Handle:BuildPlayerMenu() -{ - new Handle:menu = CreateMenu(Menu_SelectPlayer); - AddTargetsToMenu(menu, 0, true, false); - SetMenuTitle(menu, "Select A Player:"); - SetMenuExitBackButton(menu, true); - return menu; -} - -public Action:Command_TEST(client, args) -{ - -} \ No newline at end of file diff --git a/Simple Plugins Core/addons/sourcemod/scripting/simple-messagesuppression.sp b/Simple Plugins Core/addons/sourcemod/scripting/simple-messagesuppression.sp deleted file mode 100644 index f7725a4..0000000 --- a/Simple Plugins Core/addons/sourcemod/scripting/simple-messagesuppression.sp +++ /dev/null @@ -1,227 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Message Suppression -Description: - Blocks Specific Message Outputs -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include -#include - -#define SUPPRESS_VERSION "1.1.$Rev$" - -public Plugin:myinfo = -{ - name = "Simple Message Suppression", - author = "FlyingMongoose, psychonic", - description = "Blocks Specific Message Outputs", - version = SUPPRESS_VERSION, - url = "http://www.simple-plugins.com/" -} - -new Handle:cvarBlockSpectateMessage; -new Handle:cvarBlockDisconnectMessage; -new Handle:cvarBlockConnectMessage; -new Handle:cvarAdminShowMessages; -new iSpecTeam = 1; - - -public OnPluginStart() -{ - CreateConVar("suppress_version", SUPPRESS_VERSION, _, FCVAR_PLUGIN|FCVAR_NOTIFY|FCVAR_REPLICATED|FCVAR_SPONLY|FCVAR_DONTRECORD); - cvarBlockSpectateMessage = CreateConVar("sm_blockspectatemessage", "1", "If enabled it blocks the join team message if an administrator joins spectator", FCVAR_PLUGIN, true, 0.0, true, 1.0); - cvarBlockDisconnectMessage = CreateConVar("sm_blockdisconnectmessage", "1", "Blocks the disconnect message", FCVAR_PLUGIN, true, 0.0, true, 1.0); - cvarBlockConnectMessage = CreateConVar("sm_blockconnectmessage", "1", "If enabled it blocks the player connection message.", FCVAR_PLUGIN, true, 0.0, true, 1.0); - cvarAdminShowMessages = CreateConVar("sm_adminshowmessages", "1", "Shows disconnect/connect/team join messages for admins only (if disconnect message is set to be blocked)", FCVAR_PLUGIN, true, 0.0, true, 1.0); - HookEvent("player_team", ev_PlayerTeam, EventHookMode_Pre); - HookEvent("player_disconnect", ev_PlayerDisconnect, EventHookMode_Pre); - HookEvent("player_connect", ev_PlayerConnect, EventHookMode_Pre); - - new String:game_folder[64]; - GetGameFolderName(game_folder, sizeof(game_folder)) - - if (StrContains(game_folder, "insurgency", false) != -1) - { - iSpecTeam = 3; - } - else - { - new String:game_description[64]; - GetGameDescription(game_description, sizeof(game_description), true); - if (StrContains(game_description, "Insurgency", false) != -1) - { - iSpecTeam = 3; - } - } - - AutoExecConfig(true, "suppressmessage", "sourcemod"); -} - -public Action:ev_PlayerTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (GetConVarBool(cvarBlockSpectateMessage)) - { - if (!dontBroadcast && !GetEventBool(event, "silent")) - { - new iUserId = GetEventInt(event, "userid"); - new iClient = GetClientOfUserId(iUserId); - new iTeam = GetEventInt(event, "team"); - - if (iTeam == iSpecTeam && GetAdminFlag(GetUserAdmin(iClient), Admin_Kick)) - { - new iOldTeam = GetEventInt(event, "oldteam"); - new bool:bDisconnect = GetEventBool(event, "disconnect"); - new bool:bAutoteam = GetEventBool(event, "autoteam"); - decl String:strName[50]; - GetEventString(event, "name", strName, sizeof(strName)); - - if (iClient != 0) - { - if (GetConVarInt(cvarAdminShowMessages) == 1) - { - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i) && GetUserAdmin(i) != INVALID_ADMIN_ID) - { - PrintToChat(i,"%N joined team Spectator.", iClient); - PrintToConsole(i,"%N joined team Spectator.", iClient); - } - } - } - } - - new Handle:hEvent = CreateEvent("player_team"); - SetEventInt(hEvent, "userid", iUserId); - SetEventInt(hEvent, "team", iTeam); - SetEventInt(hEvent, "oldteam", iOldTeam); - SetEventBool(hEvent, "disconnect", bDisconnect); - SetEventBool(hEvent, "autoteam", bAutoteam); - SetEventBool(hEvent, "silent", true); - SetEventString(hEvent, "name", strName); - - FireEvent(hEvent, true); - - return Plugin_Handled; - } - } - } - return Plugin_Continue; -} -public Action:ev_PlayerConnect(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (GetConVarBool(cvarBlockConnectMessage)) - { - if (!dontBroadcast) - { - decl String:strName[50]; - GetEventString(event, "name", strName, sizeof(strName)); - new iIndex = GetEventInt(event, "index"); - new iUserId = GetEventInt(event, "userid"); - new iClient = GetClientOfUserId(iUserId); - decl String:strNetworkId[50]; - GetEventString(event, "networkid", strNetworkId, sizeof(strNetworkId)); - decl String:strAddress[50]; - GetEventString(event, "address", strAddress, sizeof(strAddress)); - - if (iClient != 0) - { - if (GetConVarInt(cvarAdminShowMessages) == 1) - { - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i) && GetUserAdmin(i) != INVALID_ADMIN_ID) - { - PrintToChat(i,"%N has connected.", iClient); - PrintToConsole(i,"%N has connected.", iClient); - } - } - } - } - - new Handle:hEvent = CreateEvent("player_connect"); - SetEventString(hEvent, "name", strName); - SetEventInt(hEvent, "index", iIndex); - SetEventInt(hEvent, "userid", iUserId); - SetEventString(hEvent, "networkid", strNetworkId); - SetEventString(hEvent, "address", strAddress); - - FireEvent(hEvent, true); - - return Plugin_Handled; - } - } - return Plugin_Continue; -} -public Action:ev_PlayerDisconnect(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (GetConVarBool(cvarBlockDisconnectMessage)) - { - if (!dontBroadcast) - { - new iUserId = GetEventInt(event, "userid"); - new iClient = GetClientOfUserId(iUserId); - decl String:strReason[50]; - GetEventString(event, "reason", strReason, sizeof(strReason)); - decl String:strName[50]; - GetEventString(event, "name", strName, sizeof(strName)); - decl String:strNetworkId[50]; - GetEventString(event, "networkid", strNetworkId, sizeof(strNetworkId)); - - if (iClient != 0) - { - if (GetConVarInt(cvarAdminShowMessages) == 1) - { - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i) && GetUserAdmin(i) != INVALID_ADMIN_ID) - { - PrintToChat(i, "%N has left the server.", iClient); - PrintToConsole(i, "Dropped %N from server (Disconnect by user.)", iClient); - } - } - } - } - - new Handle:hEvent = CreateEvent("player_disconnect"); - SetEventInt(hEvent, "userid", iUserId); - SetEventString(hEvent, "reason", strReason); - SetEventString(hEvent, "name", strName); - SetEventString(hEvent, "networkid", strNetworkId); - - FireEvent(hEvent, true); - - return Plugin_Handled; - } - } - - return Plugin_Continue; -} \ No newline at end of file diff --git a/Simple Plugins Core/addons/sourcemod/scripting/simple-plugins.sp b/Simple Plugins Core/addons/sourcemod/scripting/simple-plugins.sp index 4462b41..32aa5c7 100644 --- a/Simple Plugins Core/addons/sourcemod/scripting/simple-plugins.sp +++ b/Simple Plugins Core/addons/sourcemod/scripting/simple-plugins.sp @@ -222,7 +222,7 @@ public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) g_bTeamsSwitched = false; } -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) +public Action:HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) { /** @@ -256,7 +256,7 @@ public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcas if (g_CurrentMod == GameType_DOD || g_CurrentMod == GameType_L4D || g_CurrentMod == GameType_TF) { new String:sClientName[MAX_NAME_LENGTH + 1]; - GetClientName(client, sClientName, sizeof(sClientName)); + GetClientName(iClient, sClientName, sizeof(sClientName)); SetEventBool(hEvent, "autoteam", GetEventBool(event, "autoteam")); SetEventBool(hEvent, "silent", true); SetEventString(hEvent, "name", sClientName); diff --git a/Simple Plugins Core/addons/sourcemod/scripting/simple-roundimmunity.sp b/Simple Plugins Core/addons/sourcemod/scripting/simple-roundimmunity.sp deleted file mode 100644 index 5f0bca3..0000000 --- a/Simple Plugins Core/addons/sourcemod/scripting/simple-roundimmunity.sp +++ /dev/null @@ -1,947 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Round Immunity -Description: - Gives admins immunity during certain rounds -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or any later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#pragma semicolon 1 -#include -#include -#undef REQUIRE_EXTENSIONS -#undef AUTOLOAD_EXTENSIONS -#include -#include -#define REQUIRE_EXTENSIONS -#define AUTOLOAD_EXTENSIONS - -#define PLUGIN_VERSION "1.1.$Rev$" -#define SPECTATOR 1 -#define TEAM_RED 2 -#define TEAM_BLUE 3 - -#define COLOR_GREEN 0 -#define COLOR_BLACK 1 -#define COLOR_RED 2 -#define COLOR_BLUE 3 -#define COLOR_TEAM 4 -#define COLOR_RAINBOW 5 -#define COLOR_NONE 6 - -#define PLAYERCOND_SLOWED (1<<0) //1 -#define PLAYERCOND_ZOOMED (1<<1) //2 -#define PLAYERCOND_DISGUISING (1<<2) //4 -#define PLAYERCOND_DISGUISED (1<<3) //8 -#define PLAYERCOND_SPYCLOAK (1<<4) //16 -#define PLAYERCOND_UBERED (1<<5) //32 -#define PLAYERCOND_TELEPORTTRAIL (1<<6) //64 -#define PLAYERCOND_TAUNT (1<<7) //128 -// (1<<8) //256 -// (1<<9) //512 -#define PLAYERCOND_TELEPORTFLASH (1<<10) //1024 -#define PLAYERCOND_KRUBER (1<<11) //2048 -// (1<<12) //4096 -// (1<<13) //8192 -#define PLAYERCOND_BONKED (1<<14) //16384 (blame Neph if it doesn't work) -#define PLAYERCOND_BONKEDORDRINKSLOWDOWN (1<<15) //32768 -#define PLAYERCOND_HEALING (1<<16) //65536 -#define PLAYERCOND_BURNING (1<<17) //131072 -#define PLAYERCOND_FULLYCHARGEDBYMEDIC (1<<18) //262144 - -enum e_Cookies -{ - bEnabled, - iColor, - iMode -}; - -enum e_ColorNames -{ - Green, - Black, - Red, - Blue -}; - -enum e_ColorValues -{ - iRed, - iGreen, - iBlue -}; - -enum e_PlayerData -{ - Handle:hGodModeTimer, - Handle:hColorTimer, - bool:bIsAdmin, - bool:bIsImmune, - iCycleColor -}; - -/** - Global convar handles - */ -new Handle:sri_charadminflag = INVALID_HANDLE; -new Handle:sri_enabled = INVALID_HANDLE; -new Handle:sri_cookie_enabled = INVALID_HANDLE; -new Handle:sri_cookie_color = INVALID_HANDLE; -new Handle:sri_cookie_mode = INVALID_HANDLE; - -/** - Player arrays - */ -new g_aPlayers[MAXPLAYERS + 1][e_PlayerData]; -new g_aClientCookies[MAXPLAYERS + 1][e_Cookies]; - -/** - Global bools - */ -new bool:g_bLoadedLate = false; -new bool:g_bIsEnabled = true; -new bool:g_bRoundEnd = false; -new bool:g_bUseDukehacks = false; -new bool:g_bUseClientprefs = false; - -/** - Global strings/integers/floats - */ -new String:g_sCharAdminFlag[32]; -new g_iColors[e_ColorNames][e_ColorValues]; -new g_iClassMaxHealth[TFClassType] = {0, 125, 125, 200, 175, 150, 300, 175, 125, 125}; - -public Plugin:myinfo = -{ - name = "Simple Round Immunity", - author = "Simple Plugins", - description = "Gives admins immunity during certain rounds", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -} - -bool:AskPluginLoad(Handle:myself, bool:late, String:error[], err_max) -{ - g_bLoadedLate = late; - return true; -} - -public OnPluginStart() -{ - - /** - Create console variables - */ - CreateConVar("sri_version", PLUGIN_VERSION, "Simple Round Immunity", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - sri_enabled = CreateConVar("sri_enabled", "1", "Enable/Disable Admin immunity during certain round."); - sri_charadminflag = CreateConVar("sri_charadminflag", "a", "Admin flag to use for immunity (only one). Must be a in char format."); - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook some events and check extensions - */ - decl String:sExtError[256]; - LogAction(0, -1, "[SRI] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_spawn", HookPlayerSpawn, EventHookMode_Post); - HookEvent("player_hurt", HookPlayerHurt, EventHookMode_Pre); - switch (g_CurrentMod) - { - case GameType_CSS: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - new iExtStatus = GetExtensionFileStatus("game.cstrike.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SRI] Required extension was not found."); - LogAction(0, -1, "[SRI] Plugin FAILED TO LOAD."); - SetFailState("Required extension was not found."); - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SRI] Required extension is loaded with errors."); - LogAction(0, -1, "[SRI] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SRI] Plugin FAILED TO LOAD."); - SetFailState("Required extension is loaded with errors."); - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SRI] Required css extension is loaded."); - } - } - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_PostNoCopy); - HookUserMessage(GetUserMessageId("TextMsg"), UserMessageHook_Class, true); - new iExtStatus = GetExtensionFileStatus("game.tf2.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SRI] Required extension was not found."); - LogAction(0, -1, "[SRI] Plugin FAILED TO LOAD."); - SetFailState("Required extension was not found."); - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SRI] Required extension is loaded with errors."); - LogAction(0, -1, "[SRI] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SRI] Plugin FAILED TO LOAD."); - SetFailState("Required extension is loaded with errors."); - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SRI] Required tf2 extension is loaded."); - } - iExtStatus = GetExtensionFileStatus("dukehacks.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SRI] Dukehacks extension was not found."); - LogAction(0, -1, "[SRI] Plugin continued to load, but that feature will not be used."); - g_bUseDukehacks = false; - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SRI] Dukehacks extension is loaded with errors."); - LogAction(0, -1, "[SRI] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SRI] Plugin continued to load, but that feature will not be used."); - g_bUseDukehacks = false; - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SRI] Dukehacks extension is loaded and will be used."); - g_bUseDukehacks = true; - dhAddClientHook(CHK_TakeDamage, Hacks_TakeDamageHook); - } - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_PostNoCopy); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - /** - Now lets check for client prefs extension - */ - new iExtStatus = GetExtensionFileStatus("clientprefs.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SRI] Client Preferences extension was not found."); - LogAction(0, -1, "[SRI] Plugin continued to load, but that feature will not be used."); - g_bUseClientprefs = false; - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SRI] Client Preferences extension is loaded with errors."); - LogAction(0, -1, "[SRI] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SRI] Plugin continued to load, but that feature will not be used."); - g_bUseClientprefs = false; - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SRI] Client Preferences extension is loaded, checking database."); - if (!SQL_CheckConfig(clientprefs)) - { - LogAction(0, -1, "[SRI] No 'clientprefs' database found. Check your database.cfg file."); - LogAction(0, -1, "[SRI] Plugin continued to load, but Client Preferences will not be used."); - g_bUseClientprefs = false; - } - g_bUseClientprefs = true; - - /** - Deal with client cookies - */ - sri_cookie_enabled = RegClientCookie("bri_client_enabled", "Enable/Disable your immunity during the bonus round.", CookieAccess_Public); - sri_cookie_color = RegClientCookie("bri_client_color", "Color to render when immune.", CookieAccess_Public); - sri_cookie_mode = RegClientCookie("bri_client_mode", "God mode to select", CookieAccess_Public); - SetCookieMenuItem(CookieMenu_TopMenu, sri_cookie_enabled, "Bonus Round Immunity"); - } - - HookConVarChange(sri_enabled, EnabledChanged); - - RegAdminCmd("sm_immunity", Command_Immunity, ADMFLAG_ROOT, "sm_immunity: Gives you immunity"); - - LoadColors(); - - AutoExecConfig(true, "plugin.simpleroundimmunity"); -} - -public OnAllPluginsLoaded() -{ - //something - // need to deal with the unloading of dukehacks, clientprefs, and simpleplugins - // should move hooking the client prefs cookies to a function to make sure they are done post plugin start if ext is loaded late -} - -public OnLibraryRemoved(const String:name[]) -{ - //something - // need to deal with the loading of dukehacks, clientprefs, and simpleplugins -} - -public OnConfigsExecuted() -{ - GetConVarString(sri_charadminflag, g_sCharAdminFlag, sizeof(g_sCharAdminFlag)); - g_bIsEnabled = GetConVarBool(sri_enabled); - g_bRoundEnd = false; -} - -/** - Client events - */ - -public OnClientPostAdminCheck(client) -{ - if (SM_IsValidAdmin(client, g_sCharAdminFlag)) - g_aPlayers[client][bIsAdmin] = true; - else - g_aPlayers[client][bIsAdmin] = false; -} - -public OnClientCookiesCached(client) -{ - decl String:sEnabled[2], String:sColor[4], String:sMode[2]; - GetClientCookie(client, sri_cookie_enabled, sEnabled, sizeof(sEnabled)); - GetClientCookie(client, sri_cookie_color, sColor, sizeof(sColor)); - GetClientCookie(client, sri_cookie_mode, sMode, sizeof(sMode)); - g_aClientCookies[client][bEnabled] = StringToInt(sEnabled); - g_aClientCookies[client][iColor] = StringToInt(sColor); - g_aClientCookies[client][iMode] = StringToInt(sMode); -} - -public OnClientDisconnect(client) -{ - CleanUp(client); -} - -/** - Commands - */ - -public Action:Command_Immunity(client, args) -{ - if (g_aPlayers[client][IsImmune]) - { - DisableImmunity(client); - } - else - { - EnableImmunity(client); - } - return Plugin_Handled; -} - -/** - Event hooks - */ - -public Action:Hacks_TakeDamageHook(client, attacker, inflictor, Float:damage, &Float:multiplier, damagetype) -{ - if (attacker == 0 || attacker >= MaxClients) - { - return Plugin_Continue; - } - if (g_aPlayers[client][IsImmune]) - { - new TFClassType:PlayerClass = TF2_GetPlayerClass(attacker); - if (PlayerClass == TFClass_Spy) - { - multiplier *= 0.0; - return Plugin_Changed; - } - } - return Plugin_Continue; -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - g_bRoundEnd = false; - if (g_bIsEnabled) - { - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][IsImmune]) - { - DisableImmunity(i); - } - } - } -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - g_bRoundEnd = true; - if (g_bIsEnabled) - { - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][bIsAdmin]) - { - EnableImmunity(i); - } - } - } -} - -public HookPlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) -{ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - if (g_bIsEnabled && g_aPlayers[iClient][bIsAdmin] && g_bRoundEnd) - { - EnableImmunity(iClient); - } -} - -public Action:HookPlayerHurt(Handle:event, const String:name[], bool:dontBroadcast) -{ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - if (g_aPlayers[iClient][IsImmune]) - { - SetEntityHealth(iClient, 2000); - return Plugin_Continue; - } - return Plugin_Continue; -} - -/** - Cookie menus - */ - -public CookieMenu_TopMenu(client, CookieMenuAction:action, any:info, String:buffer[], maxlen) -{ - if (action == CookieMenuAction_DisplayOption) - { - //don't think we need to do anything - } - else - { - new Handle:hMenu = CreateMenu(Menu_CookieSettings); - SetMenuTitle(hMenu, "Options (Current Setting)"); - if (g_aClientCookies[client][bEnabled]) - { - AddMenuItem(hMenu, "enable", "Enabled/Disable (Enabled)"); - } - else - { - AddMenuItem(hMenu, "enable", "Enabled/Disable (Disabled)"); - } - if (g_aClientCookies[client][iMode]) - { - AddMenuItem(hMenu, "mode", "Immunity Mode Setting (God Mode)"); - } - else - { - AddMenuItem(hMenu, "mode", "Immunity Mode Setting (Health)"); - } - switch (g_aClientCookies[client][iColor]) - { - case COLOR_GREEN: - { - AddMenuItem(hMenu, "color", "Color (Green)"); - } - case COLOR_BLACK: - { - AddMenuItem(hMenu, "color", "Color (Black)"); - } - case COLOR_RED: - { - AddMenuItem(hMenu, "color", "Color (Red)"); - } - case COLOR_BLUE: - { - AddMenuItem(hMenu, "color", "Color (Blue)"); - } - case COLOR_TEAM: - { - AddMenuItem(hMenu, "color", "Color (Team)"); - } - case COLOR_RAINBOW: - { - AddMenuItem(hMenu, "color", "Color (Rainbow)"); - } - case COLOR_NONE: - { - AddMenuItem(hMenu, "color", "Color (None)"); - } - } - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, client, MENU_TIME_FOREVER); - } -} - -public Menu_CookieSettings(Handle:menu, MenuAction:action, param1, param2) -{ - new client = param1; - if (action == MenuAction_Select) - { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "enable", false)) - { - new Handle:hMenu = CreateMenu(Menu_CookieSettingsEnable); - SetMenuTitle(hMenu, "Enable/Disable Round End Immunity"); - - if (g_aClientCookies[client][bEnabled]) - { - AddMenuItem(hMenu, "enable", "Enable (Set)"); - AddMenuItem(hMenu, "disable", "Disable"); - } - else - { - AddMenuItem(hMenu, "enable", "Enabled"); - AddMenuItem(hMenu, "disable", "Disable (Set)"); - } - - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, client, MENU_TIME_FOREVER); - } - else if (StrEqual(sSelection, "mode", false)) - { - new Handle:hMenu = CreateMenu(Menu_CookieSettingsMode); - SetMenuTitle(hMenu, "Set Immunity Mode"); - - if (g_aClientCookies[client][iMode]) - { - AddMenuItem(hMenu, "god", "God Mode (Set)"); - AddMenuItem(hMenu, "health", "Health"); - } - else - { - AddMenuItem(hMenu, "god", "God Mode"); - AddMenuItem(hMenu, "health", "Health (Set)"); - } - - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, client, MENU_TIME_FOREVER); - } - else - { - new Handle:hMenu = CreateMenu(Menu_CookieSettingsColors); - SetMenuTitle(hMenu, "Select Immunity Color"); - switch (g_aClientCookies[client][iColor]) - { - case COLOR_GREEN: - { - AddMenuItem(hMenu, "Green", "Green (Set)"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_BLACK: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black (Set)"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_RED: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red (Set)"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_BLUE: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue (Set)"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_TEAM: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color (Set)"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_RAINBOW: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow (Set)"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_NONE: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None (Set)"); - } - } - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, client, MENU_TIME_FOREVER); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - ShowCookieMenu(client); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -public Menu_CookieSettingsEnable(Handle:menu, MenuAction:action, param1, param2) -{ - new client = param1; - if (action == MenuAction_Select) - { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "enable", false)) - { - SetClientCookie(client, sri_cookie_enabled, "1"); - g_aClientCookies[client][bEnabled] = 1; - PrintToChat(client, "[SM] Bonus Round Immunity is ENABLED"); - } - else - { - SetClientCookie(client, sri_cookie_enabled, "0"); - g_aClientCookies[client][bEnabled] = 0; - PrintToChat(client, "[SM] Bonus Round Immunity is DISABLED"); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - ShowCookieMenu(client); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -public Menu_CookieSettingsColors(Handle:menu, MenuAction:action, param1, param2) -{ - new client = param1; - if (action == MenuAction_Select) - { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "Green", false)) - { - SetClientCookie(client, sri_cookie_color, "0"); - g_aClientCookies[client][iColor] = COLOR_GREEN; - PrintToChat(client, "[SM] Bonus Round Immunity color set to GREEN"); - } - else if (StrEqual(sSelection, "Black", false)) - { - SetClientCookie(client, sri_cookie_color, "1"); - g_aClientCookies[client][iColor] = COLOR_BLACK; - PrintToChat(client, "[SM] Bonus Round Immunity color set to BLACK"); - } - else if (StrEqual(sSelection, "Red", false)) - { - SetClientCookie(client, sri_cookie_color, "2"); - g_aClientCookies[client][iColor] = COLOR_RED; - PrintToChat(client, "[SM] Bonus Round Immunity color set to RED"); - } - else if (StrEqual(sSelection, "Blue", false)) - { - SetClientCookie(client, sri_cookie_color, "3"); - g_aClientCookies[client][iColor] = COLOR_BLUE; - PrintToChat(client, "[SM] Bonus Round Immunity color set to BLUE"); - } - else if (StrEqual(sSelection, "Team", false)) - { - SetClientCookie(client, sri_cookie_color, "4"); - g_aClientCookies[client][iColor] = COLOR_TEAM; - PrintToChat(client, "[SM] Bonus Round Immunity color set to TEAM COLOR"); - } - else if (StrEqual(sSelection, "Rain", false)) - { - SetClientCookie(client, sri_cookie_color, "5"); - g_aClientCookies[client][iColor] = COLOR_RAINBOW; - PrintToChat(client, "[SM] Bonus Round Immunity color set to RAINBOW"); - } - else if (StrEqual(sSelection, "None", false)) - { - SetClientCookie(client, sri_cookie_color, "6"); - g_aClientCookies[client][iColor] = COLOR_NONE; - PrintToChat(client, "[SM] Bonus Round Immunity color set to NONE"); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - ShowCookieMenu(client); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -public Menu_CookieSettingsMode(Handle:menu, MenuAction:action, param1, param2) -{ - new client = param1; - if (action == MenuAction_Select) - { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "god", false)) - { - SetClientCookie(client, sri_cookie_mode, "1"); - g_aClientCookies[client][iMode] = 1; - PrintToChat(client, "[SM] Bonus Round Immunity set to GOD MODE"); - } - else - { - SetClientCookie(client, sri_cookie_mode, "0"); - g_aClientCookies[client][iMode] = 0; - PrintToChat(client, "[SM] Bonus Round Immunity set to HEALTH BONUS"); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - ShowCookieMenu(client); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -/** -Timer functions - */ - -public Action:Timer_ChangeColor(Handle:timer, any:client) -{ - if (g_aPlayers[client][CycleColor]++ == 3) - { - g_aPlayers[client][CycleColor] = 0; - } - SetEntityRenderMode(client, RENDER_TRANSCOLOR); - SetEntityRenderColor(client, g_iColors[g_aPlayers[client][CycleColor]][iRed], g_iColors[g_aPlayers[client][CycleColor]][iGreen], g_iColors[g_aPlayers[client][CycleColor]][iBlue], 255); - return Plugin_Continue; -} - -public Action:Timer_UndoGodMode(Handle:timer, any:client) -{ - if (IsClientInGame(client)) - { - SetEntProp(client, Prop_Data, "m_takedamage", 2, 1); - } - g_aPlayers[iClient][hGodModeTimer] = INVALID_HANDLE; - return Plugin_Handled; -} - -/** -Stock functions . - */ - -stock CleanUp(iClient) -{ - g_aPlayers[iClient][bIsAdmin] = false; - DisableImmunity(iClient); -} - -stock EnableImmunity(iClient) -{ - SetEntityRenderMode(iClient, RENDER_TRANSCOLOR); - switch (g_aClientCookies[iClient][iColor]) - { - case COLOR_TEAM: - { - new iTeam = GetClientTeam(iClient); - SetEntityRenderColor(iClient, g_iColors[e_ColorNames:iTeam][iRed], g_iColors[e_ColorNames:iTeam][iGreen], g_iColors[e_ColorNames:iTeam][iBlue], 255); - } - case COLOR_RAINBOW: - { - if (g_aPlayers[iClient][hColorTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hColorTimer]); - g_aPlayers[iClient][hColorTimer] = INVALID_HANDLE; - } - g_aPlayers[iClient][hColorTimer] = CreateTimer(0.2, Timer_ChangeColor, iClient, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); - } - case COLOR_NONE: - { - //We dont have to set a color - } - default: - { - SetEntityRenderColor(iClient, g_iColors[e_ColorNames:g_aClientCookies[iClient][iColor]][iRed], g_iColors[e_ColorNames:g_aClientCookies[iClient][iColor]][iGreen], g_iColors[e_ColorNames:g_aClientCookies[iClient][iColor]][iBlue], 255); - } - } - SetEntityHealth(iClient, 2000); - SetEntProp(iClient, Prop_Data, "m_takedamage", 0, 1); - g_aPlayers[iClient][hGodModeTimer] = CreateTimer(2.0, Timer_UndoGodMode, iClient); - g_aPlayers[iClient][IsImmune] = true; -} - -stock DisableImmunity(iClient) -{ - if (g_aPlayers[iClient][hGodModeTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hGodModeTimer]); - g_aPlayers[iClient][hGodModeTimer] = INVALID_HANDLE; - } - if (g_aPlayers[iClient][hColorTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hColorTimer]); - g_aPlayers[iClient][hColorTimer] = INVALID_HANDLE; - } - if (IsClientInGame(iClient)) - { - SetEntityRenderMode(iClient, RENDER_TRANSCOLOR); - SetEntityRenderColor(iClient, 255, 255, 255, 255); - new TFClassType:PlayerClass = TF2_GetPlayerClass(iClient); - new iMaxHealth = g_iClassMaxHealth[PlayerClass]; - SetEntityHealth(iClient, iMaxHealth); - } - g_aPlayers[iClient][CycleColor] = 0; - g_aPlayers[iClient][IsImmune] = false; -} - -stock LoadColors() -{ - g_iColors[Green][iRed] = 0; - g_iColors[Green][iGreen] = 255; - g_iColors[Green][iBlue] = 0; - - g_iColors[Black][iRed] = 10; - g_iColors[Black][iGreen] = 10; - g_iColors[Black][iBlue] = 0; - - g_iColors[Red][iRed] = 255; - g_iColors[Red][iGreen] = 0; - g_iColors[Red][iBlue] = 0; - - g_iColors[Blue][iRed] = 0; - g_iColors[Blue][iGreen] = 0; - g_iColors[Blue][iBlue] = 255; -} - -stock TF2_AddCond(client, cond) -{ - new Handle:cvar = FindConVar("sv_cheats"), bool:enabled = GetConVarBool(cvar), flags = GetConVarFlags(cvar); - if(!enabled) - { - SetConVarFlags(cvar, flags^FCVAR_NOTIFY); - SetConVarBool(cvar, true); - } - FakeClientCommand(client, "addcond %i", cond); - if(!enabled) - { - SetConVarBool(cvar, false); - SetConVarFlags(cvar, flags); - } -} - -stock TF2_RemoveCond(client, cond) -{ - new Handle:cvar = FindConVar("sv_cheats"), bool:enabled = GetConVarBool(cvar), flags = GetConVarFlags(cvar); - if(!enabled) - { - SetConVarFlags(cvar, flags^FCVAR_NOTIFY); - SetConVarBool(cvar, true); - } - FakeClientCommand(client, "removecond %i", cond); - if(!enabled) - { - SetConVarBool(cvar, false); - SetConVarFlags(cvar, flags); - } -} - -/** -Enabled hook - */ - -public EnabledChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (StringToInt(newValue) == 0) - { - UnhookEvent("player_spawn", HookPlayerSpawn, EventHookMode_Post); - UnhookEvent("teamplay_round_start", HookRoundStart, EventHookMode_Post); - UnhookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][bIsAdmin] && g_aPlayers[i][IsImmune]) - { - DisableImmunity(i); - } - } - g_bIsEnabled = false; - } - else - { - HookEvent("player_spawn", HookPlayerSpawn, EventHookMode_Post); - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_Post); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - g_bIsEnabled = true; - } -} diff --git a/Simple Plugins Core/addons/sourcemod/scripting/simple-spectate.sp b/Simple Plugins Core/addons/sourcemod/scripting/simple-spectate.sp deleted file mode 100644 index 4108f8f..0000000 --- a/Simple Plugins Core/addons/sourcemod/scripting/simple-spectate.sp +++ /dev/null @@ -1,2022 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Spectate -Description: - Spectate a player and follow them through death. -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include -#undef REQUIRE_EXTENSIONS -#undef AUTOLOAD_EXTENSIONS -#tryinclude -#define AUTOLOAD_EXTENSIONS -#define REQUIRE_EXTENSIONS - -#define PLUGIN_VERSION "1.2.1.$Rev$" - -#define SPECMODE_NONE 0 -#define SPECMODE_FIRSTPERSON 4 -#define SPECMODE_3RDPERSON 5 -#define SPECMODE_FREELOOK 6 -#define SPECMODE_CSS_FIRSTPERSON 3 -#define SPECMODE_CSS_3RDPERSON 4 -#define SPECMODE_CSS_FREELOOK 5 - -enum e_CvarHandles -{ - Handle:hHudMode, - Handle:hMenuType, - Handle:hRestrictHud, - Handle:hBan, - Handle:hBanPerm, - Handle:hBeacon, - Handle:hBlind, - Handle:hCheater, - Handle:hDrug, - Handle:hFreeze, - Handle:hFreezeBomb, - Handle:hKick, - Handle:hSlap, - Handle:hSlay, - Handle:hTimeBomb -}; - -enum e_CvarSettings -{ - bool:bHudMode, - bool:bMenuType, - bool:bRestrictHud, - bool:bBan, - bool:bBanPerm, - bool:bBeacon, - bool:bBlind, - bool:bCheater, - bool:bDrug, - bool:bFreeze, - bool:bFreezebomb, - bool:bKick, - bool:bSlap, - bool:bSlay, - bool:bTimeBomb -}; - -enum e_PluginSettings -{ - bool:bUseSteamBans, - bool:bUseSourceBans, - bool:bUseMySQLBans, - bool:bCanHUD, - bool:bUseDukehacks -}; - -enum e_Menus -{ - Handle:hSelectPlayer, - Handle:hBanTime, - Handle:hReason -}; - -enum e_Punishments -{ - Punish_None, - Punish_Ban, - Punish_Beacon, - Punish_Blind, - Punish_Cheater, - Punish_Drug, - Punish_Freeze, - Punish_FreezeBomb, - Punish_Kick, - Punish_Slap, - Punish_Slay, - Punish_TimeBomb -}; - -enum e_PlayerData -{ - bool:bIsDisplayingHud, - bool:bIsFlaggedCheater, - Handle:hHudTimer, - Handle:hTargetTimer, - iTargetIndex, - e_Punishments:TargetPunishment, - iBanTime -}; - -new Handle:sm_spectate_adminflag = INVALID_HANDLE; -new Handle:g_hAdminMenu = INVALID_HANDLE; -new Handle:g_hHud = INVALID_HANDLE; -new Handle:g_aPluginCvar[e_CvarHandles]; -new g_aPluginCvarSettings[e_CvarSettings]; -new g_aPluginSettings[e_PluginSettings]; -new g_aMenus[e_Menus]; -new g_aPlayers[MAXPLAYERS + 1][e_PlayerData]; -new String:g_sAdminFlags[16]; -new String:g_sPunishments[e_Punishments][15] = { "None", "Ban", "Beacon", "Blind", "Cheater", "Drug", "Freeze", "FreezeBomb", "Kick", "Slap", "Slay", "TimeBomb" }; - -public Plugin:myinfo = -{ - name = "Simple Spectate", - author = "Simple Plugins", - description = "Spectate a player and follow them through death.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -/** -Sourcemod callbacks -*/ -public OnPluginStart() -{ - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[SSPEC] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Pre); - - /** - Need to create all of our console variables. - */ - CreateConVar("sm_spectate_version", PLUGIN_VERSION, "Sourcemod Spectate", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - g_aPluginCvar[hHudMode] = CreateConVar("sm_spectate_hudmode", "1", "Hud Mode: 0 = Hud Text | 1 = Panel/Menu (NOTE: The panel/menu will override other menus until canceled)"); - g_aPluginCvar[hMenuType] = CreateConVar("sm_spectate_menutype", "0", "Menu Mode: 0 = Panel | 1 = Menu"); - g_aPluginCvar[hRestrictHud] = CreateConVar("sm_spectate_restricthud", "0", "Restrict the hud to the admin flag provided"); - g_aPluginCvar[hBan] = CreateConVar("sm_spectate_ban", "1", "Enable/Disable ban option"); - g_aPluginCvar[hBanPerm] = CreateConVar("sm_spectate_banperm", "1", "Enable/Disable permanent ban option"); - g_aPluginCvar[hBeacon] = CreateConVar("sm_spectate_beacon", "1", "Enable/Disable beacon option"); - g_aPluginCvar[hBlind] = CreateConVar("sm_spectate_blind", "1", "Enable/Disable blind option"); - g_aPluginCvar[hCheater] = CreateConVar("sm_spectate_cheater", "1", "Enable/Disable cheater option"); - g_aPluginCvar[hDrug] = CreateConVar("sm_spectate_drug", "1", "Enable/Disable drug option"); - g_aPluginCvar[hFreeze] = CreateConVar("sm_spectate_freeze", "1", "Enable/Disable freeze option"); - g_aPluginCvar[hFreezeBomb] = CreateConVar("sm_spectate_freezebomb", "1", "Enable/Disable freezebomb option"); - g_aPluginCvar[hKick] = CreateConVar("sm_spectate_kick", "1", "Enable/Disable kick option"); - g_aPluginCvar[hSlap] = CreateConVar("sm_spectate_slap", "1", "Enable/Disable slap option"); - g_aPluginCvar[hSlay] = CreateConVar("sm_spectate_slay", "1", "Enable/Disable slay option"); - g_aPluginCvar[hTimeBomb] = CreateConVar("sm_spectate_timebomb", "1", "Enable/Disable timebomb option"); - - sm_spectate_adminflag = CreateConVar("sm_spectate_adminflag", "d", "Admin Flag to use for admin hud"); - - /** - Hook console variables - */ - new e_CvarHandles:iCvar; - for ( ; _:iCvar < sizeof(g_aPluginCvar); iCvar++) - { - HookConVarChange(g_aPluginCvar[iCvar], ConVarSettingsChanged); - } - - /** - Need to register the commands we are going to create and use. - */ - RegConsoleCmd("sm_spectate", Command_Spectate, "Spectate a player"); - RegConsoleCmd("sm_spec", Command_Spectate, "Spectate a player"); - RegConsoleCmd("sm_observe", Command_Spectate, "Spectate a player"); - RegConsoleCmd("sm_stopspec", Command_StopSpectate, "Stop Spectating a player"); - RegConsoleCmd("sm_endobserve", Command_StopSpectate, "Stop Spectating a player"); - RegConsoleCmd("sm_specinfo", Command_ToggleHud, "Toggles the hud display if in spectator"); - - /** - Now we have to deal with the admin menu. If the admin library is loaded call the function to add our items. - */ - new Handle:gTopMenu; - if (LibraryExists("adminmenu") && ((gTopMenu = GetAdminTopMenu()) != INVALID_HANDLE)) - { - OnAdminMenuReady(gTopMenu); - } - - /** - Deal with the hud - Thanks to Spray Trace plugin (http://forums.alliedmods.net/showthread.php?p=665448) - */ - new String:sHudGames[32]; - GetGameFolderName(sHudGames, sizeof(sHudGames)); - g_aPluginSettings[bCanHUD] = StrEqual(sHudGames,"tf",false) - || StrEqual(sHudGames,"hl2mp",false) - || StrEqual(sHudGames,"sourceforts",false) - || StrEqual(sHudGames,"obsidian",false) - || StrEqual(sHudGames,"left4dead",false) - || StrEqual(sHudGames,"l4d",false); - - if (g_aPluginSettings[bCanHUD]) - { - g_hHud = CreateHudSynchronizer(); - } - - /** - Load translations - */ - LoadTranslations ("common.phrases"); - LoadTranslations ("simplespectate.phrases"); - - /** - Create the config file - */ - AutoExecConfig(true); -} - -public OnConfigsExecuted() -{ - new e_CvarHandles:iCvar; - for ( ; _:iCvar < sizeof(g_aPluginCvarSettings); iCvar++) - { - g_aPluginCvarSettings[iCvar] = GetConVarBool(g_aPluginCvar[iCvar]); - } - - /* - Build the global menus - */ - g_aMenus[hSelectPlayer] = BuildSelectPlayerMenu(); - g_aMenus[hBanTime] = BuildBanTimeMenu(); - g_aMenus[hReason] = BuildReasonMenu(); - - GetConVarString(sm_spectate_adminflag, g_sAdminFlags, sizeof(g_sAdminFlags)); -} - -public OnAllPluginsLoaded() -{ - - /* - Check for steambans - */ - if (FindConVar("sbsrc_version") != INVALID_HANDLE) - { - g_aPluginSettings[bUseSteamBans] = true; - } - else - { - g_aPluginSettings[bUseSteamBans] = false; - } - - /* - Check for sourcebans - */ - if (FindConVar("sb_version") != INVALID_HANDLE) - { - g_aPluginSettings[bUseSourceBans] = true; - } - else - { - g_aPluginSettings[bUseSourceBans] = false; - } - - /* - Check for mysql bans - */ - if (FindConVar("mysql_bans_version") != INVALID_HANDLE) - { - g_aPluginSettings[bUseMySQLBans] = true; - } - else - { - g_aPluginSettings[bUseMySQLBans] = false; - } - - /* - Check for dukehacks - */ - new String:sExtError[256]; - new iExtStatus = GetExtensionFileStatus("dukehacks.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SSPEC] Dukehacks extension was not found."); - LogAction(0, -1, "[SSPEC] Plugin continued to load, but that feature will not be used."); - g_aPluginSettings[bUseDukehacks] = false; - } - else if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SSPEC] Dukehacks extension is loaded with errors."); - LogAction(0, -1, "[SSPEC] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SSPEC] Plugin continued to load, but that feature will not be used."); - g_aPluginSettings[bUseDukehacks] = false; - } - else if (iExtStatus == 1) - { - LogAction(0, -1, "[SSPEC] Dukehacks extension is loaded and will be used."); - g_aPluginSettings[bUseDukehacks] = true; - dhAddClientHook(CHK_TakeDamage, Hacks_TakeDamageHook); - } - - /* - Deal with some known plugin conflicts - */ - new Handle:hObserveClient = FindConVar("observe_version"); - if (hObserveClient != INVALID_HANDLE) - { - new String:sNewFile[PLATFORM_MAX_PATH + 1], String:sOldFile[PLATFORM_MAX_PATH + 1]; - BuildPath(Path_SM, sNewFile, sizeof(sNewFile), "plugins/disabled/observe.smx"); - BuildPath(Path_SM, sOldFile, sizeof(sOldFile), "plugins/observe.smx"); - - /** - Check if plugins/observe.smx exists, and if not, ignore - */ - if(!FileExists(sOldFile)) - { - return; - } - - /** - Check if plugins/disabled/observe.smx already exists, and if so, delete it - */ - if(FileExists(sNewFile)) - { - DeleteFile(sNewFile); - } - - /** - Unload plugins/observe.smx and move it to plugins/disabled/observe.smx - */ - LogAction(0, -1, "Detected the plugin ObserveClient"); - LogAction(0, -1, "ObserveClient plugin conflicts with Simple Spectate"); - LogAction(0, -1, "Unloading plugin and disabling ObserveClient plugin"); - ServerCommand("sm plugins unload observe"); - RenameFile(sNewFile, sOldFile); - } -} - -public OnLibraryRemoved(const String:name[]) -{ - if (StrEqual(name, "adminmenu")) - { - - /** - Looks like the admin menu was removed. Set the global. - */ - g_hAdminMenu = INVALID_HANDLE; - } - else if (StrEqual(name, "simpleplugins")) - { - //something - } -} - -public OnClientDisconnect(client) -{ - - /** - Cleanup the clients variables. - */ - ResetClient(client); - - /** - Run a loop and see if we are supposed to spectate this person (is a target) - */ - for(new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][iTargetIndex] == client) - { - - /** - Cleanup the clients variables. - */ - StopFollowingPlayer(i); - g_aPlayers[i][TargetPunishment] = Punish_None; - g_aPlayers[i][iBanTime] = 0; - } - } -} - -/** -Thirdparty callbacks -*/ -public SM_OnPlayerMoved(Handle:plugin, client, team) -{ - - /** - Make sure we called the move function - */ - if (plugin != GetMyHandle()) - { - return; - } - - //Nothing -} - -public Action:Hacks_TakeDamageHook(client, attacker, inflictor, Float:damage, &Float:multiplier, damagetype) -{ - - /** - Check for a valid client - */ - if (client > 0 && client <= MaxClients) - { - - /** - Check if the client taking damage is flagged as a cheater - */ - if (g_aPlayers[client][bIsFlaggedCheater]) - { - - /** - Check for fall damage and increase it - */ - if (damagetype & DMG_FALL) - { - multiplier *= 1000.0; - return Plugin_Changed; - } - } - } - - /** - Check for a valid attacker - */ - if (attacker > 0 && attacker <= MaxClients) - { - - /** - Check if the attacker causing the damage is flagged as a cheater - */ - if (g_aPlayers[attacker][bIsFlaggedCheater]) - { - - /** - Make sure they are not hurting themselves - */ - if (client != attacker) - { - - /** - Stop the damage - */ - multiplier *= 0.0; - return Plugin_Changed; - } - } - } - return Plugin_Continue; -} - -/** -Events -*/ -public Action:HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get the client and team - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - new iTeam = GetEventInt(event, "team"); - - /** - Make sure it's a valid client - */ - if (iClient == 0) - { - return Plugin_Continue; - } - - /** - If it's a move to spectator start displaying the hud - */ - else if ((iTeam == g_aCurrentTeams[Spectator]) && (GetUserFlagBits(iClient) & ADMFLAG_GENERIC)) - { - StartDisplayingHud(iClient); - - /** - If the event was going to be broadcasted, we refire it so it is not broadcasted and stop this one - */ - if (!dontBroadcast) - { - new Handle:hEvent = CreateEvent("player_team"); - SetEventInt(hEvent, "userid", GetEventInt(event, "userid")); - SetEventInt(hEvent, "team", GetEventInt(event, "team")); - SetEventInt(hEvent, "oldteam", GetEventInt(event, "oldteam")); - SetEventBool(hEvent, "disconnect", GetEventBool(event, "disconnect")); - - if (g_CurrentMod == GameType_DOD || g_CurrentMod == GameType_L4D || g_CurrentMod == GameType_TF) - { - new String:sClientName[MAX_NAME_LENGTH + 1]; - GetClientName(client, sClientName, sizeof(sClientName)); - SetEventBool(hEvent, "autoteam", GetEventBool(event, "autoteam")); - SetEventBool(hEvent, "silent", true); - SetEventString(hEvent, "name", sClientName); - FireEvent(hEvent, true); - } - else - { - FireEvent(hEvent, true); - } - return Plugin_Handled; - } - } - - /** - Otherwise cleanup the client - */ - else - { - StopDisplayingHud(iClient); - StopFollowingPlayer(iClient); - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -/** -Commands -*/ -public Action:Command_Spectate(client, args) -{ - - /** - See if we already have a target (for toggling of command) - */ - if (g_aPlayers[client][iTargetIndex]) - { - - /** - We do, toggle it off - */ - StopFollowingPlayer(client); - - /** - We are done, bug out. - */ - return Plugin_Handled; - } - - /** - We don't... must want to enable it - See if we have some command arguments. - */ - new iCmdArgs = GetCmdArgs(); - if (iCmdArgs == 0) - { - - /** - We don't have any. Display the player menu. - */ - if (g_aPlayers[client][bIsDisplayingHud]) - { - StopDisplayingHud(client); - } - - DisplayMenu(BuildPlayerListMenu(), client, MENU_TIME_FOREVER); - return Plugin_Handled; - } - - /** - We have an argument. - Try to find the target. - */ - new String:sPlayer[128]; - GetCmdArg(1, sPlayer, sizeof(sPlayer)); - new iTarget = FindTarget(client, sPlayer, true, true); - if (iTarget == -1 || !IsClientInGame(iTarget)) - { - - /** - We couldn't find the target. Display the player menu. - */ - if (g_aPlayers[client][bIsDisplayingHud]) - { - StopDisplayingHud(client); - } - - DisplayMenu(BuildPlayerListMenu(), client, MENU_TIME_FOREVER); - return Plugin_Handled; - } - - /** - We found the target. - Call the stock function to spectate the target. - */ - StartFollowingPlayer(client, iTarget); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_StopSpectate(client, args) -{ - - /** - Cleanup the clients variables. - */ - StopFollowingPlayer(client); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_ToggleHud(client, args) -{ - - /** - Toggle the hud - */ - if (g_aPlayers[client][bIsDisplayingHud]) - { - StopDisplayingHud(client); - } - else - { - StartDisplayingHud(client); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -/** -Timers -*/ -public Action:Timer_ResetTarget(Handle:timer, any:client) -{ - - new iTargetID = GetEntPropEnt(client, Prop_Send, "m_hObserverTarget"); - - if (iTargetID != g_aPlayers[client][iTargetIndex] && IsPlayerAlive(g_aPlayers[client][iTargetIndex])) - { - - /** - Run the command to spectate the target from the clients prospectative. - */ - FakeClientCommandEx(client, "spec_player \"%N\"", g_aPlayers[client][iTargetIndex]); - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Timer_UpdateHud(Handle:timer, any:client) -{ - - /** - Make sure the client is still in game and a spectator - */ - if (!IsClientConnected(client) || !IsClientInGame(client) || GetClientTeam(client) != g_aCurrentTeams[Spectator] || !g_aPlayers[client][bIsDisplayingHud]) - { - - /** - We are done, bug out - */ - g_aPlayers[client][hHudTimer] = INVALID_HANDLE; - g_aPlayers[client][bIsDisplayingHud] = false; - return Plugin_Stop; - } - /** - Get the target - */ - new iTarget = GetEntPropEnt(client, Prop_Send, "m_hObserverTarget"); - - /** - Check to make sure the target is valid - */ - if (iTarget <= 0 || iTarget > MaxClients) - { - return Plugin_Continue; - } - - /** - Get the spectator mode - */ - new iSpecMode = GetEntProp(client, Prop_Send, "m_iObserverMode"); - - /** - This is a double check to make sure we are in spec - If we are on a regular team, specmod would = none or zero - */ - if (iSpecMode == SPECMODE_NONE) - { - - /** - We are done, bug out - */ - g_aPlayers[client][hHudTimer] = INVALID_HANDLE; - g_aPlayers[client][bIsDisplayingHud] = false; - return Plugin_Stop; - } - - /** - Check the spectator mode - CSS has different index's so we have to check game type first - */ - if (g_CurrentMod == GameType_CSS) - { - switch (iSpecMode) - { - case SPECMODE_CSS_FIRSTPERSON: - { - //Do Nothing - } - case SPECMODE_CSS_3RDPERSON: - { - //Do Nothing - } - case SPECMODE_CSS_FREELOOK: - { - return Plugin_Continue; - } - } - } - else - { - switch (iSpecMode) - { - case SPECMODE_FIRSTPERSON: - { - //Do Nothing - } - case SPECMODE_3RDPERSON: - { - //Do Nothing - } - case SPECMODE_FREELOOK: - { - return Plugin_Continue; - } - } - } - - - /** - Display with the hud - */ - if (g_aPluginSettings[bCanHUD] && !g_aPluginCvarSettings[bHudMode]) - { - new String:sSteamID[64]; - GetClientAuthString(iTarget, sSteamID, sizeof(sSteamID)); - SetHudTextParams(0.04, 0.6, 0.5, 255, 50, 50, 255); - ShowSyncHudText(client, g_hHud, "%N [%s]", iTarget, sSteamID); - } - else if (g_aPluginCvarSettings[bHudMode]) - { - if (g_aPluginCvarSettings[bMenuType]) - { - DisplayMenu(BuildPlayerHudMenu(client, iTarget), client, 1); - } - else - { - new Handle:hPanel = BuildPlayerHudPanel(client, iTarget); - SendPanelToClient(hPanel, client, Panel_PlayerHud, 1); - CloseHandle(hPanel); - } - } - - /** - We are done, keep going! - */ - return Plugin_Continue; -} - -/** -Admin Menu Callbacks -*/ -public OnAdminMenuReady(Handle:topmenu) -{ - if (topmenu == g_hAdminMenu) - { - return; - } - g_hAdminMenu = topmenu; - new TopMenuObject:player_commands = FindTopMenuCategory(g_hAdminMenu, ADMINMENU_PLAYERCOMMANDS); - if (player_commands == INVALID_TOPMENUOBJECT) - { - return; - } - AddToTopMenu(g_hAdminMenu, - "sm_spectate", - TopMenuObject_Item, - AdminMenu_SpecPlayer, - player_commands, - "sm_spectate", - ADMFLAG_GENERIC); -} - -public AdminMenu_SpecPlayer(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) -{ - if (action == TopMenuAction_DisplayOption) - { - - if (g_aPlayers[param][bIsDisplayingHud]) - { - StopDisplayingHud(param); - } - /** - See if we already have a target - */ - if (g_aPlayers[param][iTargetIndex]) - { - Format(buffer, maxlength, "Spectate(Disable)"); - } - else - { - Format(buffer, maxlength, "Spectate(Select Player)"); - } - } - else if (action == TopMenuAction_SelectOption) - { - - /** - See if we already have a target - */ - if (g_aPlayers[param][iTargetIndex]) - { - - /** - We do, toggle it off - */ - StopFollowingPlayer(param); - - /** - We are done, bug out. - */ - return; - } - else - { - DisplayMenu(BuildPlayerListMenu(), param, MENU_TIME_FOREVER); - } - } -} - -/** -Select Player Menu Callbacks -*/ -public Menu_PlayerList(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - /** - Get the selected player - */ - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - new iTarget = GetClientOfUserId(StringToInt(sSelection)); - - /** - Start following the player - */ - StartFollowingPlayer(param1, iTarget); - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_GENERIC) - { - - /** - Display the last admin menu - */ - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } - else if (param2 == MenuCancel_Exit && GetClientTeam(param1) == g_aCurrentTeams[Spectator]) - { - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_End) - { - - /** - Not a global menu, close it - */ - CloseHandle(menu); - } -} - -public Menu_SelectPlayer(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - - /** - Get the selected player - */ - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (strcmp(sSelection, "Current", false) == 0) - { - /** - Get the current target - */ - new iTarget = GetEntPropEnt(param1, Prop_Send, "m_hObserverTarget"); - - /** - Check to make sure the target is valid - */ - if (iTarget <= 0 || iTarget > MaxClients) - { - PrintToChat(param1, "\x03[SM-SPEC]\x01 %t", "Invalid Target"); - DisplayMenu(BuildPlayerListMenu(), param1, MENU_TIME_FOREVER); - } - - /** - Start following the player - */ - StartFollowingPlayer(param1, iTarget); - } - else - { - - /** - They want to select a player, show the player list - */ - DisplayMenu(BuildPlayerListMenu(), param1, MENU_TIME_FOREVER); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_End) - { - /** - Its a global menu, leave it alive - */ - } -} - -/** -Punishment Menu Callbacks -*/ -public Menu_Punishments(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - - /** - Get the menu selection - */ - new String:sSelection[15]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - - /** - Search for the correct index - */ - new e_Punishments:Index = Punish_None; - for ( ; _:Index <= sizeof(g_sPunishments); Index++) - { - if (StrEqual(sSelection, g_sPunishments[Index])) - { - break; - } - } - - /** - Display the next menu - */ - if (Index == Punish_Ban) - { - - /** - Set the punishment index and display ban time menu - */ - g_aPlayers[param1][TargetPunishment] = Index; - DisplayMenu(g_aMenus[hBanTime], param1, MENU_TIME_FOREVER); - } - else if (Index == Punish_Cheater) - { - - /** - Ask for confirmation before we set punishment index - */ - new Handle:hPanel = BuildAdminCheaterPanel(); - SendPanelToClient(hPanel, param1, Panel_AdminCheater, MENU_TIME_FOREVER); - CloseHandle(hPanel); - } - else - { - - /** - Set the punishment index and display reason menu - */ - g_aPlayers[param1][TargetPunishment] = Index; - DisplayMenu(g_aMenus[hReason], param1, MENU_TIME_FOREVER); - } - } - else if (action == MenuAction_Cancel) - { - - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - else if (action == MenuAction_End) - { - - /** - Not a global menu, close it - */ - CloseHandle(menu); - } -} - -public Menu_BanTime(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - - /** - Get the menu selection - */ - new String:sSelection[15]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - - /** - Set the ban time global - */ - g_aPlayers[param1][iBanTime] = StringToInt(sSelection); - - /** - Display the reason menu - */ - DisplayMenu(g_aMenus[hReason], param1, MENU_TIME_FOREVER); - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_End) - { - /** - Its a global menu, leave it alive - */ - } -} - -public Menu_Reason(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - - /** - Get the menu selection - */ - new String:sSelection[15]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - - /** - Perform the punishment - */ - PerformPunishment(param1, g_aPlayers[param1][iTargetIndex], g_aPlayers[param1][TargetPunishment], sSelection, g_aPlayers[param1][iBanTime]); - - /** - Reactivate the hud if still in spectator - */ - if (GetClientTeam(param1) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_End) - { - /** - Its a global menu, leave it alive - */ - } -} - -public Panel_AdminCheater(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - if (param2 == 1) - { - - /** - Set the punishment index and display reason menu - */ - g_aPlayers[param1][TargetPunishment] = Punish_Cheater; - DisplayMenu(g_aMenus[hReason], param1, MENU_TIME_FOREVER); - } - else - { - - /** - Reactivate the hud if still in spectator - */ - if (GetClientTeam(param1) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(param1); - } - } - } -} - -public Panel_PublicCheater(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - if (param2 == 1) - { - //Waiting for SB 2.0 and sb_submission to be published - } - else - { - - /** - Reactivate the hud if still in spectator - */ - if (GetClientTeam(param1) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(param1); - } - } - } -} - -/** -Hud Menu/Panel Callbacks -*/ -public Menu_PlayerHud(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "stop", false)) - { - StopFollowingPlayer(param1); - } - else if (StrEqual(sSelection, "start", false)) - { - StopDisplayingHud(param1); - DisplayMenu(g_aMenus[hSelectPlayer], param1, MENU_TIME_FOREVER); - } - else if (StrEqual(sSelection, "removecheater", false)) - { - g_aPlayers[g_aPlayers[param1][iTargetIndex]][bIsFlaggedCheater] = false; - } - else if (StrEqual(sSelection, "punish", false)) - { - if (g_aPlayers[param1][iTargetIndex]) - { - StopDisplayingHud(param1); - DisplayMenu(BuildPunishmentMenu(param1), param1, MENU_TIME_FOREVER); - } - else - { - StopDisplayingHud(param1); - PrintToChat(param1, "\x03[SM-SPEC]\x01 %t", "Must Have Target"); - DisplayMenu(g_aMenus[hSelectPlayer], param1, MENU_TIME_FOREVER); - } - } - else if (StrEqual(sSelection, "reportcheater", false)) - { - if (g_aPlayers[param1][iTargetIndex]) - { - StopDisplayingHud(param1); - new Handle:hPanel = BuildPublicCheaterPanel(); - SendPanelToClient(hPanel, param1, Panel_PublicCheater, MENU_TIME_FOREVER); - CloseHandle(hPanel); - } - else - { - StopDisplayingHud(param1); - PrintToChat(param1, "\x03[SM-SPEC]\x01 %t", "Must Have Target"); - DisplayMenu(g_aMenus[hSelectPlayer], param1, MENU_TIME_FOREVER); - } - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_Interrupted) - { - if (GetClientMenu(param1) == MenuSource_External) - { - StopDisplayingHud(param1); - } - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -public Panel_PlayerHud(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - switch (param2) - { - case 1: - { - if (g_aPlayers[param1][iTargetIndex]) - { - StopFollowingPlayer(param1); - } - else - { - StopDisplayingHud(param1); - DisplayMenu(BuildSelectPlayerMenu(), param1, MENU_TIME_FOREVER); - } - } - case 2: - { - if (!g_aPlayers[param1][iTargetIndex]) - { - StopDisplayingHud(param1); - PrintToChat(param1, "\x03[SM-SPEC]\x01 %t", "Must Have Target"); - DisplayMenu(g_aMenus[hSelectPlayer], param1, MENU_TIME_FOREVER); - return; - } - - if ((GetUserFlagBits(param1) & ADMFLAG_GENERIC) || (GetUserFlagBits(param1) & ADMFLAG_ROOT)) - { - if (g_aPlayers[g_aPlayers[param1][iTargetIndex]][bIsFlaggedCheater] && (GetUserFlagBits(param1) & ADMFLAG_ROOT)) - { - //Remove cheater flag - g_aPlayers[g_aPlayers[param1][iTargetIndex]][bIsFlaggedCheater] = false; - } - else - { - //Punish menu - StopDisplayingHud(param1); - DisplayMenu(BuildPunishmentMenu(param1), param1, MENU_TIME_FOREVER); - } - } - else - { - //Report Cheater - new Handle:hPanel = BuildPublicCheaterPanel(); - SendPanelToClient(hPanel, param1, Panel_PublicCheater, MENU_TIME_FOREVER); - CloseHandle(hPanel); - } - } - case 3: - { - StopDisplayingHud(param1); - } - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_Interrupted) - { - if (GetClientMenu(param1) == MenuSource_External) - { - StopDisplayingHud(param1); - } - } - } -} - - -/** -Stock functions -*/ -stock StartFollowingPlayer(client, target) -{ - - /** - If we have an open timer, close it. - */ - if (g_aPlayers[client][hTargetTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[client][hTargetTimer]); - g_aPlayers[client][hTargetTimer] = INVALID_HANDLE; - } - - /** - Make sure the target is on a non spectator team, and the client != target - */ - if (client == target) - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Yourself"); - return; - } - new iTargetTeam = GetClientTeam(target); - if (iTargetTeam == g_aCurrentTeams[Spectator] || iTargetTeam == g_aCurrentTeams[Unknown]) - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Spectator"); - return; - } - - /** - Check to see if client is already a spectator - */ - if (GetClientTeam(client) != g_aCurrentTeams[Spectator]) - { - - /** - Client is not a spectator, lets move them to spec. - */ - SM_MovePlayer(client, g_aCurrentTeams[Spectator]); - } - - /** - If we are using steambans call sb_status - */ - if (g_aPluginSettings[bUseSteamBans]) - { - FakeClientCommandEx(client, "sb_status"); - } - - - /** - Set the global and start to spectate the target. - Making sure it's long enough to deal with moving the client to spec if we had to. - */ - new String:sTargetName[MAX_NAME_LENGTH + 1]; - GetClientName(target, sTargetName, sizeof(sTargetName)); - g_aPlayers[client][iTargetIndex] = target; - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Spectating", sTargetName); - g_aPlayers[client][hTargetTimer] = CreateTimer(0.5, Timer_ResetTarget, client, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); - if (!g_aPlayers[client][bIsDisplayingHud] && GetClientTeam(client) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(client); - } -} - -stock StopFollowingPlayer(client) -{ - - /** - If we have an open timer, close it. - */ - if (g_aPlayers[client][hTargetTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[client][hTargetTimer]); - } - - /** - Tell the client we can't spec his target anymore... if they are in game. - */ - if (IsClientInGame(client) && g_aPlayers[client][iTargetIndex] != 0) - { - new String:sTargetName[MAX_NAME_LENGTH + 1]; - GetClientName(g_aPlayers[client][iTargetIndex], sTargetName, sizeof(sTargetName)); - if (!IsClientConnected(g_aPlayers[client][iTargetIndex]) || !IsClientInGame(g_aPlayers[client][iTargetIndex])) - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Target Left"); - } - else - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Stopped spectating", sTargetName); - } - } - - /** - Null the globals. - */ - g_aPlayers[client][iTargetIndex] = 0; - g_aPlayers[client][hTargetTimer] = INVALID_HANDLE; -} - -stock StartDisplayingHud(client) -{ - if (g_aPluginCvarSettings[bRestrictHud] && !SM_IsValidAdmin(client, g_sAdminFlags)) - { - return; - } - else - { - /** - Double check the hud timer - We should not have one, but if we do, lets cancel it for the current callback - */ - StopDisplayingHud(client); - - /** - Now we can safely display the hud and make sure the current stored handle is the current timer - */ - g_aPlayers[client][bIsDisplayingHud] = true; - g_aPlayers[client][hHudTimer] = CreateTimer(0.5, Timer_UpdateHud, client, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); - } -} - -stock StopDisplayingHud(client) -{ - if (g_aPlayers[client][hHudTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[client][hHudTimer]); - } - g_aPlayers[client][hHudTimer] = INVALID_HANDLE; - g_aPlayers[client][bIsDisplayingHud] = false; -} - -stock ResetClient(client) -{ - StopFollowingPlayer(client); - StopDisplayingHud(client); - - g_aPlayers[client][bIsFlaggedCheater] = false; - g_aPlayers[client][TargetPunishment] = Punish_None; - g_aPlayers[client][iBanTime] = -1; -} - -stock PerformPunishment(client, target, e_Punishments:punishment, const String:reason[], time = 300) -{ - new String:sTargetName[MAX_NAME_LENGTH + 1], - String:sTargetID[64]; - - /** - The target could have left the game by the time we get here - Check for a valid target - */ - if (!IsClientConnected(target) || !IsClientInGame(target)) - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Target Left"); - return; - } - - GetClientName(target, sTargetName, sizeof(sTargetName)); - GetClientAuthString(target, sTargetID, sizeof(sTargetID)); - - switch (punishment) - { - case Punish_Kick: - { - KickClient(g_aPlayers[client][iTargetIndex], "%s", reason); - } - case Punish_Ban: - { - if (g_aPluginSettings[bUseSourceBans]) - { - ClientCommand(client, "sm_ban #%d %d \"%s\"", GetClientUserId(target), time, reason); - } - else if (g_aPluginSettings[bUseMySQLBans]) - { - ClientCommand(client, "mysql_ban #%d %d \"%s\"", GetClientUserId(target), time, reason); - } - else - { - BanClient(target, time, BANFLAG_AUTHID, reason, reason); - } - } - case Punish_Cheater: - { - g_aPlayers[target][bIsFlaggedCheater] = true; - } - case Punish_Beacon: - { - ClientCommand(client, "sm_beacon \"%s\"", sTargetName); - } - case Punish_Blind: - { - ClientCommand(client, "sm_blind \"%s\"", sTargetName); - } - case Punish_Drug: - { - ClientCommand(client, "sm_drug \"%s\"", sTargetName); - } - case Punish_Freeze: - { - ClientCommand(client, "sm_freeze \"%s\"", sTargetName); - } - case Punish_FreezeBomb: - { - ClientCommand(client, "sm_freezebomb \"%s\"", sTargetName); - } - case Punish_Slap: - { - ClientCommand(client, "sm_slap \"%s\" 10", sTargetName); - } - case Punish_Slay: - { - ClientCommand(client, "sm_slay \"%s\"", sTargetName); - } - case Punish_TimeBomb: - { - ClientCommand(client, "sm_timebomb \"%s\"", sTargetName); - } - } - - if (punishment == Punish_Cheater) - { - LogAction(client, target, "[SM SPEC] %N marked %N(%s) with a %s flag for %s", client, target, sTargetID, g_sPunishments[punishment], reason); - } - else - { - ShowActivity(client, "%t", "Punished", sTargetName, g_sPunishments[punishment], reason); - LogAction(client, target, "[SM SPEC] %N punished %N(%s) with a %s for %s", client, target, sTargetID, g_sPunishments[punishment], reason); - } - - /** - Null the globals. - */ - g_aPlayers[client][TargetPunishment] = Punish_None; - g_aPlayers[client][iBanTime] = -1; -} - -/** -Build the menu of player names -*/ -stock Handle:BuildPlayerListMenu() -{ - new Handle:hMenu = CreateMenu(Menu_PlayerList); - AddTargetsToMenu(hMenu, 0, true, false); - SetMenuTitle(hMenu, "Select A Player:"); - SetMenuExitBackButton(hMenu, true); - return hMenu; -} - -/** -Build the select player menu (current or list of players) -*/ -stock Handle:BuildSelectPlayerMenu() -{ - new Handle:hMenu = CreateMenu(Menu_SelectPlayer); - SetMenuTitle(hMenu, "Select A Player:"); - AddMenuItem(hMenu, "Current", "Current Target"); - AddMenuItem(hMenu, "List", "Player List"); - SetMenuExitBackButton(hMenu, true); - return hMenu; -} - -/** -Build the punishmenu menu -*/ -stock Handle:BuildPunishmentMenu(iClient) -{ - new Handle:hMenu = CreateMenu(Menu_Punishments); - SetMenuTitle(hMenu, "Select A Punishment:"); - SetMenuExitBackButton(hMenu, true); - SetMenuExitButton(hMenu, true); - - if (g_aPluginCvarSettings[bKick] && ((GetUserFlagBits(iClient) & ADMFLAG_GENERIC) || (GetUserFlagBits(iClient) & ADMFLAG_ROOT))) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Kick], "Kick"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Kick], "Kick", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bBan] && ((GetUserFlagBits(iClient) & ADMFLAG_GENERIC) || (GetUserFlagBits(iClient) & ADMFLAG_ROOT))) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Ban], "Ban"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Ban], "Ban", ITEMDRAW_DISABLED); - } - - if (g_aPluginSettings[bUseDukehacks] && g_aPluginCvarSettings[bCheater] && (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Cheater], "Flag As Cheater"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Cheater], "Flag As Cheater", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bBeacon]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Beacon], "Beacon"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Beacon], "Beacon", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bBlind]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Blind], "Blind"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Blind], "Blind", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bDrug]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Drug], "Drug"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Drug], "Drug", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bFreeze]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Freeze], "Freeze"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Freeze], "Freeze", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bFreezebomb]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_FreezeBomb], "Freeze Bomb"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_FreezeBomb], "Freeze Bomb", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bSlap]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Slap], "Slap"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Slap], "Slap", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bSlay]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Slay], "Slay"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Slay], "Slay", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bTimeBomb]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_TimeBomb], "Time Bomb"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_TimeBomb], "Time Bomb", ITEMDRAW_DISABLED); - } - - return hMenu; -} - -/** -Build the punishmenu menu -*/ -stock Handle:BuildBanTimeMenu() -{ - new Handle:hMenu = CreateMenu(Menu_BanTime); - SetMenuTitle(hMenu, "Select Ban Type:"); - - if (g_aPluginCvarSettings[bBanPerm]) - { - AddMenuItem(hMenu, "permban", "Permanent"); - } - else - { - AddMenuItem(hMenu, "permban", "Permanent", ITEMDRAW_DISABLED); - } - - AddMenuItem(hMenu, "10", "10 Minutes"); - AddMenuItem(hMenu, "30", "30 Minutes"); - AddMenuItem(hMenu, "60", "1 Hour"); - AddMenuItem(hMenu, "240", "4 Hours"); - AddMenuItem(hMenu, "1440", "1 Day"); - AddMenuItem(hMenu, "10080", "1 Week"); - - SetMenuExitBackButton(hMenu, true); - return hMenu; -} - -/** -Build the punishmenu menu -*/ -stock Handle:BuildReasonMenu() -{ - new Handle:hMenu = CreateMenu(Menu_Reason); - SetMenuTitle(hMenu, "Select A Reason:"); - - AddMenuItem(hMenu, "Abusive", "Abusive"); - AddMenuItem(hMenu, "Racism", "Racism"); - AddMenuItem(hMenu, "General cheating/exploits", "General cheating/exploits"); - AddMenuItem(hMenu, "Wallhack", "Wallhack"); - AddMenuItem(hMenu, "Aimbot", "Aimbot"); - AddMenuItem(hMenu, "Speedhacking", "Speedhacking"); - AddMenuItem(hMenu, "Mic spamming", "Mic spamming"); - AddMenuItem(hMenu, "Admin disrepect", "Admin disrepect"); - AddMenuItem(hMenu, "Camping", "Camping"); - AddMenuItem(hMenu, "Team killing", "Team killing"); - AddMenuItem(hMenu, "Unacceptable Spray", "Unacceptable Spray"); - AddMenuItem(hMenu, "Breaking Server Rules", "Breaking Server Rules"); - AddMenuItem(hMenu, "Other", "Other"); - - SetMenuExitBackButton(hMenu, true); - return hMenu; -} - -/** -Build the cheater displays -*/ -stock Handle:BuildAdminCheaterPanel() -{ - - /** - Create the menu and set the menu options. - */ - new Handle:hPanel = CreatePanel(); - SetPanelTitle(hPanel, "Simple Spectator:"); - - DrawPanelText(hPanel, "Are you sure you want to"); - DrawPanelText(hPanel, "flag this player as a cheater?"); - DrawPanelText(hPanel, "They will not be able to damage"); - DrawPanelText(hPanel, "anyone and die on fall damage."); - DrawPanelItem(hPanel, "Yes"); - DrawPanelItem(hPanel, "No"); - - return hPanel; -} - -stock Handle:BuildPublicCheaterPanel() -{ - - /** - Create the menu and set the menu options. - */ - new Handle:hPanel = CreatePanel(); - SetPanelTitle(hPanel, "Simple Spectator:"); - - DrawPanelText(hPanel, "Are you sure you want to"); - DrawPanelText(hPanel, "submit this player as a cheater?"); - DrawPanelItem(hPanel, "Yes (Not Implemented Yet)", ITEMDRAW_DISABLED); - DrawPanelItem(hPanel, "No"); - return hPanel; -} - -/** -Build the hud displays -*/ -stock Handle:BuildPlayerHudMenu(iClient, iTarget) -{ - - /** - Create all the string variables we will need - */ - new String:sTargetName[MAX_NAME_LENGTH + 1], - String:sTargetID[64], - String:sTargetIP[16]; - - new String:sDisplayName[MAX_NAME_LENGTH + 1], - String:sDisplayID[64], - String:sDisplayIP[64], - String:sDisplayFrags[16], - String:sDisplayDeaths[16]; - - new iTargetFrags, - iTargetDeaths; - - /** - Get the targets information - */ - GetClientName(iTarget, sTargetName, sizeof(sTargetName)); - GetClientIP(iTarget, sTargetIP, sizeof(sTargetIP)); - GetClientAuthString(iTarget, sTargetID, sizeof(sTargetID)); - iTargetFrags = GetClientFrags(iTarget); - iTargetDeaths = GetClientDeaths(iTarget); - - /** - Format the strings for the menu - */ - Format(sDisplayName, sizeof(sDisplayName), "Player: %s", sTargetName); - Format(sDisplayID, sizeof(sDisplayID), "Steam ID: %s", sTargetID); - Format(sDisplayIP, sizeof(sDisplayIP), "IP Address: %s", sTargetIP); - Format(sDisplayFrags, sizeof(sDisplayFrags), "Kills: %i", iTargetFrags); - Format(sDisplayDeaths, sizeof(sDisplayDeaths), "Deaths: %i", iTargetDeaths); - - /** - Create the menu and set the menu options. - */ - new Handle:hMenu = CreateMenu(Menu_PlayerHud); - SetMenuExitBackButton(hMenu, false); - SetMenuTitle(hMenu, "Simple Spectator"); - - AddMenuItem(hMenu, "name", sDisplayName, ITEMDRAW_DISABLED); - AddMenuItem(hMenu, "steamid", sDisplayID, ITEMDRAW_DISABLED); - - if (SM_IsValidAdmin(iClient, g_sAdminFlags)) - { - AddMenuItem(hMenu, "ip", sDisplayIP, ITEMDRAW_DISABLED); - } - - AddMenuItem(hMenu, "kills", sDisplayFrags, ITEMDRAW_DISABLED); - AddMenuItem(hMenu, "deaths", sDisplayDeaths, ITEMDRAW_DISABLED); - - if (g_aPlayers[iClient][iTargetIndex]) - { - AddMenuItem(hMenu, "stop", "Stop Following"); - } - else - { - AddMenuItem(hMenu, "start", "Follow Player"); - } - - if ((GetUserFlagBits(iClient) & ADMFLAG_GENERIC) || (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - if (g_aPlayers[iTarget][bIsFlaggedCheater] && (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - AddMenuItem(hMenu, "removecheater", "Remove Cheater Flag"); - } - else - { - if (CanUserTarget(iClient, iTarget)) - { - AddMenuItem(hMenu, "punish", "Punish Player"); - } - else - { - AddMenuItem(hMenu, "punish", "Punish Player (Immune)", ITEMDRAW_DISABLED); - } - } - } - else - { - AddMenuItem(hMenu, "reportcheater", "Report Cheater"); - } - - SetMenuPagination(hMenu, MENU_NO_PAGINATION); - SetMenuExitButton(hMenu, true); - return hMenu; -} - -stock Handle:BuildPlayerHudPanel(iClient, iTarget) -{ - - /** - Create all the string variables we will need - */ - new String:sTargetName[MAX_NAME_LENGTH + 1], - String:sTargetID[64], - String:sTargetIP[16]; - - new String:sDisplayName[MAX_NAME_LENGTH + 1], - String:sDisplayID[64], - String:sDisplayIP[64], - String:sDisplayFrags[16], - String:sDisplayDeaths[16]; - - new iTargetFrags, - iTargetDeaths; - - /** - Get the targets information - */ - GetClientName(iTarget, sTargetName, sizeof(sTargetName)); - GetClientIP(iTarget, sTargetIP, sizeof(sTargetIP)); - GetClientAuthString(iTarget, sTargetID, sizeof(sTargetID)); - iTargetFrags = GetClientFrags(iTarget); - iTargetDeaths = GetClientDeaths(iTarget); - - /** - Format the strings for the menu - */ - Format(sDisplayName, sizeof(sDisplayName), "Player: %s", sTargetName); - Format(sDisplayID, sizeof(sDisplayID), "Steam ID: %s", sTargetID); - Format(sDisplayIP, sizeof(sDisplayIP), "IP Address: %s", sTargetIP); - Format(sDisplayFrags, sizeof(sDisplayFrags), "Kills: %i", iTargetFrags); - Format(sDisplayDeaths, sizeof(sDisplayDeaths), "Deaths: %i", iTargetDeaths); - - /** - Create the menu and set the menu options. - */ - new Handle:hPanel = CreatePanel(); - SetPanelTitle(hPanel, "Simple Spectator"); - - DrawPanelText(hPanel, "Player Information:"); - DrawPanelText(hPanel, sDisplayName); - DrawPanelText(hPanel, sDisplayID); - if (SM_IsValidAdmin(iClient, g_sAdminFlags)) - { - DrawPanelText(hPanel, sDisplayIP); - } - - DrawPanelText(hPanel, sDisplayFrags); - DrawPanelText(hPanel, sDisplayDeaths); - - if (g_aPlayers[iClient][iTargetIndex]) - { - DrawPanelItem(hPanel, "Stop Following"); - } - else - { - DrawPanelItem(hPanel, "Follow Player"); - } - - if ((GetUserFlagBits(iClient) & ADMFLAG_GENERIC) || (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - if (g_aPlayers[iTarget][bIsFlaggedCheater] && (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - DrawPanelItem(hPanel, "Remove Cheater Flag"); - } - else - { - if (CanUserTarget(iClient, iTarget)) - { - DrawPanelItem(hPanel, "Punish Player"); - } - else - { - DrawPanelItem(hPanel, "Punish Player (Immune)", ITEMDRAW_DISABLED); - } - } - } - else - { - DrawPanelItem(hPanel, "Report Cheater"); - } - - DrawPanelItem(hPanel, "Close Hud Panel"); - return hPanel; -} - -/** -Adjust the settings if a convar was changed -*/ -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - for (new iCvar = 0 ; _:iCvar < sizeof(g_aPluginCvarSettings); iCvar++) - { - if (g_aPluginCvar[_:iCvar] == convar) - { - if (StringToInt(newValue) == 1) - { - g_aPluginCvarSettings[_:iCvar] = true; - } - else - { - g_aPluginCvarSettings[_:iCvar] = false; - } - } - } - - /* - ReBuild the global menu that depends on cvars - */ - g_aMenus[hBanTime] = BuildBanTimeMenu(); - - /** - Run a loop to reset the hud - */ - for(new i = 1; i <= MaxClients; i++) - { - StopDisplayingHud(i); - if (IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(i); - } - } -} diff --git a/Simple Plugins Core/addons/sourcemod/scripting/simple-teambalancer.sp b/Simple Plugins Core/addons/sourcemod/scripting/simple-teambalancer.sp deleted file mode 100644 index 3302255..0000000 --- a/Simple Plugins Core/addons/sourcemod/scripting/simple-teambalancer.sp +++ /dev/null @@ -1,1797 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Team Balancer -Description: - Balances teams based upon player count - Player will not be balanced more than once in 5 (default) mins - Buddy system tries to keep buddies together - Ability to prioritize players - Ability to force players to accept the new team - Admins are immune -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include -#include - -#define PLUGIN_VERSION "2.1.$Rev$" - -enum PlayerData -{ - Handle:hBalanceTimer, - Handle:hForcedTimer, - bool:bSwitched, - bool:bFlagCarrier -}; - -/** - Global convar handles - */ -new Handle:stb_enabled = INVALID_HANDLE; -new Handle:stb_buddyenabled = INVALID_HANDLE; -new Handle:stb_logactivity = INVALID_HANDLE; -new Handle:stb_logactivity2 = INVALID_HANDLE; -new Handle:stb_unbalancelimit = INVALID_HANDLE; -new Handle:stb_deadonly = INVALID_HANDLE; -new Handle:stb_priorityenabled = INVALID_HANDLE; -new Handle:stb_uberlevel = INVALID_HANDLE; -new Handle:stb_balancedelay = INVALID_HANDLE; -new Handle:stb_livingplayerswitchdelay = INVALID_HANDLE; -new Handle:stb_livingplayercheckdelay = INVALID_HANDLE; -new Handle:stb_roundstartdelay = INVALID_HANDLE; -new Handle:stb_switchbackforced = INVALID_HANDLE; -new Handle:stb_adminflag = INVALID_HANDLE; -new Handle:stb_buddyrestriction = INVALID_HANDLE; -new Handle:stb_convarcontrol = INVALID_HANDLE; - -/** - Built-in cvars handles - */ -new Handle:stb_mp_autoteambalance = INVALID_HANDLE; -new Handle:stb_mp_teams_unbalance_limit = INVALID_HANDLE; -new Handle:TFGameModeArena = INVALID_HANDLE; - -/** - Timer handles - */ -new Handle:g_hBalanceTimer = INVALID_HANDLE; -new Handle:g_hLivingPlayerCheckTimer = INVALID_HANDLE; - -/** - Player arrays - */ -new g_aPlayers[MAXPLAYERS + 1][PlayerData]; - -/** -Global bools -*/ -new bool:g_bIsEnabled = true; -new bool:g_bPriorityPlayers = true; -new bool:g_bBuddyRestriction = false; -new bool:g_bLogActivity = false; -new bool:g_bLogActivity2 = false; -new bool:g_bDeadOnly = false; -new bool:g_bConVarControl = true; -new bool:g_bBuddyEnabled = true; -new bool:g_bBalanceInProgress = false; -new bool:g_bRoundStart = false; -new bool:g_bRoundEnd = false; -new bool:g_bSuddenDeath = false; -new bool:g_bIsArenaMode = false; - -/** - Global strings/integers/floats - */ -new g_iUnbalanceLimit, g_iLivingPlayerSwitchDelay, g_iLivingPlayerCheckDelay; -new g_iRoundStartDelay, g_iSwitchBackForced, g_iBalanceDelay; -new Float:g_fUberLevel; -new g_iOwnerOffset; -new String:g_sAdminFlag[5]; - -public Plugin:myinfo = -{ - name = "Simple Team Balancer", - author = "Simple Plugins", - description = "Balances teams based upon player count.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -} - -public OnPluginStart() -{ - - /** - Create console variables - */ - CreateConVar("stb_version", PLUGIN_VERSION, "Simple Team Balancer", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - stb_enabled = CreateConVar("stb_enabled", "1", "Enable or Disable Simple Team Balancer", _, true, 0.0, true, 1.0); - stb_priorityenabled = CreateConVar("stb_priorityenabled", "1", "Enable or Disable the prioritization of living players", _, true, 0.0, true, 1.0); - stb_buddyrestriction = CreateConVar("stb_buddyrestriction", "0", "Enable or Disable Admin Only buddy lists", _, true, 0.0, true, 1.0); - stb_logactivity = CreateConVar("stb_logactivity", "0", "Enable or Disable the disaplying of events in the log", _, true, 0.0, true, 1.0); - stb_logactivity2 = CreateConVar("stb_logactivity2", "0", "Enable or Disable the disaplying of detailed events in the log (WILL SPAM LOG)", _, true, 0.0, true, 1.0); - stb_deadonly = CreateConVar("stb_deadonly", "0", "Enable or Disable the switching of only dead players", _, true, 0.0, true, 1.0); - stb_convarcontrol = CreateConVar("stb_convarcontrol", "1", "Enable or Disable the control of builtin console variables", _, true, 0.0, true, 1.0); - stb_buddyenabled = CreateConVar("stb_buddyenabled", "1", "Enable or Disable the buddy system", _, true, 0.0, true, 1.0); - stb_unbalancelimit = CreateConVar("stb_unbalancelimit", "2", "Amount of players teams are ALLOWED to be unbalanced by", _, true, 1.0, true, 32.0); - stb_balancedelay = CreateConVar("stb_balancedelay", "10", "Delay in seconds to start an autobalance"); - stb_livingplayerswitchdelay = CreateConVar("stb_livingplayerswitchdelay", "20", "Delay in seconds to switch living players once selected"); - stb_livingplayercheckdelay = CreateConVar("stb_livingplayercheckdelay", "10", "Delay in seconds to start checking living players once teams become unbalanced"); - stb_roundstartdelay = CreateConVar("stb_roundstartdelay", "15", "Delay in seconds to start balancing teams after the start of a round"); - stb_switchbackforced = CreateConVar("stb_switchbackforced", "300", "Amount of time in seconds to not switch a player twice and force the team if enabled"); - stb_uberlevel = CreateConVar("stb_uberlevel", "1.0", "Min uber level medic must have to have priority over other living players. Setting to 0 will rarely switch a living medic", _, true, 0.0, true, 1.0); - stb_adminflag = CreateConVar("stb_adminflag", "a", "Admin flag to use for immunity. Must be a in char format."); - stb_mp_autoteambalance = FindConVar("mp_autoteambalance"); - stb_mp_teams_unbalance_limit = FindConVar("mp_teams_unbalance_limit"); - - /** - Removing the notify tags from the built in cvars. We dont want spam. - */ - if (stb_mp_autoteambalance != INVALID_HANDLE) - { - SetConVarFlags(stb_mp_autoteambalance, GetConVarFlags(stb_mp_autoteambalance)^FCVAR_NOTIFY); - } - if (stb_mp_teams_unbalance_limit != INVALID_HANDLE) - { - SetConVarFlags(stb_mp_teams_unbalance_limit, GetConVarFlags(stb_mp_teams_unbalance_limit)^FCVAR_NOTIFY); - } - - /** - Hook console variables - */ - HookConVarChange(stb_enabled, ConVarSettingsChanged); - HookConVarChange(stb_priorityenabled, ConVarSettingsChanged); - HookConVarChange(stb_buddyrestriction, ConVarSettingsChanged); - HookConVarChange(stb_logactivity, ConVarSettingsChanged); - HookConVarChange(stb_logactivity2, ConVarSettingsChanged); - HookConVarChange(stb_deadonly, ConVarSettingsChanged); - HookConVarChange(stb_convarcontrol, ConVarSettingsChanged); - HookConVarChange(stb_buddyenabled, ConVarSettingsChanged); - HookConVarChange(stb_unbalancelimit, ConVarSettingsChanged); - HookConVarChange(stb_balancedelay, ConVarSettingsChanged); - HookConVarChange(stb_livingplayerswitchdelay, ConVarSettingsChanged); - HookConVarChange(stb_livingplayercheckdelay, ConVarSettingsChanged); - HookConVarChange(stb_roundstartdelay, ConVarSettingsChanged); - HookConVarChange(stb_switchbackforced, ConVarSettingsChanged); - HookConVarChange(stb_uberlevel, ConVarSettingsChanged); - HookConVarChange(stb_mp_autoteambalance, ConVarSettingsChanged); - HookConVarChange(stb_mp_teams_unbalance_limit, ConVarSettingsChanged); - - /** - Create console commands - */ - RegConsoleCmd("sm_buddy", Command_AddBalanceBuddy, "Add a balance buddy"); - RegConsoleCmd("sm_lockbuddy", Command_LockBuddy, "Locks your balance buddy selection"); - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[STB] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_death", HookPlayerDeath, EventHookMode_Post); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Post); - switch (g_CurrentMod) - { - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - HookEvent("teamplay_suddendeath_begin", HookSuddenDeathBegin, EventHookMode_PostNoCopy); - HookEvent("teamplay_flag_event", HookFlagEvent, EventHookMode_Post); - TFGameModeArena = FindConVar("tf_gamemode_arena"); - g_iOwnerOffset = FindSendPropInfo("CBaseObject", "m_hBuilder"); - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_Post); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - - /** - Load translations and .cfg file - */ - LoadTranslations ("simpleteambalancer.phrases"); - AutoExecConfig(true, "plugin.simpleteambalancer"); - LogAction(0, -1, "[STB] Simple Team Balancer is loaded."); -} - -public OnAllPluginsLoaded() -{ - //something -} - -public OnLibraryRemoved(const String:name[]) -{ - //something -} - -public OnConfigsExecuted() -{ - - /** - Load up global variables - */ - g_bIsEnabled = GetConVarBool(stb_enabled); - g_bBuddyEnabled = GetConVarBool(stb_buddyenabled); - g_bLogActivity = GetConVarBool(stb_logactivity); - g_bLogActivity2 = GetConVarBool(stb_logactivity2); - g_bDeadOnly = GetConVarBool(stb_deadonly); - g_bPriorityPlayers = GetConVarBool(stb_priorityenabled); - g_bBuddyRestriction = GetConVarBool(stb_buddyrestriction); - g_bConVarControl = GetConVarBool(stb_convarcontrol); - g_fUberLevel = GetConVarFloat(stb_uberlevel); - g_iUnbalanceLimit = GetConVarInt(stb_unbalancelimit); - g_iBalanceDelay = GetConVarInt(stb_balancedelay); - g_iLivingPlayerSwitchDelay = GetConVarInt(stb_livingplayerswitchdelay); - g_iLivingPlayerCheckDelay = GetConVarInt(stb_livingplayercheckdelay); - g_iRoundStartDelay = GetConVarInt(stb_roundstartdelay); - g_iSwitchBackForced = GetConVarInt(stb_switchbackforced); - GetConVarString(stb_adminflag, g_sAdminFlag, sizeof(g_sAdminFlag)); - - /** - Report enabled - */ - if (g_bIsEnabled) - { - LogAction(0, -1, "[STB] Simple Team Balancer is ENABLED."); - } - else - { - LogAction(0, -1, "[STB] Simple Team Balancer is DISABLED."); - } - - - /** - Report log activity - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Log Activity ENABLED."); - } - else - { - LogAction(0, -1, "[STB] Log Activity DISABLED."); - } - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Detailed Log Activity ENABLED."); - } - else - { - LogAction(0, -1, "[STB] Detailed Log Activity DISABLED."); - } -} - -public OnMapStart() -{ - - /** - Check for arena mode - */ - if (g_CurrentMod == GameType_TF && GetConVarBool(TFGameModeArena)) - { - g_bIsArenaMode = true; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Simple Team Balancer detected arena mode and will be bypassed"); - } - } - else - { - g_bIsArenaMode = false; - } - - /** - Reset the globals - */ - g_bBalanceInProgress = false; - g_bRoundStart = false; - g_bRoundEnd = false; - g_bSuddenDeath = false; - - /** - Set the built-in convars - */ - SetGameCvars(); -} - -public OnClientPostAdminCheck(client) -{ - - /** - Make sure its a valid connected client and buddy system is enabled - */ - if (client == 0 || !g_bIsEnabled || !IsClientConnected(client) || !g_bBuddyEnabled) - { - return; - } - - /** - Make sure if its set for admins only they have the flags - */ - if (g_bBuddyRestriction && !SM_IsValidAdmin(client, g_sAdminFlag)) - { - return; - } - - /** - Start the advertisement timer - */ - CreateTimer (60.0, Timer_WelcomeAdvert, client); -} - -public OnClientDisconnect(client) -{ - - /** - Call stock function to cleaup - */ - CleanUp(client); -} - -public OnClientDisconnect_Post(client) -{ - - /** - Determine if we need a balance - */ - if (OkToBalance() && IsUnbalanced() && !g_bBalanceInProgress) - { - - /** - No balance in progress but balance is needed - */ - StartABalance(); - } -} - -public SM_OnPlayerMoved(Handle:plugin, client, team) -{ - - /** - Make sure we called the move function - */ - if (plugin != GetMyHandle()) - { - if (g_bLogActivity2) - { - LogAction(0, client, "[STB] Callback was not started with current plugin, bugging out."); - } - return; - } - - /** - Get the players name and report the event - */ - decl String:sPlayerName[64]; - GetClientName(client, sPlayerName, sizeof(sPlayerName)); - if (g_bLogActivity) - { - LogAction(0, client, "[STB] Changed %s to team %i.", sPlayerName, team); - } - - /** - If we are in TF2 fire the bult-in team balance event - */ - if(g_CurrentMod == GameType_TF) - { - new Handle:event = CreateEvent("teamplay_teambalanced_player"); - SetEventInt(event, "player", client); - SetEventInt(event, "team", team); - FireEvent(event); - } - - /** - Notify the players - */ - PrintToChatAll("[SM] %T", "BalanceMessage", LANG_SERVER, sPlayerName); - - /** - Set the players variables and start a timer - */ - g_aPlayers[client][bSwitched] = true; - g_aPlayers[client][hForcedTimer] = CreateTimer(float(g_iSwitchBackForced), Timer_ForcedExpired, client, TIMER_FLAG_NO_MAPCHANGE); - - /** - We are done, log the completion and end the balance - */ - if (g_bLogActivity) - { - LogAction(0, client, "[STB] Balance finished."); - } - g_bBalanceInProgress = false; -} - -/* HOOKED EVENTS */ - -public HookPlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get our event variables - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - decl String:sWeapon[64]; - GetEventString(event, "weapon", sWeapon, sizeof(sWeapon)); - - /** - Return if death was not caused by a player - This is the case when the player switches teams - */ - if (StrEqual(sWeapon, "world", false)) - { - return; - } - - - /** - Check if balance is needed - */ - if (IsClientInGame(iClient) && OkToBalance() && IsUnbalanced()) - { - new iSmallerTeam = GetSmallerTeam(); - - /** - Check if balance is in progress - */ - if (g_bBalanceInProgress) - { - - /** - There is a balance in progress - Check the player who died to see if he is supposed to be switched - */ - if (g_aPlayers[iClient][hBalanceTimer] != INVALID_HANDLE) - { - - /** - The player has a timer on him to switch him to other team - Stop the timer - */ - CloseHandle(g_aPlayers[iClient][hBalanceTimer]); - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] With a balance in progress the queued living player died and was switched."); - } - - /** - Call the stock change team function - */ - BalancePlayer(iClient, SM_GetForcedTeam(iClient)); - return; - } - - /** - Before we continue, lets make sure the client is switchable - */ - if (IsSwitchablePlayer(iClient, GetBiggerTeam())) - { - - /** - Now we check the buddy system - */ - if (g_bBuddyEnabled) - { - - /** - Buddy system is enabled, check to see if client has buddy - */ - new iBuddyIndex = SM_GetClientBuddy(iClient); - if (iBuddyIndex != 0 || !IsClientConnected(iBuddyIndex) || !IsClientInGame(iBuddyIndex)) - { - - /** - The client has a buddy, so we check to see if they are on same team - */ - if (GetClientTeam(iClient) == GetClientTeam(iBuddyIndex)) - { - - /** - They are, but we don't bug out, we still need to start a balance - */ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] With a balance in progress a buddy on the right team was found and skipped."); - } - } - else - { - - /** - They are not on the same team - The buddy could be in spec, and that would make it not matter where he is, or the buddy is on the smaller team - */ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] With a balance in progress a buddy on the wrong team was switched."); - } - BalancePlayer(iClient, iSmallerTeam); - return; - } - } - else - { - - /** - Client doesn't have a buddy, balance this player - */ - BalancePlayer(iClient, iSmallerTeam); - return; - } - } - else - { - - /** - Buddy system is not enabled, balance this player - */ - BalancePlayer(iClient, iSmallerTeam); - return; - } - } - } - else - { - - /** - If we get to here then we must need to start a balance - */ - StartABalance(); - } - } -} - -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get our event variables. - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - new iTeam = GetEventInt(event, "team"); - - /** - Make sure its ok to balance. - */ - if (OkToBalance()) - { - - /** - See if the client that changed teams was set to with a balance. - */ - if (g_aPlayers[iClient][hBalanceTimer] != INVALID_HANDLE - && SM_GetForcedTeam(iClient) == iTeam - && g_bBalanceInProgress) - { - - /** - The client was set to be balanced, so we close the timer. - */ - CloseHandle(g_aPlayers[iClient][hBalanceTimer]); - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - - /** - Stop the balance. - */ - g_bBalanceInProgress = false; - return; - } - - /** - It's not likely that this team change can cause us to need a balance. - If it does, start one with a small dealy to deal with forced switch backs. - */ - if (IsUnbalanced() && !g_bBalanceInProgress) - { - CreateTimer(2.0, Timer_ChangeTeamBalanceDelay, _, TIMER_FLAG_NO_MAPCHANGE); - } - } -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set the variables we need to start a round - */ - g_bRoundStart = true; - g_bRoundEnd = false; - g_bSuddenDeath = false; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Round Started"); - } - - /** - Start a delayed balance check at the start of the round - */ - CreateTimer(float(g_iRoundStartDelay), Timer_RoundStart); -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set the variables we need at round end - */ - g_bRoundEnd = true; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Round Ended"); - } -} - -public HookSuddenDeathBegin(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set the variables we need for sudden death - */ - g_bSuddenDeath = true; -} - -public HookFlagEvent(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get our event variables - */ - new iClient = GetEventInt(event, "player"); - new iFlagStatus = GetEventInt(event, "eventtype"); - - /** - Make sure we have a valid client - */ - if (!IsClientInGame(iClient)) - { - return; - } - - /** - Determine what kind of event this is - */ - switch (iFlagStatus) - { - case 1: - { - - /** - The flag was picked up - */ - g_aPlayers[iClient][bFlagCarrier] = true; - } - case 2: - { - - /** - The flag was capped - */ - g_aPlayers[iClient][bFlagCarrier] = false; - } - case 3: - { - - /** - The flag was defended, we don't have to do anything - */ - } - case 4: - { - - /** - The flag was dropped - */ - g_aPlayers[iClient][bFlagCarrier] = false; - } - } -} - -/* COMMAND EVENTS */ - -public Action:Command_AddBalanceBuddy(client, args) -{ - if (client == 0) - { - ReplyToCommand(client, "[SM] %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - if (!g_bIsEnabled || !g_bBuddyEnabled) - { - ReplyToCommand(client, "[SM] %T", "CmdDisabled", LANG_SERVER); - return Plugin_Handled; - } - if (g_bBuddyRestriction) - { - if (!SM_IsValidAdmin(client, g_sAdminFlag)) - { - ReplyToCommand(client, "[SM] %T", "RestrictedBuddy", LANG_SERVER); - return Plugin_Handled; - } - } - decl String:sPlayerUserId[24]; - GetCmdArg(1, sPlayerUserId, sizeof(sPlayerUserId)); - new iPlayer = GetClientOfUserId(StringToInt(sPlayerUserId)); - if (!iPlayer || !IsClientInGame(iPlayer) || client == iPlayer) - { - if (client == iPlayer) - { - PrintHintText(client, "%T", "SelectSelf", LANG_SERVER); - } - ReplyToCommand(client, "[SM] Usage: buddy "); - new Handle:playermenu = BuildPlayerMenu(); - DisplayMenu(playermenu, client, MENU_TIME_FOREVER); - } - else - { - decl String:cName[128]; - decl String:bName[128]; - GetClientName(client, cName, sizeof(cName)); - GetClientName(iPlayer, bName, sizeof(bName)); - if (SM_IsBuddyLocked(iPlayer)) - { - ReplyToCommand(client, "[SM] %T", "PlayerLockedBuddyMsg", LANG_SERVER, bName); - return Plugin_Handled; - } - SM_AssignBuddy(client, iPlayer); - PrintHintText(client, "%T", "BuddyMsg", LANG_SERVER, bName); - PrintHintText(iPlayer, "%T", "BuddyMsg", LANG_SERVER, cName); - } - return Plugin_Handled; -} - -public Action:Command_LockBuddy(client, args) -{ - if (client == 0) - { - ReplyToCommand(client, "[SM] %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - if (!g_bIsEnabled) - { - ReplyToCommand(client, "[SM] %T", "CmdDisabled", LANG_SERVER); - return Plugin_Handled; - } - if (g_bBuddyRestriction) - { - if (!SM_IsValidAdmin(client, g_sAdminFlag)) - { - ReplyToCommand(client, "[SM] %T", "RestrictedBuddy", LANG_SERVER); - return Plugin_Handled; - } - } - if (SM_IsBuddyLocked(client)) - { - SM_LockBuddy(client, false); - PrintHintText(client, "%T", "BuddyLockMsgDisabled", LANG_SERVER); - } - else - { - SM_LockBuddy(client, true); - PrintHintText(client, "%T", "BuddyLockMsgEnabled", LANG_SERVER); - } - return Plugin_Handled; -} - -/** -Stock functions . - */ - -stock bool:IsUnbalanced() -{ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Checking if teams are unbalanced"); - } - new Team1Count = GetTeamClientCount(g_aCurrentTeams[Team1]); - new Team2Count = GetTeamClientCount(g_aCurrentTeams[Team2]); - new ubCount = RoundFloat(FloatAbs(float(Team1Count - Team2Count))); - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Team1:%i Team2:%i Difference:%i", Team1Count, Team2Count, ubCount); - } - if (ubCount > g_iUnbalanceLimit) - { - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Teams are unbalanced"); - } - return true; - } - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Teams are not unbalanced"); - } - return false; -} - -stock bool:OkToBalance() -{ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Checking if OK to balance."); - } - new bool:bResult = false; - if (g_bIsEnabled && !g_bRoundStart && !g_bRoundEnd && !g_bIsArenaMode && !g_bSuddenDeath) - { - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Passed IF statement"); - LogAction(0, -1, "[STB] Now checking admins"); - } - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientInGame(i) && !SM_IsValidAdmin(i, g_sAdminFlag)) - { - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Found at least 1 non-admin"); - LogAction(0, -1, "[STB] OK to balance"); - } - bResult = true; - break; - } - } - if (!bResult && g_bLogActivity2) - { - LogAction(0, -1, "[STB] All admins online"); - } - } - if (!bResult && g_bLogActivity2) - { - LogAction(0, -1, "[STB] Not OK to balance"); - } - return bResult; -} - -stock bool:IsSwitchablePlayer(iClient, iBiggerTeam) -{ - - /** - Run the client thru some standard checks - */ - if (!IsClientInGame(iClient) - || SM_IsValidAdmin(iClient, g_sAdminFlag) - || g_aPlayers[iClient][bFlagCarrier] - || GetClientTeam(iClient) != iBiggerTeam - || g_aPlayers[iClient][bSwitched]) - { - - /** - The supplied client can't be switched - */ - return false; - } - - /** - The supplied client can be switched - */ - return true; -} - -stock bool:HasUber(iClient) -{ - - /** - First things first, make sure the client is a medic - */ - if(TF2_GetPlayerClass(iClient) == TFClass_Medic) - { - - /** - We can only check the active weapon, so make sure the client is holding the uber gun - */ - decl String:sWeaponName[32]; - GetClientWeapon(iClient, sWeaponName, sizeof(sWeaponName)); - if(StrEqual(sWeaponName, "tf_weapon_medigun")) - { - - /** - They are, so lets check the uber level of the gun - */ - new iEntityIndex = GetEntDataEnt2(iClient, FindSendPropInfo("CTFPlayer", "m_hActiveWeapon")); - new Float:fChargeLevel = GetEntDataFloat(iEntityIndex, FindSendPropInfo("CWeaponMedigun", "m_flChargeLevel")); - if (fChargeLevel >= g_fUberLevel) - { - - /** - The client supplied has an uber above the supplied level, return true - */ - if (g_bLogActivity2) - { - LogAction(0, iClient, "[STB] Found a medic with a uber and skipped him."); - } - return true; - } - } - } - - /** - The client supplied does not have an uber above the supplied level, return false - */ - return false; -} - -stock bool:HasBuildingsBuilt(iClient) -{ - - /** - We have to start a loop to check the owner of all the valid entities - */ - new iMaxEntities = GetMaxEntities(); - for (new i = MaxClients + 1; i <= iMaxEntities; i++) - { - if (!IsValidEntity(i)) - { - - /** - Not valid, continue to next one - */ - continue; - } - - /** - Get the name of the current entity - */ - decl String:sNetClass[32]; - GetEntityNetClass(i, sNetClass, sizeof(sNetClass)); - - /** - See if its something that an engineer would build - */ - if (strcmp(sNetClass, "CObjectSentrygun") == 0 - || strcmp(sNetClass, "CObjectTeleporter") == 0 - || strcmp(sNetClass, "CObjectDispenser") == 0) - { - - /** - It is, so lets check the owner - */ - if (GetEntDataEnt2(i, g_iOwnerOffset) == iClient) - { - - /** - The client supplied is the owner, return true - */ - if (g_bLogActivity2) - { - LogAction(0, iClient, "[STB] Found an engineer with buildings and skipped him."); - } - return true; - } - } - } - - /** - The client supplied didn't have any buildings, return false - */ - return false; -} - -stock StartABalance() -{ - - /** - See if we are already started a balance - */ - if (g_hBalanceTimer != INVALID_HANDLE) - { - - /** - We have, check if we still need to - */ - if (!IsUnbalanced() || !OkToBalance()) - { - - /** - We don't, stop the balance - It's almost impossible to reach this code, but we do it just in case - */ - CloseHandle(g_hBalanceTimer); - g_hBalanceTimer = INVALID_HANDLE; - g_bBalanceInProgress = false; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Balance delay timer was not needed and was killed before the callback."); - } - return; - } - else - { - - /** - We still need to balance - Bug out and wait for the current one to finish - */ - return; - } - } - - /** - Report that teams are unbalanced - */ - PrintToChatAll("[SM] %T", "UnBalanced", LANG_SERVER); - - /** - Check to see if we are supposed to delay the balance - */ - if (g_iBalanceDelay == 0) - { - - /** - Start the balance now - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Balance is now in progress."); - } - g_bBalanceInProgress = true; - g_hBalanceTimer = INVALID_HANDLE; - - /** - Check if we are allowed to scan living players - */ - if (!g_bDeadOnly) - { - - /** - We are allowed to, so we start a timer - */ - StartALivingPlayerTimer(); - - /** - Also report that we are now scanning dead players as well - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Now scanning dead players."); - } - } - else - { - - /** - We are not allowed to, so report that we are only scanning dead players - */ - if (g_bLogActivity) - LogAction(0, -1, "[STB] Only scanning dead players."); - } - - /** - We started the balance, bug out - */ - return; - } - - /** - We are supposed to delay the balance, start a balance timer - */ - g_hBalanceTimer = CreateTimer(float(g_iBalanceDelay), Timer_BalanceTeams, _, TIMER_FLAG_NO_MAPCHANGE); - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Teams are unbalanced. Balance delay timer started."); - } -} - -stock StartALivingPlayerTimer() -{ - - /** - Start a timer to check living players - */ - if (g_hLivingPlayerCheckTimer != INVALID_HANDLE) - { - - /** - If we for some reason already have one started, stop it. - */ - CloseHandle(g_hLivingPlayerCheckTimer); - g_hLivingPlayerCheckTimer = INVALID_HANDLE; - } - - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Living player balance delay timer started."); - } - g_hLivingPlayerCheckTimer = CreateTimer(float(g_iLivingPlayerCheckDelay), Timer_LivingPlayerCheck, _, TIMER_FLAG_NO_MAPCHANGE); -} - -stock FindSwitchablePlayer() -{ - - /** - Start a loop to find a switchable player - */ - new iPlayer; - new iBiggerTeam = GetBiggerTeam(); - for (new i = 1; i <= MaxClients; i++) - { - - /** - Check the stock function to see if we are allows to even switch the player - */ - if (!IsSwitchablePlayer(i, iBiggerTeam)) - { - continue; - } - - /** - If the mod is TF2 and they have Priority Players set check if the client has buildings or an uber - */ - if (g_CurrentMod == GameType_TF && g_bPriorityPlayers) - { - if (HasUber(i) || HasBuildingsBuilt(i)) - { - continue; - } - } - - /** - So far we are able we switch this player - Now we check the buddy system - */ - if (g_bBuddyEnabled) - { - - /** - Buddy system is enabled, check to see if client has buddy - */ - if (SM_GetClientBuddy(i) != 0) - { - - /** - The client has a buddy, so we check to see if they are on same team - */ - if (GetClientTeam(i) == GetClientTeam(SM_GetClientBuddy(i))) - { - - /** - They are, so we continue to next client - */ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] With a balance in progress a buddy on the right team was found and skipped."); - } - continue; - } - else - { - - /** - They are not on the same team, set this client - The buddy could be in spec, and that would make it not matter where he is, or the buddy is on the smaller team - */ - iPlayer = i; - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] With a balance in progress a buddy on the wrong team was found."); - } - break; - } - } - else - { - - /** - The client does not have a buddy, set this client - */ - iPlayer = i; - break; - } - } - else - { - - /** - Buddy system is not enabled, set this client - */ - iPlayer = i; - break; - } - } - - /** - Return the client we set, this could be 0, but very unlikely - */ - return iPlayer; -} - -stock BalancePlayer(iClient, iTeam) -{ - new Handle:hPack = CreateDataPack(); - WritePackCell(hPack, iClient); - WritePackCell(hPack, iTeam); - CreateTimer(0.1, Timer_BalancePlayer, hPack, TIMER_FLAG_NO_MAPCHANGE); -} - -stock CleanUp(iClient) -{ - g_aPlayers[iClient][bFlagCarrier] = false; - g_aPlayers[iClient][bSwitched] = false; - if (g_aPlayers[iClient][hForcedTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hForcedTimer]); - g_aPlayers[iClient][hForcedTimer] = INVALID_HANDLE; - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] Forced player disconnected, killing timer."); - } - } - if (g_aPlayers[iClient][hBalanceTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hBalanceTimer]); - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] Living player set to be balanced disconnected, killing timer."); - } - } -} - -stock GetSmallerTeam() -{ - - /** - Get the count of players on each team - */ - new iCountT1 = GetTeamClientCount(g_aCurrentTeams[Team1]); - new iCountT2 = GetTeamClientCount(g_aCurrentTeams[Team2]); - - /** - Return the smaller team - */ - if (iCountT1 < iCountT2) - { - return g_aCurrentTeams[Team1]; - } - else if (iCountT1 > iCountT2) - { - return g_aCurrentTeams[Team2]; - } - return 0; -} - -stock GetBiggerTeam() -{ - - /** - Get the count of players on each team - */ - new iCountT1 = GetTeamClientCount(g_aCurrentTeams[Team1]); - new iCountT2 = GetTeamClientCount(g_aCurrentTeams[Team2]); - - /** - Return the bigger team - */ - if (iCountT1 > iCountT2) - { - return g_aCurrentTeams[Team1]; - } - else if (iCountT1 < iCountT2) - { - return g_aCurrentTeams[Team2]; - } - return 0; -} - -stock SetGameCvars() -{ - if (g_bConVarControl && g_bIsEnabled) - { - if (stb_mp_autoteambalance != INVALID_HANDLE) - { - SetConVarInt(stb_mp_autoteambalance, 0); - } - if (stb_mp_teams_unbalance_limit != INVALID_HANDLE) - { - SetConVarInt(stb_mp_teams_unbalance_limit, g_iUnbalanceLimit); - } - } -} - -/* TIMER FUNCTIONS */ - -public Action:Timer_ChangeTeamBalanceDelay(Handle:timer, any:data) -{ - - /** - Finally start one if it's still unbalanced - */ - if (IsUnbalanced() && !g_bBalanceInProgress) - { - StartABalance(); - } -} - -public Action:Timer_BalanceTeams(Handle:timer, any:data) -{ - - /** - See if we still need to balance the teams - */ - if (!IsUnbalanced() || !OkToBalance()) - { - - /** - We don't, kill the balance - */ - g_bBalanceInProgress = false; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Balance delay timer was not needed and died."); - } - g_hBalanceTimer = INVALID_HANDLE; - return Plugin_Handled; - } - - /** - We still need to balance the teams - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Teams are still unbalanced. Balance is now in progress."); - } - g_bBalanceInProgress = true; - - - /** - Check if we are allowed to scan living players - */ - if (!g_bDeadOnly) - { - - /** - We are allowed to, so we start a timer - */ - StartALivingPlayerTimer(); - - /** - Also report that we are now scanning dead players as well - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Now scanning dead players."); - } - } - else - { - - /** - We are not allowed to, so report that we are only scanning dead players - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Only scanning dead players."); - } - } - - g_hBalanceTimer = INVALID_HANDLE; - return Plugin_Handled; -} - -public Action:Timer_LivingPlayerCheck(Handle:timer, any:data) -{ - - /** - Check to see if we still need to balance the teams - */ - if (!IsUnbalanced() || !OkToBalance()) - { - - /** - We don't, kill it and bug out - */ - g_bBalanceInProgress = false; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Living player balance delay timer was not needed and died."); - } - g_hLivingPlayerCheckTimer = INVALID_HANDLE; - return Plugin_Handled; - } - - /** - Call the stock function to find a player we can switch - */ - new iPlayer = FindSwitchablePlayer(); - - /** - Check to see if we found a player - */ - if (iPlayer == 0) - { - - /** - In the unlikely event that the stock function didn't return a player - Start a loop to find a random player - */ - new iBiggerTeam = GetBiggerTeam(); - do - { - iPlayer = GetRandomInt(1, MaxClients); - } while (!IsSwitchablePlayer(iPlayer, iBiggerTeam)); - - if (g_bLogActivity) - { - LogAction(0, iPlayer, "[STB] Found a random living player."); - } - } - else - { - if (g_bLogActivity) - { - LogAction(0, iPlayer, "[STB] Found a living player."); - } - } - - /** - Now that we have a player assigned them to the smaller team - */ - new iSmallerTeam = GetSmallerTeam(); - SM_SetForcedTeam(iPlayer, iSmallerTeam, true); - - /** - Let the player know we could be switching him soon - */ - PrintHintText(iPlayer, "%T", "PlayerMessage", LANG_SERVER, g_iLivingPlayerSwitchDelay); - if (g_bLogActivity) - { - LogAction(0, iPlayer, "[STB] Living player placed on a timer."); - } - - /** - Create a timer to switch the player - */ - g_aPlayers[iPlayer][hBalanceTimer] = CreateTimer(float(g_iLivingPlayerSwitchDelay), Timer_LivingPlayerBalance, iPlayer, TIMER_FLAG_NO_MAPCHANGE); - - /** - Reset the timer handle - */ - g_hLivingPlayerCheckTimer = INVALID_HANDLE; - - /** - We are done, bug out - */ - return Plugin_Handled; -} - -public Action:Timer_LivingPlayerBalance(Handle:timer, any:iClient) -{ - - /** - Check to make sure we still need to balance - */ - if (!IsUnbalanced() || !OkToBalance()) - { - - /** - We don't need to balance, bug out - */ - g_bBalanceInProgress = false; - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - SM_ClearForcedTeam(iClient); - return Plugin_Handled; - } - - /** - We still need to balance, lets make sure we can still balance this player - */ - if (!IsClientConnected(iClient) || g_aPlayers[iClient][bFlagCarrier]) - { - g_bBalanceInProgress = false; - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - SM_ClearForcedTeam(iClient); - if (g_bLogActivity) - { - if (g_aPlayers[iClient][bFlagCarrier]) - { - LogAction(0, iClient, "[STB] Living player became flag carrier, balance restarted."); - } - else - { - LogAction(0, iClient, "[STB] Living player timer was not needed and died."); - } - } - return Plugin_Handled; - } - - /** - Clear to balance this player, so do it - */ - BalancePlayer(iClient, SM_GetForcedTeam(iClient)); - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] Living player was switched."); - } - - /** - We are done, bug out - */ - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - return Plugin_Handled; -} - -public Action:Timer_BalancePlayer(Handle:timer, Handle:pack) -{ - - /** - Rest the datapack and load the variables - */ - ResetPack(pack); - new iClient = ReadPackCell(pack); - new iUnBalancedTeam = ReadPackCell(pack); - - /** - We are done with you now - */ - CloseHandle(pack); - - /** - Check the team and make sure its a valid team - */ - if(!SM_IsValidTeam(iUnBalancedTeam)) - { - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] Balance failed due to invalid team number %i", iUnBalancedTeam); - } - return Plugin_Handled; - } - - /** - Use our core function to change the clients team - */ - SM_MovePlayer(iClient, iUnBalancedTeam); - - return Plugin_Handled; -} - -public Action:Timer_RoundStart(Handle:timer, any:data) -{ - g_bRoundStart = false; - if (OkToBalance() && IsUnbalanced() && !g_bBalanceInProgress) - { - StartABalance(); - } - return Plugin_Handled; -} - -public Action:Timer_ForcedExpired(Handle:timer, any:iClient) -{ - SM_ClearForcedTeam(iClient); - g_aPlayers[iClient][bSwitched] = false; - g_aPlayers[iClient][hForcedTimer] = INVALID_HANDLE; - return Plugin_Handled; -} - -public Action:Timer_WelcomeAdvert(Handle:timer, any:iClient) -{ - if (IsClientConnected(iClient) && IsClientInGame(iClient)) - { - PrintToChat (iClient, "\x01\x04[STB]\x01 %T", "BuddyWelcomeMsg1", LANG_SERVER); - PrintToChat (iClient, "\x01\x04[STB]\x01 %T", "BuddyWelcomeMsg2", LANG_SERVER); - PrintToChat (iClient, "\x01\x04[STB]\x01 %T", "BuddyWelcomeMsg3", LANG_SERVER); - } - return Plugin_Handled; -} - -/* CONSOLE VARIABLE CHANGE EVENT */ - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (convar == stb_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsEnabled = false; - PrintToChatAll("[SM] %T", "Disabled", LANG_SERVER); - LogAction(0, -1, "[SimpleTeamBalancer] Disabled"); - } - else - { - g_bIsEnabled = true; - SetGameCvars(); - PrintToChatAll("[SM] %T", "Enabled", LANG_SERVER); - LogAction(0, -1, "[SimpleTeamBalancer] Enabled"); - } - } - else if (convar == stb_logactivity) - { - if (StringToInt(newValue) == 0) - { - g_bLogActivity = false; - LogAction(0, -1, "[STB] Log Activity DISABLED."); - } - else - { - g_bLogActivity = true; - LogAction(0, -1, "[STB] Log Activity ENABLED."); - } - } - else if (convar == stb_logactivity2) - { - if (StringToInt(newValue) == 0) - { - g_bLogActivity2 = false; - LogAction(0, -1, "[STB] Detailed Log Activity DISABLED."); - } - else - { - g_bLogActivity2 = true; - LogAction(0, -1, "[STB] Detailed Log Activity ENABLED."); - } - } - else if (convar == stb_convarcontrol) - { - if (StringToInt(newValue) == 0) - { - g_bConVarControl = false; - } - else - { - g_bConVarControl = true; - SetGameCvars(); - } - } - else if (convar == stb_deadonly) - { - if (StringToInt(newValue) == 0) - { - g_bDeadOnly = false; - } - else - { - g_bDeadOnly = true; - } - } - else if (convar == stb_priorityenabled) - { - if (StringToInt(newValue) == 0) - { - g_bPriorityPlayers = false; - } - else - { - g_bPriorityPlayers = true; - } - } - else if (convar == stb_buddyenabled) - { - if (StringToInt(newValue) == 0) - { - g_bBuddyEnabled = false; - } - else - { - g_bBuddyEnabled = true; - } - } - else if (convar == stb_buddyrestriction) - { - if (StringToInt(newValue) == 0) - { - g_bBuddyRestriction = false; - } - else - { - g_bBuddyRestriction = true; - } - } - else if (convar == stb_unbalancelimit) - { - g_iUnbalanceLimit = StringToInt(newValue); - SetGameCvars(); - } - else if (convar == stb_balancedelay) - { - g_iBalanceDelay = StringToInt(newValue); - } - else if (convar == stb_roundstartdelay) - { - g_iRoundStartDelay = StringToInt(newValue); - } - else if (convar == stb_livingplayerswitchdelay) - { - g_iLivingPlayerSwitchDelay = StringToInt(newValue); - } - else if (convar == stb_livingplayercheckdelay) - { - g_iLivingPlayerCheckDelay = StringToInt(newValue); - } - else if (convar == stb_uberlevel) - { - g_fUberLevel = StringToFloat(newValue); - } - else if (convar == stb_switchbackforced) - { - g_iSwitchBackForced = StringToInt(newValue); - } - else if (convar == stb_adminflag) - { - SetConVarString(stb_adminflag, newValue); - } - else if (convar == stb_mp_autoteambalance) - { - SetGameCvars(); - } - else if (convar == stb_mp_teams_unbalance_limit) - { - SetGameCvars(); - } -} - -/* MENU CODE */ - -stock Handle:BuildPlayerMenu() -{ - new Handle:menu = CreateMenu(Menu_SelectPlayer); - AddTargetsToMenu(menu, 0, true, false); - SetMenuTitle(menu, "Select A Player:"); - SetMenuExitButton(menu, true); - return menu; -} - -public Menu_SelectPlayer(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - new buddy = GetClientOfUserId(StringToInt(sSelection)); - if (param1 == buddy) { - PrintHintText(param1, "%T", "SelectSelf", LANG_SERVER); - } else if (!IsClientInGame(buddy)) { - PrintHintText(param1, "%T", "BuddyGone", LANG_SERVER); - } else { - decl String:cName[128]; - decl String:bName[128]; - GetClientName(param1, cName, sizeof(cName)); - GetClientName(buddy, bName, sizeof(bName)); - if (!SM_IsBuddyLocked(buddy)) { - SM_AssignBuddy(param1, buddy); - PrintHintText(param1, "%T", "BuddyMsg", LANG_SERVER, bName); - PrintHintText(buddy, "%T", "BuddyMsg", LANG_SERVER, cName); - } else - PrintHintText(param1, "%T", "PlayerLockedBuddyMsg", LANG_SERVER, bName); - } - } else if (action == MenuAction_End) { - CloseHandle(menu); - } -} \ No newline at end of file diff --git a/Simple Plugins Core/addons/sourcemod/scripting/simple-teammanager.sp b/Simple Plugins Core/addons/sourcemod/scripting/simple-teammanager.sp deleted file mode 100644 index 008f443..0000000 --- a/Simple Plugins Core/addons/sourcemod/scripting/simple-teammanager.sp +++ /dev/null @@ -1,1351 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Team Manager -Description: - Manges players and their team - Admin menu integration - Allows admins/donators to swap their teams (clears force)* - Allows admins to move players to a team (forced\unforced)* - Allows admins to scramble the teams* - *Works with Simple Team Balancer (if installed) -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include - -#define PLUGIN_VERSION "2.1.$Rev$" -#define VOTE_YES "##YES##" -#define VOTE_NO "##NO##" - -enum PlayerData -{ - iNewTeam, - bool:bQueue -}; - -new Handle:stm_enabled = INVALID_HANDLE; -new Handle:stm_logactivity = INVALID_HANDLE; -new Handle:stm_adminflag_swapteam = INVALID_HANDLE; -new Handle:stm_adminflag_moveplayer = INVALID_HANDLE; -new Handle:stm_adminflag_scramble = INVALID_HANDLE; -new Handle:stm_scrambledelay = INVALID_HANDLE; -new Handle:stm_voteenabled = INVALID_HANDLE; -new Handle:stm_votewin = INVALID_HANDLE; -new Handle:stm_votedelay = INVALID_HANDLE; -new Handle:stm_mp_bonusroundtime = INVALID_HANDLE; -new Handle:g_hAdminMenu = INVALID_HANDLE; -new Handle:g_hTimerPrepScramble = INVALID_HANDLE; -new Handle:g_hTimerClearScrambleForce = INVALID_HANDLE; - -new g_aPlayers[MAXPLAYERS + 1][PlayerData]; - -new bool:g_bIsEnabled = true; -new bool:g_bVoteEnabled = true; -new bool:g_bLogActivity = true; -new bool:g_bScrambleRoundEnd = false; -new g_iVoteDelay, g_iLastVoteTime, g_iTimeLeft; -new Float:g_fScrambleDelay, Float:g_fVoteWin; - -public Plugin:myinfo = -{ - name = "Simple Team Manager", - author = "Simple Plugins", - description = "Manages players and thier team.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -public OnPluginStart() -{ - - /** - Need to create all of our console variables. - */ - CreateConVar("stm_version", PLUGIN_VERSION, "Simple Team Manager Version",FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - stm_enabled = CreateConVar("stm_enabled", "1", "Enable or Disable Simple Team Manager", _, true, 0.0, true, 1.0); - stm_logactivity = CreateConVar("stm_logactivity", "0", "Enable or Disable the disaplying of events in the log", _, true, 0.0, true, 1.0); - stm_adminflag_swapteam = CreateConVar("stm_adminflag_swapteam", "a", "Admin flag to use for the swapteam command. Must be a in char format."); - stm_adminflag_moveplayer = CreateConVar("stm_adminflag_moveplayer", "c", "Admin flag to use for the moveplayer command. Must be a in char format."); - stm_adminflag_scramble = CreateConVar("stm_adminflag_scramble", "c", "Admin flag to use for the scrambleteam command. Must be a in char format."); - stm_scrambledelay = CreateConVar("stm_scrambledelay", "15", "Delay to scramble teams"); - stm_voteenabled = CreateConVar("stm_voteenabled", "1", "Enable or Disable voting to scramble the teams", _, true, 0.0, true, 1.0); - stm_votewin = CreateConVar("stm_votewin", "0.45", "Win percentage vote must win by", _, true, 0.0, true, 1.0); - stm_votedelay = CreateConVar("stm_votedelay", "600", "Delay before another vote can be cast"); - stm_mp_bonusroundtime = FindConVar("mp_bonusroundtime"); - - - /** - Need deal with changes to the console variables after the plugin is loaded. - We could not do this and just call the actual console variable each time we need it, but it's not efficent. - */ - HookConVarChange(stm_enabled, ConVarSettingsChanged); - HookConVarChange(stm_logactivity, ConVarSettingsChanged); - HookConVarChange(stm_scrambledelay, ConVarSettingsChanged); - HookConVarChange(stm_voteenabled, ConVarSettingsChanged); - HookConVarChange(stm_votewin, ConVarSettingsChanged); - HookConVarChange(stm_votedelay, ConVarSettingsChanged); - - /** - Need to register the commands we are going to create and use. - */ - RegConsoleCmd("sm_swapteam", Command_SwapTeam, "sm_swapteam <[0]instant/[1]queued>: Swaps your team to the other team"); - RegConsoleCmd("sm_moveplayer", Command_MovePlayer, "sm_moveplayer <[0]instant/[1]ondeath> <[0]unforced/[1]forced>: Moves a player to the specified team"); - RegConsoleCmd("sm_scrambleteams", Command_ScrambleTeams, "sm_scrambleteams: <[0]now/[1]roundend> <[0]dontrestart/[1]restartround> Scrambles the current teams"); - RegConsoleCmd("sm_votescramble", Command_VoteScramble, "sm_votescramble: Starts a vote to scramble the teams"); - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[STM] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_death", HookPlayerDeath, EventHookMode_Post); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Post); - switch (g_CurrentMod) - { - case GameType_TF: - { - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - } - case GameType_DOD: - { - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_Post); - } - default: - { - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - - /** - Now we have to deal with the admin menu. If the admin library is loaded call the function to add our items. - */ - new Handle:gTopMenu; - if (LibraryExists("adminmenu") && ((gTopMenu = GetAdminTopMenu()) != INVALID_HANDLE)) - { - OnAdminMenuReady(gTopMenu); - } - - /** - Load translations and .cfg file - */ - LoadTranslations ("simpleteammanager.phrases"); - AutoExecConfig(true, "plugin.simpleteammanager"); - LogAction(0, -1, "[STM] Simple Team Manager is loaded."); -} - -public OnAllPluginsLoaded() -{ - //something -} - -public OnLibraryRemoved(const String:name[]) -{ - if (StrEqual(name, "adminmenu")) - { - - /** - Looks like the admin menu was removed. Set the global. - */ - g_hAdminMenu = INVALID_HANDLE; - } - else if (StrEqual(name, "simpleplugins")) - { - SetFailState("Required plugin Simple SourceMod Plugins Core was removed."); - } -} - -public OnConfigsExecuted() -{ - - /** - Once we loaded up all the console variables from the config file, lets now set all the global variables we will use. - */ - g_bIsEnabled = GetConVarBool(stm_enabled); - g_bLogActivity = GetConVarBool(stm_logactivity); - g_fScrambleDelay = GetConVarFloat(stm_scrambledelay); - g_iVoteDelay = GetConVarInt(stm_votedelay); - g_fVoteWin = GetConVarFloat(stm_votewin); - g_iLastVoteTime = RoundFloat(GetEngineTime()); - g_bScrambleRoundEnd = false; - g_hTimerClearScrambleForce = INVALID_HANDLE; - - /** - Report enabled - */ - if (g_bIsEnabled) - { - LogAction(0, -1, "[STM] Simple Team Manager is ENABLED."); - } - else - { - LogAction(0, -1, "[STM] Simple Team Manager is DISABLED."); - } - - if (g_bLogActivity) - { - LogAction(0, -1, "[STM] Log Activity ENABLED."); - } - else - { - LogAction(0, -1, "[STM] Log Activity DISABLED."); - } -} - -/* COMMANDS */ - -public Action:Command_SwapTeam(client, args) -{ - - /** - Make sure we are enabled, if not bug out. - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - If this was ran from the console bug out. - */ - if (client == 0) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure the client is authorized to run this command. - */ - decl String:sFlags[5]; - GetConVarString(stm_adminflag_swapteam, sFlags, sizeof(sFlags)); - if (!SM_IsValidAdmin(client, sFlags)) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Lets make sure the client is one a team we can swap. - If he is we set the global array to the opposite team. - */ - new iTeam = GetClientTeam(client); - if (iTeam == g_aCurrentTeams[Team1]) - { - g_aPlayers[client][iNewTeam] = g_aCurrentTeams[Team2]; - } - else if (iTeam == g_aCurrentTeams[Team2]) - { - g_aPlayers[client][iNewTeam] = g_aCurrentTeams[Team1]; - } - else - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "InValidTeam", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check to see if we have command arguments. - */ - if (GetCmdArgs()) - { - - /** - We do, so lets get it and see if the client wants to be switched instantly or queued for death. - */ - decl String:sArg[5]; - GetCmdArg(1, sArg, sizeof(sArg)); - new iWantsQue = StringToInt(sArg); - if (iWantsQue && !g_aPlayers[client][bQueue]) - { - - /** - He wants the que and isn't already in it, set the global array. - */ - g_aPlayers[client][bQueue] = true; - ReplyToCommand(client, "\x01\x04[STM]\x01 %T", "PlayerQueue", LANG_SERVER); - } - else if (!iWantsQue) - { - - /** - He wants to be switched right now, lets call the stock function. - */ - SM_MovePlayer(client, g_aPlayers[client][iNewTeam]); - } - } - else - { - - /** - There are no command arguments so we build and display the swap menu. - */ - DisplaySwapModeMenu(client, client); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_MovePlayer(client, args) -{ - - /** - Make sure we are enabled, if not bug out. - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the client is authorized to run this command. - */ - decl String:sFlags[5]; - GetConVarString(stm_adminflag_moveplayer, sFlags, sizeof(sFlags)); - if (!SM_IsValidAdmin(client, sFlags)) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check to see if we have command arguments. - */ - new iCmdArgs = GetCmdArgs(); - if (iCmdArgs == 0) - { - - /** - We don't. Build the player menu, display it, and bug out. - */ - DisplayPlayerMenu(client); - return Plugin_Handled; - } - - /** - Check the first argument - If should be a players name or userid. - */ - decl String:sPlayer[64]; - GetCmdArg(1, sPlayer, sizeof(sPlayer)); - new iPlayerIndex = FindTarget(client, sPlayer, true, true); - if (iPlayerIndex == -1 || !IsClientInGame(iPlayerIndex)) - { - - /** - We don't know who this is. Build the player menu, display it, and bug out. - */ - DisplayPlayerMenu(client); - return Plugin_Handled; - } - - /** - We have figured out the first argument, lets check the second. - If should be the team the client wants to put the player on. - */ - if (iCmdArgs >= 2) - { - - /** - We have a command argument at least, lets see if we can identify the team. - */ - decl String:sTeam[24]; - GetCmdArg(2, sTeam, sizeof(sTeam)); - - new iTeam = StringToInt(sTeam); - if (SM_IsValidTeam(iTeam)) - { - - /** - It's a vaild team so lets set the global array to the new team. - */ - g_aPlayers[iPlayerIndex][iNewTeam] = iTeam; - } - else - { - - /** - It's not a vaild team so set the menu to display to the team menu. - */ - DisplayTeamMenu(client, iPlayerIndex); - return Plugin_Handled; - } - } - else - { - /** - We were not given a team, display the team menu. - */ - DisplayTeamMenu(client, iPlayerIndex); - return Plugin_Handled; - } - - /** - Check to see if we were given any more command arguments and found a team. - */ - if (iCmdArgs < 3) - { - - /** - No more command arguments and found a team. - Now lets check to see if the player is a spectator. If he is there is no reason to ask if it's instant or on death... he can't die. - */ - if (!IsClientObserver(iPlayerIndex)) - { - - /** - Not a spectator so display the swapmode menu. - */ - DisplaySwapModeMenu(client, iPlayerIndex); - } - else - { - - /** - The player is a spectator. - We make sure the player is not set to switch on death, since a spec can't die. - */ - g_aPlayers[iPlayerIndex][bQueue] = false; - } - } - - /** - We have figured out the second argument, lets check the third. - If should be the how the client wants to move the player: instant/on death. - */ - if (iCmdArgs >= 3) - { - - /** - The client gave us a command argument, lets check it. - */ - decl String:sSwapMode[5]; - GetCmdArg(3, sSwapMode, sizeof(sSwapMode)); - new iWantsQue = StringToInt(sSwapMode); - if (iWantsQue) - { - - /** - The client wants to que the player, set the global array. - */ - g_aPlayers[iPlayerIndex][bQueue] = true; - } - else - { - - /** - The client doesn't want to que the player, set the global array. - */ - g_aPlayers[iPlayerIndex][bQueue] = false; - } - } - else - { - /** - No swapmode argument, display the menu - */ - DisplaySwapModeMenu(client, iPlayerIndex); - } - - if (iCmdArgs >= 4) - { - - /** - Since we are compiling for Simple Team Balancer, and given a 4th argument, lets check it. - If should be the if the client wants to force the player to that team. - */ - decl String:sPlayerForced[5]; - GetCmdArg(4, sPlayerForced, sizeof(sPlayerForced)); - new iForceHim = StringToInt(sPlayerForced); - if (iForceHim) - { - - /** - The client wants to force the player - */ - SM_SetForcedTeam(iPlayerIndex, g_aPlayers[iPlayerIndex][iNewTeam]); - } - else - { - - /** - The client doesn't want to force the player - */ - SM_ClearForcedTeam(iPlayerIndex); - } - } - else - { - - } - - /** - We found and processed all the arguments. - */ - if (!IsPlayerAlive(iPlayerIndex)) - { - - /** - The player is not alive or died during this process so we just move him. - */ - SM_MovePlayer(iPlayerIndex, g_aPlayers[iPlayerIndex][iNewTeam]); - } - else - { - if (!g_aPlayers[iPlayerIndex][bQueue]) - { - - /** - The player is alive and is not set to be queued so we just move him. - */ - SM_MovePlayer(iPlayerIndex, g_aPlayers[iPlayerIndex][iNewTeam]); - } - } - - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_ScrambleTeams(client, args) -{ - - /** - Make sure we are enabled, if not bug out. - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the client is authorized to run this command. - */ - decl String:sFlags[5]; - GetConVarString(stm_adminflag_scramble, sFlags, sizeof(sFlags)); - if (!SM_IsValidAdmin(client, sFlags)) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check if a scramble timer was already called, if so close it down. - */ - if (g_hTimerPrepScramble != INVALID_HANDLE) - { - CloseHandle(g_hTimerPrepScramble); - g_hTimerPrepScramble = INVALID_HANDLE; - } - - /** - Check if we have any command arguments. - If we don't we display the scramble menu and bug out. - */ - new iCmdArgs = GetCmdArgs(); - if (iCmdArgs == 0) - { - DisplayScrambleMenu(client); - return Plugin_Handled; - } - - /** - We have a command argument. - It should be whether or not to scramble at round end. - */ - decl String:sRoundEnd[5]; - GetCmdArg(1, sRoundEnd, sizeof(sRoundEnd)); - if (StringToInt(sRoundEnd)) - { - /** - The client wants to scramble at round end so we set the global bool. - */ - g_bScrambleRoundEnd = true; - } - else - { - g_bScrambleRoundEnd = false; - } - - /** - Check for another command argument. - It should be whether or not to restart the round. - */ - decl String:sRestartRound[5]; - new bool:bRestartRound = false; - GetCmdArg(1, sRestartRound, sizeof(sRestartRound)); - if (StringToInt(sRestartRound)) - { - bRestartRound = true; - } - - /** - Now we start the scramble timer. - */ - StartScrambleTimer(_, bRestartRound); - - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_VoteScramble(client, args) -{ - - /** - Make sure we are enabled, if not bug out. - */ - if (!g_bVoteEnabled || !g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Make sure there is a vote in progress, if so bug out. - */ - if (IsVoteInProgress()) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "VoteInProgress", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure enough time has passed since the last vote. - */ - new iVoteTime = RoundFloat(GetEngineTime()); - if (iVoteTime - g_iLastVoteTime <= g_iVoteDelay) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "ScrambleTime", LANG_SERVER); - return Plugin_Handled; - } - - /** - Enough time has passed so reset the global vote time to now. - */ - g_iLastVoteTime = iVoteTime; - - /** - Build the vote menu and send it to everyone. - */ - new Handle:hMenu = CreateMenu(Menu_VoteScramble); - SetMenuTitle(hMenu, "Scramble Teams?"); - AddMenuItem(hMenu, VOTE_YES, "Yes"); - AddMenuItem(hMenu, VOTE_NO, "No"); - SetMenuExitButton(hMenu, false); - VoteMenuToAll(hMenu, 20); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -/* HOOKED EVENTS */ - -public HookPlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Find out who died. - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - - /** - Find out how the client died. - */ - new String:sWeapon[64]; - GetEventString(event, "weapon", sWeapon, sizeof(sWeapon)); - if (StrEqual(sWeapon, "world", false)) - { - - /** - He died because he changed teams so cleanup and bug out. - */ - s_CleanUp(iClient); - return; - } - - /** - Find out if this player was queued to change teams. - */ - if (g_aPlayers[iClient][bQueue]) - { - /** - Looks like he was, so call the stock function to move him. - */ - SM_MovePlayer(iClient, g_aPlayers[iClient][iNewTeam]); - } -} - -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Find out who changed teams. - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - - /** - If he was queued to switch teams we cleanup the variables. The client did it themself. - */ - if (g_aPlayers[iClient][bQueue]) - { - s_CleanUp(iClient); - } -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get the amount of time left in the map. - */ - new iTimeLeft; - GetMapTimeLeft(iTimeLeft); - - /** - Check to see if we are supposed to scramble at the end of the round and that there is enough time left in the map. - */ - if (g_bScrambleRoundEnd && iTimeLeft >= 60) - { - - /** - Check to see if there is a scramble timer in action and if so close it down. - */ - if (g_hTimerPrepScramble != INVALID_HANDLE) - { - CloseHandle(g_hTimerPrepScramble); - g_hTimerPrepScramble = INVALID_HANDLE; - } - - /** - Determine the round end chat time and run the scramble 1 second before it ends. - */ - new Float:fDelay = GetConVarFloat(stm_mp_bonusroundtime); - fDelay -= 1.0; - StartScrambleTimer(fDelay); - } -} - -public OnClientPostAdminCheck(client) -{ - - /** - Determine if the client has the flag to use the swapteam command. - */ - decl String:sFlags[5]; - GetConVarString(stm_adminflag_swapteam, sFlags, sizeof(sFlags)); - if (SM_IsValidAdmin(client, sFlags)) - { - /** - The client does so lets create a timer to run an advertise to tell him about it. - */ - CreateTimer (60.0, Timer_WelcomeAdvert, client); - } -} - -public OnClientDisconnect(client) -{ - - /** - Cleanup the clients variables. - */ - s_CleanUp(client); -} - -public SM_OnPlayerMoved(Handle:plugin, client, team) -{ - - /** - Make sure we called the move function - */ - if (plugin != GetMyHandle()) - { - if (g_bLogActivity) - { - LogAction(0, client, "[STM] Callback was not started with current plugin, bugging out."); - } - return; - } - - decl String:sPlayerName[64]; - GetClientName(client, sPlayerName, sizeof(sPlayerName)); - - PrintToChat(client, "\x01\x04[SM]\x01 %T", "PlayerSwitched", LANG_SERVER); - - s_CleanUp(client); -} - -/* TIMER FUNCTIONS */ - -public Action:Timer_PrepTeamScramble(Handle:timer, any:data) -{ - new bool:bRestartRound = data; - /** - Call the scramble the teams stock function. - */ - PrepTeamScramble(bRestartRound); - - /** - Reset the timer handle so we know the timer is done. - */ - g_hTimerPrepScramble = INVALID_HANDLE; - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Timer_ScrambleTheTeams(Handle:timer, any:data) -{ - new iPlayers[MAXPLAYERS + 1]; - new iCount, i, bool:bTeam, bool:bRestartRound = data; - - /** - Get all the client index numbers of valid players - */ - for(i = 1; i <= MaxClients; i++) - { - if(IsClientInGame(i)) // && !IsFakeClient(i)) - { - iPlayers[iCount++] = i; - } - } - - /** - Randomly sort the players - */ - SortIntegers(iPlayers, iCount, Sort_Random); - - /** - Loop through all the players and assign each one to a team, alternating each time - */ - for(i = 0; i < iCount; i++) - { - if (!bRestartRound) - { - /** - We didn't want to restart the round, so we move them to spec 1 at a time. - */ - SM_MovePlayer(iPlayers[i], g_aCurrentTeams[Spectator]); - } - SM_MovePlayer(iPlayers[i], bTeam ? g_aCurrentTeams[Team2] : g_aCurrentTeams[Team1]); - SM_SetForcedTeam(iPlayers[i], bTeam ? g_aCurrentTeams[Team2] : g_aCurrentTeams[Team1], true); - bTeam = !bTeam; - } - - /** - Reset this variable since we completed a scramble - */ - g_bScrambleRoundEnd = false; - - if (g_hTimerClearScrambleForce != INVALID_HANDLE) - { - CloseHandle(g_hTimerClearScrambleForce); - g_hTimerClearScrambleForce = INVALID_HANDLE; - } - - g_hTimerClearScrambleForce = CreateTimer(300.0, Timer_ClearScrambleForce, _, TIMER_FLAG_NO_MAPCHANGE); - - ServerCommand("mp_timelimit %i", g_iTimeLeft / 60); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Timer_ClearScrambleForce(Handle:timer, any:data) -{ - - for(new i = 1; i <= MaxClients; i++) - { - if(IsClientInGame(i)) // && !IsFakeClient(i)) - { - SM_ClearForcedTeam(i); - PrintToChat(i, "\x01\x04[SM]\x01 Your forced team status has been cleared"); - } - } - - g_hTimerClearScrambleForce = INVALID_HANDLE; - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Timer_WelcomeAdvert(Handle:timer, any:client) -{ - - /** - Lets make sure the client is connected and actually in the game. - */ - if (IsClientConnected(client) && IsClientInGame(client)) - { - - /** - We are good to go so lets tell him about the swapteam command. - */ - PrintToChat (client, "\x01\x04[STM]\x01 %T", "SwapTeamMsg", LANG_SERVER); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -/* STOCK FUNCTIONS */ - -stock s_CleanUp(iClient) -{ - - /** - Reset all the client variables - */ - g_aPlayers[iClient][bQueue] = false; - g_aPlayers[iClient][iNewTeam] = 0; -} - -stock StartScrambleTimer(Float:fdelay = 0.0, bool:bRestartRound = false) -{ - if (fdelay == 0.0) - { - fdelay = g_fScrambleDelay; - } - if (g_hTimerPrepScramble != INVALID_HANDLE) - { - CloseHandle(g_hTimerPrepScramble); - g_hTimerPrepScramble = INVALID_HANDLE; - } - PrintCenterTextAll("%T", "Scramble", LANG_SERVER); - g_hTimerPrepScramble = CreateTimer(fdelay, Timer_PrepTeamScramble, bRestartRound, TIMER_FLAG_NO_MAPCHANGE); -} - -stock PrepTeamScramble(bool:bRestartRound = false) -{ - new iPlayers[MAXPLAYERS + 1]; - new iCount; - - GetMapTimeLeft(g_iTimeLeft); - - if (bRestartRound) - { - - for(new i = 1; i <= MaxClients; i++) - { - if(IsClientInGame(i)) - // && !IsFakeClient(i)) - { - iPlayers[iCount++] = i; - SM_ClearForcedTeam(i); - SM_ClearBuddy(i); - SM_MovePlayer(i, g_aCurrentTeams[Spectator]); - } - } - } - else - { - //Can't move them all to spec at the same time - for(new i = 1; i <= MaxClients; i++) - { - if(IsClientInGame(i)) - // && !IsFakeClient(i)) - { - iPlayers[iCount++] = i; - SM_ClearForcedTeam(i); - SM_ClearBuddy(i); - //SM_MovePlayer(i, g_aCurrentTeams[Spectator]); - } - } - } - CreateTimer(4.0, Timer_ScrambleTheTeams, bRestartRound, TIMER_FLAG_NO_MAPCHANGE); -} - -/* CONSOLE VARIABLE CHANGE EVENT */ - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (convar == stm_enabled) { - if (StringToInt(newValue) == 0) { - g_bIsEnabled = false; - LogAction(0, -1, "[STM] Simple Team Manager is loaded and disabled."); - } else { - g_bIsEnabled = true; - LogAction(0, -1, "[STM] Simple Team Manager is loaded and enabled."); - } - } - else if (convar == stm_logactivity) { - if (StringToInt(newValue) == 0) { - g_bLogActivity = false; - LogAction(0, -1, "[STM] Log Activity DISABLED."); - } else { - g_bLogActivity = true; - LogAction(0, -1, "[STM] Log Activity ENABLED."); - } - } - else if (convar == stm_scrambledelay) - g_fScrambleDelay = StringToFloat(newValue); - else if (convar == stm_votewin) - g_fVoteWin = StringToFloat(newValue); - else if (convar == stm_votedelay) - g_iVoteDelay = StringToInt(newValue); - else if (convar == stm_voteenabled) { - if (StringToInt(newValue) == 0) - g_bVoteEnabled = false; - else - g_bVoteEnabled = true; - } -} - -/* MENU CODE */ - -public OnAdminMenuReady(Handle:topmenu) -{ - if (topmenu == g_hAdminMenu) - return; - g_hAdminMenu = topmenu; - new TopMenuObject:player_commands = FindTopMenuCategory(g_hAdminMenu, ADMINMENU_PLAYERCOMMANDS); - new TopMenuObject:server_commands = FindTopMenuCategory(g_hAdminMenu, ADMINMENU_SERVERCOMMANDS); - if (player_commands == INVALID_TOPMENUOBJECT) - return; - - AddToTopMenu(g_hAdminMenu, - "moveplayer", - TopMenuObject_Item, - AdminMenu_MovePlayer, - player_commands, - "moveplayer", - ADMFLAG_BAN); - - AddToTopMenu(g_hAdminMenu, - "scrambleteams", - TopMenuObject_Item, - AdminMenu_Scrambleteams, - server_commands, - "scrambleteams", - ADMFLAG_BAN); -} - -public AdminMenu_MovePlayer(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) -{ - if (action == TopMenuAction_DisplayOption) - Format(buffer, maxlength, "Move Player"); - else if (action == TopMenuAction_SelectOption){ - DisplayPlayerMenu(param); - } -} - -public AdminMenu_Scrambleteams(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) -{ - if (action == TopMenuAction_DisplayOption) - Format(buffer, maxlength, "Scramble Teams"); - else if (action == TopMenuAction_SelectOption) { - DisplayScrambleMenu(param); - } -} - -public Menu_SelectPlayer(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - DisplayTeamMenu(param1, GetClientOfUserId(StringToInt(sSelection))); - } else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -public Menu_SelectTeam(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new iTeam; - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - decl String:sIndex[64]; - if (SplitString(sSelection, "A", sIndex, sizeof(sIndex)) != -1) - iTeam = g_aCurrentTeams[Team1]; - else if (SplitString(sSelection, "B", sIndex, sizeof(sIndex)) != -1) - iTeam = g_aCurrentTeams[Team2]; - else { - SplitString(sSelection, "C", sIndex, sizeof(sIndex)); - iTeam = g_aCurrentTeams[Spectator]; - } - new iTarget = StringToInt(sIndex); - g_aPlayers[iTarget][iNewTeam] = iTeam; - DisplaySwapModeMenu(param1, iTarget); - } else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -public Menu_SwapMode(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - decl String:sIndex[64]; - - if (SplitString(sSelection, "A", sIndex, sizeof(sIndex)) == -1) - { - SplitString(sSelection, "B", sIndex, sizeof(sIndex)); - } - - new iTarget = StringToInt(sIndex); - - if (StrContains(sSelection, "A", true) != -1) - { - g_aPlayers[iTarget][bQueue] = false; - } - else if (StrContains(sSelection, "B", true) != -1) - { - g_aPlayers[iTarget][bQueue] = true; - } - - if (param1 == iTarget && !g_aPlayers[iTarget][bQueue]) - { - SM_MovePlayer(iTarget, g_aPlayers[iTarget][iNewTeam]); - } - else - { - DisplayForceModeMenu(param1, iTarget); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - { - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } - return; -} - -public Menu_ForceMode(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - decl String:sIndex[64]; - if (SplitString(sSelection, "A", sIndex, sizeof(sIndex)) == -1) - { - SplitString(sSelection, "B", sIndex, sizeof(sIndex)); - } - new iTarget = StringToInt(sIndex); - if (StrContains(sSelection, "A", true) != -1) - { - SM_ClearForcedTeam(iTarget); - } - else if (StrContains(sSelection, "B", true) != -1) - { - SM_SetForcedTeam(iTarget, g_aPlayers[iTarget][iNewTeam], true); - } - if (!g_aPlayers[iTarget][bQueue]) - { - SM_MovePlayer(iTarget, g_aPlayers[iTarget][iNewTeam]); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - { - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } - return; -} - -public Menu_VoteScramble(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_VoteEnd) { - new winning_votes, total_votes; - GetMenuVoteInfo(param2, winning_votes, total_votes); - if (param1 == 0) { - if (float(total_votes) / float(winning_votes) < g_fVoteWin) { - PrintToChatAll("\x01\x04[SM]\x01 %T", "VoteScramble2", LANG_SERVER, winning_votes, total_votes); - return; - } - PrintCenterTextAll("[SM] %T", "Scramble", LANG_SERVER); - PrintToChatAll("\x01\x04[SM]\x01 %T", "VoteScramble1", LANG_SERVER, winning_votes, total_votes); - StartScrambleTimer(); - } - if (param1 == 1) { - PrintToChatAll("\x01\x04[SM]\x01 %T", "VoteScramble2", LANG_SERVER, winning_votes, total_votes); - } - } - if (action == MenuAction_End) - CloseHandle(menu); -} - -public Menu_ScrambleTeams(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "NOW", false)) - g_bScrambleRoundEnd = false; - else - g_bScrambleRoundEnd = true; - DisplayScrambleMenu2(param1); - } else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -public Menu_ScrambleTeams2(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[64]; - new bool:bRestartRound; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "NO", false)) - { - bRestartRound = false; - } - else - { - bRestartRound = true; - } - StartScrambleTimer(_, bRestartRound); - } else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -stock DisplayScrambleMenu(iClient) -{ - new Handle:hMenu = CreateMenu(Menu_ScrambleTeams); - SetMenuTitle(hMenu, "Select When to Scramble:"); - AddMenuItem(hMenu, "NOW", "Instantly"); - AddMenuItem(hMenu, "END", "At Round End"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplayScrambleMenu2(iClient) -{ - new Handle:hMenu = CreateMenu(Menu_ScrambleTeams2); - SetMenuTitle(hMenu, "Select When to Scramble:"); - AddMenuItem(hMenu, "NO", "No Round Restart"); - AddMenuItem(hMenu, "YES", "Restart Round"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplaySwapModeMenu(iClient, iTarget) -{ - new Handle:hMenu = CreateMenu(Menu_SwapMode); - decl String:optionA[64]; - decl String:optionB[64]; - Format(optionA, sizeof(optionA), "%iA", iTarget); - Format(optionB, sizeof(optionB), "%iB", iTarget); - SetMenuTitle(hMenu, "Select When to Swap:"); - AddMenuItem(hMenu, optionA, "Instantly (Kills)"); - if (!IsClientObserver(iTarget)) - AddMenuItem(hMenu, optionB, "Queue on next death"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplayForceModeMenu(iClient, iTarget) -{ - new Handle:hMenu = CreateMenu(Menu_ForceMode); - decl String:optionA[64]; - decl String:optionB[64]; - Format(optionA, sizeof(optionA), "%iA", iTarget); - Format(optionB, sizeof(optionB), "%iB", iTarget); - SetMenuTitle(hMenu, "Select Force Mode:"); - AddMenuItem(hMenu, optionA, "UnForced"); - AddMenuItem(hMenu, optionB, "Forced"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplayTeamMenu(iClient, iTarget) -{ - new Handle:hMenu = CreateMenu(Menu_SelectTeam); - decl String:optionA[64]; - decl String:optionB[64]; - decl String:optionC[64]; - Format(optionA, sizeof(optionA), "%iA", iTarget); - Format(optionB, sizeof(optionB), "%iB", iTarget); - Format(optionC, sizeof(optionC), "%iC", iTarget); - SetMenuTitle(hMenu, "Select Team:"); - AddMenuItem(hMenu, optionA, "Team One"); - AddMenuItem(hMenu, optionB, "Team Two"); - AddMenuItem(hMenu, optionC, "Spectator"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplayPlayerMenu(iClient) -{ - new Handle:hMenu = CreateMenu(Menu_SelectPlayer); - AddTargetsToMenu(hMenu, 0, true, false); - SetMenuTitle(hMenu, "Select A Player:"); - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} diff --git a/Simple Plugins Core/addons/sourcemod/translations/simpledonatorbenefits.phrases.txt b/Simple Plugins Core/addons/sourcemod/translations/simpledonatorbenefits.phrases.txt deleted file mode 100644 index 3826846..0000000 --- a/Simple Plugins Core/addons/sourcemod/translations/simpledonatorbenefits.phrases.txt +++ /dev/null @@ -1,62 +0,0 @@ -"Phrases" -{ - "PlayerLevelCmd" - { - "en" "Command must be run at the player level" - "fr" "Cette commande doit être tapée en jeu" - "hu" "Ezt a parancsot jatekosi szinten kell futtatni!" - } - "RestrictedCmd" - { - "en" "You must be a donator or admin to run this command" - "fr" "Vous devez être un donateur ou un admin pour lancer cette commande" - "hu" "A parancs futtatasahoz admin, vagy tamogatoi szint szukseges!" - } - "InValidTeam" - { - "en" "You must be on red or blue to swap teams" - "fr" "Vous devez être RED ou BLU pour changer d'équipe" - "hu" "Jatekban kell lenned, hogy megcsereld a csapatokat!" - } - "PlayerQueue" - { - "en" "You have been queued to swap teams on next death" - "fr" "Vous avez été mis en attente pour changer d'équipe lors de votre prochaine mort" - "hu" "A kovetkezo halalnal csapatcsere lesz" - } - "PlayerSwitched" - { - "en" "Your team has been switched as requested" - "fr" "Vous avez changé d'équipe comme demandé" - "hu" "A keresnek eleget teve a csapatod meg lett csererlve" - } - "SwapTeamMsg" - { - "en" "Type /swapteam or !swapteam to swap your team!" - } - "ReachedCount" - { - "en" "You have reached your health limit. You must die before you can use it again" - } - "AtMaxHealth" - { - "en" "You are already at your maximum health!" - } - "ToMaxHealth" - { - "en" "Instant health bonus applied! You are not at your maximun health!" - } - "HealthBonus" - { - "en" "Instant health bonus applied!" - } - "PublicJoinMessage" - { - "#format" "{1:s}" - "en" "{1} a [donator] as joined the server" - } - "PrivateJoinMessage" - { - "en" "Thanks for donating!" - } -} \ No newline at end of file diff --git a/Simple Plugins Core/addons/sourcemod/translations/simplespectate.phrases.txt b/Simple Plugins Core/addons/sourcemod/translations/simplespectate.phrases.txt deleted file mode 100644 index 2d1a096..0000000 --- a/Simple Plugins Core/addons/sourcemod/translations/simplespectate.phrases.txt +++ /dev/null @@ -1,42 +0,0 @@ -"Phrases" -{ - "Stopped spectating" - { - "#format" "{1:s}" - "en" "Stopped tracking player: {1}" - } - "Yourself" - { - "en" "You can't spectate yourself" - } - "Spectator" - { - "en" "You can't spectate another spectator" - } - "Spectating" - { - "#format" "{1:s}" - "en" "Now spectating {1}. Type !stopspec or /stopspec to stop spectating this player" - } - "Invalid Target" - { - "en" "Invalid target" - } - "Cant Target" - { - "en" "Can't target this player" - } - "Must Have Target" - { - "en" "You must be following/tracking a player to punish" - } - "Target Left" - { - "en" "The player you were following/tracking has left" - } - "Punished" - { - "#format" "{1:s}{2:s}{3:s}" - "en" "{1} was punished with a {2} for {3}" - } -} \ No newline at end of file diff --git a/Simple Plugins Core/addons/sourcemod/translations/simpleteambalancer.phrases.txt b/Simple Plugins Core/addons/sourcemod/translations/simpleteambalancer.phrases.txt deleted file mode 100644 index 03595fd..0000000 --- a/Simple Plugins Core/addons/sourcemod/translations/simpleteambalancer.phrases.txt +++ /dev/null @@ -1,130 +0,0 @@ -"Phrases" -{ - "UnBalanced" - { - "en" "Teams are unbalanced and will be balanced shortly" - "fr" "Les équipes ne sont pas équilibrées et le seront bientôt" - "de" "Die Teams sind ungleich und werden in Kürze ausgeglichen" - "hu" "A csapatok nem kiegyenlitettek! Egyensuly beallitas kovetkezik!" - } - "Enabled" - { - "en" "Simple Team Balancer is ENABLED" - "fr" "Simple Team Balancer est ACTIVE" - "de" "Simple Team Balancer ist AKTIV" - "hu" "Az Egyszeru Csapat Egyensulytarto AKTIV!" - } - "Disabled" - { - "en" "Simple Team Balancer is DISABLED" - "fr" "Simple Team Balancer est DESACTIVE" - "de" "Simple Team Balancer ist INAKTIV" - "hu" "Az Egyszeru Csapat Egyensulytarto INAKTIV!" - } - "PlayerMessage" - { - "#format" "{1:i}" - "en" "You are going to be auto balanced in {1} seconds unless a dead player can be found" - "fr" "Vous passerez dans l'autre équipe dans {1} secondes si aucun joueur mort ne peut être trouvé dans cet intervalle" - "de" "Du wirst in {1} Sekunden zum automatischen Ausgleich herangezogen wenn kein toter Spieler gefunden werden kann" - "hu" "{1} masodpercen belul at leszel helyezve a masik csapatba, hacsak nem lesz addig egy halott jatekos!" - } - "BalanceMessage" - { - "#format" "{1:s}" - "en" "{1} was moved to the other team for game balance" - "fr" "{1} est passé dans l'autre équipe pour équilibrer la partie" - "de" "{1} wurde zum anderen Team verschoben um das Spiel auszugleichen" - "hu" "{1} at lett helyezve az egyensuly megtartasa erdekeben." - } - "PlayerLevelCmd" - { - "en" "Command must be run at the player level" - "fr" "La commande doit être lancée au niveau du joueur" - "de" "Das Kommando muss auf Spieler Ebene ausgeführt werden" - "hu" "Jatekosi szinten kell futtatni ezt a parancsot!" - } - "CmdDisabled" - { - "en" "Command is currently disabled" - "fr" "La commande est actuellement désactivée" - "de" "Das Kommando ist momentan inaktiv" - "hu" "A parancs jelenleg inaktiv" - } - "RestrictedBuddy" - { - "en" "You must be a donator or admin to add a balance buddy" - "fr" "Vous devez être un donateur ou un admin pour choisir un partenaire" - "de" "Du musst ein Spender oder Admin sein um einen Partner wählen zu können" - "hu" "Tamogato vagy admin kell hogy legyel, hogy 'Tarsat' jelolhess meg" - } - "SelectSelf" - { - "en" "You cannot be your own buddy" - "fr" "Vous ne pouvez pas être votre propre partenaire" - "de" "Du kannst nicht dein eigener Partner sein" - "hu" "Nem valaszthatod ki onmagad!" - } - "BuddyGone" - { - "en" "Your selected buddy has disconnected" - "fr" "Le partenaire que vous avez sélectionné s'est déconnecté" - "de" "Dein gewählter Partner hat die Verbindung getrennt" - "hu" "A valasztott 'Tarsad' kilepett" - } - "BuddyMsg" - { - "#format" "{1:s}" - "en" "You and {1} are now buddies" - "fr" "Vous et {1} êtes maintenant partenaires" - "de" "Du und {1} seid jetzt Partner" - "hu" "{1} es Te 'Tarsak' vagytok." - } - "BuddyLockMsgDisabled" - { - "en" "You can now be anyone's buddy" - "fr" "Vous pouvez à présent être le partenaire de n'importe qui" - "de" "Du kannst jetzt jedermanns Partner sein" - "hu" "Barkinek lehetsz a 'Tarsa'." - } - "BuddyLockMsgEnabled" - { - "en" "Buddy selection locked. Only you can change your buddy" - "fr" "Sélection de partenaire bloquée. Vous êtes le seul à pouvoir choisir votre partenaire" - "de" "Wahl des Partners gesperrt. Nur du kannst deinen Partner wechseln" - "hu" "Tars-lista lezarva. Csak Te tudod modositani a Tars-listadat." - } - "PlayerLockedBuddyMsg" - { - "#format" "{1:s}" - "en" "{1} has locked his buddy selection. Try again" - "fr" "{1} a bloqué sa sélection de partenaire. Essayez de nouveau." - "de" "{1} hat seine Wahl des Partners gesperrt. Versuche es erneut" - "hu" "{1} lezarta a Tars-listajat. Probald kesobb!" - } - "BuddyWelcomeMsg1" - { - "en" "Select a balance buddy and stay together during an autobalance!" - "fr" "Choisissez un partenaire et restez ensemble durant l'équilibrage automatique!" - "de" "Wähle einen Partner und bleibt zusammen während eines Ausgleichs" - "hu" "Valasz ki egy 'Tarsat' akivel egyuttmaradhatsz a csapatkiegyenlites alatt!" - } - "BuddyWelcomeMsg2" - { - "en" "/buddy or !buddy to select a balance buddy" - "fr" "/buddy or !buddy pour choisir un partenaire" - "de" "/buddy oder !buddy um einen Partner zu wählen" - "hu" "Hasznald a /buddy vagy !buddy parancsokat a 'Tars' kijelolesehez" - } - "BuddyWelcomeMsg3" - { - "en" "/lockbuddy or !lockbuddy to lock your selection" - "fr" "/lockbuddy or !lockbuddy pour bloquer votre sélection" - "de" "/lockbuddy oder !lockbuddy um deine Auswahl zu sperren" - "hu" "Hasznald a /lockbuddy vagy a !lockbuddy parancsokat a Tars-listad lezarasahoz" - } -} - - - - diff --git a/Simple Plugins Core/addons/sourcemod/translations/simpleteammanager.phrases.txt b/Simple Plugins Core/addons/sourcemod/translations/simpleteammanager.phrases.txt deleted file mode 100644 index f2093a7..0000000 --- a/Simple Plugins Core/addons/sourcemod/translations/simpleteammanager.phrases.txt +++ /dev/null @@ -1,92 +0,0 @@ -"Phrases" -{ - "PlayerLevelCmd" - { - "en" "Command must be run at the player level" - "fr" "Cette commande doit être tapée en jeu" - "hu" "Ezt a parancsot jatekosi szinten kell futtatni!" - } - "RestrictedCmd" - { - "en" "You must be a donator or admin to run this command" - "fr" "Vous devez être un donateur ou un admin pour lancer cette commande" - "hu" "A parancs futtatasahoz admin, vagy tamogatoi szint szukseges!" - } - "InValidTeam" - { - "en" "You must be on red or blue to swap teams" - "fr" "Vous devez être RED ou BLU pour changer d'équipe" - "hu" "Jatekban kell lenned, hogy megcsereld a csapatokat!" - } - "PlayerInValidTeam" - { - "en" "Player must be on red or blue to swap teams" - "fr" "Le joueur doit être RED ou BLU pour changer d'équipe" - "hu" "Valamelyik csapatban kell lenni, hogy csere legyen" - } - "PlayerQueue" - { - "en" "You have been queued to swap teams on next death" - "fr" "Vous avez été mis en attente pour changer d'équipe lors de votre prochaine mort" - "hu" "A kovetkezo halalnal csapatcsere lesz" - } - "PlayerSwitched" - { - "en" "Your team has been switched" - } - "PlayerSwitched1" - { - "en" "Your team has been switched as requested" - "fr" "Vous avez changé d'équipe comme demandé" - "hu" "A keresnek eleget teve a csapatod meg lett csererlve" - } - "PlayerSwitched2" - { - "en" "Your team has been switched by an Admin" - "fr" "Vous avez été changé d'équipe par un admin" - "hu" "Az Admin megcserelte a csapatodat!" - } - "SwapTeamMsg" - { - "en" "Type /swapteam or !swapteam to swap your team!" - } - "PlayerSwitched3" - { - "#format" "{1:s}" - "en" "{1}'s team has been switched" - "fr" "{1} a changé d'équipe" - "hu" "{1} csapata meg lett cserelve" - } - "Scramble" - { - "en" "Teams are about to be scrambled!" - "fr" "Les équipes vont être rééquilibrés" - "hu" "A csapatok hamarosan meg lesznek keverve!" - } - "VoteScramble1" - { - "#format" "{1:i}{2:i}" - "en" "Vote Scramble successful with {1} votes out of {2}" - "fr" "Le vote d'équilibrage des équipes a réussi avec {1} votes pour sur {2}" - "hu" "A szavazas sikeres volt, {1} szavazat a keveresre a {2} -bol" - } - "VoteScramble2" - { - "#format" "{1:i}{2:i}" - "en" "Vote Scramble failed with {1} votes out of {2}" - "fr" "Le vote d'équilibrage a échoué avec {1} votes pour sur {2}" - "hu" "A szavazas sikertelen volt, {1} szavazat a keveresre a {2} -bol" - } - "VoteInProgress" - { - "en" "A vote is currently in progress" - "fr" "Un vote est actuellement en cours" - "hu" "Egy szavazas mar fut!" - } - "ScrambleTime" - { - "en" "A vote was recently made, please wait" - "fr" "Un vote a déjà été fait récemment, réessayez plus tard" - "hu" "Nemreg volt szavazas, kerlek varj egy kicsit!" - } -} \ No newline at end of file diff --git a/Simple Round Immunity/addons/sourcemod/configs/simple-alltalkmanager_events.cfg b/Simple Round Immunity/addons/sourcemod/configs/simple-alltalkmanager_events.cfg deleted file mode 100644 index b739cf0..0000000 --- a/Simple Round Immunity/addons/sourcemod/configs/simple-alltalkmanager_events.cfg +++ /dev/null @@ -1,43 +0,0 @@ -"game_events" -{ - "teamplay_round_start" - { - "reason" "Round Start" - "setting" "1" - } - "teamplay_setup_finished" - { - "reason" "Setup Period Ended" - "setting" "0" - } - "teamplay_overtime_begin" - { - "reason" "Overtime Began" - "setting" "1" - } - "teamplay_overtime_end" - { - "reason" "Overtime Ended" - "setting" "1" - } - "teamplay_round_win" - { - "reason" "Round Ended" - "setting" "1" - } - "teamplay_suddendeath_begin" - { - "reason" "Sudden Death Began" - "setting" "1" - } - "teamplay_suddendeath_end" - { - "reason" "Sudden Death Ended" - "setting" "1" - } - "teamplay_round_stalemate" - { - "reason" "Stalemate" - "setting" "1" - } -} \ No newline at end of file diff --git a/Simple Round Immunity/addons/sourcemod/configs/simple-chatcolors.cfg b/Simple Round Immunity/addons/sourcemod/configs/simple-chatcolors.cfg deleted file mode 100644 index 14b98c6..0000000 --- a/Simple Round Immunity/addons/sourcemod/configs/simple-chatcolors.cfg +++ /dev/null @@ -1,15 +0,0 @@ -"admin_colors" -{ - "groupname2" - { - "flag" "z" - "namecolor" "{green}" - "textcolor" "{olive}" - } - "groupname1" - { - "flag" "a" - "namecolor" "{teamcolor}" - "textcolor" "{green}" - } -} \ No newline at end of file diff --git a/Simple Round Immunity/addons/sourcemod/plugins/simple-alltalkmanager.smx b/Simple Round Immunity/addons/sourcemod/plugins/simple-alltalkmanager.smx deleted file mode 100644 index 6122756af68998fb531abcd0d08698e24cff25af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7028 zcmYMtbvzvK{|E5H#I)(@Znl|CoX&~UHN!Zj9n;;Nn{LxRdD@-Xn3!&d)5fXkIDWpr zc>Ml&e_qe`C*B_=B`sY{3=DTV03bmL03d1x002T5kIVn&2Pyyn=h1Q00Khml06_R? z69xc4>oF-GtNPKRkIDF08;^!RCf8#XKW@M=0RVwVgINFo63{OE0v}C+4*&>)Ay(D^K`RS)3xJ@D zhoz$(*zLdJY4Q0H&KB-=p4N|Wx3Kx|*6BZum8H%9pZur!Was#Q`;KwExe2xog7BpuI{ z*)66j1?43lZn{SqJaj&ttkOa+Coi&C+!~b4u_&^1)9IAS=1?YsFf~gOTvp>~x%PE) zVez+qd?oUTmB?n|J?UZ6B~#pM2Jsp5(JKjW`uTgO%JSU1B1z;wMzrbWYH+#opa<_$=9IhQ}JP@xlM1! zL*S>y%2j2G8#Z+qt64@|8Hz){mFiS%)>hr#Jij6wKhVXo_TYMv4etF#H z;^Pv(lW!64*Uq?9C%^1eb=etw>$Gz%XkjK=N2KAwAYFt|Gs)iDcL{f8h!KZnk-`?5 zHodgg-c}#`sjR(S3SPY@l{WU`3>+r+2vnvFY()Qw?Wx*N1Krsb}abp8su(w!NoP&rA2zAMY`*x z2fTl@x^+*hZMybY3aNIL^xaqkaVj&CTBe=U77TwB_L!9;hV9X$b1*6QBiw$py$ix^ zPZN88%V_4j*Utjq`#KqazwVnyZpPj;Z{*&Xi4Qq>y|(Sl zSmKn2PFu*+Uh))4+CH&%Wl1t@fidDwd?@*iW*;_X&|Q+VRv)o}_GUWoTo^r!0MA9a z&K=uDKLo|@k%&~la&HaCj@3pB2{L%SCVL{-FR^OR@7b4g+H0qiazLlGm5VDGBBCbj z%hs_83%x#J`*ppy?%Kz|rTXYAe6(SYvB=g)-d4M#v3eW#6l|d&s}FA8Mnzl8z;r=XO7DM;#>c?Hsu>nsg)#&6gwO zqjjy_z$WM#Sf@b6n9X_&ddQ9T*7u)C^MGe<+zvFw6Ffk>SVlG0@||wb&`Fs5z2*#O zrcVO+X%Lob&p$%ZUi6VO1o03vzT9Edp7P@o9y2aEp&|qUwvO(Ue9q59Hk}I$Ee&uS zBpiGvSKD4&-DUiWE+}&A5wY6;@NGnS(aovBHz)D}@fCR;{F>ObFaQ+~TJ+kq36n;hx+N&48^u63Xb+nc-ly6!r z3?H4nT(#48~V@UO=R7zF4;FG=8O1D{VGj%%Xqc{cqsz8WB^aJ{ z_H_y*@>k;B*uRudm78GlDb4LTFgV>|A#hSCUEt;6OdjMw;hNGP))=@oG&nd2(scK+ zj_5#*h*?i_Ow+0e6(KBw9awzI%tzIY>I~f-TfSfS^X>{P(F+*+Tr(`Q#jXq;7ID2A z^m!f!4eV{{3e_E&^Rt^*F0}%gI5#TQy@dR*(F67vI`T{CC&vi)6LoK9hSds`Mv(@Q z)|fXB?5vTnYT{=Z^0ncwt<|W2sL-Jwk$Sv|hGzorD_^eK|8Cuk&k=)(YM+&h%wCEC zLpUo*eaLCeyvO@qa%TwF>3<&S`nyB#SA!=%7m58t?Vr`h#X4P(j>qR3qecq!X>L_c z(-85{NbAU}QJ#%ZgbY>BU;Mo9Yv20pIfMox%r-_zx!XGO&Jx}n=GBAIL|;W{!w#w=GyZJ zX}y4VWd{AzNg5677uooaS+W zA^|dX$<+wn33j8gghCt*PN!&hf!d0ztT~S6M3(DY{kh1OaV_tjU-MR!H<{TijHnUp zQ*w^#zY4X%p_=f@(=&V0M0v*TW$Y1B)VHd zwWm`PaQ8eFhV}P0IX~(w$d*sWRHB5vgpZ{*Y#R5klFCMM*#tD?%vI%<8I4uKmdpr- z%_gy+adapI=iHbD!rWO(Kq_-`&%;wA-1$miq0MxYW-0|?XMmFLa=!GFUM!LXf8QpX zMNq_jU0q{UfrO;SekDAz2a%SBhBWJy+5D zEp)D+cNL|x8XJ3wm`*BMPt@!trMz_7E3G(ADlv<}@8q_ovHa7xL$kib(lSDNp|~d} z-<4J_PIN+?+dV{j34soiLLpUSq(}ahWb$3$(#A;d@2Y7;Csb*^-&t0abeLZMl+dzI zVp;Lg5svg8d$$aUZq1wyi}Z%PV|e+~x9on36hglMpgg5 z8>GH#yqB2S#--zjQHK%Tfq(ICk6Gr0N+ZcYILL-6;b|wA-)qjtL6_k5Kvgt8bLNYM z6u_Lk7;)SgF}F}WLBMD}?(uWD`IF=K!Mld-#7KQti%zSz7zjKUQY5ELH{C~S8G?^* z;m_cV!TQ1700>qaEz;E0;<7{vtDa=>2+La%jtg+czB2?|$X`1&Q#Y+*h(>SVv=QwE zF;d_1oj-$nVfs@dU%;W9Ys%^Z4$oF?2H#?JVSMC*9{^T~k4*vJoqn7)6Gr(-$$L>! z92}HM{Gc{4>}?)cWA4)x!BW;Liz41|@-(c(6KkVit7xdrEuj4jghdYg==X28^`fjn zfE1=`CxxxIs-)c8{xH7aV_OFzKBYJ*mcE|XaQ;++RR0%)YYW@6%Oac)pnXjv{GzS* z?81qXsfM+w#HkgrKL0v9b!kB-v>0euXPYAs1kWwP@OfXL+%DxOjNpCl-q^kwpIzGQ zuxPgEJ|JMew6fo3JvA4J4i{VUggyOdoM2p{-D? zQ0(b;0UI4MCkBhJ>~?IwrorD}ulsDaWOUAuN*+_Qa==+1xZfT7%!5UtEFt=q@8GOA zWL3XWJ;S%3Ojo}^gN7$s@V%%}yvB?rkF?bdcA=oLq^=^#=FCz2Wn0|_>#$jq(GQR0 zuoZg^$Xhl27cLF5i(l!=Kv@*V0K>Lp5lE}I2?jpbL z3~Hg6AjT){P{>V${^vfy=++$nCf31mu|8Vgs&uX<>!u%9H+=fCy{ktLUW`g=>qH zX*}ZNT*cdGdX!Sf&F)Fe%m`?edF9PjYOuI0{&;r_Omr{%@bxFxiIbYG1!N8uIZ-bo zQ~e#Le~M|SUZn`3q40-aE_rV_P|L>>eeHMnSQpuXxdCTfv5+d=z1TSGmVfSUdAmyG zJF&8Xt?eOx)W2cKfpn8f^F1H&7dTECn{8at526z4Hkk!7hZ#T3YsgxW_4iq9wTu)( zK2M9Xh(>oOKAtSedP;v44j>l3nmJaBxo-J+mk;AIBm3aK$7SGG+e=!7T|_bA?jPlg zMd9xMyF;a1CYsNkig>ne?r*7M@uHQ=&PkVAd25YHo5AttGk7MKd#u_bhb>!pm)ga# zU7i`wWsFX)uc*-x2CRtq-TL=k{&eND;M9D=&v*GCbMSz>8AUiO)hUR{@iyu`83W!I zJO_f&Dgim6#2saomrwpp;t}{qjMRL|A|jidt-~9gF5H@rY`F^bV*6BIZooxoGf zreKXdyHoins7vOH_A^&7PL*IgBYbFxZsZQ4Tccez-^b`9BUYk72Z_q{Tq?7j{ixV* zf$`8uQCgv~Vjhgy3;Tr>e#<@(ObCqS70k*eKRhon zCgZTVNn2-2BnfdS3ZX<$@H^L1W}F%}3o5>*vd*?l*iN{!HZ5MD+~Pq{aTHuDD>$Xv zAEikmsEK~>-E)hLJ;cOd|AEceA^TKr#b?*lR><$LA4?bWEmi`lm26mA| z21j&%CG`E0zNxfW)$1|b_|9+=Sr;#VN?!Wd`i=X#oG_6nO~vtE(eo;3fi#qD2totA z8nE8Z`MT^y^tp>cIJF5~-plhKH+mROW)vz-vxyY5<6eSs^w&}iw9Q;M$Uq=PV@_*t zss#?0!d}mfm$yO1%Hr)!`0LC5eoV=+1Qwg@o|-NVqT?1xe)pm(TjVkZ%?{1S5mA!x zsOF2yuUB!hRJ-22JL%ohVDBza5&#hX8!gntvOVDP&hCs%80 zkx1dMZxHo}uY-xQafC4anat{$i@%;2De0k3%aceh|GK6=0vExlK~ zW2A9#f&2hA{8m)-{Iu6by$gQ$a*xvNF*jEy$x3Wp8ni#+cl8UGJ?o#>8BATID z&lDK|(a>QExG206!1=

0=W}HiQ6!(Sb8Sg4pHd-X!K^`4+&OWE{7R9@!08#XBa2 z6S(7NcG3`~P&N830_v1Zaocc^#K92kHag_Y@74%)Rzeju4F8@8_2MUv@fuf1d>3K3 zbFhgE6QGOnoarMBgz=$I9QzO{k4gbRCV4(f6zjtEiIF(L=^$A>4o8yuc#>v-lOt|@ z=qa{$H7G(wSZeF3EkQ zXjOcGeWjgB4e!Jl6)eKt*Z~A$ZV}-2a$$VJ2vjWx3-}B+Nbzx)pP70uIl5Ll8G%S&Q@ zCMmlhX6mo~bUjYtu&a+=>u9B$gU6LH9scI%{`8VnZeTpvwo_!XguAeOV^Y>jr8&myi#^j0|N>YQO(84wX^s;x(vCUa!ncAmB-zq zstl%H{baOb#jh>HjYfNtC#l{I1d`o4lGh5O2fnaflyWvE+3v)?WL6AC1Vqvl(}*B5 z*h`F|s_|yEoy;t&Z)W>v(2>A86|J70Rnnz2W@>h{@&K{rYF;4_Z9d#w`sBbDdY$R{ zO15~`z8upMqB)M*tDYM13Q$IVkVggZw-`B5GhfJrqPnPVVxA2@sSQ&QxGD|v^JbO3 zu!>7Zn3kiBL#4{HF(q?VwBYZnX{vwrWEYOtGDBOkLJ7m>xBmRw;pe>=`gAQXNZDDJ z#lOT1EjPybRyF_S)3xw3${a|#^e62GGvSEO_82IJKbuzvlNWWB;3K;-t$rl`g~(I@ z=})O~^&~x66zq*I(vkF5LD;xT7NwcZgA|SqXwS-@>nVIXmm^BBbIy-pl<+WXD>l`n zbZpG9`bYD~btpy-JU~A8?qSN7vM;*1QB1!PfYs z$eQ`8NiyLxJlw9hCN|X{ZeI1#7faEEPyR=ZSi}c?=?sB@HyAdCqYV}>UIYYwA`yeN z`IfMFIxR`tjE4Qil-IzFqJ|V`)vUt>+o`HBoYSUWyn+nSI z2iVexWyi$ZfcLZ9@3|J1_=Xy_7-N|8-o_N_bX=_jB$G%ShbTVjY9n@ z^0C~3H07%zNE)5@xsmYRs3cQC%TAR6?X=R#t$uRzo-r-W-|#eAU0{gLASR=1Y|g~C zH_p5GT|9)HhHj+$3)Cxw*tZz1iuOABiV)}$N(W1bb=n67svJ}F5Wv3|N#HKlls$Pf zR9RuBY&pPZd_?hv^qaleJI)&Y@b1)R{%_)I&Uy}^D{9ttRcuXwhp-j(+16y;Chk$1 z2_SOSim2gqmcohUk3xA*b>3RZQ$GbPbokPf>s zXIfr?TrFQTX_VaD4TCAD9rO9tA+i>dbi}>bt|J0DkQsB}q8OD?QVpOA$8LIUz?+y? zHx?P&zi^NEak#ci!E6M?(tlhjcYr95|~ z0djso1Ih{Ltf>=TaSOZyqm4R_!pV>X%0@&n;rJY3K-t?B&HFEV-RP!^EPkFYG;U?E z_}_)RN!7kb-Yauro3*)zQ|zDI8IpwbV`jwhy$;1Yv%Cl{o5UB+HU=_F`uwzT6PEIrlfuX=)0x(JLidLxNxLO}jf;p=2nPC{a1N e@WUZygbeC5w{WF@V(|1QaEv_m?g1?8hW%e>J(WfP diff --git a/Simple Round Immunity/addons/sourcemod/plugins/simple-donatorbenefits.smx b/Simple Round Immunity/addons/sourcemod/plugins/simple-donatorbenefits.smx deleted file mode 100644 index 821d61d784607595ca400d273a941a42e40de640..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16600 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 diff --git a/Simple Round Immunity/addons/sourcemod/plugins/simple-messagesuppression.smx b/Simple Round Immunity/addons/sourcemod/plugins/simple-messagesuppression.smx deleted file mode 100644 index cc20dadd37d8ff23d0a64513cc09650f4bdbf24d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4845 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 Blh*(M diff --git a/Simple Round Immunity/addons/sourcemod/plugins/simple-spectate.smx b/Simple Round Immunity/addons/sourcemod/plugins/simple-spectate.smx deleted file mode 100644 index c6885b041145a73f664650e729a5dcf8b3b0813f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19129 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%0ACwUfid=y*oPG;MRqmWr)g0 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�XP zM5L)&uZne^XHs;_L+03=Xy3CiU1O76^S{TWu{zY}Jlq((BV?9EL=m4MC%~!W0MzeW zOjQv*a;A7AS@l%h9EbjzQ3d}e&j~R0VCoAN)q_>=)m=>e=ZX9w8jM3&o1RO^+0jJ) z

_|h)w;)ME+|h#gx@oo-|ZEuRI5d) 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 z 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 z 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 KvHt-#rc|>H2mv<$ diff --git a/Simple Round Immunity/addons/sourcemod/scripting/include/simple-plugins.inc b/Simple Round Immunity/addons/sourcemod/scripting/include/simple-plugins.inc deleted file mode 100644 index 8f21956..0000000 --- a/Simple Round Immunity/addons/sourcemod/scripting/include/simple-plugins.inc +++ /dev/null @@ -1,337 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Plugins -Description: - Included file for core plugin in the Simple Plugins project -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -*************************************************************************/ - -#if defined _simpleplugin_included - #endinput -#endif - -#define _simpleplugin_included - -#define CORE_INC_VERSION "1.1.$Rev$" - -#pragma semicolon 1 -#include -#undef REQUIRE_PLUGIN -#include -#define REQUIRE_PLUGIN -#undef REQUIRE_EXTENSIONS -#undef AUTOLOAD_EXTENSIONS -#tryinclude -#tryinclude -#tryinclude -#define AUTOLOAD_EXTENSIONS -#define REQUIRE_EXTENSIONS - -enum e_SupportedMods -{ - GameType_Unknown, - GameType_AOC, - GameType_CSS, - GameType_DOD, - GameType_FF, - GameType_HIDDEN, - GameType_HL2DM, - GameType_INS, - GameType_L4D, - GameType_NEO, - GameType_SGTLS, - GameType_TF, - GameType_ZPS -}; - -enum e_Teams -{ - Unknown, - Spectator, - Team1, - Team2 -}; - -new g_aCurrentTeams[e_Teams]; -new e_SupportedMods:g_CurrentMod; -new String:g_sGameName[e_SupportedMods][32] = { "Unknown", - "Age of Chivalry", - "Counter Strike", - "Day Of Defeat", - "Fortress Forever", - "Hidden: Source", - "Half Life 2: Deathmatch", - "Insurgency", - "Left 4 Dead", - "Neotokyo", - "Stargate TLS", - "Team Fortress 2", - "Zombie Panic: Source" - }; - -public SharedPlugin:_pl_simpleplugin = -{ - name = "simple-plugins", - file = "simple-plugins.smx", -#if defined REQUIRE_PLUGIN - required = 1 -#else - required = 0 -#endif -}; - -#if !defined REQUIRE_PLUGIN -public _pl_simpleplugin_SetNTVOptional() -{ - MarkNativeAsOptional("SM_MovePlayer"); - MarkNativeAsOptional("SM_SetForcedTeam"); - MarkNativeAsOptional("SM_GetForcedTeam"); - MarkNativeAsOptional("SM_ClearForcedTeam"); - MarkNativeAsOptional("SM_GetForcedPlayer"); - MarkNativeAsOptional("SM_AssignBuddy"); - MarkNativeAsOptional("SM_SearchBuddy"); - MarkNativeAsOptional("SM_LockBuddy"); - MarkNativeAsOptional("SM_IsBuddyLocked"); - MarkNativeAsOptional("SM_ClearBuddy"); - MarkNativeAsOptional("SM_IsValidAdmin"); - MarkNativeAsOptional("SM_IsValidTeam"); -} -#endif - -/********************************************************************** - * When a player has to moved - * - * @param plugin Plugin that initiated the move - * @param client The client index of the player that was moved - * @param team The team index the player was moved to - * @noreturn - **********************************************************************/ -forward SM_OnPlayerMoved(Handle:plugin, client, team); - -/********************************************************************** - * Move a player to the supplied team - * - * @param client The client index of the player to be moved - * @param team The team to move the player to - * @noreturn - * @error Invalid client or team index - **********************************************************************/ -native SM_MovePlayer(client, team); - -/********************************************************************** - * Move a player to the supplied team - * - * @param client The client index of the player to set - * @param team The team to move the to set - * @param override Whether or not to override another plugin - * @return True if successful, false if not - * @error Invalid client or team index - **********************************************************************/ -native SM_SetForcedTeam(client, team, bool:override = false); - -/********************************************************************** - * Gets the client's forced team index - * - * @param client The client index of the player to check - * @param plugin Optional: The plugin handle of the plugin - that set the team - * @return The team index of the forced team - Zero if no forced team - * @error Invalid client index - **********************************************************************/ -native SM_GetForcedTeam(client, &Handle:plugin = INVALID_HANDLE); - -/********************************************************************** - * Clears a client's forced team - * - * @param client The client index of the player to check - * @return True if successful, false if not - * @error Invalid client index - **********************************************************************/ -native SM_ClearForcedTeam(client); - -/********************************************************************** - * Gets a forced player on the wrong that is currently on the wrong team - * This will only return a player if the calling plugin assigned the team - * - * @param team The team index the player should be on - * @return The client index of the player - Zero if no player found - * @error Invalid client index - **********************************************************************/ -native SM_GetForcedPlayer(team); - -/********************************************************************** - * Assign a players buddy - * - * @param client The client index of the player to assign - * @param player The player index of the player to assign - * @param override Whether or not to override a player lock - * @return True if successful, false if not - * @error Invalid client or player index - **********************************************************************/ -native bool:SM_AssignBuddy(client, player, bool:override = false); - -/********************************************************************** - * Rturns the client's buddy - * - * @param client The client index of the player to assign - * @return The client index of the player's buddy - Zero if no buddy - * @error Invalid client index - **********************************************************************/ -native SM_GetClientBuddy(client); - -/********************************************************************** - * Set the buddy lock setting for a client - * - * @param client The client index of the player to assign - * @param setting Setting to set, True or False - * @return True if successful, false if not - * @error Invalid client index - **********************************************************************/ -native bool:SM_LockBuddy(client, bool:setting); - -/********************************************************************** - * Returns the buddy lock setting for a client - * - * @param client The client index of the player to assign - * @return True if locked, false if not - * @error Invalid client index - **********************************************************************/ -native bool:SM_IsBuddyLocked(client); - -/********************************************************************** - * Clear a players buddy - * - * @param client The client index of the player to clear - * @param override Whether or not to override a player lock - * @return True if successful, false if not - * @error Invalid client index - **********************************************************************/ -native bool:SM_ClearBuddy(client, bool:override = false); - -/********************************************************************** - * Determine if the player has the supplied flags - * ADMFLAG_ROOT will always return true - * - * @param client The client index of the player to assign - * @param flags The char flag(s) to check against - * @return True if valid, false if not - **********************************************************************/ -native bool:SM_IsValidAdmin(client, const String:flags[]); - - -/********************************************************************** - * Determine if the team is a valid team - * - * @param team The team index to determine if valid for - currently installed/supported mod - * @return True if valid, false if not - **********************************************************************/ -native bool:SM_IsValidTeam(team); - - -public e_SupportedMods:GetCurrentMod() -{ - new String:sGameType[64]; - GetGameFolderName(sGameType, sizeof(sGameType)); - - if (StrEqual(sGameType, "aoc", false)) - { - return GameType_AOC; - } - if (StrEqual(sGameType, "cstrike", false)) - { - return GameType_CSS; - } - if (StrEqual(sGameType, "dod", false)) - { - return GameType_DOD; - } - if (StrEqual(sGameType, "ff", false)) - { - return GameType_FF; - } - if (StrEqual(sGameType, "hidden", false)) - { - return GameType_HIDDEN; - } - if (StrEqual(sGameType, "hl2mp", false)) - { - return GameType_FF; - } - if (StrEqual(sGameType, "insurgency", false) || StrEqual(sGameType, "ins", false)) - { - return GameType_INS; - } - if (StrEqual(sGameType, "l4d", false)) - { - return GameType_L4D; - } - if (StrEqual(sGameType, "nts", false)) - { - return GameType_NEO; - } - if (StrEqual(sGameType, "sgtls", false)) - { - return GameType_SGTLS; - } - if (StrEqual(sGameType, "tf", false)) - { - return GameType_TF; - } - if (StrEqual(sGameType, "zps", false)) - { - return GameType_ZPS; - } - return GameType_Unknown; -} - -public LoadCurrentTeams() -{ - switch (g_CurrentMod) - { - case GameType_INS: - { - g_aCurrentTeams[Unknown] = 0; - g_aCurrentTeams[Spectator] = 3; - g_aCurrentTeams[Team1] = 1; - g_aCurrentTeams[Team2] = 2; - } - case default: - { - g_aCurrentTeams[Unknown] = 0; - g_aCurrentTeams[Spectator] = 1; - g_aCurrentTeams[Team1] = 2; - g_aCurrentTeams[Team2] = 3; - } - } -} diff --git a/Simple Round Immunity/addons/sourcemod/scripting/simple-alltalkmanager.sp b/Simple Round Immunity/addons/sourcemod/scripting/simple-alltalkmanager.sp deleted file mode 100644 index c848332..0000000 --- a/Simple Round Immunity/addons/sourcemod/scripting/simple-alltalkmanager.sp +++ /dev/null @@ -1,515 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple AllTalk Manager -Description: - Allows you to set alltalk at different times -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#pragma semicolon 1 -#include -#include - -#define PLUGIN_VERSION "1.4.$Rev$" - -new Handle:satm_enabled = INVALID_HANDLE; -new Handle:satm_threshold_enabled = INVALID_HANDLE; -new Handle:satm_player_threshold = INVALID_HANDLE; -new Handle:satm_threshold_setting = INVALID_HANDLE; -new Handle:satm_logactivity = INVALID_HANDLE; -new Handle:satm_alltalk = INVALID_HANDLE; - -new Handle:g_aEventNames = INVALID_HANDLE; -new Handle:g_aEventReasons = INVALID_HANDLE; -new Handle:g_aEventSettings = INVALID_HANDLE; - -new bool:g_bLastThreshold = false; -new bool:g_bEnabled = true; -new bool:g_bThresholdEnabled = true; -new bool:g_bIsSetupMap = false; -new bool:g_bIsGameTF2 = false; -new bool:g_bLogActivity = false; - -new g_iLastEventIndex; - -public Plugin:myinfo = -{ - name = "Simple AllTalk Manager", - author = "Simple Plugins", - description = "Allows you to set alltalk at different times", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -} - -/** -Sourcemod callbacks -*/ -public OnPluginStart() -{ - - /** - Need to create all of our console variables. - */ - CreateConVar("satm_version", PLUGIN_VERSION, "Simple AllTalk Manager", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - satm_enabled = CreateConVar("satm_enabled", "1", "Enables/Disables Simple AllTalk Manager", _, true, 0.0, true, 1.0); - satm_threshold_enabled = CreateConVar("satm_threshold_enabled", "1", "Enables/Disables player threshold", _, true, 0.0, true, 1.0); - satm_player_threshold = CreateConVar("satm_player_threshold", "8", "Amount of players for the threshold"); - satm_threshold_setting = CreateConVar("satm_threshold_setting", "1", "Enables/Disables all talk up to player threshold, with the opposite set after the threshold", _, true, 0.0, true, 1.0); - satm_logactivity = CreateConVar("satm_logactivity", "0", "Enables/Disables log activity", _, true, 0.0, true, 1.0); - satm_alltalk = FindConVar("sv_alltalk"); - - /** - Hook console variables - */ - HookConVarChange(satm_enabled, ConVarSettingsChanged); - HookConVarChange(satm_threshold_enabled, ConVarSettingsChanged); - HookConVarChange(satm_player_threshold, ConVarSettingsChanged); - HookConVarChange(satm_logactivity, ConVarSettingsChanged); - - /** - Remove the notify flag from all talk cvar since we do it - */ - SetConVarFlags(satm_alltalk, GetConVarFlags(satm_alltalk)~FCVAR_NOTIFY); - - /** - Get the game type. We only care if it's TF2 - */ - new String:sGameType[64]; - GetGameFolderName(sGameType, sizeof(sGameType)); - if (StrEqual(sGameType, "tf", false)) - { - g_bIsGameTF2 = true; - } - - /** - Create the arrays - */ - g_aEventNames = CreateArray(255, 1); - g_aEventReasons = CreateArray(255, 1); - g_aEventSettings = CreateArray(1, 1); - - /** - Need to register the commands we are going to create and use. - */ - RegAdminCmd("sm_reloadatconfig", Command_Reload, ADMFLAG_GENERIC, "Reloads settings from config file"); - - /** - Create the config file - */ - AutoExecConfig(true); - - /** - Load the events from the config - */ - LoadEventsFromConfig(); -} - -public OnConfigsExecuted() -{ - - /** - Load up the settings - */ - g_bEnabled = GetConVarBool(satm_enabled); - g_bLogActivity = GetConVarBool(satm_logactivity); - g_bThresholdEnabled = GetConVarBool(satm_threshold_enabled); -} - -public OnMapStart() -{ - - /** - Reset the globals - */ - g_iLastEventIndex = 0; - g_bLastThreshold = false; - - /** - Check the map type if we are in TF2 - */ - if (g_bIsGameTF2) - { - g_bIsSetupMap = IsSetupPeriodMap(); - } - - /** - Set AllTalk - */ - if (g_bEnabled) - { - SetConVarBool(satm_alltalk, true); - } -} - -public OnClientDisconnect_Post(client) -{ - if (g_bEnabled) - { - SetAllTalk(-1); - } -} - -public OnClientPostAdminCheck(client) -{ - if (g_bEnabled) - { - SetAllTalk(-1); - } - CreateTimer(2.0, Timer_ShowAllTalkStatus, client, TIMER_FLAG_NO_MAPCHANGE); -} - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (convar == satm_enabled) - { - if (StringToInt(newValue)) - { - g_bEnabled = true; - } - else - { - g_bEnabled = false; - } - } - else if (convar == satm_threshold_enabled) - { - if (StringToInt(newValue)) - { - g_bThresholdEnabled = true; - } - else - { - g_bThresholdEnabled = false; - } - } - else if (convar == satm_logactivity) - { - if (StringToInt(newValue)) - { - g_bLogActivity = true; - } - else - { - g_bLogActivity = false; - } - } - if (g_bEnabled) - { - SetAllTalk(-1); - } -} - -/** -Commands -*/ -public Action:Command_Reload(client, args) -{ - - /** - Clear the array - */ - ClearArray(g_aEventNames); - ClearArray(g_aEventReasons); - ClearArray(g_aEventSettings); - - /** - Load the events from the config - */ - LoadEventsFromConfig(); - - return Plugin_Handled; -} - -/** -Game Event Hooks -*/ -public Hook_All_Events(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (!g_bIsSetupMap) - { - if (StrEqual(name, "teamplay_round_start")) - { - if (FindStringInArray(g_aEventNames, "teamplay_setup_finished") != -1) - { - g_iLastEventIndex = FindStringInArray(g_aEventNames, "teamplay_setup_finished"); - if (g_bEnabled) - { - SetAllTalk(g_iLastEventIndex); - return; - } - } - } - } - g_iLastEventIndex = FindStringInArray(g_aEventNames, name); - if (g_bEnabled) - { - SetAllTalk(g_iLastEventIndex); - } -} - -/** -Timers -*/ -public Action:Timer_ShowAllTalkStatus(Handle:timer, any:client) -{ - if (IsClientConnected(client) && IsClientInGame(client)) - { - new bool:bSetting = GetConVarBool(satm_alltalk); - if (bSetting) - { - PrintToChat(client, "\x01\x04[SM] AllTalk is \x01[on]"); - } - else - { - PrintToChat(client, "\x01\x04[SM] AllTalk is \x01[off]"); - } - } -} - -/** -Stock Functions -*/ -stock LoadEventsFromConfig() -{ - - /** - Make sure the config file is here and load it up - */ - new String:sConfigFile[256]; - BuildPath(Path_SM, sConfigFile, sizeof(sConfigFile), "configs/simple-alltalkmanager_events.cfg"); - if (!FileExists(sConfigFile)) - { - - /** - Config file doesn't exists, stop the plugin - */ - LogError("[SATM] Simple AllTalk Manager is not running! Could not find file %s", sConfigFile); - SetFailState("Could not find file %s", sConfigFile); - } - - /** - Create the arrays and variables - */ - new String:sGameEventName[256]; - new String:sReason[256]; - new iSetting; - - /** - Load config file as a KeyValues file - */ - new Handle:kvGameEvents = CreateKeyValues("game_events"); - FileToKeyValues(kvGameEvents, sConfigFile); - - if (!KvGotoFirstSubKey(kvGameEvents)) - { - return; - } - - /** - Hook the game events and load the settings - */ - do - { - - /** - Get the section name; this should be the event name - */ - KvGetSectionName(kvGameEvents, sGameEventName, sizeof(sGameEventName)); - if (!HookEventEx(sGameEventName, Hook_All_Events, EventHookMode_PostNoCopy)) - { - - /** - Could not hook this event, stop the plugin - */ - SetFailState("Could not hook event %s", sGameEventName); - } - else - { - if (g_bLogActivity) - { - LogMessage("[SATM] Hooked event: %s", sGameEventName); - } - } - - /** - Get the reason string and setting - */ - KvGetString(kvGameEvents, "reason", sReason, sizeof(sReason)); - iSetting = KvGetNum(kvGameEvents, "setting"); - if (g_bLogActivity) - { - LogMessage("[SATM] Event reason string: %s", sReason); - LogMessage("[SATM] Event setting: %i", iSetting); - } - - /** - Push the values to the arrays - */ - PushArrayString(g_aEventNames, sGameEventName); - PushArrayString(g_aEventReasons, sReason); - PushArrayCell(g_aEventSettings, iSetting); - } while (KvGotoNextKey(kvGameEvents)); - - /** - Close our handle - */ - CloseHandle(kvGameEvents); -} - -stock SetAllTalk(index) -{ - new iPlayerThreshold = GetConVarInt(satm_player_threshold); - new bool:bThresholdMet = ((GetClientCount() >= iPlayerThreshold) ? true : false); - new bool:bSetting; - - if (g_bThresholdEnabled) - { - if (bThresholdMet) - { - if (index == -1) - { - if (bThresholdMet != g_bLastThreshold) - { - g_bLastThreshold = true; - bSetting = !GetConVarBool(satm_threshold_setting); - new bool:bLastSetting = GetArrayCell(g_aEventSettings, g_iLastEventIndex); - if (bLastSetting && !bSetting) - { - bSetting = GetArrayCell(g_aEventSettings, g_iLastEventIndex); - } - } - else - { - bSetting = GetArrayCell(g_aEventSettings, g_iLastEventIndex); - } - } - else - { - bSetting = GetArrayCell(g_aEventSettings, index); - } - } - else - { - g_bLastThreshold = false; - bSetting = GetConVarBool(satm_threshold_setting); - } - } - else - { - if (index != -1) - { - bSetting = GetArrayCell(g_aEventSettings, index); - } - } - - if (GetConVarBool(satm_alltalk) != bSetting) - { - - SetConVarBool(satm_alltalk, bSetting); - - new String:sReason[256]; - if (index == -1) - { - Format(sReason, sizeof(sReason), "Player Threshold"); - } - else - { - if (!g_bIsSetupMap) - { - new String:sCurrentEvent[256]; - GetArrayString(g_aEventNames, index, sCurrentEvent, sizeof(sCurrentEvent)); - if (StrEqual(sCurrentEvent, "teamplay_setup_finished")) - { - new iRoundStartIndex = FindStringInArray(g_aEventNames, "teamplay_round_start"); - if (iRoundStartIndex != -1) - { - GetArrayString(g_aEventReasons, iRoundStartIndex, sReason, sizeof(sReason)); - } - else - { - GetArrayString(g_aEventReasons, index, sReason, sizeof(sReason)); - } - } - else - { - GetArrayString(g_aEventReasons, index, sReason, sizeof(sReason)); - } - } - else - { - GetArrayString(g_aEventReasons, index, sReason, sizeof(sReason)); - } - } - - if (bSetting) - { - PrintToChatAll("\x01\x04[SM] AllTalk turned \x01[on] \x04due to:\x01 %s", sReason); - } - else - { - PrintToChatAll("\x01\x04[SM] AllTalk turned \x01[off] \x04due to:\x01 %s", sReason); - } - } -} - -stock bool:IsSetupPeriodMap() -{ - new iEnt = -1; - new String:sMapName[32]; - - GetCurrentMap(sMapName, sizeof(sMapName)); - - if (strncmp(sMapName, "cp_", 3, false) == 0) - { - new iTeam; - while ((iEnt = FindEntityByClassname(iEnt, "team_control_point")) != -1) - { - iTeam = GetEntProp(iEnt, Prop_Send, "m_iTeamNum"); - - /** - If there is a blu CP or a neutral CP, then it's not an attack/defend map - */ - if (iTeam != 2) - { - //this is a push map - return false; - } - } - //this is a attack/defend map - return true; - } - else if (strncmp(sMapName, "ctf_", 3, false) == 0) - { - //this is a ctf map - return false; - } - return false; -} diff --git a/Simple Round Immunity/addons/sourcemod/scripting/simple-autoscrambler.sp b/Simple Round Immunity/addons/sourcemod/scripting/simple-autoscrambler.sp deleted file mode 100644 index 6c6799e..0000000 --- a/Simple Round Immunity/addons/sourcemod/scripting/simple-autoscrambler.sp +++ /dev/null @@ -1,459 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple AutoScrambler -Description: - Automatically scrambles the teams based upon a number of events. -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include - -#define PLUGIN_VERSION "1.1.$Rev$" - -/** -Different scramble modes: - -1 = Full Scramble, dont restart round. -2 = Admins Immune, dont restart round. -3 = Full Scramble, restart round and reset scores. -4 = Admins Immune, restart round and reset scores. - -*/ - -/** -Different top player modes: - -1 = Divide Top 4 players on the two teams. -2 = Protect the Top 2 players on each team. - -*/ - -enum PlayerData -{ - Handle:hForcedTimer, - bool:bProtected; -}; - -/** -Cvars used for admins -*/ -new Handle: sas_admin_immunity_enabled = INVALID_HANDLE, - Handle: sas_admin_flag_scramblenow = INVALID_HANDLE, - Handle: sas_admin_flag_immunity = INVALID_HANDLE; - -/** -Cvars used for autoscramble -*/ -new Handle: sas_autoscramble_enabled = INVALID_HANDLE, - Handle: sas_autoscramble_minplayers = INVALID_HANDLE, - Handle: sas_autoscramble_mode = INVALID_HANDLE, - Handle: sas_autoscramble_winstreak = INVALID_HANDLE, - Handle: sas_autoscramble_steamroll = INVALID_HANDLE, - Handle: sas_autoscramble_frags = INVALID_HANDLE; - -/** -Cvars used for voting -*/ -new Handle: sas_vote_enabled = INVALID_HANDLE, - Handle: sas_vote_upcount = INVALID_HANDLE, - Handle: sas_vote_winpercent = INVALID_HANDLE, - Handle: sas_vote_mode = INVALID_HANDLE, - Handle: sas_vote_minplayers = INVALID_HANDLE; - -/** -Additional cvars -*/ -new Handle: sas_enabled = INVALID_HANDLE, - Handle: sas_timer_scrambledelay = INVALID_HANDLE, - Handle: TFGameModeArena = INVALID_HANDLE; - -/** -Timers -*/ -new Handle: g_hScrambleTimer = INVALID_HANDLE; - -/** - Player arrays - */ -new g_aPlayers[MAXPLAYERS + 1][PlayerData]; - -/** - Cvar variables - */ -new bool: g_bIsEnabled, - bool: g_bIsAutoScrambleEnabled, - bool: g_bIsVoteEnabled, - bool: g_bIsAdminImmunityEnabled; -new Float: g_fTimer_ScrambleDelay, - Float: g_fVote_UpCount, - Float: g_fVote_WinPercent; -new g_iAutoScramble_Minplayers, - g_iAutoScramble_Mode, - g_iAutoScramble_WinStreak, - g_iAutoScramble_SteamRoll, - g_iAutoScramble_Frags, - g_iVote_Mode, - g_iVote_MinPlayers; -new String: g_sScrambleNowFlag[5], - String: g_sAdminImmunityFlag[5]; - -/** -Other globals -*/ -new g_iMaxEntities, - g_iOwnerOffset; - -public Plugin:myinfo = -{ - name = "Simple AutoScrambler", - author = "Simple Plugins", - description = "Automatically scrambles the teams based upon a number of events.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -public OnPluginStart() -{ - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[SAS] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - switch (g_CurrentMod) - { - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_Post); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_Post); - } - } - - /** - Create console variables - */ - CreateConVar("sas_version", PLUGIN_VERSION, "Simple AutoScrambler Version",FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - sas_enabled = CreateConVar("sas_enabled", "1", "Enable/Disable Simple AutoScrambler"); - sas_timer_scrambledelay = CreateConVar("sas_timer_scrambledelay", "5.0", "Delay used after a scramble has been started", _, true, 1.0, true, 30.0); - - /** - Cvars used for admins - */ - sas_admin_immunity_enabled = CreateConVar("sas_admin_immunity_enabled", "1", "Enable/Disable admin immunity for scrambles"); - sas_admin_flag_scramblenow = CreateConVar("sas_admin_flag_scramblenow", "z", "Admin flag to use for scramblenow function/command"); - sas_admin_flag_immunity = CreateConVar("sas_admin_flag_immunity", "z", "Admin flag to use for scramble immunity"); - - /** - Cvars used for autoscramble - */ - sas_autoscramble_enabled = CreateConVar("sas_autoscramble_enabled", "1", "Enable/Disable the autoscramble function"); - sas_autoscramble_minplayers = CreateConVar("sas_autoscramble_minplayers", "16", "Min players needed to start an autoscramble"); - sas_autoscramble_mode = CreateConVar("sas_autoscramble_mode", "1", "Scramble mode used when autoscrambling"); - sas_autoscramble_winstreak = CreateConVar("sas_autoscramble_winstreak", "5", "Max amount of wins in a row a team can achieve before an autoscramble starts"); - sas_autoscramble_steamroll = CreateConVar("sas_autoscramble_steamroll", "120", "Shortest amount of time a team can win by before an autoscramble starts (seconds)"); - sas_autoscramble_frags = CreateConVar("sas_autoscramble_frags", "1", "Min players needed to start a vote and scramble"); - - /** - Cvars used for voting - */ - sas_vote_enabled = CreateConVar("sas_vote_enabled", "1", "Enable/Disable voting for scramble"); - sas_vote_upcount = CreateConVar("sas_vote_upcount", "5", "Amount of people wanting a scramble before a vote starts. If less than 1 it will be considered a percentage. (ie 0.5 = 50% | 1 = 1 Player | 5 = 5 Players)"); - sas_vote_winpercent = CreateConVar("sas_vote_winpercent", "0.6", "Percentage of votes needed to scramble", _, true, 0.0, true, 1.0); - sas_vote_mode = CreateConVar("sas_vote_mode", "1", "Scramble mode used when a vote results in a scramble"); - sas_vote_minplayers = CreateConVar("sas_vote_minplayers", "16", "Min players needed to start a vote and scramble"); - - /** - Hook the console variables if they change - */ - HookConVarChange(sas_enabled, ConVarSettingsChanged); - HookConVarChange(sas_timer_scrambledelay, ConVarSettingsChanged); - HookConVarChange(sas_admin_immunity_enabled, ConVarSettingsChanged); - HookConVarChange(sas_admin_flag_scramblenow, ConVarSettingsChanged); - HookConVarChange(sas_admin_flag_immunity, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_enabled, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_minplayers, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_mode, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_winstreak, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_steamroll, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_frags, ConVarSettingsChanged); - HookConVarChange(sas_vote_enabled, ConVarSettingsChanged); - HookConVarChange(sas_vote_upcount, ConVarSettingsChanged); - HookConVarChange(sas_vote_winpercent, ConVarSettingsChanged); - HookConVarChange(sas_vote_mode, ConVarSettingsChanged); - HookConVarChange(sas_vote_minplayers, ConVarSettingsChanged); - - /** - Register the command - */ - RegConsoleCmd("sm_scramblenow", Command_ScrambleNow, "sm_scramblenow (mode): Scrambles the teams"); - - /** - Load translations and .cfg file - */ - LoadTranslations ("simpleautoscrambler.phrases"); - AutoExecConfig(true, "plugin.simpleautoscrambler"); - LogAction(0, -1, "[SAS] Simple AutoScrambler is loaded."); -} - -public OnAllPluginsLoaded() -{ - //something -} - -public OnLibraryRemoved(const String:name[]) -{ - //something -} - -public OnConfigsExecuted() -{ - - /** - Load up all the variable defaults - */ - LoadUpVariables(); - - /** - Log our activity - */ - if (g_bIsEnabled) - LogAction(0, -1, "Simple AutoScrambler is ENABLED"); - else - LogAction(0, -1, "Simple AutoScrambler is DISABLED"); -} - -public Action:Command_ScrambleNow(client, args) -{ - - /** - Make sure we are enabled - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the client is authorized to run this command. - */ - if (!SM_IsValidAdmin(client, g_sScrambleNowFlag)) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure it's ok to scramble at this time - */ - if (!OkToScramble) - { - return Plugin_Handled; - } - - /** - Make sure it's ok to scramble at this time - */ - LogAction(0, -1, "[SAS] The scramblenow command was used"); - - /** - Scramble the teams - */ - StartAScramble(); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - -} - -public Action:Timer_ScrambleTeams(Handle:timer, any:mode) -{ - - /** - Make sure it's still ok to scramble - */ - if (!OkToScramble) - { - return Plugin_Handled; - } - - - switch (mode) - { - case - - - - } - - - /** - Reset the handle because the timer is over and the callback is done - */ - g_hScrambleTimer = INVALID_HANDLE; - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - -} - -stock StartAScramble(mode) -{ - - /** - See if we are already started a scramble - */ - if (g_hScrambleTimer == INVALID_HANDLE) - { - - /** - There is a scramble in progress - */ - return; - - } - - /** - Report that a scramble is about to start - */ - PrintCenterTextAll("%T", "Scramble", LANG_SERVER); - - /** - Start a timer and log the action - */ - g_hScrambleTimer = CreateTimer(g_fTimer_ScrambleDelay, Timer_ScrambleTeams, mode, TIMER_FLAG_NO_MAPCHANGE); - LogAction(0, -1, "[SAS] A scamble timer was started"); -} - -stock bool:OkToScramble() -{ - -} - -stock LoadUpVariables() -{ - g_bIsEnabled = GetConVarBool(sas_enabled); - g_bIsAutoScrambleEnabled = GetConVarBool(sas_autoscramble_enabled); - g_bIsVoteEnabled = GetConVarBool(sas_vote_enabled); - g_bIsAdminImmunityEnabled = GetConVarBool(sas_admin_immunity_enabled); - g_iAutoScramble_Minplayers = GetConVarInt(sas_autoscramble_minplayers); - g_iAutoScramble_Mode = GetConVarInt(sas_autoscramble_mode); - g_iAutoScramble_WinStreak = GetConVarInt(sas_autoscramble_winstreak); - g_iAutoScramble_SteamRoll = GetConVarInt(sas_autoscramble_steamroll); - g_iAutoScramble_Frags = GetConVarInt(sas_autoscramble_frags); - g_iVote_Mode = GetConVarInt(sas_vote_mode); - g_iVote_MinPlayers = GetConVarInt(sas_vote_minplayers); - GetConVarString(sas_admin_flag_scramblenow, g_sScrambleNowFlag, sizeof(g_sScrambleNowFlag)); - GetConVarString(sas_admin_flag_immunity, g_sAdminImmunityFlag, sizeof(g_sAdminImmunityFlag)); - g_fTimer_ScrambleDelay = GetConVarFloat(sas_timer_scrambledelay); - g_fVote_UpCount = GetConVarFloat(sas_vote_upcount); - g_fVote_WinPercent = GetConVarFloat(sas_vote_winpercent); - g_iMaxEntities = GetMaxEntities(); - g_iOwnerOffset = FindSendPropInfo("CBaseObject", "m_hBuilder"); -} - -stock TF2_DestroyBuildings(client) -{ - - /** - We have to start a loop to check the owner of all the valid entities - */ - for (new i = MaxClients + 1; i <= g_iMaxEntities; i++) - { - if (!IsValidEntity(i)) - { - - /** - Not valid, continue to next one - */ - continue; - } - - /** - Get the name of the current entity - */ - decl String:sNetClass[32]; - GetEntityNetClass(i, sNetClass, sizeof(sNetClass)); - - /** - See if its something that an engineer would build - */ - if (strcmp(sNetClass, "CObjectSentrygun") == 0 - || strcmp(sNetClass, "CObjectTeleporter") == 0 - || strcmp(sNetClass, "CObjectDispenser") == 0) - { - - /** - It is, so lets check the owner - */ - if (GetEntDataEnt2(i, g_iOwnerOffset) == client) - { - - /** - It's the clients building, so we blow it up. - */ - SetVariantInt(9999); - AcceptEntityInput(i, "RemoveHealth"); - } - } - } -} \ No newline at end of file diff --git a/Simple Round Immunity/addons/sourcemod/scripting/simple-chatcolors.sp b/Simple Round Immunity/addons/sourcemod/scripting/simple-chatcolors.sp deleted file mode 100644 index 539d057..0000000 --- a/Simple Round Immunity/addons/sourcemod/scripting/simple-chatcolors.sp +++ /dev/null @@ -1,496 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Chat Colors -Description: - Changes the colors of players chat based on config file -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#pragma semicolon 1 -#include -#include - -#define PLUGIN_VERSION "0.9.0.$Rev$" - -#define CHAT_SYMBOL '@' -#define TRIGGER_SYMBOL1 '!' -#define TRIGGER_SYMBOL2 '/' -#define CHAT_MAX_MESSAGE_LENGTH 1024 - -new Handle:g_hDebugCvar = INVALID_HANDLE; -new Handle:g_aGroupNames = INVALID_HANDLE; -new Handle:g_aGroupFlag = INVALID_HANDLE; -new Handle:g_aGroupNameColor = INVALID_HANDLE; -new Handle:g_aGroupTextColor = INVALID_HANDLE; - -new bool:g_bDebug = false; - -new g_iArraySize; - -new g_aPlayerColorIndex[MAXPLAYERS + 1] = { -1, ... }; - -public Plugin:myinfo = -{ - name = "Simple Chat Colors", - author = "Simple Plugins", - description = "Changes the colors of players chat based on config file.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -/** -Sourcemod callbacks -*/ -public OnPluginStart() -{ - - /** - Need to create all of our console variables. - */ - CreateConVar("sm_chatcolors_version", PLUGIN_VERSION, "Simple Chat Colors", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - g_hDebugCvar = CreateConVar("sm_chatcolors_debug", "1", "Enable/Disable debugging information"); - - /** - Hook console variables - */ - HookConVarChange(g_hDebugCvar, ConVarSettingsChanged); - - /** - Need to register the commands we are going to use - */ - RegConsoleCmd("say", Command_Say); - RegConsoleCmd("say_team", Command_SayTeam); - RegAdminCmd("sm_reloadcolorsconfig", Command_Reload, ADMFLAG_GENERIC, "Reloads settings from config file"); - - /** - Create the arrays - */ - g_aGroupNames = CreateArray(256, 1); - g_aGroupFlag = CreateArray(15, 1); - g_aGroupNameColor = CreateArray(15, 1); - g_aGroupTextColor = CreateArray(15, 1); - - /** - Load the admins and colors from the config - */ - LoadAdminsAndColorsFromConfig(); - g_iArraySize = GetArraySize(g_aGroupNames); -} - -public OnConfigsExecuted() -{ - g_bDebug = GetConVarBool(g_hDebugCvar); - ReloadConfigFile(); -} - -public OnClientPostAdminCheck(client) -{ - - /** - Check the client to see if they are a admin - */ - CheckAdmin(client); -} - -public OnClientDisconnect(client) -{ - g_aPlayerColorIndex[client] = -1; -} - -/** -Commands -*/ -public Action:Command_Say(client, args) -{ - - /** - Make sure we are enabled. - */ - if (client == 0 || IsChatTrigger()) - { - return Plugin_Continue; - } - - if (g_aPlayerColorIndex[client] != -1) - { - - /** - The client is, so get the chat message and strip it down. - */ - decl String:sArg[CHAT_MAX_MESSAGE_LENGTH], - String:sChatMsg[CHAT_MAX_MESSAGE_LENGTH]; - - new bool:bAlive = IsPlayerAlive(client); - - GetCmdArgString(sArg, sizeof(sArg)); - StripQuotes(sArg); - TrimString(sArg); - new startidx; - if (sArg[strlen(sArg)-1] == '"') - { - sArg[strlen(sArg)-1] = '\0'; - startidx = 1; - } - - /** - Bug out if they are using the admin chat symbol (admin chat). If we are in CSS it may not find all the triggers, so we double check. - */ - if (sArg[startidx] == CHAT_SYMBOL || sArg[startidx] == TRIGGER_SYMBOL1 || sArg[startidx] == TRIGGER_SYMBOL2) - { - return Plugin_Continue; - } - - /** - Log the message for hlstatsx and other things. - */ - new iUserID = GetClientUserId(client); - decl String:sAuthID[64]; - GetClientAuthString(client, sAuthID, sizeof(sAuthID)); - LogToGame("\"%N<%i><%s><>\" say \"%s\"", client, iUserID, sAuthID, sArg); - - /** - Format the message. - */ - FormatMessage(client, 0, bAlive, sChatMsg, sArg, g_aPlayerColorIndex[client]); - - /** - Send the message. - */ - //SayText2(0, client, sChatMsg); - CPrintToChatAll(sChatMsg); - - /** - We are done, bug out, and stop the original chat message. - */ - return Plugin_Stop; - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Command_SayTeam(client, args) -{ - - /** - Make sure we are enabled. - */ - if (client == 0 || IsChatTrigger()) - { - return Plugin_Continue; - } - - /** - Check the client to see if they are a admin - */ - if (g_aPlayerColorIndex[client] != -1) - { - - /** - The client is, so get the chat message and strip it down. - */ - decl String:sArg[CHAT_MAX_MESSAGE_LENGTH], - String:sChatMsg[CHAT_MAX_MESSAGE_LENGTH]; - - new bool:bAlive = IsPlayerAlive(client); - new iCurrentTeam = GetClientTeam(client); - - GetCmdArgString(sArg, sizeof(sArg)); - StripQuotes(sArg); - TrimString(sArg); - new startidx; - if (sArg[strlen(sArg)-1] == '"') - { - sArg[strlen(sArg)-1] = '\0'; - startidx = 1; - } - - /** - Bug out if they are using the admin chat symbol (admin chat). - */ - if (sArg[startidx] == CHAT_SYMBOL || sArg[startidx] == TRIGGER_SYMBOL1 || sArg[startidx] == TRIGGER_SYMBOL2) - { - return Plugin_Continue; - } - - /** - Log the message for hlstatsx and other things. - */ - new iUserID = GetClientUserId(client); - decl String:sAuthID[64]; - GetClientAuthString(client, sAuthID, sizeof(sAuthID)); - LogToGame("\"%N<%i><%s><>\" say_team \"%s\"", client, iUserID, sAuthID, sArg); - - /** - Format the message. - */ - FormatMessage(client, iCurrentTeam, bAlive, sChatMsg, sArg, g_aPlayerColorIndex[client]); - - /** - Send the message to the same team - */ - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == iCurrentTeam) - { - CPrintToChat(client, sChatMsg); - } - } - - /** - We are done, bug out, and stop the original chat message. - */ - return Plugin_Stop; - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Command_Reload(client, args) -{ - ReloadConfigFile(); - return Plugin_Handled; -} - -/** -Stock Functions -*/ -stock LoadAdminsAndColorsFromConfig() -{ - - /** - Make sure the config file is here and load it up - */ - new String:sConfigFile[256]; - BuildPath(Path_SM, sConfigFile, sizeof(sConfigFile), "configs/simple-chatcolors.cfg"); - if (!FileExists(sConfigFile)) - { - - /** - Config file doesn't exists, stop the plugin - */ - LogError("[SCC] Simple Chat Colors is not running! Could not find file %s", sConfigFile); - SetFailState("Could not find file %s", sConfigFile); - } - - /** - Create the arrays and variables - */ - new String:sGroupName[256]; - new String:sGroupFlag[15]; - new String:sGroupNameColor[15]; - new String:sGroupTextColor[15]; - - - /** - Load config file as a KeyValues file - */ - new Handle:kvChatColors = CreateKeyValues("admin_colors"); - FileToKeyValues(kvChatColors, sConfigFile); - - if (!KvGotoFirstSubKey(kvChatColors)) - { - return; - } - - /** - Load up all the groups in the file - */ - do - { - - /** - Get the section name; should be the "group" name - */ - KvGetSectionName(kvChatColors, sGroupName, sizeof(sGroupName)); - - - /** - Get the flags and colors - */ - KvGetString(kvChatColors, "flag", sGroupFlag, sizeof(sGroupFlag)); - KvGetString(kvChatColors, "namecolor", sGroupNameColor, sizeof(sGroupNameColor)); - KvGetString(kvChatColors, "textcolor", sGroupTextColor, sizeof(sGroupTextColor)); - - if (g_bDebug) - { - LogMessage("Group Name/SteamID: %s", sGroupName); - LogMessage("Flag String: %s", sGroupFlag); - LogMessage("Color on name: %s", sGroupNameColor); - LogMessage("Color of text: %s", sGroupTextColor); - } - - /** - Push the values to the arrays - */ - PushArrayString(g_aGroupNames, sGroupName); - PushArrayString(g_aGroupFlag, sGroupFlag); - PushArrayString(g_aGroupNameColor, sGroupNameColor); - PushArrayString(g_aGroupTextColor, sGroupTextColor); - } while (KvGotoNextKey(kvChatColors)); - - /** - Close our handle - */ - CloseHandle(kvChatColors); -} - -stock ReloadConfigFile() -{ - - /** - Clear the array - */ - ClearArray(g_aGroupNames); - ClearArray(g_aGroupFlag); - ClearArray(g_aGroupNameColor); - ClearArray(g_aGroupTextColor); - - /** - Load the admins, groups, and colors from the config - */ - LoadAdminsAndColorsFromConfig(); - g_iArraySize = GetArraySize(g_aGroupNames); - - /** - Recheck all the online players for assigned colors - */ - for (new index = 1; index <= MaxClients; index++) - { - if (IsClientConnected(index) && IsClientInGame(index)) - { - CheckAdmin(index); - } - } -} - -stock CheckAdmin(client) -{ - new String:sFlags[15]; - new String:sClientSteamID[64]; - new iGroupFlags; - new iFlags; - new iIndex = -1; - - /** - Look for a steamid first - */ - GetClientAuthString(client, sClientSteamID, sizeof(sClientSteamID)); - iIndex = FindStringInArray(g_aGroupNames, sClientSteamID); - if (iIndex != -1) - { - g_aPlayerColorIndex[client] = iIndex; - } - - /** - Didn't find one, check flags - */ - else - { - /** - Search for flag in groups - */ - - iFlags = GetUserFlagBits(client); - for (iIndex = 0; iIndex < g_iArraySize; iIndex++) - { - GetArrayString(g_aGroupFlag, iIndex, sFlags, sizeof(sFlags)); - iGroupFlags = ReadFlagString(sFlags); - if (iFlags & iGroupFlags) - { - g_aPlayerColorIndex[client] = iIndex; - break; - } - } - } - - if (g_bDebug) - { - PrintToChatAll("SteamID: %s", sClientSteamID); - PrintToChatAll("Array Index: %i", iIndex); - PrintToChatAll("Flag String: %s", sFlags); - PrintToChatAll("Flag Bits of Client: %i", iFlags); - PrintToChatAll("Flag Bits of Group: %i", iGroupFlags); - } -} - -stock FormatMessage(iClient, iTeam, bool:bAlive, String:sChatMsg[], const Sting:sMessage[], iArrayIndex) -{ - decl String:sDead[10], - String:sTeam[10], - String:sClientName[64]; - - GetClientName(iClient, sClientName, sizeof(sClientName)); - - if (iTeam != 0) - { - Format(sTeam, sizeof(sTeam), "(TEAM) "); - } - else - { - Format(sTeam, sizeof(sTeam), ""); - } - if (bAlive) - { - Format(sDead, sizeof(sDead), ""); - } - else - { - Format(sDead, sizeof(sDead), "*DEAD* "); - } - - new String:sNameColor[15]; - new String:sTextColor[15]; - GetArrayString(g_aGroupNameColor, iArrayIndex, sNameColor, sizeof(sNameColor)); - GetArrayString(g_aGroupTextColor, iArrayIndex, sTextColor, sizeof(sTextColor)); - - Format(sChatMsg, CHAT_MAX_MESSAGE_LENGTH, "{default}%s%s%s%s {default}: %s%s", sDead, sTeam, sNameColor, sClientName, sTextColor, sMessage); -} - -/** -Adjust the settings if a convar was changed -*/ -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (StringToInt(newValue) == 1) - { - g_bDebug = true; - } - else - { - g_bDebug = false; - } -} \ No newline at end of file diff --git a/Simple Round Immunity/addons/sourcemod/scripting/simple-donatorbenefits.sp b/Simple Round Immunity/addons/sourcemod/scripting/simple-donatorbenefits.sp deleted file mode 100644 index e3f6845..0000000 --- a/Simple Round Immunity/addons/sourcemod/scripting/simple-donatorbenefits.sp +++ /dev/null @@ -1,1312 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Donator Benefits -Description: - Provides donator benefits to players -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include -#include - -#define PLUGIN_VERSION "1.1.$Rev$" - -#define CHAT_SYMBOL '@' -#define CHAT_MAX_MESSAGE_LENGTH 1024 - -enum PlayerData -{ - bool:bIsDonator, - bool:bQueue, - bool:bImmune, - iHealthCount, - iNewTeam -}; - -/** - Public convar handles - */ -new Handle:sdb_enabled = INVALID_HANDLE; -new Handle:sdb_donationflag = INVALID_HANDLE; -new Handle:sdb_soundfile = INVALID_HANDLE; -new Handle:sdb_joinsound_enabled = INVALID_HANDLE; -new Handle:sdb_joinpubmsg_enabled = INVALID_HANDLE; -new Handle:sdb_joinprivmsg_enabled = INVALID_HANDLE; -new Handle:sdb_chatcolors_enabled = INVALID_HANDLE; -new Handle:sdb_immunity_enabled = INVALID_HANDLE; -new Handle:sdb_ubercharge_enabled = INVALID_HANDLE; -new Handle:sdb_givehealth_enabled = INVALID_HANDLE; -new Handle:sdb_nofalldmg_enabled = INVALID_HANDLE; -new Handle:sdb_fastheavy_enabled = INVALID_HANDLE; -new Handle:sdb_swapteam_enabled = INVALID_HANDLE; -new Handle:sdb_chatcolor = INVALID_HANDLE; -new Handle:sdb_uberlevel = INVALID_HANDLE; -new Handle:sdb_healthcount = INVALID_HANDLE; -new Handle:sdb_healthbonus = INVALID_HANDLE; -new Handle:sdb_heavymultiplier = INVALID_HANDLE; - -/** -Create global enable/disable bools so we don't have to check the console variable on every call -*/ -new bool:g_bIsEnabled = true; -new bool:g_bIsJoinSoundEnabled = true; -new bool:g_bIsJoinPubMsgEnabled = true; -new bool:g_bIsJoinPrivMsgEnabled = true; -new bool:g_bIsChatColorsEnabled = true; -new bool:g_bIsImmuntyEnabled = true; -new bool:g_bIsUberChargeEnabled = true; -new bool:g_bIsGiveHealthEnabled = true; -new bool:g_bIsNoFallDmgEnabled = true; -new bool:g_bIsFastHeayEnabled = true; -new bool:g_bIsSwapTeamEnabled = true; - -/** - Player arrays - */ -new g_aPlayers[MAXPLAYERS + 1][PlayerData]; - - -/** -Rest of the globals -*/ -new bool:g_bRoundEnd = false; -new String:g_sCharDonatorFlag[5]; -new String:g_sSoundFile[PLATFORM_MAX_PATH]; -new String:g_sChatColor[11]; -new g_iHealthBonus; -new g_iHealthCount; -new g_iClassMaxHealth[TFClassType] = {0, 125, 125, 200, 175, 150, 300, 175, 125, 125}; -new g_fClassMaxSpeed[TFClassType] = {0, 400, 300, 240, 280, 320, 230, 300, 300, 300}; -new Float:g_fHeavyMultiplier = 0.0; -new Float:g_fUberLevel = 0.0; - -public Plugin:myinfo = -{ - name = "Simple Donation Benefits", - author = "Simple Plugins", - description = "Gives donators benefits to players", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -} - -public OnPluginStart() -{ - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[SDB] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_connect", HookPlayerSpawn, EventHookMode_Pre); - HookEvent("player_spawn", HookPlayerSpawn, EventHookMode_Post); - HookEvent("player_death", HookPlayerDeath, EventHookMode_Post); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Post); - switch (g_CurrentMod) - { - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - HookEvent("player_changeclass", HookPlayerClass, EventHookMode_Post); - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_Post); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - - /** - Create console variables - */ - CreateConVar("sdb_version", PLUGIN_VERSION, "Simple Donation Benefits", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - sdb_enabled = CreateConVar("sdb_enabled", "1", "Enable/Disable Simple Donation Benefits"); - sdb_donationflag = CreateConVar("sdb_donationflag", "a", "Flag ALREADY given to donators. Must be in char format"); - - /** - Create the enable/disable donator console variables - */ - sdb_joinsound_enabled = CreateConVar("sdb_joinsound_enabled", "1", "Enable/Disable donator join sound"); - sdb_joinpubmsg_enabled = CreateConVar("sdb_joinpubmsg_enabled", "1", "Enable/Disable public donator join message (replaces: as connected)"); - sdb_joinprivmsg_enabled = CreateConVar("sdb_joinprivmsg_enabled", "1", "Enable/Disable private donator join message (sent only to donator)"); - sdb_chatcolors_enabled = CreateConVar("sdb_chatcolors_enabled", "1", "Enable/Disable donator chat colors"); - sdb_immunity_enabled = CreateConVar("sdb_immunity_enabled", "1", "Enable/Disable donator round end immunity"); - sdb_ubercharge_enabled = CreateConVar("sdb_ubercharge_enabled", "1", "Enable/Disable donator medics starting with ubercharge"); - sdb_givehealth_enabled = CreateConVar("sdb_givehealth_enabled", "1", "Enable/Disable donator instant health bonus"); - sdb_nofalldmg_enabled = CreateConVar("sdb_nofalldmg_enabled", "1", "Enable/Disable no fall damage for donators"); - sdb_fastheavy_enabled = CreateConVar("sdb_fastheavy_enabled", "1", "Enable/Disable donator heavies moving faster while spinning"); - sdb_swapteam_enabled = CreateConVar("sdb_swampteam_enabled", "1", "Enable/Disable donator swap team ability"); - - /** - Create the donator setting console variables - */ - sdb_soundfile = CreateConVar("sdb_soundfile", "custom/donatorjoin.mp3", "The location of sound file"); - sdb_chatcolor = CreateConVar("sdb_chatcolor", "green", "Color to use for donator chat. Valid colors are green and lightgreen"); - sdb_uberlevel = CreateConVar("sdb_uberlevel", "0.5", "Uberlevel to give donator medic at spawn. 1.0 = full uber", _, true, 0.0, true, 1.0); - sdb_healthcount = CreateConVar("sdb_healthcount", "1", "Number of times a donator can use use instant health per life"); - sdb_healthbonus = CreateConVar("sdb_healthbonus", "100", "The amount of health to heal the donator"); - sdb_heavymultiplier = CreateConVar("sdb_heavyspeed", "0.5", "The speed multiplier for the fast heavy. Based on running speed. 1.0 = running speed. (Game Default is 0.20)", _, true, 0.0, true, 1.0); - - /** - Hook dukehacks calls - */ - dhAddClientHook(CHK_TakeDamage, Hacks_TakeDamageHook); - dhAddClientHook(CHK_PreThink, Hacks_PreThinkHook); - - /** - Hook the console variables if they change - */ - HookConVarChange(sdb_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_donationflag, ConVarSettingsChanged); - HookConVarChange(sdb_joinsound_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_joinpubmsg_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_joinprivmsg_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_chatcolors_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_immunity_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_ubercharge_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_givehealth_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_nofalldmg_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_swapteam_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_fastheavy_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_soundfile, ConVarSettingsChanged); - HookConVarChange(sdb_chatcolor, ConVarSettingsChanged); - HookConVarChange(sdb_uberlevel, ConVarSettingsChanged); - HookConVarChange(sdb_healthcount, ConVarSettingsChanged); - HookConVarChange(sdb_healthbonus, ConVarSettingsChanged); - HookConVarChange(sdb_heavymultiplier, ConVarSettingsChanged); - - /** - Register the commands - */ - RegConsoleCmd("sm_swapteams", Command_SwapTeam, "sm_swapteams <[0]instant/[1]queued>: Swaps your team to the other team"); - RegConsoleCmd("sm_ihealth", Command_InstantHealth, "sm_ihealth: Gives you a instant health pack"); - RegAdminCmd("sm_teaser", Command_Teaser, ADMFLAG_GENERIC,"sm_teaser <[0]add/[1]remove>: Gives temporary donator privilages to a player"); - RegConsoleCmd("say", Command_Say); - - RegConsoleCmd("sm_test", Command_TEST); - - /** - Load the translations - */ - LoadTranslations("common.phrases"); - LoadTranslations("simpledonatorbenefits.phrases"); - - /** - Load or create the config file - */ - AutoExecConfig(true, "plugin.simpledonatorbenefits"); - LogAction(0, -1, "[SDB] Simple Donator Benefits is loaded."); -} - -public OnAllPluginsLoaded() -{ - //something -} - -public OnLibraryRemoved(const String:name[]) -{ - //something -} - -public OnConfigsExecuted() -{ - /** - Load up all the variable defaults - */ - LoadUpVariables(); - - /** - If the join sound is enabled, prep the sound files - */ - if (g_bIsJoinSoundEnabled) - PrepSoundFile(); - - /** - Log our activity - */ - if (g_bIsEnabled) - LogAction(0, -1, "Simple Donation Benefits is ENABLED"); - else - LogAction(0, -1, "Simple Donation Benefits is DISABLED"); -} - -public OnClientPostAdminCheck(client) -{ - - /** - Check if the client is a donator - */ - if (SM_IsValidAdmin(client, g_sCharDonatorFlag)) - { - - /** - They are, so we set the player array to true and start a timer for the sound or add - */ - g_aPlayers[client][bIsDonator] = true; - if (g_bIsJoinSoundEnabled || g_bIsJoinPrivMsgEnabled) - { - CreateTimer(10.0, Timer_DonatorJoined, client, TIMER_FLAG_NO_MAPCHANGE); - } - } - else - { - /** - They aren't, so we set the player array to false - */ - g_aPlayers[client][bIsDonator] = false; - } -} - -public OnClientDisconnect_Post(client) -{ - - /** - Clean up the player variables - */ - CleanUpPlayer(client); -} - -public Action:Command_SwapTeam(client, args) -{ - - /** - Make sure we are enabled - */ - if (!g_bIsEnabled || !g_bIsSwapTeamEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the command is not started by the server - */ - if (client == 0) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure the player is a donator - */ - if (!g_aPlayers[client][bIsDonator]) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Lets make sure the client is one a team we can swap. - If he is we set the global array to the opposite team. - */ - new iTeam = GetClientTeam(client); - if (iTeam == g_aCurrentTeams[Team1]) - { - g_aPlayers[client][iNewTeam] = g_aCurrentTeams[Team2]; - } - else if (iTeam == g_aCurrentTeams[Team2]) - { - g_aPlayers[client][iNewTeam] = g_aCurrentTeams[Team1]; - } - else - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "InValidTeam", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check to see if we have command arguments. - */ - if (GetCmdArgs()) - { - - /** - We do, so lets get it and see if the client wants to be switched instantly or queued for death. - */ - decl String:sArg[5]; - GetCmdArg(1, sArg, sizeof(sArg)); - new iWantsQue = StringToInt(sArg); - if (iWantsQue && !g_aPlayers[client][bQueue]) - { - - /** - He wants the que and isn't already in it, set the global array. - */ - g_aPlayers[client][bQueue] = true; - ReplyToCommand(client, "\x01\x04[STM]\x01 %T", "PlayerQueue", LANG_SERVER); - } - else if (!iWantsQue) - { - - /** - He wants to be switched right now, lets call the stock function. - */ - SM_MovePlayer(client, g_aPlayers[client][iNewTeam]); - } - } - else - { - - /** - There are no command arguments so we build and display the swap menu. - */ - new Handle:hPlayerMenu = BuildSwapModeMenu(); - DisplayMenu(hPlayerMenu, client, MENU_TIME_FOREVER); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_InstantHealth(client, args) -{ - - /** - Make sure we are enabled - */ - if (!g_bIsEnabled || !g_bIsGiveHealthEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the command is not started by the server - */ - if (client == 0) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure the player is a donator - */ - if (!g_aPlayers[client][bIsDonator]) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check health count to see if the player has reached the max - */ - if (g_aPlayers[client][iHealthCount] >= g_iHealthCount) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "ReachedCount", LANG_SERVER); - return Plugin_Handled; - } - - /** - Get the class of the player and the max health for that class - */ - new iHealth = GetClientHealth(client); - new TFClassType:PlayerClass = TF2_GetPlayerClass(client); - new iMaxHealth = g_iClassMaxHealth[PlayerClass]; - - /** - Check to see if the player is at the max health of the class - */ - if (iHealth >= iMaxHealth) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "AtMaxHealth", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check the current health - */ - if (iHealth + g_iHealthBonus >= iMaxHealth) - { - - /** - Raise them to max health if the current health + bonus would go above it - */ - SetEntityHealth(client, iMaxHealth); - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "ToMaxHealth", LANG_SERVER); - } - else - { - - /** - Give them the instant health bonus - */ - SetEntityHealth(client, iHealth + g_iHealthBonus); - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "HealthBonus", LANG_SERVER); - } - - /** - Increase the count - */ - g_aPlayers[client][iHealthCount] += 1; - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_Teaser(client, args) -{ - - /** - Make sure we are enabled - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Check to see if we have command arguments. - */ - new iCmdArgs = GetCmdArgs(); - if (iCmdArgs == 0) - { - - /** - We don't so display the player menu. - */ - new Handle:hPlayerMenu = BuildPlayerMenu(); - DisplayMenu(hPlayerMenu, client, MENU_TIME_FOREVER); - return Plugin_Handled; - } - - /** - We have some arguments, see if we can find the player - */ - decl String:sPlayer[64]; - GetCmdArg(1, sPlayer, sizeof(sPlayer)); - new iTarget = FindTarget(client, sPlayer, true, true); - if (iTarget == -1 || !IsClientInGame(iTarget)) - { - - /** - We don't know who this is, so display the player menu. - */ - new Handle:hPlayerMenu = BuildPlayerMenu(); - DisplayMenu(hPlayerMenu, client, MENU_TIME_FOREVER); - } - else - { - /** - We found the player, see if we are supposed to turn it on or off. - */ - if (iCmdArgs >= 2) - { - decl String:sOn[3]; - GetCmdArg(2, sOn, sizeof(sOn)); - if (StringToInt(sOn)) - { - - /** - Turn temp benefits on. - */ - g_aPlayers[iTarget][bIsDonator] = true; - } - else - { - - /** - Turn temp benefits on. - */ - g_aPlayers[iTarget][bIsDonator] = false; - } - } - else - { - - /** - We don't know what to do, so just turn it on. - */ - g_aPlayers[iTarget][bIsDonator] = true; - } - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_Say(client, args) -{ - - /** - Make sure we are enabled. - */ - if (client == 0 || IsChatTrigger() || !g_bIsChatColorsEnabled || !g_bIsEnabled) - { - return Plugin_Continue; - } - - /** - Check the client to see if they are a donator. - */ - if (g_aPlayers[client][bIsDonator]) - { - - /** - The client is, so get the chat message and strip it down. - */ - decl String:sArg[CHAT_MAX_MESSAGE_LENGTH], - String:sChatMsg[CHAT_MAX_MESSAGE_LENGTH]; - new bool:bAlive = IsPlayerAlive(client); - GetCmdArgString(sArg, sizeof(sArg)); - StripQuotes(sArg); - TrimString(sArg); - new startidx; - if (sArg[strlen(sArg)-1] == '"') - { - sArg[strlen(sArg)-1] = '\0'; - startidx = 1; - } - - /** - Bug out if they are using the admin chat symbol (admin chat). - */ - if (sArg[startidx] == CHAT_SYMBOL) - { - return Plugin_Continue; - } - - /** - Format the message. - */ - FormatMessage(client, 0, bAlive, sChatMsg, sArg); - - /** - Send the message. - */ - SayText2(0, client, sChatMsg); - - /** - We are done, bug out, and stop the original chat message. - */ - return Plugin_Stop; - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Hacks_TakeDamageHook(client, attacker, inflictor, Float:damage, &Float:multiplier, damagetype) -{ - - /** - Make sure we are enabled and the client is a donator. - */ - if (g_bIsEnabled && g_bIsNoFallDmgEnabled && g_aPlayers[client][bIsDonator]) - { - - /** - Check for fall damage. - */ - if (damagetype & DMG_FALL) - { - - /** - Cancel the fall damage and bug out. - */ - multiplier *= 0.0; - return Plugin_Changed; - } - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Hacks_PreThinkHook(client) -{ - - /** - Make sure we are enabled and the client is a donator. - */ - if (!g_bIsEnabled || !g_bIsFastHeayEnabled || !g_aPlayers[client][bIsDonator]) - { - return Plugin_Continue; - } - - /** - Check the players class. We are looking for the heavy. - */ - new TFClassType:PlayerClass = TF2_GetPlayerClass(client); - if (PlayerClass == TFClass_Heavy) - { - - /** - We have a heavy, lets check the weapon. - */ - decl String:sWeaponCurrent[64]; - GetClientWeapon(client, sWeaponCurrent, sizeof(sWeaponCurrent)); - if (StrEqual(sWeaponCurrent, "tf_weapon_minigun", false)) - { - - /** - We have a minigun, check the heavies current weapon state to see if it's spinning. - */ - new iWeapon = GetPlayerWeaponSlot(client, 0); - new iWeaponState = GetEntProp(iWeapon, Prop_Send, "m_iWeaponState"); - if (iWeaponState > 0) - { - - /** - He is spinning, so lets change the heavies speed. - */ - new Float:fMaxSpeed = FloatMul(g_fHeavyMultiplier, float(g_fClassMaxSpeed[PlayerClass])); - SetEntPropFloat(client, Prop_Send, "m_flMaxspeed", fMaxSpeed); - } - } - } - - /** - We are done, bug out. - */ - // use Plugin_Continue (other options are ignored on PreThink hook) - return Plugin_Continue; -} - -public Action:HookPlayerConnect(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (!g_bIsEnabled || !g_bIsJoinPubMsgEnabled || !dontBroadcast) - { - return Plugin_Continue; - } - - /** - Get our event variables and check the client. - */ - new iUserId = GetEventInt(event,"userid"); - new iClient = GetClientOfUserId(iUserId); - if (iClient != 0) - { - - /** - Get the info on the client and format the message. - */ - decl String:sClientName[255], - String:sAuthID[255], - String:sMsg[1024]; - - GetEventString(event, "name", sClientName, sizeof(sClientName)); - GetClientAuthString(iClient, sAuthID, sizeof(sAuthID)); - Format(sMsg, sizeof(sMsg), "%T", "PublicJoinMessage", LANG_SERVER, sClientName); - - /** - Print the message to the clients and do the normal functions. - */ - for (new i = 1; i <= MaxClients; i++) - { - if(IsClientConnected(i) && IsClientInGame(i)) - { - PrintToChat(i,"\x01\x05%s", sMsg); - PrintToConsole(i,"%s has connected.", sClientName); - } - } - LogToGame("\"%s<%d><%s><>\" entered the game", sClientName, iUserId, sAuthID); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public HookPlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled && g_bIsUberChargeEnabled) - { - - /** - Get the event variables and check the class for medic - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - if (TF2_GetPlayerClass(iClient) == TFClass_Medic) - { - - /** - Start a timer to get the medic the uber boost - */ - CreateTimer(0.25, Timer_PlayerUberDelay, iClient, TIMER_FLAG_NO_MAPCHANGE); - } - } -} - -public HookPlayerClass(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled && g_bIsUberChargeEnabled) - { - - /** - Get the event variables and check the class for medic - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - if (TF2_GetPlayerClass(iClient) == TFClass_Medic) - { - - /** - Start a timer to get the medic the uber boost - */ - CreateTimer(0.25, Timer_PlayerUberDelay, iClient, TIMER_FLAG_NO_MAPCHANGE); - } - } -} - -public HookPlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled || g_bIsSwapTeamEnabled) - { - - /** - Get the event variables - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - new String:sWeapon[256]; - GetEventString(event, "weapon", sWeapon, sizeof(sWeapon)); - - /** - Bug out if world killed him. Means he changed team or something - */ - if (StrEqual(sWeapon, "world", false)) - { - g_aPlayers[iClient][bQueue] = false; - return; - } - - /** - If he is queued up, swap him - */ - if (g_aPlayers[iClient][bQueue]) - { - SM_MovePlayer(iClient, g_aPlayers[iClient][iNewTeam]); - } - } -} - -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled || g_bIsSwapTeamEnabled) - { - - /** - Get the event variables - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - - /** - If he is queued up, clear the status - */ - if (g_aPlayers[iClient][bQueue]) - { - g_aPlayers[iClient][bQueue] = false; - } - } -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set our variables. - */ - g_bRoundEnd = false; - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled && g_bIsImmuntyEnabled) - { - - /** - Get rid of their immunity. - */ - ProcessRoundEndImmunity(false); - } -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set our variables. - */ - g_bRoundEnd = true; - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled && g_bIsImmuntyEnabled) - { - - /** - Give them their immunity. - */ - ProcessRoundEndImmunity(true); - } -} - -public Action:Timer_DonatorJoined(Handle:timer, any:client) -{ - - /** - Make sure sounds are enabled. - */ - if (g_bIsEnabled && g_bIsJoinSoundEnabled) - { - EmitSoundToClient(client, g_sSoundFile); - } - - /** - Make sure private messages are enabled. - */ - if (g_bIsJoinPrivMsgEnabled) - { - - /** - Send messages to the client. - */ - decl String:sMsg[1024]; - Format(sMsg, sizeof(sMsg), "%T", "PrivateJoinMessage", LANG_SERVER); - PrintToChat(client,"\x01\x05%s", sMsg); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Timer_PlayerUberDelay(Handle:timer, any:client) -{ - - /** - Make sure the client is still in game. - */ - if (IsClientInGame(client)) - { - - /** - Make sure the client is still a medic. - */ - if (TF2_GetPlayerClass(client) == TFClass_Medic) - { - - /** - Get the medgun weapon index - */ - new iIndex = GetPlayerWeaponSlot(client, 1); - if (iIndex > 0) - { - - /** - Set the uber level with the bonus. - */ - SetEntPropFloat(iIndex, Prop_Send, "m_flChargeLevel", g_fUberLevel); - } - } - } -} - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (convar == sdb_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsEnabled = false; - } - else - { - g_bIsEnabled = true; - } - } - else if (convar == sdb_donationflag) - { - Format(g_sCharDonatorFlag, sizeof(g_sCharDonatorFlag), "%s", newValue); - } - else if (convar == sdb_soundfile) - { - Format(g_sSoundFile, sizeof(g_sSoundFile), "%s", newValue); - } - else if (convar == sdb_joinsound_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsJoinSoundEnabled = false; - } - else - { - g_bIsJoinSoundEnabled = true; - } - } - else if (convar == sdb_joinpubmsg_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsJoinPubMsgEnabled = false; - } - else - { - g_bIsJoinPubMsgEnabled = true; - } - } - else if (convar == sdb_joinprivmsg_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsJoinPrivMsgEnabled = false; - } - else - { - g_bIsJoinPrivMsgEnabled = true; - } - } - else if (convar == sdb_chatcolors_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsChatColorsEnabled = false; - } - else - { - g_bIsChatColorsEnabled = true; - } - } - else if (convar == sdb_immunity_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsImmuntyEnabled = false; - } - else - { - g_bIsImmuntyEnabled = true; - } - } - else if (convar == sdb_ubercharge_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsUberChargeEnabled = false; - } - else - { - g_bIsUberChargeEnabled = true; - } - } - else if (convar == sdb_givehealth_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsGiveHealthEnabled = false; - } - else - { - g_bIsGiveHealthEnabled = true; - } - } - else if (convar == sdb_nofalldmg_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsNoFallDmgEnabled = false; - } - else - { - g_bIsNoFallDmgEnabled = true; - } - } - else if (convar == sdb_fastheavy_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsFastHeayEnabled = false; - } - else - { - g_bIsFastHeayEnabled = true; - } - } - else if (convar == sdb_swapteam_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsSwapTeamEnabled = false; - } - else - { - g_bIsSwapTeamEnabled = true; - } - } - else if (convar == sdb_chatcolor) - { - Format(g_sChatColor, sizeof(g_sChatColor), "%s", newValue); - } - else if (convar == sdb_uberlevel) - { - g_fUberLevel = StringToFloat(newValue); - } - else if (convar == sdb_healthcount) - { - g_iHealthCount = StringToInt(newValue); - } - else if (convar == sdb_healthbonus) - { - g_iHealthBonus = StringToInt(newValue); - } - else if (convar == sdb_heavymultiplier) - { - g_fHeavyMultiplier = StringToFloat(newValue); - } -} - -stock LoadUpVariables() -{ - g_bIsEnabled = GetConVarBool(sdb_enabled); - g_bIsJoinSoundEnabled = GetConVarBool(sdb_enabled); - g_bIsJoinPubMsgEnabled = GetConVarBool(sdb_enabled); - g_bIsJoinPrivMsgEnabled = GetConVarBool(sdb_enabled); - g_bIsChatColorsEnabled = GetConVarBool(sdb_enabled); - g_bIsImmuntyEnabled = GetConVarBool(sdb_enabled); - g_bIsUberChargeEnabled = GetConVarBool(sdb_enabled); - g_bIsGiveHealthEnabled = GetConVarBool(sdb_enabled); - g_bIsNoFallDmgEnabled = GetConVarBool(sdb_enabled); - g_bIsFastHeayEnabled = GetConVarBool(sdb_enabled); - g_bIsSwapTeamEnabled = GetConVarBool(sdb_enabled); - GetConVarString(sdb_donationflag, g_sCharDonatorFlag, sizeof(g_sCharDonatorFlag)); - GetConVarString(sdb_soundfile, g_sSoundFile, sizeof(g_sSoundFile)); - GetConVarString(sdb_chatcolor, g_sChatColor, sizeof(g_sChatColor)); - g_bRoundEnd = false; - g_iHealthBonus = GetConVarInt(sdb_healthbonus); - g_iHealthCount = GetConVarInt(sdb_healthcount); - g_fHeavyMultiplier = GetConVarFloat(sdb_heavymultiplier); - g_fUberLevel = GetConVarFloat(sdb_uberlevel); -} - -stock PrepSoundFile() -{ - decl String:buffer[PLATFORM_MAX_PATH]; - PrecacheSound(g_sSoundFile, true); - Format(buffer, sizeof(buffer), "sound/%s", g_sSoundFile); - AddFileToDownloadsTable(buffer); -} - -stock CleanUpPlayer(client) -{ - g_aPlayers[client][bIsDonator] = false; - g_aPlayers[client][bQueue] = false; - g_aPlayers[client][bImmune] = false; - g_aPlayers[client][iNewTeam] = 0; - g_aPlayers[client][iHealthCount] = 0; -} - -stock ProcessRoundEndImmunity(bool:give) -{ - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][bIsDonator]) - { - if (give) - { - SetEntProp(i, Prop_Data, "m_takedamage", 0, 1); - g_aPlayers[i][bImmune] = true; - } - else - { - SetEntProp(i, Prop_Data, "m_takedamage", 2, 1); - g_aPlayers[i][bImmune] = false; - } - } - } -} - -stock FormatMessage(iClient, iTeam, bool:bAlive, String:sChatMsg[], const Sting:sMessage[]) -{ - decl String:sDead[10], - String:sTeam[10], - String:sClientName[64]; - GetClientName(iClient, sClientName, sizeof(sClientName)); - if (iTeam != 0) - Format(sTeam, sizeof(sTeam), "(TEAM) "); - else - Format(sTeam, sizeof(sTeam), ""); - if (bAlive) - Format(sDead, sizeof(sDead), ""); - else - Format(sDead, sizeof(sDead), "*DEAD* "); - if (StrContains(g_sChatColor, "light", false) == -1) - Format(sChatMsg, CHAT_MAX_MESSAGE_LENGTH, "\x01%s%s\x03%s \x01: \x05%s", sDead, sTeam, sClientName, sMessage); - else - Format(sChatMsg, CHAT_MAX_MESSAGE_LENGTH, "\x01%s%s\x03%s \x01: \x04%s", sDead, sTeam, sClientName, sMessage); -} - -stock SayText2(target, author, const String:message[]) -{ - new Handle:hBf; - if (target == 0) - hBf = StartMessageAll("SayText2"); - else - hBf = StartMessageOne("SayText2", target); - if (hBf != INVALID_HANDLE) - { - BfWriteByte(hBf, author); - BfWriteByte(hBf, true); - BfWriteString(hBf, message); - EndMessage(); - } -} - -stock ProcessAdmins() -{ - for (new i = 1; i <= MaxClients; i++) - { - if (SM_IsValidAdmin(i, g_sCharDonatorFlag)) - { - g_aPlayers[i][bDonator] = true; - } - else - { - g_aPlayers[i][bDonator] = false; - } - } -} - -stock ProcessLate() -{ - if (g_bIsEnabled) - { - ProcessAdmins(); - PrepSoundFile(); - if (g_bRoundEnd && g_bIsImmuntyEnabled) - { - ProcessRoundEndImmunity(true); - } - if (!g_bIsImmuntyEnabled) - { - ProcessRoundEndImmunity(false); - } - } - else - { - ProcessRoundEndImmunity(false); - } -} - -public Menu_SwapMode(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, 64); - if (StringToInt(sSelection)) - g_aPlayers[param1][bQueue] = false; - else - g_aPlayers[param1][bQueue] = true; - if (!g_aPlayers[param1][bQueue]) - SM_MovePlayer(param1, g_aPlayers[param1][iNewTeam]); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -public Menu_SelectPlayer(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[256]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - new iTarget = GetClientOfUserId(StringToInt(sSelection)); - if (g_aPlayers[iTarget][bIsDonator]) - g_aPlayers[iTarget][bIsDonator] = false; - else - g_aPlayers[iTarget][bIsDonator] = true; - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -stock Handle:BuildSwapModeMenu() -{ - new Handle:menu = CreateMenu(Menu_SwapMode); - SetMenuTitle(menu, "Select When to Swap:"); - AddMenuItem(menu, "0", "Instantly (Kills)"); - AddMenuItem(menu, "1", "Queue on next death"); - SetMenuExitBackButton(menu, false); - return menu; -} - -stock Handle:BuildPlayerMenu() -{ - new Handle:menu = CreateMenu(Menu_SelectPlayer); - AddTargetsToMenu(menu, 0, true, false); - SetMenuTitle(menu, "Select A Player:"); - SetMenuExitBackButton(menu, true); - return menu; -} - -public Action:Command_TEST(client, args) -{ - -} \ No newline at end of file diff --git a/Simple Round Immunity/addons/sourcemod/scripting/simple-messagesuppression.sp b/Simple Round Immunity/addons/sourcemod/scripting/simple-messagesuppression.sp deleted file mode 100644 index f7725a4..0000000 --- a/Simple Round Immunity/addons/sourcemod/scripting/simple-messagesuppression.sp +++ /dev/null @@ -1,227 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Message Suppression -Description: - Blocks Specific Message Outputs -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include -#include - -#define SUPPRESS_VERSION "1.1.$Rev$" - -public Plugin:myinfo = -{ - name = "Simple Message Suppression", - author = "FlyingMongoose, psychonic", - description = "Blocks Specific Message Outputs", - version = SUPPRESS_VERSION, - url = "http://www.simple-plugins.com/" -} - -new Handle:cvarBlockSpectateMessage; -new Handle:cvarBlockDisconnectMessage; -new Handle:cvarBlockConnectMessage; -new Handle:cvarAdminShowMessages; -new iSpecTeam = 1; - - -public OnPluginStart() -{ - CreateConVar("suppress_version", SUPPRESS_VERSION, _, FCVAR_PLUGIN|FCVAR_NOTIFY|FCVAR_REPLICATED|FCVAR_SPONLY|FCVAR_DONTRECORD); - cvarBlockSpectateMessage = CreateConVar("sm_blockspectatemessage", "1", "If enabled it blocks the join team message if an administrator joins spectator", FCVAR_PLUGIN, true, 0.0, true, 1.0); - cvarBlockDisconnectMessage = CreateConVar("sm_blockdisconnectmessage", "1", "Blocks the disconnect message", FCVAR_PLUGIN, true, 0.0, true, 1.0); - cvarBlockConnectMessage = CreateConVar("sm_blockconnectmessage", "1", "If enabled it blocks the player connection message.", FCVAR_PLUGIN, true, 0.0, true, 1.0); - cvarAdminShowMessages = CreateConVar("sm_adminshowmessages", "1", "Shows disconnect/connect/team join messages for admins only (if disconnect message is set to be blocked)", FCVAR_PLUGIN, true, 0.0, true, 1.0); - HookEvent("player_team", ev_PlayerTeam, EventHookMode_Pre); - HookEvent("player_disconnect", ev_PlayerDisconnect, EventHookMode_Pre); - HookEvent("player_connect", ev_PlayerConnect, EventHookMode_Pre); - - new String:game_folder[64]; - GetGameFolderName(game_folder, sizeof(game_folder)) - - if (StrContains(game_folder, "insurgency", false) != -1) - { - iSpecTeam = 3; - } - else - { - new String:game_description[64]; - GetGameDescription(game_description, sizeof(game_description), true); - if (StrContains(game_description, "Insurgency", false) != -1) - { - iSpecTeam = 3; - } - } - - AutoExecConfig(true, "suppressmessage", "sourcemod"); -} - -public Action:ev_PlayerTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (GetConVarBool(cvarBlockSpectateMessage)) - { - if (!dontBroadcast && !GetEventBool(event, "silent")) - { - new iUserId = GetEventInt(event, "userid"); - new iClient = GetClientOfUserId(iUserId); - new iTeam = GetEventInt(event, "team"); - - if (iTeam == iSpecTeam && GetAdminFlag(GetUserAdmin(iClient), Admin_Kick)) - { - new iOldTeam = GetEventInt(event, "oldteam"); - new bool:bDisconnect = GetEventBool(event, "disconnect"); - new bool:bAutoteam = GetEventBool(event, "autoteam"); - decl String:strName[50]; - GetEventString(event, "name", strName, sizeof(strName)); - - if (iClient != 0) - { - if (GetConVarInt(cvarAdminShowMessages) == 1) - { - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i) && GetUserAdmin(i) != INVALID_ADMIN_ID) - { - PrintToChat(i,"%N joined team Spectator.", iClient); - PrintToConsole(i,"%N joined team Spectator.", iClient); - } - } - } - } - - new Handle:hEvent = CreateEvent("player_team"); - SetEventInt(hEvent, "userid", iUserId); - SetEventInt(hEvent, "team", iTeam); - SetEventInt(hEvent, "oldteam", iOldTeam); - SetEventBool(hEvent, "disconnect", bDisconnect); - SetEventBool(hEvent, "autoteam", bAutoteam); - SetEventBool(hEvent, "silent", true); - SetEventString(hEvent, "name", strName); - - FireEvent(hEvent, true); - - return Plugin_Handled; - } - } - } - return Plugin_Continue; -} -public Action:ev_PlayerConnect(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (GetConVarBool(cvarBlockConnectMessage)) - { - if (!dontBroadcast) - { - decl String:strName[50]; - GetEventString(event, "name", strName, sizeof(strName)); - new iIndex = GetEventInt(event, "index"); - new iUserId = GetEventInt(event, "userid"); - new iClient = GetClientOfUserId(iUserId); - decl String:strNetworkId[50]; - GetEventString(event, "networkid", strNetworkId, sizeof(strNetworkId)); - decl String:strAddress[50]; - GetEventString(event, "address", strAddress, sizeof(strAddress)); - - if (iClient != 0) - { - if (GetConVarInt(cvarAdminShowMessages) == 1) - { - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i) && GetUserAdmin(i) != INVALID_ADMIN_ID) - { - PrintToChat(i,"%N has connected.", iClient); - PrintToConsole(i,"%N has connected.", iClient); - } - } - } - } - - new Handle:hEvent = CreateEvent("player_connect"); - SetEventString(hEvent, "name", strName); - SetEventInt(hEvent, "index", iIndex); - SetEventInt(hEvent, "userid", iUserId); - SetEventString(hEvent, "networkid", strNetworkId); - SetEventString(hEvent, "address", strAddress); - - FireEvent(hEvent, true); - - return Plugin_Handled; - } - } - return Plugin_Continue; -} -public Action:ev_PlayerDisconnect(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (GetConVarBool(cvarBlockDisconnectMessage)) - { - if (!dontBroadcast) - { - new iUserId = GetEventInt(event, "userid"); - new iClient = GetClientOfUserId(iUserId); - decl String:strReason[50]; - GetEventString(event, "reason", strReason, sizeof(strReason)); - decl String:strName[50]; - GetEventString(event, "name", strName, sizeof(strName)); - decl String:strNetworkId[50]; - GetEventString(event, "networkid", strNetworkId, sizeof(strNetworkId)); - - if (iClient != 0) - { - if (GetConVarInt(cvarAdminShowMessages) == 1) - { - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i) && GetUserAdmin(i) != INVALID_ADMIN_ID) - { - PrintToChat(i, "%N has left the server.", iClient); - PrintToConsole(i, "Dropped %N from server (Disconnect by user.)", iClient); - } - } - } - } - - new Handle:hEvent = CreateEvent("player_disconnect"); - SetEventInt(hEvent, "userid", iUserId); - SetEventString(hEvent, "reason", strReason); - SetEventString(hEvent, "name", strName); - SetEventString(hEvent, "networkid", strNetworkId); - - FireEvent(hEvent, true); - - return Plugin_Handled; - } - } - - return Plugin_Continue; -} \ No newline at end of file diff --git a/Simple Round Immunity/addons/sourcemod/scripting/simple-plugins.sp b/Simple Round Immunity/addons/sourcemod/scripting/simple-plugins.sp deleted file mode 100644 index 4462b41..0000000 --- a/Simple Round Immunity/addons/sourcemod/scripting/simple-plugins.sp +++ /dev/null @@ -1,785 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Plugins -Description: - Core plugin for Simple Plugins project -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#define CORE_PLUGIN_VERSION "1.1.$Rev$" - -#include - -enum e_PlayerInfo -{ - Handle:hForcedTeamPlugin = INVALID_HANDLE, - iForcedTeam = 0, - iBuddy = 0, - bool:bBuddyLocked = false -}; - -new Handle:g_fwdPlayerMoved; -new g_aPlayers[MAXPLAYERS + 1][e_PlayerInfo]; -new bool:g_bTeamsSwitched = false; - -/** -Setting our plugin information. -*/ -public Plugin:myinfo = -{ - name = "Simple Plugins Core Plugin", - author = "Simple Plugins", - description = "Core plugin for Simple Plugins", - version = CORE_PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -public bool:AskPluginLoad(Handle:myself, bool:late, String:error[], err_max) -{ - - /** - Register natives for other plugins - */ - CreateNative("SM_MovePlayer", Native_SM_MovePlayer); - CreateNative("SM_SetForcedTeam", Native_SM_SetForcedTeam); - CreateNative("SM_GetForcedTeam", Native_SM_GetForcedTeam); - CreateNative("SM_ClearForcedTeam", Native_SM_ClearForcedTeam); - CreateNative("SM_GetForcedPlayer", Native_SM_GetForcedPlayer); - CreateNative("SM_AssignBuddy", Native_SM_AssignBuddy); - CreateNative("SM_GetClientBuddy", Native_SM_GetClientBuddy); - CreateNative("SM_LockBuddy", Native_SM_LockBuddy); - CreateNative("SM_IsBuddyLocked", Native_SM_IsBuddyLocked); - CreateNative("SM_ClearBuddy", Native_SM_ClearBuddy); - CreateNative("SM_IsValidAdmin", Native_SM_IsValidAdmin); - CreateNative("SM_IsValidTeam", Native_SM_IsValidTeam); - RegPluginLibrary("simpleplugins"); - return true; -} - -public OnPluginStart() -{ - - CreateConVar("ssm_core_pl_ver", CORE_PLUGIN_VERSION, "Simple SourceMod Plugins Core Plugin Version", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - CreateConVar("ssm_core_inc_ver", CORE_INC_VERSION, "Simple SourceMod Plugins Core Include Version", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook some events to control forced players and check extensions - */ - decl String:sExtError[256]; - LogAction(0, -1, "[SSM] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Pre); - switch (g_CurrentMod) - { - case GameType_CSS: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - new iExtStatus = GetExtensionFileStatus("game.cstrike.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SSM] Required extension was not found."); - LogAction(0, -1, "[SSM] Plugin FAILED TO LOAD."); - SetFailState("Required extension was not found."); - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SSM] Required extension is loaded with errors."); - LogAction(0, -1, "[SSM] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SSM] Plugin FAILED TO LOAD."); - SetFailState("Required extension is loaded with errors."); - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SSM] Required extension is loaded."); - } - } - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_PostNoCopy); - HookUserMessage(GetUserMessageId("TextMsg"), UserMessageHook_Class, true); - new iExtStatus = GetExtensionFileStatus("game.tf2.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SSM] Required extension was not found."); - LogAction(0, -1, "[SSM] Plugin FAILED TO LOAD."); - SetFailState("Required extension was not found."); - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SSM] Required extension is loaded with errors."); - LogAction(0, -1, "[SSM] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SSM] Plugin FAILED TO LOAD."); - SetFailState("Required extension is loaded with errors."); - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SSM] Required extension is loaded."); - } - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_PostNoCopy); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - - /** - Load common translations - */ - LoadTranslations ("common.phrases"); - - /** - Create the global forward - */ - g_fwdPlayerMoved = CreateGlobalForward("SM_OnPlayerMoved", ET_Event, Param_Cell, Param_Cell, Param_Cell); -} - -public OnClientDisconnect(client) -{ - - /** - Cleanup clients/players buddy list - */ - if (!IsFakeClient(client)) - { - SM_ClearBuddy(client, true); - SM_LockBuddy(client, false); - } - SM_ClearForcedTeam(client); -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - See if the teams have been switched - */ - if (g_bTeamsSwitched) - { - - /** - Switch the teams the players are forced to - */ - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][iForcedTeam] != 0) - { - if (g_aPlayers[i][iForcedTeam] == g_aCurrentTeams[Team1]) - { - g_aPlayers[i][iForcedTeam] = g_aCurrentTeams[Team2]; - } - else - { - g_aPlayers[i][iForcedTeam] = g_aCurrentTeams[Team1]; - } - } - } - } -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - g_bTeamsSwitched = false; -} - -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get our event variables - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - new iTeam = GetEventInt(event, "team"); - - /** - See if the player is on the wrong team - */ - if (g_aPlayers[iClient][iForcedTeam] != 0 && g_aPlayers[iClient][iForcedTeam] != iTeam) - { - - /** - Move the player back to the forced team - */ - CreateTimer(1.0, Timer_ForcePlayerMove, iClient, TIMER_FLAG_NO_MAPCHANGE); - - /** - If the event was going to be broadcasted, we refire it so it is not broadcasted and stop this one - */ - if (!dontBroadcast) - { - new Handle:hEvent = CreateEvent("player_team"); - SetEventInt(hEvent, "userid", GetEventInt(event, "userid")); - SetEventInt(hEvent, "team", GetEventInt(event, "team")); - SetEventInt(hEvent, "oldteam", GetEventInt(event, "oldteam")); - SetEventBool(hEvent, "disconnect", GetEventBool(event, "disconnect")); - - if (g_CurrentMod == GameType_DOD || g_CurrentMod == GameType_L4D || g_CurrentMod == GameType_TF) - { - new String:sClientName[MAX_NAME_LENGTH + 1]; - GetClientName(client, sClientName, sizeof(sClientName)); - SetEventBool(hEvent, "autoteam", GetEventBool(event, "autoteam")); - SetEventBool(hEvent, "silent", true); - SetEventString(hEvent, "name", sClientName); - FireEvent(hEvent, true); - } - else - { - FireEvent(hEvent, true); - } - return Plugin_Handled; - } - } - return Plugin_Continue; -} - -public Action:UserMessageHook_Class(UserMsg:msg_id, Handle:bf, const players[], playersNum, bool:reliable, bool:init) -{ - new String:sMessage[120]; - BfReadString(bf, sMessage, sizeof(sMessage), true); - if (StrContains(sMessage, "#TF_TeamsSwitched", false) != -1) - { - g_bTeamsSwitched = true; - } - return Plugin_Continue; -} - -public Native_SM_MovePlayer(Handle:plugin, numParams) -{ - - /** - Get and check the client and team - */ - new iClient = GetNativeCell(1); - new iTeam = GetNativeCell(2); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (iTeam != g_aCurrentTeams[Spectator] && iTeam != g_aCurrentTeams[Team1] && iTeam != g_aCurrentTeams[Team2]) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid team %d", iTeam); - } - - MovePlayer(iClient, iTeam); - if (!IsClientObserver(iClient)) - { - RespawnPlayer(iClient); - } - - new fResult; - - Call_StartForward(g_fwdPlayerMoved); - Call_PushCell(plugin); - Call_PushCell(iClient); - Call_PushCell(iTeam); - Call_Finish(fResult); - - if (fResult != SP_ERROR_NONE) - { - return ThrowNativeError(fResult, "Forward failed"); - } - - return fResult; -} - -public Native_SM_SetForcedTeam(Handle:plugin, numParams) -{ - - /** - Get and check the client and team - */ - new iClient = GetNativeCell(1); - new iTeam = GetNativeCell(2); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (iTeam != g_aCurrentTeams[Spectator] && iTeam != g_aCurrentTeams[Team1] && iTeam != g_aCurrentTeams[Team2] && iTeam != g_aCurrentTeams[Unknown]) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid team %d", iTeam); - } - - new bool:bOverRide = GetNativeCell(3) ? true : false; - - if (!bOverRide && g_aPlayers[iClient][hForcedTeamPlugin] != INVALID_HANDLE && plugin != g_aPlayers[iClient][hForcedTeamPlugin]) - { - return false; - } - - g_aPlayers[iClient][hForcedTeamPlugin] = plugin; - g_aPlayers[iClient][iForcedTeam] = iTeam; - return true; -} - -public Native_SM_GetForcedTeam(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - - /** - Get and set the plugin if they want it - */ - new Handle:hPlugin = GetNativeCell(2); - if (hPlugin != INVALID_HANDLE) - { - SetNativeCellRef(2, g_aPlayers[iClient][hForcedTeamPlugin]); - } - - /** - Return the forced team, this could be 0 - */ - return g_aPlayers[iClient][iForcedTeam]; -} - -public Native_SM_ClearForcedTeam(Handle:plugin, numParams) -{ - - /** - Get and check the client and team - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - - g_aPlayers[iClient][hForcedTeamPlugin] = INVALID_HANDLE; - g_aPlayers[iClient][iForcedTeam] = 0; - - return true; -} - -public Native_SM_GetForcedPlayer(Handle:plugin, numParams) -{ - - /** - Get and check the team - */ - new iTeam = GetNativeCell(1); - if (iTeam != g_aCurrentTeams[Spectator] && iTeam != g_aCurrentTeams[Team1] && iTeam != g_aCurrentTeams[Team2]) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid team %d", iTeam); - } - - /** - Start a loop to check for a player on the wrong team - Also make sure the plugin that set the forced team is the plugin that asked - */ - new iPlayer = 0; - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientInGame(i) - && GetClientTeam(i) != g_aPlayers[i][iForcedTeam] - && g_aPlayers[i][iForcedTeam] == iTeam - && g_aPlayers[i][hForcedTeamPlugin] == plugin) - { - iPlayer = i; - break; - } - } - - /** - Return the player we found, this could be 0 - */ - return iPlayer; -} - -public Native_SM_AssignBuddy(Handle:plugin, numParams) -{ - - /** - Get and check the client and player - */ - new iClient = GetNativeCell(1); - new iPlayer = GetNativeCell(2); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (iPlayer < 0 || iPlayer > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid player index (%d)", iPlayer); - } - if (!IsClientConnected(iPlayer)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Player %d is not connected", iPlayer); - } - if (!IsClientInGame(iPlayer)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Player %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Bots are not supported"); - } - - /** - See if we can override his setting - */ - new bool:bOverRide = GetNativeCell(3) ? true : false; - if (!bOverRide) - { - - /** - We can't override, so check if they are locked - */ - if (g_aPlayers[iClient][bBuddyLocked] || g_aPlayers[iPlayer][bBuddyLocked]) - { - - /** - We detected at least 1 lock, so we bug out - */ - return false; - } - } - - /** - Ready to set the buddies - */ - g_aPlayers[iClient][iBuddy] = iPlayer; - g_aPlayers[iPlayer][iBuddy] = iClient; - return true; -} - -public Native_SM_GetClientBuddy(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Bots are not supported"); - } - - /** - Return the players buddy, this could be 0 - */ - return g_aPlayers[iClient][iBuddy]; -} - -public Native_SM_LockBuddy(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - new bool:bSetting = GetNativeCell(2) ? true : false; - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Bots are not supported"); - } - - g_aPlayers[iClient][bBuddyLocked] = bSetting; - return true; -} - -public Native_SM_IsBuddyLocked(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Bots are not supported"); - } - - return g_aPlayers[iClient][bBuddyLocked]; -} - -public Native_SM_ClearBuddy(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Client (%d) is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Bots are not supported"); - } - - /** - Get the clients buddy and see if we can override his setting - */ - new bool:bOverRide = GetNativeCell(2) ? true : false; - new iPlayer = g_aPlayers[iClient][iBuddy]; - - /** - There is no buddy, we don't care about anything else so bug out - */ - if (iPlayer == 0) - { - return true; - } - - /** - We determined he had a buddy, check the override setting - */ - if (!bOverRide) - { - - /** - We can't override, so check if they are locked - */ - if (g_aPlayers[iClient][bBuddyLocked] || g_aPlayers[iPlayer][bBuddyLocked]) - { - - /** - We detected at least 1 lock, so we bug out - */ - return false; - } - } - - /** - Ready to clear the buddies - */ - g_aPlayers[iClient][iBuddy] = 0; - g_aPlayers[iPlayer][iBuddy] = 0; - return true; -} - -public Native_SM_IsValidTeam(Handle:plugin, numParams) -{ - - /** - Get the team - */ - new iTeam = GetNativeCell(1); - - /** - Check the team - */ - if (iTeam == g_aCurrentTeams[Spectator] || iTeam == g_aCurrentTeams[Team1] || iTeam == g_aCurrentTeams[Team2]) - { - return true; - } - return false; -} - -public Native_SM_IsValidAdmin(Handle:plugin, numParams) -{ - /** - Get the client and flags - */ - new iClient = GetNativeCell(1); - decl String:sFlags[15]; - GetNativeString(2, sFlags, sizeof(sFlags)); - new ibFlags = ReadFlagString(sFlags); - - /** - Check the flags - */ - if ((GetUserFlagBits(iClient) & ibFlags) == ibFlags) - { - return true; - } - if (GetUserFlagBits(iClient) & ADMFLAG_ROOT) - { - return true; - } - return false; -} - -public Action:Timer_ForcePlayerMove(Handle:timer, any:iClient) -{ - - MovePlayer(iClient, g_aPlayers[iClient][iForcedTeam]); - - if (g_aPlayers[iClient][iForcedTeam] != g_aCurrentTeams[Spectator]) - { - RespawnPlayer(iClient); - } - - PrintToChat(iClient, "\x01\x04----------------------------------"); - PrintToChat(iClient, "\x01\x04You have been forced to this team."); - PrintToChat(iClient, "\x01\x04----------------------------------"); - - return Plugin_Handled; -} - -stock MovePlayer(iClient, iTeam) -{ - - /** - Change the client's team based on the mod - */ - switch (g_CurrentMod) - { - case GameType_CSS: - { - CS_SwitchTeam(iClient, iTeam); - } - default: - { - ChangeClientTeam(iClient, iTeam); - } - } -} - -stock RespawnPlayer(iClient) -{ - - /** - Respawn the client based on the mod - */ - switch (g_CurrentMod) - { - case GameType_CSS: - { - CS_RespawnPlayer(iClient); - } - case GameType_TF: - { - TF2_RespawnPlayer(iClient); - } - case GameType_INS: - { - FakeClientCommand(iClient, "kill"); - } - default: - { - // - } - } -} diff --git a/Simple Round Immunity/addons/sourcemod/scripting/simple-spectate.sp b/Simple Round Immunity/addons/sourcemod/scripting/simple-spectate.sp deleted file mode 100644 index 4108f8f..0000000 --- a/Simple Round Immunity/addons/sourcemod/scripting/simple-spectate.sp +++ /dev/null @@ -1,2022 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Spectate -Description: - Spectate a player and follow them through death. -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include -#undef REQUIRE_EXTENSIONS -#undef AUTOLOAD_EXTENSIONS -#tryinclude -#define AUTOLOAD_EXTENSIONS -#define REQUIRE_EXTENSIONS - -#define PLUGIN_VERSION "1.2.1.$Rev$" - -#define SPECMODE_NONE 0 -#define SPECMODE_FIRSTPERSON 4 -#define SPECMODE_3RDPERSON 5 -#define SPECMODE_FREELOOK 6 -#define SPECMODE_CSS_FIRSTPERSON 3 -#define SPECMODE_CSS_3RDPERSON 4 -#define SPECMODE_CSS_FREELOOK 5 - -enum e_CvarHandles -{ - Handle:hHudMode, - Handle:hMenuType, - Handle:hRestrictHud, - Handle:hBan, - Handle:hBanPerm, - Handle:hBeacon, - Handle:hBlind, - Handle:hCheater, - Handle:hDrug, - Handle:hFreeze, - Handle:hFreezeBomb, - Handle:hKick, - Handle:hSlap, - Handle:hSlay, - Handle:hTimeBomb -}; - -enum e_CvarSettings -{ - bool:bHudMode, - bool:bMenuType, - bool:bRestrictHud, - bool:bBan, - bool:bBanPerm, - bool:bBeacon, - bool:bBlind, - bool:bCheater, - bool:bDrug, - bool:bFreeze, - bool:bFreezebomb, - bool:bKick, - bool:bSlap, - bool:bSlay, - bool:bTimeBomb -}; - -enum e_PluginSettings -{ - bool:bUseSteamBans, - bool:bUseSourceBans, - bool:bUseMySQLBans, - bool:bCanHUD, - bool:bUseDukehacks -}; - -enum e_Menus -{ - Handle:hSelectPlayer, - Handle:hBanTime, - Handle:hReason -}; - -enum e_Punishments -{ - Punish_None, - Punish_Ban, - Punish_Beacon, - Punish_Blind, - Punish_Cheater, - Punish_Drug, - Punish_Freeze, - Punish_FreezeBomb, - Punish_Kick, - Punish_Slap, - Punish_Slay, - Punish_TimeBomb -}; - -enum e_PlayerData -{ - bool:bIsDisplayingHud, - bool:bIsFlaggedCheater, - Handle:hHudTimer, - Handle:hTargetTimer, - iTargetIndex, - e_Punishments:TargetPunishment, - iBanTime -}; - -new Handle:sm_spectate_adminflag = INVALID_HANDLE; -new Handle:g_hAdminMenu = INVALID_HANDLE; -new Handle:g_hHud = INVALID_HANDLE; -new Handle:g_aPluginCvar[e_CvarHandles]; -new g_aPluginCvarSettings[e_CvarSettings]; -new g_aPluginSettings[e_PluginSettings]; -new g_aMenus[e_Menus]; -new g_aPlayers[MAXPLAYERS + 1][e_PlayerData]; -new String:g_sAdminFlags[16]; -new String:g_sPunishments[e_Punishments][15] = { "None", "Ban", "Beacon", "Blind", "Cheater", "Drug", "Freeze", "FreezeBomb", "Kick", "Slap", "Slay", "TimeBomb" }; - -public Plugin:myinfo = -{ - name = "Simple Spectate", - author = "Simple Plugins", - description = "Spectate a player and follow them through death.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -/** -Sourcemod callbacks -*/ -public OnPluginStart() -{ - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[SSPEC] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Pre); - - /** - Need to create all of our console variables. - */ - CreateConVar("sm_spectate_version", PLUGIN_VERSION, "Sourcemod Spectate", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - g_aPluginCvar[hHudMode] = CreateConVar("sm_spectate_hudmode", "1", "Hud Mode: 0 = Hud Text | 1 = Panel/Menu (NOTE: The panel/menu will override other menus until canceled)"); - g_aPluginCvar[hMenuType] = CreateConVar("sm_spectate_menutype", "0", "Menu Mode: 0 = Panel | 1 = Menu"); - g_aPluginCvar[hRestrictHud] = CreateConVar("sm_spectate_restricthud", "0", "Restrict the hud to the admin flag provided"); - g_aPluginCvar[hBan] = CreateConVar("sm_spectate_ban", "1", "Enable/Disable ban option"); - g_aPluginCvar[hBanPerm] = CreateConVar("sm_spectate_banperm", "1", "Enable/Disable permanent ban option"); - g_aPluginCvar[hBeacon] = CreateConVar("sm_spectate_beacon", "1", "Enable/Disable beacon option"); - g_aPluginCvar[hBlind] = CreateConVar("sm_spectate_blind", "1", "Enable/Disable blind option"); - g_aPluginCvar[hCheater] = CreateConVar("sm_spectate_cheater", "1", "Enable/Disable cheater option"); - g_aPluginCvar[hDrug] = CreateConVar("sm_spectate_drug", "1", "Enable/Disable drug option"); - g_aPluginCvar[hFreeze] = CreateConVar("sm_spectate_freeze", "1", "Enable/Disable freeze option"); - g_aPluginCvar[hFreezeBomb] = CreateConVar("sm_spectate_freezebomb", "1", "Enable/Disable freezebomb option"); - g_aPluginCvar[hKick] = CreateConVar("sm_spectate_kick", "1", "Enable/Disable kick option"); - g_aPluginCvar[hSlap] = CreateConVar("sm_spectate_slap", "1", "Enable/Disable slap option"); - g_aPluginCvar[hSlay] = CreateConVar("sm_spectate_slay", "1", "Enable/Disable slay option"); - g_aPluginCvar[hTimeBomb] = CreateConVar("sm_spectate_timebomb", "1", "Enable/Disable timebomb option"); - - sm_spectate_adminflag = CreateConVar("sm_spectate_adminflag", "d", "Admin Flag to use for admin hud"); - - /** - Hook console variables - */ - new e_CvarHandles:iCvar; - for ( ; _:iCvar < sizeof(g_aPluginCvar); iCvar++) - { - HookConVarChange(g_aPluginCvar[iCvar], ConVarSettingsChanged); - } - - /** - Need to register the commands we are going to create and use. - */ - RegConsoleCmd("sm_spectate", Command_Spectate, "Spectate a player"); - RegConsoleCmd("sm_spec", Command_Spectate, "Spectate a player"); - RegConsoleCmd("sm_observe", Command_Spectate, "Spectate a player"); - RegConsoleCmd("sm_stopspec", Command_StopSpectate, "Stop Spectating a player"); - RegConsoleCmd("sm_endobserve", Command_StopSpectate, "Stop Spectating a player"); - RegConsoleCmd("sm_specinfo", Command_ToggleHud, "Toggles the hud display if in spectator"); - - /** - Now we have to deal with the admin menu. If the admin library is loaded call the function to add our items. - */ - new Handle:gTopMenu; - if (LibraryExists("adminmenu") && ((gTopMenu = GetAdminTopMenu()) != INVALID_HANDLE)) - { - OnAdminMenuReady(gTopMenu); - } - - /** - Deal with the hud - Thanks to Spray Trace plugin (http://forums.alliedmods.net/showthread.php?p=665448) - */ - new String:sHudGames[32]; - GetGameFolderName(sHudGames, sizeof(sHudGames)); - g_aPluginSettings[bCanHUD] = StrEqual(sHudGames,"tf",false) - || StrEqual(sHudGames,"hl2mp",false) - || StrEqual(sHudGames,"sourceforts",false) - || StrEqual(sHudGames,"obsidian",false) - || StrEqual(sHudGames,"left4dead",false) - || StrEqual(sHudGames,"l4d",false); - - if (g_aPluginSettings[bCanHUD]) - { - g_hHud = CreateHudSynchronizer(); - } - - /** - Load translations - */ - LoadTranslations ("common.phrases"); - LoadTranslations ("simplespectate.phrases"); - - /** - Create the config file - */ - AutoExecConfig(true); -} - -public OnConfigsExecuted() -{ - new e_CvarHandles:iCvar; - for ( ; _:iCvar < sizeof(g_aPluginCvarSettings); iCvar++) - { - g_aPluginCvarSettings[iCvar] = GetConVarBool(g_aPluginCvar[iCvar]); - } - - /* - Build the global menus - */ - g_aMenus[hSelectPlayer] = BuildSelectPlayerMenu(); - g_aMenus[hBanTime] = BuildBanTimeMenu(); - g_aMenus[hReason] = BuildReasonMenu(); - - GetConVarString(sm_spectate_adminflag, g_sAdminFlags, sizeof(g_sAdminFlags)); -} - -public OnAllPluginsLoaded() -{ - - /* - Check for steambans - */ - if (FindConVar("sbsrc_version") != INVALID_HANDLE) - { - g_aPluginSettings[bUseSteamBans] = true; - } - else - { - g_aPluginSettings[bUseSteamBans] = false; - } - - /* - Check for sourcebans - */ - if (FindConVar("sb_version") != INVALID_HANDLE) - { - g_aPluginSettings[bUseSourceBans] = true; - } - else - { - g_aPluginSettings[bUseSourceBans] = false; - } - - /* - Check for mysql bans - */ - if (FindConVar("mysql_bans_version") != INVALID_HANDLE) - { - g_aPluginSettings[bUseMySQLBans] = true; - } - else - { - g_aPluginSettings[bUseMySQLBans] = false; - } - - /* - Check for dukehacks - */ - new String:sExtError[256]; - new iExtStatus = GetExtensionFileStatus("dukehacks.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SSPEC] Dukehacks extension was not found."); - LogAction(0, -1, "[SSPEC] Plugin continued to load, but that feature will not be used."); - g_aPluginSettings[bUseDukehacks] = false; - } - else if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SSPEC] Dukehacks extension is loaded with errors."); - LogAction(0, -1, "[SSPEC] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SSPEC] Plugin continued to load, but that feature will not be used."); - g_aPluginSettings[bUseDukehacks] = false; - } - else if (iExtStatus == 1) - { - LogAction(0, -1, "[SSPEC] Dukehacks extension is loaded and will be used."); - g_aPluginSettings[bUseDukehacks] = true; - dhAddClientHook(CHK_TakeDamage, Hacks_TakeDamageHook); - } - - /* - Deal with some known plugin conflicts - */ - new Handle:hObserveClient = FindConVar("observe_version"); - if (hObserveClient != INVALID_HANDLE) - { - new String:sNewFile[PLATFORM_MAX_PATH + 1], String:sOldFile[PLATFORM_MAX_PATH + 1]; - BuildPath(Path_SM, sNewFile, sizeof(sNewFile), "plugins/disabled/observe.smx"); - BuildPath(Path_SM, sOldFile, sizeof(sOldFile), "plugins/observe.smx"); - - /** - Check if plugins/observe.smx exists, and if not, ignore - */ - if(!FileExists(sOldFile)) - { - return; - } - - /** - Check if plugins/disabled/observe.smx already exists, and if so, delete it - */ - if(FileExists(sNewFile)) - { - DeleteFile(sNewFile); - } - - /** - Unload plugins/observe.smx and move it to plugins/disabled/observe.smx - */ - LogAction(0, -1, "Detected the plugin ObserveClient"); - LogAction(0, -1, "ObserveClient plugin conflicts with Simple Spectate"); - LogAction(0, -1, "Unloading plugin and disabling ObserveClient plugin"); - ServerCommand("sm plugins unload observe"); - RenameFile(sNewFile, sOldFile); - } -} - -public OnLibraryRemoved(const String:name[]) -{ - if (StrEqual(name, "adminmenu")) - { - - /** - Looks like the admin menu was removed. Set the global. - */ - g_hAdminMenu = INVALID_HANDLE; - } - else if (StrEqual(name, "simpleplugins")) - { - //something - } -} - -public OnClientDisconnect(client) -{ - - /** - Cleanup the clients variables. - */ - ResetClient(client); - - /** - Run a loop and see if we are supposed to spectate this person (is a target) - */ - for(new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][iTargetIndex] == client) - { - - /** - Cleanup the clients variables. - */ - StopFollowingPlayer(i); - g_aPlayers[i][TargetPunishment] = Punish_None; - g_aPlayers[i][iBanTime] = 0; - } - } -} - -/** -Thirdparty callbacks -*/ -public SM_OnPlayerMoved(Handle:plugin, client, team) -{ - - /** - Make sure we called the move function - */ - if (plugin != GetMyHandle()) - { - return; - } - - //Nothing -} - -public Action:Hacks_TakeDamageHook(client, attacker, inflictor, Float:damage, &Float:multiplier, damagetype) -{ - - /** - Check for a valid client - */ - if (client > 0 && client <= MaxClients) - { - - /** - Check if the client taking damage is flagged as a cheater - */ - if (g_aPlayers[client][bIsFlaggedCheater]) - { - - /** - Check for fall damage and increase it - */ - if (damagetype & DMG_FALL) - { - multiplier *= 1000.0; - return Plugin_Changed; - } - } - } - - /** - Check for a valid attacker - */ - if (attacker > 0 && attacker <= MaxClients) - { - - /** - Check if the attacker causing the damage is flagged as a cheater - */ - if (g_aPlayers[attacker][bIsFlaggedCheater]) - { - - /** - Make sure they are not hurting themselves - */ - if (client != attacker) - { - - /** - Stop the damage - */ - multiplier *= 0.0; - return Plugin_Changed; - } - } - } - return Plugin_Continue; -} - -/** -Events -*/ -public Action:HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get the client and team - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - new iTeam = GetEventInt(event, "team"); - - /** - Make sure it's a valid client - */ - if (iClient == 0) - { - return Plugin_Continue; - } - - /** - If it's a move to spectator start displaying the hud - */ - else if ((iTeam == g_aCurrentTeams[Spectator]) && (GetUserFlagBits(iClient) & ADMFLAG_GENERIC)) - { - StartDisplayingHud(iClient); - - /** - If the event was going to be broadcasted, we refire it so it is not broadcasted and stop this one - */ - if (!dontBroadcast) - { - new Handle:hEvent = CreateEvent("player_team"); - SetEventInt(hEvent, "userid", GetEventInt(event, "userid")); - SetEventInt(hEvent, "team", GetEventInt(event, "team")); - SetEventInt(hEvent, "oldteam", GetEventInt(event, "oldteam")); - SetEventBool(hEvent, "disconnect", GetEventBool(event, "disconnect")); - - if (g_CurrentMod == GameType_DOD || g_CurrentMod == GameType_L4D || g_CurrentMod == GameType_TF) - { - new String:sClientName[MAX_NAME_LENGTH + 1]; - GetClientName(client, sClientName, sizeof(sClientName)); - SetEventBool(hEvent, "autoteam", GetEventBool(event, "autoteam")); - SetEventBool(hEvent, "silent", true); - SetEventString(hEvent, "name", sClientName); - FireEvent(hEvent, true); - } - else - { - FireEvent(hEvent, true); - } - return Plugin_Handled; - } - } - - /** - Otherwise cleanup the client - */ - else - { - StopDisplayingHud(iClient); - StopFollowingPlayer(iClient); - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -/** -Commands -*/ -public Action:Command_Spectate(client, args) -{ - - /** - See if we already have a target (for toggling of command) - */ - if (g_aPlayers[client][iTargetIndex]) - { - - /** - We do, toggle it off - */ - StopFollowingPlayer(client); - - /** - We are done, bug out. - */ - return Plugin_Handled; - } - - /** - We don't... must want to enable it - See if we have some command arguments. - */ - new iCmdArgs = GetCmdArgs(); - if (iCmdArgs == 0) - { - - /** - We don't have any. Display the player menu. - */ - if (g_aPlayers[client][bIsDisplayingHud]) - { - StopDisplayingHud(client); - } - - DisplayMenu(BuildPlayerListMenu(), client, MENU_TIME_FOREVER); - return Plugin_Handled; - } - - /** - We have an argument. - Try to find the target. - */ - new String:sPlayer[128]; - GetCmdArg(1, sPlayer, sizeof(sPlayer)); - new iTarget = FindTarget(client, sPlayer, true, true); - if (iTarget == -1 || !IsClientInGame(iTarget)) - { - - /** - We couldn't find the target. Display the player menu. - */ - if (g_aPlayers[client][bIsDisplayingHud]) - { - StopDisplayingHud(client); - } - - DisplayMenu(BuildPlayerListMenu(), client, MENU_TIME_FOREVER); - return Plugin_Handled; - } - - /** - We found the target. - Call the stock function to spectate the target. - */ - StartFollowingPlayer(client, iTarget); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_StopSpectate(client, args) -{ - - /** - Cleanup the clients variables. - */ - StopFollowingPlayer(client); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_ToggleHud(client, args) -{ - - /** - Toggle the hud - */ - if (g_aPlayers[client][bIsDisplayingHud]) - { - StopDisplayingHud(client); - } - else - { - StartDisplayingHud(client); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -/** -Timers -*/ -public Action:Timer_ResetTarget(Handle:timer, any:client) -{ - - new iTargetID = GetEntPropEnt(client, Prop_Send, "m_hObserverTarget"); - - if (iTargetID != g_aPlayers[client][iTargetIndex] && IsPlayerAlive(g_aPlayers[client][iTargetIndex])) - { - - /** - Run the command to spectate the target from the clients prospectative. - */ - FakeClientCommandEx(client, "spec_player \"%N\"", g_aPlayers[client][iTargetIndex]); - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Timer_UpdateHud(Handle:timer, any:client) -{ - - /** - Make sure the client is still in game and a spectator - */ - if (!IsClientConnected(client) || !IsClientInGame(client) || GetClientTeam(client) != g_aCurrentTeams[Spectator] || !g_aPlayers[client][bIsDisplayingHud]) - { - - /** - We are done, bug out - */ - g_aPlayers[client][hHudTimer] = INVALID_HANDLE; - g_aPlayers[client][bIsDisplayingHud] = false; - return Plugin_Stop; - } - /** - Get the target - */ - new iTarget = GetEntPropEnt(client, Prop_Send, "m_hObserverTarget"); - - /** - Check to make sure the target is valid - */ - if (iTarget <= 0 || iTarget > MaxClients) - { - return Plugin_Continue; - } - - /** - Get the spectator mode - */ - new iSpecMode = GetEntProp(client, Prop_Send, "m_iObserverMode"); - - /** - This is a double check to make sure we are in spec - If we are on a regular team, specmod would = none or zero - */ - if (iSpecMode == SPECMODE_NONE) - { - - /** - We are done, bug out - */ - g_aPlayers[client][hHudTimer] = INVALID_HANDLE; - g_aPlayers[client][bIsDisplayingHud] = false; - return Plugin_Stop; - } - - /** - Check the spectator mode - CSS has different index's so we have to check game type first - */ - if (g_CurrentMod == GameType_CSS) - { - switch (iSpecMode) - { - case SPECMODE_CSS_FIRSTPERSON: - { - //Do Nothing - } - case SPECMODE_CSS_3RDPERSON: - { - //Do Nothing - } - case SPECMODE_CSS_FREELOOK: - { - return Plugin_Continue; - } - } - } - else - { - switch (iSpecMode) - { - case SPECMODE_FIRSTPERSON: - { - //Do Nothing - } - case SPECMODE_3RDPERSON: - { - //Do Nothing - } - case SPECMODE_FREELOOK: - { - return Plugin_Continue; - } - } - } - - - /** - Display with the hud - */ - if (g_aPluginSettings[bCanHUD] && !g_aPluginCvarSettings[bHudMode]) - { - new String:sSteamID[64]; - GetClientAuthString(iTarget, sSteamID, sizeof(sSteamID)); - SetHudTextParams(0.04, 0.6, 0.5, 255, 50, 50, 255); - ShowSyncHudText(client, g_hHud, "%N [%s]", iTarget, sSteamID); - } - else if (g_aPluginCvarSettings[bHudMode]) - { - if (g_aPluginCvarSettings[bMenuType]) - { - DisplayMenu(BuildPlayerHudMenu(client, iTarget), client, 1); - } - else - { - new Handle:hPanel = BuildPlayerHudPanel(client, iTarget); - SendPanelToClient(hPanel, client, Panel_PlayerHud, 1); - CloseHandle(hPanel); - } - } - - /** - We are done, keep going! - */ - return Plugin_Continue; -} - -/** -Admin Menu Callbacks -*/ -public OnAdminMenuReady(Handle:topmenu) -{ - if (topmenu == g_hAdminMenu) - { - return; - } - g_hAdminMenu = topmenu; - new TopMenuObject:player_commands = FindTopMenuCategory(g_hAdminMenu, ADMINMENU_PLAYERCOMMANDS); - if (player_commands == INVALID_TOPMENUOBJECT) - { - return; - } - AddToTopMenu(g_hAdminMenu, - "sm_spectate", - TopMenuObject_Item, - AdminMenu_SpecPlayer, - player_commands, - "sm_spectate", - ADMFLAG_GENERIC); -} - -public AdminMenu_SpecPlayer(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) -{ - if (action == TopMenuAction_DisplayOption) - { - - if (g_aPlayers[param][bIsDisplayingHud]) - { - StopDisplayingHud(param); - } - /** - See if we already have a target - */ - if (g_aPlayers[param][iTargetIndex]) - { - Format(buffer, maxlength, "Spectate(Disable)"); - } - else - { - Format(buffer, maxlength, "Spectate(Select Player)"); - } - } - else if (action == TopMenuAction_SelectOption) - { - - /** - See if we already have a target - */ - if (g_aPlayers[param][iTargetIndex]) - { - - /** - We do, toggle it off - */ - StopFollowingPlayer(param); - - /** - We are done, bug out. - */ - return; - } - else - { - DisplayMenu(BuildPlayerListMenu(), param, MENU_TIME_FOREVER); - } - } -} - -/** -Select Player Menu Callbacks -*/ -public Menu_PlayerList(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - /** - Get the selected player - */ - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - new iTarget = GetClientOfUserId(StringToInt(sSelection)); - - /** - Start following the player - */ - StartFollowingPlayer(param1, iTarget); - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_GENERIC) - { - - /** - Display the last admin menu - */ - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } - else if (param2 == MenuCancel_Exit && GetClientTeam(param1) == g_aCurrentTeams[Spectator]) - { - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_End) - { - - /** - Not a global menu, close it - */ - CloseHandle(menu); - } -} - -public Menu_SelectPlayer(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - - /** - Get the selected player - */ - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (strcmp(sSelection, "Current", false) == 0) - { - /** - Get the current target - */ - new iTarget = GetEntPropEnt(param1, Prop_Send, "m_hObserverTarget"); - - /** - Check to make sure the target is valid - */ - if (iTarget <= 0 || iTarget > MaxClients) - { - PrintToChat(param1, "\x03[SM-SPEC]\x01 %t", "Invalid Target"); - DisplayMenu(BuildPlayerListMenu(), param1, MENU_TIME_FOREVER); - } - - /** - Start following the player - */ - StartFollowingPlayer(param1, iTarget); - } - else - { - - /** - They want to select a player, show the player list - */ - DisplayMenu(BuildPlayerListMenu(), param1, MENU_TIME_FOREVER); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_End) - { - /** - Its a global menu, leave it alive - */ - } -} - -/** -Punishment Menu Callbacks -*/ -public Menu_Punishments(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - - /** - Get the menu selection - */ - new String:sSelection[15]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - - /** - Search for the correct index - */ - new e_Punishments:Index = Punish_None; - for ( ; _:Index <= sizeof(g_sPunishments); Index++) - { - if (StrEqual(sSelection, g_sPunishments[Index])) - { - break; - } - } - - /** - Display the next menu - */ - if (Index == Punish_Ban) - { - - /** - Set the punishment index and display ban time menu - */ - g_aPlayers[param1][TargetPunishment] = Index; - DisplayMenu(g_aMenus[hBanTime], param1, MENU_TIME_FOREVER); - } - else if (Index == Punish_Cheater) - { - - /** - Ask for confirmation before we set punishment index - */ - new Handle:hPanel = BuildAdminCheaterPanel(); - SendPanelToClient(hPanel, param1, Panel_AdminCheater, MENU_TIME_FOREVER); - CloseHandle(hPanel); - } - else - { - - /** - Set the punishment index and display reason menu - */ - g_aPlayers[param1][TargetPunishment] = Index; - DisplayMenu(g_aMenus[hReason], param1, MENU_TIME_FOREVER); - } - } - else if (action == MenuAction_Cancel) - { - - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - else if (action == MenuAction_End) - { - - /** - Not a global menu, close it - */ - CloseHandle(menu); - } -} - -public Menu_BanTime(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - - /** - Get the menu selection - */ - new String:sSelection[15]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - - /** - Set the ban time global - */ - g_aPlayers[param1][iBanTime] = StringToInt(sSelection); - - /** - Display the reason menu - */ - DisplayMenu(g_aMenus[hReason], param1, MENU_TIME_FOREVER); - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_End) - { - /** - Its a global menu, leave it alive - */ - } -} - -public Menu_Reason(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - - /** - Get the menu selection - */ - new String:sSelection[15]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - - /** - Perform the punishment - */ - PerformPunishment(param1, g_aPlayers[param1][iTargetIndex], g_aPlayers[param1][TargetPunishment], sSelection, g_aPlayers[param1][iBanTime]); - - /** - Reactivate the hud if still in spectator - */ - if (GetClientTeam(param1) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_End) - { - /** - Its a global menu, leave it alive - */ - } -} - -public Panel_AdminCheater(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - if (param2 == 1) - { - - /** - Set the punishment index and display reason menu - */ - g_aPlayers[param1][TargetPunishment] = Punish_Cheater; - DisplayMenu(g_aMenus[hReason], param1, MENU_TIME_FOREVER); - } - else - { - - /** - Reactivate the hud if still in spectator - */ - if (GetClientTeam(param1) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(param1); - } - } - } -} - -public Panel_PublicCheater(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - if (param2 == 1) - { - //Waiting for SB 2.0 and sb_submission to be published - } - else - { - - /** - Reactivate the hud if still in spectator - */ - if (GetClientTeam(param1) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(param1); - } - } - } -} - -/** -Hud Menu/Panel Callbacks -*/ -public Menu_PlayerHud(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "stop", false)) - { - StopFollowingPlayer(param1); - } - else if (StrEqual(sSelection, "start", false)) - { - StopDisplayingHud(param1); - DisplayMenu(g_aMenus[hSelectPlayer], param1, MENU_TIME_FOREVER); - } - else if (StrEqual(sSelection, "removecheater", false)) - { - g_aPlayers[g_aPlayers[param1][iTargetIndex]][bIsFlaggedCheater] = false; - } - else if (StrEqual(sSelection, "punish", false)) - { - if (g_aPlayers[param1][iTargetIndex]) - { - StopDisplayingHud(param1); - DisplayMenu(BuildPunishmentMenu(param1), param1, MENU_TIME_FOREVER); - } - else - { - StopDisplayingHud(param1); - PrintToChat(param1, "\x03[SM-SPEC]\x01 %t", "Must Have Target"); - DisplayMenu(g_aMenus[hSelectPlayer], param1, MENU_TIME_FOREVER); - } - } - else if (StrEqual(sSelection, "reportcheater", false)) - { - if (g_aPlayers[param1][iTargetIndex]) - { - StopDisplayingHud(param1); - new Handle:hPanel = BuildPublicCheaterPanel(); - SendPanelToClient(hPanel, param1, Panel_PublicCheater, MENU_TIME_FOREVER); - CloseHandle(hPanel); - } - else - { - StopDisplayingHud(param1); - PrintToChat(param1, "\x03[SM-SPEC]\x01 %t", "Must Have Target"); - DisplayMenu(g_aMenus[hSelectPlayer], param1, MENU_TIME_FOREVER); - } - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_Interrupted) - { - if (GetClientMenu(param1) == MenuSource_External) - { - StopDisplayingHud(param1); - } - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -public Panel_PlayerHud(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - switch (param2) - { - case 1: - { - if (g_aPlayers[param1][iTargetIndex]) - { - StopFollowingPlayer(param1); - } - else - { - StopDisplayingHud(param1); - DisplayMenu(BuildSelectPlayerMenu(), param1, MENU_TIME_FOREVER); - } - } - case 2: - { - if (!g_aPlayers[param1][iTargetIndex]) - { - StopDisplayingHud(param1); - PrintToChat(param1, "\x03[SM-SPEC]\x01 %t", "Must Have Target"); - DisplayMenu(g_aMenus[hSelectPlayer], param1, MENU_TIME_FOREVER); - return; - } - - if ((GetUserFlagBits(param1) & ADMFLAG_GENERIC) || (GetUserFlagBits(param1) & ADMFLAG_ROOT)) - { - if (g_aPlayers[g_aPlayers[param1][iTargetIndex]][bIsFlaggedCheater] && (GetUserFlagBits(param1) & ADMFLAG_ROOT)) - { - //Remove cheater flag - g_aPlayers[g_aPlayers[param1][iTargetIndex]][bIsFlaggedCheater] = false; - } - else - { - //Punish menu - StopDisplayingHud(param1); - DisplayMenu(BuildPunishmentMenu(param1), param1, MENU_TIME_FOREVER); - } - } - else - { - //Report Cheater - new Handle:hPanel = BuildPublicCheaterPanel(); - SendPanelToClient(hPanel, param1, Panel_PublicCheater, MENU_TIME_FOREVER); - CloseHandle(hPanel); - } - } - case 3: - { - StopDisplayingHud(param1); - } - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_Interrupted) - { - if (GetClientMenu(param1) == MenuSource_External) - { - StopDisplayingHud(param1); - } - } - } -} - - -/** -Stock functions -*/ -stock StartFollowingPlayer(client, target) -{ - - /** - If we have an open timer, close it. - */ - if (g_aPlayers[client][hTargetTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[client][hTargetTimer]); - g_aPlayers[client][hTargetTimer] = INVALID_HANDLE; - } - - /** - Make sure the target is on a non spectator team, and the client != target - */ - if (client == target) - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Yourself"); - return; - } - new iTargetTeam = GetClientTeam(target); - if (iTargetTeam == g_aCurrentTeams[Spectator] || iTargetTeam == g_aCurrentTeams[Unknown]) - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Spectator"); - return; - } - - /** - Check to see if client is already a spectator - */ - if (GetClientTeam(client) != g_aCurrentTeams[Spectator]) - { - - /** - Client is not a spectator, lets move them to spec. - */ - SM_MovePlayer(client, g_aCurrentTeams[Spectator]); - } - - /** - If we are using steambans call sb_status - */ - if (g_aPluginSettings[bUseSteamBans]) - { - FakeClientCommandEx(client, "sb_status"); - } - - - /** - Set the global and start to spectate the target. - Making sure it's long enough to deal with moving the client to spec if we had to. - */ - new String:sTargetName[MAX_NAME_LENGTH + 1]; - GetClientName(target, sTargetName, sizeof(sTargetName)); - g_aPlayers[client][iTargetIndex] = target; - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Spectating", sTargetName); - g_aPlayers[client][hTargetTimer] = CreateTimer(0.5, Timer_ResetTarget, client, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); - if (!g_aPlayers[client][bIsDisplayingHud] && GetClientTeam(client) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(client); - } -} - -stock StopFollowingPlayer(client) -{ - - /** - If we have an open timer, close it. - */ - if (g_aPlayers[client][hTargetTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[client][hTargetTimer]); - } - - /** - Tell the client we can't spec his target anymore... if they are in game. - */ - if (IsClientInGame(client) && g_aPlayers[client][iTargetIndex] != 0) - { - new String:sTargetName[MAX_NAME_LENGTH + 1]; - GetClientName(g_aPlayers[client][iTargetIndex], sTargetName, sizeof(sTargetName)); - if (!IsClientConnected(g_aPlayers[client][iTargetIndex]) || !IsClientInGame(g_aPlayers[client][iTargetIndex])) - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Target Left"); - } - else - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Stopped spectating", sTargetName); - } - } - - /** - Null the globals. - */ - g_aPlayers[client][iTargetIndex] = 0; - g_aPlayers[client][hTargetTimer] = INVALID_HANDLE; -} - -stock StartDisplayingHud(client) -{ - if (g_aPluginCvarSettings[bRestrictHud] && !SM_IsValidAdmin(client, g_sAdminFlags)) - { - return; - } - else - { - /** - Double check the hud timer - We should not have one, but if we do, lets cancel it for the current callback - */ - StopDisplayingHud(client); - - /** - Now we can safely display the hud and make sure the current stored handle is the current timer - */ - g_aPlayers[client][bIsDisplayingHud] = true; - g_aPlayers[client][hHudTimer] = CreateTimer(0.5, Timer_UpdateHud, client, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); - } -} - -stock StopDisplayingHud(client) -{ - if (g_aPlayers[client][hHudTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[client][hHudTimer]); - } - g_aPlayers[client][hHudTimer] = INVALID_HANDLE; - g_aPlayers[client][bIsDisplayingHud] = false; -} - -stock ResetClient(client) -{ - StopFollowingPlayer(client); - StopDisplayingHud(client); - - g_aPlayers[client][bIsFlaggedCheater] = false; - g_aPlayers[client][TargetPunishment] = Punish_None; - g_aPlayers[client][iBanTime] = -1; -} - -stock PerformPunishment(client, target, e_Punishments:punishment, const String:reason[], time = 300) -{ - new String:sTargetName[MAX_NAME_LENGTH + 1], - String:sTargetID[64]; - - /** - The target could have left the game by the time we get here - Check for a valid target - */ - if (!IsClientConnected(target) || !IsClientInGame(target)) - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Target Left"); - return; - } - - GetClientName(target, sTargetName, sizeof(sTargetName)); - GetClientAuthString(target, sTargetID, sizeof(sTargetID)); - - switch (punishment) - { - case Punish_Kick: - { - KickClient(g_aPlayers[client][iTargetIndex], "%s", reason); - } - case Punish_Ban: - { - if (g_aPluginSettings[bUseSourceBans]) - { - ClientCommand(client, "sm_ban #%d %d \"%s\"", GetClientUserId(target), time, reason); - } - else if (g_aPluginSettings[bUseMySQLBans]) - { - ClientCommand(client, "mysql_ban #%d %d \"%s\"", GetClientUserId(target), time, reason); - } - else - { - BanClient(target, time, BANFLAG_AUTHID, reason, reason); - } - } - case Punish_Cheater: - { - g_aPlayers[target][bIsFlaggedCheater] = true; - } - case Punish_Beacon: - { - ClientCommand(client, "sm_beacon \"%s\"", sTargetName); - } - case Punish_Blind: - { - ClientCommand(client, "sm_blind \"%s\"", sTargetName); - } - case Punish_Drug: - { - ClientCommand(client, "sm_drug \"%s\"", sTargetName); - } - case Punish_Freeze: - { - ClientCommand(client, "sm_freeze \"%s\"", sTargetName); - } - case Punish_FreezeBomb: - { - ClientCommand(client, "sm_freezebomb \"%s\"", sTargetName); - } - case Punish_Slap: - { - ClientCommand(client, "sm_slap \"%s\" 10", sTargetName); - } - case Punish_Slay: - { - ClientCommand(client, "sm_slay \"%s\"", sTargetName); - } - case Punish_TimeBomb: - { - ClientCommand(client, "sm_timebomb \"%s\"", sTargetName); - } - } - - if (punishment == Punish_Cheater) - { - LogAction(client, target, "[SM SPEC] %N marked %N(%s) with a %s flag for %s", client, target, sTargetID, g_sPunishments[punishment], reason); - } - else - { - ShowActivity(client, "%t", "Punished", sTargetName, g_sPunishments[punishment], reason); - LogAction(client, target, "[SM SPEC] %N punished %N(%s) with a %s for %s", client, target, sTargetID, g_sPunishments[punishment], reason); - } - - /** - Null the globals. - */ - g_aPlayers[client][TargetPunishment] = Punish_None; - g_aPlayers[client][iBanTime] = -1; -} - -/** -Build the menu of player names -*/ -stock Handle:BuildPlayerListMenu() -{ - new Handle:hMenu = CreateMenu(Menu_PlayerList); - AddTargetsToMenu(hMenu, 0, true, false); - SetMenuTitle(hMenu, "Select A Player:"); - SetMenuExitBackButton(hMenu, true); - return hMenu; -} - -/** -Build the select player menu (current or list of players) -*/ -stock Handle:BuildSelectPlayerMenu() -{ - new Handle:hMenu = CreateMenu(Menu_SelectPlayer); - SetMenuTitle(hMenu, "Select A Player:"); - AddMenuItem(hMenu, "Current", "Current Target"); - AddMenuItem(hMenu, "List", "Player List"); - SetMenuExitBackButton(hMenu, true); - return hMenu; -} - -/** -Build the punishmenu menu -*/ -stock Handle:BuildPunishmentMenu(iClient) -{ - new Handle:hMenu = CreateMenu(Menu_Punishments); - SetMenuTitle(hMenu, "Select A Punishment:"); - SetMenuExitBackButton(hMenu, true); - SetMenuExitButton(hMenu, true); - - if (g_aPluginCvarSettings[bKick] && ((GetUserFlagBits(iClient) & ADMFLAG_GENERIC) || (GetUserFlagBits(iClient) & ADMFLAG_ROOT))) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Kick], "Kick"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Kick], "Kick", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bBan] && ((GetUserFlagBits(iClient) & ADMFLAG_GENERIC) || (GetUserFlagBits(iClient) & ADMFLAG_ROOT))) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Ban], "Ban"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Ban], "Ban", ITEMDRAW_DISABLED); - } - - if (g_aPluginSettings[bUseDukehacks] && g_aPluginCvarSettings[bCheater] && (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Cheater], "Flag As Cheater"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Cheater], "Flag As Cheater", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bBeacon]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Beacon], "Beacon"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Beacon], "Beacon", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bBlind]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Blind], "Blind"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Blind], "Blind", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bDrug]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Drug], "Drug"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Drug], "Drug", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bFreeze]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Freeze], "Freeze"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Freeze], "Freeze", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bFreezebomb]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_FreezeBomb], "Freeze Bomb"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_FreezeBomb], "Freeze Bomb", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bSlap]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Slap], "Slap"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Slap], "Slap", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bSlay]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Slay], "Slay"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Slay], "Slay", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bTimeBomb]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_TimeBomb], "Time Bomb"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_TimeBomb], "Time Bomb", ITEMDRAW_DISABLED); - } - - return hMenu; -} - -/** -Build the punishmenu menu -*/ -stock Handle:BuildBanTimeMenu() -{ - new Handle:hMenu = CreateMenu(Menu_BanTime); - SetMenuTitle(hMenu, "Select Ban Type:"); - - if (g_aPluginCvarSettings[bBanPerm]) - { - AddMenuItem(hMenu, "permban", "Permanent"); - } - else - { - AddMenuItem(hMenu, "permban", "Permanent", ITEMDRAW_DISABLED); - } - - AddMenuItem(hMenu, "10", "10 Minutes"); - AddMenuItem(hMenu, "30", "30 Minutes"); - AddMenuItem(hMenu, "60", "1 Hour"); - AddMenuItem(hMenu, "240", "4 Hours"); - AddMenuItem(hMenu, "1440", "1 Day"); - AddMenuItem(hMenu, "10080", "1 Week"); - - SetMenuExitBackButton(hMenu, true); - return hMenu; -} - -/** -Build the punishmenu menu -*/ -stock Handle:BuildReasonMenu() -{ - new Handle:hMenu = CreateMenu(Menu_Reason); - SetMenuTitle(hMenu, "Select A Reason:"); - - AddMenuItem(hMenu, "Abusive", "Abusive"); - AddMenuItem(hMenu, "Racism", "Racism"); - AddMenuItem(hMenu, "General cheating/exploits", "General cheating/exploits"); - AddMenuItem(hMenu, "Wallhack", "Wallhack"); - AddMenuItem(hMenu, "Aimbot", "Aimbot"); - AddMenuItem(hMenu, "Speedhacking", "Speedhacking"); - AddMenuItem(hMenu, "Mic spamming", "Mic spamming"); - AddMenuItem(hMenu, "Admin disrepect", "Admin disrepect"); - AddMenuItem(hMenu, "Camping", "Camping"); - AddMenuItem(hMenu, "Team killing", "Team killing"); - AddMenuItem(hMenu, "Unacceptable Spray", "Unacceptable Spray"); - AddMenuItem(hMenu, "Breaking Server Rules", "Breaking Server Rules"); - AddMenuItem(hMenu, "Other", "Other"); - - SetMenuExitBackButton(hMenu, true); - return hMenu; -} - -/** -Build the cheater displays -*/ -stock Handle:BuildAdminCheaterPanel() -{ - - /** - Create the menu and set the menu options. - */ - new Handle:hPanel = CreatePanel(); - SetPanelTitle(hPanel, "Simple Spectator:"); - - DrawPanelText(hPanel, "Are you sure you want to"); - DrawPanelText(hPanel, "flag this player as a cheater?"); - DrawPanelText(hPanel, "They will not be able to damage"); - DrawPanelText(hPanel, "anyone and die on fall damage."); - DrawPanelItem(hPanel, "Yes"); - DrawPanelItem(hPanel, "No"); - - return hPanel; -} - -stock Handle:BuildPublicCheaterPanel() -{ - - /** - Create the menu and set the menu options. - */ - new Handle:hPanel = CreatePanel(); - SetPanelTitle(hPanel, "Simple Spectator:"); - - DrawPanelText(hPanel, "Are you sure you want to"); - DrawPanelText(hPanel, "submit this player as a cheater?"); - DrawPanelItem(hPanel, "Yes (Not Implemented Yet)", ITEMDRAW_DISABLED); - DrawPanelItem(hPanel, "No"); - return hPanel; -} - -/** -Build the hud displays -*/ -stock Handle:BuildPlayerHudMenu(iClient, iTarget) -{ - - /** - Create all the string variables we will need - */ - new String:sTargetName[MAX_NAME_LENGTH + 1], - String:sTargetID[64], - String:sTargetIP[16]; - - new String:sDisplayName[MAX_NAME_LENGTH + 1], - String:sDisplayID[64], - String:sDisplayIP[64], - String:sDisplayFrags[16], - String:sDisplayDeaths[16]; - - new iTargetFrags, - iTargetDeaths; - - /** - Get the targets information - */ - GetClientName(iTarget, sTargetName, sizeof(sTargetName)); - GetClientIP(iTarget, sTargetIP, sizeof(sTargetIP)); - GetClientAuthString(iTarget, sTargetID, sizeof(sTargetID)); - iTargetFrags = GetClientFrags(iTarget); - iTargetDeaths = GetClientDeaths(iTarget); - - /** - Format the strings for the menu - */ - Format(sDisplayName, sizeof(sDisplayName), "Player: %s", sTargetName); - Format(sDisplayID, sizeof(sDisplayID), "Steam ID: %s", sTargetID); - Format(sDisplayIP, sizeof(sDisplayIP), "IP Address: %s", sTargetIP); - Format(sDisplayFrags, sizeof(sDisplayFrags), "Kills: %i", iTargetFrags); - Format(sDisplayDeaths, sizeof(sDisplayDeaths), "Deaths: %i", iTargetDeaths); - - /** - Create the menu and set the menu options. - */ - new Handle:hMenu = CreateMenu(Menu_PlayerHud); - SetMenuExitBackButton(hMenu, false); - SetMenuTitle(hMenu, "Simple Spectator"); - - AddMenuItem(hMenu, "name", sDisplayName, ITEMDRAW_DISABLED); - AddMenuItem(hMenu, "steamid", sDisplayID, ITEMDRAW_DISABLED); - - if (SM_IsValidAdmin(iClient, g_sAdminFlags)) - { - AddMenuItem(hMenu, "ip", sDisplayIP, ITEMDRAW_DISABLED); - } - - AddMenuItem(hMenu, "kills", sDisplayFrags, ITEMDRAW_DISABLED); - AddMenuItem(hMenu, "deaths", sDisplayDeaths, ITEMDRAW_DISABLED); - - if (g_aPlayers[iClient][iTargetIndex]) - { - AddMenuItem(hMenu, "stop", "Stop Following"); - } - else - { - AddMenuItem(hMenu, "start", "Follow Player"); - } - - if ((GetUserFlagBits(iClient) & ADMFLAG_GENERIC) || (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - if (g_aPlayers[iTarget][bIsFlaggedCheater] && (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - AddMenuItem(hMenu, "removecheater", "Remove Cheater Flag"); - } - else - { - if (CanUserTarget(iClient, iTarget)) - { - AddMenuItem(hMenu, "punish", "Punish Player"); - } - else - { - AddMenuItem(hMenu, "punish", "Punish Player (Immune)", ITEMDRAW_DISABLED); - } - } - } - else - { - AddMenuItem(hMenu, "reportcheater", "Report Cheater"); - } - - SetMenuPagination(hMenu, MENU_NO_PAGINATION); - SetMenuExitButton(hMenu, true); - return hMenu; -} - -stock Handle:BuildPlayerHudPanel(iClient, iTarget) -{ - - /** - Create all the string variables we will need - */ - new String:sTargetName[MAX_NAME_LENGTH + 1], - String:sTargetID[64], - String:sTargetIP[16]; - - new String:sDisplayName[MAX_NAME_LENGTH + 1], - String:sDisplayID[64], - String:sDisplayIP[64], - String:sDisplayFrags[16], - String:sDisplayDeaths[16]; - - new iTargetFrags, - iTargetDeaths; - - /** - Get the targets information - */ - GetClientName(iTarget, sTargetName, sizeof(sTargetName)); - GetClientIP(iTarget, sTargetIP, sizeof(sTargetIP)); - GetClientAuthString(iTarget, sTargetID, sizeof(sTargetID)); - iTargetFrags = GetClientFrags(iTarget); - iTargetDeaths = GetClientDeaths(iTarget); - - /** - Format the strings for the menu - */ - Format(sDisplayName, sizeof(sDisplayName), "Player: %s", sTargetName); - Format(sDisplayID, sizeof(sDisplayID), "Steam ID: %s", sTargetID); - Format(sDisplayIP, sizeof(sDisplayIP), "IP Address: %s", sTargetIP); - Format(sDisplayFrags, sizeof(sDisplayFrags), "Kills: %i", iTargetFrags); - Format(sDisplayDeaths, sizeof(sDisplayDeaths), "Deaths: %i", iTargetDeaths); - - /** - Create the menu and set the menu options. - */ - new Handle:hPanel = CreatePanel(); - SetPanelTitle(hPanel, "Simple Spectator"); - - DrawPanelText(hPanel, "Player Information:"); - DrawPanelText(hPanel, sDisplayName); - DrawPanelText(hPanel, sDisplayID); - if (SM_IsValidAdmin(iClient, g_sAdminFlags)) - { - DrawPanelText(hPanel, sDisplayIP); - } - - DrawPanelText(hPanel, sDisplayFrags); - DrawPanelText(hPanel, sDisplayDeaths); - - if (g_aPlayers[iClient][iTargetIndex]) - { - DrawPanelItem(hPanel, "Stop Following"); - } - else - { - DrawPanelItem(hPanel, "Follow Player"); - } - - if ((GetUserFlagBits(iClient) & ADMFLAG_GENERIC) || (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - if (g_aPlayers[iTarget][bIsFlaggedCheater] && (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - DrawPanelItem(hPanel, "Remove Cheater Flag"); - } - else - { - if (CanUserTarget(iClient, iTarget)) - { - DrawPanelItem(hPanel, "Punish Player"); - } - else - { - DrawPanelItem(hPanel, "Punish Player (Immune)", ITEMDRAW_DISABLED); - } - } - } - else - { - DrawPanelItem(hPanel, "Report Cheater"); - } - - DrawPanelItem(hPanel, "Close Hud Panel"); - return hPanel; -} - -/** -Adjust the settings if a convar was changed -*/ -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - for (new iCvar = 0 ; _:iCvar < sizeof(g_aPluginCvarSettings); iCvar++) - { - if (g_aPluginCvar[_:iCvar] == convar) - { - if (StringToInt(newValue) == 1) - { - g_aPluginCvarSettings[_:iCvar] = true; - } - else - { - g_aPluginCvarSettings[_:iCvar] = false; - } - } - } - - /* - ReBuild the global menu that depends on cvars - */ - g_aMenus[hBanTime] = BuildBanTimeMenu(); - - /** - Run a loop to reset the hud - */ - for(new i = 1; i <= MaxClients; i++) - { - StopDisplayingHud(i); - if (IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(i); - } - } -} diff --git a/Simple Round Immunity/addons/sourcemod/scripting/simple-teambalancer.sp b/Simple Round Immunity/addons/sourcemod/scripting/simple-teambalancer.sp deleted file mode 100644 index 3302255..0000000 --- a/Simple Round Immunity/addons/sourcemod/scripting/simple-teambalancer.sp +++ /dev/null @@ -1,1797 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Team Balancer -Description: - Balances teams based upon player count - Player will not be balanced more than once in 5 (default) mins - Buddy system tries to keep buddies together - Ability to prioritize players - Ability to force players to accept the new team - Admins are immune -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include -#include - -#define PLUGIN_VERSION "2.1.$Rev$" - -enum PlayerData -{ - Handle:hBalanceTimer, - Handle:hForcedTimer, - bool:bSwitched, - bool:bFlagCarrier -}; - -/** - Global convar handles - */ -new Handle:stb_enabled = INVALID_HANDLE; -new Handle:stb_buddyenabled = INVALID_HANDLE; -new Handle:stb_logactivity = INVALID_HANDLE; -new Handle:stb_logactivity2 = INVALID_HANDLE; -new Handle:stb_unbalancelimit = INVALID_HANDLE; -new Handle:stb_deadonly = INVALID_HANDLE; -new Handle:stb_priorityenabled = INVALID_HANDLE; -new Handle:stb_uberlevel = INVALID_HANDLE; -new Handle:stb_balancedelay = INVALID_HANDLE; -new Handle:stb_livingplayerswitchdelay = INVALID_HANDLE; -new Handle:stb_livingplayercheckdelay = INVALID_HANDLE; -new Handle:stb_roundstartdelay = INVALID_HANDLE; -new Handle:stb_switchbackforced = INVALID_HANDLE; -new Handle:stb_adminflag = INVALID_HANDLE; -new Handle:stb_buddyrestriction = INVALID_HANDLE; -new Handle:stb_convarcontrol = INVALID_HANDLE; - -/** - Built-in cvars handles - */ -new Handle:stb_mp_autoteambalance = INVALID_HANDLE; -new Handle:stb_mp_teams_unbalance_limit = INVALID_HANDLE; -new Handle:TFGameModeArena = INVALID_HANDLE; - -/** - Timer handles - */ -new Handle:g_hBalanceTimer = INVALID_HANDLE; -new Handle:g_hLivingPlayerCheckTimer = INVALID_HANDLE; - -/** - Player arrays - */ -new g_aPlayers[MAXPLAYERS + 1][PlayerData]; - -/** -Global bools -*/ -new bool:g_bIsEnabled = true; -new bool:g_bPriorityPlayers = true; -new bool:g_bBuddyRestriction = false; -new bool:g_bLogActivity = false; -new bool:g_bLogActivity2 = false; -new bool:g_bDeadOnly = false; -new bool:g_bConVarControl = true; -new bool:g_bBuddyEnabled = true; -new bool:g_bBalanceInProgress = false; -new bool:g_bRoundStart = false; -new bool:g_bRoundEnd = false; -new bool:g_bSuddenDeath = false; -new bool:g_bIsArenaMode = false; - -/** - Global strings/integers/floats - */ -new g_iUnbalanceLimit, g_iLivingPlayerSwitchDelay, g_iLivingPlayerCheckDelay; -new g_iRoundStartDelay, g_iSwitchBackForced, g_iBalanceDelay; -new Float:g_fUberLevel; -new g_iOwnerOffset; -new String:g_sAdminFlag[5]; - -public Plugin:myinfo = -{ - name = "Simple Team Balancer", - author = "Simple Plugins", - description = "Balances teams based upon player count.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -} - -public OnPluginStart() -{ - - /** - Create console variables - */ - CreateConVar("stb_version", PLUGIN_VERSION, "Simple Team Balancer", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - stb_enabled = CreateConVar("stb_enabled", "1", "Enable or Disable Simple Team Balancer", _, true, 0.0, true, 1.0); - stb_priorityenabled = CreateConVar("stb_priorityenabled", "1", "Enable or Disable the prioritization of living players", _, true, 0.0, true, 1.0); - stb_buddyrestriction = CreateConVar("stb_buddyrestriction", "0", "Enable or Disable Admin Only buddy lists", _, true, 0.0, true, 1.0); - stb_logactivity = CreateConVar("stb_logactivity", "0", "Enable or Disable the disaplying of events in the log", _, true, 0.0, true, 1.0); - stb_logactivity2 = CreateConVar("stb_logactivity2", "0", "Enable or Disable the disaplying of detailed events in the log (WILL SPAM LOG)", _, true, 0.0, true, 1.0); - stb_deadonly = CreateConVar("stb_deadonly", "0", "Enable or Disable the switching of only dead players", _, true, 0.0, true, 1.0); - stb_convarcontrol = CreateConVar("stb_convarcontrol", "1", "Enable or Disable the control of builtin console variables", _, true, 0.0, true, 1.0); - stb_buddyenabled = CreateConVar("stb_buddyenabled", "1", "Enable or Disable the buddy system", _, true, 0.0, true, 1.0); - stb_unbalancelimit = CreateConVar("stb_unbalancelimit", "2", "Amount of players teams are ALLOWED to be unbalanced by", _, true, 1.0, true, 32.0); - stb_balancedelay = CreateConVar("stb_balancedelay", "10", "Delay in seconds to start an autobalance"); - stb_livingplayerswitchdelay = CreateConVar("stb_livingplayerswitchdelay", "20", "Delay in seconds to switch living players once selected"); - stb_livingplayercheckdelay = CreateConVar("stb_livingplayercheckdelay", "10", "Delay in seconds to start checking living players once teams become unbalanced"); - stb_roundstartdelay = CreateConVar("stb_roundstartdelay", "15", "Delay in seconds to start balancing teams after the start of a round"); - stb_switchbackforced = CreateConVar("stb_switchbackforced", "300", "Amount of time in seconds to not switch a player twice and force the team if enabled"); - stb_uberlevel = CreateConVar("stb_uberlevel", "1.0", "Min uber level medic must have to have priority over other living players. Setting to 0 will rarely switch a living medic", _, true, 0.0, true, 1.0); - stb_adminflag = CreateConVar("stb_adminflag", "a", "Admin flag to use for immunity. Must be a in char format."); - stb_mp_autoteambalance = FindConVar("mp_autoteambalance"); - stb_mp_teams_unbalance_limit = FindConVar("mp_teams_unbalance_limit"); - - /** - Removing the notify tags from the built in cvars. We dont want spam. - */ - if (stb_mp_autoteambalance != INVALID_HANDLE) - { - SetConVarFlags(stb_mp_autoteambalance, GetConVarFlags(stb_mp_autoteambalance)^FCVAR_NOTIFY); - } - if (stb_mp_teams_unbalance_limit != INVALID_HANDLE) - { - SetConVarFlags(stb_mp_teams_unbalance_limit, GetConVarFlags(stb_mp_teams_unbalance_limit)^FCVAR_NOTIFY); - } - - /** - Hook console variables - */ - HookConVarChange(stb_enabled, ConVarSettingsChanged); - HookConVarChange(stb_priorityenabled, ConVarSettingsChanged); - HookConVarChange(stb_buddyrestriction, ConVarSettingsChanged); - HookConVarChange(stb_logactivity, ConVarSettingsChanged); - HookConVarChange(stb_logactivity2, ConVarSettingsChanged); - HookConVarChange(stb_deadonly, ConVarSettingsChanged); - HookConVarChange(stb_convarcontrol, ConVarSettingsChanged); - HookConVarChange(stb_buddyenabled, ConVarSettingsChanged); - HookConVarChange(stb_unbalancelimit, ConVarSettingsChanged); - HookConVarChange(stb_balancedelay, ConVarSettingsChanged); - HookConVarChange(stb_livingplayerswitchdelay, ConVarSettingsChanged); - HookConVarChange(stb_livingplayercheckdelay, ConVarSettingsChanged); - HookConVarChange(stb_roundstartdelay, ConVarSettingsChanged); - HookConVarChange(stb_switchbackforced, ConVarSettingsChanged); - HookConVarChange(stb_uberlevel, ConVarSettingsChanged); - HookConVarChange(stb_mp_autoteambalance, ConVarSettingsChanged); - HookConVarChange(stb_mp_teams_unbalance_limit, ConVarSettingsChanged); - - /** - Create console commands - */ - RegConsoleCmd("sm_buddy", Command_AddBalanceBuddy, "Add a balance buddy"); - RegConsoleCmd("sm_lockbuddy", Command_LockBuddy, "Locks your balance buddy selection"); - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[STB] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_death", HookPlayerDeath, EventHookMode_Post); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Post); - switch (g_CurrentMod) - { - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - HookEvent("teamplay_suddendeath_begin", HookSuddenDeathBegin, EventHookMode_PostNoCopy); - HookEvent("teamplay_flag_event", HookFlagEvent, EventHookMode_Post); - TFGameModeArena = FindConVar("tf_gamemode_arena"); - g_iOwnerOffset = FindSendPropInfo("CBaseObject", "m_hBuilder"); - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_Post); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - - /** - Load translations and .cfg file - */ - LoadTranslations ("simpleteambalancer.phrases"); - AutoExecConfig(true, "plugin.simpleteambalancer"); - LogAction(0, -1, "[STB] Simple Team Balancer is loaded."); -} - -public OnAllPluginsLoaded() -{ - //something -} - -public OnLibraryRemoved(const String:name[]) -{ - //something -} - -public OnConfigsExecuted() -{ - - /** - Load up global variables - */ - g_bIsEnabled = GetConVarBool(stb_enabled); - g_bBuddyEnabled = GetConVarBool(stb_buddyenabled); - g_bLogActivity = GetConVarBool(stb_logactivity); - g_bLogActivity2 = GetConVarBool(stb_logactivity2); - g_bDeadOnly = GetConVarBool(stb_deadonly); - g_bPriorityPlayers = GetConVarBool(stb_priorityenabled); - g_bBuddyRestriction = GetConVarBool(stb_buddyrestriction); - g_bConVarControl = GetConVarBool(stb_convarcontrol); - g_fUberLevel = GetConVarFloat(stb_uberlevel); - g_iUnbalanceLimit = GetConVarInt(stb_unbalancelimit); - g_iBalanceDelay = GetConVarInt(stb_balancedelay); - g_iLivingPlayerSwitchDelay = GetConVarInt(stb_livingplayerswitchdelay); - g_iLivingPlayerCheckDelay = GetConVarInt(stb_livingplayercheckdelay); - g_iRoundStartDelay = GetConVarInt(stb_roundstartdelay); - g_iSwitchBackForced = GetConVarInt(stb_switchbackforced); - GetConVarString(stb_adminflag, g_sAdminFlag, sizeof(g_sAdminFlag)); - - /** - Report enabled - */ - if (g_bIsEnabled) - { - LogAction(0, -1, "[STB] Simple Team Balancer is ENABLED."); - } - else - { - LogAction(0, -1, "[STB] Simple Team Balancer is DISABLED."); - } - - - /** - Report log activity - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Log Activity ENABLED."); - } - else - { - LogAction(0, -1, "[STB] Log Activity DISABLED."); - } - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Detailed Log Activity ENABLED."); - } - else - { - LogAction(0, -1, "[STB] Detailed Log Activity DISABLED."); - } -} - -public OnMapStart() -{ - - /** - Check for arena mode - */ - if (g_CurrentMod == GameType_TF && GetConVarBool(TFGameModeArena)) - { - g_bIsArenaMode = true; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Simple Team Balancer detected arena mode and will be bypassed"); - } - } - else - { - g_bIsArenaMode = false; - } - - /** - Reset the globals - */ - g_bBalanceInProgress = false; - g_bRoundStart = false; - g_bRoundEnd = false; - g_bSuddenDeath = false; - - /** - Set the built-in convars - */ - SetGameCvars(); -} - -public OnClientPostAdminCheck(client) -{ - - /** - Make sure its a valid connected client and buddy system is enabled - */ - if (client == 0 || !g_bIsEnabled || !IsClientConnected(client) || !g_bBuddyEnabled) - { - return; - } - - /** - Make sure if its set for admins only they have the flags - */ - if (g_bBuddyRestriction && !SM_IsValidAdmin(client, g_sAdminFlag)) - { - return; - } - - /** - Start the advertisement timer - */ - CreateTimer (60.0, Timer_WelcomeAdvert, client); -} - -public OnClientDisconnect(client) -{ - - /** - Call stock function to cleaup - */ - CleanUp(client); -} - -public OnClientDisconnect_Post(client) -{ - - /** - Determine if we need a balance - */ - if (OkToBalance() && IsUnbalanced() && !g_bBalanceInProgress) - { - - /** - No balance in progress but balance is needed - */ - StartABalance(); - } -} - -public SM_OnPlayerMoved(Handle:plugin, client, team) -{ - - /** - Make sure we called the move function - */ - if (plugin != GetMyHandle()) - { - if (g_bLogActivity2) - { - LogAction(0, client, "[STB] Callback was not started with current plugin, bugging out."); - } - return; - } - - /** - Get the players name and report the event - */ - decl String:sPlayerName[64]; - GetClientName(client, sPlayerName, sizeof(sPlayerName)); - if (g_bLogActivity) - { - LogAction(0, client, "[STB] Changed %s to team %i.", sPlayerName, team); - } - - /** - If we are in TF2 fire the bult-in team balance event - */ - if(g_CurrentMod == GameType_TF) - { - new Handle:event = CreateEvent("teamplay_teambalanced_player"); - SetEventInt(event, "player", client); - SetEventInt(event, "team", team); - FireEvent(event); - } - - /** - Notify the players - */ - PrintToChatAll("[SM] %T", "BalanceMessage", LANG_SERVER, sPlayerName); - - /** - Set the players variables and start a timer - */ - g_aPlayers[client][bSwitched] = true; - g_aPlayers[client][hForcedTimer] = CreateTimer(float(g_iSwitchBackForced), Timer_ForcedExpired, client, TIMER_FLAG_NO_MAPCHANGE); - - /** - We are done, log the completion and end the balance - */ - if (g_bLogActivity) - { - LogAction(0, client, "[STB] Balance finished."); - } - g_bBalanceInProgress = false; -} - -/* HOOKED EVENTS */ - -public HookPlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get our event variables - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - decl String:sWeapon[64]; - GetEventString(event, "weapon", sWeapon, sizeof(sWeapon)); - - /** - Return if death was not caused by a player - This is the case when the player switches teams - */ - if (StrEqual(sWeapon, "world", false)) - { - return; - } - - - /** - Check if balance is needed - */ - if (IsClientInGame(iClient) && OkToBalance() && IsUnbalanced()) - { - new iSmallerTeam = GetSmallerTeam(); - - /** - Check if balance is in progress - */ - if (g_bBalanceInProgress) - { - - /** - There is a balance in progress - Check the player who died to see if he is supposed to be switched - */ - if (g_aPlayers[iClient][hBalanceTimer] != INVALID_HANDLE) - { - - /** - The player has a timer on him to switch him to other team - Stop the timer - */ - CloseHandle(g_aPlayers[iClient][hBalanceTimer]); - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] With a balance in progress the queued living player died and was switched."); - } - - /** - Call the stock change team function - */ - BalancePlayer(iClient, SM_GetForcedTeam(iClient)); - return; - } - - /** - Before we continue, lets make sure the client is switchable - */ - if (IsSwitchablePlayer(iClient, GetBiggerTeam())) - { - - /** - Now we check the buddy system - */ - if (g_bBuddyEnabled) - { - - /** - Buddy system is enabled, check to see if client has buddy - */ - new iBuddyIndex = SM_GetClientBuddy(iClient); - if (iBuddyIndex != 0 || !IsClientConnected(iBuddyIndex) || !IsClientInGame(iBuddyIndex)) - { - - /** - The client has a buddy, so we check to see if they are on same team - */ - if (GetClientTeam(iClient) == GetClientTeam(iBuddyIndex)) - { - - /** - They are, but we don't bug out, we still need to start a balance - */ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] With a balance in progress a buddy on the right team was found and skipped."); - } - } - else - { - - /** - They are not on the same team - The buddy could be in spec, and that would make it not matter where he is, or the buddy is on the smaller team - */ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] With a balance in progress a buddy on the wrong team was switched."); - } - BalancePlayer(iClient, iSmallerTeam); - return; - } - } - else - { - - /** - Client doesn't have a buddy, balance this player - */ - BalancePlayer(iClient, iSmallerTeam); - return; - } - } - else - { - - /** - Buddy system is not enabled, balance this player - */ - BalancePlayer(iClient, iSmallerTeam); - return; - } - } - } - else - { - - /** - If we get to here then we must need to start a balance - */ - StartABalance(); - } - } -} - -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get our event variables. - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - new iTeam = GetEventInt(event, "team"); - - /** - Make sure its ok to balance. - */ - if (OkToBalance()) - { - - /** - See if the client that changed teams was set to with a balance. - */ - if (g_aPlayers[iClient][hBalanceTimer] != INVALID_HANDLE - && SM_GetForcedTeam(iClient) == iTeam - && g_bBalanceInProgress) - { - - /** - The client was set to be balanced, so we close the timer. - */ - CloseHandle(g_aPlayers[iClient][hBalanceTimer]); - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - - /** - Stop the balance. - */ - g_bBalanceInProgress = false; - return; - } - - /** - It's not likely that this team change can cause us to need a balance. - If it does, start one with a small dealy to deal with forced switch backs. - */ - if (IsUnbalanced() && !g_bBalanceInProgress) - { - CreateTimer(2.0, Timer_ChangeTeamBalanceDelay, _, TIMER_FLAG_NO_MAPCHANGE); - } - } -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set the variables we need to start a round - */ - g_bRoundStart = true; - g_bRoundEnd = false; - g_bSuddenDeath = false; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Round Started"); - } - - /** - Start a delayed balance check at the start of the round - */ - CreateTimer(float(g_iRoundStartDelay), Timer_RoundStart); -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set the variables we need at round end - */ - g_bRoundEnd = true; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Round Ended"); - } -} - -public HookSuddenDeathBegin(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set the variables we need for sudden death - */ - g_bSuddenDeath = true; -} - -public HookFlagEvent(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get our event variables - */ - new iClient = GetEventInt(event, "player"); - new iFlagStatus = GetEventInt(event, "eventtype"); - - /** - Make sure we have a valid client - */ - if (!IsClientInGame(iClient)) - { - return; - } - - /** - Determine what kind of event this is - */ - switch (iFlagStatus) - { - case 1: - { - - /** - The flag was picked up - */ - g_aPlayers[iClient][bFlagCarrier] = true; - } - case 2: - { - - /** - The flag was capped - */ - g_aPlayers[iClient][bFlagCarrier] = false; - } - case 3: - { - - /** - The flag was defended, we don't have to do anything - */ - } - case 4: - { - - /** - The flag was dropped - */ - g_aPlayers[iClient][bFlagCarrier] = false; - } - } -} - -/* COMMAND EVENTS */ - -public Action:Command_AddBalanceBuddy(client, args) -{ - if (client == 0) - { - ReplyToCommand(client, "[SM] %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - if (!g_bIsEnabled || !g_bBuddyEnabled) - { - ReplyToCommand(client, "[SM] %T", "CmdDisabled", LANG_SERVER); - return Plugin_Handled; - } - if (g_bBuddyRestriction) - { - if (!SM_IsValidAdmin(client, g_sAdminFlag)) - { - ReplyToCommand(client, "[SM] %T", "RestrictedBuddy", LANG_SERVER); - return Plugin_Handled; - } - } - decl String:sPlayerUserId[24]; - GetCmdArg(1, sPlayerUserId, sizeof(sPlayerUserId)); - new iPlayer = GetClientOfUserId(StringToInt(sPlayerUserId)); - if (!iPlayer || !IsClientInGame(iPlayer) || client == iPlayer) - { - if (client == iPlayer) - { - PrintHintText(client, "%T", "SelectSelf", LANG_SERVER); - } - ReplyToCommand(client, "[SM] Usage: buddy "); - new Handle:playermenu = BuildPlayerMenu(); - DisplayMenu(playermenu, client, MENU_TIME_FOREVER); - } - else - { - decl String:cName[128]; - decl String:bName[128]; - GetClientName(client, cName, sizeof(cName)); - GetClientName(iPlayer, bName, sizeof(bName)); - if (SM_IsBuddyLocked(iPlayer)) - { - ReplyToCommand(client, "[SM] %T", "PlayerLockedBuddyMsg", LANG_SERVER, bName); - return Plugin_Handled; - } - SM_AssignBuddy(client, iPlayer); - PrintHintText(client, "%T", "BuddyMsg", LANG_SERVER, bName); - PrintHintText(iPlayer, "%T", "BuddyMsg", LANG_SERVER, cName); - } - return Plugin_Handled; -} - -public Action:Command_LockBuddy(client, args) -{ - if (client == 0) - { - ReplyToCommand(client, "[SM] %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - if (!g_bIsEnabled) - { - ReplyToCommand(client, "[SM] %T", "CmdDisabled", LANG_SERVER); - return Plugin_Handled; - } - if (g_bBuddyRestriction) - { - if (!SM_IsValidAdmin(client, g_sAdminFlag)) - { - ReplyToCommand(client, "[SM] %T", "RestrictedBuddy", LANG_SERVER); - return Plugin_Handled; - } - } - if (SM_IsBuddyLocked(client)) - { - SM_LockBuddy(client, false); - PrintHintText(client, "%T", "BuddyLockMsgDisabled", LANG_SERVER); - } - else - { - SM_LockBuddy(client, true); - PrintHintText(client, "%T", "BuddyLockMsgEnabled", LANG_SERVER); - } - return Plugin_Handled; -} - -/** -Stock functions . - */ - -stock bool:IsUnbalanced() -{ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Checking if teams are unbalanced"); - } - new Team1Count = GetTeamClientCount(g_aCurrentTeams[Team1]); - new Team2Count = GetTeamClientCount(g_aCurrentTeams[Team2]); - new ubCount = RoundFloat(FloatAbs(float(Team1Count - Team2Count))); - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Team1:%i Team2:%i Difference:%i", Team1Count, Team2Count, ubCount); - } - if (ubCount > g_iUnbalanceLimit) - { - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Teams are unbalanced"); - } - return true; - } - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Teams are not unbalanced"); - } - return false; -} - -stock bool:OkToBalance() -{ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Checking if OK to balance."); - } - new bool:bResult = false; - if (g_bIsEnabled && !g_bRoundStart && !g_bRoundEnd && !g_bIsArenaMode && !g_bSuddenDeath) - { - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Passed IF statement"); - LogAction(0, -1, "[STB] Now checking admins"); - } - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientInGame(i) && !SM_IsValidAdmin(i, g_sAdminFlag)) - { - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Found at least 1 non-admin"); - LogAction(0, -1, "[STB] OK to balance"); - } - bResult = true; - break; - } - } - if (!bResult && g_bLogActivity2) - { - LogAction(0, -1, "[STB] All admins online"); - } - } - if (!bResult && g_bLogActivity2) - { - LogAction(0, -1, "[STB] Not OK to balance"); - } - return bResult; -} - -stock bool:IsSwitchablePlayer(iClient, iBiggerTeam) -{ - - /** - Run the client thru some standard checks - */ - if (!IsClientInGame(iClient) - || SM_IsValidAdmin(iClient, g_sAdminFlag) - || g_aPlayers[iClient][bFlagCarrier] - || GetClientTeam(iClient) != iBiggerTeam - || g_aPlayers[iClient][bSwitched]) - { - - /** - The supplied client can't be switched - */ - return false; - } - - /** - The supplied client can be switched - */ - return true; -} - -stock bool:HasUber(iClient) -{ - - /** - First things first, make sure the client is a medic - */ - if(TF2_GetPlayerClass(iClient) == TFClass_Medic) - { - - /** - We can only check the active weapon, so make sure the client is holding the uber gun - */ - decl String:sWeaponName[32]; - GetClientWeapon(iClient, sWeaponName, sizeof(sWeaponName)); - if(StrEqual(sWeaponName, "tf_weapon_medigun")) - { - - /** - They are, so lets check the uber level of the gun - */ - new iEntityIndex = GetEntDataEnt2(iClient, FindSendPropInfo("CTFPlayer", "m_hActiveWeapon")); - new Float:fChargeLevel = GetEntDataFloat(iEntityIndex, FindSendPropInfo("CWeaponMedigun", "m_flChargeLevel")); - if (fChargeLevel >= g_fUberLevel) - { - - /** - The client supplied has an uber above the supplied level, return true - */ - if (g_bLogActivity2) - { - LogAction(0, iClient, "[STB] Found a medic with a uber and skipped him."); - } - return true; - } - } - } - - /** - The client supplied does not have an uber above the supplied level, return false - */ - return false; -} - -stock bool:HasBuildingsBuilt(iClient) -{ - - /** - We have to start a loop to check the owner of all the valid entities - */ - new iMaxEntities = GetMaxEntities(); - for (new i = MaxClients + 1; i <= iMaxEntities; i++) - { - if (!IsValidEntity(i)) - { - - /** - Not valid, continue to next one - */ - continue; - } - - /** - Get the name of the current entity - */ - decl String:sNetClass[32]; - GetEntityNetClass(i, sNetClass, sizeof(sNetClass)); - - /** - See if its something that an engineer would build - */ - if (strcmp(sNetClass, "CObjectSentrygun") == 0 - || strcmp(sNetClass, "CObjectTeleporter") == 0 - || strcmp(sNetClass, "CObjectDispenser") == 0) - { - - /** - It is, so lets check the owner - */ - if (GetEntDataEnt2(i, g_iOwnerOffset) == iClient) - { - - /** - The client supplied is the owner, return true - */ - if (g_bLogActivity2) - { - LogAction(0, iClient, "[STB] Found an engineer with buildings and skipped him."); - } - return true; - } - } - } - - /** - The client supplied didn't have any buildings, return false - */ - return false; -} - -stock StartABalance() -{ - - /** - See if we are already started a balance - */ - if (g_hBalanceTimer != INVALID_HANDLE) - { - - /** - We have, check if we still need to - */ - if (!IsUnbalanced() || !OkToBalance()) - { - - /** - We don't, stop the balance - It's almost impossible to reach this code, but we do it just in case - */ - CloseHandle(g_hBalanceTimer); - g_hBalanceTimer = INVALID_HANDLE; - g_bBalanceInProgress = false; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Balance delay timer was not needed and was killed before the callback."); - } - return; - } - else - { - - /** - We still need to balance - Bug out and wait for the current one to finish - */ - return; - } - } - - /** - Report that teams are unbalanced - */ - PrintToChatAll("[SM] %T", "UnBalanced", LANG_SERVER); - - /** - Check to see if we are supposed to delay the balance - */ - if (g_iBalanceDelay == 0) - { - - /** - Start the balance now - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Balance is now in progress."); - } - g_bBalanceInProgress = true; - g_hBalanceTimer = INVALID_HANDLE; - - /** - Check if we are allowed to scan living players - */ - if (!g_bDeadOnly) - { - - /** - We are allowed to, so we start a timer - */ - StartALivingPlayerTimer(); - - /** - Also report that we are now scanning dead players as well - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Now scanning dead players."); - } - } - else - { - - /** - We are not allowed to, so report that we are only scanning dead players - */ - if (g_bLogActivity) - LogAction(0, -1, "[STB] Only scanning dead players."); - } - - /** - We started the balance, bug out - */ - return; - } - - /** - We are supposed to delay the balance, start a balance timer - */ - g_hBalanceTimer = CreateTimer(float(g_iBalanceDelay), Timer_BalanceTeams, _, TIMER_FLAG_NO_MAPCHANGE); - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Teams are unbalanced. Balance delay timer started."); - } -} - -stock StartALivingPlayerTimer() -{ - - /** - Start a timer to check living players - */ - if (g_hLivingPlayerCheckTimer != INVALID_HANDLE) - { - - /** - If we for some reason already have one started, stop it. - */ - CloseHandle(g_hLivingPlayerCheckTimer); - g_hLivingPlayerCheckTimer = INVALID_HANDLE; - } - - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Living player balance delay timer started."); - } - g_hLivingPlayerCheckTimer = CreateTimer(float(g_iLivingPlayerCheckDelay), Timer_LivingPlayerCheck, _, TIMER_FLAG_NO_MAPCHANGE); -} - -stock FindSwitchablePlayer() -{ - - /** - Start a loop to find a switchable player - */ - new iPlayer; - new iBiggerTeam = GetBiggerTeam(); - for (new i = 1; i <= MaxClients; i++) - { - - /** - Check the stock function to see if we are allows to even switch the player - */ - if (!IsSwitchablePlayer(i, iBiggerTeam)) - { - continue; - } - - /** - If the mod is TF2 and they have Priority Players set check if the client has buildings or an uber - */ - if (g_CurrentMod == GameType_TF && g_bPriorityPlayers) - { - if (HasUber(i) || HasBuildingsBuilt(i)) - { - continue; - } - } - - /** - So far we are able we switch this player - Now we check the buddy system - */ - if (g_bBuddyEnabled) - { - - /** - Buddy system is enabled, check to see if client has buddy - */ - if (SM_GetClientBuddy(i) != 0) - { - - /** - The client has a buddy, so we check to see if they are on same team - */ - if (GetClientTeam(i) == GetClientTeam(SM_GetClientBuddy(i))) - { - - /** - They are, so we continue to next client - */ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] With a balance in progress a buddy on the right team was found and skipped."); - } - continue; - } - else - { - - /** - They are not on the same team, set this client - The buddy could be in spec, and that would make it not matter where he is, or the buddy is on the smaller team - */ - iPlayer = i; - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] With a balance in progress a buddy on the wrong team was found."); - } - break; - } - } - else - { - - /** - The client does not have a buddy, set this client - */ - iPlayer = i; - break; - } - } - else - { - - /** - Buddy system is not enabled, set this client - */ - iPlayer = i; - break; - } - } - - /** - Return the client we set, this could be 0, but very unlikely - */ - return iPlayer; -} - -stock BalancePlayer(iClient, iTeam) -{ - new Handle:hPack = CreateDataPack(); - WritePackCell(hPack, iClient); - WritePackCell(hPack, iTeam); - CreateTimer(0.1, Timer_BalancePlayer, hPack, TIMER_FLAG_NO_MAPCHANGE); -} - -stock CleanUp(iClient) -{ - g_aPlayers[iClient][bFlagCarrier] = false; - g_aPlayers[iClient][bSwitched] = false; - if (g_aPlayers[iClient][hForcedTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hForcedTimer]); - g_aPlayers[iClient][hForcedTimer] = INVALID_HANDLE; - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] Forced player disconnected, killing timer."); - } - } - if (g_aPlayers[iClient][hBalanceTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hBalanceTimer]); - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] Living player set to be balanced disconnected, killing timer."); - } - } -} - -stock GetSmallerTeam() -{ - - /** - Get the count of players on each team - */ - new iCountT1 = GetTeamClientCount(g_aCurrentTeams[Team1]); - new iCountT2 = GetTeamClientCount(g_aCurrentTeams[Team2]); - - /** - Return the smaller team - */ - if (iCountT1 < iCountT2) - { - return g_aCurrentTeams[Team1]; - } - else if (iCountT1 > iCountT2) - { - return g_aCurrentTeams[Team2]; - } - return 0; -} - -stock GetBiggerTeam() -{ - - /** - Get the count of players on each team - */ - new iCountT1 = GetTeamClientCount(g_aCurrentTeams[Team1]); - new iCountT2 = GetTeamClientCount(g_aCurrentTeams[Team2]); - - /** - Return the bigger team - */ - if (iCountT1 > iCountT2) - { - return g_aCurrentTeams[Team1]; - } - else if (iCountT1 < iCountT2) - { - return g_aCurrentTeams[Team2]; - } - return 0; -} - -stock SetGameCvars() -{ - if (g_bConVarControl && g_bIsEnabled) - { - if (stb_mp_autoteambalance != INVALID_HANDLE) - { - SetConVarInt(stb_mp_autoteambalance, 0); - } - if (stb_mp_teams_unbalance_limit != INVALID_HANDLE) - { - SetConVarInt(stb_mp_teams_unbalance_limit, g_iUnbalanceLimit); - } - } -} - -/* TIMER FUNCTIONS */ - -public Action:Timer_ChangeTeamBalanceDelay(Handle:timer, any:data) -{ - - /** - Finally start one if it's still unbalanced - */ - if (IsUnbalanced() && !g_bBalanceInProgress) - { - StartABalance(); - } -} - -public Action:Timer_BalanceTeams(Handle:timer, any:data) -{ - - /** - See if we still need to balance the teams - */ - if (!IsUnbalanced() || !OkToBalance()) - { - - /** - We don't, kill the balance - */ - g_bBalanceInProgress = false; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Balance delay timer was not needed and died."); - } - g_hBalanceTimer = INVALID_HANDLE; - return Plugin_Handled; - } - - /** - We still need to balance the teams - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Teams are still unbalanced. Balance is now in progress."); - } - g_bBalanceInProgress = true; - - - /** - Check if we are allowed to scan living players - */ - if (!g_bDeadOnly) - { - - /** - We are allowed to, so we start a timer - */ - StartALivingPlayerTimer(); - - /** - Also report that we are now scanning dead players as well - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Now scanning dead players."); - } - } - else - { - - /** - We are not allowed to, so report that we are only scanning dead players - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Only scanning dead players."); - } - } - - g_hBalanceTimer = INVALID_HANDLE; - return Plugin_Handled; -} - -public Action:Timer_LivingPlayerCheck(Handle:timer, any:data) -{ - - /** - Check to see if we still need to balance the teams - */ - if (!IsUnbalanced() || !OkToBalance()) - { - - /** - We don't, kill it and bug out - */ - g_bBalanceInProgress = false; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Living player balance delay timer was not needed and died."); - } - g_hLivingPlayerCheckTimer = INVALID_HANDLE; - return Plugin_Handled; - } - - /** - Call the stock function to find a player we can switch - */ - new iPlayer = FindSwitchablePlayer(); - - /** - Check to see if we found a player - */ - if (iPlayer == 0) - { - - /** - In the unlikely event that the stock function didn't return a player - Start a loop to find a random player - */ - new iBiggerTeam = GetBiggerTeam(); - do - { - iPlayer = GetRandomInt(1, MaxClients); - } while (!IsSwitchablePlayer(iPlayer, iBiggerTeam)); - - if (g_bLogActivity) - { - LogAction(0, iPlayer, "[STB] Found a random living player."); - } - } - else - { - if (g_bLogActivity) - { - LogAction(0, iPlayer, "[STB] Found a living player."); - } - } - - /** - Now that we have a player assigned them to the smaller team - */ - new iSmallerTeam = GetSmallerTeam(); - SM_SetForcedTeam(iPlayer, iSmallerTeam, true); - - /** - Let the player know we could be switching him soon - */ - PrintHintText(iPlayer, "%T", "PlayerMessage", LANG_SERVER, g_iLivingPlayerSwitchDelay); - if (g_bLogActivity) - { - LogAction(0, iPlayer, "[STB] Living player placed on a timer."); - } - - /** - Create a timer to switch the player - */ - g_aPlayers[iPlayer][hBalanceTimer] = CreateTimer(float(g_iLivingPlayerSwitchDelay), Timer_LivingPlayerBalance, iPlayer, TIMER_FLAG_NO_MAPCHANGE); - - /** - Reset the timer handle - */ - g_hLivingPlayerCheckTimer = INVALID_HANDLE; - - /** - We are done, bug out - */ - return Plugin_Handled; -} - -public Action:Timer_LivingPlayerBalance(Handle:timer, any:iClient) -{ - - /** - Check to make sure we still need to balance - */ - if (!IsUnbalanced() || !OkToBalance()) - { - - /** - We don't need to balance, bug out - */ - g_bBalanceInProgress = false; - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - SM_ClearForcedTeam(iClient); - return Plugin_Handled; - } - - /** - We still need to balance, lets make sure we can still balance this player - */ - if (!IsClientConnected(iClient) || g_aPlayers[iClient][bFlagCarrier]) - { - g_bBalanceInProgress = false; - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - SM_ClearForcedTeam(iClient); - if (g_bLogActivity) - { - if (g_aPlayers[iClient][bFlagCarrier]) - { - LogAction(0, iClient, "[STB] Living player became flag carrier, balance restarted."); - } - else - { - LogAction(0, iClient, "[STB] Living player timer was not needed and died."); - } - } - return Plugin_Handled; - } - - /** - Clear to balance this player, so do it - */ - BalancePlayer(iClient, SM_GetForcedTeam(iClient)); - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] Living player was switched."); - } - - /** - We are done, bug out - */ - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - return Plugin_Handled; -} - -public Action:Timer_BalancePlayer(Handle:timer, Handle:pack) -{ - - /** - Rest the datapack and load the variables - */ - ResetPack(pack); - new iClient = ReadPackCell(pack); - new iUnBalancedTeam = ReadPackCell(pack); - - /** - We are done with you now - */ - CloseHandle(pack); - - /** - Check the team and make sure its a valid team - */ - if(!SM_IsValidTeam(iUnBalancedTeam)) - { - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] Balance failed due to invalid team number %i", iUnBalancedTeam); - } - return Plugin_Handled; - } - - /** - Use our core function to change the clients team - */ - SM_MovePlayer(iClient, iUnBalancedTeam); - - return Plugin_Handled; -} - -public Action:Timer_RoundStart(Handle:timer, any:data) -{ - g_bRoundStart = false; - if (OkToBalance() && IsUnbalanced() && !g_bBalanceInProgress) - { - StartABalance(); - } - return Plugin_Handled; -} - -public Action:Timer_ForcedExpired(Handle:timer, any:iClient) -{ - SM_ClearForcedTeam(iClient); - g_aPlayers[iClient][bSwitched] = false; - g_aPlayers[iClient][hForcedTimer] = INVALID_HANDLE; - return Plugin_Handled; -} - -public Action:Timer_WelcomeAdvert(Handle:timer, any:iClient) -{ - if (IsClientConnected(iClient) && IsClientInGame(iClient)) - { - PrintToChat (iClient, "\x01\x04[STB]\x01 %T", "BuddyWelcomeMsg1", LANG_SERVER); - PrintToChat (iClient, "\x01\x04[STB]\x01 %T", "BuddyWelcomeMsg2", LANG_SERVER); - PrintToChat (iClient, "\x01\x04[STB]\x01 %T", "BuddyWelcomeMsg3", LANG_SERVER); - } - return Plugin_Handled; -} - -/* CONSOLE VARIABLE CHANGE EVENT */ - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (convar == stb_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsEnabled = false; - PrintToChatAll("[SM] %T", "Disabled", LANG_SERVER); - LogAction(0, -1, "[SimpleTeamBalancer] Disabled"); - } - else - { - g_bIsEnabled = true; - SetGameCvars(); - PrintToChatAll("[SM] %T", "Enabled", LANG_SERVER); - LogAction(0, -1, "[SimpleTeamBalancer] Enabled"); - } - } - else if (convar == stb_logactivity) - { - if (StringToInt(newValue) == 0) - { - g_bLogActivity = false; - LogAction(0, -1, "[STB] Log Activity DISABLED."); - } - else - { - g_bLogActivity = true; - LogAction(0, -1, "[STB] Log Activity ENABLED."); - } - } - else if (convar == stb_logactivity2) - { - if (StringToInt(newValue) == 0) - { - g_bLogActivity2 = false; - LogAction(0, -1, "[STB] Detailed Log Activity DISABLED."); - } - else - { - g_bLogActivity2 = true; - LogAction(0, -1, "[STB] Detailed Log Activity ENABLED."); - } - } - else if (convar == stb_convarcontrol) - { - if (StringToInt(newValue) == 0) - { - g_bConVarControl = false; - } - else - { - g_bConVarControl = true; - SetGameCvars(); - } - } - else if (convar == stb_deadonly) - { - if (StringToInt(newValue) == 0) - { - g_bDeadOnly = false; - } - else - { - g_bDeadOnly = true; - } - } - else if (convar == stb_priorityenabled) - { - if (StringToInt(newValue) == 0) - { - g_bPriorityPlayers = false; - } - else - { - g_bPriorityPlayers = true; - } - } - else if (convar == stb_buddyenabled) - { - if (StringToInt(newValue) == 0) - { - g_bBuddyEnabled = false; - } - else - { - g_bBuddyEnabled = true; - } - } - else if (convar == stb_buddyrestriction) - { - if (StringToInt(newValue) == 0) - { - g_bBuddyRestriction = false; - } - else - { - g_bBuddyRestriction = true; - } - } - else if (convar == stb_unbalancelimit) - { - g_iUnbalanceLimit = StringToInt(newValue); - SetGameCvars(); - } - else if (convar == stb_balancedelay) - { - g_iBalanceDelay = StringToInt(newValue); - } - else if (convar == stb_roundstartdelay) - { - g_iRoundStartDelay = StringToInt(newValue); - } - else if (convar == stb_livingplayerswitchdelay) - { - g_iLivingPlayerSwitchDelay = StringToInt(newValue); - } - else if (convar == stb_livingplayercheckdelay) - { - g_iLivingPlayerCheckDelay = StringToInt(newValue); - } - else if (convar == stb_uberlevel) - { - g_fUberLevel = StringToFloat(newValue); - } - else if (convar == stb_switchbackforced) - { - g_iSwitchBackForced = StringToInt(newValue); - } - else if (convar == stb_adminflag) - { - SetConVarString(stb_adminflag, newValue); - } - else if (convar == stb_mp_autoteambalance) - { - SetGameCvars(); - } - else if (convar == stb_mp_teams_unbalance_limit) - { - SetGameCvars(); - } -} - -/* MENU CODE */ - -stock Handle:BuildPlayerMenu() -{ - new Handle:menu = CreateMenu(Menu_SelectPlayer); - AddTargetsToMenu(menu, 0, true, false); - SetMenuTitle(menu, "Select A Player:"); - SetMenuExitButton(menu, true); - return menu; -} - -public Menu_SelectPlayer(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - new buddy = GetClientOfUserId(StringToInt(sSelection)); - if (param1 == buddy) { - PrintHintText(param1, "%T", "SelectSelf", LANG_SERVER); - } else if (!IsClientInGame(buddy)) { - PrintHintText(param1, "%T", "BuddyGone", LANG_SERVER); - } else { - decl String:cName[128]; - decl String:bName[128]; - GetClientName(param1, cName, sizeof(cName)); - GetClientName(buddy, bName, sizeof(bName)); - if (!SM_IsBuddyLocked(buddy)) { - SM_AssignBuddy(param1, buddy); - PrintHintText(param1, "%T", "BuddyMsg", LANG_SERVER, bName); - PrintHintText(buddy, "%T", "BuddyMsg", LANG_SERVER, cName); - } else - PrintHintText(param1, "%T", "PlayerLockedBuddyMsg", LANG_SERVER, bName); - } - } else if (action == MenuAction_End) { - CloseHandle(menu); - } -} \ No newline at end of file diff --git a/Simple Round Immunity/addons/sourcemod/scripting/simple-teammanager.sp b/Simple Round Immunity/addons/sourcemod/scripting/simple-teammanager.sp deleted file mode 100644 index 008f443..0000000 --- a/Simple Round Immunity/addons/sourcemod/scripting/simple-teammanager.sp +++ /dev/null @@ -1,1351 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Team Manager -Description: - Manges players and their team - Admin menu integration - Allows admins/donators to swap their teams (clears force)* - Allows admins to move players to a team (forced\unforced)* - Allows admins to scramble the teams* - *Works with Simple Team Balancer (if installed) -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include - -#define PLUGIN_VERSION "2.1.$Rev$" -#define VOTE_YES "##YES##" -#define VOTE_NO "##NO##" - -enum PlayerData -{ - iNewTeam, - bool:bQueue -}; - -new Handle:stm_enabled = INVALID_HANDLE; -new Handle:stm_logactivity = INVALID_HANDLE; -new Handle:stm_adminflag_swapteam = INVALID_HANDLE; -new Handle:stm_adminflag_moveplayer = INVALID_HANDLE; -new Handle:stm_adminflag_scramble = INVALID_HANDLE; -new Handle:stm_scrambledelay = INVALID_HANDLE; -new Handle:stm_voteenabled = INVALID_HANDLE; -new Handle:stm_votewin = INVALID_HANDLE; -new Handle:stm_votedelay = INVALID_HANDLE; -new Handle:stm_mp_bonusroundtime = INVALID_HANDLE; -new Handle:g_hAdminMenu = INVALID_HANDLE; -new Handle:g_hTimerPrepScramble = INVALID_HANDLE; -new Handle:g_hTimerClearScrambleForce = INVALID_HANDLE; - -new g_aPlayers[MAXPLAYERS + 1][PlayerData]; - -new bool:g_bIsEnabled = true; -new bool:g_bVoteEnabled = true; -new bool:g_bLogActivity = true; -new bool:g_bScrambleRoundEnd = false; -new g_iVoteDelay, g_iLastVoteTime, g_iTimeLeft; -new Float:g_fScrambleDelay, Float:g_fVoteWin; - -public Plugin:myinfo = -{ - name = "Simple Team Manager", - author = "Simple Plugins", - description = "Manages players and thier team.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -public OnPluginStart() -{ - - /** - Need to create all of our console variables. - */ - CreateConVar("stm_version", PLUGIN_VERSION, "Simple Team Manager Version",FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - stm_enabled = CreateConVar("stm_enabled", "1", "Enable or Disable Simple Team Manager", _, true, 0.0, true, 1.0); - stm_logactivity = CreateConVar("stm_logactivity", "0", "Enable or Disable the disaplying of events in the log", _, true, 0.0, true, 1.0); - stm_adminflag_swapteam = CreateConVar("stm_adminflag_swapteam", "a", "Admin flag to use for the swapteam command. Must be a in char format."); - stm_adminflag_moveplayer = CreateConVar("stm_adminflag_moveplayer", "c", "Admin flag to use for the moveplayer command. Must be a in char format."); - stm_adminflag_scramble = CreateConVar("stm_adminflag_scramble", "c", "Admin flag to use for the scrambleteam command. Must be a in char format."); - stm_scrambledelay = CreateConVar("stm_scrambledelay", "15", "Delay to scramble teams"); - stm_voteenabled = CreateConVar("stm_voteenabled", "1", "Enable or Disable voting to scramble the teams", _, true, 0.0, true, 1.0); - stm_votewin = CreateConVar("stm_votewin", "0.45", "Win percentage vote must win by", _, true, 0.0, true, 1.0); - stm_votedelay = CreateConVar("stm_votedelay", "600", "Delay before another vote can be cast"); - stm_mp_bonusroundtime = FindConVar("mp_bonusroundtime"); - - - /** - Need deal with changes to the console variables after the plugin is loaded. - We could not do this and just call the actual console variable each time we need it, but it's not efficent. - */ - HookConVarChange(stm_enabled, ConVarSettingsChanged); - HookConVarChange(stm_logactivity, ConVarSettingsChanged); - HookConVarChange(stm_scrambledelay, ConVarSettingsChanged); - HookConVarChange(stm_voteenabled, ConVarSettingsChanged); - HookConVarChange(stm_votewin, ConVarSettingsChanged); - HookConVarChange(stm_votedelay, ConVarSettingsChanged); - - /** - Need to register the commands we are going to create and use. - */ - RegConsoleCmd("sm_swapteam", Command_SwapTeam, "sm_swapteam <[0]instant/[1]queued>: Swaps your team to the other team"); - RegConsoleCmd("sm_moveplayer", Command_MovePlayer, "sm_moveplayer <[0]instant/[1]ondeath> <[0]unforced/[1]forced>: Moves a player to the specified team"); - RegConsoleCmd("sm_scrambleteams", Command_ScrambleTeams, "sm_scrambleteams: <[0]now/[1]roundend> <[0]dontrestart/[1]restartround> Scrambles the current teams"); - RegConsoleCmd("sm_votescramble", Command_VoteScramble, "sm_votescramble: Starts a vote to scramble the teams"); - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[STM] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_death", HookPlayerDeath, EventHookMode_Post); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Post); - switch (g_CurrentMod) - { - case GameType_TF: - { - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - } - case GameType_DOD: - { - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_Post); - } - default: - { - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - - /** - Now we have to deal with the admin menu. If the admin library is loaded call the function to add our items. - */ - new Handle:gTopMenu; - if (LibraryExists("adminmenu") && ((gTopMenu = GetAdminTopMenu()) != INVALID_HANDLE)) - { - OnAdminMenuReady(gTopMenu); - } - - /** - Load translations and .cfg file - */ - LoadTranslations ("simpleteammanager.phrases"); - AutoExecConfig(true, "plugin.simpleteammanager"); - LogAction(0, -1, "[STM] Simple Team Manager is loaded."); -} - -public OnAllPluginsLoaded() -{ - //something -} - -public OnLibraryRemoved(const String:name[]) -{ - if (StrEqual(name, "adminmenu")) - { - - /** - Looks like the admin menu was removed. Set the global. - */ - g_hAdminMenu = INVALID_HANDLE; - } - else if (StrEqual(name, "simpleplugins")) - { - SetFailState("Required plugin Simple SourceMod Plugins Core was removed."); - } -} - -public OnConfigsExecuted() -{ - - /** - Once we loaded up all the console variables from the config file, lets now set all the global variables we will use. - */ - g_bIsEnabled = GetConVarBool(stm_enabled); - g_bLogActivity = GetConVarBool(stm_logactivity); - g_fScrambleDelay = GetConVarFloat(stm_scrambledelay); - g_iVoteDelay = GetConVarInt(stm_votedelay); - g_fVoteWin = GetConVarFloat(stm_votewin); - g_iLastVoteTime = RoundFloat(GetEngineTime()); - g_bScrambleRoundEnd = false; - g_hTimerClearScrambleForce = INVALID_HANDLE; - - /** - Report enabled - */ - if (g_bIsEnabled) - { - LogAction(0, -1, "[STM] Simple Team Manager is ENABLED."); - } - else - { - LogAction(0, -1, "[STM] Simple Team Manager is DISABLED."); - } - - if (g_bLogActivity) - { - LogAction(0, -1, "[STM] Log Activity ENABLED."); - } - else - { - LogAction(0, -1, "[STM] Log Activity DISABLED."); - } -} - -/* COMMANDS */ - -public Action:Command_SwapTeam(client, args) -{ - - /** - Make sure we are enabled, if not bug out. - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - If this was ran from the console bug out. - */ - if (client == 0) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure the client is authorized to run this command. - */ - decl String:sFlags[5]; - GetConVarString(stm_adminflag_swapteam, sFlags, sizeof(sFlags)); - if (!SM_IsValidAdmin(client, sFlags)) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Lets make sure the client is one a team we can swap. - If he is we set the global array to the opposite team. - */ - new iTeam = GetClientTeam(client); - if (iTeam == g_aCurrentTeams[Team1]) - { - g_aPlayers[client][iNewTeam] = g_aCurrentTeams[Team2]; - } - else if (iTeam == g_aCurrentTeams[Team2]) - { - g_aPlayers[client][iNewTeam] = g_aCurrentTeams[Team1]; - } - else - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "InValidTeam", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check to see if we have command arguments. - */ - if (GetCmdArgs()) - { - - /** - We do, so lets get it and see if the client wants to be switched instantly or queued for death. - */ - decl String:sArg[5]; - GetCmdArg(1, sArg, sizeof(sArg)); - new iWantsQue = StringToInt(sArg); - if (iWantsQue && !g_aPlayers[client][bQueue]) - { - - /** - He wants the que and isn't already in it, set the global array. - */ - g_aPlayers[client][bQueue] = true; - ReplyToCommand(client, "\x01\x04[STM]\x01 %T", "PlayerQueue", LANG_SERVER); - } - else if (!iWantsQue) - { - - /** - He wants to be switched right now, lets call the stock function. - */ - SM_MovePlayer(client, g_aPlayers[client][iNewTeam]); - } - } - else - { - - /** - There are no command arguments so we build and display the swap menu. - */ - DisplaySwapModeMenu(client, client); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_MovePlayer(client, args) -{ - - /** - Make sure we are enabled, if not bug out. - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the client is authorized to run this command. - */ - decl String:sFlags[5]; - GetConVarString(stm_adminflag_moveplayer, sFlags, sizeof(sFlags)); - if (!SM_IsValidAdmin(client, sFlags)) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check to see if we have command arguments. - */ - new iCmdArgs = GetCmdArgs(); - if (iCmdArgs == 0) - { - - /** - We don't. Build the player menu, display it, and bug out. - */ - DisplayPlayerMenu(client); - return Plugin_Handled; - } - - /** - Check the first argument - If should be a players name or userid. - */ - decl String:sPlayer[64]; - GetCmdArg(1, sPlayer, sizeof(sPlayer)); - new iPlayerIndex = FindTarget(client, sPlayer, true, true); - if (iPlayerIndex == -1 || !IsClientInGame(iPlayerIndex)) - { - - /** - We don't know who this is. Build the player menu, display it, and bug out. - */ - DisplayPlayerMenu(client); - return Plugin_Handled; - } - - /** - We have figured out the first argument, lets check the second. - If should be the team the client wants to put the player on. - */ - if (iCmdArgs >= 2) - { - - /** - We have a command argument at least, lets see if we can identify the team. - */ - decl String:sTeam[24]; - GetCmdArg(2, sTeam, sizeof(sTeam)); - - new iTeam = StringToInt(sTeam); - if (SM_IsValidTeam(iTeam)) - { - - /** - It's a vaild team so lets set the global array to the new team. - */ - g_aPlayers[iPlayerIndex][iNewTeam] = iTeam; - } - else - { - - /** - It's not a vaild team so set the menu to display to the team menu. - */ - DisplayTeamMenu(client, iPlayerIndex); - return Plugin_Handled; - } - } - else - { - /** - We were not given a team, display the team menu. - */ - DisplayTeamMenu(client, iPlayerIndex); - return Plugin_Handled; - } - - /** - Check to see if we were given any more command arguments and found a team. - */ - if (iCmdArgs < 3) - { - - /** - No more command arguments and found a team. - Now lets check to see if the player is a spectator. If he is there is no reason to ask if it's instant or on death... he can't die. - */ - if (!IsClientObserver(iPlayerIndex)) - { - - /** - Not a spectator so display the swapmode menu. - */ - DisplaySwapModeMenu(client, iPlayerIndex); - } - else - { - - /** - The player is a spectator. - We make sure the player is not set to switch on death, since a spec can't die. - */ - g_aPlayers[iPlayerIndex][bQueue] = false; - } - } - - /** - We have figured out the second argument, lets check the third. - If should be the how the client wants to move the player: instant/on death. - */ - if (iCmdArgs >= 3) - { - - /** - The client gave us a command argument, lets check it. - */ - decl String:sSwapMode[5]; - GetCmdArg(3, sSwapMode, sizeof(sSwapMode)); - new iWantsQue = StringToInt(sSwapMode); - if (iWantsQue) - { - - /** - The client wants to que the player, set the global array. - */ - g_aPlayers[iPlayerIndex][bQueue] = true; - } - else - { - - /** - The client doesn't want to que the player, set the global array. - */ - g_aPlayers[iPlayerIndex][bQueue] = false; - } - } - else - { - /** - No swapmode argument, display the menu - */ - DisplaySwapModeMenu(client, iPlayerIndex); - } - - if (iCmdArgs >= 4) - { - - /** - Since we are compiling for Simple Team Balancer, and given a 4th argument, lets check it. - If should be the if the client wants to force the player to that team. - */ - decl String:sPlayerForced[5]; - GetCmdArg(4, sPlayerForced, sizeof(sPlayerForced)); - new iForceHim = StringToInt(sPlayerForced); - if (iForceHim) - { - - /** - The client wants to force the player - */ - SM_SetForcedTeam(iPlayerIndex, g_aPlayers[iPlayerIndex][iNewTeam]); - } - else - { - - /** - The client doesn't want to force the player - */ - SM_ClearForcedTeam(iPlayerIndex); - } - } - else - { - - } - - /** - We found and processed all the arguments. - */ - if (!IsPlayerAlive(iPlayerIndex)) - { - - /** - The player is not alive or died during this process so we just move him. - */ - SM_MovePlayer(iPlayerIndex, g_aPlayers[iPlayerIndex][iNewTeam]); - } - else - { - if (!g_aPlayers[iPlayerIndex][bQueue]) - { - - /** - The player is alive and is not set to be queued so we just move him. - */ - SM_MovePlayer(iPlayerIndex, g_aPlayers[iPlayerIndex][iNewTeam]); - } - } - - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_ScrambleTeams(client, args) -{ - - /** - Make sure we are enabled, if not bug out. - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the client is authorized to run this command. - */ - decl String:sFlags[5]; - GetConVarString(stm_adminflag_scramble, sFlags, sizeof(sFlags)); - if (!SM_IsValidAdmin(client, sFlags)) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check if a scramble timer was already called, if so close it down. - */ - if (g_hTimerPrepScramble != INVALID_HANDLE) - { - CloseHandle(g_hTimerPrepScramble); - g_hTimerPrepScramble = INVALID_HANDLE; - } - - /** - Check if we have any command arguments. - If we don't we display the scramble menu and bug out. - */ - new iCmdArgs = GetCmdArgs(); - if (iCmdArgs == 0) - { - DisplayScrambleMenu(client); - return Plugin_Handled; - } - - /** - We have a command argument. - It should be whether or not to scramble at round end. - */ - decl String:sRoundEnd[5]; - GetCmdArg(1, sRoundEnd, sizeof(sRoundEnd)); - if (StringToInt(sRoundEnd)) - { - /** - The client wants to scramble at round end so we set the global bool. - */ - g_bScrambleRoundEnd = true; - } - else - { - g_bScrambleRoundEnd = false; - } - - /** - Check for another command argument. - It should be whether or not to restart the round. - */ - decl String:sRestartRound[5]; - new bool:bRestartRound = false; - GetCmdArg(1, sRestartRound, sizeof(sRestartRound)); - if (StringToInt(sRestartRound)) - { - bRestartRound = true; - } - - /** - Now we start the scramble timer. - */ - StartScrambleTimer(_, bRestartRound); - - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_VoteScramble(client, args) -{ - - /** - Make sure we are enabled, if not bug out. - */ - if (!g_bVoteEnabled || !g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Make sure there is a vote in progress, if so bug out. - */ - if (IsVoteInProgress()) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "VoteInProgress", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure enough time has passed since the last vote. - */ - new iVoteTime = RoundFloat(GetEngineTime()); - if (iVoteTime - g_iLastVoteTime <= g_iVoteDelay) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "ScrambleTime", LANG_SERVER); - return Plugin_Handled; - } - - /** - Enough time has passed so reset the global vote time to now. - */ - g_iLastVoteTime = iVoteTime; - - /** - Build the vote menu and send it to everyone. - */ - new Handle:hMenu = CreateMenu(Menu_VoteScramble); - SetMenuTitle(hMenu, "Scramble Teams?"); - AddMenuItem(hMenu, VOTE_YES, "Yes"); - AddMenuItem(hMenu, VOTE_NO, "No"); - SetMenuExitButton(hMenu, false); - VoteMenuToAll(hMenu, 20); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -/* HOOKED EVENTS */ - -public HookPlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Find out who died. - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - - /** - Find out how the client died. - */ - new String:sWeapon[64]; - GetEventString(event, "weapon", sWeapon, sizeof(sWeapon)); - if (StrEqual(sWeapon, "world", false)) - { - - /** - He died because he changed teams so cleanup and bug out. - */ - s_CleanUp(iClient); - return; - } - - /** - Find out if this player was queued to change teams. - */ - if (g_aPlayers[iClient][bQueue]) - { - /** - Looks like he was, so call the stock function to move him. - */ - SM_MovePlayer(iClient, g_aPlayers[iClient][iNewTeam]); - } -} - -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Find out who changed teams. - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - - /** - If he was queued to switch teams we cleanup the variables. The client did it themself. - */ - if (g_aPlayers[iClient][bQueue]) - { - s_CleanUp(iClient); - } -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get the amount of time left in the map. - */ - new iTimeLeft; - GetMapTimeLeft(iTimeLeft); - - /** - Check to see if we are supposed to scramble at the end of the round and that there is enough time left in the map. - */ - if (g_bScrambleRoundEnd && iTimeLeft >= 60) - { - - /** - Check to see if there is a scramble timer in action and if so close it down. - */ - if (g_hTimerPrepScramble != INVALID_HANDLE) - { - CloseHandle(g_hTimerPrepScramble); - g_hTimerPrepScramble = INVALID_HANDLE; - } - - /** - Determine the round end chat time and run the scramble 1 second before it ends. - */ - new Float:fDelay = GetConVarFloat(stm_mp_bonusroundtime); - fDelay -= 1.0; - StartScrambleTimer(fDelay); - } -} - -public OnClientPostAdminCheck(client) -{ - - /** - Determine if the client has the flag to use the swapteam command. - */ - decl String:sFlags[5]; - GetConVarString(stm_adminflag_swapteam, sFlags, sizeof(sFlags)); - if (SM_IsValidAdmin(client, sFlags)) - { - /** - The client does so lets create a timer to run an advertise to tell him about it. - */ - CreateTimer (60.0, Timer_WelcomeAdvert, client); - } -} - -public OnClientDisconnect(client) -{ - - /** - Cleanup the clients variables. - */ - s_CleanUp(client); -} - -public SM_OnPlayerMoved(Handle:plugin, client, team) -{ - - /** - Make sure we called the move function - */ - if (plugin != GetMyHandle()) - { - if (g_bLogActivity) - { - LogAction(0, client, "[STM] Callback was not started with current plugin, bugging out."); - } - return; - } - - decl String:sPlayerName[64]; - GetClientName(client, sPlayerName, sizeof(sPlayerName)); - - PrintToChat(client, "\x01\x04[SM]\x01 %T", "PlayerSwitched", LANG_SERVER); - - s_CleanUp(client); -} - -/* TIMER FUNCTIONS */ - -public Action:Timer_PrepTeamScramble(Handle:timer, any:data) -{ - new bool:bRestartRound = data; - /** - Call the scramble the teams stock function. - */ - PrepTeamScramble(bRestartRound); - - /** - Reset the timer handle so we know the timer is done. - */ - g_hTimerPrepScramble = INVALID_HANDLE; - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Timer_ScrambleTheTeams(Handle:timer, any:data) -{ - new iPlayers[MAXPLAYERS + 1]; - new iCount, i, bool:bTeam, bool:bRestartRound = data; - - /** - Get all the client index numbers of valid players - */ - for(i = 1; i <= MaxClients; i++) - { - if(IsClientInGame(i)) // && !IsFakeClient(i)) - { - iPlayers[iCount++] = i; - } - } - - /** - Randomly sort the players - */ - SortIntegers(iPlayers, iCount, Sort_Random); - - /** - Loop through all the players and assign each one to a team, alternating each time - */ - for(i = 0; i < iCount; i++) - { - if (!bRestartRound) - { - /** - We didn't want to restart the round, so we move them to spec 1 at a time. - */ - SM_MovePlayer(iPlayers[i], g_aCurrentTeams[Spectator]); - } - SM_MovePlayer(iPlayers[i], bTeam ? g_aCurrentTeams[Team2] : g_aCurrentTeams[Team1]); - SM_SetForcedTeam(iPlayers[i], bTeam ? g_aCurrentTeams[Team2] : g_aCurrentTeams[Team1], true); - bTeam = !bTeam; - } - - /** - Reset this variable since we completed a scramble - */ - g_bScrambleRoundEnd = false; - - if (g_hTimerClearScrambleForce != INVALID_HANDLE) - { - CloseHandle(g_hTimerClearScrambleForce); - g_hTimerClearScrambleForce = INVALID_HANDLE; - } - - g_hTimerClearScrambleForce = CreateTimer(300.0, Timer_ClearScrambleForce, _, TIMER_FLAG_NO_MAPCHANGE); - - ServerCommand("mp_timelimit %i", g_iTimeLeft / 60); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Timer_ClearScrambleForce(Handle:timer, any:data) -{ - - for(new i = 1; i <= MaxClients; i++) - { - if(IsClientInGame(i)) // && !IsFakeClient(i)) - { - SM_ClearForcedTeam(i); - PrintToChat(i, "\x01\x04[SM]\x01 Your forced team status has been cleared"); - } - } - - g_hTimerClearScrambleForce = INVALID_HANDLE; - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Timer_WelcomeAdvert(Handle:timer, any:client) -{ - - /** - Lets make sure the client is connected and actually in the game. - */ - if (IsClientConnected(client) && IsClientInGame(client)) - { - - /** - We are good to go so lets tell him about the swapteam command. - */ - PrintToChat (client, "\x01\x04[STM]\x01 %T", "SwapTeamMsg", LANG_SERVER); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -/* STOCK FUNCTIONS */ - -stock s_CleanUp(iClient) -{ - - /** - Reset all the client variables - */ - g_aPlayers[iClient][bQueue] = false; - g_aPlayers[iClient][iNewTeam] = 0; -} - -stock StartScrambleTimer(Float:fdelay = 0.0, bool:bRestartRound = false) -{ - if (fdelay == 0.0) - { - fdelay = g_fScrambleDelay; - } - if (g_hTimerPrepScramble != INVALID_HANDLE) - { - CloseHandle(g_hTimerPrepScramble); - g_hTimerPrepScramble = INVALID_HANDLE; - } - PrintCenterTextAll("%T", "Scramble", LANG_SERVER); - g_hTimerPrepScramble = CreateTimer(fdelay, Timer_PrepTeamScramble, bRestartRound, TIMER_FLAG_NO_MAPCHANGE); -} - -stock PrepTeamScramble(bool:bRestartRound = false) -{ - new iPlayers[MAXPLAYERS + 1]; - new iCount; - - GetMapTimeLeft(g_iTimeLeft); - - if (bRestartRound) - { - - for(new i = 1; i <= MaxClients; i++) - { - if(IsClientInGame(i)) - // && !IsFakeClient(i)) - { - iPlayers[iCount++] = i; - SM_ClearForcedTeam(i); - SM_ClearBuddy(i); - SM_MovePlayer(i, g_aCurrentTeams[Spectator]); - } - } - } - else - { - //Can't move them all to spec at the same time - for(new i = 1; i <= MaxClients; i++) - { - if(IsClientInGame(i)) - // && !IsFakeClient(i)) - { - iPlayers[iCount++] = i; - SM_ClearForcedTeam(i); - SM_ClearBuddy(i); - //SM_MovePlayer(i, g_aCurrentTeams[Spectator]); - } - } - } - CreateTimer(4.0, Timer_ScrambleTheTeams, bRestartRound, TIMER_FLAG_NO_MAPCHANGE); -} - -/* CONSOLE VARIABLE CHANGE EVENT */ - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (convar == stm_enabled) { - if (StringToInt(newValue) == 0) { - g_bIsEnabled = false; - LogAction(0, -1, "[STM] Simple Team Manager is loaded and disabled."); - } else { - g_bIsEnabled = true; - LogAction(0, -1, "[STM] Simple Team Manager is loaded and enabled."); - } - } - else if (convar == stm_logactivity) { - if (StringToInt(newValue) == 0) { - g_bLogActivity = false; - LogAction(0, -1, "[STM] Log Activity DISABLED."); - } else { - g_bLogActivity = true; - LogAction(0, -1, "[STM] Log Activity ENABLED."); - } - } - else if (convar == stm_scrambledelay) - g_fScrambleDelay = StringToFloat(newValue); - else if (convar == stm_votewin) - g_fVoteWin = StringToFloat(newValue); - else if (convar == stm_votedelay) - g_iVoteDelay = StringToInt(newValue); - else if (convar == stm_voteenabled) { - if (StringToInt(newValue) == 0) - g_bVoteEnabled = false; - else - g_bVoteEnabled = true; - } -} - -/* MENU CODE */ - -public OnAdminMenuReady(Handle:topmenu) -{ - if (topmenu == g_hAdminMenu) - return; - g_hAdminMenu = topmenu; - new TopMenuObject:player_commands = FindTopMenuCategory(g_hAdminMenu, ADMINMENU_PLAYERCOMMANDS); - new TopMenuObject:server_commands = FindTopMenuCategory(g_hAdminMenu, ADMINMENU_SERVERCOMMANDS); - if (player_commands == INVALID_TOPMENUOBJECT) - return; - - AddToTopMenu(g_hAdminMenu, - "moveplayer", - TopMenuObject_Item, - AdminMenu_MovePlayer, - player_commands, - "moveplayer", - ADMFLAG_BAN); - - AddToTopMenu(g_hAdminMenu, - "scrambleteams", - TopMenuObject_Item, - AdminMenu_Scrambleteams, - server_commands, - "scrambleteams", - ADMFLAG_BAN); -} - -public AdminMenu_MovePlayer(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) -{ - if (action == TopMenuAction_DisplayOption) - Format(buffer, maxlength, "Move Player"); - else if (action == TopMenuAction_SelectOption){ - DisplayPlayerMenu(param); - } -} - -public AdminMenu_Scrambleteams(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) -{ - if (action == TopMenuAction_DisplayOption) - Format(buffer, maxlength, "Scramble Teams"); - else if (action == TopMenuAction_SelectOption) { - DisplayScrambleMenu(param); - } -} - -public Menu_SelectPlayer(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - DisplayTeamMenu(param1, GetClientOfUserId(StringToInt(sSelection))); - } else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -public Menu_SelectTeam(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new iTeam; - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - decl String:sIndex[64]; - if (SplitString(sSelection, "A", sIndex, sizeof(sIndex)) != -1) - iTeam = g_aCurrentTeams[Team1]; - else if (SplitString(sSelection, "B", sIndex, sizeof(sIndex)) != -1) - iTeam = g_aCurrentTeams[Team2]; - else { - SplitString(sSelection, "C", sIndex, sizeof(sIndex)); - iTeam = g_aCurrentTeams[Spectator]; - } - new iTarget = StringToInt(sIndex); - g_aPlayers[iTarget][iNewTeam] = iTeam; - DisplaySwapModeMenu(param1, iTarget); - } else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -public Menu_SwapMode(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - decl String:sIndex[64]; - - if (SplitString(sSelection, "A", sIndex, sizeof(sIndex)) == -1) - { - SplitString(sSelection, "B", sIndex, sizeof(sIndex)); - } - - new iTarget = StringToInt(sIndex); - - if (StrContains(sSelection, "A", true) != -1) - { - g_aPlayers[iTarget][bQueue] = false; - } - else if (StrContains(sSelection, "B", true) != -1) - { - g_aPlayers[iTarget][bQueue] = true; - } - - if (param1 == iTarget && !g_aPlayers[iTarget][bQueue]) - { - SM_MovePlayer(iTarget, g_aPlayers[iTarget][iNewTeam]); - } - else - { - DisplayForceModeMenu(param1, iTarget); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - { - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } - return; -} - -public Menu_ForceMode(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - decl String:sIndex[64]; - if (SplitString(sSelection, "A", sIndex, sizeof(sIndex)) == -1) - { - SplitString(sSelection, "B", sIndex, sizeof(sIndex)); - } - new iTarget = StringToInt(sIndex); - if (StrContains(sSelection, "A", true) != -1) - { - SM_ClearForcedTeam(iTarget); - } - else if (StrContains(sSelection, "B", true) != -1) - { - SM_SetForcedTeam(iTarget, g_aPlayers[iTarget][iNewTeam], true); - } - if (!g_aPlayers[iTarget][bQueue]) - { - SM_MovePlayer(iTarget, g_aPlayers[iTarget][iNewTeam]); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - { - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } - return; -} - -public Menu_VoteScramble(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_VoteEnd) { - new winning_votes, total_votes; - GetMenuVoteInfo(param2, winning_votes, total_votes); - if (param1 == 0) { - if (float(total_votes) / float(winning_votes) < g_fVoteWin) { - PrintToChatAll("\x01\x04[SM]\x01 %T", "VoteScramble2", LANG_SERVER, winning_votes, total_votes); - return; - } - PrintCenterTextAll("[SM] %T", "Scramble", LANG_SERVER); - PrintToChatAll("\x01\x04[SM]\x01 %T", "VoteScramble1", LANG_SERVER, winning_votes, total_votes); - StartScrambleTimer(); - } - if (param1 == 1) { - PrintToChatAll("\x01\x04[SM]\x01 %T", "VoteScramble2", LANG_SERVER, winning_votes, total_votes); - } - } - if (action == MenuAction_End) - CloseHandle(menu); -} - -public Menu_ScrambleTeams(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "NOW", false)) - g_bScrambleRoundEnd = false; - else - g_bScrambleRoundEnd = true; - DisplayScrambleMenu2(param1); - } else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -public Menu_ScrambleTeams2(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[64]; - new bool:bRestartRound; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "NO", false)) - { - bRestartRound = false; - } - else - { - bRestartRound = true; - } - StartScrambleTimer(_, bRestartRound); - } else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -stock DisplayScrambleMenu(iClient) -{ - new Handle:hMenu = CreateMenu(Menu_ScrambleTeams); - SetMenuTitle(hMenu, "Select When to Scramble:"); - AddMenuItem(hMenu, "NOW", "Instantly"); - AddMenuItem(hMenu, "END", "At Round End"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplayScrambleMenu2(iClient) -{ - new Handle:hMenu = CreateMenu(Menu_ScrambleTeams2); - SetMenuTitle(hMenu, "Select When to Scramble:"); - AddMenuItem(hMenu, "NO", "No Round Restart"); - AddMenuItem(hMenu, "YES", "Restart Round"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplaySwapModeMenu(iClient, iTarget) -{ - new Handle:hMenu = CreateMenu(Menu_SwapMode); - decl String:optionA[64]; - decl String:optionB[64]; - Format(optionA, sizeof(optionA), "%iA", iTarget); - Format(optionB, sizeof(optionB), "%iB", iTarget); - SetMenuTitle(hMenu, "Select When to Swap:"); - AddMenuItem(hMenu, optionA, "Instantly (Kills)"); - if (!IsClientObserver(iTarget)) - AddMenuItem(hMenu, optionB, "Queue on next death"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplayForceModeMenu(iClient, iTarget) -{ - new Handle:hMenu = CreateMenu(Menu_ForceMode); - decl String:optionA[64]; - decl String:optionB[64]; - Format(optionA, sizeof(optionA), "%iA", iTarget); - Format(optionB, sizeof(optionB), "%iB", iTarget); - SetMenuTitle(hMenu, "Select Force Mode:"); - AddMenuItem(hMenu, optionA, "UnForced"); - AddMenuItem(hMenu, optionB, "Forced"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplayTeamMenu(iClient, iTarget) -{ - new Handle:hMenu = CreateMenu(Menu_SelectTeam); - decl String:optionA[64]; - decl String:optionB[64]; - decl String:optionC[64]; - Format(optionA, sizeof(optionA), "%iA", iTarget); - Format(optionB, sizeof(optionB), "%iB", iTarget); - Format(optionC, sizeof(optionC), "%iC", iTarget); - SetMenuTitle(hMenu, "Select Team:"); - AddMenuItem(hMenu, optionA, "Team One"); - AddMenuItem(hMenu, optionB, "Team Two"); - AddMenuItem(hMenu, optionC, "Spectator"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplayPlayerMenu(iClient) -{ - new Handle:hMenu = CreateMenu(Menu_SelectPlayer); - AddTargetsToMenu(hMenu, 0, true, false); - SetMenuTitle(hMenu, "Select A Player:"); - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} diff --git a/Simple Round Immunity/addons/sourcemod/translations/simpledonatorbenefits.phrases.txt b/Simple Round Immunity/addons/sourcemod/translations/simpledonatorbenefits.phrases.txt deleted file mode 100644 index 3826846..0000000 --- a/Simple Round Immunity/addons/sourcemod/translations/simpledonatorbenefits.phrases.txt +++ /dev/null @@ -1,62 +0,0 @@ -"Phrases" -{ - "PlayerLevelCmd" - { - "en" "Command must be run at the player level" - "fr" "Cette commande doit être tapée en jeu" - "hu" "Ezt a parancsot jatekosi szinten kell futtatni!" - } - "RestrictedCmd" - { - "en" "You must be a donator or admin to run this command" - "fr" "Vous devez être un donateur ou un admin pour lancer cette commande" - "hu" "A parancs futtatasahoz admin, vagy tamogatoi szint szukseges!" - } - "InValidTeam" - { - "en" "You must be on red or blue to swap teams" - "fr" "Vous devez être RED ou BLU pour changer d'équipe" - "hu" "Jatekban kell lenned, hogy megcsereld a csapatokat!" - } - "PlayerQueue" - { - "en" "You have been queued to swap teams on next death" - "fr" "Vous avez été mis en attente pour changer d'équipe lors de votre prochaine mort" - "hu" "A kovetkezo halalnal csapatcsere lesz" - } - "PlayerSwitched" - { - "en" "Your team has been switched as requested" - "fr" "Vous avez changé d'équipe comme demandé" - "hu" "A keresnek eleget teve a csapatod meg lett csererlve" - } - "SwapTeamMsg" - { - "en" "Type /swapteam or !swapteam to swap your team!" - } - "ReachedCount" - { - "en" "You have reached your health limit. You must die before you can use it again" - } - "AtMaxHealth" - { - "en" "You are already at your maximum health!" - } - "ToMaxHealth" - { - "en" "Instant health bonus applied! You are not at your maximun health!" - } - "HealthBonus" - { - "en" "Instant health bonus applied!" - } - "PublicJoinMessage" - { - "#format" "{1:s}" - "en" "{1} a [donator] as joined the server" - } - "PrivateJoinMessage" - { - "en" "Thanks for donating!" - } -} \ No newline at end of file diff --git a/Simple Round Immunity/addons/sourcemod/translations/simplespectate.phrases.txt b/Simple Round Immunity/addons/sourcemod/translations/simplespectate.phrases.txt deleted file mode 100644 index 2d1a096..0000000 --- a/Simple Round Immunity/addons/sourcemod/translations/simplespectate.phrases.txt +++ /dev/null @@ -1,42 +0,0 @@ -"Phrases" -{ - "Stopped spectating" - { - "#format" "{1:s}" - "en" "Stopped tracking player: {1}" - } - "Yourself" - { - "en" "You can't spectate yourself" - } - "Spectator" - { - "en" "You can't spectate another spectator" - } - "Spectating" - { - "#format" "{1:s}" - "en" "Now spectating {1}. Type !stopspec or /stopspec to stop spectating this player" - } - "Invalid Target" - { - "en" "Invalid target" - } - "Cant Target" - { - "en" "Can't target this player" - } - "Must Have Target" - { - "en" "You must be following/tracking a player to punish" - } - "Target Left" - { - "en" "The player you were following/tracking has left" - } - "Punished" - { - "#format" "{1:s}{2:s}{3:s}" - "en" "{1} was punished with a {2} for {3}" - } -} \ No newline at end of file diff --git a/Simple Round Immunity/addons/sourcemod/translations/simpleteambalancer.phrases.txt b/Simple Round Immunity/addons/sourcemod/translations/simpleteambalancer.phrases.txt deleted file mode 100644 index 03595fd..0000000 --- a/Simple Round Immunity/addons/sourcemod/translations/simpleteambalancer.phrases.txt +++ /dev/null @@ -1,130 +0,0 @@ -"Phrases" -{ - "UnBalanced" - { - "en" "Teams are unbalanced and will be balanced shortly" - "fr" "Les équipes ne sont pas équilibrées et le seront bientôt" - "de" "Die Teams sind ungleich und werden in Kürze ausgeglichen" - "hu" "A csapatok nem kiegyenlitettek! Egyensuly beallitas kovetkezik!" - } - "Enabled" - { - "en" "Simple Team Balancer is ENABLED" - "fr" "Simple Team Balancer est ACTIVE" - "de" "Simple Team Balancer ist AKTIV" - "hu" "Az Egyszeru Csapat Egyensulytarto AKTIV!" - } - "Disabled" - { - "en" "Simple Team Balancer is DISABLED" - "fr" "Simple Team Balancer est DESACTIVE" - "de" "Simple Team Balancer ist INAKTIV" - "hu" "Az Egyszeru Csapat Egyensulytarto INAKTIV!" - } - "PlayerMessage" - { - "#format" "{1:i}" - "en" "You are going to be auto balanced in {1} seconds unless a dead player can be found" - "fr" "Vous passerez dans l'autre équipe dans {1} secondes si aucun joueur mort ne peut être trouvé dans cet intervalle" - "de" "Du wirst in {1} Sekunden zum automatischen Ausgleich herangezogen wenn kein toter Spieler gefunden werden kann" - "hu" "{1} masodpercen belul at leszel helyezve a masik csapatba, hacsak nem lesz addig egy halott jatekos!" - } - "BalanceMessage" - { - "#format" "{1:s}" - "en" "{1} was moved to the other team for game balance" - "fr" "{1} est passé dans l'autre équipe pour équilibrer la partie" - "de" "{1} wurde zum anderen Team verschoben um das Spiel auszugleichen" - "hu" "{1} at lett helyezve az egyensuly megtartasa erdekeben." - } - "PlayerLevelCmd" - { - "en" "Command must be run at the player level" - "fr" "La commande doit être lancée au niveau du joueur" - "de" "Das Kommando muss auf Spieler Ebene ausgeführt werden" - "hu" "Jatekosi szinten kell futtatni ezt a parancsot!" - } - "CmdDisabled" - { - "en" "Command is currently disabled" - "fr" "La commande est actuellement désactivée" - "de" "Das Kommando ist momentan inaktiv" - "hu" "A parancs jelenleg inaktiv" - } - "RestrictedBuddy" - { - "en" "You must be a donator or admin to add a balance buddy" - "fr" "Vous devez être un donateur ou un admin pour choisir un partenaire" - "de" "Du musst ein Spender oder Admin sein um einen Partner wählen zu können" - "hu" "Tamogato vagy admin kell hogy legyel, hogy 'Tarsat' jelolhess meg" - } - "SelectSelf" - { - "en" "You cannot be your own buddy" - "fr" "Vous ne pouvez pas être votre propre partenaire" - "de" "Du kannst nicht dein eigener Partner sein" - "hu" "Nem valaszthatod ki onmagad!" - } - "BuddyGone" - { - "en" "Your selected buddy has disconnected" - "fr" "Le partenaire que vous avez sélectionné s'est déconnecté" - "de" "Dein gewählter Partner hat die Verbindung getrennt" - "hu" "A valasztott 'Tarsad' kilepett" - } - "BuddyMsg" - { - "#format" "{1:s}" - "en" "You and {1} are now buddies" - "fr" "Vous et {1} êtes maintenant partenaires" - "de" "Du und {1} seid jetzt Partner" - "hu" "{1} es Te 'Tarsak' vagytok." - } - "BuddyLockMsgDisabled" - { - "en" "You can now be anyone's buddy" - "fr" "Vous pouvez à présent être le partenaire de n'importe qui" - "de" "Du kannst jetzt jedermanns Partner sein" - "hu" "Barkinek lehetsz a 'Tarsa'." - } - "BuddyLockMsgEnabled" - { - "en" "Buddy selection locked. Only you can change your buddy" - "fr" "Sélection de partenaire bloquée. Vous êtes le seul à pouvoir choisir votre partenaire" - "de" "Wahl des Partners gesperrt. Nur du kannst deinen Partner wechseln" - "hu" "Tars-lista lezarva. Csak Te tudod modositani a Tars-listadat." - } - "PlayerLockedBuddyMsg" - { - "#format" "{1:s}" - "en" "{1} has locked his buddy selection. Try again" - "fr" "{1} a bloqué sa sélection de partenaire. Essayez de nouveau." - "de" "{1} hat seine Wahl des Partners gesperrt. Versuche es erneut" - "hu" "{1} lezarta a Tars-listajat. Probald kesobb!" - } - "BuddyWelcomeMsg1" - { - "en" "Select a balance buddy and stay together during an autobalance!" - "fr" "Choisissez un partenaire et restez ensemble durant l'équilibrage automatique!" - "de" "Wähle einen Partner und bleibt zusammen während eines Ausgleichs" - "hu" "Valasz ki egy 'Tarsat' akivel egyuttmaradhatsz a csapatkiegyenlites alatt!" - } - "BuddyWelcomeMsg2" - { - "en" "/buddy or !buddy to select a balance buddy" - "fr" "/buddy or !buddy pour choisir un partenaire" - "de" "/buddy oder !buddy um einen Partner zu wählen" - "hu" "Hasznald a /buddy vagy !buddy parancsokat a 'Tars' kijelolesehez" - } - "BuddyWelcomeMsg3" - { - "en" "/lockbuddy or !lockbuddy to lock your selection" - "fr" "/lockbuddy or !lockbuddy pour bloquer votre sélection" - "de" "/lockbuddy oder !lockbuddy um deine Auswahl zu sperren" - "hu" "Hasznald a /lockbuddy vagy a !lockbuddy parancsokat a Tars-listad lezarasahoz" - } -} - - - - diff --git a/Simple Round Immunity/addons/sourcemod/translations/simpleteammanager.phrases.txt b/Simple Round Immunity/addons/sourcemod/translations/simpleteammanager.phrases.txt deleted file mode 100644 index f2093a7..0000000 --- a/Simple Round Immunity/addons/sourcemod/translations/simpleteammanager.phrases.txt +++ /dev/null @@ -1,92 +0,0 @@ -"Phrases" -{ - "PlayerLevelCmd" - { - "en" "Command must be run at the player level" - "fr" "Cette commande doit être tapée en jeu" - "hu" "Ezt a parancsot jatekosi szinten kell futtatni!" - } - "RestrictedCmd" - { - "en" "You must be a donator or admin to run this command" - "fr" "Vous devez être un donateur ou un admin pour lancer cette commande" - "hu" "A parancs futtatasahoz admin, vagy tamogatoi szint szukseges!" - } - "InValidTeam" - { - "en" "You must be on red or blue to swap teams" - "fr" "Vous devez être RED ou BLU pour changer d'équipe" - "hu" "Jatekban kell lenned, hogy megcsereld a csapatokat!" - } - "PlayerInValidTeam" - { - "en" "Player must be on red or blue to swap teams" - "fr" "Le joueur doit être RED ou BLU pour changer d'équipe" - "hu" "Valamelyik csapatban kell lenni, hogy csere legyen" - } - "PlayerQueue" - { - "en" "You have been queued to swap teams on next death" - "fr" "Vous avez été mis en attente pour changer d'équipe lors de votre prochaine mort" - "hu" "A kovetkezo halalnal csapatcsere lesz" - } - "PlayerSwitched" - { - "en" "Your team has been switched" - } - "PlayerSwitched1" - { - "en" "Your team has been switched as requested" - "fr" "Vous avez changé d'équipe comme demandé" - "hu" "A keresnek eleget teve a csapatod meg lett csererlve" - } - "PlayerSwitched2" - { - "en" "Your team has been switched by an Admin" - "fr" "Vous avez été changé d'équipe par un admin" - "hu" "Az Admin megcserelte a csapatodat!" - } - "SwapTeamMsg" - { - "en" "Type /swapteam or !swapteam to swap your team!" - } - "PlayerSwitched3" - { - "#format" "{1:s}" - "en" "{1}'s team has been switched" - "fr" "{1} a changé d'équipe" - "hu" "{1} csapata meg lett cserelve" - } - "Scramble" - { - "en" "Teams are about to be scrambled!" - "fr" "Les équipes vont être rééquilibrés" - "hu" "A csapatok hamarosan meg lesznek keverve!" - } - "VoteScramble1" - { - "#format" "{1:i}{2:i}" - "en" "Vote Scramble successful with {1} votes out of {2}" - "fr" "Le vote d'équilibrage des équipes a réussi avec {1} votes pour sur {2}" - "hu" "A szavazas sikeres volt, {1} szavazat a keveresre a {2} -bol" - } - "VoteScramble2" - { - "#format" "{1:i}{2:i}" - "en" "Vote Scramble failed with {1} votes out of {2}" - "fr" "Le vote d'équilibrage a échoué avec {1} votes pour sur {2}" - "hu" "A szavazas sikertelen volt, {1} szavazat a keveresre a {2} -bol" - } - "VoteInProgress" - { - "en" "A vote is currently in progress" - "fr" "Un vote est actuellement en cours" - "hu" "Egy szavazas mar fut!" - } - "ScrambleTime" - { - "en" "A vote was recently made, please wait" - "fr" "Un vote a déjà été fait récemment, réessayez plus tard" - "hu" "Nemreg volt szavazas, kerlek varj egy kicsit!" - } -} \ No newline at end of file diff --git a/Simple Spectate/addons/sourcemod/configs/simple-alltalkmanager_events.cfg b/Simple Spectate/addons/sourcemod/configs/simple-alltalkmanager_events.cfg deleted file mode 100644 index b739cf0..0000000 --- a/Simple Spectate/addons/sourcemod/configs/simple-alltalkmanager_events.cfg +++ /dev/null @@ -1,43 +0,0 @@ -"game_events" -{ - "teamplay_round_start" - { - "reason" "Round Start" - "setting" "1" - } - "teamplay_setup_finished" - { - "reason" "Setup Period Ended" - "setting" "0" - } - "teamplay_overtime_begin" - { - "reason" "Overtime Began" - "setting" "1" - } - "teamplay_overtime_end" - { - "reason" "Overtime Ended" - "setting" "1" - } - "teamplay_round_win" - { - "reason" "Round Ended" - "setting" "1" - } - "teamplay_suddendeath_begin" - { - "reason" "Sudden Death Began" - "setting" "1" - } - "teamplay_suddendeath_end" - { - "reason" "Sudden Death Ended" - "setting" "1" - } - "teamplay_round_stalemate" - { - "reason" "Stalemate" - "setting" "1" - } -} \ No newline at end of file diff --git a/Simple Spectate/addons/sourcemod/configs/simple-chatcolors.cfg b/Simple Spectate/addons/sourcemod/configs/simple-chatcolors.cfg deleted file mode 100644 index 14b98c6..0000000 --- a/Simple Spectate/addons/sourcemod/configs/simple-chatcolors.cfg +++ /dev/null @@ -1,15 +0,0 @@ -"admin_colors" -{ - "groupname2" - { - "flag" "z" - "namecolor" "{green}" - "textcolor" "{olive}" - } - "groupname1" - { - "flag" "a" - "namecolor" "{teamcolor}" - "textcolor" "{green}" - } -} \ No newline at end of file diff --git a/Simple Spectate/addons/sourcemod/plugins/simple-alltalkmanager.smx b/Simple Spectate/addons/sourcemod/plugins/simple-alltalkmanager.smx deleted file mode 100644 index 6122756af68998fb531abcd0d08698e24cff25af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7028 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 diff --git a/Simple Spectate/addons/sourcemod/plugins/simple-donatorbenefits.smx b/Simple Spectate/addons/sourcemod/plugins/simple-donatorbenefits.smx deleted file mode 100644 index 821d61d784607595ca400d273a941a42e40de640..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16600 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 diff --git a/Simple Spectate/addons/sourcemod/plugins/simple-messagesuppression.smx b/Simple Spectate/addons/sourcemod/plugins/simple-messagesuppression.smx deleted file mode 100644 index cc20dadd37d8ff23d0a64513cc09650f4bdbf24d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4845 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 Blh*(M diff --git a/Simple Spectate/addons/sourcemod/plugins/simple-spectate.smx b/Simple Spectate/addons/sourcemod/plugins/simple-spectate.smx index c6885b041145a73f664650e729a5dcf8b3b0813f..127011072cfaa75bd9cdc6035ed442d9b5561ace 100644 GIT binary patch literal 19878 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 literal 19129 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%0ACwUfid=y*oPG;MRqmWr)g0 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�XP zM5L)&uZne^XHs;_L+03=Xy3CiU1O76^S{TWu{zY}Jlq((BV?9EL=m4MC%~!W0MzeW zOjQv*a;A7AS@l%h9EbjzQ3d}e&j~R0VCoAN)q_>=)m=>e=ZX9w8jM3&o1RO^+0jJ) z

_|h)w;)ME+|h#gx@oo-|ZEuRI5d) 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 z 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 z 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 KvHt-#rc|>H2mv<$ diff --git a/Simple Spectate/addons/sourcemod/scripting/include/simple-plugins.inc b/Simple Spectate/addons/sourcemod/scripting/include/simple-plugins.inc deleted file mode 100644 index 8f21956..0000000 --- a/Simple Spectate/addons/sourcemod/scripting/include/simple-plugins.inc +++ /dev/null @@ -1,337 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Plugins -Description: - Included file for core plugin in the Simple Plugins project -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -*************************************************************************/ - -#if defined _simpleplugin_included - #endinput -#endif - -#define _simpleplugin_included - -#define CORE_INC_VERSION "1.1.$Rev$" - -#pragma semicolon 1 -#include -#undef REQUIRE_PLUGIN -#include -#define REQUIRE_PLUGIN -#undef REQUIRE_EXTENSIONS -#undef AUTOLOAD_EXTENSIONS -#tryinclude -#tryinclude -#tryinclude -#define AUTOLOAD_EXTENSIONS -#define REQUIRE_EXTENSIONS - -enum e_SupportedMods -{ - GameType_Unknown, - GameType_AOC, - GameType_CSS, - GameType_DOD, - GameType_FF, - GameType_HIDDEN, - GameType_HL2DM, - GameType_INS, - GameType_L4D, - GameType_NEO, - GameType_SGTLS, - GameType_TF, - GameType_ZPS -}; - -enum e_Teams -{ - Unknown, - Spectator, - Team1, - Team2 -}; - -new g_aCurrentTeams[e_Teams]; -new e_SupportedMods:g_CurrentMod; -new String:g_sGameName[e_SupportedMods][32] = { "Unknown", - "Age of Chivalry", - "Counter Strike", - "Day Of Defeat", - "Fortress Forever", - "Hidden: Source", - "Half Life 2: Deathmatch", - "Insurgency", - "Left 4 Dead", - "Neotokyo", - "Stargate TLS", - "Team Fortress 2", - "Zombie Panic: Source" - }; - -public SharedPlugin:_pl_simpleplugin = -{ - name = "simple-plugins", - file = "simple-plugins.smx", -#if defined REQUIRE_PLUGIN - required = 1 -#else - required = 0 -#endif -}; - -#if !defined REQUIRE_PLUGIN -public _pl_simpleplugin_SetNTVOptional() -{ - MarkNativeAsOptional("SM_MovePlayer"); - MarkNativeAsOptional("SM_SetForcedTeam"); - MarkNativeAsOptional("SM_GetForcedTeam"); - MarkNativeAsOptional("SM_ClearForcedTeam"); - MarkNativeAsOptional("SM_GetForcedPlayer"); - MarkNativeAsOptional("SM_AssignBuddy"); - MarkNativeAsOptional("SM_SearchBuddy"); - MarkNativeAsOptional("SM_LockBuddy"); - MarkNativeAsOptional("SM_IsBuddyLocked"); - MarkNativeAsOptional("SM_ClearBuddy"); - MarkNativeAsOptional("SM_IsValidAdmin"); - MarkNativeAsOptional("SM_IsValidTeam"); -} -#endif - -/********************************************************************** - * When a player has to moved - * - * @param plugin Plugin that initiated the move - * @param client The client index of the player that was moved - * @param team The team index the player was moved to - * @noreturn - **********************************************************************/ -forward SM_OnPlayerMoved(Handle:plugin, client, team); - -/********************************************************************** - * Move a player to the supplied team - * - * @param client The client index of the player to be moved - * @param team The team to move the player to - * @noreturn - * @error Invalid client or team index - **********************************************************************/ -native SM_MovePlayer(client, team); - -/********************************************************************** - * Move a player to the supplied team - * - * @param client The client index of the player to set - * @param team The team to move the to set - * @param override Whether or not to override another plugin - * @return True if successful, false if not - * @error Invalid client or team index - **********************************************************************/ -native SM_SetForcedTeam(client, team, bool:override = false); - -/********************************************************************** - * Gets the client's forced team index - * - * @param client The client index of the player to check - * @param plugin Optional: The plugin handle of the plugin - that set the team - * @return The team index of the forced team - Zero if no forced team - * @error Invalid client index - **********************************************************************/ -native SM_GetForcedTeam(client, &Handle:plugin = INVALID_HANDLE); - -/********************************************************************** - * Clears a client's forced team - * - * @param client The client index of the player to check - * @return True if successful, false if not - * @error Invalid client index - **********************************************************************/ -native SM_ClearForcedTeam(client); - -/********************************************************************** - * Gets a forced player on the wrong that is currently on the wrong team - * This will only return a player if the calling plugin assigned the team - * - * @param team The team index the player should be on - * @return The client index of the player - Zero if no player found - * @error Invalid client index - **********************************************************************/ -native SM_GetForcedPlayer(team); - -/********************************************************************** - * Assign a players buddy - * - * @param client The client index of the player to assign - * @param player The player index of the player to assign - * @param override Whether or not to override a player lock - * @return True if successful, false if not - * @error Invalid client or player index - **********************************************************************/ -native bool:SM_AssignBuddy(client, player, bool:override = false); - -/********************************************************************** - * Rturns the client's buddy - * - * @param client The client index of the player to assign - * @return The client index of the player's buddy - Zero if no buddy - * @error Invalid client index - **********************************************************************/ -native SM_GetClientBuddy(client); - -/********************************************************************** - * Set the buddy lock setting for a client - * - * @param client The client index of the player to assign - * @param setting Setting to set, True or False - * @return True if successful, false if not - * @error Invalid client index - **********************************************************************/ -native bool:SM_LockBuddy(client, bool:setting); - -/********************************************************************** - * Returns the buddy lock setting for a client - * - * @param client The client index of the player to assign - * @return True if locked, false if not - * @error Invalid client index - **********************************************************************/ -native bool:SM_IsBuddyLocked(client); - -/********************************************************************** - * Clear a players buddy - * - * @param client The client index of the player to clear - * @param override Whether or not to override a player lock - * @return True if successful, false if not - * @error Invalid client index - **********************************************************************/ -native bool:SM_ClearBuddy(client, bool:override = false); - -/********************************************************************** - * Determine if the player has the supplied flags - * ADMFLAG_ROOT will always return true - * - * @param client The client index of the player to assign - * @param flags The char flag(s) to check against - * @return True if valid, false if not - **********************************************************************/ -native bool:SM_IsValidAdmin(client, const String:flags[]); - - -/********************************************************************** - * Determine if the team is a valid team - * - * @param team The team index to determine if valid for - currently installed/supported mod - * @return True if valid, false if not - **********************************************************************/ -native bool:SM_IsValidTeam(team); - - -public e_SupportedMods:GetCurrentMod() -{ - new String:sGameType[64]; - GetGameFolderName(sGameType, sizeof(sGameType)); - - if (StrEqual(sGameType, "aoc", false)) - { - return GameType_AOC; - } - if (StrEqual(sGameType, "cstrike", false)) - { - return GameType_CSS; - } - if (StrEqual(sGameType, "dod", false)) - { - return GameType_DOD; - } - if (StrEqual(sGameType, "ff", false)) - { - return GameType_FF; - } - if (StrEqual(sGameType, "hidden", false)) - { - return GameType_HIDDEN; - } - if (StrEqual(sGameType, "hl2mp", false)) - { - return GameType_FF; - } - if (StrEqual(sGameType, "insurgency", false) || StrEqual(sGameType, "ins", false)) - { - return GameType_INS; - } - if (StrEqual(sGameType, "l4d", false)) - { - return GameType_L4D; - } - if (StrEqual(sGameType, "nts", false)) - { - return GameType_NEO; - } - if (StrEqual(sGameType, "sgtls", false)) - { - return GameType_SGTLS; - } - if (StrEqual(sGameType, "tf", false)) - { - return GameType_TF; - } - if (StrEqual(sGameType, "zps", false)) - { - return GameType_ZPS; - } - return GameType_Unknown; -} - -public LoadCurrentTeams() -{ - switch (g_CurrentMod) - { - case GameType_INS: - { - g_aCurrentTeams[Unknown] = 0; - g_aCurrentTeams[Spectator] = 3; - g_aCurrentTeams[Team1] = 1; - g_aCurrentTeams[Team2] = 2; - } - case default: - { - g_aCurrentTeams[Unknown] = 0; - g_aCurrentTeams[Spectator] = 1; - g_aCurrentTeams[Team1] = 2; - g_aCurrentTeams[Team2] = 3; - } - } -} diff --git a/Simple Spectate/addons/sourcemod/scripting/simple-alltalkmanager.sp b/Simple Spectate/addons/sourcemod/scripting/simple-alltalkmanager.sp deleted file mode 100644 index c848332..0000000 --- a/Simple Spectate/addons/sourcemod/scripting/simple-alltalkmanager.sp +++ /dev/null @@ -1,515 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple AllTalk Manager -Description: - Allows you to set alltalk at different times -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#pragma semicolon 1 -#include -#include - -#define PLUGIN_VERSION "1.4.$Rev$" - -new Handle:satm_enabled = INVALID_HANDLE; -new Handle:satm_threshold_enabled = INVALID_HANDLE; -new Handle:satm_player_threshold = INVALID_HANDLE; -new Handle:satm_threshold_setting = INVALID_HANDLE; -new Handle:satm_logactivity = INVALID_HANDLE; -new Handle:satm_alltalk = INVALID_HANDLE; - -new Handle:g_aEventNames = INVALID_HANDLE; -new Handle:g_aEventReasons = INVALID_HANDLE; -new Handle:g_aEventSettings = INVALID_HANDLE; - -new bool:g_bLastThreshold = false; -new bool:g_bEnabled = true; -new bool:g_bThresholdEnabled = true; -new bool:g_bIsSetupMap = false; -new bool:g_bIsGameTF2 = false; -new bool:g_bLogActivity = false; - -new g_iLastEventIndex; - -public Plugin:myinfo = -{ - name = "Simple AllTalk Manager", - author = "Simple Plugins", - description = "Allows you to set alltalk at different times", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -} - -/** -Sourcemod callbacks -*/ -public OnPluginStart() -{ - - /** - Need to create all of our console variables. - */ - CreateConVar("satm_version", PLUGIN_VERSION, "Simple AllTalk Manager", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - satm_enabled = CreateConVar("satm_enabled", "1", "Enables/Disables Simple AllTalk Manager", _, true, 0.0, true, 1.0); - satm_threshold_enabled = CreateConVar("satm_threshold_enabled", "1", "Enables/Disables player threshold", _, true, 0.0, true, 1.0); - satm_player_threshold = CreateConVar("satm_player_threshold", "8", "Amount of players for the threshold"); - satm_threshold_setting = CreateConVar("satm_threshold_setting", "1", "Enables/Disables all talk up to player threshold, with the opposite set after the threshold", _, true, 0.0, true, 1.0); - satm_logactivity = CreateConVar("satm_logactivity", "0", "Enables/Disables log activity", _, true, 0.0, true, 1.0); - satm_alltalk = FindConVar("sv_alltalk"); - - /** - Hook console variables - */ - HookConVarChange(satm_enabled, ConVarSettingsChanged); - HookConVarChange(satm_threshold_enabled, ConVarSettingsChanged); - HookConVarChange(satm_player_threshold, ConVarSettingsChanged); - HookConVarChange(satm_logactivity, ConVarSettingsChanged); - - /** - Remove the notify flag from all talk cvar since we do it - */ - SetConVarFlags(satm_alltalk, GetConVarFlags(satm_alltalk)~FCVAR_NOTIFY); - - /** - Get the game type. We only care if it's TF2 - */ - new String:sGameType[64]; - GetGameFolderName(sGameType, sizeof(sGameType)); - if (StrEqual(sGameType, "tf", false)) - { - g_bIsGameTF2 = true; - } - - /** - Create the arrays - */ - g_aEventNames = CreateArray(255, 1); - g_aEventReasons = CreateArray(255, 1); - g_aEventSettings = CreateArray(1, 1); - - /** - Need to register the commands we are going to create and use. - */ - RegAdminCmd("sm_reloadatconfig", Command_Reload, ADMFLAG_GENERIC, "Reloads settings from config file"); - - /** - Create the config file - */ - AutoExecConfig(true); - - /** - Load the events from the config - */ - LoadEventsFromConfig(); -} - -public OnConfigsExecuted() -{ - - /** - Load up the settings - */ - g_bEnabled = GetConVarBool(satm_enabled); - g_bLogActivity = GetConVarBool(satm_logactivity); - g_bThresholdEnabled = GetConVarBool(satm_threshold_enabled); -} - -public OnMapStart() -{ - - /** - Reset the globals - */ - g_iLastEventIndex = 0; - g_bLastThreshold = false; - - /** - Check the map type if we are in TF2 - */ - if (g_bIsGameTF2) - { - g_bIsSetupMap = IsSetupPeriodMap(); - } - - /** - Set AllTalk - */ - if (g_bEnabled) - { - SetConVarBool(satm_alltalk, true); - } -} - -public OnClientDisconnect_Post(client) -{ - if (g_bEnabled) - { - SetAllTalk(-1); - } -} - -public OnClientPostAdminCheck(client) -{ - if (g_bEnabled) - { - SetAllTalk(-1); - } - CreateTimer(2.0, Timer_ShowAllTalkStatus, client, TIMER_FLAG_NO_MAPCHANGE); -} - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (convar == satm_enabled) - { - if (StringToInt(newValue)) - { - g_bEnabled = true; - } - else - { - g_bEnabled = false; - } - } - else if (convar == satm_threshold_enabled) - { - if (StringToInt(newValue)) - { - g_bThresholdEnabled = true; - } - else - { - g_bThresholdEnabled = false; - } - } - else if (convar == satm_logactivity) - { - if (StringToInt(newValue)) - { - g_bLogActivity = true; - } - else - { - g_bLogActivity = false; - } - } - if (g_bEnabled) - { - SetAllTalk(-1); - } -} - -/** -Commands -*/ -public Action:Command_Reload(client, args) -{ - - /** - Clear the array - */ - ClearArray(g_aEventNames); - ClearArray(g_aEventReasons); - ClearArray(g_aEventSettings); - - /** - Load the events from the config - */ - LoadEventsFromConfig(); - - return Plugin_Handled; -} - -/** -Game Event Hooks -*/ -public Hook_All_Events(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (!g_bIsSetupMap) - { - if (StrEqual(name, "teamplay_round_start")) - { - if (FindStringInArray(g_aEventNames, "teamplay_setup_finished") != -1) - { - g_iLastEventIndex = FindStringInArray(g_aEventNames, "teamplay_setup_finished"); - if (g_bEnabled) - { - SetAllTalk(g_iLastEventIndex); - return; - } - } - } - } - g_iLastEventIndex = FindStringInArray(g_aEventNames, name); - if (g_bEnabled) - { - SetAllTalk(g_iLastEventIndex); - } -} - -/** -Timers -*/ -public Action:Timer_ShowAllTalkStatus(Handle:timer, any:client) -{ - if (IsClientConnected(client) && IsClientInGame(client)) - { - new bool:bSetting = GetConVarBool(satm_alltalk); - if (bSetting) - { - PrintToChat(client, "\x01\x04[SM] AllTalk is \x01[on]"); - } - else - { - PrintToChat(client, "\x01\x04[SM] AllTalk is \x01[off]"); - } - } -} - -/** -Stock Functions -*/ -stock LoadEventsFromConfig() -{ - - /** - Make sure the config file is here and load it up - */ - new String:sConfigFile[256]; - BuildPath(Path_SM, sConfigFile, sizeof(sConfigFile), "configs/simple-alltalkmanager_events.cfg"); - if (!FileExists(sConfigFile)) - { - - /** - Config file doesn't exists, stop the plugin - */ - LogError("[SATM] Simple AllTalk Manager is not running! Could not find file %s", sConfigFile); - SetFailState("Could not find file %s", sConfigFile); - } - - /** - Create the arrays and variables - */ - new String:sGameEventName[256]; - new String:sReason[256]; - new iSetting; - - /** - Load config file as a KeyValues file - */ - new Handle:kvGameEvents = CreateKeyValues("game_events"); - FileToKeyValues(kvGameEvents, sConfigFile); - - if (!KvGotoFirstSubKey(kvGameEvents)) - { - return; - } - - /** - Hook the game events and load the settings - */ - do - { - - /** - Get the section name; this should be the event name - */ - KvGetSectionName(kvGameEvents, sGameEventName, sizeof(sGameEventName)); - if (!HookEventEx(sGameEventName, Hook_All_Events, EventHookMode_PostNoCopy)) - { - - /** - Could not hook this event, stop the plugin - */ - SetFailState("Could not hook event %s", sGameEventName); - } - else - { - if (g_bLogActivity) - { - LogMessage("[SATM] Hooked event: %s", sGameEventName); - } - } - - /** - Get the reason string and setting - */ - KvGetString(kvGameEvents, "reason", sReason, sizeof(sReason)); - iSetting = KvGetNum(kvGameEvents, "setting"); - if (g_bLogActivity) - { - LogMessage("[SATM] Event reason string: %s", sReason); - LogMessage("[SATM] Event setting: %i", iSetting); - } - - /** - Push the values to the arrays - */ - PushArrayString(g_aEventNames, sGameEventName); - PushArrayString(g_aEventReasons, sReason); - PushArrayCell(g_aEventSettings, iSetting); - } while (KvGotoNextKey(kvGameEvents)); - - /** - Close our handle - */ - CloseHandle(kvGameEvents); -} - -stock SetAllTalk(index) -{ - new iPlayerThreshold = GetConVarInt(satm_player_threshold); - new bool:bThresholdMet = ((GetClientCount() >= iPlayerThreshold) ? true : false); - new bool:bSetting; - - if (g_bThresholdEnabled) - { - if (bThresholdMet) - { - if (index == -1) - { - if (bThresholdMet != g_bLastThreshold) - { - g_bLastThreshold = true; - bSetting = !GetConVarBool(satm_threshold_setting); - new bool:bLastSetting = GetArrayCell(g_aEventSettings, g_iLastEventIndex); - if (bLastSetting && !bSetting) - { - bSetting = GetArrayCell(g_aEventSettings, g_iLastEventIndex); - } - } - else - { - bSetting = GetArrayCell(g_aEventSettings, g_iLastEventIndex); - } - } - else - { - bSetting = GetArrayCell(g_aEventSettings, index); - } - } - else - { - g_bLastThreshold = false; - bSetting = GetConVarBool(satm_threshold_setting); - } - } - else - { - if (index != -1) - { - bSetting = GetArrayCell(g_aEventSettings, index); - } - } - - if (GetConVarBool(satm_alltalk) != bSetting) - { - - SetConVarBool(satm_alltalk, bSetting); - - new String:sReason[256]; - if (index == -1) - { - Format(sReason, sizeof(sReason), "Player Threshold"); - } - else - { - if (!g_bIsSetupMap) - { - new String:sCurrentEvent[256]; - GetArrayString(g_aEventNames, index, sCurrentEvent, sizeof(sCurrentEvent)); - if (StrEqual(sCurrentEvent, "teamplay_setup_finished")) - { - new iRoundStartIndex = FindStringInArray(g_aEventNames, "teamplay_round_start"); - if (iRoundStartIndex != -1) - { - GetArrayString(g_aEventReasons, iRoundStartIndex, sReason, sizeof(sReason)); - } - else - { - GetArrayString(g_aEventReasons, index, sReason, sizeof(sReason)); - } - } - else - { - GetArrayString(g_aEventReasons, index, sReason, sizeof(sReason)); - } - } - else - { - GetArrayString(g_aEventReasons, index, sReason, sizeof(sReason)); - } - } - - if (bSetting) - { - PrintToChatAll("\x01\x04[SM] AllTalk turned \x01[on] \x04due to:\x01 %s", sReason); - } - else - { - PrintToChatAll("\x01\x04[SM] AllTalk turned \x01[off] \x04due to:\x01 %s", sReason); - } - } -} - -stock bool:IsSetupPeriodMap() -{ - new iEnt = -1; - new String:sMapName[32]; - - GetCurrentMap(sMapName, sizeof(sMapName)); - - if (strncmp(sMapName, "cp_", 3, false) == 0) - { - new iTeam; - while ((iEnt = FindEntityByClassname(iEnt, "team_control_point")) != -1) - { - iTeam = GetEntProp(iEnt, Prop_Send, "m_iTeamNum"); - - /** - If there is a blu CP or a neutral CP, then it's not an attack/defend map - */ - if (iTeam != 2) - { - //this is a push map - return false; - } - } - //this is a attack/defend map - return true; - } - else if (strncmp(sMapName, "ctf_", 3, false) == 0) - { - //this is a ctf map - return false; - } - return false; -} diff --git a/Simple Spectate/addons/sourcemod/scripting/simple-autoscrambler.sp b/Simple Spectate/addons/sourcemod/scripting/simple-autoscrambler.sp deleted file mode 100644 index 6c6799e..0000000 --- a/Simple Spectate/addons/sourcemod/scripting/simple-autoscrambler.sp +++ /dev/null @@ -1,459 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple AutoScrambler -Description: - Automatically scrambles the teams based upon a number of events. -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include - -#define PLUGIN_VERSION "1.1.$Rev$" - -/** -Different scramble modes: - -1 = Full Scramble, dont restart round. -2 = Admins Immune, dont restart round. -3 = Full Scramble, restart round and reset scores. -4 = Admins Immune, restart round and reset scores. - -*/ - -/** -Different top player modes: - -1 = Divide Top 4 players on the two teams. -2 = Protect the Top 2 players on each team. - -*/ - -enum PlayerData -{ - Handle:hForcedTimer, - bool:bProtected; -}; - -/** -Cvars used for admins -*/ -new Handle: sas_admin_immunity_enabled = INVALID_HANDLE, - Handle: sas_admin_flag_scramblenow = INVALID_HANDLE, - Handle: sas_admin_flag_immunity = INVALID_HANDLE; - -/** -Cvars used for autoscramble -*/ -new Handle: sas_autoscramble_enabled = INVALID_HANDLE, - Handle: sas_autoscramble_minplayers = INVALID_HANDLE, - Handle: sas_autoscramble_mode = INVALID_HANDLE, - Handle: sas_autoscramble_winstreak = INVALID_HANDLE, - Handle: sas_autoscramble_steamroll = INVALID_HANDLE, - Handle: sas_autoscramble_frags = INVALID_HANDLE; - -/** -Cvars used for voting -*/ -new Handle: sas_vote_enabled = INVALID_HANDLE, - Handle: sas_vote_upcount = INVALID_HANDLE, - Handle: sas_vote_winpercent = INVALID_HANDLE, - Handle: sas_vote_mode = INVALID_HANDLE, - Handle: sas_vote_minplayers = INVALID_HANDLE; - -/** -Additional cvars -*/ -new Handle: sas_enabled = INVALID_HANDLE, - Handle: sas_timer_scrambledelay = INVALID_HANDLE, - Handle: TFGameModeArena = INVALID_HANDLE; - -/** -Timers -*/ -new Handle: g_hScrambleTimer = INVALID_HANDLE; - -/** - Player arrays - */ -new g_aPlayers[MAXPLAYERS + 1][PlayerData]; - -/** - Cvar variables - */ -new bool: g_bIsEnabled, - bool: g_bIsAutoScrambleEnabled, - bool: g_bIsVoteEnabled, - bool: g_bIsAdminImmunityEnabled; -new Float: g_fTimer_ScrambleDelay, - Float: g_fVote_UpCount, - Float: g_fVote_WinPercent; -new g_iAutoScramble_Minplayers, - g_iAutoScramble_Mode, - g_iAutoScramble_WinStreak, - g_iAutoScramble_SteamRoll, - g_iAutoScramble_Frags, - g_iVote_Mode, - g_iVote_MinPlayers; -new String: g_sScrambleNowFlag[5], - String: g_sAdminImmunityFlag[5]; - -/** -Other globals -*/ -new g_iMaxEntities, - g_iOwnerOffset; - -public Plugin:myinfo = -{ - name = "Simple AutoScrambler", - author = "Simple Plugins", - description = "Automatically scrambles the teams based upon a number of events.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -public OnPluginStart() -{ - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[SAS] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - switch (g_CurrentMod) - { - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_Post); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_Post); - } - } - - /** - Create console variables - */ - CreateConVar("sas_version", PLUGIN_VERSION, "Simple AutoScrambler Version",FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - sas_enabled = CreateConVar("sas_enabled", "1", "Enable/Disable Simple AutoScrambler"); - sas_timer_scrambledelay = CreateConVar("sas_timer_scrambledelay", "5.0", "Delay used after a scramble has been started", _, true, 1.0, true, 30.0); - - /** - Cvars used for admins - */ - sas_admin_immunity_enabled = CreateConVar("sas_admin_immunity_enabled", "1", "Enable/Disable admin immunity for scrambles"); - sas_admin_flag_scramblenow = CreateConVar("sas_admin_flag_scramblenow", "z", "Admin flag to use for scramblenow function/command"); - sas_admin_flag_immunity = CreateConVar("sas_admin_flag_immunity", "z", "Admin flag to use for scramble immunity"); - - /** - Cvars used for autoscramble - */ - sas_autoscramble_enabled = CreateConVar("sas_autoscramble_enabled", "1", "Enable/Disable the autoscramble function"); - sas_autoscramble_minplayers = CreateConVar("sas_autoscramble_minplayers", "16", "Min players needed to start an autoscramble"); - sas_autoscramble_mode = CreateConVar("sas_autoscramble_mode", "1", "Scramble mode used when autoscrambling"); - sas_autoscramble_winstreak = CreateConVar("sas_autoscramble_winstreak", "5", "Max amount of wins in a row a team can achieve before an autoscramble starts"); - sas_autoscramble_steamroll = CreateConVar("sas_autoscramble_steamroll", "120", "Shortest amount of time a team can win by before an autoscramble starts (seconds)"); - sas_autoscramble_frags = CreateConVar("sas_autoscramble_frags", "1", "Min players needed to start a vote and scramble"); - - /** - Cvars used for voting - */ - sas_vote_enabled = CreateConVar("sas_vote_enabled", "1", "Enable/Disable voting for scramble"); - sas_vote_upcount = CreateConVar("sas_vote_upcount", "5", "Amount of people wanting a scramble before a vote starts. If less than 1 it will be considered a percentage. (ie 0.5 = 50% | 1 = 1 Player | 5 = 5 Players)"); - sas_vote_winpercent = CreateConVar("sas_vote_winpercent", "0.6", "Percentage of votes needed to scramble", _, true, 0.0, true, 1.0); - sas_vote_mode = CreateConVar("sas_vote_mode", "1", "Scramble mode used when a vote results in a scramble"); - sas_vote_minplayers = CreateConVar("sas_vote_minplayers", "16", "Min players needed to start a vote and scramble"); - - /** - Hook the console variables if they change - */ - HookConVarChange(sas_enabled, ConVarSettingsChanged); - HookConVarChange(sas_timer_scrambledelay, ConVarSettingsChanged); - HookConVarChange(sas_admin_immunity_enabled, ConVarSettingsChanged); - HookConVarChange(sas_admin_flag_scramblenow, ConVarSettingsChanged); - HookConVarChange(sas_admin_flag_immunity, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_enabled, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_minplayers, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_mode, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_winstreak, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_steamroll, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_frags, ConVarSettingsChanged); - HookConVarChange(sas_vote_enabled, ConVarSettingsChanged); - HookConVarChange(sas_vote_upcount, ConVarSettingsChanged); - HookConVarChange(sas_vote_winpercent, ConVarSettingsChanged); - HookConVarChange(sas_vote_mode, ConVarSettingsChanged); - HookConVarChange(sas_vote_minplayers, ConVarSettingsChanged); - - /** - Register the command - */ - RegConsoleCmd("sm_scramblenow", Command_ScrambleNow, "sm_scramblenow (mode): Scrambles the teams"); - - /** - Load translations and .cfg file - */ - LoadTranslations ("simpleautoscrambler.phrases"); - AutoExecConfig(true, "plugin.simpleautoscrambler"); - LogAction(0, -1, "[SAS] Simple AutoScrambler is loaded."); -} - -public OnAllPluginsLoaded() -{ - //something -} - -public OnLibraryRemoved(const String:name[]) -{ - //something -} - -public OnConfigsExecuted() -{ - - /** - Load up all the variable defaults - */ - LoadUpVariables(); - - /** - Log our activity - */ - if (g_bIsEnabled) - LogAction(0, -1, "Simple AutoScrambler is ENABLED"); - else - LogAction(0, -1, "Simple AutoScrambler is DISABLED"); -} - -public Action:Command_ScrambleNow(client, args) -{ - - /** - Make sure we are enabled - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the client is authorized to run this command. - */ - if (!SM_IsValidAdmin(client, g_sScrambleNowFlag)) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure it's ok to scramble at this time - */ - if (!OkToScramble) - { - return Plugin_Handled; - } - - /** - Make sure it's ok to scramble at this time - */ - LogAction(0, -1, "[SAS] The scramblenow command was used"); - - /** - Scramble the teams - */ - StartAScramble(); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - -} - -public Action:Timer_ScrambleTeams(Handle:timer, any:mode) -{ - - /** - Make sure it's still ok to scramble - */ - if (!OkToScramble) - { - return Plugin_Handled; - } - - - switch (mode) - { - case - - - - } - - - /** - Reset the handle because the timer is over and the callback is done - */ - g_hScrambleTimer = INVALID_HANDLE; - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - -} - -stock StartAScramble(mode) -{ - - /** - See if we are already started a scramble - */ - if (g_hScrambleTimer == INVALID_HANDLE) - { - - /** - There is a scramble in progress - */ - return; - - } - - /** - Report that a scramble is about to start - */ - PrintCenterTextAll("%T", "Scramble", LANG_SERVER); - - /** - Start a timer and log the action - */ - g_hScrambleTimer = CreateTimer(g_fTimer_ScrambleDelay, Timer_ScrambleTeams, mode, TIMER_FLAG_NO_MAPCHANGE); - LogAction(0, -1, "[SAS] A scamble timer was started"); -} - -stock bool:OkToScramble() -{ - -} - -stock LoadUpVariables() -{ - g_bIsEnabled = GetConVarBool(sas_enabled); - g_bIsAutoScrambleEnabled = GetConVarBool(sas_autoscramble_enabled); - g_bIsVoteEnabled = GetConVarBool(sas_vote_enabled); - g_bIsAdminImmunityEnabled = GetConVarBool(sas_admin_immunity_enabled); - g_iAutoScramble_Minplayers = GetConVarInt(sas_autoscramble_minplayers); - g_iAutoScramble_Mode = GetConVarInt(sas_autoscramble_mode); - g_iAutoScramble_WinStreak = GetConVarInt(sas_autoscramble_winstreak); - g_iAutoScramble_SteamRoll = GetConVarInt(sas_autoscramble_steamroll); - g_iAutoScramble_Frags = GetConVarInt(sas_autoscramble_frags); - g_iVote_Mode = GetConVarInt(sas_vote_mode); - g_iVote_MinPlayers = GetConVarInt(sas_vote_minplayers); - GetConVarString(sas_admin_flag_scramblenow, g_sScrambleNowFlag, sizeof(g_sScrambleNowFlag)); - GetConVarString(sas_admin_flag_immunity, g_sAdminImmunityFlag, sizeof(g_sAdminImmunityFlag)); - g_fTimer_ScrambleDelay = GetConVarFloat(sas_timer_scrambledelay); - g_fVote_UpCount = GetConVarFloat(sas_vote_upcount); - g_fVote_WinPercent = GetConVarFloat(sas_vote_winpercent); - g_iMaxEntities = GetMaxEntities(); - g_iOwnerOffset = FindSendPropInfo("CBaseObject", "m_hBuilder"); -} - -stock TF2_DestroyBuildings(client) -{ - - /** - We have to start a loop to check the owner of all the valid entities - */ - for (new i = MaxClients + 1; i <= g_iMaxEntities; i++) - { - if (!IsValidEntity(i)) - { - - /** - Not valid, continue to next one - */ - continue; - } - - /** - Get the name of the current entity - */ - decl String:sNetClass[32]; - GetEntityNetClass(i, sNetClass, sizeof(sNetClass)); - - /** - See if its something that an engineer would build - */ - if (strcmp(sNetClass, "CObjectSentrygun") == 0 - || strcmp(sNetClass, "CObjectTeleporter") == 0 - || strcmp(sNetClass, "CObjectDispenser") == 0) - { - - /** - It is, so lets check the owner - */ - if (GetEntDataEnt2(i, g_iOwnerOffset) == client) - { - - /** - It's the clients building, so we blow it up. - */ - SetVariantInt(9999); - AcceptEntityInput(i, "RemoveHealth"); - } - } - } -} \ No newline at end of file diff --git a/Simple Spectate/addons/sourcemod/scripting/simple-chatcolors.sp b/Simple Spectate/addons/sourcemod/scripting/simple-chatcolors.sp deleted file mode 100644 index 539d057..0000000 --- a/Simple Spectate/addons/sourcemod/scripting/simple-chatcolors.sp +++ /dev/null @@ -1,496 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Chat Colors -Description: - Changes the colors of players chat based on config file -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#pragma semicolon 1 -#include -#include - -#define PLUGIN_VERSION "0.9.0.$Rev$" - -#define CHAT_SYMBOL '@' -#define TRIGGER_SYMBOL1 '!' -#define TRIGGER_SYMBOL2 '/' -#define CHAT_MAX_MESSAGE_LENGTH 1024 - -new Handle:g_hDebugCvar = INVALID_HANDLE; -new Handle:g_aGroupNames = INVALID_HANDLE; -new Handle:g_aGroupFlag = INVALID_HANDLE; -new Handle:g_aGroupNameColor = INVALID_HANDLE; -new Handle:g_aGroupTextColor = INVALID_HANDLE; - -new bool:g_bDebug = false; - -new g_iArraySize; - -new g_aPlayerColorIndex[MAXPLAYERS + 1] = { -1, ... }; - -public Plugin:myinfo = -{ - name = "Simple Chat Colors", - author = "Simple Plugins", - description = "Changes the colors of players chat based on config file.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -/** -Sourcemod callbacks -*/ -public OnPluginStart() -{ - - /** - Need to create all of our console variables. - */ - CreateConVar("sm_chatcolors_version", PLUGIN_VERSION, "Simple Chat Colors", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - g_hDebugCvar = CreateConVar("sm_chatcolors_debug", "1", "Enable/Disable debugging information"); - - /** - Hook console variables - */ - HookConVarChange(g_hDebugCvar, ConVarSettingsChanged); - - /** - Need to register the commands we are going to use - */ - RegConsoleCmd("say", Command_Say); - RegConsoleCmd("say_team", Command_SayTeam); - RegAdminCmd("sm_reloadcolorsconfig", Command_Reload, ADMFLAG_GENERIC, "Reloads settings from config file"); - - /** - Create the arrays - */ - g_aGroupNames = CreateArray(256, 1); - g_aGroupFlag = CreateArray(15, 1); - g_aGroupNameColor = CreateArray(15, 1); - g_aGroupTextColor = CreateArray(15, 1); - - /** - Load the admins and colors from the config - */ - LoadAdminsAndColorsFromConfig(); - g_iArraySize = GetArraySize(g_aGroupNames); -} - -public OnConfigsExecuted() -{ - g_bDebug = GetConVarBool(g_hDebugCvar); - ReloadConfigFile(); -} - -public OnClientPostAdminCheck(client) -{ - - /** - Check the client to see if they are a admin - */ - CheckAdmin(client); -} - -public OnClientDisconnect(client) -{ - g_aPlayerColorIndex[client] = -1; -} - -/** -Commands -*/ -public Action:Command_Say(client, args) -{ - - /** - Make sure we are enabled. - */ - if (client == 0 || IsChatTrigger()) - { - return Plugin_Continue; - } - - if (g_aPlayerColorIndex[client] != -1) - { - - /** - The client is, so get the chat message and strip it down. - */ - decl String:sArg[CHAT_MAX_MESSAGE_LENGTH], - String:sChatMsg[CHAT_MAX_MESSAGE_LENGTH]; - - new bool:bAlive = IsPlayerAlive(client); - - GetCmdArgString(sArg, sizeof(sArg)); - StripQuotes(sArg); - TrimString(sArg); - new startidx; - if (sArg[strlen(sArg)-1] == '"') - { - sArg[strlen(sArg)-1] = '\0'; - startidx = 1; - } - - /** - Bug out if they are using the admin chat symbol (admin chat). If we are in CSS it may not find all the triggers, so we double check. - */ - if (sArg[startidx] == CHAT_SYMBOL || sArg[startidx] == TRIGGER_SYMBOL1 || sArg[startidx] == TRIGGER_SYMBOL2) - { - return Plugin_Continue; - } - - /** - Log the message for hlstatsx and other things. - */ - new iUserID = GetClientUserId(client); - decl String:sAuthID[64]; - GetClientAuthString(client, sAuthID, sizeof(sAuthID)); - LogToGame("\"%N<%i><%s><>\" say \"%s\"", client, iUserID, sAuthID, sArg); - - /** - Format the message. - */ - FormatMessage(client, 0, bAlive, sChatMsg, sArg, g_aPlayerColorIndex[client]); - - /** - Send the message. - */ - //SayText2(0, client, sChatMsg); - CPrintToChatAll(sChatMsg); - - /** - We are done, bug out, and stop the original chat message. - */ - return Plugin_Stop; - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Command_SayTeam(client, args) -{ - - /** - Make sure we are enabled. - */ - if (client == 0 || IsChatTrigger()) - { - return Plugin_Continue; - } - - /** - Check the client to see if they are a admin - */ - if (g_aPlayerColorIndex[client] != -1) - { - - /** - The client is, so get the chat message and strip it down. - */ - decl String:sArg[CHAT_MAX_MESSAGE_LENGTH], - String:sChatMsg[CHAT_MAX_MESSAGE_LENGTH]; - - new bool:bAlive = IsPlayerAlive(client); - new iCurrentTeam = GetClientTeam(client); - - GetCmdArgString(sArg, sizeof(sArg)); - StripQuotes(sArg); - TrimString(sArg); - new startidx; - if (sArg[strlen(sArg)-1] == '"') - { - sArg[strlen(sArg)-1] = '\0'; - startidx = 1; - } - - /** - Bug out if they are using the admin chat symbol (admin chat). - */ - if (sArg[startidx] == CHAT_SYMBOL || sArg[startidx] == TRIGGER_SYMBOL1 || sArg[startidx] == TRIGGER_SYMBOL2) - { - return Plugin_Continue; - } - - /** - Log the message for hlstatsx and other things. - */ - new iUserID = GetClientUserId(client); - decl String:sAuthID[64]; - GetClientAuthString(client, sAuthID, sizeof(sAuthID)); - LogToGame("\"%N<%i><%s><>\" say_team \"%s\"", client, iUserID, sAuthID, sArg); - - /** - Format the message. - */ - FormatMessage(client, iCurrentTeam, bAlive, sChatMsg, sArg, g_aPlayerColorIndex[client]); - - /** - Send the message to the same team - */ - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == iCurrentTeam) - { - CPrintToChat(client, sChatMsg); - } - } - - /** - We are done, bug out, and stop the original chat message. - */ - return Plugin_Stop; - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Command_Reload(client, args) -{ - ReloadConfigFile(); - return Plugin_Handled; -} - -/** -Stock Functions -*/ -stock LoadAdminsAndColorsFromConfig() -{ - - /** - Make sure the config file is here and load it up - */ - new String:sConfigFile[256]; - BuildPath(Path_SM, sConfigFile, sizeof(sConfigFile), "configs/simple-chatcolors.cfg"); - if (!FileExists(sConfigFile)) - { - - /** - Config file doesn't exists, stop the plugin - */ - LogError("[SCC] Simple Chat Colors is not running! Could not find file %s", sConfigFile); - SetFailState("Could not find file %s", sConfigFile); - } - - /** - Create the arrays and variables - */ - new String:sGroupName[256]; - new String:sGroupFlag[15]; - new String:sGroupNameColor[15]; - new String:sGroupTextColor[15]; - - - /** - Load config file as a KeyValues file - */ - new Handle:kvChatColors = CreateKeyValues("admin_colors"); - FileToKeyValues(kvChatColors, sConfigFile); - - if (!KvGotoFirstSubKey(kvChatColors)) - { - return; - } - - /** - Load up all the groups in the file - */ - do - { - - /** - Get the section name; should be the "group" name - */ - KvGetSectionName(kvChatColors, sGroupName, sizeof(sGroupName)); - - - /** - Get the flags and colors - */ - KvGetString(kvChatColors, "flag", sGroupFlag, sizeof(sGroupFlag)); - KvGetString(kvChatColors, "namecolor", sGroupNameColor, sizeof(sGroupNameColor)); - KvGetString(kvChatColors, "textcolor", sGroupTextColor, sizeof(sGroupTextColor)); - - if (g_bDebug) - { - LogMessage("Group Name/SteamID: %s", sGroupName); - LogMessage("Flag String: %s", sGroupFlag); - LogMessage("Color on name: %s", sGroupNameColor); - LogMessage("Color of text: %s", sGroupTextColor); - } - - /** - Push the values to the arrays - */ - PushArrayString(g_aGroupNames, sGroupName); - PushArrayString(g_aGroupFlag, sGroupFlag); - PushArrayString(g_aGroupNameColor, sGroupNameColor); - PushArrayString(g_aGroupTextColor, sGroupTextColor); - } while (KvGotoNextKey(kvChatColors)); - - /** - Close our handle - */ - CloseHandle(kvChatColors); -} - -stock ReloadConfigFile() -{ - - /** - Clear the array - */ - ClearArray(g_aGroupNames); - ClearArray(g_aGroupFlag); - ClearArray(g_aGroupNameColor); - ClearArray(g_aGroupTextColor); - - /** - Load the admins, groups, and colors from the config - */ - LoadAdminsAndColorsFromConfig(); - g_iArraySize = GetArraySize(g_aGroupNames); - - /** - Recheck all the online players for assigned colors - */ - for (new index = 1; index <= MaxClients; index++) - { - if (IsClientConnected(index) && IsClientInGame(index)) - { - CheckAdmin(index); - } - } -} - -stock CheckAdmin(client) -{ - new String:sFlags[15]; - new String:sClientSteamID[64]; - new iGroupFlags; - new iFlags; - new iIndex = -1; - - /** - Look for a steamid first - */ - GetClientAuthString(client, sClientSteamID, sizeof(sClientSteamID)); - iIndex = FindStringInArray(g_aGroupNames, sClientSteamID); - if (iIndex != -1) - { - g_aPlayerColorIndex[client] = iIndex; - } - - /** - Didn't find one, check flags - */ - else - { - /** - Search for flag in groups - */ - - iFlags = GetUserFlagBits(client); - for (iIndex = 0; iIndex < g_iArraySize; iIndex++) - { - GetArrayString(g_aGroupFlag, iIndex, sFlags, sizeof(sFlags)); - iGroupFlags = ReadFlagString(sFlags); - if (iFlags & iGroupFlags) - { - g_aPlayerColorIndex[client] = iIndex; - break; - } - } - } - - if (g_bDebug) - { - PrintToChatAll("SteamID: %s", sClientSteamID); - PrintToChatAll("Array Index: %i", iIndex); - PrintToChatAll("Flag String: %s", sFlags); - PrintToChatAll("Flag Bits of Client: %i", iFlags); - PrintToChatAll("Flag Bits of Group: %i", iGroupFlags); - } -} - -stock FormatMessage(iClient, iTeam, bool:bAlive, String:sChatMsg[], const Sting:sMessage[], iArrayIndex) -{ - decl String:sDead[10], - String:sTeam[10], - String:sClientName[64]; - - GetClientName(iClient, sClientName, sizeof(sClientName)); - - if (iTeam != 0) - { - Format(sTeam, sizeof(sTeam), "(TEAM) "); - } - else - { - Format(sTeam, sizeof(sTeam), ""); - } - if (bAlive) - { - Format(sDead, sizeof(sDead), ""); - } - else - { - Format(sDead, sizeof(sDead), "*DEAD* "); - } - - new String:sNameColor[15]; - new String:sTextColor[15]; - GetArrayString(g_aGroupNameColor, iArrayIndex, sNameColor, sizeof(sNameColor)); - GetArrayString(g_aGroupTextColor, iArrayIndex, sTextColor, sizeof(sTextColor)); - - Format(sChatMsg, CHAT_MAX_MESSAGE_LENGTH, "{default}%s%s%s%s {default}: %s%s", sDead, sTeam, sNameColor, sClientName, sTextColor, sMessage); -} - -/** -Adjust the settings if a convar was changed -*/ -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (StringToInt(newValue) == 1) - { - g_bDebug = true; - } - else - { - g_bDebug = false; - } -} \ No newline at end of file diff --git a/Simple Spectate/addons/sourcemod/scripting/simple-donatorbenefits.sp b/Simple Spectate/addons/sourcemod/scripting/simple-donatorbenefits.sp deleted file mode 100644 index e3f6845..0000000 --- a/Simple Spectate/addons/sourcemod/scripting/simple-donatorbenefits.sp +++ /dev/null @@ -1,1312 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Donator Benefits -Description: - Provides donator benefits to players -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include -#include - -#define PLUGIN_VERSION "1.1.$Rev$" - -#define CHAT_SYMBOL '@' -#define CHAT_MAX_MESSAGE_LENGTH 1024 - -enum PlayerData -{ - bool:bIsDonator, - bool:bQueue, - bool:bImmune, - iHealthCount, - iNewTeam -}; - -/** - Public convar handles - */ -new Handle:sdb_enabled = INVALID_HANDLE; -new Handle:sdb_donationflag = INVALID_HANDLE; -new Handle:sdb_soundfile = INVALID_HANDLE; -new Handle:sdb_joinsound_enabled = INVALID_HANDLE; -new Handle:sdb_joinpubmsg_enabled = INVALID_HANDLE; -new Handle:sdb_joinprivmsg_enabled = INVALID_HANDLE; -new Handle:sdb_chatcolors_enabled = INVALID_HANDLE; -new Handle:sdb_immunity_enabled = INVALID_HANDLE; -new Handle:sdb_ubercharge_enabled = INVALID_HANDLE; -new Handle:sdb_givehealth_enabled = INVALID_HANDLE; -new Handle:sdb_nofalldmg_enabled = INVALID_HANDLE; -new Handle:sdb_fastheavy_enabled = INVALID_HANDLE; -new Handle:sdb_swapteam_enabled = INVALID_HANDLE; -new Handle:sdb_chatcolor = INVALID_HANDLE; -new Handle:sdb_uberlevel = INVALID_HANDLE; -new Handle:sdb_healthcount = INVALID_HANDLE; -new Handle:sdb_healthbonus = INVALID_HANDLE; -new Handle:sdb_heavymultiplier = INVALID_HANDLE; - -/** -Create global enable/disable bools so we don't have to check the console variable on every call -*/ -new bool:g_bIsEnabled = true; -new bool:g_bIsJoinSoundEnabled = true; -new bool:g_bIsJoinPubMsgEnabled = true; -new bool:g_bIsJoinPrivMsgEnabled = true; -new bool:g_bIsChatColorsEnabled = true; -new bool:g_bIsImmuntyEnabled = true; -new bool:g_bIsUberChargeEnabled = true; -new bool:g_bIsGiveHealthEnabled = true; -new bool:g_bIsNoFallDmgEnabled = true; -new bool:g_bIsFastHeayEnabled = true; -new bool:g_bIsSwapTeamEnabled = true; - -/** - Player arrays - */ -new g_aPlayers[MAXPLAYERS + 1][PlayerData]; - - -/** -Rest of the globals -*/ -new bool:g_bRoundEnd = false; -new String:g_sCharDonatorFlag[5]; -new String:g_sSoundFile[PLATFORM_MAX_PATH]; -new String:g_sChatColor[11]; -new g_iHealthBonus; -new g_iHealthCount; -new g_iClassMaxHealth[TFClassType] = {0, 125, 125, 200, 175, 150, 300, 175, 125, 125}; -new g_fClassMaxSpeed[TFClassType] = {0, 400, 300, 240, 280, 320, 230, 300, 300, 300}; -new Float:g_fHeavyMultiplier = 0.0; -new Float:g_fUberLevel = 0.0; - -public Plugin:myinfo = -{ - name = "Simple Donation Benefits", - author = "Simple Plugins", - description = "Gives donators benefits to players", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -} - -public OnPluginStart() -{ - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[SDB] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_connect", HookPlayerSpawn, EventHookMode_Pre); - HookEvent("player_spawn", HookPlayerSpawn, EventHookMode_Post); - HookEvent("player_death", HookPlayerDeath, EventHookMode_Post); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Post); - switch (g_CurrentMod) - { - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - HookEvent("player_changeclass", HookPlayerClass, EventHookMode_Post); - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_Post); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - - /** - Create console variables - */ - CreateConVar("sdb_version", PLUGIN_VERSION, "Simple Donation Benefits", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - sdb_enabled = CreateConVar("sdb_enabled", "1", "Enable/Disable Simple Donation Benefits"); - sdb_donationflag = CreateConVar("sdb_donationflag", "a", "Flag ALREADY given to donators. Must be in char format"); - - /** - Create the enable/disable donator console variables - */ - sdb_joinsound_enabled = CreateConVar("sdb_joinsound_enabled", "1", "Enable/Disable donator join sound"); - sdb_joinpubmsg_enabled = CreateConVar("sdb_joinpubmsg_enabled", "1", "Enable/Disable public donator join message (replaces: as connected)"); - sdb_joinprivmsg_enabled = CreateConVar("sdb_joinprivmsg_enabled", "1", "Enable/Disable private donator join message (sent only to donator)"); - sdb_chatcolors_enabled = CreateConVar("sdb_chatcolors_enabled", "1", "Enable/Disable donator chat colors"); - sdb_immunity_enabled = CreateConVar("sdb_immunity_enabled", "1", "Enable/Disable donator round end immunity"); - sdb_ubercharge_enabled = CreateConVar("sdb_ubercharge_enabled", "1", "Enable/Disable donator medics starting with ubercharge"); - sdb_givehealth_enabled = CreateConVar("sdb_givehealth_enabled", "1", "Enable/Disable donator instant health bonus"); - sdb_nofalldmg_enabled = CreateConVar("sdb_nofalldmg_enabled", "1", "Enable/Disable no fall damage for donators"); - sdb_fastheavy_enabled = CreateConVar("sdb_fastheavy_enabled", "1", "Enable/Disable donator heavies moving faster while spinning"); - sdb_swapteam_enabled = CreateConVar("sdb_swampteam_enabled", "1", "Enable/Disable donator swap team ability"); - - /** - Create the donator setting console variables - */ - sdb_soundfile = CreateConVar("sdb_soundfile", "custom/donatorjoin.mp3", "The location of sound file"); - sdb_chatcolor = CreateConVar("sdb_chatcolor", "green", "Color to use for donator chat. Valid colors are green and lightgreen"); - sdb_uberlevel = CreateConVar("sdb_uberlevel", "0.5", "Uberlevel to give donator medic at spawn. 1.0 = full uber", _, true, 0.0, true, 1.0); - sdb_healthcount = CreateConVar("sdb_healthcount", "1", "Number of times a donator can use use instant health per life"); - sdb_healthbonus = CreateConVar("sdb_healthbonus", "100", "The amount of health to heal the donator"); - sdb_heavymultiplier = CreateConVar("sdb_heavyspeed", "0.5", "The speed multiplier for the fast heavy. Based on running speed. 1.0 = running speed. (Game Default is 0.20)", _, true, 0.0, true, 1.0); - - /** - Hook dukehacks calls - */ - dhAddClientHook(CHK_TakeDamage, Hacks_TakeDamageHook); - dhAddClientHook(CHK_PreThink, Hacks_PreThinkHook); - - /** - Hook the console variables if they change - */ - HookConVarChange(sdb_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_donationflag, ConVarSettingsChanged); - HookConVarChange(sdb_joinsound_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_joinpubmsg_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_joinprivmsg_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_chatcolors_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_immunity_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_ubercharge_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_givehealth_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_nofalldmg_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_swapteam_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_fastheavy_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_soundfile, ConVarSettingsChanged); - HookConVarChange(sdb_chatcolor, ConVarSettingsChanged); - HookConVarChange(sdb_uberlevel, ConVarSettingsChanged); - HookConVarChange(sdb_healthcount, ConVarSettingsChanged); - HookConVarChange(sdb_healthbonus, ConVarSettingsChanged); - HookConVarChange(sdb_heavymultiplier, ConVarSettingsChanged); - - /** - Register the commands - */ - RegConsoleCmd("sm_swapteams", Command_SwapTeam, "sm_swapteams <[0]instant/[1]queued>: Swaps your team to the other team"); - RegConsoleCmd("sm_ihealth", Command_InstantHealth, "sm_ihealth: Gives you a instant health pack"); - RegAdminCmd("sm_teaser", Command_Teaser, ADMFLAG_GENERIC,"sm_teaser <[0]add/[1]remove>: Gives temporary donator privilages to a player"); - RegConsoleCmd("say", Command_Say); - - RegConsoleCmd("sm_test", Command_TEST); - - /** - Load the translations - */ - LoadTranslations("common.phrases"); - LoadTranslations("simpledonatorbenefits.phrases"); - - /** - Load or create the config file - */ - AutoExecConfig(true, "plugin.simpledonatorbenefits"); - LogAction(0, -1, "[SDB] Simple Donator Benefits is loaded."); -} - -public OnAllPluginsLoaded() -{ - //something -} - -public OnLibraryRemoved(const String:name[]) -{ - //something -} - -public OnConfigsExecuted() -{ - /** - Load up all the variable defaults - */ - LoadUpVariables(); - - /** - If the join sound is enabled, prep the sound files - */ - if (g_bIsJoinSoundEnabled) - PrepSoundFile(); - - /** - Log our activity - */ - if (g_bIsEnabled) - LogAction(0, -1, "Simple Donation Benefits is ENABLED"); - else - LogAction(0, -1, "Simple Donation Benefits is DISABLED"); -} - -public OnClientPostAdminCheck(client) -{ - - /** - Check if the client is a donator - */ - if (SM_IsValidAdmin(client, g_sCharDonatorFlag)) - { - - /** - They are, so we set the player array to true and start a timer for the sound or add - */ - g_aPlayers[client][bIsDonator] = true; - if (g_bIsJoinSoundEnabled || g_bIsJoinPrivMsgEnabled) - { - CreateTimer(10.0, Timer_DonatorJoined, client, TIMER_FLAG_NO_MAPCHANGE); - } - } - else - { - /** - They aren't, so we set the player array to false - */ - g_aPlayers[client][bIsDonator] = false; - } -} - -public OnClientDisconnect_Post(client) -{ - - /** - Clean up the player variables - */ - CleanUpPlayer(client); -} - -public Action:Command_SwapTeam(client, args) -{ - - /** - Make sure we are enabled - */ - if (!g_bIsEnabled || !g_bIsSwapTeamEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the command is not started by the server - */ - if (client == 0) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure the player is a donator - */ - if (!g_aPlayers[client][bIsDonator]) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Lets make sure the client is one a team we can swap. - If he is we set the global array to the opposite team. - */ - new iTeam = GetClientTeam(client); - if (iTeam == g_aCurrentTeams[Team1]) - { - g_aPlayers[client][iNewTeam] = g_aCurrentTeams[Team2]; - } - else if (iTeam == g_aCurrentTeams[Team2]) - { - g_aPlayers[client][iNewTeam] = g_aCurrentTeams[Team1]; - } - else - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "InValidTeam", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check to see if we have command arguments. - */ - if (GetCmdArgs()) - { - - /** - We do, so lets get it and see if the client wants to be switched instantly or queued for death. - */ - decl String:sArg[5]; - GetCmdArg(1, sArg, sizeof(sArg)); - new iWantsQue = StringToInt(sArg); - if (iWantsQue && !g_aPlayers[client][bQueue]) - { - - /** - He wants the que and isn't already in it, set the global array. - */ - g_aPlayers[client][bQueue] = true; - ReplyToCommand(client, "\x01\x04[STM]\x01 %T", "PlayerQueue", LANG_SERVER); - } - else if (!iWantsQue) - { - - /** - He wants to be switched right now, lets call the stock function. - */ - SM_MovePlayer(client, g_aPlayers[client][iNewTeam]); - } - } - else - { - - /** - There are no command arguments so we build and display the swap menu. - */ - new Handle:hPlayerMenu = BuildSwapModeMenu(); - DisplayMenu(hPlayerMenu, client, MENU_TIME_FOREVER); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_InstantHealth(client, args) -{ - - /** - Make sure we are enabled - */ - if (!g_bIsEnabled || !g_bIsGiveHealthEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the command is not started by the server - */ - if (client == 0) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure the player is a donator - */ - if (!g_aPlayers[client][bIsDonator]) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check health count to see if the player has reached the max - */ - if (g_aPlayers[client][iHealthCount] >= g_iHealthCount) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "ReachedCount", LANG_SERVER); - return Plugin_Handled; - } - - /** - Get the class of the player and the max health for that class - */ - new iHealth = GetClientHealth(client); - new TFClassType:PlayerClass = TF2_GetPlayerClass(client); - new iMaxHealth = g_iClassMaxHealth[PlayerClass]; - - /** - Check to see if the player is at the max health of the class - */ - if (iHealth >= iMaxHealth) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "AtMaxHealth", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check the current health - */ - if (iHealth + g_iHealthBonus >= iMaxHealth) - { - - /** - Raise them to max health if the current health + bonus would go above it - */ - SetEntityHealth(client, iMaxHealth); - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "ToMaxHealth", LANG_SERVER); - } - else - { - - /** - Give them the instant health bonus - */ - SetEntityHealth(client, iHealth + g_iHealthBonus); - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "HealthBonus", LANG_SERVER); - } - - /** - Increase the count - */ - g_aPlayers[client][iHealthCount] += 1; - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_Teaser(client, args) -{ - - /** - Make sure we are enabled - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Check to see if we have command arguments. - */ - new iCmdArgs = GetCmdArgs(); - if (iCmdArgs == 0) - { - - /** - We don't so display the player menu. - */ - new Handle:hPlayerMenu = BuildPlayerMenu(); - DisplayMenu(hPlayerMenu, client, MENU_TIME_FOREVER); - return Plugin_Handled; - } - - /** - We have some arguments, see if we can find the player - */ - decl String:sPlayer[64]; - GetCmdArg(1, sPlayer, sizeof(sPlayer)); - new iTarget = FindTarget(client, sPlayer, true, true); - if (iTarget == -1 || !IsClientInGame(iTarget)) - { - - /** - We don't know who this is, so display the player menu. - */ - new Handle:hPlayerMenu = BuildPlayerMenu(); - DisplayMenu(hPlayerMenu, client, MENU_TIME_FOREVER); - } - else - { - /** - We found the player, see if we are supposed to turn it on or off. - */ - if (iCmdArgs >= 2) - { - decl String:sOn[3]; - GetCmdArg(2, sOn, sizeof(sOn)); - if (StringToInt(sOn)) - { - - /** - Turn temp benefits on. - */ - g_aPlayers[iTarget][bIsDonator] = true; - } - else - { - - /** - Turn temp benefits on. - */ - g_aPlayers[iTarget][bIsDonator] = false; - } - } - else - { - - /** - We don't know what to do, so just turn it on. - */ - g_aPlayers[iTarget][bIsDonator] = true; - } - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_Say(client, args) -{ - - /** - Make sure we are enabled. - */ - if (client == 0 || IsChatTrigger() || !g_bIsChatColorsEnabled || !g_bIsEnabled) - { - return Plugin_Continue; - } - - /** - Check the client to see if they are a donator. - */ - if (g_aPlayers[client][bIsDonator]) - { - - /** - The client is, so get the chat message and strip it down. - */ - decl String:sArg[CHAT_MAX_MESSAGE_LENGTH], - String:sChatMsg[CHAT_MAX_MESSAGE_LENGTH]; - new bool:bAlive = IsPlayerAlive(client); - GetCmdArgString(sArg, sizeof(sArg)); - StripQuotes(sArg); - TrimString(sArg); - new startidx; - if (sArg[strlen(sArg)-1] == '"') - { - sArg[strlen(sArg)-1] = '\0'; - startidx = 1; - } - - /** - Bug out if they are using the admin chat symbol (admin chat). - */ - if (sArg[startidx] == CHAT_SYMBOL) - { - return Plugin_Continue; - } - - /** - Format the message. - */ - FormatMessage(client, 0, bAlive, sChatMsg, sArg); - - /** - Send the message. - */ - SayText2(0, client, sChatMsg); - - /** - We are done, bug out, and stop the original chat message. - */ - return Plugin_Stop; - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Hacks_TakeDamageHook(client, attacker, inflictor, Float:damage, &Float:multiplier, damagetype) -{ - - /** - Make sure we are enabled and the client is a donator. - */ - if (g_bIsEnabled && g_bIsNoFallDmgEnabled && g_aPlayers[client][bIsDonator]) - { - - /** - Check for fall damage. - */ - if (damagetype & DMG_FALL) - { - - /** - Cancel the fall damage and bug out. - */ - multiplier *= 0.0; - return Plugin_Changed; - } - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Hacks_PreThinkHook(client) -{ - - /** - Make sure we are enabled and the client is a donator. - */ - if (!g_bIsEnabled || !g_bIsFastHeayEnabled || !g_aPlayers[client][bIsDonator]) - { - return Plugin_Continue; - } - - /** - Check the players class. We are looking for the heavy. - */ - new TFClassType:PlayerClass = TF2_GetPlayerClass(client); - if (PlayerClass == TFClass_Heavy) - { - - /** - We have a heavy, lets check the weapon. - */ - decl String:sWeaponCurrent[64]; - GetClientWeapon(client, sWeaponCurrent, sizeof(sWeaponCurrent)); - if (StrEqual(sWeaponCurrent, "tf_weapon_minigun", false)) - { - - /** - We have a minigun, check the heavies current weapon state to see if it's spinning. - */ - new iWeapon = GetPlayerWeaponSlot(client, 0); - new iWeaponState = GetEntProp(iWeapon, Prop_Send, "m_iWeaponState"); - if (iWeaponState > 0) - { - - /** - He is spinning, so lets change the heavies speed. - */ - new Float:fMaxSpeed = FloatMul(g_fHeavyMultiplier, float(g_fClassMaxSpeed[PlayerClass])); - SetEntPropFloat(client, Prop_Send, "m_flMaxspeed", fMaxSpeed); - } - } - } - - /** - We are done, bug out. - */ - // use Plugin_Continue (other options are ignored on PreThink hook) - return Plugin_Continue; -} - -public Action:HookPlayerConnect(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (!g_bIsEnabled || !g_bIsJoinPubMsgEnabled || !dontBroadcast) - { - return Plugin_Continue; - } - - /** - Get our event variables and check the client. - */ - new iUserId = GetEventInt(event,"userid"); - new iClient = GetClientOfUserId(iUserId); - if (iClient != 0) - { - - /** - Get the info on the client and format the message. - */ - decl String:sClientName[255], - String:sAuthID[255], - String:sMsg[1024]; - - GetEventString(event, "name", sClientName, sizeof(sClientName)); - GetClientAuthString(iClient, sAuthID, sizeof(sAuthID)); - Format(sMsg, sizeof(sMsg), "%T", "PublicJoinMessage", LANG_SERVER, sClientName); - - /** - Print the message to the clients and do the normal functions. - */ - for (new i = 1; i <= MaxClients; i++) - { - if(IsClientConnected(i) && IsClientInGame(i)) - { - PrintToChat(i,"\x01\x05%s", sMsg); - PrintToConsole(i,"%s has connected.", sClientName); - } - } - LogToGame("\"%s<%d><%s><>\" entered the game", sClientName, iUserId, sAuthID); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public HookPlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled && g_bIsUberChargeEnabled) - { - - /** - Get the event variables and check the class for medic - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - if (TF2_GetPlayerClass(iClient) == TFClass_Medic) - { - - /** - Start a timer to get the medic the uber boost - */ - CreateTimer(0.25, Timer_PlayerUberDelay, iClient, TIMER_FLAG_NO_MAPCHANGE); - } - } -} - -public HookPlayerClass(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled && g_bIsUberChargeEnabled) - { - - /** - Get the event variables and check the class for medic - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - if (TF2_GetPlayerClass(iClient) == TFClass_Medic) - { - - /** - Start a timer to get the medic the uber boost - */ - CreateTimer(0.25, Timer_PlayerUberDelay, iClient, TIMER_FLAG_NO_MAPCHANGE); - } - } -} - -public HookPlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled || g_bIsSwapTeamEnabled) - { - - /** - Get the event variables - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - new String:sWeapon[256]; - GetEventString(event, "weapon", sWeapon, sizeof(sWeapon)); - - /** - Bug out if world killed him. Means he changed team or something - */ - if (StrEqual(sWeapon, "world", false)) - { - g_aPlayers[iClient][bQueue] = false; - return; - } - - /** - If he is queued up, swap him - */ - if (g_aPlayers[iClient][bQueue]) - { - SM_MovePlayer(iClient, g_aPlayers[iClient][iNewTeam]); - } - } -} - -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled || g_bIsSwapTeamEnabled) - { - - /** - Get the event variables - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - - /** - If he is queued up, clear the status - */ - if (g_aPlayers[iClient][bQueue]) - { - g_aPlayers[iClient][bQueue] = false; - } - } -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set our variables. - */ - g_bRoundEnd = false; - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled && g_bIsImmuntyEnabled) - { - - /** - Get rid of their immunity. - */ - ProcessRoundEndImmunity(false); - } -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set our variables. - */ - g_bRoundEnd = true; - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled && g_bIsImmuntyEnabled) - { - - /** - Give them their immunity. - */ - ProcessRoundEndImmunity(true); - } -} - -public Action:Timer_DonatorJoined(Handle:timer, any:client) -{ - - /** - Make sure sounds are enabled. - */ - if (g_bIsEnabled && g_bIsJoinSoundEnabled) - { - EmitSoundToClient(client, g_sSoundFile); - } - - /** - Make sure private messages are enabled. - */ - if (g_bIsJoinPrivMsgEnabled) - { - - /** - Send messages to the client. - */ - decl String:sMsg[1024]; - Format(sMsg, sizeof(sMsg), "%T", "PrivateJoinMessage", LANG_SERVER); - PrintToChat(client,"\x01\x05%s", sMsg); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Timer_PlayerUberDelay(Handle:timer, any:client) -{ - - /** - Make sure the client is still in game. - */ - if (IsClientInGame(client)) - { - - /** - Make sure the client is still a medic. - */ - if (TF2_GetPlayerClass(client) == TFClass_Medic) - { - - /** - Get the medgun weapon index - */ - new iIndex = GetPlayerWeaponSlot(client, 1); - if (iIndex > 0) - { - - /** - Set the uber level with the bonus. - */ - SetEntPropFloat(iIndex, Prop_Send, "m_flChargeLevel", g_fUberLevel); - } - } - } -} - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (convar == sdb_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsEnabled = false; - } - else - { - g_bIsEnabled = true; - } - } - else if (convar == sdb_donationflag) - { - Format(g_sCharDonatorFlag, sizeof(g_sCharDonatorFlag), "%s", newValue); - } - else if (convar == sdb_soundfile) - { - Format(g_sSoundFile, sizeof(g_sSoundFile), "%s", newValue); - } - else if (convar == sdb_joinsound_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsJoinSoundEnabled = false; - } - else - { - g_bIsJoinSoundEnabled = true; - } - } - else if (convar == sdb_joinpubmsg_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsJoinPubMsgEnabled = false; - } - else - { - g_bIsJoinPubMsgEnabled = true; - } - } - else if (convar == sdb_joinprivmsg_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsJoinPrivMsgEnabled = false; - } - else - { - g_bIsJoinPrivMsgEnabled = true; - } - } - else if (convar == sdb_chatcolors_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsChatColorsEnabled = false; - } - else - { - g_bIsChatColorsEnabled = true; - } - } - else if (convar == sdb_immunity_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsImmuntyEnabled = false; - } - else - { - g_bIsImmuntyEnabled = true; - } - } - else if (convar == sdb_ubercharge_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsUberChargeEnabled = false; - } - else - { - g_bIsUberChargeEnabled = true; - } - } - else if (convar == sdb_givehealth_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsGiveHealthEnabled = false; - } - else - { - g_bIsGiveHealthEnabled = true; - } - } - else if (convar == sdb_nofalldmg_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsNoFallDmgEnabled = false; - } - else - { - g_bIsNoFallDmgEnabled = true; - } - } - else if (convar == sdb_fastheavy_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsFastHeayEnabled = false; - } - else - { - g_bIsFastHeayEnabled = true; - } - } - else if (convar == sdb_swapteam_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsSwapTeamEnabled = false; - } - else - { - g_bIsSwapTeamEnabled = true; - } - } - else if (convar == sdb_chatcolor) - { - Format(g_sChatColor, sizeof(g_sChatColor), "%s", newValue); - } - else if (convar == sdb_uberlevel) - { - g_fUberLevel = StringToFloat(newValue); - } - else if (convar == sdb_healthcount) - { - g_iHealthCount = StringToInt(newValue); - } - else if (convar == sdb_healthbonus) - { - g_iHealthBonus = StringToInt(newValue); - } - else if (convar == sdb_heavymultiplier) - { - g_fHeavyMultiplier = StringToFloat(newValue); - } -} - -stock LoadUpVariables() -{ - g_bIsEnabled = GetConVarBool(sdb_enabled); - g_bIsJoinSoundEnabled = GetConVarBool(sdb_enabled); - g_bIsJoinPubMsgEnabled = GetConVarBool(sdb_enabled); - g_bIsJoinPrivMsgEnabled = GetConVarBool(sdb_enabled); - g_bIsChatColorsEnabled = GetConVarBool(sdb_enabled); - g_bIsImmuntyEnabled = GetConVarBool(sdb_enabled); - g_bIsUberChargeEnabled = GetConVarBool(sdb_enabled); - g_bIsGiveHealthEnabled = GetConVarBool(sdb_enabled); - g_bIsNoFallDmgEnabled = GetConVarBool(sdb_enabled); - g_bIsFastHeayEnabled = GetConVarBool(sdb_enabled); - g_bIsSwapTeamEnabled = GetConVarBool(sdb_enabled); - GetConVarString(sdb_donationflag, g_sCharDonatorFlag, sizeof(g_sCharDonatorFlag)); - GetConVarString(sdb_soundfile, g_sSoundFile, sizeof(g_sSoundFile)); - GetConVarString(sdb_chatcolor, g_sChatColor, sizeof(g_sChatColor)); - g_bRoundEnd = false; - g_iHealthBonus = GetConVarInt(sdb_healthbonus); - g_iHealthCount = GetConVarInt(sdb_healthcount); - g_fHeavyMultiplier = GetConVarFloat(sdb_heavymultiplier); - g_fUberLevel = GetConVarFloat(sdb_uberlevel); -} - -stock PrepSoundFile() -{ - decl String:buffer[PLATFORM_MAX_PATH]; - PrecacheSound(g_sSoundFile, true); - Format(buffer, sizeof(buffer), "sound/%s", g_sSoundFile); - AddFileToDownloadsTable(buffer); -} - -stock CleanUpPlayer(client) -{ - g_aPlayers[client][bIsDonator] = false; - g_aPlayers[client][bQueue] = false; - g_aPlayers[client][bImmune] = false; - g_aPlayers[client][iNewTeam] = 0; - g_aPlayers[client][iHealthCount] = 0; -} - -stock ProcessRoundEndImmunity(bool:give) -{ - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][bIsDonator]) - { - if (give) - { - SetEntProp(i, Prop_Data, "m_takedamage", 0, 1); - g_aPlayers[i][bImmune] = true; - } - else - { - SetEntProp(i, Prop_Data, "m_takedamage", 2, 1); - g_aPlayers[i][bImmune] = false; - } - } - } -} - -stock FormatMessage(iClient, iTeam, bool:bAlive, String:sChatMsg[], const Sting:sMessage[]) -{ - decl String:sDead[10], - String:sTeam[10], - String:sClientName[64]; - GetClientName(iClient, sClientName, sizeof(sClientName)); - if (iTeam != 0) - Format(sTeam, sizeof(sTeam), "(TEAM) "); - else - Format(sTeam, sizeof(sTeam), ""); - if (bAlive) - Format(sDead, sizeof(sDead), ""); - else - Format(sDead, sizeof(sDead), "*DEAD* "); - if (StrContains(g_sChatColor, "light", false) == -1) - Format(sChatMsg, CHAT_MAX_MESSAGE_LENGTH, "\x01%s%s\x03%s \x01: \x05%s", sDead, sTeam, sClientName, sMessage); - else - Format(sChatMsg, CHAT_MAX_MESSAGE_LENGTH, "\x01%s%s\x03%s \x01: \x04%s", sDead, sTeam, sClientName, sMessage); -} - -stock SayText2(target, author, const String:message[]) -{ - new Handle:hBf; - if (target == 0) - hBf = StartMessageAll("SayText2"); - else - hBf = StartMessageOne("SayText2", target); - if (hBf != INVALID_HANDLE) - { - BfWriteByte(hBf, author); - BfWriteByte(hBf, true); - BfWriteString(hBf, message); - EndMessage(); - } -} - -stock ProcessAdmins() -{ - for (new i = 1; i <= MaxClients; i++) - { - if (SM_IsValidAdmin(i, g_sCharDonatorFlag)) - { - g_aPlayers[i][bDonator] = true; - } - else - { - g_aPlayers[i][bDonator] = false; - } - } -} - -stock ProcessLate() -{ - if (g_bIsEnabled) - { - ProcessAdmins(); - PrepSoundFile(); - if (g_bRoundEnd && g_bIsImmuntyEnabled) - { - ProcessRoundEndImmunity(true); - } - if (!g_bIsImmuntyEnabled) - { - ProcessRoundEndImmunity(false); - } - } - else - { - ProcessRoundEndImmunity(false); - } -} - -public Menu_SwapMode(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, 64); - if (StringToInt(sSelection)) - g_aPlayers[param1][bQueue] = false; - else - g_aPlayers[param1][bQueue] = true; - if (!g_aPlayers[param1][bQueue]) - SM_MovePlayer(param1, g_aPlayers[param1][iNewTeam]); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -public Menu_SelectPlayer(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[256]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - new iTarget = GetClientOfUserId(StringToInt(sSelection)); - if (g_aPlayers[iTarget][bIsDonator]) - g_aPlayers[iTarget][bIsDonator] = false; - else - g_aPlayers[iTarget][bIsDonator] = true; - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -stock Handle:BuildSwapModeMenu() -{ - new Handle:menu = CreateMenu(Menu_SwapMode); - SetMenuTitle(menu, "Select When to Swap:"); - AddMenuItem(menu, "0", "Instantly (Kills)"); - AddMenuItem(menu, "1", "Queue on next death"); - SetMenuExitBackButton(menu, false); - return menu; -} - -stock Handle:BuildPlayerMenu() -{ - new Handle:menu = CreateMenu(Menu_SelectPlayer); - AddTargetsToMenu(menu, 0, true, false); - SetMenuTitle(menu, "Select A Player:"); - SetMenuExitBackButton(menu, true); - return menu; -} - -public Action:Command_TEST(client, args) -{ - -} \ No newline at end of file diff --git a/Simple Spectate/addons/sourcemod/scripting/simple-messagesuppression.sp b/Simple Spectate/addons/sourcemod/scripting/simple-messagesuppression.sp deleted file mode 100644 index f7725a4..0000000 --- a/Simple Spectate/addons/sourcemod/scripting/simple-messagesuppression.sp +++ /dev/null @@ -1,227 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Message Suppression -Description: - Blocks Specific Message Outputs -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include -#include - -#define SUPPRESS_VERSION "1.1.$Rev$" - -public Plugin:myinfo = -{ - name = "Simple Message Suppression", - author = "FlyingMongoose, psychonic", - description = "Blocks Specific Message Outputs", - version = SUPPRESS_VERSION, - url = "http://www.simple-plugins.com/" -} - -new Handle:cvarBlockSpectateMessage; -new Handle:cvarBlockDisconnectMessage; -new Handle:cvarBlockConnectMessage; -new Handle:cvarAdminShowMessages; -new iSpecTeam = 1; - - -public OnPluginStart() -{ - CreateConVar("suppress_version", SUPPRESS_VERSION, _, FCVAR_PLUGIN|FCVAR_NOTIFY|FCVAR_REPLICATED|FCVAR_SPONLY|FCVAR_DONTRECORD); - cvarBlockSpectateMessage = CreateConVar("sm_blockspectatemessage", "1", "If enabled it blocks the join team message if an administrator joins spectator", FCVAR_PLUGIN, true, 0.0, true, 1.0); - cvarBlockDisconnectMessage = CreateConVar("sm_blockdisconnectmessage", "1", "Blocks the disconnect message", FCVAR_PLUGIN, true, 0.0, true, 1.0); - cvarBlockConnectMessage = CreateConVar("sm_blockconnectmessage", "1", "If enabled it blocks the player connection message.", FCVAR_PLUGIN, true, 0.0, true, 1.0); - cvarAdminShowMessages = CreateConVar("sm_adminshowmessages", "1", "Shows disconnect/connect/team join messages for admins only (if disconnect message is set to be blocked)", FCVAR_PLUGIN, true, 0.0, true, 1.0); - HookEvent("player_team", ev_PlayerTeam, EventHookMode_Pre); - HookEvent("player_disconnect", ev_PlayerDisconnect, EventHookMode_Pre); - HookEvent("player_connect", ev_PlayerConnect, EventHookMode_Pre); - - new String:game_folder[64]; - GetGameFolderName(game_folder, sizeof(game_folder)) - - if (StrContains(game_folder, "insurgency", false) != -1) - { - iSpecTeam = 3; - } - else - { - new String:game_description[64]; - GetGameDescription(game_description, sizeof(game_description), true); - if (StrContains(game_description, "Insurgency", false) != -1) - { - iSpecTeam = 3; - } - } - - AutoExecConfig(true, "suppressmessage", "sourcemod"); -} - -public Action:ev_PlayerTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (GetConVarBool(cvarBlockSpectateMessage)) - { - if (!dontBroadcast && !GetEventBool(event, "silent")) - { - new iUserId = GetEventInt(event, "userid"); - new iClient = GetClientOfUserId(iUserId); - new iTeam = GetEventInt(event, "team"); - - if (iTeam == iSpecTeam && GetAdminFlag(GetUserAdmin(iClient), Admin_Kick)) - { - new iOldTeam = GetEventInt(event, "oldteam"); - new bool:bDisconnect = GetEventBool(event, "disconnect"); - new bool:bAutoteam = GetEventBool(event, "autoteam"); - decl String:strName[50]; - GetEventString(event, "name", strName, sizeof(strName)); - - if (iClient != 0) - { - if (GetConVarInt(cvarAdminShowMessages) == 1) - { - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i) && GetUserAdmin(i) != INVALID_ADMIN_ID) - { - PrintToChat(i,"%N joined team Spectator.", iClient); - PrintToConsole(i,"%N joined team Spectator.", iClient); - } - } - } - } - - new Handle:hEvent = CreateEvent("player_team"); - SetEventInt(hEvent, "userid", iUserId); - SetEventInt(hEvent, "team", iTeam); - SetEventInt(hEvent, "oldteam", iOldTeam); - SetEventBool(hEvent, "disconnect", bDisconnect); - SetEventBool(hEvent, "autoteam", bAutoteam); - SetEventBool(hEvent, "silent", true); - SetEventString(hEvent, "name", strName); - - FireEvent(hEvent, true); - - return Plugin_Handled; - } - } - } - return Plugin_Continue; -} -public Action:ev_PlayerConnect(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (GetConVarBool(cvarBlockConnectMessage)) - { - if (!dontBroadcast) - { - decl String:strName[50]; - GetEventString(event, "name", strName, sizeof(strName)); - new iIndex = GetEventInt(event, "index"); - new iUserId = GetEventInt(event, "userid"); - new iClient = GetClientOfUserId(iUserId); - decl String:strNetworkId[50]; - GetEventString(event, "networkid", strNetworkId, sizeof(strNetworkId)); - decl String:strAddress[50]; - GetEventString(event, "address", strAddress, sizeof(strAddress)); - - if (iClient != 0) - { - if (GetConVarInt(cvarAdminShowMessages) == 1) - { - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i) && GetUserAdmin(i) != INVALID_ADMIN_ID) - { - PrintToChat(i,"%N has connected.", iClient); - PrintToConsole(i,"%N has connected.", iClient); - } - } - } - } - - new Handle:hEvent = CreateEvent("player_connect"); - SetEventString(hEvent, "name", strName); - SetEventInt(hEvent, "index", iIndex); - SetEventInt(hEvent, "userid", iUserId); - SetEventString(hEvent, "networkid", strNetworkId); - SetEventString(hEvent, "address", strAddress); - - FireEvent(hEvent, true); - - return Plugin_Handled; - } - } - return Plugin_Continue; -} -public Action:ev_PlayerDisconnect(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (GetConVarBool(cvarBlockDisconnectMessage)) - { - if (!dontBroadcast) - { - new iUserId = GetEventInt(event, "userid"); - new iClient = GetClientOfUserId(iUserId); - decl String:strReason[50]; - GetEventString(event, "reason", strReason, sizeof(strReason)); - decl String:strName[50]; - GetEventString(event, "name", strName, sizeof(strName)); - decl String:strNetworkId[50]; - GetEventString(event, "networkid", strNetworkId, sizeof(strNetworkId)); - - if (iClient != 0) - { - if (GetConVarInt(cvarAdminShowMessages) == 1) - { - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i) && GetUserAdmin(i) != INVALID_ADMIN_ID) - { - PrintToChat(i, "%N has left the server.", iClient); - PrintToConsole(i, "Dropped %N from server (Disconnect by user.)", iClient); - } - } - } - } - - new Handle:hEvent = CreateEvent("player_disconnect"); - SetEventInt(hEvent, "userid", iUserId); - SetEventString(hEvent, "reason", strReason); - SetEventString(hEvent, "name", strName); - SetEventString(hEvent, "networkid", strNetworkId); - - FireEvent(hEvent, true); - - return Plugin_Handled; - } - } - - return Plugin_Continue; -} \ No newline at end of file diff --git a/Simple Spectate/addons/sourcemod/scripting/simple-plugins.sp b/Simple Spectate/addons/sourcemod/scripting/simple-plugins.sp deleted file mode 100644 index 4462b41..0000000 --- a/Simple Spectate/addons/sourcemod/scripting/simple-plugins.sp +++ /dev/null @@ -1,785 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Plugins -Description: - Core plugin for Simple Plugins project -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#define CORE_PLUGIN_VERSION "1.1.$Rev$" - -#include - -enum e_PlayerInfo -{ - Handle:hForcedTeamPlugin = INVALID_HANDLE, - iForcedTeam = 0, - iBuddy = 0, - bool:bBuddyLocked = false -}; - -new Handle:g_fwdPlayerMoved; -new g_aPlayers[MAXPLAYERS + 1][e_PlayerInfo]; -new bool:g_bTeamsSwitched = false; - -/** -Setting our plugin information. -*/ -public Plugin:myinfo = -{ - name = "Simple Plugins Core Plugin", - author = "Simple Plugins", - description = "Core plugin for Simple Plugins", - version = CORE_PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -public bool:AskPluginLoad(Handle:myself, bool:late, String:error[], err_max) -{ - - /** - Register natives for other plugins - */ - CreateNative("SM_MovePlayer", Native_SM_MovePlayer); - CreateNative("SM_SetForcedTeam", Native_SM_SetForcedTeam); - CreateNative("SM_GetForcedTeam", Native_SM_GetForcedTeam); - CreateNative("SM_ClearForcedTeam", Native_SM_ClearForcedTeam); - CreateNative("SM_GetForcedPlayer", Native_SM_GetForcedPlayer); - CreateNative("SM_AssignBuddy", Native_SM_AssignBuddy); - CreateNative("SM_GetClientBuddy", Native_SM_GetClientBuddy); - CreateNative("SM_LockBuddy", Native_SM_LockBuddy); - CreateNative("SM_IsBuddyLocked", Native_SM_IsBuddyLocked); - CreateNative("SM_ClearBuddy", Native_SM_ClearBuddy); - CreateNative("SM_IsValidAdmin", Native_SM_IsValidAdmin); - CreateNative("SM_IsValidTeam", Native_SM_IsValidTeam); - RegPluginLibrary("simpleplugins"); - return true; -} - -public OnPluginStart() -{ - - CreateConVar("ssm_core_pl_ver", CORE_PLUGIN_VERSION, "Simple SourceMod Plugins Core Plugin Version", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - CreateConVar("ssm_core_inc_ver", CORE_INC_VERSION, "Simple SourceMod Plugins Core Include Version", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook some events to control forced players and check extensions - */ - decl String:sExtError[256]; - LogAction(0, -1, "[SSM] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Pre); - switch (g_CurrentMod) - { - case GameType_CSS: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - new iExtStatus = GetExtensionFileStatus("game.cstrike.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SSM] Required extension was not found."); - LogAction(0, -1, "[SSM] Plugin FAILED TO LOAD."); - SetFailState("Required extension was not found."); - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SSM] Required extension is loaded with errors."); - LogAction(0, -1, "[SSM] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SSM] Plugin FAILED TO LOAD."); - SetFailState("Required extension is loaded with errors."); - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SSM] Required extension is loaded."); - } - } - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_PostNoCopy); - HookUserMessage(GetUserMessageId("TextMsg"), UserMessageHook_Class, true); - new iExtStatus = GetExtensionFileStatus("game.tf2.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SSM] Required extension was not found."); - LogAction(0, -1, "[SSM] Plugin FAILED TO LOAD."); - SetFailState("Required extension was not found."); - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SSM] Required extension is loaded with errors."); - LogAction(0, -1, "[SSM] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SSM] Plugin FAILED TO LOAD."); - SetFailState("Required extension is loaded with errors."); - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SSM] Required extension is loaded."); - } - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_PostNoCopy); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - - /** - Load common translations - */ - LoadTranslations ("common.phrases"); - - /** - Create the global forward - */ - g_fwdPlayerMoved = CreateGlobalForward("SM_OnPlayerMoved", ET_Event, Param_Cell, Param_Cell, Param_Cell); -} - -public OnClientDisconnect(client) -{ - - /** - Cleanup clients/players buddy list - */ - if (!IsFakeClient(client)) - { - SM_ClearBuddy(client, true); - SM_LockBuddy(client, false); - } - SM_ClearForcedTeam(client); -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - See if the teams have been switched - */ - if (g_bTeamsSwitched) - { - - /** - Switch the teams the players are forced to - */ - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][iForcedTeam] != 0) - { - if (g_aPlayers[i][iForcedTeam] == g_aCurrentTeams[Team1]) - { - g_aPlayers[i][iForcedTeam] = g_aCurrentTeams[Team2]; - } - else - { - g_aPlayers[i][iForcedTeam] = g_aCurrentTeams[Team1]; - } - } - } - } -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - g_bTeamsSwitched = false; -} - -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get our event variables - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - new iTeam = GetEventInt(event, "team"); - - /** - See if the player is on the wrong team - */ - if (g_aPlayers[iClient][iForcedTeam] != 0 && g_aPlayers[iClient][iForcedTeam] != iTeam) - { - - /** - Move the player back to the forced team - */ - CreateTimer(1.0, Timer_ForcePlayerMove, iClient, TIMER_FLAG_NO_MAPCHANGE); - - /** - If the event was going to be broadcasted, we refire it so it is not broadcasted and stop this one - */ - if (!dontBroadcast) - { - new Handle:hEvent = CreateEvent("player_team"); - SetEventInt(hEvent, "userid", GetEventInt(event, "userid")); - SetEventInt(hEvent, "team", GetEventInt(event, "team")); - SetEventInt(hEvent, "oldteam", GetEventInt(event, "oldteam")); - SetEventBool(hEvent, "disconnect", GetEventBool(event, "disconnect")); - - if (g_CurrentMod == GameType_DOD || g_CurrentMod == GameType_L4D || g_CurrentMod == GameType_TF) - { - new String:sClientName[MAX_NAME_LENGTH + 1]; - GetClientName(client, sClientName, sizeof(sClientName)); - SetEventBool(hEvent, "autoteam", GetEventBool(event, "autoteam")); - SetEventBool(hEvent, "silent", true); - SetEventString(hEvent, "name", sClientName); - FireEvent(hEvent, true); - } - else - { - FireEvent(hEvent, true); - } - return Plugin_Handled; - } - } - return Plugin_Continue; -} - -public Action:UserMessageHook_Class(UserMsg:msg_id, Handle:bf, const players[], playersNum, bool:reliable, bool:init) -{ - new String:sMessage[120]; - BfReadString(bf, sMessage, sizeof(sMessage), true); - if (StrContains(sMessage, "#TF_TeamsSwitched", false) != -1) - { - g_bTeamsSwitched = true; - } - return Plugin_Continue; -} - -public Native_SM_MovePlayer(Handle:plugin, numParams) -{ - - /** - Get and check the client and team - */ - new iClient = GetNativeCell(1); - new iTeam = GetNativeCell(2); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (iTeam != g_aCurrentTeams[Spectator] && iTeam != g_aCurrentTeams[Team1] && iTeam != g_aCurrentTeams[Team2]) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid team %d", iTeam); - } - - MovePlayer(iClient, iTeam); - if (!IsClientObserver(iClient)) - { - RespawnPlayer(iClient); - } - - new fResult; - - Call_StartForward(g_fwdPlayerMoved); - Call_PushCell(plugin); - Call_PushCell(iClient); - Call_PushCell(iTeam); - Call_Finish(fResult); - - if (fResult != SP_ERROR_NONE) - { - return ThrowNativeError(fResult, "Forward failed"); - } - - return fResult; -} - -public Native_SM_SetForcedTeam(Handle:plugin, numParams) -{ - - /** - Get and check the client and team - */ - new iClient = GetNativeCell(1); - new iTeam = GetNativeCell(2); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (iTeam != g_aCurrentTeams[Spectator] && iTeam != g_aCurrentTeams[Team1] && iTeam != g_aCurrentTeams[Team2] && iTeam != g_aCurrentTeams[Unknown]) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid team %d", iTeam); - } - - new bool:bOverRide = GetNativeCell(3) ? true : false; - - if (!bOverRide && g_aPlayers[iClient][hForcedTeamPlugin] != INVALID_HANDLE && plugin != g_aPlayers[iClient][hForcedTeamPlugin]) - { - return false; - } - - g_aPlayers[iClient][hForcedTeamPlugin] = plugin; - g_aPlayers[iClient][iForcedTeam] = iTeam; - return true; -} - -public Native_SM_GetForcedTeam(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - - /** - Get and set the plugin if they want it - */ - new Handle:hPlugin = GetNativeCell(2); - if (hPlugin != INVALID_HANDLE) - { - SetNativeCellRef(2, g_aPlayers[iClient][hForcedTeamPlugin]); - } - - /** - Return the forced team, this could be 0 - */ - return g_aPlayers[iClient][iForcedTeam]; -} - -public Native_SM_ClearForcedTeam(Handle:plugin, numParams) -{ - - /** - Get and check the client and team - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - - g_aPlayers[iClient][hForcedTeamPlugin] = INVALID_HANDLE; - g_aPlayers[iClient][iForcedTeam] = 0; - - return true; -} - -public Native_SM_GetForcedPlayer(Handle:plugin, numParams) -{ - - /** - Get and check the team - */ - new iTeam = GetNativeCell(1); - if (iTeam != g_aCurrentTeams[Spectator] && iTeam != g_aCurrentTeams[Team1] && iTeam != g_aCurrentTeams[Team2]) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid team %d", iTeam); - } - - /** - Start a loop to check for a player on the wrong team - Also make sure the plugin that set the forced team is the plugin that asked - */ - new iPlayer = 0; - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientInGame(i) - && GetClientTeam(i) != g_aPlayers[i][iForcedTeam] - && g_aPlayers[i][iForcedTeam] == iTeam - && g_aPlayers[i][hForcedTeamPlugin] == plugin) - { - iPlayer = i; - break; - } - } - - /** - Return the player we found, this could be 0 - */ - return iPlayer; -} - -public Native_SM_AssignBuddy(Handle:plugin, numParams) -{ - - /** - Get and check the client and player - */ - new iClient = GetNativeCell(1); - new iPlayer = GetNativeCell(2); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (iPlayer < 0 || iPlayer > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid player index (%d)", iPlayer); - } - if (!IsClientConnected(iPlayer)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Player %d is not connected", iPlayer); - } - if (!IsClientInGame(iPlayer)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Player %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Bots are not supported"); - } - - /** - See if we can override his setting - */ - new bool:bOverRide = GetNativeCell(3) ? true : false; - if (!bOverRide) - { - - /** - We can't override, so check if they are locked - */ - if (g_aPlayers[iClient][bBuddyLocked] || g_aPlayers[iPlayer][bBuddyLocked]) - { - - /** - We detected at least 1 lock, so we bug out - */ - return false; - } - } - - /** - Ready to set the buddies - */ - g_aPlayers[iClient][iBuddy] = iPlayer; - g_aPlayers[iPlayer][iBuddy] = iClient; - return true; -} - -public Native_SM_GetClientBuddy(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Bots are not supported"); - } - - /** - Return the players buddy, this could be 0 - */ - return g_aPlayers[iClient][iBuddy]; -} - -public Native_SM_LockBuddy(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - new bool:bSetting = GetNativeCell(2) ? true : false; - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Bots are not supported"); - } - - g_aPlayers[iClient][bBuddyLocked] = bSetting; - return true; -} - -public Native_SM_IsBuddyLocked(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Bots are not supported"); - } - - return g_aPlayers[iClient][bBuddyLocked]; -} - -public Native_SM_ClearBuddy(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Client (%d) is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Bots are not supported"); - } - - /** - Get the clients buddy and see if we can override his setting - */ - new bool:bOverRide = GetNativeCell(2) ? true : false; - new iPlayer = g_aPlayers[iClient][iBuddy]; - - /** - There is no buddy, we don't care about anything else so bug out - */ - if (iPlayer == 0) - { - return true; - } - - /** - We determined he had a buddy, check the override setting - */ - if (!bOverRide) - { - - /** - We can't override, so check if they are locked - */ - if (g_aPlayers[iClient][bBuddyLocked] || g_aPlayers[iPlayer][bBuddyLocked]) - { - - /** - We detected at least 1 lock, so we bug out - */ - return false; - } - } - - /** - Ready to clear the buddies - */ - g_aPlayers[iClient][iBuddy] = 0; - g_aPlayers[iPlayer][iBuddy] = 0; - return true; -} - -public Native_SM_IsValidTeam(Handle:plugin, numParams) -{ - - /** - Get the team - */ - new iTeam = GetNativeCell(1); - - /** - Check the team - */ - if (iTeam == g_aCurrentTeams[Spectator] || iTeam == g_aCurrentTeams[Team1] || iTeam == g_aCurrentTeams[Team2]) - { - return true; - } - return false; -} - -public Native_SM_IsValidAdmin(Handle:plugin, numParams) -{ - /** - Get the client and flags - */ - new iClient = GetNativeCell(1); - decl String:sFlags[15]; - GetNativeString(2, sFlags, sizeof(sFlags)); - new ibFlags = ReadFlagString(sFlags); - - /** - Check the flags - */ - if ((GetUserFlagBits(iClient) & ibFlags) == ibFlags) - { - return true; - } - if (GetUserFlagBits(iClient) & ADMFLAG_ROOT) - { - return true; - } - return false; -} - -public Action:Timer_ForcePlayerMove(Handle:timer, any:iClient) -{ - - MovePlayer(iClient, g_aPlayers[iClient][iForcedTeam]); - - if (g_aPlayers[iClient][iForcedTeam] != g_aCurrentTeams[Spectator]) - { - RespawnPlayer(iClient); - } - - PrintToChat(iClient, "\x01\x04----------------------------------"); - PrintToChat(iClient, "\x01\x04You have been forced to this team."); - PrintToChat(iClient, "\x01\x04----------------------------------"); - - return Plugin_Handled; -} - -stock MovePlayer(iClient, iTeam) -{ - - /** - Change the client's team based on the mod - */ - switch (g_CurrentMod) - { - case GameType_CSS: - { - CS_SwitchTeam(iClient, iTeam); - } - default: - { - ChangeClientTeam(iClient, iTeam); - } - } -} - -stock RespawnPlayer(iClient) -{ - - /** - Respawn the client based on the mod - */ - switch (g_CurrentMod) - { - case GameType_CSS: - { - CS_RespawnPlayer(iClient); - } - case GameType_TF: - { - TF2_RespawnPlayer(iClient); - } - case GameType_INS: - { - FakeClientCommand(iClient, "kill"); - } - default: - { - // - } - } -} diff --git a/Simple Spectate/addons/sourcemod/scripting/simple-roundimmunity.sp b/Simple Spectate/addons/sourcemod/scripting/simple-roundimmunity.sp deleted file mode 100644 index 5f0bca3..0000000 --- a/Simple Spectate/addons/sourcemod/scripting/simple-roundimmunity.sp +++ /dev/null @@ -1,947 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Round Immunity -Description: - Gives admins immunity during certain rounds -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or any later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#pragma semicolon 1 -#include -#include -#undef REQUIRE_EXTENSIONS -#undef AUTOLOAD_EXTENSIONS -#include -#include -#define REQUIRE_EXTENSIONS -#define AUTOLOAD_EXTENSIONS - -#define PLUGIN_VERSION "1.1.$Rev$" -#define SPECTATOR 1 -#define TEAM_RED 2 -#define TEAM_BLUE 3 - -#define COLOR_GREEN 0 -#define COLOR_BLACK 1 -#define COLOR_RED 2 -#define COLOR_BLUE 3 -#define COLOR_TEAM 4 -#define COLOR_RAINBOW 5 -#define COLOR_NONE 6 - -#define PLAYERCOND_SLOWED (1<<0) //1 -#define PLAYERCOND_ZOOMED (1<<1) //2 -#define PLAYERCOND_DISGUISING (1<<2) //4 -#define PLAYERCOND_DISGUISED (1<<3) //8 -#define PLAYERCOND_SPYCLOAK (1<<4) //16 -#define PLAYERCOND_UBERED (1<<5) //32 -#define PLAYERCOND_TELEPORTTRAIL (1<<6) //64 -#define PLAYERCOND_TAUNT (1<<7) //128 -// (1<<8) //256 -// (1<<9) //512 -#define PLAYERCOND_TELEPORTFLASH (1<<10) //1024 -#define PLAYERCOND_KRUBER (1<<11) //2048 -// (1<<12) //4096 -// (1<<13) //8192 -#define PLAYERCOND_BONKED (1<<14) //16384 (blame Neph if it doesn't work) -#define PLAYERCOND_BONKEDORDRINKSLOWDOWN (1<<15) //32768 -#define PLAYERCOND_HEALING (1<<16) //65536 -#define PLAYERCOND_BURNING (1<<17) //131072 -#define PLAYERCOND_FULLYCHARGEDBYMEDIC (1<<18) //262144 - -enum e_Cookies -{ - bEnabled, - iColor, - iMode -}; - -enum e_ColorNames -{ - Green, - Black, - Red, - Blue -}; - -enum e_ColorValues -{ - iRed, - iGreen, - iBlue -}; - -enum e_PlayerData -{ - Handle:hGodModeTimer, - Handle:hColorTimer, - bool:bIsAdmin, - bool:bIsImmune, - iCycleColor -}; - -/** - Global convar handles - */ -new Handle:sri_charadminflag = INVALID_HANDLE; -new Handle:sri_enabled = INVALID_HANDLE; -new Handle:sri_cookie_enabled = INVALID_HANDLE; -new Handle:sri_cookie_color = INVALID_HANDLE; -new Handle:sri_cookie_mode = INVALID_HANDLE; - -/** - Player arrays - */ -new g_aPlayers[MAXPLAYERS + 1][e_PlayerData]; -new g_aClientCookies[MAXPLAYERS + 1][e_Cookies]; - -/** - Global bools - */ -new bool:g_bLoadedLate = false; -new bool:g_bIsEnabled = true; -new bool:g_bRoundEnd = false; -new bool:g_bUseDukehacks = false; -new bool:g_bUseClientprefs = false; - -/** - Global strings/integers/floats - */ -new String:g_sCharAdminFlag[32]; -new g_iColors[e_ColorNames][e_ColorValues]; -new g_iClassMaxHealth[TFClassType] = {0, 125, 125, 200, 175, 150, 300, 175, 125, 125}; - -public Plugin:myinfo = -{ - name = "Simple Round Immunity", - author = "Simple Plugins", - description = "Gives admins immunity during certain rounds", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -} - -bool:AskPluginLoad(Handle:myself, bool:late, String:error[], err_max) -{ - g_bLoadedLate = late; - return true; -} - -public OnPluginStart() -{ - - /** - Create console variables - */ - CreateConVar("sri_version", PLUGIN_VERSION, "Simple Round Immunity", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - sri_enabled = CreateConVar("sri_enabled", "1", "Enable/Disable Admin immunity during certain round."); - sri_charadminflag = CreateConVar("sri_charadminflag", "a", "Admin flag to use for immunity (only one). Must be a in char format."); - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook some events and check extensions - */ - decl String:sExtError[256]; - LogAction(0, -1, "[SRI] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_spawn", HookPlayerSpawn, EventHookMode_Post); - HookEvent("player_hurt", HookPlayerHurt, EventHookMode_Pre); - switch (g_CurrentMod) - { - case GameType_CSS: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - new iExtStatus = GetExtensionFileStatus("game.cstrike.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SRI] Required extension was not found."); - LogAction(0, -1, "[SRI] Plugin FAILED TO LOAD."); - SetFailState("Required extension was not found."); - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SRI] Required extension is loaded with errors."); - LogAction(0, -1, "[SRI] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SRI] Plugin FAILED TO LOAD."); - SetFailState("Required extension is loaded with errors."); - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SRI] Required css extension is loaded."); - } - } - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_PostNoCopy); - HookUserMessage(GetUserMessageId("TextMsg"), UserMessageHook_Class, true); - new iExtStatus = GetExtensionFileStatus("game.tf2.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SRI] Required extension was not found."); - LogAction(0, -1, "[SRI] Plugin FAILED TO LOAD."); - SetFailState("Required extension was not found."); - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SRI] Required extension is loaded with errors."); - LogAction(0, -1, "[SRI] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SRI] Plugin FAILED TO LOAD."); - SetFailState("Required extension is loaded with errors."); - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SRI] Required tf2 extension is loaded."); - } - iExtStatus = GetExtensionFileStatus("dukehacks.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SRI] Dukehacks extension was not found."); - LogAction(0, -1, "[SRI] Plugin continued to load, but that feature will not be used."); - g_bUseDukehacks = false; - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SRI] Dukehacks extension is loaded with errors."); - LogAction(0, -1, "[SRI] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SRI] Plugin continued to load, but that feature will not be used."); - g_bUseDukehacks = false; - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SRI] Dukehacks extension is loaded and will be used."); - g_bUseDukehacks = true; - dhAddClientHook(CHK_TakeDamage, Hacks_TakeDamageHook); - } - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_PostNoCopy); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - /** - Now lets check for client prefs extension - */ - new iExtStatus = GetExtensionFileStatus("clientprefs.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SRI] Client Preferences extension was not found."); - LogAction(0, -1, "[SRI] Plugin continued to load, but that feature will not be used."); - g_bUseClientprefs = false; - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SRI] Client Preferences extension is loaded with errors."); - LogAction(0, -1, "[SRI] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SRI] Plugin continued to load, but that feature will not be used."); - g_bUseClientprefs = false; - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SRI] Client Preferences extension is loaded, checking database."); - if (!SQL_CheckConfig(clientprefs)) - { - LogAction(0, -1, "[SRI] No 'clientprefs' database found. Check your database.cfg file."); - LogAction(0, -1, "[SRI] Plugin continued to load, but Client Preferences will not be used."); - g_bUseClientprefs = false; - } - g_bUseClientprefs = true; - - /** - Deal with client cookies - */ - sri_cookie_enabled = RegClientCookie("bri_client_enabled", "Enable/Disable your immunity during the bonus round.", CookieAccess_Public); - sri_cookie_color = RegClientCookie("bri_client_color", "Color to render when immune.", CookieAccess_Public); - sri_cookie_mode = RegClientCookie("bri_client_mode", "God mode to select", CookieAccess_Public); - SetCookieMenuItem(CookieMenu_TopMenu, sri_cookie_enabled, "Bonus Round Immunity"); - } - - HookConVarChange(sri_enabled, EnabledChanged); - - RegAdminCmd("sm_immunity", Command_Immunity, ADMFLAG_ROOT, "sm_immunity: Gives you immunity"); - - LoadColors(); - - AutoExecConfig(true, "plugin.simpleroundimmunity"); -} - -public OnAllPluginsLoaded() -{ - //something - // need to deal with the unloading of dukehacks, clientprefs, and simpleplugins - // should move hooking the client prefs cookies to a function to make sure they are done post plugin start if ext is loaded late -} - -public OnLibraryRemoved(const String:name[]) -{ - //something - // need to deal with the loading of dukehacks, clientprefs, and simpleplugins -} - -public OnConfigsExecuted() -{ - GetConVarString(sri_charadminflag, g_sCharAdminFlag, sizeof(g_sCharAdminFlag)); - g_bIsEnabled = GetConVarBool(sri_enabled); - g_bRoundEnd = false; -} - -/** - Client events - */ - -public OnClientPostAdminCheck(client) -{ - if (SM_IsValidAdmin(client, g_sCharAdminFlag)) - g_aPlayers[client][bIsAdmin] = true; - else - g_aPlayers[client][bIsAdmin] = false; -} - -public OnClientCookiesCached(client) -{ - decl String:sEnabled[2], String:sColor[4], String:sMode[2]; - GetClientCookie(client, sri_cookie_enabled, sEnabled, sizeof(sEnabled)); - GetClientCookie(client, sri_cookie_color, sColor, sizeof(sColor)); - GetClientCookie(client, sri_cookie_mode, sMode, sizeof(sMode)); - g_aClientCookies[client][bEnabled] = StringToInt(sEnabled); - g_aClientCookies[client][iColor] = StringToInt(sColor); - g_aClientCookies[client][iMode] = StringToInt(sMode); -} - -public OnClientDisconnect(client) -{ - CleanUp(client); -} - -/** - Commands - */ - -public Action:Command_Immunity(client, args) -{ - if (g_aPlayers[client][IsImmune]) - { - DisableImmunity(client); - } - else - { - EnableImmunity(client); - } - return Plugin_Handled; -} - -/** - Event hooks - */ - -public Action:Hacks_TakeDamageHook(client, attacker, inflictor, Float:damage, &Float:multiplier, damagetype) -{ - if (attacker == 0 || attacker >= MaxClients) - { - return Plugin_Continue; - } - if (g_aPlayers[client][IsImmune]) - { - new TFClassType:PlayerClass = TF2_GetPlayerClass(attacker); - if (PlayerClass == TFClass_Spy) - { - multiplier *= 0.0; - return Plugin_Changed; - } - } - return Plugin_Continue; -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - g_bRoundEnd = false; - if (g_bIsEnabled) - { - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][IsImmune]) - { - DisableImmunity(i); - } - } - } -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - g_bRoundEnd = true; - if (g_bIsEnabled) - { - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][bIsAdmin]) - { - EnableImmunity(i); - } - } - } -} - -public HookPlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) -{ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - if (g_bIsEnabled && g_aPlayers[iClient][bIsAdmin] && g_bRoundEnd) - { - EnableImmunity(iClient); - } -} - -public Action:HookPlayerHurt(Handle:event, const String:name[], bool:dontBroadcast) -{ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - if (g_aPlayers[iClient][IsImmune]) - { - SetEntityHealth(iClient, 2000); - return Plugin_Continue; - } - return Plugin_Continue; -} - -/** - Cookie menus - */ - -public CookieMenu_TopMenu(client, CookieMenuAction:action, any:info, String:buffer[], maxlen) -{ - if (action == CookieMenuAction_DisplayOption) - { - //don't think we need to do anything - } - else - { - new Handle:hMenu = CreateMenu(Menu_CookieSettings); - SetMenuTitle(hMenu, "Options (Current Setting)"); - if (g_aClientCookies[client][bEnabled]) - { - AddMenuItem(hMenu, "enable", "Enabled/Disable (Enabled)"); - } - else - { - AddMenuItem(hMenu, "enable", "Enabled/Disable (Disabled)"); - } - if (g_aClientCookies[client][iMode]) - { - AddMenuItem(hMenu, "mode", "Immunity Mode Setting (God Mode)"); - } - else - { - AddMenuItem(hMenu, "mode", "Immunity Mode Setting (Health)"); - } - switch (g_aClientCookies[client][iColor]) - { - case COLOR_GREEN: - { - AddMenuItem(hMenu, "color", "Color (Green)"); - } - case COLOR_BLACK: - { - AddMenuItem(hMenu, "color", "Color (Black)"); - } - case COLOR_RED: - { - AddMenuItem(hMenu, "color", "Color (Red)"); - } - case COLOR_BLUE: - { - AddMenuItem(hMenu, "color", "Color (Blue)"); - } - case COLOR_TEAM: - { - AddMenuItem(hMenu, "color", "Color (Team)"); - } - case COLOR_RAINBOW: - { - AddMenuItem(hMenu, "color", "Color (Rainbow)"); - } - case COLOR_NONE: - { - AddMenuItem(hMenu, "color", "Color (None)"); - } - } - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, client, MENU_TIME_FOREVER); - } -} - -public Menu_CookieSettings(Handle:menu, MenuAction:action, param1, param2) -{ - new client = param1; - if (action == MenuAction_Select) - { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "enable", false)) - { - new Handle:hMenu = CreateMenu(Menu_CookieSettingsEnable); - SetMenuTitle(hMenu, "Enable/Disable Round End Immunity"); - - if (g_aClientCookies[client][bEnabled]) - { - AddMenuItem(hMenu, "enable", "Enable (Set)"); - AddMenuItem(hMenu, "disable", "Disable"); - } - else - { - AddMenuItem(hMenu, "enable", "Enabled"); - AddMenuItem(hMenu, "disable", "Disable (Set)"); - } - - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, client, MENU_TIME_FOREVER); - } - else if (StrEqual(sSelection, "mode", false)) - { - new Handle:hMenu = CreateMenu(Menu_CookieSettingsMode); - SetMenuTitle(hMenu, "Set Immunity Mode"); - - if (g_aClientCookies[client][iMode]) - { - AddMenuItem(hMenu, "god", "God Mode (Set)"); - AddMenuItem(hMenu, "health", "Health"); - } - else - { - AddMenuItem(hMenu, "god", "God Mode"); - AddMenuItem(hMenu, "health", "Health (Set)"); - } - - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, client, MENU_TIME_FOREVER); - } - else - { - new Handle:hMenu = CreateMenu(Menu_CookieSettingsColors); - SetMenuTitle(hMenu, "Select Immunity Color"); - switch (g_aClientCookies[client][iColor]) - { - case COLOR_GREEN: - { - AddMenuItem(hMenu, "Green", "Green (Set)"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_BLACK: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black (Set)"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_RED: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red (Set)"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_BLUE: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue (Set)"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_TEAM: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color (Set)"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_RAINBOW: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow (Set)"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_NONE: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None (Set)"); - } - } - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, client, MENU_TIME_FOREVER); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - ShowCookieMenu(client); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -public Menu_CookieSettingsEnable(Handle:menu, MenuAction:action, param1, param2) -{ - new client = param1; - if (action == MenuAction_Select) - { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "enable", false)) - { - SetClientCookie(client, sri_cookie_enabled, "1"); - g_aClientCookies[client][bEnabled] = 1; - PrintToChat(client, "[SM] Bonus Round Immunity is ENABLED"); - } - else - { - SetClientCookie(client, sri_cookie_enabled, "0"); - g_aClientCookies[client][bEnabled] = 0; - PrintToChat(client, "[SM] Bonus Round Immunity is DISABLED"); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - ShowCookieMenu(client); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -public Menu_CookieSettingsColors(Handle:menu, MenuAction:action, param1, param2) -{ - new client = param1; - if (action == MenuAction_Select) - { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "Green", false)) - { - SetClientCookie(client, sri_cookie_color, "0"); - g_aClientCookies[client][iColor] = COLOR_GREEN; - PrintToChat(client, "[SM] Bonus Round Immunity color set to GREEN"); - } - else if (StrEqual(sSelection, "Black", false)) - { - SetClientCookie(client, sri_cookie_color, "1"); - g_aClientCookies[client][iColor] = COLOR_BLACK; - PrintToChat(client, "[SM] Bonus Round Immunity color set to BLACK"); - } - else if (StrEqual(sSelection, "Red", false)) - { - SetClientCookie(client, sri_cookie_color, "2"); - g_aClientCookies[client][iColor] = COLOR_RED; - PrintToChat(client, "[SM] Bonus Round Immunity color set to RED"); - } - else if (StrEqual(sSelection, "Blue", false)) - { - SetClientCookie(client, sri_cookie_color, "3"); - g_aClientCookies[client][iColor] = COLOR_BLUE; - PrintToChat(client, "[SM] Bonus Round Immunity color set to BLUE"); - } - else if (StrEqual(sSelection, "Team", false)) - { - SetClientCookie(client, sri_cookie_color, "4"); - g_aClientCookies[client][iColor] = COLOR_TEAM; - PrintToChat(client, "[SM] Bonus Round Immunity color set to TEAM COLOR"); - } - else if (StrEqual(sSelection, "Rain", false)) - { - SetClientCookie(client, sri_cookie_color, "5"); - g_aClientCookies[client][iColor] = COLOR_RAINBOW; - PrintToChat(client, "[SM] Bonus Round Immunity color set to RAINBOW"); - } - else if (StrEqual(sSelection, "None", false)) - { - SetClientCookie(client, sri_cookie_color, "6"); - g_aClientCookies[client][iColor] = COLOR_NONE; - PrintToChat(client, "[SM] Bonus Round Immunity color set to NONE"); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - ShowCookieMenu(client); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -public Menu_CookieSettingsMode(Handle:menu, MenuAction:action, param1, param2) -{ - new client = param1; - if (action == MenuAction_Select) - { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "god", false)) - { - SetClientCookie(client, sri_cookie_mode, "1"); - g_aClientCookies[client][iMode] = 1; - PrintToChat(client, "[SM] Bonus Round Immunity set to GOD MODE"); - } - else - { - SetClientCookie(client, sri_cookie_mode, "0"); - g_aClientCookies[client][iMode] = 0; - PrintToChat(client, "[SM] Bonus Round Immunity set to HEALTH BONUS"); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - ShowCookieMenu(client); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -/** -Timer functions - */ - -public Action:Timer_ChangeColor(Handle:timer, any:client) -{ - if (g_aPlayers[client][CycleColor]++ == 3) - { - g_aPlayers[client][CycleColor] = 0; - } - SetEntityRenderMode(client, RENDER_TRANSCOLOR); - SetEntityRenderColor(client, g_iColors[g_aPlayers[client][CycleColor]][iRed], g_iColors[g_aPlayers[client][CycleColor]][iGreen], g_iColors[g_aPlayers[client][CycleColor]][iBlue], 255); - return Plugin_Continue; -} - -public Action:Timer_UndoGodMode(Handle:timer, any:client) -{ - if (IsClientInGame(client)) - { - SetEntProp(client, Prop_Data, "m_takedamage", 2, 1); - } - g_aPlayers[iClient][hGodModeTimer] = INVALID_HANDLE; - return Plugin_Handled; -} - -/** -Stock functions . - */ - -stock CleanUp(iClient) -{ - g_aPlayers[iClient][bIsAdmin] = false; - DisableImmunity(iClient); -} - -stock EnableImmunity(iClient) -{ - SetEntityRenderMode(iClient, RENDER_TRANSCOLOR); - switch (g_aClientCookies[iClient][iColor]) - { - case COLOR_TEAM: - { - new iTeam = GetClientTeam(iClient); - SetEntityRenderColor(iClient, g_iColors[e_ColorNames:iTeam][iRed], g_iColors[e_ColorNames:iTeam][iGreen], g_iColors[e_ColorNames:iTeam][iBlue], 255); - } - case COLOR_RAINBOW: - { - if (g_aPlayers[iClient][hColorTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hColorTimer]); - g_aPlayers[iClient][hColorTimer] = INVALID_HANDLE; - } - g_aPlayers[iClient][hColorTimer] = CreateTimer(0.2, Timer_ChangeColor, iClient, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); - } - case COLOR_NONE: - { - //We dont have to set a color - } - default: - { - SetEntityRenderColor(iClient, g_iColors[e_ColorNames:g_aClientCookies[iClient][iColor]][iRed], g_iColors[e_ColorNames:g_aClientCookies[iClient][iColor]][iGreen], g_iColors[e_ColorNames:g_aClientCookies[iClient][iColor]][iBlue], 255); - } - } - SetEntityHealth(iClient, 2000); - SetEntProp(iClient, Prop_Data, "m_takedamage", 0, 1); - g_aPlayers[iClient][hGodModeTimer] = CreateTimer(2.0, Timer_UndoGodMode, iClient); - g_aPlayers[iClient][IsImmune] = true; -} - -stock DisableImmunity(iClient) -{ - if (g_aPlayers[iClient][hGodModeTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hGodModeTimer]); - g_aPlayers[iClient][hGodModeTimer] = INVALID_HANDLE; - } - if (g_aPlayers[iClient][hColorTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hColorTimer]); - g_aPlayers[iClient][hColorTimer] = INVALID_HANDLE; - } - if (IsClientInGame(iClient)) - { - SetEntityRenderMode(iClient, RENDER_TRANSCOLOR); - SetEntityRenderColor(iClient, 255, 255, 255, 255); - new TFClassType:PlayerClass = TF2_GetPlayerClass(iClient); - new iMaxHealth = g_iClassMaxHealth[PlayerClass]; - SetEntityHealth(iClient, iMaxHealth); - } - g_aPlayers[iClient][CycleColor] = 0; - g_aPlayers[iClient][IsImmune] = false; -} - -stock LoadColors() -{ - g_iColors[Green][iRed] = 0; - g_iColors[Green][iGreen] = 255; - g_iColors[Green][iBlue] = 0; - - g_iColors[Black][iRed] = 10; - g_iColors[Black][iGreen] = 10; - g_iColors[Black][iBlue] = 0; - - g_iColors[Red][iRed] = 255; - g_iColors[Red][iGreen] = 0; - g_iColors[Red][iBlue] = 0; - - g_iColors[Blue][iRed] = 0; - g_iColors[Blue][iGreen] = 0; - g_iColors[Blue][iBlue] = 255; -} - -stock TF2_AddCond(client, cond) -{ - new Handle:cvar = FindConVar("sv_cheats"), bool:enabled = GetConVarBool(cvar), flags = GetConVarFlags(cvar); - if(!enabled) - { - SetConVarFlags(cvar, flags^FCVAR_NOTIFY); - SetConVarBool(cvar, true); - } - FakeClientCommand(client, "addcond %i", cond); - if(!enabled) - { - SetConVarBool(cvar, false); - SetConVarFlags(cvar, flags); - } -} - -stock TF2_RemoveCond(client, cond) -{ - new Handle:cvar = FindConVar("sv_cheats"), bool:enabled = GetConVarBool(cvar), flags = GetConVarFlags(cvar); - if(!enabled) - { - SetConVarFlags(cvar, flags^FCVAR_NOTIFY); - SetConVarBool(cvar, true); - } - FakeClientCommand(client, "removecond %i", cond); - if(!enabled) - { - SetConVarBool(cvar, false); - SetConVarFlags(cvar, flags); - } -} - -/** -Enabled hook - */ - -public EnabledChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (StringToInt(newValue) == 0) - { - UnhookEvent("player_spawn", HookPlayerSpawn, EventHookMode_Post); - UnhookEvent("teamplay_round_start", HookRoundStart, EventHookMode_Post); - UnhookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][bIsAdmin] && g_aPlayers[i][IsImmune]) - { - DisableImmunity(i); - } - } - g_bIsEnabled = false; - } - else - { - HookEvent("player_spawn", HookPlayerSpawn, EventHookMode_Post); - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_Post); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - g_bIsEnabled = true; - } -} diff --git a/Simple Spectate/addons/sourcemod/scripting/simple-spectate.sp b/Simple Spectate/addons/sourcemod/scripting/simple-spectate.sp index 4108f8f..4513b6a 100644 --- a/Simple Spectate/addons/sourcemod/scripting/simple-spectate.sp +++ b/Simple Spectate/addons/sourcemod/scripting/simple-spectate.sp @@ -524,7 +524,7 @@ public Action:HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontB if (g_CurrentMod == GameType_DOD || g_CurrentMod == GameType_L4D || g_CurrentMod == GameType_TF) { new String:sClientName[MAX_NAME_LENGTH + 1]; - GetClientName(client, sClientName, sizeof(sClientName)); + GetClientName(iClient, sClientName, sizeof(sClientName)); SetEventBool(hEvent, "autoteam", GetEventBool(event, "autoteam")); SetEventBool(hEvent, "silent", true); SetEventString(hEvent, "name", sClientName); diff --git a/Simple Spectate/addons/sourcemod/scripting/simple-teambalancer.sp b/Simple Spectate/addons/sourcemod/scripting/simple-teambalancer.sp deleted file mode 100644 index 3302255..0000000 --- a/Simple Spectate/addons/sourcemod/scripting/simple-teambalancer.sp +++ /dev/null @@ -1,1797 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Team Balancer -Description: - Balances teams based upon player count - Player will not be balanced more than once in 5 (default) mins - Buddy system tries to keep buddies together - Ability to prioritize players - Ability to force players to accept the new team - Admins are immune -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include -#include - -#define PLUGIN_VERSION "2.1.$Rev$" - -enum PlayerData -{ - Handle:hBalanceTimer, - Handle:hForcedTimer, - bool:bSwitched, - bool:bFlagCarrier -}; - -/** - Global convar handles - */ -new Handle:stb_enabled = INVALID_HANDLE; -new Handle:stb_buddyenabled = INVALID_HANDLE; -new Handle:stb_logactivity = INVALID_HANDLE; -new Handle:stb_logactivity2 = INVALID_HANDLE; -new Handle:stb_unbalancelimit = INVALID_HANDLE; -new Handle:stb_deadonly = INVALID_HANDLE; -new Handle:stb_priorityenabled = INVALID_HANDLE; -new Handle:stb_uberlevel = INVALID_HANDLE; -new Handle:stb_balancedelay = INVALID_HANDLE; -new Handle:stb_livingplayerswitchdelay = INVALID_HANDLE; -new Handle:stb_livingplayercheckdelay = INVALID_HANDLE; -new Handle:stb_roundstartdelay = INVALID_HANDLE; -new Handle:stb_switchbackforced = INVALID_HANDLE; -new Handle:stb_adminflag = INVALID_HANDLE; -new Handle:stb_buddyrestriction = INVALID_HANDLE; -new Handle:stb_convarcontrol = INVALID_HANDLE; - -/** - Built-in cvars handles - */ -new Handle:stb_mp_autoteambalance = INVALID_HANDLE; -new Handle:stb_mp_teams_unbalance_limit = INVALID_HANDLE; -new Handle:TFGameModeArena = INVALID_HANDLE; - -/** - Timer handles - */ -new Handle:g_hBalanceTimer = INVALID_HANDLE; -new Handle:g_hLivingPlayerCheckTimer = INVALID_HANDLE; - -/** - Player arrays - */ -new g_aPlayers[MAXPLAYERS + 1][PlayerData]; - -/** -Global bools -*/ -new bool:g_bIsEnabled = true; -new bool:g_bPriorityPlayers = true; -new bool:g_bBuddyRestriction = false; -new bool:g_bLogActivity = false; -new bool:g_bLogActivity2 = false; -new bool:g_bDeadOnly = false; -new bool:g_bConVarControl = true; -new bool:g_bBuddyEnabled = true; -new bool:g_bBalanceInProgress = false; -new bool:g_bRoundStart = false; -new bool:g_bRoundEnd = false; -new bool:g_bSuddenDeath = false; -new bool:g_bIsArenaMode = false; - -/** - Global strings/integers/floats - */ -new g_iUnbalanceLimit, g_iLivingPlayerSwitchDelay, g_iLivingPlayerCheckDelay; -new g_iRoundStartDelay, g_iSwitchBackForced, g_iBalanceDelay; -new Float:g_fUberLevel; -new g_iOwnerOffset; -new String:g_sAdminFlag[5]; - -public Plugin:myinfo = -{ - name = "Simple Team Balancer", - author = "Simple Plugins", - description = "Balances teams based upon player count.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -} - -public OnPluginStart() -{ - - /** - Create console variables - */ - CreateConVar("stb_version", PLUGIN_VERSION, "Simple Team Balancer", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - stb_enabled = CreateConVar("stb_enabled", "1", "Enable or Disable Simple Team Balancer", _, true, 0.0, true, 1.0); - stb_priorityenabled = CreateConVar("stb_priorityenabled", "1", "Enable or Disable the prioritization of living players", _, true, 0.0, true, 1.0); - stb_buddyrestriction = CreateConVar("stb_buddyrestriction", "0", "Enable or Disable Admin Only buddy lists", _, true, 0.0, true, 1.0); - stb_logactivity = CreateConVar("stb_logactivity", "0", "Enable or Disable the disaplying of events in the log", _, true, 0.0, true, 1.0); - stb_logactivity2 = CreateConVar("stb_logactivity2", "0", "Enable or Disable the disaplying of detailed events in the log (WILL SPAM LOG)", _, true, 0.0, true, 1.0); - stb_deadonly = CreateConVar("stb_deadonly", "0", "Enable or Disable the switching of only dead players", _, true, 0.0, true, 1.0); - stb_convarcontrol = CreateConVar("stb_convarcontrol", "1", "Enable or Disable the control of builtin console variables", _, true, 0.0, true, 1.0); - stb_buddyenabled = CreateConVar("stb_buddyenabled", "1", "Enable or Disable the buddy system", _, true, 0.0, true, 1.0); - stb_unbalancelimit = CreateConVar("stb_unbalancelimit", "2", "Amount of players teams are ALLOWED to be unbalanced by", _, true, 1.0, true, 32.0); - stb_balancedelay = CreateConVar("stb_balancedelay", "10", "Delay in seconds to start an autobalance"); - stb_livingplayerswitchdelay = CreateConVar("stb_livingplayerswitchdelay", "20", "Delay in seconds to switch living players once selected"); - stb_livingplayercheckdelay = CreateConVar("stb_livingplayercheckdelay", "10", "Delay in seconds to start checking living players once teams become unbalanced"); - stb_roundstartdelay = CreateConVar("stb_roundstartdelay", "15", "Delay in seconds to start balancing teams after the start of a round"); - stb_switchbackforced = CreateConVar("stb_switchbackforced", "300", "Amount of time in seconds to not switch a player twice and force the team if enabled"); - stb_uberlevel = CreateConVar("stb_uberlevel", "1.0", "Min uber level medic must have to have priority over other living players. Setting to 0 will rarely switch a living medic", _, true, 0.0, true, 1.0); - stb_adminflag = CreateConVar("stb_adminflag", "a", "Admin flag to use for immunity. Must be a in char format."); - stb_mp_autoteambalance = FindConVar("mp_autoteambalance"); - stb_mp_teams_unbalance_limit = FindConVar("mp_teams_unbalance_limit"); - - /** - Removing the notify tags from the built in cvars. We dont want spam. - */ - if (stb_mp_autoteambalance != INVALID_HANDLE) - { - SetConVarFlags(stb_mp_autoteambalance, GetConVarFlags(stb_mp_autoteambalance)^FCVAR_NOTIFY); - } - if (stb_mp_teams_unbalance_limit != INVALID_HANDLE) - { - SetConVarFlags(stb_mp_teams_unbalance_limit, GetConVarFlags(stb_mp_teams_unbalance_limit)^FCVAR_NOTIFY); - } - - /** - Hook console variables - */ - HookConVarChange(stb_enabled, ConVarSettingsChanged); - HookConVarChange(stb_priorityenabled, ConVarSettingsChanged); - HookConVarChange(stb_buddyrestriction, ConVarSettingsChanged); - HookConVarChange(stb_logactivity, ConVarSettingsChanged); - HookConVarChange(stb_logactivity2, ConVarSettingsChanged); - HookConVarChange(stb_deadonly, ConVarSettingsChanged); - HookConVarChange(stb_convarcontrol, ConVarSettingsChanged); - HookConVarChange(stb_buddyenabled, ConVarSettingsChanged); - HookConVarChange(stb_unbalancelimit, ConVarSettingsChanged); - HookConVarChange(stb_balancedelay, ConVarSettingsChanged); - HookConVarChange(stb_livingplayerswitchdelay, ConVarSettingsChanged); - HookConVarChange(stb_livingplayercheckdelay, ConVarSettingsChanged); - HookConVarChange(stb_roundstartdelay, ConVarSettingsChanged); - HookConVarChange(stb_switchbackforced, ConVarSettingsChanged); - HookConVarChange(stb_uberlevel, ConVarSettingsChanged); - HookConVarChange(stb_mp_autoteambalance, ConVarSettingsChanged); - HookConVarChange(stb_mp_teams_unbalance_limit, ConVarSettingsChanged); - - /** - Create console commands - */ - RegConsoleCmd("sm_buddy", Command_AddBalanceBuddy, "Add a balance buddy"); - RegConsoleCmd("sm_lockbuddy", Command_LockBuddy, "Locks your balance buddy selection"); - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[STB] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_death", HookPlayerDeath, EventHookMode_Post); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Post); - switch (g_CurrentMod) - { - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - HookEvent("teamplay_suddendeath_begin", HookSuddenDeathBegin, EventHookMode_PostNoCopy); - HookEvent("teamplay_flag_event", HookFlagEvent, EventHookMode_Post); - TFGameModeArena = FindConVar("tf_gamemode_arena"); - g_iOwnerOffset = FindSendPropInfo("CBaseObject", "m_hBuilder"); - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_Post); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - - /** - Load translations and .cfg file - */ - LoadTranslations ("simpleteambalancer.phrases"); - AutoExecConfig(true, "plugin.simpleteambalancer"); - LogAction(0, -1, "[STB] Simple Team Balancer is loaded."); -} - -public OnAllPluginsLoaded() -{ - //something -} - -public OnLibraryRemoved(const String:name[]) -{ - //something -} - -public OnConfigsExecuted() -{ - - /** - Load up global variables - */ - g_bIsEnabled = GetConVarBool(stb_enabled); - g_bBuddyEnabled = GetConVarBool(stb_buddyenabled); - g_bLogActivity = GetConVarBool(stb_logactivity); - g_bLogActivity2 = GetConVarBool(stb_logactivity2); - g_bDeadOnly = GetConVarBool(stb_deadonly); - g_bPriorityPlayers = GetConVarBool(stb_priorityenabled); - g_bBuddyRestriction = GetConVarBool(stb_buddyrestriction); - g_bConVarControl = GetConVarBool(stb_convarcontrol); - g_fUberLevel = GetConVarFloat(stb_uberlevel); - g_iUnbalanceLimit = GetConVarInt(stb_unbalancelimit); - g_iBalanceDelay = GetConVarInt(stb_balancedelay); - g_iLivingPlayerSwitchDelay = GetConVarInt(stb_livingplayerswitchdelay); - g_iLivingPlayerCheckDelay = GetConVarInt(stb_livingplayercheckdelay); - g_iRoundStartDelay = GetConVarInt(stb_roundstartdelay); - g_iSwitchBackForced = GetConVarInt(stb_switchbackforced); - GetConVarString(stb_adminflag, g_sAdminFlag, sizeof(g_sAdminFlag)); - - /** - Report enabled - */ - if (g_bIsEnabled) - { - LogAction(0, -1, "[STB] Simple Team Balancer is ENABLED."); - } - else - { - LogAction(0, -1, "[STB] Simple Team Balancer is DISABLED."); - } - - - /** - Report log activity - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Log Activity ENABLED."); - } - else - { - LogAction(0, -1, "[STB] Log Activity DISABLED."); - } - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Detailed Log Activity ENABLED."); - } - else - { - LogAction(0, -1, "[STB] Detailed Log Activity DISABLED."); - } -} - -public OnMapStart() -{ - - /** - Check for arena mode - */ - if (g_CurrentMod == GameType_TF && GetConVarBool(TFGameModeArena)) - { - g_bIsArenaMode = true; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Simple Team Balancer detected arena mode and will be bypassed"); - } - } - else - { - g_bIsArenaMode = false; - } - - /** - Reset the globals - */ - g_bBalanceInProgress = false; - g_bRoundStart = false; - g_bRoundEnd = false; - g_bSuddenDeath = false; - - /** - Set the built-in convars - */ - SetGameCvars(); -} - -public OnClientPostAdminCheck(client) -{ - - /** - Make sure its a valid connected client and buddy system is enabled - */ - if (client == 0 || !g_bIsEnabled || !IsClientConnected(client) || !g_bBuddyEnabled) - { - return; - } - - /** - Make sure if its set for admins only they have the flags - */ - if (g_bBuddyRestriction && !SM_IsValidAdmin(client, g_sAdminFlag)) - { - return; - } - - /** - Start the advertisement timer - */ - CreateTimer (60.0, Timer_WelcomeAdvert, client); -} - -public OnClientDisconnect(client) -{ - - /** - Call stock function to cleaup - */ - CleanUp(client); -} - -public OnClientDisconnect_Post(client) -{ - - /** - Determine if we need a balance - */ - if (OkToBalance() && IsUnbalanced() && !g_bBalanceInProgress) - { - - /** - No balance in progress but balance is needed - */ - StartABalance(); - } -} - -public SM_OnPlayerMoved(Handle:plugin, client, team) -{ - - /** - Make sure we called the move function - */ - if (plugin != GetMyHandle()) - { - if (g_bLogActivity2) - { - LogAction(0, client, "[STB] Callback was not started with current plugin, bugging out."); - } - return; - } - - /** - Get the players name and report the event - */ - decl String:sPlayerName[64]; - GetClientName(client, sPlayerName, sizeof(sPlayerName)); - if (g_bLogActivity) - { - LogAction(0, client, "[STB] Changed %s to team %i.", sPlayerName, team); - } - - /** - If we are in TF2 fire the bult-in team balance event - */ - if(g_CurrentMod == GameType_TF) - { - new Handle:event = CreateEvent("teamplay_teambalanced_player"); - SetEventInt(event, "player", client); - SetEventInt(event, "team", team); - FireEvent(event); - } - - /** - Notify the players - */ - PrintToChatAll("[SM] %T", "BalanceMessage", LANG_SERVER, sPlayerName); - - /** - Set the players variables and start a timer - */ - g_aPlayers[client][bSwitched] = true; - g_aPlayers[client][hForcedTimer] = CreateTimer(float(g_iSwitchBackForced), Timer_ForcedExpired, client, TIMER_FLAG_NO_MAPCHANGE); - - /** - We are done, log the completion and end the balance - */ - if (g_bLogActivity) - { - LogAction(0, client, "[STB] Balance finished."); - } - g_bBalanceInProgress = false; -} - -/* HOOKED EVENTS */ - -public HookPlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get our event variables - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - decl String:sWeapon[64]; - GetEventString(event, "weapon", sWeapon, sizeof(sWeapon)); - - /** - Return if death was not caused by a player - This is the case when the player switches teams - */ - if (StrEqual(sWeapon, "world", false)) - { - return; - } - - - /** - Check if balance is needed - */ - if (IsClientInGame(iClient) && OkToBalance() && IsUnbalanced()) - { - new iSmallerTeam = GetSmallerTeam(); - - /** - Check if balance is in progress - */ - if (g_bBalanceInProgress) - { - - /** - There is a balance in progress - Check the player who died to see if he is supposed to be switched - */ - if (g_aPlayers[iClient][hBalanceTimer] != INVALID_HANDLE) - { - - /** - The player has a timer on him to switch him to other team - Stop the timer - */ - CloseHandle(g_aPlayers[iClient][hBalanceTimer]); - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] With a balance in progress the queued living player died and was switched."); - } - - /** - Call the stock change team function - */ - BalancePlayer(iClient, SM_GetForcedTeam(iClient)); - return; - } - - /** - Before we continue, lets make sure the client is switchable - */ - if (IsSwitchablePlayer(iClient, GetBiggerTeam())) - { - - /** - Now we check the buddy system - */ - if (g_bBuddyEnabled) - { - - /** - Buddy system is enabled, check to see if client has buddy - */ - new iBuddyIndex = SM_GetClientBuddy(iClient); - if (iBuddyIndex != 0 || !IsClientConnected(iBuddyIndex) || !IsClientInGame(iBuddyIndex)) - { - - /** - The client has a buddy, so we check to see if they are on same team - */ - if (GetClientTeam(iClient) == GetClientTeam(iBuddyIndex)) - { - - /** - They are, but we don't bug out, we still need to start a balance - */ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] With a balance in progress a buddy on the right team was found and skipped."); - } - } - else - { - - /** - They are not on the same team - The buddy could be in spec, and that would make it not matter where he is, or the buddy is on the smaller team - */ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] With a balance in progress a buddy on the wrong team was switched."); - } - BalancePlayer(iClient, iSmallerTeam); - return; - } - } - else - { - - /** - Client doesn't have a buddy, balance this player - */ - BalancePlayer(iClient, iSmallerTeam); - return; - } - } - else - { - - /** - Buddy system is not enabled, balance this player - */ - BalancePlayer(iClient, iSmallerTeam); - return; - } - } - } - else - { - - /** - If we get to here then we must need to start a balance - */ - StartABalance(); - } - } -} - -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get our event variables. - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - new iTeam = GetEventInt(event, "team"); - - /** - Make sure its ok to balance. - */ - if (OkToBalance()) - { - - /** - See if the client that changed teams was set to with a balance. - */ - if (g_aPlayers[iClient][hBalanceTimer] != INVALID_HANDLE - && SM_GetForcedTeam(iClient) == iTeam - && g_bBalanceInProgress) - { - - /** - The client was set to be balanced, so we close the timer. - */ - CloseHandle(g_aPlayers[iClient][hBalanceTimer]); - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - - /** - Stop the balance. - */ - g_bBalanceInProgress = false; - return; - } - - /** - It's not likely that this team change can cause us to need a balance. - If it does, start one with a small dealy to deal with forced switch backs. - */ - if (IsUnbalanced() && !g_bBalanceInProgress) - { - CreateTimer(2.0, Timer_ChangeTeamBalanceDelay, _, TIMER_FLAG_NO_MAPCHANGE); - } - } -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set the variables we need to start a round - */ - g_bRoundStart = true; - g_bRoundEnd = false; - g_bSuddenDeath = false; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Round Started"); - } - - /** - Start a delayed balance check at the start of the round - */ - CreateTimer(float(g_iRoundStartDelay), Timer_RoundStart); -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set the variables we need at round end - */ - g_bRoundEnd = true; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Round Ended"); - } -} - -public HookSuddenDeathBegin(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set the variables we need for sudden death - */ - g_bSuddenDeath = true; -} - -public HookFlagEvent(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get our event variables - */ - new iClient = GetEventInt(event, "player"); - new iFlagStatus = GetEventInt(event, "eventtype"); - - /** - Make sure we have a valid client - */ - if (!IsClientInGame(iClient)) - { - return; - } - - /** - Determine what kind of event this is - */ - switch (iFlagStatus) - { - case 1: - { - - /** - The flag was picked up - */ - g_aPlayers[iClient][bFlagCarrier] = true; - } - case 2: - { - - /** - The flag was capped - */ - g_aPlayers[iClient][bFlagCarrier] = false; - } - case 3: - { - - /** - The flag was defended, we don't have to do anything - */ - } - case 4: - { - - /** - The flag was dropped - */ - g_aPlayers[iClient][bFlagCarrier] = false; - } - } -} - -/* COMMAND EVENTS */ - -public Action:Command_AddBalanceBuddy(client, args) -{ - if (client == 0) - { - ReplyToCommand(client, "[SM] %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - if (!g_bIsEnabled || !g_bBuddyEnabled) - { - ReplyToCommand(client, "[SM] %T", "CmdDisabled", LANG_SERVER); - return Plugin_Handled; - } - if (g_bBuddyRestriction) - { - if (!SM_IsValidAdmin(client, g_sAdminFlag)) - { - ReplyToCommand(client, "[SM] %T", "RestrictedBuddy", LANG_SERVER); - return Plugin_Handled; - } - } - decl String:sPlayerUserId[24]; - GetCmdArg(1, sPlayerUserId, sizeof(sPlayerUserId)); - new iPlayer = GetClientOfUserId(StringToInt(sPlayerUserId)); - if (!iPlayer || !IsClientInGame(iPlayer) || client == iPlayer) - { - if (client == iPlayer) - { - PrintHintText(client, "%T", "SelectSelf", LANG_SERVER); - } - ReplyToCommand(client, "[SM] Usage: buddy "); - new Handle:playermenu = BuildPlayerMenu(); - DisplayMenu(playermenu, client, MENU_TIME_FOREVER); - } - else - { - decl String:cName[128]; - decl String:bName[128]; - GetClientName(client, cName, sizeof(cName)); - GetClientName(iPlayer, bName, sizeof(bName)); - if (SM_IsBuddyLocked(iPlayer)) - { - ReplyToCommand(client, "[SM] %T", "PlayerLockedBuddyMsg", LANG_SERVER, bName); - return Plugin_Handled; - } - SM_AssignBuddy(client, iPlayer); - PrintHintText(client, "%T", "BuddyMsg", LANG_SERVER, bName); - PrintHintText(iPlayer, "%T", "BuddyMsg", LANG_SERVER, cName); - } - return Plugin_Handled; -} - -public Action:Command_LockBuddy(client, args) -{ - if (client == 0) - { - ReplyToCommand(client, "[SM] %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - if (!g_bIsEnabled) - { - ReplyToCommand(client, "[SM] %T", "CmdDisabled", LANG_SERVER); - return Plugin_Handled; - } - if (g_bBuddyRestriction) - { - if (!SM_IsValidAdmin(client, g_sAdminFlag)) - { - ReplyToCommand(client, "[SM] %T", "RestrictedBuddy", LANG_SERVER); - return Plugin_Handled; - } - } - if (SM_IsBuddyLocked(client)) - { - SM_LockBuddy(client, false); - PrintHintText(client, "%T", "BuddyLockMsgDisabled", LANG_SERVER); - } - else - { - SM_LockBuddy(client, true); - PrintHintText(client, "%T", "BuddyLockMsgEnabled", LANG_SERVER); - } - return Plugin_Handled; -} - -/** -Stock functions . - */ - -stock bool:IsUnbalanced() -{ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Checking if teams are unbalanced"); - } - new Team1Count = GetTeamClientCount(g_aCurrentTeams[Team1]); - new Team2Count = GetTeamClientCount(g_aCurrentTeams[Team2]); - new ubCount = RoundFloat(FloatAbs(float(Team1Count - Team2Count))); - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Team1:%i Team2:%i Difference:%i", Team1Count, Team2Count, ubCount); - } - if (ubCount > g_iUnbalanceLimit) - { - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Teams are unbalanced"); - } - return true; - } - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Teams are not unbalanced"); - } - return false; -} - -stock bool:OkToBalance() -{ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Checking if OK to balance."); - } - new bool:bResult = false; - if (g_bIsEnabled && !g_bRoundStart && !g_bRoundEnd && !g_bIsArenaMode && !g_bSuddenDeath) - { - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Passed IF statement"); - LogAction(0, -1, "[STB] Now checking admins"); - } - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientInGame(i) && !SM_IsValidAdmin(i, g_sAdminFlag)) - { - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Found at least 1 non-admin"); - LogAction(0, -1, "[STB] OK to balance"); - } - bResult = true; - break; - } - } - if (!bResult && g_bLogActivity2) - { - LogAction(0, -1, "[STB] All admins online"); - } - } - if (!bResult && g_bLogActivity2) - { - LogAction(0, -1, "[STB] Not OK to balance"); - } - return bResult; -} - -stock bool:IsSwitchablePlayer(iClient, iBiggerTeam) -{ - - /** - Run the client thru some standard checks - */ - if (!IsClientInGame(iClient) - || SM_IsValidAdmin(iClient, g_sAdminFlag) - || g_aPlayers[iClient][bFlagCarrier] - || GetClientTeam(iClient) != iBiggerTeam - || g_aPlayers[iClient][bSwitched]) - { - - /** - The supplied client can't be switched - */ - return false; - } - - /** - The supplied client can be switched - */ - return true; -} - -stock bool:HasUber(iClient) -{ - - /** - First things first, make sure the client is a medic - */ - if(TF2_GetPlayerClass(iClient) == TFClass_Medic) - { - - /** - We can only check the active weapon, so make sure the client is holding the uber gun - */ - decl String:sWeaponName[32]; - GetClientWeapon(iClient, sWeaponName, sizeof(sWeaponName)); - if(StrEqual(sWeaponName, "tf_weapon_medigun")) - { - - /** - They are, so lets check the uber level of the gun - */ - new iEntityIndex = GetEntDataEnt2(iClient, FindSendPropInfo("CTFPlayer", "m_hActiveWeapon")); - new Float:fChargeLevel = GetEntDataFloat(iEntityIndex, FindSendPropInfo("CWeaponMedigun", "m_flChargeLevel")); - if (fChargeLevel >= g_fUberLevel) - { - - /** - The client supplied has an uber above the supplied level, return true - */ - if (g_bLogActivity2) - { - LogAction(0, iClient, "[STB] Found a medic with a uber and skipped him."); - } - return true; - } - } - } - - /** - The client supplied does not have an uber above the supplied level, return false - */ - return false; -} - -stock bool:HasBuildingsBuilt(iClient) -{ - - /** - We have to start a loop to check the owner of all the valid entities - */ - new iMaxEntities = GetMaxEntities(); - for (new i = MaxClients + 1; i <= iMaxEntities; i++) - { - if (!IsValidEntity(i)) - { - - /** - Not valid, continue to next one - */ - continue; - } - - /** - Get the name of the current entity - */ - decl String:sNetClass[32]; - GetEntityNetClass(i, sNetClass, sizeof(sNetClass)); - - /** - See if its something that an engineer would build - */ - if (strcmp(sNetClass, "CObjectSentrygun") == 0 - || strcmp(sNetClass, "CObjectTeleporter") == 0 - || strcmp(sNetClass, "CObjectDispenser") == 0) - { - - /** - It is, so lets check the owner - */ - if (GetEntDataEnt2(i, g_iOwnerOffset) == iClient) - { - - /** - The client supplied is the owner, return true - */ - if (g_bLogActivity2) - { - LogAction(0, iClient, "[STB] Found an engineer with buildings and skipped him."); - } - return true; - } - } - } - - /** - The client supplied didn't have any buildings, return false - */ - return false; -} - -stock StartABalance() -{ - - /** - See if we are already started a balance - */ - if (g_hBalanceTimer != INVALID_HANDLE) - { - - /** - We have, check if we still need to - */ - if (!IsUnbalanced() || !OkToBalance()) - { - - /** - We don't, stop the balance - It's almost impossible to reach this code, but we do it just in case - */ - CloseHandle(g_hBalanceTimer); - g_hBalanceTimer = INVALID_HANDLE; - g_bBalanceInProgress = false; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Balance delay timer was not needed and was killed before the callback."); - } - return; - } - else - { - - /** - We still need to balance - Bug out and wait for the current one to finish - */ - return; - } - } - - /** - Report that teams are unbalanced - */ - PrintToChatAll("[SM] %T", "UnBalanced", LANG_SERVER); - - /** - Check to see if we are supposed to delay the balance - */ - if (g_iBalanceDelay == 0) - { - - /** - Start the balance now - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Balance is now in progress."); - } - g_bBalanceInProgress = true; - g_hBalanceTimer = INVALID_HANDLE; - - /** - Check if we are allowed to scan living players - */ - if (!g_bDeadOnly) - { - - /** - We are allowed to, so we start a timer - */ - StartALivingPlayerTimer(); - - /** - Also report that we are now scanning dead players as well - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Now scanning dead players."); - } - } - else - { - - /** - We are not allowed to, so report that we are only scanning dead players - */ - if (g_bLogActivity) - LogAction(0, -1, "[STB] Only scanning dead players."); - } - - /** - We started the balance, bug out - */ - return; - } - - /** - We are supposed to delay the balance, start a balance timer - */ - g_hBalanceTimer = CreateTimer(float(g_iBalanceDelay), Timer_BalanceTeams, _, TIMER_FLAG_NO_MAPCHANGE); - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Teams are unbalanced. Balance delay timer started."); - } -} - -stock StartALivingPlayerTimer() -{ - - /** - Start a timer to check living players - */ - if (g_hLivingPlayerCheckTimer != INVALID_HANDLE) - { - - /** - If we for some reason already have one started, stop it. - */ - CloseHandle(g_hLivingPlayerCheckTimer); - g_hLivingPlayerCheckTimer = INVALID_HANDLE; - } - - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Living player balance delay timer started."); - } - g_hLivingPlayerCheckTimer = CreateTimer(float(g_iLivingPlayerCheckDelay), Timer_LivingPlayerCheck, _, TIMER_FLAG_NO_MAPCHANGE); -} - -stock FindSwitchablePlayer() -{ - - /** - Start a loop to find a switchable player - */ - new iPlayer; - new iBiggerTeam = GetBiggerTeam(); - for (new i = 1; i <= MaxClients; i++) - { - - /** - Check the stock function to see if we are allows to even switch the player - */ - if (!IsSwitchablePlayer(i, iBiggerTeam)) - { - continue; - } - - /** - If the mod is TF2 and they have Priority Players set check if the client has buildings or an uber - */ - if (g_CurrentMod == GameType_TF && g_bPriorityPlayers) - { - if (HasUber(i) || HasBuildingsBuilt(i)) - { - continue; - } - } - - /** - So far we are able we switch this player - Now we check the buddy system - */ - if (g_bBuddyEnabled) - { - - /** - Buddy system is enabled, check to see if client has buddy - */ - if (SM_GetClientBuddy(i) != 0) - { - - /** - The client has a buddy, so we check to see if they are on same team - */ - if (GetClientTeam(i) == GetClientTeam(SM_GetClientBuddy(i))) - { - - /** - They are, so we continue to next client - */ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] With a balance in progress a buddy on the right team was found and skipped."); - } - continue; - } - else - { - - /** - They are not on the same team, set this client - The buddy could be in spec, and that would make it not matter where he is, or the buddy is on the smaller team - */ - iPlayer = i; - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] With a balance in progress a buddy on the wrong team was found."); - } - break; - } - } - else - { - - /** - The client does not have a buddy, set this client - */ - iPlayer = i; - break; - } - } - else - { - - /** - Buddy system is not enabled, set this client - */ - iPlayer = i; - break; - } - } - - /** - Return the client we set, this could be 0, but very unlikely - */ - return iPlayer; -} - -stock BalancePlayer(iClient, iTeam) -{ - new Handle:hPack = CreateDataPack(); - WritePackCell(hPack, iClient); - WritePackCell(hPack, iTeam); - CreateTimer(0.1, Timer_BalancePlayer, hPack, TIMER_FLAG_NO_MAPCHANGE); -} - -stock CleanUp(iClient) -{ - g_aPlayers[iClient][bFlagCarrier] = false; - g_aPlayers[iClient][bSwitched] = false; - if (g_aPlayers[iClient][hForcedTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hForcedTimer]); - g_aPlayers[iClient][hForcedTimer] = INVALID_HANDLE; - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] Forced player disconnected, killing timer."); - } - } - if (g_aPlayers[iClient][hBalanceTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hBalanceTimer]); - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] Living player set to be balanced disconnected, killing timer."); - } - } -} - -stock GetSmallerTeam() -{ - - /** - Get the count of players on each team - */ - new iCountT1 = GetTeamClientCount(g_aCurrentTeams[Team1]); - new iCountT2 = GetTeamClientCount(g_aCurrentTeams[Team2]); - - /** - Return the smaller team - */ - if (iCountT1 < iCountT2) - { - return g_aCurrentTeams[Team1]; - } - else if (iCountT1 > iCountT2) - { - return g_aCurrentTeams[Team2]; - } - return 0; -} - -stock GetBiggerTeam() -{ - - /** - Get the count of players on each team - */ - new iCountT1 = GetTeamClientCount(g_aCurrentTeams[Team1]); - new iCountT2 = GetTeamClientCount(g_aCurrentTeams[Team2]); - - /** - Return the bigger team - */ - if (iCountT1 > iCountT2) - { - return g_aCurrentTeams[Team1]; - } - else if (iCountT1 < iCountT2) - { - return g_aCurrentTeams[Team2]; - } - return 0; -} - -stock SetGameCvars() -{ - if (g_bConVarControl && g_bIsEnabled) - { - if (stb_mp_autoteambalance != INVALID_HANDLE) - { - SetConVarInt(stb_mp_autoteambalance, 0); - } - if (stb_mp_teams_unbalance_limit != INVALID_HANDLE) - { - SetConVarInt(stb_mp_teams_unbalance_limit, g_iUnbalanceLimit); - } - } -} - -/* TIMER FUNCTIONS */ - -public Action:Timer_ChangeTeamBalanceDelay(Handle:timer, any:data) -{ - - /** - Finally start one if it's still unbalanced - */ - if (IsUnbalanced() && !g_bBalanceInProgress) - { - StartABalance(); - } -} - -public Action:Timer_BalanceTeams(Handle:timer, any:data) -{ - - /** - See if we still need to balance the teams - */ - if (!IsUnbalanced() || !OkToBalance()) - { - - /** - We don't, kill the balance - */ - g_bBalanceInProgress = false; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Balance delay timer was not needed and died."); - } - g_hBalanceTimer = INVALID_HANDLE; - return Plugin_Handled; - } - - /** - We still need to balance the teams - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Teams are still unbalanced. Balance is now in progress."); - } - g_bBalanceInProgress = true; - - - /** - Check if we are allowed to scan living players - */ - if (!g_bDeadOnly) - { - - /** - We are allowed to, so we start a timer - */ - StartALivingPlayerTimer(); - - /** - Also report that we are now scanning dead players as well - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Now scanning dead players."); - } - } - else - { - - /** - We are not allowed to, so report that we are only scanning dead players - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Only scanning dead players."); - } - } - - g_hBalanceTimer = INVALID_HANDLE; - return Plugin_Handled; -} - -public Action:Timer_LivingPlayerCheck(Handle:timer, any:data) -{ - - /** - Check to see if we still need to balance the teams - */ - if (!IsUnbalanced() || !OkToBalance()) - { - - /** - We don't, kill it and bug out - */ - g_bBalanceInProgress = false; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Living player balance delay timer was not needed and died."); - } - g_hLivingPlayerCheckTimer = INVALID_HANDLE; - return Plugin_Handled; - } - - /** - Call the stock function to find a player we can switch - */ - new iPlayer = FindSwitchablePlayer(); - - /** - Check to see if we found a player - */ - if (iPlayer == 0) - { - - /** - In the unlikely event that the stock function didn't return a player - Start a loop to find a random player - */ - new iBiggerTeam = GetBiggerTeam(); - do - { - iPlayer = GetRandomInt(1, MaxClients); - } while (!IsSwitchablePlayer(iPlayer, iBiggerTeam)); - - if (g_bLogActivity) - { - LogAction(0, iPlayer, "[STB] Found a random living player."); - } - } - else - { - if (g_bLogActivity) - { - LogAction(0, iPlayer, "[STB] Found a living player."); - } - } - - /** - Now that we have a player assigned them to the smaller team - */ - new iSmallerTeam = GetSmallerTeam(); - SM_SetForcedTeam(iPlayer, iSmallerTeam, true); - - /** - Let the player know we could be switching him soon - */ - PrintHintText(iPlayer, "%T", "PlayerMessage", LANG_SERVER, g_iLivingPlayerSwitchDelay); - if (g_bLogActivity) - { - LogAction(0, iPlayer, "[STB] Living player placed on a timer."); - } - - /** - Create a timer to switch the player - */ - g_aPlayers[iPlayer][hBalanceTimer] = CreateTimer(float(g_iLivingPlayerSwitchDelay), Timer_LivingPlayerBalance, iPlayer, TIMER_FLAG_NO_MAPCHANGE); - - /** - Reset the timer handle - */ - g_hLivingPlayerCheckTimer = INVALID_HANDLE; - - /** - We are done, bug out - */ - return Plugin_Handled; -} - -public Action:Timer_LivingPlayerBalance(Handle:timer, any:iClient) -{ - - /** - Check to make sure we still need to balance - */ - if (!IsUnbalanced() || !OkToBalance()) - { - - /** - We don't need to balance, bug out - */ - g_bBalanceInProgress = false; - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - SM_ClearForcedTeam(iClient); - return Plugin_Handled; - } - - /** - We still need to balance, lets make sure we can still balance this player - */ - if (!IsClientConnected(iClient) || g_aPlayers[iClient][bFlagCarrier]) - { - g_bBalanceInProgress = false; - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - SM_ClearForcedTeam(iClient); - if (g_bLogActivity) - { - if (g_aPlayers[iClient][bFlagCarrier]) - { - LogAction(0, iClient, "[STB] Living player became flag carrier, balance restarted."); - } - else - { - LogAction(0, iClient, "[STB] Living player timer was not needed and died."); - } - } - return Plugin_Handled; - } - - /** - Clear to balance this player, so do it - */ - BalancePlayer(iClient, SM_GetForcedTeam(iClient)); - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] Living player was switched."); - } - - /** - We are done, bug out - */ - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - return Plugin_Handled; -} - -public Action:Timer_BalancePlayer(Handle:timer, Handle:pack) -{ - - /** - Rest the datapack and load the variables - */ - ResetPack(pack); - new iClient = ReadPackCell(pack); - new iUnBalancedTeam = ReadPackCell(pack); - - /** - We are done with you now - */ - CloseHandle(pack); - - /** - Check the team and make sure its a valid team - */ - if(!SM_IsValidTeam(iUnBalancedTeam)) - { - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] Balance failed due to invalid team number %i", iUnBalancedTeam); - } - return Plugin_Handled; - } - - /** - Use our core function to change the clients team - */ - SM_MovePlayer(iClient, iUnBalancedTeam); - - return Plugin_Handled; -} - -public Action:Timer_RoundStart(Handle:timer, any:data) -{ - g_bRoundStart = false; - if (OkToBalance() && IsUnbalanced() && !g_bBalanceInProgress) - { - StartABalance(); - } - return Plugin_Handled; -} - -public Action:Timer_ForcedExpired(Handle:timer, any:iClient) -{ - SM_ClearForcedTeam(iClient); - g_aPlayers[iClient][bSwitched] = false; - g_aPlayers[iClient][hForcedTimer] = INVALID_HANDLE; - return Plugin_Handled; -} - -public Action:Timer_WelcomeAdvert(Handle:timer, any:iClient) -{ - if (IsClientConnected(iClient) && IsClientInGame(iClient)) - { - PrintToChat (iClient, "\x01\x04[STB]\x01 %T", "BuddyWelcomeMsg1", LANG_SERVER); - PrintToChat (iClient, "\x01\x04[STB]\x01 %T", "BuddyWelcomeMsg2", LANG_SERVER); - PrintToChat (iClient, "\x01\x04[STB]\x01 %T", "BuddyWelcomeMsg3", LANG_SERVER); - } - return Plugin_Handled; -} - -/* CONSOLE VARIABLE CHANGE EVENT */ - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (convar == stb_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsEnabled = false; - PrintToChatAll("[SM] %T", "Disabled", LANG_SERVER); - LogAction(0, -1, "[SimpleTeamBalancer] Disabled"); - } - else - { - g_bIsEnabled = true; - SetGameCvars(); - PrintToChatAll("[SM] %T", "Enabled", LANG_SERVER); - LogAction(0, -1, "[SimpleTeamBalancer] Enabled"); - } - } - else if (convar == stb_logactivity) - { - if (StringToInt(newValue) == 0) - { - g_bLogActivity = false; - LogAction(0, -1, "[STB] Log Activity DISABLED."); - } - else - { - g_bLogActivity = true; - LogAction(0, -1, "[STB] Log Activity ENABLED."); - } - } - else if (convar == stb_logactivity2) - { - if (StringToInt(newValue) == 0) - { - g_bLogActivity2 = false; - LogAction(0, -1, "[STB] Detailed Log Activity DISABLED."); - } - else - { - g_bLogActivity2 = true; - LogAction(0, -1, "[STB] Detailed Log Activity ENABLED."); - } - } - else if (convar == stb_convarcontrol) - { - if (StringToInt(newValue) == 0) - { - g_bConVarControl = false; - } - else - { - g_bConVarControl = true; - SetGameCvars(); - } - } - else if (convar == stb_deadonly) - { - if (StringToInt(newValue) == 0) - { - g_bDeadOnly = false; - } - else - { - g_bDeadOnly = true; - } - } - else if (convar == stb_priorityenabled) - { - if (StringToInt(newValue) == 0) - { - g_bPriorityPlayers = false; - } - else - { - g_bPriorityPlayers = true; - } - } - else if (convar == stb_buddyenabled) - { - if (StringToInt(newValue) == 0) - { - g_bBuddyEnabled = false; - } - else - { - g_bBuddyEnabled = true; - } - } - else if (convar == stb_buddyrestriction) - { - if (StringToInt(newValue) == 0) - { - g_bBuddyRestriction = false; - } - else - { - g_bBuddyRestriction = true; - } - } - else if (convar == stb_unbalancelimit) - { - g_iUnbalanceLimit = StringToInt(newValue); - SetGameCvars(); - } - else if (convar == stb_balancedelay) - { - g_iBalanceDelay = StringToInt(newValue); - } - else if (convar == stb_roundstartdelay) - { - g_iRoundStartDelay = StringToInt(newValue); - } - else if (convar == stb_livingplayerswitchdelay) - { - g_iLivingPlayerSwitchDelay = StringToInt(newValue); - } - else if (convar == stb_livingplayercheckdelay) - { - g_iLivingPlayerCheckDelay = StringToInt(newValue); - } - else if (convar == stb_uberlevel) - { - g_fUberLevel = StringToFloat(newValue); - } - else if (convar == stb_switchbackforced) - { - g_iSwitchBackForced = StringToInt(newValue); - } - else if (convar == stb_adminflag) - { - SetConVarString(stb_adminflag, newValue); - } - else if (convar == stb_mp_autoteambalance) - { - SetGameCvars(); - } - else if (convar == stb_mp_teams_unbalance_limit) - { - SetGameCvars(); - } -} - -/* MENU CODE */ - -stock Handle:BuildPlayerMenu() -{ - new Handle:menu = CreateMenu(Menu_SelectPlayer); - AddTargetsToMenu(menu, 0, true, false); - SetMenuTitle(menu, "Select A Player:"); - SetMenuExitButton(menu, true); - return menu; -} - -public Menu_SelectPlayer(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - new buddy = GetClientOfUserId(StringToInt(sSelection)); - if (param1 == buddy) { - PrintHintText(param1, "%T", "SelectSelf", LANG_SERVER); - } else if (!IsClientInGame(buddy)) { - PrintHintText(param1, "%T", "BuddyGone", LANG_SERVER); - } else { - decl String:cName[128]; - decl String:bName[128]; - GetClientName(param1, cName, sizeof(cName)); - GetClientName(buddy, bName, sizeof(bName)); - if (!SM_IsBuddyLocked(buddy)) { - SM_AssignBuddy(param1, buddy); - PrintHintText(param1, "%T", "BuddyMsg", LANG_SERVER, bName); - PrintHintText(buddy, "%T", "BuddyMsg", LANG_SERVER, cName); - } else - PrintHintText(param1, "%T", "PlayerLockedBuddyMsg", LANG_SERVER, bName); - } - } else if (action == MenuAction_End) { - CloseHandle(menu); - } -} \ No newline at end of file diff --git a/Simple Spectate/addons/sourcemod/scripting/simple-teammanager.sp b/Simple Spectate/addons/sourcemod/scripting/simple-teammanager.sp deleted file mode 100644 index 008f443..0000000 --- a/Simple Spectate/addons/sourcemod/scripting/simple-teammanager.sp +++ /dev/null @@ -1,1351 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Team Manager -Description: - Manges players and their team - Admin menu integration - Allows admins/donators to swap their teams (clears force)* - Allows admins to move players to a team (forced\unforced)* - Allows admins to scramble the teams* - *Works with Simple Team Balancer (if installed) -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include - -#define PLUGIN_VERSION "2.1.$Rev$" -#define VOTE_YES "##YES##" -#define VOTE_NO "##NO##" - -enum PlayerData -{ - iNewTeam, - bool:bQueue -}; - -new Handle:stm_enabled = INVALID_HANDLE; -new Handle:stm_logactivity = INVALID_HANDLE; -new Handle:stm_adminflag_swapteam = INVALID_HANDLE; -new Handle:stm_adminflag_moveplayer = INVALID_HANDLE; -new Handle:stm_adminflag_scramble = INVALID_HANDLE; -new Handle:stm_scrambledelay = INVALID_HANDLE; -new Handle:stm_voteenabled = INVALID_HANDLE; -new Handle:stm_votewin = INVALID_HANDLE; -new Handle:stm_votedelay = INVALID_HANDLE; -new Handle:stm_mp_bonusroundtime = INVALID_HANDLE; -new Handle:g_hAdminMenu = INVALID_HANDLE; -new Handle:g_hTimerPrepScramble = INVALID_HANDLE; -new Handle:g_hTimerClearScrambleForce = INVALID_HANDLE; - -new g_aPlayers[MAXPLAYERS + 1][PlayerData]; - -new bool:g_bIsEnabled = true; -new bool:g_bVoteEnabled = true; -new bool:g_bLogActivity = true; -new bool:g_bScrambleRoundEnd = false; -new g_iVoteDelay, g_iLastVoteTime, g_iTimeLeft; -new Float:g_fScrambleDelay, Float:g_fVoteWin; - -public Plugin:myinfo = -{ - name = "Simple Team Manager", - author = "Simple Plugins", - description = "Manages players and thier team.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -public OnPluginStart() -{ - - /** - Need to create all of our console variables. - */ - CreateConVar("stm_version", PLUGIN_VERSION, "Simple Team Manager Version",FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - stm_enabled = CreateConVar("stm_enabled", "1", "Enable or Disable Simple Team Manager", _, true, 0.0, true, 1.0); - stm_logactivity = CreateConVar("stm_logactivity", "0", "Enable or Disable the disaplying of events in the log", _, true, 0.0, true, 1.0); - stm_adminflag_swapteam = CreateConVar("stm_adminflag_swapteam", "a", "Admin flag to use for the swapteam command. Must be a in char format."); - stm_adminflag_moveplayer = CreateConVar("stm_adminflag_moveplayer", "c", "Admin flag to use for the moveplayer command. Must be a in char format."); - stm_adminflag_scramble = CreateConVar("stm_adminflag_scramble", "c", "Admin flag to use for the scrambleteam command. Must be a in char format."); - stm_scrambledelay = CreateConVar("stm_scrambledelay", "15", "Delay to scramble teams"); - stm_voteenabled = CreateConVar("stm_voteenabled", "1", "Enable or Disable voting to scramble the teams", _, true, 0.0, true, 1.0); - stm_votewin = CreateConVar("stm_votewin", "0.45", "Win percentage vote must win by", _, true, 0.0, true, 1.0); - stm_votedelay = CreateConVar("stm_votedelay", "600", "Delay before another vote can be cast"); - stm_mp_bonusroundtime = FindConVar("mp_bonusroundtime"); - - - /** - Need deal with changes to the console variables after the plugin is loaded. - We could not do this and just call the actual console variable each time we need it, but it's not efficent. - */ - HookConVarChange(stm_enabled, ConVarSettingsChanged); - HookConVarChange(stm_logactivity, ConVarSettingsChanged); - HookConVarChange(stm_scrambledelay, ConVarSettingsChanged); - HookConVarChange(stm_voteenabled, ConVarSettingsChanged); - HookConVarChange(stm_votewin, ConVarSettingsChanged); - HookConVarChange(stm_votedelay, ConVarSettingsChanged); - - /** - Need to register the commands we are going to create and use. - */ - RegConsoleCmd("sm_swapteam", Command_SwapTeam, "sm_swapteam <[0]instant/[1]queued>: Swaps your team to the other team"); - RegConsoleCmd("sm_moveplayer", Command_MovePlayer, "sm_moveplayer <[0]instant/[1]ondeath> <[0]unforced/[1]forced>: Moves a player to the specified team"); - RegConsoleCmd("sm_scrambleteams", Command_ScrambleTeams, "sm_scrambleteams: <[0]now/[1]roundend> <[0]dontrestart/[1]restartround> Scrambles the current teams"); - RegConsoleCmd("sm_votescramble", Command_VoteScramble, "sm_votescramble: Starts a vote to scramble the teams"); - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[STM] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_death", HookPlayerDeath, EventHookMode_Post); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Post); - switch (g_CurrentMod) - { - case GameType_TF: - { - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - } - case GameType_DOD: - { - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_Post); - } - default: - { - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - - /** - Now we have to deal with the admin menu. If the admin library is loaded call the function to add our items. - */ - new Handle:gTopMenu; - if (LibraryExists("adminmenu") && ((gTopMenu = GetAdminTopMenu()) != INVALID_HANDLE)) - { - OnAdminMenuReady(gTopMenu); - } - - /** - Load translations and .cfg file - */ - LoadTranslations ("simpleteammanager.phrases"); - AutoExecConfig(true, "plugin.simpleteammanager"); - LogAction(0, -1, "[STM] Simple Team Manager is loaded."); -} - -public OnAllPluginsLoaded() -{ - //something -} - -public OnLibraryRemoved(const String:name[]) -{ - if (StrEqual(name, "adminmenu")) - { - - /** - Looks like the admin menu was removed. Set the global. - */ - g_hAdminMenu = INVALID_HANDLE; - } - else if (StrEqual(name, "simpleplugins")) - { - SetFailState("Required plugin Simple SourceMod Plugins Core was removed."); - } -} - -public OnConfigsExecuted() -{ - - /** - Once we loaded up all the console variables from the config file, lets now set all the global variables we will use. - */ - g_bIsEnabled = GetConVarBool(stm_enabled); - g_bLogActivity = GetConVarBool(stm_logactivity); - g_fScrambleDelay = GetConVarFloat(stm_scrambledelay); - g_iVoteDelay = GetConVarInt(stm_votedelay); - g_fVoteWin = GetConVarFloat(stm_votewin); - g_iLastVoteTime = RoundFloat(GetEngineTime()); - g_bScrambleRoundEnd = false; - g_hTimerClearScrambleForce = INVALID_HANDLE; - - /** - Report enabled - */ - if (g_bIsEnabled) - { - LogAction(0, -1, "[STM] Simple Team Manager is ENABLED."); - } - else - { - LogAction(0, -1, "[STM] Simple Team Manager is DISABLED."); - } - - if (g_bLogActivity) - { - LogAction(0, -1, "[STM] Log Activity ENABLED."); - } - else - { - LogAction(0, -1, "[STM] Log Activity DISABLED."); - } -} - -/* COMMANDS */ - -public Action:Command_SwapTeam(client, args) -{ - - /** - Make sure we are enabled, if not bug out. - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - If this was ran from the console bug out. - */ - if (client == 0) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure the client is authorized to run this command. - */ - decl String:sFlags[5]; - GetConVarString(stm_adminflag_swapteam, sFlags, sizeof(sFlags)); - if (!SM_IsValidAdmin(client, sFlags)) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Lets make sure the client is one a team we can swap. - If he is we set the global array to the opposite team. - */ - new iTeam = GetClientTeam(client); - if (iTeam == g_aCurrentTeams[Team1]) - { - g_aPlayers[client][iNewTeam] = g_aCurrentTeams[Team2]; - } - else if (iTeam == g_aCurrentTeams[Team2]) - { - g_aPlayers[client][iNewTeam] = g_aCurrentTeams[Team1]; - } - else - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "InValidTeam", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check to see if we have command arguments. - */ - if (GetCmdArgs()) - { - - /** - We do, so lets get it and see if the client wants to be switched instantly or queued for death. - */ - decl String:sArg[5]; - GetCmdArg(1, sArg, sizeof(sArg)); - new iWantsQue = StringToInt(sArg); - if (iWantsQue && !g_aPlayers[client][bQueue]) - { - - /** - He wants the que and isn't already in it, set the global array. - */ - g_aPlayers[client][bQueue] = true; - ReplyToCommand(client, "\x01\x04[STM]\x01 %T", "PlayerQueue", LANG_SERVER); - } - else if (!iWantsQue) - { - - /** - He wants to be switched right now, lets call the stock function. - */ - SM_MovePlayer(client, g_aPlayers[client][iNewTeam]); - } - } - else - { - - /** - There are no command arguments so we build and display the swap menu. - */ - DisplaySwapModeMenu(client, client); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_MovePlayer(client, args) -{ - - /** - Make sure we are enabled, if not bug out. - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the client is authorized to run this command. - */ - decl String:sFlags[5]; - GetConVarString(stm_adminflag_moveplayer, sFlags, sizeof(sFlags)); - if (!SM_IsValidAdmin(client, sFlags)) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check to see if we have command arguments. - */ - new iCmdArgs = GetCmdArgs(); - if (iCmdArgs == 0) - { - - /** - We don't. Build the player menu, display it, and bug out. - */ - DisplayPlayerMenu(client); - return Plugin_Handled; - } - - /** - Check the first argument - If should be a players name or userid. - */ - decl String:sPlayer[64]; - GetCmdArg(1, sPlayer, sizeof(sPlayer)); - new iPlayerIndex = FindTarget(client, sPlayer, true, true); - if (iPlayerIndex == -1 || !IsClientInGame(iPlayerIndex)) - { - - /** - We don't know who this is. Build the player menu, display it, and bug out. - */ - DisplayPlayerMenu(client); - return Plugin_Handled; - } - - /** - We have figured out the first argument, lets check the second. - If should be the team the client wants to put the player on. - */ - if (iCmdArgs >= 2) - { - - /** - We have a command argument at least, lets see if we can identify the team. - */ - decl String:sTeam[24]; - GetCmdArg(2, sTeam, sizeof(sTeam)); - - new iTeam = StringToInt(sTeam); - if (SM_IsValidTeam(iTeam)) - { - - /** - It's a vaild team so lets set the global array to the new team. - */ - g_aPlayers[iPlayerIndex][iNewTeam] = iTeam; - } - else - { - - /** - It's not a vaild team so set the menu to display to the team menu. - */ - DisplayTeamMenu(client, iPlayerIndex); - return Plugin_Handled; - } - } - else - { - /** - We were not given a team, display the team menu. - */ - DisplayTeamMenu(client, iPlayerIndex); - return Plugin_Handled; - } - - /** - Check to see if we were given any more command arguments and found a team. - */ - if (iCmdArgs < 3) - { - - /** - No more command arguments and found a team. - Now lets check to see if the player is a spectator. If he is there is no reason to ask if it's instant or on death... he can't die. - */ - if (!IsClientObserver(iPlayerIndex)) - { - - /** - Not a spectator so display the swapmode menu. - */ - DisplaySwapModeMenu(client, iPlayerIndex); - } - else - { - - /** - The player is a spectator. - We make sure the player is not set to switch on death, since a spec can't die. - */ - g_aPlayers[iPlayerIndex][bQueue] = false; - } - } - - /** - We have figured out the second argument, lets check the third. - If should be the how the client wants to move the player: instant/on death. - */ - if (iCmdArgs >= 3) - { - - /** - The client gave us a command argument, lets check it. - */ - decl String:sSwapMode[5]; - GetCmdArg(3, sSwapMode, sizeof(sSwapMode)); - new iWantsQue = StringToInt(sSwapMode); - if (iWantsQue) - { - - /** - The client wants to que the player, set the global array. - */ - g_aPlayers[iPlayerIndex][bQueue] = true; - } - else - { - - /** - The client doesn't want to que the player, set the global array. - */ - g_aPlayers[iPlayerIndex][bQueue] = false; - } - } - else - { - /** - No swapmode argument, display the menu - */ - DisplaySwapModeMenu(client, iPlayerIndex); - } - - if (iCmdArgs >= 4) - { - - /** - Since we are compiling for Simple Team Balancer, and given a 4th argument, lets check it. - If should be the if the client wants to force the player to that team. - */ - decl String:sPlayerForced[5]; - GetCmdArg(4, sPlayerForced, sizeof(sPlayerForced)); - new iForceHim = StringToInt(sPlayerForced); - if (iForceHim) - { - - /** - The client wants to force the player - */ - SM_SetForcedTeam(iPlayerIndex, g_aPlayers[iPlayerIndex][iNewTeam]); - } - else - { - - /** - The client doesn't want to force the player - */ - SM_ClearForcedTeam(iPlayerIndex); - } - } - else - { - - } - - /** - We found and processed all the arguments. - */ - if (!IsPlayerAlive(iPlayerIndex)) - { - - /** - The player is not alive or died during this process so we just move him. - */ - SM_MovePlayer(iPlayerIndex, g_aPlayers[iPlayerIndex][iNewTeam]); - } - else - { - if (!g_aPlayers[iPlayerIndex][bQueue]) - { - - /** - The player is alive and is not set to be queued so we just move him. - */ - SM_MovePlayer(iPlayerIndex, g_aPlayers[iPlayerIndex][iNewTeam]); - } - } - - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_ScrambleTeams(client, args) -{ - - /** - Make sure we are enabled, if not bug out. - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the client is authorized to run this command. - */ - decl String:sFlags[5]; - GetConVarString(stm_adminflag_scramble, sFlags, sizeof(sFlags)); - if (!SM_IsValidAdmin(client, sFlags)) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check if a scramble timer was already called, if so close it down. - */ - if (g_hTimerPrepScramble != INVALID_HANDLE) - { - CloseHandle(g_hTimerPrepScramble); - g_hTimerPrepScramble = INVALID_HANDLE; - } - - /** - Check if we have any command arguments. - If we don't we display the scramble menu and bug out. - */ - new iCmdArgs = GetCmdArgs(); - if (iCmdArgs == 0) - { - DisplayScrambleMenu(client); - return Plugin_Handled; - } - - /** - We have a command argument. - It should be whether or not to scramble at round end. - */ - decl String:sRoundEnd[5]; - GetCmdArg(1, sRoundEnd, sizeof(sRoundEnd)); - if (StringToInt(sRoundEnd)) - { - /** - The client wants to scramble at round end so we set the global bool. - */ - g_bScrambleRoundEnd = true; - } - else - { - g_bScrambleRoundEnd = false; - } - - /** - Check for another command argument. - It should be whether or not to restart the round. - */ - decl String:sRestartRound[5]; - new bool:bRestartRound = false; - GetCmdArg(1, sRestartRound, sizeof(sRestartRound)); - if (StringToInt(sRestartRound)) - { - bRestartRound = true; - } - - /** - Now we start the scramble timer. - */ - StartScrambleTimer(_, bRestartRound); - - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_VoteScramble(client, args) -{ - - /** - Make sure we are enabled, if not bug out. - */ - if (!g_bVoteEnabled || !g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Make sure there is a vote in progress, if so bug out. - */ - if (IsVoteInProgress()) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "VoteInProgress", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure enough time has passed since the last vote. - */ - new iVoteTime = RoundFloat(GetEngineTime()); - if (iVoteTime - g_iLastVoteTime <= g_iVoteDelay) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "ScrambleTime", LANG_SERVER); - return Plugin_Handled; - } - - /** - Enough time has passed so reset the global vote time to now. - */ - g_iLastVoteTime = iVoteTime; - - /** - Build the vote menu and send it to everyone. - */ - new Handle:hMenu = CreateMenu(Menu_VoteScramble); - SetMenuTitle(hMenu, "Scramble Teams?"); - AddMenuItem(hMenu, VOTE_YES, "Yes"); - AddMenuItem(hMenu, VOTE_NO, "No"); - SetMenuExitButton(hMenu, false); - VoteMenuToAll(hMenu, 20); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -/* HOOKED EVENTS */ - -public HookPlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Find out who died. - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - - /** - Find out how the client died. - */ - new String:sWeapon[64]; - GetEventString(event, "weapon", sWeapon, sizeof(sWeapon)); - if (StrEqual(sWeapon, "world", false)) - { - - /** - He died because he changed teams so cleanup and bug out. - */ - s_CleanUp(iClient); - return; - } - - /** - Find out if this player was queued to change teams. - */ - if (g_aPlayers[iClient][bQueue]) - { - /** - Looks like he was, so call the stock function to move him. - */ - SM_MovePlayer(iClient, g_aPlayers[iClient][iNewTeam]); - } -} - -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Find out who changed teams. - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - - /** - If he was queued to switch teams we cleanup the variables. The client did it themself. - */ - if (g_aPlayers[iClient][bQueue]) - { - s_CleanUp(iClient); - } -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get the amount of time left in the map. - */ - new iTimeLeft; - GetMapTimeLeft(iTimeLeft); - - /** - Check to see if we are supposed to scramble at the end of the round and that there is enough time left in the map. - */ - if (g_bScrambleRoundEnd && iTimeLeft >= 60) - { - - /** - Check to see if there is a scramble timer in action and if so close it down. - */ - if (g_hTimerPrepScramble != INVALID_HANDLE) - { - CloseHandle(g_hTimerPrepScramble); - g_hTimerPrepScramble = INVALID_HANDLE; - } - - /** - Determine the round end chat time and run the scramble 1 second before it ends. - */ - new Float:fDelay = GetConVarFloat(stm_mp_bonusroundtime); - fDelay -= 1.0; - StartScrambleTimer(fDelay); - } -} - -public OnClientPostAdminCheck(client) -{ - - /** - Determine if the client has the flag to use the swapteam command. - */ - decl String:sFlags[5]; - GetConVarString(stm_adminflag_swapteam, sFlags, sizeof(sFlags)); - if (SM_IsValidAdmin(client, sFlags)) - { - /** - The client does so lets create a timer to run an advertise to tell him about it. - */ - CreateTimer (60.0, Timer_WelcomeAdvert, client); - } -} - -public OnClientDisconnect(client) -{ - - /** - Cleanup the clients variables. - */ - s_CleanUp(client); -} - -public SM_OnPlayerMoved(Handle:plugin, client, team) -{ - - /** - Make sure we called the move function - */ - if (plugin != GetMyHandle()) - { - if (g_bLogActivity) - { - LogAction(0, client, "[STM] Callback was not started with current plugin, bugging out."); - } - return; - } - - decl String:sPlayerName[64]; - GetClientName(client, sPlayerName, sizeof(sPlayerName)); - - PrintToChat(client, "\x01\x04[SM]\x01 %T", "PlayerSwitched", LANG_SERVER); - - s_CleanUp(client); -} - -/* TIMER FUNCTIONS */ - -public Action:Timer_PrepTeamScramble(Handle:timer, any:data) -{ - new bool:bRestartRound = data; - /** - Call the scramble the teams stock function. - */ - PrepTeamScramble(bRestartRound); - - /** - Reset the timer handle so we know the timer is done. - */ - g_hTimerPrepScramble = INVALID_HANDLE; - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Timer_ScrambleTheTeams(Handle:timer, any:data) -{ - new iPlayers[MAXPLAYERS + 1]; - new iCount, i, bool:bTeam, bool:bRestartRound = data; - - /** - Get all the client index numbers of valid players - */ - for(i = 1; i <= MaxClients; i++) - { - if(IsClientInGame(i)) // && !IsFakeClient(i)) - { - iPlayers[iCount++] = i; - } - } - - /** - Randomly sort the players - */ - SortIntegers(iPlayers, iCount, Sort_Random); - - /** - Loop through all the players and assign each one to a team, alternating each time - */ - for(i = 0; i < iCount; i++) - { - if (!bRestartRound) - { - /** - We didn't want to restart the round, so we move them to spec 1 at a time. - */ - SM_MovePlayer(iPlayers[i], g_aCurrentTeams[Spectator]); - } - SM_MovePlayer(iPlayers[i], bTeam ? g_aCurrentTeams[Team2] : g_aCurrentTeams[Team1]); - SM_SetForcedTeam(iPlayers[i], bTeam ? g_aCurrentTeams[Team2] : g_aCurrentTeams[Team1], true); - bTeam = !bTeam; - } - - /** - Reset this variable since we completed a scramble - */ - g_bScrambleRoundEnd = false; - - if (g_hTimerClearScrambleForce != INVALID_HANDLE) - { - CloseHandle(g_hTimerClearScrambleForce); - g_hTimerClearScrambleForce = INVALID_HANDLE; - } - - g_hTimerClearScrambleForce = CreateTimer(300.0, Timer_ClearScrambleForce, _, TIMER_FLAG_NO_MAPCHANGE); - - ServerCommand("mp_timelimit %i", g_iTimeLeft / 60); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Timer_ClearScrambleForce(Handle:timer, any:data) -{ - - for(new i = 1; i <= MaxClients; i++) - { - if(IsClientInGame(i)) // && !IsFakeClient(i)) - { - SM_ClearForcedTeam(i); - PrintToChat(i, "\x01\x04[SM]\x01 Your forced team status has been cleared"); - } - } - - g_hTimerClearScrambleForce = INVALID_HANDLE; - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Timer_WelcomeAdvert(Handle:timer, any:client) -{ - - /** - Lets make sure the client is connected and actually in the game. - */ - if (IsClientConnected(client) && IsClientInGame(client)) - { - - /** - We are good to go so lets tell him about the swapteam command. - */ - PrintToChat (client, "\x01\x04[STM]\x01 %T", "SwapTeamMsg", LANG_SERVER); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -/* STOCK FUNCTIONS */ - -stock s_CleanUp(iClient) -{ - - /** - Reset all the client variables - */ - g_aPlayers[iClient][bQueue] = false; - g_aPlayers[iClient][iNewTeam] = 0; -} - -stock StartScrambleTimer(Float:fdelay = 0.0, bool:bRestartRound = false) -{ - if (fdelay == 0.0) - { - fdelay = g_fScrambleDelay; - } - if (g_hTimerPrepScramble != INVALID_HANDLE) - { - CloseHandle(g_hTimerPrepScramble); - g_hTimerPrepScramble = INVALID_HANDLE; - } - PrintCenterTextAll("%T", "Scramble", LANG_SERVER); - g_hTimerPrepScramble = CreateTimer(fdelay, Timer_PrepTeamScramble, bRestartRound, TIMER_FLAG_NO_MAPCHANGE); -} - -stock PrepTeamScramble(bool:bRestartRound = false) -{ - new iPlayers[MAXPLAYERS + 1]; - new iCount; - - GetMapTimeLeft(g_iTimeLeft); - - if (bRestartRound) - { - - for(new i = 1; i <= MaxClients; i++) - { - if(IsClientInGame(i)) - // && !IsFakeClient(i)) - { - iPlayers[iCount++] = i; - SM_ClearForcedTeam(i); - SM_ClearBuddy(i); - SM_MovePlayer(i, g_aCurrentTeams[Spectator]); - } - } - } - else - { - //Can't move them all to spec at the same time - for(new i = 1; i <= MaxClients; i++) - { - if(IsClientInGame(i)) - // && !IsFakeClient(i)) - { - iPlayers[iCount++] = i; - SM_ClearForcedTeam(i); - SM_ClearBuddy(i); - //SM_MovePlayer(i, g_aCurrentTeams[Spectator]); - } - } - } - CreateTimer(4.0, Timer_ScrambleTheTeams, bRestartRound, TIMER_FLAG_NO_MAPCHANGE); -} - -/* CONSOLE VARIABLE CHANGE EVENT */ - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (convar == stm_enabled) { - if (StringToInt(newValue) == 0) { - g_bIsEnabled = false; - LogAction(0, -1, "[STM] Simple Team Manager is loaded and disabled."); - } else { - g_bIsEnabled = true; - LogAction(0, -1, "[STM] Simple Team Manager is loaded and enabled."); - } - } - else if (convar == stm_logactivity) { - if (StringToInt(newValue) == 0) { - g_bLogActivity = false; - LogAction(0, -1, "[STM] Log Activity DISABLED."); - } else { - g_bLogActivity = true; - LogAction(0, -1, "[STM] Log Activity ENABLED."); - } - } - else if (convar == stm_scrambledelay) - g_fScrambleDelay = StringToFloat(newValue); - else if (convar == stm_votewin) - g_fVoteWin = StringToFloat(newValue); - else if (convar == stm_votedelay) - g_iVoteDelay = StringToInt(newValue); - else if (convar == stm_voteenabled) { - if (StringToInt(newValue) == 0) - g_bVoteEnabled = false; - else - g_bVoteEnabled = true; - } -} - -/* MENU CODE */ - -public OnAdminMenuReady(Handle:topmenu) -{ - if (topmenu == g_hAdminMenu) - return; - g_hAdminMenu = topmenu; - new TopMenuObject:player_commands = FindTopMenuCategory(g_hAdminMenu, ADMINMENU_PLAYERCOMMANDS); - new TopMenuObject:server_commands = FindTopMenuCategory(g_hAdminMenu, ADMINMENU_SERVERCOMMANDS); - if (player_commands == INVALID_TOPMENUOBJECT) - return; - - AddToTopMenu(g_hAdminMenu, - "moveplayer", - TopMenuObject_Item, - AdminMenu_MovePlayer, - player_commands, - "moveplayer", - ADMFLAG_BAN); - - AddToTopMenu(g_hAdminMenu, - "scrambleteams", - TopMenuObject_Item, - AdminMenu_Scrambleteams, - server_commands, - "scrambleteams", - ADMFLAG_BAN); -} - -public AdminMenu_MovePlayer(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) -{ - if (action == TopMenuAction_DisplayOption) - Format(buffer, maxlength, "Move Player"); - else if (action == TopMenuAction_SelectOption){ - DisplayPlayerMenu(param); - } -} - -public AdminMenu_Scrambleteams(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) -{ - if (action == TopMenuAction_DisplayOption) - Format(buffer, maxlength, "Scramble Teams"); - else if (action == TopMenuAction_SelectOption) { - DisplayScrambleMenu(param); - } -} - -public Menu_SelectPlayer(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - DisplayTeamMenu(param1, GetClientOfUserId(StringToInt(sSelection))); - } else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -public Menu_SelectTeam(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new iTeam; - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - decl String:sIndex[64]; - if (SplitString(sSelection, "A", sIndex, sizeof(sIndex)) != -1) - iTeam = g_aCurrentTeams[Team1]; - else if (SplitString(sSelection, "B", sIndex, sizeof(sIndex)) != -1) - iTeam = g_aCurrentTeams[Team2]; - else { - SplitString(sSelection, "C", sIndex, sizeof(sIndex)); - iTeam = g_aCurrentTeams[Spectator]; - } - new iTarget = StringToInt(sIndex); - g_aPlayers[iTarget][iNewTeam] = iTeam; - DisplaySwapModeMenu(param1, iTarget); - } else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -public Menu_SwapMode(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - decl String:sIndex[64]; - - if (SplitString(sSelection, "A", sIndex, sizeof(sIndex)) == -1) - { - SplitString(sSelection, "B", sIndex, sizeof(sIndex)); - } - - new iTarget = StringToInt(sIndex); - - if (StrContains(sSelection, "A", true) != -1) - { - g_aPlayers[iTarget][bQueue] = false; - } - else if (StrContains(sSelection, "B", true) != -1) - { - g_aPlayers[iTarget][bQueue] = true; - } - - if (param1 == iTarget && !g_aPlayers[iTarget][bQueue]) - { - SM_MovePlayer(iTarget, g_aPlayers[iTarget][iNewTeam]); - } - else - { - DisplayForceModeMenu(param1, iTarget); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - { - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } - return; -} - -public Menu_ForceMode(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - decl String:sIndex[64]; - if (SplitString(sSelection, "A", sIndex, sizeof(sIndex)) == -1) - { - SplitString(sSelection, "B", sIndex, sizeof(sIndex)); - } - new iTarget = StringToInt(sIndex); - if (StrContains(sSelection, "A", true) != -1) - { - SM_ClearForcedTeam(iTarget); - } - else if (StrContains(sSelection, "B", true) != -1) - { - SM_SetForcedTeam(iTarget, g_aPlayers[iTarget][iNewTeam], true); - } - if (!g_aPlayers[iTarget][bQueue]) - { - SM_MovePlayer(iTarget, g_aPlayers[iTarget][iNewTeam]); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - { - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } - return; -} - -public Menu_VoteScramble(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_VoteEnd) { - new winning_votes, total_votes; - GetMenuVoteInfo(param2, winning_votes, total_votes); - if (param1 == 0) { - if (float(total_votes) / float(winning_votes) < g_fVoteWin) { - PrintToChatAll("\x01\x04[SM]\x01 %T", "VoteScramble2", LANG_SERVER, winning_votes, total_votes); - return; - } - PrintCenterTextAll("[SM] %T", "Scramble", LANG_SERVER); - PrintToChatAll("\x01\x04[SM]\x01 %T", "VoteScramble1", LANG_SERVER, winning_votes, total_votes); - StartScrambleTimer(); - } - if (param1 == 1) { - PrintToChatAll("\x01\x04[SM]\x01 %T", "VoteScramble2", LANG_SERVER, winning_votes, total_votes); - } - } - if (action == MenuAction_End) - CloseHandle(menu); -} - -public Menu_ScrambleTeams(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "NOW", false)) - g_bScrambleRoundEnd = false; - else - g_bScrambleRoundEnd = true; - DisplayScrambleMenu2(param1); - } else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -public Menu_ScrambleTeams2(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[64]; - new bool:bRestartRound; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "NO", false)) - { - bRestartRound = false; - } - else - { - bRestartRound = true; - } - StartScrambleTimer(_, bRestartRound); - } else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -stock DisplayScrambleMenu(iClient) -{ - new Handle:hMenu = CreateMenu(Menu_ScrambleTeams); - SetMenuTitle(hMenu, "Select When to Scramble:"); - AddMenuItem(hMenu, "NOW", "Instantly"); - AddMenuItem(hMenu, "END", "At Round End"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplayScrambleMenu2(iClient) -{ - new Handle:hMenu = CreateMenu(Menu_ScrambleTeams2); - SetMenuTitle(hMenu, "Select When to Scramble:"); - AddMenuItem(hMenu, "NO", "No Round Restart"); - AddMenuItem(hMenu, "YES", "Restart Round"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplaySwapModeMenu(iClient, iTarget) -{ - new Handle:hMenu = CreateMenu(Menu_SwapMode); - decl String:optionA[64]; - decl String:optionB[64]; - Format(optionA, sizeof(optionA), "%iA", iTarget); - Format(optionB, sizeof(optionB), "%iB", iTarget); - SetMenuTitle(hMenu, "Select When to Swap:"); - AddMenuItem(hMenu, optionA, "Instantly (Kills)"); - if (!IsClientObserver(iTarget)) - AddMenuItem(hMenu, optionB, "Queue on next death"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplayForceModeMenu(iClient, iTarget) -{ - new Handle:hMenu = CreateMenu(Menu_ForceMode); - decl String:optionA[64]; - decl String:optionB[64]; - Format(optionA, sizeof(optionA), "%iA", iTarget); - Format(optionB, sizeof(optionB), "%iB", iTarget); - SetMenuTitle(hMenu, "Select Force Mode:"); - AddMenuItem(hMenu, optionA, "UnForced"); - AddMenuItem(hMenu, optionB, "Forced"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplayTeamMenu(iClient, iTarget) -{ - new Handle:hMenu = CreateMenu(Menu_SelectTeam); - decl String:optionA[64]; - decl String:optionB[64]; - decl String:optionC[64]; - Format(optionA, sizeof(optionA), "%iA", iTarget); - Format(optionB, sizeof(optionB), "%iB", iTarget); - Format(optionC, sizeof(optionC), "%iC", iTarget); - SetMenuTitle(hMenu, "Select Team:"); - AddMenuItem(hMenu, optionA, "Team One"); - AddMenuItem(hMenu, optionB, "Team Two"); - AddMenuItem(hMenu, optionC, "Spectator"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplayPlayerMenu(iClient) -{ - new Handle:hMenu = CreateMenu(Menu_SelectPlayer); - AddTargetsToMenu(hMenu, 0, true, false); - SetMenuTitle(hMenu, "Select A Player:"); - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} diff --git a/Simple Spectate/addons/sourcemod/translations/simpledonatorbenefits.phrases.txt b/Simple Spectate/addons/sourcemod/translations/simpledonatorbenefits.phrases.txt deleted file mode 100644 index 3826846..0000000 --- a/Simple Spectate/addons/sourcemod/translations/simpledonatorbenefits.phrases.txt +++ /dev/null @@ -1,62 +0,0 @@ -"Phrases" -{ - "PlayerLevelCmd" - { - "en" "Command must be run at the player level" - "fr" "Cette commande doit être tapée en jeu" - "hu" "Ezt a parancsot jatekosi szinten kell futtatni!" - } - "RestrictedCmd" - { - "en" "You must be a donator or admin to run this command" - "fr" "Vous devez être un donateur ou un admin pour lancer cette commande" - "hu" "A parancs futtatasahoz admin, vagy tamogatoi szint szukseges!" - } - "InValidTeam" - { - "en" "You must be on red or blue to swap teams" - "fr" "Vous devez être RED ou BLU pour changer d'équipe" - "hu" "Jatekban kell lenned, hogy megcsereld a csapatokat!" - } - "PlayerQueue" - { - "en" "You have been queued to swap teams on next death" - "fr" "Vous avez été mis en attente pour changer d'équipe lors de votre prochaine mort" - "hu" "A kovetkezo halalnal csapatcsere lesz" - } - "PlayerSwitched" - { - "en" "Your team has been switched as requested" - "fr" "Vous avez changé d'équipe comme demandé" - "hu" "A keresnek eleget teve a csapatod meg lett csererlve" - } - "SwapTeamMsg" - { - "en" "Type /swapteam or !swapteam to swap your team!" - } - "ReachedCount" - { - "en" "You have reached your health limit. You must die before you can use it again" - } - "AtMaxHealth" - { - "en" "You are already at your maximum health!" - } - "ToMaxHealth" - { - "en" "Instant health bonus applied! You are not at your maximun health!" - } - "HealthBonus" - { - "en" "Instant health bonus applied!" - } - "PublicJoinMessage" - { - "#format" "{1:s}" - "en" "{1} a [donator] as joined the server" - } - "PrivateJoinMessage" - { - "en" "Thanks for donating!" - } -} \ No newline at end of file diff --git a/Simple Spectate/addons/sourcemod/translations/simpleteambalancer.phrases.txt b/Simple Spectate/addons/sourcemod/translations/simpleteambalancer.phrases.txt deleted file mode 100644 index 03595fd..0000000 --- a/Simple Spectate/addons/sourcemod/translations/simpleteambalancer.phrases.txt +++ /dev/null @@ -1,130 +0,0 @@ -"Phrases" -{ - "UnBalanced" - { - "en" "Teams are unbalanced and will be balanced shortly" - "fr" "Les équipes ne sont pas équilibrées et le seront bientôt" - "de" "Die Teams sind ungleich und werden in Kürze ausgeglichen" - "hu" "A csapatok nem kiegyenlitettek! Egyensuly beallitas kovetkezik!" - } - "Enabled" - { - "en" "Simple Team Balancer is ENABLED" - "fr" "Simple Team Balancer est ACTIVE" - "de" "Simple Team Balancer ist AKTIV" - "hu" "Az Egyszeru Csapat Egyensulytarto AKTIV!" - } - "Disabled" - { - "en" "Simple Team Balancer is DISABLED" - "fr" "Simple Team Balancer est DESACTIVE" - "de" "Simple Team Balancer ist INAKTIV" - "hu" "Az Egyszeru Csapat Egyensulytarto INAKTIV!" - } - "PlayerMessage" - { - "#format" "{1:i}" - "en" "You are going to be auto balanced in {1} seconds unless a dead player can be found" - "fr" "Vous passerez dans l'autre équipe dans {1} secondes si aucun joueur mort ne peut être trouvé dans cet intervalle" - "de" "Du wirst in {1} Sekunden zum automatischen Ausgleich herangezogen wenn kein toter Spieler gefunden werden kann" - "hu" "{1} masodpercen belul at leszel helyezve a masik csapatba, hacsak nem lesz addig egy halott jatekos!" - } - "BalanceMessage" - { - "#format" "{1:s}" - "en" "{1} was moved to the other team for game balance" - "fr" "{1} est passé dans l'autre équipe pour équilibrer la partie" - "de" "{1} wurde zum anderen Team verschoben um das Spiel auszugleichen" - "hu" "{1} at lett helyezve az egyensuly megtartasa erdekeben." - } - "PlayerLevelCmd" - { - "en" "Command must be run at the player level" - "fr" "La commande doit être lancée au niveau du joueur" - "de" "Das Kommando muss auf Spieler Ebene ausgeführt werden" - "hu" "Jatekosi szinten kell futtatni ezt a parancsot!" - } - "CmdDisabled" - { - "en" "Command is currently disabled" - "fr" "La commande est actuellement désactivée" - "de" "Das Kommando ist momentan inaktiv" - "hu" "A parancs jelenleg inaktiv" - } - "RestrictedBuddy" - { - "en" "You must be a donator or admin to add a balance buddy" - "fr" "Vous devez être un donateur ou un admin pour choisir un partenaire" - "de" "Du musst ein Spender oder Admin sein um einen Partner wählen zu können" - "hu" "Tamogato vagy admin kell hogy legyel, hogy 'Tarsat' jelolhess meg" - } - "SelectSelf" - { - "en" "You cannot be your own buddy" - "fr" "Vous ne pouvez pas être votre propre partenaire" - "de" "Du kannst nicht dein eigener Partner sein" - "hu" "Nem valaszthatod ki onmagad!" - } - "BuddyGone" - { - "en" "Your selected buddy has disconnected" - "fr" "Le partenaire que vous avez sélectionné s'est déconnecté" - "de" "Dein gewählter Partner hat die Verbindung getrennt" - "hu" "A valasztott 'Tarsad' kilepett" - } - "BuddyMsg" - { - "#format" "{1:s}" - "en" "You and {1} are now buddies" - "fr" "Vous et {1} êtes maintenant partenaires" - "de" "Du und {1} seid jetzt Partner" - "hu" "{1} es Te 'Tarsak' vagytok." - } - "BuddyLockMsgDisabled" - { - "en" "You can now be anyone's buddy" - "fr" "Vous pouvez à présent être le partenaire de n'importe qui" - "de" "Du kannst jetzt jedermanns Partner sein" - "hu" "Barkinek lehetsz a 'Tarsa'." - } - "BuddyLockMsgEnabled" - { - "en" "Buddy selection locked. Only you can change your buddy" - "fr" "Sélection de partenaire bloquée. Vous êtes le seul à pouvoir choisir votre partenaire" - "de" "Wahl des Partners gesperrt. Nur du kannst deinen Partner wechseln" - "hu" "Tars-lista lezarva. Csak Te tudod modositani a Tars-listadat." - } - "PlayerLockedBuddyMsg" - { - "#format" "{1:s}" - "en" "{1} has locked his buddy selection. Try again" - "fr" "{1} a bloqué sa sélection de partenaire. Essayez de nouveau." - "de" "{1} hat seine Wahl des Partners gesperrt. Versuche es erneut" - "hu" "{1} lezarta a Tars-listajat. Probald kesobb!" - } - "BuddyWelcomeMsg1" - { - "en" "Select a balance buddy and stay together during an autobalance!" - "fr" "Choisissez un partenaire et restez ensemble durant l'équilibrage automatique!" - "de" "Wähle einen Partner und bleibt zusammen während eines Ausgleichs" - "hu" "Valasz ki egy 'Tarsat' akivel egyuttmaradhatsz a csapatkiegyenlites alatt!" - } - "BuddyWelcomeMsg2" - { - "en" "/buddy or !buddy to select a balance buddy" - "fr" "/buddy or !buddy pour choisir un partenaire" - "de" "/buddy oder !buddy um einen Partner zu wählen" - "hu" "Hasznald a /buddy vagy !buddy parancsokat a 'Tars' kijelolesehez" - } - "BuddyWelcomeMsg3" - { - "en" "/lockbuddy or !lockbuddy to lock your selection" - "fr" "/lockbuddy or !lockbuddy pour bloquer votre sélection" - "de" "/lockbuddy oder !lockbuddy um deine Auswahl zu sperren" - "hu" "Hasznald a /lockbuddy vagy a !lockbuddy parancsokat a Tars-listad lezarasahoz" - } -} - - - - diff --git a/Simple Spectate/addons/sourcemod/translations/simpleteammanager.phrases.txt b/Simple Spectate/addons/sourcemod/translations/simpleteammanager.phrases.txt deleted file mode 100644 index f2093a7..0000000 --- a/Simple Spectate/addons/sourcemod/translations/simpleteammanager.phrases.txt +++ /dev/null @@ -1,92 +0,0 @@ -"Phrases" -{ - "PlayerLevelCmd" - { - "en" "Command must be run at the player level" - "fr" "Cette commande doit être tapée en jeu" - "hu" "Ezt a parancsot jatekosi szinten kell futtatni!" - } - "RestrictedCmd" - { - "en" "You must be a donator or admin to run this command" - "fr" "Vous devez être un donateur ou un admin pour lancer cette commande" - "hu" "A parancs futtatasahoz admin, vagy tamogatoi szint szukseges!" - } - "InValidTeam" - { - "en" "You must be on red or blue to swap teams" - "fr" "Vous devez être RED ou BLU pour changer d'équipe" - "hu" "Jatekban kell lenned, hogy megcsereld a csapatokat!" - } - "PlayerInValidTeam" - { - "en" "Player must be on red or blue to swap teams" - "fr" "Le joueur doit être RED ou BLU pour changer d'équipe" - "hu" "Valamelyik csapatban kell lenni, hogy csere legyen" - } - "PlayerQueue" - { - "en" "You have been queued to swap teams on next death" - "fr" "Vous avez été mis en attente pour changer d'équipe lors de votre prochaine mort" - "hu" "A kovetkezo halalnal csapatcsere lesz" - } - "PlayerSwitched" - { - "en" "Your team has been switched" - } - "PlayerSwitched1" - { - "en" "Your team has been switched as requested" - "fr" "Vous avez changé d'équipe comme demandé" - "hu" "A keresnek eleget teve a csapatod meg lett csererlve" - } - "PlayerSwitched2" - { - "en" "Your team has been switched by an Admin" - "fr" "Vous avez été changé d'équipe par un admin" - "hu" "Az Admin megcserelte a csapatodat!" - } - "SwapTeamMsg" - { - "en" "Type /swapteam or !swapteam to swap your team!" - } - "PlayerSwitched3" - { - "#format" "{1:s}" - "en" "{1}'s team has been switched" - "fr" "{1} a changé d'équipe" - "hu" "{1} csapata meg lett cserelve" - } - "Scramble" - { - "en" "Teams are about to be scrambled!" - "fr" "Les équipes vont être rééquilibrés" - "hu" "A csapatok hamarosan meg lesznek keverve!" - } - "VoteScramble1" - { - "#format" "{1:i}{2:i}" - "en" "Vote Scramble successful with {1} votes out of {2}" - "fr" "Le vote d'équilibrage des équipes a réussi avec {1} votes pour sur {2}" - "hu" "A szavazas sikeres volt, {1} szavazat a keveresre a {2} -bol" - } - "VoteScramble2" - { - "#format" "{1:i}{2:i}" - "en" "Vote Scramble failed with {1} votes out of {2}" - "fr" "Le vote d'équilibrage a échoué avec {1} votes pour sur {2}" - "hu" "A szavazas sikertelen volt, {1} szavazat a keveresre a {2} -bol" - } - "VoteInProgress" - { - "en" "A vote is currently in progress" - "fr" "Un vote est actuellement en cours" - "hu" "Egy szavazas mar fut!" - } - "ScrambleTime" - { - "en" "A vote was recently made, please wait" - "fr" "Un vote a déjà été fait récemment, réessayez plus tard" - "hu" "Nemreg volt szavazas, kerlek varj egy kicsit!" - } -} \ No newline at end of file diff --git a/Simple Team Balancer/addons/sourcemod/configs/simple-alltalkmanager_events.cfg b/Simple Team Balancer/addons/sourcemod/configs/simple-alltalkmanager_events.cfg deleted file mode 100644 index b739cf0..0000000 --- a/Simple Team Balancer/addons/sourcemod/configs/simple-alltalkmanager_events.cfg +++ /dev/null @@ -1,43 +0,0 @@ -"game_events" -{ - "teamplay_round_start" - { - "reason" "Round Start" - "setting" "1" - } - "teamplay_setup_finished" - { - "reason" "Setup Period Ended" - "setting" "0" - } - "teamplay_overtime_begin" - { - "reason" "Overtime Began" - "setting" "1" - } - "teamplay_overtime_end" - { - "reason" "Overtime Ended" - "setting" "1" - } - "teamplay_round_win" - { - "reason" "Round Ended" - "setting" "1" - } - "teamplay_suddendeath_begin" - { - "reason" "Sudden Death Began" - "setting" "1" - } - "teamplay_suddendeath_end" - { - "reason" "Sudden Death Ended" - "setting" "1" - } - "teamplay_round_stalemate" - { - "reason" "Stalemate" - "setting" "1" - } -} \ No newline at end of file diff --git a/Simple Team Balancer/addons/sourcemod/configs/simple-chatcolors.cfg b/Simple Team Balancer/addons/sourcemod/configs/simple-chatcolors.cfg deleted file mode 100644 index 14b98c6..0000000 --- a/Simple Team Balancer/addons/sourcemod/configs/simple-chatcolors.cfg +++ /dev/null @@ -1,15 +0,0 @@ -"admin_colors" -{ - "groupname2" - { - "flag" "z" - "namecolor" "{green}" - "textcolor" "{olive}" - } - "groupname1" - { - "flag" "a" - "namecolor" "{teamcolor}" - "textcolor" "{green}" - } -} \ No newline at end of file diff --git a/Simple Team Balancer/addons/sourcemod/plugins/simple-alltalkmanager.smx b/Simple Team Balancer/addons/sourcemod/plugins/simple-alltalkmanager.smx deleted file mode 100644 index 6122756af68998fb531abcd0d08698e24cff25af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7028 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 diff --git a/Simple Team Balancer/addons/sourcemod/plugins/simple-donatorbenefits.smx b/Simple Team Balancer/addons/sourcemod/plugins/simple-donatorbenefits.smx deleted file mode 100644 index 821d61d784607595ca400d273a941a42e40de640..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16600 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 diff --git a/Simple Team Balancer/addons/sourcemod/plugins/simple-messagesuppression.smx b/Simple Team Balancer/addons/sourcemod/plugins/simple-messagesuppression.smx deleted file mode 100644 index cc20dadd37d8ff23d0a64513cc09650f4bdbf24d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4845 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 Blh*(M diff --git a/Simple Team Balancer/addons/sourcemod/plugins/simple-spectate.smx b/Simple Team Balancer/addons/sourcemod/plugins/simple-spectate.smx deleted file mode 100644 index c6885b041145a73f664650e729a5dcf8b3b0813f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19129 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%0ACwUfid=y*oPG;MRqmWr)g0 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�XP zM5L)&uZne^XHs;_L+03=Xy3CiU1O76^S{TWu{zY}Jlq((BV?9EL=m4MC%~!W0MzeW zOjQv*a;A7AS@l%h9EbjzQ3d}e&j~R0VCoAN)q_>=)m=>e=ZX9w8jM3&o1RO^+0jJ) z

_|h)w;)ME+|h#gx@oo-|ZEuRI5d) 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 literal 17501 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 z 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 z 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 KvHt-#rc|>H2mv<$ diff --git a/Simple Team Balancer/addons/sourcemod/scripting/include/simple-plugins.inc b/Simple Team Balancer/addons/sourcemod/scripting/include/simple-plugins.inc deleted file mode 100644 index 8f21956..0000000 --- a/Simple Team Balancer/addons/sourcemod/scripting/include/simple-plugins.inc +++ /dev/null @@ -1,337 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Plugins -Description: - Included file for core plugin in the Simple Plugins project -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -*************************************************************************/ - -#if defined _simpleplugin_included - #endinput -#endif - -#define _simpleplugin_included - -#define CORE_INC_VERSION "1.1.$Rev$" - -#pragma semicolon 1 -#include -#undef REQUIRE_PLUGIN -#include -#define REQUIRE_PLUGIN -#undef REQUIRE_EXTENSIONS -#undef AUTOLOAD_EXTENSIONS -#tryinclude -#tryinclude -#tryinclude -#define AUTOLOAD_EXTENSIONS -#define REQUIRE_EXTENSIONS - -enum e_SupportedMods -{ - GameType_Unknown, - GameType_AOC, - GameType_CSS, - GameType_DOD, - GameType_FF, - GameType_HIDDEN, - GameType_HL2DM, - GameType_INS, - GameType_L4D, - GameType_NEO, - GameType_SGTLS, - GameType_TF, - GameType_ZPS -}; - -enum e_Teams -{ - Unknown, - Spectator, - Team1, - Team2 -}; - -new g_aCurrentTeams[e_Teams]; -new e_SupportedMods:g_CurrentMod; -new String:g_sGameName[e_SupportedMods][32] = { "Unknown", - "Age of Chivalry", - "Counter Strike", - "Day Of Defeat", - "Fortress Forever", - "Hidden: Source", - "Half Life 2: Deathmatch", - "Insurgency", - "Left 4 Dead", - "Neotokyo", - "Stargate TLS", - "Team Fortress 2", - "Zombie Panic: Source" - }; - -public SharedPlugin:_pl_simpleplugin = -{ - name = "simple-plugins", - file = "simple-plugins.smx", -#if defined REQUIRE_PLUGIN - required = 1 -#else - required = 0 -#endif -}; - -#if !defined REQUIRE_PLUGIN -public _pl_simpleplugin_SetNTVOptional() -{ - MarkNativeAsOptional("SM_MovePlayer"); - MarkNativeAsOptional("SM_SetForcedTeam"); - MarkNativeAsOptional("SM_GetForcedTeam"); - MarkNativeAsOptional("SM_ClearForcedTeam"); - MarkNativeAsOptional("SM_GetForcedPlayer"); - MarkNativeAsOptional("SM_AssignBuddy"); - MarkNativeAsOptional("SM_SearchBuddy"); - MarkNativeAsOptional("SM_LockBuddy"); - MarkNativeAsOptional("SM_IsBuddyLocked"); - MarkNativeAsOptional("SM_ClearBuddy"); - MarkNativeAsOptional("SM_IsValidAdmin"); - MarkNativeAsOptional("SM_IsValidTeam"); -} -#endif - -/********************************************************************** - * When a player has to moved - * - * @param plugin Plugin that initiated the move - * @param client The client index of the player that was moved - * @param team The team index the player was moved to - * @noreturn - **********************************************************************/ -forward SM_OnPlayerMoved(Handle:plugin, client, team); - -/********************************************************************** - * Move a player to the supplied team - * - * @param client The client index of the player to be moved - * @param team The team to move the player to - * @noreturn - * @error Invalid client or team index - **********************************************************************/ -native SM_MovePlayer(client, team); - -/********************************************************************** - * Move a player to the supplied team - * - * @param client The client index of the player to set - * @param team The team to move the to set - * @param override Whether or not to override another plugin - * @return True if successful, false if not - * @error Invalid client or team index - **********************************************************************/ -native SM_SetForcedTeam(client, team, bool:override = false); - -/********************************************************************** - * Gets the client's forced team index - * - * @param client The client index of the player to check - * @param plugin Optional: The plugin handle of the plugin - that set the team - * @return The team index of the forced team - Zero if no forced team - * @error Invalid client index - **********************************************************************/ -native SM_GetForcedTeam(client, &Handle:plugin = INVALID_HANDLE); - -/********************************************************************** - * Clears a client's forced team - * - * @param client The client index of the player to check - * @return True if successful, false if not - * @error Invalid client index - **********************************************************************/ -native SM_ClearForcedTeam(client); - -/********************************************************************** - * Gets a forced player on the wrong that is currently on the wrong team - * This will only return a player if the calling plugin assigned the team - * - * @param team The team index the player should be on - * @return The client index of the player - Zero if no player found - * @error Invalid client index - **********************************************************************/ -native SM_GetForcedPlayer(team); - -/********************************************************************** - * Assign a players buddy - * - * @param client The client index of the player to assign - * @param player The player index of the player to assign - * @param override Whether or not to override a player lock - * @return True if successful, false if not - * @error Invalid client or player index - **********************************************************************/ -native bool:SM_AssignBuddy(client, player, bool:override = false); - -/********************************************************************** - * Rturns the client's buddy - * - * @param client The client index of the player to assign - * @return The client index of the player's buddy - Zero if no buddy - * @error Invalid client index - **********************************************************************/ -native SM_GetClientBuddy(client); - -/********************************************************************** - * Set the buddy lock setting for a client - * - * @param client The client index of the player to assign - * @param setting Setting to set, True or False - * @return True if successful, false if not - * @error Invalid client index - **********************************************************************/ -native bool:SM_LockBuddy(client, bool:setting); - -/********************************************************************** - * Returns the buddy lock setting for a client - * - * @param client The client index of the player to assign - * @return True if locked, false if not - * @error Invalid client index - **********************************************************************/ -native bool:SM_IsBuddyLocked(client); - -/********************************************************************** - * Clear a players buddy - * - * @param client The client index of the player to clear - * @param override Whether or not to override a player lock - * @return True if successful, false if not - * @error Invalid client index - **********************************************************************/ -native bool:SM_ClearBuddy(client, bool:override = false); - -/********************************************************************** - * Determine if the player has the supplied flags - * ADMFLAG_ROOT will always return true - * - * @param client The client index of the player to assign - * @param flags The char flag(s) to check against - * @return True if valid, false if not - **********************************************************************/ -native bool:SM_IsValidAdmin(client, const String:flags[]); - - -/********************************************************************** - * Determine if the team is a valid team - * - * @param team The team index to determine if valid for - currently installed/supported mod - * @return True if valid, false if not - **********************************************************************/ -native bool:SM_IsValidTeam(team); - - -public e_SupportedMods:GetCurrentMod() -{ - new String:sGameType[64]; - GetGameFolderName(sGameType, sizeof(sGameType)); - - if (StrEqual(sGameType, "aoc", false)) - { - return GameType_AOC; - } - if (StrEqual(sGameType, "cstrike", false)) - { - return GameType_CSS; - } - if (StrEqual(sGameType, "dod", false)) - { - return GameType_DOD; - } - if (StrEqual(sGameType, "ff", false)) - { - return GameType_FF; - } - if (StrEqual(sGameType, "hidden", false)) - { - return GameType_HIDDEN; - } - if (StrEqual(sGameType, "hl2mp", false)) - { - return GameType_FF; - } - if (StrEqual(sGameType, "insurgency", false) || StrEqual(sGameType, "ins", false)) - { - return GameType_INS; - } - if (StrEqual(sGameType, "l4d", false)) - { - return GameType_L4D; - } - if (StrEqual(sGameType, "nts", false)) - { - return GameType_NEO; - } - if (StrEqual(sGameType, "sgtls", false)) - { - return GameType_SGTLS; - } - if (StrEqual(sGameType, "tf", false)) - { - return GameType_TF; - } - if (StrEqual(sGameType, "zps", false)) - { - return GameType_ZPS; - } - return GameType_Unknown; -} - -public LoadCurrentTeams() -{ - switch (g_CurrentMod) - { - case GameType_INS: - { - g_aCurrentTeams[Unknown] = 0; - g_aCurrentTeams[Spectator] = 3; - g_aCurrentTeams[Team1] = 1; - g_aCurrentTeams[Team2] = 2; - } - case default: - { - g_aCurrentTeams[Unknown] = 0; - g_aCurrentTeams[Spectator] = 1; - g_aCurrentTeams[Team1] = 2; - g_aCurrentTeams[Team2] = 3; - } - } -} diff --git a/Simple Team Balancer/addons/sourcemod/scripting/simple-alltalkmanager.sp b/Simple Team Balancer/addons/sourcemod/scripting/simple-alltalkmanager.sp deleted file mode 100644 index c848332..0000000 --- a/Simple Team Balancer/addons/sourcemod/scripting/simple-alltalkmanager.sp +++ /dev/null @@ -1,515 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple AllTalk Manager -Description: - Allows you to set alltalk at different times -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#pragma semicolon 1 -#include -#include - -#define PLUGIN_VERSION "1.4.$Rev$" - -new Handle:satm_enabled = INVALID_HANDLE; -new Handle:satm_threshold_enabled = INVALID_HANDLE; -new Handle:satm_player_threshold = INVALID_HANDLE; -new Handle:satm_threshold_setting = INVALID_HANDLE; -new Handle:satm_logactivity = INVALID_HANDLE; -new Handle:satm_alltalk = INVALID_HANDLE; - -new Handle:g_aEventNames = INVALID_HANDLE; -new Handle:g_aEventReasons = INVALID_HANDLE; -new Handle:g_aEventSettings = INVALID_HANDLE; - -new bool:g_bLastThreshold = false; -new bool:g_bEnabled = true; -new bool:g_bThresholdEnabled = true; -new bool:g_bIsSetupMap = false; -new bool:g_bIsGameTF2 = false; -new bool:g_bLogActivity = false; - -new g_iLastEventIndex; - -public Plugin:myinfo = -{ - name = "Simple AllTalk Manager", - author = "Simple Plugins", - description = "Allows you to set alltalk at different times", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -} - -/** -Sourcemod callbacks -*/ -public OnPluginStart() -{ - - /** - Need to create all of our console variables. - */ - CreateConVar("satm_version", PLUGIN_VERSION, "Simple AllTalk Manager", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - satm_enabled = CreateConVar("satm_enabled", "1", "Enables/Disables Simple AllTalk Manager", _, true, 0.0, true, 1.0); - satm_threshold_enabled = CreateConVar("satm_threshold_enabled", "1", "Enables/Disables player threshold", _, true, 0.0, true, 1.0); - satm_player_threshold = CreateConVar("satm_player_threshold", "8", "Amount of players for the threshold"); - satm_threshold_setting = CreateConVar("satm_threshold_setting", "1", "Enables/Disables all talk up to player threshold, with the opposite set after the threshold", _, true, 0.0, true, 1.0); - satm_logactivity = CreateConVar("satm_logactivity", "0", "Enables/Disables log activity", _, true, 0.0, true, 1.0); - satm_alltalk = FindConVar("sv_alltalk"); - - /** - Hook console variables - */ - HookConVarChange(satm_enabled, ConVarSettingsChanged); - HookConVarChange(satm_threshold_enabled, ConVarSettingsChanged); - HookConVarChange(satm_player_threshold, ConVarSettingsChanged); - HookConVarChange(satm_logactivity, ConVarSettingsChanged); - - /** - Remove the notify flag from all talk cvar since we do it - */ - SetConVarFlags(satm_alltalk, GetConVarFlags(satm_alltalk)~FCVAR_NOTIFY); - - /** - Get the game type. We only care if it's TF2 - */ - new String:sGameType[64]; - GetGameFolderName(sGameType, sizeof(sGameType)); - if (StrEqual(sGameType, "tf", false)) - { - g_bIsGameTF2 = true; - } - - /** - Create the arrays - */ - g_aEventNames = CreateArray(255, 1); - g_aEventReasons = CreateArray(255, 1); - g_aEventSettings = CreateArray(1, 1); - - /** - Need to register the commands we are going to create and use. - */ - RegAdminCmd("sm_reloadatconfig", Command_Reload, ADMFLAG_GENERIC, "Reloads settings from config file"); - - /** - Create the config file - */ - AutoExecConfig(true); - - /** - Load the events from the config - */ - LoadEventsFromConfig(); -} - -public OnConfigsExecuted() -{ - - /** - Load up the settings - */ - g_bEnabled = GetConVarBool(satm_enabled); - g_bLogActivity = GetConVarBool(satm_logactivity); - g_bThresholdEnabled = GetConVarBool(satm_threshold_enabled); -} - -public OnMapStart() -{ - - /** - Reset the globals - */ - g_iLastEventIndex = 0; - g_bLastThreshold = false; - - /** - Check the map type if we are in TF2 - */ - if (g_bIsGameTF2) - { - g_bIsSetupMap = IsSetupPeriodMap(); - } - - /** - Set AllTalk - */ - if (g_bEnabled) - { - SetConVarBool(satm_alltalk, true); - } -} - -public OnClientDisconnect_Post(client) -{ - if (g_bEnabled) - { - SetAllTalk(-1); - } -} - -public OnClientPostAdminCheck(client) -{ - if (g_bEnabled) - { - SetAllTalk(-1); - } - CreateTimer(2.0, Timer_ShowAllTalkStatus, client, TIMER_FLAG_NO_MAPCHANGE); -} - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (convar == satm_enabled) - { - if (StringToInt(newValue)) - { - g_bEnabled = true; - } - else - { - g_bEnabled = false; - } - } - else if (convar == satm_threshold_enabled) - { - if (StringToInt(newValue)) - { - g_bThresholdEnabled = true; - } - else - { - g_bThresholdEnabled = false; - } - } - else if (convar == satm_logactivity) - { - if (StringToInt(newValue)) - { - g_bLogActivity = true; - } - else - { - g_bLogActivity = false; - } - } - if (g_bEnabled) - { - SetAllTalk(-1); - } -} - -/** -Commands -*/ -public Action:Command_Reload(client, args) -{ - - /** - Clear the array - */ - ClearArray(g_aEventNames); - ClearArray(g_aEventReasons); - ClearArray(g_aEventSettings); - - /** - Load the events from the config - */ - LoadEventsFromConfig(); - - return Plugin_Handled; -} - -/** -Game Event Hooks -*/ -public Hook_All_Events(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (!g_bIsSetupMap) - { - if (StrEqual(name, "teamplay_round_start")) - { - if (FindStringInArray(g_aEventNames, "teamplay_setup_finished") != -1) - { - g_iLastEventIndex = FindStringInArray(g_aEventNames, "teamplay_setup_finished"); - if (g_bEnabled) - { - SetAllTalk(g_iLastEventIndex); - return; - } - } - } - } - g_iLastEventIndex = FindStringInArray(g_aEventNames, name); - if (g_bEnabled) - { - SetAllTalk(g_iLastEventIndex); - } -} - -/** -Timers -*/ -public Action:Timer_ShowAllTalkStatus(Handle:timer, any:client) -{ - if (IsClientConnected(client) && IsClientInGame(client)) - { - new bool:bSetting = GetConVarBool(satm_alltalk); - if (bSetting) - { - PrintToChat(client, "\x01\x04[SM] AllTalk is \x01[on]"); - } - else - { - PrintToChat(client, "\x01\x04[SM] AllTalk is \x01[off]"); - } - } -} - -/** -Stock Functions -*/ -stock LoadEventsFromConfig() -{ - - /** - Make sure the config file is here and load it up - */ - new String:sConfigFile[256]; - BuildPath(Path_SM, sConfigFile, sizeof(sConfigFile), "configs/simple-alltalkmanager_events.cfg"); - if (!FileExists(sConfigFile)) - { - - /** - Config file doesn't exists, stop the plugin - */ - LogError("[SATM] Simple AllTalk Manager is not running! Could not find file %s", sConfigFile); - SetFailState("Could not find file %s", sConfigFile); - } - - /** - Create the arrays and variables - */ - new String:sGameEventName[256]; - new String:sReason[256]; - new iSetting; - - /** - Load config file as a KeyValues file - */ - new Handle:kvGameEvents = CreateKeyValues("game_events"); - FileToKeyValues(kvGameEvents, sConfigFile); - - if (!KvGotoFirstSubKey(kvGameEvents)) - { - return; - } - - /** - Hook the game events and load the settings - */ - do - { - - /** - Get the section name; this should be the event name - */ - KvGetSectionName(kvGameEvents, sGameEventName, sizeof(sGameEventName)); - if (!HookEventEx(sGameEventName, Hook_All_Events, EventHookMode_PostNoCopy)) - { - - /** - Could not hook this event, stop the plugin - */ - SetFailState("Could not hook event %s", sGameEventName); - } - else - { - if (g_bLogActivity) - { - LogMessage("[SATM] Hooked event: %s", sGameEventName); - } - } - - /** - Get the reason string and setting - */ - KvGetString(kvGameEvents, "reason", sReason, sizeof(sReason)); - iSetting = KvGetNum(kvGameEvents, "setting"); - if (g_bLogActivity) - { - LogMessage("[SATM] Event reason string: %s", sReason); - LogMessage("[SATM] Event setting: %i", iSetting); - } - - /** - Push the values to the arrays - */ - PushArrayString(g_aEventNames, sGameEventName); - PushArrayString(g_aEventReasons, sReason); - PushArrayCell(g_aEventSettings, iSetting); - } while (KvGotoNextKey(kvGameEvents)); - - /** - Close our handle - */ - CloseHandle(kvGameEvents); -} - -stock SetAllTalk(index) -{ - new iPlayerThreshold = GetConVarInt(satm_player_threshold); - new bool:bThresholdMet = ((GetClientCount() >= iPlayerThreshold) ? true : false); - new bool:bSetting; - - if (g_bThresholdEnabled) - { - if (bThresholdMet) - { - if (index == -1) - { - if (bThresholdMet != g_bLastThreshold) - { - g_bLastThreshold = true; - bSetting = !GetConVarBool(satm_threshold_setting); - new bool:bLastSetting = GetArrayCell(g_aEventSettings, g_iLastEventIndex); - if (bLastSetting && !bSetting) - { - bSetting = GetArrayCell(g_aEventSettings, g_iLastEventIndex); - } - } - else - { - bSetting = GetArrayCell(g_aEventSettings, g_iLastEventIndex); - } - } - else - { - bSetting = GetArrayCell(g_aEventSettings, index); - } - } - else - { - g_bLastThreshold = false; - bSetting = GetConVarBool(satm_threshold_setting); - } - } - else - { - if (index != -1) - { - bSetting = GetArrayCell(g_aEventSettings, index); - } - } - - if (GetConVarBool(satm_alltalk) != bSetting) - { - - SetConVarBool(satm_alltalk, bSetting); - - new String:sReason[256]; - if (index == -1) - { - Format(sReason, sizeof(sReason), "Player Threshold"); - } - else - { - if (!g_bIsSetupMap) - { - new String:sCurrentEvent[256]; - GetArrayString(g_aEventNames, index, sCurrentEvent, sizeof(sCurrentEvent)); - if (StrEqual(sCurrentEvent, "teamplay_setup_finished")) - { - new iRoundStartIndex = FindStringInArray(g_aEventNames, "teamplay_round_start"); - if (iRoundStartIndex != -1) - { - GetArrayString(g_aEventReasons, iRoundStartIndex, sReason, sizeof(sReason)); - } - else - { - GetArrayString(g_aEventReasons, index, sReason, sizeof(sReason)); - } - } - else - { - GetArrayString(g_aEventReasons, index, sReason, sizeof(sReason)); - } - } - else - { - GetArrayString(g_aEventReasons, index, sReason, sizeof(sReason)); - } - } - - if (bSetting) - { - PrintToChatAll("\x01\x04[SM] AllTalk turned \x01[on] \x04due to:\x01 %s", sReason); - } - else - { - PrintToChatAll("\x01\x04[SM] AllTalk turned \x01[off] \x04due to:\x01 %s", sReason); - } - } -} - -stock bool:IsSetupPeriodMap() -{ - new iEnt = -1; - new String:sMapName[32]; - - GetCurrentMap(sMapName, sizeof(sMapName)); - - if (strncmp(sMapName, "cp_", 3, false) == 0) - { - new iTeam; - while ((iEnt = FindEntityByClassname(iEnt, "team_control_point")) != -1) - { - iTeam = GetEntProp(iEnt, Prop_Send, "m_iTeamNum"); - - /** - If there is a blu CP or a neutral CP, then it's not an attack/defend map - */ - if (iTeam != 2) - { - //this is a push map - return false; - } - } - //this is a attack/defend map - return true; - } - else if (strncmp(sMapName, "ctf_", 3, false) == 0) - { - //this is a ctf map - return false; - } - return false; -} diff --git a/Simple Team Balancer/addons/sourcemod/scripting/simple-autoscrambler.sp b/Simple Team Balancer/addons/sourcemod/scripting/simple-autoscrambler.sp deleted file mode 100644 index 6c6799e..0000000 --- a/Simple Team Balancer/addons/sourcemod/scripting/simple-autoscrambler.sp +++ /dev/null @@ -1,459 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple AutoScrambler -Description: - Automatically scrambles the teams based upon a number of events. -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include - -#define PLUGIN_VERSION "1.1.$Rev$" - -/** -Different scramble modes: - -1 = Full Scramble, dont restart round. -2 = Admins Immune, dont restart round. -3 = Full Scramble, restart round and reset scores. -4 = Admins Immune, restart round and reset scores. - -*/ - -/** -Different top player modes: - -1 = Divide Top 4 players on the two teams. -2 = Protect the Top 2 players on each team. - -*/ - -enum PlayerData -{ - Handle:hForcedTimer, - bool:bProtected; -}; - -/** -Cvars used for admins -*/ -new Handle: sas_admin_immunity_enabled = INVALID_HANDLE, - Handle: sas_admin_flag_scramblenow = INVALID_HANDLE, - Handle: sas_admin_flag_immunity = INVALID_HANDLE; - -/** -Cvars used for autoscramble -*/ -new Handle: sas_autoscramble_enabled = INVALID_HANDLE, - Handle: sas_autoscramble_minplayers = INVALID_HANDLE, - Handle: sas_autoscramble_mode = INVALID_HANDLE, - Handle: sas_autoscramble_winstreak = INVALID_HANDLE, - Handle: sas_autoscramble_steamroll = INVALID_HANDLE, - Handle: sas_autoscramble_frags = INVALID_HANDLE; - -/** -Cvars used for voting -*/ -new Handle: sas_vote_enabled = INVALID_HANDLE, - Handle: sas_vote_upcount = INVALID_HANDLE, - Handle: sas_vote_winpercent = INVALID_HANDLE, - Handle: sas_vote_mode = INVALID_HANDLE, - Handle: sas_vote_minplayers = INVALID_HANDLE; - -/** -Additional cvars -*/ -new Handle: sas_enabled = INVALID_HANDLE, - Handle: sas_timer_scrambledelay = INVALID_HANDLE, - Handle: TFGameModeArena = INVALID_HANDLE; - -/** -Timers -*/ -new Handle: g_hScrambleTimer = INVALID_HANDLE; - -/** - Player arrays - */ -new g_aPlayers[MAXPLAYERS + 1][PlayerData]; - -/** - Cvar variables - */ -new bool: g_bIsEnabled, - bool: g_bIsAutoScrambleEnabled, - bool: g_bIsVoteEnabled, - bool: g_bIsAdminImmunityEnabled; -new Float: g_fTimer_ScrambleDelay, - Float: g_fVote_UpCount, - Float: g_fVote_WinPercent; -new g_iAutoScramble_Minplayers, - g_iAutoScramble_Mode, - g_iAutoScramble_WinStreak, - g_iAutoScramble_SteamRoll, - g_iAutoScramble_Frags, - g_iVote_Mode, - g_iVote_MinPlayers; -new String: g_sScrambleNowFlag[5], - String: g_sAdminImmunityFlag[5]; - -/** -Other globals -*/ -new g_iMaxEntities, - g_iOwnerOffset; - -public Plugin:myinfo = -{ - name = "Simple AutoScrambler", - author = "Simple Plugins", - description = "Automatically scrambles the teams based upon a number of events.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -public OnPluginStart() -{ - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[SAS] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - switch (g_CurrentMod) - { - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_Post); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_Post); - } - } - - /** - Create console variables - */ - CreateConVar("sas_version", PLUGIN_VERSION, "Simple AutoScrambler Version",FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - sas_enabled = CreateConVar("sas_enabled", "1", "Enable/Disable Simple AutoScrambler"); - sas_timer_scrambledelay = CreateConVar("sas_timer_scrambledelay", "5.0", "Delay used after a scramble has been started", _, true, 1.0, true, 30.0); - - /** - Cvars used for admins - */ - sas_admin_immunity_enabled = CreateConVar("sas_admin_immunity_enabled", "1", "Enable/Disable admin immunity for scrambles"); - sas_admin_flag_scramblenow = CreateConVar("sas_admin_flag_scramblenow", "z", "Admin flag to use for scramblenow function/command"); - sas_admin_flag_immunity = CreateConVar("sas_admin_flag_immunity", "z", "Admin flag to use for scramble immunity"); - - /** - Cvars used for autoscramble - */ - sas_autoscramble_enabled = CreateConVar("sas_autoscramble_enabled", "1", "Enable/Disable the autoscramble function"); - sas_autoscramble_minplayers = CreateConVar("sas_autoscramble_minplayers", "16", "Min players needed to start an autoscramble"); - sas_autoscramble_mode = CreateConVar("sas_autoscramble_mode", "1", "Scramble mode used when autoscrambling"); - sas_autoscramble_winstreak = CreateConVar("sas_autoscramble_winstreak", "5", "Max amount of wins in a row a team can achieve before an autoscramble starts"); - sas_autoscramble_steamroll = CreateConVar("sas_autoscramble_steamroll", "120", "Shortest amount of time a team can win by before an autoscramble starts (seconds)"); - sas_autoscramble_frags = CreateConVar("sas_autoscramble_frags", "1", "Min players needed to start a vote and scramble"); - - /** - Cvars used for voting - */ - sas_vote_enabled = CreateConVar("sas_vote_enabled", "1", "Enable/Disable voting for scramble"); - sas_vote_upcount = CreateConVar("sas_vote_upcount", "5", "Amount of people wanting a scramble before a vote starts. If less than 1 it will be considered a percentage. (ie 0.5 = 50% | 1 = 1 Player | 5 = 5 Players)"); - sas_vote_winpercent = CreateConVar("sas_vote_winpercent", "0.6", "Percentage of votes needed to scramble", _, true, 0.0, true, 1.0); - sas_vote_mode = CreateConVar("sas_vote_mode", "1", "Scramble mode used when a vote results in a scramble"); - sas_vote_minplayers = CreateConVar("sas_vote_minplayers", "16", "Min players needed to start a vote and scramble"); - - /** - Hook the console variables if they change - */ - HookConVarChange(sas_enabled, ConVarSettingsChanged); - HookConVarChange(sas_timer_scrambledelay, ConVarSettingsChanged); - HookConVarChange(sas_admin_immunity_enabled, ConVarSettingsChanged); - HookConVarChange(sas_admin_flag_scramblenow, ConVarSettingsChanged); - HookConVarChange(sas_admin_flag_immunity, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_enabled, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_minplayers, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_mode, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_winstreak, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_steamroll, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_frags, ConVarSettingsChanged); - HookConVarChange(sas_vote_enabled, ConVarSettingsChanged); - HookConVarChange(sas_vote_upcount, ConVarSettingsChanged); - HookConVarChange(sas_vote_winpercent, ConVarSettingsChanged); - HookConVarChange(sas_vote_mode, ConVarSettingsChanged); - HookConVarChange(sas_vote_minplayers, ConVarSettingsChanged); - - /** - Register the command - */ - RegConsoleCmd("sm_scramblenow", Command_ScrambleNow, "sm_scramblenow (mode): Scrambles the teams"); - - /** - Load translations and .cfg file - */ - LoadTranslations ("simpleautoscrambler.phrases"); - AutoExecConfig(true, "plugin.simpleautoscrambler"); - LogAction(0, -1, "[SAS] Simple AutoScrambler is loaded."); -} - -public OnAllPluginsLoaded() -{ - //something -} - -public OnLibraryRemoved(const String:name[]) -{ - //something -} - -public OnConfigsExecuted() -{ - - /** - Load up all the variable defaults - */ - LoadUpVariables(); - - /** - Log our activity - */ - if (g_bIsEnabled) - LogAction(0, -1, "Simple AutoScrambler is ENABLED"); - else - LogAction(0, -1, "Simple AutoScrambler is DISABLED"); -} - -public Action:Command_ScrambleNow(client, args) -{ - - /** - Make sure we are enabled - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the client is authorized to run this command. - */ - if (!SM_IsValidAdmin(client, g_sScrambleNowFlag)) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure it's ok to scramble at this time - */ - if (!OkToScramble) - { - return Plugin_Handled; - } - - /** - Make sure it's ok to scramble at this time - */ - LogAction(0, -1, "[SAS] The scramblenow command was used"); - - /** - Scramble the teams - */ - StartAScramble(); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - -} - -public Action:Timer_ScrambleTeams(Handle:timer, any:mode) -{ - - /** - Make sure it's still ok to scramble - */ - if (!OkToScramble) - { - return Plugin_Handled; - } - - - switch (mode) - { - case - - - - } - - - /** - Reset the handle because the timer is over and the callback is done - */ - g_hScrambleTimer = INVALID_HANDLE; - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - -} - -stock StartAScramble(mode) -{ - - /** - See if we are already started a scramble - */ - if (g_hScrambleTimer == INVALID_HANDLE) - { - - /** - There is a scramble in progress - */ - return; - - } - - /** - Report that a scramble is about to start - */ - PrintCenterTextAll("%T", "Scramble", LANG_SERVER); - - /** - Start a timer and log the action - */ - g_hScrambleTimer = CreateTimer(g_fTimer_ScrambleDelay, Timer_ScrambleTeams, mode, TIMER_FLAG_NO_MAPCHANGE); - LogAction(0, -1, "[SAS] A scamble timer was started"); -} - -stock bool:OkToScramble() -{ - -} - -stock LoadUpVariables() -{ - g_bIsEnabled = GetConVarBool(sas_enabled); - g_bIsAutoScrambleEnabled = GetConVarBool(sas_autoscramble_enabled); - g_bIsVoteEnabled = GetConVarBool(sas_vote_enabled); - g_bIsAdminImmunityEnabled = GetConVarBool(sas_admin_immunity_enabled); - g_iAutoScramble_Minplayers = GetConVarInt(sas_autoscramble_minplayers); - g_iAutoScramble_Mode = GetConVarInt(sas_autoscramble_mode); - g_iAutoScramble_WinStreak = GetConVarInt(sas_autoscramble_winstreak); - g_iAutoScramble_SteamRoll = GetConVarInt(sas_autoscramble_steamroll); - g_iAutoScramble_Frags = GetConVarInt(sas_autoscramble_frags); - g_iVote_Mode = GetConVarInt(sas_vote_mode); - g_iVote_MinPlayers = GetConVarInt(sas_vote_minplayers); - GetConVarString(sas_admin_flag_scramblenow, g_sScrambleNowFlag, sizeof(g_sScrambleNowFlag)); - GetConVarString(sas_admin_flag_immunity, g_sAdminImmunityFlag, sizeof(g_sAdminImmunityFlag)); - g_fTimer_ScrambleDelay = GetConVarFloat(sas_timer_scrambledelay); - g_fVote_UpCount = GetConVarFloat(sas_vote_upcount); - g_fVote_WinPercent = GetConVarFloat(sas_vote_winpercent); - g_iMaxEntities = GetMaxEntities(); - g_iOwnerOffset = FindSendPropInfo("CBaseObject", "m_hBuilder"); -} - -stock TF2_DestroyBuildings(client) -{ - - /** - We have to start a loop to check the owner of all the valid entities - */ - for (new i = MaxClients + 1; i <= g_iMaxEntities; i++) - { - if (!IsValidEntity(i)) - { - - /** - Not valid, continue to next one - */ - continue; - } - - /** - Get the name of the current entity - */ - decl String:sNetClass[32]; - GetEntityNetClass(i, sNetClass, sizeof(sNetClass)); - - /** - See if its something that an engineer would build - */ - if (strcmp(sNetClass, "CObjectSentrygun") == 0 - || strcmp(sNetClass, "CObjectTeleporter") == 0 - || strcmp(sNetClass, "CObjectDispenser") == 0) - { - - /** - It is, so lets check the owner - */ - if (GetEntDataEnt2(i, g_iOwnerOffset) == client) - { - - /** - It's the clients building, so we blow it up. - */ - SetVariantInt(9999); - AcceptEntityInput(i, "RemoveHealth"); - } - } - } -} \ No newline at end of file diff --git a/Simple Team Balancer/addons/sourcemod/scripting/simple-chatcolors.sp b/Simple Team Balancer/addons/sourcemod/scripting/simple-chatcolors.sp deleted file mode 100644 index 539d057..0000000 --- a/Simple Team Balancer/addons/sourcemod/scripting/simple-chatcolors.sp +++ /dev/null @@ -1,496 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Chat Colors -Description: - Changes the colors of players chat based on config file -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#pragma semicolon 1 -#include -#include - -#define PLUGIN_VERSION "0.9.0.$Rev$" - -#define CHAT_SYMBOL '@' -#define TRIGGER_SYMBOL1 '!' -#define TRIGGER_SYMBOL2 '/' -#define CHAT_MAX_MESSAGE_LENGTH 1024 - -new Handle:g_hDebugCvar = INVALID_HANDLE; -new Handle:g_aGroupNames = INVALID_HANDLE; -new Handle:g_aGroupFlag = INVALID_HANDLE; -new Handle:g_aGroupNameColor = INVALID_HANDLE; -new Handle:g_aGroupTextColor = INVALID_HANDLE; - -new bool:g_bDebug = false; - -new g_iArraySize; - -new g_aPlayerColorIndex[MAXPLAYERS + 1] = { -1, ... }; - -public Plugin:myinfo = -{ - name = "Simple Chat Colors", - author = "Simple Plugins", - description = "Changes the colors of players chat based on config file.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -/** -Sourcemod callbacks -*/ -public OnPluginStart() -{ - - /** - Need to create all of our console variables. - */ - CreateConVar("sm_chatcolors_version", PLUGIN_VERSION, "Simple Chat Colors", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - g_hDebugCvar = CreateConVar("sm_chatcolors_debug", "1", "Enable/Disable debugging information"); - - /** - Hook console variables - */ - HookConVarChange(g_hDebugCvar, ConVarSettingsChanged); - - /** - Need to register the commands we are going to use - */ - RegConsoleCmd("say", Command_Say); - RegConsoleCmd("say_team", Command_SayTeam); - RegAdminCmd("sm_reloadcolorsconfig", Command_Reload, ADMFLAG_GENERIC, "Reloads settings from config file"); - - /** - Create the arrays - */ - g_aGroupNames = CreateArray(256, 1); - g_aGroupFlag = CreateArray(15, 1); - g_aGroupNameColor = CreateArray(15, 1); - g_aGroupTextColor = CreateArray(15, 1); - - /** - Load the admins and colors from the config - */ - LoadAdminsAndColorsFromConfig(); - g_iArraySize = GetArraySize(g_aGroupNames); -} - -public OnConfigsExecuted() -{ - g_bDebug = GetConVarBool(g_hDebugCvar); - ReloadConfigFile(); -} - -public OnClientPostAdminCheck(client) -{ - - /** - Check the client to see if they are a admin - */ - CheckAdmin(client); -} - -public OnClientDisconnect(client) -{ - g_aPlayerColorIndex[client] = -1; -} - -/** -Commands -*/ -public Action:Command_Say(client, args) -{ - - /** - Make sure we are enabled. - */ - if (client == 0 || IsChatTrigger()) - { - return Plugin_Continue; - } - - if (g_aPlayerColorIndex[client] != -1) - { - - /** - The client is, so get the chat message and strip it down. - */ - decl String:sArg[CHAT_MAX_MESSAGE_LENGTH], - String:sChatMsg[CHAT_MAX_MESSAGE_LENGTH]; - - new bool:bAlive = IsPlayerAlive(client); - - GetCmdArgString(sArg, sizeof(sArg)); - StripQuotes(sArg); - TrimString(sArg); - new startidx; - if (sArg[strlen(sArg)-1] == '"') - { - sArg[strlen(sArg)-1] = '\0'; - startidx = 1; - } - - /** - Bug out if they are using the admin chat symbol (admin chat). If we are in CSS it may not find all the triggers, so we double check. - */ - if (sArg[startidx] == CHAT_SYMBOL || sArg[startidx] == TRIGGER_SYMBOL1 || sArg[startidx] == TRIGGER_SYMBOL2) - { - return Plugin_Continue; - } - - /** - Log the message for hlstatsx and other things. - */ - new iUserID = GetClientUserId(client); - decl String:sAuthID[64]; - GetClientAuthString(client, sAuthID, sizeof(sAuthID)); - LogToGame("\"%N<%i><%s><>\" say \"%s\"", client, iUserID, sAuthID, sArg); - - /** - Format the message. - */ - FormatMessage(client, 0, bAlive, sChatMsg, sArg, g_aPlayerColorIndex[client]); - - /** - Send the message. - */ - //SayText2(0, client, sChatMsg); - CPrintToChatAll(sChatMsg); - - /** - We are done, bug out, and stop the original chat message. - */ - return Plugin_Stop; - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Command_SayTeam(client, args) -{ - - /** - Make sure we are enabled. - */ - if (client == 0 || IsChatTrigger()) - { - return Plugin_Continue; - } - - /** - Check the client to see if they are a admin - */ - if (g_aPlayerColorIndex[client] != -1) - { - - /** - The client is, so get the chat message and strip it down. - */ - decl String:sArg[CHAT_MAX_MESSAGE_LENGTH], - String:sChatMsg[CHAT_MAX_MESSAGE_LENGTH]; - - new bool:bAlive = IsPlayerAlive(client); - new iCurrentTeam = GetClientTeam(client); - - GetCmdArgString(sArg, sizeof(sArg)); - StripQuotes(sArg); - TrimString(sArg); - new startidx; - if (sArg[strlen(sArg)-1] == '"') - { - sArg[strlen(sArg)-1] = '\0'; - startidx = 1; - } - - /** - Bug out if they are using the admin chat symbol (admin chat). - */ - if (sArg[startidx] == CHAT_SYMBOL || sArg[startidx] == TRIGGER_SYMBOL1 || sArg[startidx] == TRIGGER_SYMBOL2) - { - return Plugin_Continue; - } - - /** - Log the message for hlstatsx and other things. - */ - new iUserID = GetClientUserId(client); - decl String:sAuthID[64]; - GetClientAuthString(client, sAuthID, sizeof(sAuthID)); - LogToGame("\"%N<%i><%s><>\" say_team \"%s\"", client, iUserID, sAuthID, sArg); - - /** - Format the message. - */ - FormatMessage(client, iCurrentTeam, bAlive, sChatMsg, sArg, g_aPlayerColorIndex[client]); - - /** - Send the message to the same team - */ - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == iCurrentTeam) - { - CPrintToChat(client, sChatMsg); - } - } - - /** - We are done, bug out, and stop the original chat message. - */ - return Plugin_Stop; - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Command_Reload(client, args) -{ - ReloadConfigFile(); - return Plugin_Handled; -} - -/** -Stock Functions -*/ -stock LoadAdminsAndColorsFromConfig() -{ - - /** - Make sure the config file is here and load it up - */ - new String:sConfigFile[256]; - BuildPath(Path_SM, sConfigFile, sizeof(sConfigFile), "configs/simple-chatcolors.cfg"); - if (!FileExists(sConfigFile)) - { - - /** - Config file doesn't exists, stop the plugin - */ - LogError("[SCC] Simple Chat Colors is not running! Could not find file %s", sConfigFile); - SetFailState("Could not find file %s", sConfigFile); - } - - /** - Create the arrays and variables - */ - new String:sGroupName[256]; - new String:sGroupFlag[15]; - new String:sGroupNameColor[15]; - new String:sGroupTextColor[15]; - - - /** - Load config file as a KeyValues file - */ - new Handle:kvChatColors = CreateKeyValues("admin_colors"); - FileToKeyValues(kvChatColors, sConfigFile); - - if (!KvGotoFirstSubKey(kvChatColors)) - { - return; - } - - /** - Load up all the groups in the file - */ - do - { - - /** - Get the section name; should be the "group" name - */ - KvGetSectionName(kvChatColors, sGroupName, sizeof(sGroupName)); - - - /** - Get the flags and colors - */ - KvGetString(kvChatColors, "flag", sGroupFlag, sizeof(sGroupFlag)); - KvGetString(kvChatColors, "namecolor", sGroupNameColor, sizeof(sGroupNameColor)); - KvGetString(kvChatColors, "textcolor", sGroupTextColor, sizeof(sGroupTextColor)); - - if (g_bDebug) - { - LogMessage("Group Name/SteamID: %s", sGroupName); - LogMessage("Flag String: %s", sGroupFlag); - LogMessage("Color on name: %s", sGroupNameColor); - LogMessage("Color of text: %s", sGroupTextColor); - } - - /** - Push the values to the arrays - */ - PushArrayString(g_aGroupNames, sGroupName); - PushArrayString(g_aGroupFlag, sGroupFlag); - PushArrayString(g_aGroupNameColor, sGroupNameColor); - PushArrayString(g_aGroupTextColor, sGroupTextColor); - } while (KvGotoNextKey(kvChatColors)); - - /** - Close our handle - */ - CloseHandle(kvChatColors); -} - -stock ReloadConfigFile() -{ - - /** - Clear the array - */ - ClearArray(g_aGroupNames); - ClearArray(g_aGroupFlag); - ClearArray(g_aGroupNameColor); - ClearArray(g_aGroupTextColor); - - /** - Load the admins, groups, and colors from the config - */ - LoadAdminsAndColorsFromConfig(); - g_iArraySize = GetArraySize(g_aGroupNames); - - /** - Recheck all the online players for assigned colors - */ - for (new index = 1; index <= MaxClients; index++) - { - if (IsClientConnected(index) && IsClientInGame(index)) - { - CheckAdmin(index); - } - } -} - -stock CheckAdmin(client) -{ - new String:sFlags[15]; - new String:sClientSteamID[64]; - new iGroupFlags; - new iFlags; - new iIndex = -1; - - /** - Look for a steamid first - */ - GetClientAuthString(client, sClientSteamID, sizeof(sClientSteamID)); - iIndex = FindStringInArray(g_aGroupNames, sClientSteamID); - if (iIndex != -1) - { - g_aPlayerColorIndex[client] = iIndex; - } - - /** - Didn't find one, check flags - */ - else - { - /** - Search for flag in groups - */ - - iFlags = GetUserFlagBits(client); - for (iIndex = 0; iIndex < g_iArraySize; iIndex++) - { - GetArrayString(g_aGroupFlag, iIndex, sFlags, sizeof(sFlags)); - iGroupFlags = ReadFlagString(sFlags); - if (iFlags & iGroupFlags) - { - g_aPlayerColorIndex[client] = iIndex; - break; - } - } - } - - if (g_bDebug) - { - PrintToChatAll("SteamID: %s", sClientSteamID); - PrintToChatAll("Array Index: %i", iIndex); - PrintToChatAll("Flag String: %s", sFlags); - PrintToChatAll("Flag Bits of Client: %i", iFlags); - PrintToChatAll("Flag Bits of Group: %i", iGroupFlags); - } -} - -stock FormatMessage(iClient, iTeam, bool:bAlive, String:sChatMsg[], const Sting:sMessage[], iArrayIndex) -{ - decl String:sDead[10], - String:sTeam[10], - String:sClientName[64]; - - GetClientName(iClient, sClientName, sizeof(sClientName)); - - if (iTeam != 0) - { - Format(sTeam, sizeof(sTeam), "(TEAM) "); - } - else - { - Format(sTeam, sizeof(sTeam), ""); - } - if (bAlive) - { - Format(sDead, sizeof(sDead), ""); - } - else - { - Format(sDead, sizeof(sDead), "*DEAD* "); - } - - new String:sNameColor[15]; - new String:sTextColor[15]; - GetArrayString(g_aGroupNameColor, iArrayIndex, sNameColor, sizeof(sNameColor)); - GetArrayString(g_aGroupTextColor, iArrayIndex, sTextColor, sizeof(sTextColor)); - - Format(sChatMsg, CHAT_MAX_MESSAGE_LENGTH, "{default}%s%s%s%s {default}: %s%s", sDead, sTeam, sNameColor, sClientName, sTextColor, sMessage); -} - -/** -Adjust the settings if a convar was changed -*/ -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (StringToInt(newValue) == 1) - { - g_bDebug = true; - } - else - { - g_bDebug = false; - } -} \ No newline at end of file diff --git a/Simple Team Balancer/addons/sourcemod/scripting/simple-donatorbenefits.sp b/Simple Team Balancer/addons/sourcemod/scripting/simple-donatorbenefits.sp deleted file mode 100644 index e3f6845..0000000 --- a/Simple Team Balancer/addons/sourcemod/scripting/simple-donatorbenefits.sp +++ /dev/null @@ -1,1312 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Donator Benefits -Description: - Provides donator benefits to players -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include -#include - -#define PLUGIN_VERSION "1.1.$Rev$" - -#define CHAT_SYMBOL '@' -#define CHAT_MAX_MESSAGE_LENGTH 1024 - -enum PlayerData -{ - bool:bIsDonator, - bool:bQueue, - bool:bImmune, - iHealthCount, - iNewTeam -}; - -/** - Public convar handles - */ -new Handle:sdb_enabled = INVALID_HANDLE; -new Handle:sdb_donationflag = INVALID_HANDLE; -new Handle:sdb_soundfile = INVALID_HANDLE; -new Handle:sdb_joinsound_enabled = INVALID_HANDLE; -new Handle:sdb_joinpubmsg_enabled = INVALID_HANDLE; -new Handle:sdb_joinprivmsg_enabled = INVALID_HANDLE; -new Handle:sdb_chatcolors_enabled = INVALID_HANDLE; -new Handle:sdb_immunity_enabled = INVALID_HANDLE; -new Handle:sdb_ubercharge_enabled = INVALID_HANDLE; -new Handle:sdb_givehealth_enabled = INVALID_HANDLE; -new Handle:sdb_nofalldmg_enabled = INVALID_HANDLE; -new Handle:sdb_fastheavy_enabled = INVALID_HANDLE; -new Handle:sdb_swapteam_enabled = INVALID_HANDLE; -new Handle:sdb_chatcolor = INVALID_HANDLE; -new Handle:sdb_uberlevel = INVALID_HANDLE; -new Handle:sdb_healthcount = INVALID_HANDLE; -new Handle:sdb_healthbonus = INVALID_HANDLE; -new Handle:sdb_heavymultiplier = INVALID_HANDLE; - -/** -Create global enable/disable bools so we don't have to check the console variable on every call -*/ -new bool:g_bIsEnabled = true; -new bool:g_bIsJoinSoundEnabled = true; -new bool:g_bIsJoinPubMsgEnabled = true; -new bool:g_bIsJoinPrivMsgEnabled = true; -new bool:g_bIsChatColorsEnabled = true; -new bool:g_bIsImmuntyEnabled = true; -new bool:g_bIsUberChargeEnabled = true; -new bool:g_bIsGiveHealthEnabled = true; -new bool:g_bIsNoFallDmgEnabled = true; -new bool:g_bIsFastHeayEnabled = true; -new bool:g_bIsSwapTeamEnabled = true; - -/** - Player arrays - */ -new g_aPlayers[MAXPLAYERS + 1][PlayerData]; - - -/** -Rest of the globals -*/ -new bool:g_bRoundEnd = false; -new String:g_sCharDonatorFlag[5]; -new String:g_sSoundFile[PLATFORM_MAX_PATH]; -new String:g_sChatColor[11]; -new g_iHealthBonus; -new g_iHealthCount; -new g_iClassMaxHealth[TFClassType] = {0, 125, 125, 200, 175, 150, 300, 175, 125, 125}; -new g_fClassMaxSpeed[TFClassType] = {0, 400, 300, 240, 280, 320, 230, 300, 300, 300}; -new Float:g_fHeavyMultiplier = 0.0; -new Float:g_fUberLevel = 0.0; - -public Plugin:myinfo = -{ - name = "Simple Donation Benefits", - author = "Simple Plugins", - description = "Gives donators benefits to players", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -} - -public OnPluginStart() -{ - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[SDB] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_connect", HookPlayerSpawn, EventHookMode_Pre); - HookEvent("player_spawn", HookPlayerSpawn, EventHookMode_Post); - HookEvent("player_death", HookPlayerDeath, EventHookMode_Post); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Post); - switch (g_CurrentMod) - { - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - HookEvent("player_changeclass", HookPlayerClass, EventHookMode_Post); - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_Post); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - - /** - Create console variables - */ - CreateConVar("sdb_version", PLUGIN_VERSION, "Simple Donation Benefits", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - sdb_enabled = CreateConVar("sdb_enabled", "1", "Enable/Disable Simple Donation Benefits"); - sdb_donationflag = CreateConVar("sdb_donationflag", "a", "Flag ALREADY given to donators. Must be in char format"); - - /** - Create the enable/disable donator console variables - */ - sdb_joinsound_enabled = CreateConVar("sdb_joinsound_enabled", "1", "Enable/Disable donator join sound"); - sdb_joinpubmsg_enabled = CreateConVar("sdb_joinpubmsg_enabled", "1", "Enable/Disable public donator join message (replaces: as connected)"); - sdb_joinprivmsg_enabled = CreateConVar("sdb_joinprivmsg_enabled", "1", "Enable/Disable private donator join message (sent only to donator)"); - sdb_chatcolors_enabled = CreateConVar("sdb_chatcolors_enabled", "1", "Enable/Disable donator chat colors"); - sdb_immunity_enabled = CreateConVar("sdb_immunity_enabled", "1", "Enable/Disable donator round end immunity"); - sdb_ubercharge_enabled = CreateConVar("sdb_ubercharge_enabled", "1", "Enable/Disable donator medics starting with ubercharge"); - sdb_givehealth_enabled = CreateConVar("sdb_givehealth_enabled", "1", "Enable/Disable donator instant health bonus"); - sdb_nofalldmg_enabled = CreateConVar("sdb_nofalldmg_enabled", "1", "Enable/Disable no fall damage for donators"); - sdb_fastheavy_enabled = CreateConVar("sdb_fastheavy_enabled", "1", "Enable/Disable donator heavies moving faster while spinning"); - sdb_swapteam_enabled = CreateConVar("sdb_swampteam_enabled", "1", "Enable/Disable donator swap team ability"); - - /** - Create the donator setting console variables - */ - sdb_soundfile = CreateConVar("sdb_soundfile", "custom/donatorjoin.mp3", "The location of sound file"); - sdb_chatcolor = CreateConVar("sdb_chatcolor", "green", "Color to use for donator chat. Valid colors are green and lightgreen"); - sdb_uberlevel = CreateConVar("sdb_uberlevel", "0.5", "Uberlevel to give donator medic at spawn. 1.0 = full uber", _, true, 0.0, true, 1.0); - sdb_healthcount = CreateConVar("sdb_healthcount", "1", "Number of times a donator can use use instant health per life"); - sdb_healthbonus = CreateConVar("sdb_healthbonus", "100", "The amount of health to heal the donator"); - sdb_heavymultiplier = CreateConVar("sdb_heavyspeed", "0.5", "The speed multiplier for the fast heavy. Based on running speed. 1.0 = running speed. (Game Default is 0.20)", _, true, 0.0, true, 1.0); - - /** - Hook dukehacks calls - */ - dhAddClientHook(CHK_TakeDamage, Hacks_TakeDamageHook); - dhAddClientHook(CHK_PreThink, Hacks_PreThinkHook); - - /** - Hook the console variables if they change - */ - HookConVarChange(sdb_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_donationflag, ConVarSettingsChanged); - HookConVarChange(sdb_joinsound_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_joinpubmsg_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_joinprivmsg_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_chatcolors_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_immunity_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_ubercharge_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_givehealth_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_nofalldmg_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_swapteam_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_fastheavy_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_soundfile, ConVarSettingsChanged); - HookConVarChange(sdb_chatcolor, ConVarSettingsChanged); - HookConVarChange(sdb_uberlevel, ConVarSettingsChanged); - HookConVarChange(sdb_healthcount, ConVarSettingsChanged); - HookConVarChange(sdb_healthbonus, ConVarSettingsChanged); - HookConVarChange(sdb_heavymultiplier, ConVarSettingsChanged); - - /** - Register the commands - */ - RegConsoleCmd("sm_swapteams", Command_SwapTeam, "sm_swapteams <[0]instant/[1]queued>: Swaps your team to the other team"); - RegConsoleCmd("sm_ihealth", Command_InstantHealth, "sm_ihealth: Gives you a instant health pack"); - RegAdminCmd("sm_teaser", Command_Teaser, ADMFLAG_GENERIC,"sm_teaser <[0]add/[1]remove>: Gives temporary donator privilages to a player"); - RegConsoleCmd("say", Command_Say); - - RegConsoleCmd("sm_test", Command_TEST); - - /** - Load the translations - */ - LoadTranslations("common.phrases"); - LoadTranslations("simpledonatorbenefits.phrases"); - - /** - Load or create the config file - */ - AutoExecConfig(true, "plugin.simpledonatorbenefits"); - LogAction(0, -1, "[SDB] Simple Donator Benefits is loaded."); -} - -public OnAllPluginsLoaded() -{ - //something -} - -public OnLibraryRemoved(const String:name[]) -{ - //something -} - -public OnConfigsExecuted() -{ - /** - Load up all the variable defaults - */ - LoadUpVariables(); - - /** - If the join sound is enabled, prep the sound files - */ - if (g_bIsJoinSoundEnabled) - PrepSoundFile(); - - /** - Log our activity - */ - if (g_bIsEnabled) - LogAction(0, -1, "Simple Donation Benefits is ENABLED"); - else - LogAction(0, -1, "Simple Donation Benefits is DISABLED"); -} - -public OnClientPostAdminCheck(client) -{ - - /** - Check if the client is a donator - */ - if (SM_IsValidAdmin(client, g_sCharDonatorFlag)) - { - - /** - They are, so we set the player array to true and start a timer for the sound or add - */ - g_aPlayers[client][bIsDonator] = true; - if (g_bIsJoinSoundEnabled || g_bIsJoinPrivMsgEnabled) - { - CreateTimer(10.0, Timer_DonatorJoined, client, TIMER_FLAG_NO_MAPCHANGE); - } - } - else - { - /** - They aren't, so we set the player array to false - */ - g_aPlayers[client][bIsDonator] = false; - } -} - -public OnClientDisconnect_Post(client) -{ - - /** - Clean up the player variables - */ - CleanUpPlayer(client); -} - -public Action:Command_SwapTeam(client, args) -{ - - /** - Make sure we are enabled - */ - if (!g_bIsEnabled || !g_bIsSwapTeamEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the command is not started by the server - */ - if (client == 0) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure the player is a donator - */ - if (!g_aPlayers[client][bIsDonator]) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Lets make sure the client is one a team we can swap. - If he is we set the global array to the opposite team. - */ - new iTeam = GetClientTeam(client); - if (iTeam == g_aCurrentTeams[Team1]) - { - g_aPlayers[client][iNewTeam] = g_aCurrentTeams[Team2]; - } - else if (iTeam == g_aCurrentTeams[Team2]) - { - g_aPlayers[client][iNewTeam] = g_aCurrentTeams[Team1]; - } - else - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "InValidTeam", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check to see if we have command arguments. - */ - if (GetCmdArgs()) - { - - /** - We do, so lets get it and see if the client wants to be switched instantly or queued for death. - */ - decl String:sArg[5]; - GetCmdArg(1, sArg, sizeof(sArg)); - new iWantsQue = StringToInt(sArg); - if (iWantsQue && !g_aPlayers[client][bQueue]) - { - - /** - He wants the que and isn't already in it, set the global array. - */ - g_aPlayers[client][bQueue] = true; - ReplyToCommand(client, "\x01\x04[STM]\x01 %T", "PlayerQueue", LANG_SERVER); - } - else if (!iWantsQue) - { - - /** - He wants to be switched right now, lets call the stock function. - */ - SM_MovePlayer(client, g_aPlayers[client][iNewTeam]); - } - } - else - { - - /** - There are no command arguments so we build and display the swap menu. - */ - new Handle:hPlayerMenu = BuildSwapModeMenu(); - DisplayMenu(hPlayerMenu, client, MENU_TIME_FOREVER); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_InstantHealth(client, args) -{ - - /** - Make sure we are enabled - */ - if (!g_bIsEnabled || !g_bIsGiveHealthEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the command is not started by the server - */ - if (client == 0) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure the player is a donator - */ - if (!g_aPlayers[client][bIsDonator]) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check health count to see if the player has reached the max - */ - if (g_aPlayers[client][iHealthCount] >= g_iHealthCount) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "ReachedCount", LANG_SERVER); - return Plugin_Handled; - } - - /** - Get the class of the player and the max health for that class - */ - new iHealth = GetClientHealth(client); - new TFClassType:PlayerClass = TF2_GetPlayerClass(client); - new iMaxHealth = g_iClassMaxHealth[PlayerClass]; - - /** - Check to see if the player is at the max health of the class - */ - if (iHealth >= iMaxHealth) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "AtMaxHealth", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check the current health - */ - if (iHealth + g_iHealthBonus >= iMaxHealth) - { - - /** - Raise them to max health if the current health + bonus would go above it - */ - SetEntityHealth(client, iMaxHealth); - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "ToMaxHealth", LANG_SERVER); - } - else - { - - /** - Give them the instant health bonus - */ - SetEntityHealth(client, iHealth + g_iHealthBonus); - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "HealthBonus", LANG_SERVER); - } - - /** - Increase the count - */ - g_aPlayers[client][iHealthCount] += 1; - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_Teaser(client, args) -{ - - /** - Make sure we are enabled - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Check to see if we have command arguments. - */ - new iCmdArgs = GetCmdArgs(); - if (iCmdArgs == 0) - { - - /** - We don't so display the player menu. - */ - new Handle:hPlayerMenu = BuildPlayerMenu(); - DisplayMenu(hPlayerMenu, client, MENU_TIME_FOREVER); - return Plugin_Handled; - } - - /** - We have some arguments, see if we can find the player - */ - decl String:sPlayer[64]; - GetCmdArg(1, sPlayer, sizeof(sPlayer)); - new iTarget = FindTarget(client, sPlayer, true, true); - if (iTarget == -1 || !IsClientInGame(iTarget)) - { - - /** - We don't know who this is, so display the player menu. - */ - new Handle:hPlayerMenu = BuildPlayerMenu(); - DisplayMenu(hPlayerMenu, client, MENU_TIME_FOREVER); - } - else - { - /** - We found the player, see if we are supposed to turn it on or off. - */ - if (iCmdArgs >= 2) - { - decl String:sOn[3]; - GetCmdArg(2, sOn, sizeof(sOn)); - if (StringToInt(sOn)) - { - - /** - Turn temp benefits on. - */ - g_aPlayers[iTarget][bIsDonator] = true; - } - else - { - - /** - Turn temp benefits on. - */ - g_aPlayers[iTarget][bIsDonator] = false; - } - } - else - { - - /** - We don't know what to do, so just turn it on. - */ - g_aPlayers[iTarget][bIsDonator] = true; - } - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_Say(client, args) -{ - - /** - Make sure we are enabled. - */ - if (client == 0 || IsChatTrigger() || !g_bIsChatColorsEnabled || !g_bIsEnabled) - { - return Plugin_Continue; - } - - /** - Check the client to see if they are a donator. - */ - if (g_aPlayers[client][bIsDonator]) - { - - /** - The client is, so get the chat message and strip it down. - */ - decl String:sArg[CHAT_MAX_MESSAGE_LENGTH], - String:sChatMsg[CHAT_MAX_MESSAGE_LENGTH]; - new bool:bAlive = IsPlayerAlive(client); - GetCmdArgString(sArg, sizeof(sArg)); - StripQuotes(sArg); - TrimString(sArg); - new startidx; - if (sArg[strlen(sArg)-1] == '"') - { - sArg[strlen(sArg)-1] = '\0'; - startidx = 1; - } - - /** - Bug out if they are using the admin chat symbol (admin chat). - */ - if (sArg[startidx] == CHAT_SYMBOL) - { - return Plugin_Continue; - } - - /** - Format the message. - */ - FormatMessage(client, 0, bAlive, sChatMsg, sArg); - - /** - Send the message. - */ - SayText2(0, client, sChatMsg); - - /** - We are done, bug out, and stop the original chat message. - */ - return Plugin_Stop; - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Hacks_TakeDamageHook(client, attacker, inflictor, Float:damage, &Float:multiplier, damagetype) -{ - - /** - Make sure we are enabled and the client is a donator. - */ - if (g_bIsEnabled && g_bIsNoFallDmgEnabled && g_aPlayers[client][bIsDonator]) - { - - /** - Check for fall damage. - */ - if (damagetype & DMG_FALL) - { - - /** - Cancel the fall damage and bug out. - */ - multiplier *= 0.0; - return Plugin_Changed; - } - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Hacks_PreThinkHook(client) -{ - - /** - Make sure we are enabled and the client is a donator. - */ - if (!g_bIsEnabled || !g_bIsFastHeayEnabled || !g_aPlayers[client][bIsDonator]) - { - return Plugin_Continue; - } - - /** - Check the players class. We are looking for the heavy. - */ - new TFClassType:PlayerClass = TF2_GetPlayerClass(client); - if (PlayerClass == TFClass_Heavy) - { - - /** - We have a heavy, lets check the weapon. - */ - decl String:sWeaponCurrent[64]; - GetClientWeapon(client, sWeaponCurrent, sizeof(sWeaponCurrent)); - if (StrEqual(sWeaponCurrent, "tf_weapon_minigun", false)) - { - - /** - We have a minigun, check the heavies current weapon state to see if it's spinning. - */ - new iWeapon = GetPlayerWeaponSlot(client, 0); - new iWeaponState = GetEntProp(iWeapon, Prop_Send, "m_iWeaponState"); - if (iWeaponState > 0) - { - - /** - He is spinning, so lets change the heavies speed. - */ - new Float:fMaxSpeed = FloatMul(g_fHeavyMultiplier, float(g_fClassMaxSpeed[PlayerClass])); - SetEntPropFloat(client, Prop_Send, "m_flMaxspeed", fMaxSpeed); - } - } - } - - /** - We are done, bug out. - */ - // use Plugin_Continue (other options are ignored on PreThink hook) - return Plugin_Continue; -} - -public Action:HookPlayerConnect(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (!g_bIsEnabled || !g_bIsJoinPubMsgEnabled || !dontBroadcast) - { - return Plugin_Continue; - } - - /** - Get our event variables and check the client. - */ - new iUserId = GetEventInt(event,"userid"); - new iClient = GetClientOfUserId(iUserId); - if (iClient != 0) - { - - /** - Get the info on the client and format the message. - */ - decl String:sClientName[255], - String:sAuthID[255], - String:sMsg[1024]; - - GetEventString(event, "name", sClientName, sizeof(sClientName)); - GetClientAuthString(iClient, sAuthID, sizeof(sAuthID)); - Format(sMsg, sizeof(sMsg), "%T", "PublicJoinMessage", LANG_SERVER, sClientName); - - /** - Print the message to the clients and do the normal functions. - */ - for (new i = 1; i <= MaxClients; i++) - { - if(IsClientConnected(i) && IsClientInGame(i)) - { - PrintToChat(i,"\x01\x05%s", sMsg); - PrintToConsole(i,"%s has connected.", sClientName); - } - } - LogToGame("\"%s<%d><%s><>\" entered the game", sClientName, iUserId, sAuthID); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public HookPlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled && g_bIsUberChargeEnabled) - { - - /** - Get the event variables and check the class for medic - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - if (TF2_GetPlayerClass(iClient) == TFClass_Medic) - { - - /** - Start a timer to get the medic the uber boost - */ - CreateTimer(0.25, Timer_PlayerUberDelay, iClient, TIMER_FLAG_NO_MAPCHANGE); - } - } -} - -public HookPlayerClass(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled && g_bIsUberChargeEnabled) - { - - /** - Get the event variables and check the class for medic - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - if (TF2_GetPlayerClass(iClient) == TFClass_Medic) - { - - /** - Start a timer to get the medic the uber boost - */ - CreateTimer(0.25, Timer_PlayerUberDelay, iClient, TIMER_FLAG_NO_MAPCHANGE); - } - } -} - -public HookPlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled || g_bIsSwapTeamEnabled) - { - - /** - Get the event variables - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - new String:sWeapon[256]; - GetEventString(event, "weapon", sWeapon, sizeof(sWeapon)); - - /** - Bug out if world killed him. Means he changed team or something - */ - if (StrEqual(sWeapon, "world", false)) - { - g_aPlayers[iClient][bQueue] = false; - return; - } - - /** - If he is queued up, swap him - */ - if (g_aPlayers[iClient][bQueue]) - { - SM_MovePlayer(iClient, g_aPlayers[iClient][iNewTeam]); - } - } -} - -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled || g_bIsSwapTeamEnabled) - { - - /** - Get the event variables - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - - /** - If he is queued up, clear the status - */ - if (g_aPlayers[iClient][bQueue]) - { - g_aPlayers[iClient][bQueue] = false; - } - } -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set our variables. - */ - g_bRoundEnd = false; - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled && g_bIsImmuntyEnabled) - { - - /** - Get rid of their immunity. - */ - ProcessRoundEndImmunity(false); - } -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set our variables. - */ - g_bRoundEnd = true; - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled && g_bIsImmuntyEnabled) - { - - /** - Give them their immunity. - */ - ProcessRoundEndImmunity(true); - } -} - -public Action:Timer_DonatorJoined(Handle:timer, any:client) -{ - - /** - Make sure sounds are enabled. - */ - if (g_bIsEnabled && g_bIsJoinSoundEnabled) - { - EmitSoundToClient(client, g_sSoundFile); - } - - /** - Make sure private messages are enabled. - */ - if (g_bIsJoinPrivMsgEnabled) - { - - /** - Send messages to the client. - */ - decl String:sMsg[1024]; - Format(sMsg, sizeof(sMsg), "%T", "PrivateJoinMessage", LANG_SERVER); - PrintToChat(client,"\x01\x05%s", sMsg); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Timer_PlayerUberDelay(Handle:timer, any:client) -{ - - /** - Make sure the client is still in game. - */ - if (IsClientInGame(client)) - { - - /** - Make sure the client is still a medic. - */ - if (TF2_GetPlayerClass(client) == TFClass_Medic) - { - - /** - Get the medgun weapon index - */ - new iIndex = GetPlayerWeaponSlot(client, 1); - if (iIndex > 0) - { - - /** - Set the uber level with the bonus. - */ - SetEntPropFloat(iIndex, Prop_Send, "m_flChargeLevel", g_fUberLevel); - } - } - } -} - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (convar == sdb_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsEnabled = false; - } - else - { - g_bIsEnabled = true; - } - } - else if (convar == sdb_donationflag) - { - Format(g_sCharDonatorFlag, sizeof(g_sCharDonatorFlag), "%s", newValue); - } - else if (convar == sdb_soundfile) - { - Format(g_sSoundFile, sizeof(g_sSoundFile), "%s", newValue); - } - else if (convar == sdb_joinsound_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsJoinSoundEnabled = false; - } - else - { - g_bIsJoinSoundEnabled = true; - } - } - else if (convar == sdb_joinpubmsg_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsJoinPubMsgEnabled = false; - } - else - { - g_bIsJoinPubMsgEnabled = true; - } - } - else if (convar == sdb_joinprivmsg_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsJoinPrivMsgEnabled = false; - } - else - { - g_bIsJoinPrivMsgEnabled = true; - } - } - else if (convar == sdb_chatcolors_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsChatColorsEnabled = false; - } - else - { - g_bIsChatColorsEnabled = true; - } - } - else if (convar == sdb_immunity_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsImmuntyEnabled = false; - } - else - { - g_bIsImmuntyEnabled = true; - } - } - else if (convar == sdb_ubercharge_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsUberChargeEnabled = false; - } - else - { - g_bIsUberChargeEnabled = true; - } - } - else if (convar == sdb_givehealth_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsGiveHealthEnabled = false; - } - else - { - g_bIsGiveHealthEnabled = true; - } - } - else if (convar == sdb_nofalldmg_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsNoFallDmgEnabled = false; - } - else - { - g_bIsNoFallDmgEnabled = true; - } - } - else if (convar == sdb_fastheavy_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsFastHeayEnabled = false; - } - else - { - g_bIsFastHeayEnabled = true; - } - } - else if (convar == sdb_swapteam_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsSwapTeamEnabled = false; - } - else - { - g_bIsSwapTeamEnabled = true; - } - } - else if (convar == sdb_chatcolor) - { - Format(g_sChatColor, sizeof(g_sChatColor), "%s", newValue); - } - else if (convar == sdb_uberlevel) - { - g_fUberLevel = StringToFloat(newValue); - } - else if (convar == sdb_healthcount) - { - g_iHealthCount = StringToInt(newValue); - } - else if (convar == sdb_healthbonus) - { - g_iHealthBonus = StringToInt(newValue); - } - else if (convar == sdb_heavymultiplier) - { - g_fHeavyMultiplier = StringToFloat(newValue); - } -} - -stock LoadUpVariables() -{ - g_bIsEnabled = GetConVarBool(sdb_enabled); - g_bIsJoinSoundEnabled = GetConVarBool(sdb_enabled); - g_bIsJoinPubMsgEnabled = GetConVarBool(sdb_enabled); - g_bIsJoinPrivMsgEnabled = GetConVarBool(sdb_enabled); - g_bIsChatColorsEnabled = GetConVarBool(sdb_enabled); - g_bIsImmuntyEnabled = GetConVarBool(sdb_enabled); - g_bIsUberChargeEnabled = GetConVarBool(sdb_enabled); - g_bIsGiveHealthEnabled = GetConVarBool(sdb_enabled); - g_bIsNoFallDmgEnabled = GetConVarBool(sdb_enabled); - g_bIsFastHeayEnabled = GetConVarBool(sdb_enabled); - g_bIsSwapTeamEnabled = GetConVarBool(sdb_enabled); - GetConVarString(sdb_donationflag, g_sCharDonatorFlag, sizeof(g_sCharDonatorFlag)); - GetConVarString(sdb_soundfile, g_sSoundFile, sizeof(g_sSoundFile)); - GetConVarString(sdb_chatcolor, g_sChatColor, sizeof(g_sChatColor)); - g_bRoundEnd = false; - g_iHealthBonus = GetConVarInt(sdb_healthbonus); - g_iHealthCount = GetConVarInt(sdb_healthcount); - g_fHeavyMultiplier = GetConVarFloat(sdb_heavymultiplier); - g_fUberLevel = GetConVarFloat(sdb_uberlevel); -} - -stock PrepSoundFile() -{ - decl String:buffer[PLATFORM_MAX_PATH]; - PrecacheSound(g_sSoundFile, true); - Format(buffer, sizeof(buffer), "sound/%s", g_sSoundFile); - AddFileToDownloadsTable(buffer); -} - -stock CleanUpPlayer(client) -{ - g_aPlayers[client][bIsDonator] = false; - g_aPlayers[client][bQueue] = false; - g_aPlayers[client][bImmune] = false; - g_aPlayers[client][iNewTeam] = 0; - g_aPlayers[client][iHealthCount] = 0; -} - -stock ProcessRoundEndImmunity(bool:give) -{ - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][bIsDonator]) - { - if (give) - { - SetEntProp(i, Prop_Data, "m_takedamage", 0, 1); - g_aPlayers[i][bImmune] = true; - } - else - { - SetEntProp(i, Prop_Data, "m_takedamage", 2, 1); - g_aPlayers[i][bImmune] = false; - } - } - } -} - -stock FormatMessage(iClient, iTeam, bool:bAlive, String:sChatMsg[], const Sting:sMessage[]) -{ - decl String:sDead[10], - String:sTeam[10], - String:sClientName[64]; - GetClientName(iClient, sClientName, sizeof(sClientName)); - if (iTeam != 0) - Format(sTeam, sizeof(sTeam), "(TEAM) "); - else - Format(sTeam, sizeof(sTeam), ""); - if (bAlive) - Format(sDead, sizeof(sDead), ""); - else - Format(sDead, sizeof(sDead), "*DEAD* "); - if (StrContains(g_sChatColor, "light", false) == -1) - Format(sChatMsg, CHAT_MAX_MESSAGE_LENGTH, "\x01%s%s\x03%s \x01: \x05%s", sDead, sTeam, sClientName, sMessage); - else - Format(sChatMsg, CHAT_MAX_MESSAGE_LENGTH, "\x01%s%s\x03%s \x01: \x04%s", sDead, sTeam, sClientName, sMessage); -} - -stock SayText2(target, author, const String:message[]) -{ - new Handle:hBf; - if (target == 0) - hBf = StartMessageAll("SayText2"); - else - hBf = StartMessageOne("SayText2", target); - if (hBf != INVALID_HANDLE) - { - BfWriteByte(hBf, author); - BfWriteByte(hBf, true); - BfWriteString(hBf, message); - EndMessage(); - } -} - -stock ProcessAdmins() -{ - for (new i = 1; i <= MaxClients; i++) - { - if (SM_IsValidAdmin(i, g_sCharDonatorFlag)) - { - g_aPlayers[i][bDonator] = true; - } - else - { - g_aPlayers[i][bDonator] = false; - } - } -} - -stock ProcessLate() -{ - if (g_bIsEnabled) - { - ProcessAdmins(); - PrepSoundFile(); - if (g_bRoundEnd && g_bIsImmuntyEnabled) - { - ProcessRoundEndImmunity(true); - } - if (!g_bIsImmuntyEnabled) - { - ProcessRoundEndImmunity(false); - } - } - else - { - ProcessRoundEndImmunity(false); - } -} - -public Menu_SwapMode(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, 64); - if (StringToInt(sSelection)) - g_aPlayers[param1][bQueue] = false; - else - g_aPlayers[param1][bQueue] = true; - if (!g_aPlayers[param1][bQueue]) - SM_MovePlayer(param1, g_aPlayers[param1][iNewTeam]); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -public Menu_SelectPlayer(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[256]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - new iTarget = GetClientOfUserId(StringToInt(sSelection)); - if (g_aPlayers[iTarget][bIsDonator]) - g_aPlayers[iTarget][bIsDonator] = false; - else - g_aPlayers[iTarget][bIsDonator] = true; - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -stock Handle:BuildSwapModeMenu() -{ - new Handle:menu = CreateMenu(Menu_SwapMode); - SetMenuTitle(menu, "Select When to Swap:"); - AddMenuItem(menu, "0", "Instantly (Kills)"); - AddMenuItem(menu, "1", "Queue on next death"); - SetMenuExitBackButton(menu, false); - return menu; -} - -stock Handle:BuildPlayerMenu() -{ - new Handle:menu = CreateMenu(Menu_SelectPlayer); - AddTargetsToMenu(menu, 0, true, false); - SetMenuTitle(menu, "Select A Player:"); - SetMenuExitBackButton(menu, true); - return menu; -} - -public Action:Command_TEST(client, args) -{ - -} \ No newline at end of file diff --git a/Simple Team Balancer/addons/sourcemod/scripting/simple-messagesuppression.sp b/Simple Team Balancer/addons/sourcemod/scripting/simple-messagesuppression.sp deleted file mode 100644 index f7725a4..0000000 --- a/Simple Team Balancer/addons/sourcemod/scripting/simple-messagesuppression.sp +++ /dev/null @@ -1,227 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Message Suppression -Description: - Blocks Specific Message Outputs -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include -#include - -#define SUPPRESS_VERSION "1.1.$Rev$" - -public Plugin:myinfo = -{ - name = "Simple Message Suppression", - author = "FlyingMongoose, psychonic", - description = "Blocks Specific Message Outputs", - version = SUPPRESS_VERSION, - url = "http://www.simple-plugins.com/" -} - -new Handle:cvarBlockSpectateMessage; -new Handle:cvarBlockDisconnectMessage; -new Handle:cvarBlockConnectMessage; -new Handle:cvarAdminShowMessages; -new iSpecTeam = 1; - - -public OnPluginStart() -{ - CreateConVar("suppress_version", SUPPRESS_VERSION, _, FCVAR_PLUGIN|FCVAR_NOTIFY|FCVAR_REPLICATED|FCVAR_SPONLY|FCVAR_DONTRECORD); - cvarBlockSpectateMessage = CreateConVar("sm_blockspectatemessage", "1", "If enabled it blocks the join team message if an administrator joins spectator", FCVAR_PLUGIN, true, 0.0, true, 1.0); - cvarBlockDisconnectMessage = CreateConVar("sm_blockdisconnectmessage", "1", "Blocks the disconnect message", FCVAR_PLUGIN, true, 0.0, true, 1.0); - cvarBlockConnectMessage = CreateConVar("sm_blockconnectmessage", "1", "If enabled it blocks the player connection message.", FCVAR_PLUGIN, true, 0.0, true, 1.0); - cvarAdminShowMessages = CreateConVar("sm_adminshowmessages", "1", "Shows disconnect/connect/team join messages for admins only (if disconnect message is set to be blocked)", FCVAR_PLUGIN, true, 0.0, true, 1.0); - HookEvent("player_team", ev_PlayerTeam, EventHookMode_Pre); - HookEvent("player_disconnect", ev_PlayerDisconnect, EventHookMode_Pre); - HookEvent("player_connect", ev_PlayerConnect, EventHookMode_Pre); - - new String:game_folder[64]; - GetGameFolderName(game_folder, sizeof(game_folder)) - - if (StrContains(game_folder, "insurgency", false) != -1) - { - iSpecTeam = 3; - } - else - { - new String:game_description[64]; - GetGameDescription(game_description, sizeof(game_description), true); - if (StrContains(game_description, "Insurgency", false) != -1) - { - iSpecTeam = 3; - } - } - - AutoExecConfig(true, "suppressmessage", "sourcemod"); -} - -public Action:ev_PlayerTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (GetConVarBool(cvarBlockSpectateMessage)) - { - if (!dontBroadcast && !GetEventBool(event, "silent")) - { - new iUserId = GetEventInt(event, "userid"); - new iClient = GetClientOfUserId(iUserId); - new iTeam = GetEventInt(event, "team"); - - if (iTeam == iSpecTeam && GetAdminFlag(GetUserAdmin(iClient), Admin_Kick)) - { - new iOldTeam = GetEventInt(event, "oldteam"); - new bool:bDisconnect = GetEventBool(event, "disconnect"); - new bool:bAutoteam = GetEventBool(event, "autoteam"); - decl String:strName[50]; - GetEventString(event, "name", strName, sizeof(strName)); - - if (iClient != 0) - { - if (GetConVarInt(cvarAdminShowMessages) == 1) - { - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i) && GetUserAdmin(i) != INVALID_ADMIN_ID) - { - PrintToChat(i,"%N joined team Spectator.", iClient); - PrintToConsole(i,"%N joined team Spectator.", iClient); - } - } - } - } - - new Handle:hEvent = CreateEvent("player_team"); - SetEventInt(hEvent, "userid", iUserId); - SetEventInt(hEvent, "team", iTeam); - SetEventInt(hEvent, "oldteam", iOldTeam); - SetEventBool(hEvent, "disconnect", bDisconnect); - SetEventBool(hEvent, "autoteam", bAutoteam); - SetEventBool(hEvent, "silent", true); - SetEventString(hEvent, "name", strName); - - FireEvent(hEvent, true); - - return Plugin_Handled; - } - } - } - return Plugin_Continue; -} -public Action:ev_PlayerConnect(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (GetConVarBool(cvarBlockConnectMessage)) - { - if (!dontBroadcast) - { - decl String:strName[50]; - GetEventString(event, "name", strName, sizeof(strName)); - new iIndex = GetEventInt(event, "index"); - new iUserId = GetEventInt(event, "userid"); - new iClient = GetClientOfUserId(iUserId); - decl String:strNetworkId[50]; - GetEventString(event, "networkid", strNetworkId, sizeof(strNetworkId)); - decl String:strAddress[50]; - GetEventString(event, "address", strAddress, sizeof(strAddress)); - - if (iClient != 0) - { - if (GetConVarInt(cvarAdminShowMessages) == 1) - { - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i) && GetUserAdmin(i) != INVALID_ADMIN_ID) - { - PrintToChat(i,"%N has connected.", iClient); - PrintToConsole(i,"%N has connected.", iClient); - } - } - } - } - - new Handle:hEvent = CreateEvent("player_connect"); - SetEventString(hEvent, "name", strName); - SetEventInt(hEvent, "index", iIndex); - SetEventInt(hEvent, "userid", iUserId); - SetEventString(hEvent, "networkid", strNetworkId); - SetEventString(hEvent, "address", strAddress); - - FireEvent(hEvent, true); - - return Plugin_Handled; - } - } - return Plugin_Continue; -} -public Action:ev_PlayerDisconnect(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (GetConVarBool(cvarBlockDisconnectMessage)) - { - if (!dontBroadcast) - { - new iUserId = GetEventInt(event, "userid"); - new iClient = GetClientOfUserId(iUserId); - decl String:strReason[50]; - GetEventString(event, "reason", strReason, sizeof(strReason)); - decl String:strName[50]; - GetEventString(event, "name", strName, sizeof(strName)); - decl String:strNetworkId[50]; - GetEventString(event, "networkid", strNetworkId, sizeof(strNetworkId)); - - if (iClient != 0) - { - if (GetConVarInt(cvarAdminShowMessages) == 1) - { - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i) && GetUserAdmin(i) != INVALID_ADMIN_ID) - { - PrintToChat(i, "%N has left the server.", iClient); - PrintToConsole(i, "Dropped %N from server (Disconnect by user.)", iClient); - } - } - } - } - - new Handle:hEvent = CreateEvent("player_disconnect"); - SetEventInt(hEvent, "userid", iUserId); - SetEventString(hEvent, "reason", strReason); - SetEventString(hEvent, "name", strName); - SetEventString(hEvent, "networkid", strNetworkId); - - FireEvent(hEvent, true); - - return Plugin_Handled; - } - } - - return Plugin_Continue; -} \ No newline at end of file diff --git a/Simple Team Balancer/addons/sourcemod/scripting/simple-plugins.sp b/Simple Team Balancer/addons/sourcemod/scripting/simple-plugins.sp deleted file mode 100644 index 4462b41..0000000 --- a/Simple Team Balancer/addons/sourcemod/scripting/simple-plugins.sp +++ /dev/null @@ -1,785 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Plugins -Description: - Core plugin for Simple Plugins project -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#define CORE_PLUGIN_VERSION "1.1.$Rev$" - -#include - -enum e_PlayerInfo -{ - Handle:hForcedTeamPlugin = INVALID_HANDLE, - iForcedTeam = 0, - iBuddy = 0, - bool:bBuddyLocked = false -}; - -new Handle:g_fwdPlayerMoved; -new g_aPlayers[MAXPLAYERS + 1][e_PlayerInfo]; -new bool:g_bTeamsSwitched = false; - -/** -Setting our plugin information. -*/ -public Plugin:myinfo = -{ - name = "Simple Plugins Core Plugin", - author = "Simple Plugins", - description = "Core plugin for Simple Plugins", - version = CORE_PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -public bool:AskPluginLoad(Handle:myself, bool:late, String:error[], err_max) -{ - - /** - Register natives for other plugins - */ - CreateNative("SM_MovePlayer", Native_SM_MovePlayer); - CreateNative("SM_SetForcedTeam", Native_SM_SetForcedTeam); - CreateNative("SM_GetForcedTeam", Native_SM_GetForcedTeam); - CreateNative("SM_ClearForcedTeam", Native_SM_ClearForcedTeam); - CreateNative("SM_GetForcedPlayer", Native_SM_GetForcedPlayer); - CreateNative("SM_AssignBuddy", Native_SM_AssignBuddy); - CreateNative("SM_GetClientBuddy", Native_SM_GetClientBuddy); - CreateNative("SM_LockBuddy", Native_SM_LockBuddy); - CreateNative("SM_IsBuddyLocked", Native_SM_IsBuddyLocked); - CreateNative("SM_ClearBuddy", Native_SM_ClearBuddy); - CreateNative("SM_IsValidAdmin", Native_SM_IsValidAdmin); - CreateNative("SM_IsValidTeam", Native_SM_IsValidTeam); - RegPluginLibrary("simpleplugins"); - return true; -} - -public OnPluginStart() -{ - - CreateConVar("ssm_core_pl_ver", CORE_PLUGIN_VERSION, "Simple SourceMod Plugins Core Plugin Version", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - CreateConVar("ssm_core_inc_ver", CORE_INC_VERSION, "Simple SourceMod Plugins Core Include Version", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook some events to control forced players and check extensions - */ - decl String:sExtError[256]; - LogAction(0, -1, "[SSM] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Pre); - switch (g_CurrentMod) - { - case GameType_CSS: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - new iExtStatus = GetExtensionFileStatus("game.cstrike.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SSM] Required extension was not found."); - LogAction(0, -1, "[SSM] Plugin FAILED TO LOAD."); - SetFailState("Required extension was not found."); - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SSM] Required extension is loaded with errors."); - LogAction(0, -1, "[SSM] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SSM] Plugin FAILED TO LOAD."); - SetFailState("Required extension is loaded with errors."); - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SSM] Required extension is loaded."); - } - } - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_PostNoCopy); - HookUserMessage(GetUserMessageId("TextMsg"), UserMessageHook_Class, true); - new iExtStatus = GetExtensionFileStatus("game.tf2.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SSM] Required extension was not found."); - LogAction(0, -1, "[SSM] Plugin FAILED TO LOAD."); - SetFailState("Required extension was not found."); - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SSM] Required extension is loaded with errors."); - LogAction(0, -1, "[SSM] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SSM] Plugin FAILED TO LOAD."); - SetFailState("Required extension is loaded with errors."); - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SSM] Required extension is loaded."); - } - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_PostNoCopy); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - - /** - Load common translations - */ - LoadTranslations ("common.phrases"); - - /** - Create the global forward - */ - g_fwdPlayerMoved = CreateGlobalForward("SM_OnPlayerMoved", ET_Event, Param_Cell, Param_Cell, Param_Cell); -} - -public OnClientDisconnect(client) -{ - - /** - Cleanup clients/players buddy list - */ - if (!IsFakeClient(client)) - { - SM_ClearBuddy(client, true); - SM_LockBuddy(client, false); - } - SM_ClearForcedTeam(client); -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - See if the teams have been switched - */ - if (g_bTeamsSwitched) - { - - /** - Switch the teams the players are forced to - */ - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][iForcedTeam] != 0) - { - if (g_aPlayers[i][iForcedTeam] == g_aCurrentTeams[Team1]) - { - g_aPlayers[i][iForcedTeam] = g_aCurrentTeams[Team2]; - } - else - { - g_aPlayers[i][iForcedTeam] = g_aCurrentTeams[Team1]; - } - } - } - } -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - g_bTeamsSwitched = false; -} - -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get our event variables - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - new iTeam = GetEventInt(event, "team"); - - /** - See if the player is on the wrong team - */ - if (g_aPlayers[iClient][iForcedTeam] != 0 && g_aPlayers[iClient][iForcedTeam] != iTeam) - { - - /** - Move the player back to the forced team - */ - CreateTimer(1.0, Timer_ForcePlayerMove, iClient, TIMER_FLAG_NO_MAPCHANGE); - - /** - If the event was going to be broadcasted, we refire it so it is not broadcasted and stop this one - */ - if (!dontBroadcast) - { - new Handle:hEvent = CreateEvent("player_team"); - SetEventInt(hEvent, "userid", GetEventInt(event, "userid")); - SetEventInt(hEvent, "team", GetEventInt(event, "team")); - SetEventInt(hEvent, "oldteam", GetEventInt(event, "oldteam")); - SetEventBool(hEvent, "disconnect", GetEventBool(event, "disconnect")); - - if (g_CurrentMod == GameType_DOD || g_CurrentMod == GameType_L4D || g_CurrentMod == GameType_TF) - { - new String:sClientName[MAX_NAME_LENGTH + 1]; - GetClientName(client, sClientName, sizeof(sClientName)); - SetEventBool(hEvent, "autoteam", GetEventBool(event, "autoteam")); - SetEventBool(hEvent, "silent", true); - SetEventString(hEvent, "name", sClientName); - FireEvent(hEvent, true); - } - else - { - FireEvent(hEvent, true); - } - return Plugin_Handled; - } - } - return Plugin_Continue; -} - -public Action:UserMessageHook_Class(UserMsg:msg_id, Handle:bf, const players[], playersNum, bool:reliable, bool:init) -{ - new String:sMessage[120]; - BfReadString(bf, sMessage, sizeof(sMessage), true); - if (StrContains(sMessage, "#TF_TeamsSwitched", false) != -1) - { - g_bTeamsSwitched = true; - } - return Plugin_Continue; -} - -public Native_SM_MovePlayer(Handle:plugin, numParams) -{ - - /** - Get and check the client and team - */ - new iClient = GetNativeCell(1); - new iTeam = GetNativeCell(2); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (iTeam != g_aCurrentTeams[Spectator] && iTeam != g_aCurrentTeams[Team1] && iTeam != g_aCurrentTeams[Team2]) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid team %d", iTeam); - } - - MovePlayer(iClient, iTeam); - if (!IsClientObserver(iClient)) - { - RespawnPlayer(iClient); - } - - new fResult; - - Call_StartForward(g_fwdPlayerMoved); - Call_PushCell(plugin); - Call_PushCell(iClient); - Call_PushCell(iTeam); - Call_Finish(fResult); - - if (fResult != SP_ERROR_NONE) - { - return ThrowNativeError(fResult, "Forward failed"); - } - - return fResult; -} - -public Native_SM_SetForcedTeam(Handle:plugin, numParams) -{ - - /** - Get and check the client and team - */ - new iClient = GetNativeCell(1); - new iTeam = GetNativeCell(2); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (iTeam != g_aCurrentTeams[Spectator] && iTeam != g_aCurrentTeams[Team1] && iTeam != g_aCurrentTeams[Team2] && iTeam != g_aCurrentTeams[Unknown]) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid team %d", iTeam); - } - - new bool:bOverRide = GetNativeCell(3) ? true : false; - - if (!bOverRide && g_aPlayers[iClient][hForcedTeamPlugin] != INVALID_HANDLE && plugin != g_aPlayers[iClient][hForcedTeamPlugin]) - { - return false; - } - - g_aPlayers[iClient][hForcedTeamPlugin] = plugin; - g_aPlayers[iClient][iForcedTeam] = iTeam; - return true; -} - -public Native_SM_GetForcedTeam(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - - /** - Get and set the plugin if they want it - */ - new Handle:hPlugin = GetNativeCell(2); - if (hPlugin != INVALID_HANDLE) - { - SetNativeCellRef(2, g_aPlayers[iClient][hForcedTeamPlugin]); - } - - /** - Return the forced team, this could be 0 - */ - return g_aPlayers[iClient][iForcedTeam]; -} - -public Native_SM_ClearForcedTeam(Handle:plugin, numParams) -{ - - /** - Get and check the client and team - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - - g_aPlayers[iClient][hForcedTeamPlugin] = INVALID_HANDLE; - g_aPlayers[iClient][iForcedTeam] = 0; - - return true; -} - -public Native_SM_GetForcedPlayer(Handle:plugin, numParams) -{ - - /** - Get and check the team - */ - new iTeam = GetNativeCell(1); - if (iTeam != g_aCurrentTeams[Spectator] && iTeam != g_aCurrentTeams[Team1] && iTeam != g_aCurrentTeams[Team2]) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid team %d", iTeam); - } - - /** - Start a loop to check for a player on the wrong team - Also make sure the plugin that set the forced team is the plugin that asked - */ - new iPlayer = 0; - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientInGame(i) - && GetClientTeam(i) != g_aPlayers[i][iForcedTeam] - && g_aPlayers[i][iForcedTeam] == iTeam - && g_aPlayers[i][hForcedTeamPlugin] == plugin) - { - iPlayer = i; - break; - } - } - - /** - Return the player we found, this could be 0 - */ - return iPlayer; -} - -public Native_SM_AssignBuddy(Handle:plugin, numParams) -{ - - /** - Get and check the client and player - */ - new iClient = GetNativeCell(1); - new iPlayer = GetNativeCell(2); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (iPlayer < 0 || iPlayer > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid player index (%d)", iPlayer); - } - if (!IsClientConnected(iPlayer)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Player %d is not connected", iPlayer); - } - if (!IsClientInGame(iPlayer)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Player %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Bots are not supported"); - } - - /** - See if we can override his setting - */ - new bool:bOverRide = GetNativeCell(3) ? true : false; - if (!bOverRide) - { - - /** - We can't override, so check if they are locked - */ - if (g_aPlayers[iClient][bBuddyLocked] || g_aPlayers[iPlayer][bBuddyLocked]) - { - - /** - We detected at least 1 lock, so we bug out - */ - return false; - } - } - - /** - Ready to set the buddies - */ - g_aPlayers[iClient][iBuddy] = iPlayer; - g_aPlayers[iPlayer][iBuddy] = iClient; - return true; -} - -public Native_SM_GetClientBuddy(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Bots are not supported"); - } - - /** - Return the players buddy, this could be 0 - */ - return g_aPlayers[iClient][iBuddy]; -} - -public Native_SM_LockBuddy(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - new bool:bSetting = GetNativeCell(2) ? true : false; - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Bots are not supported"); - } - - g_aPlayers[iClient][bBuddyLocked] = bSetting; - return true; -} - -public Native_SM_IsBuddyLocked(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Bots are not supported"); - } - - return g_aPlayers[iClient][bBuddyLocked]; -} - -public Native_SM_ClearBuddy(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Client (%d) is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Bots are not supported"); - } - - /** - Get the clients buddy and see if we can override his setting - */ - new bool:bOverRide = GetNativeCell(2) ? true : false; - new iPlayer = g_aPlayers[iClient][iBuddy]; - - /** - There is no buddy, we don't care about anything else so bug out - */ - if (iPlayer == 0) - { - return true; - } - - /** - We determined he had a buddy, check the override setting - */ - if (!bOverRide) - { - - /** - We can't override, so check if they are locked - */ - if (g_aPlayers[iClient][bBuddyLocked] || g_aPlayers[iPlayer][bBuddyLocked]) - { - - /** - We detected at least 1 lock, so we bug out - */ - return false; - } - } - - /** - Ready to clear the buddies - */ - g_aPlayers[iClient][iBuddy] = 0; - g_aPlayers[iPlayer][iBuddy] = 0; - return true; -} - -public Native_SM_IsValidTeam(Handle:plugin, numParams) -{ - - /** - Get the team - */ - new iTeam = GetNativeCell(1); - - /** - Check the team - */ - if (iTeam == g_aCurrentTeams[Spectator] || iTeam == g_aCurrentTeams[Team1] || iTeam == g_aCurrentTeams[Team2]) - { - return true; - } - return false; -} - -public Native_SM_IsValidAdmin(Handle:plugin, numParams) -{ - /** - Get the client and flags - */ - new iClient = GetNativeCell(1); - decl String:sFlags[15]; - GetNativeString(2, sFlags, sizeof(sFlags)); - new ibFlags = ReadFlagString(sFlags); - - /** - Check the flags - */ - if ((GetUserFlagBits(iClient) & ibFlags) == ibFlags) - { - return true; - } - if (GetUserFlagBits(iClient) & ADMFLAG_ROOT) - { - return true; - } - return false; -} - -public Action:Timer_ForcePlayerMove(Handle:timer, any:iClient) -{ - - MovePlayer(iClient, g_aPlayers[iClient][iForcedTeam]); - - if (g_aPlayers[iClient][iForcedTeam] != g_aCurrentTeams[Spectator]) - { - RespawnPlayer(iClient); - } - - PrintToChat(iClient, "\x01\x04----------------------------------"); - PrintToChat(iClient, "\x01\x04You have been forced to this team."); - PrintToChat(iClient, "\x01\x04----------------------------------"); - - return Plugin_Handled; -} - -stock MovePlayer(iClient, iTeam) -{ - - /** - Change the client's team based on the mod - */ - switch (g_CurrentMod) - { - case GameType_CSS: - { - CS_SwitchTeam(iClient, iTeam); - } - default: - { - ChangeClientTeam(iClient, iTeam); - } - } -} - -stock RespawnPlayer(iClient) -{ - - /** - Respawn the client based on the mod - */ - switch (g_CurrentMod) - { - case GameType_CSS: - { - CS_RespawnPlayer(iClient); - } - case GameType_TF: - { - TF2_RespawnPlayer(iClient); - } - case GameType_INS: - { - FakeClientCommand(iClient, "kill"); - } - default: - { - // - } - } -} diff --git a/Simple Team Balancer/addons/sourcemod/scripting/simple-roundimmunity.sp b/Simple Team Balancer/addons/sourcemod/scripting/simple-roundimmunity.sp deleted file mode 100644 index 5f0bca3..0000000 --- a/Simple Team Balancer/addons/sourcemod/scripting/simple-roundimmunity.sp +++ /dev/null @@ -1,947 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Round Immunity -Description: - Gives admins immunity during certain rounds -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or any later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#pragma semicolon 1 -#include -#include -#undef REQUIRE_EXTENSIONS -#undef AUTOLOAD_EXTENSIONS -#include -#include -#define REQUIRE_EXTENSIONS -#define AUTOLOAD_EXTENSIONS - -#define PLUGIN_VERSION "1.1.$Rev$" -#define SPECTATOR 1 -#define TEAM_RED 2 -#define TEAM_BLUE 3 - -#define COLOR_GREEN 0 -#define COLOR_BLACK 1 -#define COLOR_RED 2 -#define COLOR_BLUE 3 -#define COLOR_TEAM 4 -#define COLOR_RAINBOW 5 -#define COLOR_NONE 6 - -#define PLAYERCOND_SLOWED (1<<0) //1 -#define PLAYERCOND_ZOOMED (1<<1) //2 -#define PLAYERCOND_DISGUISING (1<<2) //4 -#define PLAYERCOND_DISGUISED (1<<3) //8 -#define PLAYERCOND_SPYCLOAK (1<<4) //16 -#define PLAYERCOND_UBERED (1<<5) //32 -#define PLAYERCOND_TELEPORTTRAIL (1<<6) //64 -#define PLAYERCOND_TAUNT (1<<7) //128 -// (1<<8) //256 -// (1<<9) //512 -#define PLAYERCOND_TELEPORTFLASH (1<<10) //1024 -#define PLAYERCOND_KRUBER (1<<11) //2048 -// (1<<12) //4096 -// (1<<13) //8192 -#define PLAYERCOND_BONKED (1<<14) //16384 (blame Neph if it doesn't work) -#define PLAYERCOND_BONKEDORDRINKSLOWDOWN (1<<15) //32768 -#define PLAYERCOND_HEALING (1<<16) //65536 -#define PLAYERCOND_BURNING (1<<17) //131072 -#define PLAYERCOND_FULLYCHARGEDBYMEDIC (1<<18) //262144 - -enum e_Cookies -{ - bEnabled, - iColor, - iMode -}; - -enum e_ColorNames -{ - Green, - Black, - Red, - Blue -}; - -enum e_ColorValues -{ - iRed, - iGreen, - iBlue -}; - -enum e_PlayerData -{ - Handle:hGodModeTimer, - Handle:hColorTimer, - bool:bIsAdmin, - bool:bIsImmune, - iCycleColor -}; - -/** - Global convar handles - */ -new Handle:sri_charadminflag = INVALID_HANDLE; -new Handle:sri_enabled = INVALID_HANDLE; -new Handle:sri_cookie_enabled = INVALID_HANDLE; -new Handle:sri_cookie_color = INVALID_HANDLE; -new Handle:sri_cookie_mode = INVALID_HANDLE; - -/** - Player arrays - */ -new g_aPlayers[MAXPLAYERS + 1][e_PlayerData]; -new g_aClientCookies[MAXPLAYERS + 1][e_Cookies]; - -/** - Global bools - */ -new bool:g_bLoadedLate = false; -new bool:g_bIsEnabled = true; -new bool:g_bRoundEnd = false; -new bool:g_bUseDukehacks = false; -new bool:g_bUseClientprefs = false; - -/** - Global strings/integers/floats - */ -new String:g_sCharAdminFlag[32]; -new g_iColors[e_ColorNames][e_ColorValues]; -new g_iClassMaxHealth[TFClassType] = {0, 125, 125, 200, 175, 150, 300, 175, 125, 125}; - -public Plugin:myinfo = -{ - name = "Simple Round Immunity", - author = "Simple Plugins", - description = "Gives admins immunity during certain rounds", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -} - -bool:AskPluginLoad(Handle:myself, bool:late, String:error[], err_max) -{ - g_bLoadedLate = late; - return true; -} - -public OnPluginStart() -{ - - /** - Create console variables - */ - CreateConVar("sri_version", PLUGIN_VERSION, "Simple Round Immunity", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - sri_enabled = CreateConVar("sri_enabled", "1", "Enable/Disable Admin immunity during certain round."); - sri_charadminflag = CreateConVar("sri_charadminflag", "a", "Admin flag to use for immunity (only one). Must be a in char format."); - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook some events and check extensions - */ - decl String:sExtError[256]; - LogAction(0, -1, "[SRI] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_spawn", HookPlayerSpawn, EventHookMode_Post); - HookEvent("player_hurt", HookPlayerHurt, EventHookMode_Pre); - switch (g_CurrentMod) - { - case GameType_CSS: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - new iExtStatus = GetExtensionFileStatus("game.cstrike.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SRI] Required extension was not found."); - LogAction(0, -1, "[SRI] Plugin FAILED TO LOAD."); - SetFailState("Required extension was not found."); - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SRI] Required extension is loaded with errors."); - LogAction(0, -1, "[SRI] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SRI] Plugin FAILED TO LOAD."); - SetFailState("Required extension is loaded with errors."); - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SRI] Required css extension is loaded."); - } - } - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_PostNoCopy); - HookUserMessage(GetUserMessageId("TextMsg"), UserMessageHook_Class, true); - new iExtStatus = GetExtensionFileStatus("game.tf2.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SRI] Required extension was not found."); - LogAction(0, -1, "[SRI] Plugin FAILED TO LOAD."); - SetFailState("Required extension was not found."); - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SRI] Required extension is loaded with errors."); - LogAction(0, -1, "[SRI] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SRI] Plugin FAILED TO LOAD."); - SetFailState("Required extension is loaded with errors."); - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SRI] Required tf2 extension is loaded."); - } - iExtStatus = GetExtensionFileStatus("dukehacks.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SRI] Dukehacks extension was not found."); - LogAction(0, -1, "[SRI] Plugin continued to load, but that feature will not be used."); - g_bUseDukehacks = false; - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SRI] Dukehacks extension is loaded with errors."); - LogAction(0, -1, "[SRI] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SRI] Plugin continued to load, but that feature will not be used."); - g_bUseDukehacks = false; - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SRI] Dukehacks extension is loaded and will be used."); - g_bUseDukehacks = true; - dhAddClientHook(CHK_TakeDamage, Hacks_TakeDamageHook); - } - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_PostNoCopy); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - /** - Now lets check for client prefs extension - */ - new iExtStatus = GetExtensionFileStatus("clientprefs.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SRI] Client Preferences extension was not found."); - LogAction(0, -1, "[SRI] Plugin continued to load, but that feature will not be used."); - g_bUseClientprefs = false; - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SRI] Client Preferences extension is loaded with errors."); - LogAction(0, -1, "[SRI] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SRI] Plugin continued to load, but that feature will not be used."); - g_bUseClientprefs = false; - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SRI] Client Preferences extension is loaded, checking database."); - if (!SQL_CheckConfig(clientprefs)) - { - LogAction(0, -1, "[SRI] No 'clientprefs' database found. Check your database.cfg file."); - LogAction(0, -1, "[SRI] Plugin continued to load, but Client Preferences will not be used."); - g_bUseClientprefs = false; - } - g_bUseClientprefs = true; - - /** - Deal with client cookies - */ - sri_cookie_enabled = RegClientCookie("bri_client_enabled", "Enable/Disable your immunity during the bonus round.", CookieAccess_Public); - sri_cookie_color = RegClientCookie("bri_client_color", "Color to render when immune.", CookieAccess_Public); - sri_cookie_mode = RegClientCookie("bri_client_mode", "God mode to select", CookieAccess_Public); - SetCookieMenuItem(CookieMenu_TopMenu, sri_cookie_enabled, "Bonus Round Immunity"); - } - - HookConVarChange(sri_enabled, EnabledChanged); - - RegAdminCmd("sm_immunity", Command_Immunity, ADMFLAG_ROOT, "sm_immunity: Gives you immunity"); - - LoadColors(); - - AutoExecConfig(true, "plugin.simpleroundimmunity"); -} - -public OnAllPluginsLoaded() -{ - //something - // need to deal with the unloading of dukehacks, clientprefs, and simpleplugins - // should move hooking the client prefs cookies to a function to make sure they are done post plugin start if ext is loaded late -} - -public OnLibraryRemoved(const String:name[]) -{ - //something - // need to deal with the loading of dukehacks, clientprefs, and simpleplugins -} - -public OnConfigsExecuted() -{ - GetConVarString(sri_charadminflag, g_sCharAdminFlag, sizeof(g_sCharAdminFlag)); - g_bIsEnabled = GetConVarBool(sri_enabled); - g_bRoundEnd = false; -} - -/** - Client events - */ - -public OnClientPostAdminCheck(client) -{ - if (SM_IsValidAdmin(client, g_sCharAdminFlag)) - g_aPlayers[client][bIsAdmin] = true; - else - g_aPlayers[client][bIsAdmin] = false; -} - -public OnClientCookiesCached(client) -{ - decl String:sEnabled[2], String:sColor[4], String:sMode[2]; - GetClientCookie(client, sri_cookie_enabled, sEnabled, sizeof(sEnabled)); - GetClientCookie(client, sri_cookie_color, sColor, sizeof(sColor)); - GetClientCookie(client, sri_cookie_mode, sMode, sizeof(sMode)); - g_aClientCookies[client][bEnabled] = StringToInt(sEnabled); - g_aClientCookies[client][iColor] = StringToInt(sColor); - g_aClientCookies[client][iMode] = StringToInt(sMode); -} - -public OnClientDisconnect(client) -{ - CleanUp(client); -} - -/** - Commands - */ - -public Action:Command_Immunity(client, args) -{ - if (g_aPlayers[client][IsImmune]) - { - DisableImmunity(client); - } - else - { - EnableImmunity(client); - } - return Plugin_Handled; -} - -/** - Event hooks - */ - -public Action:Hacks_TakeDamageHook(client, attacker, inflictor, Float:damage, &Float:multiplier, damagetype) -{ - if (attacker == 0 || attacker >= MaxClients) - { - return Plugin_Continue; - } - if (g_aPlayers[client][IsImmune]) - { - new TFClassType:PlayerClass = TF2_GetPlayerClass(attacker); - if (PlayerClass == TFClass_Spy) - { - multiplier *= 0.0; - return Plugin_Changed; - } - } - return Plugin_Continue; -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - g_bRoundEnd = false; - if (g_bIsEnabled) - { - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][IsImmune]) - { - DisableImmunity(i); - } - } - } -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - g_bRoundEnd = true; - if (g_bIsEnabled) - { - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][bIsAdmin]) - { - EnableImmunity(i); - } - } - } -} - -public HookPlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) -{ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - if (g_bIsEnabled && g_aPlayers[iClient][bIsAdmin] && g_bRoundEnd) - { - EnableImmunity(iClient); - } -} - -public Action:HookPlayerHurt(Handle:event, const String:name[], bool:dontBroadcast) -{ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - if (g_aPlayers[iClient][IsImmune]) - { - SetEntityHealth(iClient, 2000); - return Plugin_Continue; - } - return Plugin_Continue; -} - -/** - Cookie menus - */ - -public CookieMenu_TopMenu(client, CookieMenuAction:action, any:info, String:buffer[], maxlen) -{ - if (action == CookieMenuAction_DisplayOption) - { - //don't think we need to do anything - } - else - { - new Handle:hMenu = CreateMenu(Menu_CookieSettings); - SetMenuTitle(hMenu, "Options (Current Setting)"); - if (g_aClientCookies[client][bEnabled]) - { - AddMenuItem(hMenu, "enable", "Enabled/Disable (Enabled)"); - } - else - { - AddMenuItem(hMenu, "enable", "Enabled/Disable (Disabled)"); - } - if (g_aClientCookies[client][iMode]) - { - AddMenuItem(hMenu, "mode", "Immunity Mode Setting (God Mode)"); - } - else - { - AddMenuItem(hMenu, "mode", "Immunity Mode Setting (Health)"); - } - switch (g_aClientCookies[client][iColor]) - { - case COLOR_GREEN: - { - AddMenuItem(hMenu, "color", "Color (Green)"); - } - case COLOR_BLACK: - { - AddMenuItem(hMenu, "color", "Color (Black)"); - } - case COLOR_RED: - { - AddMenuItem(hMenu, "color", "Color (Red)"); - } - case COLOR_BLUE: - { - AddMenuItem(hMenu, "color", "Color (Blue)"); - } - case COLOR_TEAM: - { - AddMenuItem(hMenu, "color", "Color (Team)"); - } - case COLOR_RAINBOW: - { - AddMenuItem(hMenu, "color", "Color (Rainbow)"); - } - case COLOR_NONE: - { - AddMenuItem(hMenu, "color", "Color (None)"); - } - } - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, client, MENU_TIME_FOREVER); - } -} - -public Menu_CookieSettings(Handle:menu, MenuAction:action, param1, param2) -{ - new client = param1; - if (action == MenuAction_Select) - { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "enable", false)) - { - new Handle:hMenu = CreateMenu(Menu_CookieSettingsEnable); - SetMenuTitle(hMenu, "Enable/Disable Round End Immunity"); - - if (g_aClientCookies[client][bEnabled]) - { - AddMenuItem(hMenu, "enable", "Enable (Set)"); - AddMenuItem(hMenu, "disable", "Disable"); - } - else - { - AddMenuItem(hMenu, "enable", "Enabled"); - AddMenuItem(hMenu, "disable", "Disable (Set)"); - } - - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, client, MENU_TIME_FOREVER); - } - else if (StrEqual(sSelection, "mode", false)) - { - new Handle:hMenu = CreateMenu(Menu_CookieSettingsMode); - SetMenuTitle(hMenu, "Set Immunity Mode"); - - if (g_aClientCookies[client][iMode]) - { - AddMenuItem(hMenu, "god", "God Mode (Set)"); - AddMenuItem(hMenu, "health", "Health"); - } - else - { - AddMenuItem(hMenu, "god", "God Mode"); - AddMenuItem(hMenu, "health", "Health (Set)"); - } - - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, client, MENU_TIME_FOREVER); - } - else - { - new Handle:hMenu = CreateMenu(Menu_CookieSettingsColors); - SetMenuTitle(hMenu, "Select Immunity Color"); - switch (g_aClientCookies[client][iColor]) - { - case COLOR_GREEN: - { - AddMenuItem(hMenu, "Green", "Green (Set)"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_BLACK: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black (Set)"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_RED: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red (Set)"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_BLUE: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue (Set)"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_TEAM: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color (Set)"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_RAINBOW: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow (Set)"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_NONE: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None (Set)"); - } - } - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, client, MENU_TIME_FOREVER); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - ShowCookieMenu(client); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -public Menu_CookieSettingsEnable(Handle:menu, MenuAction:action, param1, param2) -{ - new client = param1; - if (action == MenuAction_Select) - { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "enable", false)) - { - SetClientCookie(client, sri_cookie_enabled, "1"); - g_aClientCookies[client][bEnabled] = 1; - PrintToChat(client, "[SM] Bonus Round Immunity is ENABLED"); - } - else - { - SetClientCookie(client, sri_cookie_enabled, "0"); - g_aClientCookies[client][bEnabled] = 0; - PrintToChat(client, "[SM] Bonus Round Immunity is DISABLED"); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - ShowCookieMenu(client); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -public Menu_CookieSettingsColors(Handle:menu, MenuAction:action, param1, param2) -{ - new client = param1; - if (action == MenuAction_Select) - { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "Green", false)) - { - SetClientCookie(client, sri_cookie_color, "0"); - g_aClientCookies[client][iColor] = COLOR_GREEN; - PrintToChat(client, "[SM] Bonus Round Immunity color set to GREEN"); - } - else if (StrEqual(sSelection, "Black", false)) - { - SetClientCookie(client, sri_cookie_color, "1"); - g_aClientCookies[client][iColor] = COLOR_BLACK; - PrintToChat(client, "[SM] Bonus Round Immunity color set to BLACK"); - } - else if (StrEqual(sSelection, "Red", false)) - { - SetClientCookie(client, sri_cookie_color, "2"); - g_aClientCookies[client][iColor] = COLOR_RED; - PrintToChat(client, "[SM] Bonus Round Immunity color set to RED"); - } - else if (StrEqual(sSelection, "Blue", false)) - { - SetClientCookie(client, sri_cookie_color, "3"); - g_aClientCookies[client][iColor] = COLOR_BLUE; - PrintToChat(client, "[SM] Bonus Round Immunity color set to BLUE"); - } - else if (StrEqual(sSelection, "Team", false)) - { - SetClientCookie(client, sri_cookie_color, "4"); - g_aClientCookies[client][iColor] = COLOR_TEAM; - PrintToChat(client, "[SM] Bonus Round Immunity color set to TEAM COLOR"); - } - else if (StrEqual(sSelection, "Rain", false)) - { - SetClientCookie(client, sri_cookie_color, "5"); - g_aClientCookies[client][iColor] = COLOR_RAINBOW; - PrintToChat(client, "[SM] Bonus Round Immunity color set to RAINBOW"); - } - else if (StrEqual(sSelection, "None", false)) - { - SetClientCookie(client, sri_cookie_color, "6"); - g_aClientCookies[client][iColor] = COLOR_NONE; - PrintToChat(client, "[SM] Bonus Round Immunity color set to NONE"); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - ShowCookieMenu(client); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -public Menu_CookieSettingsMode(Handle:menu, MenuAction:action, param1, param2) -{ - new client = param1; - if (action == MenuAction_Select) - { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "god", false)) - { - SetClientCookie(client, sri_cookie_mode, "1"); - g_aClientCookies[client][iMode] = 1; - PrintToChat(client, "[SM] Bonus Round Immunity set to GOD MODE"); - } - else - { - SetClientCookie(client, sri_cookie_mode, "0"); - g_aClientCookies[client][iMode] = 0; - PrintToChat(client, "[SM] Bonus Round Immunity set to HEALTH BONUS"); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - ShowCookieMenu(client); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -/** -Timer functions - */ - -public Action:Timer_ChangeColor(Handle:timer, any:client) -{ - if (g_aPlayers[client][CycleColor]++ == 3) - { - g_aPlayers[client][CycleColor] = 0; - } - SetEntityRenderMode(client, RENDER_TRANSCOLOR); - SetEntityRenderColor(client, g_iColors[g_aPlayers[client][CycleColor]][iRed], g_iColors[g_aPlayers[client][CycleColor]][iGreen], g_iColors[g_aPlayers[client][CycleColor]][iBlue], 255); - return Plugin_Continue; -} - -public Action:Timer_UndoGodMode(Handle:timer, any:client) -{ - if (IsClientInGame(client)) - { - SetEntProp(client, Prop_Data, "m_takedamage", 2, 1); - } - g_aPlayers[iClient][hGodModeTimer] = INVALID_HANDLE; - return Plugin_Handled; -} - -/** -Stock functions . - */ - -stock CleanUp(iClient) -{ - g_aPlayers[iClient][bIsAdmin] = false; - DisableImmunity(iClient); -} - -stock EnableImmunity(iClient) -{ - SetEntityRenderMode(iClient, RENDER_TRANSCOLOR); - switch (g_aClientCookies[iClient][iColor]) - { - case COLOR_TEAM: - { - new iTeam = GetClientTeam(iClient); - SetEntityRenderColor(iClient, g_iColors[e_ColorNames:iTeam][iRed], g_iColors[e_ColorNames:iTeam][iGreen], g_iColors[e_ColorNames:iTeam][iBlue], 255); - } - case COLOR_RAINBOW: - { - if (g_aPlayers[iClient][hColorTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hColorTimer]); - g_aPlayers[iClient][hColorTimer] = INVALID_HANDLE; - } - g_aPlayers[iClient][hColorTimer] = CreateTimer(0.2, Timer_ChangeColor, iClient, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); - } - case COLOR_NONE: - { - //We dont have to set a color - } - default: - { - SetEntityRenderColor(iClient, g_iColors[e_ColorNames:g_aClientCookies[iClient][iColor]][iRed], g_iColors[e_ColorNames:g_aClientCookies[iClient][iColor]][iGreen], g_iColors[e_ColorNames:g_aClientCookies[iClient][iColor]][iBlue], 255); - } - } - SetEntityHealth(iClient, 2000); - SetEntProp(iClient, Prop_Data, "m_takedamage", 0, 1); - g_aPlayers[iClient][hGodModeTimer] = CreateTimer(2.0, Timer_UndoGodMode, iClient); - g_aPlayers[iClient][IsImmune] = true; -} - -stock DisableImmunity(iClient) -{ - if (g_aPlayers[iClient][hGodModeTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hGodModeTimer]); - g_aPlayers[iClient][hGodModeTimer] = INVALID_HANDLE; - } - if (g_aPlayers[iClient][hColorTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hColorTimer]); - g_aPlayers[iClient][hColorTimer] = INVALID_HANDLE; - } - if (IsClientInGame(iClient)) - { - SetEntityRenderMode(iClient, RENDER_TRANSCOLOR); - SetEntityRenderColor(iClient, 255, 255, 255, 255); - new TFClassType:PlayerClass = TF2_GetPlayerClass(iClient); - new iMaxHealth = g_iClassMaxHealth[PlayerClass]; - SetEntityHealth(iClient, iMaxHealth); - } - g_aPlayers[iClient][CycleColor] = 0; - g_aPlayers[iClient][IsImmune] = false; -} - -stock LoadColors() -{ - g_iColors[Green][iRed] = 0; - g_iColors[Green][iGreen] = 255; - g_iColors[Green][iBlue] = 0; - - g_iColors[Black][iRed] = 10; - g_iColors[Black][iGreen] = 10; - g_iColors[Black][iBlue] = 0; - - g_iColors[Red][iRed] = 255; - g_iColors[Red][iGreen] = 0; - g_iColors[Red][iBlue] = 0; - - g_iColors[Blue][iRed] = 0; - g_iColors[Blue][iGreen] = 0; - g_iColors[Blue][iBlue] = 255; -} - -stock TF2_AddCond(client, cond) -{ - new Handle:cvar = FindConVar("sv_cheats"), bool:enabled = GetConVarBool(cvar), flags = GetConVarFlags(cvar); - if(!enabled) - { - SetConVarFlags(cvar, flags^FCVAR_NOTIFY); - SetConVarBool(cvar, true); - } - FakeClientCommand(client, "addcond %i", cond); - if(!enabled) - { - SetConVarBool(cvar, false); - SetConVarFlags(cvar, flags); - } -} - -stock TF2_RemoveCond(client, cond) -{ - new Handle:cvar = FindConVar("sv_cheats"), bool:enabled = GetConVarBool(cvar), flags = GetConVarFlags(cvar); - if(!enabled) - { - SetConVarFlags(cvar, flags^FCVAR_NOTIFY); - SetConVarBool(cvar, true); - } - FakeClientCommand(client, "removecond %i", cond); - if(!enabled) - { - SetConVarBool(cvar, false); - SetConVarFlags(cvar, flags); - } -} - -/** -Enabled hook - */ - -public EnabledChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (StringToInt(newValue) == 0) - { - UnhookEvent("player_spawn", HookPlayerSpawn, EventHookMode_Post); - UnhookEvent("teamplay_round_start", HookRoundStart, EventHookMode_Post); - UnhookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][bIsAdmin] && g_aPlayers[i][IsImmune]) - { - DisableImmunity(i); - } - } - g_bIsEnabled = false; - } - else - { - HookEvent("player_spawn", HookPlayerSpawn, EventHookMode_Post); - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_Post); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - g_bIsEnabled = true; - } -} diff --git a/Simple Team Balancer/addons/sourcemod/scripting/simple-spectate.sp b/Simple Team Balancer/addons/sourcemod/scripting/simple-spectate.sp deleted file mode 100644 index 4108f8f..0000000 --- a/Simple Team Balancer/addons/sourcemod/scripting/simple-spectate.sp +++ /dev/null @@ -1,2022 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Spectate -Description: - Spectate a player and follow them through death. -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include -#undef REQUIRE_EXTENSIONS -#undef AUTOLOAD_EXTENSIONS -#tryinclude -#define AUTOLOAD_EXTENSIONS -#define REQUIRE_EXTENSIONS - -#define PLUGIN_VERSION "1.2.1.$Rev$" - -#define SPECMODE_NONE 0 -#define SPECMODE_FIRSTPERSON 4 -#define SPECMODE_3RDPERSON 5 -#define SPECMODE_FREELOOK 6 -#define SPECMODE_CSS_FIRSTPERSON 3 -#define SPECMODE_CSS_3RDPERSON 4 -#define SPECMODE_CSS_FREELOOK 5 - -enum e_CvarHandles -{ - Handle:hHudMode, - Handle:hMenuType, - Handle:hRestrictHud, - Handle:hBan, - Handle:hBanPerm, - Handle:hBeacon, - Handle:hBlind, - Handle:hCheater, - Handle:hDrug, - Handle:hFreeze, - Handle:hFreezeBomb, - Handle:hKick, - Handle:hSlap, - Handle:hSlay, - Handle:hTimeBomb -}; - -enum e_CvarSettings -{ - bool:bHudMode, - bool:bMenuType, - bool:bRestrictHud, - bool:bBan, - bool:bBanPerm, - bool:bBeacon, - bool:bBlind, - bool:bCheater, - bool:bDrug, - bool:bFreeze, - bool:bFreezebomb, - bool:bKick, - bool:bSlap, - bool:bSlay, - bool:bTimeBomb -}; - -enum e_PluginSettings -{ - bool:bUseSteamBans, - bool:bUseSourceBans, - bool:bUseMySQLBans, - bool:bCanHUD, - bool:bUseDukehacks -}; - -enum e_Menus -{ - Handle:hSelectPlayer, - Handle:hBanTime, - Handle:hReason -}; - -enum e_Punishments -{ - Punish_None, - Punish_Ban, - Punish_Beacon, - Punish_Blind, - Punish_Cheater, - Punish_Drug, - Punish_Freeze, - Punish_FreezeBomb, - Punish_Kick, - Punish_Slap, - Punish_Slay, - Punish_TimeBomb -}; - -enum e_PlayerData -{ - bool:bIsDisplayingHud, - bool:bIsFlaggedCheater, - Handle:hHudTimer, - Handle:hTargetTimer, - iTargetIndex, - e_Punishments:TargetPunishment, - iBanTime -}; - -new Handle:sm_spectate_adminflag = INVALID_HANDLE; -new Handle:g_hAdminMenu = INVALID_HANDLE; -new Handle:g_hHud = INVALID_HANDLE; -new Handle:g_aPluginCvar[e_CvarHandles]; -new g_aPluginCvarSettings[e_CvarSettings]; -new g_aPluginSettings[e_PluginSettings]; -new g_aMenus[e_Menus]; -new g_aPlayers[MAXPLAYERS + 1][e_PlayerData]; -new String:g_sAdminFlags[16]; -new String:g_sPunishments[e_Punishments][15] = { "None", "Ban", "Beacon", "Blind", "Cheater", "Drug", "Freeze", "FreezeBomb", "Kick", "Slap", "Slay", "TimeBomb" }; - -public Plugin:myinfo = -{ - name = "Simple Spectate", - author = "Simple Plugins", - description = "Spectate a player and follow them through death.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -/** -Sourcemod callbacks -*/ -public OnPluginStart() -{ - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[SSPEC] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Pre); - - /** - Need to create all of our console variables. - */ - CreateConVar("sm_spectate_version", PLUGIN_VERSION, "Sourcemod Spectate", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - g_aPluginCvar[hHudMode] = CreateConVar("sm_spectate_hudmode", "1", "Hud Mode: 0 = Hud Text | 1 = Panel/Menu (NOTE: The panel/menu will override other menus until canceled)"); - g_aPluginCvar[hMenuType] = CreateConVar("sm_spectate_menutype", "0", "Menu Mode: 0 = Panel | 1 = Menu"); - g_aPluginCvar[hRestrictHud] = CreateConVar("sm_spectate_restricthud", "0", "Restrict the hud to the admin flag provided"); - g_aPluginCvar[hBan] = CreateConVar("sm_spectate_ban", "1", "Enable/Disable ban option"); - g_aPluginCvar[hBanPerm] = CreateConVar("sm_spectate_banperm", "1", "Enable/Disable permanent ban option"); - g_aPluginCvar[hBeacon] = CreateConVar("sm_spectate_beacon", "1", "Enable/Disable beacon option"); - g_aPluginCvar[hBlind] = CreateConVar("sm_spectate_blind", "1", "Enable/Disable blind option"); - g_aPluginCvar[hCheater] = CreateConVar("sm_spectate_cheater", "1", "Enable/Disable cheater option"); - g_aPluginCvar[hDrug] = CreateConVar("sm_spectate_drug", "1", "Enable/Disable drug option"); - g_aPluginCvar[hFreeze] = CreateConVar("sm_spectate_freeze", "1", "Enable/Disable freeze option"); - g_aPluginCvar[hFreezeBomb] = CreateConVar("sm_spectate_freezebomb", "1", "Enable/Disable freezebomb option"); - g_aPluginCvar[hKick] = CreateConVar("sm_spectate_kick", "1", "Enable/Disable kick option"); - g_aPluginCvar[hSlap] = CreateConVar("sm_spectate_slap", "1", "Enable/Disable slap option"); - g_aPluginCvar[hSlay] = CreateConVar("sm_spectate_slay", "1", "Enable/Disable slay option"); - g_aPluginCvar[hTimeBomb] = CreateConVar("sm_spectate_timebomb", "1", "Enable/Disable timebomb option"); - - sm_spectate_adminflag = CreateConVar("sm_spectate_adminflag", "d", "Admin Flag to use for admin hud"); - - /** - Hook console variables - */ - new e_CvarHandles:iCvar; - for ( ; _:iCvar < sizeof(g_aPluginCvar); iCvar++) - { - HookConVarChange(g_aPluginCvar[iCvar], ConVarSettingsChanged); - } - - /** - Need to register the commands we are going to create and use. - */ - RegConsoleCmd("sm_spectate", Command_Spectate, "Spectate a player"); - RegConsoleCmd("sm_spec", Command_Spectate, "Spectate a player"); - RegConsoleCmd("sm_observe", Command_Spectate, "Spectate a player"); - RegConsoleCmd("sm_stopspec", Command_StopSpectate, "Stop Spectating a player"); - RegConsoleCmd("sm_endobserve", Command_StopSpectate, "Stop Spectating a player"); - RegConsoleCmd("sm_specinfo", Command_ToggleHud, "Toggles the hud display if in spectator"); - - /** - Now we have to deal with the admin menu. If the admin library is loaded call the function to add our items. - */ - new Handle:gTopMenu; - if (LibraryExists("adminmenu") && ((gTopMenu = GetAdminTopMenu()) != INVALID_HANDLE)) - { - OnAdminMenuReady(gTopMenu); - } - - /** - Deal with the hud - Thanks to Spray Trace plugin (http://forums.alliedmods.net/showthread.php?p=665448) - */ - new String:sHudGames[32]; - GetGameFolderName(sHudGames, sizeof(sHudGames)); - g_aPluginSettings[bCanHUD] = StrEqual(sHudGames,"tf",false) - || StrEqual(sHudGames,"hl2mp",false) - || StrEqual(sHudGames,"sourceforts",false) - || StrEqual(sHudGames,"obsidian",false) - || StrEqual(sHudGames,"left4dead",false) - || StrEqual(sHudGames,"l4d",false); - - if (g_aPluginSettings[bCanHUD]) - { - g_hHud = CreateHudSynchronizer(); - } - - /** - Load translations - */ - LoadTranslations ("common.phrases"); - LoadTranslations ("simplespectate.phrases"); - - /** - Create the config file - */ - AutoExecConfig(true); -} - -public OnConfigsExecuted() -{ - new e_CvarHandles:iCvar; - for ( ; _:iCvar < sizeof(g_aPluginCvarSettings); iCvar++) - { - g_aPluginCvarSettings[iCvar] = GetConVarBool(g_aPluginCvar[iCvar]); - } - - /* - Build the global menus - */ - g_aMenus[hSelectPlayer] = BuildSelectPlayerMenu(); - g_aMenus[hBanTime] = BuildBanTimeMenu(); - g_aMenus[hReason] = BuildReasonMenu(); - - GetConVarString(sm_spectate_adminflag, g_sAdminFlags, sizeof(g_sAdminFlags)); -} - -public OnAllPluginsLoaded() -{ - - /* - Check for steambans - */ - if (FindConVar("sbsrc_version") != INVALID_HANDLE) - { - g_aPluginSettings[bUseSteamBans] = true; - } - else - { - g_aPluginSettings[bUseSteamBans] = false; - } - - /* - Check for sourcebans - */ - if (FindConVar("sb_version") != INVALID_HANDLE) - { - g_aPluginSettings[bUseSourceBans] = true; - } - else - { - g_aPluginSettings[bUseSourceBans] = false; - } - - /* - Check for mysql bans - */ - if (FindConVar("mysql_bans_version") != INVALID_HANDLE) - { - g_aPluginSettings[bUseMySQLBans] = true; - } - else - { - g_aPluginSettings[bUseMySQLBans] = false; - } - - /* - Check for dukehacks - */ - new String:sExtError[256]; - new iExtStatus = GetExtensionFileStatus("dukehacks.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SSPEC] Dukehacks extension was not found."); - LogAction(0, -1, "[SSPEC] Plugin continued to load, but that feature will not be used."); - g_aPluginSettings[bUseDukehacks] = false; - } - else if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SSPEC] Dukehacks extension is loaded with errors."); - LogAction(0, -1, "[SSPEC] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SSPEC] Plugin continued to load, but that feature will not be used."); - g_aPluginSettings[bUseDukehacks] = false; - } - else if (iExtStatus == 1) - { - LogAction(0, -1, "[SSPEC] Dukehacks extension is loaded and will be used."); - g_aPluginSettings[bUseDukehacks] = true; - dhAddClientHook(CHK_TakeDamage, Hacks_TakeDamageHook); - } - - /* - Deal with some known plugin conflicts - */ - new Handle:hObserveClient = FindConVar("observe_version"); - if (hObserveClient != INVALID_HANDLE) - { - new String:sNewFile[PLATFORM_MAX_PATH + 1], String:sOldFile[PLATFORM_MAX_PATH + 1]; - BuildPath(Path_SM, sNewFile, sizeof(sNewFile), "plugins/disabled/observe.smx"); - BuildPath(Path_SM, sOldFile, sizeof(sOldFile), "plugins/observe.smx"); - - /** - Check if plugins/observe.smx exists, and if not, ignore - */ - if(!FileExists(sOldFile)) - { - return; - } - - /** - Check if plugins/disabled/observe.smx already exists, and if so, delete it - */ - if(FileExists(sNewFile)) - { - DeleteFile(sNewFile); - } - - /** - Unload plugins/observe.smx and move it to plugins/disabled/observe.smx - */ - LogAction(0, -1, "Detected the plugin ObserveClient"); - LogAction(0, -1, "ObserveClient plugin conflicts with Simple Spectate"); - LogAction(0, -1, "Unloading plugin and disabling ObserveClient plugin"); - ServerCommand("sm plugins unload observe"); - RenameFile(sNewFile, sOldFile); - } -} - -public OnLibraryRemoved(const String:name[]) -{ - if (StrEqual(name, "adminmenu")) - { - - /** - Looks like the admin menu was removed. Set the global. - */ - g_hAdminMenu = INVALID_HANDLE; - } - else if (StrEqual(name, "simpleplugins")) - { - //something - } -} - -public OnClientDisconnect(client) -{ - - /** - Cleanup the clients variables. - */ - ResetClient(client); - - /** - Run a loop and see if we are supposed to spectate this person (is a target) - */ - for(new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][iTargetIndex] == client) - { - - /** - Cleanup the clients variables. - */ - StopFollowingPlayer(i); - g_aPlayers[i][TargetPunishment] = Punish_None; - g_aPlayers[i][iBanTime] = 0; - } - } -} - -/** -Thirdparty callbacks -*/ -public SM_OnPlayerMoved(Handle:plugin, client, team) -{ - - /** - Make sure we called the move function - */ - if (plugin != GetMyHandle()) - { - return; - } - - //Nothing -} - -public Action:Hacks_TakeDamageHook(client, attacker, inflictor, Float:damage, &Float:multiplier, damagetype) -{ - - /** - Check for a valid client - */ - if (client > 0 && client <= MaxClients) - { - - /** - Check if the client taking damage is flagged as a cheater - */ - if (g_aPlayers[client][bIsFlaggedCheater]) - { - - /** - Check for fall damage and increase it - */ - if (damagetype & DMG_FALL) - { - multiplier *= 1000.0; - return Plugin_Changed; - } - } - } - - /** - Check for a valid attacker - */ - if (attacker > 0 && attacker <= MaxClients) - { - - /** - Check if the attacker causing the damage is flagged as a cheater - */ - if (g_aPlayers[attacker][bIsFlaggedCheater]) - { - - /** - Make sure they are not hurting themselves - */ - if (client != attacker) - { - - /** - Stop the damage - */ - multiplier *= 0.0; - return Plugin_Changed; - } - } - } - return Plugin_Continue; -} - -/** -Events -*/ -public Action:HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get the client and team - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - new iTeam = GetEventInt(event, "team"); - - /** - Make sure it's a valid client - */ - if (iClient == 0) - { - return Plugin_Continue; - } - - /** - If it's a move to spectator start displaying the hud - */ - else if ((iTeam == g_aCurrentTeams[Spectator]) && (GetUserFlagBits(iClient) & ADMFLAG_GENERIC)) - { - StartDisplayingHud(iClient); - - /** - If the event was going to be broadcasted, we refire it so it is not broadcasted and stop this one - */ - if (!dontBroadcast) - { - new Handle:hEvent = CreateEvent("player_team"); - SetEventInt(hEvent, "userid", GetEventInt(event, "userid")); - SetEventInt(hEvent, "team", GetEventInt(event, "team")); - SetEventInt(hEvent, "oldteam", GetEventInt(event, "oldteam")); - SetEventBool(hEvent, "disconnect", GetEventBool(event, "disconnect")); - - if (g_CurrentMod == GameType_DOD || g_CurrentMod == GameType_L4D || g_CurrentMod == GameType_TF) - { - new String:sClientName[MAX_NAME_LENGTH + 1]; - GetClientName(client, sClientName, sizeof(sClientName)); - SetEventBool(hEvent, "autoteam", GetEventBool(event, "autoteam")); - SetEventBool(hEvent, "silent", true); - SetEventString(hEvent, "name", sClientName); - FireEvent(hEvent, true); - } - else - { - FireEvent(hEvent, true); - } - return Plugin_Handled; - } - } - - /** - Otherwise cleanup the client - */ - else - { - StopDisplayingHud(iClient); - StopFollowingPlayer(iClient); - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -/** -Commands -*/ -public Action:Command_Spectate(client, args) -{ - - /** - See if we already have a target (for toggling of command) - */ - if (g_aPlayers[client][iTargetIndex]) - { - - /** - We do, toggle it off - */ - StopFollowingPlayer(client); - - /** - We are done, bug out. - */ - return Plugin_Handled; - } - - /** - We don't... must want to enable it - See if we have some command arguments. - */ - new iCmdArgs = GetCmdArgs(); - if (iCmdArgs == 0) - { - - /** - We don't have any. Display the player menu. - */ - if (g_aPlayers[client][bIsDisplayingHud]) - { - StopDisplayingHud(client); - } - - DisplayMenu(BuildPlayerListMenu(), client, MENU_TIME_FOREVER); - return Plugin_Handled; - } - - /** - We have an argument. - Try to find the target. - */ - new String:sPlayer[128]; - GetCmdArg(1, sPlayer, sizeof(sPlayer)); - new iTarget = FindTarget(client, sPlayer, true, true); - if (iTarget == -1 || !IsClientInGame(iTarget)) - { - - /** - We couldn't find the target. Display the player menu. - */ - if (g_aPlayers[client][bIsDisplayingHud]) - { - StopDisplayingHud(client); - } - - DisplayMenu(BuildPlayerListMenu(), client, MENU_TIME_FOREVER); - return Plugin_Handled; - } - - /** - We found the target. - Call the stock function to spectate the target. - */ - StartFollowingPlayer(client, iTarget); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_StopSpectate(client, args) -{ - - /** - Cleanup the clients variables. - */ - StopFollowingPlayer(client); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_ToggleHud(client, args) -{ - - /** - Toggle the hud - */ - if (g_aPlayers[client][bIsDisplayingHud]) - { - StopDisplayingHud(client); - } - else - { - StartDisplayingHud(client); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -/** -Timers -*/ -public Action:Timer_ResetTarget(Handle:timer, any:client) -{ - - new iTargetID = GetEntPropEnt(client, Prop_Send, "m_hObserverTarget"); - - if (iTargetID != g_aPlayers[client][iTargetIndex] && IsPlayerAlive(g_aPlayers[client][iTargetIndex])) - { - - /** - Run the command to spectate the target from the clients prospectative. - */ - FakeClientCommandEx(client, "spec_player \"%N\"", g_aPlayers[client][iTargetIndex]); - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Timer_UpdateHud(Handle:timer, any:client) -{ - - /** - Make sure the client is still in game and a spectator - */ - if (!IsClientConnected(client) || !IsClientInGame(client) || GetClientTeam(client) != g_aCurrentTeams[Spectator] || !g_aPlayers[client][bIsDisplayingHud]) - { - - /** - We are done, bug out - */ - g_aPlayers[client][hHudTimer] = INVALID_HANDLE; - g_aPlayers[client][bIsDisplayingHud] = false; - return Plugin_Stop; - } - /** - Get the target - */ - new iTarget = GetEntPropEnt(client, Prop_Send, "m_hObserverTarget"); - - /** - Check to make sure the target is valid - */ - if (iTarget <= 0 || iTarget > MaxClients) - { - return Plugin_Continue; - } - - /** - Get the spectator mode - */ - new iSpecMode = GetEntProp(client, Prop_Send, "m_iObserverMode"); - - /** - This is a double check to make sure we are in spec - If we are on a regular team, specmod would = none or zero - */ - if (iSpecMode == SPECMODE_NONE) - { - - /** - We are done, bug out - */ - g_aPlayers[client][hHudTimer] = INVALID_HANDLE; - g_aPlayers[client][bIsDisplayingHud] = false; - return Plugin_Stop; - } - - /** - Check the spectator mode - CSS has different index's so we have to check game type first - */ - if (g_CurrentMod == GameType_CSS) - { - switch (iSpecMode) - { - case SPECMODE_CSS_FIRSTPERSON: - { - //Do Nothing - } - case SPECMODE_CSS_3RDPERSON: - { - //Do Nothing - } - case SPECMODE_CSS_FREELOOK: - { - return Plugin_Continue; - } - } - } - else - { - switch (iSpecMode) - { - case SPECMODE_FIRSTPERSON: - { - //Do Nothing - } - case SPECMODE_3RDPERSON: - { - //Do Nothing - } - case SPECMODE_FREELOOK: - { - return Plugin_Continue; - } - } - } - - - /** - Display with the hud - */ - if (g_aPluginSettings[bCanHUD] && !g_aPluginCvarSettings[bHudMode]) - { - new String:sSteamID[64]; - GetClientAuthString(iTarget, sSteamID, sizeof(sSteamID)); - SetHudTextParams(0.04, 0.6, 0.5, 255, 50, 50, 255); - ShowSyncHudText(client, g_hHud, "%N [%s]", iTarget, sSteamID); - } - else if (g_aPluginCvarSettings[bHudMode]) - { - if (g_aPluginCvarSettings[bMenuType]) - { - DisplayMenu(BuildPlayerHudMenu(client, iTarget), client, 1); - } - else - { - new Handle:hPanel = BuildPlayerHudPanel(client, iTarget); - SendPanelToClient(hPanel, client, Panel_PlayerHud, 1); - CloseHandle(hPanel); - } - } - - /** - We are done, keep going! - */ - return Plugin_Continue; -} - -/** -Admin Menu Callbacks -*/ -public OnAdminMenuReady(Handle:topmenu) -{ - if (topmenu == g_hAdminMenu) - { - return; - } - g_hAdminMenu = topmenu; - new TopMenuObject:player_commands = FindTopMenuCategory(g_hAdminMenu, ADMINMENU_PLAYERCOMMANDS); - if (player_commands == INVALID_TOPMENUOBJECT) - { - return; - } - AddToTopMenu(g_hAdminMenu, - "sm_spectate", - TopMenuObject_Item, - AdminMenu_SpecPlayer, - player_commands, - "sm_spectate", - ADMFLAG_GENERIC); -} - -public AdminMenu_SpecPlayer(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) -{ - if (action == TopMenuAction_DisplayOption) - { - - if (g_aPlayers[param][bIsDisplayingHud]) - { - StopDisplayingHud(param); - } - /** - See if we already have a target - */ - if (g_aPlayers[param][iTargetIndex]) - { - Format(buffer, maxlength, "Spectate(Disable)"); - } - else - { - Format(buffer, maxlength, "Spectate(Select Player)"); - } - } - else if (action == TopMenuAction_SelectOption) - { - - /** - See if we already have a target - */ - if (g_aPlayers[param][iTargetIndex]) - { - - /** - We do, toggle it off - */ - StopFollowingPlayer(param); - - /** - We are done, bug out. - */ - return; - } - else - { - DisplayMenu(BuildPlayerListMenu(), param, MENU_TIME_FOREVER); - } - } -} - -/** -Select Player Menu Callbacks -*/ -public Menu_PlayerList(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - /** - Get the selected player - */ - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - new iTarget = GetClientOfUserId(StringToInt(sSelection)); - - /** - Start following the player - */ - StartFollowingPlayer(param1, iTarget); - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_GENERIC) - { - - /** - Display the last admin menu - */ - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } - else if (param2 == MenuCancel_Exit && GetClientTeam(param1) == g_aCurrentTeams[Spectator]) - { - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_End) - { - - /** - Not a global menu, close it - */ - CloseHandle(menu); - } -} - -public Menu_SelectPlayer(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - - /** - Get the selected player - */ - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (strcmp(sSelection, "Current", false) == 0) - { - /** - Get the current target - */ - new iTarget = GetEntPropEnt(param1, Prop_Send, "m_hObserverTarget"); - - /** - Check to make sure the target is valid - */ - if (iTarget <= 0 || iTarget > MaxClients) - { - PrintToChat(param1, "\x03[SM-SPEC]\x01 %t", "Invalid Target"); - DisplayMenu(BuildPlayerListMenu(), param1, MENU_TIME_FOREVER); - } - - /** - Start following the player - */ - StartFollowingPlayer(param1, iTarget); - } - else - { - - /** - They want to select a player, show the player list - */ - DisplayMenu(BuildPlayerListMenu(), param1, MENU_TIME_FOREVER); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_End) - { - /** - Its a global menu, leave it alive - */ - } -} - -/** -Punishment Menu Callbacks -*/ -public Menu_Punishments(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - - /** - Get the menu selection - */ - new String:sSelection[15]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - - /** - Search for the correct index - */ - new e_Punishments:Index = Punish_None; - for ( ; _:Index <= sizeof(g_sPunishments); Index++) - { - if (StrEqual(sSelection, g_sPunishments[Index])) - { - break; - } - } - - /** - Display the next menu - */ - if (Index == Punish_Ban) - { - - /** - Set the punishment index and display ban time menu - */ - g_aPlayers[param1][TargetPunishment] = Index; - DisplayMenu(g_aMenus[hBanTime], param1, MENU_TIME_FOREVER); - } - else if (Index == Punish_Cheater) - { - - /** - Ask for confirmation before we set punishment index - */ - new Handle:hPanel = BuildAdminCheaterPanel(); - SendPanelToClient(hPanel, param1, Panel_AdminCheater, MENU_TIME_FOREVER); - CloseHandle(hPanel); - } - else - { - - /** - Set the punishment index and display reason menu - */ - g_aPlayers[param1][TargetPunishment] = Index; - DisplayMenu(g_aMenus[hReason], param1, MENU_TIME_FOREVER); - } - } - else if (action == MenuAction_Cancel) - { - - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - else if (action == MenuAction_End) - { - - /** - Not a global menu, close it - */ - CloseHandle(menu); - } -} - -public Menu_BanTime(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - - /** - Get the menu selection - */ - new String:sSelection[15]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - - /** - Set the ban time global - */ - g_aPlayers[param1][iBanTime] = StringToInt(sSelection); - - /** - Display the reason menu - */ - DisplayMenu(g_aMenus[hReason], param1, MENU_TIME_FOREVER); - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_End) - { - /** - Its a global menu, leave it alive - */ - } -} - -public Menu_Reason(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - - /** - Get the menu selection - */ - new String:sSelection[15]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - - /** - Perform the punishment - */ - PerformPunishment(param1, g_aPlayers[param1][iTargetIndex], g_aPlayers[param1][TargetPunishment], sSelection, g_aPlayers[param1][iBanTime]); - - /** - Reactivate the hud if still in spectator - */ - if (GetClientTeam(param1) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_End) - { - /** - Its a global menu, leave it alive - */ - } -} - -public Panel_AdminCheater(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - if (param2 == 1) - { - - /** - Set the punishment index and display reason menu - */ - g_aPlayers[param1][TargetPunishment] = Punish_Cheater; - DisplayMenu(g_aMenus[hReason], param1, MENU_TIME_FOREVER); - } - else - { - - /** - Reactivate the hud if still in spectator - */ - if (GetClientTeam(param1) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(param1); - } - } - } -} - -public Panel_PublicCheater(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - if (param2 == 1) - { - //Waiting for SB 2.0 and sb_submission to be published - } - else - { - - /** - Reactivate the hud if still in spectator - */ - if (GetClientTeam(param1) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(param1); - } - } - } -} - -/** -Hud Menu/Panel Callbacks -*/ -public Menu_PlayerHud(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "stop", false)) - { - StopFollowingPlayer(param1); - } - else if (StrEqual(sSelection, "start", false)) - { - StopDisplayingHud(param1); - DisplayMenu(g_aMenus[hSelectPlayer], param1, MENU_TIME_FOREVER); - } - else if (StrEqual(sSelection, "removecheater", false)) - { - g_aPlayers[g_aPlayers[param1][iTargetIndex]][bIsFlaggedCheater] = false; - } - else if (StrEqual(sSelection, "punish", false)) - { - if (g_aPlayers[param1][iTargetIndex]) - { - StopDisplayingHud(param1); - DisplayMenu(BuildPunishmentMenu(param1), param1, MENU_TIME_FOREVER); - } - else - { - StopDisplayingHud(param1); - PrintToChat(param1, "\x03[SM-SPEC]\x01 %t", "Must Have Target"); - DisplayMenu(g_aMenus[hSelectPlayer], param1, MENU_TIME_FOREVER); - } - } - else if (StrEqual(sSelection, "reportcheater", false)) - { - if (g_aPlayers[param1][iTargetIndex]) - { - StopDisplayingHud(param1); - new Handle:hPanel = BuildPublicCheaterPanel(); - SendPanelToClient(hPanel, param1, Panel_PublicCheater, MENU_TIME_FOREVER); - CloseHandle(hPanel); - } - else - { - StopDisplayingHud(param1); - PrintToChat(param1, "\x03[SM-SPEC]\x01 %t", "Must Have Target"); - DisplayMenu(g_aMenus[hSelectPlayer], param1, MENU_TIME_FOREVER); - } - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_Interrupted) - { - if (GetClientMenu(param1) == MenuSource_External) - { - StopDisplayingHud(param1); - } - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -public Panel_PlayerHud(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - switch (param2) - { - case 1: - { - if (g_aPlayers[param1][iTargetIndex]) - { - StopFollowingPlayer(param1); - } - else - { - StopDisplayingHud(param1); - DisplayMenu(BuildSelectPlayerMenu(), param1, MENU_TIME_FOREVER); - } - } - case 2: - { - if (!g_aPlayers[param1][iTargetIndex]) - { - StopDisplayingHud(param1); - PrintToChat(param1, "\x03[SM-SPEC]\x01 %t", "Must Have Target"); - DisplayMenu(g_aMenus[hSelectPlayer], param1, MENU_TIME_FOREVER); - return; - } - - if ((GetUserFlagBits(param1) & ADMFLAG_GENERIC) || (GetUserFlagBits(param1) & ADMFLAG_ROOT)) - { - if (g_aPlayers[g_aPlayers[param1][iTargetIndex]][bIsFlaggedCheater] && (GetUserFlagBits(param1) & ADMFLAG_ROOT)) - { - //Remove cheater flag - g_aPlayers[g_aPlayers[param1][iTargetIndex]][bIsFlaggedCheater] = false; - } - else - { - //Punish menu - StopDisplayingHud(param1); - DisplayMenu(BuildPunishmentMenu(param1), param1, MENU_TIME_FOREVER); - } - } - else - { - //Report Cheater - new Handle:hPanel = BuildPublicCheaterPanel(); - SendPanelToClient(hPanel, param1, Panel_PublicCheater, MENU_TIME_FOREVER); - CloseHandle(hPanel); - } - } - case 3: - { - StopDisplayingHud(param1); - } - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_Interrupted) - { - if (GetClientMenu(param1) == MenuSource_External) - { - StopDisplayingHud(param1); - } - } - } -} - - -/** -Stock functions -*/ -stock StartFollowingPlayer(client, target) -{ - - /** - If we have an open timer, close it. - */ - if (g_aPlayers[client][hTargetTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[client][hTargetTimer]); - g_aPlayers[client][hTargetTimer] = INVALID_HANDLE; - } - - /** - Make sure the target is on a non spectator team, and the client != target - */ - if (client == target) - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Yourself"); - return; - } - new iTargetTeam = GetClientTeam(target); - if (iTargetTeam == g_aCurrentTeams[Spectator] || iTargetTeam == g_aCurrentTeams[Unknown]) - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Spectator"); - return; - } - - /** - Check to see if client is already a spectator - */ - if (GetClientTeam(client) != g_aCurrentTeams[Spectator]) - { - - /** - Client is not a spectator, lets move them to spec. - */ - SM_MovePlayer(client, g_aCurrentTeams[Spectator]); - } - - /** - If we are using steambans call sb_status - */ - if (g_aPluginSettings[bUseSteamBans]) - { - FakeClientCommandEx(client, "sb_status"); - } - - - /** - Set the global and start to spectate the target. - Making sure it's long enough to deal with moving the client to spec if we had to. - */ - new String:sTargetName[MAX_NAME_LENGTH + 1]; - GetClientName(target, sTargetName, sizeof(sTargetName)); - g_aPlayers[client][iTargetIndex] = target; - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Spectating", sTargetName); - g_aPlayers[client][hTargetTimer] = CreateTimer(0.5, Timer_ResetTarget, client, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); - if (!g_aPlayers[client][bIsDisplayingHud] && GetClientTeam(client) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(client); - } -} - -stock StopFollowingPlayer(client) -{ - - /** - If we have an open timer, close it. - */ - if (g_aPlayers[client][hTargetTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[client][hTargetTimer]); - } - - /** - Tell the client we can't spec his target anymore... if they are in game. - */ - if (IsClientInGame(client) && g_aPlayers[client][iTargetIndex] != 0) - { - new String:sTargetName[MAX_NAME_LENGTH + 1]; - GetClientName(g_aPlayers[client][iTargetIndex], sTargetName, sizeof(sTargetName)); - if (!IsClientConnected(g_aPlayers[client][iTargetIndex]) || !IsClientInGame(g_aPlayers[client][iTargetIndex])) - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Target Left"); - } - else - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Stopped spectating", sTargetName); - } - } - - /** - Null the globals. - */ - g_aPlayers[client][iTargetIndex] = 0; - g_aPlayers[client][hTargetTimer] = INVALID_HANDLE; -} - -stock StartDisplayingHud(client) -{ - if (g_aPluginCvarSettings[bRestrictHud] && !SM_IsValidAdmin(client, g_sAdminFlags)) - { - return; - } - else - { - /** - Double check the hud timer - We should not have one, but if we do, lets cancel it for the current callback - */ - StopDisplayingHud(client); - - /** - Now we can safely display the hud and make sure the current stored handle is the current timer - */ - g_aPlayers[client][bIsDisplayingHud] = true; - g_aPlayers[client][hHudTimer] = CreateTimer(0.5, Timer_UpdateHud, client, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); - } -} - -stock StopDisplayingHud(client) -{ - if (g_aPlayers[client][hHudTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[client][hHudTimer]); - } - g_aPlayers[client][hHudTimer] = INVALID_HANDLE; - g_aPlayers[client][bIsDisplayingHud] = false; -} - -stock ResetClient(client) -{ - StopFollowingPlayer(client); - StopDisplayingHud(client); - - g_aPlayers[client][bIsFlaggedCheater] = false; - g_aPlayers[client][TargetPunishment] = Punish_None; - g_aPlayers[client][iBanTime] = -1; -} - -stock PerformPunishment(client, target, e_Punishments:punishment, const String:reason[], time = 300) -{ - new String:sTargetName[MAX_NAME_LENGTH + 1], - String:sTargetID[64]; - - /** - The target could have left the game by the time we get here - Check for a valid target - */ - if (!IsClientConnected(target) || !IsClientInGame(target)) - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Target Left"); - return; - } - - GetClientName(target, sTargetName, sizeof(sTargetName)); - GetClientAuthString(target, sTargetID, sizeof(sTargetID)); - - switch (punishment) - { - case Punish_Kick: - { - KickClient(g_aPlayers[client][iTargetIndex], "%s", reason); - } - case Punish_Ban: - { - if (g_aPluginSettings[bUseSourceBans]) - { - ClientCommand(client, "sm_ban #%d %d \"%s\"", GetClientUserId(target), time, reason); - } - else if (g_aPluginSettings[bUseMySQLBans]) - { - ClientCommand(client, "mysql_ban #%d %d \"%s\"", GetClientUserId(target), time, reason); - } - else - { - BanClient(target, time, BANFLAG_AUTHID, reason, reason); - } - } - case Punish_Cheater: - { - g_aPlayers[target][bIsFlaggedCheater] = true; - } - case Punish_Beacon: - { - ClientCommand(client, "sm_beacon \"%s\"", sTargetName); - } - case Punish_Blind: - { - ClientCommand(client, "sm_blind \"%s\"", sTargetName); - } - case Punish_Drug: - { - ClientCommand(client, "sm_drug \"%s\"", sTargetName); - } - case Punish_Freeze: - { - ClientCommand(client, "sm_freeze \"%s\"", sTargetName); - } - case Punish_FreezeBomb: - { - ClientCommand(client, "sm_freezebomb \"%s\"", sTargetName); - } - case Punish_Slap: - { - ClientCommand(client, "sm_slap \"%s\" 10", sTargetName); - } - case Punish_Slay: - { - ClientCommand(client, "sm_slay \"%s\"", sTargetName); - } - case Punish_TimeBomb: - { - ClientCommand(client, "sm_timebomb \"%s\"", sTargetName); - } - } - - if (punishment == Punish_Cheater) - { - LogAction(client, target, "[SM SPEC] %N marked %N(%s) with a %s flag for %s", client, target, sTargetID, g_sPunishments[punishment], reason); - } - else - { - ShowActivity(client, "%t", "Punished", sTargetName, g_sPunishments[punishment], reason); - LogAction(client, target, "[SM SPEC] %N punished %N(%s) with a %s for %s", client, target, sTargetID, g_sPunishments[punishment], reason); - } - - /** - Null the globals. - */ - g_aPlayers[client][TargetPunishment] = Punish_None; - g_aPlayers[client][iBanTime] = -1; -} - -/** -Build the menu of player names -*/ -stock Handle:BuildPlayerListMenu() -{ - new Handle:hMenu = CreateMenu(Menu_PlayerList); - AddTargetsToMenu(hMenu, 0, true, false); - SetMenuTitle(hMenu, "Select A Player:"); - SetMenuExitBackButton(hMenu, true); - return hMenu; -} - -/** -Build the select player menu (current or list of players) -*/ -stock Handle:BuildSelectPlayerMenu() -{ - new Handle:hMenu = CreateMenu(Menu_SelectPlayer); - SetMenuTitle(hMenu, "Select A Player:"); - AddMenuItem(hMenu, "Current", "Current Target"); - AddMenuItem(hMenu, "List", "Player List"); - SetMenuExitBackButton(hMenu, true); - return hMenu; -} - -/** -Build the punishmenu menu -*/ -stock Handle:BuildPunishmentMenu(iClient) -{ - new Handle:hMenu = CreateMenu(Menu_Punishments); - SetMenuTitle(hMenu, "Select A Punishment:"); - SetMenuExitBackButton(hMenu, true); - SetMenuExitButton(hMenu, true); - - if (g_aPluginCvarSettings[bKick] && ((GetUserFlagBits(iClient) & ADMFLAG_GENERIC) || (GetUserFlagBits(iClient) & ADMFLAG_ROOT))) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Kick], "Kick"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Kick], "Kick", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bBan] && ((GetUserFlagBits(iClient) & ADMFLAG_GENERIC) || (GetUserFlagBits(iClient) & ADMFLAG_ROOT))) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Ban], "Ban"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Ban], "Ban", ITEMDRAW_DISABLED); - } - - if (g_aPluginSettings[bUseDukehacks] && g_aPluginCvarSettings[bCheater] && (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Cheater], "Flag As Cheater"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Cheater], "Flag As Cheater", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bBeacon]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Beacon], "Beacon"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Beacon], "Beacon", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bBlind]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Blind], "Blind"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Blind], "Blind", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bDrug]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Drug], "Drug"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Drug], "Drug", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bFreeze]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Freeze], "Freeze"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Freeze], "Freeze", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bFreezebomb]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_FreezeBomb], "Freeze Bomb"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_FreezeBomb], "Freeze Bomb", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bSlap]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Slap], "Slap"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Slap], "Slap", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bSlay]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Slay], "Slay"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Slay], "Slay", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bTimeBomb]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_TimeBomb], "Time Bomb"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_TimeBomb], "Time Bomb", ITEMDRAW_DISABLED); - } - - return hMenu; -} - -/** -Build the punishmenu menu -*/ -stock Handle:BuildBanTimeMenu() -{ - new Handle:hMenu = CreateMenu(Menu_BanTime); - SetMenuTitle(hMenu, "Select Ban Type:"); - - if (g_aPluginCvarSettings[bBanPerm]) - { - AddMenuItem(hMenu, "permban", "Permanent"); - } - else - { - AddMenuItem(hMenu, "permban", "Permanent", ITEMDRAW_DISABLED); - } - - AddMenuItem(hMenu, "10", "10 Minutes"); - AddMenuItem(hMenu, "30", "30 Minutes"); - AddMenuItem(hMenu, "60", "1 Hour"); - AddMenuItem(hMenu, "240", "4 Hours"); - AddMenuItem(hMenu, "1440", "1 Day"); - AddMenuItem(hMenu, "10080", "1 Week"); - - SetMenuExitBackButton(hMenu, true); - return hMenu; -} - -/** -Build the punishmenu menu -*/ -stock Handle:BuildReasonMenu() -{ - new Handle:hMenu = CreateMenu(Menu_Reason); - SetMenuTitle(hMenu, "Select A Reason:"); - - AddMenuItem(hMenu, "Abusive", "Abusive"); - AddMenuItem(hMenu, "Racism", "Racism"); - AddMenuItem(hMenu, "General cheating/exploits", "General cheating/exploits"); - AddMenuItem(hMenu, "Wallhack", "Wallhack"); - AddMenuItem(hMenu, "Aimbot", "Aimbot"); - AddMenuItem(hMenu, "Speedhacking", "Speedhacking"); - AddMenuItem(hMenu, "Mic spamming", "Mic spamming"); - AddMenuItem(hMenu, "Admin disrepect", "Admin disrepect"); - AddMenuItem(hMenu, "Camping", "Camping"); - AddMenuItem(hMenu, "Team killing", "Team killing"); - AddMenuItem(hMenu, "Unacceptable Spray", "Unacceptable Spray"); - AddMenuItem(hMenu, "Breaking Server Rules", "Breaking Server Rules"); - AddMenuItem(hMenu, "Other", "Other"); - - SetMenuExitBackButton(hMenu, true); - return hMenu; -} - -/** -Build the cheater displays -*/ -stock Handle:BuildAdminCheaterPanel() -{ - - /** - Create the menu and set the menu options. - */ - new Handle:hPanel = CreatePanel(); - SetPanelTitle(hPanel, "Simple Spectator:"); - - DrawPanelText(hPanel, "Are you sure you want to"); - DrawPanelText(hPanel, "flag this player as a cheater?"); - DrawPanelText(hPanel, "They will not be able to damage"); - DrawPanelText(hPanel, "anyone and die on fall damage."); - DrawPanelItem(hPanel, "Yes"); - DrawPanelItem(hPanel, "No"); - - return hPanel; -} - -stock Handle:BuildPublicCheaterPanel() -{ - - /** - Create the menu and set the menu options. - */ - new Handle:hPanel = CreatePanel(); - SetPanelTitle(hPanel, "Simple Spectator:"); - - DrawPanelText(hPanel, "Are you sure you want to"); - DrawPanelText(hPanel, "submit this player as a cheater?"); - DrawPanelItem(hPanel, "Yes (Not Implemented Yet)", ITEMDRAW_DISABLED); - DrawPanelItem(hPanel, "No"); - return hPanel; -} - -/** -Build the hud displays -*/ -stock Handle:BuildPlayerHudMenu(iClient, iTarget) -{ - - /** - Create all the string variables we will need - */ - new String:sTargetName[MAX_NAME_LENGTH + 1], - String:sTargetID[64], - String:sTargetIP[16]; - - new String:sDisplayName[MAX_NAME_LENGTH + 1], - String:sDisplayID[64], - String:sDisplayIP[64], - String:sDisplayFrags[16], - String:sDisplayDeaths[16]; - - new iTargetFrags, - iTargetDeaths; - - /** - Get the targets information - */ - GetClientName(iTarget, sTargetName, sizeof(sTargetName)); - GetClientIP(iTarget, sTargetIP, sizeof(sTargetIP)); - GetClientAuthString(iTarget, sTargetID, sizeof(sTargetID)); - iTargetFrags = GetClientFrags(iTarget); - iTargetDeaths = GetClientDeaths(iTarget); - - /** - Format the strings for the menu - */ - Format(sDisplayName, sizeof(sDisplayName), "Player: %s", sTargetName); - Format(sDisplayID, sizeof(sDisplayID), "Steam ID: %s", sTargetID); - Format(sDisplayIP, sizeof(sDisplayIP), "IP Address: %s", sTargetIP); - Format(sDisplayFrags, sizeof(sDisplayFrags), "Kills: %i", iTargetFrags); - Format(sDisplayDeaths, sizeof(sDisplayDeaths), "Deaths: %i", iTargetDeaths); - - /** - Create the menu and set the menu options. - */ - new Handle:hMenu = CreateMenu(Menu_PlayerHud); - SetMenuExitBackButton(hMenu, false); - SetMenuTitle(hMenu, "Simple Spectator"); - - AddMenuItem(hMenu, "name", sDisplayName, ITEMDRAW_DISABLED); - AddMenuItem(hMenu, "steamid", sDisplayID, ITEMDRAW_DISABLED); - - if (SM_IsValidAdmin(iClient, g_sAdminFlags)) - { - AddMenuItem(hMenu, "ip", sDisplayIP, ITEMDRAW_DISABLED); - } - - AddMenuItem(hMenu, "kills", sDisplayFrags, ITEMDRAW_DISABLED); - AddMenuItem(hMenu, "deaths", sDisplayDeaths, ITEMDRAW_DISABLED); - - if (g_aPlayers[iClient][iTargetIndex]) - { - AddMenuItem(hMenu, "stop", "Stop Following"); - } - else - { - AddMenuItem(hMenu, "start", "Follow Player"); - } - - if ((GetUserFlagBits(iClient) & ADMFLAG_GENERIC) || (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - if (g_aPlayers[iTarget][bIsFlaggedCheater] && (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - AddMenuItem(hMenu, "removecheater", "Remove Cheater Flag"); - } - else - { - if (CanUserTarget(iClient, iTarget)) - { - AddMenuItem(hMenu, "punish", "Punish Player"); - } - else - { - AddMenuItem(hMenu, "punish", "Punish Player (Immune)", ITEMDRAW_DISABLED); - } - } - } - else - { - AddMenuItem(hMenu, "reportcheater", "Report Cheater"); - } - - SetMenuPagination(hMenu, MENU_NO_PAGINATION); - SetMenuExitButton(hMenu, true); - return hMenu; -} - -stock Handle:BuildPlayerHudPanel(iClient, iTarget) -{ - - /** - Create all the string variables we will need - */ - new String:sTargetName[MAX_NAME_LENGTH + 1], - String:sTargetID[64], - String:sTargetIP[16]; - - new String:sDisplayName[MAX_NAME_LENGTH + 1], - String:sDisplayID[64], - String:sDisplayIP[64], - String:sDisplayFrags[16], - String:sDisplayDeaths[16]; - - new iTargetFrags, - iTargetDeaths; - - /** - Get the targets information - */ - GetClientName(iTarget, sTargetName, sizeof(sTargetName)); - GetClientIP(iTarget, sTargetIP, sizeof(sTargetIP)); - GetClientAuthString(iTarget, sTargetID, sizeof(sTargetID)); - iTargetFrags = GetClientFrags(iTarget); - iTargetDeaths = GetClientDeaths(iTarget); - - /** - Format the strings for the menu - */ - Format(sDisplayName, sizeof(sDisplayName), "Player: %s", sTargetName); - Format(sDisplayID, sizeof(sDisplayID), "Steam ID: %s", sTargetID); - Format(sDisplayIP, sizeof(sDisplayIP), "IP Address: %s", sTargetIP); - Format(sDisplayFrags, sizeof(sDisplayFrags), "Kills: %i", iTargetFrags); - Format(sDisplayDeaths, sizeof(sDisplayDeaths), "Deaths: %i", iTargetDeaths); - - /** - Create the menu and set the menu options. - */ - new Handle:hPanel = CreatePanel(); - SetPanelTitle(hPanel, "Simple Spectator"); - - DrawPanelText(hPanel, "Player Information:"); - DrawPanelText(hPanel, sDisplayName); - DrawPanelText(hPanel, sDisplayID); - if (SM_IsValidAdmin(iClient, g_sAdminFlags)) - { - DrawPanelText(hPanel, sDisplayIP); - } - - DrawPanelText(hPanel, sDisplayFrags); - DrawPanelText(hPanel, sDisplayDeaths); - - if (g_aPlayers[iClient][iTargetIndex]) - { - DrawPanelItem(hPanel, "Stop Following"); - } - else - { - DrawPanelItem(hPanel, "Follow Player"); - } - - if ((GetUserFlagBits(iClient) & ADMFLAG_GENERIC) || (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - if (g_aPlayers[iTarget][bIsFlaggedCheater] && (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - DrawPanelItem(hPanel, "Remove Cheater Flag"); - } - else - { - if (CanUserTarget(iClient, iTarget)) - { - DrawPanelItem(hPanel, "Punish Player"); - } - else - { - DrawPanelItem(hPanel, "Punish Player (Immune)", ITEMDRAW_DISABLED); - } - } - } - else - { - DrawPanelItem(hPanel, "Report Cheater"); - } - - DrawPanelItem(hPanel, "Close Hud Panel"); - return hPanel; -} - -/** -Adjust the settings if a convar was changed -*/ -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - for (new iCvar = 0 ; _:iCvar < sizeof(g_aPluginCvarSettings); iCvar++) - { - if (g_aPluginCvar[_:iCvar] == convar) - { - if (StringToInt(newValue) == 1) - { - g_aPluginCvarSettings[_:iCvar] = true; - } - else - { - g_aPluginCvarSettings[_:iCvar] = false; - } - } - } - - /* - ReBuild the global menu that depends on cvars - */ - g_aMenus[hBanTime] = BuildBanTimeMenu(); - - /** - Run a loop to reset the hud - */ - for(new i = 1; i <= MaxClients; i++) - { - StopDisplayingHud(i); - if (IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(i); - } - } -} diff --git a/Simple Team Balancer/addons/sourcemod/scripting/simple-teammanager.sp b/Simple Team Balancer/addons/sourcemod/scripting/simple-teammanager.sp deleted file mode 100644 index 008f443..0000000 --- a/Simple Team Balancer/addons/sourcemod/scripting/simple-teammanager.sp +++ /dev/null @@ -1,1351 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Team Manager -Description: - Manges players and their team - Admin menu integration - Allows admins/donators to swap their teams (clears force)* - Allows admins to move players to a team (forced\unforced)* - Allows admins to scramble the teams* - *Works with Simple Team Balancer (if installed) -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include - -#define PLUGIN_VERSION "2.1.$Rev$" -#define VOTE_YES "##YES##" -#define VOTE_NO "##NO##" - -enum PlayerData -{ - iNewTeam, - bool:bQueue -}; - -new Handle:stm_enabled = INVALID_HANDLE; -new Handle:stm_logactivity = INVALID_HANDLE; -new Handle:stm_adminflag_swapteam = INVALID_HANDLE; -new Handle:stm_adminflag_moveplayer = INVALID_HANDLE; -new Handle:stm_adminflag_scramble = INVALID_HANDLE; -new Handle:stm_scrambledelay = INVALID_HANDLE; -new Handle:stm_voteenabled = INVALID_HANDLE; -new Handle:stm_votewin = INVALID_HANDLE; -new Handle:stm_votedelay = INVALID_HANDLE; -new Handle:stm_mp_bonusroundtime = INVALID_HANDLE; -new Handle:g_hAdminMenu = INVALID_HANDLE; -new Handle:g_hTimerPrepScramble = INVALID_HANDLE; -new Handle:g_hTimerClearScrambleForce = INVALID_HANDLE; - -new g_aPlayers[MAXPLAYERS + 1][PlayerData]; - -new bool:g_bIsEnabled = true; -new bool:g_bVoteEnabled = true; -new bool:g_bLogActivity = true; -new bool:g_bScrambleRoundEnd = false; -new g_iVoteDelay, g_iLastVoteTime, g_iTimeLeft; -new Float:g_fScrambleDelay, Float:g_fVoteWin; - -public Plugin:myinfo = -{ - name = "Simple Team Manager", - author = "Simple Plugins", - description = "Manages players and thier team.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -public OnPluginStart() -{ - - /** - Need to create all of our console variables. - */ - CreateConVar("stm_version", PLUGIN_VERSION, "Simple Team Manager Version",FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - stm_enabled = CreateConVar("stm_enabled", "1", "Enable or Disable Simple Team Manager", _, true, 0.0, true, 1.0); - stm_logactivity = CreateConVar("stm_logactivity", "0", "Enable or Disable the disaplying of events in the log", _, true, 0.0, true, 1.0); - stm_adminflag_swapteam = CreateConVar("stm_adminflag_swapteam", "a", "Admin flag to use for the swapteam command. Must be a in char format."); - stm_adminflag_moveplayer = CreateConVar("stm_adminflag_moveplayer", "c", "Admin flag to use for the moveplayer command. Must be a in char format."); - stm_adminflag_scramble = CreateConVar("stm_adminflag_scramble", "c", "Admin flag to use for the scrambleteam command. Must be a in char format."); - stm_scrambledelay = CreateConVar("stm_scrambledelay", "15", "Delay to scramble teams"); - stm_voteenabled = CreateConVar("stm_voteenabled", "1", "Enable or Disable voting to scramble the teams", _, true, 0.0, true, 1.0); - stm_votewin = CreateConVar("stm_votewin", "0.45", "Win percentage vote must win by", _, true, 0.0, true, 1.0); - stm_votedelay = CreateConVar("stm_votedelay", "600", "Delay before another vote can be cast"); - stm_mp_bonusroundtime = FindConVar("mp_bonusroundtime"); - - - /** - Need deal with changes to the console variables after the plugin is loaded. - We could not do this and just call the actual console variable each time we need it, but it's not efficent. - */ - HookConVarChange(stm_enabled, ConVarSettingsChanged); - HookConVarChange(stm_logactivity, ConVarSettingsChanged); - HookConVarChange(stm_scrambledelay, ConVarSettingsChanged); - HookConVarChange(stm_voteenabled, ConVarSettingsChanged); - HookConVarChange(stm_votewin, ConVarSettingsChanged); - HookConVarChange(stm_votedelay, ConVarSettingsChanged); - - /** - Need to register the commands we are going to create and use. - */ - RegConsoleCmd("sm_swapteam", Command_SwapTeam, "sm_swapteam <[0]instant/[1]queued>: Swaps your team to the other team"); - RegConsoleCmd("sm_moveplayer", Command_MovePlayer, "sm_moveplayer <[0]instant/[1]ondeath> <[0]unforced/[1]forced>: Moves a player to the specified team"); - RegConsoleCmd("sm_scrambleteams", Command_ScrambleTeams, "sm_scrambleteams: <[0]now/[1]roundend> <[0]dontrestart/[1]restartround> Scrambles the current teams"); - RegConsoleCmd("sm_votescramble", Command_VoteScramble, "sm_votescramble: Starts a vote to scramble the teams"); - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[STM] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_death", HookPlayerDeath, EventHookMode_Post); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Post); - switch (g_CurrentMod) - { - case GameType_TF: - { - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - } - case GameType_DOD: - { - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_Post); - } - default: - { - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - - /** - Now we have to deal with the admin menu. If the admin library is loaded call the function to add our items. - */ - new Handle:gTopMenu; - if (LibraryExists("adminmenu") && ((gTopMenu = GetAdminTopMenu()) != INVALID_HANDLE)) - { - OnAdminMenuReady(gTopMenu); - } - - /** - Load translations and .cfg file - */ - LoadTranslations ("simpleteammanager.phrases"); - AutoExecConfig(true, "plugin.simpleteammanager"); - LogAction(0, -1, "[STM] Simple Team Manager is loaded."); -} - -public OnAllPluginsLoaded() -{ - //something -} - -public OnLibraryRemoved(const String:name[]) -{ - if (StrEqual(name, "adminmenu")) - { - - /** - Looks like the admin menu was removed. Set the global. - */ - g_hAdminMenu = INVALID_HANDLE; - } - else if (StrEqual(name, "simpleplugins")) - { - SetFailState("Required plugin Simple SourceMod Plugins Core was removed."); - } -} - -public OnConfigsExecuted() -{ - - /** - Once we loaded up all the console variables from the config file, lets now set all the global variables we will use. - */ - g_bIsEnabled = GetConVarBool(stm_enabled); - g_bLogActivity = GetConVarBool(stm_logactivity); - g_fScrambleDelay = GetConVarFloat(stm_scrambledelay); - g_iVoteDelay = GetConVarInt(stm_votedelay); - g_fVoteWin = GetConVarFloat(stm_votewin); - g_iLastVoteTime = RoundFloat(GetEngineTime()); - g_bScrambleRoundEnd = false; - g_hTimerClearScrambleForce = INVALID_HANDLE; - - /** - Report enabled - */ - if (g_bIsEnabled) - { - LogAction(0, -1, "[STM] Simple Team Manager is ENABLED."); - } - else - { - LogAction(0, -1, "[STM] Simple Team Manager is DISABLED."); - } - - if (g_bLogActivity) - { - LogAction(0, -1, "[STM] Log Activity ENABLED."); - } - else - { - LogAction(0, -1, "[STM] Log Activity DISABLED."); - } -} - -/* COMMANDS */ - -public Action:Command_SwapTeam(client, args) -{ - - /** - Make sure we are enabled, if not bug out. - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - If this was ran from the console bug out. - */ - if (client == 0) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure the client is authorized to run this command. - */ - decl String:sFlags[5]; - GetConVarString(stm_adminflag_swapteam, sFlags, sizeof(sFlags)); - if (!SM_IsValidAdmin(client, sFlags)) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Lets make sure the client is one a team we can swap. - If he is we set the global array to the opposite team. - */ - new iTeam = GetClientTeam(client); - if (iTeam == g_aCurrentTeams[Team1]) - { - g_aPlayers[client][iNewTeam] = g_aCurrentTeams[Team2]; - } - else if (iTeam == g_aCurrentTeams[Team2]) - { - g_aPlayers[client][iNewTeam] = g_aCurrentTeams[Team1]; - } - else - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "InValidTeam", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check to see if we have command arguments. - */ - if (GetCmdArgs()) - { - - /** - We do, so lets get it and see if the client wants to be switched instantly or queued for death. - */ - decl String:sArg[5]; - GetCmdArg(1, sArg, sizeof(sArg)); - new iWantsQue = StringToInt(sArg); - if (iWantsQue && !g_aPlayers[client][bQueue]) - { - - /** - He wants the que and isn't already in it, set the global array. - */ - g_aPlayers[client][bQueue] = true; - ReplyToCommand(client, "\x01\x04[STM]\x01 %T", "PlayerQueue", LANG_SERVER); - } - else if (!iWantsQue) - { - - /** - He wants to be switched right now, lets call the stock function. - */ - SM_MovePlayer(client, g_aPlayers[client][iNewTeam]); - } - } - else - { - - /** - There are no command arguments so we build and display the swap menu. - */ - DisplaySwapModeMenu(client, client); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_MovePlayer(client, args) -{ - - /** - Make sure we are enabled, if not bug out. - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the client is authorized to run this command. - */ - decl String:sFlags[5]; - GetConVarString(stm_adminflag_moveplayer, sFlags, sizeof(sFlags)); - if (!SM_IsValidAdmin(client, sFlags)) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check to see if we have command arguments. - */ - new iCmdArgs = GetCmdArgs(); - if (iCmdArgs == 0) - { - - /** - We don't. Build the player menu, display it, and bug out. - */ - DisplayPlayerMenu(client); - return Plugin_Handled; - } - - /** - Check the first argument - If should be a players name or userid. - */ - decl String:sPlayer[64]; - GetCmdArg(1, sPlayer, sizeof(sPlayer)); - new iPlayerIndex = FindTarget(client, sPlayer, true, true); - if (iPlayerIndex == -1 || !IsClientInGame(iPlayerIndex)) - { - - /** - We don't know who this is. Build the player menu, display it, and bug out. - */ - DisplayPlayerMenu(client); - return Plugin_Handled; - } - - /** - We have figured out the first argument, lets check the second. - If should be the team the client wants to put the player on. - */ - if (iCmdArgs >= 2) - { - - /** - We have a command argument at least, lets see if we can identify the team. - */ - decl String:sTeam[24]; - GetCmdArg(2, sTeam, sizeof(sTeam)); - - new iTeam = StringToInt(sTeam); - if (SM_IsValidTeam(iTeam)) - { - - /** - It's a vaild team so lets set the global array to the new team. - */ - g_aPlayers[iPlayerIndex][iNewTeam] = iTeam; - } - else - { - - /** - It's not a vaild team so set the menu to display to the team menu. - */ - DisplayTeamMenu(client, iPlayerIndex); - return Plugin_Handled; - } - } - else - { - /** - We were not given a team, display the team menu. - */ - DisplayTeamMenu(client, iPlayerIndex); - return Plugin_Handled; - } - - /** - Check to see if we were given any more command arguments and found a team. - */ - if (iCmdArgs < 3) - { - - /** - No more command arguments and found a team. - Now lets check to see if the player is a spectator. If he is there is no reason to ask if it's instant or on death... he can't die. - */ - if (!IsClientObserver(iPlayerIndex)) - { - - /** - Not a spectator so display the swapmode menu. - */ - DisplaySwapModeMenu(client, iPlayerIndex); - } - else - { - - /** - The player is a spectator. - We make sure the player is not set to switch on death, since a spec can't die. - */ - g_aPlayers[iPlayerIndex][bQueue] = false; - } - } - - /** - We have figured out the second argument, lets check the third. - If should be the how the client wants to move the player: instant/on death. - */ - if (iCmdArgs >= 3) - { - - /** - The client gave us a command argument, lets check it. - */ - decl String:sSwapMode[5]; - GetCmdArg(3, sSwapMode, sizeof(sSwapMode)); - new iWantsQue = StringToInt(sSwapMode); - if (iWantsQue) - { - - /** - The client wants to que the player, set the global array. - */ - g_aPlayers[iPlayerIndex][bQueue] = true; - } - else - { - - /** - The client doesn't want to que the player, set the global array. - */ - g_aPlayers[iPlayerIndex][bQueue] = false; - } - } - else - { - /** - No swapmode argument, display the menu - */ - DisplaySwapModeMenu(client, iPlayerIndex); - } - - if (iCmdArgs >= 4) - { - - /** - Since we are compiling for Simple Team Balancer, and given a 4th argument, lets check it. - If should be the if the client wants to force the player to that team. - */ - decl String:sPlayerForced[5]; - GetCmdArg(4, sPlayerForced, sizeof(sPlayerForced)); - new iForceHim = StringToInt(sPlayerForced); - if (iForceHim) - { - - /** - The client wants to force the player - */ - SM_SetForcedTeam(iPlayerIndex, g_aPlayers[iPlayerIndex][iNewTeam]); - } - else - { - - /** - The client doesn't want to force the player - */ - SM_ClearForcedTeam(iPlayerIndex); - } - } - else - { - - } - - /** - We found and processed all the arguments. - */ - if (!IsPlayerAlive(iPlayerIndex)) - { - - /** - The player is not alive or died during this process so we just move him. - */ - SM_MovePlayer(iPlayerIndex, g_aPlayers[iPlayerIndex][iNewTeam]); - } - else - { - if (!g_aPlayers[iPlayerIndex][bQueue]) - { - - /** - The player is alive and is not set to be queued so we just move him. - */ - SM_MovePlayer(iPlayerIndex, g_aPlayers[iPlayerIndex][iNewTeam]); - } - } - - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_ScrambleTeams(client, args) -{ - - /** - Make sure we are enabled, if not bug out. - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the client is authorized to run this command. - */ - decl String:sFlags[5]; - GetConVarString(stm_adminflag_scramble, sFlags, sizeof(sFlags)); - if (!SM_IsValidAdmin(client, sFlags)) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check if a scramble timer was already called, if so close it down. - */ - if (g_hTimerPrepScramble != INVALID_HANDLE) - { - CloseHandle(g_hTimerPrepScramble); - g_hTimerPrepScramble = INVALID_HANDLE; - } - - /** - Check if we have any command arguments. - If we don't we display the scramble menu and bug out. - */ - new iCmdArgs = GetCmdArgs(); - if (iCmdArgs == 0) - { - DisplayScrambleMenu(client); - return Plugin_Handled; - } - - /** - We have a command argument. - It should be whether or not to scramble at round end. - */ - decl String:sRoundEnd[5]; - GetCmdArg(1, sRoundEnd, sizeof(sRoundEnd)); - if (StringToInt(sRoundEnd)) - { - /** - The client wants to scramble at round end so we set the global bool. - */ - g_bScrambleRoundEnd = true; - } - else - { - g_bScrambleRoundEnd = false; - } - - /** - Check for another command argument. - It should be whether or not to restart the round. - */ - decl String:sRestartRound[5]; - new bool:bRestartRound = false; - GetCmdArg(1, sRestartRound, sizeof(sRestartRound)); - if (StringToInt(sRestartRound)) - { - bRestartRound = true; - } - - /** - Now we start the scramble timer. - */ - StartScrambleTimer(_, bRestartRound); - - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_VoteScramble(client, args) -{ - - /** - Make sure we are enabled, if not bug out. - */ - if (!g_bVoteEnabled || !g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Make sure there is a vote in progress, if so bug out. - */ - if (IsVoteInProgress()) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "VoteInProgress", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure enough time has passed since the last vote. - */ - new iVoteTime = RoundFloat(GetEngineTime()); - if (iVoteTime - g_iLastVoteTime <= g_iVoteDelay) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "ScrambleTime", LANG_SERVER); - return Plugin_Handled; - } - - /** - Enough time has passed so reset the global vote time to now. - */ - g_iLastVoteTime = iVoteTime; - - /** - Build the vote menu and send it to everyone. - */ - new Handle:hMenu = CreateMenu(Menu_VoteScramble); - SetMenuTitle(hMenu, "Scramble Teams?"); - AddMenuItem(hMenu, VOTE_YES, "Yes"); - AddMenuItem(hMenu, VOTE_NO, "No"); - SetMenuExitButton(hMenu, false); - VoteMenuToAll(hMenu, 20); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -/* HOOKED EVENTS */ - -public HookPlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Find out who died. - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - - /** - Find out how the client died. - */ - new String:sWeapon[64]; - GetEventString(event, "weapon", sWeapon, sizeof(sWeapon)); - if (StrEqual(sWeapon, "world", false)) - { - - /** - He died because he changed teams so cleanup and bug out. - */ - s_CleanUp(iClient); - return; - } - - /** - Find out if this player was queued to change teams. - */ - if (g_aPlayers[iClient][bQueue]) - { - /** - Looks like he was, so call the stock function to move him. - */ - SM_MovePlayer(iClient, g_aPlayers[iClient][iNewTeam]); - } -} - -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Find out who changed teams. - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - - /** - If he was queued to switch teams we cleanup the variables. The client did it themself. - */ - if (g_aPlayers[iClient][bQueue]) - { - s_CleanUp(iClient); - } -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get the amount of time left in the map. - */ - new iTimeLeft; - GetMapTimeLeft(iTimeLeft); - - /** - Check to see if we are supposed to scramble at the end of the round and that there is enough time left in the map. - */ - if (g_bScrambleRoundEnd && iTimeLeft >= 60) - { - - /** - Check to see if there is a scramble timer in action and if so close it down. - */ - if (g_hTimerPrepScramble != INVALID_HANDLE) - { - CloseHandle(g_hTimerPrepScramble); - g_hTimerPrepScramble = INVALID_HANDLE; - } - - /** - Determine the round end chat time and run the scramble 1 second before it ends. - */ - new Float:fDelay = GetConVarFloat(stm_mp_bonusroundtime); - fDelay -= 1.0; - StartScrambleTimer(fDelay); - } -} - -public OnClientPostAdminCheck(client) -{ - - /** - Determine if the client has the flag to use the swapteam command. - */ - decl String:sFlags[5]; - GetConVarString(stm_adminflag_swapteam, sFlags, sizeof(sFlags)); - if (SM_IsValidAdmin(client, sFlags)) - { - /** - The client does so lets create a timer to run an advertise to tell him about it. - */ - CreateTimer (60.0, Timer_WelcomeAdvert, client); - } -} - -public OnClientDisconnect(client) -{ - - /** - Cleanup the clients variables. - */ - s_CleanUp(client); -} - -public SM_OnPlayerMoved(Handle:plugin, client, team) -{ - - /** - Make sure we called the move function - */ - if (plugin != GetMyHandle()) - { - if (g_bLogActivity) - { - LogAction(0, client, "[STM] Callback was not started with current plugin, bugging out."); - } - return; - } - - decl String:sPlayerName[64]; - GetClientName(client, sPlayerName, sizeof(sPlayerName)); - - PrintToChat(client, "\x01\x04[SM]\x01 %T", "PlayerSwitched", LANG_SERVER); - - s_CleanUp(client); -} - -/* TIMER FUNCTIONS */ - -public Action:Timer_PrepTeamScramble(Handle:timer, any:data) -{ - new bool:bRestartRound = data; - /** - Call the scramble the teams stock function. - */ - PrepTeamScramble(bRestartRound); - - /** - Reset the timer handle so we know the timer is done. - */ - g_hTimerPrepScramble = INVALID_HANDLE; - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Timer_ScrambleTheTeams(Handle:timer, any:data) -{ - new iPlayers[MAXPLAYERS + 1]; - new iCount, i, bool:bTeam, bool:bRestartRound = data; - - /** - Get all the client index numbers of valid players - */ - for(i = 1; i <= MaxClients; i++) - { - if(IsClientInGame(i)) // && !IsFakeClient(i)) - { - iPlayers[iCount++] = i; - } - } - - /** - Randomly sort the players - */ - SortIntegers(iPlayers, iCount, Sort_Random); - - /** - Loop through all the players and assign each one to a team, alternating each time - */ - for(i = 0; i < iCount; i++) - { - if (!bRestartRound) - { - /** - We didn't want to restart the round, so we move them to spec 1 at a time. - */ - SM_MovePlayer(iPlayers[i], g_aCurrentTeams[Spectator]); - } - SM_MovePlayer(iPlayers[i], bTeam ? g_aCurrentTeams[Team2] : g_aCurrentTeams[Team1]); - SM_SetForcedTeam(iPlayers[i], bTeam ? g_aCurrentTeams[Team2] : g_aCurrentTeams[Team1], true); - bTeam = !bTeam; - } - - /** - Reset this variable since we completed a scramble - */ - g_bScrambleRoundEnd = false; - - if (g_hTimerClearScrambleForce != INVALID_HANDLE) - { - CloseHandle(g_hTimerClearScrambleForce); - g_hTimerClearScrambleForce = INVALID_HANDLE; - } - - g_hTimerClearScrambleForce = CreateTimer(300.0, Timer_ClearScrambleForce, _, TIMER_FLAG_NO_MAPCHANGE); - - ServerCommand("mp_timelimit %i", g_iTimeLeft / 60); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Timer_ClearScrambleForce(Handle:timer, any:data) -{ - - for(new i = 1; i <= MaxClients; i++) - { - if(IsClientInGame(i)) // && !IsFakeClient(i)) - { - SM_ClearForcedTeam(i); - PrintToChat(i, "\x01\x04[SM]\x01 Your forced team status has been cleared"); - } - } - - g_hTimerClearScrambleForce = INVALID_HANDLE; - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Timer_WelcomeAdvert(Handle:timer, any:client) -{ - - /** - Lets make sure the client is connected and actually in the game. - */ - if (IsClientConnected(client) && IsClientInGame(client)) - { - - /** - We are good to go so lets tell him about the swapteam command. - */ - PrintToChat (client, "\x01\x04[STM]\x01 %T", "SwapTeamMsg", LANG_SERVER); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -/* STOCK FUNCTIONS */ - -stock s_CleanUp(iClient) -{ - - /** - Reset all the client variables - */ - g_aPlayers[iClient][bQueue] = false; - g_aPlayers[iClient][iNewTeam] = 0; -} - -stock StartScrambleTimer(Float:fdelay = 0.0, bool:bRestartRound = false) -{ - if (fdelay == 0.0) - { - fdelay = g_fScrambleDelay; - } - if (g_hTimerPrepScramble != INVALID_HANDLE) - { - CloseHandle(g_hTimerPrepScramble); - g_hTimerPrepScramble = INVALID_HANDLE; - } - PrintCenterTextAll("%T", "Scramble", LANG_SERVER); - g_hTimerPrepScramble = CreateTimer(fdelay, Timer_PrepTeamScramble, bRestartRound, TIMER_FLAG_NO_MAPCHANGE); -} - -stock PrepTeamScramble(bool:bRestartRound = false) -{ - new iPlayers[MAXPLAYERS + 1]; - new iCount; - - GetMapTimeLeft(g_iTimeLeft); - - if (bRestartRound) - { - - for(new i = 1; i <= MaxClients; i++) - { - if(IsClientInGame(i)) - // && !IsFakeClient(i)) - { - iPlayers[iCount++] = i; - SM_ClearForcedTeam(i); - SM_ClearBuddy(i); - SM_MovePlayer(i, g_aCurrentTeams[Spectator]); - } - } - } - else - { - //Can't move them all to spec at the same time - for(new i = 1; i <= MaxClients; i++) - { - if(IsClientInGame(i)) - // && !IsFakeClient(i)) - { - iPlayers[iCount++] = i; - SM_ClearForcedTeam(i); - SM_ClearBuddy(i); - //SM_MovePlayer(i, g_aCurrentTeams[Spectator]); - } - } - } - CreateTimer(4.0, Timer_ScrambleTheTeams, bRestartRound, TIMER_FLAG_NO_MAPCHANGE); -} - -/* CONSOLE VARIABLE CHANGE EVENT */ - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (convar == stm_enabled) { - if (StringToInt(newValue) == 0) { - g_bIsEnabled = false; - LogAction(0, -1, "[STM] Simple Team Manager is loaded and disabled."); - } else { - g_bIsEnabled = true; - LogAction(0, -1, "[STM] Simple Team Manager is loaded and enabled."); - } - } - else if (convar == stm_logactivity) { - if (StringToInt(newValue) == 0) { - g_bLogActivity = false; - LogAction(0, -1, "[STM] Log Activity DISABLED."); - } else { - g_bLogActivity = true; - LogAction(0, -1, "[STM] Log Activity ENABLED."); - } - } - else if (convar == stm_scrambledelay) - g_fScrambleDelay = StringToFloat(newValue); - else if (convar == stm_votewin) - g_fVoteWin = StringToFloat(newValue); - else if (convar == stm_votedelay) - g_iVoteDelay = StringToInt(newValue); - else if (convar == stm_voteenabled) { - if (StringToInt(newValue) == 0) - g_bVoteEnabled = false; - else - g_bVoteEnabled = true; - } -} - -/* MENU CODE */ - -public OnAdminMenuReady(Handle:topmenu) -{ - if (topmenu == g_hAdminMenu) - return; - g_hAdminMenu = topmenu; - new TopMenuObject:player_commands = FindTopMenuCategory(g_hAdminMenu, ADMINMENU_PLAYERCOMMANDS); - new TopMenuObject:server_commands = FindTopMenuCategory(g_hAdminMenu, ADMINMENU_SERVERCOMMANDS); - if (player_commands == INVALID_TOPMENUOBJECT) - return; - - AddToTopMenu(g_hAdminMenu, - "moveplayer", - TopMenuObject_Item, - AdminMenu_MovePlayer, - player_commands, - "moveplayer", - ADMFLAG_BAN); - - AddToTopMenu(g_hAdminMenu, - "scrambleteams", - TopMenuObject_Item, - AdminMenu_Scrambleteams, - server_commands, - "scrambleteams", - ADMFLAG_BAN); -} - -public AdminMenu_MovePlayer(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) -{ - if (action == TopMenuAction_DisplayOption) - Format(buffer, maxlength, "Move Player"); - else if (action == TopMenuAction_SelectOption){ - DisplayPlayerMenu(param); - } -} - -public AdminMenu_Scrambleteams(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) -{ - if (action == TopMenuAction_DisplayOption) - Format(buffer, maxlength, "Scramble Teams"); - else if (action == TopMenuAction_SelectOption) { - DisplayScrambleMenu(param); - } -} - -public Menu_SelectPlayer(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - DisplayTeamMenu(param1, GetClientOfUserId(StringToInt(sSelection))); - } else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -public Menu_SelectTeam(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new iTeam; - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - decl String:sIndex[64]; - if (SplitString(sSelection, "A", sIndex, sizeof(sIndex)) != -1) - iTeam = g_aCurrentTeams[Team1]; - else if (SplitString(sSelection, "B", sIndex, sizeof(sIndex)) != -1) - iTeam = g_aCurrentTeams[Team2]; - else { - SplitString(sSelection, "C", sIndex, sizeof(sIndex)); - iTeam = g_aCurrentTeams[Spectator]; - } - new iTarget = StringToInt(sIndex); - g_aPlayers[iTarget][iNewTeam] = iTeam; - DisplaySwapModeMenu(param1, iTarget); - } else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -public Menu_SwapMode(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - decl String:sIndex[64]; - - if (SplitString(sSelection, "A", sIndex, sizeof(sIndex)) == -1) - { - SplitString(sSelection, "B", sIndex, sizeof(sIndex)); - } - - new iTarget = StringToInt(sIndex); - - if (StrContains(sSelection, "A", true) != -1) - { - g_aPlayers[iTarget][bQueue] = false; - } - else if (StrContains(sSelection, "B", true) != -1) - { - g_aPlayers[iTarget][bQueue] = true; - } - - if (param1 == iTarget && !g_aPlayers[iTarget][bQueue]) - { - SM_MovePlayer(iTarget, g_aPlayers[iTarget][iNewTeam]); - } - else - { - DisplayForceModeMenu(param1, iTarget); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - { - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } - return; -} - -public Menu_ForceMode(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - decl String:sIndex[64]; - if (SplitString(sSelection, "A", sIndex, sizeof(sIndex)) == -1) - { - SplitString(sSelection, "B", sIndex, sizeof(sIndex)); - } - new iTarget = StringToInt(sIndex); - if (StrContains(sSelection, "A", true) != -1) - { - SM_ClearForcedTeam(iTarget); - } - else if (StrContains(sSelection, "B", true) != -1) - { - SM_SetForcedTeam(iTarget, g_aPlayers[iTarget][iNewTeam], true); - } - if (!g_aPlayers[iTarget][bQueue]) - { - SM_MovePlayer(iTarget, g_aPlayers[iTarget][iNewTeam]); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - { - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } - return; -} - -public Menu_VoteScramble(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_VoteEnd) { - new winning_votes, total_votes; - GetMenuVoteInfo(param2, winning_votes, total_votes); - if (param1 == 0) { - if (float(total_votes) / float(winning_votes) < g_fVoteWin) { - PrintToChatAll("\x01\x04[SM]\x01 %T", "VoteScramble2", LANG_SERVER, winning_votes, total_votes); - return; - } - PrintCenterTextAll("[SM] %T", "Scramble", LANG_SERVER); - PrintToChatAll("\x01\x04[SM]\x01 %T", "VoteScramble1", LANG_SERVER, winning_votes, total_votes); - StartScrambleTimer(); - } - if (param1 == 1) { - PrintToChatAll("\x01\x04[SM]\x01 %T", "VoteScramble2", LANG_SERVER, winning_votes, total_votes); - } - } - if (action == MenuAction_End) - CloseHandle(menu); -} - -public Menu_ScrambleTeams(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "NOW", false)) - g_bScrambleRoundEnd = false; - else - g_bScrambleRoundEnd = true; - DisplayScrambleMenu2(param1); - } else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -public Menu_ScrambleTeams2(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[64]; - new bool:bRestartRound; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "NO", false)) - { - bRestartRound = false; - } - else - { - bRestartRound = true; - } - StartScrambleTimer(_, bRestartRound); - } else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -stock DisplayScrambleMenu(iClient) -{ - new Handle:hMenu = CreateMenu(Menu_ScrambleTeams); - SetMenuTitle(hMenu, "Select When to Scramble:"); - AddMenuItem(hMenu, "NOW", "Instantly"); - AddMenuItem(hMenu, "END", "At Round End"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplayScrambleMenu2(iClient) -{ - new Handle:hMenu = CreateMenu(Menu_ScrambleTeams2); - SetMenuTitle(hMenu, "Select When to Scramble:"); - AddMenuItem(hMenu, "NO", "No Round Restart"); - AddMenuItem(hMenu, "YES", "Restart Round"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplaySwapModeMenu(iClient, iTarget) -{ - new Handle:hMenu = CreateMenu(Menu_SwapMode); - decl String:optionA[64]; - decl String:optionB[64]; - Format(optionA, sizeof(optionA), "%iA", iTarget); - Format(optionB, sizeof(optionB), "%iB", iTarget); - SetMenuTitle(hMenu, "Select When to Swap:"); - AddMenuItem(hMenu, optionA, "Instantly (Kills)"); - if (!IsClientObserver(iTarget)) - AddMenuItem(hMenu, optionB, "Queue on next death"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplayForceModeMenu(iClient, iTarget) -{ - new Handle:hMenu = CreateMenu(Menu_ForceMode); - decl String:optionA[64]; - decl String:optionB[64]; - Format(optionA, sizeof(optionA), "%iA", iTarget); - Format(optionB, sizeof(optionB), "%iB", iTarget); - SetMenuTitle(hMenu, "Select Force Mode:"); - AddMenuItem(hMenu, optionA, "UnForced"); - AddMenuItem(hMenu, optionB, "Forced"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplayTeamMenu(iClient, iTarget) -{ - new Handle:hMenu = CreateMenu(Menu_SelectTeam); - decl String:optionA[64]; - decl String:optionB[64]; - decl String:optionC[64]; - Format(optionA, sizeof(optionA), "%iA", iTarget); - Format(optionB, sizeof(optionB), "%iB", iTarget); - Format(optionC, sizeof(optionC), "%iC", iTarget); - SetMenuTitle(hMenu, "Select Team:"); - AddMenuItem(hMenu, optionA, "Team One"); - AddMenuItem(hMenu, optionB, "Team Two"); - AddMenuItem(hMenu, optionC, "Spectator"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplayPlayerMenu(iClient) -{ - new Handle:hMenu = CreateMenu(Menu_SelectPlayer); - AddTargetsToMenu(hMenu, 0, true, false); - SetMenuTitle(hMenu, "Select A Player:"); - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} diff --git a/Simple Team Balancer/addons/sourcemod/translations/simpledonatorbenefits.phrases.txt b/Simple Team Balancer/addons/sourcemod/translations/simpledonatorbenefits.phrases.txt deleted file mode 100644 index 3826846..0000000 --- a/Simple Team Balancer/addons/sourcemod/translations/simpledonatorbenefits.phrases.txt +++ /dev/null @@ -1,62 +0,0 @@ -"Phrases" -{ - "PlayerLevelCmd" - { - "en" "Command must be run at the player level" - "fr" "Cette commande doit être tapée en jeu" - "hu" "Ezt a parancsot jatekosi szinten kell futtatni!" - } - "RestrictedCmd" - { - "en" "You must be a donator or admin to run this command" - "fr" "Vous devez être un donateur ou un admin pour lancer cette commande" - "hu" "A parancs futtatasahoz admin, vagy tamogatoi szint szukseges!" - } - "InValidTeam" - { - "en" "You must be on red or blue to swap teams" - "fr" "Vous devez être RED ou BLU pour changer d'équipe" - "hu" "Jatekban kell lenned, hogy megcsereld a csapatokat!" - } - "PlayerQueue" - { - "en" "You have been queued to swap teams on next death" - "fr" "Vous avez été mis en attente pour changer d'équipe lors de votre prochaine mort" - "hu" "A kovetkezo halalnal csapatcsere lesz" - } - "PlayerSwitched" - { - "en" "Your team has been switched as requested" - "fr" "Vous avez changé d'équipe comme demandé" - "hu" "A keresnek eleget teve a csapatod meg lett csererlve" - } - "SwapTeamMsg" - { - "en" "Type /swapteam or !swapteam to swap your team!" - } - "ReachedCount" - { - "en" "You have reached your health limit. You must die before you can use it again" - } - "AtMaxHealth" - { - "en" "You are already at your maximum health!" - } - "ToMaxHealth" - { - "en" "Instant health bonus applied! You are not at your maximun health!" - } - "HealthBonus" - { - "en" "Instant health bonus applied!" - } - "PublicJoinMessage" - { - "#format" "{1:s}" - "en" "{1} a [donator] as joined the server" - } - "PrivateJoinMessage" - { - "en" "Thanks for donating!" - } -} \ No newline at end of file diff --git a/Simple Team Balancer/addons/sourcemod/translations/simplespectate.phrases.txt b/Simple Team Balancer/addons/sourcemod/translations/simplespectate.phrases.txt deleted file mode 100644 index 2d1a096..0000000 --- a/Simple Team Balancer/addons/sourcemod/translations/simplespectate.phrases.txt +++ /dev/null @@ -1,42 +0,0 @@ -"Phrases" -{ - "Stopped spectating" - { - "#format" "{1:s}" - "en" "Stopped tracking player: {1}" - } - "Yourself" - { - "en" "You can't spectate yourself" - } - "Spectator" - { - "en" "You can't spectate another spectator" - } - "Spectating" - { - "#format" "{1:s}" - "en" "Now spectating {1}. Type !stopspec or /stopspec to stop spectating this player" - } - "Invalid Target" - { - "en" "Invalid target" - } - "Cant Target" - { - "en" "Can't target this player" - } - "Must Have Target" - { - "en" "You must be following/tracking a player to punish" - } - "Target Left" - { - "en" "The player you were following/tracking has left" - } - "Punished" - { - "#format" "{1:s}{2:s}{3:s}" - "en" "{1} was punished with a {2} for {3}" - } -} \ No newline at end of file diff --git a/Simple Team Balancer/addons/sourcemod/translations/simpleteammanager.phrases.txt b/Simple Team Balancer/addons/sourcemod/translations/simpleteammanager.phrases.txt deleted file mode 100644 index f2093a7..0000000 --- a/Simple Team Balancer/addons/sourcemod/translations/simpleteammanager.phrases.txt +++ /dev/null @@ -1,92 +0,0 @@ -"Phrases" -{ - "PlayerLevelCmd" - { - "en" "Command must be run at the player level" - "fr" "Cette commande doit être tapée en jeu" - "hu" "Ezt a parancsot jatekosi szinten kell futtatni!" - } - "RestrictedCmd" - { - "en" "You must be a donator or admin to run this command" - "fr" "Vous devez être un donateur ou un admin pour lancer cette commande" - "hu" "A parancs futtatasahoz admin, vagy tamogatoi szint szukseges!" - } - "InValidTeam" - { - "en" "You must be on red or blue to swap teams" - "fr" "Vous devez être RED ou BLU pour changer d'équipe" - "hu" "Jatekban kell lenned, hogy megcsereld a csapatokat!" - } - "PlayerInValidTeam" - { - "en" "Player must be on red or blue to swap teams" - "fr" "Le joueur doit être RED ou BLU pour changer d'équipe" - "hu" "Valamelyik csapatban kell lenni, hogy csere legyen" - } - "PlayerQueue" - { - "en" "You have been queued to swap teams on next death" - "fr" "Vous avez été mis en attente pour changer d'équipe lors de votre prochaine mort" - "hu" "A kovetkezo halalnal csapatcsere lesz" - } - "PlayerSwitched" - { - "en" "Your team has been switched" - } - "PlayerSwitched1" - { - "en" "Your team has been switched as requested" - "fr" "Vous avez changé d'équipe comme demandé" - "hu" "A keresnek eleget teve a csapatod meg lett csererlve" - } - "PlayerSwitched2" - { - "en" "Your team has been switched by an Admin" - "fr" "Vous avez été changé d'équipe par un admin" - "hu" "Az Admin megcserelte a csapatodat!" - } - "SwapTeamMsg" - { - "en" "Type /swapteam or !swapteam to swap your team!" - } - "PlayerSwitched3" - { - "#format" "{1:s}" - "en" "{1}'s team has been switched" - "fr" "{1} a changé d'équipe" - "hu" "{1} csapata meg lett cserelve" - } - "Scramble" - { - "en" "Teams are about to be scrambled!" - "fr" "Les équipes vont être rééquilibrés" - "hu" "A csapatok hamarosan meg lesznek keverve!" - } - "VoteScramble1" - { - "#format" "{1:i}{2:i}" - "en" "Vote Scramble successful with {1} votes out of {2}" - "fr" "Le vote d'équilibrage des équipes a réussi avec {1} votes pour sur {2}" - "hu" "A szavazas sikeres volt, {1} szavazat a keveresre a {2} -bol" - } - "VoteScramble2" - { - "#format" "{1:i}{2:i}" - "en" "Vote Scramble failed with {1} votes out of {2}" - "fr" "Le vote d'équilibrage a échoué avec {1} votes pour sur {2}" - "hu" "A szavazas sikertelen volt, {1} szavazat a keveresre a {2} -bol" - } - "VoteInProgress" - { - "en" "A vote is currently in progress" - "fr" "Un vote est actuellement en cours" - "hu" "Egy szavazas mar fut!" - } - "ScrambleTime" - { - "en" "A vote was recently made, please wait" - "fr" "Un vote a déjà été fait récemment, réessayez plus tard" - "hu" "Nemreg volt szavazas, kerlek varj egy kicsit!" - } -} \ No newline at end of file diff --git a/Simple Team Manager/addons/sourcemod/configs/simple-alltalkmanager_events.cfg b/Simple Team Manager/addons/sourcemod/configs/simple-alltalkmanager_events.cfg deleted file mode 100644 index b739cf0..0000000 --- a/Simple Team Manager/addons/sourcemod/configs/simple-alltalkmanager_events.cfg +++ /dev/null @@ -1,43 +0,0 @@ -"game_events" -{ - "teamplay_round_start" - { - "reason" "Round Start" - "setting" "1" - } - "teamplay_setup_finished" - { - "reason" "Setup Period Ended" - "setting" "0" - } - "teamplay_overtime_begin" - { - "reason" "Overtime Began" - "setting" "1" - } - "teamplay_overtime_end" - { - "reason" "Overtime Ended" - "setting" "1" - } - "teamplay_round_win" - { - "reason" "Round Ended" - "setting" "1" - } - "teamplay_suddendeath_begin" - { - "reason" "Sudden Death Began" - "setting" "1" - } - "teamplay_suddendeath_end" - { - "reason" "Sudden Death Ended" - "setting" "1" - } - "teamplay_round_stalemate" - { - "reason" "Stalemate" - "setting" "1" - } -} \ No newline at end of file diff --git a/Simple Team Manager/addons/sourcemod/configs/simple-chatcolors.cfg b/Simple Team Manager/addons/sourcemod/configs/simple-chatcolors.cfg deleted file mode 100644 index 14b98c6..0000000 --- a/Simple Team Manager/addons/sourcemod/configs/simple-chatcolors.cfg +++ /dev/null @@ -1,15 +0,0 @@ -"admin_colors" -{ - "groupname2" - { - "flag" "z" - "namecolor" "{green}" - "textcolor" "{olive}" - } - "groupname1" - { - "flag" "a" - "namecolor" "{teamcolor}" - "textcolor" "{green}" - } -} \ No newline at end of file diff --git a/Simple Team Manager/addons/sourcemod/plugins/simple-alltalkmanager.smx b/Simple Team Manager/addons/sourcemod/plugins/simple-alltalkmanager.smx deleted file mode 100644 index 6122756af68998fb531abcd0d08698e24cff25af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7028 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 diff --git a/Simple Team Manager/addons/sourcemod/plugins/simple-donatorbenefits.smx b/Simple Team Manager/addons/sourcemod/plugins/simple-donatorbenefits.smx deleted file mode 100644 index 821d61d784607595ca400d273a941a42e40de640..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16600 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 diff --git a/Simple Team Manager/addons/sourcemod/plugins/simple-messagesuppression.smx b/Simple Team Manager/addons/sourcemod/plugins/simple-messagesuppression.smx deleted file mode 100644 index cc20dadd37d8ff23d0a64513cc09650f4bdbf24d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4845 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 Blh*(M diff --git a/Simple Team Manager/addons/sourcemod/plugins/simple-spectate.smx b/Simple Team Manager/addons/sourcemod/plugins/simple-spectate.smx deleted file mode 100644 index c6885b041145a73f664650e729a5dcf8b3b0813f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19129 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%0ACwUfid=y*oPG;MRqmWr)g0 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�XP zM5L)&uZne^XHs;_L+03=Xy3CiU1O76^S{TWu{zY}Jlq((BV?9EL=m4MC%~!W0MzeW zOjQv*a;A7AS@l%h9EbjzQ3d}e&j~R0VCoAN)q_>=)m=>e=ZX9w8jM3&o1RO^+0jJ) z

_|h)w;)ME+|h#gx@oo-|ZEuRI5d) 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 z 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 z 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 KvHt-#rc|>H2mv<$ diff --git a/Simple Team Manager/addons/sourcemod/scripting/include/simple-plugins.inc b/Simple Team Manager/addons/sourcemod/scripting/include/simple-plugins.inc deleted file mode 100644 index 8f21956..0000000 --- a/Simple Team Manager/addons/sourcemod/scripting/include/simple-plugins.inc +++ /dev/null @@ -1,337 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Plugins -Description: - Included file for core plugin in the Simple Plugins project -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -*************************************************************************/ - -#if defined _simpleplugin_included - #endinput -#endif - -#define _simpleplugin_included - -#define CORE_INC_VERSION "1.1.$Rev$" - -#pragma semicolon 1 -#include -#undef REQUIRE_PLUGIN -#include -#define REQUIRE_PLUGIN -#undef REQUIRE_EXTENSIONS -#undef AUTOLOAD_EXTENSIONS -#tryinclude -#tryinclude -#tryinclude -#define AUTOLOAD_EXTENSIONS -#define REQUIRE_EXTENSIONS - -enum e_SupportedMods -{ - GameType_Unknown, - GameType_AOC, - GameType_CSS, - GameType_DOD, - GameType_FF, - GameType_HIDDEN, - GameType_HL2DM, - GameType_INS, - GameType_L4D, - GameType_NEO, - GameType_SGTLS, - GameType_TF, - GameType_ZPS -}; - -enum e_Teams -{ - Unknown, - Spectator, - Team1, - Team2 -}; - -new g_aCurrentTeams[e_Teams]; -new e_SupportedMods:g_CurrentMod; -new String:g_sGameName[e_SupportedMods][32] = { "Unknown", - "Age of Chivalry", - "Counter Strike", - "Day Of Defeat", - "Fortress Forever", - "Hidden: Source", - "Half Life 2: Deathmatch", - "Insurgency", - "Left 4 Dead", - "Neotokyo", - "Stargate TLS", - "Team Fortress 2", - "Zombie Panic: Source" - }; - -public SharedPlugin:_pl_simpleplugin = -{ - name = "simple-plugins", - file = "simple-plugins.smx", -#if defined REQUIRE_PLUGIN - required = 1 -#else - required = 0 -#endif -}; - -#if !defined REQUIRE_PLUGIN -public _pl_simpleplugin_SetNTVOptional() -{ - MarkNativeAsOptional("SM_MovePlayer"); - MarkNativeAsOptional("SM_SetForcedTeam"); - MarkNativeAsOptional("SM_GetForcedTeam"); - MarkNativeAsOptional("SM_ClearForcedTeam"); - MarkNativeAsOptional("SM_GetForcedPlayer"); - MarkNativeAsOptional("SM_AssignBuddy"); - MarkNativeAsOptional("SM_SearchBuddy"); - MarkNativeAsOptional("SM_LockBuddy"); - MarkNativeAsOptional("SM_IsBuddyLocked"); - MarkNativeAsOptional("SM_ClearBuddy"); - MarkNativeAsOptional("SM_IsValidAdmin"); - MarkNativeAsOptional("SM_IsValidTeam"); -} -#endif - -/********************************************************************** - * When a player has to moved - * - * @param plugin Plugin that initiated the move - * @param client The client index of the player that was moved - * @param team The team index the player was moved to - * @noreturn - **********************************************************************/ -forward SM_OnPlayerMoved(Handle:plugin, client, team); - -/********************************************************************** - * Move a player to the supplied team - * - * @param client The client index of the player to be moved - * @param team The team to move the player to - * @noreturn - * @error Invalid client or team index - **********************************************************************/ -native SM_MovePlayer(client, team); - -/********************************************************************** - * Move a player to the supplied team - * - * @param client The client index of the player to set - * @param team The team to move the to set - * @param override Whether or not to override another plugin - * @return True if successful, false if not - * @error Invalid client or team index - **********************************************************************/ -native SM_SetForcedTeam(client, team, bool:override = false); - -/********************************************************************** - * Gets the client's forced team index - * - * @param client The client index of the player to check - * @param plugin Optional: The plugin handle of the plugin - that set the team - * @return The team index of the forced team - Zero if no forced team - * @error Invalid client index - **********************************************************************/ -native SM_GetForcedTeam(client, &Handle:plugin = INVALID_HANDLE); - -/********************************************************************** - * Clears a client's forced team - * - * @param client The client index of the player to check - * @return True if successful, false if not - * @error Invalid client index - **********************************************************************/ -native SM_ClearForcedTeam(client); - -/********************************************************************** - * Gets a forced player on the wrong that is currently on the wrong team - * This will only return a player if the calling plugin assigned the team - * - * @param team The team index the player should be on - * @return The client index of the player - Zero if no player found - * @error Invalid client index - **********************************************************************/ -native SM_GetForcedPlayer(team); - -/********************************************************************** - * Assign a players buddy - * - * @param client The client index of the player to assign - * @param player The player index of the player to assign - * @param override Whether or not to override a player lock - * @return True if successful, false if not - * @error Invalid client or player index - **********************************************************************/ -native bool:SM_AssignBuddy(client, player, bool:override = false); - -/********************************************************************** - * Rturns the client's buddy - * - * @param client The client index of the player to assign - * @return The client index of the player's buddy - Zero if no buddy - * @error Invalid client index - **********************************************************************/ -native SM_GetClientBuddy(client); - -/********************************************************************** - * Set the buddy lock setting for a client - * - * @param client The client index of the player to assign - * @param setting Setting to set, True or False - * @return True if successful, false if not - * @error Invalid client index - **********************************************************************/ -native bool:SM_LockBuddy(client, bool:setting); - -/********************************************************************** - * Returns the buddy lock setting for a client - * - * @param client The client index of the player to assign - * @return True if locked, false if not - * @error Invalid client index - **********************************************************************/ -native bool:SM_IsBuddyLocked(client); - -/********************************************************************** - * Clear a players buddy - * - * @param client The client index of the player to clear - * @param override Whether or not to override a player lock - * @return True if successful, false if not - * @error Invalid client index - **********************************************************************/ -native bool:SM_ClearBuddy(client, bool:override = false); - -/********************************************************************** - * Determine if the player has the supplied flags - * ADMFLAG_ROOT will always return true - * - * @param client The client index of the player to assign - * @param flags The char flag(s) to check against - * @return True if valid, false if not - **********************************************************************/ -native bool:SM_IsValidAdmin(client, const String:flags[]); - - -/********************************************************************** - * Determine if the team is a valid team - * - * @param team The team index to determine if valid for - currently installed/supported mod - * @return True if valid, false if not - **********************************************************************/ -native bool:SM_IsValidTeam(team); - - -public e_SupportedMods:GetCurrentMod() -{ - new String:sGameType[64]; - GetGameFolderName(sGameType, sizeof(sGameType)); - - if (StrEqual(sGameType, "aoc", false)) - { - return GameType_AOC; - } - if (StrEqual(sGameType, "cstrike", false)) - { - return GameType_CSS; - } - if (StrEqual(sGameType, "dod", false)) - { - return GameType_DOD; - } - if (StrEqual(sGameType, "ff", false)) - { - return GameType_FF; - } - if (StrEqual(sGameType, "hidden", false)) - { - return GameType_HIDDEN; - } - if (StrEqual(sGameType, "hl2mp", false)) - { - return GameType_FF; - } - if (StrEqual(sGameType, "insurgency", false) || StrEqual(sGameType, "ins", false)) - { - return GameType_INS; - } - if (StrEqual(sGameType, "l4d", false)) - { - return GameType_L4D; - } - if (StrEqual(sGameType, "nts", false)) - { - return GameType_NEO; - } - if (StrEqual(sGameType, "sgtls", false)) - { - return GameType_SGTLS; - } - if (StrEqual(sGameType, "tf", false)) - { - return GameType_TF; - } - if (StrEqual(sGameType, "zps", false)) - { - return GameType_ZPS; - } - return GameType_Unknown; -} - -public LoadCurrentTeams() -{ - switch (g_CurrentMod) - { - case GameType_INS: - { - g_aCurrentTeams[Unknown] = 0; - g_aCurrentTeams[Spectator] = 3; - g_aCurrentTeams[Team1] = 1; - g_aCurrentTeams[Team2] = 2; - } - case default: - { - g_aCurrentTeams[Unknown] = 0; - g_aCurrentTeams[Spectator] = 1; - g_aCurrentTeams[Team1] = 2; - g_aCurrentTeams[Team2] = 3; - } - } -} diff --git a/Simple Team Manager/addons/sourcemod/scripting/simple-alltalkmanager.sp b/Simple Team Manager/addons/sourcemod/scripting/simple-alltalkmanager.sp deleted file mode 100644 index c848332..0000000 --- a/Simple Team Manager/addons/sourcemod/scripting/simple-alltalkmanager.sp +++ /dev/null @@ -1,515 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple AllTalk Manager -Description: - Allows you to set alltalk at different times -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#pragma semicolon 1 -#include -#include - -#define PLUGIN_VERSION "1.4.$Rev$" - -new Handle:satm_enabled = INVALID_HANDLE; -new Handle:satm_threshold_enabled = INVALID_HANDLE; -new Handle:satm_player_threshold = INVALID_HANDLE; -new Handle:satm_threshold_setting = INVALID_HANDLE; -new Handle:satm_logactivity = INVALID_HANDLE; -new Handle:satm_alltalk = INVALID_HANDLE; - -new Handle:g_aEventNames = INVALID_HANDLE; -new Handle:g_aEventReasons = INVALID_HANDLE; -new Handle:g_aEventSettings = INVALID_HANDLE; - -new bool:g_bLastThreshold = false; -new bool:g_bEnabled = true; -new bool:g_bThresholdEnabled = true; -new bool:g_bIsSetupMap = false; -new bool:g_bIsGameTF2 = false; -new bool:g_bLogActivity = false; - -new g_iLastEventIndex; - -public Plugin:myinfo = -{ - name = "Simple AllTalk Manager", - author = "Simple Plugins", - description = "Allows you to set alltalk at different times", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -} - -/** -Sourcemod callbacks -*/ -public OnPluginStart() -{ - - /** - Need to create all of our console variables. - */ - CreateConVar("satm_version", PLUGIN_VERSION, "Simple AllTalk Manager", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - satm_enabled = CreateConVar("satm_enabled", "1", "Enables/Disables Simple AllTalk Manager", _, true, 0.0, true, 1.0); - satm_threshold_enabled = CreateConVar("satm_threshold_enabled", "1", "Enables/Disables player threshold", _, true, 0.0, true, 1.0); - satm_player_threshold = CreateConVar("satm_player_threshold", "8", "Amount of players for the threshold"); - satm_threshold_setting = CreateConVar("satm_threshold_setting", "1", "Enables/Disables all talk up to player threshold, with the opposite set after the threshold", _, true, 0.0, true, 1.0); - satm_logactivity = CreateConVar("satm_logactivity", "0", "Enables/Disables log activity", _, true, 0.0, true, 1.0); - satm_alltalk = FindConVar("sv_alltalk"); - - /** - Hook console variables - */ - HookConVarChange(satm_enabled, ConVarSettingsChanged); - HookConVarChange(satm_threshold_enabled, ConVarSettingsChanged); - HookConVarChange(satm_player_threshold, ConVarSettingsChanged); - HookConVarChange(satm_logactivity, ConVarSettingsChanged); - - /** - Remove the notify flag from all talk cvar since we do it - */ - SetConVarFlags(satm_alltalk, GetConVarFlags(satm_alltalk)~FCVAR_NOTIFY); - - /** - Get the game type. We only care if it's TF2 - */ - new String:sGameType[64]; - GetGameFolderName(sGameType, sizeof(sGameType)); - if (StrEqual(sGameType, "tf", false)) - { - g_bIsGameTF2 = true; - } - - /** - Create the arrays - */ - g_aEventNames = CreateArray(255, 1); - g_aEventReasons = CreateArray(255, 1); - g_aEventSettings = CreateArray(1, 1); - - /** - Need to register the commands we are going to create and use. - */ - RegAdminCmd("sm_reloadatconfig", Command_Reload, ADMFLAG_GENERIC, "Reloads settings from config file"); - - /** - Create the config file - */ - AutoExecConfig(true); - - /** - Load the events from the config - */ - LoadEventsFromConfig(); -} - -public OnConfigsExecuted() -{ - - /** - Load up the settings - */ - g_bEnabled = GetConVarBool(satm_enabled); - g_bLogActivity = GetConVarBool(satm_logactivity); - g_bThresholdEnabled = GetConVarBool(satm_threshold_enabled); -} - -public OnMapStart() -{ - - /** - Reset the globals - */ - g_iLastEventIndex = 0; - g_bLastThreshold = false; - - /** - Check the map type if we are in TF2 - */ - if (g_bIsGameTF2) - { - g_bIsSetupMap = IsSetupPeriodMap(); - } - - /** - Set AllTalk - */ - if (g_bEnabled) - { - SetConVarBool(satm_alltalk, true); - } -} - -public OnClientDisconnect_Post(client) -{ - if (g_bEnabled) - { - SetAllTalk(-1); - } -} - -public OnClientPostAdminCheck(client) -{ - if (g_bEnabled) - { - SetAllTalk(-1); - } - CreateTimer(2.0, Timer_ShowAllTalkStatus, client, TIMER_FLAG_NO_MAPCHANGE); -} - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (convar == satm_enabled) - { - if (StringToInt(newValue)) - { - g_bEnabled = true; - } - else - { - g_bEnabled = false; - } - } - else if (convar == satm_threshold_enabled) - { - if (StringToInt(newValue)) - { - g_bThresholdEnabled = true; - } - else - { - g_bThresholdEnabled = false; - } - } - else if (convar == satm_logactivity) - { - if (StringToInt(newValue)) - { - g_bLogActivity = true; - } - else - { - g_bLogActivity = false; - } - } - if (g_bEnabled) - { - SetAllTalk(-1); - } -} - -/** -Commands -*/ -public Action:Command_Reload(client, args) -{ - - /** - Clear the array - */ - ClearArray(g_aEventNames); - ClearArray(g_aEventReasons); - ClearArray(g_aEventSettings); - - /** - Load the events from the config - */ - LoadEventsFromConfig(); - - return Plugin_Handled; -} - -/** -Game Event Hooks -*/ -public Hook_All_Events(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (!g_bIsSetupMap) - { - if (StrEqual(name, "teamplay_round_start")) - { - if (FindStringInArray(g_aEventNames, "teamplay_setup_finished") != -1) - { - g_iLastEventIndex = FindStringInArray(g_aEventNames, "teamplay_setup_finished"); - if (g_bEnabled) - { - SetAllTalk(g_iLastEventIndex); - return; - } - } - } - } - g_iLastEventIndex = FindStringInArray(g_aEventNames, name); - if (g_bEnabled) - { - SetAllTalk(g_iLastEventIndex); - } -} - -/** -Timers -*/ -public Action:Timer_ShowAllTalkStatus(Handle:timer, any:client) -{ - if (IsClientConnected(client) && IsClientInGame(client)) - { - new bool:bSetting = GetConVarBool(satm_alltalk); - if (bSetting) - { - PrintToChat(client, "\x01\x04[SM] AllTalk is \x01[on]"); - } - else - { - PrintToChat(client, "\x01\x04[SM] AllTalk is \x01[off]"); - } - } -} - -/** -Stock Functions -*/ -stock LoadEventsFromConfig() -{ - - /** - Make sure the config file is here and load it up - */ - new String:sConfigFile[256]; - BuildPath(Path_SM, sConfigFile, sizeof(sConfigFile), "configs/simple-alltalkmanager_events.cfg"); - if (!FileExists(sConfigFile)) - { - - /** - Config file doesn't exists, stop the plugin - */ - LogError("[SATM] Simple AllTalk Manager is not running! Could not find file %s", sConfigFile); - SetFailState("Could not find file %s", sConfigFile); - } - - /** - Create the arrays and variables - */ - new String:sGameEventName[256]; - new String:sReason[256]; - new iSetting; - - /** - Load config file as a KeyValues file - */ - new Handle:kvGameEvents = CreateKeyValues("game_events"); - FileToKeyValues(kvGameEvents, sConfigFile); - - if (!KvGotoFirstSubKey(kvGameEvents)) - { - return; - } - - /** - Hook the game events and load the settings - */ - do - { - - /** - Get the section name; this should be the event name - */ - KvGetSectionName(kvGameEvents, sGameEventName, sizeof(sGameEventName)); - if (!HookEventEx(sGameEventName, Hook_All_Events, EventHookMode_PostNoCopy)) - { - - /** - Could not hook this event, stop the plugin - */ - SetFailState("Could not hook event %s", sGameEventName); - } - else - { - if (g_bLogActivity) - { - LogMessage("[SATM] Hooked event: %s", sGameEventName); - } - } - - /** - Get the reason string and setting - */ - KvGetString(kvGameEvents, "reason", sReason, sizeof(sReason)); - iSetting = KvGetNum(kvGameEvents, "setting"); - if (g_bLogActivity) - { - LogMessage("[SATM] Event reason string: %s", sReason); - LogMessage("[SATM] Event setting: %i", iSetting); - } - - /** - Push the values to the arrays - */ - PushArrayString(g_aEventNames, sGameEventName); - PushArrayString(g_aEventReasons, sReason); - PushArrayCell(g_aEventSettings, iSetting); - } while (KvGotoNextKey(kvGameEvents)); - - /** - Close our handle - */ - CloseHandle(kvGameEvents); -} - -stock SetAllTalk(index) -{ - new iPlayerThreshold = GetConVarInt(satm_player_threshold); - new bool:bThresholdMet = ((GetClientCount() >= iPlayerThreshold) ? true : false); - new bool:bSetting; - - if (g_bThresholdEnabled) - { - if (bThresholdMet) - { - if (index == -1) - { - if (bThresholdMet != g_bLastThreshold) - { - g_bLastThreshold = true; - bSetting = !GetConVarBool(satm_threshold_setting); - new bool:bLastSetting = GetArrayCell(g_aEventSettings, g_iLastEventIndex); - if (bLastSetting && !bSetting) - { - bSetting = GetArrayCell(g_aEventSettings, g_iLastEventIndex); - } - } - else - { - bSetting = GetArrayCell(g_aEventSettings, g_iLastEventIndex); - } - } - else - { - bSetting = GetArrayCell(g_aEventSettings, index); - } - } - else - { - g_bLastThreshold = false; - bSetting = GetConVarBool(satm_threshold_setting); - } - } - else - { - if (index != -1) - { - bSetting = GetArrayCell(g_aEventSettings, index); - } - } - - if (GetConVarBool(satm_alltalk) != bSetting) - { - - SetConVarBool(satm_alltalk, bSetting); - - new String:sReason[256]; - if (index == -1) - { - Format(sReason, sizeof(sReason), "Player Threshold"); - } - else - { - if (!g_bIsSetupMap) - { - new String:sCurrentEvent[256]; - GetArrayString(g_aEventNames, index, sCurrentEvent, sizeof(sCurrentEvent)); - if (StrEqual(sCurrentEvent, "teamplay_setup_finished")) - { - new iRoundStartIndex = FindStringInArray(g_aEventNames, "teamplay_round_start"); - if (iRoundStartIndex != -1) - { - GetArrayString(g_aEventReasons, iRoundStartIndex, sReason, sizeof(sReason)); - } - else - { - GetArrayString(g_aEventReasons, index, sReason, sizeof(sReason)); - } - } - else - { - GetArrayString(g_aEventReasons, index, sReason, sizeof(sReason)); - } - } - else - { - GetArrayString(g_aEventReasons, index, sReason, sizeof(sReason)); - } - } - - if (bSetting) - { - PrintToChatAll("\x01\x04[SM] AllTalk turned \x01[on] \x04due to:\x01 %s", sReason); - } - else - { - PrintToChatAll("\x01\x04[SM] AllTalk turned \x01[off] \x04due to:\x01 %s", sReason); - } - } -} - -stock bool:IsSetupPeriodMap() -{ - new iEnt = -1; - new String:sMapName[32]; - - GetCurrentMap(sMapName, sizeof(sMapName)); - - if (strncmp(sMapName, "cp_", 3, false) == 0) - { - new iTeam; - while ((iEnt = FindEntityByClassname(iEnt, "team_control_point")) != -1) - { - iTeam = GetEntProp(iEnt, Prop_Send, "m_iTeamNum"); - - /** - If there is a blu CP or a neutral CP, then it's not an attack/defend map - */ - if (iTeam != 2) - { - //this is a push map - return false; - } - } - //this is a attack/defend map - return true; - } - else if (strncmp(sMapName, "ctf_", 3, false) == 0) - { - //this is a ctf map - return false; - } - return false; -} diff --git a/Simple Team Manager/addons/sourcemod/scripting/simple-autoscrambler.sp b/Simple Team Manager/addons/sourcemod/scripting/simple-autoscrambler.sp deleted file mode 100644 index 6c6799e..0000000 --- a/Simple Team Manager/addons/sourcemod/scripting/simple-autoscrambler.sp +++ /dev/null @@ -1,459 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple AutoScrambler -Description: - Automatically scrambles the teams based upon a number of events. -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include - -#define PLUGIN_VERSION "1.1.$Rev$" - -/** -Different scramble modes: - -1 = Full Scramble, dont restart round. -2 = Admins Immune, dont restart round. -3 = Full Scramble, restart round and reset scores. -4 = Admins Immune, restart round and reset scores. - -*/ - -/** -Different top player modes: - -1 = Divide Top 4 players on the two teams. -2 = Protect the Top 2 players on each team. - -*/ - -enum PlayerData -{ - Handle:hForcedTimer, - bool:bProtected; -}; - -/** -Cvars used for admins -*/ -new Handle: sas_admin_immunity_enabled = INVALID_HANDLE, - Handle: sas_admin_flag_scramblenow = INVALID_HANDLE, - Handle: sas_admin_flag_immunity = INVALID_HANDLE; - -/** -Cvars used for autoscramble -*/ -new Handle: sas_autoscramble_enabled = INVALID_HANDLE, - Handle: sas_autoscramble_minplayers = INVALID_HANDLE, - Handle: sas_autoscramble_mode = INVALID_HANDLE, - Handle: sas_autoscramble_winstreak = INVALID_HANDLE, - Handle: sas_autoscramble_steamroll = INVALID_HANDLE, - Handle: sas_autoscramble_frags = INVALID_HANDLE; - -/** -Cvars used for voting -*/ -new Handle: sas_vote_enabled = INVALID_HANDLE, - Handle: sas_vote_upcount = INVALID_HANDLE, - Handle: sas_vote_winpercent = INVALID_HANDLE, - Handle: sas_vote_mode = INVALID_HANDLE, - Handle: sas_vote_minplayers = INVALID_HANDLE; - -/** -Additional cvars -*/ -new Handle: sas_enabled = INVALID_HANDLE, - Handle: sas_timer_scrambledelay = INVALID_HANDLE, - Handle: TFGameModeArena = INVALID_HANDLE; - -/** -Timers -*/ -new Handle: g_hScrambleTimer = INVALID_HANDLE; - -/** - Player arrays - */ -new g_aPlayers[MAXPLAYERS + 1][PlayerData]; - -/** - Cvar variables - */ -new bool: g_bIsEnabled, - bool: g_bIsAutoScrambleEnabled, - bool: g_bIsVoteEnabled, - bool: g_bIsAdminImmunityEnabled; -new Float: g_fTimer_ScrambleDelay, - Float: g_fVote_UpCount, - Float: g_fVote_WinPercent; -new g_iAutoScramble_Minplayers, - g_iAutoScramble_Mode, - g_iAutoScramble_WinStreak, - g_iAutoScramble_SteamRoll, - g_iAutoScramble_Frags, - g_iVote_Mode, - g_iVote_MinPlayers; -new String: g_sScrambleNowFlag[5], - String: g_sAdminImmunityFlag[5]; - -/** -Other globals -*/ -new g_iMaxEntities, - g_iOwnerOffset; - -public Plugin:myinfo = -{ - name = "Simple AutoScrambler", - author = "Simple Plugins", - description = "Automatically scrambles the teams based upon a number of events.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -public OnPluginStart() -{ - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[SAS] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - switch (g_CurrentMod) - { - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_Post); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_Post); - } - } - - /** - Create console variables - */ - CreateConVar("sas_version", PLUGIN_VERSION, "Simple AutoScrambler Version",FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - sas_enabled = CreateConVar("sas_enabled", "1", "Enable/Disable Simple AutoScrambler"); - sas_timer_scrambledelay = CreateConVar("sas_timer_scrambledelay", "5.0", "Delay used after a scramble has been started", _, true, 1.0, true, 30.0); - - /** - Cvars used for admins - */ - sas_admin_immunity_enabled = CreateConVar("sas_admin_immunity_enabled", "1", "Enable/Disable admin immunity for scrambles"); - sas_admin_flag_scramblenow = CreateConVar("sas_admin_flag_scramblenow", "z", "Admin flag to use for scramblenow function/command"); - sas_admin_flag_immunity = CreateConVar("sas_admin_flag_immunity", "z", "Admin flag to use for scramble immunity"); - - /** - Cvars used for autoscramble - */ - sas_autoscramble_enabled = CreateConVar("sas_autoscramble_enabled", "1", "Enable/Disable the autoscramble function"); - sas_autoscramble_minplayers = CreateConVar("sas_autoscramble_minplayers", "16", "Min players needed to start an autoscramble"); - sas_autoscramble_mode = CreateConVar("sas_autoscramble_mode", "1", "Scramble mode used when autoscrambling"); - sas_autoscramble_winstreak = CreateConVar("sas_autoscramble_winstreak", "5", "Max amount of wins in a row a team can achieve before an autoscramble starts"); - sas_autoscramble_steamroll = CreateConVar("sas_autoscramble_steamroll", "120", "Shortest amount of time a team can win by before an autoscramble starts (seconds)"); - sas_autoscramble_frags = CreateConVar("sas_autoscramble_frags", "1", "Min players needed to start a vote and scramble"); - - /** - Cvars used for voting - */ - sas_vote_enabled = CreateConVar("sas_vote_enabled", "1", "Enable/Disable voting for scramble"); - sas_vote_upcount = CreateConVar("sas_vote_upcount", "5", "Amount of people wanting a scramble before a vote starts. If less than 1 it will be considered a percentage. (ie 0.5 = 50% | 1 = 1 Player | 5 = 5 Players)"); - sas_vote_winpercent = CreateConVar("sas_vote_winpercent", "0.6", "Percentage of votes needed to scramble", _, true, 0.0, true, 1.0); - sas_vote_mode = CreateConVar("sas_vote_mode", "1", "Scramble mode used when a vote results in a scramble"); - sas_vote_minplayers = CreateConVar("sas_vote_minplayers", "16", "Min players needed to start a vote and scramble"); - - /** - Hook the console variables if they change - */ - HookConVarChange(sas_enabled, ConVarSettingsChanged); - HookConVarChange(sas_timer_scrambledelay, ConVarSettingsChanged); - HookConVarChange(sas_admin_immunity_enabled, ConVarSettingsChanged); - HookConVarChange(sas_admin_flag_scramblenow, ConVarSettingsChanged); - HookConVarChange(sas_admin_flag_immunity, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_enabled, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_minplayers, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_mode, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_winstreak, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_steamroll, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_frags, ConVarSettingsChanged); - HookConVarChange(sas_vote_enabled, ConVarSettingsChanged); - HookConVarChange(sas_vote_upcount, ConVarSettingsChanged); - HookConVarChange(sas_vote_winpercent, ConVarSettingsChanged); - HookConVarChange(sas_vote_mode, ConVarSettingsChanged); - HookConVarChange(sas_vote_minplayers, ConVarSettingsChanged); - - /** - Register the command - */ - RegConsoleCmd("sm_scramblenow", Command_ScrambleNow, "sm_scramblenow (mode): Scrambles the teams"); - - /** - Load translations and .cfg file - */ - LoadTranslations ("simpleautoscrambler.phrases"); - AutoExecConfig(true, "plugin.simpleautoscrambler"); - LogAction(0, -1, "[SAS] Simple AutoScrambler is loaded."); -} - -public OnAllPluginsLoaded() -{ - //something -} - -public OnLibraryRemoved(const String:name[]) -{ - //something -} - -public OnConfigsExecuted() -{ - - /** - Load up all the variable defaults - */ - LoadUpVariables(); - - /** - Log our activity - */ - if (g_bIsEnabled) - LogAction(0, -1, "Simple AutoScrambler is ENABLED"); - else - LogAction(0, -1, "Simple AutoScrambler is DISABLED"); -} - -public Action:Command_ScrambleNow(client, args) -{ - - /** - Make sure we are enabled - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the client is authorized to run this command. - */ - if (!SM_IsValidAdmin(client, g_sScrambleNowFlag)) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure it's ok to scramble at this time - */ - if (!OkToScramble) - { - return Plugin_Handled; - } - - /** - Make sure it's ok to scramble at this time - */ - LogAction(0, -1, "[SAS] The scramblenow command was used"); - - /** - Scramble the teams - */ - StartAScramble(); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - -} - -public Action:Timer_ScrambleTeams(Handle:timer, any:mode) -{ - - /** - Make sure it's still ok to scramble - */ - if (!OkToScramble) - { - return Plugin_Handled; - } - - - switch (mode) - { - case - - - - } - - - /** - Reset the handle because the timer is over and the callback is done - */ - g_hScrambleTimer = INVALID_HANDLE; - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - -} - -stock StartAScramble(mode) -{ - - /** - See if we are already started a scramble - */ - if (g_hScrambleTimer == INVALID_HANDLE) - { - - /** - There is a scramble in progress - */ - return; - - } - - /** - Report that a scramble is about to start - */ - PrintCenterTextAll("%T", "Scramble", LANG_SERVER); - - /** - Start a timer and log the action - */ - g_hScrambleTimer = CreateTimer(g_fTimer_ScrambleDelay, Timer_ScrambleTeams, mode, TIMER_FLAG_NO_MAPCHANGE); - LogAction(0, -1, "[SAS] A scamble timer was started"); -} - -stock bool:OkToScramble() -{ - -} - -stock LoadUpVariables() -{ - g_bIsEnabled = GetConVarBool(sas_enabled); - g_bIsAutoScrambleEnabled = GetConVarBool(sas_autoscramble_enabled); - g_bIsVoteEnabled = GetConVarBool(sas_vote_enabled); - g_bIsAdminImmunityEnabled = GetConVarBool(sas_admin_immunity_enabled); - g_iAutoScramble_Minplayers = GetConVarInt(sas_autoscramble_minplayers); - g_iAutoScramble_Mode = GetConVarInt(sas_autoscramble_mode); - g_iAutoScramble_WinStreak = GetConVarInt(sas_autoscramble_winstreak); - g_iAutoScramble_SteamRoll = GetConVarInt(sas_autoscramble_steamroll); - g_iAutoScramble_Frags = GetConVarInt(sas_autoscramble_frags); - g_iVote_Mode = GetConVarInt(sas_vote_mode); - g_iVote_MinPlayers = GetConVarInt(sas_vote_minplayers); - GetConVarString(sas_admin_flag_scramblenow, g_sScrambleNowFlag, sizeof(g_sScrambleNowFlag)); - GetConVarString(sas_admin_flag_immunity, g_sAdminImmunityFlag, sizeof(g_sAdminImmunityFlag)); - g_fTimer_ScrambleDelay = GetConVarFloat(sas_timer_scrambledelay); - g_fVote_UpCount = GetConVarFloat(sas_vote_upcount); - g_fVote_WinPercent = GetConVarFloat(sas_vote_winpercent); - g_iMaxEntities = GetMaxEntities(); - g_iOwnerOffset = FindSendPropInfo("CBaseObject", "m_hBuilder"); -} - -stock TF2_DestroyBuildings(client) -{ - - /** - We have to start a loop to check the owner of all the valid entities - */ - for (new i = MaxClients + 1; i <= g_iMaxEntities; i++) - { - if (!IsValidEntity(i)) - { - - /** - Not valid, continue to next one - */ - continue; - } - - /** - Get the name of the current entity - */ - decl String:sNetClass[32]; - GetEntityNetClass(i, sNetClass, sizeof(sNetClass)); - - /** - See if its something that an engineer would build - */ - if (strcmp(sNetClass, "CObjectSentrygun") == 0 - || strcmp(sNetClass, "CObjectTeleporter") == 0 - || strcmp(sNetClass, "CObjectDispenser") == 0) - { - - /** - It is, so lets check the owner - */ - if (GetEntDataEnt2(i, g_iOwnerOffset) == client) - { - - /** - It's the clients building, so we blow it up. - */ - SetVariantInt(9999); - AcceptEntityInput(i, "RemoveHealth"); - } - } - } -} \ No newline at end of file diff --git a/Simple Team Manager/addons/sourcemod/scripting/simple-chatcolors.sp b/Simple Team Manager/addons/sourcemod/scripting/simple-chatcolors.sp deleted file mode 100644 index 539d057..0000000 --- a/Simple Team Manager/addons/sourcemod/scripting/simple-chatcolors.sp +++ /dev/null @@ -1,496 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Chat Colors -Description: - Changes the colors of players chat based on config file -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#pragma semicolon 1 -#include -#include - -#define PLUGIN_VERSION "0.9.0.$Rev$" - -#define CHAT_SYMBOL '@' -#define TRIGGER_SYMBOL1 '!' -#define TRIGGER_SYMBOL2 '/' -#define CHAT_MAX_MESSAGE_LENGTH 1024 - -new Handle:g_hDebugCvar = INVALID_HANDLE; -new Handle:g_aGroupNames = INVALID_HANDLE; -new Handle:g_aGroupFlag = INVALID_HANDLE; -new Handle:g_aGroupNameColor = INVALID_HANDLE; -new Handle:g_aGroupTextColor = INVALID_HANDLE; - -new bool:g_bDebug = false; - -new g_iArraySize; - -new g_aPlayerColorIndex[MAXPLAYERS + 1] = { -1, ... }; - -public Plugin:myinfo = -{ - name = "Simple Chat Colors", - author = "Simple Plugins", - description = "Changes the colors of players chat based on config file.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -/** -Sourcemod callbacks -*/ -public OnPluginStart() -{ - - /** - Need to create all of our console variables. - */ - CreateConVar("sm_chatcolors_version", PLUGIN_VERSION, "Simple Chat Colors", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - g_hDebugCvar = CreateConVar("sm_chatcolors_debug", "1", "Enable/Disable debugging information"); - - /** - Hook console variables - */ - HookConVarChange(g_hDebugCvar, ConVarSettingsChanged); - - /** - Need to register the commands we are going to use - */ - RegConsoleCmd("say", Command_Say); - RegConsoleCmd("say_team", Command_SayTeam); - RegAdminCmd("sm_reloadcolorsconfig", Command_Reload, ADMFLAG_GENERIC, "Reloads settings from config file"); - - /** - Create the arrays - */ - g_aGroupNames = CreateArray(256, 1); - g_aGroupFlag = CreateArray(15, 1); - g_aGroupNameColor = CreateArray(15, 1); - g_aGroupTextColor = CreateArray(15, 1); - - /** - Load the admins and colors from the config - */ - LoadAdminsAndColorsFromConfig(); - g_iArraySize = GetArraySize(g_aGroupNames); -} - -public OnConfigsExecuted() -{ - g_bDebug = GetConVarBool(g_hDebugCvar); - ReloadConfigFile(); -} - -public OnClientPostAdminCheck(client) -{ - - /** - Check the client to see if they are a admin - */ - CheckAdmin(client); -} - -public OnClientDisconnect(client) -{ - g_aPlayerColorIndex[client] = -1; -} - -/** -Commands -*/ -public Action:Command_Say(client, args) -{ - - /** - Make sure we are enabled. - */ - if (client == 0 || IsChatTrigger()) - { - return Plugin_Continue; - } - - if (g_aPlayerColorIndex[client] != -1) - { - - /** - The client is, so get the chat message and strip it down. - */ - decl String:sArg[CHAT_MAX_MESSAGE_LENGTH], - String:sChatMsg[CHAT_MAX_MESSAGE_LENGTH]; - - new bool:bAlive = IsPlayerAlive(client); - - GetCmdArgString(sArg, sizeof(sArg)); - StripQuotes(sArg); - TrimString(sArg); - new startidx; - if (sArg[strlen(sArg)-1] == '"') - { - sArg[strlen(sArg)-1] = '\0'; - startidx = 1; - } - - /** - Bug out if they are using the admin chat symbol (admin chat). If we are in CSS it may not find all the triggers, so we double check. - */ - if (sArg[startidx] == CHAT_SYMBOL || sArg[startidx] == TRIGGER_SYMBOL1 || sArg[startidx] == TRIGGER_SYMBOL2) - { - return Plugin_Continue; - } - - /** - Log the message for hlstatsx and other things. - */ - new iUserID = GetClientUserId(client); - decl String:sAuthID[64]; - GetClientAuthString(client, sAuthID, sizeof(sAuthID)); - LogToGame("\"%N<%i><%s><>\" say \"%s\"", client, iUserID, sAuthID, sArg); - - /** - Format the message. - */ - FormatMessage(client, 0, bAlive, sChatMsg, sArg, g_aPlayerColorIndex[client]); - - /** - Send the message. - */ - //SayText2(0, client, sChatMsg); - CPrintToChatAll(sChatMsg); - - /** - We are done, bug out, and stop the original chat message. - */ - return Plugin_Stop; - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Command_SayTeam(client, args) -{ - - /** - Make sure we are enabled. - */ - if (client == 0 || IsChatTrigger()) - { - return Plugin_Continue; - } - - /** - Check the client to see if they are a admin - */ - if (g_aPlayerColorIndex[client] != -1) - { - - /** - The client is, so get the chat message and strip it down. - */ - decl String:sArg[CHAT_MAX_MESSAGE_LENGTH], - String:sChatMsg[CHAT_MAX_MESSAGE_LENGTH]; - - new bool:bAlive = IsPlayerAlive(client); - new iCurrentTeam = GetClientTeam(client); - - GetCmdArgString(sArg, sizeof(sArg)); - StripQuotes(sArg); - TrimString(sArg); - new startidx; - if (sArg[strlen(sArg)-1] == '"') - { - sArg[strlen(sArg)-1] = '\0'; - startidx = 1; - } - - /** - Bug out if they are using the admin chat symbol (admin chat). - */ - if (sArg[startidx] == CHAT_SYMBOL || sArg[startidx] == TRIGGER_SYMBOL1 || sArg[startidx] == TRIGGER_SYMBOL2) - { - return Plugin_Continue; - } - - /** - Log the message for hlstatsx and other things. - */ - new iUserID = GetClientUserId(client); - decl String:sAuthID[64]; - GetClientAuthString(client, sAuthID, sizeof(sAuthID)); - LogToGame("\"%N<%i><%s><>\" say_team \"%s\"", client, iUserID, sAuthID, sArg); - - /** - Format the message. - */ - FormatMessage(client, iCurrentTeam, bAlive, sChatMsg, sArg, g_aPlayerColorIndex[client]); - - /** - Send the message to the same team - */ - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == iCurrentTeam) - { - CPrintToChat(client, sChatMsg); - } - } - - /** - We are done, bug out, and stop the original chat message. - */ - return Plugin_Stop; - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Command_Reload(client, args) -{ - ReloadConfigFile(); - return Plugin_Handled; -} - -/** -Stock Functions -*/ -stock LoadAdminsAndColorsFromConfig() -{ - - /** - Make sure the config file is here and load it up - */ - new String:sConfigFile[256]; - BuildPath(Path_SM, sConfigFile, sizeof(sConfigFile), "configs/simple-chatcolors.cfg"); - if (!FileExists(sConfigFile)) - { - - /** - Config file doesn't exists, stop the plugin - */ - LogError("[SCC] Simple Chat Colors is not running! Could not find file %s", sConfigFile); - SetFailState("Could not find file %s", sConfigFile); - } - - /** - Create the arrays and variables - */ - new String:sGroupName[256]; - new String:sGroupFlag[15]; - new String:sGroupNameColor[15]; - new String:sGroupTextColor[15]; - - - /** - Load config file as a KeyValues file - */ - new Handle:kvChatColors = CreateKeyValues("admin_colors"); - FileToKeyValues(kvChatColors, sConfigFile); - - if (!KvGotoFirstSubKey(kvChatColors)) - { - return; - } - - /** - Load up all the groups in the file - */ - do - { - - /** - Get the section name; should be the "group" name - */ - KvGetSectionName(kvChatColors, sGroupName, sizeof(sGroupName)); - - - /** - Get the flags and colors - */ - KvGetString(kvChatColors, "flag", sGroupFlag, sizeof(sGroupFlag)); - KvGetString(kvChatColors, "namecolor", sGroupNameColor, sizeof(sGroupNameColor)); - KvGetString(kvChatColors, "textcolor", sGroupTextColor, sizeof(sGroupTextColor)); - - if (g_bDebug) - { - LogMessage("Group Name/SteamID: %s", sGroupName); - LogMessage("Flag String: %s", sGroupFlag); - LogMessage("Color on name: %s", sGroupNameColor); - LogMessage("Color of text: %s", sGroupTextColor); - } - - /** - Push the values to the arrays - */ - PushArrayString(g_aGroupNames, sGroupName); - PushArrayString(g_aGroupFlag, sGroupFlag); - PushArrayString(g_aGroupNameColor, sGroupNameColor); - PushArrayString(g_aGroupTextColor, sGroupTextColor); - } while (KvGotoNextKey(kvChatColors)); - - /** - Close our handle - */ - CloseHandle(kvChatColors); -} - -stock ReloadConfigFile() -{ - - /** - Clear the array - */ - ClearArray(g_aGroupNames); - ClearArray(g_aGroupFlag); - ClearArray(g_aGroupNameColor); - ClearArray(g_aGroupTextColor); - - /** - Load the admins, groups, and colors from the config - */ - LoadAdminsAndColorsFromConfig(); - g_iArraySize = GetArraySize(g_aGroupNames); - - /** - Recheck all the online players for assigned colors - */ - for (new index = 1; index <= MaxClients; index++) - { - if (IsClientConnected(index) && IsClientInGame(index)) - { - CheckAdmin(index); - } - } -} - -stock CheckAdmin(client) -{ - new String:sFlags[15]; - new String:sClientSteamID[64]; - new iGroupFlags; - new iFlags; - new iIndex = -1; - - /** - Look for a steamid first - */ - GetClientAuthString(client, sClientSteamID, sizeof(sClientSteamID)); - iIndex = FindStringInArray(g_aGroupNames, sClientSteamID); - if (iIndex != -1) - { - g_aPlayerColorIndex[client] = iIndex; - } - - /** - Didn't find one, check flags - */ - else - { - /** - Search for flag in groups - */ - - iFlags = GetUserFlagBits(client); - for (iIndex = 0; iIndex < g_iArraySize; iIndex++) - { - GetArrayString(g_aGroupFlag, iIndex, sFlags, sizeof(sFlags)); - iGroupFlags = ReadFlagString(sFlags); - if (iFlags & iGroupFlags) - { - g_aPlayerColorIndex[client] = iIndex; - break; - } - } - } - - if (g_bDebug) - { - PrintToChatAll("SteamID: %s", sClientSteamID); - PrintToChatAll("Array Index: %i", iIndex); - PrintToChatAll("Flag String: %s", sFlags); - PrintToChatAll("Flag Bits of Client: %i", iFlags); - PrintToChatAll("Flag Bits of Group: %i", iGroupFlags); - } -} - -stock FormatMessage(iClient, iTeam, bool:bAlive, String:sChatMsg[], const Sting:sMessage[], iArrayIndex) -{ - decl String:sDead[10], - String:sTeam[10], - String:sClientName[64]; - - GetClientName(iClient, sClientName, sizeof(sClientName)); - - if (iTeam != 0) - { - Format(sTeam, sizeof(sTeam), "(TEAM) "); - } - else - { - Format(sTeam, sizeof(sTeam), ""); - } - if (bAlive) - { - Format(sDead, sizeof(sDead), ""); - } - else - { - Format(sDead, sizeof(sDead), "*DEAD* "); - } - - new String:sNameColor[15]; - new String:sTextColor[15]; - GetArrayString(g_aGroupNameColor, iArrayIndex, sNameColor, sizeof(sNameColor)); - GetArrayString(g_aGroupTextColor, iArrayIndex, sTextColor, sizeof(sTextColor)); - - Format(sChatMsg, CHAT_MAX_MESSAGE_LENGTH, "{default}%s%s%s%s {default}: %s%s", sDead, sTeam, sNameColor, sClientName, sTextColor, sMessage); -} - -/** -Adjust the settings if a convar was changed -*/ -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (StringToInt(newValue) == 1) - { - g_bDebug = true; - } - else - { - g_bDebug = false; - } -} \ No newline at end of file diff --git a/Simple Team Manager/addons/sourcemod/scripting/simple-donatorbenefits.sp b/Simple Team Manager/addons/sourcemod/scripting/simple-donatorbenefits.sp deleted file mode 100644 index e3f6845..0000000 --- a/Simple Team Manager/addons/sourcemod/scripting/simple-donatorbenefits.sp +++ /dev/null @@ -1,1312 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Donator Benefits -Description: - Provides donator benefits to players -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include -#include - -#define PLUGIN_VERSION "1.1.$Rev$" - -#define CHAT_SYMBOL '@' -#define CHAT_MAX_MESSAGE_LENGTH 1024 - -enum PlayerData -{ - bool:bIsDonator, - bool:bQueue, - bool:bImmune, - iHealthCount, - iNewTeam -}; - -/** - Public convar handles - */ -new Handle:sdb_enabled = INVALID_HANDLE; -new Handle:sdb_donationflag = INVALID_HANDLE; -new Handle:sdb_soundfile = INVALID_HANDLE; -new Handle:sdb_joinsound_enabled = INVALID_HANDLE; -new Handle:sdb_joinpubmsg_enabled = INVALID_HANDLE; -new Handle:sdb_joinprivmsg_enabled = INVALID_HANDLE; -new Handle:sdb_chatcolors_enabled = INVALID_HANDLE; -new Handle:sdb_immunity_enabled = INVALID_HANDLE; -new Handle:sdb_ubercharge_enabled = INVALID_HANDLE; -new Handle:sdb_givehealth_enabled = INVALID_HANDLE; -new Handle:sdb_nofalldmg_enabled = INVALID_HANDLE; -new Handle:sdb_fastheavy_enabled = INVALID_HANDLE; -new Handle:sdb_swapteam_enabled = INVALID_HANDLE; -new Handle:sdb_chatcolor = INVALID_HANDLE; -new Handle:sdb_uberlevel = INVALID_HANDLE; -new Handle:sdb_healthcount = INVALID_HANDLE; -new Handle:sdb_healthbonus = INVALID_HANDLE; -new Handle:sdb_heavymultiplier = INVALID_HANDLE; - -/** -Create global enable/disable bools so we don't have to check the console variable on every call -*/ -new bool:g_bIsEnabled = true; -new bool:g_bIsJoinSoundEnabled = true; -new bool:g_bIsJoinPubMsgEnabled = true; -new bool:g_bIsJoinPrivMsgEnabled = true; -new bool:g_bIsChatColorsEnabled = true; -new bool:g_bIsImmuntyEnabled = true; -new bool:g_bIsUberChargeEnabled = true; -new bool:g_bIsGiveHealthEnabled = true; -new bool:g_bIsNoFallDmgEnabled = true; -new bool:g_bIsFastHeayEnabled = true; -new bool:g_bIsSwapTeamEnabled = true; - -/** - Player arrays - */ -new g_aPlayers[MAXPLAYERS + 1][PlayerData]; - - -/** -Rest of the globals -*/ -new bool:g_bRoundEnd = false; -new String:g_sCharDonatorFlag[5]; -new String:g_sSoundFile[PLATFORM_MAX_PATH]; -new String:g_sChatColor[11]; -new g_iHealthBonus; -new g_iHealthCount; -new g_iClassMaxHealth[TFClassType] = {0, 125, 125, 200, 175, 150, 300, 175, 125, 125}; -new g_fClassMaxSpeed[TFClassType] = {0, 400, 300, 240, 280, 320, 230, 300, 300, 300}; -new Float:g_fHeavyMultiplier = 0.0; -new Float:g_fUberLevel = 0.0; - -public Plugin:myinfo = -{ - name = "Simple Donation Benefits", - author = "Simple Plugins", - description = "Gives donators benefits to players", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -} - -public OnPluginStart() -{ - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[SDB] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_connect", HookPlayerSpawn, EventHookMode_Pre); - HookEvent("player_spawn", HookPlayerSpawn, EventHookMode_Post); - HookEvent("player_death", HookPlayerDeath, EventHookMode_Post); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Post); - switch (g_CurrentMod) - { - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - HookEvent("player_changeclass", HookPlayerClass, EventHookMode_Post); - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_Post); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - - /** - Create console variables - */ - CreateConVar("sdb_version", PLUGIN_VERSION, "Simple Donation Benefits", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - sdb_enabled = CreateConVar("sdb_enabled", "1", "Enable/Disable Simple Donation Benefits"); - sdb_donationflag = CreateConVar("sdb_donationflag", "a", "Flag ALREADY given to donators. Must be in char format"); - - /** - Create the enable/disable donator console variables - */ - sdb_joinsound_enabled = CreateConVar("sdb_joinsound_enabled", "1", "Enable/Disable donator join sound"); - sdb_joinpubmsg_enabled = CreateConVar("sdb_joinpubmsg_enabled", "1", "Enable/Disable public donator join message (replaces: as connected)"); - sdb_joinprivmsg_enabled = CreateConVar("sdb_joinprivmsg_enabled", "1", "Enable/Disable private donator join message (sent only to donator)"); - sdb_chatcolors_enabled = CreateConVar("sdb_chatcolors_enabled", "1", "Enable/Disable donator chat colors"); - sdb_immunity_enabled = CreateConVar("sdb_immunity_enabled", "1", "Enable/Disable donator round end immunity"); - sdb_ubercharge_enabled = CreateConVar("sdb_ubercharge_enabled", "1", "Enable/Disable donator medics starting with ubercharge"); - sdb_givehealth_enabled = CreateConVar("sdb_givehealth_enabled", "1", "Enable/Disable donator instant health bonus"); - sdb_nofalldmg_enabled = CreateConVar("sdb_nofalldmg_enabled", "1", "Enable/Disable no fall damage for donators"); - sdb_fastheavy_enabled = CreateConVar("sdb_fastheavy_enabled", "1", "Enable/Disable donator heavies moving faster while spinning"); - sdb_swapteam_enabled = CreateConVar("sdb_swampteam_enabled", "1", "Enable/Disable donator swap team ability"); - - /** - Create the donator setting console variables - */ - sdb_soundfile = CreateConVar("sdb_soundfile", "custom/donatorjoin.mp3", "The location of sound file"); - sdb_chatcolor = CreateConVar("sdb_chatcolor", "green", "Color to use for donator chat. Valid colors are green and lightgreen"); - sdb_uberlevel = CreateConVar("sdb_uberlevel", "0.5", "Uberlevel to give donator medic at spawn. 1.0 = full uber", _, true, 0.0, true, 1.0); - sdb_healthcount = CreateConVar("sdb_healthcount", "1", "Number of times a donator can use use instant health per life"); - sdb_healthbonus = CreateConVar("sdb_healthbonus", "100", "The amount of health to heal the donator"); - sdb_heavymultiplier = CreateConVar("sdb_heavyspeed", "0.5", "The speed multiplier for the fast heavy. Based on running speed. 1.0 = running speed. (Game Default is 0.20)", _, true, 0.0, true, 1.0); - - /** - Hook dukehacks calls - */ - dhAddClientHook(CHK_TakeDamage, Hacks_TakeDamageHook); - dhAddClientHook(CHK_PreThink, Hacks_PreThinkHook); - - /** - Hook the console variables if they change - */ - HookConVarChange(sdb_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_donationflag, ConVarSettingsChanged); - HookConVarChange(sdb_joinsound_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_joinpubmsg_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_joinprivmsg_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_chatcolors_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_immunity_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_ubercharge_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_givehealth_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_nofalldmg_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_swapteam_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_fastheavy_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_soundfile, ConVarSettingsChanged); - HookConVarChange(sdb_chatcolor, ConVarSettingsChanged); - HookConVarChange(sdb_uberlevel, ConVarSettingsChanged); - HookConVarChange(sdb_healthcount, ConVarSettingsChanged); - HookConVarChange(sdb_healthbonus, ConVarSettingsChanged); - HookConVarChange(sdb_heavymultiplier, ConVarSettingsChanged); - - /** - Register the commands - */ - RegConsoleCmd("sm_swapteams", Command_SwapTeam, "sm_swapteams <[0]instant/[1]queued>: Swaps your team to the other team"); - RegConsoleCmd("sm_ihealth", Command_InstantHealth, "sm_ihealth: Gives you a instant health pack"); - RegAdminCmd("sm_teaser", Command_Teaser, ADMFLAG_GENERIC,"sm_teaser <[0]add/[1]remove>: Gives temporary donator privilages to a player"); - RegConsoleCmd("say", Command_Say); - - RegConsoleCmd("sm_test", Command_TEST); - - /** - Load the translations - */ - LoadTranslations("common.phrases"); - LoadTranslations("simpledonatorbenefits.phrases"); - - /** - Load or create the config file - */ - AutoExecConfig(true, "plugin.simpledonatorbenefits"); - LogAction(0, -1, "[SDB] Simple Donator Benefits is loaded."); -} - -public OnAllPluginsLoaded() -{ - //something -} - -public OnLibraryRemoved(const String:name[]) -{ - //something -} - -public OnConfigsExecuted() -{ - /** - Load up all the variable defaults - */ - LoadUpVariables(); - - /** - If the join sound is enabled, prep the sound files - */ - if (g_bIsJoinSoundEnabled) - PrepSoundFile(); - - /** - Log our activity - */ - if (g_bIsEnabled) - LogAction(0, -1, "Simple Donation Benefits is ENABLED"); - else - LogAction(0, -1, "Simple Donation Benefits is DISABLED"); -} - -public OnClientPostAdminCheck(client) -{ - - /** - Check if the client is a donator - */ - if (SM_IsValidAdmin(client, g_sCharDonatorFlag)) - { - - /** - They are, so we set the player array to true and start a timer for the sound or add - */ - g_aPlayers[client][bIsDonator] = true; - if (g_bIsJoinSoundEnabled || g_bIsJoinPrivMsgEnabled) - { - CreateTimer(10.0, Timer_DonatorJoined, client, TIMER_FLAG_NO_MAPCHANGE); - } - } - else - { - /** - They aren't, so we set the player array to false - */ - g_aPlayers[client][bIsDonator] = false; - } -} - -public OnClientDisconnect_Post(client) -{ - - /** - Clean up the player variables - */ - CleanUpPlayer(client); -} - -public Action:Command_SwapTeam(client, args) -{ - - /** - Make sure we are enabled - */ - if (!g_bIsEnabled || !g_bIsSwapTeamEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the command is not started by the server - */ - if (client == 0) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure the player is a donator - */ - if (!g_aPlayers[client][bIsDonator]) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Lets make sure the client is one a team we can swap. - If he is we set the global array to the opposite team. - */ - new iTeam = GetClientTeam(client); - if (iTeam == g_aCurrentTeams[Team1]) - { - g_aPlayers[client][iNewTeam] = g_aCurrentTeams[Team2]; - } - else if (iTeam == g_aCurrentTeams[Team2]) - { - g_aPlayers[client][iNewTeam] = g_aCurrentTeams[Team1]; - } - else - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "InValidTeam", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check to see if we have command arguments. - */ - if (GetCmdArgs()) - { - - /** - We do, so lets get it and see if the client wants to be switched instantly or queued for death. - */ - decl String:sArg[5]; - GetCmdArg(1, sArg, sizeof(sArg)); - new iWantsQue = StringToInt(sArg); - if (iWantsQue && !g_aPlayers[client][bQueue]) - { - - /** - He wants the que and isn't already in it, set the global array. - */ - g_aPlayers[client][bQueue] = true; - ReplyToCommand(client, "\x01\x04[STM]\x01 %T", "PlayerQueue", LANG_SERVER); - } - else if (!iWantsQue) - { - - /** - He wants to be switched right now, lets call the stock function. - */ - SM_MovePlayer(client, g_aPlayers[client][iNewTeam]); - } - } - else - { - - /** - There are no command arguments so we build and display the swap menu. - */ - new Handle:hPlayerMenu = BuildSwapModeMenu(); - DisplayMenu(hPlayerMenu, client, MENU_TIME_FOREVER); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_InstantHealth(client, args) -{ - - /** - Make sure we are enabled - */ - if (!g_bIsEnabled || !g_bIsGiveHealthEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the command is not started by the server - */ - if (client == 0) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure the player is a donator - */ - if (!g_aPlayers[client][bIsDonator]) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check health count to see if the player has reached the max - */ - if (g_aPlayers[client][iHealthCount] >= g_iHealthCount) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "ReachedCount", LANG_SERVER); - return Plugin_Handled; - } - - /** - Get the class of the player and the max health for that class - */ - new iHealth = GetClientHealth(client); - new TFClassType:PlayerClass = TF2_GetPlayerClass(client); - new iMaxHealth = g_iClassMaxHealth[PlayerClass]; - - /** - Check to see if the player is at the max health of the class - */ - if (iHealth >= iMaxHealth) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "AtMaxHealth", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check the current health - */ - if (iHealth + g_iHealthBonus >= iMaxHealth) - { - - /** - Raise them to max health if the current health + bonus would go above it - */ - SetEntityHealth(client, iMaxHealth); - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "ToMaxHealth", LANG_SERVER); - } - else - { - - /** - Give them the instant health bonus - */ - SetEntityHealth(client, iHealth + g_iHealthBonus); - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "HealthBonus", LANG_SERVER); - } - - /** - Increase the count - */ - g_aPlayers[client][iHealthCount] += 1; - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_Teaser(client, args) -{ - - /** - Make sure we are enabled - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Check to see if we have command arguments. - */ - new iCmdArgs = GetCmdArgs(); - if (iCmdArgs == 0) - { - - /** - We don't so display the player menu. - */ - new Handle:hPlayerMenu = BuildPlayerMenu(); - DisplayMenu(hPlayerMenu, client, MENU_TIME_FOREVER); - return Plugin_Handled; - } - - /** - We have some arguments, see if we can find the player - */ - decl String:sPlayer[64]; - GetCmdArg(1, sPlayer, sizeof(sPlayer)); - new iTarget = FindTarget(client, sPlayer, true, true); - if (iTarget == -1 || !IsClientInGame(iTarget)) - { - - /** - We don't know who this is, so display the player menu. - */ - new Handle:hPlayerMenu = BuildPlayerMenu(); - DisplayMenu(hPlayerMenu, client, MENU_TIME_FOREVER); - } - else - { - /** - We found the player, see if we are supposed to turn it on or off. - */ - if (iCmdArgs >= 2) - { - decl String:sOn[3]; - GetCmdArg(2, sOn, sizeof(sOn)); - if (StringToInt(sOn)) - { - - /** - Turn temp benefits on. - */ - g_aPlayers[iTarget][bIsDonator] = true; - } - else - { - - /** - Turn temp benefits on. - */ - g_aPlayers[iTarget][bIsDonator] = false; - } - } - else - { - - /** - We don't know what to do, so just turn it on. - */ - g_aPlayers[iTarget][bIsDonator] = true; - } - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_Say(client, args) -{ - - /** - Make sure we are enabled. - */ - if (client == 0 || IsChatTrigger() || !g_bIsChatColorsEnabled || !g_bIsEnabled) - { - return Plugin_Continue; - } - - /** - Check the client to see if they are a donator. - */ - if (g_aPlayers[client][bIsDonator]) - { - - /** - The client is, so get the chat message and strip it down. - */ - decl String:sArg[CHAT_MAX_MESSAGE_LENGTH], - String:sChatMsg[CHAT_MAX_MESSAGE_LENGTH]; - new bool:bAlive = IsPlayerAlive(client); - GetCmdArgString(sArg, sizeof(sArg)); - StripQuotes(sArg); - TrimString(sArg); - new startidx; - if (sArg[strlen(sArg)-1] == '"') - { - sArg[strlen(sArg)-1] = '\0'; - startidx = 1; - } - - /** - Bug out if they are using the admin chat symbol (admin chat). - */ - if (sArg[startidx] == CHAT_SYMBOL) - { - return Plugin_Continue; - } - - /** - Format the message. - */ - FormatMessage(client, 0, bAlive, sChatMsg, sArg); - - /** - Send the message. - */ - SayText2(0, client, sChatMsg); - - /** - We are done, bug out, and stop the original chat message. - */ - return Plugin_Stop; - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Hacks_TakeDamageHook(client, attacker, inflictor, Float:damage, &Float:multiplier, damagetype) -{ - - /** - Make sure we are enabled and the client is a donator. - */ - if (g_bIsEnabled && g_bIsNoFallDmgEnabled && g_aPlayers[client][bIsDonator]) - { - - /** - Check for fall damage. - */ - if (damagetype & DMG_FALL) - { - - /** - Cancel the fall damage and bug out. - */ - multiplier *= 0.0; - return Plugin_Changed; - } - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Hacks_PreThinkHook(client) -{ - - /** - Make sure we are enabled and the client is a donator. - */ - if (!g_bIsEnabled || !g_bIsFastHeayEnabled || !g_aPlayers[client][bIsDonator]) - { - return Plugin_Continue; - } - - /** - Check the players class. We are looking for the heavy. - */ - new TFClassType:PlayerClass = TF2_GetPlayerClass(client); - if (PlayerClass == TFClass_Heavy) - { - - /** - We have a heavy, lets check the weapon. - */ - decl String:sWeaponCurrent[64]; - GetClientWeapon(client, sWeaponCurrent, sizeof(sWeaponCurrent)); - if (StrEqual(sWeaponCurrent, "tf_weapon_minigun", false)) - { - - /** - We have a minigun, check the heavies current weapon state to see if it's spinning. - */ - new iWeapon = GetPlayerWeaponSlot(client, 0); - new iWeaponState = GetEntProp(iWeapon, Prop_Send, "m_iWeaponState"); - if (iWeaponState > 0) - { - - /** - He is spinning, so lets change the heavies speed. - */ - new Float:fMaxSpeed = FloatMul(g_fHeavyMultiplier, float(g_fClassMaxSpeed[PlayerClass])); - SetEntPropFloat(client, Prop_Send, "m_flMaxspeed", fMaxSpeed); - } - } - } - - /** - We are done, bug out. - */ - // use Plugin_Continue (other options are ignored on PreThink hook) - return Plugin_Continue; -} - -public Action:HookPlayerConnect(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (!g_bIsEnabled || !g_bIsJoinPubMsgEnabled || !dontBroadcast) - { - return Plugin_Continue; - } - - /** - Get our event variables and check the client. - */ - new iUserId = GetEventInt(event,"userid"); - new iClient = GetClientOfUserId(iUserId); - if (iClient != 0) - { - - /** - Get the info on the client and format the message. - */ - decl String:sClientName[255], - String:sAuthID[255], - String:sMsg[1024]; - - GetEventString(event, "name", sClientName, sizeof(sClientName)); - GetClientAuthString(iClient, sAuthID, sizeof(sAuthID)); - Format(sMsg, sizeof(sMsg), "%T", "PublicJoinMessage", LANG_SERVER, sClientName); - - /** - Print the message to the clients and do the normal functions. - */ - for (new i = 1; i <= MaxClients; i++) - { - if(IsClientConnected(i) && IsClientInGame(i)) - { - PrintToChat(i,"\x01\x05%s", sMsg); - PrintToConsole(i,"%s has connected.", sClientName); - } - } - LogToGame("\"%s<%d><%s><>\" entered the game", sClientName, iUserId, sAuthID); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public HookPlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled && g_bIsUberChargeEnabled) - { - - /** - Get the event variables and check the class for medic - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - if (TF2_GetPlayerClass(iClient) == TFClass_Medic) - { - - /** - Start a timer to get the medic the uber boost - */ - CreateTimer(0.25, Timer_PlayerUberDelay, iClient, TIMER_FLAG_NO_MAPCHANGE); - } - } -} - -public HookPlayerClass(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled && g_bIsUberChargeEnabled) - { - - /** - Get the event variables and check the class for medic - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - if (TF2_GetPlayerClass(iClient) == TFClass_Medic) - { - - /** - Start a timer to get the medic the uber boost - */ - CreateTimer(0.25, Timer_PlayerUberDelay, iClient, TIMER_FLAG_NO_MAPCHANGE); - } - } -} - -public HookPlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled || g_bIsSwapTeamEnabled) - { - - /** - Get the event variables - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - new String:sWeapon[256]; - GetEventString(event, "weapon", sWeapon, sizeof(sWeapon)); - - /** - Bug out if world killed him. Means he changed team or something - */ - if (StrEqual(sWeapon, "world", false)) - { - g_aPlayers[iClient][bQueue] = false; - return; - } - - /** - If he is queued up, swap him - */ - if (g_aPlayers[iClient][bQueue]) - { - SM_MovePlayer(iClient, g_aPlayers[iClient][iNewTeam]); - } - } -} - -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled || g_bIsSwapTeamEnabled) - { - - /** - Get the event variables - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - - /** - If he is queued up, clear the status - */ - if (g_aPlayers[iClient][bQueue]) - { - g_aPlayers[iClient][bQueue] = false; - } - } -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set our variables. - */ - g_bRoundEnd = false; - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled && g_bIsImmuntyEnabled) - { - - /** - Get rid of their immunity. - */ - ProcessRoundEndImmunity(false); - } -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set our variables. - */ - g_bRoundEnd = true; - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled && g_bIsImmuntyEnabled) - { - - /** - Give them their immunity. - */ - ProcessRoundEndImmunity(true); - } -} - -public Action:Timer_DonatorJoined(Handle:timer, any:client) -{ - - /** - Make sure sounds are enabled. - */ - if (g_bIsEnabled && g_bIsJoinSoundEnabled) - { - EmitSoundToClient(client, g_sSoundFile); - } - - /** - Make sure private messages are enabled. - */ - if (g_bIsJoinPrivMsgEnabled) - { - - /** - Send messages to the client. - */ - decl String:sMsg[1024]; - Format(sMsg, sizeof(sMsg), "%T", "PrivateJoinMessage", LANG_SERVER); - PrintToChat(client,"\x01\x05%s", sMsg); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Timer_PlayerUberDelay(Handle:timer, any:client) -{ - - /** - Make sure the client is still in game. - */ - if (IsClientInGame(client)) - { - - /** - Make sure the client is still a medic. - */ - if (TF2_GetPlayerClass(client) == TFClass_Medic) - { - - /** - Get the medgun weapon index - */ - new iIndex = GetPlayerWeaponSlot(client, 1); - if (iIndex > 0) - { - - /** - Set the uber level with the bonus. - */ - SetEntPropFloat(iIndex, Prop_Send, "m_flChargeLevel", g_fUberLevel); - } - } - } -} - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (convar == sdb_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsEnabled = false; - } - else - { - g_bIsEnabled = true; - } - } - else if (convar == sdb_donationflag) - { - Format(g_sCharDonatorFlag, sizeof(g_sCharDonatorFlag), "%s", newValue); - } - else if (convar == sdb_soundfile) - { - Format(g_sSoundFile, sizeof(g_sSoundFile), "%s", newValue); - } - else if (convar == sdb_joinsound_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsJoinSoundEnabled = false; - } - else - { - g_bIsJoinSoundEnabled = true; - } - } - else if (convar == sdb_joinpubmsg_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsJoinPubMsgEnabled = false; - } - else - { - g_bIsJoinPubMsgEnabled = true; - } - } - else if (convar == sdb_joinprivmsg_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsJoinPrivMsgEnabled = false; - } - else - { - g_bIsJoinPrivMsgEnabled = true; - } - } - else if (convar == sdb_chatcolors_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsChatColorsEnabled = false; - } - else - { - g_bIsChatColorsEnabled = true; - } - } - else if (convar == sdb_immunity_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsImmuntyEnabled = false; - } - else - { - g_bIsImmuntyEnabled = true; - } - } - else if (convar == sdb_ubercharge_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsUberChargeEnabled = false; - } - else - { - g_bIsUberChargeEnabled = true; - } - } - else if (convar == sdb_givehealth_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsGiveHealthEnabled = false; - } - else - { - g_bIsGiveHealthEnabled = true; - } - } - else if (convar == sdb_nofalldmg_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsNoFallDmgEnabled = false; - } - else - { - g_bIsNoFallDmgEnabled = true; - } - } - else if (convar == sdb_fastheavy_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsFastHeayEnabled = false; - } - else - { - g_bIsFastHeayEnabled = true; - } - } - else if (convar == sdb_swapteam_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsSwapTeamEnabled = false; - } - else - { - g_bIsSwapTeamEnabled = true; - } - } - else if (convar == sdb_chatcolor) - { - Format(g_sChatColor, sizeof(g_sChatColor), "%s", newValue); - } - else if (convar == sdb_uberlevel) - { - g_fUberLevel = StringToFloat(newValue); - } - else if (convar == sdb_healthcount) - { - g_iHealthCount = StringToInt(newValue); - } - else if (convar == sdb_healthbonus) - { - g_iHealthBonus = StringToInt(newValue); - } - else if (convar == sdb_heavymultiplier) - { - g_fHeavyMultiplier = StringToFloat(newValue); - } -} - -stock LoadUpVariables() -{ - g_bIsEnabled = GetConVarBool(sdb_enabled); - g_bIsJoinSoundEnabled = GetConVarBool(sdb_enabled); - g_bIsJoinPubMsgEnabled = GetConVarBool(sdb_enabled); - g_bIsJoinPrivMsgEnabled = GetConVarBool(sdb_enabled); - g_bIsChatColorsEnabled = GetConVarBool(sdb_enabled); - g_bIsImmuntyEnabled = GetConVarBool(sdb_enabled); - g_bIsUberChargeEnabled = GetConVarBool(sdb_enabled); - g_bIsGiveHealthEnabled = GetConVarBool(sdb_enabled); - g_bIsNoFallDmgEnabled = GetConVarBool(sdb_enabled); - g_bIsFastHeayEnabled = GetConVarBool(sdb_enabled); - g_bIsSwapTeamEnabled = GetConVarBool(sdb_enabled); - GetConVarString(sdb_donationflag, g_sCharDonatorFlag, sizeof(g_sCharDonatorFlag)); - GetConVarString(sdb_soundfile, g_sSoundFile, sizeof(g_sSoundFile)); - GetConVarString(sdb_chatcolor, g_sChatColor, sizeof(g_sChatColor)); - g_bRoundEnd = false; - g_iHealthBonus = GetConVarInt(sdb_healthbonus); - g_iHealthCount = GetConVarInt(sdb_healthcount); - g_fHeavyMultiplier = GetConVarFloat(sdb_heavymultiplier); - g_fUberLevel = GetConVarFloat(sdb_uberlevel); -} - -stock PrepSoundFile() -{ - decl String:buffer[PLATFORM_MAX_PATH]; - PrecacheSound(g_sSoundFile, true); - Format(buffer, sizeof(buffer), "sound/%s", g_sSoundFile); - AddFileToDownloadsTable(buffer); -} - -stock CleanUpPlayer(client) -{ - g_aPlayers[client][bIsDonator] = false; - g_aPlayers[client][bQueue] = false; - g_aPlayers[client][bImmune] = false; - g_aPlayers[client][iNewTeam] = 0; - g_aPlayers[client][iHealthCount] = 0; -} - -stock ProcessRoundEndImmunity(bool:give) -{ - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][bIsDonator]) - { - if (give) - { - SetEntProp(i, Prop_Data, "m_takedamage", 0, 1); - g_aPlayers[i][bImmune] = true; - } - else - { - SetEntProp(i, Prop_Data, "m_takedamage", 2, 1); - g_aPlayers[i][bImmune] = false; - } - } - } -} - -stock FormatMessage(iClient, iTeam, bool:bAlive, String:sChatMsg[], const Sting:sMessage[]) -{ - decl String:sDead[10], - String:sTeam[10], - String:sClientName[64]; - GetClientName(iClient, sClientName, sizeof(sClientName)); - if (iTeam != 0) - Format(sTeam, sizeof(sTeam), "(TEAM) "); - else - Format(sTeam, sizeof(sTeam), ""); - if (bAlive) - Format(sDead, sizeof(sDead), ""); - else - Format(sDead, sizeof(sDead), "*DEAD* "); - if (StrContains(g_sChatColor, "light", false) == -1) - Format(sChatMsg, CHAT_MAX_MESSAGE_LENGTH, "\x01%s%s\x03%s \x01: \x05%s", sDead, sTeam, sClientName, sMessage); - else - Format(sChatMsg, CHAT_MAX_MESSAGE_LENGTH, "\x01%s%s\x03%s \x01: \x04%s", sDead, sTeam, sClientName, sMessage); -} - -stock SayText2(target, author, const String:message[]) -{ - new Handle:hBf; - if (target == 0) - hBf = StartMessageAll("SayText2"); - else - hBf = StartMessageOne("SayText2", target); - if (hBf != INVALID_HANDLE) - { - BfWriteByte(hBf, author); - BfWriteByte(hBf, true); - BfWriteString(hBf, message); - EndMessage(); - } -} - -stock ProcessAdmins() -{ - for (new i = 1; i <= MaxClients; i++) - { - if (SM_IsValidAdmin(i, g_sCharDonatorFlag)) - { - g_aPlayers[i][bDonator] = true; - } - else - { - g_aPlayers[i][bDonator] = false; - } - } -} - -stock ProcessLate() -{ - if (g_bIsEnabled) - { - ProcessAdmins(); - PrepSoundFile(); - if (g_bRoundEnd && g_bIsImmuntyEnabled) - { - ProcessRoundEndImmunity(true); - } - if (!g_bIsImmuntyEnabled) - { - ProcessRoundEndImmunity(false); - } - } - else - { - ProcessRoundEndImmunity(false); - } -} - -public Menu_SwapMode(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, 64); - if (StringToInt(sSelection)) - g_aPlayers[param1][bQueue] = false; - else - g_aPlayers[param1][bQueue] = true; - if (!g_aPlayers[param1][bQueue]) - SM_MovePlayer(param1, g_aPlayers[param1][iNewTeam]); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -public Menu_SelectPlayer(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[256]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - new iTarget = GetClientOfUserId(StringToInt(sSelection)); - if (g_aPlayers[iTarget][bIsDonator]) - g_aPlayers[iTarget][bIsDonator] = false; - else - g_aPlayers[iTarget][bIsDonator] = true; - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -stock Handle:BuildSwapModeMenu() -{ - new Handle:menu = CreateMenu(Menu_SwapMode); - SetMenuTitle(menu, "Select When to Swap:"); - AddMenuItem(menu, "0", "Instantly (Kills)"); - AddMenuItem(menu, "1", "Queue on next death"); - SetMenuExitBackButton(menu, false); - return menu; -} - -stock Handle:BuildPlayerMenu() -{ - new Handle:menu = CreateMenu(Menu_SelectPlayer); - AddTargetsToMenu(menu, 0, true, false); - SetMenuTitle(menu, "Select A Player:"); - SetMenuExitBackButton(menu, true); - return menu; -} - -public Action:Command_TEST(client, args) -{ - -} \ No newline at end of file diff --git a/Simple Team Manager/addons/sourcemod/scripting/simple-messagesuppression.sp b/Simple Team Manager/addons/sourcemod/scripting/simple-messagesuppression.sp deleted file mode 100644 index f7725a4..0000000 --- a/Simple Team Manager/addons/sourcemod/scripting/simple-messagesuppression.sp +++ /dev/null @@ -1,227 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Message Suppression -Description: - Blocks Specific Message Outputs -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include -#include - -#define SUPPRESS_VERSION "1.1.$Rev$" - -public Plugin:myinfo = -{ - name = "Simple Message Suppression", - author = "FlyingMongoose, psychonic", - description = "Blocks Specific Message Outputs", - version = SUPPRESS_VERSION, - url = "http://www.simple-plugins.com/" -} - -new Handle:cvarBlockSpectateMessage; -new Handle:cvarBlockDisconnectMessage; -new Handle:cvarBlockConnectMessage; -new Handle:cvarAdminShowMessages; -new iSpecTeam = 1; - - -public OnPluginStart() -{ - CreateConVar("suppress_version", SUPPRESS_VERSION, _, FCVAR_PLUGIN|FCVAR_NOTIFY|FCVAR_REPLICATED|FCVAR_SPONLY|FCVAR_DONTRECORD); - cvarBlockSpectateMessage = CreateConVar("sm_blockspectatemessage", "1", "If enabled it blocks the join team message if an administrator joins spectator", FCVAR_PLUGIN, true, 0.0, true, 1.0); - cvarBlockDisconnectMessage = CreateConVar("sm_blockdisconnectmessage", "1", "Blocks the disconnect message", FCVAR_PLUGIN, true, 0.0, true, 1.0); - cvarBlockConnectMessage = CreateConVar("sm_blockconnectmessage", "1", "If enabled it blocks the player connection message.", FCVAR_PLUGIN, true, 0.0, true, 1.0); - cvarAdminShowMessages = CreateConVar("sm_adminshowmessages", "1", "Shows disconnect/connect/team join messages for admins only (if disconnect message is set to be blocked)", FCVAR_PLUGIN, true, 0.0, true, 1.0); - HookEvent("player_team", ev_PlayerTeam, EventHookMode_Pre); - HookEvent("player_disconnect", ev_PlayerDisconnect, EventHookMode_Pre); - HookEvent("player_connect", ev_PlayerConnect, EventHookMode_Pre); - - new String:game_folder[64]; - GetGameFolderName(game_folder, sizeof(game_folder)) - - if (StrContains(game_folder, "insurgency", false) != -1) - { - iSpecTeam = 3; - } - else - { - new String:game_description[64]; - GetGameDescription(game_description, sizeof(game_description), true); - if (StrContains(game_description, "Insurgency", false) != -1) - { - iSpecTeam = 3; - } - } - - AutoExecConfig(true, "suppressmessage", "sourcemod"); -} - -public Action:ev_PlayerTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (GetConVarBool(cvarBlockSpectateMessage)) - { - if (!dontBroadcast && !GetEventBool(event, "silent")) - { - new iUserId = GetEventInt(event, "userid"); - new iClient = GetClientOfUserId(iUserId); - new iTeam = GetEventInt(event, "team"); - - if (iTeam == iSpecTeam && GetAdminFlag(GetUserAdmin(iClient), Admin_Kick)) - { - new iOldTeam = GetEventInt(event, "oldteam"); - new bool:bDisconnect = GetEventBool(event, "disconnect"); - new bool:bAutoteam = GetEventBool(event, "autoteam"); - decl String:strName[50]; - GetEventString(event, "name", strName, sizeof(strName)); - - if (iClient != 0) - { - if (GetConVarInt(cvarAdminShowMessages) == 1) - { - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i) && GetUserAdmin(i) != INVALID_ADMIN_ID) - { - PrintToChat(i,"%N joined team Spectator.", iClient); - PrintToConsole(i,"%N joined team Spectator.", iClient); - } - } - } - } - - new Handle:hEvent = CreateEvent("player_team"); - SetEventInt(hEvent, "userid", iUserId); - SetEventInt(hEvent, "team", iTeam); - SetEventInt(hEvent, "oldteam", iOldTeam); - SetEventBool(hEvent, "disconnect", bDisconnect); - SetEventBool(hEvent, "autoteam", bAutoteam); - SetEventBool(hEvent, "silent", true); - SetEventString(hEvent, "name", strName); - - FireEvent(hEvent, true); - - return Plugin_Handled; - } - } - } - return Plugin_Continue; -} -public Action:ev_PlayerConnect(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (GetConVarBool(cvarBlockConnectMessage)) - { - if (!dontBroadcast) - { - decl String:strName[50]; - GetEventString(event, "name", strName, sizeof(strName)); - new iIndex = GetEventInt(event, "index"); - new iUserId = GetEventInt(event, "userid"); - new iClient = GetClientOfUserId(iUserId); - decl String:strNetworkId[50]; - GetEventString(event, "networkid", strNetworkId, sizeof(strNetworkId)); - decl String:strAddress[50]; - GetEventString(event, "address", strAddress, sizeof(strAddress)); - - if (iClient != 0) - { - if (GetConVarInt(cvarAdminShowMessages) == 1) - { - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i) && GetUserAdmin(i) != INVALID_ADMIN_ID) - { - PrintToChat(i,"%N has connected.", iClient); - PrintToConsole(i,"%N has connected.", iClient); - } - } - } - } - - new Handle:hEvent = CreateEvent("player_connect"); - SetEventString(hEvent, "name", strName); - SetEventInt(hEvent, "index", iIndex); - SetEventInt(hEvent, "userid", iUserId); - SetEventString(hEvent, "networkid", strNetworkId); - SetEventString(hEvent, "address", strAddress); - - FireEvent(hEvent, true); - - return Plugin_Handled; - } - } - return Plugin_Continue; -} -public Action:ev_PlayerDisconnect(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (GetConVarBool(cvarBlockDisconnectMessage)) - { - if (!dontBroadcast) - { - new iUserId = GetEventInt(event, "userid"); - new iClient = GetClientOfUserId(iUserId); - decl String:strReason[50]; - GetEventString(event, "reason", strReason, sizeof(strReason)); - decl String:strName[50]; - GetEventString(event, "name", strName, sizeof(strName)); - decl String:strNetworkId[50]; - GetEventString(event, "networkid", strNetworkId, sizeof(strNetworkId)); - - if (iClient != 0) - { - if (GetConVarInt(cvarAdminShowMessages) == 1) - { - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i) && GetUserAdmin(i) != INVALID_ADMIN_ID) - { - PrintToChat(i, "%N has left the server.", iClient); - PrintToConsole(i, "Dropped %N from server (Disconnect by user.)", iClient); - } - } - } - } - - new Handle:hEvent = CreateEvent("player_disconnect"); - SetEventInt(hEvent, "userid", iUserId); - SetEventString(hEvent, "reason", strReason); - SetEventString(hEvent, "name", strName); - SetEventString(hEvent, "networkid", strNetworkId); - - FireEvent(hEvent, true); - - return Plugin_Handled; - } - } - - return Plugin_Continue; -} \ No newline at end of file diff --git a/Simple Team Manager/addons/sourcemod/scripting/simple-plugins.sp b/Simple Team Manager/addons/sourcemod/scripting/simple-plugins.sp deleted file mode 100644 index 4462b41..0000000 --- a/Simple Team Manager/addons/sourcemod/scripting/simple-plugins.sp +++ /dev/null @@ -1,785 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Plugins -Description: - Core plugin for Simple Plugins project -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#define CORE_PLUGIN_VERSION "1.1.$Rev$" - -#include - -enum e_PlayerInfo -{ - Handle:hForcedTeamPlugin = INVALID_HANDLE, - iForcedTeam = 0, - iBuddy = 0, - bool:bBuddyLocked = false -}; - -new Handle:g_fwdPlayerMoved; -new g_aPlayers[MAXPLAYERS + 1][e_PlayerInfo]; -new bool:g_bTeamsSwitched = false; - -/** -Setting our plugin information. -*/ -public Plugin:myinfo = -{ - name = "Simple Plugins Core Plugin", - author = "Simple Plugins", - description = "Core plugin for Simple Plugins", - version = CORE_PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -public bool:AskPluginLoad(Handle:myself, bool:late, String:error[], err_max) -{ - - /** - Register natives for other plugins - */ - CreateNative("SM_MovePlayer", Native_SM_MovePlayer); - CreateNative("SM_SetForcedTeam", Native_SM_SetForcedTeam); - CreateNative("SM_GetForcedTeam", Native_SM_GetForcedTeam); - CreateNative("SM_ClearForcedTeam", Native_SM_ClearForcedTeam); - CreateNative("SM_GetForcedPlayer", Native_SM_GetForcedPlayer); - CreateNative("SM_AssignBuddy", Native_SM_AssignBuddy); - CreateNative("SM_GetClientBuddy", Native_SM_GetClientBuddy); - CreateNative("SM_LockBuddy", Native_SM_LockBuddy); - CreateNative("SM_IsBuddyLocked", Native_SM_IsBuddyLocked); - CreateNative("SM_ClearBuddy", Native_SM_ClearBuddy); - CreateNative("SM_IsValidAdmin", Native_SM_IsValidAdmin); - CreateNative("SM_IsValidTeam", Native_SM_IsValidTeam); - RegPluginLibrary("simpleplugins"); - return true; -} - -public OnPluginStart() -{ - - CreateConVar("ssm_core_pl_ver", CORE_PLUGIN_VERSION, "Simple SourceMod Plugins Core Plugin Version", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - CreateConVar("ssm_core_inc_ver", CORE_INC_VERSION, "Simple SourceMod Plugins Core Include Version", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook some events to control forced players and check extensions - */ - decl String:sExtError[256]; - LogAction(0, -1, "[SSM] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Pre); - switch (g_CurrentMod) - { - case GameType_CSS: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - new iExtStatus = GetExtensionFileStatus("game.cstrike.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SSM] Required extension was not found."); - LogAction(0, -1, "[SSM] Plugin FAILED TO LOAD."); - SetFailState("Required extension was not found."); - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SSM] Required extension is loaded with errors."); - LogAction(0, -1, "[SSM] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SSM] Plugin FAILED TO LOAD."); - SetFailState("Required extension is loaded with errors."); - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SSM] Required extension is loaded."); - } - } - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_PostNoCopy); - HookUserMessage(GetUserMessageId("TextMsg"), UserMessageHook_Class, true); - new iExtStatus = GetExtensionFileStatus("game.tf2.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SSM] Required extension was not found."); - LogAction(0, -1, "[SSM] Plugin FAILED TO LOAD."); - SetFailState("Required extension was not found."); - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SSM] Required extension is loaded with errors."); - LogAction(0, -1, "[SSM] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SSM] Plugin FAILED TO LOAD."); - SetFailState("Required extension is loaded with errors."); - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SSM] Required extension is loaded."); - } - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_PostNoCopy); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - - /** - Load common translations - */ - LoadTranslations ("common.phrases"); - - /** - Create the global forward - */ - g_fwdPlayerMoved = CreateGlobalForward("SM_OnPlayerMoved", ET_Event, Param_Cell, Param_Cell, Param_Cell); -} - -public OnClientDisconnect(client) -{ - - /** - Cleanup clients/players buddy list - */ - if (!IsFakeClient(client)) - { - SM_ClearBuddy(client, true); - SM_LockBuddy(client, false); - } - SM_ClearForcedTeam(client); -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - See if the teams have been switched - */ - if (g_bTeamsSwitched) - { - - /** - Switch the teams the players are forced to - */ - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][iForcedTeam] != 0) - { - if (g_aPlayers[i][iForcedTeam] == g_aCurrentTeams[Team1]) - { - g_aPlayers[i][iForcedTeam] = g_aCurrentTeams[Team2]; - } - else - { - g_aPlayers[i][iForcedTeam] = g_aCurrentTeams[Team1]; - } - } - } - } -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - g_bTeamsSwitched = false; -} - -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get our event variables - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - new iTeam = GetEventInt(event, "team"); - - /** - See if the player is on the wrong team - */ - if (g_aPlayers[iClient][iForcedTeam] != 0 && g_aPlayers[iClient][iForcedTeam] != iTeam) - { - - /** - Move the player back to the forced team - */ - CreateTimer(1.0, Timer_ForcePlayerMove, iClient, TIMER_FLAG_NO_MAPCHANGE); - - /** - If the event was going to be broadcasted, we refire it so it is not broadcasted and stop this one - */ - if (!dontBroadcast) - { - new Handle:hEvent = CreateEvent("player_team"); - SetEventInt(hEvent, "userid", GetEventInt(event, "userid")); - SetEventInt(hEvent, "team", GetEventInt(event, "team")); - SetEventInt(hEvent, "oldteam", GetEventInt(event, "oldteam")); - SetEventBool(hEvent, "disconnect", GetEventBool(event, "disconnect")); - - if (g_CurrentMod == GameType_DOD || g_CurrentMod == GameType_L4D || g_CurrentMod == GameType_TF) - { - new String:sClientName[MAX_NAME_LENGTH + 1]; - GetClientName(client, sClientName, sizeof(sClientName)); - SetEventBool(hEvent, "autoteam", GetEventBool(event, "autoteam")); - SetEventBool(hEvent, "silent", true); - SetEventString(hEvent, "name", sClientName); - FireEvent(hEvent, true); - } - else - { - FireEvent(hEvent, true); - } - return Plugin_Handled; - } - } - return Plugin_Continue; -} - -public Action:UserMessageHook_Class(UserMsg:msg_id, Handle:bf, const players[], playersNum, bool:reliable, bool:init) -{ - new String:sMessage[120]; - BfReadString(bf, sMessage, sizeof(sMessage), true); - if (StrContains(sMessage, "#TF_TeamsSwitched", false) != -1) - { - g_bTeamsSwitched = true; - } - return Plugin_Continue; -} - -public Native_SM_MovePlayer(Handle:plugin, numParams) -{ - - /** - Get and check the client and team - */ - new iClient = GetNativeCell(1); - new iTeam = GetNativeCell(2); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (iTeam != g_aCurrentTeams[Spectator] && iTeam != g_aCurrentTeams[Team1] && iTeam != g_aCurrentTeams[Team2]) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid team %d", iTeam); - } - - MovePlayer(iClient, iTeam); - if (!IsClientObserver(iClient)) - { - RespawnPlayer(iClient); - } - - new fResult; - - Call_StartForward(g_fwdPlayerMoved); - Call_PushCell(plugin); - Call_PushCell(iClient); - Call_PushCell(iTeam); - Call_Finish(fResult); - - if (fResult != SP_ERROR_NONE) - { - return ThrowNativeError(fResult, "Forward failed"); - } - - return fResult; -} - -public Native_SM_SetForcedTeam(Handle:plugin, numParams) -{ - - /** - Get and check the client and team - */ - new iClient = GetNativeCell(1); - new iTeam = GetNativeCell(2); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (iTeam != g_aCurrentTeams[Spectator] && iTeam != g_aCurrentTeams[Team1] && iTeam != g_aCurrentTeams[Team2] && iTeam != g_aCurrentTeams[Unknown]) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid team %d", iTeam); - } - - new bool:bOverRide = GetNativeCell(3) ? true : false; - - if (!bOverRide && g_aPlayers[iClient][hForcedTeamPlugin] != INVALID_HANDLE && plugin != g_aPlayers[iClient][hForcedTeamPlugin]) - { - return false; - } - - g_aPlayers[iClient][hForcedTeamPlugin] = plugin; - g_aPlayers[iClient][iForcedTeam] = iTeam; - return true; -} - -public Native_SM_GetForcedTeam(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - - /** - Get and set the plugin if they want it - */ - new Handle:hPlugin = GetNativeCell(2); - if (hPlugin != INVALID_HANDLE) - { - SetNativeCellRef(2, g_aPlayers[iClient][hForcedTeamPlugin]); - } - - /** - Return the forced team, this could be 0 - */ - return g_aPlayers[iClient][iForcedTeam]; -} - -public Native_SM_ClearForcedTeam(Handle:plugin, numParams) -{ - - /** - Get and check the client and team - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - - g_aPlayers[iClient][hForcedTeamPlugin] = INVALID_HANDLE; - g_aPlayers[iClient][iForcedTeam] = 0; - - return true; -} - -public Native_SM_GetForcedPlayer(Handle:plugin, numParams) -{ - - /** - Get and check the team - */ - new iTeam = GetNativeCell(1); - if (iTeam != g_aCurrentTeams[Spectator] && iTeam != g_aCurrentTeams[Team1] && iTeam != g_aCurrentTeams[Team2]) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid team %d", iTeam); - } - - /** - Start a loop to check for a player on the wrong team - Also make sure the plugin that set the forced team is the plugin that asked - */ - new iPlayer = 0; - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientInGame(i) - && GetClientTeam(i) != g_aPlayers[i][iForcedTeam] - && g_aPlayers[i][iForcedTeam] == iTeam - && g_aPlayers[i][hForcedTeamPlugin] == plugin) - { - iPlayer = i; - break; - } - } - - /** - Return the player we found, this could be 0 - */ - return iPlayer; -} - -public Native_SM_AssignBuddy(Handle:plugin, numParams) -{ - - /** - Get and check the client and player - */ - new iClient = GetNativeCell(1); - new iPlayer = GetNativeCell(2); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (iPlayer < 0 || iPlayer > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid player index (%d)", iPlayer); - } - if (!IsClientConnected(iPlayer)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Player %d is not connected", iPlayer); - } - if (!IsClientInGame(iPlayer)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Player %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Bots are not supported"); - } - - /** - See if we can override his setting - */ - new bool:bOverRide = GetNativeCell(3) ? true : false; - if (!bOverRide) - { - - /** - We can't override, so check if they are locked - */ - if (g_aPlayers[iClient][bBuddyLocked] || g_aPlayers[iPlayer][bBuddyLocked]) - { - - /** - We detected at least 1 lock, so we bug out - */ - return false; - } - } - - /** - Ready to set the buddies - */ - g_aPlayers[iClient][iBuddy] = iPlayer; - g_aPlayers[iPlayer][iBuddy] = iClient; - return true; -} - -public Native_SM_GetClientBuddy(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Bots are not supported"); - } - - /** - Return the players buddy, this could be 0 - */ - return g_aPlayers[iClient][iBuddy]; -} - -public Native_SM_LockBuddy(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - new bool:bSetting = GetNativeCell(2) ? true : false; - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Bots are not supported"); - } - - g_aPlayers[iClient][bBuddyLocked] = bSetting; - return true; -} - -public Native_SM_IsBuddyLocked(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Bots are not supported"); - } - - return g_aPlayers[iClient][bBuddyLocked]; -} - -public Native_SM_ClearBuddy(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Client (%d) is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Bots are not supported"); - } - - /** - Get the clients buddy and see if we can override his setting - */ - new bool:bOverRide = GetNativeCell(2) ? true : false; - new iPlayer = g_aPlayers[iClient][iBuddy]; - - /** - There is no buddy, we don't care about anything else so bug out - */ - if (iPlayer == 0) - { - return true; - } - - /** - We determined he had a buddy, check the override setting - */ - if (!bOverRide) - { - - /** - We can't override, so check if they are locked - */ - if (g_aPlayers[iClient][bBuddyLocked] || g_aPlayers[iPlayer][bBuddyLocked]) - { - - /** - We detected at least 1 lock, so we bug out - */ - return false; - } - } - - /** - Ready to clear the buddies - */ - g_aPlayers[iClient][iBuddy] = 0; - g_aPlayers[iPlayer][iBuddy] = 0; - return true; -} - -public Native_SM_IsValidTeam(Handle:plugin, numParams) -{ - - /** - Get the team - */ - new iTeam = GetNativeCell(1); - - /** - Check the team - */ - if (iTeam == g_aCurrentTeams[Spectator] || iTeam == g_aCurrentTeams[Team1] || iTeam == g_aCurrentTeams[Team2]) - { - return true; - } - return false; -} - -public Native_SM_IsValidAdmin(Handle:plugin, numParams) -{ - /** - Get the client and flags - */ - new iClient = GetNativeCell(1); - decl String:sFlags[15]; - GetNativeString(2, sFlags, sizeof(sFlags)); - new ibFlags = ReadFlagString(sFlags); - - /** - Check the flags - */ - if ((GetUserFlagBits(iClient) & ibFlags) == ibFlags) - { - return true; - } - if (GetUserFlagBits(iClient) & ADMFLAG_ROOT) - { - return true; - } - return false; -} - -public Action:Timer_ForcePlayerMove(Handle:timer, any:iClient) -{ - - MovePlayer(iClient, g_aPlayers[iClient][iForcedTeam]); - - if (g_aPlayers[iClient][iForcedTeam] != g_aCurrentTeams[Spectator]) - { - RespawnPlayer(iClient); - } - - PrintToChat(iClient, "\x01\x04----------------------------------"); - PrintToChat(iClient, "\x01\x04You have been forced to this team."); - PrintToChat(iClient, "\x01\x04----------------------------------"); - - return Plugin_Handled; -} - -stock MovePlayer(iClient, iTeam) -{ - - /** - Change the client's team based on the mod - */ - switch (g_CurrentMod) - { - case GameType_CSS: - { - CS_SwitchTeam(iClient, iTeam); - } - default: - { - ChangeClientTeam(iClient, iTeam); - } - } -} - -stock RespawnPlayer(iClient) -{ - - /** - Respawn the client based on the mod - */ - switch (g_CurrentMod) - { - case GameType_CSS: - { - CS_RespawnPlayer(iClient); - } - case GameType_TF: - { - TF2_RespawnPlayer(iClient); - } - case GameType_INS: - { - FakeClientCommand(iClient, "kill"); - } - default: - { - // - } - } -} diff --git a/Simple Team Manager/addons/sourcemod/scripting/simple-roundimmunity.sp b/Simple Team Manager/addons/sourcemod/scripting/simple-roundimmunity.sp deleted file mode 100644 index 5f0bca3..0000000 --- a/Simple Team Manager/addons/sourcemod/scripting/simple-roundimmunity.sp +++ /dev/null @@ -1,947 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Round Immunity -Description: - Gives admins immunity during certain rounds -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or any later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#pragma semicolon 1 -#include -#include -#undef REQUIRE_EXTENSIONS -#undef AUTOLOAD_EXTENSIONS -#include -#include -#define REQUIRE_EXTENSIONS -#define AUTOLOAD_EXTENSIONS - -#define PLUGIN_VERSION "1.1.$Rev$" -#define SPECTATOR 1 -#define TEAM_RED 2 -#define TEAM_BLUE 3 - -#define COLOR_GREEN 0 -#define COLOR_BLACK 1 -#define COLOR_RED 2 -#define COLOR_BLUE 3 -#define COLOR_TEAM 4 -#define COLOR_RAINBOW 5 -#define COLOR_NONE 6 - -#define PLAYERCOND_SLOWED (1<<0) //1 -#define PLAYERCOND_ZOOMED (1<<1) //2 -#define PLAYERCOND_DISGUISING (1<<2) //4 -#define PLAYERCOND_DISGUISED (1<<3) //8 -#define PLAYERCOND_SPYCLOAK (1<<4) //16 -#define PLAYERCOND_UBERED (1<<5) //32 -#define PLAYERCOND_TELEPORTTRAIL (1<<6) //64 -#define PLAYERCOND_TAUNT (1<<7) //128 -// (1<<8) //256 -// (1<<9) //512 -#define PLAYERCOND_TELEPORTFLASH (1<<10) //1024 -#define PLAYERCOND_KRUBER (1<<11) //2048 -// (1<<12) //4096 -// (1<<13) //8192 -#define PLAYERCOND_BONKED (1<<14) //16384 (blame Neph if it doesn't work) -#define PLAYERCOND_BONKEDORDRINKSLOWDOWN (1<<15) //32768 -#define PLAYERCOND_HEALING (1<<16) //65536 -#define PLAYERCOND_BURNING (1<<17) //131072 -#define PLAYERCOND_FULLYCHARGEDBYMEDIC (1<<18) //262144 - -enum e_Cookies -{ - bEnabled, - iColor, - iMode -}; - -enum e_ColorNames -{ - Green, - Black, - Red, - Blue -}; - -enum e_ColorValues -{ - iRed, - iGreen, - iBlue -}; - -enum e_PlayerData -{ - Handle:hGodModeTimer, - Handle:hColorTimer, - bool:bIsAdmin, - bool:bIsImmune, - iCycleColor -}; - -/** - Global convar handles - */ -new Handle:sri_charadminflag = INVALID_HANDLE; -new Handle:sri_enabled = INVALID_HANDLE; -new Handle:sri_cookie_enabled = INVALID_HANDLE; -new Handle:sri_cookie_color = INVALID_HANDLE; -new Handle:sri_cookie_mode = INVALID_HANDLE; - -/** - Player arrays - */ -new g_aPlayers[MAXPLAYERS + 1][e_PlayerData]; -new g_aClientCookies[MAXPLAYERS + 1][e_Cookies]; - -/** - Global bools - */ -new bool:g_bLoadedLate = false; -new bool:g_bIsEnabled = true; -new bool:g_bRoundEnd = false; -new bool:g_bUseDukehacks = false; -new bool:g_bUseClientprefs = false; - -/** - Global strings/integers/floats - */ -new String:g_sCharAdminFlag[32]; -new g_iColors[e_ColorNames][e_ColorValues]; -new g_iClassMaxHealth[TFClassType] = {0, 125, 125, 200, 175, 150, 300, 175, 125, 125}; - -public Plugin:myinfo = -{ - name = "Simple Round Immunity", - author = "Simple Plugins", - description = "Gives admins immunity during certain rounds", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -} - -bool:AskPluginLoad(Handle:myself, bool:late, String:error[], err_max) -{ - g_bLoadedLate = late; - return true; -} - -public OnPluginStart() -{ - - /** - Create console variables - */ - CreateConVar("sri_version", PLUGIN_VERSION, "Simple Round Immunity", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - sri_enabled = CreateConVar("sri_enabled", "1", "Enable/Disable Admin immunity during certain round."); - sri_charadminflag = CreateConVar("sri_charadminflag", "a", "Admin flag to use for immunity (only one). Must be a in char format."); - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook some events and check extensions - */ - decl String:sExtError[256]; - LogAction(0, -1, "[SRI] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_spawn", HookPlayerSpawn, EventHookMode_Post); - HookEvent("player_hurt", HookPlayerHurt, EventHookMode_Pre); - switch (g_CurrentMod) - { - case GameType_CSS: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - new iExtStatus = GetExtensionFileStatus("game.cstrike.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SRI] Required extension was not found."); - LogAction(0, -1, "[SRI] Plugin FAILED TO LOAD."); - SetFailState("Required extension was not found."); - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SRI] Required extension is loaded with errors."); - LogAction(0, -1, "[SRI] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SRI] Plugin FAILED TO LOAD."); - SetFailState("Required extension is loaded with errors."); - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SRI] Required css extension is loaded."); - } - } - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_PostNoCopy); - HookUserMessage(GetUserMessageId("TextMsg"), UserMessageHook_Class, true); - new iExtStatus = GetExtensionFileStatus("game.tf2.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SRI] Required extension was not found."); - LogAction(0, -1, "[SRI] Plugin FAILED TO LOAD."); - SetFailState("Required extension was not found."); - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SRI] Required extension is loaded with errors."); - LogAction(0, -1, "[SRI] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SRI] Plugin FAILED TO LOAD."); - SetFailState("Required extension is loaded with errors."); - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SRI] Required tf2 extension is loaded."); - } - iExtStatus = GetExtensionFileStatus("dukehacks.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SRI] Dukehacks extension was not found."); - LogAction(0, -1, "[SRI] Plugin continued to load, but that feature will not be used."); - g_bUseDukehacks = false; - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SRI] Dukehacks extension is loaded with errors."); - LogAction(0, -1, "[SRI] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SRI] Plugin continued to load, but that feature will not be used."); - g_bUseDukehacks = false; - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SRI] Dukehacks extension is loaded and will be used."); - g_bUseDukehacks = true; - dhAddClientHook(CHK_TakeDamage, Hacks_TakeDamageHook); - } - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_PostNoCopy); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - /** - Now lets check for client prefs extension - */ - new iExtStatus = GetExtensionFileStatus("clientprefs.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SRI] Client Preferences extension was not found."); - LogAction(0, -1, "[SRI] Plugin continued to load, but that feature will not be used."); - g_bUseClientprefs = false; - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SRI] Client Preferences extension is loaded with errors."); - LogAction(0, -1, "[SRI] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SRI] Plugin continued to load, but that feature will not be used."); - g_bUseClientprefs = false; - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SRI] Client Preferences extension is loaded, checking database."); - if (!SQL_CheckConfig(clientprefs)) - { - LogAction(0, -1, "[SRI] No 'clientprefs' database found. Check your database.cfg file."); - LogAction(0, -1, "[SRI] Plugin continued to load, but Client Preferences will not be used."); - g_bUseClientprefs = false; - } - g_bUseClientprefs = true; - - /** - Deal with client cookies - */ - sri_cookie_enabled = RegClientCookie("bri_client_enabled", "Enable/Disable your immunity during the bonus round.", CookieAccess_Public); - sri_cookie_color = RegClientCookie("bri_client_color", "Color to render when immune.", CookieAccess_Public); - sri_cookie_mode = RegClientCookie("bri_client_mode", "God mode to select", CookieAccess_Public); - SetCookieMenuItem(CookieMenu_TopMenu, sri_cookie_enabled, "Bonus Round Immunity"); - } - - HookConVarChange(sri_enabled, EnabledChanged); - - RegAdminCmd("sm_immunity", Command_Immunity, ADMFLAG_ROOT, "sm_immunity: Gives you immunity"); - - LoadColors(); - - AutoExecConfig(true, "plugin.simpleroundimmunity"); -} - -public OnAllPluginsLoaded() -{ - //something - // need to deal with the unloading of dukehacks, clientprefs, and simpleplugins - // should move hooking the client prefs cookies to a function to make sure they are done post plugin start if ext is loaded late -} - -public OnLibraryRemoved(const String:name[]) -{ - //something - // need to deal with the loading of dukehacks, clientprefs, and simpleplugins -} - -public OnConfigsExecuted() -{ - GetConVarString(sri_charadminflag, g_sCharAdminFlag, sizeof(g_sCharAdminFlag)); - g_bIsEnabled = GetConVarBool(sri_enabled); - g_bRoundEnd = false; -} - -/** - Client events - */ - -public OnClientPostAdminCheck(client) -{ - if (SM_IsValidAdmin(client, g_sCharAdminFlag)) - g_aPlayers[client][bIsAdmin] = true; - else - g_aPlayers[client][bIsAdmin] = false; -} - -public OnClientCookiesCached(client) -{ - decl String:sEnabled[2], String:sColor[4], String:sMode[2]; - GetClientCookie(client, sri_cookie_enabled, sEnabled, sizeof(sEnabled)); - GetClientCookie(client, sri_cookie_color, sColor, sizeof(sColor)); - GetClientCookie(client, sri_cookie_mode, sMode, sizeof(sMode)); - g_aClientCookies[client][bEnabled] = StringToInt(sEnabled); - g_aClientCookies[client][iColor] = StringToInt(sColor); - g_aClientCookies[client][iMode] = StringToInt(sMode); -} - -public OnClientDisconnect(client) -{ - CleanUp(client); -} - -/** - Commands - */ - -public Action:Command_Immunity(client, args) -{ - if (g_aPlayers[client][IsImmune]) - { - DisableImmunity(client); - } - else - { - EnableImmunity(client); - } - return Plugin_Handled; -} - -/** - Event hooks - */ - -public Action:Hacks_TakeDamageHook(client, attacker, inflictor, Float:damage, &Float:multiplier, damagetype) -{ - if (attacker == 0 || attacker >= MaxClients) - { - return Plugin_Continue; - } - if (g_aPlayers[client][IsImmune]) - { - new TFClassType:PlayerClass = TF2_GetPlayerClass(attacker); - if (PlayerClass == TFClass_Spy) - { - multiplier *= 0.0; - return Plugin_Changed; - } - } - return Plugin_Continue; -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - g_bRoundEnd = false; - if (g_bIsEnabled) - { - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][IsImmune]) - { - DisableImmunity(i); - } - } - } -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - g_bRoundEnd = true; - if (g_bIsEnabled) - { - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][bIsAdmin]) - { - EnableImmunity(i); - } - } - } -} - -public HookPlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) -{ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - if (g_bIsEnabled && g_aPlayers[iClient][bIsAdmin] && g_bRoundEnd) - { - EnableImmunity(iClient); - } -} - -public Action:HookPlayerHurt(Handle:event, const String:name[], bool:dontBroadcast) -{ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - if (g_aPlayers[iClient][IsImmune]) - { - SetEntityHealth(iClient, 2000); - return Plugin_Continue; - } - return Plugin_Continue; -} - -/** - Cookie menus - */ - -public CookieMenu_TopMenu(client, CookieMenuAction:action, any:info, String:buffer[], maxlen) -{ - if (action == CookieMenuAction_DisplayOption) - { - //don't think we need to do anything - } - else - { - new Handle:hMenu = CreateMenu(Menu_CookieSettings); - SetMenuTitle(hMenu, "Options (Current Setting)"); - if (g_aClientCookies[client][bEnabled]) - { - AddMenuItem(hMenu, "enable", "Enabled/Disable (Enabled)"); - } - else - { - AddMenuItem(hMenu, "enable", "Enabled/Disable (Disabled)"); - } - if (g_aClientCookies[client][iMode]) - { - AddMenuItem(hMenu, "mode", "Immunity Mode Setting (God Mode)"); - } - else - { - AddMenuItem(hMenu, "mode", "Immunity Mode Setting (Health)"); - } - switch (g_aClientCookies[client][iColor]) - { - case COLOR_GREEN: - { - AddMenuItem(hMenu, "color", "Color (Green)"); - } - case COLOR_BLACK: - { - AddMenuItem(hMenu, "color", "Color (Black)"); - } - case COLOR_RED: - { - AddMenuItem(hMenu, "color", "Color (Red)"); - } - case COLOR_BLUE: - { - AddMenuItem(hMenu, "color", "Color (Blue)"); - } - case COLOR_TEAM: - { - AddMenuItem(hMenu, "color", "Color (Team)"); - } - case COLOR_RAINBOW: - { - AddMenuItem(hMenu, "color", "Color (Rainbow)"); - } - case COLOR_NONE: - { - AddMenuItem(hMenu, "color", "Color (None)"); - } - } - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, client, MENU_TIME_FOREVER); - } -} - -public Menu_CookieSettings(Handle:menu, MenuAction:action, param1, param2) -{ - new client = param1; - if (action == MenuAction_Select) - { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "enable", false)) - { - new Handle:hMenu = CreateMenu(Menu_CookieSettingsEnable); - SetMenuTitle(hMenu, "Enable/Disable Round End Immunity"); - - if (g_aClientCookies[client][bEnabled]) - { - AddMenuItem(hMenu, "enable", "Enable (Set)"); - AddMenuItem(hMenu, "disable", "Disable"); - } - else - { - AddMenuItem(hMenu, "enable", "Enabled"); - AddMenuItem(hMenu, "disable", "Disable (Set)"); - } - - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, client, MENU_TIME_FOREVER); - } - else if (StrEqual(sSelection, "mode", false)) - { - new Handle:hMenu = CreateMenu(Menu_CookieSettingsMode); - SetMenuTitle(hMenu, "Set Immunity Mode"); - - if (g_aClientCookies[client][iMode]) - { - AddMenuItem(hMenu, "god", "God Mode (Set)"); - AddMenuItem(hMenu, "health", "Health"); - } - else - { - AddMenuItem(hMenu, "god", "God Mode"); - AddMenuItem(hMenu, "health", "Health (Set)"); - } - - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, client, MENU_TIME_FOREVER); - } - else - { - new Handle:hMenu = CreateMenu(Menu_CookieSettingsColors); - SetMenuTitle(hMenu, "Select Immunity Color"); - switch (g_aClientCookies[client][iColor]) - { - case COLOR_GREEN: - { - AddMenuItem(hMenu, "Green", "Green (Set)"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_BLACK: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black (Set)"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_RED: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red (Set)"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_BLUE: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue (Set)"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_TEAM: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color (Set)"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_RAINBOW: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow (Set)"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_NONE: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None (Set)"); - } - } - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, client, MENU_TIME_FOREVER); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - ShowCookieMenu(client); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -public Menu_CookieSettingsEnable(Handle:menu, MenuAction:action, param1, param2) -{ - new client = param1; - if (action == MenuAction_Select) - { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "enable", false)) - { - SetClientCookie(client, sri_cookie_enabled, "1"); - g_aClientCookies[client][bEnabled] = 1; - PrintToChat(client, "[SM] Bonus Round Immunity is ENABLED"); - } - else - { - SetClientCookie(client, sri_cookie_enabled, "0"); - g_aClientCookies[client][bEnabled] = 0; - PrintToChat(client, "[SM] Bonus Round Immunity is DISABLED"); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - ShowCookieMenu(client); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -public Menu_CookieSettingsColors(Handle:menu, MenuAction:action, param1, param2) -{ - new client = param1; - if (action == MenuAction_Select) - { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "Green", false)) - { - SetClientCookie(client, sri_cookie_color, "0"); - g_aClientCookies[client][iColor] = COLOR_GREEN; - PrintToChat(client, "[SM] Bonus Round Immunity color set to GREEN"); - } - else if (StrEqual(sSelection, "Black", false)) - { - SetClientCookie(client, sri_cookie_color, "1"); - g_aClientCookies[client][iColor] = COLOR_BLACK; - PrintToChat(client, "[SM] Bonus Round Immunity color set to BLACK"); - } - else if (StrEqual(sSelection, "Red", false)) - { - SetClientCookie(client, sri_cookie_color, "2"); - g_aClientCookies[client][iColor] = COLOR_RED; - PrintToChat(client, "[SM] Bonus Round Immunity color set to RED"); - } - else if (StrEqual(sSelection, "Blue", false)) - { - SetClientCookie(client, sri_cookie_color, "3"); - g_aClientCookies[client][iColor] = COLOR_BLUE; - PrintToChat(client, "[SM] Bonus Round Immunity color set to BLUE"); - } - else if (StrEqual(sSelection, "Team", false)) - { - SetClientCookie(client, sri_cookie_color, "4"); - g_aClientCookies[client][iColor] = COLOR_TEAM; - PrintToChat(client, "[SM] Bonus Round Immunity color set to TEAM COLOR"); - } - else if (StrEqual(sSelection, "Rain", false)) - { - SetClientCookie(client, sri_cookie_color, "5"); - g_aClientCookies[client][iColor] = COLOR_RAINBOW; - PrintToChat(client, "[SM] Bonus Round Immunity color set to RAINBOW"); - } - else if (StrEqual(sSelection, "None", false)) - { - SetClientCookie(client, sri_cookie_color, "6"); - g_aClientCookies[client][iColor] = COLOR_NONE; - PrintToChat(client, "[SM] Bonus Round Immunity color set to NONE"); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - ShowCookieMenu(client); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -public Menu_CookieSettingsMode(Handle:menu, MenuAction:action, param1, param2) -{ - new client = param1; - if (action == MenuAction_Select) - { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "god", false)) - { - SetClientCookie(client, sri_cookie_mode, "1"); - g_aClientCookies[client][iMode] = 1; - PrintToChat(client, "[SM] Bonus Round Immunity set to GOD MODE"); - } - else - { - SetClientCookie(client, sri_cookie_mode, "0"); - g_aClientCookies[client][iMode] = 0; - PrintToChat(client, "[SM] Bonus Round Immunity set to HEALTH BONUS"); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - ShowCookieMenu(client); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -/** -Timer functions - */ - -public Action:Timer_ChangeColor(Handle:timer, any:client) -{ - if (g_aPlayers[client][CycleColor]++ == 3) - { - g_aPlayers[client][CycleColor] = 0; - } - SetEntityRenderMode(client, RENDER_TRANSCOLOR); - SetEntityRenderColor(client, g_iColors[g_aPlayers[client][CycleColor]][iRed], g_iColors[g_aPlayers[client][CycleColor]][iGreen], g_iColors[g_aPlayers[client][CycleColor]][iBlue], 255); - return Plugin_Continue; -} - -public Action:Timer_UndoGodMode(Handle:timer, any:client) -{ - if (IsClientInGame(client)) - { - SetEntProp(client, Prop_Data, "m_takedamage", 2, 1); - } - g_aPlayers[iClient][hGodModeTimer] = INVALID_HANDLE; - return Plugin_Handled; -} - -/** -Stock functions . - */ - -stock CleanUp(iClient) -{ - g_aPlayers[iClient][bIsAdmin] = false; - DisableImmunity(iClient); -} - -stock EnableImmunity(iClient) -{ - SetEntityRenderMode(iClient, RENDER_TRANSCOLOR); - switch (g_aClientCookies[iClient][iColor]) - { - case COLOR_TEAM: - { - new iTeam = GetClientTeam(iClient); - SetEntityRenderColor(iClient, g_iColors[e_ColorNames:iTeam][iRed], g_iColors[e_ColorNames:iTeam][iGreen], g_iColors[e_ColorNames:iTeam][iBlue], 255); - } - case COLOR_RAINBOW: - { - if (g_aPlayers[iClient][hColorTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hColorTimer]); - g_aPlayers[iClient][hColorTimer] = INVALID_HANDLE; - } - g_aPlayers[iClient][hColorTimer] = CreateTimer(0.2, Timer_ChangeColor, iClient, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); - } - case COLOR_NONE: - { - //We dont have to set a color - } - default: - { - SetEntityRenderColor(iClient, g_iColors[e_ColorNames:g_aClientCookies[iClient][iColor]][iRed], g_iColors[e_ColorNames:g_aClientCookies[iClient][iColor]][iGreen], g_iColors[e_ColorNames:g_aClientCookies[iClient][iColor]][iBlue], 255); - } - } - SetEntityHealth(iClient, 2000); - SetEntProp(iClient, Prop_Data, "m_takedamage", 0, 1); - g_aPlayers[iClient][hGodModeTimer] = CreateTimer(2.0, Timer_UndoGodMode, iClient); - g_aPlayers[iClient][IsImmune] = true; -} - -stock DisableImmunity(iClient) -{ - if (g_aPlayers[iClient][hGodModeTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hGodModeTimer]); - g_aPlayers[iClient][hGodModeTimer] = INVALID_HANDLE; - } - if (g_aPlayers[iClient][hColorTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hColorTimer]); - g_aPlayers[iClient][hColorTimer] = INVALID_HANDLE; - } - if (IsClientInGame(iClient)) - { - SetEntityRenderMode(iClient, RENDER_TRANSCOLOR); - SetEntityRenderColor(iClient, 255, 255, 255, 255); - new TFClassType:PlayerClass = TF2_GetPlayerClass(iClient); - new iMaxHealth = g_iClassMaxHealth[PlayerClass]; - SetEntityHealth(iClient, iMaxHealth); - } - g_aPlayers[iClient][CycleColor] = 0; - g_aPlayers[iClient][IsImmune] = false; -} - -stock LoadColors() -{ - g_iColors[Green][iRed] = 0; - g_iColors[Green][iGreen] = 255; - g_iColors[Green][iBlue] = 0; - - g_iColors[Black][iRed] = 10; - g_iColors[Black][iGreen] = 10; - g_iColors[Black][iBlue] = 0; - - g_iColors[Red][iRed] = 255; - g_iColors[Red][iGreen] = 0; - g_iColors[Red][iBlue] = 0; - - g_iColors[Blue][iRed] = 0; - g_iColors[Blue][iGreen] = 0; - g_iColors[Blue][iBlue] = 255; -} - -stock TF2_AddCond(client, cond) -{ - new Handle:cvar = FindConVar("sv_cheats"), bool:enabled = GetConVarBool(cvar), flags = GetConVarFlags(cvar); - if(!enabled) - { - SetConVarFlags(cvar, flags^FCVAR_NOTIFY); - SetConVarBool(cvar, true); - } - FakeClientCommand(client, "addcond %i", cond); - if(!enabled) - { - SetConVarBool(cvar, false); - SetConVarFlags(cvar, flags); - } -} - -stock TF2_RemoveCond(client, cond) -{ - new Handle:cvar = FindConVar("sv_cheats"), bool:enabled = GetConVarBool(cvar), flags = GetConVarFlags(cvar); - if(!enabled) - { - SetConVarFlags(cvar, flags^FCVAR_NOTIFY); - SetConVarBool(cvar, true); - } - FakeClientCommand(client, "removecond %i", cond); - if(!enabled) - { - SetConVarBool(cvar, false); - SetConVarFlags(cvar, flags); - } -} - -/** -Enabled hook - */ - -public EnabledChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (StringToInt(newValue) == 0) - { - UnhookEvent("player_spawn", HookPlayerSpawn, EventHookMode_Post); - UnhookEvent("teamplay_round_start", HookRoundStart, EventHookMode_Post); - UnhookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][bIsAdmin] && g_aPlayers[i][IsImmune]) - { - DisableImmunity(i); - } - } - g_bIsEnabled = false; - } - else - { - HookEvent("player_spawn", HookPlayerSpawn, EventHookMode_Post); - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_Post); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - g_bIsEnabled = true; - } -} diff --git a/Simple Team Manager/addons/sourcemod/scripting/simple-spectate.sp b/Simple Team Manager/addons/sourcemod/scripting/simple-spectate.sp deleted file mode 100644 index 4108f8f..0000000 --- a/Simple Team Manager/addons/sourcemod/scripting/simple-spectate.sp +++ /dev/null @@ -1,2022 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Spectate -Description: - Spectate a player and follow them through death. -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include -#undef REQUIRE_EXTENSIONS -#undef AUTOLOAD_EXTENSIONS -#tryinclude -#define AUTOLOAD_EXTENSIONS -#define REQUIRE_EXTENSIONS - -#define PLUGIN_VERSION "1.2.1.$Rev$" - -#define SPECMODE_NONE 0 -#define SPECMODE_FIRSTPERSON 4 -#define SPECMODE_3RDPERSON 5 -#define SPECMODE_FREELOOK 6 -#define SPECMODE_CSS_FIRSTPERSON 3 -#define SPECMODE_CSS_3RDPERSON 4 -#define SPECMODE_CSS_FREELOOK 5 - -enum e_CvarHandles -{ - Handle:hHudMode, - Handle:hMenuType, - Handle:hRestrictHud, - Handle:hBan, - Handle:hBanPerm, - Handle:hBeacon, - Handle:hBlind, - Handle:hCheater, - Handle:hDrug, - Handle:hFreeze, - Handle:hFreezeBomb, - Handle:hKick, - Handle:hSlap, - Handle:hSlay, - Handle:hTimeBomb -}; - -enum e_CvarSettings -{ - bool:bHudMode, - bool:bMenuType, - bool:bRestrictHud, - bool:bBan, - bool:bBanPerm, - bool:bBeacon, - bool:bBlind, - bool:bCheater, - bool:bDrug, - bool:bFreeze, - bool:bFreezebomb, - bool:bKick, - bool:bSlap, - bool:bSlay, - bool:bTimeBomb -}; - -enum e_PluginSettings -{ - bool:bUseSteamBans, - bool:bUseSourceBans, - bool:bUseMySQLBans, - bool:bCanHUD, - bool:bUseDukehacks -}; - -enum e_Menus -{ - Handle:hSelectPlayer, - Handle:hBanTime, - Handle:hReason -}; - -enum e_Punishments -{ - Punish_None, - Punish_Ban, - Punish_Beacon, - Punish_Blind, - Punish_Cheater, - Punish_Drug, - Punish_Freeze, - Punish_FreezeBomb, - Punish_Kick, - Punish_Slap, - Punish_Slay, - Punish_TimeBomb -}; - -enum e_PlayerData -{ - bool:bIsDisplayingHud, - bool:bIsFlaggedCheater, - Handle:hHudTimer, - Handle:hTargetTimer, - iTargetIndex, - e_Punishments:TargetPunishment, - iBanTime -}; - -new Handle:sm_spectate_adminflag = INVALID_HANDLE; -new Handle:g_hAdminMenu = INVALID_HANDLE; -new Handle:g_hHud = INVALID_HANDLE; -new Handle:g_aPluginCvar[e_CvarHandles]; -new g_aPluginCvarSettings[e_CvarSettings]; -new g_aPluginSettings[e_PluginSettings]; -new g_aMenus[e_Menus]; -new g_aPlayers[MAXPLAYERS + 1][e_PlayerData]; -new String:g_sAdminFlags[16]; -new String:g_sPunishments[e_Punishments][15] = { "None", "Ban", "Beacon", "Blind", "Cheater", "Drug", "Freeze", "FreezeBomb", "Kick", "Slap", "Slay", "TimeBomb" }; - -public Plugin:myinfo = -{ - name = "Simple Spectate", - author = "Simple Plugins", - description = "Spectate a player and follow them through death.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -/** -Sourcemod callbacks -*/ -public OnPluginStart() -{ - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[SSPEC] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Pre); - - /** - Need to create all of our console variables. - */ - CreateConVar("sm_spectate_version", PLUGIN_VERSION, "Sourcemod Spectate", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - g_aPluginCvar[hHudMode] = CreateConVar("sm_spectate_hudmode", "1", "Hud Mode: 0 = Hud Text | 1 = Panel/Menu (NOTE: The panel/menu will override other menus until canceled)"); - g_aPluginCvar[hMenuType] = CreateConVar("sm_spectate_menutype", "0", "Menu Mode: 0 = Panel | 1 = Menu"); - g_aPluginCvar[hRestrictHud] = CreateConVar("sm_spectate_restricthud", "0", "Restrict the hud to the admin flag provided"); - g_aPluginCvar[hBan] = CreateConVar("sm_spectate_ban", "1", "Enable/Disable ban option"); - g_aPluginCvar[hBanPerm] = CreateConVar("sm_spectate_banperm", "1", "Enable/Disable permanent ban option"); - g_aPluginCvar[hBeacon] = CreateConVar("sm_spectate_beacon", "1", "Enable/Disable beacon option"); - g_aPluginCvar[hBlind] = CreateConVar("sm_spectate_blind", "1", "Enable/Disable blind option"); - g_aPluginCvar[hCheater] = CreateConVar("sm_spectate_cheater", "1", "Enable/Disable cheater option"); - g_aPluginCvar[hDrug] = CreateConVar("sm_spectate_drug", "1", "Enable/Disable drug option"); - g_aPluginCvar[hFreeze] = CreateConVar("sm_spectate_freeze", "1", "Enable/Disable freeze option"); - g_aPluginCvar[hFreezeBomb] = CreateConVar("sm_spectate_freezebomb", "1", "Enable/Disable freezebomb option"); - g_aPluginCvar[hKick] = CreateConVar("sm_spectate_kick", "1", "Enable/Disable kick option"); - g_aPluginCvar[hSlap] = CreateConVar("sm_spectate_slap", "1", "Enable/Disable slap option"); - g_aPluginCvar[hSlay] = CreateConVar("sm_spectate_slay", "1", "Enable/Disable slay option"); - g_aPluginCvar[hTimeBomb] = CreateConVar("sm_spectate_timebomb", "1", "Enable/Disable timebomb option"); - - sm_spectate_adminflag = CreateConVar("sm_spectate_adminflag", "d", "Admin Flag to use for admin hud"); - - /** - Hook console variables - */ - new e_CvarHandles:iCvar; - for ( ; _:iCvar < sizeof(g_aPluginCvar); iCvar++) - { - HookConVarChange(g_aPluginCvar[iCvar], ConVarSettingsChanged); - } - - /** - Need to register the commands we are going to create and use. - */ - RegConsoleCmd("sm_spectate", Command_Spectate, "Spectate a player"); - RegConsoleCmd("sm_spec", Command_Spectate, "Spectate a player"); - RegConsoleCmd("sm_observe", Command_Spectate, "Spectate a player"); - RegConsoleCmd("sm_stopspec", Command_StopSpectate, "Stop Spectating a player"); - RegConsoleCmd("sm_endobserve", Command_StopSpectate, "Stop Spectating a player"); - RegConsoleCmd("sm_specinfo", Command_ToggleHud, "Toggles the hud display if in spectator"); - - /** - Now we have to deal with the admin menu. If the admin library is loaded call the function to add our items. - */ - new Handle:gTopMenu; - if (LibraryExists("adminmenu") && ((gTopMenu = GetAdminTopMenu()) != INVALID_HANDLE)) - { - OnAdminMenuReady(gTopMenu); - } - - /** - Deal with the hud - Thanks to Spray Trace plugin (http://forums.alliedmods.net/showthread.php?p=665448) - */ - new String:sHudGames[32]; - GetGameFolderName(sHudGames, sizeof(sHudGames)); - g_aPluginSettings[bCanHUD] = StrEqual(sHudGames,"tf",false) - || StrEqual(sHudGames,"hl2mp",false) - || StrEqual(sHudGames,"sourceforts",false) - || StrEqual(sHudGames,"obsidian",false) - || StrEqual(sHudGames,"left4dead",false) - || StrEqual(sHudGames,"l4d",false); - - if (g_aPluginSettings[bCanHUD]) - { - g_hHud = CreateHudSynchronizer(); - } - - /** - Load translations - */ - LoadTranslations ("common.phrases"); - LoadTranslations ("simplespectate.phrases"); - - /** - Create the config file - */ - AutoExecConfig(true); -} - -public OnConfigsExecuted() -{ - new e_CvarHandles:iCvar; - for ( ; _:iCvar < sizeof(g_aPluginCvarSettings); iCvar++) - { - g_aPluginCvarSettings[iCvar] = GetConVarBool(g_aPluginCvar[iCvar]); - } - - /* - Build the global menus - */ - g_aMenus[hSelectPlayer] = BuildSelectPlayerMenu(); - g_aMenus[hBanTime] = BuildBanTimeMenu(); - g_aMenus[hReason] = BuildReasonMenu(); - - GetConVarString(sm_spectate_adminflag, g_sAdminFlags, sizeof(g_sAdminFlags)); -} - -public OnAllPluginsLoaded() -{ - - /* - Check for steambans - */ - if (FindConVar("sbsrc_version") != INVALID_HANDLE) - { - g_aPluginSettings[bUseSteamBans] = true; - } - else - { - g_aPluginSettings[bUseSteamBans] = false; - } - - /* - Check for sourcebans - */ - if (FindConVar("sb_version") != INVALID_HANDLE) - { - g_aPluginSettings[bUseSourceBans] = true; - } - else - { - g_aPluginSettings[bUseSourceBans] = false; - } - - /* - Check for mysql bans - */ - if (FindConVar("mysql_bans_version") != INVALID_HANDLE) - { - g_aPluginSettings[bUseMySQLBans] = true; - } - else - { - g_aPluginSettings[bUseMySQLBans] = false; - } - - /* - Check for dukehacks - */ - new String:sExtError[256]; - new iExtStatus = GetExtensionFileStatus("dukehacks.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SSPEC] Dukehacks extension was not found."); - LogAction(0, -1, "[SSPEC] Plugin continued to load, but that feature will not be used."); - g_aPluginSettings[bUseDukehacks] = false; - } - else if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SSPEC] Dukehacks extension is loaded with errors."); - LogAction(0, -1, "[SSPEC] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SSPEC] Plugin continued to load, but that feature will not be used."); - g_aPluginSettings[bUseDukehacks] = false; - } - else if (iExtStatus == 1) - { - LogAction(0, -1, "[SSPEC] Dukehacks extension is loaded and will be used."); - g_aPluginSettings[bUseDukehacks] = true; - dhAddClientHook(CHK_TakeDamage, Hacks_TakeDamageHook); - } - - /* - Deal with some known plugin conflicts - */ - new Handle:hObserveClient = FindConVar("observe_version"); - if (hObserveClient != INVALID_HANDLE) - { - new String:sNewFile[PLATFORM_MAX_PATH + 1], String:sOldFile[PLATFORM_MAX_PATH + 1]; - BuildPath(Path_SM, sNewFile, sizeof(sNewFile), "plugins/disabled/observe.smx"); - BuildPath(Path_SM, sOldFile, sizeof(sOldFile), "plugins/observe.smx"); - - /** - Check if plugins/observe.smx exists, and if not, ignore - */ - if(!FileExists(sOldFile)) - { - return; - } - - /** - Check if plugins/disabled/observe.smx already exists, and if so, delete it - */ - if(FileExists(sNewFile)) - { - DeleteFile(sNewFile); - } - - /** - Unload plugins/observe.smx and move it to plugins/disabled/observe.smx - */ - LogAction(0, -1, "Detected the plugin ObserveClient"); - LogAction(0, -1, "ObserveClient plugin conflicts with Simple Spectate"); - LogAction(0, -1, "Unloading plugin and disabling ObserveClient plugin"); - ServerCommand("sm plugins unload observe"); - RenameFile(sNewFile, sOldFile); - } -} - -public OnLibraryRemoved(const String:name[]) -{ - if (StrEqual(name, "adminmenu")) - { - - /** - Looks like the admin menu was removed. Set the global. - */ - g_hAdminMenu = INVALID_HANDLE; - } - else if (StrEqual(name, "simpleplugins")) - { - //something - } -} - -public OnClientDisconnect(client) -{ - - /** - Cleanup the clients variables. - */ - ResetClient(client); - - /** - Run a loop and see if we are supposed to spectate this person (is a target) - */ - for(new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][iTargetIndex] == client) - { - - /** - Cleanup the clients variables. - */ - StopFollowingPlayer(i); - g_aPlayers[i][TargetPunishment] = Punish_None; - g_aPlayers[i][iBanTime] = 0; - } - } -} - -/** -Thirdparty callbacks -*/ -public SM_OnPlayerMoved(Handle:plugin, client, team) -{ - - /** - Make sure we called the move function - */ - if (plugin != GetMyHandle()) - { - return; - } - - //Nothing -} - -public Action:Hacks_TakeDamageHook(client, attacker, inflictor, Float:damage, &Float:multiplier, damagetype) -{ - - /** - Check for a valid client - */ - if (client > 0 && client <= MaxClients) - { - - /** - Check if the client taking damage is flagged as a cheater - */ - if (g_aPlayers[client][bIsFlaggedCheater]) - { - - /** - Check for fall damage and increase it - */ - if (damagetype & DMG_FALL) - { - multiplier *= 1000.0; - return Plugin_Changed; - } - } - } - - /** - Check for a valid attacker - */ - if (attacker > 0 && attacker <= MaxClients) - { - - /** - Check if the attacker causing the damage is flagged as a cheater - */ - if (g_aPlayers[attacker][bIsFlaggedCheater]) - { - - /** - Make sure they are not hurting themselves - */ - if (client != attacker) - { - - /** - Stop the damage - */ - multiplier *= 0.0; - return Plugin_Changed; - } - } - } - return Plugin_Continue; -} - -/** -Events -*/ -public Action:HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get the client and team - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - new iTeam = GetEventInt(event, "team"); - - /** - Make sure it's a valid client - */ - if (iClient == 0) - { - return Plugin_Continue; - } - - /** - If it's a move to spectator start displaying the hud - */ - else if ((iTeam == g_aCurrentTeams[Spectator]) && (GetUserFlagBits(iClient) & ADMFLAG_GENERIC)) - { - StartDisplayingHud(iClient); - - /** - If the event was going to be broadcasted, we refire it so it is not broadcasted and stop this one - */ - if (!dontBroadcast) - { - new Handle:hEvent = CreateEvent("player_team"); - SetEventInt(hEvent, "userid", GetEventInt(event, "userid")); - SetEventInt(hEvent, "team", GetEventInt(event, "team")); - SetEventInt(hEvent, "oldteam", GetEventInt(event, "oldteam")); - SetEventBool(hEvent, "disconnect", GetEventBool(event, "disconnect")); - - if (g_CurrentMod == GameType_DOD || g_CurrentMod == GameType_L4D || g_CurrentMod == GameType_TF) - { - new String:sClientName[MAX_NAME_LENGTH + 1]; - GetClientName(client, sClientName, sizeof(sClientName)); - SetEventBool(hEvent, "autoteam", GetEventBool(event, "autoteam")); - SetEventBool(hEvent, "silent", true); - SetEventString(hEvent, "name", sClientName); - FireEvent(hEvent, true); - } - else - { - FireEvent(hEvent, true); - } - return Plugin_Handled; - } - } - - /** - Otherwise cleanup the client - */ - else - { - StopDisplayingHud(iClient); - StopFollowingPlayer(iClient); - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -/** -Commands -*/ -public Action:Command_Spectate(client, args) -{ - - /** - See if we already have a target (for toggling of command) - */ - if (g_aPlayers[client][iTargetIndex]) - { - - /** - We do, toggle it off - */ - StopFollowingPlayer(client); - - /** - We are done, bug out. - */ - return Plugin_Handled; - } - - /** - We don't... must want to enable it - See if we have some command arguments. - */ - new iCmdArgs = GetCmdArgs(); - if (iCmdArgs == 0) - { - - /** - We don't have any. Display the player menu. - */ - if (g_aPlayers[client][bIsDisplayingHud]) - { - StopDisplayingHud(client); - } - - DisplayMenu(BuildPlayerListMenu(), client, MENU_TIME_FOREVER); - return Plugin_Handled; - } - - /** - We have an argument. - Try to find the target. - */ - new String:sPlayer[128]; - GetCmdArg(1, sPlayer, sizeof(sPlayer)); - new iTarget = FindTarget(client, sPlayer, true, true); - if (iTarget == -1 || !IsClientInGame(iTarget)) - { - - /** - We couldn't find the target. Display the player menu. - */ - if (g_aPlayers[client][bIsDisplayingHud]) - { - StopDisplayingHud(client); - } - - DisplayMenu(BuildPlayerListMenu(), client, MENU_TIME_FOREVER); - return Plugin_Handled; - } - - /** - We found the target. - Call the stock function to spectate the target. - */ - StartFollowingPlayer(client, iTarget); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_StopSpectate(client, args) -{ - - /** - Cleanup the clients variables. - */ - StopFollowingPlayer(client); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_ToggleHud(client, args) -{ - - /** - Toggle the hud - */ - if (g_aPlayers[client][bIsDisplayingHud]) - { - StopDisplayingHud(client); - } - else - { - StartDisplayingHud(client); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -/** -Timers -*/ -public Action:Timer_ResetTarget(Handle:timer, any:client) -{ - - new iTargetID = GetEntPropEnt(client, Prop_Send, "m_hObserverTarget"); - - if (iTargetID != g_aPlayers[client][iTargetIndex] && IsPlayerAlive(g_aPlayers[client][iTargetIndex])) - { - - /** - Run the command to spectate the target from the clients prospectative. - */ - FakeClientCommandEx(client, "spec_player \"%N\"", g_aPlayers[client][iTargetIndex]); - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Timer_UpdateHud(Handle:timer, any:client) -{ - - /** - Make sure the client is still in game and a spectator - */ - if (!IsClientConnected(client) || !IsClientInGame(client) || GetClientTeam(client) != g_aCurrentTeams[Spectator] || !g_aPlayers[client][bIsDisplayingHud]) - { - - /** - We are done, bug out - */ - g_aPlayers[client][hHudTimer] = INVALID_HANDLE; - g_aPlayers[client][bIsDisplayingHud] = false; - return Plugin_Stop; - } - /** - Get the target - */ - new iTarget = GetEntPropEnt(client, Prop_Send, "m_hObserverTarget"); - - /** - Check to make sure the target is valid - */ - if (iTarget <= 0 || iTarget > MaxClients) - { - return Plugin_Continue; - } - - /** - Get the spectator mode - */ - new iSpecMode = GetEntProp(client, Prop_Send, "m_iObserverMode"); - - /** - This is a double check to make sure we are in spec - If we are on a regular team, specmod would = none or zero - */ - if (iSpecMode == SPECMODE_NONE) - { - - /** - We are done, bug out - */ - g_aPlayers[client][hHudTimer] = INVALID_HANDLE; - g_aPlayers[client][bIsDisplayingHud] = false; - return Plugin_Stop; - } - - /** - Check the spectator mode - CSS has different index's so we have to check game type first - */ - if (g_CurrentMod == GameType_CSS) - { - switch (iSpecMode) - { - case SPECMODE_CSS_FIRSTPERSON: - { - //Do Nothing - } - case SPECMODE_CSS_3RDPERSON: - { - //Do Nothing - } - case SPECMODE_CSS_FREELOOK: - { - return Plugin_Continue; - } - } - } - else - { - switch (iSpecMode) - { - case SPECMODE_FIRSTPERSON: - { - //Do Nothing - } - case SPECMODE_3RDPERSON: - { - //Do Nothing - } - case SPECMODE_FREELOOK: - { - return Plugin_Continue; - } - } - } - - - /** - Display with the hud - */ - if (g_aPluginSettings[bCanHUD] && !g_aPluginCvarSettings[bHudMode]) - { - new String:sSteamID[64]; - GetClientAuthString(iTarget, sSteamID, sizeof(sSteamID)); - SetHudTextParams(0.04, 0.6, 0.5, 255, 50, 50, 255); - ShowSyncHudText(client, g_hHud, "%N [%s]", iTarget, sSteamID); - } - else if (g_aPluginCvarSettings[bHudMode]) - { - if (g_aPluginCvarSettings[bMenuType]) - { - DisplayMenu(BuildPlayerHudMenu(client, iTarget), client, 1); - } - else - { - new Handle:hPanel = BuildPlayerHudPanel(client, iTarget); - SendPanelToClient(hPanel, client, Panel_PlayerHud, 1); - CloseHandle(hPanel); - } - } - - /** - We are done, keep going! - */ - return Plugin_Continue; -} - -/** -Admin Menu Callbacks -*/ -public OnAdminMenuReady(Handle:topmenu) -{ - if (topmenu == g_hAdminMenu) - { - return; - } - g_hAdminMenu = topmenu; - new TopMenuObject:player_commands = FindTopMenuCategory(g_hAdminMenu, ADMINMENU_PLAYERCOMMANDS); - if (player_commands == INVALID_TOPMENUOBJECT) - { - return; - } - AddToTopMenu(g_hAdminMenu, - "sm_spectate", - TopMenuObject_Item, - AdminMenu_SpecPlayer, - player_commands, - "sm_spectate", - ADMFLAG_GENERIC); -} - -public AdminMenu_SpecPlayer(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) -{ - if (action == TopMenuAction_DisplayOption) - { - - if (g_aPlayers[param][bIsDisplayingHud]) - { - StopDisplayingHud(param); - } - /** - See if we already have a target - */ - if (g_aPlayers[param][iTargetIndex]) - { - Format(buffer, maxlength, "Spectate(Disable)"); - } - else - { - Format(buffer, maxlength, "Spectate(Select Player)"); - } - } - else if (action == TopMenuAction_SelectOption) - { - - /** - See if we already have a target - */ - if (g_aPlayers[param][iTargetIndex]) - { - - /** - We do, toggle it off - */ - StopFollowingPlayer(param); - - /** - We are done, bug out. - */ - return; - } - else - { - DisplayMenu(BuildPlayerListMenu(), param, MENU_TIME_FOREVER); - } - } -} - -/** -Select Player Menu Callbacks -*/ -public Menu_PlayerList(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - /** - Get the selected player - */ - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - new iTarget = GetClientOfUserId(StringToInt(sSelection)); - - /** - Start following the player - */ - StartFollowingPlayer(param1, iTarget); - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_GENERIC) - { - - /** - Display the last admin menu - */ - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } - else if (param2 == MenuCancel_Exit && GetClientTeam(param1) == g_aCurrentTeams[Spectator]) - { - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_End) - { - - /** - Not a global menu, close it - */ - CloseHandle(menu); - } -} - -public Menu_SelectPlayer(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - - /** - Get the selected player - */ - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (strcmp(sSelection, "Current", false) == 0) - { - /** - Get the current target - */ - new iTarget = GetEntPropEnt(param1, Prop_Send, "m_hObserverTarget"); - - /** - Check to make sure the target is valid - */ - if (iTarget <= 0 || iTarget > MaxClients) - { - PrintToChat(param1, "\x03[SM-SPEC]\x01 %t", "Invalid Target"); - DisplayMenu(BuildPlayerListMenu(), param1, MENU_TIME_FOREVER); - } - - /** - Start following the player - */ - StartFollowingPlayer(param1, iTarget); - } - else - { - - /** - They want to select a player, show the player list - */ - DisplayMenu(BuildPlayerListMenu(), param1, MENU_TIME_FOREVER); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_End) - { - /** - Its a global menu, leave it alive - */ - } -} - -/** -Punishment Menu Callbacks -*/ -public Menu_Punishments(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - - /** - Get the menu selection - */ - new String:sSelection[15]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - - /** - Search for the correct index - */ - new e_Punishments:Index = Punish_None; - for ( ; _:Index <= sizeof(g_sPunishments); Index++) - { - if (StrEqual(sSelection, g_sPunishments[Index])) - { - break; - } - } - - /** - Display the next menu - */ - if (Index == Punish_Ban) - { - - /** - Set the punishment index and display ban time menu - */ - g_aPlayers[param1][TargetPunishment] = Index; - DisplayMenu(g_aMenus[hBanTime], param1, MENU_TIME_FOREVER); - } - else if (Index == Punish_Cheater) - { - - /** - Ask for confirmation before we set punishment index - */ - new Handle:hPanel = BuildAdminCheaterPanel(); - SendPanelToClient(hPanel, param1, Panel_AdminCheater, MENU_TIME_FOREVER); - CloseHandle(hPanel); - } - else - { - - /** - Set the punishment index and display reason menu - */ - g_aPlayers[param1][TargetPunishment] = Index; - DisplayMenu(g_aMenus[hReason], param1, MENU_TIME_FOREVER); - } - } - else if (action == MenuAction_Cancel) - { - - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - else if (action == MenuAction_End) - { - - /** - Not a global menu, close it - */ - CloseHandle(menu); - } -} - -public Menu_BanTime(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - - /** - Get the menu selection - */ - new String:sSelection[15]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - - /** - Set the ban time global - */ - g_aPlayers[param1][iBanTime] = StringToInt(sSelection); - - /** - Display the reason menu - */ - DisplayMenu(g_aMenus[hReason], param1, MENU_TIME_FOREVER); - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_End) - { - /** - Its a global menu, leave it alive - */ - } -} - -public Menu_Reason(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - - /** - Get the menu selection - */ - new String:sSelection[15]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - - /** - Perform the punishment - */ - PerformPunishment(param1, g_aPlayers[param1][iTargetIndex], g_aPlayers[param1][TargetPunishment], sSelection, g_aPlayers[param1][iBanTime]); - - /** - Reactivate the hud if still in spectator - */ - if (GetClientTeam(param1) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_End) - { - /** - Its a global menu, leave it alive - */ - } -} - -public Panel_AdminCheater(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - if (param2 == 1) - { - - /** - Set the punishment index and display reason menu - */ - g_aPlayers[param1][TargetPunishment] = Punish_Cheater; - DisplayMenu(g_aMenus[hReason], param1, MENU_TIME_FOREVER); - } - else - { - - /** - Reactivate the hud if still in spectator - */ - if (GetClientTeam(param1) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(param1); - } - } - } -} - -public Panel_PublicCheater(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - if (param2 == 1) - { - //Waiting for SB 2.0 and sb_submission to be published - } - else - { - - /** - Reactivate the hud if still in spectator - */ - if (GetClientTeam(param1) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(param1); - } - } - } -} - -/** -Hud Menu/Panel Callbacks -*/ -public Menu_PlayerHud(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "stop", false)) - { - StopFollowingPlayer(param1); - } - else if (StrEqual(sSelection, "start", false)) - { - StopDisplayingHud(param1); - DisplayMenu(g_aMenus[hSelectPlayer], param1, MENU_TIME_FOREVER); - } - else if (StrEqual(sSelection, "removecheater", false)) - { - g_aPlayers[g_aPlayers[param1][iTargetIndex]][bIsFlaggedCheater] = false; - } - else if (StrEqual(sSelection, "punish", false)) - { - if (g_aPlayers[param1][iTargetIndex]) - { - StopDisplayingHud(param1); - DisplayMenu(BuildPunishmentMenu(param1), param1, MENU_TIME_FOREVER); - } - else - { - StopDisplayingHud(param1); - PrintToChat(param1, "\x03[SM-SPEC]\x01 %t", "Must Have Target"); - DisplayMenu(g_aMenus[hSelectPlayer], param1, MENU_TIME_FOREVER); - } - } - else if (StrEqual(sSelection, "reportcheater", false)) - { - if (g_aPlayers[param1][iTargetIndex]) - { - StopDisplayingHud(param1); - new Handle:hPanel = BuildPublicCheaterPanel(); - SendPanelToClient(hPanel, param1, Panel_PublicCheater, MENU_TIME_FOREVER); - CloseHandle(hPanel); - } - else - { - StopDisplayingHud(param1); - PrintToChat(param1, "\x03[SM-SPEC]\x01 %t", "Must Have Target"); - DisplayMenu(g_aMenus[hSelectPlayer], param1, MENU_TIME_FOREVER); - } - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_Interrupted) - { - if (GetClientMenu(param1) == MenuSource_External) - { - StopDisplayingHud(param1); - } - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -public Panel_PlayerHud(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - switch (param2) - { - case 1: - { - if (g_aPlayers[param1][iTargetIndex]) - { - StopFollowingPlayer(param1); - } - else - { - StopDisplayingHud(param1); - DisplayMenu(BuildSelectPlayerMenu(), param1, MENU_TIME_FOREVER); - } - } - case 2: - { - if (!g_aPlayers[param1][iTargetIndex]) - { - StopDisplayingHud(param1); - PrintToChat(param1, "\x03[SM-SPEC]\x01 %t", "Must Have Target"); - DisplayMenu(g_aMenus[hSelectPlayer], param1, MENU_TIME_FOREVER); - return; - } - - if ((GetUserFlagBits(param1) & ADMFLAG_GENERIC) || (GetUserFlagBits(param1) & ADMFLAG_ROOT)) - { - if (g_aPlayers[g_aPlayers[param1][iTargetIndex]][bIsFlaggedCheater] && (GetUserFlagBits(param1) & ADMFLAG_ROOT)) - { - //Remove cheater flag - g_aPlayers[g_aPlayers[param1][iTargetIndex]][bIsFlaggedCheater] = false; - } - else - { - //Punish menu - StopDisplayingHud(param1); - DisplayMenu(BuildPunishmentMenu(param1), param1, MENU_TIME_FOREVER); - } - } - else - { - //Report Cheater - new Handle:hPanel = BuildPublicCheaterPanel(); - SendPanelToClient(hPanel, param1, Panel_PublicCheater, MENU_TIME_FOREVER); - CloseHandle(hPanel); - } - } - case 3: - { - StopDisplayingHud(param1); - } - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_Interrupted) - { - if (GetClientMenu(param1) == MenuSource_External) - { - StopDisplayingHud(param1); - } - } - } -} - - -/** -Stock functions -*/ -stock StartFollowingPlayer(client, target) -{ - - /** - If we have an open timer, close it. - */ - if (g_aPlayers[client][hTargetTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[client][hTargetTimer]); - g_aPlayers[client][hTargetTimer] = INVALID_HANDLE; - } - - /** - Make sure the target is on a non spectator team, and the client != target - */ - if (client == target) - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Yourself"); - return; - } - new iTargetTeam = GetClientTeam(target); - if (iTargetTeam == g_aCurrentTeams[Spectator] || iTargetTeam == g_aCurrentTeams[Unknown]) - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Spectator"); - return; - } - - /** - Check to see if client is already a spectator - */ - if (GetClientTeam(client) != g_aCurrentTeams[Spectator]) - { - - /** - Client is not a spectator, lets move them to spec. - */ - SM_MovePlayer(client, g_aCurrentTeams[Spectator]); - } - - /** - If we are using steambans call sb_status - */ - if (g_aPluginSettings[bUseSteamBans]) - { - FakeClientCommandEx(client, "sb_status"); - } - - - /** - Set the global and start to spectate the target. - Making sure it's long enough to deal with moving the client to spec if we had to. - */ - new String:sTargetName[MAX_NAME_LENGTH + 1]; - GetClientName(target, sTargetName, sizeof(sTargetName)); - g_aPlayers[client][iTargetIndex] = target; - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Spectating", sTargetName); - g_aPlayers[client][hTargetTimer] = CreateTimer(0.5, Timer_ResetTarget, client, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); - if (!g_aPlayers[client][bIsDisplayingHud] && GetClientTeam(client) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(client); - } -} - -stock StopFollowingPlayer(client) -{ - - /** - If we have an open timer, close it. - */ - if (g_aPlayers[client][hTargetTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[client][hTargetTimer]); - } - - /** - Tell the client we can't spec his target anymore... if they are in game. - */ - if (IsClientInGame(client) && g_aPlayers[client][iTargetIndex] != 0) - { - new String:sTargetName[MAX_NAME_LENGTH + 1]; - GetClientName(g_aPlayers[client][iTargetIndex], sTargetName, sizeof(sTargetName)); - if (!IsClientConnected(g_aPlayers[client][iTargetIndex]) || !IsClientInGame(g_aPlayers[client][iTargetIndex])) - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Target Left"); - } - else - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Stopped spectating", sTargetName); - } - } - - /** - Null the globals. - */ - g_aPlayers[client][iTargetIndex] = 0; - g_aPlayers[client][hTargetTimer] = INVALID_HANDLE; -} - -stock StartDisplayingHud(client) -{ - if (g_aPluginCvarSettings[bRestrictHud] && !SM_IsValidAdmin(client, g_sAdminFlags)) - { - return; - } - else - { - /** - Double check the hud timer - We should not have one, but if we do, lets cancel it for the current callback - */ - StopDisplayingHud(client); - - /** - Now we can safely display the hud and make sure the current stored handle is the current timer - */ - g_aPlayers[client][bIsDisplayingHud] = true; - g_aPlayers[client][hHudTimer] = CreateTimer(0.5, Timer_UpdateHud, client, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); - } -} - -stock StopDisplayingHud(client) -{ - if (g_aPlayers[client][hHudTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[client][hHudTimer]); - } - g_aPlayers[client][hHudTimer] = INVALID_HANDLE; - g_aPlayers[client][bIsDisplayingHud] = false; -} - -stock ResetClient(client) -{ - StopFollowingPlayer(client); - StopDisplayingHud(client); - - g_aPlayers[client][bIsFlaggedCheater] = false; - g_aPlayers[client][TargetPunishment] = Punish_None; - g_aPlayers[client][iBanTime] = -1; -} - -stock PerformPunishment(client, target, e_Punishments:punishment, const String:reason[], time = 300) -{ - new String:sTargetName[MAX_NAME_LENGTH + 1], - String:sTargetID[64]; - - /** - The target could have left the game by the time we get here - Check for a valid target - */ - if (!IsClientConnected(target) || !IsClientInGame(target)) - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Target Left"); - return; - } - - GetClientName(target, sTargetName, sizeof(sTargetName)); - GetClientAuthString(target, sTargetID, sizeof(sTargetID)); - - switch (punishment) - { - case Punish_Kick: - { - KickClient(g_aPlayers[client][iTargetIndex], "%s", reason); - } - case Punish_Ban: - { - if (g_aPluginSettings[bUseSourceBans]) - { - ClientCommand(client, "sm_ban #%d %d \"%s\"", GetClientUserId(target), time, reason); - } - else if (g_aPluginSettings[bUseMySQLBans]) - { - ClientCommand(client, "mysql_ban #%d %d \"%s\"", GetClientUserId(target), time, reason); - } - else - { - BanClient(target, time, BANFLAG_AUTHID, reason, reason); - } - } - case Punish_Cheater: - { - g_aPlayers[target][bIsFlaggedCheater] = true; - } - case Punish_Beacon: - { - ClientCommand(client, "sm_beacon \"%s\"", sTargetName); - } - case Punish_Blind: - { - ClientCommand(client, "sm_blind \"%s\"", sTargetName); - } - case Punish_Drug: - { - ClientCommand(client, "sm_drug \"%s\"", sTargetName); - } - case Punish_Freeze: - { - ClientCommand(client, "sm_freeze \"%s\"", sTargetName); - } - case Punish_FreezeBomb: - { - ClientCommand(client, "sm_freezebomb \"%s\"", sTargetName); - } - case Punish_Slap: - { - ClientCommand(client, "sm_slap \"%s\" 10", sTargetName); - } - case Punish_Slay: - { - ClientCommand(client, "sm_slay \"%s\"", sTargetName); - } - case Punish_TimeBomb: - { - ClientCommand(client, "sm_timebomb \"%s\"", sTargetName); - } - } - - if (punishment == Punish_Cheater) - { - LogAction(client, target, "[SM SPEC] %N marked %N(%s) with a %s flag for %s", client, target, sTargetID, g_sPunishments[punishment], reason); - } - else - { - ShowActivity(client, "%t", "Punished", sTargetName, g_sPunishments[punishment], reason); - LogAction(client, target, "[SM SPEC] %N punished %N(%s) with a %s for %s", client, target, sTargetID, g_sPunishments[punishment], reason); - } - - /** - Null the globals. - */ - g_aPlayers[client][TargetPunishment] = Punish_None; - g_aPlayers[client][iBanTime] = -1; -} - -/** -Build the menu of player names -*/ -stock Handle:BuildPlayerListMenu() -{ - new Handle:hMenu = CreateMenu(Menu_PlayerList); - AddTargetsToMenu(hMenu, 0, true, false); - SetMenuTitle(hMenu, "Select A Player:"); - SetMenuExitBackButton(hMenu, true); - return hMenu; -} - -/** -Build the select player menu (current or list of players) -*/ -stock Handle:BuildSelectPlayerMenu() -{ - new Handle:hMenu = CreateMenu(Menu_SelectPlayer); - SetMenuTitle(hMenu, "Select A Player:"); - AddMenuItem(hMenu, "Current", "Current Target"); - AddMenuItem(hMenu, "List", "Player List"); - SetMenuExitBackButton(hMenu, true); - return hMenu; -} - -/** -Build the punishmenu menu -*/ -stock Handle:BuildPunishmentMenu(iClient) -{ - new Handle:hMenu = CreateMenu(Menu_Punishments); - SetMenuTitle(hMenu, "Select A Punishment:"); - SetMenuExitBackButton(hMenu, true); - SetMenuExitButton(hMenu, true); - - if (g_aPluginCvarSettings[bKick] && ((GetUserFlagBits(iClient) & ADMFLAG_GENERIC) || (GetUserFlagBits(iClient) & ADMFLAG_ROOT))) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Kick], "Kick"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Kick], "Kick", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bBan] && ((GetUserFlagBits(iClient) & ADMFLAG_GENERIC) || (GetUserFlagBits(iClient) & ADMFLAG_ROOT))) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Ban], "Ban"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Ban], "Ban", ITEMDRAW_DISABLED); - } - - if (g_aPluginSettings[bUseDukehacks] && g_aPluginCvarSettings[bCheater] && (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Cheater], "Flag As Cheater"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Cheater], "Flag As Cheater", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bBeacon]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Beacon], "Beacon"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Beacon], "Beacon", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bBlind]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Blind], "Blind"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Blind], "Blind", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bDrug]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Drug], "Drug"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Drug], "Drug", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bFreeze]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Freeze], "Freeze"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Freeze], "Freeze", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bFreezebomb]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_FreezeBomb], "Freeze Bomb"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_FreezeBomb], "Freeze Bomb", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bSlap]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Slap], "Slap"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Slap], "Slap", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bSlay]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Slay], "Slay"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Slay], "Slay", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bTimeBomb]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_TimeBomb], "Time Bomb"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_TimeBomb], "Time Bomb", ITEMDRAW_DISABLED); - } - - return hMenu; -} - -/** -Build the punishmenu menu -*/ -stock Handle:BuildBanTimeMenu() -{ - new Handle:hMenu = CreateMenu(Menu_BanTime); - SetMenuTitle(hMenu, "Select Ban Type:"); - - if (g_aPluginCvarSettings[bBanPerm]) - { - AddMenuItem(hMenu, "permban", "Permanent"); - } - else - { - AddMenuItem(hMenu, "permban", "Permanent", ITEMDRAW_DISABLED); - } - - AddMenuItem(hMenu, "10", "10 Minutes"); - AddMenuItem(hMenu, "30", "30 Minutes"); - AddMenuItem(hMenu, "60", "1 Hour"); - AddMenuItem(hMenu, "240", "4 Hours"); - AddMenuItem(hMenu, "1440", "1 Day"); - AddMenuItem(hMenu, "10080", "1 Week"); - - SetMenuExitBackButton(hMenu, true); - return hMenu; -} - -/** -Build the punishmenu menu -*/ -stock Handle:BuildReasonMenu() -{ - new Handle:hMenu = CreateMenu(Menu_Reason); - SetMenuTitle(hMenu, "Select A Reason:"); - - AddMenuItem(hMenu, "Abusive", "Abusive"); - AddMenuItem(hMenu, "Racism", "Racism"); - AddMenuItem(hMenu, "General cheating/exploits", "General cheating/exploits"); - AddMenuItem(hMenu, "Wallhack", "Wallhack"); - AddMenuItem(hMenu, "Aimbot", "Aimbot"); - AddMenuItem(hMenu, "Speedhacking", "Speedhacking"); - AddMenuItem(hMenu, "Mic spamming", "Mic spamming"); - AddMenuItem(hMenu, "Admin disrepect", "Admin disrepect"); - AddMenuItem(hMenu, "Camping", "Camping"); - AddMenuItem(hMenu, "Team killing", "Team killing"); - AddMenuItem(hMenu, "Unacceptable Spray", "Unacceptable Spray"); - AddMenuItem(hMenu, "Breaking Server Rules", "Breaking Server Rules"); - AddMenuItem(hMenu, "Other", "Other"); - - SetMenuExitBackButton(hMenu, true); - return hMenu; -} - -/** -Build the cheater displays -*/ -stock Handle:BuildAdminCheaterPanel() -{ - - /** - Create the menu and set the menu options. - */ - new Handle:hPanel = CreatePanel(); - SetPanelTitle(hPanel, "Simple Spectator:"); - - DrawPanelText(hPanel, "Are you sure you want to"); - DrawPanelText(hPanel, "flag this player as a cheater?"); - DrawPanelText(hPanel, "They will not be able to damage"); - DrawPanelText(hPanel, "anyone and die on fall damage."); - DrawPanelItem(hPanel, "Yes"); - DrawPanelItem(hPanel, "No"); - - return hPanel; -} - -stock Handle:BuildPublicCheaterPanel() -{ - - /** - Create the menu and set the menu options. - */ - new Handle:hPanel = CreatePanel(); - SetPanelTitle(hPanel, "Simple Spectator:"); - - DrawPanelText(hPanel, "Are you sure you want to"); - DrawPanelText(hPanel, "submit this player as a cheater?"); - DrawPanelItem(hPanel, "Yes (Not Implemented Yet)", ITEMDRAW_DISABLED); - DrawPanelItem(hPanel, "No"); - return hPanel; -} - -/** -Build the hud displays -*/ -stock Handle:BuildPlayerHudMenu(iClient, iTarget) -{ - - /** - Create all the string variables we will need - */ - new String:sTargetName[MAX_NAME_LENGTH + 1], - String:sTargetID[64], - String:sTargetIP[16]; - - new String:sDisplayName[MAX_NAME_LENGTH + 1], - String:sDisplayID[64], - String:sDisplayIP[64], - String:sDisplayFrags[16], - String:sDisplayDeaths[16]; - - new iTargetFrags, - iTargetDeaths; - - /** - Get the targets information - */ - GetClientName(iTarget, sTargetName, sizeof(sTargetName)); - GetClientIP(iTarget, sTargetIP, sizeof(sTargetIP)); - GetClientAuthString(iTarget, sTargetID, sizeof(sTargetID)); - iTargetFrags = GetClientFrags(iTarget); - iTargetDeaths = GetClientDeaths(iTarget); - - /** - Format the strings for the menu - */ - Format(sDisplayName, sizeof(sDisplayName), "Player: %s", sTargetName); - Format(sDisplayID, sizeof(sDisplayID), "Steam ID: %s", sTargetID); - Format(sDisplayIP, sizeof(sDisplayIP), "IP Address: %s", sTargetIP); - Format(sDisplayFrags, sizeof(sDisplayFrags), "Kills: %i", iTargetFrags); - Format(sDisplayDeaths, sizeof(sDisplayDeaths), "Deaths: %i", iTargetDeaths); - - /** - Create the menu and set the menu options. - */ - new Handle:hMenu = CreateMenu(Menu_PlayerHud); - SetMenuExitBackButton(hMenu, false); - SetMenuTitle(hMenu, "Simple Spectator"); - - AddMenuItem(hMenu, "name", sDisplayName, ITEMDRAW_DISABLED); - AddMenuItem(hMenu, "steamid", sDisplayID, ITEMDRAW_DISABLED); - - if (SM_IsValidAdmin(iClient, g_sAdminFlags)) - { - AddMenuItem(hMenu, "ip", sDisplayIP, ITEMDRAW_DISABLED); - } - - AddMenuItem(hMenu, "kills", sDisplayFrags, ITEMDRAW_DISABLED); - AddMenuItem(hMenu, "deaths", sDisplayDeaths, ITEMDRAW_DISABLED); - - if (g_aPlayers[iClient][iTargetIndex]) - { - AddMenuItem(hMenu, "stop", "Stop Following"); - } - else - { - AddMenuItem(hMenu, "start", "Follow Player"); - } - - if ((GetUserFlagBits(iClient) & ADMFLAG_GENERIC) || (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - if (g_aPlayers[iTarget][bIsFlaggedCheater] && (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - AddMenuItem(hMenu, "removecheater", "Remove Cheater Flag"); - } - else - { - if (CanUserTarget(iClient, iTarget)) - { - AddMenuItem(hMenu, "punish", "Punish Player"); - } - else - { - AddMenuItem(hMenu, "punish", "Punish Player (Immune)", ITEMDRAW_DISABLED); - } - } - } - else - { - AddMenuItem(hMenu, "reportcheater", "Report Cheater"); - } - - SetMenuPagination(hMenu, MENU_NO_PAGINATION); - SetMenuExitButton(hMenu, true); - return hMenu; -} - -stock Handle:BuildPlayerHudPanel(iClient, iTarget) -{ - - /** - Create all the string variables we will need - */ - new String:sTargetName[MAX_NAME_LENGTH + 1], - String:sTargetID[64], - String:sTargetIP[16]; - - new String:sDisplayName[MAX_NAME_LENGTH + 1], - String:sDisplayID[64], - String:sDisplayIP[64], - String:sDisplayFrags[16], - String:sDisplayDeaths[16]; - - new iTargetFrags, - iTargetDeaths; - - /** - Get the targets information - */ - GetClientName(iTarget, sTargetName, sizeof(sTargetName)); - GetClientIP(iTarget, sTargetIP, sizeof(sTargetIP)); - GetClientAuthString(iTarget, sTargetID, sizeof(sTargetID)); - iTargetFrags = GetClientFrags(iTarget); - iTargetDeaths = GetClientDeaths(iTarget); - - /** - Format the strings for the menu - */ - Format(sDisplayName, sizeof(sDisplayName), "Player: %s", sTargetName); - Format(sDisplayID, sizeof(sDisplayID), "Steam ID: %s", sTargetID); - Format(sDisplayIP, sizeof(sDisplayIP), "IP Address: %s", sTargetIP); - Format(sDisplayFrags, sizeof(sDisplayFrags), "Kills: %i", iTargetFrags); - Format(sDisplayDeaths, sizeof(sDisplayDeaths), "Deaths: %i", iTargetDeaths); - - /** - Create the menu and set the menu options. - */ - new Handle:hPanel = CreatePanel(); - SetPanelTitle(hPanel, "Simple Spectator"); - - DrawPanelText(hPanel, "Player Information:"); - DrawPanelText(hPanel, sDisplayName); - DrawPanelText(hPanel, sDisplayID); - if (SM_IsValidAdmin(iClient, g_sAdminFlags)) - { - DrawPanelText(hPanel, sDisplayIP); - } - - DrawPanelText(hPanel, sDisplayFrags); - DrawPanelText(hPanel, sDisplayDeaths); - - if (g_aPlayers[iClient][iTargetIndex]) - { - DrawPanelItem(hPanel, "Stop Following"); - } - else - { - DrawPanelItem(hPanel, "Follow Player"); - } - - if ((GetUserFlagBits(iClient) & ADMFLAG_GENERIC) || (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - if (g_aPlayers[iTarget][bIsFlaggedCheater] && (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - DrawPanelItem(hPanel, "Remove Cheater Flag"); - } - else - { - if (CanUserTarget(iClient, iTarget)) - { - DrawPanelItem(hPanel, "Punish Player"); - } - else - { - DrawPanelItem(hPanel, "Punish Player (Immune)", ITEMDRAW_DISABLED); - } - } - } - else - { - DrawPanelItem(hPanel, "Report Cheater"); - } - - DrawPanelItem(hPanel, "Close Hud Panel"); - return hPanel; -} - -/** -Adjust the settings if a convar was changed -*/ -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - for (new iCvar = 0 ; _:iCvar < sizeof(g_aPluginCvarSettings); iCvar++) - { - if (g_aPluginCvar[_:iCvar] == convar) - { - if (StringToInt(newValue) == 1) - { - g_aPluginCvarSettings[_:iCvar] = true; - } - else - { - g_aPluginCvarSettings[_:iCvar] = false; - } - } - } - - /* - ReBuild the global menu that depends on cvars - */ - g_aMenus[hBanTime] = BuildBanTimeMenu(); - - /** - Run a loop to reset the hud - */ - for(new i = 1; i <= MaxClients; i++) - { - StopDisplayingHud(i); - if (IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(i); - } - } -} diff --git a/Simple Team Manager/addons/sourcemod/scripting/simple-teambalancer.sp b/Simple Team Manager/addons/sourcemod/scripting/simple-teambalancer.sp deleted file mode 100644 index 3302255..0000000 --- a/Simple Team Manager/addons/sourcemod/scripting/simple-teambalancer.sp +++ /dev/null @@ -1,1797 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Team Balancer -Description: - Balances teams based upon player count - Player will not be balanced more than once in 5 (default) mins - Buddy system tries to keep buddies together - Ability to prioritize players - Ability to force players to accept the new team - Admins are immune -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include -#include - -#define PLUGIN_VERSION "2.1.$Rev$" - -enum PlayerData -{ - Handle:hBalanceTimer, - Handle:hForcedTimer, - bool:bSwitched, - bool:bFlagCarrier -}; - -/** - Global convar handles - */ -new Handle:stb_enabled = INVALID_HANDLE; -new Handle:stb_buddyenabled = INVALID_HANDLE; -new Handle:stb_logactivity = INVALID_HANDLE; -new Handle:stb_logactivity2 = INVALID_HANDLE; -new Handle:stb_unbalancelimit = INVALID_HANDLE; -new Handle:stb_deadonly = INVALID_HANDLE; -new Handle:stb_priorityenabled = INVALID_HANDLE; -new Handle:stb_uberlevel = INVALID_HANDLE; -new Handle:stb_balancedelay = INVALID_HANDLE; -new Handle:stb_livingplayerswitchdelay = INVALID_HANDLE; -new Handle:stb_livingplayercheckdelay = INVALID_HANDLE; -new Handle:stb_roundstartdelay = INVALID_HANDLE; -new Handle:stb_switchbackforced = INVALID_HANDLE; -new Handle:stb_adminflag = INVALID_HANDLE; -new Handle:stb_buddyrestriction = INVALID_HANDLE; -new Handle:stb_convarcontrol = INVALID_HANDLE; - -/** - Built-in cvars handles - */ -new Handle:stb_mp_autoteambalance = INVALID_HANDLE; -new Handle:stb_mp_teams_unbalance_limit = INVALID_HANDLE; -new Handle:TFGameModeArena = INVALID_HANDLE; - -/** - Timer handles - */ -new Handle:g_hBalanceTimer = INVALID_HANDLE; -new Handle:g_hLivingPlayerCheckTimer = INVALID_HANDLE; - -/** - Player arrays - */ -new g_aPlayers[MAXPLAYERS + 1][PlayerData]; - -/** -Global bools -*/ -new bool:g_bIsEnabled = true; -new bool:g_bPriorityPlayers = true; -new bool:g_bBuddyRestriction = false; -new bool:g_bLogActivity = false; -new bool:g_bLogActivity2 = false; -new bool:g_bDeadOnly = false; -new bool:g_bConVarControl = true; -new bool:g_bBuddyEnabled = true; -new bool:g_bBalanceInProgress = false; -new bool:g_bRoundStart = false; -new bool:g_bRoundEnd = false; -new bool:g_bSuddenDeath = false; -new bool:g_bIsArenaMode = false; - -/** - Global strings/integers/floats - */ -new g_iUnbalanceLimit, g_iLivingPlayerSwitchDelay, g_iLivingPlayerCheckDelay; -new g_iRoundStartDelay, g_iSwitchBackForced, g_iBalanceDelay; -new Float:g_fUberLevel; -new g_iOwnerOffset; -new String:g_sAdminFlag[5]; - -public Plugin:myinfo = -{ - name = "Simple Team Balancer", - author = "Simple Plugins", - description = "Balances teams based upon player count.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -} - -public OnPluginStart() -{ - - /** - Create console variables - */ - CreateConVar("stb_version", PLUGIN_VERSION, "Simple Team Balancer", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - stb_enabled = CreateConVar("stb_enabled", "1", "Enable or Disable Simple Team Balancer", _, true, 0.0, true, 1.0); - stb_priorityenabled = CreateConVar("stb_priorityenabled", "1", "Enable or Disable the prioritization of living players", _, true, 0.0, true, 1.0); - stb_buddyrestriction = CreateConVar("stb_buddyrestriction", "0", "Enable or Disable Admin Only buddy lists", _, true, 0.0, true, 1.0); - stb_logactivity = CreateConVar("stb_logactivity", "0", "Enable or Disable the disaplying of events in the log", _, true, 0.0, true, 1.0); - stb_logactivity2 = CreateConVar("stb_logactivity2", "0", "Enable or Disable the disaplying of detailed events in the log (WILL SPAM LOG)", _, true, 0.0, true, 1.0); - stb_deadonly = CreateConVar("stb_deadonly", "0", "Enable or Disable the switching of only dead players", _, true, 0.0, true, 1.0); - stb_convarcontrol = CreateConVar("stb_convarcontrol", "1", "Enable or Disable the control of builtin console variables", _, true, 0.0, true, 1.0); - stb_buddyenabled = CreateConVar("stb_buddyenabled", "1", "Enable or Disable the buddy system", _, true, 0.0, true, 1.0); - stb_unbalancelimit = CreateConVar("stb_unbalancelimit", "2", "Amount of players teams are ALLOWED to be unbalanced by", _, true, 1.0, true, 32.0); - stb_balancedelay = CreateConVar("stb_balancedelay", "10", "Delay in seconds to start an autobalance"); - stb_livingplayerswitchdelay = CreateConVar("stb_livingplayerswitchdelay", "20", "Delay in seconds to switch living players once selected"); - stb_livingplayercheckdelay = CreateConVar("stb_livingplayercheckdelay", "10", "Delay in seconds to start checking living players once teams become unbalanced"); - stb_roundstartdelay = CreateConVar("stb_roundstartdelay", "15", "Delay in seconds to start balancing teams after the start of a round"); - stb_switchbackforced = CreateConVar("stb_switchbackforced", "300", "Amount of time in seconds to not switch a player twice and force the team if enabled"); - stb_uberlevel = CreateConVar("stb_uberlevel", "1.0", "Min uber level medic must have to have priority over other living players. Setting to 0 will rarely switch a living medic", _, true, 0.0, true, 1.0); - stb_adminflag = CreateConVar("stb_adminflag", "a", "Admin flag to use for immunity. Must be a in char format."); - stb_mp_autoteambalance = FindConVar("mp_autoteambalance"); - stb_mp_teams_unbalance_limit = FindConVar("mp_teams_unbalance_limit"); - - /** - Removing the notify tags from the built in cvars. We dont want spam. - */ - if (stb_mp_autoteambalance != INVALID_HANDLE) - { - SetConVarFlags(stb_mp_autoteambalance, GetConVarFlags(stb_mp_autoteambalance)^FCVAR_NOTIFY); - } - if (stb_mp_teams_unbalance_limit != INVALID_HANDLE) - { - SetConVarFlags(stb_mp_teams_unbalance_limit, GetConVarFlags(stb_mp_teams_unbalance_limit)^FCVAR_NOTIFY); - } - - /** - Hook console variables - */ - HookConVarChange(stb_enabled, ConVarSettingsChanged); - HookConVarChange(stb_priorityenabled, ConVarSettingsChanged); - HookConVarChange(stb_buddyrestriction, ConVarSettingsChanged); - HookConVarChange(stb_logactivity, ConVarSettingsChanged); - HookConVarChange(stb_logactivity2, ConVarSettingsChanged); - HookConVarChange(stb_deadonly, ConVarSettingsChanged); - HookConVarChange(stb_convarcontrol, ConVarSettingsChanged); - HookConVarChange(stb_buddyenabled, ConVarSettingsChanged); - HookConVarChange(stb_unbalancelimit, ConVarSettingsChanged); - HookConVarChange(stb_balancedelay, ConVarSettingsChanged); - HookConVarChange(stb_livingplayerswitchdelay, ConVarSettingsChanged); - HookConVarChange(stb_livingplayercheckdelay, ConVarSettingsChanged); - HookConVarChange(stb_roundstartdelay, ConVarSettingsChanged); - HookConVarChange(stb_switchbackforced, ConVarSettingsChanged); - HookConVarChange(stb_uberlevel, ConVarSettingsChanged); - HookConVarChange(stb_mp_autoteambalance, ConVarSettingsChanged); - HookConVarChange(stb_mp_teams_unbalance_limit, ConVarSettingsChanged); - - /** - Create console commands - */ - RegConsoleCmd("sm_buddy", Command_AddBalanceBuddy, "Add a balance buddy"); - RegConsoleCmd("sm_lockbuddy", Command_LockBuddy, "Locks your balance buddy selection"); - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[STB] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_death", HookPlayerDeath, EventHookMode_Post); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Post); - switch (g_CurrentMod) - { - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - HookEvent("teamplay_suddendeath_begin", HookSuddenDeathBegin, EventHookMode_PostNoCopy); - HookEvent("teamplay_flag_event", HookFlagEvent, EventHookMode_Post); - TFGameModeArena = FindConVar("tf_gamemode_arena"); - g_iOwnerOffset = FindSendPropInfo("CBaseObject", "m_hBuilder"); - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_Post); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - - /** - Load translations and .cfg file - */ - LoadTranslations ("simpleteambalancer.phrases"); - AutoExecConfig(true, "plugin.simpleteambalancer"); - LogAction(0, -1, "[STB] Simple Team Balancer is loaded."); -} - -public OnAllPluginsLoaded() -{ - //something -} - -public OnLibraryRemoved(const String:name[]) -{ - //something -} - -public OnConfigsExecuted() -{ - - /** - Load up global variables - */ - g_bIsEnabled = GetConVarBool(stb_enabled); - g_bBuddyEnabled = GetConVarBool(stb_buddyenabled); - g_bLogActivity = GetConVarBool(stb_logactivity); - g_bLogActivity2 = GetConVarBool(stb_logactivity2); - g_bDeadOnly = GetConVarBool(stb_deadonly); - g_bPriorityPlayers = GetConVarBool(stb_priorityenabled); - g_bBuddyRestriction = GetConVarBool(stb_buddyrestriction); - g_bConVarControl = GetConVarBool(stb_convarcontrol); - g_fUberLevel = GetConVarFloat(stb_uberlevel); - g_iUnbalanceLimit = GetConVarInt(stb_unbalancelimit); - g_iBalanceDelay = GetConVarInt(stb_balancedelay); - g_iLivingPlayerSwitchDelay = GetConVarInt(stb_livingplayerswitchdelay); - g_iLivingPlayerCheckDelay = GetConVarInt(stb_livingplayercheckdelay); - g_iRoundStartDelay = GetConVarInt(stb_roundstartdelay); - g_iSwitchBackForced = GetConVarInt(stb_switchbackforced); - GetConVarString(stb_adminflag, g_sAdminFlag, sizeof(g_sAdminFlag)); - - /** - Report enabled - */ - if (g_bIsEnabled) - { - LogAction(0, -1, "[STB] Simple Team Balancer is ENABLED."); - } - else - { - LogAction(0, -1, "[STB] Simple Team Balancer is DISABLED."); - } - - - /** - Report log activity - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Log Activity ENABLED."); - } - else - { - LogAction(0, -1, "[STB] Log Activity DISABLED."); - } - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Detailed Log Activity ENABLED."); - } - else - { - LogAction(0, -1, "[STB] Detailed Log Activity DISABLED."); - } -} - -public OnMapStart() -{ - - /** - Check for arena mode - */ - if (g_CurrentMod == GameType_TF && GetConVarBool(TFGameModeArena)) - { - g_bIsArenaMode = true; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Simple Team Balancer detected arena mode and will be bypassed"); - } - } - else - { - g_bIsArenaMode = false; - } - - /** - Reset the globals - */ - g_bBalanceInProgress = false; - g_bRoundStart = false; - g_bRoundEnd = false; - g_bSuddenDeath = false; - - /** - Set the built-in convars - */ - SetGameCvars(); -} - -public OnClientPostAdminCheck(client) -{ - - /** - Make sure its a valid connected client and buddy system is enabled - */ - if (client == 0 || !g_bIsEnabled || !IsClientConnected(client) || !g_bBuddyEnabled) - { - return; - } - - /** - Make sure if its set for admins only they have the flags - */ - if (g_bBuddyRestriction && !SM_IsValidAdmin(client, g_sAdminFlag)) - { - return; - } - - /** - Start the advertisement timer - */ - CreateTimer (60.0, Timer_WelcomeAdvert, client); -} - -public OnClientDisconnect(client) -{ - - /** - Call stock function to cleaup - */ - CleanUp(client); -} - -public OnClientDisconnect_Post(client) -{ - - /** - Determine if we need a balance - */ - if (OkToBalance() && IsUnbalanced() && !g_bBalanceInProgress) - { - - /** - No balance in progress but balance is needed - */ - StartABalance(); - } -} - -public SM_OnPlayerMoved(Handle:plugin, client, team) -{ - - /** - Make sure we called the move function - */ - if (plugin != GetMyHandle()) - { - if (g_bLogActivity2) - { - LogAction(0, client, "[STB] Callback was not started with current plugin, bugging out."); - } - return; - } - - /** - Get the players name and report the event - */ - decl String:sPlayerName[64]; - GetClientName(client, sPlayerName, sizeof(sPlayerName)); - if (g_bLogActivity) - { - LogAction(0, client, "[STB] Changed %s to team %i.", sPlayerName, team); - } - - /** - If we are in TF2 fire the bult-in team balance event - */ - if(g_CurrentMod == GameType_TF) - { - new Handle:event = CreateEvent("teamplay_teambalanced_player"); - SetEventInt(event, "player", client); - SetEventInt(event, "team", team); - FireEvent(event); - } - - /** - Notify the players - */ - PrintToChatAll("[SM] %T", "BalanceMessage", LANG_SERVER, sPlayerName); - - /** - Set the players variables and start a timer - */ - g_aPlayers[client][bSwitched] = true; - g_aPlayers[client][hForcedTimer] = CreateTimer(float(g_iSwitchBackForced), Timer_ForcedExpired, client, TIMER_FLAG_NO_MAPCHANGE); - - /** - We are done, log the completion and end the balance - */ - if (g_bLogActivity) - { - LogAction(0, client, "[STB] Balance finished."); - } - g_bBalanceInProgress = false; -} - -/* HOOKED EVENTS */ - -public HookPlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get our event variables - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - decl String:sWeapon[64]; - GetEventString(event, "weapon", sWeapon, sizeof(sWeapon)); - - /** - Return if death was not caused by a player - This is the case when the player switches teams - */ - if (StrEqual(sWeapon, "world", false)) - { - return; - } - - - /** - Check if balance is needed - */ - if (IsClientInGame(iClient) && OkToBalance() && IsUnbalanced()) - { - new iSmallerTeam = GetSmallerTeam(); - - /** - Check if balance is in progress - */ - if (g_bBalanceInProgress) - { - - /** - There is a balance in progress - Check the player who died to see if he is supposed to be switched - */ - if (g_aPlayers[iClient][hBalanceTimer] != INVALID_HANDLE) - { - - /** - The player has a timer on him to switch him to other team - Stop the timer - */ - CloseHandle(g_aPlayers[iClient][hBalanceTimer]); - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] With a balance in progress the queued living player died and was switched."); - } - - /** - Call the stock change team function - */ - BalancePlayer(iClient, SM_GetForcedTeam(iClient)); - return; - } - - /** - Before we continue, lets make sure the client is switchable - */ - if (IsSwitchablePlayer(iClient, GetBiggerTeam())) - { - - /** - Now we check the buddy system - */ - if (g_bBuddyEnabled) - { - - /** - Buddy system is enabled, check to see if client has buddy - */ - new iBuddyIndex = SM_GetClientBuddy(iClient); - if (iBuddyIndex != 0 || !IsClientConnected(iBuddyIndex) || !IsClientInGame(iBuddyIndex)) - { - - /** - The client has a buddy, so we check to see if they are on same team - */ - if (GetClientTeam(iClient) == GetClientTeam(iBuddyIndex)) - { - - /** - They are, but we don't bug out, we still need to start a balance - */ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] With a balance in progress a buddy on the right team was found and skipped."); - } - } - else - { - - /** - They are not on the same team - The buddy could be in spec, and that would make it not matter where he is, or the buddy is on the smaller team - */ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] With a balance in progress a buddy on the wrong team was switched."); - } - BalancePlayer(iClient, iSmallerTeam); - return; - } - } - else - { - - /** - Client doesn't have a buddy, balance this player - */ - BalancePlayer(iClient, iSmallerTeam); - return; - } - } - else - { - - /** - Buddy system is not enabled, balance this player - */ - BalancePlayer(iClient, iSmallerTeam); - return; - } - } - } - else - { - - /** - If we get to here then we must need to start a balance - */ - StartABalance(); - } - } -} - -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get our event variables. - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - new iTeam = GetEventInt(event, "team"); - - /** - Make sure its ok to balance. - */ - if (OkToBalance()) - { - - /** - See if the client that changed teams was set to with a balance. - */ - if (g_aPlayers[iClient][hBalanceTimer] != INVALID_HANDLE - && SM_GetForcedTeam(iClient) == iTeam - && g_bBalanceInProgress) - { - - /** - The client was set to be balanced, so we close the timer. - */ - CloseHandle(g_aPlayers[iClient][hBalanceTimer]); - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - - /** - Stop the balance. - */ - g_bBalanceInProgress = false; - return; - } - - /** - It's not likely that this team change can cause us to need a balance. - If it does, start one with a small dealy to deal with forced switch backs. - */ - if (IsUnbalanced() && !g_bBalanceInProgress) - { - CreateTimer(2.0, Timer_ChangeTeamBalanceDelay, _, TIMER_FLAG_NO_MAPCHANGE); - } - } -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set the variables we need to start a round - */ - g_bRoundStart = true; - g_bRoundEnd = false; - g_bSuddenDeath = false; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Round Started"); - } - - /** - Start a delayed balance check at the start of the round - */ - CreateTimer(float(g_iRoundStartDelay), Timer_RoundStart); -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set the variables we need at round end - */ - g_bRoundEnd = true; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Round Ended"); - } -} - -public HookSuddenDeathBegin(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set the variables we need for sudden death - */ - g_bSuddenDeath = true; -} - -public HookFlagEvent(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get our event variables - */ - new iClient = GetEventInt(event, "player"); - new iFlagStatus = GetEventInt(event, "eventtype"); - - /** - Make sure we have a valid client - */ - if (!IsClientInGame(iClient)) - { - return; - } - - /** - Determine what kind of event this is - */ - switch (iFlagStatus) - { - case 1: - { - - /** - The flag was picked up - */ - g_aPlayers[iClient][bFlagCarrier] = true; - } - case 2: - { - - /** - The flag was capped - */ - g_aPlayers[iClient][bFlagCarrier] = false; - } - case 3: - { - - /** - The flag was defended, we don't have to do anything - */ - } - case 4: - { - - /** - The flag was dropped - */ - g_aPlayers[iClient][bFlagCarrier] = false; - } - } -} - -/* COMMAND EVENTS */ - -public Action:Command_AddBalanceBuddy(client, args) -{ - if (client == 0) - { - ReplyToCommand(client, "[SM] %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - if (!g_bIsEnabled || !g_bBuddyEnabled) - { - ReplyToCommand(client, "[SM] %T", "CmdDisabled", LANG_SERVER); - return Plugin_Handled; - } - if (g_bBuddyRestriction) - { - if (!SM_IsValidAdmin(client, g_sAdminFlag)) - { - ReplyToCommand(client, "[SM] %T", "RestrictedBuddy", LANG_SERVER); - return Plugin_Handled; - } - } - decl String:sPlayerUserId[24]; - GetCmdArg(1, sPlayerUserId, sizeof(sPlayerUserId)); - new iPlayer = GetClientOfUserId(StringToInt(sPlayerUserId)); - if (!iPlayer || !IsClientInGame(iPlayer) || client == iPlayer) - { - if (client == iPlayer) - { - PrintHintText(client, "%T", "SelectSelf", LANG_SERVER); - } - ReplyToCommand(client, "[SM] Usage: buddy "); - new Handle:playermenu = BuildPlayerMenu(); - DisplayMenu(playermenu, client, MENU_TIME_FOREVER); - } - else - { - decl String:cName[128]; - decl String:bName[128]; - GetClientName(client, cName, sizeof(cName)); - GetClientName(iPlayer, bName, sizeof(bName)); - if (SM_IsBuddyLocked(iPlayer)) - { - ReplyToCommand(client, "[SM] %T", "PlayerLockedBuddyMsg", LANG_SERVER, bName); - return Plugin_Handled; - } - SM_AssignBuddy(client, iPlayer); - PrintHintText(client, "%T", "BuddyMsg", LANG_SERVER, bName); - PrintHintText(iPlayer, "%T", "BuddyMsg", LANG_SERVER, cName); - } - return Plugin_Handled; -} - -public Action:Command_LockBuddy(client, args) -{ - if (client == 0) - { - ReplyToCommand(client, "[SM] %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - if (!g_bIsEnabled) - { - ReplyToCommand(client, "[SM] %T", "CmdDisabled", LANG_SERVER); - return Plugin_Handled; - } - if (g_bBuddyRestriction) - { - if (!SM_IsValidAdmin(client, g_sAdminFlag)) - { - ReplyToCommand(client, "[SM] %T", "RestrictedBuddy", LANG_SERVER); - return Plugin_Handled; - } - } - if (SM_IsBuddyLocked(client)) - { - SM_LockBuddy(client, false); - PrintHintText(client, "%T", "BuddyLockMsgDisabled", LANG_SERVER); - } - else - { - SM_LockBuddy(client, true); - PrintHintText(client, "%T", "BuddyLockMsgEnabled", LANG_SERVER); - } - return Plugin_Handled; -} - -/** -Stock functions . - */ - -stock bool:IsUnbalanced() -{ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Checking if teams are unbalanced"); - } - new Team1Count = GetTeamClientCount(g_aCurrentTeams[Team1]); - new Team2Count = GetTeamClientCount(g_aCurrentTeams[Team2]); - new ubCount = RoundFloat(FloatAbs(float(Team1Count - Team2Count))); - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Team1:%i Team2:%i Difference:%i", Team1Count, Team2Count, ubCount); - } - if (ubCount > g_iUnbalanceLimit) - { - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Teams are unbalanced"); - } - return true; - } - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Teams are not unbalanced"); - } - return false; -} - -stock bool:OkToBalance() -{ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Checking if OK to balance."); - } - new bool:bResult = false; - if (g_bIsEnabled && !g_bRoundStart && !g_bRoundEnd && !g_bIsArenaMode && !g_bSuddenDeath) - { - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Passed IF statement"); - LogAction(0, -1, "[STB] Now checking admins"); - } - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientInGame(i) && !SM_IsValidAdmin(i, g_sAdminFlag)) - { - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Found at least 1 non-admin"); - LogAction(0, -1, "[STB] OK to balance"); - } - bResult = true; - break; - } - } - if (!bResult && g_bLogActivity2) - { - LogAction(0, -1, "[STB] All admins online"); - } - } - if (!bResult && g_bLogActivity2) - { - LogAction(0, -1, "[STB] Not OK to balance"); - } - return bResult; -} - -stock bool:IsSwitchablePlayer(iClient, iBiggerTeam) -{ - - /** - Run the client thru some standard checks - */ - if (!IsClientInGame(iClient) - || SM_IsValidAdmin(iClient, g_sAdminFlag) - || g_aPlayers[iClient][bFlagCarrier] - || GetClientTeam(iClient) != iBiggerTeam - || g_aPlayers[iClient][bSwitched]) - { - - /** - The supplied client can't be switched - */ - return false; - } - - /** - The supplied client can be switched - */ - return true; -} - -stock bool:HasUber(iClient) -{ - - /** - First things first, make sure the client is a medic - */ - if(TF2_GetPlayerClass(iClient) == TFClass_Medic) - { - - /** - We can only check the active weapon, so make sure the client is holding the uber gun - */ - decl String:sWeaponName[32]; - GetClientWeapon(iClient, sWeaponName, sizeof(sWeaponName)); - if(StrEqual(sWeaponName, "tf_weapon_medigun")) - { - - /** - They are, so lets check the uber level of the gun - */ - new iEntityIndex = GetEntDataEnt2(iClient, FindSendPropInfo("CTFPlayer", "m_hActiveWeapon")); - new Float:fChargeLevel = GetEntDataFloat(iEntityIndex, FindSendPropInfo("CWeaponMedigun", "m_flChargeLevel")); - if (fChargeLevel >= g_fUberLevel) - { - - /** - The client supplied has an uber above the supplied level, return true - */ - if (g_bLogActivity2) - { - LogAction(0, iClient, "[STB] Found a medic with a uber and skipped him."); - } - return true; - } - } - } - - /** - The client supplied does not have an uber above the supplied level, return false - */ - return false; -} - -stock bool:HasBuildingsBuilt(iClient) -{ - - /** - We have to start a loop to check the owner of all the valid entities - */ - new iMaxEntities = GetMaxEntities(); - for (new i = MaxClients + 1; i <= iMaxEntities; i++) - { - if (!IsValidEntity(i)) - { - - /** - Not valid, continue to next one - */ - continue; - } - - /** - Get the name of the current entity - */ - decl String:sNetClass[32]; - GetEntityNetClass(i, sNetClass, sizeof(sNetClass)); - - /** - See if its something that an engineer would build - */ - if (strcmp(sNetClass, "CObjectSentrygun") == 0 - || strcmp(sNetClass, "CObjectTeleporter") == 0 - || strcmp(sNetClass, "CObjectDispenser") == 0) - { - - /** - It is, so lets check the owner - */ - if (GetEntDataEnt2(i, g_iOwnerOffset) == iClient) - { - - /** - The client supplied is the owner, return true - */ - if (g_bLogActivity2) - { - LogAction(0, iClient, "[STB] Found an engineer with buildings and skipped him."); - } - return true; - } - } - } - - /** - The client supplied didn't have any buildings, return false - */ - return false; -} - -stock StartABalance() -{ - - /** - See if we are already started a balance - */ - if (g_hBalanceTimer != INVALID_HANDLE) - { - - /** - We have, check if we still need to - */ - if (!IsUnbalanced() || !OkToBalance()) - { - - /** - We don't, stop the balance - It's almost impossible to reach this code, but we do it just in case - */ - CloseHandle(g_hBalanceTimer); - g_hBalanceTimer = INVALID_HANDLE; - g_bBalanceInProgress = false; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Balance delay timer was not needed and was killed before the callback."); - } - return; - } - else - { - - /** - We still need to balance - Bug out and wait for the current one to finish - */ - return; - } - } - - /** - Report that teams are unbalanced - */ - PrintToChatAll("[SM] %T", "UnBalanced", LANG_SERVER); - - /** - Check to see if we are supposed to delay the balance - */ - if (g_iBalanceDelay == 0) - { - - /** - Start the balance now - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Balance is now in progress."); - } - g_bBalanceInProgress = true; - g_hBalanceTimer = INVALID_HANDLE; - - /** - Check if we are allowed to scan living players - */ - if (!g_bDeadOnly) - { - - /** - We are allowed to, so we start a timer - */ - StartALivingPlayerTimer(); - - /** - Also report that we are now scanning dead players as well - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Now scanning dead players."); - } - } - else - { - - /** - We are not allowed to, so report that we are only scanning dead players - */ - if (g_bLogActivity) - LogAction(0, -1, "[STB] Only scanning dead players."); - } - - /** - We started the balance, bug out - */ - return; - } - - /** - We are supposed to delay the balance, start a balance timer - */ - g_hBalanceTimer = CreateTimer(float(g_iBalanceDelay), Timer_BalanceTeams, _, TIMER_FLAG_NO_MAPCHANGE); - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Teams are unbalanced. Balance delay timer started."); - } -} - -stock StartALivingPlayerTimer() -{ - - /** - Start a timer to check living players - */ - if (g_hLivingPlayerCheckTimer != INVALID_HANDLE) - { - - /** - If we for some reason already have one started, stop it. - */ - CloseHandle(g_hLivingPlayerCheckTimer); - g_hLivingPlayerCheckTimer = INVALID_HANDLE; - } - - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Living player balance delay timer started."); - } - g_hLivingPlayerCheckTimer = CreateTimer(float(g_iLivingPlayerCheckDelay), Timer_LivingPlayerCheck, _, TIMER_FLAG_NO_MAPCHANGE); -} - -stock FindSwitchablePlayer() -{ - - /** - Start a loop to find a switchable player - */ - new iPlayer; - new iBiggerTeam = GetBiggerTeam(); - for (new i = 1; i <= MaxClients; i++) - { - - /** - Check the stock function to see if we are allows to even switch the player - */ - if (!IsSwitchablePlayer(i, iBiggerTeam)) - { - continue; - } - - /** - If the mod is TF2 and they have Priority Players set check if the client has buildings or an uber - */ - if (g_CurrentMod == GameType_TF && g_bPriorityPlayers) - { - if (HasUber(i) || HasBuildingsBuilt(i)) - { - continue; - } - } - - /** - So far we are able we switch this player - Now we check the buddy system - */ - if (g_bBuddyEnabled) - { - - /** - Buddy system is enabled, check to see if client has buddy - */ - if (SM_GetClientBuddy(i) != 0) - { - - /** - The client has a buddy, so we check to see if they are on same team - */ - if (GetClientTeam(i) == GetClientTeam(SM_GetClientBuddy(i))) - { - - /** - They are, so we continue to next client - */ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] With a balance in progress a buddy on the right team was found and skipped."); - } - continue; - } - else - { - - /** - They are not on the same team, set this client - The buddy could be in spec, and that would make it not matter where he is, or the buddy is on the smaller team - */ - iPlayer = i; - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] With a balance in progress a buddy on the wrong team was found."); - } - break; - } - } - else - { - - /** - The client does not have a buddy, set this client - */ - iPlayer = i; - break; - } - } - else - { - - /** - Buddy system is not enabled, set this client - */ - iPlayer = i; - break; - } - } - - /** - Return the client we set, this could be 0, but very unlikely - */ - return iPlayer; -} - -stock BalancePlayer(iClient, iTeam) -{ - new Handle:hPack = CreateDataPack(); - WritePackCell(hPack, iClient); - WritePackCell(hPack, iTeam); - CreateTimer(0.1, Timer_BalancePlayer, hPack, TIMER_FLAG_NO_MAPCHANGE); -} - -stock CleanUp(iClient) -{ - g_aPlayers[iClient][bFlagCarrier] = false; - g_aPlayers[iClient][bSwitched] = false; - if (g_aPlayers[iClient][hForcedTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hForcedTimer]); - g_aPlayers[iClient][hForcedTimer] = INVALID_HANDLE; - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] Forced player disconnected, killing timer."); - } - } - if (g_aPlayers[iClient][hBalanceTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hBalanceTimer]); - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] Living player set to be balanced disconnected, killing timer."); - } - } -} - -stock GetSmallerTeam() -{ - - /** - Get the count of players on each team - */ - new iCountT1 = GetTeamClientCount(g_aCurrentTeams[Team1]); - new iCountT2 = GetTeamClientCount(g_aCurrentTeams[Team2]); - - /** - Return the smaller team - */ - if (iCountT1 < iCountT2) - { - return g_aCurrentTeams[Team1]; - } - else if (iCountT1 > iCountT2) - { - return g_aCurrentTeams[Team2]; - } - return 0; -} - -stock GetBiggerTeam() -{ - - /** - Get the count of players on each team - */ - new iCountT1 = GetTeamClientCount(g_aCurrentTeams[Team1]); - new iCountT2 = GetTeamClientCount(g_aCurrentTeams[Team2]); - - /** - Return the bigger team - */ - if (iCountT1 > iCountT2) - { - return g_aCurrentTeams[Team1]; - } - else if (iCountT1 < iCountT2) - { - return g_aCurrentTeams[Team2]; - } - return 0; -} - -stock SetGameCvars() -{ - if (g_bConVarControl && g_bIsEnabled) - { - if (stb_mp_autoteambalance != INVALID_HANDLE) - { - SetConVarInt(stb_mp_autoteambalance, 0); - } - if (stb_mp_teams_unbalance_limit != INVALID_HANDLE) - { - SetConVarInt(stb_mp_teams_unbalance_limit, g_iUnbalanceLimit); - } - } -} - -/* TIMER FUNCTIONS */ - -public Action:Timer_ChangeTeamBalanceDelay(Handle:timer, any:data) -{ - - /** - Finally start one if it's still unbalanced - */ - if (IsUnbalanced() && !g_bBalanceInProgress) - { - StartABalance(); - } -} - -public Action:Timer_BalanceTeams(Handle:timer, any:data) -{ - - /** - See if we still need to balance the teams - */ - if (!IsUnbalanced() || !OkToBalance()) - { - - /** - We don't, kill the balance - */ - g_bBalanceInProgress = false; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Balance delay timer was not needed and died."); - } - g_hBalanceTimer = INVALID_HANDLE; - return Plugin_Handled; - } - - /** - We still need to balance the teams - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Teams are still unbalanced. Balance is now in progress."); - } - g_bBalanceInProgress = true; - - - /** - Check if we are allowed to scan living players - */ - if (!g_bDeadOnly) - { - - /** - We are allowed to, so we start a timer - */ - StartALivingPlayerTimer(); - - /** - Also report that we are now scanning dead players as well - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Now scanning dead players."); - } - } - else - { - - /** - We are not allowed to, so report that we are only scanning dead players - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Only scanning dead players."); - } - } - - g_hBalanceTimer = INVALID_HANDLE; - return Plugin_Handled; -} - -public Action:Timer_LivingPlayerCheck(Handle:timer, any:data) -{ - - /** - Check to see if we still need to balance the teams - */ - if (!IsUnbalanced() || !OkToBalance()) - { - - /** - We don't, kill it and bug out - */ - g_bBalanceInProgress = false; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Living player balance delay timer was not needed and died."); - } - g_hLivingPlayerCheckTimer = INVALID_HANDLE; - return Plugin_Handled; - } - - /** - Call the stock function to find a player we can switch - */ - new iPlayer = FindSwitchablePlayer(); - - /** - Check to see if we found a player - */ - if (iPlayer == 0) - { - - /** - In the unlikely event that the stock function didn't return a player - Start a loop to find a random player - */ - new iBiggerTeam = GetBiggerTeam(); - do - { - iPlayer = GetRandomInt(1, MaxClients); - } while (!IsSwitchablePlayer(iPlayer, iBiggerTeam)); - - if (g_bLogActivity) - { - LogAction(0, iPlayer, "[STB] Found a random living player."); - } - } - else - { - if (g_bLogActivity) - { - LogAction(0, iPlayer, "[STB] Found a living player."); - } - } - - /** - Now that we have a player assigned them to the smaller team - */ - new iSmallerTeam = GetSmallerTeam(); - SM_SetForcedTeam(iPlayer, iSmallerTeam, true); - - /** - Let the player know we could be switching him soon - */ - PrintHintText(iPlayer, "%T", "PlayerMessage", LANG_SERVER, g_iLivingPlayerSwitchDelay); - if (g_bLogActivity) - { - LogAction(0, iPlayer, "[STB] Living player placed on a timer."); - } - - /** - Create a timer to switch the player - */ - g_aPlayers[iPlayer][hBalanceTimer] = CreateTimer(float(g_iLivingPlayerSwitchDelay), Timer_LivingPlayerBalance, iPlayer, TIMER_FLAG_NO_MAPCHANGE); - - /** - Reset the timer handle - */ - g_hLivingPlayerCheckTimer = INVALID_HANDLE; - - /** - We are done, bug out - */ - return Plugin_Handled; -} - -public Action:Timer_LivingPlayerBalance(Handle:timer, any:iClient) -{ - - /** - Check to make sure we still need to balance - */ - if (!IsUnbalanced() || !OkToBalance()) - { - - /** - We don't need to balance, bug out - */ - g_bBalanceInProgress = false; - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - SM_ClearForcedTeam(iClient); - return Plugin_Handled; - } - - /** - We still need to balance, lets make sure we can still balance this player - */ - if (!IsClientConnected(iClient) || g_aPlayers[iClient][bFlagCarrier]) - { - g_bBalanceInProgress = false; - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - SM_ClearForcedTeam(iClient); - if (g_bLogActivity) - { - if (g_aPlayers[iClient][bFlagCarrier]) - { - LogAction(0, iClient, "[STB] Living player became flag carrier, balance restarted."); - } - else - { - LogAction(0, iClient, "[STB] Living player timer was not needed and died."); - } - } - return Plugin_Handled; - } - - /** - Clear to balance this player, so do it - */ - BalancePlayer(iClient, SM_GetForcedTeam(iClient)); - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] Living player was switched."); - } - - /** - We are done, bug out - */ - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - return Plugin_Handled; -} - -public Action:Timer_BalancePlayer(Handle:timer, Handle:pack) -{ - - /** - Rest the datapack and load the variables - */ - ResetPack(pack); - new iClient = ReadPackCell(pack); - new iUnBalancedTeam = ReadPackCell(pack); - - /** - We are done with you now - */ - CloseHandle(pack); - - /** - Check the team and make sure its a valid team - */ - if(!SM_IsValidTeam(iUnBalancedTeam)) - { - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] Balance failed due to invalid team number %i", iUnBalancedTeam); - } - return Plugin_Handled; - } - - /** - Use our core function to change the clients team - */ - SM_MovePlayer(iClient, iUnBalancedTeam); - - return Plugin_Handled; -} - -public Action:Timer_RoundStart(Handle:timer, any:data) -{ - g_bRoundStart = false; - if (OkToBalance() && IsUnbalanced() && !g_bBalanceInProgress) - { - StartABalance(); - } - return Plugin_Handled; -} - -public Action:Timer_ForcedExpired(Handle:timer, any:iClient) -{ - SM_ClearForcedTeam(iClient); - g_aPlayers[iClient][bSwitched] = false; - g_aPlayers[iClient][hForcedTimer] = INVALID_HANDLE; - return Plugin_Handled; -} - -public Action:Timer_WelcomeAdvert(Handle:timer, any:iClient) -{ - if (IsClientConnected(iClient) && IsClientInGame(iClient)) - { - PrintToChat (iClient, "\x01\x04[STB]\x01 %T", "BuddyWelcomeMsg1", LANG_SERVER); - PrintToChat (iClient, "\x01\x04[STB]\x01 %T", "BuddyWelcomeMsg2", LANG_SERVER); - PrintToChat (iClient, "\x01\x04[STB]\x01 %T", "BuddyWelcomeMsg3", LANG_SERVER); - } - return Plugin_Handled; -} - -/* CONSOLE VARIABLE CHANGE EVENT */ - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (convar == stb_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsEnabled = false; - PrintToChatAll("[SM] %T", "Disabled", LANG_SERVER); - LogAction(0, -1, "[SimpleTeamBalancer] Disabled"); - } - else - { - g_bIsEnabled = true; - SetGameCvars(); - PrintToChatAll("[SM] %T", "Enabled", LANG_SERVER); - LogAction(0, -1, "[SimpleTeamBalancer] Enabled"); - } - } - else if (convar == stb_logactivity) - { - if (StringToInt(newValue) == 0) - { - g_bLogActivity = false; - LogAction(0, -1, "[STB] Log Activity DISABLED."); - } - else - { - g_bLogActivity = true; - LogAction(0, -1, "[STB] Log Activity ENABLED."); - } - } - else if (convar == stb_logactivity2) - { - if (StringToInt(newValue) == 0) - { - g_bLogActivity2 = false; - LogAction(0, -1, "[STB] Detailed Log Activity DISABLED."); - } - else - { - g_bLogActivity2 = true; - LogAction(0, -1, "[STB] Detailed Log Activity ENABLED."); - } - } - else if (convar == stb_convarcontrol) - { - if (StringToInt(newValue) == 0) - { - g_bConVarControl = false; - } - else - { - g_bConVarControl = true; - SetGameCvars(); - } - } - else if (convar == stb_deadonly) - { - if (StringToInt(newValue) == 0) - { - g_bDeadOnly = false; - } - else - { - g_bDeadOnly = true; - } - } - else if (convar == stb_priorityenabled) - { - if (StringToInt(newValue) == 0) - { - g_bPriorityPlayers = false; - } - else - { - g_bPriorityPlayers = true; - } - } - else if (convar == stb_buddyenabled) - { - if (StringToInt(newValue) == 0) - { - g_bBuddyEnabled = false; - } - else - { - g_bBuddyEnabled = true; - } - } - else if (convar == stb_buddyrestriction) - { - if (StringToInt(newValue) == 0) - { - g_bBuddyRestriction = false; - } - else - { - g_bBuddyRestriction = true; - } - } - else if (convar == stb_unbalancelimit) - { - g_iUnbalanceLimit = StringToInt(newValue); - SetGameCvars(); - } - else if (convar == stb_balancedelay) - { - g_iBalanceDelay = StringToInt(newValue); - } - else if (convar == stb_roundstartdelay) - { - g_iRoundStartDelay = StringToInt(newValue); - } - else if (convar == stb_livingplayerswitchdelay) - { - g_iLivingPlayerSwitchDelay = StringToInt(newValue); - } - else if (convar == stb_livingplayercheckdelay) - { - g_iLivingPlayerCheckDelay = StringToInt(newValue); - } - else if (convar == stb_uberlevel) - { - g_fUberLevel = StringToFloat(newValue); - } - else if (convar == stb_switchbackforced) - { - g_iSwitchBackForced = StringToInt(newValue); - } - else if (convar == stb_adminflag) - { - SetConVarString(stb_adminflag, newValue); - } - else if (convar == stb_mp_autoteambalance) - { - SetGameCvars(); - } - else if (convar == stb_mp_teams_unbalance_limit) - { - SetGameCvars(); - } -} - -/* MENU CODE */ - -stock Handle:BuildPlayerMenu() -{ - new Handle:menu = CreateMenu(Menu_SelectPlayer); - AddTargetsToMenu(menu, 0, true, false); - SetMenuTitle(menu, "Select A Player:"); - SetMenuExitButton(menu, true); - return menu; -} - -public Menu_SelectPlayer(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - new buddy = GetClientOfUserId(StringToInt(sSelection)); - if (param1 == buddy) { - PrintHintText(param1, "%T", "SelectSelf", LANG_SERVER); - } else if (!IsClientInGame(buddy)) { - PrintHintText(param1, "%T", "BuddyGone", LANG_SERVER); - } else { - decl String:cName[128]; - decl String:bName[128]; - GetClientName(param1, cName, sizeof(cName)); - GetClientName(buddy, bName, sizeof(bName)); - if (!SM_IsBuddyLocked(buddy)) { - SM_AssignBuddy(param1, buddy); - PrintHintText(param1, "%T", "BuddyMsg", LANG_SERVER, bName); - PrintHintText(buddy, "%T", "BuddyMsg", LANG_SERVER, cName); - } else - PrintHintText(param1, "%T", "PlayerLockedBuddyMsg", LANG_SERVER, bName); - } - } else if (action == MenuAction_End) { - CloseHandle(menu); - } -} \ No newline at end of file diff --git a/Simple Team Manager/addons/sourcemod/translations/simpledonatorbenefits.phrases.txt b/Simple Team Manager/addons/sourcemod/translations/simpledonatorbenefits.phrases.txt deleted file mode 100644 index 3826846..0000000 --- a/Simple Team Manager/addons/sourcemod/translations/simpledonatorbenefits.phrases.txt +++ /dev/null @@ -1,62 +0,0 @@ -"Phrases" -{ - "PlayerLevelCmd" - { - "en" "Command must be run at the player level" - "fr" "Cette commande doit être tapée en jeu" - "hu" "Ezt a parancsot jatekosi szinten kell futtatni!" - } - "RestrictedCmd" - { - "en" "You must be a donator or admin to run this command" - "fr" "Vous devez être un donateur ou un admin pour lancer cette commande" - "hu" "A parancs futtatasahoz admin, vagy tamogatoi szint szukseges!" - } - "InValidTeam" - { - "en" "You must be on red or blue to swap teams" - "fr" "Vous devez être RED ou BLU pour changer d'équipe" - "hu" "Jatekban kell lenned, hogy megcsereld a csapatokat!" - } - "PlayerQueue" - { - "en" "You have been queued to swap teams on next death" - "fr" "Vous avez été mis en attente pour changer d'équipe lors de votre prochaine mort" - "hu" "A kovetkezo halalnal csapatcsere lesz" - } - "PlayerSwitched" - { - "en" "Your team has been switched as requested" - "fr" "Vous avez changé d'équipe comme demandé" - "hu" "A keresnek eleget teve a csapatod meg lett csererlve" - } - "SwapTeamMsg" - { - "en" "Type /swapteam or !swapteam to swap your team!" - } - "ReachedCount" - { - "en" "You have reached your health limit. You must die before you can use it again" - } - "AtMaxHealth" - { - "en" "You are already at your maximum health!" - } - "ToMaxHealth" - { - "en" "Instant health bonus applied! You are not at your maximun health!" - } - "HealthBonus" - { - "en" "Instant health bonus applied!" - } - "PublicJoinMessage" - { - "#format" "{1:s}" - "en" "{1} a [donator] as joined the server" - } - "PrivateJoinMessage" - { - "en" "Thanks for donating!" - } -} \ No newline at end of file diff --git a/Simple Team Manager/addons/sourcemod/translations/simplespectate.phrases.txt b/Simple Team Manager/addons/sourcemod/translations/simplespectate.phrases.txt deleted file mode 100644 index 2d1a096..0000000 --- a/Simple Team Manager/addons/sourcemod/translations/simplespectate.phrases.txt +++ /dev/null @@ -1,42 +0,0 @@ -"Phrases" -{ - "Stopped spectating" - { - "#format" "{1:s}" - "en" "Stopped tracking player: {1}" - } - "Yourself" - { - "en" "You can't spectate yourself" - } - "Spectator" - { - "en" "You can't spectate another spectator" - } - "Spectating" - { - "#format" "{1:s}" - "en" "Now spectating {1}. Type !stopspec or /stopspec to stop spectating this player" - } - "Invalid Target" - { - "en" "Invalid target" - } - "Cant Target" - { - "en" "Can't target this player" - } - "Must Have Target" - { - "en" "You must be following/tracking a player to punish" - } - "Target Left" - { - "en" "The player you were following/tracking has left" - } - "Punished" - { - "#format" "{1:s}{2:s}{3:s}" - "en" "{1} was punished with a {2} for {3}" - } -} \ No newline at end of file diff --git a/Simple Team Manager/addons/sourcemod/translations/simpleteambalancer.phrases.txt b/Simple Team Manager/addons/sourcemod/translations/simpleteambalancer.phrases.txt deleted file mode 100644 index 03595fd..0000000 --- a/Simple Team Manager/addons/sourcemod/translations/simpleteambalancer.phrases.txt +++ /dev/null @@ -1,130 +0,0 @@ -"Phrases" -{ - "UnBalanced" - { - "en" "Teams are unbalanced and will be balanced shortly" - "fr" "Les équipes ne sont pas équilibrées et le seront bientôt" - "de" "Die Teams sind ungleich und werden in Kürze ausgeglichen" - "hu" "A csapatok nem kiegyenlitettek! Egyensuly beallitas kovetkezik!" - } - "Enabled" - { - "en" "Simple Team Balancer is ENABLED" - "fr" "Simple Team Balancer est ACTIVE" - "de" "Simple Team Balancer ist AKTIV" - "hu" "Az Egyszeru Csapat Egyensulytarto AKTIV!" - } - "Disabled" - { - "en" "Simple Team Balancer is DISABLED" - "fr" "Simple Team Balancer est DESACTIVE" - "de" "Simple Team Balancer ist INAKTIV" - "hu" "Az Egyszeru Csapat Egyensulytarto INAKTIV!" - } - "PlayerMessage" - { - "#format" "{1:i}" - "en" "You are going to be auto balanced in {1} seconds unless a dead player can be found" - "fr" "Vous passerez dans l'autre équipe dans {1} secondes si aucun joueur mort ne peut être trouvé dans cet intervalle" - "de" "Du wirst in {1} Sekunden zum automatischen Ausgleich herangezogen wenn kein toter Spieler gefunden werden kann" - "hu" "{1} masodpercen belul at leszel helyezve a masik csapatba, hacsak nem lesz addig egy halott jatekos!" - } - "BalanceMessage" - { - "#format" "{1:s}" - "en" "{1} was moved to the other team for game balance" - "fr" "{1} est passé dans l'autre équipe pour équilibrer la partie" - "de" "{1} wurde zum anderen Team verschoben um das Spiel auszugleichen" - "hu" "{1} at lett helyezve az egyensuly megtartasa erdekeben." - } - "PlayerLevelCmd" - { - "en" "Command must be run at the player level" - "fr" "La commande doit être lancée au niveau du joueur" - "de" "Das Kommando muss auf Spieler Ebene ausgeführt werden" - "hu" "Jatekosi szinten kell futtatni ezt a parancsot!" - } - "CmdDisabled" - { - "en" "Command is currently disabled" - "fr" "La commande est actuellement désactivée" - "de" "Das Kommando ist momentan inaktiv" - "hu" "A parancs jelenleg inaktiv" - } - "RestrictedBuddy" - { - "en" "You must be a donator or admin to add a balance buddy" - "fr" "Vous devez être un donateur ou un admin pour choisir un partenaire" - "de" "Du musst ein Spender oder Admin sein um einen Partner wählen zu können" - "hu" "Tamogato vagy admin kell hogy legyel, hogy 'Tarsat' jelolhess meg" - } - "SelectSelf" - { - "en" "You cannot be your own buddy" - "fr" "Vous ne pouvez pas être votre propre partenaire" - "de" "Du kannst nicht dein eigener Partner sein" - "hu" "Nem valaszthatod ki onmagad!" - } - "BuddyGone" - { - "en" "Your selected buddy has disconnected" - "fr" "Le partenaire que vous avez sélectionné s'est déconnecté" - "de" "Dein gewählter Partner hat die Verbindung getrennt" - "hu" "A valasztott 'Tarsad' kilepett" - } - "BuddyMsg" - { - "#format" "{1:s}" - "en" "You and {1} are now buddies" - "fr" "Vous et {1} êtes maintenant partenaires" - "de" "Du und {1} seid jetzt Partner" - "hu" "{1} es Te 'Tarsak' vagytok." - } - "BuddyLockMsgDisabled" - { - "en" "You can now be anyone's buddy" - "fr" "Vous pouvez à présent être le partenaire de n'importe qui" - "de" "Du kannst jetzt jedermanns Partner sein" - "hu" "Barkinek lehetsz a 'Tarsa'." - } - "BuddyLockMsgEnabled" - { - "en" "Buddy selection locked. Only you can change your buddy" - "fr" "Sélection de partenaire bloquée. Vous êtes le seul à pouvoir choisir votre partenaire" - "de" "Wahl des Partners gesperrt. Nur du kannst deinen Partner wechseln" - "hu" "Tars-lista lezarva. Csak Te tudod modositani a Tars-listadat." - } - "PlayerLockedBuddyMsg" - { - "#format" "{1:s}" - "en" "{1} has locked his buddy selection. Try again" - "fr" "{1} a bloqué sa sélection de partenaire. Essayez de nouveau." - "de" "{1} hat seine Wahl des Partners gesperrt. Versuche es erneut" - "hu" "{1} lezarta a Tars-listajat. Probald kesobb!" - } - "BuddyWelcomeMsg1" - { - "en" "Select a balance buddy and stay together during an autobalance!" - "fr" "Choisissez un partenaire et restez ensemble durant l'équilibrage automatique!" - "de" "Wähle einen Partner und bleibt zusammen während eines Ausgleichs" - "hu" "Valasz ki egy 'Tarsat' akivel egyuttmaradhatsz a csapatkiegyenlites alatt!" - } - "BuddyWelcomeMsg2" - { - "en" "/buddy or !buddy to select a balance buddy" - "fr" "/buddy or !buddy pour choisir un partenaire" - "de" "/buddy oder !buddy um einen Partner zu wählen" - "hu" "Hasznald a /buddy vagy !buddy parancsokat a 'Tars' kijelolesehez" - } - "BuddyWelcomeMsg3" - { - "en" "/lockbuddy or !lockbuddy to lock your selection" - "fr" "/lockbuddy or !lockbuddy pour bloquer votre sélection" - "de" "/lockbuddy oder !lockbuddy um deine Auswahl zu sperren" - "hu" "Hasznald a /lockbuddy vagy a !lockbuddy parancsokat a Tars-listad lezarasahoz" - } -} - - - - diff --git a/addons/sourcemod/configs/simple-alltalkmanager_events.cfg b/addons/sourcemod/configs/simple-alltalkmanager_events.cfg deleted file mode 100644 index b739cf0..0000000 --- a/addons/sourcemod/configs/simple-alltalkmanager_events.cfg +++ /dev/null @@ -1,43 +0,0 @@ -"game_events" -{ - "teamplay_round_start" - { - "reason" "Round Start" - "setting" "1" - } - "teamplay_setup_finished" - { - "reason" "Setup Period Ended" - "setting" "0" - } - "teamplay_overtime_begin" - { - "reason" "Overtime Began" - "setting" "1" - } - "teamplay_overtime_end" - { - "reason" "Overtime Ended" - "setting" "1" - } - "teamplay_round_win" - { - "reason" "Round Ended" - "setting" "1" - } - "teamplay_suddendeath_begin" - { - "reason" "Sudden Death Began" - "setting" "1" - } - "teamplay_suddendeath_end" - { - "reason" "Sudden Death Ended" - "setting" "1" - } - "teamplay_round_stalemate" - { - "reason" "Stalemate" - "setting" "1" - } -} \ No newline at end of file diff --git a/addons/sourcemod/configs/simple-chatcolors.cfg b/addons/sourcemod/configs/simple-chatcolors.cfg deleted file mode 100644 index 14b98c6..0000000 --- a/addons/sourcemod/configs/simple-chatcolors.cfg +++ /dev/null @@ -1,15 +0,0 @@ -"admin_colors" -{ - "groupname2" - { - "flag" "z" - "namecolor" "{green}" - "textcolor" "{olive}" - } - "groupname1" - { - "flag" "a" - "namecolor" "{teamcolor}" - "textcolor" "{green}" - } -} \ No newline at end of file diff --git a/addons/sourcemod/plugins/simple-alltalkmanager.smx b/addons/sourcemod/plugins/simple-alltalkmanager.smx deleted file mode 100644 index 6122756af68998fb531abcd0d08698e24cff25af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7028 zcmYMtbvzvK{|E5H#I)(@Znl|CoX&~UHN!Zj9n;;Nn{LxRdD@-Xn3!&d)5fXkIDWpr zc>Ml&e_qe`C*B_=B`sY{3=DTV03bmL03d1x002T5kIVn&2Pyyn=h1Q00Khml06_R? z69xc4>oF-GtNPKRkIDF08;^!RCf8#XKW@M=0RVwVgINFo63{OE0v}C+4*&>)Ay(D^K`RS)3xJ@D zhoz$(*zLdJY4Q0H&KB-=p4N|Wx3Kx|*6BZum8H%9pZur!Was#Q`;KwExe2xog7BpuI{ z*)66j1?43lZn{SqJaj&ttkOa+Coi&C+!~b4u_&^1)9IAS=1?YsFf~gOTvp>~x%PE) zVez+qd?oUTmB?n|J?UZ6B~#pM2Jsp5(JKjW`uTgO%JSU1B1z;wMzrbWYH+#opa<_$=9IhQ}JP@xlM1! zL*S>y%2j2G8#Z+qt64@|8Hz){mFiS%)>hr#Jij6wKhVXo_TYMv4etF#H z;^Pv(lW!64*Uq?9C%^1eb=etw>$Gz%XkjK=N2KAwAYFt|Gs)iDcL{f8h!KZnk-`?5 zHodgg-c}#`sjR(S3SPY@l{WU`3>+r+2vnvFY()Qw?Wx*N1Krsb}abp8su(w!NoP&rA2zAMY`*x z2fTl@x^+*hZMybY3aNIL^xaqkaVj&CTBe=U77TwB_L!9;hV9X$b1*6QBiw$py$ix^ zPZN88%V_4j*Utjq`#KqazwVnyZpPj;Z{*&Xi4Qq>y|(Sl zSmKn2PFu*+Uh))4+CH&%Wl1t@fidDwd?@*iW*;_X&|Q+VRv)o}_GUWoTo^r!0MA9a z&K=uDKLo|@k%&~la&HaCj@3pB2{L%SCVL{-FR^OR@7b4g+H0qiazLlGm5VDGBBCbj z%hs_83%x#J`*ppy?%Kz|rTXYAe6(SYvB=g)-d4M#v3eW#6l|d&s}FA8Mnzl8z;r=XO7DM;#>c?Hsu>nsg)#&6gwO zqjjy_z$WM#Sf@b6n9X_&ddQ9T*7u)C^MGe<+zvFw6Ffk>SVlG0@||wb&`Fs5z2*#O zrcVO+X%Lob&p$%ZUi6VO1o03vzT9Edp7P@o9y2aEp&|qUwvO(Ue9q59Hk}I$Ee&uS zBpiGvSKD4&-DUiWE+}&A5wY6;@NGnS(aovBHz)D}@fCR;{F>ObFaQ+~TJ+kq36n;hx+N&48^u63Xb+nc-ly6!r z3?H4nT(#48~V@UO=R7zF4;FG=8O1D{VGj%%Xqc{cqsz8WB^aJ{ z_H_y*@>k;B*uRudm78GlDb4LTFgV>|A#hSCUEt;6OdjMw;hNGP))=@oG&nd2(scK+ zj_5#*h*?i_Ow+0e6(KBw9awzI%tzIY>I~f-TfSfS^X>{P(F+*+Tr(`Q#jXq;7ID2A z^m!f!4eV{{3e_E&^Rt^*F0}%gI5#TQy@dR*(F67vI`T{CC&vi)6LoK9hSds`Mv(@Q z)|fXB?5vTnYT{=Z^0ncwt<|W2sL-Jwk$Sv|hGzorD_^eK|8Cuk&k=)(YM+&h%wCEC zLpUo*eaLCeyvO@qa%TwF>3<&S`nyB#SA!=%7m58t?Vr`h#X4P(j>qR3qecq!X>L_c z(-85{NbAU}QJ#%ZgbY>BU;Mo9Yv20pIfMox%r-_zx!XGO&Jx}n=GBAIL|;W{!w#w=GyZJ zX}y4VWd{AzNg5677uooaS+W zA^|dX$<+wn33j8gghCt*PN!&hf!d0ztT~S6M3(DY{kh1OaV_tjU-MR!H<{TijHnUp zQ*w^#zY4X%p_=f@(=&V0M0v*TW$Y1B)VHd zwWm`PaQ8eFhV}P0IX~(w$d*sWRHB5vgpZ{*Y#R5klFCMM*#tD?%vI%<8I4uKmdpr- z%_gy+adapI=iHbD!rWO(Kq_-`&%;wA-1$miq0MxYW-0|?XMmFLa=!GFUM!LXf8QpX zMNq_jU0q{UfrO;SekDAz2a%SBhBWJy+5D zEp)D+cNL|x8XJ3wm`*BMPt@!trMz_7E3G(ADlv<}@8q_ovHa7xL$kib(lSDNp|~d} z-<4J_PIN+?+dV{j34soiLLpUSq(}ahWb$3$(#A;d@2Y7;Csb*^-&t0abeLZMl+dzI zVp;Lg5svg8d$$aUZq1wyi}Z%PV|e+~x9on36hglMpgg5 z8>GH#yqB2S#--zjQHK%Tfq(ICk6Gr0N+ZcYILL-6;b|wA-)qjtL6_k5Kvgt8bLNYM z6u_Lk7;)SgF}F}WLBMD}?(uWD`IF=K!Mld-#7KQti%zSz7zjKUQY5ELH{C~S8G?^* z;m_cV!TQ1700>qaEz;E0;<7{vtDa=>2+La%jtg+czB2?|$X`1&Q#Y+*h(>SVv=QwE zF;d_1oj-$nVfs@dU%;W9Ys%^Z4$oF?2H#?JVSMC*9{^T~k4*vJoqn7)6Gr(-$$L>! z92}HM{Gc{4>}?)cWA4)x!BW;Liz41|@-(c(6KkVit7xdrEuj4jghdYg==X28^`fjn zfE1=`CxxxIs-)c8{xH7aV_OFzKBYJ*mcE|XaQ;++RR0%)YYW@6%Oac)pnXjv{GzS* z?81qXsfM+w#HkgrKL0v9b!kB-v>0euXPYAs1kWwP@OfXL+%DxOjNpCl-q^kwpIzGQ zuxPgEJ|JMew6fo3JvA4J4i{VUggyOdoM2p{-D? zQ0(b;0UI4MCkBhJ>~?IwrorD}ulsDaWOUAuN*+_Qa==+1xZfT7%!5UtEFt=q@8GOA zWL3XWJ;S%3Ojo}^gN7$s@V%%}yvB?rkF?bdcA=oLq^=^#=FCz2Wn0|_>#$jq(GQR0 zuoZg^$Xhl27cLF5i(l!=Kv@*V0K>Lp5lE}I2?jpbL z3~Hg6AjT){P{>V${^vfy=++$nCf31mu|8Vgs&uX<>!u%9H+=fCy{ktLUW`g=>qH zX*}ZNT*cdGdX!Sf&F)Fe%m`?edF9PjYOuI0{&;r_Omr{%@bxFxiIbYG1!N8uIZ-bo zQ~e#Le~M|SUZn`3q40-aE_rV_P|L>>eeHMnSQpuXxdCTfv5+d=z1TSGmVfSUdAmyG zJF&8Xt?eOx)W2cKfpn8f^F1H&7dTECn{8at526z4Hkk!7hZ#T3YsgxW_4iq9wTu)( zK2M9Xh(>oOKAtSedP;v44j>l3nmJaBxo-J+mk;AIBm3aK$7SGG+e=!7T|_bA?jPlg zMd9xMyF;a1CYsNkig>ne?r*7M@uHQ=&PkVAd25YHo5AttGk7MKd#u_bhb>!pm)ga# zU7i`wWsFX)uc*-x2CRtq-TL=k{&eND;M9D=&v*GCbMSz>8AUiO)hUR{@iyu`83W!I zJO_f&Dgim6#2saomrwpp;t}{qjMRL|A|jidt-~9gF5H@rY`F^bV*6BIZooxoGf zreKXdyHoins7vOH_A^&7PL*IgBYbFxZsZQ4Tccez-^b`9BUYk72Z_q{Tq?7j{ixV* zf$`8uQCgv~Vjhgy3;Tr>e#<@(ObCqS70k*eKRhon zCgZTVNn2-2BnfdS3ZX<$@H^L1W}F%}3o5>*vd*?l*iN{!HZ5MD+~Pq{aTHuDD>$Xv zAEikmsEK~>-E)hLJ;cOd|AEceA^TKr#b?*lR><$LA4?bWEmi`lm26mA| z21j&%CG`E0zNxfW)$1|b_|9+=Sr;#VN?!Wd`i=X#oG_6nO~vtE(eo;3fi#qD2totA z8nE8Z`MT^y^tp>cIJF5~-plhKH+mROW)vz-vxyY5<6eSs^w&}iw9Q;M$Uq=PV@_*t zss#?0!d}mfm$yO1%Hr)!`0LC5eoV=+1Qwg@o|-NVqT?1xe)pm(TjVkZ%?{1S5mA!x zsOF2yuUB!hRJ-22JL%ohVDBza5&#hX8!gntvOVDP&hCs%80 zkx1dMZxHo}uY-xQafC4anat{$i@%;2De0k3%aceh|GK6=0vExlK~ zW2A9#f&2hA{8m)-{Iu6by$gQ$a*xvNF*jEy$x3Wp8ni#+cl8UGJ?o#>8BATID z&lDK|(a>QExG206!1=

0=W}HiQ6!(Sb8Sg4pHd-X!K^`4+&OWE{7R9@!08#XBa2 z6S(7NcG3`~P&N830_v1Zaocc^#K92kHag_Y@74%)Rzeju4F8@8_2MUv@fuf1d>3K3 zbFhgE6QGOnoarMBgz=$I9QzO{k4gbRCV4(f6zjtEiIF(L=^$A>4o8yuc#>v-lOt|@ z=qa{$H7G(wSZeF3EkQ zXjOcGeWjgB4e!Jl6)eKt*Z~A$ZV}-2a$$VJ2vjWx3-}B+Nbzx)pP70uIl5Ll8G%S&Q@ zCMmlhX6mo~bUjYtu&a+=>u9B$gU6LH9scI%{`8VnZeTpvwo_!XguAeOV^Y>jr8&myi#^j0|N>YQO(84wX^s;x(vCUa!ncAmB-zq zstl%H{baOb#jh>HjYfNtC#l{I1d`o4lGh5O2fnaflyWvE+3v)?WL6AC1Vqvl(}*B5 z*h`F|s_|yEoy;t&Z)W>v(2>A86|J70Rnnz2W@>h{@&K{rYF;4_Z9d#w`sBbDdY$R{ zO15~`z8upMqB)M*tDYM13Q$IVkVggZw-`B5GhfJrqPnPVVxA2@sSQ&QxGD|v^JbO3 zu!>7Zn3kiBL#4{HF(q?VwBYZnX{vwrWEYOtGDBOkLJ7m>xBmRw;pe>=`gAQXNZDDJ z#lOT1EjPybRyF_S)3xw3${a|#^e62GGvSEO_82IJKbuzvlNWWB;3K;-t$rl`g~(I@ z=})O~^&~x66zq*I(vkF5LD;xT7NwcZgA|SqXwS-@>nVIXmm^BBbIy-pl<+WXD>l`n zbZpG9`bYD~btpy-JU~A8?qSN7vM;*1QB1!PfYs z$eQ`8NiyLxJlw9hCN|X{ZeI1#7faEEPyR=ZSi}c?=?sB@HyAdCqYV}>UIYYwA`yeN z`IfMFIxR`tjE4Qil-IzFqJ|V`)vUt>+o`HBoYSUWyn+nSI z2iVexWyi$ZfcLZ9@3|J1_=Xy_7-N|8-o_N_bX=_jB$G%ShbTVjY9n@ z^0C~3H07%zNE)5@xsmYRs3cQC%TAR6?X=R#t$uRzo-r-W-|#eAU0{gLASR=1Y|g~C zH_p5GT|9)HhHj+$3)Cxw*tZz1iuOABiV)}$N(W1bb=n67svJ}F5Wv3|N#HKlls$Pf zR9RuBY&pPZd_?hv^qaleJI)&Y@b1)R{%_)I&Uy}^D{9ttRcuXwhp-j(+16y;Chk$1 z2_SOSim2gqmcohUk3xA*b>3RZQ$GbPbokPf>s zXIfr?TrFQTX_VaD4TCAD9rO9tA+i>dbi}>bt|J0DkQsB}q8OD?QVpOA$8LIUz?+y? zHx?P&zi^NEak#ci!E6M?(tlhjcYr95|~ z0djso1Ih{Ltf>=TaSOZyqm4R_!pV>X%0@&n;rJY3K-t?B&HFEV-RP!^EPkFYG;U?E z_}_)RN!7kb-Yauro3*)zQ|zDI8IpwbV`jwhy$;1Yv%Cl{o5UB+HU=_F`uwzT6PEIrlfuX=)0x(JLidLxNxLO}jf;p=2nPC{a1N e@WUZygbeC5w{WF@V(|1QaEv_m?g1?8hW%e>J(WfP diff --git a/addons/sourcemod/plugins/simple-donatorbenefits.smx b/addons/sourcemod/plugins/simple-donatorbenefits.smx deleted file mode 100644 index 821d61d784607595ca400d273a941a42e40de640..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16600 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 diff --git a/addons/sourcemod/plugins/simple-messagesuppression.smx b/addons/sourcemod/plugins/simple-messagesuppression.smx deleted file mode 100644 index cc20dadd37d8ff23d0a64513cc09650f4bdbf24d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4845 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 Blh*(M diff --git a/addons/sourcemod/plugins/simple-spectate.smx b/addons/sourcemod/plugins/simple-spectate.smx deleted file mode 100644 index c6885b041145a73f664650e729a5dcf8b3b0813f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19129 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%0ACwUfid=y*oPG;MRqmWr)g0 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�XP zM5L)&uZne^XHs;_L+03=Xy3CiU1O76^S{TWu{zY}Jlq((BV?9EL=m4MC%~!W0MzeW zOjQv*a;A7AS@l%h9EbjzQ3d}e&j~R0VCoAN)q_>=)m=>e=ZX9w8jM3&o1RO^+0jJ) z

_|h)w;)ME+|h#gx@oo-|ZEuRI5d) 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 z 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 z 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 KvHt-#rc|>H2mv<$ diff --git a/addons/sourcemod/scripting/include/simple-plugins.inc b/addons/sourcemod/scripting/include/simple-plugins.inc deleted file mode 100644 index 8f21956..0000000 --- a/addons/sourcemod/scripting/include/simple-plugins.inc +++ /dev/null @@ -1,337 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Plugins -Description: - Included file for core plugin in the Simple Plugins project -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -*************************************************************************/ - -#if defined _simpleplugin_included - #endinput -#endif - -#define _simpleplugin_included - -#define CORE_INC_VERSION "1.1.$Rev$" - -#pragma semicolon 1 -#include -#undef REQUIRE_PLUGIN -#include -#define REQUIRE_PLUGIN -#undef REQUIRE_EXTENSIONS -#undef AUTOLOAD_EXTENSIONS -#tryinclude -#tryinclude -#tryinclude -#define AUTOLOAD_EXTENSIONS -#define REQUIRE_EXTENSIONS - -enum e_SupportedMods -{ - GameType_Unknown, - GameType_AOC, - GameType_CSS, - GameType_DOD, - GameType_FF, - GameType_HIDDEN, - GameType_HL2DM, - GameType_INS, - GameType_L4D, - GameType_NEO, - GameType_SGTLS, - GameType_TF, - GameType_ZPS -}; - -enum e_Teams -{ - Unknown, - Spectator, - Team1, - Team2 -}; - -new g_aCurrentTeams[e_Teams]; -new e_SupportedMods:g_CurrentMod; -new String:g_sGameName[e_SupportedMods][32] = { "Unknown", - "Age of Chivalry", - "Counter Strike", - "Day Of Defeat", - "Fortress Forever", - "Hidden: Source", - "Half Life 2: Deathmatch", - "Insurgency", - "Left 4 Dead", - "Neotokyo", - "Stargate TLS", - "Team Fortress 2", - "Zombie Panic: Source" - }; - -public SharedPlugin:_pl_simpleplugin = -{ - name = "simple-plugins", - file = "simple-plugins.smx", -#if defined REQUIRE_PLUGIN - required = 1 -#else - required = 0 -#endif -}; - -#if !defined REQUIRE_PLUGIN -public _pl_simpleplugin_SetNTVOptional() -{ - MarkNativeAsOptional("SM_MovePlayer"); - MarkNativeAsOptional("SM_SetForcedTeam"); - MarkNativeAsOptional("SM_GetForcedTeam"); - MarkNativeAsOptional("SM_ClearForcedTeam"); - MarkNativeAsOptional("SM_GetForcedPlayer"); - MarkNativeAsOptional("SM_AssignBuddy"); - MarkNativeAsOptional("SM_SearchBuddy"); - MarkNativeAsOptional("SM_LockBuddy"); - MarkNativeAsOptional("SM_IsBuddyLocked"); - MarkNativeAsOptional("SM_ClearBuddy"); - MarkNativeAsOptional("SM_IsValidAdmin"); - MarkNativeAsOptional("SM_IsValidTeam"); -} -#endif - -/********************************************************************** - * When a player has to moved - * - * @param plugin Plugin that initiated the move - * @param client The client index of the player that was moved - * @param team The team index the player was moved to - * @noreturn - **********************************************************************/ -forward SM_OnPlayerMoved(Handle:plugin, client, team); - -/********************************************************************** - * Move a player to the supplied team - * - * @param client The client index of the player to be moved - * @param team The team to move the player to - * @noreturn - * @error Invalid client or team index - **********************************************************************/ -native SM_MovePlayer(client, team); - -/********************************************************************** - * Move a player to the supplied team - * - * @param client The client index of the player to set - * @param team The team to move the to set - * @param override Whether or not to override another plugin - * @return True if successful, false if not - * @error Invalid client or team index - **********************************************************************/ -native SM_SetForcedTeam(client, team, bool:override = false); - -/********************************************************************** - * Gets the client's forced team index - * - * @param client The client index of the player to check - * @param plugin Optional: The plugin handle of the plugin - that set the team - * @return The team index of the forced team - Zero if no forced team - * @error Invalid client index - **********************************************************************/ -native SM_GetForcedTeam(client, &Handle:plugin = INVALID_HANDLE); - -/********************************************************************** - * Clears a client's forced team - * - * @param client The client index of the player to check - * @return True if successful, false if not - * @error Invalid client index - **********************************************************************/ -native SM_ClearForcedTeam(client); - -/********************************************************************** - * Gets a forced player on the wrong that is currently on the wrong team - * This will only return a player if the calling plugin assigned the team - * - * @param team The team index the player should be on - * @return The client index of the player - Zero if no player found - * @error Invalid client index - **********************************************************************/ -native SM_GetForcedPlayer(team); - -/********************************************************************** - * Assign a players buddy - * - * @param client The client index of the player to assign - * @param player The player index of the player to assign - * @param override Whether or not to override a player lock - * @return True if successful, false if not - * @error Invalid client or player index - **********************************************************************/ -native bool:SM_AssignBuddy(client, player, bool:override = false); - -/********************************************************************** - * Rturns the client's buddy - * - * @param client The client index of the player to assign - * @return The client index of the player's buddy - Zero if no buddy - * @error Invalid client index - **********************************************************************/ -native SM_GetClientBuddy(client); - -/********************************************************************** - * Set the buddy lock setting for a client - * - * @param client The client index of the player to assign - * @param setting Setting to set, True or False - * @return True if successful, false if not - * @error Invalid client index - **********************************************************************/ -native bool:SM_LockBuddy(client, bool:setting); - -/********************************************************************** - * Returns the buddy lock setting for a client - * - * @param client The client index of the player to assign - * @return True if locked, false if not - * @error Invalid client index - **********************************************************************/ -native bool:SM_IsBuddyLocked(client); - -/********************************************************************** - * Clear a players buddy - * - * @param client The client index of the player to clear - * @param override Whether or not to override a player lock - * @return True if successful, false if not - * @error Invalid client index - **********************************************************************/ -native bool:SM_ClearBuddy(client, bool:override = false); - -/********************************************************************** - * Determine if the player has the supplied flags - * ADMFLAG_ROOT will always return true - * - * @param client The client index of the player to assign - * @param flags The char flag(s) to check against - * @return True if valid, false if not - **********************************************************************/ -native bool:SM_IsValidAdmin(client, const String:flags[]); - - -/********************************************************************** - * Determine if the team is a valid team - * - * @param team The team index to determine if valid for - currently installed/supported mod - * @return True if valid, false if not - **********************************************************************/ -native bool:SM_IsValidTeam(team); - - -public e_SupportedMods:GetCurrentMod() -{ - new String:sGameType[64]; - GetGameFolderName(sGameType, sizeof(sGameType)); - - if (StrEqual(sGameType, "aoc", false)) - { - return GameType_AOC; - } - if (StrEqual(sGameType, "cstrike", false)) - { - return GameType_CSS; - } - if (StrEqual(sGameType, "dod", false)) - { - return GameType_DOD; - } - if (StrEqual(sGameType, "ff", false)) - { - return GameType_FF; - } - if (StrEqual(sGameType, "hidden", false)) - { - return GameType_HIDDEN; - } - if (StrEqual(sGameType, "hl2mp", false)) - { - return GameType_FF; - } - if (StrEqual(sGameType, "insurgency", false) || StrEqual(sGameType, "ins", false)) - { - return GameType_INS; - } - if (StrEqual(sGameType, "l4d", false)) - { - return GameType_L4D; - } - if (StrEqual(sGameType, "nts", false)) - { - return GameType_NEO; - } - if (StrEqual(sGameType, "sgtls", false)) - { - return GameType_SGTLS; - } - if (StrEqual(sGameType, "tf", false)) - { - return GameType_TF; - } - if (StrEqual(sGameType, "zps", false)) - { - return GameType_ZPS; - } - return GameType_Unknown; -} - -public LoadCurrentTeams() -{ - switch (g_CurrentMod) - { - case GameType_INS: - { - g_aCurrentTeams[Unknown] = 0; - g_aCurrentTeams[Spectator] = 3; - g_aCurrentTeams[Team1] = 1; - g_aCurrentTeams[Team2] = 2; - } - case default: - { - g_aCurrentTeams[Unknown] = 0; - g_aCurrentTeams[Spectator] = 1; - g_aCurrentTeams[Team1] = 2; - g_aCurrentTeams[Team2] = 3; - } - } -} diff --git a/addons/sourcemod/scripting/simple-alltalkmanager.sp b/addons/sourcemod/scripting/simple-alltalkmanager.sp deleted file mode 100644 index c848332..0000000 --- a/addons/sourcemod/scripting/simple-alltalkmanager.sp +++ /dev/null @@ -1,515 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple AllTalk Manager -Description: - Allows you to set alltalk at different times -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#pragma semicolon 1 -#include -#include - -#define PLUGIN_VERSION "1.4.$Rev$" - -new Handle:satm_enabled = INVALID_HANDLE; -new Handle:satm_threshold_enabled = INVALID_HANDLE; -new Handle:satm_player_threshold = INVALID_HANDLE; -new Handle:satm_threshold_setting = INVALID_HANDLE; -new Handle:satm_logactivity = INVALID_HANDLE; -new Handle:satm_alltalk = INVALID_HANDLE; - -new Handle:g_aEventNames = INVALID_HANDLE; -new Handle:g_aEventReasons = INVALID_HANDLE; -new Handle:g_aEventSettings = INVALID_HANDLE; - -new bool:g_bLastThreshold = false; -new bool:g_bEnabled = true; -new bool:g_bThresholdEnabled = true; -new bool:g_bIsSetupMap = false; -new bool:g_bIsGameTF2 = false; -new bool:g_bLogActivity = false; - -new g_iLastEventIndex; - -public Plugin:myinfo = -{ - name = "Simple AllTalk Manager", - author = "Simple Plugins", - description = "Allows you to set alltalk at different times", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -} - -/** -Sourcemod callbacks -*/ -public OnPluginStart() -{ - - /** - Need to create all of our console variables. - */ - CreateConVar("satm_version", PLUGIN_VERSION, "Simple AllTalk Manager", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - satm_enabled = CreateConVar("satm_enabled", "1", "Enables/Disables Simple AllTalk Manager", _, true, 0.0, true, 1.0); - satm_threshold_enabled = CreateConVar("satm_threshold_enabled", "1", "Enables/Disables player threshold", _, true, 0.0, true, 1.0); - satm_player_threshold = CreateConVar("satm_player_threshold", "8", "Amount of players for the threshold"); - satm_threshold_setting = CreateConVar("satm_threshold_setting", "1", "Enables/Disables all talk up to player threshold, with the opposite set after the threshold", _, true, 0.0, true, 1.0); - satm_logactivity = CreateConVar("satm_logactivity", "0", "Enables/Disables log activity", _, true, 0.0, true, 1.0); - satm_alltalk = FindConVar("sv_alltalk"); - - /** - Hook console variables - */ - HookConVarChange(satm_enabled, ConVarSettingsChanged); - HookConVarChange(satm_threshold_enabled, ConVarSettingsChanged); - HookConVarChange(satm_player_threshold, ConVarSettingsChanged); - HookConVarChange(satm_logactivity, ConVarSettingsChanged); - - /** - Remove the notify flag from all talk cvar since we do it - */ - SetConVarFlags(satm_alltalk, GetConVarFlags(satm_alltalk)~FCVAR_NOTIFY); - - /** - Get the game type. We only care if it's TF2 - */ - new String:sGameType[64]; - GetGameFolderName(sGameType, sizeof(sGameType)); - if (StrEqual(sGameType, "tf", false)) - { - g_bIsGameTF2 = true; - } - - /** - Create the arrays - */ - g_aEventNames = CreateArray(255, 1); - g_aEventReasons = CreateArray(255, 1); - g_aEventSettings = CreateArray(1, 1); - - /** - Need to register the commands we are going to create and use. - */ - RegAdminCmd("sm_reloadatconfig", Command_Reload, ADMFLAG_GENERIC, "Reloads settings from config file"); - - /** - Create the config file - */ - AutoExecConfig(true); - - /** - Load the events from the config - */ - LoadEventsFromConfig(); -} - -public OnConfigsExecuted() -{ - - /** - Load up the settings - */ - g_bEnabled = GetConVarBool(satm_enabled); - g_bLogActivity = GetConVarBool(satm_logactivity); - g_bThresholdEnabled = GetConVarBool(satm_threshold_enabled); -} - -public OnMapStart() -{ - - /** - Reset the globals - */ - g_iLastEventIndex = 0; - g_bLastThreshold = false; - - /** - Check the map type if we are in TF2 - */ - if (g_bIsGameTF2) - { - g_bIsSetupMap = IsSetupPeriodMap(); - } - - /** - Set AllTalk - */ - if (g_bEnabled) - { - SetConVarBool(satm_alltalk, true); - } -} - -public OnClientDisconnect_Post(client) -{ - if (g_bEnabled) - { - SetAllTalk(-1); - } -} - -public OnClientPostAdminCheck(client) -{ - if (g_bEnabled) - { - SetAllTalk(-1); - } - CreateTimer(2.0, Timer_ShowAllTalkStatus, client, TIMER_FLAG_NO_MAPCHANGE); -} - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (convar == satm_enabled) - { - if (StringToInt(newValue)) - { - g_bEnabled = true; - } - else - { - g_bEnabled = false; - } - } - else if (convar == satm_threshold_enabled) - { - if (StringToInt(newValue)) - { - g_bThresholdEnabled = true; - } - else - { - g_bThresholdEnabled = false; - } - } - else if (convar == satm_logactivity) - { - if (StringToInt(newValue)) - { - g_bLogActivity = true; - } - else - { - g_bLogActivity = false; - } - } - if (g_bEnabled) - { - SetAllTalk(-1); - } -} - -/** -Commands -*/ -public Action:Command_Reload(client, args) -{ - - /** - Clear the array - */ - ClearArray(g_aEventNames); - ClearArray(g_aEventReasons); - ClearArray(g_aEventSettings); - - /** - Load the events from the config - */ - LoadEventsFromConfig(); - - return Plugin_Handled; -} - -/** -Game Event Hooks -*/ -public Hook_All_Events(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (!g_bIsSetupMap) - { - if (StrEqual(name, "teamplay_round_start")) - { - if (FindStringInArray(g_aEventNames, "teamplay_setup_finished") != -1) - { - g_iLastEventIndex = FindStringInArray(g_aEventNames, "teamplay_setup_finished"); - if (g_bEnabled) - { - SetAllTalk(g_iLastEventIndex); - return; - } - } - } - } - g_iLastEventIndex = FindStringInArray(g_aEventNames, name); - if (g_bEnabled) - { - SetAllTalk(g_iLastEventIndex); - } -} - -/** -Timers -*/ -public Action:Timer_ShowAllTalkStatus(Handle:timer, any:client) -{ - if (IsClientConnected(client) && IsClientInGame(client)) - { - new bool:bSetting = GetConVarBool(satm_alltalk); - if (bSetting) - { - PrintToChat(client, "\x01\x04[SM] AllTalk is \x01[on]"); - } - else - { - PrintToChat(client, "\x01\x04[SM] AllTalk is \x01[off]"); - } - } -} - -/** -Stock Functions -*/ -stock LoadEventsFromConfig() -{ - - /** - Make sure the config file is here and load it up - */ - new String:sConfigFile[256]; - BuildPath(Path_SM, sConfigFile, sizeof(sConfigFile), "configs/simple-alltalkmanager_events.cfg"); - if (!FileExists(sConfigFile)) - { - - /** - Config file doesn't exists, stop the plugin - */ - LogError("[SATM] Simple AllTalk Manager is not running! Could not find file %s", sConfigFile); - SetFailState("Could not find file %s", sConfigFile); - } - - /** - Create the arrays and variables - */ - new String:sGameEventName[256]; - new String:sReason[256]; - new iSetting; - - /** - Load config file as a KeyValues file - */ - new Handle:kvGameEvents = CreateKeyValues("game_events"); - FileToKeyValues(kvGameEvents, sConfigFile); - - if (!KvGotoFirstSubKey(kvGameEvents)) - { - return; - } - - /** - Hook the game events and load the settings - */ - do - { - - /** - Get the section name; this should be the event name - */ - KvGetSectionName(kvGameEvents, sGameEventName, sizeof(sGameEventName)); - if (!HookEventEx(sGameEventName, Hook_All_Events, EventHookMode_PostNoCopy)) - { - - /** - Could not hook this event, stop the plugin - */ - SetFailState("Could not hook event %s", sGameEventName); - } - else - { - if (g_bLogActivity) - { - LogMessage("[SATM] Hooked event: %s", sGameEventName); - } - } - - /** - Get the reason string and setting - */ - KvGetString(kvGameEvents, "reason", sReason, sizeof(sReason)); - iSetting = KvGetNum(kvGameEvents, "setting"); - if (g_bLogActivity) - { - LogMessage("[SATM] Event reason string: %s", sReason); - LogMessage("[SATM] Event setting: %i", iSetting); - } - - /** - Push the values to the arrays - */ - PushArrayString(g_aEventNames, sGameEventName); - PushArrayString(g_aEventReasons, sReason); - PushArrayCell(g_aEventSettings, iSetting); - } while (KvGotoNextKey(kvGameEvents)); - - /** - Close our handle - */ - CloseHandle(kvGameEvents); -} - -stock SetAllTalk(index) -{ - new iPlayerThreshold = GetConVarInt(satm_player_threshold); - new bool:bThresholdMet = ((GetClientCount() >= iPlayerThreshold) ? true : false); - new bool:bSetting; - - if (g_bThresholdEnabled) - { - if (bThresholdMet) - { - if (index == -1) - { - if (bThresholdMet != g_bLastThreshold) - { - g_bLastThreshold = true; - bSetting = !GetConVarBool(satm_threshold_setting); - new bool:bLastSetting = GetArrayCell(g_aEventSettings, g_iLastEventIndex); - if (bLastSetting && !bSetting) - { - bSetting = GetArrayCell(g_aEventSettings, g_iLastEventIndex); - } - } - else - { - bSetting = GetArrayCell(g_aEventSettings, g_iLastEventIndex); - } - } - else - { - bSetting = GetArrayCell(g_aEventSettings, index); - } - } - else - { - g_bLastThreshold = false; - bSetting = GetConVarBool(satm_threshold_setting); - } - } - else - { - if (index != -1) - { - bSetting = GetArrayCell(g_aEventSettings, index); - } - } - - if (GetConVarBool(satm_alltalk) != bSetting) - { - - SetConVarBool(satm_alltalk, bSetting); - - new String:sReason[256]; - if (index == -1) - { - Format(sReason, sizeof(sReason), "Player Threshold"); - } - else - { - if (!g_bIsSetupMap) - { - new String:sCurrentEvent[256]; - GetArrayString(g_aEventNames, index, sCurrentEvent, sizeof(sCurrentEvent)); - if (StrEqual(sCurrentEvent, "teamplay_setup_finished")) - { - new iRoundStartIndex = FindStringInArray(g_aEventNames, "teamplay_round_start"); - if (iRoundStartIndex != -1) - { - GetArrayString(g_aEventReasons, iRoundStartIndex, sReason, sizeof(sReason)); - } - else - { - GetArrayString(g_aEventReasons, index, sReason, sizeof(sReason)); - } - } - else - { - GetArrayString(g_aEventReasons, index, sReason, sizeof(sReason)); - } - } - else - { - GetArrayString(g_aEventReasons, index, sReason, sizeof(sReason)); - } - } - - if (bSetting) - { - PrintToChatAll("\x01\x04[SM] AllTalk turned \x01[on] \x04due to:\x01 %s", sReason); - } - else - { - PrintToChatAll("\x01\x04[SM] AllTalk turned \x01[off] \x04due to:\x01 %s", sReason); - } - } -} - -stock bool:IsSetupPeriodMap() -{ - new iEnt = -1; - new String:sMapName[32]; - - GetCurrentMap(sMapName, sizeof(sMapName)); - - if (strncmp(sMapName, "cp_", 3, false) == 0) - { - new iTeam; - while ((iEnt = FindEntityByClassname(iEnt, "team_control_point")) != -1) - { - iTeam = GetEntProp(iEnt, Prop_Send, "m_iTeamNum"); - - /** - If there is a blu CP or a neutral CP, then it's not an attack/defend map - */ - if (iTeam != 2) - { - //this is a push map - return false; - } - } - //this is a attack/defend map - return true; - } - else if (strncmp(sMapName, "ctf_", 3, false) == 0) - { - //this is a ctf map - return false; - } - return false; -} diff --git a/addons/sourcemod/scripting/simple-autoscrambler.sp b/addons/sourcemod/scripting/simple-autoscrambler.sp deleted file mode 100644 index 6c6799e..0000000 --- a/addons/sourcemod/scripting/simple-autoscrambler.sp +++ /dev/null @@ -1,459 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple AutoScrambler -Description: - Automatically scrambles the teams based upon a number of events. -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include - -#define PLUGIN_VERSION "1.1.$Rev$" - -/** -Different scramble modes: - -1 = Full Scramble, dont restart round. -2 = Admins Immune, dont restart round. -3 = Full Scramble, restart round and reset scores. -4 = Admins Immune, restart round and reset scores. - -*/ - -/** -Different top player modes: - -1 = Divide Top 4 players on the two teams. -2 = Protect the Top 2 players on each team. - -*/ - -enum PlayerData -{ - Handle:hForcedTimer, - bool:bProtected; -}; - -/** -Cvars used for admins -*/ -new Handle: sas_admin_immunity_enabled = INVALID_HANDLE, - Handle: sas_admin_flag_scramblenow = INVALID_HANDLE, - Handle: sas_admin_flag_immunity = INVALID_HANDLE; - -/** -Cvars used for autoscramble -*/ -new Handle: sas_autoscramble_enabled = INVALID_HANDLE, - Handle: sas_autoscramble_minplayers = INVALID_HANDLE, - Handle: sas_autoscramble_mode = INVALID_HANDLE, - Handle: sas_autoscramble_winstreak = INVALID_HANDLE, - Handle: sas_autoscramble_steamroll = INVALID_HANDLE, - Handle: sas_autoscramble_frags = INVALID_HANDLE; - -/** -Cvars used for voting -*/ -new Handle: sas_vote_enabled = INVALID_HANDLE, - Handle: sas_vote_upcount = INVALID_HANDLE, - Handle: sas_vote_winpercent = INVALID_HANDLE, - Handle: sas_vote_mode = INVALID_HANDLE, - Handle: sas_vote_minplayers = INVALID_HANDLE; - -/** -Additional cvars -*/ -new Handle: sas_enabled = INVALID_HANDLE, - Handle: sas_timer_scrambledelay = INVALID_HANDLE, - Handle: TFGameModeArena = INVALID_HANDLE; - -/** -Timers -*/ -new Handle: g_hScrambleTimer = INVALID_HANDLE; - -/** - Player arrays - */ -new g_aPlayers[MAXPLAYERS + 1][PlayerData]; - -/** - Cvar variables - */ -new bool: g_bIsEnabled, - bool: g_bIsAutoScrambleEnabled, - bool: g_bIsVoteEnabled, - bool: g_bIsAdminImmunityEnabled; -new Float: g_fTimer_ScrambleDelay, - Float: g_fVote_UpCount, - Float: g_fVote_WinPercent; -new g_iAutoScramble_Minplayers, - g_iAutoScramble_Mode, - g_iAutoScramble_WinStreak, - g_iAutoScramble_SteamRoll, - g_iAutoScramble_Frags, - g_iVote_Mode, - g_iVote_MinPlayers; -new String: g_sScrambleNowFlag[5], - String: g_sAdminImmunityFlag[5]; - -/** -Other globals -*/ -new g_iMaxEntities, - g_iOwnerOffset; - -public Plugin:myinfo = -{ - name = "Simple AutoScrambler", - author = "Simple Plugins", - description = "Automatically scrambles the teams based upon a number of events.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -public OnPluginStart() -{ - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[SAS] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - switch (g_CurrentMod) - { - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_Post); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_Post); - } - } - - /** - Create console variables - */ - CreateConVar("sas_version", PLUGIN_VERSION, "Simple AutoScrambler Version",FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - sas_enabled = CreateConVar("sas_enabled", "1", "Enable/Disable Simple AutoScrambler"); - sas_timer_scrambledelay = CreateConVar("sas_timer_scrambledelay", "5.0", "Delay used after a scramble has been started", _, true, 1.0, true, 30.0); - - /** - Cvars used for admins - */ - sas_admin_immunity_enabled = CreateConVar("sas_admin_immunity_enabled", "1", "Enable/Disable admin immunity for scrambles"); - sas_admin_flag_scramblenow = CreateConVar("sas_admin_flag_scramblenow", "z", "Admin flag to use for scramblenow function/command"); - sas_admin_flag_immunity = CreateConVar("sas_admin_flag_immunity", "z", "Admin flag to use for scramble immunity"); - - /** - Cvars used for autoscramble - */ - sas_autoscramble_enabled = CreateConVar("sas_autoscramble_enabled", "1", "Enable/Disable the autoscramble function"); - sas_autoscramble_minplayers = CreateConVar("sas_autoscramble_minplayers", "16", "Min players needed to start an autoscramble"); - sas_autoscramble_mode = CreateConVar("sas_autoscramble_mode", "1", "Scramble mode used when autoscrambling"); - sas_autoscramble_winstreak = CreateConVar("sas_autoscramble_winstreak", "5", "Max amount of wins in a row a team can achieve before an autoscramble starts"); - sas_autoscramble_steamroll = CreateConVar("sas_autoscramble_steamroll", "120", "Shortest amount of time a team can win by before an autoscramble starts (seconds)"); - sas_autoscramble_frags = CreateConVar("sas_autoscramble_frags", "1", "Min players needed to start a vote and scramble"); - - /** - Cvars used for voting - */ - sas_vote_enabled = CreateConVar("sas_vote_enabled", "1", "Enable/Disable voting for scramble"); - sas_vote_upcount = CreateConVar("sas_vote_upcount", "5", "Amount of people wanting a scramble before a vote starts. If less than 1 it will be considered a percentage. (ie 0.5 = 50% | 1 = 1 Player | 5 = 5 Players)"); - sas_vote_winpercent = CreateConVar("sas_vote_winpercent", "0.6", "Percentage of votes needed to scramble", _, true, 0.0, true, 1.0); - sas_vote_mode = CreateConVar("sas_vote_mode", "1", "Scramble mode used when a vote results in a scramble"); - sas_vote_minplayers = CreateConVar("sas_vote_minplayers", "16", "Min players needed to start a vote and scramble"); - - /** - Hook the console variables if they change - */ - HookConVarChange(sas_enabled, ConVarSettingsChanged); - HookConVarChange(sas_timer_scrambledelay, ConVarSettingsChanged); - HookConVarChange(sas_admin_immunity_enabled, ConVarSettingsChanged); - HookConVarChange(sas_admin_flag_scramblenow, ConVarSettingsChanged); - HookConVarChange(sas_admin_flag_immunity, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_enabled, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_minplayers, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_mode, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_winstreak, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_steamroll, ConVarSettingsChanged); - HookConVarChange(sas_autoscramble_frags, ConVarSettingsChanged); - HookConVarChange(sas_vote_enabled, ConVarSettingsChanged); - HookConVarChange(sas_vote_upcount, ConVarSettingsChanged); - HookConVarChange(sas_vote_winpercent, ConVarSettingsChanged); - HookConVarChange(sas_vote_mode, ConVarSettingsChanged); - HookConVarChange(sas_vote_minplayers, ConVarSettingsChanged); - - /** - Register the command - */ - RegConsoleCmd("sm_scramblenow", Command_ScrambleNow, "sm_scramblenow (mode): Scrambles the teams"); - - /** - Load translations and .cfg file - */ - LoadTranslations ("simpleautoscrambler.phrases"); - AutoExecConfig(true, "plugin.simpleautoscrambler"); - LogAction(0, -1, "[SAS] Simple AutoScrambler is loaded."); -} - -public OnAllPluginsLoaded() -{ - //something -} - -public OnLibraryRemoved(const String:name[]) -{ - //something -} - -public OnConfigsExecuted() -{ - - /** - Load up all the variable defaults - */ - LoadUpVariables(); - - /** - Log our activity - */ - if (g_bIsEnabled) - LogAction(0, -1, "Simple AutoScrambler is ENABLED"); - else - LogAction(0, -1, "Simple AutoScrambler is DISABLED"); -} - -public Action:Command_ScrambleNow(client, args) -{ - - /** - Make sure we are enabled - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the client is authorized to run this command. - */ - if (!SM_IsValidAdmin(client, g_sScrambleNowFlag)) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure it's ok to scramble at this time - */ - if (!OkToScramble) - { - return Plugin_Handled; - } - - /** - Make sure it's ok to scramble at this time - */ - LogAction(0, -1, "[SAS] The scramblenow command was used"); - - /** - Scramble the teams - */ - StartAScramble(); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - -} - -public Action:Timer_ScrambleTeams(Handle:timer, any:mode) -{ - - /** - Make sure it's still ok to scramble - */ - if (!OkToScramble) - { - return Plugin_Handled; - } - - - switch (mode) - { - case - - - - } - - - /** - Reset the handle because the timer is over and the callback is done - */ - g_hScrambleTimer = INVALID_HANDLE; - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - -} - -stock StartAScramble(mode) -{ - - /** - See if we are already started a scramble - */ - if (g_hScrambleTimer == INVALID_HANDLE) - { - - /** - There is a scramble in progress - */ - return; - - } - - /** - Report that a scramble is about to start - */ - PrintCenterTextAll("%T", "Scramble", LANG_SERVER); - - /** - Start a timer and log the action - */ - g_hScrambleTimer = CreateTimer(g_fTimer_ScrambleDelay, Timer_ScrambleTeams, mode, TIMER_FLAG_NO_MAPCHANGE); - LogAction(0, -1, "[SAS] A scamble timer was started"); -} - -stock bool:OkToScramble() -{ - -} - -stock LoadUpVariables() -{ - g_bIsEnabled = GetConVarBool(sas_enabled); - g_bIsAutoScrambleEnabled = GetConVarBool(sas_autoscramble_enabled); - g_bIsVoteEnabled = GetConVarBool(sas_vote_enabled); - g_bIsAdminImmunityEnabled = GetConVarBool(sas_admin_immunity_enabled); - g_iAutoScramble_Minplayers = GetConVarInt(sas_autoscramble_minplayers); - g_iAutoScramble_Mode = GetConVarInt(sas_autoscramble_mode); - g_iAutoScramble_WinStreak = GetConVarInt(sas_autoscramble_winstreak); - g_iAutoScramble_SteamRoll = GetConVarInt(sas_autoscramble_steamroll); - g_iAutoScramble_Frags = GetConVarInt(sas_autoscramble_frags); - g_iVote_Mode = GetConVarInt(sas_vote_mode); - g_iVote_MinPlayers = GetConVarInt(sas_vote_minplayers); - GetConVarString(sas_admin_flag_scramblenow, g_sScrambleNowFlag, sizeof(g_sScrambleNowFlag)); - GetConVarString(sas_admin_flag_immunity, g_sAdminImmunityFlag, sizeof(g_sAdminImmunityFlag)); - g_fTimer_ScrambleDelay = GetConVarFloat(sas_timer_scrambledelay); - g_fVote_UpCount = GetConVarFloat(sas_vote_upcount); - g_fVote_WinPercent = GetConVarFloat(sas_vote_winpercent); - g_iMaxEntities = GetMaxEntities(); - g_iOwnerOffset = FindSendPropInfo("CBaseObject", "m_hBuilder"); -} - -stock TF2_DestroyBuildings(client) -{ - - /** - We have to start a loop to check the owner of all the valid entities - */ - for (new i = MaxClients + 1; i <= g_iMaxEntities; i++) - { - if (!IsValidEntity(i)) - { - - /** - Not valid, continue to next one - */ - continue; - } - - /** - Get the name of the current entity - */ - decl String:sNetClass[32]; - GetEntityNetClass(i, sNetClass, sizeof(sNetClass)); - - /** - See if its something that an engineer would build - */ - if (strcmp(sNetClass, "CObjectSentrygun") == 0 - || strcmp(sNetClass, "CObjectTeleporter") == 0 - || strcmp(sNetClass, "CObjectDispenser") == 0) - { - - /** - It is, so lets check the owner - */ - if (GetEntDataEnt2(i, g_iOwnerOffset) == client) - { - - /** - It's the clients building, so we blow it up. - */ - SetVariantInt(9999); - AcceptEntityInput(i, "RemoveHealth"); - } - } - } -} \ No newline at end of file diff --git a/addons/sourcemod/scripting/simple-chatcolors.sp b/addons/sourcemod/scripting/simple-chatcolors.sp deleted file mode 100644 index 539d057..0000000 --- a/addons/sourcemod/scripting/simple-chatcolors.sp +++ /dev/null @@ -1,496 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Chat Colors -Description: - Changes the colors of players chat based on config file -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#pragma semicolon 1 -#include -#include - -#define PLUGIN_VERSION "0.9.0.$Rev$" - -#define CHAT_SYMBOL '@' -#define TRIGGER_SYMBOL1 '!' -#define TRIGGER_SYMBOL2 '/' -#define CHAT_MAX_MESSAGE_LENGTH 1024 - -new Handle:g_hDebugCvar = INVALID_HANDLE; -new Handle:g_aGroupNames = INVALID_HANDLE; -new Handle:g_aGroupFlag = INVALID_HANDLE; -new Handle:g_aGroupNameColor = INVALID_HANDLE; -new Handle:g_aGroupTextColor = INVALID_HANDLE; - -new bool:g_bDebug = false; - -new g_iArraySize; - -new g_aPlayerColorIndex[MAXPLAYERS + 1] = { -1, ... }; - -public Plugin:myinfo = -{ - name = "Simple Chat Colors", - author = "Simple Plugins", - description = "Changes the colors of players chat based on config file.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -/** -Sourcemod callbacks -*/ -public OnPluginStart() -{ - - /** - Need to create all of our console variables. - */ - CreateConVar("sm_chatcolors_version", PLUGIN_VERSION, "Simple Chat Colors", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - g_hDebugCvar = CreateConVar("sm_chatcolors_debug", "1", "Enable/Disable debugging information"); - - /** - Hook console variables - */ - HookConVarChange(g_hDebugCvar, ConVarSettingsChanged); - - /** - Need to register the commands we are going to use - */ - RegConsoleCmd("say", Command_Say); - RegConsoleCmd("say_team", Command_SayTeam); - RegAdminCmd("sm_reloadcolorsconfig", Command_Reload, ADMFLAG_GENERIC, "Reloads settings from config file"); - - /** - Create the arrays - */ - g_aGroupNames = CreateArray(256, 1); - g_aGroupFlag = CreateArray(15, 1); - g_aGroupNameColor = CreateArray(15, 1); - g_aGroupTextColor = CreateArray(15, 1); - - /** - Load the admins and colors from the config - */ - LoadAdminsAndColorsFromConfig(); - g_iArraySize = GetArraySize(g_aGroupNames); -} - -public OnConfigsExecuted() -{ - g_bDebug = GetConVarBool(g_hDebugCvar); - ReloadConfigFile(); -} - -public OnClientPostAdminCheck(client) -{ - - /** - Check the client to see if they are a admin - */ - CheckAdmin(client); -} - -public OnClientDisconnect(client) -{ - g_aPlayerColorIndex[client] = -1; -} - -/** -Commands -*/ -public Action:Command_Say(client, args) -{ - - /** - Make sure we are enabled. - */ - if (client == 0 || IsChatTrigger()) - { - return Plugin_Continue; - } - - if (g_aPlayerColorIndex[client] != -1) - { - - /** - The client is, so get the chat message and strip it down. - */ - decl String:sArg[CHAT_MAX_MESSAGE_LENGTH], - String:sChatMsg[CHAT_MAX_MESSAGE_LENGTH]; - - new bool:bAlive = IsPlayerAlive(client); - - GetCmdArgString(sArg, sizeof(sArg)); - StripQuotes(sArg); - TrimString(sArg); - new startidx; - if (sArg[strlen(sArg)-1] == '"') - { - sArg[strlen(sArg)-1] = '\0'; - startidx = 1; - } - - /** - Bug out if they are using the admin chat symbol (admin chat). If we are in CSS it may not find all the triggers, so we double check. - */ - if (sArg[startidx] == CHAT_SYMBOL || sArg[startidx] == TRIGGER_SYMBOL1 || sArg[startidx] == TRIGGER_SYMBOL2) - { - return Plugin_Continue; - } - - /** - Log the message for hlstatsx and other things. - */ - new iUserID = GetClientUserId(client); - decl String:sAuthID[64]; - GetClientAuthString(client, sAuthID, sizeof(sAuthID)); - LogToGame("\"%N<%i><%s><>\" say \"%s\"", client, iUserID, sAuthID, sArg); - - /** - Format the message. - */ - FormatMessage(client, 0, bAlive, sChatMsg, sArg, g_aPlayerColorIndex[client]); - - /** - Send the message. - */ - //SayText2(0, client, sChatMsg); - CPrintToChatAll(sChatMsg); - - /** - We are done, bug out, and stop the original chat message. - */ - return Plugin_Stop; - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Command_SayTeam(client, args) -{ - - /** - Make sure we are enabled. - */ - if (client == 0 || IsChatTrigger()) - { - return Plugin_Continue; - } - - /** - Check the client to see if they are a admin - */ - if (g_aPlayerColorIndex[client] != -1) - { - - /** - The client is, so get the chat message and strip it down. - */ - decl String:sArg[CHAT_MAX_MESSAGE_LENGTH], - String:sChatMsg[CHAT_MAX_MESSAGE_LENGTH]; - - new bool:bAlive = IsPlayerAlive(client); - new iCurrentTeam = GetClientTeam(client); - - GetCmdArgString(sArg, sizeof(sArg)); - StripQuotes(sArg); - TrimString(sArg); - new startidx; - if (sArg[strlen(sArg)-1] == '"') - { - sArg[strlen(sArg)-1] = '\0'; - startidx = 1; - } - - /** - Bug out if they are using the admin chat symbol (admin chat). - */ - if (sArg[startidx] == CHAT_SYMBOL || sArg[startidx] == TRIGGER_SYMBOL1 || sArg[startidx] == TRIGGER_SYMBOL2) - { - return Plugin_Continue; - } - - /** - Log the message for hlstatsx and other things. - */ - new iUserID = GetClientUserId(client); - decl String:sAuthID[64]; - GetClientAuthString(client, sAuthID, sizeof(sAuthID)); - LogToGame("\"%N<%i><%s><>\" say_team \"%s\"", client, iUserID, sAuthID, sArg); - - /** - Format the message. - */ - FormatMessage(client, iCurrentTeam, bAlive, sChatMsg, sArg, g_aPlayerColorIndex[client]); - - /** - Send the message to the same team - */ - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == iCurrentTeam) - { - CPrintToChat(client, sChatMsg); - } - } - - /** - We are done, bug out, and stop the original chat message. - */ - return Plugin_Stop; - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Command_Reload(client, args) -{ - ReloadConfigFile(); - return Plugin_Handled; -} - -/** -Stock Functions -*/ -stock LoadAdminsAndColorsFromConfig() -{ - - /** - Make sure the config file is here and load it up - */ - new String:sConfigFile[256]; - BuildPath(Path_SM, sConfigFile, sizeof(sConfigFile), "configs/simple-chatcolors.cfg"); - if (!FileExists(sConfigFile)) - { - - /** - Config file doesn't exists, stop the plugin - */ - LogError("[SCC] Simple Chat Colors is not running! Could not find file %s", sConfigFile); - SetFailState("Could not find file %s", sConfigFile); - } - - /** - Create the arrays and variables - */ - new String:sGroupName[256]; - new String:sGroupFlag[15]; - new String:sGroupNameColor[15]; - new String:sGroupTextColor[15]; - - - /** - Load config file as a KeyValues file - */ - new Handle:kvChatColors = CreateKeyValues("admin_colors"); - FileToKeyValues(kvChatColors, sConfigFile); - - if (!KvGotoFirstSubKey(kvChatColors)) - { - return; - } - - /** - Load up all the groups in the file - */ - do - { - - /** - Get the section name; should be the "group" name - */ - KvGetSectionName(kvChatColors, sGroupName, sizeof(sGroupName)); - - - /** - Get the flags and colors - */ - KvGetString(kvChatColors, "flag", sGroupFlag, sizeof(sGroupFlag)); - KvGetString(kvChatColors, "namecolor", sGroupNameColor, sizeof(sGroupNameColor)); - KvGetString(kvChatColors, "textcolor", sGroupTextColor, sizeof(sGroupTextColor)); - - if (g_bDebug) - { - LogMessage("Group Name/SteamID: %s", sGroupName); - LogMessage("Flag String: %s", sGroupFlag); - LogMessage("Color on name: %s", sGroupNameColor); - LogMessage("Color of text: %s", sGroupTextColor); - } - - /** - Push the values to the arrays - */ - PushArrayString(g_aGroupNames, sGroupName); - PushArrayString(g_aGroupFlag, sGroupFlag); - PushArrayString(g_aGroupNameColor, sGroupNameColor); - PushArrayString(g_aGroupTextColor, sGroupTextColor); - } while (KvGotoNextKey(kvChatColors)); - - /** - Close our handle - */ - CloseHandle(kvChatColors); -} - -stock ReloadConfigFile() -{ - - /** - Clear the array - */ - ClearArray(g_aGroupNames); - ClearArray(g_aGroupFlag); - ClearArray(g_aGroupNameColor); - ClearArray(g_aGroupTextColor); - - /** - Load the admins, groups, and colors from the config - */ - LoadAdminsAndColorsFromConfig(); - g_iArraySize = GetArraySize(g_aGroupNames); - - /** - Recheck all the online players for assigned colors - */ - for (new index = 1; index <= MaxClients; index++) - { - if (IsClientConnected(index) && IsClientInGame(index)) - { - CheckAdmin(index); - } - } -} - -stock CheckAdmin(client) -{ - new String:sFlags[15]; - new String:sClientSteamID[64]; - new iGroupFlags; - new iFlags; - new iIndex = -1; - - /** - Look for a steamid first - */ - GetClientAuthString(client, sClientSteamID, sizeof(sClientSteamID)); - iIndex = FindStringInArray(g_aGroupNames, sClientSteamID); - if (iIndex != -1) - { - g_aPlayerColorIndex[client] = iIndex; - } - - /** - Didn't find one, check flags - */ - else - { - /** - Search for flag in groups - */ - - iFlags = GetUserFlagBits(client); - for (iIndex = 0; iIndex < g_iArraySize; iIndex++) - { - GetArrayString(g_aGroupFlag, iIndex, sFlags, sizeof(sFlags)); - iGroupFlags = ReadFlagString(sFlags); - if (iFlags & iGroupFlags) - { - g_aPlayerColorIndex[client] = iIndex; - break; - } - } - } - - if (g_bDebug) - { - PrintToChatAll("SteamID: %s", sClientSteamID); - PrintToChatAll("Array Index: %i", iIndex); - PrintToChatAll("Flag String: %s", sFlags); - PrintToChatAll("Flag Bits of Client: %i", iFlags); - PrintToChatAll("Flag Bits of Group: %i", iGroupFlags); - } -} - -stock FormatMessage(iClient, iTeam, bool:bAlive, String:sChatMsg[], const Sting:sMessage[], iArrayIndex) -{ - decl String:sDead[10], - String:sTeam[10], - String:sClientName[64]; - - GetClientName(iClient, sClientName, sizeof(sClientName)); - - if (iTeam != 0) - { - Format(sTeam, sizeof(sTeam), "(TEAM) "); - } - else - { - Format(sTeam, sizeof(sTeam), ""); - } - if (bAlive) - { - Format(sDead, sizeof(sDead), ""); - } - else - { - Format(sDead, sizeof(sDead), "*DEAD* "); - } - - new String:sNameColor[15]; - new String:sTextColor[15]; - GetArrayString(g_aGroupNameColor, iArrayIndex, sNameColor, sizeof(sNameColor)); - GetArrayString(g_aGroupTextColor, iArrayIndex, sTextColor, sizeof(sTextColor)); - - Format(sChatMsg, CHAT_MAX_MESSAGE_LENGTH, "{default}%s%s%s%s {default}: %s%s", sDead, sTeam, sNameColor, sClientName, sTextColor, sMessage); -} - -/** -Adjust the settings if a convar was changed -*/ -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (StringToInt(newValue) == 1) - { - g_bDebug = true; - } - else - { - g_bDebug = false; - } -} \ No newline at end of file diff --git a/addons/sourcemod/scripting/simple-donatorbenefits.sp b/addons/sourcemod/scripting/simple-donatorbenefits.sp deleted file mode 100644 index e3f6845..0000000 --- a/addons/sourcemod/scripting/simple-donatorbenefits.sp +++ /dev/null @@ -1,1312 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Donator Benefits -Description: - Provides donator benefits to players -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include -#include - -#define PLUGIN_VERSION "1.1.$Rev$" - -#define CHAT_SYMBOL '@' -#define CHAT_MAX_MESSAGE_LENGTH 1024 - -enum PlayerData -{ - bool:bIsDonator, - bool:bQueue, - bool:bImmune, - iHealthCount, - iNewTeam -}; - -/** - Public convar handles - */ -new Handle:sdb_enabled = INVALID_HANDLE; -new Handle:sdb_donationflag = INVALID_HANDLE; -new Handle:sdb_soundfile = INVALID_HANDLE; -new Handle:sdb_joinsound_enabled = INVALID_HANDLE; -new Handle:sdb_joinpubmsg_enabled = INVALID_HANDLE; -new Handle:sdb_joinprivmsg_enabled = INVALID_HANDLE; -new Handle:sdb_chatcolors_enabled = INVALID_HANDLE; -new Handle:sdb_immunity_enabled = INVALID_HANDLE; -new Handle:sdb_ubercharge_enabled = INVALID_HANDLE; -new Handle:sdb_givehealth_enabled = INVALID_HANDLE; -new Handle:sdb_nofalldmg_enabled = INVALID_HANDLE; -new Handle:sdb_fastheavy_enabled = INVALID_HANDLE; -new Handle:sdb_swapteam_enabled = INVALID_HANDLE; -new Handle:sdb_chatcolor = INVALID_HANDLE; -new Handle:sdb_uberlevel = INVALID_HANDLE; -new Handle:sdb_healthcount = INVALID_HANDLE; -new Handle:sdb_healthbonus = INVALID_HANDLE; -new Handle:sdb_heavymultiplier = INVALID_HANDLE; - -/** -Create global enable/disable bools so we don't have to check the console variable on every call -*/ -new bool:g_bIsEnabled = true; -new bool:g_bIsJoinSoundEnabled = true; -new bool:g_bIsJoinPubMsgEnabled = true; -new bool:g_bIsJoinPrivMsgEnabled = true; -new bool:g_bIsChatColorsEnabled = true; -new bool:g_bIsImmuntyEnabled = true; -new bool:g_bIsUberChargeEnabled = true; -new bool:g_bIsGiveHealthEnabled = true; -new bool:g_bIsNoFallDmgEnabled = true; -new bool:g_bIsFastHeayEnabled = true; -new bool:g_bIsSwapTeamEnabled = true; - -/** - Player arrays - */ -new g_aPlayers[MAXPLAYERS + 1][PlayerData]; - - -/** -Rest of the globals -*/ -new bool:g_bRoundEnd = false; -new String:g_sCharDonatorFlag[5]; -new String:g_sSoundFile[PLATFORM_MAX_PATH]; -new String:g_sChatColor[11]; -new g_iHealthBonus; -new g_iHealthCount; -new g_iClassMaxHealth[TFClassType] = {0, 125, 125, 200, 175, 150, 300, 175, 125, 125}; -new g_fClassMaxSpeed[TFClassType] = {0, 400, 300, 240, 280, 320, 230, 300, 300, 300}; -new Float:g_fHeavyMultiplier = 0.0; -new Float:g_fUberLevel = 0.0; - -public Plugin:myinfo = -{ - name = "Simple Donation Benefits", - author = "Simple Plugins", - description = "Gives donators benefits to players", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -} - -public OnPluginStart() -{ - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[SDB] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_connect", HookPlayerSpawn, EventHookMode_Pre); - HookEvent("player_spawn", HookPlayerSpawn, EventHookMode_Post); - HookEvent("player_death", HookPlayerDeath, EventHookMode_Post); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Post); - switch (g_CurrentMod) - { - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - HookEvent("player_changeclass", HookPlayerClass, EventHookMode_Post); - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_Post); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - - /** - Create console variables - */ - CreateConVar("sdb_version", PLUGIN_VERSION, "Simple Donation Benefits", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - sdb_enabled = CreateConVar("sdb_enabled", "1", "Enable/Disable Simple Donation Benefits"); - sdb_donationflag = CreateConVar("sdb_donationflag", "a", "Flag ALREADY given to donators. Must be in char format"); - - /** - Create the enable/disable donator console variables - */ - sdb_joinsound_enabled = CreateConVar("sdb_joinsound_enabled", "1", "Enable/Disable donator join sound"); - sdb_joinpubmsg_enabled = CreateConVar("sdb_joinpubmsg_enabled", "1", "Enable/Disable public donator join message (replaces: as connected)"); - sdb_joinprivmsg_enabled = CreateConVar("sdb_joinprivmsg_enabled", "1", "Enable/Disable private donator join message (sent only to donator)"); - sdb_chatcolors_enabled = CreateConVar("sdb_chatcolors_enabled", "1", "Enable/Disable donator chat colors"); - sdb_immunity_enabled = CreateConVar("sdb_immunity_enabled", "1", "Enable/Disable donator round end immunity"); - sdb_ubercharge_enabled = CreateConVar("sdb_ubercharge_enabled", "1", "Enable/Disable donator medics starting with ubercharge"); - sdb_givehealth_enabled = CreateConVar("sdb_givehealth_enabled", "1", "Enable/Disable donator instant health bonus"); - sdb_nofalldmg_enabled = CreateConVar("sdb_nofalldmg_enabled", "1", "Enable/Disable no fall damage for donators"); - sdb_fastheavy_enabled = CreateConVar("sdb_fastheavy_enabled", "1", "Enable/Disable donator heavies moving faster while spinning"); - sdb_swapteam_enabled = CreateConVar("sdb_swampteam_enabled", "1", "Enable/Disable donator swap team ability"); - - /** - Create the donator setting console variables - */ - sdb_soundfile = CreateConVar("sdb_soundfile", "custom/donatorjoin.mp3", "The location of sound file"); - sdb_chatcolor = CreateConVar("sdb_chatcolor", "green", "Color to use for donator chat. Valid colors are green and lightgreen"); - sdb_uberlevel = CreateConVar("sdb_uberlevel", "0.5", "Uberlevel to give donator medic at spawn. 1.0 = full uber", _, true, 0.0, true, 1.0); - sdb_healthcount = CreateConVar("sdb_healthcount", "1", "Number of times a donator can use use instant health per life"); - sdb_healthbonus = CreateConVar("sdb_healthbonus", "100", "The amount of health to heal the donator"); - sdb_heavymultiplier = CreateConVar("sdb_heavyspeed", "0.5", "The speed multiplier for the fast heavy. Based on running speed. 1.0 = running speed. (Game Default is 0.20)", _, true, 0.0, true, 1.0); - - /** - Hook dukehacks calls - */ - dhAddClientHook(CHK_TakeDamage, Hacks_TakeDamageHook); - dhAddClientHook(CHK_PreThink, Hacks_PreThinkHook); - - /** - Hook the console variables if they change - */ - HookConVarChange(sdb_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_donationflag, ConVarSettingsChanged); - HookConVarChange(sdb_joinsound_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_joinpubmsg_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_joinprivmsg_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_chatcolors_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_immunity_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_ubercharge_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_givehealth_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_nofalldmg_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_swapteam_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_fastheavy_enabled, ConVarSettingsChanged); - HookConVarChange(sdb_soundfile, ConVarSettingsChanged); - HookConVarChange(sdb_chatcolor, ConVarSettingsChanged); - HookConVarChange(sdb_uberlevel, ConVarSettingsChanged); - HookConVarChange(sdb_healthcount, ConVarSettingsChanged); - HookConVarChange(sdb_healthbonus, ConVarSettingsChanged); - HookConVarChange(sdb_heavymultiplier, ConVarSettingsChanged); - - /** - Register the commands - */ - RegConsoleCmd("sm_swapteams", Command_SwapTeam, "sm_swapteams <[0]instant/[1]queued>: Swaps your team to the other team"); - RegConsoleCmd("sm_ihealth", Command_InstantHealth, "sm_ihealth: Gives you a instant health pack"); - RegAdminCmd("sm_teaser", Command_Teaser, ADMFLAG_GENERIC,"sm_teaser <[0]add/[1]remove>: Gives temporary donator privilages to a player"); - RegConsoleCmd("say", Command_Say); - - RegConsoleCmd("sm_test", Command_TEST); - - /** - Load the translations - */ - LoadTranslations("common.phrases"); - LoadTranslations("simpledonatorbenefits.phrases"); - - /** - Load or create the config file - */ - AutoExecConfig(true, "plugin.simpledonatorbenefits"); - LogAction(0, -1, "[SDB] Simple Donator Benefits is loaded."); -} - -public OnAllPluginsLoaded() -{ - //something -} - -public OnLibraryRemoved(const String:name[]) -{ - //something -} - -public OnConfigsExecuted() -{ - /** - Load up all the variable defaults - */ - LoadUpVariables(); - - /** - If the join sound is enabled, prep the sound files - */ - if (g_bIsJoinSoundEnabled) - PrepSoundFile(); - - /** - Log our activity - */ - if (g_bIsEnabled) - LogAction(0, -1, "Simple Donation Benefits is ENABLED"); - else - LogAction(0, -1, "Simple Donation Benefits is DISABLED"); -} - -public OnClientPostAdminCheck(client) -{ - - /** - Check if the client is a donator - */ - if (SM_IsValidAdmin(client, g_sCharDonatorFlag)) - { - - /** - They are, so we set the player array to true and start a timer for the sound or add - */ - g_aPlayers[client][bIsDonator] = true; - if (g_bIsJoinSoundEnabled || g_bIsJoinPrivMsgEnabled) - { - CreateTimer(10.0, Timer_DonatorJoined, client, TIMER_FLAG_NO_MAPCHANGE); - } - } - else - { - /** - They aren't, so we set the player array to false - */ - g_aPlayers[client][bIsDonator] = false; - } -} - -public OnClientDisconnect_Post(client) -{ - - /** - Clean up the player variables - */ - CleanUpPlayer(client); -} - -public Action:Command_SwapTeam(client, args) -{ - - /** - Make sure we are enabled - */ - if (!g_bIsEnabled || !g_bIsSwapTeamEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the command is not started by the server - */ - if (client == 0) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure the player is a donator - */ - if (!g_aPlayers[client][bIsDonator]) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Lets make sure the client is one a team we can swap. - If he is we set the global array to the opposite team. - */ - new iTeam = GetClientTeam(client); - if (iTeam == g_aCurrentTeams[Team1]) - { - g_aPlayers[client][iNewTeam] = g_aCurrentTeams[Team2]; - } - else if (iTeam == g_aCurrentTeams[Team2]) - { - g_aPlayers[client][iNewTeam] = g_aCurrentTeams[Team1]; - } - else - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "InValidTeam", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check to see if we have command arguments. - */ - if (GetCmdArgs()) - { - - /** - We do, so lets get it and see if the client wants to be switched instantly or queued for death. - */ - decl String:sArg[5]; - GetCmdArg(1, sArg, sizeof(sArg)); - new iWantsQue = StringToInt(sArg); - if (iWantsQue && !g_aPlayers[client][bQueue]) - { - - /** - He wants the que and isn't already in it, set the global array. - */ - g_aPlayers[client][bQueue] = true; - ReplyToCommand(client, "\x01\x04[STM]\x01 %T", "PlayerQueue", LANG_SERVER); - } - else if (!iWantsQue) - { - - /** - He wants to be switched right now, lets call the stock function. - */ - SM_MovePlayer(client, g_aPlayers[client][iNewTeam]); - } - } - else - { - - /** - There are no command arguments so we build and display the swap menu. - */ - new Handle:hPlayerMenu = BuildSwapModeMenu(); - DisplayMenu(hPlayerMenu, client, MENU_TIME_FOREVER); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_InstantHealth(client, args) -{ - - /** - Make sure we are enabled - */ - if (!g_bIsEnabled || !g_bIsGiveHealthEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the command is not started by the server - */ - if (client == 0) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure the player is a donator - */ - if (!g_aPlayers[client][bIsDonator]) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check health count to see if the player has reached the max - */ - if (g_aPlayers[client][iHealthCount] >= g_iHealthCount) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "ReachedCount", LANG_SERVER); - return Plugin_Handled; - } - - /** - Get the class of the player and the max health for that class - */ - new iHealth = GetClientHealth(client); - new TFClassType:PlayerClass = TF2_GetPlayerClass(client); - new iMaxHealth = g_iClassMaxHealth[PlayerClass]; - - /** - Check to see if the player is at the max health of the class - */ - if (iHealth >= iMaxHealth) - { - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "AtMaxHealth", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check the current health - */ - if (iHealth + g_iHealthBonus >= iMaxHealth) - { - - /** - Raise them to max health if the current health + bonus would go above it - */ - SetEntityHealth(client, iMaxHealth); - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "ToMaxHealth", LANG_SERVER); - } - else - { - - /** - Give them the instant health bonus - */ - SetEntityHealth(client, iHealth + g_iHealthBonus); - ReplyToCommand(client, "\x01\x04[SDB]\x01 %T", "HealthBonus", LANG_SERVER); - } - - /** - Increase the count - */ - g_aPlayers[client][iHealthCount] += 1; - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_Teaser(client, args) -{ - - /** - Make sure we are enabled - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Check to see if we have command arguments. - */ - new iCmdArgs = GetCmdArgs(); - if (iCmdArgs == 0) - { - - /** - We don't so display the player menu. - */ - new Handle:hPlayerMenu = BuildPlayerMenu(); - DisplayMenu(hPlayerMenu, client, MENU_TIME_FOREVER); - return Plugin_Handled; - } - - /** - We have some arguments, see if we can find the player - */ - decl String:sPlayer[64]; - GetCmdArg(1, sPlayer, sizeof(sPlayer)); - new iTarget = FindTarget(client, sPlayer, true, true); - if (iTarget == -1 || !IsClientInGame(iTarget)) - { - - /** - We don't know who this is, so display the player menu. - */ - new Handle:hPlayerMenu = BuildPlayerMenu(); - DisplayMenu(hPlayerMenu, client, MENU_TIME_FOREVER); - } - else - { - /** - We found the player, see if we are supposed to turn it on or off. - */ - if (iCmdArgs >= 2) - { - decl String:sOn[3]; - GetCmdArg(2, sOn, sizeof(sOn)); - if (StringToInt(sOn)) - { - - /** - Turn temp benefits on. - */ - g_aPlayers[iTarget][bIsDonator] = true; - } - else - { - - /** - Turn temp benefits on. - */ - g_aPlayers[iTarget][bIsDonator] = false; - } - } - else - { - - /** - We don't know what to do, so just turn it on. - */ - g_aPlayers[iTarget][bIsDonator] = true; - } - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_Say(client, args) -{ - - /** - Make sure we are enabled. - */ - if (client == 0 || IsChatTrigger() || !g_bIsChatColorsEnabled || !g_bIsEnabled) - { - return Plugin_Continue; - } - - /** - Check the client to see if they are a donator. - */ - if (g_aPlayers[client][bIsDonator]) - { - - /** - The client is, so get the chat message and strip it down. - */ - decl String:sArg[CHAT_MAX_MESSAGE_LENGTH], - String:sChatMsg[CHAT_MAX_MESSAGE_LENGTH]; - new bool:bAlive = IsPlayerAlive(client); - GetCmdArgString(sArg, sizeof(sArg)); - StripQuotes(sArg); - TrimString(sArg); - new startidx; - if (sArg[strlen(sArg)-1] == '"') - { - sArg[strlen(sArg)-1] = '\0'; - startidx = 1; - } - - /** - Bug out if they are using the admin chat symbol (admin chat). - */ - if (sArg[startidx] == CHAT_SYMBOL) - { - return Plugin_Continue; - } - - /** - Format the message. - */ - FormatMessage(client, 0, bAlive, sChatMsg, sArg); - - /** - Send the message. - */ - SayText2(0, client, sChatMsg); - - /** - We are done, bug out, and stop the original chat message. - */ - return Plugin_Stop; - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Hacks_TakeDamageHook(client, attacker, inflictor, Float:damage, &Float:multiplier, damagetype) -{ - - /** - Make sure we are enabled and the client is a donator. - */ - if (g_bIsEnabled && g_bIsNoFallDmgEnabled && g_aPlayers[client][bIsDonator]) - { - - /** - Check for fall damage. - */ - if (damagetype & DMG_FALL) - { - - /** - Cancel the fall damage and bug out. - */ - multiplier *= 0.0; - return Plugin_Changed; - } - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Hacks_PreThinkHook(client) -{ - - /** - Make sure we are enabled and the client is a donator. - */ - if (!g_bIsEnabled || !g_bIsFastHeayEnabled || !g_aPlayers[client][bIsDonator]) - { - return Plugin_Continue; - } - - /** - Check the players class. We are looking for the heavy. - */ - new TFClassType:PlayerClass = TF2_GetPlayerClass(client); - if (PlayerClass == TFClass_Heavy) - { - - /** - We have a heavy, lets check the weapon. - */ - decl String:sWeaponCurrent[64]; - GetClientWeapon(client, sWeaponCurrent, sizeof(sWeaponCurrent)); - if (StrEqual(sWeaponCurrent, "tf_weapon_minigun", false)) - { - - /** - We have a minigun, check the heavies current weapon state to see if it's spinning. - */ - new iWeapon = GetPlayerWeaponSlot(client, 0); - new iWeaponState = GetEntProp(iWeapon, Prop_Send, "m_iWeaponState"); - if (iWeaponState > 0) - { - - /** - He is spinning, so lets change the heavies speed. - */ - new Float:fMaxSpeed = FloatMul(g_fHeavyMultiplier, float(g_fClassMaxSpeed[PlayerClass])); - SetEntPropFloat(client, Prop_Send, "m_flMaxspeed", fMaxSpeed); - } - } - } - - /** - We are done, bug out. - */ - // use Plugin_Continue (other options are ignored on PreThink hook) - return Plugin_Continue; -} - -public Action:HookPlayerConnect(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (!g_bIsEnabled || !g_bIsJoinPubMsgEnabled || !dontBroadcast) - { - return Plugin_Continue; - } - - /** - Get our event variables and check the client. - */ - new iUserId = GetEventInt(event,"userid"); - new iClient = GetClientOfUserId(iUserId); - if (iClient != 0) - { - - /** - Get the info on the client and format the message. - */ - decl String:sClientName[255], - String:sAuthID[255], - String:sMsg[1024]; - - GetEventString(event, "name", sClientName, sizeof(sClientName)); - GetClientAuthString(iClient, sAuthID, sizeof(sAuthID)); - Format(sMsg, sizeof(sMsg), "%T", "PublicJoinMessage", LANG_SERVER, sClientName); - - /** - Print the message to the clients and do the normal functions. - */ - for (new i = 1; i <= MaxClients; i++) - { - if(IsClientConnected(i) && IsClientInGame(i)) - { - PrintToChat(i,"\x01\x05%s", sMsg); - PrintToConsole(i,"%s has connected.", sClientName); - } - } - LogToGame("\"%s<%d><%s><>\" entered the game", sClientName, iUserId, sAuthID); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public HookPlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled && g_bIsUberChargeEnabled) - { - - /** - Get the event variables and check the class for medic - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - if (TF2_GetPlayerClass(iClient) == TFClass_Medic) - { - - /** - Start a timer to get the medic the uber boost - */ - CreateTimer(0.25, Timer_PlayerUberDelay, iClient, TIMER_FLAG_NO_MAPCHANGE); - } - } -} - -public HookPlayerClass(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled && g_bIsUberChargeEnabled) - { - - /** - Get the event variables and check the class for medic - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - if (TF2_GetPlayerClass(iClient) == TFClass_Medic) - { - - /** - Start a timer to get the medic the uber boost - */ - CreateTimer(0.25, Timer_PlayerUberDelay, iClient, TIMER_FLAG_NO_MAPCHANGE); - } - } -} - -public HookPlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled || g_bIsSwapTeamEnabled) - { - - /** - Get the event variables - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - new String:sWeapon[256]; - GetEventString(event, "weapon", sWeapon, sizeof(sWeapon)); - - /** - Bug out if world killed him. Means he changed team or something - */ - if (StrEqual(sWeapon, "world", false)) - { - g_aPlayers[iClient][bQueue] = false; - return; - } - - /** - If he is queued up, swap him - */ - if (g_aPlayers[iClient][bQueue]) - { - SM_MovePlayer(iClient, g_aPlayers[iClient][iNewTeam]); - } - } -} - -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled || g_bIsSwapTeamEnabled) - { - - /** - Get the event variables - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - - /** - If he is queued up, clear the status - */ - if (g_aPlayers[iClient][bQueue]) - { - g_aPlayers[iClient][bQueue] = false; - } - } -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set our variables. - */ - g_bRoundEnd = false; - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled && g_bIsImmuntyEnabled) - { - - /** - Get rid of their immunity. - */ - ProcessRoundEndImmunity(false); - } -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set our variables. - */ - g_bRoundEnd = true; - - /** - Make sure we are enabled. - */ - if (g_bIsEnabled && g_bIsImmuntyEnabled) - { - - /** - Give them their immunity. - */ - ProcessRoundEndImmunity(true); - } -} - -public Action:Timer_DonatorJoined(Handle:timer, any:client) -{ - - /** - Make sure sounds are enabled. - */ - if (g_bIsEnabled && g_bIsJoinSoundEnabled) - { - EmitSoundToClient(client, g_sSoundFile); - } - - /** - Make sure private messages are enabled. - */ - if (g_bIsJoinPrivMsgEnabled) - { - - /** - Send messages to the client. - */ - decl String:sMsg[1024]; - Format(sMsg, sizeof(sMsg), "%T", "PrivateJoinMessage", LANG_SERVER); - PrintToChat(client,"\x01\x05%s", sMsg); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Timer_PlayerUberDelay(Handle:timer, any:client) -{ - - /** - Make sure the client is still in game. - */ - if (IsClientInGame(client)) - { - - /** - Make sure the client is still a medic. - */ - if (TF2_GetPlayerClass(client) == TFClass_Medic) - { - - /** - Get the medgun weapon index - */ - new iIndex = GetPlayerWeaponSlot(client, 1); - if (iIndex > 0) - { - - /** - Set the uber level with the bonus. - */ - SetEntPropFloat(iIndex, Prop_Send, "m_flChargeLevel", g_fUberLevel); - } - } - } -} - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (convar == sdb_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsEnabled = false; - } - else - { - g_bIsEnabled = true; - } - } - else if (convar == sdb_donationflag) - { - Format(g_sCharDonatorFlag, sizeof(g_sCharDonatorFlag), "%s", newValue); - } - else if (convar == sdb_soundfile) - { - Format(g_sSoundFile, sizeof(g_sSoundFile), "%s", newValue); - } - else if (convar == sdb_joinsound_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsJoinSoundEnabled = false; - } - else - { - g_bIsJoinSoundEnabled = true; - } - } - else if (convar == sdb_joinpubmsg_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsJoinPubMsgEnabled = false; - } - else - { - g_bIsJoinPubMsgEnabled = true; - } - } - else if (convar == sdb_joinprivmsg_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsJoinPrivMsgEnabled = false; - } - else - { - g_bIsJoinPrivMsgEnabled = true; - } - } - else if (convar == sdb_chatcolors_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsChatColorsEnabled = false; - } - else - { - g_bIsChatColorsEnabled = true; - } - } - else if (convar == sdb_immunity_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsImmuntyEnabled = false; - } - else - { - g_bIsImmuntyEnabled = true; - } - } - else if (convar == sdb_ubercharge_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsUberChargeEnabled = false; - } - else - { - g_bIsUberChargeEnabled = true; - } - } - else if (convar == sdb_givehealth_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsGiveHealthEnabled = false; - } - else - { - g_bIsGiveHealthEnabled = true; - } - } - else if (convar == sdb_nofalldmg_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsNoFallDmgEnabled = false; - } - else - { - g_bIsNoFallDmgEnabled = true; - } - } - else if (convar == sdb_fastheavy_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsFastHeayEnabled = false; - } - else - { - g_bIsFastHeayEnabled = true; - } - } - else if (convar == sdb_swapteam_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsSwapTeamEnabled = false; - } - else - { - g_bIsSwapTeamEnabled = true; - } - } - else if (convar == sdb_chatcolor) - { - Format(g_sChatColor, sizeof(g_sChatColor), "%s", newValue); - } - else if (convar == sdb_uberlevel) - { - g_fUberLevel = StringToFloat(newValue); - } - else if (convar == sdb_healthcount) - { - g_iHealthCount = StringToInt(newValue); - } - else if (convar == sdb_healthbonus) - { - g_iHealthBonus = StringToInt(newValue); - } - else if (convar == sdb_heavymultiplier) - { - g_fHeavyMultiplier = StringToFloat(newValue); - } -} - -stock LoadUpVariables() -{ - g_bIsEnabled = GetConVarBool(sdb_enabled); - g_bIsJoinSoundEnabled = GetConVarBool(sdb_enabled); - g_bIsJoinPubMsgEnabled = GetConVarBool(sdb_enabled); - g_bIsJoinPrivMsgEnabled = GetConVarBool(sdb_enabled); - g_bIsChatColorsEnabled = GetConVarBool(sdb_enabled); - g_bIsImmuntyEnabled = GetConVarBool(sdb_enabled); - g_bIsUberChargeEnabled = GetConVarBool(sdb_enabled); - g_bIsGiveHealthEnabled = GetConVarBool(sdb_enabled); - g_bIsNoFallDmgEnabled = GetConVarBool(sdb_enabled); - g_bIsFastHeayEnabled = GetConVarBool(sdb_enabled); - g_bIsSwapTeamEnabled = GetConVarBool(sdb_enabled); - GetConVarString(sdb_donationflag, g_sCharDonatorFlag, sizeof(g_sCharDonatorFlag)); - GetConVarString(sdb_soundfile, g_sSoundFile, sizeof(g_sSoundFile)); - GetConVarString(sdb_chatcolor, g_sChatColor, sizeof(g_sChatColor)); - g_bRoundEnd = false; - g_iHealthBonus = GetConVarInt(sdb_healthbonus); - g_iHealthCount = GetConVarInt(sdb_healthcount); - g_fHeavyMultiplier = GetConVarFloat(sdb_heavymultiplier); - g_fUberLevel = GetConVarFloat(sdb_uberlevel); -} - -stock PrepSoundFile() -{ - decl String:buffer[PLATFORM_MAX_PATH]; - PrecacheSound(g_sSoundFile, true); - Format(buffer, sizeof(buffer), "sound/%s", g_sSoundFile); - AddFileToDownloadsTable(buffer); -} - -stock CleanUpPlayer(client) -{ - g_aPlayers[client][bIsDonator] = false; - g_aPlayers[client][bQueue] = false; - g_aPlayers[client][bImmune] = false; - g_aPlayers[client][iNewTeam] = 0; - g_aPlayers[client][iHealthCount] = 0; -} - -stock ProcessRoundEndImmunity(bool:give) -{ - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][bIsDonator]) - { - if (give) - { - SetEntProp(i, Prop_Data, "m_takedamage", 0, 1); - g_aPlayers[i][bImmune] = true; - } - else - { - SetEntProp(i, Prop_Data, "m_takedamage", 2, 1); - g_aPlayers[i][bImmune] = false; - } - } - } -} - -stock FormatMessage(iClient, iTeam, bool:bAlive, String:sChatMsg[], const Sting:sMessage[]) -{ - decl String:sDead[10], - String:sTeam[10], - String:sClientName[64]; - GetClientName(iClient, sClientName, sizeof(sClientName)); - if (iTeam != 0) - Format(sTeam, sizeof(sTeam), "(TEAM) "); - else - Format(sTeam, sizeof(sTeam), ""); - if (bAlive) - Format(sDead, sizeof(sDead), ""); - else - Format(sDead, sizeof(sDead), "*DEAD* "); - if (StrContains(g_sChatColor, "light", false) == -1) - Format(sChatMsg, CHAT_MAX_MESSAGE_LENGTH, "\x01%s%s\x03%s \x01: \x05%s", sDead, sTeam, sClientName, sMessage); - else - Format(sChatMsg, CHAT_MAX_MESSAGE_LENGTH, "\x01%s%s\x03%s \x01: \x04%s", sDead, sTeam, sClientName, sMessage); -} - -stock SayText2(target, author, const String:message[]) -{ - new Handle:hBf; - if (target == 0) - hBf = StartMessageAll("SayText2"); - else - hBf = StartMessageOne("SayText2", target); - if (hBf != INVALID_HANDLE) - { - BfWriteByte(hBf, author); - BfWriteByte(hBf, true); - BfWriteString(hBf, message); - EndMessage(); - } -} - -stock ProcessAdmins() -{ - for (new i = 1; i <= MaxClients; i++) - { - if (SM_IsValidAdmin(i, g_sCharDonatorFlag)) - { - g_aPlayers[i][bDonator] = true; - } - else - { - g_aPlayers[i][bDonator] = false; - } - } -} - -stock ProcessLate() -{ - if (g_bIsEnabled) - { - ProcessAdmins(); - PrepSoundFile(); - if (g_bRoundEnd && g_bIsImmuntyEnabled) - { - ProcessRoundEndImmunity(true); - } - if (!g_bIsImmuntyEnabled) - { - ProcessRoundEndImmunity(false); - } - } - else - { - ProcessRoundEndImmunity(false); - } -} - -public Menu_SwapMode(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, 64); - if (StringToInt(sSelection)) - g_aPlayers[param1][bQueue] = false; - else - g_aPlayers[param1][bQueue] = true; - if (!g_aPlayers[param1][bQueue]) - SM_MovePlayer(param1, g_aPlayers[param1][iNewTeam]); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -public Menu_SelectPlayer(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[256]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - new iTarget = GetClientOfUserId(StringToInt(sSelection)); - if (g_aPlayers[iTarget][bIsDonator]) - g_aPlayers[iTarget][bIsDonator] = false; - else - g_aPlayers[iTarget][bIsDonator] = true; - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -stock Handle:BuildSwapModeMenu() -{ - new Handle:menu = CreateMenu(Menu_SwapMode); - SetMenuTitle(menu, "Select When to Swap:"); - AddMenuItem(menu, "0", "Instantly (Kills)"); - AddMenuItem(menu, "1", "Queue on next death"); - SetMenuExitBackButton(menu, false); - return menu; -} - -stock Handle:BuildPlayerMenu() -{ - new Handle:menu = CreateMenu(Menu_SelectPlayer); - AddTargetsToMenu(menu, 0, true, false); - SetMenuTitle(menu, "Select A Player:"); - SetMenuExitBackButton(menu, true); - return menu; -} - -public Action:Command_TEST(client, args) -{ - -} \ No newline at end of file diff --git a/addons/sourcemod/scripting/simple-messagesuppression.sp b/addons/sourcemod/scripting/simple-messagesuppression.sp deleted file mode 100644 index f7725a4..0000000 --- a/addons/sourcemod/scripting/simple-messagesuppression.sp +++ /dev/null @@ -1,227 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Message Suppression -Description: - Blocks Specific Message Outputs -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include -#include - -#define SUPPRESS_VERSION "1.1.$Rev$" - -public Plugin:myinfo = -{ - name = "Simple Message Suppression", - author = "FlyingMongoose, psychonic", - description = "Blocks Specific Message Outputs", - version = SUPPRESS_VERSION, - url = "http://www.simple-plugins.com/" -} - -new Handle:cvarBlockSpectateMessage; -new Handle:cvarBlockDisconnectMessage; -new Handle:cvarBlockConnectMessage; -new Handle:cvarAdminShowMessages; -new iSpecTeam = 1; - - -public OnPluginStart() -{ - CreateConVar("suppress_version", SUPPRESS_VERSION, _, FCVAR_PLUGIN|FCVAR_NOTIFY|FCVAR_REPLICATED|FCVAR_SPONLY|FCVAR_DONTRECORD); - cvarBlockSpectateMessage = CreateConVar("sm_blockspectatemessage", "1", "If enabled it blocks the join team message if an administrator joins spectator", FCVAR_PLUGIN, true, 0.0, true, 1.0); - cvarBlockDisconnectMessage = CreateConVar("sm_blockdisconnectmessage", "1", "Blocks the disconnect message", FCVAR_PLUGIN, true, 0.0, true, 1.0); - cvarBlockConnectMessage = CreateConVar("sm_blockconnectmessage", "1", "If enabled it blocks the player connection message.", FCVAR_PLUGIN, true, 0.0, true, 1.0); - cvarAdminShowMessages = CreateConVar("sm_adminshowmessages", "1", "Shows disconnect/connect/team join messages for admins only (if disconnect message is set to be blocked)", FCVAR_PLUGIN, true, 0.0, true, 1.0); - HookEvent("player_team", ev_PlayerTeam, EventHookMode_Pre); - HookEvent("player_disconnect", ev_PlayerDisconnect, EventHookMode_Pre); - HookEvent("player_connect", ev_PlayerConnect, EventHookMode_Pre); - - new String:game_folder[64]; - GetGameFolderName(game_folder, sizeof(game_folder)) - - if (StrContains(game_folder, "insurgency", false) != -1) - { - iSpecTeam = 3; - } - else - { - new String:game_description[64]; - GetGameDescription(game_description, sizeof(game_description), true); - if (StrContains(game_description, "Insurgency", false) != -1) - { - iSpecTeam = 3; - } - } - - AutoExecConfig(true, "suppressmessage", "sourcemod"); -} - -public Action:ev_PlayerTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (GetConVarBool(cvarBlockSpectateMessage)) - { - if (!dontBroadcast && !GetEventBool(event, "silent")) - { - new iUserId = GetEventInt(event, "userid"); - new iClient = GetClientOfUserId(iUserId); - new iTeam = GetEventInt(event, "team"); - - if (iTeam == iSpecTeam && GetAdminFlag(GetUserAdmin(iClient), Admin_Kick)) - { - new iOldTeam = GetEventInt(event, "oldteam"); - new bool:bDisconnect = GetEventBool(event, "disconnect"); - new bool:bAutoteam = GetEventBool(event, "autoteam"); - decl String:strName[50]; - GetEventString(event, "name", strName, sizeof(strName)); - - if (iClient != 0) - { - if (GetConVarInt(cvarAdminShowMessages) == 1) - { - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i) && GetUserAdmin(i) != INVALID_ADMIN_ID) - { - PrintToChat(i,"%N joined team Spectator.", iClient); - PrintToConsole(i,"%N joined team Spectator.", iClient); - } - } - } - } - - new Handle:hEvent = CreateEvent("player_team"); - SetEventInt(hEvent, "userid", iUserId); - SetEventInt(hEvent, "team", iTeam); - SetEventInt(hEvent, "oldteam", iOldTeam); - SetEventBool(hEvent, "disconnect", bDisconnect); - SetEventBool(hEvent, "autoteam", bAutoteam); - SetEventBool(hEvent, "silent", true); - SetEventString(hEvent, "name", strName); - - FireEvent(hEvent, true); - - return Plugin_Handled; - } - } - } - return Plugin_Continue; -} -public Action:ev_PlayerConnect(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (GetConVarBool(cvarBlockConnectMessage)) - { - if (!dontBroadcast) - { - decl String:strName[50]; - GetEventString(event, "name", strName, sizeof(strName)); - new iIndex = GetEventInt(event, "index"); - new iUserId = GetEventInt(event, "userid"); - new iClient = GetClientOfUserId(iUserId); - decl String:strNetworkId[50]; - GetEventString(event, "networkid", strNetworkId, sizeof(strNetworkId)); - decl String:strAddress[50]; - GetEventString(event, "address", strAddress, sizeof(strAddress)); - - if (iClient != 0) - { - if (GetConVarInt(cvarAdminShowMessages) == 1) - { - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i) && GetUserAdmin(i) != INVALID_ADMIN_ID) - { - PrintToChat(i,"%N has connected.", iClient); - PrintToConsole(i,"%N has connected.", iClient); - } - } - } - } - - new Handle:hEvent = CreateEvent("player_connect"); - SetEventString(hEvent, "name", strName); - SetEventInt(hEvent, "index", iIndex); - SetEventInt(hEvent, "userid", iUserId); - SetEventString(hEvent, "networkid", strNetworkId); - SetEventString(hEvent, "address", strAddress); - - FireEvent(hEvent, true); - - return Plugin_Handled; - } - } - return Plugin_Continue; -} -public Action:ev_PlayerDisconnect(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (GetConVarBool(cvarBlockDisconnectMessage)) - { - if (!dontBroadcast) - { - new iUserId = GetEventInt(event, "userid"); - new iClient = GetClientOfUserId(iUserId); - decl String:strReason[50]; - GetEventString(event, "reason", strReason, sizeof(strReason)); - decl String:strName[50]; - GetEventString(event, "name", strName, sizeof(strName)); - decl String:strNetworkId[50]; - GetEventString(event, "networkid", strNetworkId, sizeof(strNetworkId)); - - if (iClient != 0) - { - if (GetConVarInt(cvarAdminShowMessages) == 1) - { - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i) && GetUserAdmin(i) != INVALID_ADMIN_ID) - { - PrintToChat(i, "%N has left the server.", iClient); - PrintToConsole(i, "Dropped %N from server (Disconnect by user.)", iClient); - } - } - } - } - - new Handle:hEvent = CreateEvent("player_disconnect"); - SetEventInt(hEvent, "userid", iUserId); - SetEventString(hEvent, "reason", strReason); - SetEventString(hEvent, "name", strName); - SetEventString(hEvent, "networkid", strNetworkId); - - FireEvent(hEvent, true); - - return Plugin_Handled; - } - } - - return Plugin_Continue; -} \ No newline at end of file diff --git a/addons/sourcemod/scripting/simple-plugins.sp b/addons/sourcemod/scripting/simple-plugins.sp deleted file mode 100644 index 4462b41..0000000 --- a/addons/sourcemod/scripting/simple-plugins.sp +++ /dev/null @@ -1,785 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Plugins -Description: - Core plugin for Simple Plugins project -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#define CORE_PLUGIN_VERSION "1.1.$Rev$" - -#include - -enum e_PlayerInfo -{ - Handle:hForcedTeamPlugin = INVALID_HANDLE, - iForcedTeam = 0, - iBuddy = 0, - bool:bBuddyLocked = false -}; - -new Handle:g_fwdPlayerMoved; -new g_aPlayers[MAXPLAYERS + 1][e_PlayerInfo]; -new bool:g_bTeamsSwitched = false; - -/** -Setting our plugin information. -*/ -public Plugin:myinfo = -{ - name = "Simple Plugins Core Plugin", - author = "Simple Plugins", - description = "Core plugin for Simple Plugins", - version = CORE_PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -public bool:AskPluginLoad(Handle:myself, bool:late, String:error[], err_max) -{ - - /** - Register natives for other plugins - */ - CreateNative("SM_MovePlayer", Native_SM_MovePlayer); - CreateNative("SM_SetForcedTeam", Native_SM_SetForcedTeam); - CreateNative("SM_GetForcedTeam", Native_SM_GetForcedTeam); - CreateNative("SM_ClearForcedTeam", Native_SM_ClearForcedTeam); - CreateNative("SM_GetForcedPlayer", Native_SM_GetForcedPlayer); - CreateNative("SM_AssignBuddy", Native_SM_AssignBuddy); - CreateNative("SM_GetClientBuddy", Native_SM_GetClientBuddy); - CreateNative("SM_LockBuddy", Native_SM_LockBuddy); - CreateNative("SM_IsBuddyLocked", Native_SM_IsBuddyLocked); - CreateNative("SM_ClearBuddy", Native_SM_ClearBuddy); - CreateNative("SM_IsValidAdmin", Native_SM_IsValidAdmin); - CreateNative("SM_IsValidTeam", Native_SM_IsValidTeam); - RegPluginLibrary("simpleplugins"); - return true; -} - -public OnPluginStart() -{ - - CreateConVar("ssm_core_pl_ver", CORE_PLUGIN_VERSION, "Simple SourceMod Plugins Core Plugin Version", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - CreateConVar("ssm_core_inc_ver", CORE_INC_VERSION, "Simple SourceMod Plugins Core Include Version", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook some events to control forced players and check extensions - */ - decl String:sExtError[256]; - LogAction(0, -1, "[SSM] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Pre); - switch (g_CurrentMod) - { - case GameType_CSS: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - new iExtStatus = GetExtensionFileStatus("game.cstrike.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SSM] Required extension was not found."); - LogAction(0, -1, "[SSM] Plugin FAILED TO LOAD."); - SetFailState("Required extension was not found."); - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SSM] Required extension is loaded with errors."); - LogAction(0, -1, "[SSM] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SSM] Plugin FAILED TO LOAD."); - SetFailState("Required extension is loaded with errors."); - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SSM] Required extension is loaded."); - } - } - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_PostNoCopy); - HookUserMessage(GetUserMessageId("TextMsg"), UserMessageHook_Class, true); - new iExtStatus = GetExtensionFileStatus("game.tf2.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SSM] Required extension was not found."); - LogAction(0, -1, "[SSM] Plugin FAILED TO LOAD."); - SetFailState("Required extension was not found."); - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SSM] Required extension is loaded with errors."); - LogAction(0, -1, "[SSM] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SSM] Plugin FAILED TO LOAD."); - SetFailState("Required extension is loaded with errors."); - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SSM] Required extension is loaded."); - } - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_PostNoCopy); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - - /** - Load common translations - */ - LoadTranslations ("common.phrases"); - - /** - Create the global forward - */ - g_fwdPlayerMoved = CreateGlobalForward("SM_OnPlayerMoved", ET_Event, Param_Cell, Param_Cell, Param_Cell); -} - -public OnClientDisconnect(client) -{ - - /** - Cleanup clients/players buddy list - */ - if (!IsFakeClient(client)) - { - SM_ClearBuddy(client, true); - SM_LockBuddy(client, false); - } - SM_ClearForcedTeam(client); -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - See if the teams have been switched - */ - if (g_bTeamsSwitched) - { - - /** - Switch the teams the players are forced to - */ - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][iForcedTeam] != 0) - { - if (g_aPlayers[i][iForcedTeam] == g_aCurrentTeams[Team1]) - { - g_aPlayers[i][iForcedTeam] = g_aCurrentTeams[Team2]; - } - else - { - g_aPlayers[i][iForcedTeam] = g_aCurrentTeams[Team1]; - } - } - } - } -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - g_bTeamsSwitched = false; -} - -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get our event variables - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - new iTeam = GetEventInt(event, "team"); - - /** - See if the player is on the wrong team - */ - if (g_aPlayers[iClient][iForcedTeam] != 0 && g_aPlayers[iClient][iForcedTeam] != iTeam) - { - - /** - Move the player back to the forced team - */ - CreateTimer(1.0, Timer_ForcePlayerMove, iClient, TIMER_FLAG_NO_MAPCHANGE); - - /** - If the event was going to be broadcasted, we refire it so it is not broadcasted and stop this one - */ - if (!dontBroadcast) - { - new Handle:hEvent = CreateEvent("player_team"); - SetEventInt(hEvent, "userid", GetEventInt(event, "userid")); - SetEventInt(hEvent, "team", GetEventInt(event, "team")); - SetEventInt(hEvent, "oldteam", GetEventInt(event, "oldteam")); - SetEventBool(hEvent, "disconnect", GetEventBool(event, "disconnect")); - - if (g_CurrentMod == GameType_DOD || g_CurrentMod == GameType_L4D || g_CurrentMod == GameType_TF) - { - new String:sClientName[MAX_NAME_LENGTH + 1]; - GetClientName(client, sClientName, sizeof(sClientName)); - SetEventBool(hEvent, "autoteam", GetEventBool(event, "autoteam")); - SetEventBool(hEvent, "silent", true); - SetEventString(hEvent, "name", sClientName); - FireEvent(hEvent, true); - } - else - { - FireEvent(hEvent, true); - } - return Plugin_Handled; - } - } - return Plugin_Continue; -} - -public Action:UserMessageHook_Class(UserMsg:msg_id, Handle:bf, const players[], playersNum, bool:reliable, bool:init) -{ - new String:sMessage[120]; - BfReadString(bf, sMessage, sizeof(sMessage), true); - if (StrContains(sMessage, "#TF_TeamsSwitched", false) != -1) - { - g_bTeamsSwitched = true; - } - return Plugin_Continue; -} - -public Native_SM_MovePlayer(Handle:plugin, numParams) -{ - - /** - Get and check the client and team - */ - new iClient = GetNativeCell(1); - new iTeam = GetNativeCell(2); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (iTeam != g_aCurrentTeams[Spectator] && iTeam != g_aCurrentTeams[Team1] && iTeam != g_aCurrentTeams[Team2]) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid team %d", iTeam); - } - - MovePlayer(iClient, iTeam); - if (!IsClientObserver(iClient)) - { - RespawnPlayer(iClient); - } - - new fResult; - - Call_StartForward(g_fwdPlayerMoved); - Call_PushCell(plugin); - Call_PushCell(iClient); - Call_PushCell(iTeam); - Call_Finish(fResult); - - if (fResult != SP_ERROR_NONE) - { - return ThrowNativeError(fResult, "Forward failed"); - } - - return fResult; -} - -public Native_SM_SetForcedTeam(Handle:plugin, numParams) -{ - - /** - Get and check the client and team - */ - new iClient = GetNativeCell(1); - new iTeam = GetNativeCell(2); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (iTeam != g_aCurrentTeams[Spectator] && iTeam != g_aCurrentTeams[Team1] && iTeam != g_aCurrentTeams[Team2] && iTeam != g_aCurrentTeams[Unknown]) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid team %d", iTeam); - } - - new bool:bOverRide = GetNativeCell(3) ? true : false; - - if (!bOverRide && g_aPlayers[iClient][hForcedTeamPlugin] != INVALID_HANDLE && plugin != g_aPlayers[iClient][hForcedTeamPlugin]) - { - return false; - } - - g_aPlayers[iClient][hForcedTeamPlugin] = plugin; - g_aPlayers[iClient][iForcedTeam] = iTeam; - return true; -} - -public Native_SM_GetForcedTeam(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - - /** - Get and set the plugin if they want it - */ - new Handle:hPlugin = GetNativeCell(2); - if (hPlugin != INVALID_HANDLE) - { - SetNativeCellRef(2, g_aPlayers[iClient][hForcedTeamPlugin]); - } - - /** - Return the forced team, this could be 0 - */ - return g_aPlayers[iClient][iForcedTeam]; -} - -public Native_SM_ClearForcedTeam(Handle:plugin, numParams) -{ - - /** - Get and check the client and team - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - - g_aPlayers[iClient][hForcedTeamPlugin] = INVALID_HANDLE; - g_aPlayers[iClient][iForcedTeam] = 0; - - return true; -} - -public Native_SM_GetForcedPlayer(Handle:plugin, numParams) -{ - - /** - Get and check the team - */ - new iTeam = GetNativeCell(1); - if (iTeam != g_aCurrentTeams[Spectator] && iTeam != g_aCurrentTeams[Team1] && iTeam != g_aCurrentTeams[Team2]) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid team %d", iTeam); - } - - /** - Start a loop to check for a player on the wrong team - Also make sure the plugin that set the forced team is the plugin that asked - */ - new iPlayer = 0; - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientInGame(i) - && GetClientTeam(i) != g_aPlayers[i][iForcedTeam] - && g_aPlayers[i][iForcedTeam] == iTeam - && g_aPlayers[i][hForcedTeamPlugin] == plugin) - { - iPlayer = i; - break; - } - } - - /** - Return the player we found, this could be 0 - */ - return iPlayer; -} - -public Native_SM_AssignBuddy(Handle:plugin, numParams) -{ - - /** - Get and check the client and player - */ - new iClient = GetNativeCell(1); - new iPlayer = GetNativeCell(2); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (iPlayer < 0 || iPlayer > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid player index (%d)", iPlayer); - } - if (!IsClientConnected(iPlayer)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Player %d is not connected", iPlayer); - } - if (!IsClientInGame(iPlayer)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Player %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Bots are not supported"); - } - - /** - See if we can override his setting - */ - new bool:bOverRide = GetNativeCell(3) ? true : false; - if (!bOverRide) - { - - /** - We can't override, so check if they are locked - */ - if (g_aPlayers[iClient][bBuddyLocked] || g_aPlayers[iPlayer][bBuddyLocked]) - { - - /** - We detected at least 1 lock, so we bug out - */ - return false; - } - } - - /** - Ready to set the buddies - */ - g_aPlayers[iClient][iBuddy] = iPlayer; - g_aPlayers[iPlayer][iBuddy] = iClient; - return true; -} - -public Native_SM_GetClientBuddy(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Bots are not supported"); - } - - /** - Return the players buddy, this could be 0 - */ - return g_aPlayers[iClient][iBuddy]; -} - -public Native_SM_LockBuddy(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - new bool:bSetting = GetNativeCell(2) ? true : false; - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Bots are not supported"); - } - - g_aPlayers[iClient][bBuddyLocked] = bSetting; - return true; -} - -public Native_SM_IsBuddyLocked(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_INDEX, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Bots are not supported"); - } - - return g_aPlayers[iClient][bBuddyLocked]; -} - -public Native_SM_ClearBuddy(Handle:plugin, numParams) -{ - - /** - Get and check the client - */ - new iClient = GetNativeCell(1); - if (iClient < 1 || iClient > MaxClients) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Invalid client index (%d)", iClient); - } - if (!IsClientConnected(iClient)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Client (%d) is not connected", iClient); - } - if (!IsClientInGame(iClient)) - { - return ThrowNativeError(SP_ERROR_INDEX, "Client %d is not in the game", iClient); - } - if (IsFakeClient(iClient)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Bots are not supported"); - } - - /** - Get the clients buddy and see if we can override his setting - */ - new bool:bOverRide = GetNativeCell(2) ? true : false; - new iPlayer = g_aPlayers[iClient][iBuddy]; - - /** - There is no buddy, we don't care about anything else so bug out - */ - if (iPlayer == 0) - { - return true; - } - - /** - We determined he had a buddy, check the override setting - */ - if (!bOverRide) - { - - /** - We can't override, so check if they are locked - */ - if (g_aPlayers[iClient][bBuddyLocked] || g_aPlayers[iPlayer][bBuddyLocked]) - { - - /** - We detected at least 1 lock, so we bug out - */ - return false; - } - } - - /** - Ready to clear the buddies - */ - g_aPlayers[iClient][iBuddy] = 0; - g_aPlayers[iPlayer][iBuddy] = 0; - return true; -} - -public Native_SM_IsValidTeam(Handle:plugin, numParams) -{ - - /** - Get the team - */ - new iTeam = GetNativeCell(1); - - /** - Check the team - */ - if (iTeam == g_aCurrentTeams[Spectator] || iTeam == g_aCurrentTeams[Team1] || iTeam == g_aCurrentTeams[Team2]) - { - return true; - } - return false; -} - -public Native_SM_IsValidAdmin(Handle:plugin, numParams) -{ - /** - Get the client and flags - */ - new iClient = GetNativeCell(1); - decl String:sFlags[15]; - GetNativeString(2, sFlags, sizeof(sFlags)); - new ibFlags = ReadFlagString(sFlags); - - /** - Check the flags - */ - if ((GetUserFlagBits(iClient) & ibFlags) == ibFlags) - { - return true; - } - if (GetUserFlagBits(iClient) & ADMFLAG_ROOT) - { - return true; - } - return false; -} - -public Action:Timer_ForcePlayerMove(Handle:timer, any:iClient) -{ - - MovePlayer(iClient, g_aPlayers[iClient][iForcedTeam]); - - if (g_aPlayers[iClient][iForcedTeam] != g_aCurrentTeams[Spectator]) - { - RespawnPlayer(iClient); - } - - PrintToChat(iClient, "\x01\x04----------------------------------"); - PrintToChat(iClient, "\x01\x04You have been forced to this team."); - PrintToChat(iClient, "\x01\x04----------------------------------"); - - return Plugin_Handled; -} - -stock MovePlayer(iClient, iTeam) -{ - - /** - Change the client's team based on the mod - */ - switch (g_CurrentMod) - { - case GameType_CSS: - { - CS_SwitchTeam(iClient, iTeam); - } - default: - { - ChangeClientTeam(iClient, iTeam); - } - } -} - -stock RespawnPlayer(iClient) -{ - - /** - Respawn the client based on the mod - */ - switch (g_CurrentMod) - { - case GameType_CSS: - { - CS_RespawnPlayer(iClient); - } - case GameType_TF: - { - TF2_RespawnPlayer(iClient); - } - case GameType_INS: - { - FakeClientCommand(iClient, "kill"); - } - default: - { - // - } - } -} diff --git a/addons/sourcemod/scripting/simple-roundimmunity.sp b/addons/sourcemod/scripting/simple-roundimmunity.sp deleted file mode 100644 index 5f0bca3..0000000 --- a/addons/sourcemod/scripting/simple-roundimmunity.sp +++ /dev/null @@ -1,947 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Round Immunity -Description: - Gives admins immunity during certain rounds -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or any later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#pragma semicolon 1 -#include -#include -#undef REQUIRE_EXTENSIONS -#undef AUTOLOAD_EXTENSIONS -#include -#include -#define REQUIRE_EXTENSIONS -#define AUTOLOAD_EXTENSIONS - -#define PLUGIN_VERSION "1.1.$Rev$" -#define SPECTATOR 1 -#define TEAM_RED 2 -#define TEAM_BLUE 3 - -#define COLOR_GREEN 0 -#define COLOR_BLACK 1 -#define COLOR_RED 2 -#define COLOR_BLUE 3 -#define COLOR_TEAM 4 -#define COLOR_RAINBOW 5 -#define COLOR_NONE 6 - -#define PLAYERCOND_SLOWED (1<<0) //1 -#define PLAYERCOND_ZOOMED (1<<1) //2 -#define PLAYERCOND_DISGUISING (1<<2) //4 -#define PLAYERCOND_DISGUISED (1<<3) //8 -#define PLAYERCOND_SPYCLOAK (1<<4) //16 -#define PLAYERCOND_UBERED (1<<5) //32 -#define PLAYERCOND_TELEPORTTRAIL (1<<6) //64 -#define PLAYERCOND_TAUNT (1<<7) //128 -// (1<<8) //256 -// (1<<9) //512 -#define PLAYERCOND_TELEPORTFLASH (1<<10) //1024 -#define PLAYERCOND_KRUBER (1<<11) //2048 -// (1<<12) //4096 -// (1<<13) //8192 -#define PLAYERCOND_BONKED (1<<14) //16384 (blame Neph if it doesn't work) -#define PLAYERCOND_BONKEDORDRINKSLOWDOWN (1<<15) //32768 -#define PLAYERCOND_HEALING (1<<16) //65536 -#define PLAYERCOND_BURNING (1<<17) //131072 -#define PLAYERCOND_FULLYCHARGEDBYMEDIC (1<<18) //262144 - -enum e_Cookies -{ - bEnabled, - iColor, - iMode -}; - -enum e_ColorNames -{ - Green, - Black, - Red, - Blue -}; - -enum e_ColorValues -{ - iRed, - iGreen, - iBlue -}; - -enum e_PlayerData -{ - Handle:hGodModeTimer, - Handle:hColorTimer, - bool:bIsAdmin, - bool:bIsImmune, - iCycleColor -}; - -/** - Global convar handles - */ -new Handle:sri_charadminflag = INVALID_HANDLE; -new Handle:sri_enabled = INVALID_HANDLE; -new Handle:sri_cookie_enabled = INVALID_HANDLE; -new Handle:sri_cookie_color = INVALID_HANDLE; -new Handle:sri_cookie_mode = INVALID_HANDLE; - -/** - Player arrays - */ -new g_aPlayers[MAXPLAYERS + 1][e_PlayerData]; -new g_aClientCookies[MAXPLAYERS + 1][e_Cookies]; - -/** - Global bools - */ -new bool:g_bLoadedLate = false; -new bool:g_bIsEnabled = true; -new bool:g_bRoundEnd = false; -new bool:g_bUseDukehacks = false; -new bool:g_bUseClientprefs = false; - -/** - Global strings/integers/floats - */ -new String:g_sCharAdminFlag[32]; -new g_iColors[e_ColorNames][e_ColorValues]; -new g_iClassMaxHealth[TFClassType] = {0, 125, 125, 200, 175, 150, 300, 175, 125, 125}; - -public Plugin:myinfo = -{ - name = "Simple Round Immunity", - author = "Simple Plugins", - description = "Gives admins immunity during certain rounds", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -} - -bool:AskPluginLoad(Handle:myself, bool:late, String:error[], err_max) -{ - g_bLoadedLate = late; - return true; -} - -public OnPluginStart() -{ - - /** - Create console variables - */ - CreateConVar("sri_version", PLUGIN_VERSION, "Simple Round Immunity", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - sri_enabled = CreateConVar("sri_enabled", "1", "Enable/Disable Admin immunity during certain round."); - sri_charadminflag = CreateConVar("sri_charadminflag", "a", "Admin flag to use for immunity (only one). Must be a in char format."); - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook some events and check extensions - */ - decl String:sExtError[256]; - LogAction(0, -1, "[SRI] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_spawn", HookPlayerSpawn, EventHookMode_Post); - HookEvent("player_hurt", HookPlayerHurt, EventHookMode_Pre); - switch (g_CurrentMod) - { - case GameType_CSS: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - new iExtStatus = GetExtensionFileStatus("game.cstrike.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SRI] Required extension was not found."); - LogAction(0, -1, "[SRI] Plugin FAILED TO LOAD."); - SetFailState("Required extension was not found."); - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SRI] Required extension is loaded with errors."); - LogAction(0, -1, "[SRI] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SRI] Plugin FAILED TO LOAD."); - SetFailState("Required extension is loaded with errors."); - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SRI] Required css extension is loaded."); - } - } - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_PostNoCopy); - HookUserMessage(GetUserMessageId("TextMsg"), UserMessageHook_Class, true); - new iExtStatus = GetExtensionFileStatus("game.tf2.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SRI] Required extension was not found."); - LogAction(0, -1, "[SRI] Plugin FAILED TO LOAD."); - SetFailState("Required extension was not found."); - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SRI] Required extension is loaded with errors."); - LogAction(0, -1, "[SRI] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SRI] Plugin FAILED TO LOAD."); - SetFailState("Required extension is loaded with errors."); - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SRI] Required tf2 extension is loaded."); - } - iExtStatus = GetExtensionFileStatus("dukehacks.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SRI] Dukehacks extension was not found."); - LogAction(0, -1, "[SRI] Plugin continued to load, but that feature will not be used."); - g_bUseDukehacks = false; - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SRI] Dukehacks extension is loaded with errors."); - LogAction(0, -1, "[SRI] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SRI] Plugin continued to load, but that feature will not be used."); - g_bUseDukehacks = false; - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SRI] Dukehacks extension is loaded and will be used."); - g_bUseDukehacks = true; - dhAddClientHook(CHK_TakeDamage, Hacks_TakeDamageHook); - } - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_PostNoCopy); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - /** - Now lets check for client prefs extension - */ - new iExtStatus = GetExtensionFileStatus("clientprefs.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SRI] Client Preferences extension was not found."); - LogAction(0, -1, "[SRI] Plugin continued to load, but that feature will not be used."); - g_bUseClientprefs = false; - } - if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SRI] Client Preferences extension is loaded with errors."); - LogAction(0, -1, "[SRI] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SRI] Plugin continued to load, but that feature will not be used."); - g_bUseClientprefs = false; - } - if (iExtStatus == 1) - { - LogAction(0, -1, "[SRI] Client Preferences extension is loaded, checking database."); - if (!SQL_CheckConfig(clientprefs)) - { - LogAction(0, -1, "[SRI] No 'clientprefs' database found. Check your database.cfg file."); - LogAction(0, -1, "[SRI] Plugin continued to load, but Client Preferences will not be used."); - g_bUseClientprefs = false; - } - g_bUseClientprefs = true; - - /** - Deal with client cookies - */ - sri_cookie_enabled = RegClientCookie("bri_client_enabled", "Enable/Disable your immunity during the bonus round.", CookieAccess_Public); - sri_cookie_color = RegClientCookie("bri_client_color", "Color to render when immune.", CookieAccess_Public); - sri_cookie_mode = RegClientCookie("bri_client_mode", "God mode to select", CookieAccess_Public); - SetCookieMenuItem(CookieMenu_TopMenu, sri_cookie_enabled, "Bonus Round Immunity"); - } - - HookConVarChange(sri_enabled, EnabledChanged); - - RegAdminCmd("sm_immunity", Command_Immunity, ADMFLAG_ROOT, "sm_immunity: Gives you immunity"); - - LoadColors(); - - AutoExecConfig(true, "plugin.simpleroundimmunity"); -} - -public OnAllPluginsLoaded() -{ - //something - // need to deal with the unloading of dukehacks, clientprefs, and simpleplugins - // should move hooking the client prefs cookies to a function to make sure they are done post plugin start if ext is loaded late -} - -public OnLibraryRemoved(const String:name[]) -{ - //something - // need to deal with the loading of dukehacks, clientprefs, and simpleplugins -} - -public OnConfigsExecuted() -{ - GetConVarString(sri_charadminflag, g_sCharAdminFlag, sizeof(g_sCharAdminFlag)); - g_bIsEnabled = GetConVarBool(sri_enabled); - g_bRoundEnd = false; -} - -/** - Client events - */ - -public OnClientPostAdminCheck(client) -{ - if (SM_IsValidAdmin(client, g_sCharAdminFlag)) - g_aPlayers[client][bIsAdmin] = true; - else - g_aPlayers[client][bIsAdmin] = false; -} - -public OnClientCookiesCached(client) -{ - decl String:sEnabled[2], String:sColor[4], String:sMode[2]; - GetClientCookie(client, sri_cookie_enabled, sEnabled, sizeof(sEnabled)); - GetClientCookie(client, sri_cookie_color, sColor, sizeof(sColor)); - GetClientCookie(client, sri_cookie_mode, sMode, sizeof(sMode)); - g_aClientCookies[client][bEnabled] = StringToInt(sEnabled); - g_aClientCookies[client][iColor] = StringToInt(sColor); - g_aClientCookies[client][iMode] = StringToInt(sMode); -} - -public OnClientDisconnect(client) -{ - CleanUp(client); -} - -/** - Commands - */ - -public Action:Command_Immunity(client, args) -{ - if (g_aPlayers[client][IsImmune]) - { - DisableImmunity(client); - } - else - { - EnableImmunity(client); - } - return Plugin_Handled; -} - -/** - Event hooks - */ - -public Action:Hacks_TakeDamageHook(client, attacker, inflictor, Float:damage, &Float:multiplier, damagetype) -{ - if (attacker == 0 || attacker >= MaxClients) - { - return Plugin_Continue; - } - if (g_aPlayers[client][IsImmune]) - { - new TFClassType:PlayerClass = TF2_GetPlayerClass(attacker); - if (PlayerClass == TFClass_Spy) - { - multiplier *= 0.0; - return Plugin_Changed; - } - } - return Plugin_Continue; -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - g_bRoundEnd = false; - if (g_bIsEnabled) - { - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][IsImmune]) - { - DisableImmunity(i); - } - } - } -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - g_bRoundEnd = true; - if (g_bIsEnabled) - { - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][bIsAdmin]) - { - EnableImmunity(i); - } - } - } -} - -public HookPlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) -{ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - if (g_bIsEnabled && g_aPlayers[iClient][bIsAdmin] && g_bRoundEnd) - { - EnableImmunity(iClient); - } -} - -public Action:HookPlayerHurt(Handle:event, const String:name[], bool:dontBroadcast) -{ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - if (g_aPlayers[iClient][IsImmune]) - { - SetEntityHealth(iClient, 2000); - return Plugin_Continue; - } - return Plugin_Continue; -} - -/** - Cookie menus - */ - -public CookieMenu_TopMenu(client, CookieMenuAction:action, any:info, String:buffer[], maxlen) -{ - if (action == CookieMenuAction_DisplayOption) - { - //don't think we need to do anything - } - else - { - new Handle:hMenu = CreateMenu(Menu_CookieSettings); - SetMenuTitle(hMenu, "Options (Current Setting)"); - if (g_aClientCookies[client][bEnabled]) - { - AddMenuItem(hMenu, "enable", "Enabled/Disable (Enabled)"); - } - else - { - AddMenuItem(hMenu, "enable", "Enabled/Disable (Disabled)"); - } - if (g_aClientCookies[client][iMode]) - { - AddMenuItem(hMenu, "mode", "Immunity Mode Setting (God Mode)"); - } - else - { - AddMenuItem(hMenu, "mode", "Immunity Mode Setting (Health)"); - } - switch (g_aClientCookies[client][iColor]) - { - case COLOR_GREEN: - { - AddMenuItem(hMenu, "color", "Color (Green)"); - } - case COLOR_BLACK: - { - AddMenuItem(hMenu, "color", "Color (Black)"); - } - case COLOR_RED: - { - AddMenuItem(hMenu, "color", "Color (Red)"); - } - case COLOR_BLUE: - { - AddMenuItem(hMenu, "color", "Color (Blue)"); - } - case COLOR_TEAM: - { - AddMenuItem(hMenu, "color", "Color (Team)"); - } - case COLOR_RAINBOW: - { - AddMenuItem(hMenu, "color", "Color (Rainbow)"); - } - case COLOR_NONE: - { - AddMenuItem(hMenu, "color", "Color (None)"); - } - } - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, client, MENU_TIME_FOREVER); - } -} - -public Menu_CookieSettings(Handle:menu, MenuAction:action, param1, param2) -{ - new client = param1; - if (action == MenuAction_Select) - { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "enable", false)) - { - new Handle:hMenu = CreateMenu(Menu_CookieSettingsEnable); - SetMenuTitle(hMenu, "Enable/Disable Round End Immunity"); - - if (g_aClientCookies[client][bEnabled]) - { - AddMenuItem(hMenu, "enable", "Enable (Set)"); - AddMenuItem(hMenu, "disable", "Disable"); - } - else - { - AddMenuItem(hMenu, "enable", "Enabled"); - AddMenuItem(hMenu, "disable", "Disable (Set)"); - } - - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, client, MENU_TIME_FOREVER); - } - else if (StrEqual(sSelection, "mode", false)) - { - new Handle:hMenu = CreateMenu(Menu_CookieSettingsMode); - SetMenuTitle(hMenu, "Set Immunity Mode"); - - if (g_aClientCookies[client][iMode]) - { - AddMenuItem(hMenu, "god", "God Mode (Set)"); - AddMenuItem(hMenu, "health", "Health"); - } - else - { - AddMenuItem(hMenu, "god", "God Mode"); - AddMenuItem(hMenu, "health", "Health (Set)"); - } - - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, client, MENU_TIME_FOREVER); - } - else - { - new Handle:hMenu = CreateMenu(Menu_CookieSettingsColors); - SetMenuTitle(hMenu, "Select Immunity Color"); - switch (g_aClientCookies[client][iColor]) - { - case COLOR_GREEN: - { - AddMenuItem(hMenu, "Green", "Green (Set)"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_BLACK: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black (Set)"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_RED: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red (Set)"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_BLUE: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue (Set)"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_TEAM: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color (Set)"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_RAINBOW: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow (Set)"); - AddMenuItem(hMenu, "None", "None"); - } - case COLOR_NONE: - { - AddMenuItem(hMenu, "Green", "Green"); - AddMenuItem(hMenu, "Black", "Black"); - AddMenuItem(hMenu, "Red", "Red"); - AddMenuItem(hMenu, "Blue", "Blue"); - AddMenuItem(hMenu, "Team", "Team Color"); - AddMenuItem(hMenu, "Rain", "Rainbow"); - AddMenuItem(hMenu, "None", "None (Set)"); - } - } - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, client, MENU_TIME_FOREVER); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - ShowCookieMenu(client); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -public Menu_CookieSettingsEnable(Handle:menu, MenuAction:action, param1, param2) -{ - new client = param1; - if (action == MenuAction_Select) - { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "enable", false)) - { - SetClientCookie(client, sri_cookie_enabled, "1"); - g_aClientCookies[client][bEnabled] = 1; - PrintToChat(client, "[SM] Bonus Round Immunity is ENABLED"); - } - else - { - SetClientCookie(client, sri_cookie_enabled, "0"); - g_aClientCookies[client][bEnabled] = 0; - PrintToChat(client, "[SM] Bonus Round Immunity is DISABLED"); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - ShowCookieMenu(client); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -public Menu_CookieSettingsColors(Handle:menu, MenuAction:action, param1, param2) -{ - new client = param1; - if (action == MenuAction_Select) - { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "Green", false)) - { - SetClientCookie(client, sri_cookie_color, "0"); - g_aClientCookies[client][iColor] = COLOR_GREEN; - PrintToChat(client, "[SM] Bonus Round Immunity color set to GREEN"); - } - else if (StrEqual(sSelection, "Black", false)) - { - SetClientCookie(client, sri_cookie_color, "1"); - g_aClientCookies[client][iColor] = COLOR_BLACK; - PrintToChat(client, "[SM] Bonus Round Immunity color set to BLACK"); - } - else if (StrEqual(sSelection, "Red", false)) - { - SetClientCookie(client, sri_cookie_color, "2"); - g_aClientCookies[client][iColor] = COLOR_RED; - PrintToChat(client, "[SM] Bonus Round Immunity color set to RED"); - } - else if (StrEqual(sSelection, "Blue", false)) - { - SetClientCookie(client, sri_cookie_color, "3"); - g_aClientCookies[client][iColor] = COLOR_BLUE; - PrintToChat(client, "[SM] Bonus Round Immunity color set to BLUE"); - } - else if (StrEqual(sSelection, "Team", false)) - { - SetClientCookie(client, sri_cookie_color, "4"); - g_aClientCookies[client][iColor] = COLOR_TEAM; - PrintToChat(client, "[SM] Bonus Round Immunity color set to TEAM COLOR"); - } - else if (StrEqual(sSelection, "Rain", false)) - { - SetClientCookie(client, sri_cookie_color, "5"); - g_aClientCookies[client][iColor] = COLOR_RAINBOW; - PrintToChat(client, "[SM] Bonus Round Immunity color set to RAINBOW"); - } - else if (StrEqual(sSelection, "None", false)) - { - SetClientCookie(client, sri_cookie_color, "6"); - g_aClientCookies[client][iColor] = COLOR_NONE; - PrintToChat(client, "[SM] Bonus Round Immunity color set to NONE"); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - ShowCookieMenu(client); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -public Menu_CookieSettingsMode(Handle:menu, MenuAction:action, param1, param2) -{ - new client = param1; - if (action == MenuAction_Select) - { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "god", false)) - { - SetClientCookie(client, sri_cookie_mode, "1"); - g_aClientCookies[client][iMode] = 1; - PrintToChat(client, "[SM] Bonus Round Immunity set to GOD MODE"); - } - else - { - SetClientCookie(client, sri_cookie_mode, "0"); - g_aClientCookies[client][iMode] = 0; - PrintToChat(client, "[SM] Bonus Round Immunity set to HEALTH BONUS"); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - ShowCookieMenu(client); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -/** -Timer functions - */ - -public Action:Timer_ChangeColor(Handle:timer, any:client) -{ - if (g_aPlayers[client][CycleColor]++ == 3) - { - g_aPlayers[client][CycleColor] = 0; - } - SetEntityRenderMode(client, RENDER_TRANSCOLOR); - SetEntityRenderColor(client, g_iColors[g_aPlayers[client][CycleColor]][iRed], g_iColors[g_aPlayers[client][CycleColor]][iGreen], g_iColors[g_aPlayers[client][CycleColor]][iBlue], 255); - return Plugin_Continue; -} - -public Action:Timer_UndoGodMode(Handle:timer, any:client) -{ - if (IsClientInGame(client)) - { - SetEntProp(client, Prop_Data, "m_takedamage", 2, 1); - } - g_aPlayers[iClient][hGodModeTimer] = INVALID_HANDLE; - return Plugin_Handled; -} - -/** -Stock functions . - */ - -stock CleanUp(iClient) -{ - g_aPlayers[iClient][bIsAdmin] = false; - DisableImmunity(iClient); -} - -stock EnableImmunity(iClient) -{ - SetEntityRenderMode(iClient, RENDER_TRANSCOLOR); - switch (g_aClientCookies[iClient][iColor]) - { - case COLOR_TEAM: - { - new iTeam = GetClientTeam(iClient); - SetEntityRenderColor(iClient, g_iColors[e_ColorNames:iTeam][iRed], g_iColors[e_ColorNames:iTeam][iGreen], g_iColors[e_ColorNames:iTeam][iBlue], 255); - } - case COLOR_RAINBOW: - { - if (g_aPlayers[iClient][hColorTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hColorTimer]); - g_aPlayers[iClient][hColorTimer] = INVALID_HANDLE; - } - g_aPlayers[iClient][hColorTimer] = CreateTimer(0.2, Timer_ChangeColor, iClient, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); - } - case COLOR_NONE: - { - //We dont have to set a color - } - default: - { - SetEntityRenderColor(iClient, g_iColors[e_ColorNames:g_aClientCookies[iClient][iColor]][iRed], g_iColors[e_ColorNames:g_aClientCookies[iClient][iColor]][iGreen], g_iColors[e_ColorNames:g_aClientCookies[iClient][iColor]][iBlue], 255); - } - } - SetEntityHealth(iClient, 2000); - SetEntProp(iClient, Prop_Data, "m_takedamage", 0, 1); - g_aPlayers[iClient][hGodModeTimer] = CreateTimer(2.0, Timer_UndoGodMode, iClient); - g_aPlayers[iClient][IsImmune] = true; -} - -stock DisableImmunity(iClient) -{ - if (g_aPlayers[iClient][hGodModeTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hGodModeTimer]); - g_aPlayers[iClient][hGodModeTimer] = INVALID_HANDLE; - } - if (g_aPlayers[iClient][hColorTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hColorTimer]); - g_aPlayers[iClient][hColorTimer] = INVALID_HANDLE; - } - if (IsClientInGame(iClient)) - { - SetEntityRenderMode(iClient, RENDER_TRANSCOLOR); - SetEntityRenderColor(iClient, 255, 255, 255, 255); - new TFClassType:PlayerClass = TF2_GetPlayerClass(iClient); - new iMaxHealth = g_iClassMaxHealth[PlayerClass]; - SetEntityHealth(iClient, iMaxHealth); - } - g_aPlayers[iClient][CycleColor] = 0; - g_aPlayers[iClient][IsImmune] = false; -} - -stock LoadColors() -{ - g_iColors[Green][iRed] = 0; - g_iColors[Green][iGreen] = 255; - g_iColors[Green][iBlue] = 0; - - g_iColors[Black][iRed] = 10; - g_iColors[Black][iGreen] = 10; - g_iColors[Black][iBlue] = 0; - - g_iColors[Red][iRed] = 255; - g_iColors[Red][iGreen] = 0; - g_iColors[Red][iBlue] = 0; - - g_iColors[Blue][iRed] = 0; - g_iColors[Blue][iGreen] = 0; - g_iColors[Blue][iBlue] = 255; -} - -stock TF2_AddCond(client, cond) -{ - new Handle:cvar = FindConVar("sv_cheats"), bool:enabled = GetConVarBool(cvar), flags = GetConVarFlags(cvar); - if(!enabled) - { - SetConVarFlags(cvar, flags^FCVAR_NOTIFY); - SetConVarBool(cvar, true); - } - FakeClientCommand(client, "addcond %i", cond); - if(!enabled) - { - SetConVarBool(cvar, false); - SetConVarFlags(cvar, flags); - } -} - -stock TF2_RemoveCond(client, cond) -{ - new Handle:cvar = FindConVar("sv_cheats"), bool:enabled = GetConVarBool(cvar), flags = GetConVarFlags(cvar); - if(!enabled) - { - SetConVarFlags(cvar, flags^FCVAR_NOTIFY); - SetConVarBool(cvar, true); - } - FakeClientCommand(client, "removecond %i", cond); - if(!enabled) - { - SetConVarBool(cvar, false); - SetConVarFlags(cvar, flags); - } -} - -/** -Enabled hook - */ - -public EnabledChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (StringToInt(newValue) == 0) - { - UnhookEvent("player_spawn", HookPlayerSpawn, EventHookMode_Post); - UnhookEvent("teamplay_round_start", HookRoundStart, EventHookMode_Post); - UnhookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - for (new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][bIsAdmin] && g_aPlayers[i][IsImmune]) - { - DisableImmunity(i); - } - } - g_bIsEnabled = false; - } - else - { - HookEvent("player_spawn", HookPlayerSpawn, EventHookMode_Post); - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_Post); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - g_bIsEnabled = true; - } -} diff --git a/addons/sourcemod/scripting/simple-spectate.sp b/addons/sourcemod/scripting/simple-spectate.sp deleted file mode 100644 index 4108f8f..0000000 --- a/addons/sourcemod/scripting/simple-spectate.sp +++ /dev/null @@ -1,2022 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Spectate -Description: - Spectate a player and follow them through death. -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include -#undef REQUIRE_EXTENSIONS -#undef AUTOLOAD_EXTENSIONS -#tryinclude -#define AUTOLOAD_EXTENSIONS -#define REQUIRE_EXTENSIONS - -#define PLUGIN_VERSION "1.2.1.$Rev$" - -#define SPECMODE_NONE 0 -#define SPECMODE_FIRSTPERSON 4 -#define SPECMODE_3RDPERSON 5 -#define SPECMODE_FREELOOK 6 -#define SPECMODE_CSS_FIRSTPERSON 3 -#define SPECMODE_CSS_3RDPERSON 4 -#define SPECMODE_CSS_FREELOOK 5 - -enum e_CvarHandles -{ - Handle:hHudMode, - Handle:hMenuType, - Handle:hRestrictHud, - Handle:hBan, - Handle:hBanPerm, - Handle:hBeacon, - Handle:hBlind, - Handle:hCheater, - Handle:hDrug, - Handle:hFreeze, - Handle:hFreezeBomb, - Handle:hKick, - Handle:hSlap, - Handle:hSlay, - Handle:hTimeBomb -}; - -enum e_CvarSettings -{ - bool:bHudMode, - bool:bMenuType, - bool:bRestrictHud, - bool:bBan, - bool:bBanPerm, - bool:bBeacon, - bool:bBlind, - bool:bCheater, - bool:bDrug, - bool:bFreeze, - bool:bFreezebomb, - bool:bKick, - bool:bSlap, - bool:bSlay, - bool:bTimeBomb -}; - -enum e_PluginSettings -{ - bool:bUseSteamBans, - bool:bUseSourceBans, - bool:bUseMySQLBans, - bool:bCanHUD, - bool:bUseDukehacks -}; - -enum e_Menus -{ - Handle:hSelectPlayer, - Handle:hBanTime, - Handle:hReason -}; - -enum e_Punishments -{ - Punish_None, - Punish_Ban, - Punish_Beacon, - Punish_Blind, - Punish_Cheater, - Punish_Drug, - Punish_Freeze, - Punish_FreezeBomb, - Punish_Kick, - Punish_Slap, - Punish_Slay, - Punish_TimeBomb -}; - -enum e_PlayerData -{ - bool:bIsDisplayingHud, - bool:bIsFlaggedCheater, - Handle:hHudTimer, - Handle:hTargetTimer, - iTargetIndex, - e_Punishments:TargetPunishment, - iBanTime -}; - -new Handle:sm_spectate_adminflag = INVALID_HANDLE; -new Handle:g_hAdminMenu = INVALID_HANDLE; -new Handle:g_hHud = INVALID_HANDLE; -new Handle:g_aPluginCvar[e_CvarHandles]; -new g_aPluginCvarSettings[e_CvarSettings]; -new g_aPluginSettings[e_PluginSettings]; -new g_aMenus[e_Menus]; -new g_aPlayers[MAXPLAYERS + 1][e_PlayerData]; -new String:g_sAdminFlags[16]; -new String:g_sPunishments[e_Punishments][15] = { "None", "Ban", "Beacon", "Blind", "Cheater", "Drug", "Freeze", "FreezeBomb", "Kick", "Slap", "Slay", "TimeBomb" }; - -public Plugin:myinfo = -{ - name = "Simple Spectate", - author = "Simple Plugins", - description = "Spectate a player and follow them through death.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -/** -Sourcemod callbacks -*/ -public OnPluginStart() -{ - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[SSPEC] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Pre); - - /** - Need to create all of our console variables. - */ - CreateConVar("sm_spectate_version", PLUGIN_VERSION, "Sourcemod Spectate", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - g_aPluginCvar[hHudMode] = CreateConVar("sm_spectate_hudmode", "1", "Hud Mode: 0 = Hud Text | 1 = Panel/Menu (NOTE: The panel/menu will override other menus until canceled)"); - g_aPluginCvar[hMenuType] = CreateConVar("sm_spectate_menutype", "0", "Menu Mode: 0 = Panel | 1 = Menu"); - g_aPluginCvar[hRestrictHud] = CreateConVar("sm_spectate_restricthud", "0", "Restrict the hud to the admin flag provided"); - g_aPluginCvar[hBan] = CreateConVar("sm_spectate_ban", "1", "Enable/Disable ban option"); - g_aPluginCvar[hBanPerm] = CreateConVar("sm_spectate_banperm", "1", "Enable/Disable permanent ban option"); - g_aPluginCvar[hBeacon] = CreateConVar("sm_spectate_beacon", "1", "Enable/Disable beacon option"); - g_aPluginCvar[hBlind] = CreateConVar("sm_spectate_blind", "1", "Enable/Disable blind option"); - g_aPluginCvar[hCheater] = CreateConVar("sm_spectate_cheater", "1", "Enable/Disable cheater option"); - g_aPluginCvar[hDrug] = CreateConVar("sm_spectate_drug", "1", "Enable/Disable drug option"); - g_aPluginCvar[hFreeze] = CreateConVar("sm_spectate_freeze", "1", "Enable/Disable freeze option"); - g_aPluginCvar[hFreezeBomb] = CreateConVar("sm_spectate_freezebomb", "1", "Enable/Disable freezebomb option"); - g_aPluginCvar[hKick] = CreateConVar("sm_spectate_kick", "1", "Enable/Disable kick option"); - g_aPluginCvar[hSlap] = CreateConVar("sm_spectate_slap", "1", "Enable/Disable slap option"); - g_aPluginCvar[hSlay] = CreateConVar("sm_spectate_slay", "1", "Enable/Disable slay option"); - g_aPluginCvar[hTimeBomb] = CreateConVar("sm_spectate_timebomb", "1", "Enable/Disable timebomb option"); - - sm_spectate_adminflag = CreateConVar("sm_spectate_adminflag", "d", "Admin Flag to use for admin hud"); - - /** - Hook console variables - */ - new e_CvarHandles:iCvar; - for ( ; _:iCvar < sizeof(g_aPluginCvar); iCvar++) - { - HookConVarChange(g_aPluginCvar[iCvar], ConVarSettingsChanged); - } - - /** - Need to register the commands we are going to create and use. - */ - RegConsoleCmd("sm_spectate", Command_Spectate, "Spectate a player"); - RegConsoleCmd("sm_spec", Command_Spectate, "Spectate a player"); - RegConsoleCmd("sm_observe", Command_Spectate, "Spectate a player"); - RegConsoleCmd("sm_stopspec", Command_StopSpectate, "Stop Spectating a player"); - RegConsoleCmd("sm_endobserve", Command_StopSpectate, "Stop Spectating a player"); - RegConsoleCmd("sm_specinfo", Command_ToggleHud, "Toggles the hud display if in spectator"); - - /** - Now we have to deal with the admin menu. If the admin library is loaded call the function to add our items. - */ - new Handle:gTopMenu; - if (LibraryExists("adminmenu") && ((gTopMenu = GetAdminTopMenu()) != INVALID_HANDLE)) - { - OnAdminMenuReady(gTopMenu); - } - - /** - Deal with the hud - Thanks to Spray Trace plugin (http://forums.alliedmods.net/showthread.php?p=665448) - */ - new String:sHudGames[32]; - GetGameFolderName(sHudGames, sizeof(sHudGames)); - g_aPluginSettings[bCanHUD] = StrEqual(sHudGames,"tf",false) - || StrEqual(sHudGames,"hl2mp",false) - || StrEqual(sHudGames,"sourceforts",false) - || StrEqual(sHudGames,"obsidian",false) - || StrEqual(sHudGames,"left4dead",false) - || StrEqual(sHudGames,"l4d",false); - - if (g_aPluginSettings[bCanHUD]) - { - g_hHud = CreateHudSynchronizer(); - } - - /** - Load translations - */ - LoadTranslations ("common.phrases"); - LoadTranslations ("simplespectate.phrases"); - - /** - Create the config file - */ - AutoExecConfig(true); -} - -public OnConfigsExecuted() -{ - new e_CvarHandles:iCvar; - for ( ; _:iCvar < sizeof(g_aPluginCvarSettings); iCvar++) - { - g_aPluginCvarSettings[iCvar] = GetConVarBool(g_aPluginCvar[iCvar]); - } - - /* - Build the global menus - */ - g_aMenus[hSelectPlayer] = BuildSelectPlayerMenu(); - g_aMenus[hBanTime] = BuildBanTimeMenu(); - g_aMenus[hReason] = BuildReasonMenu(); - - GetConVarString(sm_spectate_adminflag, g_sAdminFlags, sizeof(g_sAdminFlags)); -} - -public OnAllPluginsLoaded() -{ - - /* - Check for steambans - */ - if (FindConVar("sbsrc_version") != INVALID_HANDLE) - { - g_aPluginSettings[bUseSteamBans] = true; - } - else - { - g_aPluginSettings[bUseSteamBans] = false; - } - - /* - Check for sourcebans - */ - if (FindConVar("sb_version") != INVALID_HANDLE) - { - g_aPluginSettings[bUseSourceBans] = true; - } - else - { - g_aPluginSettings[bUseSourceBans] = false; - } - - /* - Check for mysql bans - */ - if (FindConVar("mysql_bans_version") != INVALID_HANDLE) - { - g_aPluginSettings[bUseMySQLBans] = true; - } - else - { - g_aPluginSettings[bUseMySQLBans] = false; - } - - /* - Check for dukehacks - */ - new String:sExtError[256]; - new iExtStatus = GetExtensionFileStatus("dukehacks.ext", sExtError, sizeof(sExtError)); - if (iExtStatus == -2) - { - LogAction(0, -1, "[SSPEC] Dukehacks extension was not found."); - LogAction(0, -1, "[SSPEC] Plugin continued to load, but that feature will not be used."); - g_aPluginSettings[bUseDukehacks] = false; - } - else if (iExtStatus == -1 || iExtStatus == 0) - { - LogAction(0, -1, "[SSPEC] Dukehacks extension is loaded with errors."); - LogAction(0, -1, "[SSPEC] Status reported was [%s].", sExtError); - LogAction(0, -1, "[SSPEC] Plugin continued to load, but that feature will not be used."); - g_aPluginSettings[bUseDukehacks] = false; - } - else if (iExtStatus == 1) - { - LogAction(0, -1, "[SSPEC] Dukehacks extension is loaded and will be used."); - g_aPluginSettings[bUseDukehacks] = true; - dhAddClientHook(CHK_TakeDamage, Hacks_TakeDamageHook); - } - - /* - Deal with some known plugin conflicts - */ - new Handle:hObserveClient = FindConVar("observe_version"); - if (hObserveClient != INVALID_HANDLE) - { - new String:sNewFile[PLATFORM_MAX_PATH + 1], String:sOldFile[PLATFORM_MAX_PATH + 1]; - BuildPath(Path_SM, sNewFile, sizeof(sNewFile), "plugins/disabled/observe.smx"); - BuildPath(Path_SM, sOldFile, sizeof(sOldFile), "plugins/observe.smx"); - - /** - Check if plugins/observe.smx exists, and if not, ignore - */ - if(!FileExists(sOldFile)) - { - return; - } - - /** - Check if plugins/disabled/observe.smx already exists, and if so, delete it - */ - if(FileExists(sNewFile)) - { - DeleteFile(sNewFile); - } - - /** - Unload plugins/observe.smx and move it to plugins/disabled/observe.smx - */ - LogAction(0, -1, "Detected the plugin ObserveClient"); - LogAction(0, -1, "ObserveClient plugin conflicts with Simple Spectate"); - LogAction(0, -1, "Unloading plugin and disabling ObserveClient plugin"); - ServerCommand("sm plugins unload observe"); - RenameFile(sNewFile, sOldFile); - } -} - -public OnLibraryRemoved(const String:name[]) -{ - if (StrEqual(name, "adminmenu")) - { - - /** - Looks like the admin menu was removed. Set the global. - */ - g_hAdminMenu = INVALID_HANDLE; - } - else if (StrEqual(name, "simpleplugins")) - { - //something - } -} - -public OnClientDisconnect(client) -{ - - /** - Cleanup the clients variables. - */ - ResetClient(client); - - /** - Run a loop and see if we are supposed to spectate this person (is a target) - */ - for(new i = 1; i <= MaxClients; i++) - { - if (g_aPlayers[i][iTargetIndex] == client) - { - - /** - Cleanup the clients variables. - */ - StopFollowingPlayer(i); - g_aPlayers[i][TargetPunishment] = Punish_None; - g_aPlayers[i][iBanTime] = 0; - } - } -} - -/** -Thirdparty callbacks -*/ -public SM_OnPlayerMoved(Handle:plugin, client, team) -{ - - /** - Make sure we called the move function - */ - if (plugin != GetMyHandle()) - { - return; - } - - //Nothing -} - -public Action:Hacks_TakeDamageHook(client, attacker, inflictor, Float:damage, &Float:multiplier, damagetype) -{ - - /** - Check for a valid client - */ - if (client > 0 && client <= MaxClients) - { - - /** - Check if the client taking damage is flagged as a cheater - */ - if (g_aPlayers[client][bIsFlaggedCheater]) - { - - /** - Check for fall damage and increase it - */ - if (damagetype & DMG_FALL) - { - multiplier *= 1000.0; - return Plugin_Changed; - } - } - } - - /** - Check for a valid attacker - */ - if (attacker > 0 && attacker <= MaxClients) - { - - /** - Check if the attacker causing the damage is flagged as a cheater - */ - if (g_aPlayers[attacker][bIsFlaggedCheater]) - { - - /** - Make sure they are not hurting themselves - */ - if (client != attacker) - { - - /** - Stop the damage - */ - multiplier *= 0.0; - return Plugin_Changed; - } - } - } - return Plugin_Continue; -} - -/** -Events -*/ -public Action:HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get the client and team - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - new iTeam = GetEventInt(event, "team"); - - /** - Make sure it's a valid client - */ - if (iClient == 0) - { - return Plugin_Continue; - } - - /** - If it's a move to spectator start displaying the hud - */ - else if ((iTeam == g_aCurrentTeams[Spectator]) && (GetUserFlagBits(iClient) & ADMFLAG_GENERIC)) - { - StartDisplayingHud(iClient); - - /** - If the event was going to be broadcasted, we refire it so it is not broadcasted and stop this one - */ - if (!dontBroadcast) - { - new Handle:hEvent = CreateEvent("player_team"); - SetEventInt(hEvent, "userid", GetEventInt(event, "userid")); - SetEventInt(hEvent, "team", GetEventInt(event, "team")); - SetEventInt(hEvent, "oldteam", GetEventInt(event, "oldteam")); - SetEventBool(hEvent, "disconnect", GetEventBool(event, "disconnect")); - - if (g_CurrentMod == GameType_DOD || g_CurrentMod == GameType_L4D || g_CurrentMod == GameType_TF) - { - new String:sClientName[MAX_NAME_LENGTH + 1]; - GetClientName(client, sClientName, sizeof(sClientName)); - SetEventBool(hEvent, "autoteam", GetEventBool(event, "autoteam")); - SetEventBool(hEvent, "silent", true); - SetEventString(hEvent, "name", sClientName); - FireEvent(hEvent, true); - } - else - { - FireEvent(hEvent, true); - } - return Plugin_Handled; - } - } - - /** - Otherwise cleanup the client - */ - else - { - StopDisplayingHud(iClient); - StopFollowingPlayer(iClient); - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -/** -Commands -*/ -public Action:Command_Spectate(client, args) -{ - - /** - See if we already have a target (for toggling of command) - */ - if (g_aPlayers[client][iTargetIndex]) - { - - /** - We do, toggle it off - */ - StopFollowingPlayer(client); - - /** - We are done, bug out. - */ - return Plugin_Handled; - } - - /** - We don't... must want to enable it - See if we have some command arguments. - */ - new iCmdArgs = GetCmdArgs(); - if (iCmdArgs == 0) - { - - /** - We don't have any. Display the player menu. - */ - if (g_aPlayers[client][bIsDisplayingHud]) - { - StopDisplayingHud(client); - } - - DisplayMenu(BuildPlayerListMenu(), client, MENU_TIME_FOREVER); - return Plugin_Handled; - } - - /** - We have an argument. - Try to find the target. - */ - new String:sPlayer[128]; - GetCmdArg(1, sPlayer, sizeof(sPlayer)); - new iTarget = FindTarget(client, sPlayer, true, true); - if (iTarget == -1 || !IsClientInGame(iTarget)) - { - - /** - We couldn't find the target. Display the player menu. - */ - if (g_aPlayers[client][bIsDisplayingHud]) - { - StopDisplayingHud(client); - } - - DisplayMenu(BuildPlayerListMenu(), client, MENU_TIME_FOREVER); - return Plugin_Handled; - } - - /** - We found the target. - Call the stock function to spectate the target. - */ - StartFollowingPlayer(client, iTarget); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_StopSpectate(client, args) -{ - - /** - Cleanup the clients variables. - */ - StopFollowingPlayer(client); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_ToggleHud(client, args) -{ - - /** - Toggle the hud - */ - if (g_aPlayers[client][bIsDisplayingHud]) - { - StopDisplayingHud(client); - } - else - { - StartDisplayingHud(client); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -/** -Timers -*/ -public Action:Timer_ResetTarget(Handle:timer, any:client) -{ - - new iTargetID = GetEntPropEnt(client, Prop_Send, "m_hObserverTarget"); - - if (iTargetID != g_aPlayers[client][iTargetIndex] && IsPlayerAlive(g_aPlayers[client][iTargetIndex])) - { - - /** - Run the command to spectate the target from the clients prospectative. - */ - FakeClientCommandEx(client, "spec_player \"%N\"", g_aPlayers[client][iTargetIndex]); - } - - /** - We are done, bug out. - */ - return Plugin_Continue; -} - -public Action:Timer_UpdateHud(Handle:timer, any:client) -{ - - /** - Make sure the client is still in game and a spectator - */ - if (!IsClientConnected(client) || !IsClientInGame(client) || GetClientTeam(client) != g_aCurrentTeams[Spectator] || !g_aPlayers[client][bIsDisplayingHud]) - { - - /** - We are done, bug out - */ - g_aPlayers[client][hHudTimer] = INVALID_HANDLE; - g_aPlayers[client][bIsDisplayingHud] = false; - return Plugin_Stop; - } - /** - Get the target - */ - new iTarget = GetEntPropEnt(client, Prop_Send, "m_hObserverTarget"); - - /** - Check to make sure the target is valid - */ - if (iTarget <= 0 || iTarget > MaxClients) - { - return Plugin_Continue; - } - - /** - Get the spectator mode - */ - new iSpecMode = GetEntProp(client, Prop_Send, "m_iObserverMode"); - - /** - This is a double check to make sure we are in spec - If we are on a regular team, specmod would = none or zero - */ - if (iSpecMode == SPECMODE_NONE) - { - - /** - We are done, bug out - */ - g_aPlayers[client][hHudTimer] = INVALID_HANDLE; - g_aPlayers[client][bIsDisplayingHud] = false; - return Plugin_Stop; - } - - /** - Check the spectator mode - CSS has different index's so we have to check game type first - */ - if (g_CurrentMod == GameType_CSS) - { - switch (iSpecMode) - { - case SPECMODE_CSS_FIRSTPERSON: - { - //Do Nothing - } - case SPECMODE_CSS_3RDPERSON: - { - //Do Nothing - } - case SPECMODE_CSS_FREELOOK: - { - return Plugin_Continue; - } - } - } - else - { - switch (iSpecMode) - { - case SPECMODE_FIRSTPERSON: - { - //Do Nothing - } - case SPECMODE_3RDPERSON: - { - //Do Nothing - } - case SPECMODE_FREELOOK: - { - return Plugin_Continue; - } - } - } - - - /** - Display with the hud - */ - if (g_aPluginSettings[bCanHUD] && !g_aPluginCvarSettings[bHudMode]) - { - new String:sSteamID[64]; - GetClientAuthString(iTarget, sSteamID, sizeof(sSteamID)); - SetHudTextParams(0.04, 0.6, 0.5, 255, 50, 50, 255); - ShowSyncHudText(client, g_hHud, "%N [%s]", iTarget, sSteamID); - } - else if (g_aPluginCvarSettings[bHudMode]) - { - if (g_aPluginCvarSettings[bMenuType]) - { - DisplayMenu(BuildPlayerHudMenu(client, iTarget), client, 1); - } - else - { - new Handle:hPanel = BuildPlayerHudPanel(client, iTarget); - SendPanelToClient(hPanel, client, Panel_PlayerHud, 1); - CloseHandle(hPanel); - } - } - - /** - We are done, keep going! - */ - return Plugin_Continue; -} - -/** -Admin Menu Callbacks -*/ -public OnAdminMenuReady(Handle:topmenu) -{ - if (topmenu == g_hAdminMenu) - { - return; - } - g_hAdminMenu = topmenu; - new TopMenuObject:player_commands = FindTopMenuCategory(g_hAdminMenu, ADMINMENU_PLAYERCOMMANDS); - if (player_commands == INVALID_TOPMENUOBJECT) - { - return; - } - AddToTopMenu(g_hAdminMenu, - "sm_spectate", - TopMenuObject_Item, - AdminMenu_SpecPlayer, - player_commands, - "sm_spectate", - ADMFLAG_GENERIC); -} - -public AdminMenu_SpecPlayer(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) -{ - if (action == TopMenuAction_DisplayOption) - { - - if (g_aPlayers[param][bIsDisplayingHud]) - { - StopDisplayingHud(param); - } - /** - See if we already have a target - */ - if (g_aPlayers[param][iTargetIndex]) - { - Format(buffer, maxlength, "Spectate(Disable)"); - } - else - { - Format(buffer, maxlength, "Spectate(Select Player)"); - } - } - else if (action == TopMenuAction_SelectOption) - { - - /** - See if we already have a target - */ - if (g_aPlayers[param][iTargetIndex]) - { - - /** - We do, toggle it off - */ - StopFollowingPlayer(param); - - /** - We are done, bug out. - */ - return; - } - else - { - DisplayMenu(BuildPlayerListMenu(), param, MENU_TIME_FOREVER); - } - } -} - -/** -Select Player Menu Callbacks -*/ -public Menu_PlayerList(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - /** - Get the selected player - */ - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - new iTarget = GetClientOfUserId(StringToInt(sSelection)); - - /** - Start following the player - */ - StartFollowingPlayer(param1, iTarget); - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_GENERIC) - { - - /** - Display the last admin menu - */ - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } - else if (param2 == MenuCancel_Exit && GetClientTeam(param1) == g_aCurrentTeams[Spectator]) - { - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_End) - { - - /** - Not a global menu, close it - */ - CloseHandle(menu); - } -} - -public Menu_SelectPlayer(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - - /** - Get the selected player - */ - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (strcmp(sSelection, "Current", false) == 0) - { - /** - Get the current target - */ - new iTarget = GetEntPropEnt(param1, Prop_Send, "m_hObserverTarget"); - - /** - Check to make sure the target is valid - */ - if (iTarget <= 0 || iTarget > MaxClients) - { - PrintToChat(param1, "\x03[SM-SPEC]\x01 %t", "Invalid Target"); - DisplayMenu(BuildPlayerListMenu(), param1, MENU_TIME_FOREVER); - } - - /** - Start following the player - */ - StartFollowingPlayer(param1, iTarget); - } - else - { - - /** - They want to select a player, show the player list - */ - DisplayMenu(BuildPlayerListMenu(), param1, MENU_TIME_FOREVER); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_End) - { - /** - Its a global menu, leave it alive - */ - } -} - -/** -Punishment Menu Callbacks -*/ -public Menu_Punishments(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - - /** - Get the menu selection - */ - new String:sSelection[15]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - - /** - Search for the correct index - */ - new e_Punishments:Index = Punish_None; - for ( ; _:Index <= sizeof(g_sPunishments); Index++) - { - if (StrEqual(sSelection, g_sPunishments[Index])) - { - break; - } - } - - /** - Display the next menu - */ - if (Index == Punish_Ban) - { - - /** - Set the punishment index and display ban time menu - */ - g_aPlayers[param1][TargetPunishment] = Index; - DisplayMenu(g_aMenus[hBanTime], param1, MENU_TIME_FOREVER); - } - else if (Index == Punish_Cheater) - { - - /** - Ask for confirmation before we set punishment index - */ - new Handle:hPanel = BuildAdminCheaterPanel(); - SendPanelToClient(hPanel, param1, Panel_AdminCheater, MENU_TIME_FOREVER); - CloseHandle(hPanel); - } - else - { - - /** - Set the punishment index and display reason menu - */ - g_aPlayers[param1][TargetPunishment] = Index; - DisplayMenu(g_aMenus[hReason], param1, MENU_TIME_FOREVER); - } - } - else if (action == MenuAction_Cancel) - { - - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - else if (action == MenuAction_End) - { - - /** - Not a global menu, close it - */ - CloseHandle(menu); - } -} - -public Menu_BanTime(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - - /** - Get the menu selection - */ - new String:sSelection[15]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - - /** - Set the ban time global - */ - g_aPlayers[param1][iBanTime] = StringToInt(sSelection); - - /** - Display the reason menu - */ - DisplayMenu(g_aMenus[hReason], param1, MENU_TIME_FOREVER); - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_End) - { - /** - Its a global menu, leave it alive - */ - } -} - -public Menu_Reason(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - - /** - Get the menu selection - */ - new String:sSelection[15]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - - /** - Perform the punishment - */ - PerformPunishment(param1, g_aPlayers[param1][iTargetIndex], g_aPlayers[param1][TargetPunishment], sSelection, g_aPlayers[param1][iBanTime]); - - /** - Reactivate the hud if still in spectator - */ - if (GetClientTeam(param1) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack) - { - - /** - They canceled the current menu, start the hud back up - */ - StartDisplayingHud(param1); - } - } - else if (action == MenuAction_End) - { - /** - Its a global menu, leave it alive - */ - } -} - -public Panel_AdminCheater(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - if (param2 == 1) - { - - /** - Set the punishment index and display reason menu - */ - g_aPlayers[param1][TargetPunishment] = Punish_Cheater; - DisplayMenu(g_aMenus[hReason], param1, MENU_TIME_FOREVER); - } - else - { - - /** - Reactivate the hud if still in spectator - */ - if (GetClientTeam(param1) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(param1); - } - } - } -} - -public Panel_PublicCheater(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - if (param2 == 1) - { - //Waiting for SB 2.0 and sb_submission to be published - } - else - { - - /** - Reactivate the hud if still in spectator - */ - if (GetClientTeam(param1) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(param1); - } - } - } -} - -/** -Hud Menu/Panel Callbacks -*/ -public Menu_PlayerHud(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "stop", false)) - { - StopFollowingPlayer(param1); - } - else if (StrEqual(sSelection, "start", false)) - { - StopDisplayingHud(param1); - DisplayMenu(g_aMenus[hSelectPlayer], param1, MENU_TIME_FOREVER); - } - else if (StrEqual(sSelection, "removecheater", false)) - { - g_aPlayers[g_aPlayers[param1][iTargetIndex]][bIsFlaggedCheater] = false; - } - else if (StrEqual(sSelection, "punish", false)) - { - if (g_aPlayers[param1][iTargetIndex]) - { - StopDisplayingHud(param1); - DisplayMenu(BuildPunishmentMenu(param1), param1, MENU_TIME_FOREVER); - } - else - { - StopDisplayingHud(param1); - PrintToChat(param1, "\x03[SM-SPEC]\x01 %t", "Must Have Target"); - DisplayMenu(g_aMenus[hSelectPlayer], param1, MENU_TIME_FOREVER); - } - } - else if (StrEqual(sSelection, "reportcheater", false)) - { - if (g_aPlayers[param1][iTargetIndex]) - { - StopDisplayingHud(param1); - new Handle:hPanel = BuildPublicCheaterPanel(); - SendPanelToClient(hPanel, param1, Panel_PublicCheater, MENU_TIME_FOREVER); - CloseHandle(hPanel); - } - else - { - StopDisplayingHud(param1); - PrintToChat(param1, "\x03[SM-SPEC]\x01 %t", "Must Have Target"); - DisplayMenu(g_aMenus[hSelectPlayer], param1, MENU_TIME_FOREVER); - } - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_Interrupted) - { - if (GetClientMenu(param1) == MenuSource_External) - { - StopDisplayingHud(param1); - } - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } -} - -public Panel_PlayerHud(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - switch (param2) - { - case 1: - { - if (g_aPlayers[param1][iTargetIndex]) - { - StopFollowingPlayer(param1); - } - else - { - StopDisplayingHud(param1); - DisplayMenu(BuildSelectPlayerMenu(), param1, MENU_TIME_FOREVER); - } - } - case 2: - { - if (!g_aPlayers[param1][iTargetIndex]) - { - StopDisplayingHud(param1); - PrintToChat(param1, "\x03[SM-SPEC]\x01 %t", "Must Have Target"); - DisplayMenu(g_aMenus[hSelectPlayer], param1, MENU_TIME_FOREVER); - return; - } - - if ((GetUserFlagBits(param1) & ADMFLAG_GENERIC) || (GetUserFlagBits(param1) & ADMFLAG_ROOT)) - { - if (g_aPlayers[g_aPlayers[param1][iTargetIndex]][bIsFlaggedCheater] && (GetUserFlagBits(param1) & ADMFLAG_ROOT)) - { - //Remove cheater flag - g_aPlayers[g_aPlayers[param1][iTargetIndex]][bIsFlaggedCheater] = false; - } - else - { - //Punish menu - StopDisplayingHud(param1); - DisplayMenu(BuildPunishmentMenu(param1), param1, MENU_TIME_FOREVER); - } - } - else - { - //Report Cheater - new Handle:hPanel = BuildPublicCheaterPanel(); - SendPanelToClient(hPanel, param1, Panel_PublicCheater, MENU_TIME_FOREVER); - CloseHandle(hPanel); - } - } - case 3: - { - StopDisplayingHud(param1); - } - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_Interrupted) - { - if (GetClientMenu(param1) == MenuSource_External) - { - StopDisplayingHud(param1); - } - } - } -} - - -/** -Stock functions -*/ -stock StartFollowingPlayer(client, target) -{ - - /** - If we have an open timer, close it. - */ - if (g_aPlayers[client][hTargetTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[client][hTargetTimer]); - g_aPlayers[client][hTargetTimer] = INVALID_HANDLE; - } - - /** - Make sure the target is on a non spectator team, and the client != target - */ - if (client == target) - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Yourself"); - return; - } - new iTargetTeam = GetClientTeam(target); - if (iTargetTeam == g_aCurrentTeams[Spectator] || iTargetTeam == g_aCurrentTeams[Unknown]) - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Spectator"); - return; - } - - /** - Check to see if client is already a spectator - */ - if (GetClientTeam(client) != g_aCurrentTeams[Spectator]) - { - - /** - Client is not a spectator, lets move them to spec. - */ - SM_MovePlayer(client, g_aCurrentTeams[Spectator]); - } - - /** - If we are using steambans call sb_status - */ - if (g_aPluginSettings[bUseSteamBans]) - { - FakeClientCommandEx(client, "sb_status"); - } - - - /** - Set the global and start to spectate the target. - Making sure it's long enough to deal with moving the client to spec if we had to. - */ - new String:sTargetName[MAX_NAME_LENGTH + 1]; - GetClientName(target, sTargetName, sizeof(sTargetName)); - g_aPlayers[client][iTargetIndex] = target; - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Spectating", sTargetName); - g_aPlayers[client][hTargetTimer] = CreateTimer(0.5, Timer_ResetTarget, client, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); - if (!g_aPlayers[client][bIsDisplayingHud] && GetClientTeam(client) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(client); - } -} - -stock StopFollowingPlayer(client) -{ - - /** - If we have an open timer, close it. - */ - if (g_aPlayers[client][hTargetTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[client][hTargetTimer]); - } - - /** - Tell the client we can't spec his target anymore... if they are in game. - */ - if (IsClientInGame(client) && g_aPlayers[client][iTargetIndex] != 0) - { - new String:sTargetName[MAX_NAME_LENGTH + 1]; - GetClientName(g_aPlayers[client][iTargetIndex], sTargetName, sizeof(sTargetName)); - if (!IsClientConnected(g_aPlayers[client][iTargetIndex]) || !IsClientInGame(g_aPlayers[client][iTargetIndex])) - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Target Left"); - } - else - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Stopped spectating", sTargetName); - } - } - - /** - Null the globals. - */ - g_aPlayers[client][iTargetIndex] = 0; - g_aPlayers[client][hTargetTimer] = INVALID_HANDLE; -} - -stock StartDisplayingHud(client) -{ - if (g_aPluginCvarSettings[bRestrictHud] && !SM_IsValidAdmin(client, g_sAdminFlags)) - { - return; - } - else - { - /** - Double check the hud timer - We should not have one, but if we do, lets cancel it for the current callback - */ - StopDisplayingHud(client); - - /** - Now we can safely display the hud and make sure the current stored handle is the current timer - */ - g_aPlayers[client][bIsDisplayingHud] = true; - g_aPlayers[client][hHudTimer] = CreateTimer(0.5, Timer_UpdateHud, client, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); - } -} - -stock StopDisplayingHud(client) -{ - if (g_aPlayers[client][hHudTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[client][hHudTimer]); - } - g_aPlayers[client][hHudTimer] = INVALID_HANDLE; - g_aPlayers[client][bIsDisplayingHud] = false; -} - -stock ResetClient(client) -{ - StopFollowingPlayer(client); - StopDisplayingHud(client); - - g_aPlayers[client][bIsFlaggedCheater] = false; - g_aPlayers[client][TargetPunishment] = Punish_None; - g_aPlayers[client][iBanTime] = -1; -} - -stock PerformPunishment(client, target, e_Punishments:punishment, const String:reason[], time = 300) -{ - new String:sTargetName[MAX_NAME_LENGTH + 1], - String:sTargetID[64]; - - /** - The target could have left the game by the time we get here - Check for a valid target - */ - if (!IsClientConnected(target) || !IsClientInGame(target)) - { - PrintToChat(client, "\x03[SM-SPEC]\x01 %t", "Target Left"); - return; - } - - GetClientName(target, sTargetName, sizeof(sTargetName)); - GetClientAuthString(target, sTargetID, sizeof(sTargetID)); - - switch (punishment) - { - case Punish_Kick: - { - KickClient(g_aPlayers[client][iTargetIndex], "%s", reason); - } - case Punish_Ban: - { - if (g_aPluginSettings[bUseSourceBans]) - { - ClientCommand(client, "sm_ban #%d %d \"%s\"", GetClientUserId(target), time, reason); - } - else if (g_aPluginSettings[bUseMySQLBans]) - { - ClientCommand(client, "mysql_ban #%d %d \"%s\"", GetClientUserId(target), time, reason); - } - else - { - BanClient(target, time, BANFLAG_AUTHID, reason, reason); - } - } - case Punish_Cheater: - { - g_aPlayers[target][bIsFlaggedCheater] = true; - } - case Punish_Beacon: - { - ClientCommand(client, "sm_beacon \"%s\"", sTargetName); - } - case Punish_Blind: - { - ClientCommand(client, "sm_blind \"%s\"", sTargetName); - } - case Punish_Drug: - { - ClientCommand(client, "sm_drug \"%s\"", sTargetName); - } - case Punish_Freeze: - { - ClientCommand(client, "sm_freeze \"%s\"", sTargetName); - } - case Punish_FreezeBomb: - { - ClientCommand(client, "sm_freezebomb \"%s\"", sTargetName); - } - case Punish_Slap: - { - ClientCommand(client, "sm_slap \"%s\" 10", sTargetName); - } - case Punish_Slay: - { - ClientCommand(client, "sm_slay \"%s\"", sTargetName); - } - case Punish_TimeBomb: - { - ClientCommand(client, "sm_timebomb \"%s\"", sTargetName); - } - } - - if (punishment == Punish_Cheater) - { - LogAction(client, target, "[SM SPEC] %N marked %N(%s) with a %s flag for %s", client, target, sTargetID, g_sPunishments[punishment], reason); - } - else - { - ShowActivity(client, "%t", "Punished", sTargetName, g_sPunishments[punishment], reason); - LogAction(client, target, "[SM SPEC] %N punished %N(%s) with a %s for %s", client, target, sTargetID, g_sPunishments[punishment], reason); - } - - /** - Null the globals. - */ - g_aPlayers[client][TargetPunishment] = Punish_None; - g_aPlayers[client][iBanTime] = -1; -} - -/** -Build the menu of player names -*/ -stock Handle:BuildPlayerListMenu() -{ - new Handle:hMenu = CreateMenu(Menu_PlayerList); - AddTargetsToMenu(hMenu, 0, true, false); - SetMenuTitle(hMenu, "Select A Player:"); - SetMenuExitBackButton(hMenu, true); - return hMenu; -} - -/** -Build the select player menu (current or list of players) -*/ -stock Handle:BuildSelectPlayerMenu() -{ - new Handle:hMenu = CreateMenu(Menu_SelectPlayer); - SetMenuTitle(hMenu, "Select A Player:"); - AddMenuItem(hMenu, "Current", "Current Target"); - AddMenuItem(hMenu, "List", "Player List"); - SetMenuExitBackButton(hMenu, true); - return hMenu; -} - -/** -Build the punishmenu menu -*/ -stock Handle:BuildPunishmentMenu(iClient) -{ - new Handle:hMenu = CreateMenu(Menu_Punishments); - SetMenuTitle(hMenu, "Select A Punishment:"); - SetMenuExitBackButton(hMenu, true); - SetMenuExitButton(hMenu, true); - - if (g_aPluginCvarSettings[bKick] && ((GetUserFlagBits(iClient) & ADMFLAG_GENERIC) || (GetUserFlagBits(iClient) & ADMFLAG_ROOT))) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Kick], "Kick"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Kick], "Kick", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bBan] && ((GetUserFlagBits(iClient) & ADMFLAG_GENERIC) || (GetUserFlagBits(iClient) & ADMFLAG_ROOT))) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Ban], "Ban"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Ban], "Ban", ITEMDRAW_DISABLED); - } - - if (g_aPluginSettings[bUseDukehacks] && g_aPluginCvarSettings[bCheater] && (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Cheater], "Flag As Cheater"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Cheater], "Flag As Cheater", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bBeacon]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Beacon], "Beacon"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Beacon], "Beacon", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bBlind]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Blind], "Blind"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Blind], "Blind", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bDrug]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Drug], "Drug"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Drug], "Drug", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bFreeze]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Freeze], "Freeze"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Freeze], "Freeze", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bFreezebomb]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_FreezeBomb], "Freeze Bomb"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_FreezeBomb], "Freeze Bomb", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bSlap]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Slap], "Slap"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Slap], "Slap", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bSlay]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_Slay], "Slay"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_Slay], "Slay", ITEMDRAW_DISABLED); - } - - if (g_aPluginCvarSettings[bTimeBomb]) - { - AddMenuItem(hMenu, g_sPunishments[Punish_TimeBomb], "Time Bomb"); - } - else - { - AddMenuItem(hMenu, g_sPunishments[Punish_TimeBomb], "Time Bomb", ITEMDRAW_DISABLED); - } - - return hMenu; -} - -/** -Build the punishmenu menu -*/ -stock Handle:BuildBanTimeMenu() -{ - new Handle:hMenu = CreateMenu(Menu_BanTime); - SetMenuTitle(hMenu, "Select Ban Type:"); - - if (g_aPluginCvarSettings[bBanPerm]) - { - AddMenuItem(hMenu, "permban", "Permanent"); - } - else - { - AddMenuItem(hMenu, "permban", "Permanent", ITEMDRAW_DISABLED); - } - - AddMenuItem(hMenu, "10", "10 Minutes"); - AddMenuItem(hMenu, "30", "30 Minutes"); - AddMenuItem(hMenu, "60", "1 Hour"); - AddMenuItem(hMenu, "240", "4 Hours"); - AddMenuItem(hMenu, "1440", "1 Day"); - AddMenuItem(hMenu, "10080", "1 Week"); - - SetMenuExitBackButton(hMenu, true); - return hMenu; -} - -/** -Build the punishmenu menu -*/ -stock Handle:BuildReasonMenu() -{ - new Handle:hMenu = CreateMenu(Menu_Reason); - SetMenuTitle(hMenu, "Select A Reason:"); - - AddMenuItem(hMenu, "Abusive", "Abusive"); - AddMenuItem(hMenu, "Racism", "Racism"); - AddMenuItem(hMenu, "General cheating/exploits", "General cheating/exploits"); - AddMenuItem(hMenu, "Wallhack", "Wallhack"); - AddMenuItem(hMenu, "Aimbot", "Aimbot"); - AddMenuItem(hMenu, "Speedhacking", "Speedhacking"); - AddMenuItem(hMenu, "Mic spamming", "Mic spamming"); - AddMenuItem(hMenu, "Admin disrepect", "Admin disrepect"); - AddMenuItem(hMenu, "Camping", "Camping"); - AddMenuItem(hMenu, "Team killing", "Team killing"); - AddMenuItem(hMenu, "Unacceptable Spray", "Unacceptable Spray"); - AddMenuItem(hMenu, "Breaking Server Rules", "Breaking Server Rules"); - AddMenuItem(hMenu, "Other", "Other"); - - SetMenuExitBackButton(hMenu, true); - return hMenu; -} - -/** -Build the cheater displays -*/ -stock Handle:BuildAdminCheaterPanel() -{ - - /** - Create the menu and set the menu options. - */ - new Handle:hPanel = CreatePanel(); - SetPanelTitle(hPanel, "Simple Spectator:"); - - DrawPanelText(hPanel, "Are you sure you want to"); - DrawPanelText(hPanel, "flag this player as a cheater?"); - DrawPanelText(hPanel, "They will not be able to damage"); - DrawPanelText(hPanel, "anyone and die on fall damage."); - DrawPanelItem(hPanel, "Yes"); - DrawPanelItem(hPanel, "No"); - - return hPanel; -} - -stock Handle:BuildPublicCheaterPanel() -{ - - /** - Create the menu and set the menu options. - */ - new Handle:hPanel = CreatePanel(); - SetPanelTitle(hPanel, "Simple Spectator:"); - - DrawPanelText(hPanel, "Are you sure you want to"); - DrawPanelText(hPanel, "submit this player as a cheater?"); - DrawPanelItem(hPanel, "Yes (Not Implemented Yet)", ITEMDRAW_DISABLED); - DrawPanelItem(hPanel, "No"); - return hPanel; -} - -/** -Build the hud displays -*/ -stock Handle:BuildPlayerHudMenu(iClient, iTarget) -{ - - /** - Create all the string variables we will need - */ - new String:sTargetName[MAX_NAME_LENGTH + 1], - String:sTargetID[64], - String:sTargetIP[16]; - - new String:sDisplayName[MAX_NAME_LENGTH + 1], - String:sDisplayID[64], - String:sDisplayIP[64], - String:sDisplayFrags[16], - String:sDisplayDeaths[16]; - - new iTargetFrags, - iTargetDeaths; - - /** - Get the targets information - */ - GetClientName(iTarget, sTargetName, sizeof(sTargetName)); - GetClientIP(iTarget, sTargetIP, sizeof(sTargetIP)); - GetClientAuthString(iTarget, sTargetID, sizeof(sTargetID)); - iTargetFrags = GetClientFrags(iTarget); - iTargetDeaths = GetClientDeaths(iTarget); - - /** - Format the strings for the menu - */ - Format(sDisplayName, sizeof(sDisplayName), "Player: %s", sTargetName); - Format(sDisplayID, sizeof(sDisplayID), "Steam ID: %s", sTargetID); - Format(sDisplayIP, sizeof(sDisplayIP), "IP Address: %s", sTargetIP); - Format(sDisplayFrags, sizeof(sDisplayFrags), "Kills: %i", iTargetFrags); - Format(sDisplayDeaths, sizeof(sDisplayDeaths), "Deaths: %i", iTargetDeaths); - - /** - Create the menu and set the menu options. - */ - new Handle:hMenu = CreateMenu(Menu_PlayerHud); - SetMenuExitBackButton(hMenu, false); - SetMenuTitle(hMenu, "Simple Spectator"); - - AddMenuItem(hMenu, "name", sDisplayName, ITEMDRAW_DISABLED); - AddMenuItem(hMenu, "steamid", sDisplayID, ITEMDRAW_DISABLED); - - if (SM_IsValidAdmin(iClient, g_sAdminFlags)) - { - AddMenuItem(hMenu, "ip", sDisplayIP, ITEMDRAW_DISABLED); - } - - AddMenuItem(hMenu, "kills", sDisplayFrags, ITEMDRAW_DISABLED); - AddMenuItem(hMenu, "deaths", sDisplayDeaths, ITEMDRAW_DISABLED); - - if (g_aPlayers[iClient][iTargetIndex]) - { - AddMenuItem(hMenu, "stop", "Stop Following"); - } - else - { - AddMenuItem(hMenu, "start", "Follow Player"); - } - - if ((GetUserFlagBits(iClient) & ADMFLAG_GENERIC) || (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - if (g_aPlayers[iTarget][bIsFlaggedCheater] && (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - AddMenuItem(hMenu, "removecheater", "Remove Cheater Flag"); - } - else - { - if (CanUserTarget(iClient, iTarget)) - { - AddMenuItem(hMenu, "punish", "Punish Player"); - } - else - { - AddMenuItem(hMenu, "punish", "Punish Player (Immune)", ITEMDRAW_DISABLED); - } - } - } - else - { - AddMenuItem(hMenu, "reportcheater", "Report Cheater"); - } - - SetMenuPagination(hMenu, MENU_NO_PAGINATION); - SetMenuExitButton(hMenu, true); - return hMenu; -} - -stock Handle:BuildPlayerHudPanel(iClient, iTarget) -{ - - /** - Create all the string variables we will need - */ - new String:sTargetName[MAX_NAME_LENGTH + 1], - String:sTargetID[64], - String:sTargetIP[16]; - - new String:sDisplayName[MAX_NAME_LENGTH + 1], - String:sDisplayID[64], - String:sDisplayIP[64], - String:sDisplayFrags[16], - String:sDisplayDeaths[16]; - - new iTargetFrags, - iTargetDeaths; - - /** - Get the targets information - */ - GetClientName(iTarget, sTargetName, sizeof(sTargetName)); - GetClientIP(iTarget, sTargetIP, sizeof(sTargetIP)); - GetClientAuthString(iTarget, sTargetID, sizeof(sTargetID)); - iTargetFrags = GetClientFrags(iTarget); - iTargetDeaths = GetClientDeaths(iTarget); - - /** - Format the strings for the menu - */ - Format(sDisplayName, sizeof(sDisplayName), "Player: %s", sTargetName); - Format(sDisplayID, sizeof(sDisplayID), "Steam ID: %s", sTargetID); - Format(sDisplayIP, sizeof(sDisplayIP), "IP Address: %s", sTargetIP); - Format(sDisplayFrags, sizeof(sDisplayFrags), "Kills: %i", iTargetFrags); - Format(sDisplayDeaths, sizeof(sDisplayDeaths), "Deaths: %i", iTargetDeaths); - - /** - Create the menu and set the menu options. - */ - new Handle:hPanel = CreatePanel(); - SetPanelTitle(hPanel, "Simple Spectator"); - - DrawPanelText(hPanel, "Player Information:"); - DrawPanelText(hPanel, sDisplayName); - DrawPanelText(hPanel, sDisplayID); - if (SM_IsValidAdmin(iClient, g_sAdminFlags)) - { - DrawPanelText(hPanel, sDisplayIP); - } - - DrawPanelText(hPanel, sDisplayFrags); - DrawPanelText(hPanel, sDisplayDeaths); - - if (g_aPlayers[iClient][iTargetIndex]) - { - DrawPanelItem(hPanel, "Stop Following"); - } - else - { - DrawPanelItem(hPanel, "Follow Player"); - } - - if ((GetUserFlagBits(iClient) & ADMFLAG_GENERIC) || (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - if (g_aPlayers[iTarget][bIsFlaggedCheater] && (GetUserFlagBits(iClient) & ADMFLAG_ROOT)) - { - DrawPanelItem(hPanel, "Remove Cheater Flag"); - } - else - { - if (CanUserTarget(iClient, iTarget)) - { - DrawPanelItem(hPanel, "Punish Player"); - } - else - { - DrawPanelItem(hPanel, "Punish Player (Immune)", ITEMDRAW_DISABLED); - } - } - } - else - { - DrawPanelItem(hPanel, "Report Cheater"); - } - - DrawPanelItem(hPanel, "Close Hud Panel"); - return hPanel; -} - -/** -Adjust the settings if a convar was changed -*/ -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - for (new iCvar = 0 ; _:iCvar < sizeof(g_aPluginCvarSettings); iCvar++) - { - if (g_aPluginCvar[_:iCvar] == convar) - { - if (StringToInt(newValue) == 1) - { - g_aPluginCvarSettings[_:iCvar] = true; - } - else - { - g_aPluginCvarSettings[_:iCvar] = false; - } - } - } - - /* - ReBuild the global menu that depends on cvars - */ - g_aMenus[hBanTime] = BuildBanTimeMenu(); - - /** - Run a loop to reset the hud - */ - for(new i = 1; i <= MaxClients; i++) - { - StopDisplayingHud(i); - if (IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == g_aCurrentTeams[Spectator]) - { - StartDisplayingHud(i); - } - } -} diff --git a/addons/sourcemod/scripting/simple-teambalancer.sp b/addons/sourcemod/scripting/simple-teambalancer.sp deleted file mode 100644 index 3302255..0000000 --- a/addons/sourcemod/scripting/simple-teambalancer.sp +++ /dev/null @@ -1,1797 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Team Balancer -Description: - Balances teams based upon player count - Player will not be balanced more than once in 5 (default) mins - Buddy system tries to keep buddies together - Ability to prioritize players - Ability to force players to accept the new team - Admins are immune -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include -#include - -#define PLUGIN_VERSION "2.1.$Rev$" - -enum PlayerData -{ - Handle:hBalanceTimer, - Handle:hForcedTimer, - bool:bSwitched, - bool:bFlagCarrier -}; - -/** - Global convar handles - */ -new Handle:stb_enabled = INVALID_HANDLE; -new Handle:stb_buddyenabled = INVALID_HANDLE; -new Handle:stb_logactivity = INVALID_HANDLE; -new Handle:stb_logactivity2 = INVALID_HANDLE; -new Handle:stb_unbalancelimit = INVALID_HANDLE; -new Handle:stb_deadonly = INVALID_HANDLE; -new Handle:stb_priorityenabled = INVALID_HANDLE; -new Handle:stb_uberlevel = INVALID_HANDLE; -new Handle:stb_balancedelay = INVALID_HANDLE; -new Handle:stb_livingplayerswitchdelay = INVALID_HANDLE; -new Handle:stb_livingplayercheckdelay = INVALID_HANDLE; -new Handle:stb_roundstartdelay = INVALID_HANDLE; -new Handle:stb_switchbackforced = INVALID_HANDLE; -new Handle:stb_adminflag = INVALID_HANDLE; -new Handle:stb_buddyrestriction = INVALID_HANDLE; -new Handle:stb_convarcontrol = INVALID_HANDLE; - -/** - Built-in cvars handles - */ -new Handle:stb_mp_autoteambalance = INVALID_HANDLE; -new Handle:stb_mp_teams_unbalance_limit = INVALID_HANDLE; -new Handle:TFGameModeArena = INVALID_HANDLE; - -/** - Timer handles - */ -new Handle:g_hBalanceTimer = INVALID_HANDLE; -new Handle:g_hLivingPlayerCheckTimer = INVALID_HANDLE; - -/** - Player arrays - */ -new g_aPlayers[MAXPLAYERS + 1][PlayerData]; - -/** -Global bools -*/ -new bool:g_bIsEnabled = true; -new bool:g_bPriorityPlayers = true; -new bool:g_bBuddyRestriction = false; -new bool:g_bLogActivity = false; -new bool:g_bLogActivity2 = false; -new bool:g_bDeadOnly = false; -new bool:g_bConVarControl = true; -new bool:g_bBuddyEnabled = true; -new bool:g_bBalanceInProgress = false; -new bool:g_bRoundStart = false; -new bool:g_bRoundEnd = false; -new bool:g_bSuddenDeath = false; -new bool:g_bIsArenaMode = false; - -/** - Global strings/integers/floats - */ -new g_iUnbalanceLimit, g_iLivingPlayerSwitchDelay, g_iLivingPlayerCheckDelay; -new g_iRoundStartDelay, g_iSwitchBackForced, g_iBalanceDelay; -new Float:g_fUberLevel; -new g_iOwnerOffset; -new String:g_sAdminFlag[5]; - -public Plugin:myinfo = -{ - name = "Simple Team Balancer", - author = "Simple Plugins", - description = "Balances teams based upon player count.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -} - -public OnPluginStart() -{ - - /** - Create console variables - */ - CreateConVar("stb_version", PLUGIN_VERSION, "Simple Team Balancer", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - stb_enabled = CreateConVar("stb_enabled", "1", "Enable or Disable Simple Team Balancer", _, true, 0.0, true, 1.0); - stb_priorityenabled = CreateConVar("stb_priorityenabled", "1", "Enable or Disable the prioritization of living players", _, true, 0.0, true, 1.0); - stb_buddyrestriction = CreateConVar("stb_buddyrestriction", "0", "Enable or Disable Admin Only buddy lists", _, true, 0.0, true, 1.0); - stb_logactivity = CreateConVar("stb_logactivity", "0", "Enable or Disable the disaplying of events in the log", _, true, 0.0, true, 1.0); - stb_logactivity2 = CreateConVar("stb_logactivity2", "0", "Enable or Disable the disaplying of detailed events in the log (WILL SPAM LOG)", _, true, 0.0, true, 1.0); - stb_deadonly = CreateConVar("stb_deadonly", "0", "Enable or Disable the switching of only dead players", _, true, 0.0, true, 1.0); - stb_convarcontrol = CreateConVar("stb_convarcontrol", "1", "Enable or Disable the control of builtin console variables", _, true, 0.0, true, 1.0); - stb_buddyenabled = CreateConVar("stb_buddyenabled", "1", "Enable or Disable the buddy system", _, true, 0.0, true, 1.0); - stb_unbalancelimit = CreateConVar("stb_unbalancelimit", "2", "Amount of players teams are ALLOWED to be unbalanced by", _, true, 1.0, true, 32.0); - stb_balancedelay = CreateConVar("stb_balancedelay", "10", "Delay in seconds to start an autobalance"); - stb_livingplayerswitchdelay = CreateConVar("stb_livingplayerswitchdelay", "20", "Delay in seconds to switch living players once selected"); - stb_livingplayercheckdelay = CreateConVar("stb_livingplayercheckdelay", "10", "Delay in seconds to start checking living players once teams become unbalanced"); - stb_roundstartdelay = CreateConVar("stb_roundstartdelay", "15", "Delay in seconds to start balancing teams after the start of a round"); - stb_switchbackforced = CreateConVar("stb_switchbackforced", "300", "Amount of time in seconds to not switch a player twice and force the team if enabled"); - stb_uberlevel = CreateConVar("stb_uberlevel", "1.0", "Min uber level medic must have to have priority over other living players. Setting to 0 will rarely switch a living medic", _, true, 0.0, true, 1.0); - stb_adminflag = CreateConVar("stb_adminflag", "a", "Admin flag to use for immunity. Must be a in char format."); - stb_mp_autoteambalance = FindConVar("mp_autoteambalance"); - stb_mp_teams_unbalance_limit = FindConVar("mp_teams_unbalance_limit"); - - /** - Removing the notify tags from the built in cvars. We dont want spam. - */ - if (stb_mp_autoteambalance != INVALID_HANDLE) - { - SetConVarFlags(stb_mp_autoteambalance, GetConVarFlags(stb_mp_autoteambalance)^FCVAR_NOTIFY); - } - if (stb_mp_teams_unbalance_limit != INVALID_HANDLE) - { - SetConVarFlags(stb_mp_teams_unbalance_limit, GetConVarFlags(stb_mp_teams_unbalance_limit)^FCVAR_NOTIFY); - } - - /** - Hook console variables - */ - HookConVarChange(stb_enabled, ConVarSettingsChanged); - HookConVarChange(stb_priorityenabled, ConVarSettingsChanged); - HookConVarChange(stb_buddyrestriction, ConVarSettingsChanged); - HookConVarChange(stb_logactivity, ConVarSettingsChanged); - HookConVarChange(stb_logactivity2, ConVarSettingsChanged); - HookConVarChange(stb_deadonly, ConVarSettingsChanged); - HookConVarChange(stb_convarcontrol, ConVarSettingsChanged); - HookConVarChange(stb_buddyenabled, ConVarSettingsChanged); - HookConVarChange(stb_unbalancelimit, ConVarSettingsChanged); - HookConVarChange(stb_balancedelay, ConVarSettingsChanged); - HookConVarChange(stb_livingplayerswitchdelay, ConVarSettingsChanged); - HookConVarChange(stb_livingplayercheckdelay, ConVarSettingsChanged); - HookConVarChange(stb_roundstartdelay, ConVarSettingsChanged); - HookConVarChange(stb_switchbackforced, ConVarSettingsChanged); - HookConVarChange(stb_uberlevel, ConVarSettingsChanged); - HookConVarChange(stb_mp_autoteambalance, ConVarSettingsChanged); - HookConVarChange(stb_mp_teams_unbalance_limit, ConVarSettingsChanged); - - /** - Create console commands - */ - RegConsoleCmd("sm_buddy", Command_AddBalanceBuddy, "Add a balance buddy"); - RegConsoleCmd("sm_lockbuddy", Command_LockBuddy, "Locks your balance buddy selection"); - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[STB] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_death", HookPlayerDeath, EventHookMode_Post); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Post); - switch (g_CurrentMod) - { - case GameType_TF: - { - HookEvent("teamplay_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - HookEvent("teamplay_suddendeath_begin", HookSuddenDeathBegin, EventHookMode_PostNoCopy); - HookEvent("teamplay_flag_event", HookFlagEvent, EventHookMode_Post); - TFGameModeArena = FindConVar("tf_gamemode_arena"); - g_iOwnerOffset = FindSendPropInfo("CBaseObject", "m_hBuilder"); - } - case GameType_DOD: - { - HookEvent("dod_round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_Post); - } - default: - { - HookEvent("round_start", HookRoundStart, EventHookMode_PostNoCopy); - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - - /** - Load translations and .cfg file - */ - LoadTranslations ("simpleteambalancer.phrases"); - AutoExecConfig(true, "plugin.simpleteambalancer"); - LogAction(0, -1, "[STB] Simple Team Balancer is loaded."); -} - -public OnAllPluginsLoaded() -{ - //something -} - -public OnLibraryRemoved(const String:name[]) -{ - //something -} - -public OnConfigsExecuted() -{ - - /** - Load up global variables - */ - g_bIsEnabled = GetConVarBool(stb_enabled); - g_bBuddyEnabled = GetConVarBool(stb_buddyenabled); - g_bLogActivity = GetConVarBool(stb_logactivity); - g_bLogActivity2 = GetConVarBool(stb_logactivity2); - g_bDeadOnly = GetConVarBool(stb_deadonly); - g_bPriorityPlayers = GetConVarBool(stb_priorityenabled); - g_bBuddyRestriction = GetConVarBool(stb_buddyrestriction); - g_bConVarControl = GetConVarBool(stb_convarcontrol); - g_fUberLevel = GetConVarFloat(stb_uberlevel); - g_iUnbalanceLimit = GetConVarInt(stb_unbalancelimit); - g_iBalanceDelay = GetConVarInt(stb_balancedelay); - g_iLivingPlayerSwitchDelay = GetConVarInt(stb_livingplayerswitchdelay); - g_iLivingPlayerCheckDelay = GetConVarInt(stb_livingplayercheckdelay); - g_iRoundStartDelay = GetConVarInt(stb_roundstartdelay); - g_iSwitchBackForced = GetConVarInt(stb_switchbackforced); - GetConVarString(stb_adminflag, g_sAdminFlag, sizeof(g_sAdminFlag)); - - /** - Report enabled - */ - if (g_bIsEnabled) - { - LogAction(0, -1, "[STB] Simple Team Balancer is ENABLED."); - } - else - { - LogAction(0, -1, "[STB] Simple Team Balancer is DISABLED."); - } - - - /** - Report log activity - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Log Activity ENABLED."); - } - else - { - LogAction(0, -1, "[STB] Log Activity DISABLED."); - } - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Detailed Log Activity ENABLED."); - } - else - { - LogAction(0, -1, "[STB] Detailed Log Activity DISABLED."); - } -} - -public OnMapStart() -{ - - /** - Check for arena mode - */ - if (g_CurrentMod == GameType_TF && GetConVarBool(TFGameModeArena)) - { - g_bIsArenaMode = true; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Simple Team Balancer detected arena mode and will be bypassed"); - } - } - else - { - g_bIsArenaMode = false; - } - - /** - Reset the globals - */ - g_bBalanceInProgress = false; - g_bRoundStart = false; - g_bRoundEnd = false; - g_bSuddenDeath = false; - - /** - Set the built-in convars - */ - SetGameCvars(); -} - -public OnClientPostAdminCheck(client) -{ - - /** - Make sure its a valid connected client and buddy system is enabled - */ - if (client == 0 || !g_bIsEnabled || !IsClientConnected(client) || !g_bBuddyEnabled) - { - return; - } - - /** - Make sure if its set for admins only they have the flags - */ - if (g_bBuddyRestriction && !SM_IsValidAdmin(client, g_sAdminFlag)) - { - return; - } - - /** - Start the advertisement timer - */ - CreateTimer (60.0, Timer_WelcomeAdvert, client); -} - -public OnClientDisconnect(client) -{ - - /** - Call stock function to cleaup - */ - CleanUp(client); -} - -public OnClientDisconnect_Post(client) -{ - - /** - Determine if we need a balance - */ - if (OkToBalance() && IsUnbalanced() && !g_bBalanceInProgress) - { - - /** - No balance in progress but balance is needed - */ - StartABalance(); - } -} - -public SM_OnPlayerMoved(Handle:plugin, client, team) -{ - - /** - Make sure we called the move function - */ - if (plugin != GetMyHandle()) - { - if (g_bLogActivity2) - { - LogAction(0, client, "[STB] Callback was not started with current plugin, bugging out."); - } - return; - } - - /** - Get the players name and report the event - */ - decl String:sPlayerName[64]; - GetClientName(client, sPlayerName, sizeof(sPlayerName)); - if (g_bLogActivity) - { - LogAction(0, client, "[STB] Changed %s to team %i.", sPlayerName, team); - } - - /** - If we are in TF2 fire the bult-in team balance event - */ - if(g_CurrentMod == GameType_TF) - { - new Handle:event = CreateEvent("teamplay_teambalanced_player"); - SetEventInt(event, "player", client); - SetEventInt(event, "team", team); - FireEvent(event); - } - - /** - Notify the players - */ - PrintToChatAll("[SM] %T", "BalanceMessage", LANG_SERVER, sPlayerName); - - /** - Set the players variables and start a timer - */ - g_aPlayers[client][bSwitched] = true; - g_aPlayers[client][hForcedTimer] = CreateTimer(float(g_iSwitchBackForced), Timer_ForcedExpired, client, TIMER_FLAG_NO_MAPCHANGE); - - /** - We are done, log the completion and end the balance - */ - if (g_bLogActivity) - { - LogAction(0, client, "[STB] Balance finished."); - } - g_bBalanceInProgress = false; -} - -/* HOOKED EVENTS */ - -public HookPlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get our event variables - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - decl String:sWeapon[64]; - GetEventString(event, "weapon", sWeapon, sizeof(sWeapon)); - - /** - Return if death was not caused by a player - This is the case when the player switches teams - */ - if (StrEqual(sWeapon, "world", false)) - { - return; - } - - - /** - Check if balance is needed - */ - if (IsClientInGame(iClient) && OkToBalance() && IsUnbalanced()) - { - new iSmallerTeam = GetSmallerTeam(); - - /** - Check if balance is in progress - */ - if (g_bBalanceInProgress) - { - - /** - There is a balance in progress - Check the player who died to see if he is supposed to be switched - */ - if (g_aPlayers[iClient][hBalanceTimer] != INVALID_HANDLE) - { - - /** - The player has a timer on him to switch him to other team - Stop the timer - */ - CloseHandle(g_aPlayers[iClient][hBalanceTimer]); - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] With a balance in progress the queued living player died and was switched."); - } - - /** - Call the stock change team function - */ - BalancePlayer(iClient, SM_GetForcedTeam(iClient)); - return; - } - - /** - Before we continue, lets make sure the client is switchable - */ - if (IsSwitchablePlayer(iClient, GetBiggerTeam())) - { - - /** - Now we check the buddy system - */ - if (g_bBuddyEnabled) - { - - /** - Buddy system is enabled, check to see if client has buddy - */ - new iBuddyIndex = SM_GetClientBuddy(iClient); - if (iBuddyIndex != 0 || !IsClientConnected(iBuddyIndex) || !IsClientInGame(iBuddyIndex)) - { - - /** - The client has a buddy, so we check to see if they are on same team - */ - if (GetClientTeam(iClient) == GetClientTeam(iBuddyIndex)) - { - - /** - They are, but we don't bug out, we still need to start a balance - */ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] With a balance in progress a buddy on the right team was found and skipped."); - } - } - else - { - - /** - They are not on the same team - The buddy could be in spec, and that would make it not matter where he is, or the buddy is on the smaller team - */ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] With a balance in progress a buddy on the wrong team was switched."); - } - BalancePlayer(iClient, iSmallerTeam); - return; - } - } - else - { - - /** - Client doesn't have a buddy, balance this player - */ - BalancePlayer(iClient, iSmallerTeam); - return; - } - } - else - { - - /** - Buddy system is not enabled, balance this player - */ - BalancePlayer(iClient, iSmallerTeam); - return; - } - } - } - else - { - - /** - If we get to here then we must need to start a balance - */ - StartABalance(); - } - } -} - -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get our event variables. - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - new iTeam = GetEventInt(event, "team"); - - /** - Make sure its ok to balance. - */ - if (OkToBalance()) - { - - /** - See if the client that changed teams was set to with a balance. - */ - if (g_aPlayers[iClient][hBalanceTimer] != INVALID_HANDLE - && SM_GetForcedTeam(iClient) == iTeam - && g_bBalanceInProgress) - { - - /** - The client was set to be balanced, so we close the timer. - */ - CloseHandle(g_aPlayers[iClient][hBalanceTimer]); - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - - /** - Stop the balance. - */ - g_bBalanceInProgress = false; - return; - } - - /** - It's not likely that this team change can cause us to need a balance. - If it does, start one with a small dealy to deal with forced switch backs. - */ - if (IsUnbalanced() && !g_bBalanceInProgress) - { - CreateTimer(2.0, Timer_ChangeTeamBalanceDelay, _, TIMER_FLAG_NO_MAPCHANGE); - } - } -} - -public HookRoundStart(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set the variables we need to start a round - */ - g_bRoundStart = true; - g_bRoundEnd = false; - g_bSuddenDeath = false; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Round Started"); - } - - /** - Start a delayed balance check at the start of the round - */ - CreateTimer(float(g_iRoundStartDelay), Timer_RoundStart); -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set the variables we need at round end - */ - g_bRoundEnd = true; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Round Ended"); - } -} - -public HookSuddenDeathBegin(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Set the variables we need for sudden death - */ - g_bSuddenDeath = true; -} - -public HookFlagEvent(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get our event variables - */ - new iClient = GetEventInt(event, "player"); - new iFlagStatus = GetEventInt(event, "eventtype"); - - /** - Make sure we have a valid client - */ - if (!IsClientInGame(iClient)) - { - return; - } - - /** - Determine what kind of event this is - */ - switch (iFlagStatus) - { - case 1: - { - - /** - The flag was picked up - */ - g_aPlayers[iClient][bFlagCarrier] = true; - } - case 2: - { - - /** - The flag was capped - */ - g_aPlayers[iClient][bFlagCarrier] = false; - } - case 3: - { - - /** - The flag was defended, we don't have to do anything - */ - } - case 4: - { - - /** - The flag was dropped - */ - g_aPlayers[iClient][bFlagCarrier] = false; - } - } -} - -/* COMMAND EVENTS */ - -public Action:Command_AddBalanceBuddy(client, args) -{ - if (client == 0) - { - ReplyToCommand(client, "[SM] %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - if (!g_bIsEnabled || !g_bBuddyEnabled) - { - ReplyToCommand(client, "[SM] %T", "CmdDisabled", LANG_SERVER); - return Plugin_Handled; - } - if (g_bBuddyRestriction) - { - if (!SM_IsValidAdmin(client, g_sAdminFlag)) - { - ReplyToCommand(client, "[SM] %T", "RestrictedBuddy", LANG_SERVER); - return Plugin_Handled; - } - } - decl String:sPlayerUserId[24]; - GetCmdArg(1, sPlayerUserId, sizeof(sPlayerUserId)); - new iPlayer = GetClientOfUserId(StringToInt(sPlayerUserId)); - if (!iPlayer || !IsClientInGame(iPlayer) || client == iPlayer) - { - if (client == iPlayer) - { - PrintHintText(client, "%T", "SelectSelf", LANG_SERVER); - } - ReplyToCommand(client, "[SM] Usage: buddy "); - new Handle:playermenu = BuildPlayerMenu(); - DisplayMenu(playermenu, client, MENU_TIME_FOREVER); - } - else - { - decl String:cName[128]; - decl String:bName[128]; - GetClientName(client, cName, sizeof(cName)); - GetClientName(iPlayer, bName, sizeof(bName)); - if (SM_IsBuddyLocked(iPlayer)) - { - ReplyToCommand(client, "[SM] %T", "PlayerLockedBuddyMsg", LANG_SERVER, bName); - return Plugin_Handled; - } - SM_AssignBuddy(client, iPlayer); - PrintHintText(client, "%T", "BuddyMsg", LANG_SERVER, bName); - PrintHintText(iPlayer, "%T", "BuddyMsg", LANG_SERVER, cName); - } - return Plugin_Handled; -} - -public Action:Command_LockBuddy(client, args) -{ - if (client == 0) - { - ReplyToCommand(client, "[SM] %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - if (!g_bIsEnabled) - { - ReplyToCommand(client, "[SM] %T", "CmdDisabled", LANG_SERVER); - return Plugin_Handled; - } - if (g_bBuddyRestriction) - { - if (!SM_IsValidAdmin(client, g_sAdminFlag)) - { - ReplyToCommand(client, "[SM] %T", "RestrictedBuddy", LANG_SERVER); - return Plugin_Handled; - } - } - if (SM_IsBuddyLocked(client)) - { - SM_LockBuddy(client, false); - PrintHintText(client, "%T", "BuddyLockMsgDisabled", LANG_SERVER); - } - else - { - SM_LockBuddy(client, true); - PrintHintText(client, "%T", "BuddyLockMsgEnabled", LANG_SERVER); - } - return Plugin_Handled; -} - -/** -Stock functions . - */ - -stock bool:IsUnbalanced() -{ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Checking if teams are unbalanced"); - } - new Team1Count = GetTeamClientCount(g_aCurrentTeams[Team1]); - new Team2Count = GetTeamClientCount(g_aCurrentTeams[Team2]); - new ubCount = RoundFloat(FloatAbs(float(Team1Count - Team2Count))); - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Team1:%i Team2:%i Difference:%i", Team1Count, Team2Count, ubCount); - } - if (ubCount > g_iUnbalanceLimit) - { - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Teams are unbalanced"); - } - return true; - } - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Teams are not unbalanced"); - } - return false; -} - -stock bool:OkToBalance() -{ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Checking if OK to balance."); - } - new bool:bResult = false; - if (g_bIsEnabled && !g_bRoundStart && !g_bRoundEnd && !g_bIsArenaMode && !g_bSuddenDeath) - { - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Passed IF statement"); - LogAction(0, -1, "[STB] Now checking admins"); - } - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientInGame(i) && !SM_IsValidAdmin(i, g_sAdminFlag)) - { - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] Found at least 1 non-admin"); - LogAction(0, -1, "[STB] OK to balance"); - } - bResult = true; - break; - } - } - if (!bResult && g_bLogActivity2) - { - LogAction(0, -1, "[STB] All admins online"); - } - } - if (!bResult && g_bLogActivity2) - { - LogAction(0, -1, "[STB] Not OK to balance"); - } - return bResult; -} - -stock bool:IsSwitchablePlayer(iClient, iBiggerTeam) -{ - - /** - Run the client thru some standard checks - */ - if (!IsClientInGame(iClient) - || SM_IsValidAdmin(iClient, g_sAdminFlag) - || g_aPlayers[iClient][bFlagCarrier] - || GetClientTeam(iClient) != iBiggerTeam - || g_aPlayers[iClient][bSwitched]) - { - - /** - The supplied client can't be switched - */ - return false; - } - - /** - The supplied client can be switched - */ - return true; -} - -stock bool:HasUber(iClient) -{ - - /** - First things first, make sure the client is a medic - */ - if(TF2_GetPlayerClass(iClient) == TFClass_Medic) - { - - /** - We can only check the active weapon, so make sure the client is holding the uber gun - */ - decl String:sWeaponName[32]; - GetClientWeapon(iClient, sWeaponName, sizeof(sWeaponName)); - if(StrEqual(sWeaponName, "tf_weapon_medigun")) - { - - /** - They are, so lets check the uber level of the gun - */ - new iEntityIndex = GetEntDataEnt2(iClient, FindSendPropInfo("CTFPlayer", "m_hActiveWeapon")); - new Float:fChargeLevel = GetEntDataFloat(iEntityIndex, FindSendPropInfo("CWeaponMedigun", "m_flChargeLevel")); - if (fChargeLevel >= g_fUberLevel) - { - - /** - The client supplied has an uber above the supplied level, return true - */ - if (g_bLogActivity2) - { - LogAction(0, iClient, "[STB] Found a medic with a uber and skipped him."); - } - return true; - } - } - } - - /** - The client supplied does not have an uber above the supplied level, return false - */ - return false; -} - -stock bool:HasBuildingsBuilt(iClient) -{ - - /** - We have to start a loop to check the owner of all the valid entities - */ - new iMaxEntities = GetMaxEntities(); - for (new i = MaxClients + 1; i <= iMaxEntities; i++) - { - if (!IsValidEntity(i)) - { - - /** - Not valid, continue to next one - */ - continue; - } - - /** - Get the name of the current entity - */ - decl String:sNetClass[32]; - GetEntityNetClass(i, sNetClass, sizeof(sNetClass)); - - /** - See if its something that an engineer would build - */ - if (strcmp(sNetClass, "CObjectSentrygun") == 0 - || strcmp(sNetClass, "CObjectTeleporter") == 0 - || strcmp(sNetClass, "CObjectDispenser") == 0) - { - - /** - It is, so lets check the owner - */ - if (GetEntDataEnt2(i, g_iOwnerOffset) == iClient) - { - - /** - The client supplied is the owner, return true - */ - if (g_bLogActivity2) - { - LogAction(0, iClient, "[STB] Found an engineer with buildings and skipped him."); - } - return true; - } - } - } - - /** - The client supplied didn't have any buildings, return false - */ - return false; -} - -stock StartABalance() -{ - - /** - See if we are already started a balance - */ - if (g_hBalanceTimer != INVALID_HANDLE) - { - - /** - We have, check if we still need to - */ - if (!IsUnbalanced() || !OkToBalance()) - { - - /** - We don't, stop the balance - It's almost impossible to reach this code, but we do it just in case - */ - CloseHandle(g_hBalanceTimer); - g_hBalanceTimer = INVALID_HANDLE; - g_bBalanceInProgress = false; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Balance delay timer was not needed and was killed before the callback."); - } - return; - } - else - { - - /** - We still need to balance - Bug out and wait for the current one to finish - */ - return; - } - } - - /** - Report that teams are unbalanced - */ - PrintToChatAll("[SM] %T", "UnBalanced", LANG_SERVER); - - /** - Check to see if we are supposed to delay the balance - */ - if (g_iBalanceDelay == 0) - { - - /** - Start the balance now - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Balance is now in progress."); - } - g_bBalanceInProgress = true; - g_hBalanceTimer = INVALID_HANDLE; - - /** - Check if we are allowed to scan living players - */ - if (!g_bDeadOnly) - { - - /** - We are allowed to, so we start a timer - */ - StartALivingPlayerTimer(); - - /** - Also report that we are now scanning dead players as well - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Now scanning dead players."); - } - } - else - { - - /** - We are not allowed to, so report that we are only scanning dead players - */ - if (g_bLogActivity) - LogAction(0, -1, "[STB] Only scanning dead players."); - } - - /** - We started the balance, bug out - */ - return; - } - - /** - We are supposed to delay the balance, start a balance timer - */ - g_hBalanceTimer = CreateTimer(float(g_iBalanceDelay), Timer_BalanceTeams, _, TIMER_FLAG_NO_MAPCHANGE); - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Teams are unbalanced. Balance delay timer started."); - } -} - -stock StartALivingPlayerTimer() -{ - - /** - Start a timer to check living players - */ - if (g_hLivingPlayerCheckTimer != INVALID_HANDLE) - { - - /** - If we for some reason already have one started, stop it. - */ - CloseHandle(g_hLivingPlayerCheckTimer); - g_hLivingPlayerCheckTimer = INVALID_HANDLE; - } - - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Living player balance delay timer started."); - } - g_hLivingPlayerCheckTimer = CreateTimer(float(g_iLivingPlayerCheckDelay), Timer_LivingPlayerCheck, _, TIMER_FLAG_NO_MAPCHANGE); -} - -stock FindSwitchablePlayer() -{ - - /** - Start a loop to find a switchable player - */ - new iPlayer; - new iBiggerTeam = GetBiggerTeam(); - for (new i = 1; i <= MaxClients; i++) - { - - /** - Check the stock function to see if we are allows to even switch the player - */ - if (!IsSwitchablePlayer(i, iBiggerTeam)) - { - continue; - } - - /** - If the mod is TF2 and they have Priority Players set check if the client has buildings or an uber - */ - if (g_CurrentMod == GameType_TF && g_bPriorityPlayers) - { - if (HasUber(i) || HasBuildingsBuilt(i)) - { - continue; - } - } - - /** - So far we are able we switch this player - Now we check the buddy system - */ - if (g_bBuddyEnabled) - { - - /** - Buddy system is enabled, check to see if client has buddy - */ - if (SM_GetClientBuddy(i) != 0) - { - - /** - The client has a buddy, so we check to see if they are on same team - */ - if (GetClientTeam(i) == GetClientTeam(SM_GetClientBuddy(i))) - { - - /** - They are, so we continue to next client - */ - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] With a balance in progress a buddy on the right team was found and skipped."); - } - continue; - } - else - { - - /** - They are not on the same team, set this client - The buddy could be in spec, and that would make it not matter where he is, or the buddy is on the smaller team - */ - iPlayer = i; - if (g_bLogActivity2) - { - LogAction(0, -1, "[STB] With a balance in progress a buddy on the wrong team was found."); - } - break; - } - } - else - { - - /** - The client does not have a buddy, set this client - */ - iPlayer = i; - break; - } - } - else - { - - /** - Buddy system is not enabled, set this client - */ - iPlayer = i; - break; - } - } - - /** - Return the client we set, this could be 0, but very unlikely - */ - return iPlayer; -} - -stock BalancePlayer(iClient, iTeam) -{ - new Handle:hPack = CreateDataPack(); - WritePackCell(hPack, iClient); - WritePackCell(hPack, iTeam); - CreateTimer(0.1, Timer_BalancePlayer, hPack, TIMER_FLAG_NO_MAPCHANGE); -} - -stock CleanUp(iClient) -{ - g_aPlayers[iClient][bFlagCarrier] = false; - g_aPlayers[iClient][bSwitched] = false; - if (g_aPlayers[iClient][hForcedTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hForcedTimer]); - g_aPlayers[iClient][hForcedTimer] = INVALID_HANDLE; - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] Forced player disconnected, killing timer."); - } - } - if (g_aPlayers[iClient][hBalanceTimer] != INVALID_HANDLE) - { - CloseHandle(g_aPlayers[iClient][hBalanceTimer]); - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] Living player set to be balanced disconnected, killing timer."); - } - } -} - -stock GetSmallerTeam() -{ - - /** - Get the count of players on each team - */ - new iCountT1 = GetTeamClientCount(g_aCurrentTeams[Team1]); - new iCountT2 = GetTeamClientCount(g_aCurrentTeams[Team2]); - - /** - Return the smaller team - */ - if (iCountT1 < iCountT2) - { - return g_aCurrentTeams[Team1]; - } - else if (iCountT1 > iCountT2) - { - return g_aCurrentTeams[Team2]; - } - return 0; -} - -stock GetBiggerTeam() -{ - - /** - Get the count of players on each team - */ - new iCountT1 = GetTeamClientCount(g_aCurrentTeams[Team1]); - new iCountT2 = GetTeamClientCount(g_aCurrentTeams[Team2]); - - /** - Return the bigger team - */ - if (iCountT1 > iCountT2) - { - return g_aCurrentTeams[Team1]; - } - else if (iCountT1 < iCountT2) - { - return g_aCurrentTeams[Team2]; - } - return 0; -} - -stock SetGameCvars() -{ - if (g_bConVarControl && g_bIsEnabled) - { - if (stb_mp_autoteambalance != INVALID_HANDLE) - { - SetConVarInt(stb_mp_autoteambalance, 0); - } - if (stb_mp_teams_unbalance_limit != INVALID_HANDLE) - { - SetConVarInt(stb_mp_teams_unbalance_limit, g_iUnbalanceLimit); - } - } -} - -/* TIMER FUNCTIONS */ - -public Action:Timer_ChangeTeamBalanceDelay(Handle:timer, any:data) -{ - - /** - Finally start one if it's still unbalanced - */ - if (IsUnbalanced() && !g_bBalanceInProgress) - { - StartABalance(); - } -} - -public Action:Timer_BalanceTeams(Handle:timer, any:data) -{ - - /** - See if we still need to balance the teams - */ - if (!IsUnbalanced() || !OkToBalance()) - { - - /** - We don't, kill the balance - */ - g_bBalanceInProgress = false; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Balance delay timer was not needed and died."); - } - g_hBalanceTimer = INVALID_HANDLE; - return Plugin_Handled; - } - - /** - We still need to balance the teams - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Teams are still unbalanced. Balance is now in progress."); - } - g_bBalanceInProgress = true; - - - /** - Check if we are allowed to scan living players - */ - if (!g_bDeadOnly) - { - - /** - We are allowed to, so we start a timer - */ - StartALivingPlayerTimer(); - - /** - Also report that we are now scanning dead players as well - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Now scanning dead players."); - } - } - else - { - - /** - We are not allowed to, so report that we are only scanning dead players - */ - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Only scanning dead players."); - } - } - - g_hBalanceTimer = INVALID_HANDLE; - return Plugin_Handled; -} - -public Action:Timer_LivingPlayerCheck(Handle:timer, any:data) -{ - - /** - Check to see if we still need to balance the teams - */ - if (!IsUnbalanced() || !OkToBalance()) - { - - /** - We don't, kill it and bug out - */ - g_bBalanceInProgress = false; - if (g_bLogActivity) - { - LogAction(0, -1, "[STB] Living player balance delay timer was not needed and died."); - } - g_hLivingPlayerCheckTimer = INVALID_HANDLE; - return Plugin_Handled; - } - - /** - Call the stock function to find a player we can switch - */ - new iPlayer = FindSwitchablePlayer(); - - /** - Check to see if we found a player - */ - if (iPlayer == 0) - { - - /** - In the unlikely event that the stock function didn't return a player - Start a loop to find a random player - */ - new iBiggerTeam = GetBiggerTeam(); - do - { - iPlayer = GetRandomInt(1, MaxClients); - } while (!IsSwitchablePlayer(iPlayer, iBiggerTeam)); - - if (g_bLogActivity) - { - LogAction(0, iPlayer, "[STB] Found a random living player."); - } - } - else - { - if (g_bLogActivity) - { - LogAction(0, iPlayer, "[STB] Found a living player."); - } - } - - /** - Now that we have a player assigned them to the smaller team - */ - new iSmallerTeam = GetSmallerTeam(); - SM_SetForcedTeam(iPlayer, iSmallerTeam, true); - - /** - Let the player know we could be switching him soon - */ - PrintHintText(iPlayer, "%T", "PlayerMessage", LANG_SERVER, g_iLivingPlayerSwitchDelay); - if (g_bLogActivity) - { - LogAction(0, iPlayer, "[STB] Living player placed on a timer."); - } - - /** - Create a timer to switch the player - */ - g_aPlayers[iPlayer][hBalanceTimer] = CreateTimer(float(g_iLivingPlayerSwitchDelay), Timer_LivingPlayerBalance, iPlayer, TIMER_FLAG_NO_MAPCHANGE); - - /** - Reset the timer handle - */ - g_hLivingPlayerCheckTimer = INVALID_HANDLE; - - /** - We are done, bug out - */ - return Plugin_Handled; -} - -public Action:Timer_LivingPlayerBalance(Handle:timer, any:iClient) -{ - - /** - Check to make sure we still need to balance - */ - if (!IsUnbalanced() || !OkToBalance()) - { - - /** - We don't need to balance, bug out - */ - g_bBalanceInProgress = false; - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - SM_ClearForcedTeam(iClient); - return Plugin_Handled; - } - - /** - We still need to balance, lets make sure we can still balance this player - */ - if (!IsClientConnected(iClient) || g_aPlayers[iClient][bFlagCarrier]) - { - g_bBalanceInProgress = false; - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - SM_ClearForcedTeam(iClient); - if (g_bLogActivity) - { - if (g_aPlayers[iClient][bFlagCarrier]) - { - LogAction(0, iClient, "[STB] Living player became flag carrier, balance restarted."); - } - else - { - LogAction(0, iClient, "[STB] Living player timer was not needed and died."); - } - } - return Plugin_Handled; - } - - /** - Clear to balance this player, so do it - */ - BalancePlayer(iClient, SM_GetForcedTeam(iClient)); - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] Living player was switched."); - } - - /** - We are done, bug out - */ - g_aPlayers[iClient][hBalanceTimer] = INVALID_HANDLE; - return Plugin_Handled; -} - -public Action:Timer_BalancePlayer(Handle:timer, Handle:pack) -{ - - /** - Rest the datapack and load the variables - */ - ResetPack(pack); - new iClient = ReadPackCell(pack); - new iUnBalancedTeam = ReadPackCell(pack); - - /** - We are done with you now - */ - CloseHandle(pack); - - /** - Check the team and make sure its a valid team - */ - if(!SM_IsValidTeam(iUnBalancedTeam)) - { - if (g_bLogActivity) - { - LogAction(0, iClient, "[STB] Balance failed due to invalid team number %i", iUnBalancedTeam); - } - return Plugin_Handled; - } - - /** - Use our core function to change the clients team - */ - SM_MovePlayer(iClient, iUnBalancedTeam); - - return Plugin_Handled; -} - -public Action:Timer_RoundStart(Handle:timer, any:data) -{ - g_bRoundStart = false; - if (OkToBalance() && IsUnbalanced() && !g_bBalanceInProgress) - { - StartABalance(); - } - return Plugin_Handled; -} - -public Action:Timer_ForcedExpired(Handle:timer, any:iClient) -{ - SM_ClearForcedTeam(iClient); - g_aPlayers[iClient][bSwitched] = false; - g_aPlayers[iClient][hForcedTimer] = INVALID_HANDLE; - return Plugin_Handled; -} - -public Action:Timer_WelcomeAdvert(Handle:timer, any:iClient) -{ - if (IsClientConnected(iClient) && IsClientInGame(iClient)) - { - PrintToChat (iClient, "\x01\x04[STB]\x01 %T", "BuddyWelcomeMsg1", LANG_SERVER); - PrintToChat (iClient, "\x01\x04[STB]\x01 %T", "BuddyWelcomeMsg2", LANG_SERVER); - PrintToChat (iClient, "\x01\x04[STB]\x01 %T", "BuddyWelcomeMsg3", LANG_SERVER); - } - return Plugin_Handled; -} - -/* CONSOLE VARIABLE CHANGE EVENT */ - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (convar == stb_enabled) - { - if (StringToInt(newValue) == 0) - { - g_bIsEnabled = false; - PrintToChatAll("[SM] %T", "Disabled", LANG_SERVER); - LogAction(0, -1, "[SimpleTeamBalancer] Disabled"); - } - else - { - g_bIsEnabled = true; - SetGameCvars(); - PrintToChatAll("[SM] %T", "Enabled", LANG_SERVER); - LogAction(0, -1, "[SimpleTeamBalancer] Enabled"); - } - } - else if (convar == stb_logactivity) - { - if (StringToInt(newValue) == 0) - { - g_bLogActivity = false; - LogAction(0, -1, "[STB] Log Activity DISABLED."); - } - else - { - g_bLogActivity = true; - LogAction(0, -1, "[STB] Log Activity ENABLED."); - } - } - else if (convar == stb_logactivity2) - { - if (StringToInt(newValue) == 0) - { - g_bLogActivity2 = false; - LogAction(0, -1, "[STB] Detailed Log Activity DISABLED."); - } - else - { - g_bLogActivity2 = true; - LogAction(0, -1, "[STB] Detailed Log Activity ENABLED."); - } - } - else if (convar == stb_convarcontrol) - { - if (StringToInt(newValue) == 0) - { - g_bConVarControl = false; - } - else - { - g_bConVarControl = true; - SetGameCvars(); - } - } - else if (convar == stb_deadonly) - { - if (StringToInt(newValue) == 0) - { - g_bDeadOnly = false; - } - else - { - g_bDeadOnly = true; - } - } - else if (convar == stb_priorityenabled) - { - if (StringToInt(newValue) == 0) - { - g_bPriorityPlayers = false; - } - else - { - g_bPriorityPlayers = true; - } - } - else if (convar == stb_buddyenabled) - { - if (StringToInt(newValue) == 0) - { - g_bBuddyEnabled = false; - } - else - { - g_bBuddyEnabled = true; - } - } - else if (convar == stb_buddyrestriction) - { - if (StringToInt(newValue) == 0) - { - g_bBuddyRestriction = false; - } - else - { - g_bBuddyRestriction = true; - } - } - else if (convar == stb_unbalancelimit) - { - g_iUnbalanceLimit = StringToInt(newValue); - SetGameCvars(); - } - else if (convar == stb_balancedelay) - { - g_iBalanceDelay = StringToInt(newValue); - } - else if (convar == stb_roundstartdelay) - { - g_iRoundStartDelay = StringToInt(newValue); - } - else if (convar == stb_livingplayerswitchdelay) - { - g_iLivingPlayerSwitchDelay = StringToInt(newValue); - } - else if (convar == stb_livingplayercheckdelay) - { - g_iLivingPlayerCheckDelay = StringToInt(newValue); - } - else if (convar == stb_uberlevel) - { - g_fUberLevel = StringToFloat(newValue); - } - else if (convar == stb_switchbackforced) - { - g_iSwitchBackForced = StringToInt(newValue); - } - else if (convar == stb_adminflag) - { - SetConVarString(stb_adminflag, newValue); - } - else if (convar == stb_mp_autoteambalance) - { - SetGameCvars(); - } - else if (convar == stb_mp_teams_unbalance_limit) - { - SetGameCvars(); - } -} - -/* MENU CODE */ - -stock Handle:BuildPlayerMenu() -{ - new Handle:menu = CreateMenu(Menu_SelectPlayer); - AddTargetsToMenu(menu, 0, true, false); - SetMenuTitle(menu, "Select A Player:"); - SetMenuExitButton(menu, true); - return menu; -} - -public Menu_SelectPlayer(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[24]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - new buddy = GetClientOfUserId(StringToInt(sSelection)); - if (param1 == buddy) { - PrintHintText(param1, "%T", "SelectSelf", LANG_SERVER); - } else if (!IsClientInGame(buddy)) { - PrintHintText(param1, "%T", "BuddyGone", LANG_SERVER); - } else { - decl String:cName[128]; - decl String:bName[128]; - GetClientName(param1, cName, sizeof(cName)); - GetClientName(buddy, bName, sizeof(bName)); - if (!SM_IsBuddyLocked(buddy)) { - SM_AssignBuddy(param1, buddy); - PrintHintText(param1, "%T", "BuddyMsg", LANG_SERVER, bName); - PrintHintText(buddy, "%T", "BuddyMsg", LANG_SERVER, cName); - } else - PrintHintText(param1, "%T", "PlayerLockedBuddyMsg", LANG_SERVER, bName); - } - } else if (action == MenuAction_End) { - CloseHandle(menu); - } -} \ No newline at end of file diff --git a/addons/sourcemod/scripting/simple-teammanager.sp b/addons/sourcemod/scripting/simple-teammanager.sp deleted file mode 100644 index 008f443..0000000 --- a/addons/sourcemod/scripting/simple-teammanager.sp +++ /dev/null @@ -1,1351 +0,0 @@ -/************************************************************************ -************************************************************************* -Simple Team Manager -Description: - Manges players and their team - Admin menu integration - Allows admins/donators to swap their teams (clears force)* - Allows admins to move players to a team (forced\unforced)* - Allows admins to scramble the teams* - *Works with Simple Team Balancer (if installed) -************************************************************************* -************************************************************************* -This file is part of Simple Plugins project. - -This plugin is free software: you can redistribute -it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the License, or -later version. - -This plugin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this plugin. If not, see . -************************************************************************* -************************************************************************* -File Information -$Id$ -$Author$ -$Revision$ -$Date$ -$LastChangedBy$ -$LastChangedDate$ -$URL$ -$Copyright: (c) Simple Plugins 2008-2009$ -************************************************************************* -************************************************************************* -*/ - -#include - -#define PLUGIN_VERSION "2.1.$Rev$" -#define VOTE_YES "##YES##" -#define VOTE_NO "##NO##" - -enum PlayerData -{ - iNewTeam, - bool:bQueue -}; - -new Handle:stm_enabled = INVALID_HANDLE; -new Handle:stm_logactivity = INVALID_HANDLE; -new Handle:stm_adminflag_swapteam = INVALID_HANDLE; -new Handle:stm_adminflag_moveplayer = INVALID_HANDLE; -new Handle:stm_adminflag_scramble = INVALID_HANDLE; -new Handle:stm_scrambledelay = INVALID_HANDLE; -new Handle:stm_voteenabled = INVALID_HANDLE; -new Handle:stm_votewin = INVALID_HANDLE; -new Handle:stm_votedelay = INVALID_HANDLE; -new Handle:stm_mp_bonusroundtime = INVALID_HANDLE; -new Handle:g_hAdminMenu = INVALID_HANDLE; -new Handle:g_hTimerPrepScramble = INVALID_HANDLE; -new Handle:g_hTimerClearScrambleForce = INVALID_HANDLE; - -new g_aPlayers[MAXPLAYERS + 1][PlayerData]; - -new bool:g_bIsEnabled = true; -new bool:g_bVoteEnabled = true; -new bool:g_bLogActivity = true; -new bool:g_bScrambleRoundEnd = false; -new g_iVoteDelay, g_iLastVoteTime, g_iTimeLeft; -new Float:g_fScrambleDelay, Float:g_fVoteWin; - -public Plugin:myinfo = -{ - name = "Simple Team Manager", - author = "Simple Plugins", - description = "Manages players and thier team.", - version = PLUGIN_VERSION, - url = "http://www.simple-plugins.com" -}; - -public OnPluginStart() -{ - - /** - Need to create all of our console variables. - */ - CreateConVar("stm_version", PLUGIN_VERSION, "Simple Team Manager Version",FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); - stm_enabled = CreateConVar("stm_enabled", "1", "Enable or Disable Simple Team Manager", _, true, 0.0, true, 1.0); - stm_logactivity = CreateConVar("stm_logactivity", "0", "Enable or Disable the disaplying of events in the log", _, true, 0.0, true, 1.0); - stm_adminflag_swapteam = CreateConVar("stm_adminflag_swapteam", "a", "Admin flag to use for the swapteam command. Must be a in char format."); - stm_adminflag_moveplayer = CreateConVar("stm_adminflag_moveplayer", "c", "Admin flag to use for the moveplayer command. Must be a in char format."); - stm_adminflag_scramble = CreateConVar("stm_adminflag_scramble", "c", "Admin flag to use for the scrambleteam command. Must be a in char format."); - stm_scrambledelay = CreateConVar("stm_scrambledelay", "15", "Delay to scramble teams"); - stm_voteenabled = CreateConVar("stm_voteenabled", "1", "Enable or Disable voting to scramble the teams", _, true, 0.0, true, 1.0); - stm_votewin = CreateConVar("stm_votewin", "0.45", "Win percentage vote must win by", _, true, 0.0, true, 1.0); - stm_votedelay = CreateConVar("stm_votedelay", "600", "Delay before another vote can be cast"); - stm_mp_bonusroundtime = FindConVar("mp_bonusroundtime"); - - - /** - Need deal with changes to the console variables after the plugin is loaded. - We could not do this and just call the actual console variable each time we need it, but it's not efficent. - */ - HookConVarChange(stm_enabled, ConVarSettingsChanged); - HookConVarChange(stm_logactivity, ConVarSettingsChanged); - HookConVarChange(stm_scrambledelay, ConVarSettingsChanged); - HookConVarChange(stm_voteenabled, ConVarSettingsChanged); - HookConVarChange(stm_votewin, ConVarSettingsChanged); - HookConVarChange(stm_votedelay, ConVarSettingsChanged); - - /** - Need to register the commands we are going to create and use. - */ - RegConsoleCmd("sm_swapteam", Command_SwapTeam, "sm_swapteam <[0]instant/[1]queued>: Swaps your team to the other team"); - RegConsoleCmd("sm_moveplayer", Command_MovePlayer, "sm_moveplayer <[0]instant/[1]ondeath> <[0]unforced/[1]forced>: Moves a player to the specified team"); - RegConsoleCmd("sm_scrambleteams", Command_ScrambleTeams, "sm_scrambleteams: <[0]now/[1]roundend> <[0]dontrestart/[1]restartround> Scrambles the current teams"); - RegConsoleCmd("sm_votescramble", Command_VoteScramble, "sm_votescramble: Starts a vote to scramble the teams"); - - /** - Get game type and load the team numbers - */ - g_CurrentMod = GetCurrentMod(); - LoadCurrentTeams(); - - /** - Hook the game events - */ - LogAction(0, -1, "[STM] Hooking events for [%s].", g_sGameName[g_CurrentMod]); - HookEvent("player_death", HookPlayerDeath, EventHookMode_Post); - HookEvent("player_team", HookPlayerChangeTeam, EventHookMode_Post); - switch (g_CurrentMod) - { - case GameType_TF: - { - HookEvent("teamplay_round_win", HookRoundEnd, EventHookMode_Post); - } - case GameType_DOD: - { - HookEvent("dod_round_win", HookRoundEnd, EventHookMode_Post); - } - default: - { - HookEvent("round_end", HookRoundEnd, EventHookMode_PostNoCopy); - } - } - - /** - Now we have to deal with the admin menu. If the admin library is loaded call the function to add our items. - */ - new Handle:gTopMenu; - if (LibraryExists("adminmenu") && ((gTopMenu = GetAdminTopMenu()) != INVALID_HANDLE)) - { - OnAdminMenuReady(gTopMenu); - } - - /** - Load translations and .cfg file - */ - LoadTranslations ("simpleteammanager.phrases"); - AutoExecConfig(true, "plugin.simpleteammanager"); - LogAction(0, -1, "[STM] Simple Team Manager is loaded."); -} - -public OnAllPluginsLoaded() -{ - //something -} - -public OnLibraryRemoved(const String:name[]) -{ - if (StrEqual(name, "adminmenu")) - { - - /** - Looks like the admin menu was removed. Set the global. - */ - g_hAdminMenu = INVALID_HANDLE; - } - else if (StrEqual(name, "simpleplugins")) - { - SetFailState("Required plugin Simple SourceMod Plugins Core was removed."); - } -} - -public OnConfigsExecuted() -{ - - /** - Once we loaded up all the console variables from the config file, lets now set all the global variables we will use. - */ - g_bIsEnabled = GetConVarBool(stm_enabled); - g_bLogActivity = GetConVarBool(stm_logactivity); - g_fScrambleDelay = GetConVarFloat(stm_scrambledelay); - g_iVoteDelay = GetConVarInt(stm_votedelay); - g_fVoteWin = GetConVarFloat(stm_votewin); - g_iLastVoteTime = RoundFloat(GetEngineTime()); - g_bScrambleRoundEnd = false; - g_hTimerClearScrambleForce = INVALID_HANDLE; - - /** - Report enabled - */ - if (g_bIsEnabled) - { - LogAction(0, -1, "[STM] Simple Team Manager is ENABLED."); - } - else - { - LogAction(0, -1, "[STM] Simple Team Manager is DISABLED."); - } - - if (g_bLogActivity) - { - LogAction(0, -1, "[STM] Log Activity ENABLED."); - } - else - { - LogAction(0, -1, "[STM] Log Activity DISABLED."); - } -} - -/* COMMANDS */ - -public Action:Command_SwapTeam(client, args) -{ - - /** - Make sure we are enabled, if not bug out. - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - If this was ran from the console bug out. - */ - if (client == 0) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "PlayerLevelCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure the client is authorized to run this command. - */ - decl String:sFlags[5]; - GetConVarString(stm_adminflag_swapteam, sFlags, sizeof(sFlags)); - if (!SM_IsValidAdmin(client, sFlags)) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Lets make sure the client is one a team we can swap. - If he is we set the global array to the opposite team. - */ - new iTeam = GetClientTeam(client); - if (iTeam == g_aCurrentTeams[Team1]) - { - g_aPlayers[client][iNewTeam] = g_aCurrentTeams[Team2]; - } - else if (iTeam == g_aCurrentTeams[Team2]) - { - g_aPlayers[client][iNewTeam] = g_aCurrentTeams[Team1]; - } - else - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "InValidTeam", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check to see if we have command arguments. - */ - if (GetCmdArgs()) - { - - /** - We do, so lets get it and see if the client wants to be switched instantly or queued for death. - */ - decl String:sArg[5]; - GetCmdArg(1, sArg, sizeof(sArg)); - new iWantsQue = StringToInt(sArg); - if (iWantsQue && !g_aPlayers[client][bQueue]) - { - - /** - He wants the que and isn't already in it, set the global array. - */ - g_aPlayers[client][bQueue] = true; - ReplyToCommand(client, "\x01\x04[STM]\x01 %T", "PlayerQueue", LANG_SERVER); - } - else if (!iWantsQue) - { - - /** - He wants to be switched right now, lets call the stock function. - */ - SM_MovePlayer(client, g_aPlayers[client][iNewTeam]); - } - } - else - { - - /** - There are no command arguments so we build and display the swap menu. - */ - DisplaySwapModeMenu(client, client); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_MovePlayer(client, args) -{ - - /** - Make sure we are enabled, if not bug out. - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the client is authorized to run this command. - */ - decl String:sFlags[5]; - GetConVarString(stm_adminflag_moveplayer, sFlags, sizeof(sFlags)); - if (!SM_IsValidAdmin(client, sFlags)) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check to see if we have command arguments. - */ - new iCmdArgs = GetCmdArgs(); - if (iCmdArgs == 0) - { - - /** - We don't. Build the player menu, display it, and bug out. - */ - DisplayPlayerMenu(client); - return Plugin_Handled; - } - - /** - Check the first argument - If should be a players name or userid. - */ - decl String:sPlayer[64]; - GetCmdArg(1, sPlayer, sizeof(sPlayer)); - new iPlayerIndex = FindTarget(client, sPlayer, true, true); - if (iPlayerIndex == -1 || !IsClientInGame(iPlayerIndex)) - { - - /** - We don't know who this is. Build the player menu, display it, and bug out. - */ - DisplayPlayerMenu(client); - return Plugin_Handled; - } - - /** - We have figured out the first argument, lets check the second. - If should be the team the client wants to put the player on. - */ - if (iCmdArgs >= 2) - { - - /** - We have a command argument at least, lets see if we can identify the team. - */ - decl String:sTeam[24]; - GetCmdArg(2, sTeam, sizeof(sTeam)); - - new iTeam = StringToInt(sTeam); - if (SM_IsValidTeam(iTeam)) - { - - /** - It's a vaild team so lets set the global array to the new team. - */ - g_aPlayers[iPlayerIndex][iNewTeam] = iTeam; - } - else - { - - /** - It's not a vaild team so set the menu to display to the team menu. - */ - DisplayTeamMenu(client, iPlayerIndex); - return Plugin_Handled; - } - } - else - { - /** - We were not given a team, display the team menu. - */ - DisplayTeamMenu(client, iPlayerIndex); - return Plugin_Handled; - } - - /** - Check to see if we were given any more command arguments and found a team. - */ - if (iCmdArgs < 3) - { - - /** - No more command arguments and found a team. - Now lets check to see if the player is a spectator. If he is there is no reason to ask if it's instant or on death... he can't die. - */ - if (!IsClientObserver(iPlayerIndex)) - { - - /** - Not a spectator so display the swapmode menu. - */ - DisplaySwapModeMenu(client, iPlayerIndex); - } - else - { - - /** - The player is a spectator. - We make sure the player is not set to switch on death, since a spec can't die. - */ - g_aPlayers[iPlayerIndex][bQueue] = false; - } - } - - /** - We have figured out the second argument, lets check the third. - If should be the how the client wants to move the player: instant/on death. - */ - if (iCmdArgs >= 3) - { - - /** - The client gave us a command argument, lets check it. - */ - decl String:sSwapMode[5]; - GetCmdArg(3, sSwapMode, sizeof(sSwapMode)); - new iWantsQue = StringToInt(sSwapMode); - if (iWantsQue) - { - - /** - The client wants to que the player, set the global array. - */ - g_aPlayers[iPlayerIndex][bQueue] = true; - } - else - { - - /** - The client doesn't want to que the player, set the global array. - */ - g_aPlayers[iPlayerIndex][bQueue] = false; - } - } - else - { - /** - No swapmode argument, display the menu - */ - DisplaySwapModeMenu(client, iPlayerIndex); - } - - if (iCmdArgs >= 4) - { - - /** - Since we are compiling for Simple Team Balancer, and given a 4th argument, lets check it. - If should be the if the client wants to force the player to that team. - */ - decl String:sPlayerForced[5]; - GetCmdArg(4, sPlayerForced, sizeof(sPlayerForced)); - new iForceHim = StringToInt(sPlayerForced); - if (iForceHim) - { - - /** - The client wants to force the player - */ - SM_SetForcedTeam(iPlayerIndex, g_aPlayers[iPlayerIndex][iNewTeam]); - } - else - { - - /** - The client doesn't want to force the player - */ - SM_ClearForcedTeam(iPlayerIndex); - } - } - else - { - - } - - /** - We found and processed all the arguments. - */ - if (!IsPlayerAlive(iPlayerIndex)) - { - - /** - The player is not alive or died during this process so we just move him. - */ - SM_MovePlayer(iPlayerIndex, g_aPlayers[iPlayerIndex][iNewTeam]); - } - else - { - if (!g_aPlayers[iPlayerIndex][bQueue]) - { - - /** - The player is alive and is not set to be queued so we just move him. - */ - SM_MovePlayer(iPlayerIndex, g_aPlayers[iPlayerIndex][iNewTeam]); - } - } - - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_ScrambleTeams(client, args) -{ - - /** - Make sure we are enabled, if not bug out. - */ - if (!g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Make sure the client is authorized to run this command. - */ - decl String:sFlags[5]; - GetConVarString(stm_adminflag_scramble, sFlags, sizeof(sFlags)); - if (!SM_IsValidAdmin(client, sFlags)) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "RestrictedCmd", LANG_SERVER); - return Plugin_Handled; - } - - /** - Check if a scramble timer was already called, if so close it down. - */ - if (g_hTimerPrepScramble != INVALID_HANDLE) - { - CloseHandle(g_hTimerPrepScramble); - g_hTimerPrepScramble = INVALID_HANDLE; - } - - /** - Check if we have any command arguments. - If we don't we display the scramble menu and bug out. - */ - new iCmdArgs = GetCmdArgs(); - if (iCmdArgs == 0) - { - DisplayScrambleMenu(client); - return Plugin_Handled; - } - - /** - We have a command argument. - It should be whether or not to scramble at round end. - */ - decl String:sRoundEnd[5]; - GetCmdArg(1, sRoundEnd, sizeof(sRoundEnd)); - if (StringToInt(sRoundEnd)) - { - /** - The client wants to scramble at round end so we set the global bool. - */ - g_bScrambleRoundEnd = true; - } - else - { - g_bScrambleRoundEnd = false; - } - - /** - Check for another command argument. - It should be whether or not to restart the round. - */ - decl String:sRestartRound[5]; - new bool:bRestartRound = false; - GetCmdArg(1, sRestartRound, sizeof(sRestartRound)); - if (StringToInt(sRestartRound)) - { - bRestartRound = true; - } - - /** - Now we start the scramble timer. - */ - StartScrambleTimer(_, bRestartRound); - - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Command_VoteScramble(client, args) -{ - - /** - Make sure we are enabled, if not bug out. - */ - if (!g_bVoteEnabled || !g_bIsEnabled) - { - return Plugin_Handled; - } - - /** - Make sure there is a vote in progress, if so bug out. - */ - if (IsVoteInProgress()) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "VoteInProgress", LANG_SERVER); - return Plugin_Handled; - } - - /** - Make sure enough time has passed since the last vote. - */ - new iVoteTime = RoundFloat(GetEngineTime()); - if (iVoteTime - g_iLastVoteTime <= g_iVoteDelay) - { - ReplyToCommand(client, "\x01\x04[SM]\x01 %T", "ScrambleTime", LANG_SERVER); - return Plugin_Handled; - } - - /** - Enough time has passed so reset the global vote time to now. - */ - g_iLastVoteTime = iVoteTime; - - /** - Build the vote menu and send it to everyone. - */ - new Handle:hMenu = CreateMenu(Menu_VoteScramble); - SetMenuTitle(hMenu, "Scramble Teams?"); - AddMenuItem(hMenu, VOTE_YES, "Yes"); - AddMenuItem(hMenu, VOTE_NO, "No"); - SetMenuExitButton(hMenu, false); - VoteMenuToAll(hMenu, 20); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -/* HOOKED EVENTS */ - -public HookPlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Find out who died. - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - - /** - Find out how the client died. - */ - new String:sWeapon[64]; - GetEventString(event, "weapon", sWeapon, sizeof(sWeapon)); - if (StrEqual(sWeapon, "world", false)) - { - - /** - He died because he changed teams so cleanup and bug out. - */ - s_CleanUp(iClient); - return; - } - - /** - Find out if this player was queued to change teams. - */ - if (g_aPlayers[iClient][bQueue]) - { - /** - Looks like he was, so call the stock function to move him. - */ - SM_MovePlayer(iClient, g_aPlayers[iClient][iNewTeam]); - } -} - -public HookPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Find out who changed teams. - */ - new iClient = GetClientOfUserId(GetEventInt(event, "userid")); - - /** - If he was queued to switch teams we cleanup the variables. The client did it themself. - */ - if (g_aPlayers[iClient][bQueue]) - { - s_CleanUp(iClient); - } -} - -public HookRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - - /** - Get the amount of time left in the map. - */ - new iTimeLeft; - GetMapTimeLeft(iTimeLeft); - - /** - Check to see if we are supposed to scramble at the end of the round and that there is enough time left in the map. - */ - if (g_bScrambleRoundEnd && iTimeLeft >= 60) - { - - /** - Check to see if there is a scramble timer in action and if so close it down. - */ - if (g_hTimerPrepScramble != INVALID_HANDLE) - { - CloseHandle(g_hTimerPrepScramble); - g_hTimerPrepScramble = INVALID_HANDLE; - } - - /** - Determine the round end chat time and run the scramble 1 second before it ends. - */ - new Float:fDelay = GetConVarFloat(stm_mp_bonusroundtime); - fDelay -= 1.0; - StartScrambleTimer(fDelay); - } -} - -public OnClientPostAdminCheck(client) -{ - - /** - Determine if the client has the flag to use the swapteam command. - */ - decl String:sFlags[5]; - GetConVarString(stm_adminflag_swapteam, sFlags, sizeof(sFlags)); - if (SM_IsValidAdmin(client, sFlags)) - { - /** - The client does so lets create a timer to run an advertise to tell him about it. - */ - CreateTimer (60.0, Timer_WelcomeAdvert, client); - } -} - -public OnClientDisconnect(client) -{ - - /** - Cleanup the clients variables. - */ - s_CleanUp(client); -} - -public SM_OnPlayerMoved(Handle:plugin, client, team) -{ - - /** - Make sure we called the move function - */ - if (plugin != GetMyHandle()) - { - if (g_bLogActivity) - { - LogAction(0, client, "[STM] Callback was not started with current plugin, bugging out."); - } - return; - } - - decl String:sPlayerName[64]; - GetClientName(client, sPlayerName, sizeof(sPlayerName)); - - PrintToChat(client, "\x01\x04[SM]\x01 %T", "PlayerSwitched", LANG_SERVER); - - s_CleanUp(client); -} - -/* TIMER FUNCTIONS */ - -public Action:Timer_PrepTeamScramble(Handle:timer, any:data) -{ - new bool:bRestartRound = data; - /** - Call the scramble the teams stock function. - */ - PrepTeamScramble(bRestartRound); - - /** - Reset the timer handle so we know the timer is done. - */ - g_hTimerPrepScramble = INVALID_HANDLE; - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Timer_ScrambleTheTeams(Handle:timer, any:data) -{ - new iPlayers[MAXPLAYERS + 1]; - new iCount, i, bool:bTeam, bool:bRestartRound = data; - - /** - Get all the client index numbers of valid players - */ - for(i = 1; i <= MaxClients; i++) - { - if(IsClientInGame(i)) // && !IsFakeClient(i)) - { - iPlayers[iCount++] = i; - } - } - - /** - Randomly sort the players - */ - SortIntegers(iPlayers, iCount, Sort_Random); - - /** - Loop through all the players and assign each one to a team, alternating each time - */ - for(i = 0; i < iCount; i++) - { - if (!bRestartRound) - { - /** - We didn't want to restart the round, so we move them to spec 1 at a time. - */ - SM_MovePlayer(iPlayers[i], g_aCurrentTeams[Spectator]); - } - SM_MovePlayer(iPlayers[i], bTeam ? g_aCurrentTeams[Team2] : g_aCurrentTeams[Team1]); - SM_SetForcedTeam(iPlayers[i], bTeam ? g_aCurrentTeams[Team2] : g_aCurrentTeams[Team1], true); - bTeam = !bTeam; - } - - /** - Reset this variable since we completed a scramble - */ - g_bScrambleRoundEnd = false; - - if (g_hTimerClearScrambleForce != INVALID_HANDLE) - { - CloseHandle(g_hTimerClearScrambleForce); - g_hTimerClearScrambleForce = INVALID_HANDLE; - } - - g_hTimerClearScrambleForce = CreateTimer(300.0, Timer_ClearScrambleForce, _, TIMER_FLAG_NO_MAPCHANGE); - - ServerCommand("mp_timelimit %i", g_iTimeLeft / 60); - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Timer_ClearScrambleForce(Handle:timer, any:data) -{ - - for(new i = 1; i <= MaxClients; i++) - { - if(IsClientInGame(i)) // && !IsFakeClient(i)) - { - SM_ClearForcedTeam(i); - PrintToChat(i, "\x01\x04[SM]\x01 Your forced team status has been cleared"); - } - } - - g_hTimerClearScrambleForce = INVALID_HANDLE; - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -public Action:Timer_WelcomeAdvert(Handle:timer, any:client) -{ - - /** - Lets make sure the client is connected and actually in the game. - */ - if (IsClientConnected(client) && IsClientInGame(client)) - { - - /** - We are good to go so lets tell him about the swapteam command. - */ - PrintToChat (client, "\x01\x04[STM]\x01 %T", "SwapTeamMsg", LANG_SERVER); - } - - /** - We are done, bug out. - */ - return Plugin_Handled; -} - -/* STOCK FUNCTIONS */ - -stock s_CleanUp(iClient) -{ - - /** - Reset all the client variables - */ - g_aPlayers[iClient][bQueue] = false; - g_aPlayers[iClient][iNewTeam] = 0; -} - -stock StartScrambleTimer(Float:fdelay = 0.0, bool:bRestartRound = false) -{ - if (fdelay == 0.0) - { - fdelay = g_fScrambleDelay; - } - if (g_hTimerPrepScramble != INVALID_HANDLE) - { - CloseHandle(g_hTimerPrepScramble); - g_hTimerPrepScramble = INVALID_HANDLE; - } - PrintCenterTextAll("%T", "Scramble", LANG_SERVER); - g_hTimerPrepScramble = CreateTimer(fdelay, Timer_PrepTeamScramble, bRestartRound, TIMER_FLAG_NO_MAPCHANGE); -} - -stock PrepTeamScramble(bool:bRestartRound = false) -{ - new iPlayers[MAXPLAYERS + 1]; - new iCount; - - GetMapTimeLeft(g_iTimeLeft); - - if (bRestartRound) - { - - for(new i = 1; i <= MaxClients; i++) - { - if(IsClientInGame(i)) - // && !IsFakeClient(i)) - { - iPlayers[iCount++] = i; - SM_ClearForcedTeam(i); - SM_ClearBuddy(i); - SM_MovePlayer(i, g_aCurrentTeams[Spectator]); - } - } - } - else - { - //Can't move them all to spec at the same time - for(new i = 1; i <= MaxClients; i++) - { - if(IsClientInGame(i)) - // && !IsFakeClient(i)) - { - iPlayers[iCount++] = i; - SM_ClearForcedTeam(i); - SM_ClearBuddy(i); - //SM_MovePlayer(i, g_aCurrentTeams[Spectator]); - } - } - } - CreateTimer(4.0, Timer_ScrambleTheTeams, bRestartRound, TIMER_FLAG_NO_MAPCHANGE); -} - -/* CONSOLE VARIABLE CHANGE EVENT */ - -public ConVarSettingsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) -{ - if (convar == stm_enabled) { - if (StringToInt(newValue) == 0) { - g_bIsEnabled = false; - LogAction(0, -1, "[STM] Simple Team Manager is loaded and disabled."); - } else { - g_bIsEnabled = true; - LogAction(0, -1, "[STM] Simple Team Manager is loaded and enabled."); - } - } - else if (convar == stm_logactivity) { - if (StringToInt(newValue) == 0) { - g_bLogActivity = false; - LogAction(0, -1, "[STM] Log Activity DISABLED."); - } else { - g_bLogActivity = true; - LogAction(0, -1, "[STM] Log Activity ENABLED."); - } - } - else if (convar == stm_scrambledelay) - g_fScrambleDelay = StringToFloat(newValue); - else if (convar == stm_votewin) - g_fVoteWin = StringToFloat(newValue); - else if (convar == stm_votedelay) - g_iVoteDelay = StringToInt(newValue); - else if (convar == stm_voteenabled) { - if (StringToInt(newValue) == 0) - g_bVoteEnabled = false; - else - g_bVoteEnabled = true; - } -} - -/* MENU CODE */ - -public OnAdminMenuReady(Handle:topmenu) -{ - if (topmenu == g_hAdminMenu) - return; - g_hAdminMenu = topmenu; - new TopMenuObject:player_commands = FindTopMenuCategory(g_hAdminMenu, ADMINMENU_PLAYERCOMMANDS); - new TopMenuObject:server_commands = FindTopMenuCategory(g_hAdminMenu, ADMINMENU_SERVERCOMMANDS); - if (player_commands == INVALID_TOPMENUOBJECT) - return; - - AddToTopMenu(g_hAdminMenu, - "moveplayer", - TopMenuObject_Item, - AdminMenu_MovePlayer, - player_commands, - "moveplayer", - ADMFLAG_BAN); - - AddToTopMenu(g_hAdminMenu, - "scrambleteams", - TopMenuObject_Item, - AdminMenu_Scrambleteams, - server_commands, - "scrambleteams", - ADMFLAG_BAN); -} - -public AdminMenu_MovePlayer(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) -{ - if (action == TopMenuAction_DisplayOption) - Format(buffer, maxlength, "Move Player"); - else if (action == TopMenuAction_SelectOption){ - DisplayPlayerMenu(param); - } -} - -public AdminMenu_Scrambleteams(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) -{ - if (action == TopMenuAction_DisplayOption) - Format(buffer, maxlength, "Scramble Teams"); - else if (action == TopMenuAction_SelectOption) { - DisplayScrambleMenu(param); - } -} - -public Menu_SelectPlayer(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - DisplayTeamMenu(param1, GetClientOfUserId(StringToInt(sSelection))); - } else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -public Menu_SelectTeam(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new iTeam; - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - decl String:sIndex[64]; - if (SplitString(sSelection, "A", sIndex, sizeof(sIndex)) != -1) - iTeam = g_aCurrentTeams[Team1]; - else if (SplitString(sSelection, "B", sIndex, sizeof(sIndex)) != -1) - iTeam = g_aCurrentTeams[Team2]; - else { - SplitString(sSelection, "C", sIndex, sizeof(sIndex)); - iTeam = g_aCurrentTeams[Spectator]; - } - new iTarget = StringToInt(sIndex); - g_aPlayers[iTarget][iNewTeam] = iTeam; - DisplaySwapModeMenu(param1, iTarget); - } else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -public Menu_SwapMode(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - decl String:sIndex[64]; - - if (SplitString(sSelection, "A", sIndex, sizeof(sIndex)) == -1) - { - SplitString(sSelection, "B", sIndex, sizeof(sIndex)); - } - - new iTarget = StringToInt(sIndex); - - if (StrContains(sSelection, "A", true) != -1) - { - g_aPlayers[iTarget][bQueue] = false; - } - else if (StrContains(sSelection, "B", true) != -1) - { - g_aPlayers[iTarget][bQueue] = true; - } - - if (param1 == iTarget && !g_aPlayers[iTarget][bQueue]) - { - SM_MovePlayer(iTarget, g_aPlayers[iTarget][iNewTeam]); - } - else - { - DisplayForceModeMenu(param1, iTarget); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - { - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } - return; -} - -public Menu_ForceMode(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) - { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - decl String:sIndex[64]; - if (SplitString(sSelection, "A", sIndex, sizeof(sIndex)) == -1) - { - SplitString(sSelection, "B", sIndex, sizeof(sIndex)); - } - new iTarget = StringToInt(sIndex); - if (StrContains(sSelection, "A", true) != -1) - { - SM_ClearForcedTeam(iTarget); - } - else if (StrContains(sSelection, "B", true) != -1) - { - SM_SetForcedTeam(iTarget, g_aPlayers[iTarget][iNewTeam], true); - } - if (!g_aPlayers[iTarget][bQueue]) - { - SM_MovePlayer(iTarget, g_aPlayers[iTarget][iNewTeam]); - } - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - { - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } - } - else if (action == MenuAction_End) - { - CloseHandle(menu); - } - return; -} - -public Menu_VoteScramble(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_VoteEnd) { - new winning_votes, total_votes; - GetMenuVoteInfo(param2, winning_votes, total_votes); - if (param1 == 0) { - if (float(total_votes) / float(winning_votes) < g_fVoteWin) { - PrintToChatAll("\x01\x04[SM]\x01 %T", "VoteScramble2", LANG_SERVER, winning_votes, total_votes); - return; - } - PrintCenterTextAll("[SM] %T", "Scramble", LANG_SERVER); - PrintToChatAll("\x01\x04[SM]\x01 %T", "VoteScramble1", LANG_SERVER, winning_votes, total_votes); - StartScrambleTimer(); - } - if (param1 == 1) { - PrintToChatAll("\x01\x04[SM]\x01 %T", "VoteScramble2", LANG_SERVER, winning_votes, total_votes); - } - } - if (action == MenuAction_End) - CloseHandle(menu); -} - -public Menu_ScrambleTeams(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[64]; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "NOW", false)) - g_bScrambleRoundEnd = false; - else - g_bScrambleRoundEnd = true; - DisplayScrambleMenu2(param1); - } else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -public Menu_ScrambleTeams2(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Select) { - new String:sSelection[64]; - new bool:bRestartRound; - GetMenuItem(menu, param2, sSelection, sizeof(sSelection)); - if (StrEqual(sSelection, "NO", false)) - { - bRestartRound = false; - } - else - { - bRestartRound = true; - } - StartScrambleTimer(_, bRestartRound); - } else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack && g_hAdminMenu != INVALID_HANDLE && GetUserFlagBits(param1) & ADMFLAG_BAN) - DisplayTopMenu(g_hAdminMenu, param1, TopMenuPosition_LastCategory); - } else if (action == MenuAction_End) - CloseHandle(menu); - return; -} - -stock DisplayScrambleMenu(iClient) -{ - new Handle:hMenu = CreateMenu(Menu_ScrambleTeams); - SetMenuTitle(hMenu, "Select When to Scramble:"); - AddMenuItem(hMenu, "NOW", "Instantly"); - AddMenuItem(hMenu, "END", "At Round End"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplayScrambleMenu2(iClient) -{ - new Handle:hMenu = CreateMenu(Menu_ScrambleTeams2); - SetMenuTitle(hMenu, "Select When to Scramble:"); - AddMenuItem(hMenu, "NO", "No Round Restart"); - AddMenuItem(hMenu, "YES", "Restart Round"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplaySwapModeMenu(iClient, iTarget) -{ - new Handle:hMenu = CreateMenu(Menu_SwapMode); - decl String:optionA[64]; - decl String:optionB[64]; - Format(optionA, sizeof(optionA), "%iA", iTarget); - Format(optionB, sizeof(optionB), "%iB", iTarget); - SetMenuTitle(hMenu, "Select When to Swap:"); - AddMenuItem(hMenu, optionA, "Instantly (Kills)"); - if (!IsClientObserver(iTarget)) - AddMenuItem(hMenu, optionB, "Queue on next death"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplayForceModeMenu(iClient, iTarget) -{ - new Handle:hMenu = CreateMenu(Menu_ForceMode); - decl String:optionA[64]; - decl String:optionB[64]; - Format(optionA, sizeof(optionA), "%iA", iTarget); - Format(optionB, sizeof(optionB), "%iB", iTarget); - SetMenuTitle(hMenu, "Select Force Mode:"); - AddMenuItem(hMenu, optionA, "UnForced"); - AddMenuItem(hMenu, optionB, "Forced"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplayTeamMenu(iClient, iTarget) -{ - new Handle:hMenu = CreateMenu(Menu_SelectTeam); - decl String:optionA[64]; - decl String:optionB[64]; - decl String:optionC[64]; - Format(optionA, sizeof(optionA), "%iA", iTarget); - Format(optionB, sizeof(optionB), "%iB", iTarget); - Format(optionC, sizeof(optionC), "%iC", iTarget); - SetMenuTitle(hMenu, "Select Team:"); - AddMenuItem(hMenu, optionA, "Team One"); - AddMenuItem(hMenu, optionB, "Team Two"); - AddMenuItem(hMenu, optionC, "Spectator"); - SetMenuExitBackButton(hMenu, false); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} - -stock DisplayPlayerMenu(iClient) -{ - new Handle:hMenu = CreateMenu(Menu_SelectPlayer); - AddTargetsToMenu(hMenu, 0, true, false); - SetMenuTitle(hMenu, "Select A Player:"); - SetMenuExitBackButton(hMenu, true); - DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER); -} diff --git a/addons/sourcemod/translations/simpledonatorbenefits.phrases.txt b/addons/sourcemod/translations/simpledonatorbenefits.phrases.txt deleted file mode 100644 index 3826846..0000000 --- a/addons/sourcemod/translations/simpledonatorbenefits.phrases.txt +++ /dev/null @@ -1,62 +0,0 @@ -"Phrases" -{ - "PlayerLevelCmd" - { - "en" "Command must be run at the player level" - "fr" "Cette commande doit être tapée en jeu" - "hu" "Ezt a parancsot jatekosi szinten kell futtatni!" - } - "RestrictedCmd" - { - "en" "You must be a donator or admin to run this command" - "fr" "Vous devez être un donateur ou un admin pour lancer cette commande" - "hu" "A parancs futtatasahoz admin, vagy tamogatoi szint szukseges!" - } - "InValidTeam" - { - "en" "You must be on red or blue to swap teams" - "fr" "Vous devez être RED ou BLU pour changer d'équipe" - "hu" "Jatekban kell lenned, hogy megcsereld a csapatokat!" - } - "PlayerQueue" - { - "en" "You have been queued to swap teams on next death" - "fr" "Vous avez été mis en attente pour changer d'équipe lors de votre prochaine mort" - "hu" "A kovetkezo halalnal csapatcsere lesz" - } - "PlayerSwitched" - { - "en" "Your team has been switched as requested" - "fr" "Vous avez changé d'équipe comme demandé" - "hu" "A keresnek eleget teve a csapatod meg lett csererlve" - } - "SwapTeamMsg" - { - "en" "Type /swapteam or !swapteam to swap your team!" - } - "ReachedCount" - { - "en" "You have reached your health limit. You must die before you can use it again" - } - "AtMaxHealth" - { - "en" "You are already at your maximum health!" - } - "ToMaxHealth" - { - "en" "Instant health bonus applied! You are not at your maximun health!" - } - "HealthBonus" - { - "en" "Instant health bonus applied!" - } - "PublicJoinMessage" - { - "#format" "{1:s}" - "en" "{1} a [donator] as joined the server" - } - "PrivateJoinMessage" - { - "en" "Thanks for donating!" - } -} \ No newline at end of file diff --git a/addons/sourcemod/translations/simplespectate.phrases.txt b/addons/sourcemod/translations/simplespectate.phrases.txt deleted file mode 100644 index 2d1a096..0000000 --- a/addons/sourcemod/translations/simplespectate.phrases.txt +++ /dev/null @@ -1,42 +0,0 @@ -"Phrases" -{ - "Stopped spectating" - { - "#format" "{1:s}" - "en" "Stopped tracking player: {1}" - } - "Yourself" - { - "en" "You can't spectate yourself" - } - "Spectator" - { - "en" "You can't spectate another spectator" - } - "Spectating" - { - "#format" "{1:s}" - "en" "Now spectating {1}. Type !stopspec or /stopspec to stop spectating this player" - } - "Invalid Target" - { - "en" "Invalid target" - } - "Cant Target" - { - "en" "Can't target this player" - } - "Must Have Target" - { - "en" "You must be following/tracking a player to punish" - } - "Target Left" - { - "en" "The player you were following/tracking has left" - } - "Punished" - { - "#format" "{1:s}{2:s}{3:s}" - "en" "{1} was punished with a {2} for {3}" - } -} \ No newline at end of file diff --git a/addons/sourcemod/translations/simpleteambalancer.phrases.txt b/addons/sourcemod/translations/simpleteambalancer.phrases.txt deleted file mode 100644 index 03595fd..0000000 --- a/addons/sourcemod/translations/simpleteambalancer.phrases.txt +++ /dev/null @@ -1,130 +0,0 @@ -"Phrases" -{ - "UnBalanced" - { - "en" "Teams are unbalanced and will be balanced shortly" - "fr" "Les équipes ne sont pas équilibrées et le seront bientôt" - "de" "Die Teams sind ungleich und werden in Kürze ausgeglichen" - "hu" "A csapatok nem kiegyenlitettek! Egyensuly beallitas kovetkezik!" - } - "Enabled" - { - "en" "Simple Team Balancer is ENABLED" - "fr" "Simple Team Balancer est ACTIVE" - "de" "Simple Team Balancer ist AKTIV" - "hu" "Az Egyszeru Csapat Egyensulytarto AKTIV!" - } - "Disabled" - { - "en" "Simple Team Balancer is DISABLED" - "fr" "Simple Team Balancer est DESACTIVE" - "de" "Simple Team Balancer ist INAKTIV" - "hu" "Az Egyszeru Csapat Egyensulytarto INAKTIV!" - } - "PlayerMessage" - { - "#format" "{1:i}" - "en" "You are going to be auto balanced in {1} seconds unless a dead player can be found" - "fr" "Vous passerez dans l'autre équipe dans {1} secondes si aucun joueur mort ne peut être trouvé dans cet intervalle" - "de" "Du wirst in {1} Sekunden zum automatischen Ausgleich herangezogen wenn kein toter Spieler gefunden werden kann" - "hu" "{1} masodpercen belul at leszel helyezve a masik csapatba, hacsak nem lesz addig egy halott jatekos!" - } - "BalanceMessage" - { - "#format" "{1:s}" - "en" "{1} was moved to the other team for game balance" - "fr" "{1} est passé dans l'autre équipe pour équilibrer la partie" - "de" "{1} wurde zum anderen Team verschoben um das Spiel auszugleichen" - "hu" "{1} at lett helyezve az egyensuly megtartasa erdekeben." - } - "PlayerLevelCmd" - { - "en" "Command must be run at the player level" - "fr" "La commande doit être lancée au niveau du joueur" - "de" "Das Kommando muss auf Spieler Ebene ausgeführt werden" - "hu" "Jatekosi szinten kell futtatni ezt a parancsot!" - } - "CmdDisabled" - { - "en" "Command is currently disabled" - "fr" "La commande est actuellement désactivée" - "de" "Das Kommando ist momentan inaktiv" - "hu" "A parancs jelenleg inaktiv" - } - "RestrictedBuddy" - { - "en" "You must be a donator or admin to add a balance buddy" - "fr" "Vous devez être un donateur ou un admin pour choisir un partenaire" - "de" "Du musst ein Spender oder Admin sein um einen Partner wählen zu können" - "hu" "Tamogato vagy admin kell hogy legyel, hogy 'Tarsat' jelolhess meg" - } - "SelectSelf" - { - "en" "You cannot be your own buddy" - "fr" "Vous ne pouvez pas être votre propre partenaire" - "de" "Du kannst nicht dein eigener Partner sein" - "hu" "Nem valaszthatod ki onmagad!" - } - "BuddyGone" - { - "en" "Your selected buddy has disconnected" - "fr" "Le partenaire que vous avez sélectionné s'est déconnecté" - "de" "Dein gewählter Partner hat die Verbindung getrennt" - "hu" "A valasztott 'Tarsad' kilepett" - } - "BuddyMsg" - { - "#format" "{1:s}" - "en" "You and {1} are now buddies" - "fr" "Vous et {1} êtes maintenant partenaires" - "de" "Du und {1} seid jetzt Partner" - "hu" "{1} es Te 'Tarsak' vagytok." - } - "BuddyLockMsgDisabled" - { - "en" "You can now be anyone's buddy" - "fr" "Vous pouvez à présent être le partenaire de n'importe qui" - "de" "Du kannst jetzt jedermanns Partner sein" - "hu" "Barkinek lehetsz a 'Tarsa'." - } - "BuddyLockMsgEnabled" - { - "en" "Buddy selection locked. Only you can change your buddy" - "fr" "Sélection de partenaire bloquée. Vous êtes le seul à pouvoir choisir votre partenaire" - "de" "Wahl des Partners gesperrt. Nur du kannst deinen Partner wechseln" - "hu" "Tars-lista lezarva. Csak Te tudod modositani a Tars-listadat." - } - "PlayerLockedBuddyMsg" - { - "#format" "{1:s}" - "en" "{1} has locked his buddy selection. Try again" - "fr" "{1} a bloqué sa sélection de partenaire. Essayez de nouveau." - "de" "{1} hat seine Wahl des Partners gesperrt. Versuche es erneut" - "hu" "{1} lezarta a Tars-listajat. Probald kesobb!" - } - "BuddyWelcomeMsg1" - { - "en" "Select a balance buddy and stay together during an autobalance!" - "fr" "Choisissez un partenaire et restez ensemble durant l'équilibrage automatique!" - "de" "Wähle einen Partner und bleibt zusammen während eines Ausgleichs" - "hu" "Valasz ki egy 'Tarsat' akivel egyuttmaradhatsz a csapatkiegyenlites alatt!" - } - "BuddyWelcomeMsg2" - { - "en" "/buddy or !buddy to select a balance buddy" - "fr" "/buddy or !buddy pour choisir un partenaire" - "de" "/buddy oder !buddy um einen Partner zu wählen" - "hu" "Hasznald a /buddy vagy !buddy parancsokat a 'Tars' kijelolesehez" - } - "BuddyWelcomeMsg3" - { - "en" "/lockbuddy or !lockbuddy to lock your selection" - "fr" "/lockbuddy or !lockbuddy pour bloquer votre sélection" - "de" "/lockbuddy oder !lockbuddy um deine Auswahl zu sperren" - "hu" "Hasznald a /lockbuddy vagy a !lockbuddy parancsokat a Tars-listad lezarasahoz" - } -} - - - - diff --git a/addons/sourcemod/translations/simpleteammanager.phrases.txt b/addons/sourcemod/translations/simpleteammanager.phrases.txt deleted file mode 100644 index f2093a7..0000000 --- a/addons/sourcemod/translations/simpleteammanager.phrases.txt +++ /dev/null @@ -1,92 +0,0 @@ -"Phrases" -{ - "PlayerLevelCmd" - { - "en" "Command must be run at the player level" - "fr" "Cette commande doit être tapée en jeu" - "hu" "Ezt a parancsot jatekosi szinten kell futtatni!" - } - "RestrictedCmd" - { - "en" "You must be a donator or admin to run this command" - "fr" "Vous devez être un donateur ou un admin pour lancer cette commande" - "hu" "A parancs futtatasahoz admin, vagy tamogatoi szint szukseges!" - } - "InValidTeam" - { - "en" "You must be on red or blue to swap teams" - "fr" "Vous devez être RED ou BLU pour changer d'équipe" - "hu" "Jatekban kell lenned, hogy megcsereld a csapatokat!" - } - "PlayerInValidTeam" - { - "en" "Player must be on red or blue to swap teams" - "fr" "Le joueur doit être RED ou BLU pour changer d'équipe" - "hu" "Valamelyik csapatban kell lenni, hogy csere legyen" - } - "PlayerQueue" - { - "en" "You have been queued to swap teams on next death" - "fr" "Vous avez été mis en attente pour changer d'équipe lors de votre prochaine mort" - "hu" "A kovetkezo halalnal csapatcsere lesz" - } - "PlayerSwitched" - { - "en" "Your team has been switched" - } - "PlayerSwitched1" - { - "en" "Your team has been switched as requested" - "fr" "Vous avez changé d'équipe comme demandé" - "hu" "A keresnek eleget teve a csapatod meg lett csererlve" - } - "PlayerSwitched2" - { - "en" "Your team has been switched by an Admin" - "fr" "Vous avez été changé d'équipe par un admin" - "hu" "Az Admin megcserelte a csapatodat!" - } - "SwapTeamMsg" - { - "en" "Type /swapteam or !swapteam to swap your team!" - } - "PlayerSwitched3" - { - "#format" "{1:s}" - "en" "{1}'s team has been switched" - "fr" "{1} a changé d'équipe" - "hu" "{1} csapata meg lett cserelve" - } - "Scramble" - { - "en" "Teams are about to be scrambled!" - "fr" "Les équipes vont être rééquilibrés" - "hu" "A csapatok hamarosan meg lesznek keverve!" - } - "VoteScramble1" - { - "#format" "{1:i}{2:i}" - "en" "Vote Scramble successful with {1} votes out of {2}" - "fr" "Le vote d'équilibrage des équipes a réussi avec {1} votes pour sur {2}" - "hu" "A szavazas sikeres volt, {1} szavazat a keveresre a {2} -bol" - } - "VoteScramble2" - { - "#format" "{1:i}{2:i}" - "en" "Vote Scramble failed with {1} votes out of {2}" - "fr" "Le vote d'équilibrage a échoué avec {1} votes pour sur {2}" - "hu" "A szavazas sikertelen volt, {1} szavazat a keveresre a {2} -bol" - } - "VoteInProgress" - { - "en" "A vote is currently in progress" - "fr" "Un vote est actuellement en cours" - "hu" "Egy szavazas mar fut!" - } - "ScrambleTime" - { - "en" "A vote was recently made, please wait" - "fr" "Un vote a déjà été fait récemment, réessayez plus tard" - "hu" "Nemreg volt szavazas, kerlek varj egy kicsit!" - } -} \ No newline at end of file