HLMOD.HU Forrás Megtekintés - www.hlmod.hu
  1. #define PLUGIN "AFK Manager"
  2. #define AUTHOR "Leon McVeran"
  3. #define VERSION "v1.6"
  4. #define PDATE "2nd August 2011"
  5.  
  6. #include <amxmodx>
  7. #include <amxmisc>
  8. #include <cstrike>
  9. #include <fakemeta>
  10.  
  11. #define KICK_IMMUNITY ADMIN_BAN
  12.  
  13. #define TASK_AFK_CHECK 142500
  14. #define FREQ_AFK_CHECK 5.0
  15. #define MAX_WARN 3
  16.  
  17. static const OFFSET_LINUX = 5
  18. new const m_iJoiningState = 125
  19.  
  20. new bool:g_bSpec[33]
  21. new bool:g_bSpecAccess[33]
  22. new Float:g_fLastActivity[33]
  23. new g_iAFKCheck
  24. new g_iAFKTime[33]
  25. new g_iDropBomb
  26. new g_iKickTime
  27. new g_iMaxPlayers
  28. new g_iMinPlayers
  29. new g_iTransferTime
  30. new g_iWarn[33]
  31. new g_vOrigin[33][3]
  32.  
  33. new CVAR_afk_drop_bomb
  34. new CVAR_afk_check
  35. new CVAR_afk_transfer_time
  36. new CVAR_afk_kick_time
  37. new CVAR_afk_kick_players
  38.  
  39. new CVAR_afk_spec_pw
  40.  
  41.  
  42. public plugin_init(){
  43. register_plugin(PLUGIN, VERSION, AUTHOR)
  44. register_dictionary("afk_manager.txt")
  45.  
  46. register_logevent("event_round_end", 2, "0=World triggered", "1=Round_End")
  47. register_logevent("event_round_start", 2, "0=World triggered", "1=Round_Start")
  48.  
  49. // Support der alten Menüs
  50. register_clcmd("jointeam", "cmd_jointeam") // new menu
  51. register_menucmd(register_menuid("Team_Select", 1), 511, "cmd_jointeam") // old menu
  52.  
  53. register_clcmd("joinclass", "cmd_joinclass") // new menu
  54. register_menucmd(register_menuid("Terrorist_Select", 1), 511, "cmd_joinclass") // old menu
  55. register_menucmd(register_menuid("CT_Select", 1), 511, "cmd_joinclass") // old menu
  56.  
  57. register_clcmd("say", "cmd_say")
  58.  
  59. CVAR_afk_check = register_cvar("afk_check", "1")
  60. CVAR_afk_drop_bomb = register_cvar("afk_drop_bomb", "2")
  61. CVAR_afk_transfer_time = register_cvar("afk_transfer_time", "9")
  62. CVAR_afk_kick_time = register_cvar("afk_kick_time", "24")
  63. CVAR_afk_kick_players = register_cvar("afk_kick_players", "12")
  64.  
  65. CVAR_afk_spec_pw = register_cvar("afk_spec_pw", "password")
  66. }
  67.  
  68. public plugin_cfg(){
  69. g_iMaxPlayers = get_maxplayers()
  70. }
  71.  
  72. public client_connect(id){
  73.  
  74. // Spieler als Spectator entmarkieren
  75. g_bSpec[id] = false
  76. g_bSpecAccess[id] = false
  77.  
  78. // Positionen zurücksetzen
  79. g_vOrigin[id] = {0, 0, 0}
  80.  
  81. // Counter zurücksetzen
  82. g_iAFKTime[id] = 0
  83. g_iWarn[id] = 0
  84. }
  85.  
  86. public event_round_start(){
  87.  
  88. // AFK Check eingeschaltet
  89. g_iAFKCheck = get_pcvar_num(CVAR_afk_check)
  90. if (g_iAFKCheck){
  91.  
  92. // Spawn-Positionen aktualisieren
  93. new iPlayers[32], pNum
  94. get_players(iPlayers, pNum, "a")
  95. for (new p = 0; p < pNum; p++){
  96. get_user_origin(iPlayers[p], g_vOrigin[iPlayers[p]])
  97. }
  98.  
  99. // Loop anlegen falls nicht vorhanden
  100. if (!task_exists(TASK_AFK_CHECK)) set_task(FREQ_AFK_CHECK, "func_afk_check", TASK_AFK_CHECK, _, _, "b")
  101.  
  102. // Kick und Transferzeiten festlegen
  103. if (get_pcvar_num(CVAR_afk_transfer_time) < 6) set_pcvar_num(CVAR_afk_transfer_time, 6)
  104. if (get_pcvar_num(CVAR_afk_kick_time) < 6) set_pcvar_num(CVAR_afk_kick_time, 6)
  105. g_iDropBomb = get_pcvar_num(CVAR_afk_drop_bomb)
  106. g_iTransferTime = get_pcvar_num(CVAR_afk_transfer_time)
  107. g_iKickTime = get_pcvar_num(CVAR_afk_kick_time)
  108. g_iMinPlayers = get_pcvar_num(CVAR_afk_kick_players)
  109. }
  110.  
  111. // AFK Check ausgeschaltet
  112. else{
  113.  
  114. // Loop löschen falls vorhanden
  115. if (task_exists(TASK_AFK_CHECK)) remove_task(TASK_AFK_CHECK)
  116. }
  117.  
  118.  
  119. }
  120.  
  121. public event_round_end(){
  122.  
  123. // Check darf nicht durchgeführt werden
  124. g_iAFKCheck = 0
  125. }
  126.  
  127. public cmd_jointeam(id){
  128.  
  129. // Spieler als Spectator markieren, sonst kann man den Kick umgehen, indem man keiner Klasse joined.
  130. g_bSpec[id] = true
  131. }
  132.  
  133. public cmd_joinclass(id){
  134.  
  135. // Spieler als Spectator entmarkieren
  136. g_bSpec[id] = false
  137.  
  138. // Positionen zurücksetzen
  139. g_vOrigin[id] = {0, 0, 0}
  140.  
  141. // Counter zurücksetzen
  142. g_iAFKTime[id] = 0
  143. g_iWarn[id] = 0
  144. }
  145.  
  146. public cmd_say(id){
  147. new szMsg[64], szCommand[16], szTrash[2]
  148. read_args(szMsg, 63)
  149. remove_quotes(szMsg)
  150. parse(szMsg, szCommand, 15, szTrash, 1)
  151.  
  152. // Wir interessieren uns nur für Chatnachrichten die nicht mehr als 2 Wörter beinhalten
  153. if (!szTrash[0]){
  154.  
  155. new szPassword[32]
  156. get_pcvar_string(CVAR_afk_spec_pw, szPassword, 31)
  157. if (equal(szCommand, szPassword)){
  158. print_color(id, "!g[AMXX] %L", LANG_PLAYER, "AFK_ACCESS_GRANTED")
  159. g_bSpecAccess[id] = true
  160. return PLUGIN_HANDLED
  161. }
  162. }
  163. return PLUGIN_CONTINUE
  164. }
  165.  
  166. public func_afk_check(taskid){
  167. if (g_iAFKCheck){
  168. new CsTeams:eTeam
  169.  
  170. // Alle Spieler überprüfen
  171. for (new id = 1; id <= g_iMaxPlayers; id++){
  172.  
  173. // Bots nicht überprüfen
  174. if (is_user_bot(id)) continue
  175.  
  176. // AFK Funktionen für Specs
  177. if (is_user_connected(id) && !is_user_hltv(id)){
  178. eTeam = cs_get_user_team(id)
  179. if (eTeam == CS_TEAM_SPECTATOR || eTeam == CS_TEAM_UNASSIGNED || g_bSpec[id]){
  180.  
  181. // Counter erhöhen
  182. g_iAFKTime[id]++
  183.  
  184. // Spec-Kick
  185. if (g_iAFKTime[id] >= g_iKickTime - MAX_WARN){
  186. func_kick_player(id)
  187. }
  188. }
  189. }
  190.  
  191. // AFK Funktionen für lebende Spieler
  192. if (is_user_alive(id)){
  193.  
  194. // Positionen überprüfen
  195. if (g_iAFKCheck == 1){
  196. new vOrigin[3]
  197. get_user_origin(id, vOrigin)
  198.  
  199. if (g_vOrigin[id][0] != vOrigin[0] || g_vOrigin[id][1] != vOrigin[1]){
  200. g_vOrigin[id][0] = vOrigin[0]
  201. g_vOrigin[id][1] = vOrigin[1]
  202. g_vOrigin[id][2] = vOrigin[2]
  203. g_iAFKTime[id] = 0
  204. g_iWarn[id] = 0
  205. }
  206. else{
  207. g_iAFKTime[id]++
  208. }
  209. }
  210.  
  211. // Letzte Aktivität ermitteln
  212. else{
  213. new Float:fLastActivity
  214. fLastActivity = cs_get_user_lastactivity(id)
  215.  
  216. if (fLastActivity != g_fLastActivity[id]){
  217. g_fLastActivity[id] = fLastActivity
  218. g_iAFKTime[id] = 0
  219. g_iWarn[id] = 0
  220. }
  221. else{
  222. g_iAFKTime[id] = floatround((get_gametime() - fLastActivity) / FREQ_AFK_CHECK)
  223. }
  224. }
  225.  
  226. // Bombentransfer
  227. if (g_iDropBomb && g_iAFKTime[id] >= 3){
  228. if (g_iDropBomb == 1){
  229. if (pev(id, pev_weapons) & (1 << CSW_C4)) engclient_cmd(id, "drop", "weapon_c4")
  230. }
  231. else{
  232. func_transfer_bomb(id)
  233. }
  234. }
  235.  
  236. // Spec-Switch
  237. if (g_iAFKTime[id] >= g_iTransferTime - MAX_WARN){
  238. func_transfer_player(id)
  239. }
  240. }
  241. }
  242. }
  243. }
  244.  
  245. public func_transfer_bomb(id){
  246.  
  247. // Abbrechen wenn der Spieler keine Bombe hat
  248. if (!(pev(id, pev_weapons) & (1 << CSW_C4))) return
  249.  
  250. // Ermittle alle lebenden Terroristen
  251. new iPlayers[32], pNum
  252. get_players(iPlayers, pNum, "ae", "TERRORIST")
  253.  
  254. // Abbrechen falls weniger als 2 Terroristen leben
  255. if (pNum < 2) return
  256.  
  257. // Finde den nächsten Terroristen der nicht AFK ist
  258. new vCarrier[3], vRecipient[3], iRecipient, iDistance, iMinDistance = 999999
  259. get_user_origin(id, vCarrier)
  260. for (new p = 0; p < pNum; p++){
  261. if (g_iAFKTime[iPlayers[p]] < 2){
  262. get_user_origin(iPlayers[p], vRecipient)
  263. iDistance = get_distance(vCarrier, vRecipient)
  264. if (iDistance < iMinDistance){
  265. iMinDistance = iDistance
  266. iRecipient = iPlayers[p]
  267. }
  268. }
  269. }
  270.  
  271. // Abbrechen wenn alle Terroristen AFK sind
  272. if (!iRecipient) return
  273.  
  274. // Bombe transferieren
  275. engclient_cmd(id, "drop", "weapon_c4")
  276. new iC4 = engfunc(EngFunc_FindEntityByString, -1, "classname", "weapon_c4")
  277. if (pev_valid(iC4)){
  278. new iBackpack = pev(iC4, pev_owner)
  279. if (iBackpack > g_iMaxPlayers){
  280. set_pev(iBackpack, pev_flags, pev(iBackpack, pev_flags) | FL_ONGROUND)
  281. dllfunc(DLLFunc_Touch, iBackpack, iRecipient)
  282. }
  283. }
  284.  
  285. // Nachrichten anzeigen
  286. new szRecipient[32], szMsg[128]
  287. get_user_name(iRecipient, szRecipient, 31)
  288. set_hudmessage(255, 255, 0, -1.0, 0.8, 0, 3.0, 6.0, 0.1, 0.2, -1)
  289. for (new p = 0; p < pNum; p++){
  290. if (iPlayers[p] != iRecipient){
  291. format(szMsg, 127, "%L", iPlayers[p], "AFK_TRANSFER_BOMB", szRecipient)
  292. show_hudmessage(iPlayers[p], "%s", szMsg)
  293. }
  294. }
  295. format(szMsg, 127, "%L", iRecipient, "AFK_GOT_BOMB")
  296. show_hudmessage(iRecipient, szMsg)
  297. }
  298.  
  299. public func_transfer_player(id){
  300.  
  301. // Warnung anzeigen, wenn nicht schon max-mal verwarnt
  302. if (g_iWarn[id] < MAX_WARN){
  303. print_color(id,"!g[AMXX] %L", LANG_PLAYER, "AFK_TRANSFER_WARN", floatround(FREQ_AFK_CHECK) * (MAX_WARN - g_iWarn[id]))
  304. g_iWarn[id]++
  305. return
  306. }
  307.  
  308. // Eigentlich sollte die Bombe schon transferiert worden sein
  309. if (pev(id, pev_weapons) & (1 << CSW_C4)){
  310. engclient_cmd(id, "drop", "weapon_c4")
  311. }
  312.  
  313. // Spieler tranferieren
  314. if (is_user_alive(id)) user_silentkill(id)
  315.  
  316. // Allow players to choose a team more than one time per round (Thanks ConnorMcLeod)
  317. // I use this method caused of some issue with deathmatch (Player will be respawned as T or CT)
  318. set_pdata_int(id, m_iJoiningState, get_pdata_int(id, m_iJoiningState, OFFSET_LINUX) & ~(1<<8), OFFSET_LINUX)
  319. engclient_cmd(id, "jointeam", "6")
  320. set_pdata_int(id, m_iJoiningState, get_pdata_int(id, m_iJoiningState, OFFSET_LINUX) & ~(1<<8), OFFSET_LINUX)
  321. //cs_set_user_team(id, CS_TEAM_SPECTATOR)
  322. //cs_reset_user_model(id)
  323.  
  324. // Positionen zurücksetzen
  325. g_vOrigin[id] = {0, 0, 0}
  326.  
  327. // Counter zurücksetzen
  328. g_iAFKTime[id] = 0
  329. g_iWarn[id] = 0
  330.  
  331. // Nachrichten anzeigen
  332. new szName[32]
  333. get_user_name(id, szName, 31)
  334. print_color( 0 , "!g[AMXX] %L", LANG_PLAYER, "AFK_TRANSFER_PLAYER", szName)
  335. log_amx(" %s jatekos at keralt nezobe, AFK miatt.", szName)
  336. }
  337.  
  338. public func_kick_player(id){
  339.  
  340. // Abbrechen wenn es sich um einen Admin handelt
  341. if (get_user_flags(id) & KICK_IMMUNITY || g_bSpecAccess[id]) return
  342.  
  343. // Anzahl der aktuellen Spieler ermitteln
  344. new iCurrentPlayers = get_playersnum(1)
  345.  
  346. // Sind noch Plätze frei?
  347. if (iCurrentPlayers < g_iMinPlayers || !g_iMinPlayers) return
  348.  
  349. // Warnung anzeigen, wenn nicht schon max-mal verwarnt
  350. if (g_iWarn[id] < MAX_WARN){
  351. print_color(id, "!g[AMXX] %L", LANG_PLAYER, "AFK_KICK_WARN", floatround(FREQ_AFK_CHECK) * (MAX_WARN - g_iWarn[id]))
  352. g_iWarn[id]++
  353. return
  354. }
  355.  
  356. // Spieler kicken
  357. new szMsg[192]
  358. format(szMsg, 191, "%L", id, "AFK_KICK_REASON")
  359. server_cmd("kick #%d ^"%s^"", get_user_userid(id), szMsg)
  360.  
  361. // Nachrichten anzeigen
  362. new szName[32]
  363. get_user_name(id, szName, 31)
  364. print_color( 0 , "!g[AMXX] %L", LANG_PLAYER, "AFK_KICK_PLAYER", szName)
  365. log_amx("Player ^"%s^" kirugtak, amiert AFK.", szName)
  366. }
  367. stock print_color(const id, const input[], any:...) {
  368. new count = 1, players[32]
  369. static msg[191]
  370. vformat(msg, 190, input, 3)
  371.  
  372. replace_all(msg, 190, "!g", "^4")
  373. replace_all(msg, 190, "!y", "^1")
  374. replace_all(msg, 190, "!t", "^3")
  375.  
  376. if (id) players[0] = id; else get_players(players, count, "ch")
  377. {
  378. for (new i = 0; i < count; i++)
  379. {
  380. if (is_user_connected(players[i]))
  381. {
  382. message_begin(MSG_ONE_UNRELIABLE, get_user_msgid("SayText"), _, players[i])
  383. write_byte(players[i])
  384. write_string(msg)
  385. message_end()
  386. }
  387. }
  388. }
  389. return PLUGIN_HANDLED
  390. }
  391.