/// <summary> /// 不要になったWindowを閉じる /// </summary> /// <param name="telops">Telops</param> public static void GarbageWindows( IReadOnlyList <OnePointTelop> telops) { // 不要になったWindowを閉じる var removeWindowList = new List <OnePointTelopWindow>(); foreach (var window in telopWindowList.Values) { if (!telops.Any(x => x.ID == window.DataSource.ID)) { removeWindowList.Add(window); } } foreach (var window in removeWindowList) { ActInvoker.Invoke(() => { window.DataSource.Left = window.Left; window.DataSource.Top = window.Top; window.Close(); }); telopWindowList.Remove(window.DataSource.ID); } }
/// <summary> /// Panelの位置を設定する /// </summary> public void LayoutPanels() { if (this.SpellTimerPanels != null) { ActInvoker.Invoke(() => { foreach (var panel in this.SpellTimerPanels) { var setting = PanelSettings.Default.SettingsTable .Where(x => x.PanelName == panel.PanelName) .FirstOrDefault(); if (setting != null) { panel.Left = setting.Left; panel.Top = setting.Top; } else { panel.Left = 10.0d; panel.Top = 10.0d; } } }); } }
/// <summary> /// 表示切り替えボタン(スペスペボタン)の状態を切り替える /// </summary> /// <param name="visible"> /// 切り替える状態</param> public static void ChangeSwitchVisibleButton( bool visible) { Settings.Default.OverlayVisible = visible; Settings.Default.Save(); SpellTimerCore.Default.ClosePanels(); OnePointTelopController.CloseTelops(); FF14PluginHelper.RefreshPlayer(); LogBuffer.RefreshPartyList(); LogBuffer.RefreshPetID(); if (Settings.Default.OverlayVisible) { SpellTimerCore.Default.ActivatePanels(); OnePointTelopController.ActivateTelops(); } ActInvoker.Invoke(() => { if (Settings.Default.OverlayVisible) { SwitchVisibleButton.BackColor = Color.OrangeRed; SwitchVisibleButton.ForeColor = Color.WhiteSmoke; } else { SwitchVisibleButton.BackColor = SystemColors.Control; SwitchVisibleButton.ForeColor = Color.Black; } }); }
/// <summary> /// 表示切り替えボタン(スペスペボタン)の状態を切り替える /// </summary> /// <param name="visible"> /// 切り替える状態</param> public static void ChangeSwitchVisibleButton( bool visible) { Settings.Default.OverlayVisible = visible; Settings.Default.Save(); SpellTimerCore.Default.ClosePanels(); OnePointTelopController.CloseTelops(); TableCompiler.Instance.RefreshPlayerPlacceholder(); TableCompiler.Instance.RefreshPartyPlaceholders(); TableCompiler.Instance.RefreshPetPlaceholder(); TableCompiler.Instance.RecompileSpells(); TableCompiler.Instance.RecompileTickers(); if (Settings.Default.OverlayVisible) { SpellTimerCore.Default.ActivatePanels(); OnePointTelopController.ActivateTelops(); } ActInvoker.Invoke(() => { if (Settings.Default.OverlayVisible) { SwitchVisibleButton.BackColor = Color.OrangeRed; SwitchVisibleButton.ForeColor = Color.WhiteSmoke; } else { SwitchVisibleButton.BackColor = SystemColors.Control; SwitchVisibleButton.ForeColor = Color.Black; } }); }
private void ReplaceButton() { if (this.SwitchVisibleButton != null && !this.SwitchVisibleButton.IsDisposed && this.SwitchVisibleButton.IsHandleCreated) { var leftButton = ( from Control x in ActGlobals.oFormActMain.Controls where !x.Equals(this.SwitchVisibleButton) && ( x is Button || x is CheckBox ) orderby x.Left select x).FirstOrDefault(); var location = leftButton != null ? new Point(leftButton.Left - this.SwitchVisibleButton.Width - 1, 0) : new Point(ActGlobals.oFormActMain.Width - 533, 0); ActInvoker.Invoke(() => { if (this.SwitchVisibleButton != null) { this.SwitchVisibleButton.Location = location; } }); } }
/// <summary> /// リスタートのときスペルのカウントをリセットする /// </summary> private void ResetCountAtRestart() { // 無効? if (!Settings.Default.ResetOnWipeOut) { return; } // 0.1秒毎に判定する if ((DateTime.Now - this.lastWipeOutDetectDateTime).TotalSeconds <= 0.1) { return; } this.lastWipeOutDetectDateTime = DateTime.Now; var combatants = FFXIVPlugin.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) { // インスタンススペルを消去する SpellTable.Instance.RemoveInstanceSpellsAll(); SpellTable.ResetCount(); TickerTable.Instance.ResetCount(); this.lastWipeOutDateTime = DateTime.Now; // wipeoutログを発生させる LogParser.RaiseLog(DateTime.Now, CombatAnalyzer.Wipeout); ActInvoker.Invoke(() => { // ACT本体に戦闘終了を通知する if (Settings.Default.WipeoutNotifyToACT) { ActGlobals.oFormActMain.ActCommands("end"); } }); } } }
/// <summary> /// 再生する /// </summary> /// <param name="source"> /// 再生する対象</param> public void Play( string source) { try { if (string.IsNullOrWhiteSpace(source)) { return; } if (this.EnabledYukkuri) { this.ttsYukkuriPlugin.Speak(source); } else { Task.Run(() => { // wav? if (source.EndsWith(".wav")) { // ファイルが存在する? if (File.Exists(source)) { ActInvoker.Invoke(() => { ActGlobals.oFormActMain.PlaySound(source); }); } } else { ActInvoker.Invoke(() => { ActGlobals.oFormActMain.TTS(source); }); } }).ContinueWith((t) => { if (t != null) { t.Dispose(); } }); } } catch (Exception ex) { ActGlobals.oFormActMain.WriteExceptionLog( ex, Translate.Get("SoundError")); } }
/// <summary> /// Panelを隠す /// </summary> public void HidePanels() { if (this.SpellTimerPanels != null) { ActInvoker.Invoke(() => { foreach (var panel in this.SpellTimerPanels) { panel.HideOverlay(); } }); } }
/// <summary> /// テロップをActive化する /// </summary> public static void ActivateTelops() { if (telopWindowList != null) { ActInvoker.Invoke(() => { foreach (var telop in telopWindowList.Values) { telop.Activate(); } }); } }
/// <summary> /// テロップを隠す /// </summary> public static void HideTelops() { if (telopWindowList != null) { ActInvoker.Invoke(() => { foreach (var telop in telopWindowList.Values) { telop.HideOverlay(); } }); } }
/// <summary> /// 表示切り替えボタン(スペスペボタン)の状態を切り替える /// </summary> /// <param name="visible"> /// 切り替える状態</param> public async void ChangeSwitchVisibleButton( bool visible) { await Task.Run(() => { this.SwitchOverlay(visible); }); ActInvoker.Invoke(() => { this.ChangeButtonColor(); }); }
/// <summary> /// Panelをアクティブ化する /// </summary> public void ActivatePanels() { if (this.SpellTimerPanels != null) { ActInvoker.Invoke(() => { foreach (var panel in this.SpellTimerPanels) { panel.Activate(); } }); } }
/// <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> /// 不要なスペルタイマWindowを閉じる /// </summary> /// <param name="spells">Spell</param> private void GarbageSpellPanelWindows( IReadOnlyList <Models.SpellTimer> spells) { if (this.SpellTimerPanels != null) { var removeList = new List <SpellTimerListWindow>(); foreach (var panel in this.SpellTimerPanels) { // パネルの位置を保存する var setting = ( from x in PanelSettings.Default.SettingsTable where x.PanelName == panel.PanelName select x).FirstOrDefault(); if (setting == null) { setting = PanelSettings.Default.SettingsTable.NewPanelSettingsRow(); PanelSettings.Default.SettingsTable.AddPanelSettingsRow(setting); } setting.PanelName = panel.PanelName; setting.Left = panel.Left; setting.Top = panel.Top; // 毎分0秒の時保存する if (DateTime.Now.Second == 0) { PanelSettings.Default.Save(); } // スペルリストに存在しないパネルを閉じる if (!spells.Any(x => x.Panel == panel.PanelName)) { ActInvoker.Invoke(() => panel.Close()); removeList.Add(panel); } } foreach (var item in removeList) { this.SpellTimerPanels.Remove(item); } } }
public void Wipeout( bool isRaiseWipeoutLog = true) { // リセットするのは10秒に1回にする // 暗転中もずっとリセットし続けてしまうので var now = DateTime.Now; if ((now - this.lastWipeOutDateTime).TotalSeconds >= 10.0) { this.lastWipeOutDateTime = now; Task.Run(() => { if (Settings.Default.WipeoutNotifyToACT) { CommonSounds.Instance.PlayWipeout(); } // ChatログをFlushする ParsedLogWorker.Instance.Flush(true); Thread.Sleep(TimeSpan.FromSeconds(1)); // ACT本体に戦闘終了を通知する if (Settings.Default.WipeoutNotifyToACT) { ActInvoker.Invoke(() => ActGlobals.oFormActMain.EndCombat(true)); } // トリガーをリセットする SpellTable.ResetCount(); TickerTable.Instance.ResetCount(); // wipeoutログを発生させる if (isRaiseWipeoutLog) { Task.Run(() => { Thread.Sleep(200); LogParser.RaiseLog(now, WipeoutKeywords.Wipeout); }); } }); } }
/// <summary> /// テロップを閉じる /// </summary> public static void CloseTelops() { if (telopWindowList != null) { ActInvoker.Invoke(() => { foreach (var telop in telopWindowList.Values) { telop.DataSource.Left = telop.Left; telop.DataSource.Top = telop.Top; telop.Close(); } }); OnePointTelopTable.Default.Save(); telopWindowList.Clear(); } }
/// <summary> /// Panelを閉じる /// </summary> public void ClosePanels() { if (this.SpellTimerPanels != null) { ActInvoker.Invoke(() => { // Panelの位置を保存する foreach (var panel in this.SpellTimerPanels) { var setting = ( from x in PanelSettings.Default.SettingsTable where x.PanelName == panel.PanelName select x).FirstOrDefault(); if (setting == null) { setting = PanelSettings.Default.SettingsTable.NewPanelSettingsRow(); PanelSettings.Default.SettingsTable.AddPanelSettingsRow(setting); } setting.PanelName = panel.PanelName; setting.Left = panel.Left; setting.Top = panel.Top; } if (this.SpellTimerPanels.Count > 0) { PanelSettings.Default.Save(); } foreach (var panel in this.SpellTimerPanels) { panel.Close(); } this.SpellTimerPanels.Clear(); }); } }
/// <summary> /// リスタートのときスペルのカウントをリセットする /// </summary> public void ResetCountAtRestart() { // 無効? if (!Settings.Default.ResetOnWipeOut) { return; } if ((DateTime.Now - this.lastWipeOutDetectDateTime).TotalSeconds <= 0.1) { return; } this.lastWipeOutDetectDateTime = DateTime.Now; var player = CombatantsManager.Instance.Player; var party = CombatantsManager.Instance.GetPartyList(); if (party == null || party.Count() < 1) { if (player == null || player.ID == 0) { return; } party = new[] { player }; } // 異常なデータ? if (party.Count() > 1) { var first = party.First(); if (party.Count() == party.Count(x => x.CurrentHP == first.CurrentHP && x.MaxHP == first.MaxHP)) { return; } if (!party.Any(x => x.IsPlayer)) { return; } } if (player != null) { switch (player.JobInfo.Role) { case Roles.Crafter: case Roles.Gatherer: return; } } // 関係者が全員死んでる? if (party.Count() == party.Count(x => x.CurrentHP <= 0 && x.MaxHP > 0)) { // リセットするのは10秒に1回にする // 暗転中もずっとリセットし続けてしまうので var now = DateTime.Now; if ((now - this.lastWipeOutDateTime).TotalSeconds >= 10.0) { this.lastWipeOutDateTime = now; Task.Run(() => { Thread.Sleep(TimeSpan.FromSeconds(1)); // ACT本体に戦闘終了を通知する if (Settings.Default.WipeoutNotifyToACT) { ActInvoker.Invoke(() => ActGlobals.oFormActMain.EndCombat(true)); CommonSounds.Instance.PlayWipeout(); } // トリガーをリセットする SpellTable.ResetCount(); TickerTable.Instance.ResetCount(); // wipeoutログを発生させる Task.Run(() => { Thread.Sleep(200); LogParser.RaiseLog(now, ConstantKeywords.Wipeout); }); }); } } }
/// <summary> /// ログとマッチングする /// </summary> /// <param name="logLines">ログ行</param> public static void Match( string[] logLines) { var telops = OnePointTelopTable.Default.EnabledTable; // 不要になったWindowを閉じる var removeWindowList = new List <OnePointTelopWindow>(); foreach (var window in telopWindowList.Values) { if (!telops.Any(x => x.ID == window.DataSource.ID)) { removeWindowList.Add(window); } } foreach (var window in removeWindowList) { ActInvoker.Invoke(() => { window.DataSource.Left = window.Left; window.DataSource.Top = window.Top; window.Close(); }); telopWindowList.Remove(window.DataSource.ID); } foreach (var telop in telops.AsParallel()) { var regex = telop.Regex; var regexToHide = telop.RegexToHide; var isForceHide = false; foreach (var log in logLines) { // 通常マッチ if (regex == null) { var keyword = LogBuffer.MakeKeyword(telop.Keyword); if (!string.IsNullOrWhiteSpace(keyword)) { if (log.ToUpper().Contains( keyword.ToUpper())) { if (!telop.AddMessageEnabled) { telop.MessageReplaced = telop.Message; } else { telop.MessageReplaced += string.IsNullOrWhiteSpace(telop.MessageReplaced) ? telop.Message : Environment.NewLine + telop.Message; } telop.MatchDateTime = DateTime.Now; telop.Delayed = false; telop.MatchedLog = log; SoundController.Default.Play(telop.MatchSound); SoundController.Default.Play(telop.MatchTextToSpeak); continue; } } } // 正規表現マッチ if (regex != null) { if (regex.IsMatch(log)) { if (!telop.AddMessageEnabled) { telop.MessageReplaced = regex.Replace(log, telop.Message); } else { telop.MessageReplaced += string.IsNullOrWhiteSpace(telop.MessageReplaced) ? regex.Replace(log, telop.Message) : Environment.NewLine + regex.Replace(log, telop.Message); } telop.MatchDateTime = DateTime.Now; telop.Delayed = false; telop.MatchedLog = log; SoundController.Default.Play(telop.MatchSound); if (!string.IsNullOrWhiteSpace(telop.MatchTextToSpeak)) { var tts = regex.Replace(log, telop.MatchTextToSpeak); SoundController.Default.Play(tts); } continue; } } // 通常マッチ(強制非表示) if (regexToHide == null) { var keyword = LogBuffer.MakeKeyword(telop.KeywordToHide); if (!string.IsNullOrWhiteSpace(keyword)) { if (log.ToUpper().Contains( keyword.ToUpper())) { isForceHide = true; continue; } } } // 正規表現マッチ(強制非表示) if (regexToHide != null) { if (regexToHide.IsMatch(log)) { isForceHide = true; continue; } } } // end loop logLines // ディレイ時間が経過した? if (!telop.Delayed && telop.MatchDateTime > DateTime.MinValue && telop.Delay > 0) { var delayed = telop.MatchDateTime.AddSeconds(telop.Delay); if (DateTime.Now >= delayed) { telop.Delayed = true; SoundController.Default.Play(telop.DelaySound); var tts = regex != null && !string.IsNullOrWhiteSpace(telop.DelayTextToSpeak) ? regex.Replace(telop.MatchedLog, telop.DelayTextToSpeak) : telop.DelayTextToSpeak; SoundController.Default.Play(tts); } } var w = telopWindowList.ContainsKey(telop.ID) ? telopWindowList[telop.ID] : null; if (w == null) { w = new OnePointTelopWindow() { Title = "OnePointTelop - " + telop.Title, DataSource = telop }; if (Settings.Default.ClickThroughEnabled) { w.ToTransparentWindow(); } w.Opacity = 0; w.Show(); telopWindowList.Add(telop.ID, w); } // telopの位置を保存する if (DateTime.Now.Second == 0) { telop.Left = w.Left; telop.Top = w.Top; OnePointTelopTable.Default.Save(); } if (Settings.Default.OverlayVisible && Settings.Default.TelopAlwaysVisible) { // ドラッグ中じゃない? if (!w.IsDragging) { w.Refresh(); w.ShowOverlay(); } continue; } if (telop.MatchDateTime > DateTime.MinValue) { var start = telop.MatchDateTime.AddSeconds(telop.Delay); var end = telop.MatchDateTime.AddSeconds(telop.Delay + telop.DisplayTime); if (start <= DateTime.Now && DateTime.Now <= end) { w.Refresh(); w.ShowOverlay(); } else { w.HideOverlay(); if (DateTime.Now > end) { telop.MatchDateTime = DateTime.MinValue; telop.MessageReplaced = string.Empty; } } if (isForceHide) { w.HideOverlay(); telop.MatchDateTime = DateTime.MinValue; telop.MessageReplaced = string.Empty; } } else { w.HideOverlay(); telop.MessageReplaced = string.Empty; } } // end loop telops }
/// <summary> /// Commandとマッチングする /// </summary> /// <param name="logLines"> /// ログ行</param> public static void MatchCommand( IReadOnlyList <string> logLines) { var commandDone = false; foreach (var log in logLines) { // 正規表現の前にキーワードがなければ抜けてしまう if (!log.ToLower().Contains("/spespe")) { continue; } var match = regexCommand.Match(log); if (!match.Success) { continue; } var command = match.Groups["command"].ToString().ToLower(); var target = match.Groups["target"].ToString().ToLower(); var windowname = match.Groups["windowname"].ToString().Replace(@"""", string.Empty); var valueAsText = match.Groups["value"].ToString(); var value = false; if (!bool.TryParse(valueAsText, out value)) { value = false; } switch (command) { case "analyze": switch (target) { case "on": SpecialSpellTimerPlugin.ConfigPanel.CombatAnalyzerEnabled = true; commandDone = true; break; case "off": SpecialSpellTimerPlugin.ConfigPanel.CombatAnalyzerEnabled = false; commandDone = true; break; } break; case "refresh": switch (target) { case "spells": SpellTimerCore.Default.ClosePanels(); commandDone = true; break; case "telops": OnePointTelopController.CloseTelops(); commandDone = true; break; case "me": FF14PluginHelper.RefreshPlayer(); commandDone = true; break; case "pt": LogBuffer.RefreshPartyList(); commandDone = true; break; case "pet": LogBuffer.RefreshPetID(); commandDone = true; break; } break; case "changeenabled": var changed = false; switch (target) { case "spells": foreach (var spell in SpellTimerTable.Table) { if (spell.Panel.Trim().ToLower() == windowname.Trim().ToLower() || spell.SpellTitle.Trim().ToLower() == windowname.Trim().ToLower() || windowname.Trim().ToLower() == "all") { changed = true; spell.Enabled = value; } } if (changed) { ActInvoker.Invoke(() => { SpecialSpellTimerPlugin.ConfigPanel.LoadSpellTimerTable(); }); commandDone = true; } break; case "telops": foreach (var telop in OnePointTelopTable.Default.Table) { if (telop.Title.Trim().ToLower() == windowname.Trim().ToLower() || windowname.Trim().ToLower() == "all") { changed = true; telop.Enabled = value; } } if (changed) { ActInvoker.Invoke(() => { SpecialSpellTimerPlugin.ConfigPanel.LoadTelopTable(); }); commandDone = true; } break; } break; case "set": switch (target) { case "placeholder": if (windowname.Trim().ToLower() != "all" && windowname.Trim() != string.Empty && valueAsText.Trim() != string.Empty) { LogBuffer.SetCustomPlaceholder(windowname.Trim(), valueAsText.Trim()); commandDone = true; } break; } break; case "clear": switch (target) { case "placeholder": if (windowname.Trim().ToLower() == "all") { LogBuffer.ClearCustomPlaceholderAll(); commandDone = true; } else if (windowname.Trim() != string.Empty) { LogBuffer.ClearCustomPlaceholder(windowname.Trim()); commandDone = true; } break; } break; case "on": SpecialSpellTimerPlugin.ChangeSwitchVisibleButton(true); commandDone = true; break; case "off": SpecialSpellTimerPlugin.ChangeSwitchVisibleButton(false); commandDone = true; break; } } // loop end logLines // コマンドを実行したらシステム音を鳴らす if (commandDone) { SystemSounds.Asterisk.Play(); } } // method end
/// <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.Instance.EnumlateWave(); this.MatchSoundComboBox.ValueMember = "FullPath"; this.MatchSoundComboBox.DisplayMember = "Name"; this.OverSoundComboBox.DataSource = SoundController.Instance.EnumlateWave(); this.OverSoundComboBox.ValueMember = "FullPath"; this.OverSoundComboBox.DisplayMember = "Name"; this.BeforeSoundComboBox.DataSource = SoundController.Instance.EnumlateWave(); this.BeforeSoundComboBox.ValueMember = "FullPath"; this.BeforeSoundComboBox.DisplayMember = "Name"; this.TimeupSoundComboBox.DataSource = SoundController.Instance.EnumlateWave(); this.TimeupSoundComboBox.ValueMember = "FullPath"; this.TimeupSoundComboBox.DisplayMember = "Name"; // イベントを設定する 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.Instance.Play((string)this.MatchSoundComboBox.SelectedValue ?? string.Empty); }; this.Play2Button.Click += (s1, e1) => { SoundController.Instance.Play((string)this.OverSoundComboBox.SelectedValue ?? string.Empty); }; this.Play3Button.Click += (s1, e1) => { SoundController.Instance.Play((string)this.TimeupSoundComboBox.SelectedValue ?? string.Empty); }; this.Play4Button.Click += (s1, e1) => { SoundController.Instance.Play((string)this.BeforeSoundComboBox.SelectedValue ?? string.Empty); }; this.Speak1Button.Click += (s1, e1) => { SoundController.Instance.Play(this.MatchTextToSpeakTextBox.Text); }; this.Speak2Button.Click += (s1, e1) => { SoundController.Instance.Play(this.OverTextToSpeakTextBox.Text); }; this.Speak3Button.Click += (s1, e1) => { SoundController.Instance.Play(this.TimeupTextToSpeakTextBox.Text); }; this.Speak4Button.Click += (s1, e1) => { SoundController.Instance.Play(this.BeforeTextToSpeakTextBox.Text); }; this.SpellTimerTreeView.AfterCheck += (s1, e1) => { var source = e1.Node.Tag as Spell; if (source != null) { source.Enabled = e1.Node.Checked; source.UpdateDone = false; } else { foreach (TreeNode node in e1.Node.Nodes) { var sourceChild = node.Tag as Spell; if (sourceChild != null) { sourceChild.Enabled = e1.Node.Checked; } node.Checked = e1.Node.Checked; } } // キャッシュを無効にする TableCompiler.Instance.RecompileSpells(); // スペルの有効・無効が変化した際に、標準のスペルタイマーに反映する SpellsController.Instance.ApplyToNormalSpellTimer(); }; this.SelectJobButton.Click += async(s1, e1) => { var src = this.DetailGroupBox.Tag as Spell; if (src != null) { using (var f = new SelectJobForm()) { f.JobFilter = src.JobFilter; if (await Task.Run(() => f.ShowDialog(this.ParentForm)) == DialogResult.OK) { src.JobFilter = f.JobFilter; // ジョブ限定ボタンの色を変える(未設定:黒、設定有:青) this.SelectJobButton.ForeColor = src.JobFilter != string.Empty ? Color.Blue : Button.DefaultForeColor; } } } }; this.SelectZoneButton.Click += async(s1, e1) => { var src = this.DetailGroupBox.Tag as Spell; if (src != null) { using (var f = new SelectZoneForm()) { f.ZoneFilter = src.ZoneFilter; if (await Task.Run(() => f.ShowDialog(this.ParentForm)) == DialogResult.OK) { src.ZoneFilter = f.ZoneFilter; // ゾーン限定ボタンの色を変える(未設定:黒、設定有:青) this.SelectZoneButton.ForeColor = src.ZoneFilter != string.Empty ? Color.Blue : Button.DefaultForeColor; } } } }; this.SetConditionButton.Click += async(s1, e1) => { var src = this.DetailGroupBox.Tag as Spell; if (src != null) { using (var f = new SetConditionForm()) { f.TimersMustRunning = src.TimersMustRunningForStart; f.TimersMustStopping = src.TimersMustStoppingForStart; if (await Task.Run(() => f.ShowDialog(this.ParentForm)) == 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.SelectIconButton.Click += async(s1, e1) => { var selectedIcon = (string)this.SelectIconButton.Tag; var spell = this.DetailGroupBox.Tag as Spell; var result = await SelectIconForm.ShowDialogAsync( selectedIcon, this, spell); if (result.Result) { ActInvoker.Invoke(() => { this.SelectIconButton.Tag = result.Icon; this.SelectIconButton.BackgroundImageLayout = ImageLayout.Zoom; this.SelectIconButton.BackgroundImage = null; this.SelectIconButton.FlatAppearance.BorderSize = 1; var icon = IconController.Instance.GetIconFile(result.Icon); if (icon != null && File.Exists(icon.FullPath)) { this.SelectIconButton.BackgroundImage = System.Drawing.Image.FromFile( icon.FullPath); this.SelectIconButton.FlatAppearance.BorderSize = 0; } this.SpellVisualSetting.SpellIcon = result.Icon; 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.TemporarilyDisplaySpellCheckBox.CheckedChanged += (s1, e1) => { var src = this.DetailGroupBox.Tag as Spell; if (src == null) { return; } src.IsTemporaryDisplay = this.TemporarilyDisplaySpellCheckBox.Checked; src.UpdateDone = false; TableCompiler.Instance.RecompileSpells(); }; // スペルパネル単位のエクスポート this.ExportBySpellPanelButton.Click += this.ExportBySpellPanelButton_Click; // オプションのロードメソッドを呼ぶ this.LoadOption(); this.LoadDQXOption(); // ワンポイントテロップのロードメソッドを呼ぶ this.LoadOnePointTelop(); // 戦闘アナライザのロードメソッドを呼ぶ this.LoadCombatAnalyzer(); }
/// <summary> /// リスタートのときスペルのカウントをリセットする /// </summary> public void ResetCountAtRestart() { // 無効? if (!Settings.Default.ResetOnWipeOut) { return; } if ((DateTime.Now - this.lastWipeOutDetectDateTime).TotalSeconds <= 0.1) { return; } this.lastWipeOutDetectDateTime = DateTime.Now; var party = default(IEnumerable <Combatant>); party = FFXIVPlugin.Instance.GetPartyList(); if (party == null || party.Count() < 1) { return; } // 異常なデータ? if (party.Count() > 1) { var first = party.First(); if (party.Count() == party.Count(x => x.CurrentHP == first.CurrentHP && x.MaxHP == first.MaxHP)) { return; } if (!party.Any(x => x.IsPlayer)) { return; } if (party.Any(x => x.IsNPC())) { return; } } var player = FFXIVPlugin.Instance.GetPlayer(); if (player != null) { switch (player.AsJob().Role) { case Roles.Crafter: case Roles.Gatherer: return; } } // 関係者が全員死んでる? if (party.Count() == party.Count(x => x.CurrentHP <= 0 && x.MaxHP > 0)) { // リセットするのは15秒に1回にする // 暗転中もずっとリセットし続けてしまうので if ((DateTime.Now - this.lastWipeOutDateTime).TotalSeconds >= 15.0) { this.lastWipeOutDateTime = DateTime.Now; // インスタンススペルを消去する SpellTable.ResetCount(); TickerTable.Instance.ResetCount(); // wipeoutログを発生させる LogParser.RaiseLog(DateTime.Now, ConstantKeywords.Wipeout); ActInvoker.Invoke(() => { // ACT本体に戦闘終了を通知する if (Settings.Default.WipeoutNotifyToACT) { ActGlobals.oFormActMain.ActCommands("end"); } }); } } }
/// <summary> /// ログ1行とマッチングする /// </summary> /// <param name="logLine">ログ行</param> /// <returns> /// コマンドを実行したか?</returns> public static bool MatchCommandCore( string logLine) { var r = false; // 正規表現の前にキーワードがなければ抜けてしまう if (!logLine.ToLower().Contains("/spespe")) { return(r); } var match = regexCommand.Match(logLine); if (!match.Success) { return(r); } var command = match.Groups["command"].ToString().ToLower(); var target = match.Groups["target"].ToString().ToLower(); var windowname = match.Groups["windowname"].ToString().Replace(@"""", string.Empty); var valueAsText = match.Groups["value"].ToString(); var value = false; if (!bool.TryParse(valueAsText, out value)) { value = false; } switch (command) { case "analyze": switch (target) { case "on": PluginCore.Instance.ConfigPanel.CombatAnalyzerEnabled = true; r = true; break; case "off": PluginCore.Instance.ConfigPanel.CombatAnalyzerEnabled = false; r = true; break; } break; case "refresh": switch (target) { case "spells": SpellsController.Instance.ClosePanels(); r = true; break; case "telops": TickersController.Instance.CloseTelops(); r = true; break; case "pt": TableCompiler.Instance.RefreshPlayerPlacceholder(); TableCompiler.Instance.RefreshPartyPlaceholders(); TableCompiler.Instance.RecompileSpells(); TableCompiler.Instance.RecompileTickers(); r = true; break; case "pet": TableCompiler.Instance.RefreshPetPlaceholder(); TableCompiler.Instance.RecompileSpells(); TableCompiler.Instance.RecompileTickers(); r = true; break; } break; case "changeenabled": var changed = false; switch (target) { case "spells": foreach (var spell in SpellTimerTable.Instance.Table) { if (spell.Panel.Trim().ToLower() == windowname.Trim().ToLower() || spell.SpellTitle.Trim().ToLower() == windowname.Trim().ToLower() || windowname.Trim().ToLower() == "all") { changed = true; spell.Enabled = value; } } if (changed) { ActInvoker.Invoke(() => { PluginCore.Instance.ConfigPanel.LoadSpellTimerTable(); }); r = true; } break; case "telops": foreach (var telop in OnePointTelopTable.Instance.Table) { if (telop.Title.Trim().ToLower() == windowname.Trim().ToLower() || windowname.Trim().ToLower() == "all") { changed = true; telop.Enabled = value; } } if (changed) { ActInvoker.Invoke(() => { PluginCore.Instance.ConfigPanel.LoadTelopTable(); }); r = true; } break; } break; case "set": switch (target) { case "placeholder": if (windowname.Trim().ToLower() != "all" && windowname.Trim() != string.Empty && valueAsText.Trim() != string.Empty) { TableCompiler.Instance.SetCustomPlaceholder(windowname.Trim(), valueAsText.Trim()); r = true; } break; } break; case "clear": switch (target) { case "placeholder": if (windowname.Trim().ToLower() == "all") { TableCompiler.Instance.ClearCustomPlaceholderAll(); r = true; } else if (windowname.Trim() != string.Empty) { TableCompiler.Instance.ClearCustomPlaceholder(windowname.Trim()); r = true; } break; } break; case "on": PluginCore.Instance.ChangeSwitchVisibleButton(true); r = true; break; case "off": PluginCore.Instance.ChangeSwitchVisibleButton(false); r = true; break; } return(r); }
/// <summary> /// Windowを更新する /// </summary> private void RefreshWindow() { #if DEBUG var sw1 = Stopwatch.StartNew(); #endif // 有効なSpellリストを取得する var spellArray = SpellTimerTable.EnabledTable; // 不要なWindowを閉じる if (this.SpellTimerPanels != null) { var removeList = new List <SpellTimerListWindow>(); foreach (var panel in this.SpellTimerPanels) { // パネルの位置を保存する var setting = ( from x in PanelSettings.Default.SettingsTable where x.PanelName == panel.PanelName select x).FirstOrDefault(); if (setting == null) { setting = PanelSettings.Default.SettingsTable.NewPanelSettingsRow(); PanelSettings.Default.SettingsTable.AddPanelSettingsRow(setting); } setting.PanelName = panel.PanelName; setting.Left = panel.Left; setting.Top = panel.Top; // 毎分0秒の時保存する if (DateTime.Now.Second == 0) { PanelSettings.Default.Save(); } // スペルリストに存在しないパネルを閉じる if (!spellArray.Any(x => x.Panel == panel.PanelName)) { ActInvoker.Invoke(() => panel.Close()); removeList.Add(panel); } } foreach (var item in removeList) { this.SpellTimerPanels.Remove(item); } } #if DEBUG sw1.Stop(); Debug.WriteLine("Refresh ClosePanels ->" + sw1.ElapsedMilliseconds.ToString("N0") + "ms"); #endif // ACTが起動していない? if (ActGlobals.oFormActMain == null || !ActGlobals.oFormActMain.Visible) { this.HidePanels(); this.RefreshInterval = 1000; return; } if ((DateTime.Now - this.LastFFXIVProcessDateTime).TotalSeconds >= 5.0d) { // FF14が起動していない? if (FF14PluginHelper.GetFFXIVProcess == null) { this.RefreshInterval = 1000; if (!Settings.Default.OverlayForceVisible) { this.ClosePanels(); OnePointTelopController.CloseTelops(); return; } } this.LastFFXIVProcessDateTime = DateTime.Now; } // タイマの間隔を標準に戻す this.RefreshInterval = Settings.Default.RefreshInterval; // ログを取り出す #if DEBUG var sw2 = Stopwatch.StartNew(); #endif var logLines = this.LogBuffer.GetLogLines(); #if DEBUG sw2.Stop(); Debug.WriteLine("Refresh GetLog ->" + sw2.ElapsedMilliseconds.ToString("N0") + "ms"); #endif // テロップとマッチングする #if DEBUG var sw3 = Stopwatch.StartNew(); #endif OnePointTelopController.Match( logLines); #if DEBUG sw3.Stop(); Debug.WriteLine("Refresh MatchTelop ->" + sw3.ElapsedMilliseconds.ToString("N0") + "ms"); #endif // スペルリストとマッチングする #if DEBUG var sw4 = Stopwatch.StartNew(); #endif this.MatchSpells( spellArray, logLines); #if DEBUG sw4.Stop(); Debug.WriteLine("Refresh MatchSpell ->" + sw4.ElapsedMilliseconds.ToString("N0") + "ms"); #endif // コマンドとマッチングする TextCommandController.MatchCommand( logLines); // オーバーレイが非表示? if (!Settings.Default.OverlayVisible) { this.HidePanels(); OnePointTelopController.HideTelops(); return; } // Windowを表示する #if DEBUG var sw5 = Stopwatch.StartNew(); #endif var panelNames = spellArray.Select(x => x.Panel.Trim()).Distinct(); foreach (var name in panelNames) { var w = this.SpellTimerPanels.Where(x => x.PanelName == name).FirstOrDefault(); if (w == null) { w = new SpellTimerListWindow() { Title = "SpecialSpellTimer - " + name, PanelName = name, }; this.SpellTimerPanels.Add(w); // クリックスルー? if (Settings.Default.ClickThroughEnabled) { w.ToTransparentWindow(); } w.Show(); } w.SpellTimers = ( from x in spellArray where x.Panel.Trim() == name select x).ToArray(); // ドラッグ中じゃない? if (!w.IsDragging) { w.RefreshSpellTimer(); } } #if DEBUG sw5.Stop(); Debug.WriteLine("Refresh RefreshSpell ->" + sw5.ElapsedMilliseconds.ToString("N0") + "ms"); #endif }