LazyGatherer/Controller/GpAlertController.cs --- 1/4 --- C# 3 3 using Dalamud.Game.Text.SeStringHandling; 4 4 using Dalamud.Plugin.Services; 5 5 using FFXIVClientStructs.FFXIV.Client.UI; . 6 using FFXIVClientStructs.FFXIV.Client.UI.Agent; 6 7 using LazyGatherer.Models; . 8 using AgentId = Dalamud.Game.Agent.AgentId; 7 9 8 10 namespace LazyGatherer.Controller; 9 11   LazyGatherer/Controller/GpAlertController.cs --- 2/4 --- C# 22 24 23 public void Dispose() 25 public void Dispose() 24 { 26 { 25 Service.Framework.Update -= OnFrameworkUpdate; 27 Service.ClientState.ClassJobChanged -= ClientState_ClassJobChanged; 26 Service.ClientState.ClassJobChanged -= ClientState_ClassJobChanged; 28 Service.Framework.Update -= OnFrameworkUpdate; 27 } 29 } 28 30 29 // 31 //   LazyGatherer/Controller/GpAlertController.cs --- 3/4 --- C# 71 } 73 } 72 74 73 // Play sound and print message 75 // Play sound and print message 74 UIGlobals.PlayChatSoundEffect(Service.Config.GpAlertSound); 76 PlayAlertSound(); 75 if (Service.Config.GpAlertSendChatMessage) 77 if (Service.Config.GpAlertSendChatMessage) 76 { 78 { 77 PrintMessage(); 79 PrintMessage();   LazyGatherer/Controller/GpAlertController.cs --- 4/4 --- C# 99 var sb = new SeStringBuilder() 101 var sb = new SeStringBuilder() 100 .AddUiForeground("[LazyGatherer] ", 45) 102 .AddUiForeground("[LazyGatherer] ", 45) 101 .AddUiForeground("[GP Alert] ", 57) 103 .AddUiForeground("[GP Alert] ", 57) 102 .Append("GP has reached the configured threshold!"); 104 .Append($"GP has reached {Service.Config.GpAlertThreshold}."); 103 105 104 Service.ChatGui.Print(new XivChatEntry { Type = Service.Config.GpAlertChatType, Message = sb.BuiltString }) 106 Service.ChatGui.Print(new XivChatEntry { Type = Service.Config.GpAlertChatType, Message = sb.BuiltString }) ... ; ... ; 105 } 107 } ... 108 ... 109 public static unsafe void PlayAlertSound() ... 110 { ... 111 if (Service.Config.GpAlertSoundIsAlarm) ... 112 { ... 113 var agentInterfacePtr = Service.GameGui.GetAgentById((int)AgentId.Alarm); ... 114 if (agentInterfacePtr != IntPtr.Zero) ... 115 { ... 116 ((AgentAlarm*)agentInterfacePtr.Address)->PlayAlarmSoundEffect(Service.Config.GpAlertAlarmSoundEffe ... ... ct); ... 117 } ... 118 else ... 119 { ... 120 Service.Log.Warning("Could not find AgentAlarm, playing default sound effect."); ... 121 UIGlobals.PlayChatSoundEffect(1); ... 122 } ... 123 } ... 124 else ... 125 { ... 126 UIGlobals.PlayChatSoundEffect(Service.Config.GpAlertSoundEffectId); ... 127 } ... 128 } 106 } 129 }   LazyGatherer/LazyGatherer.csproj --- XML 3 3 4 <PropertyGroup> 4 <PropertyGroup> 5 <Authors>Hiroa</Authors> 5 <Authors>Hiroa</Authors> 6 <Version>1.4.0</Version> 6 <Version>1.4.1</Version> 7 <Description>Display the optimal rotation for maximum yield with your current GP.</Description> 7 <Description>Display the optimal rotation for maximum yield with your current GP.</Description> 8 <PackageProjectUrl>https://github.com/Hiroa/LazyGatherer</PackageProjectUrl> 8 <PackageProjectUrl>https://github.com/Hiroa/LazyGatherer</PackageProjectUrl> 9 </PropertyGroup> 9 </PropertyGroup>   LazyGatherer/LazyGathererPlugin.cs --- C# 33 33 Service.UIController.Dispose(); 34 34 Service.MasterpieceController.Dispose(); 35 35 Service.GatheringController.Dispose(); .. 36 Service.GpAlertController.Dispose(); 36 37 Service.ConfigAddon.Dispose(); 37 38 Service.GpAlertAddon.Dispose(); 38 39 KamiToolKitLibrary.Dispose();   LazyGatherer/Models/AlertSoundConfig.cs --- C# 1 using System; 2 using FFXIVClientStructs.FFXIV.Client.UI.Agent; 3 4 namespace LazyGatherer.Models; 5 6 public class AlertSoundConfig 7 { 8 public readonly bool IsAnAlarm; 9 public readonly uint SoundEffectId = 1; 10 public readonly AlarmSoundEffect AlarmSoundEffect; 11 12 public AlertSoundConfig(uint soundEffectId) 13 { 14 SoundEffectId = soundEffectId; 15 } 16 17 public AlertSoundConfig(AlarmSoundEffect alarmSoundEffect) 18 { 19 IsAnAlarm = true; 20 AlarmSoundEffect = alarmSoundEffect; 21 } 22 23 public override bool Equals(object? obj) 24 { 25 return obj is AlertSoundConfig other && 26 IsAnAlarm == other.IsAnAlarm && 27 SoundEffectId == other.SoundEffectId && 28 AlarmSoundEffect == other.AlarmSoundEffect; 29 } 30 31 public override int GetHashCode() 32 { 33 return HashCode.Combine(IsAnAlarm, SoundEffectId, AlarmSoundEffect); 34 } 35 36 public static AlertSoundConfig FromConfig() 37 { 38 return Service.Config.GpAlertSoundIsAlarm 39 ? new AlertSoundConfig(Service.Config.GpAlertAlarmSoundEffect) 40 : new AlertSoundConfig(Service.Config.GpAlertSoundEffectId); 41 } 42 } 43   LazyGatherer/Models/Config.cs --- 1/2 --- C# 1 1 using Dalamud.Configuration; 2 2 using Dalamud.Game.Text; . 3 using FFXIVClientStructs.FFXIV.Client.UI.Agent; 3 4 4 5 namespace LazyGatherer.Models; 5 6   LazyGatherer/Models/Config.cs --- 2/2 --- C# 23 // GP Alert 24 // GP Alert 24 public bool GpAlertEnabled = false; 25 public bool GpAlertEnabled = false; 25 public uint GpAlertThreshold = 0; 26 public uint GpAlertThreshold = 0; .. 27 public bool GpAlertSoundIsAlarm = false; 26 public uint GpAlertSound = 1; 28 public uint GpAlertSoundEffectId = 1; .. 29 public AlarmSoundEffect GpAlertAlarmSoundEffect = AlarmSoundEffect.Bell; 27 public bool GpAlertSendChatMessage = false; 30 public bool GpAlertSendChatMessage = false; 28 public XivChatType GpAlertChatType = XivChatType.Echo; 31 public XivChatType GpAlertChatType = XivChatType.Echo; 29 } 32 }   LazyGatherer/UI/Addon/GpAlertAddon.cs --- 1/3 --- C# 3 3 using System.Linq; 4 4 using System.Numerics; 5 5 using Dalamud.Game.Text; 6 6 using FFXIVClientStructs.FFXIV.Client.UI.Agent; 7 7 using FFXIVClientStructs.FFXIV.Component.GUI; 8 8 using KamiToolKit; 9 9 using KamiToolKit.Nodes; 10 10 using KamiToolKit.Premade.Node.Simple; .. 11 using LazyGatherer.Controller; .. 12 using LazyGatherer.Models; 11 13 12 14 namespace LazyGatherer.UI.Addon; 13 15   LazyGatherer/UI/Addon/GpAlertAddon.cs --- 2/3 --- C# 23 { XivChatType.Shout, "Shout" }, 25 { XivChatType.Shout, "Shout" }, 24 }; 26 }; 25 27 26 private readonly Dictionary<uint, string> soundOptions = new() 28 private readonly Dictionary<AlertSoundConfig, string> soundOptions = new() 27 { 29 { .. 30 // Alarm sound .. 31 { new AlertSoundConfig(AlarmSoundEffect.Bell), "Alarm - Bell" }, .. 32 { new AlertSoundConfig(AlarmSoundEffect.MusicBox), "Alarm - MusicBox" }, .. 33 { new AlertSoundConfig(AlarmSoundEffect.Prelude), "Alarm - Prelude" }, .. 34 { new AlertSoundConfig(AlarmSoundEffect.Chocobo), "Alarm - Chocobo" }, .. 35 { new AlertSoundConfig(AlarmSoundEffect.LaNoscea), "Alarm - LaNoscea" }, .. 36 { new AlertSoundConfig(AlarmSoundEffect.Festival), "Alarm - Festival" }, .. 37 .. 38 // Sound effect 28 { 1, "Sound 1" }, 39 { new AlertSoundConfig(1), "Sound effect 1" }, 29 { 2, "Sound 2" }, 40 { new AlertSoundConfig(2), "Sound effect 2" }, 30 { 3, "Sound 3" }, 41 { new AlertSoundConfig(3), "Sound effect 3" }, 31 { 4, "Sound 4" }, 42 { new AlertSoundConfig(4), "Sound effect 4" }, 32 { 5, "Sound 5" }, 43 { new AlertSoundConfig(5), "Sound effect 5" }, 33 { 6, "Sound 6" }, 44 { new AlertSoundConfig(6), "Sound effect 6" }, 34 { 7, "Sound 7" }, 45 { new AlertSoundConfig(7), "Sound effect 7" }, 35 { 8, "Sound 8" }, 46 { new AlertSoundConfig(8), "Sound effect 8" }, 36 { 9, "Sound 9" }, 47 { new AlertSoundConfig(9), "Sound effect 9" }, 37 { 10, "Sound 10" }, 48 { new AlertSoundConfig(10), "Sound effect 10" }, 38 { 11, "Sound 11" }, 49 { new AlertSoundConfig(11), "Sound effect 11" }, 39 { 12, "Sound 12" }, 50 { new AlertSoundConfig(12), "Sound effect 12" }, 40 { 13, "Sound 13" }, 51 { new AlertSoundConfig(13), "Sound effect 13" }, 41 { 14, "Sound 14" }, 52 { new AlertSoundConfig(14), "Sound effect 14" }, 42 { 15, "Sound 15" }, 53 { new AlertSoundConfig(15), "Sound effect 15" }, 43 { 16, "Sound 16" }, 54 { new AlertSoundConfig(16), "Sound effect 16" }, 44 }; 55 }; 45 56 46 protected override unsafe void OnSetup(AtkUnitBase* addon, Span<AtkValue> atkValueSpan) 57 protected override unsafe void OnSetup(AtkUnitBase* addon, Span<AtkValue> atkValueSpan)   LazyGatherer/UI/Addon/GpAlertAddon.cs --- 3/3 --- C# 120 Size = new Vector2(ContentSize.X - 20.0f, 24f), 131 Size = new Vector2(ContentSize.X - 20.0f, 24f), 121 Position = new Vector2(ContentStartPosition.X + 20, gpAlertSoundTn.Bounds.Bottom), 132 Position = new Vector2(ContentStartPosition.X + 20, gpAlertSoundTn.Bounds.Bottom), 122 Options = soundOptions.Values.ToList(), 133 Options = soundOptions.Values.ToList(), 123 SelectedOption = soundOptions[Service.Config.GpAlertSound], 134 SelectedOption = soundOptions[AlertSoundConfig.FromConfig()], 124 OnOptionSelected = selectedItem => 135 OnOptionSelected = selectedItem => 125 { 136 { 126 Service.Config.GpAlertSound = soundOptions 137 var alertSound = soundOptions.First(kvp => kvp.Value == selectedItem).Key; 127 .First(kvp => kvp.Value == selectedItem).Key; ... 128 UIGlobals.PlayChatSoundEffect(Service.Config.GpAlertSound); 138 Service.Config.GpAlertSoundIsAlarm = alertSound.IsAnAlarm; ... 139 Service.Config.GpAlertSoundEffectId = alertSound.SoundEffectId; ... 140 Service.Config.GpAlertAlarmSoundEffect = alertSound.AlarmSoundEffect; ... 141 GpAlertController.PlayAlertSound(); 129 Service.Interface.SavePluginConfig(Service.Config); 142 Service.Interface.SavePluginConfig(Service.Config); 130 Service.GatheringController.ComputeRotations(); 143 Service.GatheringController.ComputeRotations(); 131 }, 144 },