2026-04-30 11:18:02 +03:00

204 lines
5.4 KiB
C#

using System;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Dalamud.Hooking;
using Dalamud.Plugin.Services;
using OmicronMountMusicFixer;
public class BGMController
{
public delegate void SongChangedHandler(int oldSong, int currentSong, int oldSecondSong, int secondSong);
private unsafe delegate DisableRestart* AddDisableRestartIdPrototype(BGMScene* scene, ushort songId);
private unsafe delegate int GetSpecialModeByScenePrototype(BGMPlayer* bgmPlayer);
private const SceneFlags SceneZeroFlags = SceneFlags.Resume;
private const int SceneCount = 12;
private const int PlayersCount = 2;
public SongChangedHandler OnSongChanged;
private readonly AddDisableRestartIdPrototype _addDisableRestartId;
private readonly Hook<GetSpecialModeByScenePrototype> _getSpecialModeForSceneHook;
public int OldSongId { get; private set; }
public int OldScene { get; private set; }
public int CurrentSongId { get; private set; }
public int CurrentScene { get; private set; }
public int SecondSongId { get; private set; }
public int SecondScene { get; private set; }
public int OldSecondSongId { get; private set; }
public int OldSecondScene { get; private set; }
public int PlayingSongId { get; private set; }
public int PlayingScene { get; private set; }
public int CurrentAudibleSong
{
get
{
if (PlayingSongId != 0)
{
return PlayingSongId;
}
return CurrentSongId;
}
}
public unsafe BGMController()
{
_addDisableRestartId = Marshal.GetDelegateForFunctionPointer<AddDisableRestartIdPrototype>(BGMAddressResolver.AddRestartId);
_getSpecialModeForSceneHook = DalamudApi.Hooks.HookFromAddress<GetSpecialModeByScenePrototype>((IntPtr)BGMAddressResolver.GetSpecialMode, (GetSpecialModeByScenePrototype)GetSpecialModeBySceneDetour, (HookBackend)0);
_getSpecialModeForSceneHook.Enable();
}
public void Dispose()
{
_getSpecialModeForSceneHook?.Disable();
_getSpecialModeForSceneHook?.Dispose();
}
public void SetSpecialModeHandling(bool value)
{
if (value)
{
_getSpecialModeForSceneHook.Enable();
}
else
{
_getSpecialModeForSceneHook.Disable();
}
}
public unsafe void Update()
{
ushort num = 0;
ushort num2 = 0;
int currentScene = 0;
int secondScene = 0;
if (BGMAddressResolver.BGMSceneList != IntPtr.Zero)
{
BGMScene* ptr = (BGMScene*)((IntPtr)BGMAddressResolver.BGMSceneList).ToPointer();
for (int i = 0; i < 12; i++)
{
if (PlayingSongId != 0 && i == PlayingScene)
{
if (ptr[PlayingScene].BgmId != PlayingSongId)
{
SetSong((ushort)PlayingSongId, PlayingScene);
}
}
else if (ptr[i].BgmReference != 0 && ptr[i].BgmId != 0 && ptr[i].BgmId != 9999)
{
if (num != 0)
{
num2 = ptr[i].BgmId;
secondScene = i;
break;
}
num = ptr[i].BgmId;
currentScene = i;
}
}
}
int oldSong = 0;
int currentSong = 0;
int oldSecondSong = 0;
int secondSong = 0;
bool flag = false;
bool flag2 = false;
if (CurrentSongId != num)
{
OldSongId = CurrentSongId;
OldScene = CurrentScene;
CurrentSongId = num;
CurrentScene = currentScene;
flag = true;
oldSong = OldSongId;
currentSong = CurrentSongId;
}
if (SecondSongId != num2)
{
OldSecondSongId = SecondSongId;
OldSecondScene = SecondScene;
SecondSongId = num2;
SecondScene = secondScene;
flag2 = true;
oldSecondSong = OldSecondSongId;
secondSong = SecondSongId;
}
if (flag || flag2)
{
OnSongChanged?.Invoke(oldSong, currentSong, oldSecondSong, secondSong);
}
}
public unsafe void SetSong(ushort songId, int priority = 0)
{
if ((priority < 0 || priority >= 12) ? true : false)
{
throw new IndexOutOfRangeException();
}
if ((songId != 0 && SongList.Instance.TryGetSong(songId, out var song) && !song.FileExists) || BGMAddressResolver.BGMSceneList == IntPtr.Zero)
{
return;
}
BGMScene* bgms = (BGMScene*)((IntPtr)BGMAddressResolver.BGMSceneList).ToPointer();
bgms[priority].BgmReference = songId;
bgms[priority].BgmId = songId;
bgms[priority].PreviousBgmId = songId;
if (songId == 0 && priority == 0)
{
bgms[priority].Flags = SceneFlags.Resume;
}
bgms[priority].Timer = 0f;
bgms[priority].TimerEnable = 0;
PlayingSongId = songId;
PlayingScene = priority;
if (SongList.Instance.IsDisableRestart(songId))
{
bgms[priority].Flags = SceneFlags.EnableDisableRestart;
_addDisableRestartId(bgms + priority, songId);
bgms[priority].Flags = SceneFlags.ForceAutoReset;
Task.Delay(500).ContinueWith(delegate
{
bgms[priority].Flags = SceneFlags.ForceAutoReset | SceneFlags.EnableDisableRestart;
});
}
}
private unsafe int GetSpecialModeBySceneDetour(BGMPlayer* player)
{
if (player->BgmScene != PlayingScene || player->BgmId != PlayingSongId)
{
return _getSpecialModeForSceneHook.Original(player);
}
if (!SongList.Instance.TryGetSong(player->BgmId, out var song))
{
return _getSpecialModeForSceneHook.Original(player);
}
uint bgmScene = 10u;
if (song.SpecialMode == 2)
{
bgmScene = 6u;
}
uint bgmScene2 = player->BgmScene;
player->BgmScene = bgmScene;
int result = _getSpecialModeForSceneHook.Original(player);
player->BgmScene = bgmScene2;
return result;
}
}