catastropy averted?
This commit is contained in:
@@ -0,0 +1,203 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user