HLMOD.HU Forrás Megtekintés - www.hlmod.hu
  1. /*
  2.   Description:
  3.   When you die or round ends and you are still alive
  4.   A left side menu shows who and how much you did damage to and who damaged you.
  5.  
  6.   Developed:
  7.   2007-12-20
  8.  
  9.   By:
  10.   [30+]Gemeni (gemeni@30plus.ownit.se)
  11.  
  12.   Version history:
  13.   1.0.0 - First Version
  14.   1.0.1 - Added number of hits
  15.   1.0.2 - Added hitgroup information
  16.   1.0.3 - Created a long and short version of the report.
  17.   If the Long version that includes hitgroups does not fit
  18.   in the panel, the short version is displayed
  19.   Added coloring in the panel
  20.   1.1.0 - Added option so you can turn damage report on and off, and also
  21.   decide if it should be printed in menu or chat. Use /damage_report help to get info
  22.   Big thanks to death_beam team since I used their code to learn about
  23.   KeyValues!
  24.   1.1.1 - Stripped chat output.
  25.   Resetting damage data on round start
  26.   1.1.2 - Added total dmg taken/given and X indicator for kill/killed
  27.   1.1.3 - Removed errors from translation stuff that was not completed
  28.   Still looking at getting translation to work
  29.   1.1.5 - Added support to show again the last report that was shown to a player
  30.   1.1.6 - Fixed saving of settings on map end
  31.   1.1.7 - Problem with bogus entries in damagereportsetting file
  32.   1.1.8 - Added most kills info
  33.   1.1.9 - Fixed memory leak
  34.   1.1.10 - Checking if player still ingame before trying to display.
  35.   1.2.0 - Added translations
  36.  
  37.   Fordította: BBk
  38. */
  39.  
  40. #pragma semicolon 1
  41. #include <sourcemod>
  42. #include <sdktools>
  43.  
  44. // Definitions
  45. #define MAXHITGROUPS 7
  46. #define NROFOPTIONS 2
  47. #define MAX_FILE_LEN 80
  48.  
  49. #define DrON 1
  50. #define DrOFF 0
  51. #define DrPop 1
  52. #define DrChat 0
  53.  
  54. #define propOnOff 0
  55. #define propPopChat 1
  56.  
  57. #define PLUGIN_VERSION "1.2.0"
  58.  
  59. public Plugin:myinfo =
  60. {
  61. name = "Damage report",
  62. author = "[30+]Gemeni",
  63. description = "Jelentesek, kit sebeztel meg es teged ki sebzett meg",
  64. version = PLUGIN_VERSION,
  65. url = "http://30plus.ownit.se/"
  66. };
  67.  
  68. // Global variables
  69. new g_DamageDone[MAXPLAYERS+1][MAXPLAYERS+1];
  70. new g_HitsDone[MAXPLAYERS+1][MAXPLAYERS+1];
  71. new g_HitboxDone[MAXPLAYERS+1][MAXPLAYERS+1][MAXHITGROUPS+1];
  72.  
  73. new g_DamageTaken[MAXPLAYERS+1][MAXPLAYERS+1];
  74. new g_HitsTaken[MAXPLAYERS+1][MAXPLAYERS+1];
  75. new g_HitboxTaken[MAXPLAYERS+1][MAXPLAYERS+1][MAXHITGROUPS+1];
  76.  
  77. new String:g_PlayerName[MAXPLAYERS+1][32];
  78.  
  79. new g_KilledPlayer[MAXPLAYERS+1][MAXPLAYERS+1];
  80.  
  81. new g_PlayerDROption[MAXPLAYERS+1][NROFOPTIONS];
  82. new String:g_filenameSettings[MAX_FILE_LEN];
  83. new Handle:KVSettings = INVALID_HANDLE;
  84.  
  85. new g_defaultPropOnOff = DrON;
  86. new g_defaultPropChatPop = DrPop;
  87.  
  88. new bool:g_lateLoaded;
  89.  
  90. // History stats
  91. new String:g_HistDamageDone[MAXPLAYERS+1][512];
  92. new String:g_HistDamageDoneLong[MAXPLAYERS+1][512];
  93. new g_HistTotalDamageDone[MAXPLAYERS+1];
  94. new String:g_HistDamageTaken[MAXPLAYERS+1][512];
  95. new String:g_HistDamageTakenLong[MAXPLAYERS+1][512];
  96. new g_HistTotalDamageTaken[MAXPLAYERS+1];
  97.  
  98.  
  99. new Handle:g_versionConVar;
  100.  
  101. new g_maxClients;
  102.  
  103. // Variable for Temp fix
  104. new g_MenuCleared[MAXPLAYERS+1];
  105.  
  106.  
  107. public bool:AskPluginLoad(Handle:myself, bool:late, String:error[], err_max)
  108. {
  109. g_lateLoaded = late;
  110. return true;
  111. }
  112.  
  113. // Hook events on plugin start
  114. public OnPluginStart(){
  115. g_versionConVar = CreateConVar("sm_damage_report_version", PLUGIN_VERSION, "Damage report version", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY);
  116. SetConVarString(g_versionConVar, PLUGIN_VERSION);
  117. HookEvent("player_death", Event_PlayerDeath);
  118. HookEvent("player_hurt", Event_PlayerHurt);
  119. HookEvent("player_spawn", Event_PlayerSpawn);
  120. HookEvent("round_end", Event_RoundEnd);
  121. HookEvent("round_start", EventRoundStart);
  122.  
  123. HookEvent("player_disconnect", Event_PlayerDisconnect);
  124. HookEvent("player_connect", Event_PlayerConnect);
  125.  
  126. RegConsoleCmd("damage_report", Command_DamageReport);
  127. RegConsoleCmd("last_damage_report", Command_LastDamageReport);
  128. RegConsoleCmd("ldr", Command_LastDamageReport);
  129.  
  130. LoadTranslations("gem_damage_report.phrases");
  131.  
  132.  
  133. KVSettings=CreateKeyValues("DamageReportSetting");
  134. BuildPath(Path_SM, g_filenameSettings, MAX_FILE_LEN, "data/damagereportsetting.txt");
  135. if(!FileToKeyValues(KVSettings, g_filenameSettings))
  136. {
  137. KeyValuesToFile(KVSettings, g_filenameSettings);
  138. }
  139.  
  140. if(g_lateLoaded)
  141. {
  142. // Plugin was not loaded at beginning of round
  143. // Find settings for all players already connected
  144. for(new i = 1; i < g_maxClients; i++)
  145. {
  146. if(IsClientInGame(i) && !IsFakeClient(i))
  147. {
  148. FindSettingsForClient(i);
  149. }
  150. }
  151. }
  152. }
  153.  
  154. public Action:Command_LastDamageReport(client, args)
  155. {
  156. // Dont do anything if command comes from server
  157. if (client == 0) {
  158. return Plugin_Handled;
  159. }
  160.  
  161. if ((strcmp(g_HistDamageDone[client], "") != 0) || (strcmp(g_HistDamageTaken[client], "") != 0)) {
  162. DisplayDamageReport(client, g_HistDamageDone[client] ,g_HistDamageDoneLong[client] ,g_HistDamageTaken[client], g_HistDamageTakenLong[client], g_HistTotalDamageDone[client], g_HistTotalDamageTaken[client]);
  163. }
  164. else {
  165. PrintToChat(client, "\x04%t", "tagNoHist");
  166. }
  167.  
  168. return Plugin_Handled;
  169. }
  170. public Action:Command_DamageReport(client, args)
  171. {
  172. // Dont do anything if command comes from server
  173. if (client == 0) {
  174. return Plugin_Handled;
  175. }
  176.  
  177. // If you send in to few or to many arguments. Tell them to ask for help
  178. if (args != 1)
  179. {
  180. PrintToChat(client, "\x04%t","tagUsage");
  181. return Plugin_Handled;
  182. }
  183.  
  184. new String:option[20];
  185. GetCmdArg(1, option, sizeof(option));
  186.  
  187. if (strcmp(option, "on", false) == 0) {
  188. g_PlayerDROption[client][propOnOff] = DrON;
  189. PrintToChat(client, "\x04%t","tagDmgRepOn");
  190. }
  191. else if (strcmp(option, "off", false) == 0) {
  192. g_PlayerDROption[client][propOnOff] = DrOFF;
  193. PrintToChat(client, "\x04%t","tagDmgRepOff");
  194. }
  195. else if (strcmp(option, "popup", false) == 0) {
  196. g_PlayerDROption[client][propPopChat] = DrPop;
  197. PrintToChat(client, "\x04%t","tagDmgRepPop");
  198. }
  199. else if (strcmp(option, "chat", false) == 0) {
  200. g_PlayerDROption[client][propPopChat] = DrChat;
  201. PrintToChat(client, "\x04%t","tagDmgRepChat");
  202. }
  203. else if (strcmp(option, "status", false) == 0) {
  204. if(g_PlayerDROption[client][propOnOff] == DrON) {
  205. PrintToChat(client, "\x04%t","tagDmgRepOn");
  206. if(g_PlayerDROption[client][propPopChat] == DrPop) {
  207. PrintToChat(client, "\x04%t","tagDmgRepPop");
  208. }
  209. else {
  210. PrintToChat(client, "\x04%t","tagDmgRepChat");
  211. }
  212. }
  213. else {
  214. PrintToChat(client, "\x04%t","tagDmgRepOff");
  215. }
  216. }
  217. else {
  218. //new String:helpString1[200] = "/damage_report on (Turn it on) /damage_report off (Turn it off)\n";
  219. //new String:helpString2[200] = "/damage_report popup (It will show as a left menu) /damage_report chat (It will show up in the chat)";
  220. //new String:helpString3[200] = "/damage_report status (See current damage report settings)";
  221. //new String:helpString4[200] = "/last_damage_report or /ldr will display the last damage report that was shown to you";
  222. PrintToChat(client, "\x04%t", "tagHelpLine1");
  223. PrintToChat(client, "\x04%t", "tagHelpLine2");
  224. PrintToChat(client, "\x04%t", "tagHelpLine3");
  225. PrintToChat(client, "\x04%t", "tagHelpLine4");
  226. }
  227.  
  228. StoreSettingsForClient(client);
  229.  
  230. return Plugin_Handled;
  231. }
  232.  
  233.  
  234. // Save all settings on map end
  235. public OnMapEnd() {
  236. // Save user settings to a file
  237. KvRewind(KVSettings);
  238. KeyValuesToFile(KVSettings, g_filenameSettings);
  239.  
  240. clearAllDamageData();
  241. }
  242.  
  243. public OnMapStart() {
  244. g_maxClients = GetMaxClients();
  245.  
  246.  
  247. // Temp fix to for clearing menues on start
  248. for (new i=1; i<=g_maxClients; i++)
  249. {
  250. g_MenuCleared[i] = 0;
  251. }
  252. }
  253.  
  254. // Initializations to be done at the beginning of the round
  255. public EventRoundStart(Handle:event, const String:name[], bool:dontBroadcast)
  256. {
  257. clearAllDamageData();
  258. }
  259.  
  260.  
  261. // In this event we store how much damage attacker did to victim in one array
  262. // and how much damage victim took from attacker in another array
  263. public Event_PlayerHurt(Handle:event, const String:name[], bool:dontBroadcast)
  264. {
  265. new healthDmg = GetEventInt(event,"dmg_health");
  266. new hitgroup = GetEventInt(event, "hitgroup");
  267.  
  268. new victim_id = GetEventInt(event, "userid");
  269. new attacker_id = GetEventInt(event, "attacker");
  270.  
  271. new victim = GetClientOfUserId(victim_id);
  272. new attacker = GetClientOfUserId(attacker_id);
  273.  
  274. // Log damage taken to the vicitm and damage done to the attacker
  275. g_DamageDone[attacker][victim] += healthDmg;
  276. g_HitsDone[attacker][victim]++;
  277. g_HitboxDone[attacker][victim][hitgroup]++;
  278.  
  279. g_DamageTaken[victim][attacker] += healthDmg;
  280. g_HitsTaken[victim][attacker]++;
  281. g_HitboxTaken[victim][attacker][hitgroup]++;
  282. }
  283.  
  284.  
  285. // Upon player dead, check who is the victim and attacker and
  286. // Call up on the buildDamageString function
  287. public Event_PlayerDeath(Handle:event, const String:name[], bool:dontBroadcast)
  288. {
  289. new victim_id = GetEventInt(event, "userid");
  290. new attacker_id = GetEventInt(event, "attacker");
  291.  
  292. new victim = GetClientOfUserId(victim_id);
  293. new attacker = GetClientOfUserId(attacker_id);
  294.  
  295. g_KilledPlayer[attacker][victim]=1;
  296.  
  297. if ((g_PlayerDROption[victim][propOnOff] == DrON) && (!IsFakeClient(victim)) && IsClientInGame(victim)) {
  298. BuildDamageString(victim, attacker);
  299. }
  300. }
  301.  
  302. // Local Function where we loop through all attackers and victims for a client.
  303. // if any damage is taken or done a timer is called that will display a Panel with the info.
  304. BuildDamageString (in_victim, in_attacker) {
  305. new String:damageReport[512];
  306. new String:damageReportLong[600];
  307. new String:damageDone[512];
  308. new String:damageTaken[512];
  309. new String:damageDoneLong[512];
  310. new String:damageTakenLong[512];
  311. new String:killer[10];
  312. new String:xkiller[10];
  313. new String:killed[10];
  314. new String:xkilled[10];
  315. new totalDmgTaken, totalDmgDone;
  316. new String:g_HitboxName[MAXHITGROUPS+1][20];
  317. new String:temp[20];
  318.  
  319. new String:hitsTrans[20];
  320. new String:dmgTrans[20];
  321. new String:dmgDoneTrans[20];
  322. new String:dmgTakenTrans[20];
  323.  
  324. Format(hitsTrans, sizeof(hitsTrans), "%T", "tagHits", in_victim);
  325. Format(dmgTrans, sizeof(dmgTrans), "%T", "tagDmg", in_victim);
  326. Format(dmgDoneTrans, sizeof(dmgDoneTrans), "%T", "tagDmgDone", in_victim);
  327. Format(dmgTakenTrans, sizeof(dmgTakenTrans), "%T", "tagDmgTaken", in_victim);
  328.  
  329. Format(temp, sizeof(temp), "%T", "hbBody", in_victim);
  330. //strcopy(g_PlayerName[client], sizeof(g_PlayerName[]), clientName);
  331. g_HitboxName[0] = temp;
  332. Format(temp, sizeof(temp), "%T", "hbHead", in_victim);
  333. g_HitboxName[1] = temp;
  334. Format(temp, sizeof(temp), "%T", "hbChest", in_victim);
  335. g_HitboxName[2] = temp;
  336. Format(temp, sizeof(temp), "%T", "hbStomach", in_victim);
  337. g_HitboxName[3] = temp;
  338. Format(temp, sizeof(temp), "%T", "hbLeft_arm", in_victim);
  339. g_HitboxName[4] = temp;
  340. Format(temp, sizeof(temp), "%T", "hbRight_arm", in_victim);
  341. g_HitboxName[5] = temp;
  342. Format(temp, sizeof(temp), "%T", "hbLeft_leg", in_victim);
  343. g_HitboxName[6] = temp;
  344. Format(temp, sizeof(temp), "%T", "hbRight_leg", in_victim);
  345. g_HitboxName[7] = temp;
  346.  
  347.  
  348. // Loop through all damage where you inflicted damage
  349. for (new i=1; i<=g_maxClients; i++)
  350. {
  351. if(g_DamageDone[in_victim][i] >0)
  352. {
  353. if (g_KilledPlayer[in_victim][i] == 1) {
  354. Format(killed, sizeof(killed), " %T", "tagKilled", in_victim);
  355. xkilled="X ";
  356. }
  357. else {
  358. killed="";
  359. xkilled="--";
  360. }
  361.  
  362. Format(damageDone, sizeof(damageDone), "%s%s%s [%d %s, %d %s]%s\n", damageDone, xkilled, g_PlayerName[i], g_DamageDone[in_victim][i], dmgTrans, g_HitsDone[in_victim][i], hitsTrans, killed);
  363. Format(damageDoneLong, sizeof(damageDoneLong), "%s%s%s [%d %s, %d %s]%s\n", damageDoneLong, xkilled, g_PlayerName[i], g_DamageDone[in_victim][i], dmgTrans, g_HitsDone[in_victim][i], hitsTrans, killed);
  364. Format(damageDoneLong, sizeof(damageDoneLong), "%s ", damageDoneLong);
  365. totalDmgDone += g_DamageDone[in_victim][i];
  366. for(new j=0; j<=MAXHITGROUPS; j++) {
  367. if (g_HitboxDone[in_victim][i][j] > 0) {
  368. Format(damageDoneLong, sizeof(damageDoneLong), "%s%s:%d ", damageDoneLong, g_HitboxName[j], g_HitboxDone[in_victim][i][j]);
  369. }
  370. }
  371. Format(damageDoneLong, sizeof(damageDoneLong), "%s\n", damageDoneLong);
  372. }
  373. }
  374.  
  375. // If you did any damage, add it to the report
  376. if (strcmp(damageDone, "", false) != 0) {
  377. Format(damageReport, sizeof(damageReport), "%s\n%s", dmgDoneTrans, damageDone);
  378. Format(damageReportLong, sizeof(damageReportLong), "%s\n%s", dmgDoneTrans, damageDoneLong);
  379. }
  380.  
  381. // Loop through all damage where you took damage
  382. for (new i=1; i<=g_maxClients; i++)
  383. {
  384. if(g_DamageTaken[in_victim][i] >0)
  385. {
  386. if (i == in_attacker) {
  387. Format(killer, sizeof(killer), " %T", "tagKiller", in_victim);
  388. xkiller="X ";
  389. }
  390. else {
  391. killer="";
  392. xkiller="--";
  393. }
  394.  
  395. Format(damageTaken, sizeof(damageTaken), "%s%s%s [%d %s, %d %s]%s\n", damageTaken, xkiller, g_PlayerName[i], g_DamageTaken[in_victim][i], dmgTrans, g_HitsTaken[in_victim][i], hitsTrans, killer);
  396.  
  397. Format(damageTakenLong, sizeof(damageTakenLong), "%s%s%s [%d %s, %d %s]%s\n", damageTakenLong, xkiller, g_PlayerName[i], g_DamageTaken[in_victim][i], dmgTrans, g_HitsTaken[in_victim][i], hitsTrans, killer);
  398. Format(damageTakenLong, sizeof(damageTakenLong), "%s ", damageTakenLong);
  399. totalDmgTaken += g_DamageTaken[in_victim][i];
  400. for(new j=0; j<=MAXHITGROUPS; j++) {
  401. if (g_HitboxTaken[in_victim][i][j] > 0) {
  402. Format(damageTakenLong, sizeof(damageTakenLong), "%s%s:%d ", damageTakenLong, g_HitboxName[j], g_HitboxTaken[in_victim][i][j]);
  403. }
  404. }
  405. Format(damageTakenLong, sizeof(damageTakenLong), "%s\n", damageTakenLong);
  406. }
  407. }
  408.  
  409. // If you took any damage, add it to the report
  410. if (strcmp(damageTaken, "") != 0) {
  411. Format(damageReport, sizeof(damageReport), "%s%s\n%s", damageReport, dmgTakenTrans, damageTaken);
  412. Format(damageReportLong, sizeof(damageReportLong), "%s%s\n%s", damageReportLong, dmgTakenTrans, damageTakenLong);
  413. }
  414.  
  415. // If damageReport is not empy
  416. if (strcmp(damageReport, "") != 0) {
  417. // store values if players what to view the last stats shown
  418. g_HistDamageDone[in_victim] = damageDone;
  419. g_HistDamageDoneLong[in_victim] = damageDoneLong;
  420. g_HistTotalDamageDone[in_victim] = totalDmgDone;
  421.  
  422. g_HistDamageTaken[in_victim] = damageTaken;
  423. g_HistDamageTakenLong[in_victim] = damageTakenLong;
  424. g_HistTotalDamageTaken[in_victim] = totalDmgTaken;
  425.  
  426. DisplayDamageReport(in_victim, damageDone ,damageDoneLong ,damageTaken, damageTakenLong, totalDmgDone, totalDmgTaken);
  427. }
  428. }
  429.  
  430. DisplayDamageReport(in_victim, String:damageDone[512] ,String:damageDoneLong[512] ,String:damageTaken[512], String:damageTakenLong[512], totalDmgDone, totalDmgTaken) {
  431. if (g_PlayerDROption[in_victim][propPopChat] == DrPop) {
  432. // Display damage report to the dead vicitm
  433. new Handle:pack;
  434. CreateDataTimer(1.0,DisplayDamageReportMenu, pack, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE);
  435. WritePackCell(pack, in_victim);
  436. //LogToGame("%s", damageReport);
  437. if (strlen(damageTakenLong)+strlen(damageDoneLong)<512-30) {
  438. WritePackString(pack, damageDoneLong);
  439. WritePackString(pack, damageTakenLong);
  440. WritePackCell(pack, totalDmgDone);
  441. WritePackCell(pack, totalDmgTaken);
  442. }
  443. else {
  444. WritePackString(pack, damageDone);
  445. WritePackString(pack, damageTaken);
  446. WritePackCell(pack, totalDmgDone);
  447. WritePackCell(pack, totalDmgTaken);
  448. }
  449. }
  450. else {
  451. if (strcmp(damageDoneLong, "", false) != 0) {
  452. PrintToChat(in_victim, "\x04\n%t\n", "tagChatHeaderVictim", totalDmgDone);
  453. PrintToChat(in_victim, "\x04%s", damageDoneLong);
  454. }
  455. if (strcmp(damageTakenLong, "", false) != 0) {
  456. PrintToChat(in_victim, "\x04%t\n", "tagChatHeaderAttacker", totalDmgTaken);
  457. PrintToChat(in_victim, "\x04%s", damageTakenLong);
  458. }
  459. }
  460. }
  461.  
  462. // This is called by the timer.
  463. // It checks if a menu/panel already is displayed ... if so
  464. // let the timer try again after the delay, hoping the menu is closed
  465. public Action:DisplayDamageReportMenu(Handle:timer, Handle:pack) {
  466. new String:p_damageDone[512];
  467. new String:p_damageTaken[512];
  468. new String:victimItem[100];
  469. new String:attackerItem[100];
  470. new p_victim;
  471. new p_totalDmgDone;
  472. new p_totalDmgTaken;
  473.  
  474. ResetPack(pack);
  475. p_victim = ReadPackCell(pack);
  476. ReadPackString(pack, p_damageDone, sizeof(p_damageDone));
  477. ReadPackString(pack, p_damageTaken, sizeof(p_damageTaken));
  478. p_totalDmgDone = ReadPackCell(pack);
  479. p_totalDmgTaken = ReadPackCell(pack);
  480.  
  481. if (!IsClientInGame(p_victim)) {
  482. return Plugin_Stop;
  483. }
  484.  
  485.  
  486. if (GetClientMenu(p_victim)!=MenuSource_None) {
  487. return Plugin_Continue;
  488. }
  489.  
  490. new Handle:damageReportPanel = CreatePanel();
  491.  
  492. if (strcmp(p_damageDone, "") != 0) {
  493. //LogToGame("%s", p_damageReport);
  494.  
  495. Format(victimItem, sizeof(victimItem), "%T", "tagPopHeaderVictim", p_victim, p_totalDmgDone);
  496. DrawPanelItem(damageReportPanel, victimItem);
  497. DrawPanelText(damageReportPanel, p_damageDone);
  498. }
  499. if (strcmp(p_damageTaken, "") != 0) {
  500. //LogToGame("%s", p_damageReport);
  501. Format(attackerItem, sizeof(attackerItem), "%T", "tagPopHeaderAttacker", p_victim, p_totalDmgTaken);
  502. DrawPanelItem(damageReportPanel, attackerItem);
  503. DrawPanelText(damageReportPanel, p_damageTaken);
  504. }
  505. new String:exitTrans[20];
  506. new String:usageTrans[100];
  507. Format(exitTrans, sizeof(exitTrans), "%T", "tagPopExit", p_victim);
  508. Format(usageTrans, sizeof(usageTrans), "%T", "tagPopUsage", p_victim);
  509.  
  510. DrawPanelItem(damageReportPanel, exitTrans);
  511. DrawPanelText(damageReportPanel, usageTrans);
  512.  
  513. SendPanelToClient(damageReportPanel, p_victim, Handler_MyPanel, 8);
  514. CloseHandle(damageReportPanel);
  515. return Plugin_Stop;
  516. }
  517.  
  518.  
  519. // Display time timer will close my panel ... no need to handle anything
  520. // CloseHandle seems to be called when the timer for the panel runs out
  521. public Handler_MyPanel(Handle:menu, MenuAction:action, param1, param2) {
  522. }
  523.  
  524.  
  525. // Store the name of the player at time of spawn. If player disconnects before
  526. // round end, the name can still be displayed in the damage reports.
  527. public Event_PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast){
  528. new userid = GetEventInt(event,"userid");
  529. new client = GetClientOfUserId(userid);
  530. // Temp fix menu
  531. if (g_MenuCleared[client] == 0) {
  532. new Handle:TempPanel = CreatePanel();
  533. DrawPanelText(TempPanel, "DR Fix");
  534. SendPanelToClient(TempPanel, client, Handler_MyPanel, 1);
  535. g_MenuCleared[client] = 1;
  536. CloseHandle(TempPanel);
  537. }
  538. // Store Player names if they disconnect before round has ended
  539. new String:clientName[32];
  540. GetClientName(client, clientName, sizeof(clientName));
  541. strcopy(g_PlayerName[client], sizeof(g_PlayerName[]), clientName);
  542.  
  543. // This shows that there is something strange when you spawn for the first time.
  544. }
  545.  
  546. // Temp Fix
  547. public Event_PlayerDisconnect(Handle:event, const String:name[], bool:dontBroadcast){
  548. new userid = GetEventInt(event,"userid");
  549. new client = GetClientOfUserId(userid);
  550. g_MenuCleared[client] = 0;
  551.  
  552. g_HistDamageDone[client] = "";
  553. g_HistDamageDoneLong[client] = "";
  554. g_HistTotalDamageDone[client] = 0;
  555.  
  556. g_HistDamageTaken[client] = "";
  557. g_HistDamageTakenLong[client] = "";
  558. g_HistTotalDamageTaken[client] = 0;
  559. }
  560.  
  561. public Event_PlayerConnect(Handle:event, const String:name[], bool:dontBroadcast){
  562. new userid = GetEventInt(event,"userid");
  563. new client = GetClientOfUserId(userid);
  564. g_MenuCleared[client] = 0;
  565.  
  566. g_HistDamageDone[client] = "";
  567. g_HistDamageDoneLong[client] = "";
  568. g_HistTotalDamageDone[client] = 0;
  569.  
  570. g_HistDamageTaken[client] = "";
  571. g_HistDamageTakenLong[client] = "";
  572. g_HistTotalDamageTaken[client] = 0;
  573. }
  574.  
  575. public OnClientPostAdminCheck(client) {
  576. FindSettingsForClient(client);
  577. }
  578.  
  579. FindSettingsForClient(client) {
  580. new String:steamId[20];
  581. GetClientAuthString(client, steamId, 20);
  582.  
  583. KvRewind(KVSettings);
  584. if(KvJumpToKey(KVSettings, steamId))
  585. {
  586. g_PlayerDROption[client][propOnOff] = KvGetNum(KVSettings, "OnOff", g_defaultPropOnOff);
  587. g_PlayerDROption[client][propPopChat] = KvGetNum(KVSettings, "PopChat", g_defaultPropChatPop);
  588. } else {
  589. g_PlayerDROption[client][propOnOff] = g_defaultPropOnOff;
  590. g_PlayerDROption[client][propPopChat] = g_defaultPropChatPop;
  591. }
  592. KvRewind(KVSettings);
  593. }
  594.  
  595. StoreSettingsForClient(client) {
  596. new String:steamId[40];
  597. GetClientAuthString(client, steamId, 20);
  598.  
  599. if(StrContains(steamId, "steam", false) != -1) {
  600.  
  601. KvRewind(KVSettings);
  602. if ((g_PlayerDROption[client][propOnOff] == g_defaultPropOnOff) && (g_PlayerDROption[client][propPopChat] == g_defaultPropChatPop)) {
  603. if(KvJumpToKey(KVSettings, steamId))
  604. {
  605. KvDeleteThis(KVSettings);
  606. }
  607. }
  608. else {
  609. KvJumpToKey(KVSettings, steamId, true);
  610. KvSetNum(KVSettings, "OnOff", g_PlayerDROption[client][propOnOff]);
  611. KvSetNum(KVSettings, "PopChat", g_PlayerDROption[client][propPopChat]);
  612. }
  613. }
  614. }
  615.  
  616. // Check if there are any living players. If so, trigger a timer for them so they will see their damage report
  617. // Calculate who did max damage and display it as a hint.
  618. // clear global damage done/taken arrays
  619. public Event_RoundEnd (Handle:event, const String:name[], bool:dontBroadcast)
  620. {
  621. // Make sure that we have a normal round end
  622. // reason 16 is game commencing
  623. // other reasons are real round ends
  624. new reason = GetEventInt(event, "reason");
  625. if(reason == 16) {
  626. return;
  627. }
  628.  
  629. new damage, hits, mostDamage, mostDamagePlayer, mostHits, kills, mostKills, mostKillsPlayer;
  630.  
  631. // Display damage report to living players
  632. // -1 in the damage string will make sure noone will be shown as the (Killer)
  633. for (new i=1; i<=g_maxClients; i++)
  634. {
  635. if(IsClientInGame (i)) {
  636. if (IsClientConnected (i) && !IsFakeClient (i) && IsPlayerAlive (i)) {
  637. BuildDamageString(i, -1);
  638. }
  639. }
  640. }
  641.  
  642. // Finding out who did the most damage
  643. for (new i=1; i<=g_maxClients; i++)
  644. {
  645. damage = 0;
  646. hits = 0;
  647. for (new j=1; j<=g_maxClients; j++)
  648. {
  649. damage = damage + g_DamageDone[i][j];
  650. hits = hits + g_HitsDone[i][j];
  651. }
  652. if (damage > mostDamage) {
  653. mostDamage = damage;
  654. mostDamagePlayer = i;
  655. mostHits = hits;
  656. }
  657. }
  658.  
  659. mostKills = 0;
  660. for (new i=1; i<=g_maxClients; i++)
  661. {
  662. kills = 0;
  663. for (new j=1; j<=g_maxClients; j++)
  664. {
  665. kills = kills + g_KilledPlayer[i][j];
  666. }
  667. if (kills > mostKills) {
  668. mostKills = kills;
  669. mostKillsPlayer = i;
  670. }
  671. }
  672.  
  673. // Display to all the player that did the most damage this round
  674. for (new i=1; i<=g_maxClients; i++)
  675. {
  676. if(IsClientInGame (i)) {
  677. if (IsClientConnected (i) && !IsFakeClient (i) && IsPlayerAlive (i)) {
  678. if(mostDamage > 0) {
  679. PrintToChat(i, "\x04%t", "tagMostDmg", g_PlayerName[mostDamagePlayer], mostDamage, mostHits);
  680. }
  681. if(mostKills > 0) {
  682. PrintToChat(i, "\x04%t", "tagMostKills", g_PlayerName[mostKillsPlayer], mostKills);
  683. }
  684. }
  685. }
  686. }
  687. }
  688.  
  689. clearAllDamageData()
  690. {
  691. // Clear all logged damage
  692. for (new i=1; i<=g_maxClients; i++)
  693. {
  694. for (new j=1; j<=g_maxClients; j++)
  695. {
  696. g_DamageDone[i][j]=0;
  697. g_DamageTaken[i][j]=0;
  698. g_HitsDone[i][j]=0;
  699. g_HitsTaken[i][j]=0;
  700. g_KilledPlayer[i][j]=0;
  701. for (new k=0; k<=MAXHITGROUPS; k++)
  702. {
  703. g_HitboxDone[i][j][k]=0;
  704. g_HitboxTaken[i][j][k]=0;
  705. }
  706. }
  707. }
  708. }
  709.