Skip to content
This repository has been archived by the owner on Jul 17, 2024. It is now read-only.

Commit

Permalink
Fix ARR title screens and detect title/lobby more reliably
Browse files Browse the repository at this point in the history
  • Loading branch information
slotthhy committed Jan 8, 2024
1 parent 763274c commit e627813
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 56 deletions.
13 changes: 13 additions & 0 deletions TitleEdit/GameLobbyType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace TitleEdit;

public enum GameLobbyType
{
Movie = -1,
Title = 0,
CharaSelect = 1,
Aetherial = 2,
LaNoscea = 3,
BlackShroud = 4,
Thanalan = 5,
Residence = 6,
}
93 changes: 38 additions & 55 deletions TitleEdit/TitleEdit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ private delegate IntPtr OnFixOn(IntPtr self,
private delegate ulong OnLoadLogoResource(IntPtr p1, string p2, int p3, int p4);
private delegate IntPtr OnPlayMusic(IntPtr self, string filename, float volume, uint fadeTime);
private delegate void SetTimePrototype(ushort timeOffset);
private delegate byte LobbyUpdate(GameLobbyType mapId, int time);

// The size of the BGMControl object
private const int ControlSize = 88;
Expand All @@ -34,13 +35,14 @@ private delegate IntPtr OnFixOn(IntPtr self,
private readonly Hook<OnPlayMusic> _playMusicHook;
private readonly Hook<OnFixOn> _fixOnHook;
private readonly Hook<OnLoadLogoResource> _loadLogoResourceHook;

private readonly Hook<LobbyUpdate> _lobbyUpdateHook;
private readonly SetTimePrototype _setTime;

private readonly string _titleScreenBasePath;
private bool _titleCameraNeedsSet;
private bool _amForcingTime;
private bool _amForcingWeather;
private GameLobbyType _lastLobbyUpdateMapId = GameLobbyType.Movie;

private TitleEditScreen _currentScreen;

Expand Down Expand Up @@ -72,10 +74,37 @@ public TitleEdit(TitleEditConfiguration configuration, string screenDir)
_fixOnHook = DalamudApi.Hooks.HookFromAddress<OnFixOn>(TitleEditAddressResolver.FixOn, HandleFixOn);
_loadLogoResourceHook =
DalamudApi.Hooks.HookFromAddress<OnLoadLogoResource>(TitleEditAddressResolver.LoadLogoResource, HandleLoadLogoResource);
_lobbyUpdateHook = DalamudApi.Hooks.HookFromAddress<LobbyUpdate>(TitleEditAddressResolver.LobbyUpdate, LobbyUpdateDetour);

_setTime = Marshal.GetDelegateForFunctionPointer<SetTimePrototype>(TitleEditAddressResolver.SetTime);
DalamudApi.PluginLog.Info("TitleEdit hook init finished");
}

private byte LobbyUpdateDetour(GameLobbyType mapId, int time)
{
_lastLobbyUpdateMapId = mapId;
var gameTitleScreen = TitleEditAddressResolver.GetGameExpectedTitleScreen(); // this is expac title, not GameLobbyType
var currentMap = (GameLobbyType)TitleEditAddressResolver.CurrentLobbyMap;

var isARRTitleScreen = gameTitleScreen == 0;
var isTitleScreenToLobby = currentMap == GameLobbyType.Title && mapId == GameLobbyType.CharaSelect;
var isLobbyToTitleScreen = currentMap == GameLobbyType.CharaSelect && mapId == GameLobbyType.Title;
var shouldApply = isARRTitleScreen && (isTitleScreenToLobby || isLobbyToTitleScreen);

DalamudApi.PluginLog.Verbose($"[LobbyUpdateDetour] map {mapId} time {time} currentMap {currentMap} " +
$"gameTitleScreen {gameTitleScreen} isARRTitleScreen {isARRTitleScreen} " +
$"isTitleScreenToLobby {isTitleScreenToLobby} isLobbyToTitleScreen {isLobbyToTitleScreen} " +
$"shouldApply {shouldApply}");

if (shouldApply)
{
DalamudApi.PluginLog.Debug($"[LobbyUpdateDetour] Running!");
// This tells the game it was playing a movie so it skips the "same zone" check entirely
TitleEditAddressResolver.CurrentLobbyMap = (short)GameLobbyType.Movie;
}

return _lobbyUpdateHook.Original(mapId, time);
}

internal void RefreshCurrentTitleEditScreen()
{
Expand Down Expand Up @@ -130,9 +159,7 @@ internal void RefreshCurrentTitleEditScreen()
if (GetState("_TitleMenu") == UiState.Visible)
DalamudApi.PluginInterface.UiBuilder.AddNotification($"Now displaying: {_currentScreen.Name}", "Title Edit", NotificationType.Info);
});

}

}

