/// <summary> /// ACT標準のスペルタイマーの設定を追加・更新する /// </summary> /// <param name="spellTimer">元になるスペルタイマー</param> /// <param name="useRecastTime">リキャスト時間にRecastの値を使うか。falseの場合はCompleteScheduledTimeから計算される</param> public void UpdateNormalSpellTimer(Models.SpellTimer spellTimer, bool useRecastTime) { if (!Settings.Default.EnabledNotifyNormalSpellTimer) { return; } var prefix = Settings.Default.NotifyNormalSpellTimerPrefix; var spellName = prefix + "spell_" + spellTimer.SpellTitle; var categoryName = prefix + spellTimer.Panel; var recastTime = useRecastTime ? spellTimer.RecastTime : (spellTimer.CompleteScheduledTime - DateTime.Now).TotalSeconds; var timerData = new TimerData(spellName, categoryName); timerData.TimerValue = (int)recastTime; timerData.RemoveValue = (int)-Settings.Default.TimeOfHideSpell; timerData.WarningValue = 0; timerData.OnlyMasterTicks = true; timerData.Tooltip = spellTimer.SpellTitleReplaced; timerData.Panel1Display = false; timerData.Panel2Display = false; // disable warning sound timerData.WarningSoundData = "none"; // initialize other parameters timerData.RestrictToMe = false; timerData.AbsoluteTiming = false; timerData.RestrictToCategory = false; ActGlobals.oFormSpellTimers.AddEditTimerDef(timerData); }
/// <summary> /// instanceが不要になっていたらコレクションから除去する /// </summary> /// <param name="instance">インスタンス</param> public static void TryRemoveInstance( SpellTimer instance) { var ttl = Settings.Default.TimeOfHideSpell + 30; lock (instance) { if (instance.CompleteScheduledTime != DateTime.MinValue && (DateTime.Now - instance.CompleteScheduledTime).TotalSeconds >= ttl) { // ガーベージタイマを止める instance.StopGarbageInstanceTimer(); SpellTimer o; instanceSpells.TryRemove(instance.SpellTitleReplaced, out o); // スペルコレクション本体から除去する lock (lockObject) { table.Remove(instance); } instance.Dispose(); } } }
/// <summary> /// instanceが不要になっていたらコレクションから除去する /// </summary> /// <param name="instance">インスタンス</param> public void TryRemoveInstance( SpellTimer instance) { var ttl = Settings.Default.TimeOfHideSpell + 30; lock (instance) { if (instance.CompleteScheduledTime != DateTime.MinValue && (DateTime.Now - instance.CompleteScheduledTime).TotalSeconds >= ttl) { // ガーベージタイマを止める instance.StopGarbageInstanceTimer(); if (!instance.IsInstance || instance.IsTemporaryDisplay) { return; } this.instanceSpells.TryRemove(instance.SpellTitleReplaced, out SpellTimer o); // スペルコレクション本体から除去する lock (lockObject) { this.table.Remove(instance); } // コンパイル済みリストから除去する TableCompiler.Instance.RemoveSpell(instance); instance.Dispose(); } } }
public void AddInstanceSpell( SpellTimer instancedSpell) { lock (this.spellListLocker) { this.spellList.Add(instancedSpell); } }
/// <summary> /// ACT標準のスペルタイマーに通知する /// </summary> /// <param name="spellTimer">通知先に対応するスペルタイマー</param> public void NotifyNormalSpellTimer(Models.SpellTimer spellTimer) { if (!Settings.Default.EnabledNotifyNormalSpellTimer) { return; } var prefix = Settings.Default.NotifyNormalSpellTimerPrefix; var spellName = prefix + "spell_" + spellTimer.SpellTitle; ActGlobals.oFormSpellTimers.NotifySpell("attacker", spellName, false, "victim", false); }
public void RemoveSpell( SpellTimer instancedSpell) { lock (this.spellListLocker) { this.spellList.Remove(instancedSpell); } lock (this.triggerList) { this.triggerList.Remove(instancedSpell); } }
public void AddSpell( SpellTimer instancedSpell) { lock (this.spellListLocker) { this.spellList.Add(instancedSpell); } lock (this.triggerList) { this.triggerList.Add(instancedSpell); } }
/// <summary> /// 同じスペル表示名のインスタンスを取得するか新たに作成する /// </summary> /// <param name="spellTitle">スペル表示名</param> /// <param name="sourceSpell">インスタンスの元となるスペル</param> /// <returns>インスタンススペル</returns> public static SpellTimer GetOrAddInstance( string spellTitle, SpellTimer sourceSpell) { var instance = instanceSpells.GetOrAdd( spellTitle, (x) => { var ns = new SpellTimer(); ns.SpellTitleReplaced = x; ns.guid = Guid.NewGuid(); ns.Panel = sourceSpell.Panel; ns.SpellTitle = sourceSpell.SpellTitle; ns.SpellIcon = sourceSpell.SpellIcon; ns.SpellIconSize = sourceSpell.SpellIconSize; ns.Keyword = sourceSpell.Keyword; ns.KeywordForExtend1 = sourceSpell.KeywordForExtend1; ns.KeywordForExtend2 = sourceSpell.KeywordForExtend2; ns.RecastTime = sourceSpell.RecastTime; ns.RecastTimeExtending1 = sourceSpell.RecastTimeExtending1; ns.RecastTimeExtending2 = sourceSpell.RecastTimeExtending2; ns.ExtendBeyondOriginalRecastTime = sourceSpell.ExtendBeyondOriginalRecastTime; ns.UpperLimitOfExtension = sourceSpell.UpperLimitOfExtension; ns.RepeatEnabled = sourceSpell.RepeatEnabled; ns.ProgressBarVisible = sourceSpell.ProgressBarVisible; ns.MatchSound = sourceSpell.MatchSound; ns.MatchTextToSpeak = sourceSpell.MatchTextToSpeak; ns.OverSound = sourceSpell.OverSound; ns.OverTextToSpeak = sourceSpell.OverTextToSpeak; ns.OverTime = sourceSpell.OverTime; ns.BeforeSound = sourceSpell.BeforeSound; ns.BeforeTextToSpeak = sourceSpell.BeforeTextToSpeak; ns.BeforeTime = sourceSpell.BeforeTime; ns.TimeupSound = sourceSpell.TimeupSound; ns.TimeupTextToSpeak = sourceSpell.TimeupTextToSpeak; ns.MatchDateTime = sourceSpell.MatchDateTime; ns.TimeupHide = sourceSpell.TimeupHide; ns.IsReverse = sourceSpell.IsReverse; ns.Font = sourceSpell.Font; ns.FontFamily = sourceSpell.FontFamily; ns.FontSize = sourceSpell.FontSize; ns.FontStyle = sourceSpell.FontStyle; ns.FontColor = sourceSpell.FontColor; ns.FontOutlineColor = sourceSpell.FontOutlineColor; ns.WarningFontColor = sourceSpell.WarningFontColor; ns.WarningFontOutlineColor = sourceSpell.WarningFontOutlineColor; ns.BarColor = sourceSpell.BarColor; ns.BarOutlineColor = sourceSpell.BarOutlineColor; ns.BarWidth = sourceSpell.BarWidth; ns.BarHeight = sourceSpell.BarHeight; ns.BackgroundColor = sourceSpell.BackgroundColor; ns.BackgroundAlpha = sourceSpell.BackgroundAlpha; ns.DontHide = sourceSpell.DontHide; ns.HideSpellName = sourceSpell.HideSpellName; ns.WarningTime = sourceSpell.WarningTime; ns.ChangeFontColorsWhenWarning = sourceSpell.ChangeFontColorsWhenWarning; ns.OverlapRecastTime = sourceSpell.OverlapRecastTime; ns.ReduceIconBrightness = sourceSpell.ReduceIconBrightness; ns.RegexEnabled = sourceSpell.RegexEnabled; ns.JobFilter = sourceSpell.JobFilter; ns.ZoneFilter = sourceSpell.ZoneFilter; ns.TimersMustRunningForStart = sourceSpell.TimersMustRunningForStart; ns.TimersMustStoppingForStart = sourceSpell.TimersMustStoppingForStart; ns.Enabled = sourceSpell.Enabled; ns.MatchedLog = sourceSpell.MatchedLog; ns.Regex = sourceSpell.Regex; ns.RegexPattern = sourceSpell.RegexPattern; ns.KeywordReplaced = sourceSpell.KeywordReplaced; ns.RegexForExtend1 = sourceSpell.RegexForExtend1; ns.RegexForExtendPattern1 = sourceSpell.RegexForExtendPattern1; ns.KeywordForExtendReplaced1 = sourceSpell.KeywordForExtendReplaced1; ns.RegexForExtend2 = sourceSpell.RegexForExtend2; ns.RegexForExtendPattern2 = sourceSpell.RegexForExtendPattern2; ns.KeywordForExtendReplaced2 = sourceSpell.KeywordForExtendReplaced2; ns.ToInstance = false; ns.IsInstance = true; return(ns); }); lock (instance) { instance.CompleteScheduledTime = DateTime.MinValue; instanceSpells.TryAdd( instance.SpellTitleReplaced, instance); // スペルテーブル本体に登録する lock (lockObject) { instance.ID = Table.Max(y => y.ID) + 1; table.Add(instance); TableCompiler.Instance.AddInstanceSpell(instance); } } return(instance); }
/// <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); } }