/// <summary> /// ペットIDを更新する /// </summary> public static void RefreshPetID() { // Combatantリストを取得する var combatant = FF14PluginHelper.GetCombatantList(); if (combatant != null && combatant.Count > 0) { var pet = ( from x in combatant where x.OwnerID == combatant[0].ID && ( x.Name.Contains("フェアリー・") || x.Name.Contains("・エギ") || x.Name.Contains("カーバンクル・") ) select x).FirstOrDefault(); if (pet != null) { petid = Convert.ToString((long)((ulong)pet.ID), 16).ToUpper(); petidZone = ActGlobals.oFormActMain.CurrentZone; // 置換後のマッチングキーワードを消去する SpellTimerTable.ClearReplacedKeywords(); OnePointTelopTable.Default.ClearReplacedKeywords(); } } }
/// <summary> /// 終了する /// </summary> public void End() { // 戦闘分析を開放する CombatAnalyzer.Default.Denitialize(); // ログバッファを開放する if (this.LogBuffer != null) { this.LogBuffer.Dispose(); this.LogBuffer = null; } lock (lockObject) { // 監視を開放する if (this.RefreshTimer != null) { this.RefreshTimer.Stop(); this.RefreshTimer.Dispose(); this.RefreshTimer = null; } } // 全てのPanelを閉じる this.ClosePanels(); OnePointTelopController.CloseTelops(); // 設定を保存する Settings.Default.Save(); SpellTimerTable.Save(); OnePointTelopTable.Default.Save(); // instanceを初期化する instance = null; }
/// <summary> /// カスタムプレースホルダーを全て削除する /// </summary> public static void ClearCustomPlaceholderAll() { customPlaceholders.Clear(); // 置換後のマッチングキーワードを消去する SpellTimerTable.ClearReplacedKeywords(); OnePointTelopTable.Default.ClearReplacedKeywords(); }
/// <summary> /// カスタムプレースホルダーに追加する /// <param name="name">追加するプレースホルダーの名称</param> /// <param name="value">置換する文字列</param> /// </summary> public static void SetCustomPlaceholder(string name, string value) { customPlaceholders.AddOrUpdate(ToCustomPlaceholderKey(name), value, (key, oldValue) => value); // 置換後のマッチングキーワードを消去する SpellTimerTable.ClearReplacedKeywords(); OnePointTelopTable.Default.ClearReplacedKeywords(); }
/// <summary> /// カスタムプレースホルダーを削除する /// <param name="name">削除するプレースホルダーの名称</param> /// </summary> public static void ClearCustomPlaceholder(string name) { customPlaceholders.Remove(name); // 置換後のマッチングキーワードを消去する SpellTimerTable.ClearReplacedKeywords(); OnePointTelopTable.Default.ClearReplacedKeywords(); }
/// <summary> /// カスタムプレースホルダーに追加する /// <param name="name">追加するプレースホルダーの名称</param> /// <param name="value">置換する文字列</param> /// </summary> public static void SetCustomPlaceholder(string name, string value) { customPlaceholders[name] = value; // 置換後のマッチングキーワードを消去する SpellTimerTable.ClearReplacedKeywords(); OnePointTelopTable.Default.ClearReplacedKeywords(); }
/// <summary> /// エクスポート Click /// </summary> /// <param name="sender">イベント発生元</param> /// <param name="e">イベント引数</param> private void ExportButton_Click(object sender, EventArgs e) { this.SaveFileDialog.FileName = "ACT.SpecialSpellTimer.Spells.xml"; if (this.SaveFileDialog.ShowDialog(this) != DialogResult.Cancel) { SpellTimerTable.Save( this.SaveFileDialog.FileName); } }
/// <summary> /// カスタムプレースホルダーを削除する /// <param name="name">削除するプレースホルダーの名称</param> /// </summary> public static void ClearCustomPlaceholder(string name) { string beforeValue; customPlaceholders.TryRemove(ToCustomPlaceholderKey(name), out beforeValue); // 置換後のマッチングキーワードを消去する SpellTimerTable.ClearReplacedKeywords(); OnePointTelopTable.Default.ClearReplacedKeywords(); }
/// <summary> /// スペルタイマテーブルを読み込む /// </summary> public void LoadSpellTimerTable() { try { this.SpellTimerTreeView.SuspendLayout(); this.SpellTimerTreeView.Nodes.Clear(); var panels = SpellTimerTable.Table .Where(x => !x.IsInstance) .OrderBy(x => x.Panel) .Select(x => x.Panel) .Distinct(); foreach (var panelName in panels) { var children = new List <TreeNode>(); var spells = SpellTimerTable.Table .Where(x => !x.IsInstance) .OrderBy(x => x.DisplayNo) .Where(x => x.Panel == panelName); foreach (var spell in spells) { var nc = new TreeNode() { Text = spell.SpellTitle, ToolTipText = spell.Keyword, Checked = spell.Enabled, Tag = spell, }; children.Add(nc); } var n = new TreeNode( panelName, children.ToArray()); n.Checked = children.Any(x => x.Checked); this.SpellTimerTreeView.Nodes.Add(n); } // スペルの再描画を行わせる SpellTimerTable.ClearUpdateFlags(); // 標準のスペルタイマーへ変更を反映する SpellTimerCore.Default.applyToNormalSpellTimer(); this.SpellTimerTreeView.ExpandAll(); } finally { this.SpellTimerTreeView.ResumeLayout(); } }
/// <summary> /// インポート Click /// </summary> /// <param name="sender">イベント発生元</param> /// <param name="e">イベント引数</param> private void ImportButton_Click(object sender, EventArgs e) { this.OpenFileDialog.FileName = "ACT.SpecialSpellTimer.Spells.xml"; if (this.OpenFileDialog.ShowDialog(this) != DialogResult.Cancel) { SpellTimerTable.Load( this.OpenFileDialog.FileName, false); this.LoadSpellTimerTable(); } }
/// <summary> /// 終了する /// </summary> public void End() { this.running = false; // 戦闘分析を開放する CombatAnalyzer.Default.Denitialize(); // ログバッファを開放する if (this.LogBuffer != null) { this.LogBuffer.Dispose(); this.LogBuffer = null; } // 監視を開放する if (this.RefreshWindowTimer != null) { this.RefreshWindowTimer.Stop(); this.RefreshWindowTimer = null; } if (this.logPoller != null) { if (this.logPoller.IsAlive) { try { if (!this.logPoller.Join(TimeSpan.FromSeconds(5))) { this.logPoller.Abort(); } } catch { } this.logPoller = null; } } // 全てのPanelを閉じる this.ClosePanels(); OnePointTelopController.CloseTelops(); // 設定を保存する Settings.Default.Save(); SpellTimerTable.Save(); OnePointTelopTable.Default.Save(); // instanceを初期化する instance = null; }
/// <summary> /// 初期化する /// </summary> /// <param name="pluginScreenSpace">Pluginタブ</param> /// <param name="pluginStatusText">Pluginステータスラベル</param> void IActPluginV1.InitPlugin( TabPage pluginScreenSpace, Label pluginStatusText) { Logger.Begin(); try { Logger.Write("Plugin Start."); pluginScreenSpace.Text = "SpecialSpellTimer(スペスペ)"; this.PluginStatusLabel = pluginStatusText; // アップデートを確認する Task.Run(() => { this.Update(); }); // 自身の場所を格納しておく var plugin = ActGlobals.oFormActMain.PluginGetSelfData(this); if (plugin != null) { SpecialSpellTimerPlugin.Location = plugin.pluginFile.DirectoryName; } // 設定Panelを追加する ConfigPanel = new ConfigPanel(); pluginScreenSpace.Controls.Add(ConfigPanel); ConfigPanel.Size = pluginScreenSpace.Size; ConfigPanel.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Bottom | AnchorStyles.Right; // 設定ファイルのバックアップを作成する SpellTimerTable.Backup(); OnePointTelopTable.Default.Backup(); PanelSettings.Default.Backup(); // 本体を開始する SpellTimerCore.Default.Begin(); this.SetSwitchVisibleButton(); this.PluginStatusLabel.Text = "Plugin Started"; Logger.Write("Plugin Started."); } catch (Exception ex) { Logger.Write(Utility.Translate.Get("ACTPluginStartError"), ex); this.PluginStatusLabel.Text = "Plugin Initialize Error"; } }
/// <summary> /// リスタートのときスペルのカウントをリセットする /// </summary> private void ResetCountAtRestart() { // FFXIV以外での使用ならば何もしない if (Settings.Default.UseOtherThanFFXIV) { return; } // 無効? if (!Settings.Default.ResetOnWipeOut) { return; } // Combatantsを頻繁に取得したくないので5秒に1回だけ判定する if ((DateTime.Now - this.LastCheckWipeOutDateTime).TotalSeconds <= 5d) { this.LastCheckWipeOutDateTime = DateTime.Now; return; } this.LastCheckWipeOutDateTime = DateTime.Now; var combatants = FF14PluginHelper.GetCombatantListParty(); if (combatants == null || combatants.Count < 1) { return; } // 関係者が全員死んでる? if (combatants.Count == combatants.Count(x => x.CurrentHP <= 0)) { // リセットするのは15秒に1回にする // 暗転中もずっとリセットし続けてしまうので if ((DateTime.Now - this.LastWipeOutDateTime).TotalSeconds >= 15.0) { Logger.Write("Party was wiped out. Reset spells and tickers."); // スペルのカウントをリセットする SpellTimerTable.ResetCount(); // テロップのカウントをリセットする OnePointTelopTable.Default.ResetCount(); this.LastWipeOutDateTime = DateTime.Now; } } }
/// <summary> /// 終了する /// </summary> public void End() { this.running = false; // 戦闘分析を開放する CombatAnalyzer.Default.Denitialize(); // ログバッファを開放する if (this.LogBuffer != null) { this.LogBuffer.Dispose(); this.LogBuffer = null; } // Viewの描画を開放する if (this.refreshWindowTimer != null) { this.refreshWindowTimer.Stop(); this.refreshWindowTimer = null; } // 監視を開放する if (this.logPoller != null) { this.logPoller.Join(TimeSpan.FromSeconds(5)); if (this.logPoller.IsAlive) { this.logPoller.Abort(); } this.logPoller = null; } // 全てのPanelを閉じる this.ClosePanels(); OnePointTelopController.CloseTelops(); // 設定を保存する Settings.Default.Save(); SpellTimerTable.Save(); OnePointTelopTable.Default.Save(); // テーブルコンパイラを停止する TableCompiler.Instance.End(); // FFXIVのスキャンを停止する FFXIV.Instance.End(); // instanceを初期化する instance = null; }
/// <summary> /// リスタートのときスペルのカウントをリセットする /// </summary> private void ResetCountAtRestart() { // FFXIV以外での使用ならば何もしない if (Settings.Default.UseOtherThanFFXIV) { return; } // 無効? if (!Settings.Default.ResetOnWipeOut) { return; } var combatants = FFXIV.Instance.GetPartyList(); if (combatants == null || combatants.Count < 1) { return; } // 関係者が全員死んでる? if (combatants.Count == combatants.Count(x => x.CurrentHP <= 0)) { // リセットするのは15秒に1回にする // 暗転中もずっとリセットし続けてしまうので if ((DateTime.Now - this.LastWipeOutDateTime).TotalSeconds >= 15.0) { Logger.Write("Party was wiped out. Reset spells and tickers."); SpellTimerTable.ResetCount(); OnePointTelopTable.Default.ResetCount(); // ACT本体に戦闘終了を通知する if (Settings.Default.WipeoutNotifyToACT) { ActInvoker.Invoke(() => { ActGlobals.oFormActMain.ActCommands("end"); }); } this.LastWipeOutDateTime = DateTime.Now; } } }
/// <summary> /// 削除 Click /// </summary> /// <param name="sender">イベント発生元</param> /// <param name="e">イベント引数</param> private void DeleteButton_Click(object sender, EventArgs e) { this.EditSpellsTableBlock(() => { lock (SpellTimerTable.Table) { var src = this.DetailGroupBox.Tag as SpellTimer; if (src != null) { SpellTimerTable.Table.Remove(src); TableCompiler.Instance.RecompileSpells(); SpellTimerTable.RemoveAllInstanceSpells(); SpellTimerTable.Save(); this.DetailGroupBox.Visible = false; this.DetailPanelGroupBox.Visible = false; } } }); // 今の選択ノードを取り出す var targetNode = this.SpellTimerTreeView.SelectedNode; if (targetNode != null) { // 1個前のノードを取り出しておく var prevNode = targetNode.PrevNode; if (targetNode.Parent != null && targetNode.Parent.Nodes.Count > 1) { targetNode.Remove(); if (prevNode != null) { this.SpellTimerTreeView.SelectedNode = prevNode; } } else { targetNode.Parent.Remove(); } } // 標準のスペルタイマーへ変更を反映する SpellTimerCore.Default.ApplyToNormalSpellTimer(); }
/// <summary> /// キーワードを再生成する /// </summary> public static void RefeshKeywords() { if (!Settings.Default.DQXUtilityEnabled) { return; } // 置換後のマッチングキーワードを消去する SpellTimerTable.ClearReplacedKeywords(); OnePointTelopTable.Default.ClearReplacedKeywords(); // スペルタイマーの再描画を行う SpellTimerTable.ClearUpdateFlags(); // モニタタブの情報を無効にする SpecialSpellTimerPlugin.ConfigPanel.InvalidatePlaceholders(); }
/// <summary> /// 削除 Click /// </summary> /// <param name="sender">イベント発生元</param> /// <param name="e">イベント引数</param> private void DeleteButton_Click(object sender, EventArgs e) { lock (SpellTimerTable.Table) { var src = this.DetailGroupBox.Tag as SpellTimer; if (src != null) { SpellTimerTable.Table.Remove(src); SpellTimerTable.Save(); this.DetailGroupBox.Visible = false; this.DetailPanelGroupBox.Visible = false; } } // 今の選択ノードを取り出す var targetNode = this.SpellTimerTreeView.SelectedNode; if (targetNode != null) { // 1個前のノードを取り出しておく var prevNode = targetNode.PrevNode; if (targetNode.Parent != null && targetNode.Parent.Nodes.Count > 1) { targetNode.Remove(); if (prevNode != null) { this.SpellTimerTreeView.SelectedNode = prevNode; } } else { targetNode.Parent.Remove(); } } }
private void VisualSettingControl_Load(object sender, EventArgs e) { var colorSetDirectory = this.GetColorSetDirectory; if (Directory.Exists(colorSetDirectory)) { this.OpenFileDialog.InitialDirectory = colorSetDirectory; this.SaveFileDialog.InitialDirectory = colorSetDirectory; } this.WidthNumericUpDown.Value = this.BarSize.Width; this.HeightNumericUpDown.Value = this.BarSize.Height; this.RefreshSampleImage(); this.ChangeFontItem.Click += (s1, e1) => { var f = new FontDialogWindow(); f.SetOwner(this.ParentForm); f.FontInfo = this.GetFontInfo(); if (f.ShowDialog().Value) { this.SetFontInfo(f.FontInfo); this.RefreshSampleImage(); } }; this.ChangeFontColorItem.Click += (s1, e1) => { this.ColorDialog.Color = this.FontColor; if (this.ColorDialog.ShowDialog(this) != DialogResult.Cancel) { this.FontColor = this.ColorDialog.Color; this.RefreshSampleImage(); } }; this.ChangeFontOutlineColorItem.Click += (s1, e1) => { this.ColorDialog.Color = this.FontOutlineColor; if (this.ColorDialog.ShowDialog(this) != DialogResult.Cancel) { this.FontOutlineColor = this.ColorDialog.Color; this.RefreshSampleImage(); } }; this.ChangeBarColorItem.Click += (s1, e1) => { this.ColorDialog.Color = this.BarColor; if (this.ColorDialog.ShowDialog(this) != DialogResult.Cancel) { this.BarColor = this.ColorDialog.Color; this.RefreshSampleImage(); } }; this.ChangeBarOutlineColorItem.Click += (s1, e1) => { this.ColorDialog.Color = this.BarOutlineColor; if (this.ColorDialog.ShowDialog(this) != DialogResult.Cancel) { this.BarOutlineColor = this.ColorDialog.Color; this.RefreshSampleImage(); } }; this.ChangeBackgoundColorItem.Click += (s1, e1) => { this.ColorDialog.Color = this.backgroundColor; if (this.ColorDialog.ShowDialog(this) != DialogResult.Cancel) { this.backgroundColor = Color.FromArgb( this.alphaDialog.Alpha, this.ColorDialog.Color); this.RefreshSampleImage(); } }; this.ChangeBackgroundAlphaItem.Click += (s1, e1) => { this.alphaDialog.Alpha = this.backgroundColor.A; if (this.alphaDialog.ShowDialog(this) != DialogResult.Cancel) { this.backgroundColor = Color.FromArgb( this.alphaDialog.Alpha, this.backgroundColor); this.RefreshSampleImage(); } }; this.LoadColorSetItem.Click += (s1, e1) => { if (this.OpenFileDialog.ShowDialog(this) != DialogResult.Cancel) { using (var sr = new StreamReader(this.OpenFileDialog.FileName, new UTF8Encoding(false))) { var xs = new XmlSerializer(typeof(ColorSet)); var colorSet = xs.Deserialize(sr) as ColorSet; if (colorSet != null) { this.FontColor = colorSet.FontColor.FromHTML(); this.FontOutlineColor = colorSet.FontOutlineColor.FromHTML(); this.BarColor = colorSet.BarColor.FromHTML(); this.BarOutlineColor = colorSet.BarOutlineColor.FromHTML(); this.backgroundColor = string.IsNullOrWhiteSpace(colorSet.BackgroundColor) ? Color.Transparent : Color.FromArgb(colorSet.BackgroundAlpha, colorSet.BackgroundColor.FromHTML()); this.RefreshSampleImage(); // カラーパレットに登録する this.ColorDialog.CustomColors = new int[] { ColorTranslator.ToOle(colorSet.FontColor.FromHTML()), ColorTranslator.ToOle(colorSet.FontOutlineColor.FromHTML()), ColorTranslator.ToOle(colorSet.BarColor.FromHTML()), ColorTranslator.ToOle(colorSet.BarOutlineColor.FromHTML()), }; } } } }; this.SaveColorSetItem.Click += (s1, e1) => { if (string.IsNullOrWhiteSpace(this.SaveFileDialog.FileName)) { this.SaveFileDialog.FileName = "スペスペ配色セット.xml"; } if (this.SaveFileDialog.ShowDialog(this) != DialogResult.Cancel) { var colorSet = new ColorSet() { FontColor = this.FontColor.ToHTML(), FontOutlineColor = this.FontOutlineColor.ToHTML(), BarColor = this.BarColor.ToHTML(), BarOutlineColor = this.BarOutlineColor.ToHTML(), BackgroundColor = this.backgroundColor.ToHTML(), BackgroundAlpha = this.backgroundColor.A, }; using (var sw = new StreamWriter(this.SaveFileDialog.FileName, false, new UTF8Encoding(false))) { var xs = new XmlSerializer(typeof(ColorSet)); xs.Serialize(sw, colorSet); } } }; this.WidthNumericUpDown.ValueChanged += (s1, e1) => { this.RefreshSampleImage(); }; this.HeightNumericUpDown.ValueChanged += (s1, e1) => { this.RefreshSampleImage(); }; this.ResetSpellFontItem.Click += (s1, e1) => { foreach (var s in SpellTimerTable.Table) { s.Font = this.GetFontInfo(); } SpellTimerCore.Default.ClosePanels(); SpellTimerTable.Save(); }; this.ResetSpellBarSizeItem.Click += (s1, e1) => { foreach (var s in SpellTimerTable.Table) { s.BarWidth = this.BarSize.Width; s.BarHeight = this.BarSize.Height; } SpellTimerCore.Default.ClosePanels(); SpellTimerTable.Save(); }; this.ResetSpellColorItem.Click += (s1, e1) => { foreach (var s in SpellTimerTable.Table) { s.FontColor = this.FontColor.ToHTML(); s.FontOutlineColor = this.FontOutlineColor.ToHTML(); s.BarColor = this.BarColor.ToHTML(); s.BarOutlineColor = this.BarOutlineColor.ToHTML(); s.BackgroundColor = this.backgroundColor.ToHTML(); s.BackgroundAlpha = this.backgroundColor.A; } SpellTimerCore.Default.ClosePanels(); SpellTimerTable.Save(); }; this.ResetTelopFontItem.Click += (s1, e1) => { foreach (var s in OnePointTelopTable.Default.Table) { s.Font = this.GetFontInfo(); } OnePointTelopController.CloseTelops(); OnePointTelopTable.Default.Save(); }; this.ResetTelopColorItem.Click += (s1, e1) => { foreach (var s in OnePointTelopTable.Default.Table) { s.FontColor = this.FontColor.ToHTML(); s.FontOutlineColor = this.FontOutlineColor.ToHTML(); s.BackgroundColor = this.backgroundColor.ToHTML(); s.BackgroundAlpha = this.backgroundColor.A; } OnePointTelopController.CloseTelops(); OnePointTelopTable.Default.Save(); }; }
/// <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> /// 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> /// パーティリストを更新する /// </summary> public static void RefreshPartyList() { // プレイヤー情報を取得する var player = FF14PluginHelper.GetPlayer(); if (player == null) { return; } if (enabledPartyMemberPlaceHolder) { #if DEBUG Debug.WriteLine("PT: Refresh"); #endif // PTメンバの名前を記録しておく var combatants = FF14PluginHelper.GetCombatantListParty(); // FF14内部のPTメンバ自動ソート順で並び替える var sorted = from x in combatants join y in Job.JobList on x.Job equals y.JobId where x.ID != player.ID orderby y.Role, x.Job, x.ID descending select x.Name.Trim(); partyList = new List <string>(sorted); // パーティメンバが空だったら自分を補完しておく if (!combatants.Any()) { combatants.Add(player); } var newList = new Dictionary <string, string>(); // ジョブ名によるプレースホルダを登録する foreach (var job in Job.JobList) { // このジョブに該当するパーティメンバを抽出する var combatantsByJob = ( from x in combatants where x.Job == job.JobId orderby x.ID == player.ID ? 0 : 1, x.ID descending select x).ToArray(); if (!combatantsByJob.Any()) { continue; } // <JOBn>形式を置換する // ex. <PLD1> → Taro Paladin // ex. <PLD2> → Jiro Paladin for (int i = 0; i < combatantsByJob.Length; i++) { var placeholder = string.Format( "<{0}{1}>", job.JobName, i + 1); newList.Add(placeholder.ToUpper(), combatantsByJob[i].Name); } // <JOB>形式を置換する // ただし、この場合は正規表現のグループ形式とする // また、グループ名にはジョブの略称を設定する // ex. <PLD> → (?<PLDs>Taro Paladin|Jiro Paladin) var names = string.Join("|", combatantsByJob.Select(x => x.Name).ToArray()); var oldValue = string.Format("<{0}>", job.JobName); var newValue = string.Format( "(?<{0}s>{1})", job.JobName.ToUpper(), names); newList.Add(oldValue.ToUpper(), newValue); } placeholderToJobNameDictionaly = newList; } else { partyList = EMPTY_STRING_LIST; placeholderToJobNameDictionaly = EMPTY_STRING_PAIR_MAP; } // 置換後のマッチングキーワードを消去する SpellTimerTable.ClearReplacedKeywords(); OnePointTelopTable.Default.ClearReplacedKeywords(); // スペルタイマーの再描画を行う SpellTimerTable.ClearUpdateFlags(); // モニタタブの情報を無効にする SpecialSpellTimerPlugin.ConfigPanel.InvalidatePlaceholders(); }
/// <summary> /// 追加 Click /// </summary> /// <param name="sender">イベント発生元</param> /// <param name="e">イベント引数</param> private void AddButton_Click(object sender, EventArgs e) { lock (SpellTimerTable.Table) { var nr = new SpellTimer(); nr.ID = SpellTimerTable.Table.Any() ? SpellTimerTable.Table.Max(x => x.ID) + 1 : 1; nr.Panel = "General"; nr.SpellTitle = "New Spell"; nr.ProgressBarVisible = true; nr.FontColor = Settings.Default.FontColor.ToHTML(); nr.FontOutlineColor = Settings.Default.FontOutlineColor.ToHTML(); nr.BarColor = Settings.Default.ProgressBarColor.ToHTML(); nr.BarOutlineColor = Settings.Default.ProgressBarOutlineColor.ToHTML(); nr.FontFamily = Settings.Default.Font.Name; nr.FontSize = Settings.Default.Font.Size; nr.FontStyle = (int)Settings.Default.Font.Style; nr.BarWidth = Settings.Default.ProgressBarSize.Width; nr.BarHeight = Settings.Default.ProgressBarSize.Height; nr.BackgroundColor = Settings.Default.BackgroundColor.ToHTML(); nr.JobFilter = string.Empty; // 現在選択しているノードの情報を一部コピーする if (this.SpellTimerTreeView.SelectedNode != null) { var baseRow = this.SpellTimerTreeView.SelectedNode.Tag != null ? this.SpellTimerTreeView.SelectedNode.Tag as SpellTimer : this.SpellTimerTreeView.SelectedNode.Nodes[0].Tag as SpellTimer; if (baseRow != null) { nr.Panel = baseRow.Panel; nr.SpellTitle = baseRow.SpellTitle + " New"; nr.Keyword = baseRow.Keyword; nr.RegexEnabled = baseRow.RegexEnabled; nr.RecastTime = baseRow.RecastTime; nr.RepeatEnabled = baseRow.RepeatEnabled; nr.ProgressBarVisible = baseRow.ProgressBarVisible; nr.IsReverse = baseRow.IsReverse; nr.FontColor = baseRow.FontColor; nr.FontOutlineColor = baseRow.FontOutlineColor; nr.BarColor = baseRow.BarColor; nr.BarOutlineColor = baseRow.BarOutlineColor; nr.DontHide = baseRow.DontHide; nr.FontFamily = baseRow.FontFamily; nr.FontSize = baseRow.FontSize; nr.FontStyle = baseRow.FontStyle; nr.BarWidth = baseRow.BarWidth; nr.BarHeight = baseRow.BarHeight; nr.BackgroundColor = baseRow.BackgroundColor; nr.BackgroundAlpha = baseRow.BackgroundAlpha; nr.JobFilter = baseRow.JobFilter; } } nr.MatchDateTime = DateTime.MinValue; nr.Enabled = true; nr.DisplayNo = SpellTimerTable.Table.Any() ? SpellTimerTable.Table.Max(x => x.DisplayNo) + 1 : 50; nr.Regex = null; nr.RegexPattern = string.Empty; SpellTimerTable.Table.Add(nr); SpellTimerTable.Save(); // 新しいノードを生成する var node = new TreeNode(nr.SpellTitle) { Tag = nr, ToolTipText = nr.Keyword, Checked = nr.Enabled }; // 親ノードがあれば追加する foreach (TreeNode item in this.SpellTimerTreeView.Nodes) { if (item.Text == nr.Panel) { item.Nodes.Add(node); this.SpellTimerTreeView.SelectedNode = node; break; } } // 親ノードがなかった if (this.SpellTimerTreeView.SelectedNode != node) { var parentNode = new TreeNode(nr.Panel, new TreeNode[] { node }) { Checked = true }; this.SpellTimerTreeView.Nodes.Add(parentNode); this.SpellTimerTreeView.SelectedNode = node; } } }
/// <summary> /// Load /// </summary> /// <param name="sender">イベント発生元</param> /// <param name="e">イベント引数</param> private void ConfigPanel_Load(object sender, EventArgs e) { this.LoadSpellTimerTable(); this.DetailGroupBox.Visible = false; this.DetailPanelGroupBox.Visible = false; // コンボボックスにアイテムを装填する this.MatchSoundComboBox.DataSource = SoundController.Default.EnumlateWave(); this.MatchSoundComboBox.ValueMember = "FullPath"; this.MatchSoundComboBox.DisplayMember = "Name"; this.OverSoundComboBox.DataSource = SoundController.Default.EnumlateWave(); this.OverSoundComboBox.ValueMember = "FullPath"; this.OverSoundComboBox.DisplayMember = "Name"; this.BeforeSoundComboBox.DataSource = SoundController.Default.EnumlateWave(); this.BeforeSoundComboBox.ValueMember = "FullPath"; this.BeforeSoundComboBox.DisplayMember = "Name"; this.TimeupSoundComboBox.DataSource = SoundController.Default.EnumlateWave(); this.TimeupSoundComboBox.ValueMember = "FullPath"; this.TimeupSoundComboBox.DisplayMember = "Name"; this.SpellIconComboBox.DataSource = IconController.Default.EnumlateIcon() .OrderBy(x => x.RelativePath) .ToArray(); this.SpellIconComboBox.ValueMember = "RelativePath"; this.SpellIconComboBox.DisplayMember = "RelativePath"; // イベントを設定する this.SpellTimerTreeView.AfterSelect += this.SpellTimerTreeView_AfterSelect; this.AddButton.Click += this.AddButton_Click; this.UpdateButton.Click += this.UpdateButton_Click; this.DeleteButton.Click += this.DeleteButton_Click; this.Play1Button.Click += (s1, e1) => { SoundController.Default.Play((string)this.MatchSoundComboBox.SelectedValue ?? string.Empty); }; this.Play2Button.Click += (s1, e1) => { SoundController.Default.Play((string)this.OverSoundComboBox.SelectedValue ?? string.Empty); }; this.Play3Button.Click += (s1, e1) => { SoundController.Default.Play((string)this.TimeupSoundComboBox.SelectedValue ?? string.Empty); }; this.Play4Button.Click += (s1, e1) => { SoundController.Default.Play((string)this.BeforeSoundComboBox.SelectedValue ?? string.Empty); }; this.Speak1Button.Click += (s1, e1) => { SoundController.Default.Play(this.MatchTextToSpeakTextBox.Text); }; this.Speak2Button.Click += (s1, e1) => { SoundController.Default.Play(this.OverTextToSpeakTextBox.Text); }; this.Speak3Button.Click += (s1, e1) => { SoundController.Default.Play(this.TimeupTextToSpeakTextBox.Text); }; this.Speak4Button.Click += (s1, e1) => { SoundController.Default.Play(this.BeforeTextToSpeakTextBox.Text); }; this.SpellTimerTreeView.AfterCheck += (s1, e1) => { var source = e1.Node.Tag as SpellTimer; if (source != null) { source.Enabled = e1.Node.Checked; source.UpdateDone = false; } else { foreach (TreeNode node in e1.Node.Nodes) { var sourceChild = node.Tag as SpellTimer; if (sourceChild != null) { sourceChild.Enabled = e1.Node.Checked; } node.Checked = e1.Node.Checked; } } // キャッシュを無効にする SpellTimerTable.ClearReplacedKeywords(); // スペルの有効・無効が変化した際に、標準のスペルタイマーに反映する SpellTimerCore.Default.applyToNormalSpellTimer(); }; this.SelectJobButton.Click += (s1, e1) => { var src = this.DetailGroupBox.Tag as SpellTimer; if (src != null) { using (var f = new SelectJobForm()) { f.JobFilter = src.JobFilter; if (f.ShowDialog(this) == DialogResult.OK) { src.JobFilter = f.JobFilter; // ジョブ限定ボタンの色を変える(未設定:黒、設定有:青) this.SelectJobButton.ForeColor = src.JobFilter != string.Empty ? Color.Blue : Button.DefaultForeColor; } } } }; this.SelectZoneButton.Click += (s1, e1) => { var src = this.DetailGroupBox.Tag as SpellTimer; if (src != null) { using (var f = new SelectZoneForm()) { f.ZoneFilter = src.ZoneFilter; if (f.ShowDialog(this) == DialogResult.OK) { src.ZoneFilter = f.ZoneFilter; // ゾーン限定ボタンの色を変える(未設定:黒、設定有:青) this.SelectZoneButton.ForeColor = src.ZoneFilter != string.Empty ? Color.Blue : Button.DefaultForeColor; } } } }; this.SetConditionButton.Click += (s1, e1) => { var src = this.DetailGroupBox.Tag as SpellTimer; if (src != null) { using (var f = new SetConditionForm()) { f.TimersMustRunning = src.TimersMustRunningForStart; f.TimersMustStopping = src.TimersMustStoppingForStart; if (f.ShowDialog(this) == DialogResult.OK) { src.TimersMustRunningForStart = f.TimersMustRunning; src.TimersMustStoppingForStart = f.TimersMustStopping; // 条件設定ボタンの色を変える(未設定:黒、設定有:青) this.SetConditionButton.ForeColor = (src.TimersMustRunningForStart.Length != 0 || src.TimersMustStoppingForStart.Length != 0) ? Color.Blue : Button.DefaultForeColor; } } } }; this.SpellIconComboBox.SelectionChangeCommitted += (s1, e1) => { this.SpellVisualSetting.SpellIcon = (string)this.SpellIconComboBox.SelectedValue; this.SpellVisualSetting.RefreshSampleImage(); }; this.SpellIconSizeUpDown.ValueChanged += (s1, e1) => { this.SpellVisualSetting.SpellIconSize = (int)this.SpellIconSizeUpDown.Value; this.SpellVisualSetting.RefreshSampleImage(); }; this.HideSpellNameCheckBox.CheckedChanged += (s1, e1) => { this.SpellVisualSetting.HideSpellName = this.HideSpellNameCheckBox.Checked; this.SpellVisualSetting.RefreshSampleImage(); }; this.OverlapRecastTimeCheckBox.CheckedChanged += (s1, e1) => { this.SpellVisualSetting.OverlapRecastTime = this.OverlapRecastTimeCheckBox.Checked; this.SpellVisualSetting.RefreshSampleImage(); }; // オプションのロードメソッドを呼ぶ this.LoadOption(); // ワンポイントテロップのロードメソッドを呼ぶ this.LoadOnePointTelop(); // 戦闘アナライザのロードメソッドを呼ぶ this.LoadCombatAnalyzer(); }
/// <summary> /// 更新 Click /// </summary> /// <param name="sender">イベント発生元</param> /// <param name="e">イベント引数</param> private void UpdateButton_Click(object sender, EventArgs e) { lock (SpellTimerTable.Table) { if (string.IsNullOrWhiteSpace(this.PanelNameTextBox.Text)) { MessageBox.Show( this, Translate.Get("UpdateSpellPanelTitle"), "ACT.SpecialSpellTimer", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; } if (string.IsNullOrWhiteSpace(this.SpellTitleTextBox.Text)) { MessageBox.Show( this, Translate.Get("UpdateSpellNameTitle"), "ACT.SpecialSpellTimer", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; } var src = this.DetailGroupBox.Tag as SpellTimer; if (src != null) { src.Panel = this.PanelNameTextBox.Text; src.SpellTitle = this.SpellTitleTextBox.Text; src.DisplayNo = (int)this.DisplayNoNumericUpDown.Value; src.Keyword = this.KeywordTextBox.Text; src.RegexEnabled = this.RegexEnabledCheckBox.Checked; src.RecastTime = (int)this.RecastTimeNumericUpDown.Value; src.RepeatEnabled = this.RepeatCheckBox.Checked; src.ProgressBarVisible = this.ShowProgressBarCheckBox.Checked; src.MatchSound = (string)this.MatchSoundComboBox.SelectedValue ?? string.Empty; src.MatchTextToSpeak = this.MatchTextToSpeakTextBox.Text; src.OverSound = (string)this.OverSoundComboBox.SelectedValue ?? string.Empty; src.OverTextToSpeak = this.OverTextToSpeakTextBox.Text; src.OverTime = (int)this.OverTimeNumericUpDown.Value; src.TimeupSound = (string)this.TimeupSoundComboBox.SelectedValue ?? string.Empty; src.TimeupTextToSpeak = this.TimeupTextToSpeakTextBox.Text; src.IsReverse = this.IsReverseCheckBox.Checked; src.DontHide = this.DontHideCheckBox.Checked; src.FontFamily = this.SpellVisualSetting.TextFont.Name; src.FontSize = this.SpellVisualSetting.TextFont.Size; src.FontStyle = (int)this.SpellVisualSetting.TextFont.Style; src.FontColor = this.SpellVisualSetting.FontColor.ToHTML(); src.FontOutlineColor = this.SpellVisualSetting.FontOutlineColor.ToHTML(); src.BarColor = this.SpellVisualSetting.BarColor.ToHTML(); src.BarOutlineColor = this.SpellVisualSetting.BarOutlineColor.ToHTML(); src.BarWidth = this.SpellVisualSetting.BarSize.Width; src.BarHeight = this.SpellVisualSetting.BarSize.Height; src.BackgroundColor = this.SpellVisualSetting.BackgroundColor.ToHTML(); src.BackgroundAlpha = this.SpellVisualSetting.BackgroundColor.A; var panel = SpellTimerTable.Table.Where(x => x.Panel == src.Panel); foreach (var s in panel) { s.BackgroundColor = src.BackgroundColor; } SpellTimerTable.Save(); this.LoadSpellTimerTable(); // 一度全てのパネルを閉じる SpellTimerCore.Default.ClosePanels(); foreach (TreeNode root in this.SpellTimerTreeView.Nodes) { if (root.Nodes != null) { foreach (TreeNode node in root.Nodes) { var ds = node.Tag as SpellTimer; if (ds != null) { if (ds.ID == src.ID) { this.SpellTimerTreeView.SelectedNode = node; break; } } } } } } } }
/// <summary> /// 更新 Click /// </summary> /// <param name="sender">イベント発生元</param> /// <param name="e">イベント引数</param> private void UpdateButton_Click(object sender, EventArgs e) { lock (SpellTimerTable.Table) { if (string.IsNullOrWhiteSpace(this.PanelNameTextBox.Text)) { MessageBox.Show( this, Translate.Get("UpdateSpellPanelTitle"), "ACT.SpecialSpellTimer", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; } if (string.IsNullOrWhiteSpace(this.SpellTitleTextBox.Text)) { MessageBox.Show( this, Translate.Get("UpdateSpellNameTitle"), "ACT.SpecialSpellTimer", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; } var src = this.DetailGroupBox.Tag as SpellTimer; if (src != null) { src.Panel = this.PanelNameTextBox.Text; src.SpellTitle = this.SpellTitleTextBox.Text; src.SpellIcon = (string)this.SpellIconComboBox.SelectedValue ?? string.Empty; src.SpellIconSize = (int)this.SpellIconSizeUpDown.Value; src.DisplayNo = (int)this.DisplayNoNumericUpDown.Value; src.Keyword = this.KeywordTextBox.Text; src.RegexEnabled = this.RegexEnabledCheckBox.Checked; src.RecastTime = (long)this.RecastTimeNumericUpDown.Value; src.RepeatEnabled = this.RepeatCheckBox.Checked; src.ProgressBarVisible = this.ShowProgressBarCheckBox.Checked; src.KeywordForExtend1 = this.KeywordToExpand1TextBox.Text; src.RecastTimeExtending1 = (long)this.ExpandSecounds1NumericUpDown.Value; src.KeywordForExtend2 = this.KeywordToExpand2TextBox.Text; src.RecastTimeExtending2 = (long)this.ExpandSecounds2NumericUpDown.Value; src.ExtendBeyondOriginalRecastTime = this.ExtendBeyondOriginalRecastTimeCheckBox.Checked; src.UpperLimitOfExtension = (long)this.UpperLimitOfExtensionNumericUpDown.Value; src.MatchSound = (string)this.MatchSoundComboBox.SelectedValue ?? string.Empty; src.MatchTextToSpeak = this.MatchTextToSpeakTextBox.Text; src.OverSound = (string)this.OverSoundComboBox.SelectedValue ?? string.Empty; src.OverTextToSpeak = this.OverTextToSpeakTextBox.Text; src.OverTime = (int)this.OverTimeNumericUpDown.Value; src.BeforeSound = (string)this.BeforeSoundComboBox.SelectedValue ?? string.Empty; src.BeforeTextToSpeak = this.BeforeTextToSpeakTextBox.Text; src.BeforeTime = (int)this.BeforeTimeNumericUpDown.Value; src.TimeupSound = (string)this.TimeupSoundComboBox.SelectedValue ?? string.Empty; src.TimeupTextToSpeak = this.TimeupTextToSpeakTextBox.Text; src.IsReverse = this.IsReverseCheckBox.Checked; src.DontHide = this.DontHideCheckBox.Checked; src.HideSpellName = this.HideSpellNameCheckBox.Checked; src.OverlapRecastTime = this.OverlapRecastTimeCheckBox.Checked; src.ReduceIconBrightness = this.ReduceIconBrightnessCheckBox.Checked; src.ToInstance = this.ToInstanceCheckBox.Checked; src.Font = this.SpellVisualSetting.GetFontInfo(); src.FontColor = this.SpellVisualSetting.FontColor.ToHTML(); src.FontOutlineColor = this.SpellVisualSetting.FontOutlineColor.ToHTML(); src.BarColor = this.SpellVisualSetting.BarColor.ToHTML(); src.BarOutlineColor = this.SpellVisualSetting.BarOutlineColor.ToHTML(); src.BarWidth = this.SpellVisualSetting.BarSize.Width; src.BarHeight = this.SpellVisualSetting.BarSize.Height; src.BackgroundColor = this.SpellVisualSetting.BackgroundColor.ToHTML(); src.BackgroundAlpha = this.SpellVisualSetting.BackgroundColor.A; var panel = SpellTimerTable.Table.Where(x => x.Panel == src.Panel); foreach (var s in panel) { s.BackgroundColor = src.BackgroundColor; } SpellTimerTable.ClearReplacedKeywords(); SpellTimerTable.RemoveAllInstanceSpells(); SpellTimerTable.Save(); this.LoadSpellTimerTable(); // 一度全てのパネルを閉じる SpellTimerCore.Default.ClosePanels(); foreach (TreeNode root in this.SpellTimerTreeView.Nodes) { if (root.Nodes != null) { foreach (TreeNode node in root.Nodes) { var ds = node.Tag as SpellTimer; if (ds != null) { if (ds.ID == src.ID) { this.SpellTimerTreeView.SelectedNode = node; break; } } } } } } } }
/// <summary> /// 追加 Click /// </summary> /// <param name="sender">イベント発生元</param> /// <param name="e">イベント引数</param> private void AddButton_Click(object sender, EventArgs e) { lock (SpellTimerTable.Table) { var nr = new SpellTimer(); nr.ID = SpellTimerTable.Table.Any() ? SpellTimerTable.Table.Max(x => x.ID) + 1 : 1; nr.guid = Guid.NewGuid(); nr.Panel = "General"; nr.SpellTitle = "New Spell"; nr.SpellIcon = string.Empty; nr.SpellIconSize = 24; nr.ProgressBarVisible = true; nr.FontColor = Settings.Default.FontColor.ToHTML(); nr.FontOutlineColor = Settings.Default.FontOutlineColor.ToHTML(); nr.BarColor = Settings.Default.ProgressBarColor.ToHTML(); nr.BarOutlineColor = Settings.Default.ProgressBarOutlineColor.ToHTML(); nr.FontFamily = Settings.Default.Font.Name; nr.FontSize = Settings.Default.Font.Size; nr.FontStyle = (int)Settings.Default.Font.Style; nr.BarWidth = Settings.Default.ProgressBarSize.Width; nr.BarHeight = Settings.Default.ProgressBarSize.Height; nr.BackgroundColor = Settings.Default.BackgroundColor.ToHTML(); nr.JobFilter = string.Empty; nr.ZoneFilter = string.Empty; nr.TimersMustRunningForStart = new Guid[0]; nr.TimersMustStoppingForStart = new Guid[0]; // 現在選択しているノードの情報を一部コピーする if (this.SpellTimerTreeView.SelectedNode != null) { var baseRow = this.SpellTimerTreeView.SelectedNode.Tag != null ? this.SpellTimerTreeView.SelectedNode.Tag as SpellTimer : this.SpellTimerTreeView.SelectedNode.Nodes[0].Tag as SpellTimer; if (baseRow != null) { nr.Panel = baseRow.Panel; nr.SpellTitle = baseRow.SpellTitle + " New"; nr.SpellIcon = baseRow.SpellIcon; nr.SpellIconSize = baseRow.SpellIconSize; nr.Keyword = baseRow.Keyword; nr.RegexEnabled = baseRow.RegexEnabled; nr.RecastTime = baseRow.RecastTime; nr.KeywordForExtend1 = baseRow.KeywordForExtend1; nr.RecastTimeExtending1 = baseRow.RecastTimeExtending1; nr.KeywordForExtend2 = baseRow.KeywordForExtend2; nr.RecastTimeExtending2 = baseRow.RecastTimeExtending2; nr.ExtendBeyondOriginalRecastTime = baseRow.ExtendBeyondOriginalRecastTime; nr.UpperLimitOfExtension = baseRow.UpperLimitOfExtension; nr.RepeatEnabled = baseRow.RepeatEnabled; nr.ProgressBarVisible = baseRow.ProgressBarVisible; nr.IsReverse = baseRow.IsReverse; nr.FontColor = baseRow.FontColor; nr.FontOutlineColor = baseRow.FontOutlineColor; nr.BarColor = baseRow.BarColor; nr.BarOutlineColor = baseRow.BarOutlineColor; nr.DontHide = baseRow.DontHide; nr.HideSpellName = baseRow.HideSpellName; nr.OverlapRecastTime = baseRow.OverlapRecastTime; nr.ReduceIconBrightness = baseRow.ReduceIconBrightness; nr.FontFamily = baseRow.FontFamily; nr.FontSize = baseRow.FontSize; nr.FontStyle = baseRow.FontStyle; nr.Font = baseRow.Font; nr.BarWidth = baseRow.BarWidth; nr.BarHeight = baseRow.BarHeight; nr.BackgroundColor = baseRow.BackgroundColor; nr.BackgroundAlpha = baseRow.BackgroundAlpha; nr.JobFilter = baseRow.JobFilter; nr.ZoneFilter = baseRow.ZoneFilter; nr.TimersMustRunningForStart = baseRow.TimersMustRunningForStart; nr.TimersMustStoppingForStart = baseRow.TimersMustStoppingForStart; nr.ToInstance = baseRow.ToInstance; } } nr.MatchDateTime = DateTime.MinValue; nr.UpdateDone = false; nr.Enabled = true; nr.DisplayNo = SpellTimerTable.Table.Any() ? SpellTimerTable.Table.Max(x => x.DisplayNo) + 1 : 50; nr.Regex = null; nr.RegexPattern = string.Empty; SpellTimerTable.Table.Add(nr); SpellTimerTable.ClearReplacedKeywords(); SpellTimerTable.RemoveAllInstanceSpells(); SpellTimerTable.Save(); // 新しいノードを生成する var node = new TreeNode(nr.SpellTitle) { Tag = nr, ToolTipText = nr.Keyword, Checked = nr.Enabled }; // 親ノードがあれば追加する foreach (TreeNode item in this.SpellTimerTreeView.Nodes) { if (item.Text == nr.Panel) { item.Nodes.Add(node); this.SpellTimerTreeView.SelectedNode = node; break; } } // 親ノードがなかった if (this.SpellTimerTreeView.SelectedNode != node) { var parentNode = new TreeNode(nr.Panel, new TreeNode[] { node }) { Checked = true }; this.SpellTimerTreeView.Nodes.Add(parentNode); this.SpellTimerTreeView.SelectedNode = node; } // ゾーン限定ボタンの色を変える(未設定:黒、設定有:青) this.SelectZoneButton.ForeColor = nr.ZoneFilter != string.Empty ? Color.Blue : Button.DefaultForeColor; // ジョブ限定ボタンの色を変える(未設定:黒、設定有:青) this.SelectJobButton.ForeColor = nr.JobFilter != string.Empty ? Color.Blue : Button.DefaultForeColor; // 条件設定ボタンの色を変える(未設定:黒、設定有:青) this.SetConditionButton.ForeColor = (nr.TimersMustRunningForStart.Length != 0 || nr.TimersMustStoppingForStart.Length != 0) ? Color.Blue : Button.DefaultForeColor; } // 標準のスペルタイマーへ変更を反映する SpellTimerCore.Default.applyToNormalSpellTimer(); }