private bool IsScreenValid(TitleEditScreen screen)
Expand All @@ -158,25 +185,15 @@ private int HandleCreateScene(string p1, uint p2, IntPtr p3, uint p4, IntPtr p5,
_amForcingTime = false;
_amForcingWeather = false;

if (IsLobby(p1))
if (_lastLobbyUpdateMapId == GameLobbyType.CharaSelect)
{
Log("Loading lobby and lobby fixon.");
var returnVal = _createSceneHook.Original(p1, p2, p3, p4, p5, p6, p7);
FixOn(new Vector3(0, 0, 0), new Vector3(0, 0.8580103f, 0), 1);
return returnVal;
}

// Log("---------------");
// GetState("_ScreenText");
// GetState("Title");
// GetState("_TitleLogo");
// GetState("_TitleMenu");
// GetState("_TitleRevision");
// GetState("_TitleRights");
// GetState("CursorAddon");
// Log("---------------");

if (IsTitleScreen(p1))// && GetState("_ScreenText") != UiState.Null)

if (_lastLobbyUpdateMapId == GameLobbyType.Title)
{
Log("Loading custom title.");
RefreshCurrentTitleEditScreen();
Expand Down Expand Up @@ -295,6 +312,7 @@ public void Enable()
_createSceneHook.Enable();
_playMusicHook.Enable();
_fixOnHook.Enable();
_lobbyUpdateHook.Enable();
}

public void Dispose()
Expand All @@ -305,6 +323,7 @@ public void Dispose()
_createSceneHook.Dispose();
_playMusicHook.Dispose();
_fixOnHook.Dispose();
_lobbyUpdateHook.Dispose();
}

private void ForceTime(ushort timeOffset, int forceTime)
Expand Down Expand Up @@ -382,39 +401,6 @@ public void SetWeather(byte weather)
}
}

// TODO: Eventually figure out how to do these without excluding free trial players
private bool IsTitleScreen(string path)
{
var ret =
(path == "ex4/05_zon_z5/chr/z5c1/level/z5c1"
|| path == "ex3/05_zon_z4/chr/z4c1/level/z4c1"
|| path == "ex2/05_zon_z3/chr/z3c1/level/z3c1"
|| path == "ex1/05_zon_z2/chr/z2c1/level/z2c1"
|| path == "ffxiv/zon_z1/chr/z1c1/level/z1c1")
&& !IsLobby(path)
&& !IsCharaMake(path);
Log($"IsTitleScreen: {ret}");
return ret;
}

private bool IsLobby(string path)
{
var ret =
GetState("CharaSelect") == UiState.Visible
&& path == "ffxiv/zon_z1/chr/z1c1/level/z1c1";
Log($"IsLobby: {ret}");
return ret;
}

private bool IsCharaMake(string path)
{
var ret =
GetState("_CharaMakeBgSelector") == UiState.Visible
&& path == "ffxiv/zon_z1/chr/z1c1/level/z1c1";
Log($"IsCharaMake: {ret}");
return ret;
}

