Skip to content

Commit

Permalink
Use MiniGame BGM scene for About tab (#2132)
Browse files Browse the repository at this point in the history
* Use MiniGame BGM scene for About tab

* Use span comparison in GameGui.IsInLobby
  • Loading branch information
goaaats authored Dec 6, 2024
2 parents e2298ea + 865a05f commit 722ee32
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 52 deletions.
47 changes: 14 additions & 33 deletions Dalamud/Game/Gui/GameGui.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@
using Dalamud.Plugin.Services;
using Dalamud.Utility;

using FFXIVClientStructs.FFXIV.Client.Game;
using FFXIVClientStructs.FFXIV.Client.Game.Control;
using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel;
using FFXIVClientStructs.FFXIV.Client.System.String;
using FFXIVClientStructs.FFXIV.Client.UI;
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
using FFXIVClientStructs.FFXIV.Common.Component.BGCollision;
using FFXIVClientStructs.FFXIV.Component.GUI;

using ImGuiNET;

using Vector2 = System.Numerics.Vector2;
Expand All @@ -34,7 +36,6 @@ internal sealed unsafe class GameGui : IInternalDisposableService, IGameGui

private readonly GameGuiAddressResolver address;

private readonly Hook<SetGlobalBgmDelegate> setGlobalBgmHook;
private readonly Hook<AgentItemDetail.Delegates.Update> handleItemHoverHook;
private readonly Hook<AgentItemDetail.Delegates.ReceiveEvent> handleItemOutHook;
private readonly Hook<AgentActionDetail.Delegates.HandleActionHover> handleActionHoverHook;
Expand All @@ -50,12 +51,8 @@ private GameGui(TargetSigScanner sigScanner)
this.address.Setup(sigScanner);

Log.Verbose("===== G A M E G U I =====");
Log.Verbose($"GameGuiManager address {Util.DescribeAddress(this.address.BaseAddress)}");
Log.Verbose($"SetGlobalBgm address {Util.DescribeAddress(this.address.SetGlobalBgm)}");
Log.Verbose($"HandleImm address {Util.DescribeAddress(this.address.HandleImm)}");

this.setGlobalBgmHook = Hook<SetGlobalBgmDelegate>.FromAddress(this.address.SetGlobalBgm, this.HandleSetGlobalBgmDetour);

this.handleItemHoverHook = Hook<AgentItemDetail.Delegates.Update>.FromAddress((nint)AgentItemDetail.StaticVirtualTablePointer->Update, this.HandleItemHoverDetour);
this.handleItemOutHook = Hook<AgentItemDetail.Delegates.ReceiveEvent>.FromAddress((nint)AgentItemDetail.StaticVirtualTablePointer->ReceiveEvent, this.HandleItemOutDetour);

Expand All @@ -68,7 +65,6 @@ private GameGui(TargetSigScanner sigScanner)

this.utf8StringFromSequenceHook = Hook<Utf8String.Delegates.Ctor_FromSequence>.FromAddress(Utf8String.Addresses.Ctor_FromSequence.Value, this.Utf8StringFromSequenceDetour);

this.setGlobalBgmHook.Enable();
this.handleItemHoverHook.Enable();
this.handleItemOutHook.Enable();
this.handleImmHook.Enable();
Expand All @@ -80,9 +76,6 @@ private GameGui(TargetSigScanner sigScanner)

// Hooked delegates

[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
private delegate IntPtr SetGlobalBgmDelegate(ushort bgmKey, byte a2, uint a3, uint a4, uint a5, byte a6);

[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
private delegate char HandleImmDelegate(IntPtr framework, char a2, byte a3);

Expand Down Expand Up @@ -254,7 +247,6 @@ public IntPtr FindAgentInterface(IntPtr addonPtr)
/// </summary>
void IInternalDisposableService.DisposeService()
{
this.setGlobalBgmHook.Dispose();
this.handleItemHoverHook.Dispose();
this.handleItemOutHook.Dispose();
this.handleImmHook.Dispose();
Expand All @@ -265,25 +257,23 @@ void IInternalDisposableService.DisposeService()
}

/// <summary>
/// Indicates if the game is on the title screen.
/// Indicates if the game is in the lobby scene (title screen, chara select, chara make, aesthetician etc.).
/// </summary>
/// <returns>A value indicating whether or not the game is on the title screen.</returns>
internal bool IsOnTitleScreen()
{
var charaSelect = this.GetAddonByName("CharaSelect");
var charaMake = this.GetAddonByName("CharaMake");
var titleDcWorldMap = this.GetAddonByName("TitleDCWorldMap");
if (charaMake != nint.Zero || charaSelect != nint.Zero || titleDcWorldMap != nint.Zero)
return false;
/// <returns>A value indicating whether or not the game is in the lobby scene.</returns>
internal bool IsInLobby() => RaptureAtkModule.Instance()->CurrentUIScene.StartsWith("LobbyMain"u8);

return !Service<ClientState.ClientState>.Get().IsLoggedIn;
}
/// <summary>
/// Sets the current background music.
/// </summary>
/// <param name="bgmId">The BGM row id.</param>
/// <param name="sceneId">The BGM scene index. Defaults to MiniGame scene to avoid conflicts.</param>
internal void SetBgm(ushort bgmId, uint sceneId = 2) => BGMSystem.SetBGM(bgmId, sceneId);

/// <summary>
/// Set the current background music.
/// Resets the current background music.
/// </summary>
/// <param name="bgmKey">The background music key.</param>
internal void SetBgm(ushort bgmKey) => this.setGlobalBgmHook.Original(bgmKey, 0, 0, 0, 0, 0);
/// <param name="sceneId">The BGM scene index.</param>
internal void ResetBgm(uint sceneId = 2) => BGMSystem.Instance()->ResetBGM(sceneId);

/// <summary>
/// Reset the stored "UI hide" state.
Expand All @@ -293,15 +283,6 @@ internal void ResetUiHideState()
this.GameUiHidden = false;
}

private IntPtr HandleSetGlobalBgmDetour(ushort bgmKey, byte a2, uint a3, uint a4, uint a5, byte a6)
{
var retVal = this.setGlobalBgmHook.Original(bgmKey, a2, a3, a4, a5, a6);

Log.Verbose("SetGlobalBgm: {0} {1} {2} {3} {4} {5} -> {6}", bgmKey, a2, a3, a4, a5, a6, retVal);

return retVal;
}

private void HandleItemHoverDetour(AgentItemDetail* thisPtr, uint frameCount)
{
this.handleItemHoverHook.Original(thisPtr, frameCount);
Expand Down
11 changes: 0 additions & 11 deletions Dalamud/Game/Gui/GameGuiAddressResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,6 @@ namespace Dalamud.Game.Gui;
/// </summary>
internal sealed class GameGuiAddressResolver : BaseAddressResolver
{
/// <summary>
/// Gets the base address of the native GuiManager class.
/// </summary>
public IntPtr BaseAddress { get; private set; }

/// <summary>
/// Gets the address of the native SetGlobalBgm method.
/// </summary>
public IntPtr SetGlobalBgm { get; private set; }

/// <summary>
/// Gets the address of the native HandleImm method.
/// </summary>
Expand All @@ -23,7 +13,6 @@ internal sealed class GameGuiAddressResolver : BaseAddressResolver
/// <inheritdoc/>
protected override void Setup64Bit(ISigScanner sig)
{
this.SetGlobalBgm = sig.ScanText("E8 ?? ?? ?? ?? 8B 2F"); // unnamed in CS
this.HandleImm = sig.ScanText("E8 ?? ?? ?? ?? 84 C0 75 10 48 83 FF 09"); // unnamed in CS
}
}
2 changes: 1 addition & 1 deletion Dalamud/Interface/Internal/DalamudCommands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ private void OnBgmSetCommand(string command, string arguments)
else
{
// Revert to the original BGM by specifying an invalid one
gameGui.SetBgm(9999);
gameGui.ResetBgm();
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Diagnostics;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Numerics;
Expand Down Expand Up @@ -194,6 +194,7 @@ Dalamud is licensed under AGPL v3 or later.
private readonly IFontAtlas privateAtlas;

private string creditsText;
private bool isBgmSet;

private bool resetNow = false;
private IDalamudTextureWrap? logoTexture;
Expand Down Expand Up @@ -222,10 +223,13 @@ public override unsafe void OnOpen()

this.creditsText = string.Format(CreditsTextTempl, typeof(Dalamud).Assembly.GetName().Version, pluginCredits, Util.GetGitHashClientStructs());

var gg = Service<GameGui>.Get();
if (!gg.IsOnTitleScreen() && UIState.Instance() != null)
var gameGui = Service<GameGui>.Get();
var playerState = PlayerState.Instance();

if (!gameGui.IsInLobby() && playerState != null)
{
gg.SetBgm((ushort)(UIState.Instance()->PlayerState.MaxExpansion > 3 ? 833 : 132));
gameGui.SetBgm((ushort)(playerState->MaxExpansion > 3 ? 833 : 132));
this.isBgmSet = true;
}

this.creditsThrottler.Restart();
Expand All @@ -242,9 +246,15 @@ public override void OnClose()
{
this.creditsThrottler.Reset();

var gg = Service<GameGui>.Get();
if (!gg.IsOnTitleScreen())
gg.SetBgm(9999);
if (this.isBgmSet)
{
var gameGui = Service<GameGui>.Get();

if (!gameGui.IsInLobby())
gameGui.ResetBgm();

this.isBgmSet = false;
}

Service<DalamudInterface>.Get().SetCreditsDarkeningAnimation(false);
}
Expand Down

0 comments on commit 722ee32

Please sign in to comment.