204 lines
5.4 KiB
C#
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;
|
|
}
|
|
}
|