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",