HLMOD.HU Forrás Megtekintés - www.hlmod.hu
  1. /*
  2.   Fordította: BBk
  3. */
  4. /*
  5. advancedc4timer.sp
  6.  
  7. Description:
  8. Advanced c4 countdown timer. Based on the original sm c4 timer by sslice.
  9.  
  10. Versions:
  11. 0.5
  12. * Initial Release
  13.  
  14. 0.6
  15. * Restructued most of the code
  16. * Added user configuration of sounds
  17. * Added optional announcement
  18. * Changed timer to go 30, 20, 10, 9.....1
  19.  
  20. 1.0
  21. * Minor code and naming standards changes
  22. * Added support for late loading
  23.  
  24. 1.1
  25. * Added an exit option to the settings menu
  26. * Changed command to sm_c4timer
  27. * Made the SoundNames array const
  28. * Added new hud text
  29.  
  30. 1.1.1
  31. * Fixed voice countdown bug
  32.  
  33. 1.2
  34. * Added translations
  35. * Added name to bomb exploded message
  36. * Added bomb defused hud message
  37.  
  38. 1.2.1
  39. * Updated translation files and script to match
  40. * Changed menu behavior
  41.  
  42. 1.3
  43. * Changed naming convention to be more in line with base sourcemod
  44. * Improved timer synchronization
  45. * Changed from panels to menus
  46.  
  47. 1.4
  48. * Removed duplicate menu exit
  49. * Added autoloading of config file
  50. * Added verbose, flexible bombtimer messages
  51. * Added the ability to have the voice or text messages start at 10 instead of 30
  52.  
  53. 1.4.1
  54. * Added individual sounds
  55.  
  56. */
  57.  
  58. #pragma semicolon 1
  59.  
  60. #include <sourcemod>
  61. #include <sdktools>
  62.  
  63. #define PLUGIN_VERSION "1.4.1"
  64. #define NUM_SOUNDS 12
  65. #define TIMER 30
  66.  
  67. #define TWENTY 0
  68. #define ONE 1
  69. #define TWO 2
  70. #define THREE 3
  71. #define FOUR 4
  72. #define FIVE 5
  73. #define SIX 6
  74. #define SEVEN 7
  75. #define EIGHT 8
  76. #define NINE 9
  77. #define TEN 10
  78. #define THIRTY 11
  79.  
  80. #define NUM_PREFS 4
  81. #define SOUND 0
  82. #define CHAT 1
  83. #define CENTER 2
  84. #define HUD 3
  85.  
  86. #define SOUND_AT_TEN 1
  87. #define TEXT_AT_TEN 2
  88.  
  89. public Plugin:myinfo =
  90. {
  91. name = "Advanced c4 Countdown Timer",
  92. author = "dalto",
  93. description = "Plugin that gives a countdown for the C4 explosion in Counter-Strike Source.",
  94. version = PLUGIN_VERSION,
  95. url = "http://forums.alliedmods.net"
  96. };
  97.  
  98.  
  99. // Global Variables
  100. new String:g_soundsList[1][NUM_SOUNDS][PLATFORM_MAX_PATH];
  101. new g_c4Preferences[MAXPLAYERS + 1][NUM_PREFS];
  102. new Handle:g_kvC4 = INVALID_HANDLE;
  103. new String:g_filenameC4[PLATFORM_MAX_PATH];
  104. new Handle:g_CvarEnable = INVALID_HANDLE;
  105. new Handle:g_CvarMPc4Timer = INVALID_HANDLE;
  106. new Handle:g_CvarAnnounce = INVALID_HANDLE;
  107. new Handle:g_CvarChatDefault = INVALID_HANDLE;
  108. new Handle:g_CvarSoundDefault = INVALID_HANDLE;
  109. new Handle:g_CvarHUDDefault = INVALID_HANDLE;
  110. new Handle:g_CvarCenterDefault = INVALID_HANDLE;
  111. new Handle:g_CvarAltStart = INVALID_HANDLE;
  112. new Float:g_explosionTime;
  113. new g_countdown;
  114. new bool:g_lateLoaded;
  115. new String:g_planter[40];
  116. static const String:g_soundNames[NUM_SOUNDS][] = {"20", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "30"};
  117. new Handle:hTimer = INVALID_HANDLE;
  118.  
  119. // We need to capture if the plugin was late loaded so we can make sure initializations
  120. // are handled properly
  121. public bool:AskPluginLoad(Handle:myself, bool:late, String:error[], err_max)
  122. {
  123. g_lateLoaded = late;
  124. return true;
  125. }
  126.  
  127. public OnPluginStart()
  128. {
  129. CreateConVar("sm_c4_timer_version", PLUGIN_VERSION, "Fejlett c4 Idozito Verzio", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY);
  130. g_CvarEnable = CreateConVar("sm_c4_timer_enable", "1", "C4 idozito engedelyezese");
  131. g_CvarAnnounce = CreateConVar("sm_c4_timer_announce", "1", "Hirdetesek engedelyezese");
  132. g_CvarChatDefault = CreateConVar("sm_c4_timer_chat_default", "0", "Chat uzenetek engedelyezese");
  133. g_CvarCenterDefault = CreateConVar("sm_c4_timer_center_default", "0", "Kozepponti preferencia engedelyezese");
  134. g_CvarHUDDefault = CreateConVar("sm_c4_timer_hud_default", "1", "HUD uzenetek engedelyezese");
  135. g_CvarSoundDefault = CreateConVar("sm_c4_timer_sound_default", "1", "Hangok engedelyezese");
  136. g_CvarAltStart = CreateConVar("sm_c4_timer_start_at_ten", "0", "1 hangok engedelyezese 10-nel, 2 szovegek engedelyezese 10-nel, 3 mind2 engedelyezese ");
  137.  
  138. g_CvarMPc4Timer = FindConVar("mp_c4timer");
  139.  
  140. LoadTranslations("plugin.advancedc4timer");
  141.  
  142. // Execute the config file
  143. AutoExecConfig(true, "advancedc4timer");
  144.  
  145. HookEvent("bomb_planted", EventBombPlanted, EventHookMode_Pre);
  146. HookEvent("round_start", EventRoundStart, EventHookMode_PostNoCopy);
  147. HookEvent("bomb_exploded", EventBombExploded, EventHookMode_PostNoCopy);
  148. HookEvent("bomb_defused", EventBombDefused, EventHookMode_Post);
  149. RegConsoleCmd("sm_c4timer", SettingsMenu);
  150.  
  151. LoadSounds();
  152.  
  153. g_kvC4=CreateKeyValues("c4UserSettings");
  154. BuildPath(Path_SM, g_filenameC4, PLATFORM_MAX_PATH, "data/c4usersettings.txt");
  155. if(!FileToKeyValues(g_kvC4, g_filenameC4))
  156. KeyValuesToFile(g_kvC4, g_filenameC4);
  157.  
  158. // if the plugin was loaded late we have a bunch of initialization that needs to be done
  159. if(g_lateLoaded)
  160. {
  161. // Next we need to whatever we would have done as each client authorized
  162. for(new i = 1; i <= GetMaxClients(); i++)
  163. {
  164. if(IsClientInGame(i))
  165. {
  166. PrepareClient(i);
  167. }
  168. }
  169. }
  170. }
  171.  
  172. public OnMapStart()
  173. {
  174. for(new i = 0; i < NUM_SOUNDS; i++)
  175. {
  176. PrepareSound(i);
  177. }
  178. }
  179.  
  180. // When a new client is authorized we create sound preferences
  181. // for them if they do not have any already
  182. public OnClientAuthorized(client, const String:auth[])
  183. {
  184. PrepareClient(client);
  185. }
  186.  
  187. public Action:EventBombPlanted(Handle:event, const String:name[], bool:dontBroadcast)
  188. {
  189. if(!GetConVarBool(g_CvarEnable))
  190. {
  191. return Plugin_Continue;
  192. }
  193.  
  194. g_explosionTime = GetEngineTime() + GetConVarFloat(g_CvarMPc4Timer);
  195.  
  196. GetClientName(GetClientOfUserId(GetEventInt(event, "userid")), g_planter, sizeof(g_planter));
  197.  
  198. g_countdown = GetConVarInt(g_CvarMPc4Timer) - 1;
  199.  
  200. hTimer = CreateTimer((g_explosionTime - float(g_countdown)) - GetEngineTime(), TimerCountdown);
  201.  
  202. return Plugin_Continue;
  203. }
  204.  
  205. public EventBombDefused(Handle:event, const String:name[], bool:dontBroadcast)
  206. {
  207. if(!GetConVarBool(g_CvarEnable))
  208. {
  209. return;
  210. }
  211.  
  212. if(IsValidHandle(hTimer))
  213. {
  214. CloseHandle(hTimer);
  215. }
  216. decl String:defuser[40];
  217. GetClientName(GetClientOfUserId(GetEventInt(event, "userid")), defuser, sizeof(defuser));
  218. for(new i = 1; i <= GetMaxClients(); i++)
  219. {
  220. if(IsClientInGame(i) && !IsFakeClient(i) && g_c4Preferences[i][HUD])
  221. {
  222. PrintHintText(i, "%T", "bomb defused", i, defuser);
  223. }
  224. }
  225. }
  226.  
  227. public Action:TimerCountdown(Handle:timer, any:data)
  228. {
  229. BombMessage(g_countdown);
  230. if(--g_countdown)
  231. {
  232. hTimer = CreateTimer((g_explosionTime - float(g_countdown)) - GetEngineTime(), TimerCountdown);
  233. }
  234. }
  235.  
  236. // Loads the soundsList array with the c4 sounds
  237. public LoadSounds()
  238. {
  239. new Handle:kvQSL = CreateKeyValues("c4SoundsList");
  240. new String:fileQSL[PLATFORM_MAX_PATH];
  241.  
  242. BuildPath(Path_SM, fileQSL, PLATFORM_MAX_PATH, "configs/c4soundslist.cfg");
  243. FileToKeyValues(kvQSL, fileQSL);
  244.  
  245. if (!KvGotoFirstSubKey(kvQSL))
  246. {
  247. SetFailState("configs/c4soundslist.cfg nem talalhato vagy nem pontosan strukturalt");
  248. CloseHandle(kvQSL);
  249. return;
  250. }
  251.  
  252. for(new i = 0; i < NUM_SOUNDS; i++)
  253. {
  254. KvGetString(kvQSL, g_soundNames[i], g_soundsList[0][i], PLATFORM_MAX_PATH);
  255. }
  256.  
  257. CloseHandle(kvQSL);
  258. }
  259.  
  260. public PrepareSound(sound)
  261. {
  262. new String:downloadFile[PLATFORM_MAX_PATH];
  263.  
  264. if(!StrEqual(g_soundsList[0][sound], ""))
  265. {
  266. PrecacheSound(g_soundsList[0][sound], true);
  267. Format(downloadFile, PLATFORM_MAX_PATH, "sound/%s", g_soundsList[0][sound]);
  268. AddFileToDownloadsTable(downloadFile);
  269. }
  270. }
  271.  
  272. // Sends the bomb message
  273. public BombMessage(count)
  274. {
  275. new soundKey;
  276. decl String:buffer[200];
  277.  
  278. switch(count)
  279. {
  280. case 1, 2, 3, 4, 5, 6, 7, 8, 9, 10:
  281. soundKey = count;
  282. case 20:
  283. soundKey = TWENTY;
  284. case 30:
  285. soundKey = THIRTY;
  286. default:
  287. return;
  288. }
  289.  
  290. for (new i = 1; i <= GetMaxClients(); i++)
  291. {
  292. if(IsClientInGame(i) && !IsFakeClient(i) && !StrEqual(g_soundsList[0][soundKey], ""))
  293. {
  294. Format(buffer, sizeof(buffer), "countdown %i", count);
  295. Format(buffer, sizeof(buffer), "%T", buffer, i, count);
  296. if(g_c4Preferences[i][SOUND] && !(GetConVarInt(g_CvarAltStart) & SOUND_AT_TEN && (soundKey < 1 || soundKey > 10)))
  297. {
  298. EmitSoundToClient(i, g_soundsList[0][soundKey]);
  299. }
  300. if(!(GetConVarInt(g_CvarAltStart) & TEXT_AT_TEN && (soundKey < 1 || soundKey > 10)))
  301. {
  302. if(g_c4Preferences[i][CHAT])
  303. {
  304. PrintToChat(i, "Bomb: %s", buffer);
  305. }
  306. if(g_c4Preferences[i][CENTER])
  307. {
  308. PrintCenterText(i, buffer);
  309. }
  310. if(g_c4Preferences[i][HUD])
  311. {
  312. PrintHintText(i, buffer);
  313. }
  314. }
  315. }
  316. }
  317. }
  318.  
  319. public Action:TimerAnnounce(Handle:timer, any:client)
  320. {
  321. if(IsClientInGame(client))
  322. {
  323. PrintToChat(client, "%t", "announce");
  324. }
  325. }
  326.  
  327. // This selects or disables the c4 settings
  328. public SettingsMenuHandler(Handle:menu, MenuAction:action, param1, param2)
  329. {
  330. if(action == MenuAction_Select)
  331. {
  332. // Update both the soundPreference array and User Settings KV
  333. switch(param2)
  334. {
  335. case 0:
  336. g_c4Preferences[param1][SOUND] = Flip(g_c4Preferences[param1][SOUND]);
  337. case 1:
  338. g_c4Preferences[param1][CHAT] = Flip(g_c4Preferences[param1][CHAT]);
  339. case 2:
  340. g_c4Preferences[param1][CENTER] = Flip(g_c4Preferences[param1][CENTER]);
  341. case 3:
  342. g_c4Preferences[param1][HUD] = Flip(g_c4Preferences[param1][HUD]);
  343. }
  344. new String:steamId[20];
  345. GetClientAuthString(param1, steamId, 20);
  346. KvRewind(g_kvC4);
  347. KvJumpToKey(g_kvC4, steamId);
  348. KvSetNum(g_kvC4, "sound", g_c4Preferences[param1][SOUND]);
  349. KvSetNum(g_kvC4, "chat", g_c4Preferences[param1][CHAT]);
  350. KvSetNum(g_kvC4, "center", g_c4Preferences[param1][CENTER]);
  351. KvSetNum(g_kvC4, "hud", g_c4Preferences[param1][HUD]);
  352. KvSetNum(g_kvC4, "timestamp", GetTime());
  353. SettingsMenu(param1, 0);
  354. } else if(action == MenuAction_End) {
  355. CloseHandle(menu);
  356. }
  357. }
  358.  
  359. // This creates the settings panel
  360. public Action:SettingsMenu(client, args)
  361. {
  362. decl String:buffer[100];
  363. new Handle:menu = CreateMenu(SettingsMenuHandler);
  364. Format(buffer, sizeof(buffer), "%T", "c4 menu", client);
  365. SetMenuTitle(menu, buffer);
  366. if(g_c4Preferences[client][SOUND] == 1)
  367. {
  368. Format(buffer, sizeof(buffer), "%T", "disable sound", client);
  369. } else {
  370. Format(buffer, sizeof(buffer), "%T", "enable sound", client);
  371. }
  372. AddMenuItem(menu, "menu item", buffer);
  373.  
  374. if(g_c4Preferences[client][CHAT] == 1)
  375. {
  376. Format(buffer, sizeof(buffer), "%T", "disable chat", client);
  377. }
  378. else {
  379. Format(buffer, sizeof(buffer), "%T", "enable chat", client);
  380. }
  381. AddMenuItem(menu, "menu item", buffer);
  382.  
  383. if(g_c4Preferences[client][CENTER] == 1)
  384. {
  385. Format(buffer, sizeof(buffer), "%T", "disable center", client);
  386. } else {
  387. Format(buffer, sizeof(buffer), "%T", "enable center", client);
  388. }
  389. AddMenuItem(menu, "menu item", buffer);
  390.  
  391. if(g_c4Preferences[client][HUD] == 1)
  392. {
  393. Format(buffer, sizeof(buffer), "%T", "disable hud", client);
  394. }
  395. else {
  396. Format(buffer, sizeof(buffer), "%T", "enable hud", client);
  397. }
  398. AddMenuItem(menu, "menu item", buffer);
  399.  
  400. DisplayMenu(menu, client, 15);
  401.  
  402. return Plugin_Handled;
  403. }
  404.  
  405. // Switches a non-zero number to a 0 and a 0 to a 1
  406. public Flip(flipNum)
  407. {
  408. if(flipNum == 0)
  409. {
  410. return 1;
  411. }
  412. else
  413. {
  414. return 0;
  415. }
  416. }
  417.  
  418. // Initializations to be done at the beginning of the round
  419. public EventRoundStart(Handle:event, const String:name[], bool:dontBroadcast)
  420. {
  421. // Save user settings to a file
  422. KvRewind(g_kvC4);
  423. KeyValuesToFile(g_kvC4, g_filenameC4);
  424. if(IsValidHandle(hTimer))
  425. {
  426. CloseHandle(hTimer);
  427. }
  428. }
  429.  
  430. // When a user disconnects we need to update their timestamp in kvC4
  431. public OnClientDisconnect(client)
  432. {
  433. new String:steamId[20];
  434. if(client && !IsFakeClient(client))
  435. {
  436. GetClientAuthString(client, steamId, 20);
  437. KvRewind(g_kvC4);
  438. if(KvJumpToKey(g_kvC4, steamId))
  439. {
  440. KvSetNum(g_kvC4, "timestamp", GetTime());
  441. }
  442. }
  443. }
  444.  
  445. public PrepareClient(client)
  446. {
  447. new String:steamId[20];
  448. if(client)
  449. {
  450. if(!IsFakeClient(client))
  451. {
  452. // Get the users saved setting or create them if they don't exist
  453. GetClientAuthString(client, steamId, 20);
  454. KvRewind(g_kvC4);
  455. if(KvJumpToKey(g_kvC4, steamId))
  456. {
  457. g_c4Preferences[client][SOUND] = KvGetNum(g_kvC4, "sound", GetConVarInt(g_CvarSoundDefault));
  458. g_c4Preferences[client][CHAT] = KvGetNum(g_kvC4, "chat", GetConVarInt(g_CvarChatDefault));
  459. g_c4Preferences[client][CENTER] = KvGetNum(g_kvC4, "center", GetConVarInt(g_CvarCenterDefault));
  460. g_c4Preferences[client][HUD] = KvGetNum(g_kvC4, "hud", GetConVarInt(g_CvarHUDDefault));
  461. } else {
  462. KvRewind(g_kvC4);
  463. KvJumpToKey(g_kvC4, steamId, true);
  464. KvSetNum(g_kvC4, "sound", GetConVarInt(g_CvarSoundDefault));
  465. KvSetNum(g_kvC4, "chat", GetConVarInt(g_CvarChatDefault));
  466. KvSetNum(g_kvC4, "center", GetConVarInt(g_CvarCenterDefault));
  467. KvSetNum(g_kvC4, "hud", GetConVarInt(g_CvarHUDDefault));
  468. g_c4Preferences[client][SOUND] = GetConVarInt(g_CvarSoundDefault);
  469. g_c4Preferences[client][CHAT] = GetConVarInt(g_CvarChatDefault);
  470. g_c4Preferences[client][CENTER] = GetConVarInt(g_CvarCenterDefault);
  471. g_c4Preferences[client][HUD] = GetConVarInt(g_CvarHUDDefault);
  472. }
  473. KvRewind(g_kvC4);
  474.  
  475. // Make the announcement in 30 seconds unless announcements are turned off
  476. if(GetConVarBool(g_CvarAnnounce))
  477. {
  478. CreateTimer(30.0, TimerAnnounce, client);
  479. }
  480. }
  481. }
  482. }
  483.  
  484. public EventBombExploded(Handle:event, const String:name[], bool:dontBroadcast)
  485. {
  486. if(IsValidHandle(hTimer))
  487. {
  488. CloseHandle(hTimer);
  489. }
  490. for(new i = 1; i <= GetMaxClients(); i++)
  491. {
  492. if(IsClientInGame(i) && !IsFakeClient(i) && g_c4Preferences[i][HUD])
  493. {
  494. PrintHintText(i, "%T", "bomb exploded", i, g_planter);
  495. }
  496. }
  497. }
  498.