HLMOD.HU Forrás Megtekintés - www.hlmod.hu
  1. #define PLUGIN "Server Messages"
  2. #define AUTHOR "Leon McVeran"
  3. #define VERSION "v1.4"
  4. #define PDATE "22nd September 2009"
  5.  
  6. #include <amxmodx>
  7. #include <amxmisc>
  8. #include <vault>
  9.  
  10. new const g_szFileName[] = "server_messages.txt"
  11.  
  12. #define ACCESS_PRINT_MSG ADMIN_CHAT
  13. #define ACCESS_LIST_MSG ADMIN_ALL
  14.  
  15. #define TASK_REMOVE_TUTOR 8000
  16. #define TASK_SHOW_MESSAGE 8033
  17.  
  18. // Don't modify any defines under this line, otherwise it could lead to an error
  19. #define SM_MESSAGES (1<<0)
  20. #define SM_RULES (1<<1)
  21. #define SM_INFOS (1<<2)
  22.  
  23. #define SKIP_NOTHING 0
  24. #define SKIP_DEAD (1<<0)
  25. #define SKIP_ALIVE (1<<1)
  26. #define SKIP_BOTS (1<<2)
  27. #define SKIP_REAL (1<<3)
  28.  
  29. new bool:g_bMsgEnabled[33]
  30. new g_iActivity[33]
  31. new g_iMsgCount
  32. new g_iRuleCount
  33. new g_iInfoCount
  34. new g_szFilePath[64]
  35. new g_szLastMsg[3][16]
  36.  
  37. new CVAR_msg_mode
  38. new CVAR_msg_show
  39. new CVAR_msg_style
  40. new CVAR_rule_mode
  41. new CVAR_rule_show
  42. new CVAR_rule_style
  43. new CVAR_rule_prefix
  44. new CVAR_info_mode
  45. new CVAR_info_show
  46. new CVAR_info_style
  47. new CVAR_min_activity
  48. new CVAR_show_frequency
  49. new CVAR_show_skip
  50. new CVAR_show_time
  51. new CVAR_tutor_sound
  52. new CVAR_tutor_warn
  53.  
  54. new gMsgTutorClose
  55. new gMsgTutorText
  56. new gMsgSayText
  57.  
  58. public plugin_init(){
  59. register_plugin(PLUGIN, VERSION, AUTHOR)
  60. register_dictionary(g_szFileName)
  61.  
  62. if (is_running("czero") || is_running("cstrike")){
  63. register_event("HLTV", "event_freezetime_start", "a", "1=0", "2=0")
  64.  
  65. register_concmd("amx_print_custom", "cmd_custom_print", ACCESS_PRINT_MSG, "<authid, nick, @group or #userid> <your message> [optional: <mode> <style>]")
  66. register_concmd("amx_print_msg", "cmd_server_print", ACCESS_PRINT_MSG, "<authid, nick, @group or #userid> <msg number> [optional: <mode> <style>]")
  67. register_concmd("amx_print_rule", "cmd_server_print", ACCESS_PRINT_MSG, "<authid, nick, @group or #userid> <rule number> [optional: <mode> <style>]")
  68. register_concmd("amx_print_info", "cmd_server_print", ACCESS_PRINT_MSG, "<authid, nick, @group or #userid> <info number> [optional: <mode> <style>]")
  69. register_concmd("amx_list_msg", "cmd_server_list", ACCESS_LIST_MSG, "- shows a list of all server messages")
  70. register_concmd("amx_list_rule", "cmd_server_list", ACCESS_LIST_MSG, "- shows a list of all server rules")
  71. register_concmd("amx_list_info", "cmd_server_list", ACCESS_LIST_MSG, "- shows a list of all server informations")
  72.  
  73. register_clcmd("joinclass", "cmd_joinclass") // New VGUI Menu
  74. register_menucmd(register_menuid("Terrorist_Select", 1), 511, "cmd_joinclass") // Old Style Menu
  75. register_menucmd(register_menuid("CT_Select", 1), 511, "cmd_joinclass") // Old Style Menu
  76.  
  77. CVAR_msg_mode = register_cvar("sm_msg_mode", "3")
  78. CVAR_msg_show = register_cvar("sm_msg_show", "1")
  79. CVAR_msg_style = register_cvar("sm_msg_style", "0")
  80.  
  81. CVAR_rule_mode = register_cvar("sm_rule_mode", "4")
  82. CVAR_rule_show = register_cvar("sm_rule_show", "1")
  83. CVAR_rule_style = register_cvar("sm_rule_style", "3")
  84. CVAR_rule_prefix = register_cvar("sm_rule_prefix", "1")
  85.  
  86. CVAR_info_mode = register_cvar("sm_info_mode", "4")
  87. CVAR_info_show = register_cvar("sm_info_show", "1")
  88. CVAR_info_style = register_cvar("sm_info_style", "0")
  89.  
  90. CVAR_min_activity = register_cvar("sm_min_activity", "4320")
  91. CVAR_show_frequency = register_cvar("sm_show_frequency", "15")
  92. CVAR_show_skip = register_cvar("sm_show_skip", "2")
  93. CVAR_show_time = register_cvar("sm_show_time", "8")
  94. CVAR_tutor_sound = register_cvar("sm_tutor_sound", "0")
  95. CVAR_tutor_warn = register_cvar("sm_tutor_warn", "1")
  96. }
  97. else{
  98. new ErrMsg[256]
  99. format(ErrMsg, 255, "[AMXX] Nem sikerult betolteni a %s fajlt.", PLUGIN)
  100. set_fail_state(ErrMsg)
  101. }
  102. }
  103.  
  104. public plugin_precache(){
  105. precache_generic("gfx/career/icon_!.tga")
  106. precache_generic("gfx/career/icon_!-bigger.tga")
  107. precache_generic("gfx/career/icon_i.tga")
  108. precache_generic("gfx/career/icon_i-bigger.tga")
  109. precache_generic("gfx/career/icon_skulls.tga")
  110. precache_generic("gfx/career/round_corner_ne.tga")
  111. precache_generic("gfx/career/round_corner_nw.tga")
  112. precache_generic("gfx/career/round_corner_se.tga")
  113. precache_generic("gfx/career/round_corner_sw.tga")
  114.  
  115. precache_generic("resource/TutorScheme.res")
  116. precache_generic("resource/UI/TutorTextWindow.res")
  117.  
  118. precache_sound("events/enemy_died.wav")
  119. precache_sound("events/friend_died.wav")
  120. precache_sound("events/task_complete.wav")
  121. precache_sound("events/tutor_msg.wav")
  122. }
  123.  
  124. public plugin_cfg(){
  125. gMsgTutorClose = get_user_msgid("TutorClose")
  126. gMsgTutorText = get_user_msgid("TutorText")
  127. gMsgSayText = get_user_msgid("SayText")
  128.  
  129. // Store the path to our used txt-file
  130. get_datadir(g_szFilePath, 63)
  131. format(g_szFilePath, 63, "%s/lang/%s", g_szFilePath, g_szFileName)
  132.  
  133. new iLanguages
  134. if (file_exists(g_szFilePath)){
  135. new szMsg[32], szBuffer[128], szLastMsg[32], fp=fopen(g_szFilePath, "r")
  136. while (!feof(fp) && iLanguages < 2){
  137. szBuffer[0]='^0'
  138. fgets(fp, szBuffer, 127)
  139. parse(szBuffer, szMsg, 31)
  140. if (!equali(szMsg, szLastMsg)){
  141.  
  142. // Saves the current message for blocking duplicative messages
  143. copy(szLastMsg, 31, szMsg)
  144.  
  145. if (equali(szMsg, "SERVER_MSG_", 11)){
  146. g_iMsgCount+=1
  147. }
  148. else if (equali(szMsg, "SERVER_RULE_", 12)){
  149. g_iRuleCount+=1
  150. }
  151. else if (equali(szMsg, "SERVER_INFO_", 12)){
  152. g_iInfoCount+=1
  153. }
  154.  
  155. // Stop loop if we reached the second language
  156. else if (szMsg[0] == '[' && szMsg[3] == ']'){
  157. iLanguages+=1
  158. }
  159. }
  160. }
  161. fclose(fp)
  162. }
  163. else{
  164. server_print("%L", LANG_SERVER, "SM_ERROR_FILE")
  165. }
  166. }
  167.  
  168. /* == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == ==
  169. EVENTS
  170.  == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == ==*/
  171.  
  172. public client_authorized(id){
  173. if (!is_user_bot(id)){
  174. LoadData(id)
  175. }
  176. }
  177.  
  178. public client_disconnect(id){
  179. if (!is_user_bot(id)){
  180. SaveData(id)
  181. Remove_TutorMsg(id)
  182. }
  183. }
  184.  
  185. public event_freezetime_start(){
  186. // Without this event, we can not change the frequency or duration of messages
  187. remove_task(TASK_SHOW_MESSAGE)
  188. set_task(get_pcvar_num(CVAR_show_frequency) < get_pcvar_num(CVAR_show_time) ? get_pcvar_float(CVAR_show_time) + 1.0 : get_pcvar_float(CVAR_show_frequency), "func_show_message", TASK_SHOW_MESSAGE, _, _, "b")
  189. }
  190.  
  191. /* == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == ==
  192. COMMANDS
  193.  == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == ==*/
  194.  
  195. public cmd_joinclass(id){
  196. if (get_pcvar_num(CVAR_tutor_warn) && !is_user_bot(id)){
  197. new szMsg[256]
  198. if (g_iActivity[id] == 0) format(szMsg, 255, "%L", id, "SM_RESTART_THE_GAME")
  199. if (g_iActivity[id] <= 60) format(szMsg, 255, "%L", id, "SM_CAN_NOT_READ")
  200.  
  201. if (strlen(szMsg)){
  202. replace_all(szMsg, 254, "\n", "^n")
  203. set_hudmessage(240, 0, 0, -1.0, 0.65, 2, 0.1, 16.0, 0.02, 0.02, 8)
  204. show_hudmessage(id, szMsg)
  205. }
  206. }
  207. }
  208.  
  209. public cmd_custom_print(id, level, cid){
  210. if (!cmd_access(id, level, cid, 3)){
  211. return PLUGIN_HANDLED
  212. }
  213. new szTarget[32], szMsg[256], szMode[4], szStyle[4], szAdminName[32], szTargetName[32]
  214. read_argv(1, szTarget, 31)
  215. read_argv(2, szMsg, 255)
  216. read_argv(3, szMode, 3)
  217. read_argv(4, szStyle, 3)
  218. get_user_name(id, szAdminName, 31)
  219.  
  220. // Check if the third parameter a number or not
  221. if (strlen(szMode)){
  222. if (!is_str_num(szMode)){
  223. client_print(id, print_console, "%L", LANG_PLAYER, "SM_CUSTOM_USAGE")
  224. return PLUGIN_HANDLED
  225. }
  226. }
  227.  
  228. // Define mode and style of the message (defaults: mode 4 and style 0)
  229. new iMode = strlen(szMode) ? str_to_num(szMode) : 4
  230. new iStyle = strlen(szStyle) ? str_to_num(szStyle) : 0
  231.  
  232. // Let's go, print the messages on clients
  233. if (szTarget[0] == '@'){
  234. new iPlayers[32], pNum
  235. if (get_cmd_targets(id, szTarget, iPlayers, pNum, szTargetName, SKIP_BOTS)){
  236. for (new p = 0; p < pNum; p++){
  237. func_print_message(iPlayers[p], szMsg, iMode, iStyle, true)
  238. }
  239. }
  240. }
  241. else{
  242. new iPlayer = cmd_target(id, szTarget, 8)
  243. if (!iPlayer) return PLUGIN_HANDLED
  244. get_user_name(iPlayer, szTargetName, 31)
  245.  
  246. func_print_message(iPlayer, szMsg, iMode, iStyle, true)
  247. }
  248.  
  249. if (strlen(szTargetName)){
  250. log_amx("%L", LANG_SERVER, "SM_PRINT_LOG", szAdminName, szTargetName, szMsg, iMode, iStyle)
  251. }
  252. return PLUGIN_HANDLED
  253. }
  254.  
  255. public cmd_server_print(id, level, cid){
  256. if (!cmd_access(id, level, cid, 3)){
  257. return PLUGIN_HANDLED
  258. }
  259. new szCommand[32], szTarget[32], szNumber[4], szMode[4], szStyle[4], szAdminName[32], szTargetName[32]
  260. read_argv(0, szCommand, 31)
  261. read_argv(1, szTarget, 31)
  262. read_argv(2, szNumber, 3)
  263. read_argv(3, szMode, 3)
  264. read_argv(4, szStyle, 3)
  265. get_user_name(id, szAdminName, 31)
  266.  
  267. // Define which type of message are used
  268. new szSearchedMsg[20], iMode, iStyle, bool:bPrefix
  269. if (equal(szCommand, "amx_print_msg")){
  270. copy(szSearchedMsg, 19, "SERVER_MSG_")
  271. iMode = strlen(szMode) ? str_to_num(szMode) : get_pcvar_num(CVAR_msg_mode)
  272. iStyle = strlen(szStyle) ? str_to_num(szStyle) : get_pcvar_num(CVAR_msg_style)
  273. }
  274. else if (equal(szCommand, "amx_print_rule")){
  275. copy(szSearchedMsg, 19, "SERVER_RULE_")
  276. iMode = strlen(szMode) ? str_to_num(szMode) : get_pcvar_num(CVAR_rule_mode)
  277. iStyle = strlen(szStyle) ? str_to_num(szStyle) : get_pcvar_num(CVAR_rule_style)
  278. bPrefix = get_pcvar_num(CVAR_rule_prefix) ? true : false
  279. }
  280. else if (equal(szCommand, "amx_print_info")){
  281. copy(szSearchedMsg, 19, "SERVER_INFO_")
  282. iMode = strlen(szMode) ? str_to_num(szMode) : get_pcvar_num(CVAR_info_mode)
  283. iStyle = strlen(szStyle) ? str_to_num(szStyle) : get_pcvar_num(CVAR_info_style)
  284. }
  285.  
  286. // Technically we should never get here
  287. if (!strlen(szSearchedMsg)){
  288. client_print(id, print_console, "%L", LANG_PLAYER, "SM_ERROR_SEARCH")
  289. return PLUGIN_HANDLED
  290. }
  291.  
  292. // Check if the second parameter a number or not
  293. if (!is_str_num(szNumber)){
  294. client_print(id, print_console, "%L", LANG_PLAYER, "SM_ERROR_NUMBER")
  295. return PLUGIN_HANDLED
  296. }
  297.  
  298. // Merge the different parameters to define and check the message.
  299. add(szSearchedMsg, 19, szNumber)
  300. if (!is_msg_valid(szSearchedMsg)){
  301. client_print(id, print_console, "%L", LANG_PLAYER, "SM_ERROR_MESSAGE")
  302. return PLUGIN_HANDLED
  303. }
  304.  
  305. // Let's go, print the messages on clients
  306. if (szTarget[0] == '@'){
  307. new iPlayers[32], pNum
  308. if (get_cmd_targets(id, szTarget, iPlayers, pNum, szTargetName, SKIP_BOTS)){
  309. for (new p = 0; p < pNum; p++){
  310. new szMsg[256]
  311. if (bPrefix){
  312. format(szMsg, 255, "%L^n%L", iPlayers[p], "SM_RULE_PREFIX", str_to_num(szSearchedMsg[12]), iPlayers[p], szSearchedMsg)
  313. }
  314. else{
  315. format(szMsg, 255, "%L", iPlayers[p], szSearchedMsg)
  316. }
  317. func_print_message(iPlayers[p], szMsg, iMode, iStyle, true)
  318. }
  319. }
  320. }
  321. else{
  322. new iPlayer = cmd_target(id, szTarget, 8)
  323. if (!iPlayer) return PLUGIN_HANDLED
  324. get_user_name(iPlayer, szTargetName, 31)
  325.  
  326. new szMsg[256]
  327. if (bPrefix){
  328. format(szMsg, 255, "%L^n%L", iPlayer, "SM_RULE_PREFIX", str_to_num(szSearchedMsg[12]), iPlayer, szSearchedMsg)
  329. }
  330. else{
  331. format(szMsg, 255, "%L", iPlayer, szSearchedMsg)
  332. }
  333. func_print_message(iPlayer, szMsg, iMode, iStyle, true)
  334. }
  335.  
  336. if (strlen(szTargetName)){
  337. log_amx("%L", LANG_SERVER, "SM_PRINT_LOG", szAdminName, szTargetName, szSearchedMsg, iMode, iStyle)
  338. }
  339. return PLUGIN_HANDLED
  340. }
  341.  
  342. public cmd_server_list(id, level, cid){
  343. if (!cmd_access(id, level, cid, 1)){
  344. return PLUGIN_HANDLED
  345. }
  346. new szCommand[32]
  347. read_argv(0, szCommand, 31)
  348.  
  349. new iType, iTotalMsg
  350. if (equal(szCommand, "amx_list_msg")){
  351. iType = SM_MESSAGES
  352. iTotalMsg = g_iMsgCount
  353. }
  354. else if (equal(szCommand, "amx_list_rule")){
  355. iType = SM_RULES
  356. iTotalMsg = g_iRuleCount
  357. }
  358. else if (equal(szCommand, "amx_list_info")){
  359. iType = SM_INFOS
  360. iTotalMsg = g_iInfoCount
  361. }
  362.  
  363. // Technically we should never get here
  364. if (!iType){
  365. client_print(id, print_console, "%L", LANG_PLAYER, "SM_ERROR_SEARCH")
  366. return PLUGIN_HANDLED
  367. }
  368.  
  369. new param[5]
  370. param[0] = id //player id
  371. param[1] = iType //msg type
  372. param[2] = iTotalMsg //total msg
  373. param[3] = 0 //current msg
  374. param[4] = 0 //printed msg
  375. func_list_messages(param)
  376.  
  377. return PLUGIN_HANDLED
  378. }
  379.  
  380. /* == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == ==
  381. FUNCTIONS
  382.  == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == ==*/
  383.  
  384. public func_print_message(id, szMsg[], iMode, iStyle, bool:bSound){
  385.  
  386. if (is_user_connected(id) && g_bMsgEnabled[id]){
  387.  
  388. // Check if we can use the tutor, otherwise we send a hudmessage
  389. if (iMode == 4 && g_iActivity[id] == 0){
  390. iMode = 3
  391. }
  392.  
  393. // Store Messages into a Buffer to replace all placeholders
  394. new szBuffer[384]
  395. copy(szBuffer, 383, szMsg)
  396.  
  397. // Replace all \n with ^n because it is difficult to type "^" in the console. So you can use \n for a word wrap.
  398. replace_all(szBuffer, 383, "\n", "^n")
  399.  
  400. // Replace placeholders with their expressions
  401. new szReplacement[64], iSeconds, iMinutes, iHours
  402. get_cvar_string("hostname", szReplacement, 63)
  403. replace(szBuffer, 383, "#hostname#", szReplacement)
  404.  
  405. get_user_name(id, szReplacement, 63)
  406. replace(szBuffer, 383, "#playername#", szReplacement)
  407.  
  408. get_cvar_string("amx_nextmap", szReplacement, 63)
  409. replace(szBuffer, 383, "#nextmap#", szReplacement)
  410.  
  411. get_mapname(szReplacement, 63)
  412. replace(szBuffer, 383, "#currentmap#", szReplacement)
  413.  
  414. get_time("%m/%d/%Y - %H:%M:%S", szReplacement, 63)
  415. replace(szBuffer, 383, "#time#", szReplacement)
  416.  
  417. iSeconds = get_timeleft()
  418. format(szReplacement, 63, "%d:%02d", (iSeconds / 60), (iSeconds % 60))
  419. replace(szBuffer, 383, "#timeleft#", szReplacement)
  420.  
  421. iSeconds = get_user_time(id)
  422. iHours = iSeconds / 3600
  423. iMinutes = (iSeconds - (iHours * 3600)) / 60
  424. iSeconds -= ((iHours * 3600) + (iMinutes * 60))
  425. format(szReplacement, 63, "%d:%02d:%02d", iHours, iMinutes, iSeconds)
  426. replace(szBuffer, 383, "#playtime#", szReplacement)
  427.  
  428. // Create messages and cut all chars over 256
  429. copy(szMsg, 255, szBuffer)
  430.  
  431. switch(iMode){
  432. case 1: {
  433. replace_all(szMsg, 255, "^n", " ")
  434. Create_ChatMsg(id, szMsg)
  435. }
  436. case 2: {
  437. replace_all(szMsg, 255, "^n", " ")
  438. client_print(id, print_center, szMsg)
  439. }
  440. case 3: {
  441. set_hudmessage(0, 200, 0, 0.05, 0.35, 2, 0.1, get_pcvar_num(CVAR_show_time) < 5 ? 5.0 : get_pcvar_float(CVAR_show_time), 0.02, 0.02, 8)
  442. show_hudmessage(id, szMsg)
  443. }
  444. case 4: {
  445. // We can use only 192 chars for a tutor msg
  446. format(szMsg, 192, szMsg)
  447. Create_TutorMsg(id, szMsg, iStyle, bSound)
  448. }
  449. default: client_print(id, print_console, szMsg)
  450. }
  451. }
  452. }
  453.  
  454. public func_list_messages(param[]){
  455. new id = param[0]
  456. if (param[3] < param[2]){
  457.  
  458. new szPrint[20], iLen
  459. if (param[1] == SM_MESSAGES){
  460. iLen += format(szPrint, 19, "SERVER_MSG_")
  461. }
  462. else if (param[1] == SM_RULES){
  463. iLen += format(szPrint, 19, "SERVER_RULE_")
  464. }
  465. else if (param[1] == SM_INFOS){
  466. iLen += format(szPrint, 19, "SERVER_INFO_")
  467. }
  468.  
  469. for(new i=param[3];i<=param[2];i++){
  470. new szArg[4]
  471. num_to_str(i, szArg, 3)
  472. format(szPrint[iLen], 19 - iLen, szArg)
  473. if (is_msg_valid(szPrint)){
  474. if (param[4] == 0){
  475. if (param[1] == SM_MESSAGES){
  476. client_print(id, print_console, "^n%L", LANG_PLAYER, "SM_START_MSG_LISTING")
  477. }
  478. else if (param[1] == SM_RULES){
  479. client_print(id, print_console, "^n%L", LANG_PLAYER, "SM_START_RULE_LISTING")
  480. }
  481. else if (param[1] == SM_INFOS){
  482. client_print(id, print_console, "^n%L", LANG_PLAYER, "SM_START_INFO_LISTING")
  483. }
  484. }
  485. param[4]+=1
  486.  
  487. new szMsg[256]
  488. format(szMsg, 255, "%L", id, szPrint)
  489. replace_all(szMsg, 255, "\n", i > 9 ? "^n " : "^n ")
  490. client_print(id, print_console, "%i: %s", i, szMsg)
  491.  
  492. if (param[4] % 10 == 0){
  493. param[3]+=1
  494. break
  495. }
  496. }
  497. param[3]+=1
  498. }
  499. set_task(0.1, "func_list_messages", id, param, 5)
  500. }
  501. else{
  502. console_print(id,"^n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+^n")
  503. }
  504. }
  505.  
  506. public func_show_message(taskid){
  507.  
  508. // Define the next message
  509. new iTypes, iTotalMsg
  510. if (get_pcvar_num(CVAR_msg_show)){
  511. iTypes += SM_MESSAGES
  512. iTotalMsg += g_iMsgCount
  513. }
  514. if (get_pcvar_num(CVAR_rule_show)){
  515. iTypes += SM_RULES
  516. iTotalMsg += g_iRuleCount
  517. }
  518. if (get_pcvar_num(CVAR_info_show)){
  519. iTypes += SM_INFOS
  520. iTotalMsg += g_iInfoCount
  521. }
  522. if (!iTypes || !iTotalMsg){
  523. return PLUGIN_HANDLED
  524. }
  525.  
  526. new bool:bFound, iTryFind
  527. while (!bFound && iTryFind < 3){
  528. iTryFind+=1
  529.  
  530. new szNextMsg[16], iNextMsg = random_num(1, iTotalMsg)
  531. switch(iTypes){
  532. case SM_MESSAGES + SM_RULES + SM_INFOS: {
  533. if (iNextMsg <= g_iMsgCount){
  534. format(szNextMsg, 15, "SERVER_MSG_%i", iNextMsg)
  535. }
  536. else if (iNextMsg <= g_iMsgCount + g_iRuleCount){
  537. format(szNextMsg, 15, "SERVER_RULE_%i", iNextMsg - g_iMsgCount)
  538. }
  539. else{
  540. format(szNextMsg, 15, "SERVER_INFO_%i", iNextMsg - g_iMsgCount - g_iRuleCount)
  541. }
  542. }
  543. case SM_MESSAGES + SM_RULES: {
  544. if (iNextMsg <= g_iMsgCount){
  545. format(szNextMsg, 15, "SERVER_MSG_%i", iNextMsg)
  546. }
  547. else{
  548. format(szNextMsg, 15, "SERVER_RULE_%i", iNextMsg - g_iMsgCount)
  549. }
  550. }
  551. case SM_MESSAGES + SM_INFOS: {
  552. if (iNextMsg <= g_iMsgCount){
  553. format(szNextMsg, 15, "SERVER_MSG_%i", iNextMsg)
  554. }
  555. else{
  556. format(szNextMsg, 15, "SERVER_INFO_%i", iNextMsg - g_iMsgCount)
  557. }
  558. }
  559. case SM_RULES + SM_INFOS: {
  560. if (iNextMsg <= g_iRuleCount){
  561. format(szNextMsg, 15, "SERVER_RULE_%i", iNextMsg)
  562. }
  563. else{
  564. format(szNextMsg, 15, "SERVER_INFO_%i", iNextMsg - g_iRuleCount)
  565. }
  566. }
  567. case SM_MESSAGES: {
  568. format(szNextMsg, 15, "SERVER_MSG_%i", iNextMsg)
  569. }
  570. case SM_RULES: {
  571. format(szNextMsg, 15, "SERVER_RULE_%i", iNextMsg)
  572. }
  573. case SM_INFOS: {
  574. format(szNextMsg, 15, "SERVER_INFO_%i", iNextMsg)
  575. }
  576. }
  577.  
  578. if ((!equali(g_szLastMsg[0], szNextMsg) && !equali(g_szLastMsg[1], szNextMsg) && !equali(g_szLastMsg[2], szNextMsg)) || iTryFind == 3){
  579. if (is_msg_valid(szNextMsg)){
  580. bFound = true
  581.  
  582. // Store the last messages to minimize the chance of duplicate messages
  583. if (iTotalMsg > 3) copy(g_szLastMsg[2], 15, g_szLastMsg[1])
  584. if (iTotalMsg > 2) copy(g_szLastMsg[1], 15, g_szLastMsg[0])
  585. if (iTotalMsg > 1) copy(g_szLastMsg[0], 15, szNextMsg)
  586.  
  587. new iMode, iStyle, bool:bPrefix
  588. if (equal(szNextMsg, "SERVER_MSG_", 11)){
  589. iMode = get_pcvar_num(CVAR_msg_mode)
  590. iStyle = get_pcvar_num(CVAR_msg_style)
  591. }
  592. else if (equal(szNextMsg, "SERVER_RULE_", 12)){
  593. iMode = get_pcvar_num(CVAR_rule_mode)
  594. iStyle = get_pcvar_num(CVAR_rule_style)
  595. bPrefix = get_pcvar_num(CVAR_rule_prefix) ? true : false
  596. }
  597. else if (equal(szNextMsg, "SERVER_INFO_", 12)){
  598. iMode = get_pcvar_num(CVAR_info_mode)
  599. iStyle = get_pcvar_num(CVAR_info_style)
  600. }
  601.  
  602. new szFlags[6], iPlayers[32], pNum, iSkip = get_pcvar_num(CVAR_show_skip)
  603. if (iSkip) add(szFlags, 5, iSkip == 1 ? "a" : "b")
  604. add(szFlags, 5, "c")
  605. get_players(iPlayers, pNum, szFlags)
  606. for (new p = 0; p < pNum; p++){
  607. new szMsg[256]
  608. if (bPrefix){
  609. format(szMsg, 255, "%L^n%L", iPlayers[p], "SM_RULE_PREFIX", str_to_num(szNextMsg[12]), iPlayers[p], szNextMsg)
  610. }
  611. else{
  612. format(szMsg, 255, "%L", iPlayers[p], szNextMsg)
  613. }
  614. func_print_message(iPlayers[p], szMsg, iMode, iStyle, false)
  615. }
  616. }
  617. }
  618. }
  619.  
  620. return PLUGIN_CONTINUE
  621. }
  622.  
  623. /* == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == ==
  624. STOCKS
  625.  == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == ==*/
  626.  
  627. // Diese Funktion ermittelt alle Zielpersonen (iPlayers), an denen ein Befehl ausgeführt werden soll.
  628. // Dazu kann auch in der Variablen iSkip angegeben werden, welche Personen übersprungen werden sollen.
  629. // Des Weiteren gibt die Funktion den Namen der Zielgruppe in der Variablen szTargetName zurück.
  630. stock get_cmd_targets(id, szArg[], iPlayers[32], &pNum, szTargetName[32], iSkip = SKIP_NOTHING){
  631. new szFlags[6]
  632. if (iSkip & SKIP_DEAD) add(szFlags, 5, "a")
  633. if (iSkip & SKIP_ALIVE) add(szFlags, 5, "b")
  634. if (iSkip & SKIP_BOTS) add(szFlags, 5, "c")
  635. if (iSkip & SKIP_REAL) add(szFlags, 5, "d")
  636.  
  637. if (equali(szArg[1], "A") || equali(szArg[1], "ALL")){
  638. copy(szTargetName, 31, "everyone")
  639. get_players(iPlayers, pNum, szFlags)
  640. }
  641. else if (equali(szArg[1], "C") || equali(szArg[1], "CT") || equali(szArg[1], "COUNTER")){
  642. copy(szTargetName, 31, "all Counter-Terrorists")
  643. add(szFlags, 5, "e")
  644. get_players(iPlayers, pNum, szFlags, "CT")
  645. }
  646. else if (equali(szArg[1], "T") || equali(szArg[1], "TE") || equali(szArg[1], "TERROR") || equali(szArg[1], "TERRORIST")){
  647. copy(szTargetName, 31, "all Terrorists")
  648. add(szFlags, 5, "e")
  649. get_players(iPlayers, pNum, szFlags, "TERRORIST")
  650. }
  651.  
  652. if (pNum == 0){
  653. client_print(id, print_console, "[AMXX] %L", LANG_PLAYER, "SM_NO_CLIENT")
  654. return 0
  655. }
  656.  
  657. return 1
  658. }
  659.  
  660. stock bool:is_msg_valid(szSearchedMsg[]){
  661. new bool:bFound, iLanguages
  662. if (file_exists(g_szFilePath)){
  663. new szMsg[32], szBuffer[128], szLastMsg[32], fp=fopen(g_szFilePath, "r")
  664. while (!feof(fp) && !bFound && iLanguages < 2){
  665. szBuffer[0]='^0'
  666. fgets(fp, szBuffer, 127)
  667. parse(szBuffer, szMsg, 31)
  668. if (!equali(szMsg, szLastMsg)){
  669.  
  670. // Saves the current message for blocking duplicative messages
  671. copy(szLastMsg, 31, szMsg)
  672.  
  673. if (equali(szMsg, szSearchedMsg, strlen(szSearchedMsg))){
  674. bFound = true
  675. }
  676.  
  677. // Stop loop if we reached the second language
  678. else if (szMsg[0] == '[' && szMsg[3] == ']'){
  679. iLanguages += 1
  680. }
  681. }
  682. }
  683. fclose(fp)
  684. }
  685.  
  686. // Message or File not exists
  687. if (!bFound){
  688. return false
  689. }
  690. return true
  691. }
  692.  
  693. stock SaveData(id){
  694. new szAuthid[32], szKey[64], szData[16]
  695.  
  696. get_user_authid(id, szAuthid, 31)
  697. format(szKey, 63, "SERV_MSG_%s", szAuthid)
  698.  
  699. new iMinutes = g_iActivity[id] + (get_user_time(id) / 60)
  700. num_to_str(iMinutes, szData, 15)
  701.  
  702. set_vaultdata(szKey, szData)
  703. }
  704.  
  705. stock LoadData(id){
  706. new szAuthid[32], szKey[64], szData[16]
  707.  
  708. get_user_authid(id, szAuthid, 31)
  709. format(szKey, 63, "SERV_MSG_%s", szAuthid)
  710.  
  711. if (vaultdata_exists(szKey)){
  712. get_vaultdata(szKey, szData, 15)
  713. g_iActivity[id] = strlen(szData) ? str_to_num(szData) : 0
  714. g_bMsgEnabled[id] = (g_iActivity[id] < get_pcvar_num(CVAR_min_activity) || !get_pcvar_num(CVAR_min_activity)) ? true : false
  715. }
  716. else{
  717. g_iActivity[id] = 0
  718. g_bMsgEnabled[id] = true
  719. }
  720. }
  721.  
  722. /* == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == ==
  723. CREATES (Messages and Effects)
  724.  == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == ==*/
  725.  
  726. stock Create_TutorMsg(id, szMsg[], iStyle, bool:bSound){
  727.  
  728. if (is_user_connected(id)){
  729. // A user message must be smaller than 192 Bytes, otherwise the server crashs.
  730. szMsg[182]='^0'
  731.  
  732. // Playback of a typical sound of the tutor
  733. if (bSound || get_pcvar_num(CVAR_tutor_sound)){
  734. switch(iStyle){
  735. case 1: client_cmd(id, "spk events/friend_died.wav")
  736. case 2: client_cmd(id, "spk events/enemy_died.wav")
  737. case 5: client_cmd(id, "spk events/task_complete.wav")
  738. default: client_cmd(id, "spk events/tutor_msg.wav")
  739. }
  740. }
  741.  
  742. // I think we can remove this but this is also called by the original tutor, so we emulate this too.
  743. Remove_TutorMsg(TASK_REMOVE_TUTOR+id)
  744.  
  745. // Create a Tutor message
  746. message_begin(MSG_ONE_UNRELIABLE , gMsgTutorText, {0, 0, 0}, id)
  747. write_string(szMsg) // displayed message
  748. write_byte(0) // ???
  749. write_short(0) // ???
  750. write_short(0) // ???
  751. write_short(1<<iStyle) // class of a message
  752. message_end()
  753.  
  754. // Hide Tutor in ... seconds
  755. set_task(get_pcvar_num(CVAR_show_time) < 5 ? 5.0 : get_pcvar_float(CVAR_show_time), "Remove_TutorMsg", TASK_REMOVE_TUTOR+id)
  756. }
  757. }
  758.  
  759. public Remove_TutorMsg(taskid){
  760. if(task_exists(taskid)) remove_task(taskid)
  761. new id = taskid >= TASK_REMOVE_TUTOR ? taskid - TASK_REMOVE_TUTOR : taskid
  762.  
  763. message_begin(MSG_ONE_UNRELIABLE , gMsgTutorClose, {0, 0, 0}, id)
  764. message_end()
  765. }
  766.  
  767. stock Create_ChatMsg(id, szMsg[]){
  768. format(szMsg, 255, "^x04%s", szMsg)
  769.  
  770. // A user message must be smaller than 192 Bytes, otherwise the server crashs.
  771. szMsg[182]='^0'
  772.  
  773. message_begin(MSG_ONE_UNRELIABLE , gMsgSayText, {0, 0, 0}, id)
  774. write_byte(id)
  775. write_string(szMsg)
  776. message_end()
  777. }
  778.