Skip to content

Commit

Permalink
alarm base code - wip for #53
Browse files Browse the repository at this point in the history
  • Loading branch information
xorus committed Jan 2, 2024
1 parent bd12ea2 commit a146685
Show file tree
Hide file tree
Showing 11 changed files with 361 additions and 23 deletions.
1 change: 1 addition & 0 deletions Plugin/Configuration/ConfigurationFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public enum TextAlign
public DtrConfiguration Dtr = new();
public FloatingWindowConfiguration FloatingWindow = new();
public WebServerConfiguration WebServer = new();
public CombatAlarmsConfiguration CombatAlarms = new();

public int Version { get; set; } = 3;

Expand Down
54 changes: 54 additions & 0 deletions Plugin/Configuration/Legacy/CombatAlarmsConfiguration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// This file is part of EngageTimer
// Copyright (C) 2023 Xorus <xorus@posteo.net>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

using System.Collections.Generic;
using System.Numerics;

namespace EngageTimer.Configuration.Legacy;

public class CombatAlarmsConfiguration
{
public enum TextType
{
DalamudNotification = 0,
GameToast = 1,
ChatLogMessage = 2
}

public class Alarm
{
public bool Enabled = true;
public int StartTime;
public int Duration;
public string? Text;
public Vector4? Color;
public int? Sfx;
public TextType TextType = TextType.DalamudNotification;
public bool Blink;
}

public readonly List<Alarm> Alarms = new()
{
// new Alarm()
// {
// StartTime = 5,
// Duration = 30,
// TextType = TextType.DalamudNotification,
// Color = new Vector4(255, 0, 0, 1),
// Text = "Potion Window!",
// Sfx = 16
// }
};
}
20 changes: 14 additions & 6 deletions Plugin/Game/SFXPlay.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,27 @@ public GameSound()

public class SfxPlay
{
public const uint FirstSeSfx = 37 - 1;
public const uint SmallTick = 29;
public const uint CdTick = 48;
private readonly GameSound _gameSound = new();

public void SoundEffect(uint id)
public SfxPlay()
{
/* Force a sound to play on load as a workaround for the CLR taking some time to init the pointy method call,
* we dont want a freeze midway through a countdown
* https://discord.com/channels/581875019861328007/653504487352303619/988123102116450335
* https://i.imgur.com/BrLUr2p.png
* */
SoundEffect(0); // should be cursor sound
}

public unsafe void SoundEffect(uint id)
{
// var s = new Stopwatch();
// s.Start();
unsafe
{
_gameSound.PlaySoundEffect(id, IntPtr.Zero, IntPtr.Zero, 0);
}
_gameSound.PlaySoundEffect(id, IntPtr.Zero, IntPtr.Zero, 0);
// s.Stop();
// PluginIoC.Logger.Debug("Sound play took " + s.ElapsedMilliseconds + "ms");
// Plugin.Logger.Debug("Sound play took " + s.ElapsedMilliseconds + "ms");
}
}
18 changes: 3 additions & 15 deletions Plugin/Game/TickingSound.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,28 +19,16 @@ namespace EngageTimer.Game;