enum UiState
{
Null,
Expand All @@ -425,7 +411,7 @@ enum UiState
private unsafe UiState GetState(string uiName)
{
// Log($"GetState({uiName})");
var ui = (AtkUnitBase*)DalamudApi.GameGui.GetAddonByName(uiName, 1);
var ui = (AtkUnitBase*)DalamudApi.GameGui.GetAddonByName(uiName);
var ret = UiState.Null;
if (ui != null)
{
Expand All @@ -442,7 +428,7 @@ public unsafe void DisableTitleLogo(int delay = 2001)
Task.Delay(delay).ContinueWith(_ =>
{
Log($"Logo task running after {delay} delay");
var addon = (AtkUnitBase*)DalamudApi.GameGui.GetAddonByName("_TitleLogo", 1);
var addon = (AtkUnitBase*)DalamudApi.GameGui.GetAddonByName("_TitleLogo");
if (addon == null || addon->UldManager.NodeListCount < 2) return;
var node = addon->UldManager.NodeList[1];
if (node == null) return;
Expand All @@ -469,7 +455,7 @@ public unsafe void DisableTitleLogo(int delay = 2001)

public unsafe void EnableTitleLogo()
{
var addon = (AtkUnitBase*)DalamudApi.GameGui.GetAddonByName("_TitleLogo", 1);
var addon = (AtkUnitBase*)DalamudApi.GameGui.GetAddonByName("_TitleLogo");
if (addon == null || addon->UldManager.NodeListCount < 2) return;
var node = addon->UldManager.NodeList[1];
if (node == null) return;
Expand Down Expand Up @@ -589,9 +575,6 @@ private float[] FloatArrayFromVector3(Vector3 floats)

private void Log(string s)
{
#if !DEBUG
if (_configuration.DebugLogging)
#endif
DalamudApi.PluginLog.Debug($"[dbg] {s}");
}
}
2 changes: 1 addition & 1 deletion TitleEdit/TitleEdit.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<DalamudLibPath>$(appdata)\XIVLauncher\addon\Hooks\dev\</DalamudLibPath>
<PluginVersion>2.2.6.13</PluginVersion>
<PluginVersion>2.2.7.0</PluginVersion>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net7.0-windows</TargetFramework>
Expand Down
20 changes: 20 additions & 0 deletions TitleEdit/TitleEditAddressResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ public static IntPtr RenderCamera
public static IntPtr PlayMusic { get; private set; }
public static IntPtr BgmControl { get; private set; }
public static IntPtr WeatherPtrBase { get; private set; }
public static IntPtr LobbyUpdate { get; private set; }
public static IntPtr LobbyCurrentMap { get; private set; }
public static IntPtr LobbyThing { get; private set; }

public static void Setup64Bit()
{
Expand All @@ -38,6 +41,23 @@ public static void Setup64Bit()
PlayMusic = DalamudApi.SigScanner.ScanText("E8 ?? ?? ?? ?? 48 89 47 18 89 5F 20");
BgmControl = DalamudApi.SigScanner.GetStaticAddressFromSig("48 8B 05 ?? ?? ?? ?? 48 85 C0 74 37 83 78 08 04");
WeatherPtrBase = DalamudApi.SigScanner.GetStaticAddressFromSig("48 8B 05 ?? ?? ?? ?? 48 8B D9 0F 29 7C 24 ?? 41 8B FF");
LobbyUpdate = DalamudApi.SigScanner.ScanText("E8 ?? ?? ?? ?? EB 1C 3B CF");
LobbyCurrentMap = DalamudApi.SigScanner.GetStaticAddressFromSig("0F B7 05 ?? ?? ?? ?? 49 8B CE");
LobbyThing = DalamudApi.SigScanner.GetStaticAddressFromSig("48 8B 0D ?? ?? ?? ?? 8B 51 38 2B D3");
}

public static int GetGameExpectedTitleScreen()
{
unsafe
{
return *(int*) (*((nint*)LobbyThing) + 56);
}
}

public static short CurrentLobbyMap
{
get => Marshal.ReadInt16(LobbyCurrentMap);
set => Marshal.WriteInt16(LobbyCurrentMap, value);
}
}
}

0 comments on commit e627813

Please sign in to comment.