Exemplo n.º 1
0
        /// <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);
        }
Exemplo n.º 2
0
        /// <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();
                }
            }
        }
Exemplo n.º 3
0
        /// <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);
     }
 }
Exemplo n.º 5
0
        /// <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);
            }
        }
Exemplo n.º 8
0
        /// <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);
            }
        }