public class TickingSound
{
private readonly SfxPlay _sfx = new();

private int? _lastNumberPlayed;

// This is a workaround for CLR taking some time to init the pointy method call.
private bool _soundLoaded;

public void Update()
{
// if (!_configuration.DisplayCountdown) return;
var configuration = Plugin.Config;
var state = Plugin.State;
if (!configuration.Countdown.EnableTickingSound || state.Mocked) return;
if (!_soundLoaded)
{
_sfx.SoundEffect(0); // should be cursor sound
_soundLoaded = true;
return;
}

if (state.CountingDown &&
state.CountDownValue > 5 && state.CountDownValue <= configuration.Countdown.StartTickingFrom)
if (state is { CountingDown: true, CountDownValue: > 5 } &&
state.CountDownValue <= configuration.Countdown.StartTickingFrom)
TickSound((int)Math.Ceiling(state.CountDownValue));
}

Expand All @@ -50,6 +38,6 @@ private void TickSound(int n)
if (!configuration.Countdown.EnableTickingSound || _lastNumberPlayed == n)
return;
_lastNumberPlayed = n;
_sfx.SoundEffect(configuration.Countdown.UseAlternativeSound ? SfxPlay.SmallTick : SfxPlay.CdTick);
Plugin.SfxPlay.SoundEffect(configuration.Countdown.UseAlternativeSound ? SfxPlay.SmallTick : SfxPlay.CdTick);
}
}
9 changes: 8 additions & 1 deletion Plugin/Plugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
using Dalamud.Plugin.Services;
using EngageTimer.Commands;
using EngageTimer.Configuration;
using EngageTimer.Game;
using EngageTimer.Status;
using EngageTimer.Ui;
using JetBrains.Annotations;
Expand All @@ -39,6 +40,7 @@ public sealed class Plugin : IDalamudPlugin
[PluginService] public static IGameInteropProvider GameInterop { get; private set; } = null!;
[PluginService] public static IPluginLog Logger { get; private set; } = null!;
[PluginService] public static IAddonLifecycle AddonLifecycle { get; private set; } = null!;
[PluginService] public static IToastGui ToastGui { get; private set; } = null!;
public static ConfigurationFile Config { get; private set; } = null!;
public static State State { get; private set; } = null!;
public static Translator Translator { get; private set; } = null!;
Expand All @@ -48,6 +50,8 @@ public sealed class Plugin : IDalamudPlugin
private static FrameworkThings FrameworkThings { get; set; } = null!;
private static MainCommand MainCommand { get; set; } = null!;
private static SettingsCommand SettingsCommand { get; set; } = null!;
private static CombatAlarm CombatAlarm { get; set; } = null!;
public static SfxPlay SfxPlay { get; set; } = null!;

public Plugin(DalamudPluginInterface pluginInterface)
{
Expand All @@ -60,15 +64,18 @@ public Plugin(DalamudPluginInterface pluginInterface)
MainCommand = new MainCommand();
SettingsCommand = new SettingsCommand();
PluginUi = new PluginUi();
CombatAlarm = new CombatAlarm();
SfxPlay = new SfxPlay();
}

void IDisposable.Dispose()
{
PluginInterface.SavePluginConfig(Config);
Translator.Dispose();
CombatAlarm.Dispose();
PluginUi.Dispose();
FrameworkThings.Dispose();
MainCommand.Dispose();
SettingsCommand.Dispose();
Translator.Dispose();
}
}
165 changes: 165 additions & 0 deletions Plugin/Status/CombatAlarm.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
// This file is part of EngageTimer
// Copyright (C) 2023 Xorus <xorus@posteo.net>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

using System;
using System.Collections.Generic;
using System.Net.Mime;
using Dalamud.Game.Gui.Toast;
using Dalamud.Game.Text;
using Dalamud.Interface.Internal.Notifications;
using Dalamud.Plugin.Services;
using EngageTimer.Configuration.Legacy;
using EngageTimer.Game;

namespace EngageTimer.Status;

