implemened game sound effects for notifs

This commit is contained in:
choco
2025-10-06 21:55:45 +02:00
parent 83e4555e4b
commit 9b6d00570e
2 changed files with 55 additions and 37 deletions

View File

@@ -1,4 +1,5 @@
using Dalamud.Interface; using Dalamud.Interface;
using Dalamud.Plugin.Services;
using LightlessSync.LightlessConfiguration; using LightlessSync.LightlessConfiguration;
using LightlessSync.LightlessConfiguration.Models; using LightlessSync.LightlessConfiguration.Models;
using LightlessSync.Services.Mediator; using LightlessSync.Services.Mediator;
@@ -6,6 +7,8 @@ using LightlessSync.UI;
using LightlessSync.UI.Models; using LightlessSync.UI.Models;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using FFXIVClientStructs.FFXIV.Client.UI;
namespace LightlessSync.Services; namespace LightlessSync.Services;
public class LightlessNotificationService : DisposableMediatorSubscriberBase, IHostedService public class LightlessNotificationService : DisposableMediatorSubscriberBase, IHostedService
{ {
@@ -48,7 +51,6 @@ public class LightlessNotificationService : DisposableMediatorSubscriberBase, IH
SoundEffectId = soundEffectId ?? NotificationSounds.GetDefaultSound(type) SoundEffectId = soundEffectId ?? NotificationSounds.GetDefaultSound(type)
}; };
// Play sound effect if specified
if (notification.SoundEffectId.HasValue) if (notification.SoundEffectId.HasValue)
{ {
PlayNotificationSound(notification.SoundEffectId.Value); PlayNotificationSound(notification.SoundEffectId.Value);
@@ -100,7 +102,6 @@ public class LightlessNotificationService : DisposableMediatorSubscriberBase, IH
} }
}; };
// Play sound effect
if (notification.SoundEffectId.HasValue) if (notification.SoundEffectId.HasValue)
{ {
PlayNotificationSound(notification.SoundEffectId.Value); PlayNotificationSound(notification.SoundEffectId.Value);
@@ -140,7 +141,6 @@ public class LightlessNotificationService : DisposableMediatorSubscriberBase, IH
SoundEffectId = NotificationSounds.DownloadComplete SoundEffectId = NotificationSounds.DownloadComplete
}; };
// Play sound effect
if (notification.SoundEffectId.HasValue) if (notification.SoundEffectId.HasValue)
{ {
PlayNotificationSound(notification.SoundEffectId.Value); PlayNotificationSound(notification.SoundEffectId.Value);
@@ -188,7 +188,6 @@ public class LightlessNotificationService : DisposableMediatorSubscriberBase, IH
SoundEffectId = NotificationSounds.Error SoundEffectId = NotificationSounds.Error
}; };
// Play sound effect
if (notification.SoundEffectId.HasValue) if (notification.SoundEffectId.HasValue)
{ {
PlayNotificationSound(notification.SoundEffectId.Value); PlayNotificationSound(notification.SoundEffectId.Value);
@@ -198,7 +197,6 @@ public class LightlessNotificationService : DisposableMediatorSubscriberBase, IH
} }
public void ShowPairDownloadNotification(List<(string playerName, float progress, string status)> downloadStatus, int queueWaiting = 0) public void ShowPairDownloadNotification(List<(string playerName, float progress, string status)> downloadStatus, int queueWaiting = 0)
{ {
// Filter out queue status from user downloads
var userDownloads = downloadStatus.Where(x => x.playerName != "Pair Queue").ToList(); var userDownloads = downloadStatus.Where(x => x.playerName != "Pair Queue").ToList();
var totalProgress = userDownloads.Count > 0 ? userDownloads.Average(x => x.progress) : 0f; var totalProgress = userDownloads.Count > 0 ? userDownloads.Average(x => x.progress) : 0f;
@@ -207,13 +205,11 @@ public class LightlessNotificationService : DisposableMediatorSubscriberBase, IH
var message = ""; var message = "";
// Add queue status at the top if there are waiting items
if (queueWaiting > 0) if (queueWaiting > 0)
{ {
message = $"Queue: {queueWaiting} waiting"; message = $"Queue: {queueWaiting} waiting";
} }
// Add download progress if there are downloads
if (totalCount > 0) if (totalCount > 0)
{ {
var progressMessage = $"Progress: {completedCount}/{totalCount} completed"; var progressMessage = $"Progress: {completedCount}/{totalCount} completed";
@@ -240,7 +236,6 @@ public class LightlessNotificationService : DisposableMediatorSubscriberBase, IH
message += string.IsNullOrEmpty(message) ? downloadLines : $"\n{downloadLines}"; message += string.IsNullOrEmpty(message) ? downloadLines : $"\n{downloadLines}";
} }
// Check if all downloads are completed
var allDownloadsCompleted = userDownloads.All(x => x.progress >= 1.0f) && userDownloads.Any(); var allDownloadsCompleted = userDownloads.All(x => x.progress >= 1.0f) && userDownloads.Any();
var notification = new LightlessNotification var notification = new LightlessNotification
@@ -259,6 +254,7 @@ public class LightlessNotificationService : DisposableMediatorSubscriberBase, IH
DismissPairDownloadNotification(); DismissPairDownloadNotification();
} }
} }
public void DismissPairDownloadNotification() public void DismissPairDownloadNotification()
{ {
Mediator.Publish(new LightlessNotificationDismissMessage("pair_download_progress")); Mediator.Publish(new LightlessNotificationDismissMessage("pair_download_progress"));
@@ -268,15 +264,15 @@ public class LightlessNotificationService : DisposableMediatorSubscriberBase, IH
{ {
try try
{ {
// TODO: Implement proper sound playback try
// The ChatGui.PlaySoundEffect method doesn't exist in the current Dalamud API {
// For now, just log what sound would be played UIGlobals.PlayChatSoundEffect(soundEffectId);
_logger.LogDebug("Would play notification sound effect {SoundId}", soundEffectId); _logger.LogDebug("Played notification sound effect {SoundId} via ChatGui", soundEffectId);
}
// Future implementation options: catch (Exception chatEx)
// 1. Use UIModule->PlaySound() with proper unsafe interop {
// 2. Use game's sound system through SigScanner _logger.LogWarning(chatEx, "Failed to play sound via ChatGui for ID {SoundId}", soundEffectId);
// 3. Wait for official Dalamud sound API }
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@@ -1,41 +1,63 @@
using LightlessSync.LightlessConfiguration.Models; using LightlessSync.LightlessConfiguration.Models;
namespace LightlessSync.UI.Models; namespace LightlessSync.UI.Models;
/// <summary> /// <summary>
/// Common FFXIV sound effect IDs for notifications /// Common FFXIV <se.#> sound effect IDs for notifications.
/// These correspond to the same sound IDs used in macros (116).
/// </summary> /// </summary>
public static class NotificationSounds public static class NotificationSounds
{ {
/// <summary> // ─────────────────────────────────────────────
/// General notification sound (quest complete) // Base <se.#> IDs (116)
/// </summary> // https://ffxiv.consolegameswiki.com/wiki/Macros#Sound_Effects
public const uint Info = 37; // ─────────────────────────────────────────────
public const uint Se1 = 1; // Soft chime
public const uint Se2 = 2; // Higher chime
public const uint Se3 = 3; // Bell tone
public const uint Se4 = 4; // Harp tone
public const uint Se5 = 5; // Drum / percussion
public const uint Se6 = 6; // Mechanical click
public const uint Se7 = 7; // Metallic chime
public const uint Se8 = 8; // Wooden tone
public const uint Se9 = 9; // Wind / flute tone
public const uint Se10 = 10; // Magical sparkle
public const uint Se11 = 11; // Metallic ring
public const uint Se12 = 12; // Deep thud
public const uint Se13 = 13; // "Tell received" ping
public const uint Se14 = 14; // Success fanfare short
public const uint Se15 = 15; // System warning
public const uint Se16 = 16; // Error / failure──────────────────────────────────────────
/// <summary> /// <summary>
/// Warning/alert sound (system error) /// General notification sound (<se.2>)
/// </summary> /// </summary>
public const uint Warning = 15; public const uint Info = Se2;
/// <summary> /// <summary>
/// Error sound (action failed) /// Warning/alert sound (<se.15>)
/// </summary> /// </summary>
public const uint Error = 16; public const uint Warning = Se15;
/// <summary> /// <summary>
/// Success sound (level up) /// Error sound (<se.16>)
/// </summary> /// </summary>
public const uint Success = 25; public const uint Error = Se16;
/// <summary> /// <summary>
/// Pair request sound (tell received) /// Success sound (<se.14>)
/// </summary> /// </summary>
public const uint PairRequest = 13; public const uint Success = Se14;
/// <summary> /// <summary>
/// Download complete sound (item obtained) /// Pair request sound (<se.13>, same as tell notification)
/// </summary> /// </summary>
public const uint DownloadComplete = 30; public const uint PairRequest = Se13;
/// <summary>
/// Download complete sound (<se.10>, a clean sparkle tone)
/// </summary>
public const uint DownloadComplete = Se10;
/// <summary> /// <summary>
/// Get default sound for notification type /// Get default sound for notification type