PvPAnnouncer/Configuration.cs --- C# 20 20 21 21 public bool NewConfig { get; set; } = true; 22 22 public int RepeatVoiceLineQueue { get; set; } = 3; .. 23 public int ClearEventsAfter { get; set; } = 2; .. 24 public int ClearVoicelinesAfter { get; set; } = 5; 23 25 public int RepeatEventCommentaryQueue { get; set; } = 3; 24 26 public int AnimationDelayFactor { get; set; } = 250; 25 27   PvPAnnouncer/Impl/Announcer.cs --- 1/9 --- C# 1 1 using System; 2 2 using System.Collections.Generic; . 3 using System.Linq; 3 4 using System.Threading.Tasks; . 5 using System.Timers; 4 6 using Dalamud.Game.ClientState.Conditions; 5 7 using FFXIVClientStructs.FFXIV.Client.UI; 6 8 using PvPAnnouncer.Data;   PvPAnnouncer/Impl/Announcer.cs --- 2/9 --- C# 10 12 11 namespace PvPAnnouncer.Impl; 13 namespace PvPAnnouncer.Impl; 12 14 13 public class Announcer(IEventShoutcastMapping eventShoutcastMapping, IShoutcastRepository shoutcastRepository) 15 public class Announcer : IAnnouncer, IDisposable 14 : IAnnouncer .. 15 { 16 { .. 17 /* .. 18 * Objectives: .. 19 * 1. Comment a Reasonable amount .. 20 * 2. Dont repeat voice lines .. 21 * 3. Don't comment on the same thing twice .. 22 * 4. Don't say more than one thing at a time or comment too quickly .. 23 * 5. Use the appropriate gender for the challenger .. 24 */ .. 25 .. 26 //todo rewrite - divide and conquer .. 27 // per announcer % .. 28 16 private readonly Queue<string> _lastEvents = new(); 29 private readonly Queue<(string eventStr, DateTime entered)> _lastEvents = new(); 17 /* .. 18 * Objectives: .. 19 * 1. Comment a Reasonable amount .. 20 * 2. Dont repeat voice lines .. 21 * 3. Don't comment on the same thing twice .. 22 * 4. Don't say more than one thing at a time or comment too quickly .. 23 * 5. Use the appropriate gender for the challenger .. 24 */ .. 25 .. 26 //todo rewrite - divide and conquer .. 27 // per announcer % .. 28 .. 29 .. 30 private readonly Queue<string> _lastVoiceLines = new(); 30 private readonly Queue<(string line, DateTime entered)> _lastVoiceLines = new(); .. 31 private readonly Queue<string> _lastTriggers = new(); .. 32 31 private int _lastVoiceLineLength; 33 private int _lastVoiceLineLength; 32 private long _timestamp; 34 private long _timestamp; .. 35 private readonly IEventShoutcastMapping _eventShoutcastMapping; .. 36 private readonly IShoutcastRepository _shoutcastRepository; .. 37 private readonly Timer _clearTimer; .. 38 .. 39 public Announcer(IEventShoutcastMapping eventShoutcastMapping, IShoutcastRepository shoutcastRepository) .. 40 { .. 41 _eventShoutcastMapping = eventShoutcastMapping; .. 42 _shoutcastRepository = shoutcastRepository; .. 43 _clearTimer = new Timer(60 * 1000); .. 44 _clearTimer.Elapsed += ClearQueueAfter; .. 45 _clearTimer.Enabled = true; .. 46 } .. 47 .. 48 public List<string> GetLastTriggers() .. 49 { .. 50 return _lastTriggers.ToList(); .. 51 } 33 52 34 public void ClearQueue() 53 public void ClearQueue() 35 { 54 {   PvPAnnouncer/Impl/Announcer.cs --- 3/9 --- C# 39 58 } .. 59 .. 60 .. 61 private void ClearQueueAfter(object? sender, ElapsedEventArgs elapsedEventArgs) .. 62 { .. 63 while (_lastVoiceLines.Count > 0 && (DateTime.UtcNow - _lastVoiceLines.Peek().entered).TotalSeconds > .. 64 60 * PluginServices.Config.ClearVoicelinesAfter) .. 65 { .. 66 PluginServices.PluginLog.Verbose( .. 67 $"Dequeuing Voice Line {_lastVoiceLines.Peek().line} from history as its older than {PluginServices.Config.ClearVoicelinesAfter} minute(s)"); .. 68 _lastVoiceLines.Dequeue(); .. 69 } .. 70 .. 71 while (_lastEvents.Count > 0 && (DateTime.UtcNow - _lastEvents.Peek().entered).TotalSeconds > .. 72 60 * PluginServices.Config.ClearEventsAfter) .. 73 { .. 74 PluginServices.PluginLog.Verbose( .. 75 $"Dequeuing Event {_lastEvents.Peek().eventStr} from history as its older than {PluginServices.Config.ClearEventsAfter} minute(s)"); .. 76 .. 77 _lastEvents.Dequeue(); .. 78 } .. 79 } 40 80 41 81 private bool ShouldAnnounce() // this function will determine if the settings let us 42 82 {   PvPAnnouncer/Impl/Announcer.cs --- 4/9 --- C# 205 PluginServices.PluginLog.Verbose("Adding Event to history"); 245 PluginServices.PluginLog.Verbose("Adding Event to history"); 206 if (_lastEvents.Count > PluginServices.Config.RepeatEventCommentaryQueue - 1) 246 if (_lastEvents.Count > PluginServices.Config.RepeatEventCommentaryQueue - 1) 207 { 247 { 208 PluginServices.PluginLog.Verbose($"Dequeuing Event from history"); 248 PluginServices.PluginLog.Verbose($"Dequeuing Event {_lastEvents.Peek().eventStr} from history"); 209 249 210 _lastEvents.Dequeue(); 250 _lastEvents.Dequeue(); 211 } 251 } 212 252 213 _lastEvents.Enqueue(e.Id); 253 _lastEvents.Enqueue((e.Id, DateTime.UtcNow)); 214 } 254 } 215 255 216 256   PvPAnnouncer/Impl/Announcer.cs --- 5/9 --- C# 220 260 221 if (_lastVoiceLines.Count > PluginServices.Config.RepeatVoiceLineQueue - 1) 261 if (_lastVoiceLines.Count > PluginServices.Config.RepeatVoiceLineQueue - 1) 222 { 262 { 223 PluginServices.PluginLog.Verbose($"Dequeuing Voice Line from history"); 263 PluginServices.PluginLog.Verbose($"Dequeuing Voice Line {_lastVoiceLines.Peek().line} from history"); 224 264 225 _lastVoiceLines.Dequeue(); 265 _lastVoiceLines.Dequeue(); 226 } 266 } 227 267 228 _lastVoiceLines.Enqueue(talk.Id); 268 _lastVoiceLines.Enqueue((talk.Id, DateTime.UtcNow)); 229 } 269 } 230 270 231 private bool FailsRepeatCommentaryCheck(PvPEvent pvpEvent) 271 private bool FailsRepeatCommentaryCheck(PvPEvent pvpEvent) 232 { 272 { 233 bool b = _lastEvents.Contains(pvpEvent.Id); 273 var b = _lastEvents.Any(e => e.eventStr.Equals(pvpEvent.Id)); 234 foreach (var lastEvent in _lastEvents) 274 foreach (var lastEvent in _lastEvents) 235 { 275 { 236 PluginServices.PluginLog.Verbose($"Last Event: {lastEvent}"); 276 PluginServices.PluginLog.Verbose($"Last Event: {lastEvent.eventStr}"); 237 } 277 } 238 278 239 PluginServices.PluginLog.Verbose($"Repeat commentary check triggered - value is {b}"); 279 PluginServices.PluginLog.Verbose($"Repeat commentary check triggered - value is {b}");   PvPAnnouncer/Impl/Announcer.cs --- 6/9 --- C# 245 { 285 { 246 List<Shoutcast> sounds = []; 286 List<Shoutcast> sounds = []; 247 287 248 foreach (var shoutcastId in eventShoutcastMapping.GetShoutcastList(pvpEvent.Id)) 288 foreach (var shoutcastId in _eventShoutcastMapping.GetShoutcastList(pvpEvent.Id)) 249 { 289 { 250 var sound = shoutcastRepository.GetShoutcast(shoutcastId); 290 var sound = _shoutcastRepository.GetShoutcast(shoutcastId); 251 if (sound == null) 291 if (sound == null) 252 { 292 { 253 PluginServices.PluginLog.Warning($"{shoutcastId} not found."); 293 PluginServices.PluginLog.Warning($"{shoutcastId} not found.");   PvPAnnouncer/Impl/Announcer.cs --- 7/9 --- C# 287 if (!bypass) 327 if (!bypass) 288 { 328 { 289 foreach (var sound in Enumerable.Where(Enumerable.ToList(sounds), 329 foreach (var sound in Enumerable.Where(Enumerable.ToList(sounds), 290 sound => _lastVoiceLines.Contains(sound.Id))) 330 sound => _lastVoiceLines.Any(s => s.line.Equals(sound.Id)))) 291 { 331 { 292 sounds.Remove(sound); 332 sounds.Remove(sound); 293 } 333 }   PvPAnnouncer/Impl/Announcer.cs --- 8/9 --- C# 327 367 AddEventToRecentList(pvpEvent); 328 368 if (chosenLine != null) 329 369 { ... 370 _lastTriggers.Enqueue($"{pvpEvent.Id} -> {chosenLine.Id}"); ... 371 if (_lastTriggers.Count > 10) _lastTriggers.Dequeue(); ... 372 330 373 AddVoiceLineToRecentList(chosenLine); 331 374 _lastVoiceLineLength = chosenLine.Duration;   PvPAnnouncer/Impl/Announcer.cs --- 9/9 --- C# 334 377 _timestamp = DateTimeOffset.Now.ToUnixTimeSeconds(); 335 378 } ... 379 ... 380 public void Dispose() ... 381 { ... 382 _clearTimer.Enabled = false; ... 383 _clearTimer.Dispose(); ... 384 } 336 385 }   PvPAnnouncer/Impl/DutyManager.cs --- C# 203 203 204 204 public void DutyStarted(IDutyStateEventArgs args) 205 205 { ... 206 PluginServices.Announcer.ClearQueue(); // new duty - fully reset everything 206 207 EmitToBroker(new MatchStartedMessage()); 207 208 } 208 209   PvPAnnouncer/Interfaces/IAnnouncer.cs --- 1/2 --- C# . 1 using System.Collections.Generic; 1 2 using PvPAnnouncer.Data; 2 3 using PvPAnnouncer.Interfaces.PvPEvents; 3 4   PvPAnnouncer/Interfaces/IAnnouncer.cs --- 2/2 --- C# 11 12 void SendBattleTalk(Shoutcast shoutcast); 12 13 void ClearQueue(); 13 14 void PlayAndSendBattleTalkForTesting(Shoutcast shoutcast); .. 15 List<string> GetLastTriggers(); .. 16 void Dispose(); 14 17 }   PvPAnnouncer/PvPAnnouncer.csproj --- XML 3 <Project Sdk="Dalamud.NET.Sdk/15.0.0"> 3 <Project Sdk="Dalamud.NET.Sdk/15.0.0"> 4 <PropertyGroup> 4 <PropertyGroup> 5 <Authors>Spide-r</Authors> 5 <Authors>Spide-r</Authors> 6 <Version>1.6.2.1</Version> 6 <Version>1.6.2.2</Version> 7 <PackageProjectUrl>https://github.com/spide-r/PvPAnnouncer</PackageProjectUrl> 7 <PackageProjectUrl>https://github.com/spide-r/PvPAnnouncer</PackageProjectUrl> 8 <PackageLicenseExpression>AGPL-3.0-or-later</PackageLicenseExpression> 8 <PackageLicenseExpression>AGPL-3.0-or-later</PackageLicenseExpression> 9 <IsPackable>false</IsPackable> 9 <IsPackable>false</IsPackable>   PvPAnnouncer/PvPAnnouncerPlugin.cs --- C# 120 120 PluginServices.EventHooksPublisher.Dispose(); 121 121 PluginServices.PlayerStateTracker.Dispose(); 122 122 PluginServices.DutyManager.Dispose(); ... 123 PluginServices.Announcer.Dispose(); 123 124 UnloadCommands(); 124 125 } 125 126 }   PvPAnnouncer/Windows/ConfigWindow.cs --- 1/2 --- C# 78 78 var repeatVoiceLine = _configuration.RepeatVoiceLineQueue; 79 79 var repeatEventCommentary = _configuration.RepeatEventCommentaryQueue; 80 80 var animationDelayFactor = _configuration.AnimationDelayFactor; .. 81 var clearEventsAfter = _configuration.ClearEventsAfter; .. 82 var clearVoicelinesAfter = _configuration.ClearVoicelinesAfter; 81 83 var notify = _configuration.Notify; 82 84 var icon = _configuration.WantsIcon; 83 85   PvPAnnouncer/Windows/ConfigWindow.cs --- 2/2 --- C# 279 281 _configuration.Save(); 280 282 } ... 283 ... 284 ImGui.Unindent(); ... 285 ImGui.TextWrapped("Maximum amount of minutes an event can be put on cooldown before being triggered"); ... 286 ImGui.Indent(); ... 287 if (ImGui.SliderInt("###SliderClearEvents", ref clearEventsAfter, 1, 10)) ... 288 { ... 289 _configuration.ClearEventsAfter = clearEventsAfter; ... 290 _configuration.Save(); ... 291 } ... 292 ... 293 ImGui.Unindent(); ... 294 ... 295 ImGui.TextWrapped("Maximum amount of minutes a voiceline can be put on cooldown before being heard again"); ... 296 ImGui.Indent(); ... 297 if (ImGui.SliderInt("###SliderClearVoicelines", ref clearVoicelinesAfter, 1, 10)) ... 298 { ... 299 _configuration.ClearVoicelinesAfter = clearVoicelinesAfter; ... 300 _configuration.Save(); ... 301 } 281 302 282 303 ImGui.Unindent(); 283 304 if (ImguiTools.CtrlShiftButton("Reset Above Values to Default"))   PvPAnnouncer/Windows/CustomizationWindow.cs --- 1/2 --- C# 129 129 if (ImGui.CollapsingHeader("Event Tester###Testerheader")) EventTester(); ... 130 ... 131 ... 132 if (ImGui.CollapsingHeader("Event Queue###QueueHeader")) EventQueue(); 130 133 131 134 ImGui.NewLine(); 132 135   PvPAnnouncer/Windows/CustomizationWindow.cs --- 2/2 --- C# 426 429 } 427 430 } ... 431 ... 432 private void EventQueue() ... 433 { ... 434 ImGui.TextWrapped("Here are the last 10 triggered events and their voicelines:"); ... 435 foreach (var lastTrigger in PluginServices.Announcer.GetLastTriggers()) ImGui.TextWrapped(lastTrigger); ... 436 } 428 437 429 438 public void Dispose() 430 439 {   PvPAnnouncer/Windows/MainWindow.cs --- C# 25 } 25 } 26 26 27 ImGui.TextWrapped( 27 ImGui.TextWrapped( 28 "Welcome to NPC Announcer! This plugin will take many NPC's and put them into your PvP match! " + 28 "Welcome to NPC Announcer! This plugin will take many NPC's and put them into your game! " + 29 "\nPlease contact .spider in the Dalamud Discord for feedback/suggestions!" + 29 "\nPlease contact .spider in the Dalamud Discord for feedback/suggestions!" + 30 "\nView the config with /pvpannouncer"); 30 "\nView the config with /npcannouncer"); 31 ImGui.Spacing(); 31 ImGui.Spacing(); 32 ImGui.Text("Attributions"); 32 ImGui.Text("Attributions"); 33 ImGui.BulletText("DeathRecap, VFXEditor, OofPlugin"); 33 ImGui.BulletText("DeathRecap, VFXEditor, OofPlugin");   PvPAnnouncer/json/shoutcast.json --- JSON 1908 "shoutcaster": "Zenos", 1908 "shoutcaster": "Zenos", 1909 "duration": "3", 1909 "duration": "3", 1910 "soundPath": "sound/voice/vo_line/8201356", 1910 "soundPath": "sound/voice/vo_line/8201356", 1911 "instanceContentTextDataRow": "17315" 1911 "instanceContentTextDataRow": "17312" 1912 }, 1912 }, 1913 { 1913 { 1914 "id": "ThePowerToTranscend", 1914 "id": "ThePowerToTranscend",