HLMOD.HU Forrás Megtekintés - www.hlmod.hu
  1. /*
  2.   Fordította: BBk
  3. */
  4.  
  5. /***************************************************************************
  6. * This plugin reads keyword/wav/mp3 combinations from a configfile and when
  7. * a player says one of the keywords, it will trigger HL to play that Wav/MP3
  8. * file to all or dead/alive players. It allows reloading of the file without
  9. * restarting the current level, as well as adding keyword/wav/mp3
  10. * combinations from the console during gameplay. Also includes banning
  11. * players from playing sounds.
  12. *
  13. * Credits:
  14. * - Luke Sankey -> original author
  15. * - HunteR -> modifications
  16. *
  17. * Functions included in this plugin:
  18. * mp_sank_sounds_download 1/0 - turn internal download system on/off
  19. * mp_sank_sounds_freezetime <x> - x = time in seconds to wait till first sounds are played (connect sound)
  20. * mp_sank_sounds_obey_duration <x> - determine whos sounds may overlap (bit mask) (see readme.txt)
  21. * amx_sound - turn Sank Sounds on/off
  22. * amx_sound_help - prints all available sounds to console
  23. * amx_sound_play <dir/sound> - plays a specific wav/mp3/speech
  24. * amx_sound_add <keyword> <dir/sound> - adds a word/wav/mp3/speech
  25. * amx_sound_reload <filename> - reload your snd-list.cfg or custom .cfg
  26. * amx_sound_remove <keyword> <dir/sound> - remove a word/wav/mp3
  27. * amx_sound_write <filename> - write all settings to custom .cfg
  28. * amx_sound_reset <player> - resets quota for specified player
  29. * amx_sound_debug - prints debugs (debug mode must be on, see define below)
  30. * amx_sound_ban <player> - bans player from using sounds for current map
  31. * amx_sound_unban <player> - unbans player from using sounds for current map
  32. * amx_sound_top <x> - shows the top <x> most played keywords (leave <x> away for top 10)
  33. *
  34. * Config file settings:
  35. * SND_WARN - The number at which a player will get warned for playing too many sounds each map
  36. * SND_MAX - The number at which a player will get muted for playing too many sounds each map
  37. * SND_MAX_DUR - The maximum amount of seconds a player can play sounds each map (float )
  38. * SND_JOIN - The Sounds to play when a person joins the game
  39. * SND_EXIT - The Sounds to play when a person exits the game
  40. * SND_DELAY - Minimum delay between sounds (float)
  41. * SND_MODE XX - Determinates who can play and who can hear sounds (see readme.txt for details)
  42. * SND_IMMUNITY "XYZ" - Determine the access levels which shall have immunity to warn/ban
  43. * EXACT_MATCH 1/0 - Determinates if plugin triggers on exact match, or partial speech match
  44. * ADMINS_ONLY 1/0 - Determinates if only admins are allowed to play sounds
  45. * DISPLAY_KEYWORDS 1/0 - Determinates if keywords are shown in chat or not
  46. *
  47. * Commands available for each player:
  48. * amx_sound_help - prints all available sounds to console
  49. * say "/soundson" - now the player can hear sounds again
  50. * say "/soundsoff" - player disables ability to hear sounds
  51. * say "/sounds" - shows a list of all sounds
  52. * say "/soundlist" - shows a list of all sounds
  53. *
  54. * ported to Amx Mod X by White Panther
  55. *
  56. * v1.0.2 (original 4.1 but this is AmxModX):
  57. * - initial release for AmxModX
  58. * - renamed commands to fit with AmxModX
  59. * - Admin sounds cannot be seen by normal people when using amx_sound_help
  60. * - sounds are precached from file
  61. * - fix: check if soundfile exist before precache (that should solve some probs)
  62. * - fix: if chat message was longer than 29 chars the first wav in cfg was played
  63. *
  64. * v1.1.3 :
  65. * - fixed bug with spaces between keywords and wavs
  66. * - multiple Join and Exit sounds can now be used
  67. * - fixed bug where connect and disconnect sound have not been played
  68. * - fixed bug where dead players could not hear sounds
  69. * - added bot check
  70. * - added option to only allow admins to play sounds
  71. *
  72. * v 1.2.4 :
  73. * - added mp3 support (they have to be in <Mod-Dir>/sound too) (engine module needed therefore) (+ hotfix: wavs not being played)
  74. * - changed the way of initializing each sound file (if bad file it wont be loaded and error msg will be printed)
  75. * - changed SND_KICK to SND_MAX
  76. * - increased default defines ( words: 40 - > 80 / each wavs: 10 -> 14 / file chars: 30 -> 60 )
  77. * - fixed bug for 32 players
  78. * - increased memory usage for variables to 64K (should fix probs)
  79. * - while parsing there is now a check if file exists (if not it wont be put in list)
  80. *
  81. * v1.2.5:
  82. * - added a cvar to enable or disable auto download (change will take place after restart/mapchange)
  83. *
  84. * v1.3:
  85. * - fixed:
  86. * - fixed prob where strings were copied into other strings with no size match
  87. * - removed bot detection (maybe this was causing some problems, playing sounds to bots does not do any harm)
  88. * - admin sounds could not be played (eg: hallo; misc/hi.wav;@misc/hi2.wav -> hi2.wav was not played, even by admins)
  89. * - added:
  90. * - type "/sounds" in chat to get a MOTD window with all sounds available (not all mods support MOTD window)
  91. * - ability for speech sounds (like the AmxModX's speechmenu)
  92. * - admin check to "amx_sound_debug" so in debugmode only admins can use it
  93. * - list is now sorted by name for more readable output (sort by Bailopan) (sort can be turned off by define)
  94. *
  95. * v1.3.2:
  96. * - fixed:
  97. * - mp3 support not working
  98. * - changed:
  99. * - mp3 now dont need to be in sound folder but anywhere you want (anywhere in your mod folder though)
  100. * just specify the correct path (eg: music/mymusic/my.mp3 or sound/testmp3/test.mp3 or mainfolder.mp3)
  101. * - amx_sound_debug can now also be used if debug mode is off (this function prints the sound matrix)
  102. *
  103. * v1.3.3:
  104. * - added:
  105. * - cvar "mp_sank_sounds_freezetime" to define when first connect/disconnect sounds are played after mapchange (in seconds)
  106. *
  107. * v1.3.4:
  108. * - fixed:
  109. * - error where some players could not hear any sound
  110. * - changed:
  111. * - some log messages got better checks
  112. * - reimplemented check for bots
  113. *
  114. * v1.3.5:
  115. * - added:
  116. * - with "/soundson" and "/soundsoff" each player can activate/deactivate the ability to hear sounds
  117. *
  118. * v1.3.7:
  119. * - added:
  120. * - "DISPLAY_KEYWORDS" to config, it determinates if keywords are shown in chat or not
  121. * - option to load specific sounds only on specific maps
  122. * - changed:
  123. * - "SND_DELAY" is now a float
  124. *
  125. * v1.4.0:
  126. * - added:
  127. * - option to load packages of sounds, packages cycle with each map-change (packages must be numbered)
  128. * - ability to ban people from using sounds (only for current map) ( amx_sound_ban <player> <1/0 OR on/off> )
  129. * - changed:
  130. * - precache method changed
  131. * - all keywords are now stored into buffer, even those sounds that are not precached
  132. * - code improvements
  133. *
  134. * v1.4.1:
  135. * - fixed:
  136. * - when setting DISPLAY_KEYWORDS to 0 chat was disabled
  137. *
  138. * v1.4.2:
  139. * - fixed:
  140. * - players could be banned from sounds after reconnect
  141. * - added:
  142. * - option to include sounds from "half-life.gcf" and <current mod>.gcf
  143. *
  144. * v1.4.2b:
  145. * - fixed:
  146. * - compile error when disabling mp3 support
  147. *
  148. * v1.4.3:
  149. * - fixed:
  150. * - keywords without or with wrong files will not be added anymore
  151. * - possible errors fixed
  152. * - error with MOTD display fixed
  153. *
  154. * v1.4.5:
  155. * - fixed:
  156. * - ADMINS_ONLY was not working always
  157. * - players could only play less sound than specified in SND_MAX
  158. * - runtime error with amx_sound_reload
  159. * - added:
  160. * - sounds can now also be used in team chat
  161. * - amx_sound_unban to unban players
  162. * - changed:
  163. * - keyword check tweaked
  164. * - amx_sound_ban now do not expect additional parameter "on / off" or "1 / 0"
  165. *
  166. * v1.4.7:
  167. * - fixed:
  168. * - keywords with admin and public sounds, could block normal players from playing normal sounds
  169. * - runtime error which could stop plugin to work
  170. * - message telling players to wait till next sound can be played is not displayed on every word anymore
  171. *
  172. * v1.5.0: ( AmxModX 1.71 or better ONLY )
  173. * - fixed:
  174. * - sounds being not in a subfolder ( eg: sound/mysound.wav ) will now be played
  175. * - reconnecting to reset quota will not work anymore
  176. * - no more overlapping sounds ( Join and Exit sounds will still overlap other but others cannot overlap them )
  177. * - amx_sound_reset now accepts IDs too
  178. * - sound quota could be increased even if no sound was played
  179. * - added:
  180. * - sound duration is now calculated
  181. * - changed:
  182. * - SND_DELAY does not affect admins anymore
  183. * - SND_SPLIT has been replaced with more customizable SND_MODE
  184. * - removed support to disable MP3
  185. *
  186. * v1.5.0b:
  187. * - fixed:
  188. * - rare runtime error
  189. *
  190. * v1.5.1:
  191. * - fixed:
  192. * - calculation for MP3's encoded with MPEG 2
  193. * - added:
  194. * - saying "/soundlist" will now show sound list like "/sounds" does
  195. * - CVAR: "mp_sank_sounds_obey_duration" to determine if sounds may overlap or not ( default: 1 = do not overlap )
  196. *
  197. * v1.5.1b:
  198. * - fixed:
  199. * - runtime error in mp3 calculation
  200. *
  201. * v1.5.2:
  202. * - fixed:
  203. * - support for SND_DELAY was accidently removed
  204. * - some possible minor bugs
  205. * - added:
  206. * - SND_MAX_DUR: maximum of seconds a player can play sounds each map
  207. * - two new options for SND_MODE ( read help for more information )
  208. *
  209. * v1.5.3:
  210. * - fixed:
  211. * - admin being able to play sounds when "mp_sank_sounds_obey_duration" was on
  212. * - added:
  213. * - CVAR: "mp_sank_sounds_motd_address" to use a website to show all sounds ( empty cvar = no website will be used )
  214. *
  215. * v1.5.4:
  216. * - fixed:
  217. * - error in mp3 calculation
  218. * - when using "mapnameonly" option, following options have been ignored
  219. * - added:
  220. * - minor detection for damaged/invalid files
  221. * - changed:
  222. * - both "SND-LIST.CFG" and "snd-list.cfg" will work now ( linux )
  223. * - code improvements
  224. * - faster config parsing/writing
  225. *
  226. * v1.5.5:
  227. * - fixed:
  228. * - error in mp3 calculation ( once again :( )
  229. * - added:
  230. * - additional debug info for mp3's when compiled in DEGUB_MODE 1
  231. *
  232. * v1.5.6:
  233. * - fixed:
  234. * - sounds located in <MODDIR>/sounds/ (no subfolder) not being played if dead and alive not being splitted
  235. * - long lines not being parsed correctly
  236. * - players could play one more sound than allowed
  237. *
  238. * v1.6.0: (16.4.2007)
  239. * - fixed:
  240. * - speech sounds not being played
  241. * - join / exit sound duration was incorrect
  242. * - SND_WARN / SND_MAX error checking could display wrong error
  243. * - added:
  244. * - access can be defined for every sound and keyword seperately
  245. * - changed:
  246. * - partly rewritten
  247. * - way of saving data
  248. * - sounds when enabling and disabling Sank Sounds are not precached anymore ( hard coded )
  249. * - many code improvements
  250. *
  251. * v1.6.2: (16.01.2008)
  252. * - fixed:
  253. * - removed debug message
  254. * - admins are not included in overlapping check anymore
  255. * - non admins could see sounds that are for admins only
  256. * - bug when adding and removing sounds ingame to list (wierd keywords and sounds)
  257. * - added:
  258. * - "PLAY_COUNT_KEY" and "PLAY_COUNT" to data structure to count how often a key and sound has been used
  259. * - messages for players when enabling/disabling sounds and if players have to wait cause of delay
  260. * - changed:
  261. * - sank sounds is now precaching sounds after plugin init (fakemeta modul needed)
  262. * - no more engine, but therefore fakemeta is needed
  263. * - minor code tweaks
  264. *
  265. * v1.6.3: (29.02.2008)
  266. * - fixed:
  267. * - runtime error if more sounds added than defined in MAX_KEYWORDS
  268. * - commenting SND_JOIN and SND_EXIT (adding # or // infront of them) made the following sounds to be added to these options
  269. * - changed:
  270. * - CVAR "mp_sank_sounds_obey_duration" is now a bitmask (see readme.txt)
  271. *
  272. * v1.6.4: (21.12.2008)
  273. * - added:
  274. * - warning for unsupported mp3 files
  275. * - changed:
  276. * - mp3 detection code rewritten
  277. *
  278. * v1.6.5: (14.01.2009)
  279. * - fixed:
  280. * - wav detection for bad files
  281. *
  282. * v1.6.5b: (22.01.2009)
  283. * - changed:
  284. * - removed warning for unsupported mp3s (they are supported)
  285. *
  286. * v1.6.6: (03.03.2009)
  287. * - fixed:
  288. * - last entry in configfile was not sorted
  289. * - runtime error with keywords without any sound
  290. * - exploit where SND_JOIN and SND_EXIT could be used as keywords
  291. * - changed:
  292. * - SND_JOIN and SND_JOIN do not have to be before any other keyword
  293. *
  294. * v1.6.6b: (29.03.2009)
  295. * - fixed:
  296. * - runtime error
  297. * - if SND_JOIN or SND_JOIN was not at the beginning and more sounds were added afterwards, those new sounds overwrote previous sounds
  298. *
  299. * v1.6.6c: (30.06.2009)
  300. * - fixed:
  301. * - removed debug message
  302. *
  303. * v1.6.6d: (03.07.2009)
  304. * - fixed:
  305. * - speech files not being played
  306. *
  307. * v1.7.0: (08.08.2011)
  308. * - added:
  309. * - further checks for bad configfiles
  310. * - new option SND_IMMUNITY (defines all levels that shall get immunity)
  311. * - info when used last sound
  312. * - amx_sound_top <x> shows the top <x> (default 10) most played keywords during current map
  313. * - using keywords followed by a ! (eg: haha!) will play the sound bound to a location (WAVs only)
  314. * you can move away from the sound. NO config change needed
  315. * - changed:
  316. * - WAVs are not bound to <mod-dir>/sound folder anymore (config change needed unfortunately)
  317. * all sounds now need the full path (eg: haha; sound/misc/haha.wav)
  318. *
  319. * v1.7.1: (11.08.2011)
  320. * - fixed:
  321. * - WAVs not downloading and producing error messages
  322. *
  323. * v1.8.0: (11.01.2012)
  324. * - fixed:
  325. * - adding new sounds with console command could add it but it would not be available
  326. * - changed:
  327. * - dynamic arrays are now used to store key/sound data to remove limits
  328. * - saving to default config file is now allowed
  329. *
  330. * v1.8.1: (14.03.2013)
  331. * - fixed:
  332. * - determination if sound can be played for admins
  333. * - "amx_sound_add" could add empty keywords if sound was invalid
  334. * - "amx_sound_add" is not checking sounds if they exist anymore
  335. * - changed:
  336. * - increased motd webpage link length to 255 characters
  337. *
  338. * v1.8.2: (01.09.2013)
  339. * - fixed:
  340. * - exit sounds could be replaced by keyword sounds
  341. *
  342. * v1.8.3: (21.10.2013)
  343. * - fixed:
  344. * - ADMINS_ONLY setting was ignored
  345. *
  346. * v1.8.4: (06.01.2014)
  347. * - fixed:
  348. * - admins could get spammed with "You are muted" messages
  349. *
  350. * IMPORTANT:
  351. * a) if u want to use the internal download system do not use more than 200 sounds (HL cannot handle it)
  352. * (also depending on map, you may need to use even less)
  353. * but if u disable the internal download system u can use as many sounds as the plugin can handle
  354. * (max should be over 100000 sounds (depending on the Array Defines ), BUT the plugin speed
  355. * is another question with thousands of sounds ;) )
  356. *
  357. * b) File has to look like this:
  358. * SND_MAX; 20
  359. * SND_MAX_DUR; 180.0
  360. * SND_WARN; 17
  361. * SND_JOIN; misc/hi.wav
  362. * SND_EXIT; misc/comeagain.wav
  363. * SND_DELAY; 0.0
  364. * SND_MODE; 15
  365. * SND_IMMUNITY; "l"
  366. * EXACT_MATCH; 1
  367. * ADMINS_ONLY; 0
  368. * DISPLAY_KEYWORDS; 1
  369. *
  370. * # Word/Sound combinations:
  371. * crap; misc/awwcrap.Wav;misc/awwcrap2.wav
  372. * woohoo; misc/woohoo.wav
  373. * @ha ha; misc/haha.wav
  374. * @abm@godlike; misc/godlike.wav
  375. * doh; misc/doh.wav;misc/doh2.wav;@misc/doh3.wav
  376. * mp3; sound/mymp3.mp3;music/mymp3s/number2.mp3;mainfolder.mp3
  377. * target; "target destroyed"
  378. *
  379. * mapname TESTMAP
  380. * testmap; misc/doh.wav
  381. * mapname TESTMAP2
  382. * testmap2; misc/haha.wav;sound/mymp3.mp3
  383. * testmap3; misc/hi.wav
  384. *
  385. * package 1
  386. * haha2; misc/haha.wav
  387. * doh3; misc/doh3.wav
  388. * package 2
  389. * hi; misc/hi.wav
  390. *
  391. * modspecific
  392. * <keyword>; <location>/<name>.wav
  393. *
  394. * Follow these instructions
  395. * wavs:
  396. * - base directory is "mod-dir/sound/"
  397. * - put EXACT PATH to the wav beginning from base directory (eg misc/test.wav or test2.wav)
  398. * mp3:
  399. * - base directory is "mod-dir/"
  400. * - put the EXACT PATH to the mp3 (eg sound/test.mp3 or music/mymp3s/test2.mp3 or mainfolder.mp3)
  401. * speech:
  402. * - base directory is "mod-dir/sound/vox/"
  403. * - these files are inside the steam package
  404. * - for a list look at c)
  405. * mapname:
  406. * - type mapname <space> the real mapname (without .bsp)
  407. * - everthing below will be loaded only on this map
  408. * mapnameonly:
  409. * - type mapnameonly <space> the real mapname (without .bsp)
  410. * - everthing below will be loaded only on this map
  411. * - everthing below will be only available on this map
  412. * package:
  413. * - type package <space> number
  414. * - everthing below will be loaded only once and switched to next package on map-change
  415. * - if only 1 package this package will be used every map-change
  416. * modspecific:
  417. * - every sound below that line must be inside half-life.gcf or <yourmod>.gcf
  418. * - if you add other files then said above they may/will crash your server as these sounds are assumed to be existent
  419. *
  420. * c) speech sounds must be put in quotes (eg: target; "target destroyed")
  421. * you may not put different speech types into 1 speech or the speech wont be played
  422. * speech without directory is used from "vox/.."
  423. * first specify the speech type (ONLY ONCE eg hgrunt/) and then put the words with spaces between each speech
  424. * eg "hgrunt/yessir barney/stop1" will not work as 2 different speeches
  425. * BUT "hgrunt/yessir no" will work
  426. * get all available speech sounds here:
  427. * "http://www.adminmod.org/help/online/Admin_Mod_Reference/Half_Life_Sounds.htm"
  428. *
  429. * d) "@" infront of a
  430. * - word means only admin can use this word
  431. * - wav/mp3/speech/word means players can use the word but this sound is only played by admins
  432. *
  433. * e) custom admin access:
  434. * - infront of a word/sound add @<ACCESS_LEVELS>@
  435. * - replace <ACCESS_LEVELS> with the access levels you desire
  436. * - @abc@ means: everyone with access a, b or c can use it
  437. *
  438. ***************************************************************************/
  439.  
  440. #include <amxmodx>
  441. #include <amxmisc>
  442. #include <fakemeta>
  443.  
  444. // set this to 1 to get some debug messages
  445. #define DEBUG_MODE 0
  446.  
  447. // turn this off to stop list from being sorted by keywords in alphabetic order
  448. #define ALLOW_SORT 1
  449.  
  450. // Array Defines, ATTENTION: ( MAX_RANDOM + 1 ) * TOK_LENGTH must be smaller 2048 !!!
  451. #define BUFFER_LEN 2048 // Maximum number of space per line to use when reading configfile
  452. #define MAX_RANDOM 15 // Maximum number of tries to find a sound file
  453. #define TOK_LENGTH 60 // Maximum length of keyword and sound file strings
  454. #define MAX_BANS 32 // Maximum number of bans stored
  455. #define NUM_PER_LINE 6 // Number of words per line from amx_sound_help
  456.  
  457. //#pragma dynamic 16384
  458. #pragma dynamic 65536
  459.  
  460. #define ACCESS_ADMIN ADMIN_LEVEL_A
  461.  
  462. #define PLUGIN_AUTHOR "White Panther, Luke Sankey, HunteR"
  463. #define PLUGIN_VERSION "1.8.4"
  464.  
  465. new Enable_Sound[] = "misc/woohoo.wav" // Sound played when Sank Soounds being enabled
  466. new Disable_Sound[] = "misc/awwcrap.wav" // Sound played when Sank Soounds being disabled
  467.  
  468. new config_filename[128]
  469.  
  470. new SndCount[33] = {0, ...} // Holds the number telling how many sounds a player has played
  471. new Float:SndLenghtCount[33] = {0.0, ...}
  472. new SndOn[33] = {1, ...}
  473.  
  474. new SND_WARN = 0 // The number at which a player will get warned for playing too many sounds
  475. new SND_MAX = 0 // The number at which a player will get muted for playing too many sounds
  476. new Float:SND_MAX_DUR = 0.0
  477. new Float:SND_DELAY = 0.0 // Minimum delay between sounds
  478. new SND_MODE = 15 // Determinates who can play and who can hear sounds (dead and alive)
  479. new SND_IMMUNITY = ACCESS_ADMIN // Determine the access levels which shall have immunity to warn/ban (default ACCESS_ADMIN for backwards compatability)
  480. new EXACT_MATCH = 1 // Determinates if plugin triggers on exact match, or partial speech match
  481. new ADMINS_ONLY = 0 // Determinates if only admins are allowed to play sounds
  482. new DISPLAY_KEYWORDS = 1 // Determinates if keywords are shown in chat or not
  483.  
  484. new Float:NextSoundTime // spam protection
  485. new Float:Join_exit_SoundTime // spam protection 2
  486. new Float:LastSoundTime = 0.0
  487. new bSoundsEnabled = 1 // amx_sound <on/off> or <1/0>
  488.  
  489. new CVAR_freezetime, CVAR_obey_duration
  490.  
  491. new g_max_players
  492. new banned_player_steamids[MAX_BANS][60]
  493. new restrict_playing_sounds[33]
  494. new sound_quota_steamids[33][60]
  495.  
  496. new motd_sound_list_address[256]
  497.  
  498. enum
  499. {
  500. PARSE_SND_MAX,
  501. PARSE_SND_MAX_DUR,
  502. PARSE_SND_WARN,
  503. PARSE_SND_DELAY,
  504. PARSE_SND_MODE,
  505. PARSE_SND_IMMUNITY,
  506. PARSE_EXACT_MATCH,
  507. PARSE_ADMINS_ONLY,
  508. PARSE_DISPLAY_KEYWORDS,
  509. PARSE_KEYWORD
  510. }
  511.  
  512. enum
  513. {
  514. ERROR_NONE,
  515. ERROR_MAX_KEYWORDS,
  516. ERROR_STRING_LENGTH
  517. }
  518.  
  519. enum
  520. {
  521. RESULT_OK = 1,
  522. RESULT_BAD_ALIVE_STATUS = 0,
  523. RESULT_QUOTA_EXCEEDED = -1,
  524. RESULT_QUOTA_DURATION_EXCEEDED = -2,
  525. RESULT_SOUND_DELAY = -3,
  526. RESULT_ADMINS_ONLY = -4,
  527. }
  528.  
  529. enum
  530. {
  531. FLAG_IGNORE_AMOUNT = 1,
  532. FLAGS_JOIN_SND = 2,
  533. FLAGS_EXIT_SND = 4
  534. }
  535.  
  536. enum
  537. {
  538. SOUND_TYPE_SPEECH,
  539. SOUND_TYPE_MP3,
  540. SOUND_TYPE_WAV,
  541. SOUND_TYPE_WAV_LOCAL
  542. }
  543.  
  544. enum _:SOUND_DATA_BASE
  545. {
  546. KEYWORD[TOK_LENGTH],
  547. ADMIN_LEVEL_BASE,
  548. SOUND_AMOUNT,
  549. FLAGS,
  550. PLAY_COUNT_KEY,
  551. Array:SUB_INDEX
  552. }
  553. enum _:SOUND_DATA_SUB
  554. {
  555. SOUND_FILE[TOK_LENGTH],
  556. Float:DURATION,
  557. ADMIN_LEVEL,
  558. SOUND_TYPE,
  559. PLAY_COUNT
  560. }
  561. new Array:soundData
  562.  
  563. public plugin_init( )
  564. {
  565. register_plugin("Sank Sounds Plugin", PLUGIN_VERSION, PLUGIN_AUTHOR)
  566. register_cvar("sanksounds_version", PLUGIN_VERSION, FCVAR_SERVER)
  567. set_cvar_string("sanksounds_version", PLUGIN_VERSION)
  568.  
  569. register_concmd("amx_sound_reset", "amx_sound_reset", ACCESS_ADMIN, " <jatekos | all> : Hang kvota torlese a felhasznalo ^"user^", vagy mindenki ^"all^" szamara.")
  570. register_concmd("amx_sound_add", "amx_sound_add", ACCESS_ADMIN, " <kulcsszo> <dir/sound> : Egy Szo/Hang hozzaadasa a listahoz.")
  571. register_clcmd("amx_sound_help", "amx_sound_help")
  572. register_concmd("amx_sound", "amx_sound", ACCESS_ADMIN, " : Hangok be es kikapcsolasa")
  573. register_concmd("amx_sound_play", "amx_sound_play", ACCESS_ADMIN, " <dir/sound> : Hang lejatszasa minden felhasznalo szamara.")
  574. register_concmd("amx_sound_reload", "amx_sound_reload", ACCESS_ADMIN, " : Az snd-list.cfg vagy a custom.cfg ujratoltese. A fajlnev opcionalis. Ha nincs fajlnev, az alap toltodik be")
  575. register_concmd("amx_sound_remove", "amx_sound_remove", ACCESS_ADMIN, " <kulcsszo> <dir/sound> : Egy szo/wav/mp3 torlese a listabol. Fontos az idezojel.")
  576. register_concmd("amx_sound_write", "amx_sound_write", ACCESS_ADMIN, " : Beleir a jelenlegi hang-configuracios fajlba.")
  577. register_concmd("amx_sound_debug", "amx_sound_debug", ACCESS_ADMIN, "Kiirja a teljes szo/hang listat.")
  578. register_concmd("amx_sound_ban", "amx_sound_ban", ACCESS_ADMIN, " <nev vagy #userid>: Megtiltja a jatekosnak a hang lejátszasat ezen a palyan.")
  579. register_concmd("amx_sound_unban", "amx_sound_unban", ACCESS_ADMIN, " <nev vagy #userid>: Engedelyezi a jatekosnak a hang lejatszasat ezen a palyan.")
  580. register_concmd("amx_sound_top", "amx_sound_top", ACCESS_ADMIN, " <szam> (optional): Megmutatja a leggyakrabban lejatszott <x> kulcsszot (alap 10) ezen a palyan.")
  581. register_clcmd("say", "HandleSay")
  582. register_clcmd("say_team", "HandleSay")
  583.  
  584. register_cvar("mp_sank_sounds_download", "1")
  585. CVAR_freezetime = register_cvar("mp_sank_sounds_freezetime", "0")
  586. CVAR_obey_duration = register_cvar("mp_sank_sounds_obey_duration", "1")
  587. register_cvar("mp_sank_sounds_motd_address", "")
  588.  
  589. g_max_players = get_maxplayers()
  590.  
  591. soundData = ArrayCreate(SOUND_DATA_BASE)
  592. }
  593.  
  594. public plugin_cfg( )
  595. {
  596. get_cvar_string("mp_sank_sounds_motd_address", motd_sound_list_address, 255)
  597.  
  598. new configpath[61]
  599. get_configsdir(configpath, 60)
  600. format(config_filename, 127, "%s/SND-LIST.CFG", configpath) // Name of file to parse
  601.  
  602. // check if file in capital letter exists
  603. // otherwise make it all lowercase and try to load it
  604. if ( file_exists(config_filename) )
  605. {
  606. parse_sound_file(config_filename)
  607. }else
  608. {
  609. strtolower(config_filename)
  610. parse_sound_file(config_filename)
  611. }
  612. }
  613.  
  614. public client_putinserver( id )
  615. {
  616. restrict_playing_sounds[id] = -1
  617.  
  618. new steamid[60], i
  619. get_user_authid(id, steamid, 59)
  620. for ( i = 0; i < MAX_BANS; ++i )
  621. {
  622. if ( equal(steamid, banned_player_steamids[i]) )
  623. restrict_playing_sounds[id] = i
  624. }
  625.  
  626. if ( !equal(steamid, sound_quota_steamids[id]) )
  627. {
  628. copy(sound_quota_steamids[id], 59, steamid)
  629. SndCount[id] = 0
  630. SndLenghtCount[id] = 0.0
  631. }
  632.  
  633. SndOn[id] = 1
  634.  
  635. new Float:gametime = get_gametime()
  636. if ( gametime <= get_pcvar_num(CVAR_freezetime) )
  637. return
  638.  
  639. new sData[SOUND_DATA_BASE]
  640. ArrayGetArray(soundData, 0, sData)
  641. if ( sData[SOUND_AMOUNT] == 0 )
  642. return
  643.  
  644. if ( Join_exit_SoundTime >= gametime )
  645. return
  646.  
  647. if ( sData[SOUND_AMOUNT] == 0 )
  648. return
  649.  
  650. new rand = random(sData[SOUND_AMOUNT])
  651. new subData[SOUND_DATA_SUB]
  652. ArrayGetArray(sData[SUB_INDEX], rand, subData)
  653.  
  654. if ( subData[ADMIN_LEVEL] != 0
  655. && !(get_user_flags(id) & subData[ADMIN_LEVEL]) )
  656. return
  657.  
  658. playsoundall(subData[SOUND_FILE], subData[SOUND_TYPE])
  659.  
  660. Join_exit_SoundTime = gametime + subData[DURATION]
  661. if ( NextSoundTime < Join_exit_SoundTime )
  662. NextSoundTime = Join_exit_SoundTime
  663. }
  664.  
  665. public client_disconnect( id )
  666. {
  667. SndOn[id] = 1
  668. restrict_playing_sounds[id] = -1
  669.  
  670. new Float:gametime = get_gametime()
  671. if ( gametime <= get_pcvar_num(CVAR_freezetime) )
  672. return
  673.  
  674. new sData[SOUND_DATA_BASE]
  675. ArrayGetArray(soundData, 1, sData)
  676. if ( sData[SOUND_AMOUNT] == 0 )
  677. return
  678.  
  679. if ( Join_exit_SoundTime >= gametime )
  680. return
  681.  
  682. if ( sData[SOUND_AMOUNT] == 0 )
  683. return
  684.  
  685. new rand = random(sData[SOUND_AMOUNT])
  686. new subData[SOUND_DATA_SUB]
  687. ArrayGetArray(sData[SUB_INDEX], rand, subData)
  688.  
  689. if ( subData[ADMIN_LEVEL] != 0
  690. && !(get_user_flags(id) & subData[ADMIN_LEVEL]) )
  691. return
  692.  
  693. playsoundall(subData[SOUND_FILE], subData[SOUND_TYPE])
  694.  
  695. Join_exit_SoundTime = gametime + subData[DURATION]
  696. if ( NextSoundTime < Join_exit_SoundTime )
  697. NextSoundTime = Join_exit_SoundTime
  698. }
  699.  
  700. public amx_sound_reset( id , level , cid )
  701. {
  702. if ( !cmd_access(id, level, cid, 2) )
  703. return PLUGIN_HANDLED
  704.  
  705. new arg[33], target
  706. read_argv(1, arg, 32)
  707. if ( equal(arg, "all") == 1 )
  708. {
  709. client_print(id, print_console, "Sank Sounds >> A Kvota torolve minden jatekosnal")
  710. for ( target = 1; target <= g_max_players; ++target )
  711. {
  712. SndCount[target] = 0
  713. SndLenghtCount[target] = 0.0
  714. }
  715. }else
  716. {
  717. target = cmd_target(id, arg, 1)
  718. if ( !target )
  719. return PLUGIN_HANDLED
  720.  
  721. SndCount[target] = 0
  722. SndLenghtCount[target] = 0.0
  723. new name[33]
  724. get_user_name(target, name, 32)
  725. client_print(id, print_console, "Sank Sounds >> A Kvota torolve lett ennel a jatekosnal: ^"%s^"", name)
  726. }
  727.  
  728. return PLUGIN_HANDLED
  729. }
  730.  
  731. //////////////////////////////////////////////////////////////////////////////
  732. // Adds a Word/Sound combo to the list. If it is a valid line in the config
  733. // file, then it is a valid parameter here. The only difference is you can
  734. // only specify one Sound file at a time with this command.
  735. //
  736. // Usage: amx_sound_add <keyword> <dir/sound>
  737. // Usage: amx_sound_add <setting> <value>
  738. //////////////////////////////////////////////////////////////////////////////
  739. public amx_sound_add( id , level , cid )
  740. {
  741. if ( !cmd_access(id, level, cid, 2) )
  742. return PLUGIN_HANDLED
  743.  
  744. new Word[TOK_LENGTH + 1], Sound[TOK_LENGTH + 1]
  745. new configOption = 0
  746.  
  747. read_argv(1, Word, TOK_LENGTH)
  748. read_argv(2, Sound, TOK_LENGTH)
  749. if ( strlen(Word) <= 0
  750. || strlen(Sound) == 0 )
  751. {
  752. client_print(id, print_console, "Sank Sounds >>Ervenytelen formatum")
  753. client_print(id, print_console, "Sank Sounds >>Hasznalat: amx_sound_add kulcsszo <dir/sound>")
  754.  
  755. return PLUGIN_HANDLED
  756. }
  757.  
  758. // First look for special parameters
  759. if ( equali(Word, "SND_MAX") )
  760. {
  761. SND_MAX = str_to_num(Sound)
  762. configOption = 1
  763. }else if ( equali(Word, "SND_MAX_DUR") )
  764. {
  765. SND_MAX_DUR = floatstr(Sound)
  766. configOption = 1
  767. }else if ( equali(Word, "SND_WARN") )
  768. {
  769. SND_WARN = str_to_num(Sound)
  770. configOption = 1
  771. }else if ( equali(Word, "SND_DELAY") )
  772. {
  773. SND_DELAY = floatstr(Sound)
  774. configOption = 1
  775. }else if ( equali(Word, "SND_MODE") )
  776. {
  777. SND_MODE = str_to_num(Sound)
  778. configOption = 1
  779. }else if ( equali(Word, "SND_IMMUNITY") )
  780. {
  781. SND_IMMUNITY = str_to_num(Sound)
  782. configOption = 1
  783. }else if ( equali(Word, "EXACT_MATCH") )
  784. {
  785. EXACT_MATCH = str_to_num(Sound)
  786. configOption = 1
  787. }else if ( equali(Word, "ADMINS_ONLY") )
  788. {
  789. ADMINS_ONLY = str_to_num(Sound)
  790. configOption = 1
  791. }else if ( equali(Word, "DISPLAY_KEYWORDS") )
  792. {
  793. DISPLAY_KEYWORDS = str_to_num(Sound)
  794. configOption = 1
  795. }
  796.  
  797. if ( configOption )
  798. {
  799. // Do some error checking on the user-input numbers
  800. ErrorCheck()
  801.  
  802. return PLUGIN_HANDLED
  803. }
  804.  
  805. // Loop once for each keyword
  806. new i, j
  807. new sData[SOUND_DATA_BASE]
  808. new subData[SOUND_DATA_SUB]
  809. new aLen = ArraySize(soundData)
  810. new subLen
  811. new resCode
  812. for( i = 0; i < aLen; ++i )
  813. {
  814. ArrayGetArray(soundData, i, sData)
  815. // If no match found, keep looping
  816. if ( !equal(Word, sData[KEYWORD], TOK_LENGTH) )
  817. continue
  818.  
  819. // See if the Sound already exists
  820. subLen = ArraySize(sData[SUB_INDEX])
  821. for( j = 0; j < subLen; ++j )
  822. {
  823. ArrayGetArray(sData[SUB_INDEX], j, subData)
  824. // See if this is the same as the new Sound
  825. if ( equali(Sound, subData[SOUND_FILE], TOK_LENGTH) )
  826. {
  827. client_print(id, print_console, "Sank Sounds >> ^"%s; %s^" mar letezik", Word, Sound)
  828.  
  829. return PLUGIN_HANDLED
  830. }
  831. }
  832.  
  833. // Word exists, but Sound is new to the list, so add entry
  834. resCode = array_add_inner_element(i, j, Sound, 0)
  835. if ( resCode != -1 )
  836. client_print(id, print_console, "Sank Sounds >> ^"%s^" hang sikeresen hozzaadva a ^"%s^" szohoz", Sound, Word)
  837.  
  838. return PLUGIN_HANDLED
  839. }
  840.  
  841. // Word/Sound combo is new to the list, so make a new entry
  842. array_add_element(i, Word)
  843. resCode = array_add_inner_element(i, 0, Sound, 0)
  844. if ( resCode != -1 )
  845. {
  846. ArraySort(soundData, "sortSoundDataFunc")
  847. client_print(id, print_console, "Sank Sounds >> ^"%s; %s^" sikeresen hozzaadva", Word, Sound)
  848. }else
  849. {
  850. // removed keyword because no sound could be added
  851. array_remove(i)
  852. }
  853.  
  854. return PLUGIN_HANDLED
  855. }
  856.  
  857. //////////////////////////////////////////////////////////////////////////////
  858. // amx_sound_help lists all amx_sound commands and keywords to the user.
  859. //
  860. // Usage: amx_sound_help
  861. //////////////////////////////////////////////////////////////////////////////
  862. public amx_sound_help( id )
  863. {
  864. print_sound_list(id)
  865.  
  866. return PLUGIN_HANDLED
  867. }
  868.  
  869. //////////////////////////////////////////////////////////////////////////////
  870. // Turns on/off the playing of the Sound files for this plugin only
  871. //////////////////////////////////////////////////////////////////////////////
  872. public amx_sound( id , level , cid )
  873. {
  874. if ( !cmd_access(id, level, cid, 2) )
  875. return PLUGIN_HANDLED
  876.  
  877. new onoff[5]
  878. read_argv(1, onoff, 4)
  879. if ( equal(onoff, "on")
  880. || equal(onoff, "1") )
  881. {
  882. if ( bSoundsEnabled == 1 )
  883. console_print(id, "Sank Sounds >> A Plugin mar be van kapcsolva")
  884. else
  885. {
  886. bSoundsEnabled = 1
  887. console_print(id, "Sank Sounds >> A Plugin bekapcsolva")
  888. client_print(0, print_chat, "Sank Sounds >> A Plugin be van kapcsolva")
  889. if ( Enable_Sound[0] )
  890. {
  891. new type = Enable_Sound[0] == '^"' ? SOUND_TYPE_SPEECH : ( Enable_Sound[strlen(Enable_Sound) - 1] == '3' ? SOUND_TYPE_MP3 : SOUND_TYPE_WAV )
  892. playsoundall(Enable_Sound, type)
  893. }
  894. }
  895.  
  896. return PLUGIN_HANDLED
  897. }else if ( equal(onoff, "off")
  898. || equal(onoff, "0") )
  899. {
  900. if ( bSoundsEnabled == 0 )
  901. console_print(id, "Sank Sounds >> A Plugin mar ki van kapcsolva")
  902. else
  903. {
  904. bSoundsEnabled = 0
  905. console_print(id, "Sank Sounds >> A Plugin kikapcsolva")
  906. client_print(0, print_chat, "Sank Sounds >> A Plugin ki van kapcsolva")
  907. if ( Disable_Sound[0] )
  908. {
  909. new type = Disable_Sound[0] == '^"' ? SOUND_TYPE_SPEECH : ( Disable_Sound[strlen(Disable_Sound) - 1] == '3' ? SOUND_TYPE_MP3 : SOUND_TYPE_WAV )
  910. playsoundall(Disable_Sound, type)
  911. }
  912. }
  913. }
  914.  
  915. return PLUGIN_HANDLED
  916. }
  917.  
  918. //////////////////////////////////////////////////////////////////////////////
  919. // Plays a sound to all players
  920. //
  921. // Usage: amx_sound_play <dir/sound>
  922. //////////////////////////////////////////////////////////////////////////////
  923. public amx_sound_play( id , level , cid )
  924. {
  925. if ( !cmd_access(id, level, cid, 2) )
  926. return PLUGIN_HANDLED
  927.  
  928. new arg[128]
  929. read_argv(1, arg, 127)
  930.  
  931. if ( strlen(arg) < 1 )
  932. {
  933. client_print(id, print_console, "Sank Sounds >> A hang ervenytelen.")
  934.  
  935. return PLUGIN_HANDLED
  936. }
  937.  
  938. new type = arg[0] == '^"' ? SOUND_TYPE_SPEECH : ( arg[strlen(arg) - 1] == '3' ? SOUND_TYPE_MP3 : SOUND_TYPE_WAV )
  939. playsoundall(arg, type)
  940.  
  941. return PLUGIN_HANDLED
  942. }
  943.  
  944. //////////////////////////////////////////////////////////////////////////////
  945. // Reloads the Word/Sound combos from filename
  946. //
  947. // Usage: amx_sound_reload <filename>
  948. //////////////////////////////////////////////////////////////////////////////
  949. public amx_sound_reload( id , level , cid )
  950. {
  951. if ( !cmd_access(id, level, cid, 0) )
  952. return PLUGIN_HANDLED
  953.  
  954. new parsefile[128]
  955. read_argv(1, parsefile, 127)
  956. // Initialize sound_data array
  957. array_clear()
  958. soundData = ArrayCreate(SOUND_DATA_BASE)
  959.  
  960. parse_sound_file(parsefile, 0)
  961.  
  962. return PLUGIN_HANDLED
  963. }
  964.  
  965. //////////////////////////////////////////////////////////////////////////////
  966. // Removes a Word/Sound combo from the list. You must specify a keyword, but it
  967. // is not necessary to specify a Sound if you want to remove all Sounds associated
  968. // with that keyword
  969. //
  970. // Usage: amx_sound_remove <keyWord> <dir/sound>"
  971. //////////////////////////////////////////////////////////////////////////////
  972. public amx_sound_remove( id , level , cid )
  973. {
  974. if ( !cmd_access(id, level, cid, 2) )
  975. return PLUGIN_HANDLED
  976.  
  977. new Word[TOK_LENGTH + 1], Sound[TOK_LENGTH + 1]
  978.  
  979. read_argv(1, Word, TOK_LENGTH)
  980. read_argv(2, Sound, TOK_LENGTH)
  981. if ( strlen(Word) == 0 )
  982. {
  983. client_print(id, print_console, "Sank Sounds >> Ervenytelen formatum")
  984. client_print(id, print_console, "Sank Sounds >> Hasznalat: amx_sound_remove kulcsszo <dir/sound>")
  985.  
  986. return PLUGIN_HANDLED
  987. }
  988.  
  989. // speech must have extra ""
  990. if ( strlen(Sound) != 0
  991. && containi(Sound, ".wav") == -1
  992. && containi(Sound, ".mp") == -1 )
  993. format(Sound, TOK_LENGTH, "^"%s^"", Sound)
  994.  
  995. // Loop once for each keyWord
  996. new iCurWord, jCurSound
  997. new sData[SOUND_DATA_BASE]
  998. new subData[SOUND_DATA_SUB]
  999. new aLen = ArraySize(soundData)
  1000. new subLen
  1001. for( iCurWord = 0; iCurWord < aLen; ++iCurWord )
  1002. {
  1003. ArrayGetArray(soundData, iCurWord, sData)
  1004. // Look for a Word match
  1005. if ( !equali(Word, sData[KEYWORD], TOK_LENGTH) )
  1006. continue
  1007.  
  1008. // If no Sound was specified, then remove the whole Word's entry
  1009. if ( strlen(Sound) == 0 )
  1010. {
  1011. array_remove(iCurWord)
  1012.  
  1013. client_print(id, print_console, "Sank Sounds >> %s szo sikeresen torolve", Word)
  1014.  
  1015. return PLUGIN_HANDLED
  1016. }
  1017.  
  1018. // Just remove the one Sound, if it exists
  1019. subLen = ArraySize(sData[SUB_INDEX])
  1020. for( jCurSound = 0; jCurSound < subLen; ++jCurSound )
  1021. {
  1022. ArrayGetArray(sData[SUB_INDEX], iCurWord, subData)
  1023. // Look for a Sound match
  1024. if ( !equali(Sound, subData[SOUND_FILE], TOK_LENGTH) )
  1025. continue
  1026.  
  1027. if ( sData[SOUND_AMOUNT] == 1 ) // If this is the only Sound entry, then remove the entry altogether
  1028. {
  1029. array_remove(iCurWord)
  1030.  
  1031. client_print(id, print_console, "Sank Sounds >> %s szo sikeresen torolve", Word)
  1032. }else
  1033. {
  1034. array_remove_inner(iCurWord, jCurSound)
  1035.  
  1036. client_print(id, print_console, "Sank Sounds >> %s hang sikeresen torolve lett a %s szorol", Sound, Word)
  1037. }
  1038.  
  1039. return PLUGIN_HANDLED
  1040. }
  1041. // We reached the end for this Word, and the Sound didn't exist
  1042. client_print(id, print_console, "Sank Sounds >> %s hang nem talalhato", Sound)
  1043.  
  1044. return PLUGIN_HANDLED
  1045. }
  1046. // We reached the end, and the Word didn't exist
  1047. client_print(id, print_console, "Sank Sounds >> %s nem talalhato", Word)
  1048.  
  1049. return PLUGIN_HANDLED
  1050. }
  1051.  
  1052. //////////////////////////////////////////////////////////////////////////////
  1053. // Saves the current configuration of Word/Sound combos to filename for possible
  1054. // reloading at a later time. You cannot overwrite the default file.
  1055. //
  1056. // Usage: amx_sound_write <filename>
  1057. //////////////////////////////////////////////////////////////////////////////
  1058. public amx_sound_write( id , level , cid )
  1059. {
  1060. if ( !cmd_access(id, level, cid, 2) )
  1061. return PLUGIN_HANDLED
  1062.  
  1063. new savefile[128]
  1064.  
  1065. read_argv(1, savefile, 127)
  1066. if ( strlen(savefile) <= 1 )
  1067. {
  1068. if ( strlen(savefile) == 1
  1069. && savefile[0] == '!' )
  1070. copy(savefile, 127, config_filename)
  1071. else
  1072. {
  1073. client_print(id, print_console, "Sank Sounds >> Nem adtal meg fajlnevet. To save to default configfile use ! olyan fajlnev/parameter.")
  1074. return PLUGIN_HANDLED
  1075. }
  1076. }
  1077.  
  1078. new TimeStamp[128], name[33], Text[64]
  1079. new Textlen = 63
  1080. get_user_name(id, name, 32)
  1081. get_time("%H:%M:%S %A %B %d, %Y", TimeStamp, 127)
  1082.  
  1083. new file = fopen(savefile, "w+")
  1084. if ( !file )
  1085. {
  1086. log_amx("Sank Sounds >> Nem sikerult a ^"%s^" fajl beolvasasa", savefile)
  1087.  
  1088. return PLUGIN_HANDLED
  1089. }
  1090.  
  1091. formatex(Text, Textlen, "# Idopont:^t^t%s^n", TimeStamp)
  1092. fputs(file, Text)
  1093. formatex(Text, Textlen, "# Fajlt letrehozta:^t%s^n", name)
  1094. fputs(file, Text)
  1095. fputs(file, "^n") // blank line
  1096. fputs(file, "# Fontos parameterek:^n")
  1097. formatex(Text, Textlen, "SND_MAX;^t^t%d^n", SND_MAX)
  1098. fputs(file, Text)
  1099. formatex(Text, Textlen, "SND_MAX_DUR;^t^t%.1f^n", SND_MAX_DUR)
  1100. fputs(file, Text)
  1101. formatex(Text, Textlen, "SND_WARN;^t^t%d^n", SND_WARN)
  1102. fputs(file, Text)
  1103.  
  1104. new sData[SOUND_DATA_BASE]
  1105. new subData[SOUND_DATA_SUB]
  1106. ArrayGetArray(soundData, 0, sData);
  1107. new subLen = ArraySize(sData[SUB_INDEX])
  1108. fputs(file, "SND_JOIN;^t^t")
  1109. for ( new j = 0; j < subLen; ++j )
  1110. {
  1111. ArrayGetArray(sData[SUB_INDEX], j, subData);
  1112. cfg_write_keysound(file, subData)
  1113. }
  1114. fputc(file, '^n')
  1115. ArrayGetArray(soundData, 1, sData);
  1116. subLen = ArraySize(sData[SUB_INDEX])
  1117. fputs(file, "SND_EXIT;^t^t")
  1118. for ( new j = 0; j < subLen; ++j )
  1119. {
  1120. ArrayGetArray(sData[SUB_INDEX], j, subData);
  1121. cfg_write_keysound(file, subData)
  1122. }
  1123. fputc(file, '^n')
  1124. formatex(Text, Textlen, "SND_DELAY;^t^t%f^n", SND_DELAY)
  1125. fputs(file, Text)
  1126. formatex(Text, Textlen, "SND_MODE;^t^t%d^n", SND_MODE)
  1127. fputs(file, Text)
  1128. new snd_imm_str[32]
  1129. get_flags(SND_IMMUNITY, snd_imm_str, 26)
  1130. formatex(Text, Textlen, "SND_IMMUNITY;^t^t^"%s^"^n", snd_imm_str)
  1131. fputs(file, Text)
  1132. formatex(Text, Textlen, "EXACT_MATCH;^t^t%d^n", EXACT_MATCH)
  1133. fputs(file, Text)
  1134. formatex(Text, Textlen, "ADMINS_ONLY;^t^t%d^n", ADMINS_ONLY)
  1135. fputs(file, Text)
  1136. formatex(Text, Textlen, "DISPLAY_KEYWORDS;^t%d^n", DISPLAY_KEYWORDS)
  1137. fputs(file, Text)
  1138. fputs(file, "^n") // blank line
  1139. fputs(file, "# Word/Sound combinations:^n")
  1140.  
  1141. new aLen = ArraySize(soundData)
  1142. new j
  1143. for ( new i = 2; i < aLen; ++i ) // first 2 elements are reserved for Join / Exit sounds
  1144. {
  1145. ArrayGetArray(soundData, i, sData);
  1146.  
  1147. cfg_write_keyword(file, sData)
  1148. subLen = ArraySize(sData[SUB_INDEX])
  1149. for ( j = 0; j < subLen; ++j )
  1150. {
  1151. ArrayGetArray(sData[SUB_INDEX], j, subData);
  1152. cfg_write_keysound(file, subData)
  1153. }
  1154. fputc(file, '^n')
  1155. }
  1156.  
  1157. fclose(file)
  1158.  
  1159. client_print(id, print_console, "Sank Sounds >> %s sikeresen hozzaadva a configuraciohoz", savefile)
  1160.  
  1161. return PLUGIN_HANDLED
  1162. }
  1163.  
  1164. //////////////////////////////////////////////////////////////////////////////
  1165. // Prints out Word/Sound combo matrix for debugging purposes. Kinda cool, even
  1166. // if you're not really debugging.
  1167. //
  1168. // Usage: amx_sound_debug
  1169. // Usage: amx_sound_reload <filename>
  1170. //////////////////////////////////////////////////////////////////////////////
  1171. public amx_sound_debug( id , level , cid )
  1172. {
  1173. if ( !cmd_access(id, level, cid, 1)
  1174. && id > 0 )
  1175. return PLUGIN_HANDLED
  1176.  
  1177. new i, j, join_snd_buff[BUFFER_LEN], exit_snd_buff[BUFFER_LEN]
  1178.  
  1179. if ( !is_dedicated_server()
  1180. && id == 1 ) // for listenserver and with id = 1 we can use server_print
  1181. id = 0
  1182.  
  1183. if ( id )
  1184. client_print(id, print_console, "SND_WARN: %d^nSND_MAX: %d^nSND_MAX_DUR: %5.1f^n", SND_WARN, SND_MAX, SND_MAX_DUR)
  1185. else
  1186. server_print("SND_WARN: %d^nSND_MAX: %d^nSND_MAX_DUR: %5.1f", SND_WARN, SND_MAX, SND_MAX_DUR)
  1187.  
  1188. new sData[SOUND_DATA_BASE]
  1189. new subData[SOUND_DATA_SUB]
  1190. new aLen = ArraySize(soundData)
  1191. new subLen
  1192. ArrayGetArray(soundData, 0, sData)
  1193. subLen = ArraySize(sData[SUB_INDEX])
  1194. new tempstr[TOK_LENGTH]
  1195. for( i = 0; i < subLen; ++i )
  1196. {
  1197. ArrayGetArray(sData[SUB_INDEX], i, subData)
  1198. formatex(tempstr, TOK_LENGTH, "%s;", subData[SOUND_FILE])
  1199. add(join_snd_buff, BUFFER_LEN, tempstr)
  1200. }
  1201. ArrayGetArray(soundData, 1, sData)
  1202. subLen = ArraySize(sData[SUB_INDEX])
  1203. for( i = 0; i < subLen; ++i )
  1204. {
  1205. ArrayGetArray(sData[SUB_INDEX], i, subData)
  1206. formatex(tempstr, TOK_LENGTH, "%s;", subData[SOUND_FILE])
  1207. add(exit_snd_buff, BUFFER_LEN, tempstr)
  1208. }
  1209.  
  1210. new snd_imm_str[32]
  1211. get_flags(SND_IMMUNITY, snd_imm_str, 26)
  1212. if ( id )
  1213. {
  1214. client_print(id, print_console, "SND_JOIN: %s", join_snd_buff)
  1215. client_print(id, print_console, "SND_EXIT: %s", exit_snd_buff)
  1216. client_print(id, print_console, "SND_DELAY: %f^nSND_MODE: %d^nSND_IMMUNITY: %s^nEXACT_MATCH: %d", SND_DELAY, SND_MODE, snd_imm_str, EXACT_MATCH)
  1217. client_print(id, print_console, "ADMINS_ONLY: %d^nDISPLAY_KEYWORDS: %d", ADMINS_ONLY, DISPLAY_KEYWORDS)
  1218. }else
  1219. {
  1220. server_print("SND_JOIN: %s", join_snd_buff)
  1221. server_print("SND_EXIT: %s", exit_snd_buff)
  1222. server_print("SND_DELAY: %f^nSND_MODE: %d^nSND_IMMUNITY: %s^nEXACT_MATCH: %d", SND_DELAY, SND_MODE, snd_imm_str, EXACT_MATCH)
  1223. server_print("ADMINS_ONLY: %d^nDISPLAY_KEYWORDS: %d", ADMINS_ONLY, DISPLAY_KEYWORDS)
  1224. }
  1225.  
  1226. // Print out the matrix of sound data, so we got what we think we did
  1227. for( i = 2; i < aLen; ++i ) // first 2 elements are reserved for Join / Exit sounds
  1228. {
  1229. ArrayGetArray(soundData, i, sData)
  1230.  
  1231. new access_level[32]
  1232. get_flags(sData[ADMIN_LEVEL_BASE], access_level, 31)
  1233. if ( id )
  1234. client_print(id, print_console, "^n[%d] ^"%s^" %d hanggal %s es ^"%s^" szinttel (lejatsszva: %d)", i - 2, sData[KEYWORD], sData[SOUND_AMOUNT], sData[SOUND_AMOUNT] > 1 ? "s" : "", access_level, sData[PLAY_COUNT_KEY])
  1235. else
  1236. server_print("^n[%d] ^"%s^" %d hanggal %s es ^"%s^" szinttel (lejatsszva: %d)", i - 2, sData[KEYWORD], sData[SOUND_AMOUNT], sData[SOUND_AMOUNT] > 1 ? "s" : "", access_level, sData[PLAY_COUNT_KEY])
  1237. subLen = ArraySize(sData[SUB_INDEX])
  1238. for( j = 0; j < subLen; ++j )
  1239. {
  1240. ArrayGetArray(sData[SUB_INDEX], j, subData)
  1241.  
  1242. get_flags(subData[ADMIN_LEVEL], access_level, 31)
  1243. if ( id )
  1244. client_print(id, print_console, " ^"%s^" - ido: %5.2f - admin szint ^"%s^" (lejatsszva: %d)", subData[SOUND_FILE], subData[DURATION], access_level, subData[PLAY_COUNT])
  1245. else
  1246. server_print(" ^"%s^" - ido: %5.2f - admin szint ^"%s^" (lejatsszva: %d)", subData[SOUND_FILE], subData[DURATION], access_level, subData[PLAY_COUNT])
  1247. }
  1248. }
  1249.  
  1250. return PLUGIN_HANDLED
  1251. }
  1252.  
  1253. //////////////////////////////////////////////////////////////////////////////
  1254. // Bans players from using sounds for current map
  1255. //
  1256. // Usage: amx_sound_ban <player>
  1257. //////////////////////////////////////////////////////////////////////////////
  1258. public amx_sound_ban( id , level , cid )
  1259. {
  1260. if ( !cmd_access(id, level, cid, 2) )
  1261. return PLUGIN_HANDLED
  1262.  
  1263. new arg[33]
  1264. read_argv(1, arg, 32)
  1265. new player = cmd_target(id, arg, 1)
  1266. if ( !player )
  1267. return PLUGIN_HANDLED
  1268.  
  1269. if ( get_user_flags(player) & (SND_IMMUNITY | ACCESS_ADMIN) )
  1270. return PLUGIN_HANDLED
  1271.  
  1272. if ( restrict_playing_sounds[player] == -1 )
  1273. {
  1274. new found, empty = -1
  1275. new steamid[60]
  1276. get_user_authid(id, steamid, 59)
  1277. for ( new i = 0; i < MAX_BANS; ++i )
  1278. {
  1279. if ( empty == -1
  1280. && !banned_player_steamids[i][0] )
  1281. empty = i
  1282.  
  1283. if ( !equal(steamid, banned_player_steamids[i]) )
  1284. continue
  1285.  
  1286. found = 1
  1287.  
  1288. break
  1289. }
  1290. if ( !found )
  1291. {
  1292. if ( empty == -1 )
  1293. empty = 0
  1294.  
  1295. copy(banned_player_steamids[empty], 59, steamid)
  1296.  
  1297. restrict_playing_sounds[player] = empty
  1298. }
  1299. }
  1300.  
  1301. new name[33]
  1302. get_user_name(player, name, 32)
  1303. client_print(id, print_console, "Sank Sounds >> ^"%s^" nevu jatekos kitiltva a hangok lejatszasa miatt", name)
  1304.  
  1305. return PLUGIN_HANDLED
  1306. }
  1307.  
  1308. //////////////////////////////////////////////////////////////////////////////
  1309. // Unbans players from using sounds for current map
  1310. //
  1311. // Usage: amx_sound_unban <player>
  1312. //////////////////////////////////////////////////////////////////////////////
  1313. public amx_sound_unban( id , level , cid )
  1314. {
  1315. if ( !cmd_access(id, level, cid, 2) )
  1316. return PLUGIN_HANDLED
  1317.  
  1318. new arg[33]
  1319. read_argv(1, arg, 32)
  1320. new player = cmd_target(id, arg)
  1321. if ( !player )
  1322. return PLUGIN_HANDLED
  1323.  
  1324. if ( restrict_playing_sounds[player] != -1 )
  1325. {
  1326. new found = -1
  1327. new steamid[60]
  1328. get_user_authid(id, steamid, 59)
  1329. for ( new i = 0; i < MAX_BANS; ++i )
  1330. {
  1331. if ( !equal(steamid, banned_player_steamids[i]) )
  1332. continue
  1333.  
  1334. found = i
  1335.  
  1336. break
  1337. }
  1338. if ( found != -1 )
  1339. banned_player_steamids[found][0] = 0
  1340.  
  1341. restrict_playing_sounds[player] = -1
  1342. }
  1343.  
  1344. new name[33]
  1345. get_user_name(player, name, 32)
  1346. client_print(id, print_console, "Sank Sounds >> ^"%s^" nevu jatekos feloldva a hangok lejatszasa alol", name)
  1347.  
  1348. return PLUGIN_HANDLED
  1349. }
  1350.  
  1351. public amx_sound_top( id , level , cid )
  1352. {
  1353. if ( !cmd_access(id, level, cid, 1) )
  1354. return PLUGIN_HANDLED
  1355.  
  1356. new arg[33]
  1357. read_argv(1, arg, 32)
  1358. new topX = 10
  1359. if ( strlen(arg) > 0 )
  1360. topX = str_to_num(arg)
  1361.  
  1362. if ( topX < 1
  1363. || topX > 50 )
  1364. {
  1365. client_print(id, print_console, "Sank Sounds >> Allits be egy erteket 1 - 50 kozott vagy hagyd uresen")
  1366. return PLUGIN_HANDLED
  1367. }
  1368.  
  1369. new topIDs[50] = {-1, ...}
  1370. new topCount[50] = {0, ...}
  1371. new sData[SOUND_DATA_BASE]
  1372. new aLen = ArraySize(soundData)
  1373. for ( new keyIndex = 0; keyIndex < aLen; ++keyIndex )
  1374. {
  1375. ArrayGetArray(soundData, keyIndex, sData)
  1376.  
  1377. for ( new i = 0; i < topX; ++i )
  1378. {
  1379. if ( sData[PLAY_COUNT_KEY] <= topCount[i] )
  1380. continue
  1381.  
  1382. // copy all other down
  1383. for ( new j = topX - 1; j > i; --j )
  1384. {
  1385. topIDs[j] = topIDs[j - 1]
  1386. topCount[j] = topCount[j - 1]
  1387. }
  1388. topIDs[i] = keyIndex
  1389. topCount[i] = sData[PLAY_COUNT_KEY]
  1390. break
  1391. }
  1392. }
  1393. new text[512]
  1394. new counter = 0
  1395. client_print(id, print_console, "Sank Sounds >> Top %d:", topX)
  1396. while ( counter < topX )
  1397. {
  1398. if ( topIDs[counter] != -1 )
  1399. {
  1400. ArrayGetArray(soundData, topIDs[counter], sData)
  1401. format(text, 511, "%s(%d) %s^n", text, topCount[counter], sData[KEYWORD])
  1402. }else
  1403. counter = topX - 1
  1404. if ( (counter % 10 == 0
  1405. && counter != 0 )
  1406. || counter == topX - 1 )
  1407. {
  1408. client_print(id, print_console, text)
  1409. text[0] = 0
  1410. }
  1411. ++counter
  1412. }
  1413.  
  1414. return PLUGIN_HANDLED
  1415. }
  1416.  
  1417. //////////////////////////////////////////////////////////////////////////////
  1418. // Everything a person says goes through here, and we determine if we want to
  1419. // play a sound or not.
  1420. //
  1421. // Usage: say <anything>
  1422. //////////////////////////////////////////////////////////////////////////////
  1423. public HandleSay( id )
  1424. {
  1425. // If sounds are not enabled, then skip this whole thing
  1426. if ( !bSoundsEnabled )
  1427. return PLUGIN_CONTINUE
  1428.  
  1429. // player is banned from playing sounds
  1430. if ( restrict_playing_sounds[id] != -1 )
  1431. return PLUGIN_CONTINUE
  1432.  
  1433. new Speech[128]
  1434. read_args(Speech, 127)
  1435. remove_quotes(Speech)
  1436.  
  1437. // credit to SR71Goku for fixing this oversight:
  1438. new speachLen = strlen(Speech)
  1439. if ( !speachLen )
  1440. return PLUGIN_CONTINUE
  1441.  
  1442. if ( equal(Speech, "/sound", 6) )
  1443. {
  1444. if ( Speech[6] == 's' )
  1445. {
  1446. if ( Speech[7] == 'o'
  1447. && Speech[8] == 'n'
  1448. && Speech[9] == 0 )
  1449. {
  1450. SndOn[id] = 1
  1451. client_print(id, print_chat, "Sank Sounds >> Ismet hallhatod a hangokat")
  1452. }else if ( Speech[7] == 'o'
  1453. && Speech[8] == 'f'
  1454. && Speech[9] == 'f'
  1455. && Speech[10] == 0 )
  1456. {
  1457. SndOn[id] = 0
  1458. client_print(id, print_chat, "Sank Sounds >> Onnek a hangok lejatsszasa le lett tiltva")
  1459. }else if ( Speech[7] == 0 )
  1460. print_sound_list(id, 1)
  1461. else
  1462. return PLUGIN_CONTINUE
  1463.  
  1464. return PLUGIN_HANDLED
  1465. }else if ( Speech[6] == 'l'
  1466. && Speech[7] == 'i'
  1467. && Speech[8] == 's'
  1468. && Speech[9] == 't'
  1469. && Speech[10] == 0 )
  1470. {
  1471. print_sound_list(id, 1)
  1472.  
  1473. return PLUGIN_HANDLED
  1474. }
  1475.  
  1476. return PLUGIN_CONTINUE
  1477. }
  1478.  
  1479. new ListIndex = -1
  1480. new pinToLocation = (Speech[speachLen - 1] == '!')
  1481. new sData[SOUND_DATA_BASE]
  1482. new subData[SOUND_DATA_SUB]
  1483. new aLen = ArraySize(soundData)
  1484. // Check to see if what the player said is a trigger for a sound
  1485. for ( new i = 2; i < aLen; ++i ) // first 2 elements are reserved for Join / Exit sounds
  1486. {
  1487. ArrayGetArray(soundData, i, sData)
  1488.  
  1489. if ( equali(Speech, sData[KEYWORD])
  1490. || (EXACT_MATCH == 1
  1491. && pinToLocation == 1
  1492. && speachLen == strlen(sData[KEYWORD]) + 1
  1493. && equali(Speech, sData[KEYWORD], speachLen - 1) )
  1494. || ( EXACT_MATCH == 0
  1495. && containi(Speech, sData[KEYWORD]) != -1 ) )
  1496. {
  1497. // check for access
  1498. if ( sData[ADMIN_LEVEL_BASE] == 0
  1499. || get_user_flags(id) & sData[ADMIN_LEVEL_BASE] )
  1500. ListIndex = i
  1501.  
  1502. break
  1503. }
  1504. }
  1505.  
  1506. // check If player used NO sound trigger
  1507. if ( ListIndex == -1 )
  1508. return PLUGIN_CONTINUE
  1509.  
  1510. if ( sData[SOUND_AMOUNT] == 0 )
  1511. return PLUGIN_CONTINUE
  1512.  
  1513. new obey_duration_mode = get_pcvar_num(CVAR_obey_duration)
  1514. new Float:gametime = get_gametime()
  1515. new allowedToPlay = isUserAllowed2Play(id, gametime, obey_duration_mode)
  1516. if ( allowedToPlay == RESULT_OK )
  1517. {
  1518. displayQuotaWarning(id)
  1519. new rand
  1520. new timeout
  1521. new playFile[TOK_LENGTH]
  1522.  
  1523. // This for loop runs around until it finds a real file to play
  1524. // Defaults to the first Sound file, if no file is found at random.
  1525. for( timeout = MAX_RANDOM; // Initial condition
  1526. timeout >= 0 && !strlen(playFile); // While these are true
  1527. --timeout ) // Update each iteration
  1528. {
  1529. rand = random(sData[SOUND_AMOUNT])
  1530. // If for some reason we never find a file
  1531. // then default to the first Sound entry
  1532. if ( !timeout )
  1533. rand = 0
  1534.  
  1535. ArrayGetArray(sData[SUB_INDEX], rand, subData)
  1536. // check if sound has access defined, if so only allow admins to use it
  1537. if ( subData[ADMIN_LEVEL] == 0
  1538. || ( get_user_flags(id) & subData[ADMIN_LEVEL] ) )
  1539. copy(playFile, TOK_LENGTH, subData[SOUND_FILE])
  1540. }
  1541.  
  1542. if ( playFile[0] )
  1543. {
  1544. NextSoundTime = gametime + subData[DURATION]
  1545.  
  1546. // Increment their playsound count
  1547. ++SndCount[id]
  1548. SndLenghtCount[id] += subData[DURATION]
  1549.  
  1550. // increment counter
  1551. ++sData[PLAY_COUNT_KEY]
  1552. ++subData[PLAY_COUNT]
  1553.  
  1554. new type = subData[SOUND_TYPE]
  1555. if ( pinToLocation == 1
  1556. && type == SOUND_TYPE_WAV )
  1557. type = SOUND_TYPE_WAV_LOCAL
  1558. playsoundall(playFile, type, SND_MODE & 16, is_user_alive(id))
  1559.  
  1560. LastSoundTime = gametime
  1561. ArraySetArray(sData[SUB_INDEX], rand, subData)
  1562. ArraySetArray(soundData, ListIndex, sData)
  1563. }
  1564. }else if ( allowedToPlay == RESULT_QUOTA_EXCEEDED
  1565. || allowedToPlay == RESULT_QUOTA_DURATION_EXCEEDED )
  1566. {
  1567. if ( !displayQuotaExceeded(id) )
  1568. {
  1569. if ( allowedToPlay == RESULT_SOUND_DELAY
  1570. && obey_duration_mode != 0 )
  1571. client_print(id, print_chat, "Sank Sounds >> Egy hangot mar lejatsszottal ( varnod kell %3.1f masodpercet )", NextSoundTime + SND_DELAY - gametime)
  1572. else if ( allowedToPlay != RESULT_QUOTA_EXCEEDED
  1573. && allowedToPlay != RESULT_QUOTA_DURATION_EXCEEDED )
  1574. client_print(id, print_chat, "Sank Sounds >> Ne jatssz le olyan gyakran ( varj %3.1f masodpercet )", LastSoundTime + SND_DELAY - gametime)
  1575. }
  1576. }
  1577.  
  1578. if ( DISPLAY_KEYWORDS == 0 )
  1579. return PLUGIN_HANDLED
  1580.  
  1581. return PLUGIN_CONTINUE
  1582. }
  1583.  
  1584. //////////////////////////////////////////////////////////////////////////////
  1585. // Parses the sound file specified by loadfile. If loadfile is empty, then
  1586. // it parses the default config_filename.
  1587. //////////////////////////////////////////////////////////////////////////////
  1588. parse_sound_file( loadfile[] , precache_sounds = 1 )
  1589. {
  1590. if ( !strlen(loadfile) )
  1591. copy(loadfile, 127, config_filename)
  1592.  
  1593. if ( !file_exists(loadfile) )
  1594. {
  1595. // file does not exist
  1596. log_amx("Sank Sounds >> Nem talalhato a ^"%s^" fajl", loadfile)
  1597.  
  1598. return
  1599. }
  1600.  
  1601. new current_package_str[4]
  1602. new current_package, package_num
  1603. if ( vaultdata_exists("sank_sounds_current_package") )
  1604. {
  1605. get_vaultdata("sank_sounds_current_package", current_package_str, 3)
  1606. current_package = str_to_num(current_package_str)
  1607. }
  1608.  
  1609. new allowed_to_precache = 1, allow_check_existence = 1, allow_to_use_sounds = 1
  1610. new allow_global_precache = get_cvar_num("mp_sank_sounds_download")
  1611. new mapname[32]
  1612. get_mapname(mapname, 31)
  1613.  
  1614. new i
  1615. new ListIndex = -1
  1616. new tmpIndex = -1
  1617. new maxLineBuf_len = BUFFER_LEN - 1
  1618. new strLineBuf[BUFFER_LEN]
  1619.  
  1620. new error_code = ERROR_NONE
  1621. new parse_option = PARSE_KEYWORD
  1622. new temp_str[128]
  1623. new check_for_semi
  1624. new position
  1625.  
  1626. new sData[SOUND_DATA_BASE]
  1627.  
  1628. new file = fopen(loadfile, "r")
  1629. if ( !file )
  1630. {
  1631. log_amx("Sank Sounds >> Nem sikerult a ^"%s^" fajl beolvasasa", loadfile)
  1632.  
  1633. return
  1634. }
  1635.  
  1636. while ( fgets(file, strLineBuf, maxLineBuf_len) )
  1637. {
  1638. if ( (strLineBuf[0] == '^n') // empty line
  1639. || ( strLineBuf[0] == 10 && strLineBuf[1] == '^n' ) // empty line
  1640. || ( strLineBuf[0] == '/' && strLineBuf[1] == '/' ) // comment
  1641. || (strLineBuf[0] == '#') ) // another comment
  1642. continue
  1643.  
  1644. trim(strLineBuf) // remove newline and spaces
  1645.  
  1646. if ( equali(strLineBuf, "package ", 8) )
  1647. {
  1648. ++package_num
  1649. if ( current_package )
  1650. {
  1651. if ( current_package == str_to_num(strLineBuf[8]) )
  1652. allowed_to_precache = 1
  1653. else
  1654. allowed_to_precache = 0
  1655. }else
  1656. {
  1657. current_package = 1
  1658. allowed_to_precache = 1
  1659. }
  1660.  
  1661. allow_to_use_sounds = 1
  1662. allow_check_existence = 1
  1663.  
  1664. continue
  1665. }else if ( equali(strLineBuf, "mapname ", 8) )
  1666. {
  1667. if ( equali(strLineBuf[8], mapname) )
  1668. allowed_to_precache = 1
  1669. else
  1670. allowed_to_precache = 0
  1671.  
  1672. allow_to_use_sounds = 1
  1673. allow_check_existence = 1
  1674.  
  1675. continue
  1676. }else if ( equali(strLineBuf, "mapnameonly ", 12) )
  1677. {
  1678. if ( equali(strLineBuf[12], mapname) )
  1679. {
  1680. allowed_to_precache = 1
  1681. allow_to_use_sounds = 1
  1682. }else
  1683. {
  1684. allowed_to_precache = 0
  1685. allow_to_use_sounds = 0
  1686. }
  1687.  
  1688. allow_check_existence = 1
  1689.  
  1690. continue
  1691. }else if ( equali(strLineBuf, "modspecific", 11) )
  1692. {
  1693. allow_to_use_sounds = 1
  1694. allow_check_existence = 0
  1695.  
  1696. continue
  1697. }
  1698.  
  1699. if ( !allow_to_use_sounds ) // check for sounds that can be used only on specified map
  1700. continue
  1701.  
  1702. error_code = ERROR_NONE
  1703. position = 0
  1704. for( i = 0; ; ++i )
  1705. {
  1706. // check if reached end of buffer ( input has been parsed )
  1707. if ( position >= strlen(strLineBuf) )
  1708. {
  1709. strLineBuf[0] = 0
  1710. break
  1711. }
  1712.  
  1713. temp_str[0] = 0 // reset
  1714. check_for_semi = contain(strLineBuf[position], ";")
  1715. if ( check_for_semi != -1 )
  1716. {
  1717. copyc(temp_str, 127, strLineBuf[position], ';')
  1718. position += check_for_semi + 1
  1719. }else
  1720. {
  1721. copy(temp_str, 127, strLineBuf[position])
  1722. position += strlen(temp_str)
  1723. }
  1724.  
  1725. // Now remove any spaces or tabs from around the strings -- clean them up
  1726. trim(temp_str)
  1727.  
  1728. // check if file length is bigger than array
  1729. if ( strlen(temp_str) > TOK_LENGTH )
  1730. {
  1731. error_code = ERROR_STRING_LENGTH
  1732.  
  1733. break
  1734. }
  1735.  
  1736. if ( i == 0 )
  1737. { // first entry is not a sound file
  1738. if ( equali(temp_str, "SND_MAX") )
  1739. parse_option = PARSE_SND_MAX
  1740. else if ( equali(temp_str, "SND_MAX_DUR") )
  1741. parse_option = PARSE_SND_MAX_DUR
  1742. else if ( equali(temp_str, "SND_WARN") )
  1743. parse_option = PARSE_SND_WARN
  1744. else if ( equali(temp_str, "SND_DELAY") )
  1745. parse_option = PARSE_SND_DELAY
  1746. else if ( equali(temp_str, "SND_MODE") )
  1747. parse_option = PARSE_SND_MODE
  1748. else if ( equali(temp_str, "SND_IMMUNITY") )
  1749. parse_option = PARSE_SND_IMMUNITY
  1750. else if ( equali(temp_str, "EXACT_MATCH") )
  1751. parse_option = PARSE_EXACT_MATCH
  1752. else if ( equali(temp_str, "ADMINS_ONLY") )
  1753. parse_option = PARSE_ADMINS_ONLY
  1754. else if ( equali(temp_str, "DISPLAY_KEYWORDS") )
  1755. parse_option = PARSE_DISPLAY_KEYWORDS
  1756. else
  1757. {
  1758. parse_option = PARSE_KEYWORD
  1759. if ( ListIndex != -1 )
  1760. ArrayGetArray(soundData, ListIndex, sData)
  1761. if ( ListIndex != -1
  1762. && sData[SOUND_AMOUNT] == 0
  1763. && !(sData[FLAGS] & FLAG_IGNORE_AMOUNT) ) // check if allowed to ignore amount of sounds ( eg: SND_JOIN / SND_EXIT )
  1764. {
  1765. log_amx("Sank Sounds >> Ervenyes hang nelkuli kulcsszot talaltam. Atugras erre a kulcsszora: ^"%s^"", sData[KEYWORD])
  1766. array_remove(ListIndex)
  1767. }else
  1768. ++ListIndex
  1769.  
  1770. new result = array_add_element(ListIndex, temp_str)
  1771. if ( result > -1 )
  1772. {
  1773. tmpIndex = result
  1774. --ListIndex
  1775. }else
  1776. {
  1777. tmpIndex = -1
  1778. if ( result == -1 )
  1779. ListIndex = 2
  1780. }
  1781. }
  1782. }else
  1783. {
  1784. switch ( parse_option )
  1785. {
  1786. case PARSE_SND_MAX:
  1787. {
  1788. SND_MAX = str_to_num(temp_str)
  1789. }
  1790. case PARSE_SND_MAX_DUR:
  1791. {
  1792. SND_MAX_DUR = floatstr(temp_str)
  1793. }
  1794. case PARSE_SND_WARN:
  1795. {
  1796. SND_WARN = str_to_num(temp_str)
  1797. }
  1798. case PARSE_SND_DELAY:
  1799. {
  1800. SND_DELAY = floatstr(temp_str)
  1801. }
  1802. case PARSE_SND_MODE:
  1803. {
  1804. SND_MODE = str_to_num(temp_str)
  1805. }
  1806. case PARSE_SND_IMMUNITY:
  1807. {
  1808. if ( temp_str[0] == '^"' )
  1809. {
  1810. new temp_str2[32]
  1811. copyc(temp_str2, 31, temp_str[1], '^"')
  1812. if ( strlen(temp_str2) == 0 )
  1813. SND_IMMUNITY = (1<<30)
  1814. else
  1815. SND_IMMUNITY = read_flags(temp_str2)
  1816. }else
  1817. SND_IMMUNITY = read_flags(temp_str)
  1818. }
  1819. case PARSE_EXACT_MATCH:
  1820. {
  1821. EXACT_MATCH = str_to_num(temp_str)
  1822. }
  1823. case PARSE_ADMINS_ONLY:
  1824. {
  1825. ADMINS_ONLY = str_to_num(temp_str)
  1826. }
  1827. case PARSE_DISPLAY_KEYWORDS:
  1828. {
  1829. DISPLAY_KEYWORDS = str_to_num(temp_str)
  1830. }
  1831. case PARSE_KEYWORD:
  1832. {
  1833. new error_value = -1
  1834. if ( tmpIndex != -1 )
  1835. error_value = array_add_inner_element(tmpIndex, i - 1, temp_str, allow_check_existence, allow_global_precache, precache_sounds, allowed_to_precache)
  1836. else
  1837. error_value = array_add_inner_element(ListIndex, i - 1, temp_str, allow_check_existence, allow_global_precache, precache_sounds, allowed_to_precache)
  1838. if ( error_value == -1 )
  1839. {
  1840. // sound could not be added
  1841. continue
  1842. }
  1843. }
  1844. }
  1845. }
  1846. }
  1847.  
  1848. if ( error_code == ERROR_STRING_LENGTH )
  1849. {
  1850. log_amx("Sank Sounds >> Atugras erre a szo/hang kombinaciora. A Szo vagy Hang tul hosszu: ^"%s^". A hossz %i de max. %i lehet (valtson nevet/torolje a spaceket a configban vagy bovitse a TOK_LENGTH erteket)", temp_str, strlen(temp_str), TOK_LENGTH)
  1851.  
  1852. continue
  1853. }
  1854. if ( error_code != ERROR_NONE )
  1855. {
  1856. log_amx("Sank Sounds >> Fatal Error")
  1857.  
  1858. continue
  1859. }
  1860.  
  1861. // If we finished MAX_RANDOM times, and strLineBuf[position] still has contents
  1862. // then we should have a bigger MAX_RANDOM
  1863. else if ( position < strlen(strLineBuf) )
  1864. {
  1865. log_amx("Sank Sounds >> A hang-lista reszlegesen hibas. Novelje a MAX_RANDOM erteket. Tovabb a fajl feldolgozasara ^"%s^"^n", loadfile)
  1866. }
  1867. }
  1868.  
  1869. fclose(file)
  1870.  
  1871. if ( ListIndex != -1 )
  1872. {
  1873. ArrayGetArray(soundData, ListIndex, sData)
  1874. if ( sData[SOUND_AMOUNT] == 0
  1875. && !(sData[FLAGS] & FLAG_IGNORE_AMOUNT) ) // check if allowed to ignore amount of sounds ( eg: SND_JOIN / SND_EXIT )
  1876. {
  1877. log_amx("Sank Sounds >> Ervenyes hang nelkul talalt kulcsszo. Atugras erre a kulcsszora: ^"%s^"", sData[KEYWORD])
  1878. array_remove(ListIndex)
  1879. --ListIndex
  1880. }
  1881. }
  1882.  
  1883. // Now we have all of the data from the text file in our data structures.
  1884. // Next we do some error checking, some setup, and we're done parsing!
  1885. ErrorCheck()
  1886.  
  1887. ++current_package
  1888. if ( current_package > package_num )
  1889. current_package = 1
  1890.  
  1891. num_to_str(current_package, current_package_str, 3)
  1892. set_vaultdata("sank_sounds_current_package", current_package_str)
  1893.  
  1894. //++ListIndex
  1895. #if ALLOW_SORT == 1
  1896. if ( ListIndex > 1 )
  1897. ArraySort(soundData, "sortSoundDataFunc")
  1898. #endif
  1899. }
  1900.  
  1901. //////////////////////////////////////////////////////////////////////////////
  1902. // Returns status indicating if user is allowed to play a sound
  1903. // or the reason why he is not
  1904. //////////////////////////////////////////////////////////////////////////////
  1905. isUserAllowed2Play( id , Float:gametime , obey_duration_mode )
  1906. {
  1907. // order of checks is important
  1908.  
  1909. new admin_flags = get_user_flags(id)
  1910.  
  1911. // check if only admins can play sounds
  1912. if ( ADMINS_ONLY
  1913. && !(admin_flags & ACCESS_ADMIN) )
  1914. return RESULT_ADMINS_ONLY
  1915.  
  1916. // check if super admin
  1917. if ( admin_flags & ADMIN_RCON )
  1918. {
  1919. // check if super admin has to obey duration
  1920. if ( !(obey_duration_mode & 4) )
  1921. return RESULT_OK
  1922. return RESULT_SOUND_DELAY
  1923. }
  1924.  
  1925. // check if admin
  1926. if ( admin_flags & ACCESS_ADMIN )
  1927. {
  1928. // check if admin has to obey duration
  1929. if ( !(obey_duration_mode & 2) )
  1930. return RESULT_OK
  1931. return RESULT_SOUND_DELAY
  1932. }
  1933.  
  1934. if ( SND_MAX != 0
  1935. && SndCount[id] >= SND_MAX )
  1936. return RESULT_QUOTA_EXCEEDED
  1937.  
  1938. if ( SND_MAX_DUR != 0.0
  1939. && SndLenghtCount[id] > SND_MAX_DUR )
  1940. return RESULT_QUOTA_DURATION_EXCEEDED
  1941.  
  1942. // check if player is allowed to play sounds depending on alive config
  1943. if ( !(SND_MODE & (is_user_alive(id) + 1)) )
  1944. return RESULT_BAD_ALIVE_STATUS
  1945.  
  1946. // check for sound overlapping + delay time
  1947. if ( gametime > NextSoundTime + SND_DELAY )
  1948. return RESULT_OK
  1949.  
  1950. // check if overlapping is allowed
  1951. // or for delay time
  1952. if ( !(obey_duration_mode & 1)
  1953. && gametime > LastSoundTime + SND_DELAY )
  1954. return RESULT_OK
  1955.  
  1956. return RESULT_SOUND_DELAY
  1957. }
  1958.  
  1959. displayQuotaWarning( id )
  1960. {
  1961. new admin_flags = get_user_flags(id)
  1962. if ( (admin_flags & (SND_IMMUNITY | ACCESS_ADMIN)) > 0)
  1963. return
  1964.  
  1965. if ( SND_MAX != 0 )
  1966. {
  1967. if ( SndCount[id] >= SND_WARN )
  1968. {
  1969. if ( SndCount[id] + 1 == SND_MAX )
  1970. client_print(id, print_chat, "Sank Sounds >> Ez volt az utolso lejatszhato hangod")
  1971. else
  1972. client_print(id, print_chat, "Sank Sounds >> Van %d masodperced mielott lenemitananak", SND_MAX - SndCount[id] - 1)
  1973. }
  1974. }
  1975. }
  1976.  
  1977. displayQuotaExceeded( id )
  1978. {
  1979. new admin_flags = get_user_flags(id)
  1980. if ( (admin_flags & (SND_IMMUNITY | ACCESS_ADMIN)) > 0)
  1981. return 0
  1982.  
  1983. if ( SND_MAX != 0 )
  1984. {
  1985. if ( SndCount[id] >= SND_MAX )
  1986. {
  1987. if ( SndCount[id] - 3 < SND_MAX )
  1988. {
  1989. client_print(id, print_chat, "Sank Sounds >> Figyelmeztettek, le lettel nemitva")
  1990.  
  1991. // player is already muted, we increament here to save a variable to protect player from "you are muted" spam ( only 3 warnings )
  1992. ++SndCount[id]
  1993. }
  1994. return 1
  1995. }
  1996. }
  1997. return 0
  1998. }
  1999.  
  2000. //////////////////////////////////////////////////////////////////////////////
  2001. // Checks the input variables for invalid values
  2002. //////////////////////////////////////////////////////////////////////////////
  2003. ErrorCheck( )
  2004. {
  2005. // Can't have negative delay between sounds
  2006. if ( SND_DELAY < 0.0 )
  2007. {
  2008. log_amx("Sank Sounds >> SND_DELAY erteke nem lehet negativ. Allitsd at erre: 0")
  2009. SND_DELAY = 0.0
  2010. }
  2011.  
  2012. // If SND_MAX is zero, then sounds quota is disabled. Can't have negative quota
  2013. if ( SND_MAX < 0 )
  2014. {
  2015. SND_MAX = 0 // in case it was negative
  2016. log_amx("Sank Sounds >> SND_MAX erteke nem lehet negativ. Allitsd at erre: 0")
  2017. }
  2018.  
  2019. // If SND_MAX_DUR is zero, then sounds quota is disabled. Can't have negative quota
  2020. if ( SND_MAX_DUR < 0.0 )
  2021. {
  2022. SND_MAX_DUR = 0.0 // in case it was negative
  2023. log_amx("Sank Sounds >> SND_MAX_DUR erteke nem lehet negativ. Allitsd at erre: 0.0")
  2024. }
  2025.  
  2026. // If SND_WARN is zero, then we can't have warning every time a keyword is said,
  2027. // so we default to 3 less than max
  2028. else if ( ( SND_WARN <= 0 && SND_MAX != 0 )
  2029. || SND_MAX < SND_WARN )
  2030. {
  2031. if ( SND_MAX < SND_WARN )
  2032. // And finally, if they want to warn after a person has been
  2033. // muted, that's silly, so we'll fix it.
  2034. log_amx("Sank Sounds >> SND_WARN erteke nem lehet nagyobb SND_MAX ertekenel")
  2035. else if ( SND_WARN <= 0 )
  2036. log_amx("Sank Sounds >> SND_WARN erteke nem lehet nulla")
  2037.  
  2038. if ( SND_MAX > 3 )
  2039. SND_WARN = SND_MAX - 3
  2040. else
  2041. SND_WARN = SND_MAX - 1
  2042.  
  2043. log_amx("Sank Sounds >> SND_WARN beallitva az alap ertekre: %i", SND_WARN)
  2044. }
  2045. }
  2046.  
  2047. playsoundall( sound[] , type , split_dead_alive = 0 , sender_alive_status = 0 )
  2048. {
  2049. new alive
  2050. for( new i = 1; i <= g_max_players; ++i )
  2051. {
  2052. if ( !is_user_connected(i) )
  2053. continue
  2054.  
  2055. if ( is_user_bot(i) )
  2056. continue
  2057.  
  2058. if ( !SndOn[i] )
  2059. continue
  2060.  
  2061. alive = is_user_alive(i)
  2062. if ( !(SND_MODE & ( alive * 4 + 4 )) )
  2063. continue
  2064.  
  2065. if ( split_dead_alive
  2066. && alive != sender_alive_status // make sure if splited both are in same group
  2067. && !(SND_MODE & ( alive * 32 + 32 )) ) // OR check if different groups may hear each other
  2068. continue
  2069.  
  2070. if ( type == SOUND_TYPE_MP3 )
  2071. client_cmd(i, "mp3 play ^"%s^"", sound)
  2072. else if ( type == SOUND_TYPE_WAV_LOCAL )
  2073. client_cmd(i, "play ^"%s^"", sound)
  2074. else if ( type == SOUND_TYPE_SPEECH )
  2075. client_cmd(i, "spk %s", sound)
  2076. else
  2077. client_cmd(i, "spk ^"%s^"", sound)
  2078. }
  2079. }
  2080.  
  2081. print_sound_list( id , motd_msg = 0 )
  2082. {
  2083. new text[256], motd_buffer[2048], ilen, skip_for_loop
  2084. new info_text[70] = "Ird be < kulcsszo >: Egy hang lejatsszasahoz. Kulcsszavak listaja:"
  2085. if ( strlen(motd_sound_list_address) > 3 ) // make sure at least you have something like: a.b ( http://a.b )
  2086. {
  2087. copy(motd_buffer, 255, motd_sound_list_address)
  2088. skip_for_loop = 1
  2089. motd_msg = 1
  2090. }else if ( motd_msg )
  2091. ilen = format(motd_buffer, 2047, "<body bgcolor=#000000><font color=#FFB000><pre>%s^n", info_text)
  2092. else
  2093. client_print(id, print_console, info_text)
  2094.  
  2095. // Loop once for each keyword
  2096. new i, j = -1
  2097. new sData[SOUND_DATA_BASE]
  2098. new aLen = ArraySize(soundData)
  2099. for ( i = 2; i < aLen && skip_for_loop == 0; ++i ) // first 2 elements are reserved for Join / Exit sounds
  2100. {
  2101. ArrayGetArray(soundData, i, sData)
  2102.  
  2103. // check if player can see admin sounds
  2104. ++j
  2105. new found_stricted = 0
  2106. if ( sData[ADMIN_LEVEL_BASE] == 0
  2107. || get_user_flags(id) & sData[ADMIN_LEVEL_BASE] )
  2108. {
  2109. if ( motd_msg )
  2110. ilen += format(motd_buffer[ilen], 2047 - ilen, "%s", sData[KEYWORD])
  2111. else
  2112. add(text, 255, sData[KEYWORD])
  2113. }else
  2114. {
  2115. --j
  2116. found_stricted = 1
  2117. }
  2118.  
  2119. if ( !found_stricted )
  2120. {
  2121. if ( j % NUM_PER_LINE == NUM_PER_LINE - 1 )
  2122. {
  2123. // We got NUM_PER_LINE on this line,
  2124. // so print it and start on the next line
  2125. if ( motd_msg )
  2126. ilen += format(motd_buffer[ilen], 2047 - ilen, "^n")
  2127. else
  2128. {
  2129. client_print(id, print_console, "%s", text)
  2130. text[0] = 0
  2131. }
  2132. }else
  2133. {
  2134. if ( motd_msg )
  2135. ilen += format(motd_buffer[ilen], 2047 - ilen, " | ")
  2136. else
  2137. add(text, 255, " | ")
  2138. }
  2139. }
  2140. }
  2141. if ( motd_msg
  2142. && strlen(motd_buffer) )
  2143. show_motd(id, motd_buffer)
  2144. else if ( strlen(text) )
  2145. client_print(id, print_console, text)
  2146. }
  2147.  
  2148. #if ALLOW_SORT == 1
  2149. public sortSoundDataFunc( Array:array , item1 , item2 , const data[] , data_size )
  2150. {
  2151. new data1[SOUND_DATA_BASE]
  2152. new data2[SOUND_DATA_BASE]
  2153. ArrayGetArray(array, item1, data1)
  2154. ArrayGetArray(array, item2, data2)
  2155. if ( (data1[FLAGS] & FLAGS_JOIN_SND) == FLAGS_JOIN_SND )
  2156. return -1;
  2157. if ( (data2[FLAGS] & FLAGS_JOIN_SND) == FLAGS_JOIN_SND )
  2158. return 1;
  2159. if ( (data1[FLAGS] & FLAGS_EXIT_SND) == FLAGS_EXIT_SND )
  2160. return -1;
  2161. if ( (data2[FLAGS] & FLAGS_EXIT_SND) == FLAGS_EXIT_SND )
  2162. return 1;
  2163. return strcmp(data1[KEYWORD], data2[KEYWORD])
  2164. }
  2165. #endif
  2166.  
  2167. array_add_element( num , keyword[] )
  2168. {
  2169. new join_check = equali(keyword, "SND_JOIN")
  2170. new exit_check = equali(keyword, "SND_EXIT")
  2171. // if index is 0 or 1 but not the correct keyword then make sure to save in correct array position
  2172. if ( join_check == 0
  2173. && exit_check == 0 )
  2174. {
  2175. if ( num == 0
  2176. || num == 1 )
  2177. {
  2178. join_check = -1
  2179. exit_check = -1
  2180. num = 2
  2181. }
  2182. }else
  2183. {
  2184. if ( num > 1 )
  2185. {
  2186. if ( join_check != 0 )
  2187. {
  2188. num = 0
  2189. exit_check = -1
  2190. }else if ( exit_check != 0 )
  2191. {
  2192. num = 1
  2193. join_check = -1
  2194. }
  2195. }
  2196. }
  2197.  
  2198. new sData[SOUND_DATA_BASE]
  2199. if ( join_check > 0 )
  2200. sData[FLAGS] |= FLAGS_JOIN_SND | FLAG_IGNORE_AMOUNT
  2201. if ( exit_check > 0 )
  2202. sData[FLAGS] |= FLAGS_EXIT_SND | FLAG_IGNORE_AMOUNT
  2203. sData[ADMIN_LEVEL_BASE] = cfg_parse_access(keyword)
  2204. copy(sData[KEYWORD], TOK_LENGTH, keyword)
  2205. sData[PLAY_COUNT_KEY] = 0
  2206. sData[SUB_INDEX] = _:ArrayCreate(SOUND_DATA_SUB)
  2207. if ( num < ArraySize(soundData) )
  2208. ArrayInsertArrayBefore(soundData, num, sData)
  2209. else
  2210. ArrayPushArray(soundData, sData)
  2211.  
  2212. return (join_check == -1 && exit_check == -1)
  2213. ? -1
  2214. : (join_check == -1 || exit_check == -1)
  2215. ? num : -2
  2216. }
  2217.  
  2218. array_add_inner_element( num , elem , soundfile[] , allow_check_existence = 1 , allow_global_precache = 0 , precache_sounds = 0 , allowed_to_precache = 0 )
  2219. {
  2220. new subData[SOUND_DATA_SUB]
  2221. subData[ADMIN_LEVEL] = cfg_parse_access(soundfile)
  2222. subData[SOUND_TYPE] = soundfile[0] == '^"' ? SOUND_TYPE_SPEECH : ( soundfile[strlen(soundfile) - 1] == '3' ? SOUND_TYPE_MP3 : SOUND_TYPE_WAV )
  2223. subData[PLAY_COUNT] = 0
  2224.  
  2225. // check if not speech sounds
  2226. if ( soundfile[0] != '^"' )
  2227. {
  2228. new sound_file_name[TOK_LENGTH + 1 + 10]
  2229. new is_mp3 = ( containi(soundfile, ".mp3") != -1 )
  2230. new isWav_inSound_folder = 0
  2231. if ( !is_mp3 )
  2232. { // ".mp3" in not in the string
  2233. if ( equali(soundfile, "sound/", 6) )
  2234. {
  2235. formatex(sound_file_name, TOK_LENGTH + 10, "%s", soundfile)
  2236. isWav_inSound_folder = 1
  2237. }else
  2238. formatex(sound_file_name, TOK_LENGTH + 10, "sound/../%s", soundfile)
  2239. }
  2240. else
  2241. {
  2242. copy(sound_file_name, TOK_LENGTH + 10, soundfile)
  2243. }
  2244.  
  2245. if ( allow_check_existence )
  2246. {
  2247. if ( !file_exists(sound_file_name) )
  2248. {
  2249. log_amx("Sank Sounds >> A betoltendo fajl nem letezik. Atugras erre a fajlra: ^"%s^"", sound_file_name)
  2250.  
  2251. return -1
  2252. }
  2253.  
  2254. subData[DURATION] = _:cfg_get_duration(sound_file_name, is_mp3 ? SOUND_TYPE_MP3 : SOUND_TYPE_WAV )
  2255.  
  2256. if ( subData[DURATION] <= 0.0 )
  2257. {
  2258. log_amx("Sank Sounds >> A hang idotartama nem valos. A Fajl serult. Atugras erre a fajlra: ^"%s^"", sound_file_name)
  2259.  
  2260. return -1
  2261. }
  2262. }
  2263.  
  2264. if ( allow_global_precache
  2265. && precache_sounds == 1
  2266. && allowed_to_precache )
  2267. {
  2268. if ( is_mp3
  2269. || !isWav_inSound_folder )
  2270. engfunc(EngFunc_PrecacheGeneric, soundfile)
  2271. else
  2272. engfunc(EngFunc_PrecacheSound, soundfile[6])
  2273. }
  2274. }
  2275.  
  2276. copy(subData[SOUND_FILE], TOK_LENGTH, soundfile)
  2277.  
  2278. new sData[SOUND_DATA_BASE]
  2279. ArrayGetArray(soundData, num, sData)
  2280. ++sData[SOUND_AMOUNT]
  2281. if ( elem < ArraySize(sData[SUB_INDEX]) )
  2282. ArrayInsertArrayBefore(sData[SUB_INDEX], elem, subData)
  2283. else
  2284. ArrayPushArray(sData[SUB_INDEX], subData)
  2285. ArraySetArray(soundData, num, sData)
  2286.  
  2287. return 1
  2288. }
  2289.  
  2290. array_clear( )
  2291. {
  2292. new sData[SOUND_DATA_BASE]
  2293. new aLen = ArraySize(soundData)
  2294. for ( new i = 0; i < aLen; ++i )
  2295. {
  2296. ArrayGetArray(soundData, i, sData)
  2297. ArrayDestroy(sData[SUB_INDEX])
  2298. }
  2299. ArrayDestroy(soundData)
  2300. }
  2301.  
  2302. array_remove( index )
  2303. {
  2304. new sData[SOUND_DATA_BASE]
  2305. ArrayGetArray(soundData, index, sData)
  2306. ArrayDestroy(sData[SUB_INDEX])
  2307. if ( index > 1 ) // join/exit keywords may not be removed
  2308. ArrayDeleteItem(soundData, index)
  2309. else
  2310. sData[SUB_INDEX] = _:ArrayCreate(SOUND_DATA_SUB)
  2311. }
  2312.  
  2313. array_remove_inner( index , elem )
  2314. {
  2315. new sData[SOUND_DATA_BASE]
  2316. ArrayGetArray(soundData, index, sData)
  2317. --sData[SOUND_AMOUNT]
  2318. ArrayDeleteItem(sData[SUB_INDEX], elem)
  2319. ArraySetArray(soundData, index, sData)
  2320. }
  2321.  
  2322. cfg_write_keyword( file , data[] )
  2323. {
  2324. if ( data[ADMIN_LEVEL_BASE] )
  2325. {
  2326. new access_str[32]
  2327. get_flags(data[ADMIN_LEVEL_BASE], access_str, 31)
  2328. fputc(file, '@')
  2329. fputs(file, access_str)
  2330. fputc(file, '@')
  2331. }
  2332. fputs(file, data[KEYWORD])
  2333. fputs(file, ";^t^t")
  2334. }
  2335.  
  2336. cfg_write_keysound( file , subdata[] )
  2337. {
  2338. if ( subdata[ADMIN_LEVEL] )
  2339. {
  2340. new access_str[32]
  2341. get_flags(subdata[ADMIN_LEVEL], access_str, 31)
  2342. fputc(file, '@')
  2343. fputs(file, access_str)
  2344. fputc(file, '@')
  2345. }
  2346. fputs(file, subdata[SOUND_FILE])
  2347. fputs(file, ";")
  2348. }
  2349.  
  2350. cfg_parse_access( str[] )
  2351. {
  2352. new access_level
  2353. if ( str[0] == '@' )
  2354. {
  2355. new second_at = contain(str[1], "@")
  2356. if ( second_at != -1 )
  2357. {
  2358. new temp_access[32]
  2359. copy(temp_access, second_at, str[1])
  2360. strtolower(temp_access)
  2361. access_level = read_flags(temp_access)
  2362. copy(str, 127, str[second_at + 1 + 1])
  2363. }else
  2364. {
  2365. access_level = SND_IMMUNITY
  2366. copy(str, 127, str[1])
  2367. }
  2368. }
  2369.  
  2370. return access_level
  2371. }
  2372.  
  2373. Float:cfg_get_duration( sound_file[] , type )
  2374. {
  2375. switch ( type )
  2376. {
  2377. case SOUND_TYPE_WAV:
  2378. {
  2379. return cfg_get_wav_duration(sound_file)
  2380. }
  2381. case SOUND_TYPE_MP3:
  2382. {
  2383. return cfg_get_mp3_duration(sound_file)
  2384. }
  2385. }
  2386.  
  2387. return 0.0
  2388. }
  2389.  
  2390. Float:cfg_get_wav_duration( wav_file[] )
  2391. {
  2392. new file = fopen(wav_file, "rb")
  2393. new dummy_input
  2394. new i
  2395. for ( i = 0; i < 24; ++i )
  2396. dummy_input = fgetc(file)
  2397.  
  2398. // 24th byte
  2399. new hertz = fgetc(file)
  2400. // 25th byte
  2401. hertz += fgetc(file) * 256
  2402. // 26th byte
  2403. hertz += fgetc(file) * 256 * 256
  2404.  
  2405. for ( i = 27; i < 34; ++i )
  2406. dummy_input = fgetc(file)
  2407.  
  2408. // 34th byte
  2409. new bitrate = fgetc(file)
  2410.  
  2411. // bytes for data length start right after ascii "data", so search for it
  2412. // normally it is at 35 but also saw at 44, so just in case add bigger search area
  2413. new data_found
  2414.  
  2415. do
  2416. {
  2417. dummy_input = fgetc(file)
  2418. if ( dummy_input == 'd' )
  2419. data_found = 1
  2420. else if ( dummy_input == 'a'
  2421. && data_found == 1 )
  2422. data_found = 2
  2423. else if ( dummy_input == 't'
  2424. && data_found == 2 )
  2425. data_found = 3
  2426. else if ( dummy_input == 'a'
  2427. && data_found == 3 )
  2428. data_found = 4
  2429. else
  2430. data_found = 0
  2431. }while ( dummy_input != -1 && data_found < 4 )
  2432.  
  2433. if ( dummy_input == -1
  2434. || hertz <= 0
  2435. || bitrate <= 0
  2436. || data_found != 4 )
  2437. {
  2438. fclose(file)
  2439. return 0.0
  2440. }
  2441.  
  2442. // 1st byte after data
  2443. new data_length = fgetc(file)
  2444. // 2nd byte after data
  2445. data_length += fgetc(file) * 256
  2446. // 3rd byte after data
  2447. data_length += fgetc(file) * 256 * 256
  2448. // 4th byte after data
  2449. data_length += fgetc(file) * 256 * 256 * 256
  2450.  
  2451. fclose(file)
  2452.  
  2453. return float(data_length) / ( float(hertz * bitrate) / 8.0 )
  2454. }
  2455.  
  2456. enum
  2457. {
  2458. MP3_MPEG_VERSION_BIT1 = 8,
  2459. MP3_MPEG_VERSION_BIT2 = 16,
  2460. MP3_LAYER_BIT1 = 2,
  2461. MP3_LAYER_BIT2 = 4,
  2462. MP3_PROTECT_BIT = 1,
  2463.  
  2464. MP3_BITRATE_BIT1 = 16,
  2465. MP3_BITRATE_BIT2 = 32,
  2466. MP3_BITRATE_BIT3 = 64,
  2467. MP3_BITRATE_BIT4 = 128,
  2468. MP3_BITRATE_INVALID = 15,
  2469. MP3_SAMPLERATE_BIT1 = 4,
  2470. MP3_SAMPLERATE_BIT2 = 8,
  2471. MP3_SAMPLERATE_INVALID = 3,
  2472. MP3_PADDING_BIT = 2,
  2473. MP3_PRIVATE_BIT = 1,
  2474. }
  2475.  
  2476. // bitrate info
  2477. new const bitrate_table[] = {
  2478. //MPEG 2 & 2.5
  2479. 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, -1, // Layer I
  2480. 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, -1, // Layer II
  2481. 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, -1, // Layer III
  2482. //MPEG 1
  2483. 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, -1, // Layer I
  2484. 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, -1, // Layer II
  2485. 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, -1, // Layer III
  2486. }
  2487.  
  2488. #if DEBUG_MODE == 1
  2489. // frequency info
  2490. new const samplingrate_table[] = {
  2491. 11025, 12000, 8000, 0, // MPEG 2.5 // have not seen MPEG 2.5, so UNTESTED
  2492. -1, -1, -1, 0, // reserved
  2493. 22050, 24000, 16000, 0, // MPEG 2
  2494. 44100, 48000, 32000, 0 // MPEG 1
  2495. }
  2496. #endif
  2497.  
  2498. Float:cfg_get_mp3_duration( mp3_file[] )
  2499. {
  2500. new file = fopen(mp3_file, "rb")
  2501. new byte, found_header, file_pos
  2502. new byte2
  2503.  
  2504. new mpeg_version
  2505. new layer
  2506. new mp3_bitrate
  2507. new mp3_samplerate
  2508. new result = -1
  2509. do
  2510. {
  2511. byte = fgetc(file)
  2512. if ( byte == -1 )
  2513. break
  2514.  
  2515. ++file_pos
  2516. if ( byte != 255 )
  2517. continue
  2518.  
  2519. byte = fgetc(file)
  2520. byte2 = fgetc(file)
  2521. result = verify_header(byte, byte2, mpeg_version, layer, mp3_bitrate, mp3_samplerate)
  2522. if ( result == -1 )
  2523. {
  2524. fseek(file, file_pos, SEEK_SET)
  2525. ++file_pos
  2526. continue
  2527. }else
  2528. break
  2529. }while ( !found_header && byte != -1 )
  2530.  
  2531. fclose(file)
  2532.  
  2533. if ( byte == -1 )
  2534. return 0.0
  2535.  
  2536. new mpeg_version_for_bitrate = 0
  2537. if ( mpeg_version == 3 )
  2538. mpeg_version_for_bitrate = 1
  2539. new mp3_bitrate_kbps = bitrate_table[mpeg_version_for_bitrate * ( 3 * 16 ) + ( layer - 1 ) * 16 + mp3_bitrate]
  2540.  
  2541. #if DEBUG_MODE == 1
  2542. log_amx("Sank Sounds >> DEBUG a fajlnal ^"%s^"", mp3_file)
  2543. log_amx("Sank Sounds >> Data bytes = %i / %i", byte, byte2)
  2544. log_amx("Sank Sounds >> Fejfajl pozicio = %i", file_pos)
  2545. new mpeg_version_str[10]
  2546. if ( mpeg_version == 0 )
  2547. copy(mpeg_version_str, 9, "MPEG 2.5")
  2548. else if ( mpeg_version == 2 )
  2549. copy(mpeg_version_str, 9, "MPEG 2")
  2550. else if ( mpeg_version == 3 )
  2551. copy(mpeg_version_str, 9, "MPEG 1")
  2552. log_amx("Sank Sounds >> MPEG verzio = %i / Formatum: %s", mpeg_version, mpeg_version_str)
  2553. log_amx("Sank Sounds >> Layer = %i", layer)
  2554. log_amx("Sank Sounds >> Bitrate = %iKbps (%i)", mp3_bitrate_kbps, mp3_bitrate)
  2555.  
  2556. new mp3_samplerate_hz = samplingrate_table[mpeg_version * 4 + mp3_samplerate]
  2557.  
  2558. log_amx("Sank Sounds >> Samplerate = %iHz (%i)", mp3_samplerate_hz, mp3_samplerate)
  2559. #endif
  2560. new size_of_file = file_size(mp3_file, 0)
  2561.  
  2562. if ( mp3_bitrate_kbps == 0 )
  2563. return 0.0
  2564.  
  2565. //song length...
  2566. return float(size_of_file) / ( float(mp3_bitrate_kbps) * 1000.0 ) * 8.0
  2567. }
  2568.  
  2569. verify_header( header , header2 , &mpeg_version , &layer , &mp3_bitrate , &mp3_samplerate)
  2570. {
  2571. // check if first 3 bits set
  2572. if ( header & 0xe0 != 0xe0 )
  2573. return -1
  2574.  
  2575. layer = 4
  2576. - ( header & MP3_LAYER_BIT1 ) / MP3_LAYER_BIT1
  2577. + ( header & MP3_LAYER_BIT2 ) / MP3_LAYER_BIT1
  2578.  
  2579. if ( layer != 3 )
  2580. return -1
  2581.  
  2582. mp3_bitrate = ( header2 & MP3_BITRATE_BIT1 ) / MP3_BITRATE_BIT1
  2583. + ( header2 & MP3_BITRATE_BIT2 ) / MP3_BITRATE_BIT1
  2584. + ( header2 & MP3_BITRATE_BIT3 ) / MP3_BITRATE_BIT1
  2585. + ( header2 & MP3_BITRATE_BIT4 ) / MP3_BITRATE_BIT1
  2586.  
  2587. if ( mp3_bitrate & MP3_BITRATE_INVALID == MP3_BITRATE_INVALID )
  2588. return -1
  2589.  
  2590. mp3_samplerate = ( header2 & MP3_SAMPLERATE_BIT1 ) / MP3_SAMPLERATE_BIT1
  2591. + ( header2 & MP3_SAMPLERATE_BIT2 ) / MP3_SAMPLERATE_BIT1
  2592.  
  2593. if ( mp3_samplerate & MP3_SAMPLERATE_INVALID == MP3_SAMPLERATE_INVALID )
  2594. return -1
  2595.  
  2596. mpeg_version = ( header & MP3_MPEG_VERSION_BIT1 ) / MP3_MPEG_VERSION_BIT1
  2597. + ( header & MP3_MPEG_VERSION_BIT2 ) / MP3_MPEG_VERSION_BIT1
  2598.  
  2599. return 1
  2600. }
  2601.  
  2602. /*
  2603. * plugin_sank_sounds.sma
  2604. * Author: Luke Sankey
  2605. * Date: March 21, 2001 - Original hard-coded version
  2606. * Date: July 2, 2001 - Rewrote to be text file configurable
  2607. * Date: November 18, 2001 - Added admin_sound_play command, new variables
  2608. * SND_DELAY, SND_SPLIT and EXACT_MATCH, as well as the ability to
  2609. * have admin-only sounds, like the original version had.
  2610. * Date: March 30, 2002 - Now ignores speech of length zero.
  2611. * Date: May 30, 2002 - Updated for use with new playerinfo function
  2612. * Date: November 12, 2002 - Moved snd-list.cfg file to new location, and
  2613. * made it all lower-case. Sorry, linux guys, if it confuses you.
  2614. * Added some new ideas from Bill Bateman:
  2615. * 1.) added SND_PUNISH and changed SND_KICK to SND_MAX
  2616. * 2.) ability to either speak or play sounds
  2617. *
  2618. * Last Updated: May 12, 2003
  2619. *
  2620. *
  2621. *
  2622. * HunteR's modifications:
  2623. * - Players no longer kicked, they are "muted" (no longer able to play sounds)
  2624. * - All sounds are now "spoken" (using the speak command)
  2625. * - As a result, all "\" must become "/"
  2626. * - Ability to reset a player's sound count mid-game
  2627. *
  2628. * My most deepest thanks goes to William Bateman (aka HunteR)
  2629. * http://thepit.shacknet.nu
  2630. * huntercc@hotmail.com
  2631. * For he was the one who got me motivated once again to write this plugin
  2632. * since I don't run a server anymore. And besides that, he helped write
  2633. * parts of it.
  2634. *
  2635. * I hope you enjoy this new functionality on the old plugin_sank_sounds
  2636. */
  2637.