/// <summary> /// ログファイルからログを取得する /// </summary> /// <param name="logfile"></param> /// <returns></returns> public static FFXIVLog[] GetLogsFromFile(string logfile) { byte[] buffer = File.ReadAllBytes(logfile); MemoryStream ms = new MemoryStream(buffer); BinaryReader br = new BinaryReader(ms); int lastCount = br.ReadInt32(); int currentCount = br.ReadInt32(); int length = currentCount - lastCount; FFXIVLog[] logs = new FFXIVLog[length]; int[] array = new int[length]; for (int i = 0; i < length; i++) { array[i] = br.ReadInt32(); } int lastptr =0; int j =0; foreach (int ptr in array) { byte[] data = br.ReadBytes(ptr - lastptr); logs[j++] = FFXIVLog.ParseSingleLog(data); lastptr = ptr; } return logs; }
/// <summary> /// ログファイルからログを取得する /// </summary> /// <param name="logfile"></param> /// <returns></returns> public static FFXIVLog[] GetLogsFromFile(string logfile) { byte[] buffer = File.ReadAllBytes(logfile); MemoryStream ms = new MemoryStream(buffer); BinaryReader br = new BinaryReader(ms); int lastCount = br.ReadInt32(); int currentCount = br.ReadInt32(); int length = currentCount - lastCount; FFXIVLog[] logs = new FFXIVLog[length]; int[] array = new int[length]; for (int i = 0; i < length; i++) { array[i] = br.ReadInt32(); } int lastptr = 0; int j = 0; foreach (int ptr in array) { byte[] data = br.ReadBytes(ptr - lastptr); logs[j++] = FFXIVLog.ParseSingleLog(data); lastptr = ptr; } return(logs); }
/// <summary> /// ログを取得する /// </summary> /// <param name="data"></param> /// <returns></returns> public static FFXIVLog[] Parse(byte[] data) { List <FFXIVLog> loglist = new List <FFXIVLog>(); foreach (byte[] _dat in ParseLogData(data)) { FFXIVLog log = ParseSingleLog(_dat); loglist.Add(log); } return(loglist.ToArray()); }
/// <summary> /// 内容からログを生成する /// </summary> /// <param name="totalseconds"></param> /// <param name="logtype"></param> /// <param name="actiontype"></param> /// <param name="logbody"></param> /// <returns></returns> public static FFXIVLog CreateLog(int totalseconds, int logtype, int actiontype, string logbody) { DateTime timestamp = StartDateTime.AddSeconds(totalseconds); FFXIVLog log = new FFXIVLog(); log.TotalSeconds = totalseconds; log.TimstampHexString = totalseconds.ToString("X").PadLeft(8, '0'); log.TimeStampServerTime = timestamp; log.LogTypeHexString = logtype.ToString("X").PadLeft(2, '0') + actiontype.ToString("X").PadLeft(2, '0'); log.LogBody = logbody; log.LogBodyReplaceTabCode = tabcodeRegex.Replace(log.LogBody, ""); //log.Raw = data; return(log); }
/// <summary> /// ログを追加する /// </summary> /// <param name="log"></param> public void AddLog(FFXIVLog log) { FFXIVLogDataSet.AnaylzedRow arow = ar.Add(log); //string myname = rep.GetMyName(); //if (myname == "") // return; //int My_TotalDmg = rep.GetTotalDamage(myname, 0); //int My_HitCount = rep.GetHitCount(myname, 0); //int My_MissCount = rep.GetMissCount(myname, 0); //double My_HitRate = (double)My_HitCount / (double)(My_HitCount + My_MissCount) * 100; //double My_Dps = rep.GetTotalDamage(myname, log.TotalSeconds - 60) / 60.0; //if (ar.ds.Anaylzed.Count > 2) //{ // TimeSpan span = (log.TimeStampServerTime - ar.ds.Anaylzed[0].ServerTime); // DateTime viewDateTime = new DateTime(1900, 1, 1, span.Hours, span.Minutes, span.Seconds); // LastTimeLabel.Text = viewDateTime.ToString("HH:mm:ss"); //} //TotalDmgLabel.Text = String.Format("total {0:#,0}", My_TotalDmg); //if (My_HitCount + My_MissCount > 0) //{ // HitLabel.Text = String.Format("hit {0:#,0}/{1:#,0} {2:0.0}%", My_HitCount, My_HitCount + My_MissCount, My_HitRate); //} //DpsLabel.Text = String.Format("dps {0:0.0}/sec", My_Dps); ////ログ形式で表示 //string a = CreateReport(arow); //if (a != "") //{ // fF14FastReportDataSet.Reportlog.AddReportlogRow(a); // //int cnt = listView1.Height / listView1.Items[0].Bounds.Height +1; // //while (listView1.Items.Count > cnt) // //{ // // listView1.Items.RemoveAt(0); // //} // //int index = Math.Max(0, listView1.Items.Count - cnt); // //listView1.EnsureVisible(listView1.Items.Count-1); // if (!OnMouse) // { // // dataGridView1. // dataGridView1.FirstDisplayedScrollingRowIndex = dataGridView1.Rows.Count - 1; // } //} Write(); }
/// <summary> /// /// </summary> /// <param name="data"></param> /// <returns></returns> public static FFXIVLog ParseSingleLog(byte[] data) { string str = GetFF14String(data); int secs = Convert.ToInt32(str.Substring(0, 8), 16); DateTime timestamp = StartDateTime.AddSeconds(secs); FFXIVLog log = new FFXIVLog(); log.TotalSeconds = secs; log.TimstampHexString = str.Substring(0, 8); log.TimeStampServerTime = timestamp; log.LogTypeHexString = str.Substring(8, 4); log.LogBody = str.Substring(13); log.LogBodyReplaceTabCode = tabcodeRegex.Replace(log.LogBody, ""); log.Raw = data; return(log); }
/// <summary> /// ログを反復して読み込みます /// </summary> private void ReadThread() { while (Enable) { try { if (ffxivLogMemoryInfo == null) {//ログ位置のサーチから ffxivLogMemoryInfo = FFXIVLogMemoryInfo.Create(); continue; } byte[][] newlogsdata = ffxivLogMemoryInfo.GetNewLogsData(); FFXIVLog[] newLogs = new FFXIVLog[newlogsdata.Length]; for (int i = 0; i < newLogs.Length; i++) { newLogs[i] = FFXIVLog.ParseSingleLog(newlogsdata[i]); } LogEventArgs e = new LogEventArgs(); e.IsSuccess = true; e.LogCount = newLogs.Length; e.NewLogsData = newlogsdata; e.NewLogs = newLogs; if (LogEvent != null) { LogEvent(this, e); } System.Threading.Thread.Sleep((int)(LogReadIntervalSec * 1000)); } catch { LogEventArgs e = new LogEventArgs(); e.IsSuccess = false; if (LogEvent != null) { LogEvent(this, e); } System.Threading.Thread.Sleep((int)(RetryIntervalSec * 1000)); } } }
/// <summary> /// ペット名なら頭に"MY","PT"等をつける /// </summary> /// <param name="baseName"></param> /// <param name="log"></param> /// <returns></returns> private string NameConvertTo(FFXIVLog log, string baseName) { if (baseName.StartsWith("カーバンクル") || baseName.StartsWith("イフリート・エギ") || baseName.StartsWith("タイタン・エギ") || baseName.StartsWith("ガルーダ・エギ") || baseName.StartsWith("フェアリー・エオス") || baseName.StartsWith("フェアリー・セレネ")) { if (log.TO == LOG_CATEGORY_TO.EMPTY_OR_ME) { return baseName + "(MY)"; } else if (log.TO == LOG_CATEGORY_TO.PTMEMBER) { return baseName + "(PT)"; } else if (log.TO == LOG_CATEGORY_TO.ENEMY) { return baseName + "(EN)"; } return baseName + "(OTHER)"; } return baseName; }
/// <summary> /// ダメージ系のアナライズ /// </summary> /// <param name="arow"></param> /// <param name="log"></param> private void HitAnalyze(FFXIVLogDataSet.AnaylzedRow arow, FFXIVLog log) { //敵視UPの場合 if (log.LogBodyReplaceTabCode.Contains("敵視をアップ")) { Regex HateRegex = new Regex(@": ⇒ (?<to>.+)の敵視をアップ。"); Match match = HateRegex.Match(log.LogBodyReplaceTabCode.Replace("{022705CF01010103}", "").Replace("{0227050101010103}", ""));// System.Diagnostics.Debug.Write(log.LogBody); arow.To = NameConvertTo(log,match.Groups["to"].Value); arow.IsDamage = true; arow.IsHate = true; SearchAction(arow, log); return; } else { Regex HitRegex = new Regex(@":(\s|(?<from>.+)の(?<action>攻撃))\s⇒\s(|(?<crit>クリティカル!)\s)(?<to>[^!]+)[はに](|(?<dodge>[^\d\s]*)\s)(?<dmg>\d+)(|\((?<bonus>[+-]\d+)\%\))ダメージ"); arow.IsDamage = true;//ダメージタイプである arow.IsHP = true;//HPに影響する Match match = HitRegex.Match(log.LogBodyReplaceTabCode.Replace("{022705CF01010103}", "").Replace("{0227050101010103}", "")); //System.Diagnostics.Debug.Write(log.LogBody); arow.From = NameConvertFrom(log,match.Groups["from"].Value); arow.To = NameConvertTo(log,match.Groups["to"].Value); arow.ActionName = match.Groups["action"].Value; if (match.Groups["dmg"].Value != "") { arow.Numeric = Convert.ToInt32(match.Groups["dmg"].Value,10); } arow.IsCritical = match.Groups["crit"].Value != ""; if (match.Groups["bonus"].Value != "") { arow.BonusRate = Convert.ToInt32(match.Groups["bonus"].Value); } if (match.Groups["dodge"].Value.Contains("ブロック")) { arow.IsBlock = true; } if (match.Groups["dodge"].Value.Contains("受け流し")) { arow.IsParry = true; } } if (arow.From == "") { SearchAction(arow, log); } if (arow.IsFromNull()) arow.From = FF14LogParser.UnknownName; if (arow.IsActionNameNull()) arow.ActionName = FF14LogParser.UnknownName; //int damage = Convert.ToInt32(match.Groups["damage"].Value,10); //int bonus = Convert.ToInt32(match.Groups["bonus"].Value,10); //string to = match.Groups["to"].Value; }
/// <summary> /// 実行した中断したの分析 /// </summary> /// <param name="arow"></param> /// <param name="log"></param> private void ActionStartDoneAnalyze(FFXIVLogDataSet.AnaylzedRow arow, FFXIVLog log) { Regex ActionRegex = new Regex(@":(ターゲットが範囲外のため、|)(?<from>[^:\s⇒].+)[はの]「(?<action>[^」]+)」"); string _logstring = log.LogBodyReplaceTabCode; Match match = ActionRegex.Match(_logstring); arow.ActionName = match.Groups["action"].Value; if (log.LogBodyReplaceTabCode.Contains("中断した")) { arow.IsInterrupted = true; } else if (log.LogBodyReplaceTabCode.Contains("中断された")) { arow.IsInterrupted = true; } else if (log.LogBodyReplaceTabCode.Contains("の構え") || log.LogBodyReplaceTabCode.Contains("を唱えた")) { arow.IsStarted = true; } else { arow.IsDone = true; } arow.ActionName= match.Groups["action"].Value; arow.From = NameConvertFrom(log,match.Groups["from"].Value); }
/// <summary> /// ミス解析 /// </summary> /// <param name="arow"></param> /// <param name="log"></param> private void DodgeAnalyze(FFXIVLogDataSet.AnaylzedRow arow, FFXIVLog log) { Regex dodgeRegex = new Regex(@":(\s|(?<from>.+)の(?<action>攻撃))\s⇒\s(?<to>.+)にミス|: ⇒ (?<to>.+)は「(?<action>[^」]+)」をレジストした。|: ⇒ (?<to>.+)に効果なし。|: ⇒ (?<to>.+)はレジストした!"); arow.IsDodge = true; string _logstring = log.LogBodyReplaceTabCode; Match match = dodgeRegex.Match(_logstring); arow.ActionName = match.Groups["action"].Value; arow.To =NameConvertTo(log, match.Groups["to"].Value); //System.Diagnostics.Debug.Assert(arow.To != ""); arow.From =NameConvertFrom(log, match.Groups["from"].Value); if (arow.From == "") { SearchAction(arow, log); } }
private void SearchAction(FFXIVLogDataSet.AnaylzedRow arow, FFXIVLog log) { List<string> bodyList = new List<string>(); bodyList.Add(log.LogBodyReplaceTabCode); List<int> parentLogtypes = new List<int>(GetParentActionLogTypes(arow)); if (parentLogtypes.Count == 0) { return; } for (int i = ds.Anaylzed.Count - 2; i >= 0; i--) { FFXIVLogDataSet.AnaylzedRow ActionRow = ds.Anaylzed[i]; bodyList.Insert(0, ActionRow.Body); int minLogType = (int)log.LogType / 4 * 4; if(parentLogtypes.Contains(ActionRow.LogType) && (ActionRow.ActionType == 0xAB || ActionRow.ActionType == 0x2B)) { arow.ActionName = ds.Anaylzed[i].ActionName; arow.From = ds.Anaylzed[i].From; ActionRow.To = arow.To; break; } else if (ActionRow.TotalSeconds < log.TotalSeconds - 1)//2秒猶予 { arow.ActionName = FF14LogParser.UnknownName; arow.From = FF14LogParser.UnknownName; break; } } }
/// <summary> /// コンテンツの開始終了 /// </summary> /// <param name="arow"></param> /// <param name="log"></param> private void ContentStartEnd(FFXIVLogDataSet.AnaylzedRow arow, FFXIVLog log) { string _logstring = log.LogBodyReplaceTabCode; Regex contentStartRegex = new Regex(@":「(?<content>.+)」の攻略を開始した。"); Match match = contentStartRegex.Match(_logstring); if (match.Success) { arow.IsContentStart = true; arow.ContentName = match.Groups["content"].Value; ds.ContentRegion.AddContentRegionRow(arow.ID, -1, arow.ContentName, true, false); } Regex contentEndRegex = new Regex(@":[^「]*?「(?<content>.+)」の攻略を終了した。"); match = contentEndRegex.Match(_logstring); if (match.Success) { arow.IsContentEnd = true; arow.ContentName = match.Groups["content"].Value; FFXIVLogDataSet.ContentRegionRow[]rows= (FFXIVLogDataSet.ContentRegionRow[]) ds.ContentRegion.Select(String.Format("ContentName = '{0}'",arow.ContentName.Replace("'","''"))); if (rows.Length > 0) { rows[rows.Length - 1].EndLogID = arow.ID; } } //:「(?<content>.+)」の攻略を開始した。 }
/// <summary> /// ログを追加する /// </summary> /// <param name="log"></param> public void AddLog(FFXIVLog log) { report.Add(log); lastDateTime = log.TimeStampServerTime.ToLocalTime(); if (ViewLog) { LogTextLabel.Text = String.Format("[{0}]{1}", log.TimeStampServerTime.AddHours(9.0).ToString("HH:mm:ss"), log.LogBodyReplaceTabCode); } else if(LogTextLabel.Text !="") { LogTextLabel.Text = ""; } }
/// <summary> /// タブコードをエスケープしたデータを取得します。 /// </summary> /// <returns></returns> public byte[] EscapeTabcode() { return(FFXIVLog.EscapeTabData(Raw)); }
/// <summary> /// 表示するログか /// </summary> /// <param name="log"></param> /// <returns></returns> private bool IsVisibleLog(FFXIVLog log) { if (log.LogTypeHexString == "0018" && FCBox.Checked)//fc { return true; } else if (log.LogTypeHexString == "000B" && ShoutBox.Checked)//shout { return true; } else if (log.LogTypeHexString == "000C" && YellBox.Checked)//yell { return true; } else if (log.LogTypeHexString == "000E" && PartyBox.Checked)//Party { return true; } else if (log.LogTypeHexString == "000B" && ShoutBox.Checked)//shout { return true; } else if (log.LogTypeHexString == "0010" && LS1Box.Checked) //LS1 { return true; } else if (log.LogTypeHexString == "0011" && LS2Box.Checked) //LS2 { return true; } else if (log.LogTypeHexString == "0012" && LS3Box.Checked) //LS3 { return true; } else if (log.LogTypeHexString == "0013" && LS4Box.Checked) //LS4 { return true; } else if (log.LogTypeHexString == "0014" && LS5Box.Checked) //LS5 { return true; } else if (log.LogTypeHexString == "0015" && LS6Box.Checked) //LS6 { return true; } else if (log.LogTypeHexString == "0016" && LS7Box.Checked) //LS7 { return true; } else if (log.LogTypeHexString == "0017" && LS8Box.Checked) //LS8 { return true; } return false; }
/// <summary> /// 内容からログを生成する /// </summary> /// <param name="totalseconds"></param> /// <param name="logtype"></param> /// <param name="actiontype"></param> /// <param name="logbody"></param> /// <returns></returns> public static FFXIVLog CreateLog(int totalseconds,int logtype, int actiontype,string logbody) { DateTime timestamp = StartDateTime.AddSeconds(totalseconds); FFXIVLog log = new FFXIVLog(); log.TotalSeconds = totalseconds; log.TimstampHexString = totalseconds.ToString("X").PadLeft(8,'0'); log.TimeStampServerTime = timestamp; log.LogTypeHexString = logtype.ToString("X").PadLeft(2, '0') + actiontype.ToString("X").PadLeft(2, '0'); log.LogBody = logbody; log.LogBodyReplaceTabCode = tabcodeRegex.Replace(log.LogBody, ""); //log.Raw = data; return log; }
/// <summary> /// /// </summary> /// <param name="data"></param> /// <returns></returns> public static FFXIVLog ParseSingleLog(byte[] data) { string str = GetFF14String(data); int secs = Convert.ToInt32(str.Substring(0, 8),16); DateTime timestamp = StartDateTime.AddSeconds(secs); FFXIVLog log = new FFXIVLog(); log.TotalSeconds = secs; log.TimstampHexString = str.Substring(0, 8); log.TimeStampServerTime = timestamp; log.LogTypeHexString = str.Substring(8, 4); log.LogBody = str.Substring(13); log.LogBodyReplaceTabCode = tabcodeRegex.Replace(log.LogBody, ""); log.Raw = data; return log; }
/// <summary> /// ログの種類からログカラーを取得します /// </summary> /// <param name="log"></param> /// <returns></returns> private Color GetColorFromLog(FFXIVLog log) { if (log.LogTypeHexString == "0018")//fc { return Color.LightGreen; } else if (log.LogTypeHexString =="000B")//shout { return Color.DarkOrange; } else if (log.LogTypeHexString == "000C")//yell { return Color.Orange; } else if (log.LogTypeHexString == "000E")//Party { return Color.LightSeaGreen; } else if (log.LogTypeHexString == "0010" || //LS log.LogTypeHexString == "0011" || log.LogTypeHexString == "0012" || log.LogTypeHexString == "0013" || log.LogTypeHexString == "0014" || log.LogTypeHexString == "0015" || log.LogTypeHexString == "0016" || log.LogTypeHexString == "0017") { return Color.Green; } //デフォルトはホワイトスモーク return Color.WhiteSmoke; }
/// <summary> /// ログを追加する /// </summary>d /// <param name="log"></param> /// <returns></returns> public FFXIVLogDataSet.AnaylzedRow Add(FFXIVLog log) { FFXIVLogDataSet.AnaylzedRow arow = ds.Anaylzed.NewAnaylzedRow(); arow.Body = log.LogBodyReplaceTabCode; arow.TotalSeconds = log.TotalSeconds; arow.ServerTime = log.TimeStampServerTime; arow.LocalTime = log.TimeStampServerTime.AddHours(9); arow.ActionType = log.ActionType; arow.LogType = log.LogType; arow.FLAG_WHO = log.LogType / 4; arow.FLAG_TO = log.LogType & 3; arow.FLAG_FIGHT = log.ActionType / 128; arow.FLAG_INFO = log.ActionType / 16; arow.FLAG_UNKNOWN = log.ActionType / 4; arow.FLAG_NUM = log.ActionType & 7; ds.Anaylzed.AddAnaylzedRow(arow); if (log.WHO != LOG_CATEGORY_WHO.SYSTEM && log.LOG_TYPE == LOG_CATEGORY_TYPE.BATTLE) { if (log.BATTLE_TYPE == LOG_BATTLE_TYPE.HIT)// log.ActionType == 0xA9 || log.ActionType == 0x29)//A9と29があるのはなぜだろう { HitAnalyze(arow, log); } else if (log.BATTLE_TYPE == LOG_BATTLE_TYPE.DONE)// log.ActionType == 0x2B||log.ActionType == 0xAB) { ActionStartDoneAnalyze(arow, log); } else if (log.BATTLE_TYPE == LOG_BATTLE_TYPE.MISS)// log.ActionType == 0xAA||log.ActionType==0x2A)//AAと2Aがある { DodgeAnalyze(arow, log); } else if (log.BATTLE_TYPE == LOG_BATTLE_TYPE.EFFECT1 || log.BATTLE_TYPE == LOG_BATTLE_TYPE.EFFECT2)// log.ActionType == 0xAE || log.ActionType == 0x2E)//ON OFFが表示される効果 { EffectAnalyze(arow, log); } else if (log.BATTLE_TYPE == LOG_BATTLE_TYPE.HEAL)//log.ActionType == 0xAD || log.ActionType == 0x2D) { CureAnalyze(arow, log); } } else if (log.LOG_TYPE == LOG_CATEGORY_TYPE.GAME_EVENT) { if (log.GAME_EVENT_TYPE == LOG_GAME_EVENT_TYPE.DOWN_KO)//log.ActionType == 0xBA || log.ActionType == 0x3A) {//倒されたとき KOAnaylyze(arow, log); if (arow.IsKO) { CloseDot(arow.To, arow, false);//ひとつ閉じる FFXIVLogDataSet.ActorRow acrow = ds.Actor.FindByName(arow.To); if (acrow != null) { arow.EnemyGroupID = acrow.GroupCount; } } } else if (log.GAME_EVENT_TYPE == LOG_GAME_EVENT_TYPE.EVENT)// log.ActionType == 0x39) {//コンテンツの開始等 ContentStartEnd(arow, log); LevelSyncStartEnd(arow, log); if (log.LogBodyReplaceTabCode.Contains("チェンジ")) {//ジョブチェンジ Regex regex = new Regex(@":(?<name>[A-Z][a-z']+? [A-Z][a-z']+?)は「(?<jobclass>\w+?)」にチェンジした。");// :Choco Ponは「白魔道士」にチェンジした。 Match match = regex.Match(log.LogBodyReplaceTabCode); if (match.Success) { string name = match.Groups["name"].Value; string jobclass = match.Groups["jobclass"].Value; FFXIVLogDataSet.ActorRow actor = ds.Actor.FindByName(name); if (actor != null) { actor.ClassJob = jobclass; } } } } } //TO と FROM FFXIVLogDataSet.ActorRow acrow_from = null; FFXIVLogDataSet.ActorRow acrow_to = null; if (!arow.IsToNull() && arow.To != "" && arow.To != FF14LogParser.UnknownName) {//Toに名前が入っていれば acrow_to = ds.Actor.FindByName(arow.To); bool need = false; if (acrow_to == null) { need = true; acrow_to = ds.Actor.NewActorRow(); acrow_to.Name = arow.To; acrow_to.FirstLogID = arow.ID; acrow_to.LastLogID = arow.ID; acrow_to.LastSeconds = arow.TotalSeconds; acrow_to.GroupCount = 1; ds.Actor.AddActorRow(acrow_to); } else { need = false; if (arow.TotalSeconds - acrow_to.LastSeconds > 60) {//最後にみてから60秒以上経過していれば、更新する //DOT閉じる CloseDot(arow.To, arow, true); acrow_to.GroupCount++;//名前が同じだが、別グループである need = true; } acrow_to.LastLogID = arow.ID; acrow_to.LastSeconds = arow.TotalSeconds; arow.EnemyGroupID = acrow_to.GroupCount; } //Toのカテゴリわけ //Actorを更新する if (need)// FFXIVLog.GetBATTLE_TYPE(arow.ac (arow.ActionType == 0x2B || arow.ActionType == 0xAB)) { acrow_to.IsMe = false; acrow_to.IsMyPet = false; acrow_to.IsPTMember = false; acrow_to.IsPTPet = false; acrow_to.IsNPC = false; acrow_to.IsAllianceMember = false; if (arow.FLAG_TO == (int)LOG_CATEGORY_TO.EMPTY_OR_ME) {//ME int ptype = GetPlayerTypeFromName(acrow_to.Name); if (ptype == 0) { acrow_to.IsMe = true; } else if (ptype == 1) { acrow_to.IsMyPet = true; } else { acrow_to.IsNPC = true; } } else if (arow.FLAG_TO == (int)LOG_CATEGORY_TO.PTMEMBER) {//PT int ptype = GetPlayerTypeFromName(acrow_to.Name); if (ptype == 0) { acrow_to.IsPTMember = true; } else if (ptype == 1) { acrow_to.IsPTPet = true; } else { acrow_to.IsNPC = true; } } else if (arow.FLAG_TO == (int)LOG_CATEGORY_TO.ENEMY) { int ptype = GetPlayerTypeFromName(acrow_to.Name); if (ptype == 0) { acrow_to.IsOther = true; } else if (ptype == 1) { acrow_to.IsOther = true; } else { acrow_to.IsNPC = true; } } else if (arow.FLAG_TO == (int)LOG_CATEGORY_TO.OTHER) { int ptype = GetPlayerTypeFromName(acrow_to.Name); if (ptype == 0 || ptype == 1) { acrow_to.IsOther = true; } else { acrow_to.IsNPC = true; } } else { } } }//TOの処理END if (!arow.IsFromNull() && arow.From != "" && arow.From != FF14LogParser.UnknownName) {//Fromに名前が入っていれば //bool need = false; acrow_from = ds.Actor.FindByName(arow.From); if (acrow_from == null) { // need = true; acrow_from = ds.Actor.NewActorRow(); acrow_from.Name = arow.From; acrow_from.FirstLogID = arow.ID; acrow_from.LastLogID = arow.ID; acrow_from.LastSeconds = arow.TotalSeconds; acrow_from.GroupCount = 1; ds.Actor.AddActorRow(acrow_from); } else { // need = false; if (arow.TotalSeconds - acrow_from.LastSeconds > 60) {//最後にみてから60秒以上経過していれば、更新する //DOT閉じる CloseDot(arow.From, arow, true); acrow_from.GroupCount++;//名前が同じだが、別グループである // need = true; } acrow_from.LastLogID = arow.ID; acrow_from.LastSeconds = arow.TotalSeconds; arow.EnemyGroupID = acrow_from.GroupCount; } //DOTのDamageBaseを設定する FFXIVLogDataSet.ActionRow action = null; if (!arow.IsNumericNull() && arow.ActionName != "攻撃") { action = ds.Action.FindByName(arow.ActionName); if (action != null && action.DD威力 > 0) { if (action.Name != "サンダガ" && action.Name != "ファイア" && action.Name != "ファイラ" && action.Name != "ファイガ" && action.Name != "フレア" && action.Name !="インパルスドライブ") { double bai = 1.0; if (arow.IsCritical) { bai = 1.5; } if (arow.BonusRate > 0) { bai = (100 + arow.BonusRate) / 100.0; } acrow_from.DamageBase = (double)arow.Numeric / bai / action.DD威力; } } } //Actorを更新する if (true)//(need)// FFXIVLog.GetBATTLE_TYPE(arow.ac (arow.ActionType == 0x2B || arow.ActionType == 0xAB)) { acrow_from.IsMe = false; acrow_from.IsMyPet = false; acrow_from.IsPTMember = false; acrow_from.IsPTPet = false; acrow_from.IsNPC = false; acrow_from.IsAllianceMember = false; if (arow.LogType >= 0x04 && arow.LogType <= 0x07) {//ME int ptype = GetPlayerTypeFromName(acrow_from.Name); if (ptype == 0) { acrow_from.IsMe = true; } else if (ptype == 1) { acrow_from.IsMyPet = true; } else { acrow_from.IsNPC = true; } } else if (arow.LogType >= 0x08 && arow.LogType <= 0x0B) {//PT int ptype = GetPlayerTypeFromName(acrow_from.Name); if (ptype == 0) { acrow_from.IsPTMember = true; } else if (ptype == 1) { acrow_from.IsPTPet = true; } else { acrow_from.IsNPC = true; } } else if (arow.LogType >= 0x0C && arow.LogType <= 0x0F) {//Ally int ptype = GetPlayerTypeFromName(acrow_from.Name); if (ptype == 0 || ptype == 1) { acrow_from.IsAllianceMember = true; } else { } } else if (arow.LogType >= 0x10 && arow.LogType <= 0x13) { int ptype = GetPlayerTypeFromName(acrow_from.Name); if (ptype == 0) { acrow_from.IsOther = true; } else if (ptype == 1) { acrow_from.IsOther = true; } else { } } else if (arow.LogType >= 0x14) { int ptype = GetPlayerTypeFromName(acrow_from.Name); if (ptype == 0 || ptype == 1) { acrow_from.IsOther = true; } else { acrow_from.IsNPC = true; } } else { } if (action != null && (acrow_from.IsMe || acrow_from.IsPTMember || acrow_from.IsOther)) {//クラス・ジョブの設定 if (acrow_from.IsClassJobNull()) { acrow_from.ClassJob = action.Class; } else { List<string> classes = new List<string>(action.Class.Split(new char[] { ' ' })); List<string> forecast_classes = new List<string>(acrow_from.ClassJob.Split(new char[] { ' ' })); List<string> new_classes = new List<string>(); foreach (string cls in forecast_classes) { if (classes.Contains(cls)) { new_classes.Add(cls); } } if (new_classes.Count > 0) { acrow_from.ClassJob = String.Join(" ", new_classes.ToArray()); } else { acrow_from.ClassJob = action.Class; } } } } } //if ((acrow_from!=null&&acrow_from.Name.Contains("カーバンクル")) && (acrow_to!=null && acrow_to.Name == "オチュー")) //{ //} //FROMの処理END //EnemyGroup処理 自分・味方から⇒敵に攻撃 if (((acrow_from != null && acrow_from.Name != FF14LogParser.UnknownName) && (acrow_to != null && acrow_to.Name != FF14LogParser.UnknownName)) && (acrow_from.IsMe || acrow_from.IsMyPet || acrow_from.IsPTMember || acrow_from.IsPTPet)) { if (!arow.IsActionNameNull()) { FFXIVLogDataSet.ActionRow action = ds.Action.FindByName(arow.ActionName); if ((action != null && action.IsAttack && !arow.IsCure) || arow.ActionName == "攻撃") { FFXIVLogDataSet.EnemyGroupRow eg = ds.EnemyGroup.FindByName(acrow_to.Name); if (eg == null) { eg = ds.EnemyGroup.NewEnemyGroupRow(); eg.Name = acrow_to.Name; eg.FirstID = arow.ID; eg.FirstSeconds = arow.TotalSeconds; eg.LastID = arow.ID; eg.LastSeconds = arow.TotalSeconds; eg.KOCount = 0; eg.Count = 1; ds.EnemyGroup.AddEnemyGroupRow(eg); } else { if (eg.LastSeconds < arow.TotalSeconds - 60) { //Dotを閉じる CloseDot(eg.Name, arow, true); eg.FirstID = arow.ID; eg.FirstSeconds = arow.TotalSeconds; eg.LastID = arow.ID; eg.LastSeconds = arow.TotalSeconds; eg.KOCount = 0; eg.Count = 1; } else if (arow.FLAG_TO == (int)LOG_CATEGORY_TO.OTHER) { eg.LastID = arow.ID; eg.LastSeconds = arow.TotalSeconds; eg.Count++; } else { eg.LastID = arow.ID; eg.LastSeconds = arow.TotalSeconds; } } } } } //EnemyGroup処理 敵⇒自分味方への攻撃 if (((acrow_from != null && acrow_from.Name != FF14LogParser.UnknownName) && (acrow_to != null && acrow_to.Name != FF14LogParser.UnknownName)) && (acrow_to.IsMe || acrow_to.IsMyPet || acrow_to.IsPTMember || acrow_to.IsPTPet)) { if (arow.FLAG_WHO == (int)LOG_CATEGORY_WHO.NPC) { FFXIVLogDataSet.EnemyGroupRow eg = ds.EnemyGroup.FindByName(acrow_from.Name); if (eg == null) { eg = ds.EnemyGroup.NewEnemyGroupRow(); eg.Name = acrow_from.Name; eg.FirstID = arow.ID; eg.FirstSeconds = arow.TotalSeconds; eg.LastID = arow.ID; eg.LastSeconds = arow.TotalSeconds; eg.KOCount = 0; eg.Count = 1; ds.EnemyGroup.AddEnemyGroupRow(eg); } else { if (eg.LastSeconds < arow.TotalSeconds - 60) { //Dotを閉じる CloseDot(eg.Name, arow, true); eg.FirstID = arow.ID; eg.FirstSeconds = arow.TotalSeconds; eg.LastID = arow.ID; eg.LastSeconds = arow.TotalSeconds; eg.KOCount = 0; eg.Count = 1; } else if (arow.FLAG_WHO == (int)LOG_CATEGORY_WHO.NPC) { eg.LastID = arow.ID; eg.LastSeconds = arow.TotalSeconds; eg.Count++; } else { eg.LastID = arow.ID; eg.LastSeconds = arow.TotalSeconds; } } } } //DOTをとじる for (int i = DotRowList.Count-1; i >=0 ; i--) { if ( DotRowList[i].IsDamageBaseNull() || DotRowList[i].DamageBase==0) { FFXIVLogDataSet.ActorRow actor = ds.Actor.FindByName(DotRowList[i].From); if (actor != null &&!actor.IsDamageBaseNull()&& actor.DamageBase>0) { DotRowList[i].DamageBase = actor.DamageBase; } } else if (DotRowList[i].TotalSeconds + DotRowList[i].DotSecs <=arow.TotalSeconds) { DotRowList[i].DotEndSeconds = DotRowList[i].TotalSeconds + DotRowList[i].DotSecs; DotRowList.Remove(DotRowList[i]); } } return arow; }
private void CureAnalyze(FFXIVLogDataSet.AnaylzedRow arow, FFXIVLog log) { string _logstring = log.LogBodyReplaceTabCode; Regex actionStartRegex = new Regex(@":\s\s⇒\s(|(?<crit>クリティカル!)\s)(?<to>[^!]+)[は](|(?<dodge>[^\d\s]*)\s)(?<num>\d+)(|\((?<bonus>[+-]\d+)\%\))(?<hpmp>\w+)(回復|吸収)"); Match match = actionStartRegex.Match(_logstring); arow.IsCure = true; arow.To = NameConvertTo(log,match.Groups["to"].Value); arow.From = NameConvertFrom(log,match.Groups["from"].Value); arow.ActionName = match.Groups["action"].Value; if(match.Groups["num"].Value!="") { arow.Numeric = Convert.ToInt32(match.Groups["num"].Value, 10); } if (match.Groups["hpmp"].Value == "HP") { arow.IsHP = true; } else if (match.Groups["hpmp"].Value == "TP") { arow.IsTP = true; } else if (match.Groups["hpmp"].Value == "MP") { arow.IsMP = true; } if (match.Groups["crit"].Value != "") { arow.IsCritical = true; } if (arow.From == "") { if (!log.LogBodyReplaceTabCode.Contains("吸収")) { SearchAction(arow, log); } else { } } }
/// <summary> /// レベルシンクの開始と終了 /// </summary> /// <param name="arow"></param> /// <param name="log"></param> private void LevelSyncStartEnd(FFXIVLogDataSet.AnaylzedRow arow, FFXIVLog log) { string _logstring = log.LogBodyReplaceTabCode; Regex LevelSyncRegex = new Regex(@":レベル(?<level>\d+)にシンクされました。"); Match match = LevelSyncRegex.Match(_logstring); if (match.Success) { arow.SyncLevel = Convert.ToInt32(match.Groups["level"].Value, 10); arow.IsLevelSyncStart = true; } Regex LevelSyncEndRegex = new Regex(@":レベルシンクが解除されました。"); if (LevelSyncEndRegex.Match(_logstring).Success) { arow.IsLevelSyncEnd = true; } }
/// <summary> /// ログを追加する /// </summary> /// <param name="log"></param> public void Add(FFXIVLog log) { FFXIVLogDataSet.AnaylzedRow arow = ar.Add(log); }
/// <summary> /// 倒した倒された力尽きた /// </summary> /// <param name="arow"></param> /// <param name="log"></param> private void KOAnaylyze(FFXIVLogDataSet.AnaylzedRow arow, FFXIVLog log) { string _logstring = log.LogBodyReplaceTabCode; Regex koRegex = new Regex(@":(?<to>.+)は、力尽きた。|:(?<to>.+)は、(?<from>.+)に倒された。|:(?<from>.+)は、(?<to>.+)を倒した。"); Match match = koRegex.Match(_logstring); if (match.Success) { arow.IsKO = true; arow.To = NameConvertTo(log, match.Groups["to"].Value); arow.From = NameConvertFrom(log, match.Groups["from"].Value); FFXIVLogDataSet.EnemyGroupRow eg = ds.EnemyGroup.FindByName(arow.To); if (eg != null && (arow.FLAG_WHO == (int)LOG_CATEGORY_WHO.MYSELF || arow.FLAG_WHO == (int)LOG_CATEGORY_WHO.PTMEMBER)) { eg.KOCount ++; if (eg.KOCount > eg.Count) { eg.Count = eg.KOCount; } } } }
/// <summary> /// ログが追加された /// </summary> /// <param name="log"></param> private void LogAdded(FFXIVLog log) { rf.AddLog(log); //arf.AddLog(log); }
private void EffectAnalyze(FFXIVLogDataSet.AnaylzedRow arow, FFXIVLog log) { string _logstring = log.LogBodyReplaceTabCode; Regex buffRegex = new Regex(@": ⇒ (?<to>.+)に「(?<buff>[^」]+)」の(?<on>効果)。|(?<to>[^:\s⇒].+)の「(?<buff>[^」]+)」が(?<off>切れた)。"); Match match = buffRegex.Match(_logstring); if (match.Groups["on"].Value != "") { arow.IsBuffOn = true; } else if (match.Groups["off"].Value != "") { arow.IsDebuffRemove = true; } arow.To = NameConvertTo(log,match.Groups["to"].Value); arow.From = NameConvertFrom(log,match.Groups["from"].Value); arow.BuffName = match.Groups["buff"].Value; if (arow.From == "") { SearchAction(arow, log); } if (arow.IsBuffOn && !arow.IsBuffNameNull()) { FFXIVLogDataSet.ActionRow action = null; if (arow.BuffName == "桜花狂咲") { action = ds.Action.FindByName("桜華狂咲"); } else { action = ds.Action.FindByName(arow.BuffName); } if (action != null) { SetDotSpace(arow); } } if (arow.IsBuffRemove && !arow.IsBuffNameNull()) { FFXIVLogDataSet.ActionRow action = ds.Action.FindByName(arow.BuffName); if (action ==null && arow.BuffName == "桜花狂咲") { action = ds.Action.FindByName("桜華狂咲"); } if (action != null) { CloseDot(arow.To, arow, false); } } }
/// <summary> /// ゲーム画面で表示される形に近いStringを取得する /// </summary> /// <param name="data"></param> /// <returns></returns> public static string GetFF14String(byte[] data) { byte[] a = new byte[] { 0xEE, 0x81, 0xAF };//EE81AFは3バイトの特殊文字 リプレースすることで表示可能 byte[] buff = FFXIVLog.EscapeTabData(data); return(Encoding.GetEncoding("utf-8").GetString(buff).Replace(Encoding.GetEncoding("utf-8").GetString(a), "⇒")); }
/// <summary> /// ログを1行追加する /// </summary> /// <param name="log"></param> private void AddLog(FFXIVLog log) { LogBodyBox.SelectionColor = GetColorFromLog(log); Font baseFont = LogBodyBox.SelectionFont; Font fnt = new Font(baseFont.FontFamily, baseFont.Size, baseFont.Style | FontStyle.Bold); //Fontを変更する LogBodyBox.SelectionFont = fnt; //文字列を挿入する LogBodyBox.SelectedText = String.Format("[{0}]{1}:{2}\r\n", log.TimeStampServerTime.ToString("MM/dd HH:mm:ss"), log.LogTypeHexString, log.LogBodyReplaceTabCode); baseFont.Dispose(); fnt.Dispose(); }