using System; using System.Reflection; using Advanced_Combat_Tracker; using System.Windows.Forms; using System.Text.RegularExpressions; using System.Text; using System.Globalization; [assembly: AssemblyTitle("STO Parsing Plugin with raw damage")] [assembly: AssemblyDescription("A basic parser that reads the combat logs in Star Trek Online")] [assembly: AssemblyCopyright("Hilbert@mancom")] [assembly: AssemblyVersion("1.0.5.0")] /* Version History * 1.0.5.0 - 2012/04/17 * - resolved a problem with misses and pets * 1.0.4.3 - 2012/04/07 * - pet deaths' not counting anymore * 1.0.4.2 - 2012/03/24 * - pet deaths counting again, to measure level of pet spam in matches * 1.0.4.0 - 2011/12/17 * - Borg radiation proc was counting as 0 * 1.0.3.0 - 2011/11/27 * - pets' deaths were counting towards players' kills * 1.0.0.0 - 2011/10/?? * - initial version */ namespace Parsing_Plugin { public class STO_Parser : IActPluginV1 { private static string[] separatorLog = new string[] { "::", "," }; private static CultureInfo cultureLog = new CultureInfo("en-US"); private static CultureInfo cultureDisplay = new CultureInfo("de-DE"); Label lblStatus = null; public void InitPlugin(TabPage pluginScreenSpace, Label pluginStatusText) { // Setting this Regex will allow ACT to extract the character's name from the file name as the first capture group // when opening new log files. We'll say the log file name may look like "20080706-Player.log" ActGlobals.oFormActMain.LogPathHasCharName = false; // A windows file system filter to search updated log files with. ActGlobals.oFormActMain.LogFileFilter = "Combat*.log"; // If all log files are in a single folder, this isn't an issue. If log files are split into different folders, // enter the parent folder name here. This way ACT will monitor that base folder and all sub-folders for updated files. ActGlobals.oFormActMain.LogFileParentFolderName = "GameClient"; // Then to apply the settings and restart the log checking thread ActGlobals.oFormActMain.ResetCheckLogs(); // This is the absolute path of where you wish ACT generated macro exports to be put. I'll leave it up to you // to determine this path programatically. If left blank, ACT will attempt to find EQ2 by registry or log file parents. // ActGlobals.oFormActMain.GameMacroFolder = @"C:\Program Files\Game Company\Game Folder"; // Lets say that the log file time stamp is like: "[13:42:57]" // ACT needs to know the length of the timestamp and spacing at the beginning of the log line ActGlobals.oFormActMain.TimeStampLen = 19; // Remember to include spaces after the time stamp // Replace ACT's default DateTime parser with your own implementation matching your format ActGlobals.oFormActMain.GetDateTimeFromLog = new FormActMain.DateTimeLogParser(ParseDateTime); // This Regex is only used by a quick parsing method to find the current zone name based on a file position // If you do not define this correctly, the quick parser will fail and take a while to do so. // You still need to implement a zone change parser in your engine regardless of this // ActGlobals.oFormActMain.ZoneChangeRegex = new Regex(@"You have entered: (.+)\.", RegexOptions.Compiled); // All of your parsing engine will be based off of this event // You should not use Before/AfterCombatAction as you may enter infinite loops. AfterLogLineRead is okay, but not recommended ActGlobals.oFormActMain.BeforeLogLineRead += new LogLineEventDelegate(oFormActMain_BeforeLogLineRead); lblStatus = pluginStatusText; lblStatus.Text = "STO ACT plugin loaded"; } void oFormActMain_BeforeLogLineRead(bool isImport, LogLineEventArgs logInfo) { // Vorhandensein von :: als Zeichen für ein STO-Log nehmen if (!logInfo.logLine.Contains("::")) return; ActGlobals.oFormActMain.GlobalTimeSorter++; DateTime timestamp; string ownerDisplay; string ownerInternal; string sourceDisplay; string sourceInternal; string targetDisplay; string targetInternal; string eventDisplay; string eventInternal; string type; string flags; float magnitude; float magnitudeBase; // Konstruktor, der eine Logzeile splittet string[] split; split = logInfo.logLine.Split(separatorLog, StringSplitOptions.None); DateTime.TryParseExact(split[0], "yy:MM:dd:HH:mm:ss.f::", cultureDisplay, DateTimeStyles.AssumeLocal, out timestamp); ownerDisplay = split[1]; ownerInternal = split[2]; sourceDisplay = split[3]; sourceInternal = split[4]; targetDisplay = split[5]; targetInternal = split[6]; eventDisplay = split[7]; eventInternal = split[8]; type = split[9]; flags = split[10]; magnitude = float.Parse(split[11], cultureLog); magnitudeBase = float.Parse(split[12], cultureLog); if (ownerDisplay=="" || ownerDisplay=="*") {ownerDisplay = sourceDisplay; ownerInternal = sourceInternal;} //if (ownerInternal=="" || ownerInternal=="*") ownerInternal = sourceInternal; if (sourceDisplay=="" || sourceDisplay=="*") {sourceDisplay = ownerDisplay; sourceInternal = ownerInternal;} //if (sourceInternal == "" || sourceInternal == "*") sourceInternal = ownerInternal; if (targetDisplay == "" || targetDisplay == "*") {targetDisplay = sourceDisplay; targetInternal = sourceInternal;} //if (targetInternal == "" || targetInternal == "*") targetInternal = ownerInternal; //Falls kein Spieler, dann zu nichts machen if (!ownerInternal.Contains("@")) { ownerInternal = "[Pet Spam]"; ownerDisplay = "[Pet Spam]"; } if (!targetInternal.Contains("@")) { targetInternal = "[Pet Spam]"; targetDisplay = "[Pet Spam]"; } // Für Borg-Radiation-Proc korrigieren if (eventDisplay == "Chaotic Particle Stream" && magnitudeBase==0) magnitudeBase = magnitude; //Angriff bool critical = false; if (flags.Contains("Critical")) critical = true; int powerattack = (int)SwingTypeEnum.Melee; if (!sourceInternal.Contains("@")) powerattack = (int)SwingTypeEnum.NonMelee; if (magnitude >= 0 && !flags.Contains("Miss")) { //lblStatus.Text = magnitudeBase.ToString(); if (ActGlobals.oFormActMain.SetEncounter(logInfo.detectedTime, ownerDisplay, targetDisplay)) { ActGlobals.oFormActMain.AddCombatAction(powerattack, critical, "None", ownerDisplay, eventDisplay, (int)magnitudeBase, logInfo.detectedTime, ActGlobals.oFormActMain.GlobalTimeSorter, targetDisplay, type); //ActGlobals.oFormActMain.AddCombatAction(powerattack, critical, "None", ownerDisplay , eventDisplay, (int)magnitude, logInfo.detectedTime, ActGlobals.oFormActMain.GlobalTimeSorter, targetDisplay, type); } } else if (magnitude < 0 && magnitudeBase==0) // Heals haben base magnitude 0, und der eigene Shield Damage (der nur für einen selbst geloggt wird) hat negative base magnitude und wird somit hierdurch herausgefiltert { if (ActGlobals.oFormActMain.SetEncounter(logInfo.detectedTime, ownerDisplay, targetDisplay)) { ActGlobals.oFormActMain.AddCombatAction((int)SwingTypeEnum.Healing, critical, "None", ownerDisplay, eventDisplay, -(int)magnitude, logInfo.detectedTime, ActGlobals.oFormActMain.GlobalTimeSorter, targetDisplay, type); } } if (flags.Contains("Kill") && targetDisplay != "[Pet Spam]") ActGlobals.oFormActMain.AddCombatAction(powerattack, critical, "None", ownerDisplay, "Killing", Dnum.Death, logInfo.detectedTime, ActGlobals.oFormActMain.GlobalTimeSorter, targetDisplay, type); else if (flags.Contains("Miss")) ActGlobals.oFormActMain.AddCombatAction(powerattack, critical, "None", ownerDisplay, eventDisplay, new Dnum(Dnum.Miss, "miss"), logInfo.detectedTime, ActGlobals.oFormActMain.GlobalTimeSorter, targetDisplay, type); } private DateTime ParseDateTime(string FullLogLine) // Must match the DateTimeLogParser delegate signature { // lblStatus.Text = DateTime.ParseExact(FullLogLine.Substring(0, 19), "yy:MM:dd:HH:mm:ss.f", System.Globalization.CultureInfo.InvariantCulture).ToString(); return DateTime.ParseExact(FullLogLine.Substring(0, 19), "yy:MM:dd:HH:mm:ss.f", System.Globalization.CultureInfo.InvariantCulture); } public void DeInitPlugin() { ActGlobals.oFormActMain.BeforeLogLineRead -= oFormActMain_BeforeLogLineRead; lblStatus.Text = "STO ACT plugin unloaded"; } } }