public sealed class CombatAlarm : IDisposable
{
private enum AlarmActionType
{
Start,
Stop
}

private class AlarmAction
{
public AlarmActionType Type { get; init; }
public int Id { get; init; }
public CombatAlarmsConfiguration.Alarm Config { get; init; } = null!;
}

private readonly Dictionary<int, AlarmAction> _alarms = new();

// private readonly List<int> _rangAlarms = new();
private int? _lastCheck = null;

public CombatAlarm()
{
Plugin.Config.OnSave += ConfigurationChanged;
Plugin.Framework.Update += FrameworkUpdate;
ConfigurationChanged(null, EventArgs.Empty);
Plugin.State.InCombatChanged += InCombatChanged;
}


private void ConfigurationChanged(object? sender, EventArgs e)
{
_alarms.Clear();
for (var index = 0; index < Plugin.Config.CombatAlarms.Alarms.Count; index++)
{
var alarm = Plugin.Config.CombatAlarms.Alarms[index];
_alarms[alarm.StartTime] = new AlarmAction()
{
Type = AlarmActionType.Start,
Id = index,
Config = alarm
};
_alarms[alarm.StartTime + alarm.Duration] = new AlarmAction()
{
Type = AlarmActionType.Stop,
Id = index,
Config = alarm
};
}
}

private void InCombatChanged(object? sender, EventArgs e)
{
if (!Plugin.State.InCombat)
{
// + clear whatever alarms are up
// _rangAlarms.Clear();
ClearAlarms();
}
}

private void FrameworkUpdate(IFramework framework)
{
if (!Plugin.State.InCombat) return;

// only run once a second
var time = (int)Math.Floor(Plugin.State.CombatDuration.TotalSeconds);
if (_lastCheck == time) return;
_lastCheck = time;

if (!_alarms.TryGetValue(time, out var alarm)) return;

if (alarm.Type == AlarmActionType.Start)
{
RunAlarm(alarm.Config);
// _rangAlarms.Add(time);
}

if (alarm.Type == AlarmActionType.Stop)
{
ClearAlarms();
}
}

private void RunAlarm(CombatAlarmsConfiguration.Alarm alarm)
{
if (alarm.Sfx != null)
{
// Plugin.SfxPlay.SoundEffect();
Plugin.SfxPlay.SoundEffect((uint)(SfxPlay.FirstSeSfx + alarm.Sfx));
}

var trimText = alarm.Text?.Trim();
if (trimText is { Length: > 0 })
{
switch (alarm.TextType)
{
case CombatAlarmsConfiguration.TextType.DalamudNotification:
Plugin.PluginInterface.UiBuilder.AddNotification(
trimText,
"EngageTimer",
NotificationType.Info,
8000
);
break;
case CombatAlarmsConfiguration.TextType.GameToast:
Plugin.ToastGui.ShowNormal(trimText);
break;
case CombatAlarmsConfiguration.TextType.ChatLogMessage:
// Plugin.ChatGui.Print(trimText, "EngageTimer");
Plugin.ChatGui.Print(new XivChatEntry()
{
Type = XivChatType.Echo,
Name = "EngageTimer",
Message = trimText
});
break;
}
}

if (alarm.Color != null)
{
Plugin.State.OverrideFwColor = alarm.Color;
Plugin.State.BlinkStopwatch = alarm.Blink;
}
}

private void ClearAlarms()
{
Plugin.State.OverrideFwColor = null;
Plugin.State.BlinkStopwatch = false;
}

public void Dispose()
{
Plugin.Config.OnSave -= ConfigurationChanged;
Plugin.Framework.Update -= FrameworkUpdate;
}
}
4 changes: 4 additions & 0 deletions Plugin/Status/State.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.

using System;
using System.Numerics;

namespace EngageTimer.Status;

Expand All @@ -26,6 +27,9 @@ public class State
public DateTime CombatStart { get; set; }
public bool Mocked { get; set; }

public Vector4? OverrideFwColor { get; set; }
public bool BlinkStopwatch { get; set; } = false;

public bool InCombat
{
get => _inCombat;
Expand Down
7 changes: 6 additions & 1 deletion Plugin/Ui/FloatingWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,12 @@ private void DrawWindow(bool stopwatchActive, bool countdownActive)

if (ImGui.Begin("EngageTimer stopwatch", ref _stopwatchVisible, flags))
{
ImGui.PushStyleColor(ImGuiCol.Text, Plugin.Config.FloatingWindow.TextColor);
var color = Plugin.State.OverrideFwColor ?? Plugin.Config.FloatingWindow.TextColor;
// use time to change color every half second
if (Plugin.State.BlinkStopwatch && ImGui.GetTime() % 1 < 0.5)
color = Plugin.Config.FloatingWindow.TextColor;

ImGui.PushStyleColor(ImGuiCol.Text, color);
ImGui.SetWindowFontScale(Plugin.Config.FloatingWindow.Scale);

var stopwatchDecimals = Plugin.Config.FloatingWindow.DecimalStopwatchPrecision > 0;
Expand Down
1 change: 1 addition & 0 deletions Plugin/Ui/PluginUi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public PluginUi()
Plugin.NumberTextures = new NumberTextures();
_windowSystem = new WindowSystem("Engage Timer");
_windowSystem.AddWindow(_settings);
// _windowSystem.AddWindow(new SfxDebug());
Plugin.PluginInterface.UiBuilder.Draw += Draw;
Plugin.PluginInterface.UiBuilder.OpenConfigUi += OpenSettings;
}
Expand Down
Loading

0 comments on commit a146685

Please sign in to comment.