/// <summary> /// 1ログ1スペルに対して判定する /// </summary> /// <param name="spell">スペル</param> /// <param name="logLine">ログ</param> public void MatchCore( Models.Spell spell, string logLine) { var regex = spell.Regex; var notifyNeeded = false; var matched = false; if (!spell.IsInstance) { // マッチング計測開始 spell.StartMatching(); // 開始条件を確認する if (ConditionUtility.CheckConditionsForSpell(spell)) { // 正規表現が無効? if (!spell.RegexEnabled || regex == null) { var keyword = spell.KeywordReplaced; if (string.IsNullOrWhiteSpace(keyword)) { return; } // キーワードが含まれるか? if (logLine.Contains(keyword, StringComparison.OrdinalIgnoreCase)) { matched = true; var targetSpell = spell; // ヒットしたログを格納する targetSpell.MatchedLog = logLine; // スペル名(表示テキスト)を置換する var replacedTitle = ConditionUtility.GetReplacedTitle(targetSpell); // PC名を置換する replacedTitle = FFXIVPlugin.Instance.ReplacePartyMemberName( replacedTitle, Settings.Default.PCNameInitialOnDisplayStyle); targetSpell.SpellTitleReplaced = replacedTitle; targetSpell.UpdateDone = false; targetSpell.OverDone = false; targetSpell.BeforeDone = false; targetSpell.TimeupDone = false; var now = DateTime.Now; // ホットバーからリキャスト時間の読込みを試みる double d = 0d; if (!this.TryGetHotbarRecast(targetSpell, out d)) { d = targetSpell.RecastTime; } targetSpell.CompleteScheduledTime = now.AddSeconds(d); targetSpell.MatchDateTime = now; // マッチング計測終了 spell.EndMatching(); // マッチ時点のサウンドを再生する targetSpell.Play(targetSpell.MatchSound, targetSpell.MatchAdvancedConfig); targetSpell.Play(targetSpell.MatchTextToSpeak, targetSpell.MatchAdvancedConfig); notifyNeeded = true; // 遅延サウンドタイマを開始する targetSpell.StartOverSoundTimer(); targetSpell.StartBeforeSoundTimer(); targetSpell.StartTimeupSoundTimer(); } } else { // 正規表現でマッチングする var match = regex.Match(logLine); if (match.Success) { matched = true; #if DEBUG if (logLine.Contains("MARK")) { Debug.WriteLine("MARK"); } #endif var targetSpell = default(Spell); void setTitle() { targetSpell = spell; // ヒットしたログを格納する targetSpell.MatchedLog = logLine; // スペル名(表示テキスト)を置換する var replacedTitle = match.Result(ConditionUtility.GetReplacedTitle(targetSpell)); // PC名を置換する replacedTitle = FFXIVPlugin.Instance.ReplacePartyMemberName( replacedTitle, Settings.Default.PCNameInitialOnDisplayStyle); // インスタンス化する? if (targetSpell.ToInstance) { // 同じタイトルのインスタンススペルを探す // 存在すればそれを使用して、なければ新しいインスタンスを生成する targetSpell = SpellTable.Instance.GetOrAddInstance( replacedTitle, targetSpell); } else { targetSpell.SpellTitleReplaced = replacedTitle; } } // スペルタイトルを編集する setTitle(); targetSpell.UpdateDone = false; targetSpell.OverDone = false; targetSpell.BeforeDone = false; targetSpell.TimeupDone = false; var now = DateTime.Now; // 効果時間を決定する // グループ "duration" をキャプチャーしていた場合は効果時間を置換する // 最大値9999を超えていた場合は無視する var duration = targetSpell.RecastTime; var d = 0d; var durationAsText = match.Groups["duration"].Value; if (double.TryParse(durationAsText, out d) && d < 9999) { duration = d; } else { // ホットバーからリキャスト時間の読込を試みる if (this.TryGetHotbarRecast(targetSpell, out d)) { duration = d; } } targetSpell.CompleteScheduledTime = now.AddSeconds(duration); // スペル対象を保存する // グループ "target" をキャプチャーしていた場合はその文字列を保存する var targetName = match.Groups["target"].Value; if (!string.IsNullOrWhiteSpace(targetName)) { targetSpell.TargetName = targetName; } // マッチ日時を格納する targetSpell.MatchDateTime = now; // マッチング計測終了 spell.EndMatching(); // マッチ時点のサウンドを再生する targetSpell.Play(targetSpell.MatchSound, targetSpell.MatchAdvancedConfig); if (!string.IsNullOrWhiteSpace(targetSpell.MatchTextToSpeak)) { var tts = match.Result(targetSpell.MatchTextToSpeak); targetSpell.Play(tts, targetSpell.MatchAdvancedConfig); } notifyNeeded = true; // 遅延サウンドタイマを開始する targetSpell.StartOverSoundTimer(); targetSpell.StartBeforeSoundTimer(); targetSpell.StartTimeupSoundTimer(); } } } } // 延長をマッチングする if (spell.MatchDateTime > DateTime.MinValue) { var keywords = new string[] { spell.KeywordForExtendReplaced1, spell.KeywordForExtendReplaced2 }; var regexes = new Regex[] { spell.RegexForExtend1, spell.RegexForExtend2 }; var timeToExtends = new double[] { spell.RecastTimeExtending1, spell.RecastTimeExtending2 }; for (int i = 0; i < 2; i++) { var keywordToExtend = keywords[i]; var regexToExtend = regexes[i]; var timeToExtend = timeToExtends[i]; // マッチングする var exntended = false; if (!spell.RegexEnabled || regexToExtend == null) { if (!string.IsNullOrWhiteSpace(keywordToExtend)) { exntended = logLine.Contains(keywordToExtend, StringComparison.OrdinalIgnoreCase); } } else { var match = regexToExtend.Match(logLine); exntended = match.Success; if (exntended) { // targetをキャプチャーしている? if (!string.IsNullOrWhiteSpace(spell.TargetName)) { var targetName = match.Groups["target"].Value; if (!string.IsNullOrWhiteSpace(targetName)) { // targetが当初のマッチングと一致するか確認する if (spell.TargetName != targetName) { exntended = false; } } } } } if (!exntended) { continue; } var now = DateTime.Now; // リキャストタイムを延長する var newSchedule = spell.CompleteScheduledTime.AddSeconds(timeToExtend); spell.BeforeDone = false; spell.UpdateDone = false; if (spell.ExtendBeyondOriginalRecastTime) { if (spell.UpperLimitOfExtension > 0) { var newDuration = (newSchedule - now).TotalSeconds; if (newDuration > (double)spell.UpperLimitOfExtension) { newSchedule = newSchedule.AddSeconds( (newDuration - (double)spell.UpperLimitOfExtension) * -1); } } } else { var newDuration = (newSchedule - now).TotalSeconds; if (newDuration > (double)spell.RecastTime) { newSchedule = newSchedule.AddSeconds( (newDuration - (double)spell.RecastTime) * -1); } } spell.CompleteScheduledTime = newSchedule; spell.MatchDateTime = now; notifyNeeded = true; // 遅延サウンドタイマを開始(更新)する spell.StartOverSoundTimer(); spell.StartBeforeSoundTimer(); spell.StartTimeupSoundTimer(); } } // end if 延長マッチング // ホットバー情報を更新する if (!matched) { var now = DateTime.Now; if (spell.CompleteScheduledTime > now) { double d; if (this.TryGetHotbarRecast(spell, out d)) { // ホットバー情報と0.6秒以上乖離したら補正する var newSchedule = now.AddSeconds(d); if (Math.Abs((newSchedule - spell.CompleteScheduledTime).TotalSeconds) >= 0.6d) { spell.CompleteScheduledTime = newSchedule; spell.BeforeDone = false; spell.UpdateDone = false; notifyNeeded = true; spell.StartOverSoundTimer(); spell.StartBeforeSoundTimer(); spell.StartTimeupSoundTimer(); } } } } // ACT標準のSpellTimerに変更を通知する if (notifyNeeded) { this.UpdateNormalSpellTimer(spell, false); this.NotifyNormalSpellTimer(spell); } }
/// <summary> /// Spellをマッチングする /// </summary> /// <param name="spells">Spell</param> /// <param name="logLines">ログ</param> private void MatchSpells( IReadOnlyList <SpellTimer> spells, IReadOnlyList <string> logLines) { foreach (var logLine in logLines) { // マッチする? spells.AsParallel().ForAll(spell => { var regex = spell.Regex; var notifyNeeded = false; if (!spell.IsInstance) { // 開始条件を確認する if (ConditionUtility.CheckConditionsForSpell(spell)) { // 正規表現が無効? if (!spell.RegexEnabled || regex == null) { var keyword = spell.KeywordReplaced; if (string.IsNullOrWhiteSpace(keyword)) { return; } // キーワードが含まれるか? if (logLine.ToUpper().Contains( keyword.ToUpper())) { var targetSpell = spell; // ヒットしたログを格納する targetSpell.MatchedLog = logLine; // スペル名(表示テキスト)を置換する var replacedTitle = ConditionUtility.GetReplacedTitle(targetSpell); targetSpell.SpellTitleReplaced = replacedTitle; targetSpell.MatchDateTime = DateTime.Now; targetSpell.UpdateDone = false; targetSpell.OverDone = false; targetSpell.BeforeDone = false; targetSpell.TimeupDone = false; targetSpell.CompleteScheduledTime = targetSpell.MatchDateTime.AddSeconds(targetSpell.RecastTime); // マッチ時点のサウンドを再生する this.Play(targetSpell.MatchSound); this.Play(targetSpell.MatchTextToSpeak); notifyNeeded = true; } } else { // 正規表現でマッチングする var match = regex.Match(logLine); if (match.Success) { var targetSpell = spell; // ヒットしたログを格納する targetSpell.MatchedLog = logLine; // スペル名(表示テキスト)を置換する var replacedTitle = match.Result(ConditionUtility.GetReplacedTitle(targetSpell)); // インスタンス化する? if (spell.ToInstance) { // 同じタイトルのインスタンススペルを探す // 存在すればそれを使用して、なければ新しいインスタンスを生成する targetSpell = SpellTimerTable.GetOrAddInstance( replacedTitle, spell); } targetSpell.SpellTitleReplaced = replacedTitle; targetSpell.MatchDateTime = DateTime.Now; targetSpell.UpdateDone = false; targetSpell.OverDone = false; targetSpell.BeforeDone = false; targetSpell.TimeupDone = false; // 効果時間を決定する // グループ "duration" をキャプチャーしていた場合は効果時間を置換する var durationAsText = match.Groups["duration"].Value; long duration; if (!long.TryParse(durationAsText, out duration)) { duration = targetSpell.RecastTime; } targetSpell.CompleteScheduledTime = targetSpell.MatchDateTime.AddSeconds(duration); // マッチ時点のサウンドを再生する this.Play(targetSpell.MatchSound); if (!string.IsNullOrWhiteSpace(targetSpell.MatchTextToSpeak)) { var tts = match.Result(targetSpell.MatchTextToSpeak); this.Play(tts); } notifyNeeded = true; } } } } // 延長をマッチングする if (spell.MatchDateTime > DateTime.MinValue) { var keywords = new string[] { spell.KeywordForExtendReplaced1, spell.KeywordForExtendReplaced2 }; var regexes = new Regex[] { spell.RegexForExtend1, spell.RegexForExtend2 }; var timeToExtends = new long[] { spell.RecastTimeExtending1, spell.RecastTimeExtending2 }; for (int i = 0; i < 2; i++) { var keywordToExtend = keywords[i]; var regexToExtend = regexes[i]; var timeToExtend = timeToExtends[i]; // マッチングする var match = false; if (!spell.RegexEnabled || regexToExtend == null) { if (!string.IsNullOrWhiteSpace(keywordToExtend)) { match = logLine.ToUpper().Contains(keywordToExtend.ToUpper()); } } else { match = regexToExtend.Match(logLine).Success; } if (!match) { continue; } var now = DateTime.Now; // リキャストタイムを延長する var newSchedule = spell.CompleteScheduledTime.AddSeconds(timeToExtend); spell.BeforeDone = false; spell.UpdateDone = false; if (spell.ExtendBeyondOriginalRecastTime) { if (spell.UpperLimitOfExtension > 0) { var newDuration = (newSchedule - now).TotalSeconds; if (newDuration > (double)spell.UpperLimitOfExtension) { newSchedule = newSchedule.AddSeconds( (newDuration - (double)spell.UpperLimitOfExtension) * -1); } } } else { var newDuration = (newSchedule - now).TotalSeconds; if (newDuration > (double)spell.RecastTime) { newSchedule = newSchedule.AddSeconds( (newDuration - (double)spell.RecastTime) * -1); } } spell.MatchDateTime = now; spell.CompleteScheduledTime = newSchedule; notifyNeeded = true; } } // end if 延長マッチング // ACT標準のSpellTimerに変更を通知する if (notifyNeeded) { this.updateNormalSpellTimer(spell, false); this.notifyNormalSpellTimer(spell); } }); // end loop spells } // スペルの更新とサウンド処理を行う foreach (var spell in spells) { var regex = spell.Regex; // Repeat対象のSpellを更新する if (spell.RepeatEnabled && spell.MatchDateTime > DateTime.MinValue) { if (DateTime.Now >= spell.MatchDateTime.AddSeconds(spell.RecastTime)) { spell.MatchDateTime = DateTime.Now; spell.UpdateDone = false; spell.OverDone = false; spell.TimeupDone = false; } } // n秒後のSoundを再生する if (spell.OverTime > 0 && !spell.OverDone && spell.MatchDateTime > DateTime.MinValue) { var over = spell.MatchDateTime.AddSeconds(spell.OverTime); if (DateTime.Now >= over) { this.Play(spell.OverSound); if (!string.IsNullOrWhiteSpace(spell.OverTextToSpeak)) { var tts = spell.RegexEnabled && regex != null? regex.Replace(spell.MatchedLog, spell.OverTextToSpeak) : spell.OverTextToSpeak; this.Play(tts); } spell.OverDone = true; } } // リキャストn秒前のSoundを再生する if (spell.BeforeTime > 0 && !spell.BeforeDone && spell.MatchDateTime > DateTime.MinValue) { if (spell.CompleteScheduledTime > DateTime.MinValue) { var before = spell.CompleteScheduledTime.AddSeconds(spell.BeforeTime * -1); if (DateTime.Now >= before) { this.Play(spell.BeforeSound); if (!string.IsNullOrWhiteSpace(spell.BeforeTextToSpeak)) { var tts = spell.RegexEnabled && regex != null? regex.Replace(spell.MatchedLog, spell.BeforeTextToSpeak) : spell.BeforeTextToSpeak; this.Play(tts); } spell.BeforeDone = true; } } } // リキャスト完了のSoundを再生する if (spell.RecastTime > 0 && !spell.TimeupDone && spell.MatchDateTime > DateTime.MinValue) { if (spell.CompleteScheduledTime > DateTime.MinValue && DateTime.Now >= spell.CompleteScheduledTime) { this.Play(spell.TimeupSound); if (!string.IsNullOrWhiteSpace(spell.TimeupTextToSpeak)) { var tts = spell.RegexEnabled && regex != null? regex.Replace(spell.MatchedLog, spell.TimeupTextToSpeak) : spell.TimeupTextToSpeak; this.Play(tts); } spell.TimeupDone = true; } } // インスタンス化したスペルを削除する if (spell.IsInstance) { SpellTimerTable.TryRemoveInstance(spell); } } }
/// <summary> /// Spellをマッチングする /// </summary> /// <param name="spells">Spell</param> /// <param name="logLines">ログ</param> private void MatchSpells( IReadOnlyList <Models.SpellTimer> spells, IReadOnlyList <string> logLines) { foreach (var logLine in logLines) { // マッチする? spells.AsParallel().ForAll(spell => { var regex = spell.Regex; var notifyNeeded = false; if (!spell.IsInstance) { // 開始条件を確認する if (ConditionUtility.CheckConditionsForSpell(spell)) { // 正規表現が無効? if (!spell.RegexEnabled || regex == null) { var keyword = spell.KeywordReplaced; if (string.IsNullOrWhiteSpace(keyword)) { return; } // キーワードが含まれるか? if (logLine.ToUpper().Contains( keyword.ToUpper())) { var targetSpell = spell; // ヒットしたログを格納する targetSpell.MatchedLog = logLine; // スペル名(表示テキスト)を置換する var replacedTitle = ConditionUtility.GetReplacedTitle(targetSpell); targetSpell.SpellTitleReplaced = replacedTitle; targetSpell.MatchDateTime = DateTime.Now; targetSpell.UpdateDone = false; targetSpell.OverDone = false; targetSpell.BeforeDone = false; targetSpell.TimeupDone = false; targetSpell.CompleteScheduledTime = targetSpell.MatchDateTime.AddSeconds(targetSpell.RecastTime); // マッチ時点のサウンドを再生する this.Play(targetSpell.MatchSound); this.Play(targetSpell.MatchTextToSpeak); notifyNeeded = true; // 遅延サウンドタイマを開始する targetSpell.StartOverSoundTimer(); targetSpell.StartBeforeSoundTimer(); targetSpell.StartTimeupSoundTimer(); } } else { // 正規表現でマッチングする var match = regex.Match(logLine); if (match.Success) { var targetSpell = spell; // ヒットしたログを格納する targetSpell.MatchedLog = logLine; // スペル名(表示テキスト)を置換する var replacedTitle = match.Result(ConditionUtility.GetReplacedTitle(targetSpell)); // インスタンス化する? if (spell.ToInstance) { // 同じタイトルのインスタンススペルを探す // 存在すればそれを使用して、なければ新しいインスタンスを生成する targetSpell = SpellTimerTable.GetOrAddInstance( replacedTitle, spell); // インスタンスのガーベージタイマをスタートする targetSpell.StartGarbageInstanceTimer(); } targetSpell.SpellTitleReplaced = replacedTitle; targetSpell.MatchDateTime = DateTime.Now; targetSpell.UpdateDone = false; targetSpell.OverDone = false; targetSpell.BeforeDone = false; targetSpell.TimeupDone = false; // 効果時間を決定する // グループ "duration" をキャプチャーしていた場合は効果時間を置換する var durationAsText = match.Groups["duration"].Value; double duration; if (!double.TryParse(durationAsText, out duration)) { duration = targetSpell.RecastTime; } targetSpell.CompleteScheduledTime = targetSpell.MatchDateTime.AddSeconds(duration); // スペル対象を保存する // グループ "target" をキャプチャーしていた場合はその文字列を保存する var targetName = match.Groups["target"].Value; if (!string.IsNullOrWhiteSpace(targetName)) { targetSpell.TargetName = targetName; } // マッチ時点のサウンドを再生する this.Play(targetSpell.MatchSound); if (!string.IsNullOrWhiteSpace(targetSpell.MatchTextToSpeak)) { var tts = match.Result(targetSpell.MatchTextToSpeak); this.Play(tts); } notifyNeeded = true; // 遅延サウンドタイマを開始する targetSpell.StartOverSoundTimer(); targetSpell.StartBeforeSoundTimer(); targetSpell.StartTimeupSoundTimer(); } } } } // 延長をマッチングする if (spell.MatchDateTime > DateTime.MinValue) { var keywords = new string[] { spell.KeywordForExtendReplaced1, spell.KeywordForExtendReplaced2 }; var regexes = new Regex[] { spell.RegexForExtend1, spell.RegexForExtend2 }; var timeToExtends = new double[] { spell.RecastTimeExtending1, spell.RecastTimeExtending2 }; for (int i = 0; i < 2; i++) { var keywordToExtend = keywords[i]; var regexToExtend = regexes[i]; var timeToExtend = timeToExtends[i]; // マッチングする var matched = false; if (!spell.RegexEnabled || regexToExtend == null) { if (!string.IsNullOrWhiteSpace(keywordToExtend)) { matched = logLine.ToUpper().Contains(keywordToExtend.ToUpper()); } } else { var match = regexToExtend.Match(logLine); matched = match.Success; if (matched) { // targetをキャプチャーしている? if (!string.IsNullOrWhiteSpace(spell.TargetName)) { var targetName = match.Groups["target"].Value; if (!string.IsNullOrWhiteSpace(targetName)) { // targetが当初のマッチングと一致するか確認する if (spell.TargetName != targetName) { matched = false; } } } } } if (!matched) { continue; } var now = DateTime.Now; // リキャストタイムを延長する var newSchedule = spell.CompleteScheduledTime.AddSeconds(timeToExtend); spell.BeforeDone = false; spell.UpdateDone = false; if (spell.ExtendBeyondOriginalRecastTime) { if (spell.UpperLimitOfExtension > 0) { var newDuration = (newSchedule - now).TotalSeconds; if (newDuration > (double)spell.UpperLimitOfExtension) { newSchedule = newSchedule.AddSeconds( (newDuration - (double)spell.UpperLimitOfExtension) * -1); } } } else { var newDuration = (newSchedule - now).TotalSeconds; if (newDuration > (double)spell.RecastTime) { newSchedule = newSchedule.AddSeconds( (newDuration - (double)spell.RecastTime) * -1); } } spell.MatchDateTime = now; spell.CompleteScheduledTime = newSchedule; notifyNeeded = true; // 遅延サウンドタイマを開始(更新)する spell.StartOverSoundTimer(); spell.StartBeforeSoundTimer(); spell.StartTimeupSoundTimer(); } } // end if 延長マッチング // ACT標準のSpellTimerに変更を通知する if (notifyNeeded) { this.UpdateNormalSpellTimer(spell, false); this.NotifyNormalSpellTimer(spell); } }); // end loop of Spells } // end loop of LogLines }
/// <summary> /// 1ログ1スペルに対して判定する /// </summary> /// <param name="spell">スペル</param> /// <param name="logLine">ログ</param> public void MatchCore( Models.SpellTimer spell, string logLine) { var regex = spell.Regex; var notifyNeeded = false; if (!spell.IsInstance) { // マッチング計測開始 spell.StartMatching(); // 開始条件を確認する if (ConditionUtility.CheckConditionsForSpell(spell)) { // 正規表現が無効? if (!spell.RegexEnabled || regex == null) { var keyword = spell.KeywordReplaced; if (string.IsNullOrWhiteSpace(keyword)) { return; } // キーワードが含まれるか? if (logLine.Contains(keyword, StringComparison.OrdinalIgnoreCase)) { var targetSpell = spell; // ヒットしたログを格納する targetSpell.MatchedLog = logLine; // スペル名(表示テキスト)を置換する var replacedTitle = ConditionUtility.GetReplacedTitle(targetSpell); // PC名を置換する replacedTitle = FFXIVPlugin.Instance.ReplacePartyMemberName(replacedTitle); targetSpell.SpellTitleReplaced = replacedTitle; targetSpell.UpdateDone = false; targetSpell.OverDone = false; targetSpell.BeforeDone = false; targetSpell.TimeupDone = false; var now = DateTime.Now; targetSpell.CompleteScheduledTime = now.AddSeconds(targetSpell.RecastTime); targetSpell.MatchDateTime = now; // マッチング計測終了 spell.EndMatching(); // マッチ時点のサウンドを再生する this.Play(targetSpell.MatchSound); this.Play(targetSpell.MatchTextToSpeak); // DISCORDに通知する? if (targetSpell.NotifyToDiscord) { DiscordBridge.Instance.SendMessageDelegate?.Invoke( $"{replacedTitle} {targetSpell.RecastTime:N0}"); } notifyNeeded = true; // 遅延サウンドタイマを開始する targetSpell.StartOverSoundTimer(); targetSpell.StartBeforeSoundTimer(); targetSpell.StartTimeupSoundTimer(); } } else { // 正規表現でマッチングする var match = regex.Match(logLine); if (match.Success) { var targetSpell = spell; // ヒットしたログを格納する targetSpell.MatchedLog = logLine; // スペル名(表示テキスト)を置換する var replacedTitle = match.Result(ConditionUtility.GetReplacedTitle(targetSpell)); // PC名を置換する replacedTitle = FFXIVPlugin.Instance.ReplacePartyMemberName(replacedTitle); // インスタンス化する? if (spell.ToInstance) { // 同じタイトルのインスタンススペルを探す // 存在すればそれを使用して、なければ新しいインスタンスを生成する targetSpell = SpellTimerTable.Instance.GetOrAddInstance( replacedTitle, spell); // インスタンスのガーベージタイマをスタートする targetSpell.StartGarbageInstanceTimer(); } targetSpell.SpellTitleReplaced = replacedTitle; targetSpell.UpdateDone = false; targetSpell.OverDone = false; targetSpell.BeforeDone = false; targetSpell.TimeupDone = false; var now = DateTime.Now; // 効果時間を決定する // グループ "duration" をキャプチャーしていた場合は効果時間を置換する var durationAsText = match.Groups["duration"].Value; double duration; if (!double.TryParse(durationAsText, out duration)) { duration = targetSpell.RecastTime; } targetSpell.CompleteScheduledTime = now.AddSeconds(duration); // スペル対象を保存する // グループ "target" をキャプチャーしていた場合はその文字列を保存する var targetName = match.Groups["target"].Value; if (!string.IsNullOrWhiteSpace(targetName)) { targetSpell.TargetName = targetName; } // マッチ日時を格納する targetSpell.MatchDateTime = now; // マッチング計測終了 spell.EndMatching(); // マッチ時点のサウンドを再生する this.Play(targetSpell.MatchSound); if (!string.IsNullOrWhiteSpace(targetSpell.MatchTextToSpeak)) { var tts = match.Result(targetSpell.MatchTextToSpeak); this.Play(tts); } // DISCORDに通知する? if (targetSpell.NotifyToDiscord) { DiscordBridge.Instance.SendMessageDelegate?.Invoke( $"{replacedTitle} {targetSpell.RecastTime:N0}"); } notifyNeeded = true; // 遅延サウンドタイマを開始する targetSpell.StartOverSoundTimer(); targetSpell.StartBeforeSoundTimer(); targetSpell.StartTimeupSoundTimer(); } } } } // 延長をマッチングする if (spell.MatchDateTime > DateTime.MinValue) { var keywords = new string[] { spell.KeywordForExtendReplaced1, spell.KeywordForExtendReplaced2 }; var regexes = new Regex[] { spell.RegexForExtend1, spell.RegexForExtend2 }; var timeToExtends = new double[] { spell.RecastTimeExtending1, spell.RecastTimeExtending2 }; for (int i = 0; i < 2; i++) { var keywordToExtend = keywords[i]; var regexToExtend = regexes[i]; var timeToExtend = timeToExtends[i]; // マッチングする var matched = false; if (!spell.RegexEnabled || regexToExtend == null) { if (!string.IsNullOrWhiteSpace(keywordToExtend)) { matched = logLine.Contains(keywordToExtend, StringComparison.OrdinalIgnoreCase); } } else { var match = regexToExtend.Match(logLine); matched = match.Success; if (matched) { // targetをキャプチャーしている? if (!string.IsNullOrWhiteSpace(spell.TargetName)) { var targetName = match.Groups["target"].Value; if (!string.IsNullOrWhiteSpace(targetName)) { // targetが当初のマッチングと一致するか確認する if (spell.TargetName != targetName) { matched = false; } } } } } if (!matched) { continue; } var now = DateTime.Now; // リキャストタイムを延長する var newSchedule = spell.CompleteScheduledTime.AddSeconds(timeToExtend); spell.BeforeDone = false; spell.UpdateDone = false; if (spell.ExtendBeyondOriginalRecastTime) { if (spell.UpperLimitOfExtension > 0) { var newDuration = (newSchedule - now).TotalSeconds; if (newDuration > (double)spell.UpperLimitOfExtension) { newSchedule = newSchedule.AddSeconds( (newDuration - (double)spell.UpperLimitOfExtension) * -1); } } } else { var newDuration = (newSchedule - now).TotalSeconds; if (newDuration > (double)spell.RecastTime) { newSchedule = newSchedule.AddSeconds( (newDuration - (double)spell.RecastTime) * -1); } } spell.CompleteScheduledTime = newSchedule; spell.MatchDateTime = now; notifyNeeded = true; // 遅延サウンドタイマを開始(更新)する spell.StartOverSoundTimer(); spell.StartBeforeSoundTimer(); spell.StartTimeupSoundTimer(); } } // end if 延長マッチング // ACT標準のSpellTimerに変更を通知する if (notifyNeeded) { this.UpdateNormalSpellTimer(spell, false); this.NotifyNormalSpellTimer(spell); } }