From 6a96c1dc8115c07b64f600ef363ac4e33d316398 Mon Sep 17 00:00:00 2001 From: evelyntsmg Date: Sun, 31 May 2026 04:04:41 +0200 Subject: [PATCH 01/20] Refactor the archipelago client into ArchipelagoClientModule ... and everything that cascaded from there --- src/archipelago.cs | 449 +++--- src/client/client.cs | 206 +-- src/customization.cs | 549 ++++--- src/data/ArchipelagoData.cs | 2324 ++++++++++++++++------------ src/delegates/capture_delegates.cs | 2 +- src/gui/debugWindow.cs | 696 ++++----- src/gui/recent_items.cs | 3 +- src/gui/toast.cs | 3 +- src/hooks.cs | 1317 ++++++++-------- src/modules/captures.cs | 49 +- src/modules/deathlink.cs | 85 +- src/modules/hardcore_contest.cs | 10 +- src/modules/overdrives.cs | 286 ++-- 13 files changed, 3124 insertions(+), 2855 deletions(-) diff --git a/src/archipelago.cs b/src/archipelago.cs index 50395df..e38c784 100644 --- a/src/archipelago.cs +++ b/src/archipelago.cs @@ -25,14 +25,12 @@ using static Fahrenheit.FFX.Globals; //using Fahrenheit.Modules.ArchipelagoFFX.GUI; using static ArchipelagoFFX.ArchipelagoData; -using static ArchipelagoFFX.Client.FFXArchipelagoClient; using Color = Archipelago.MultiClient.Net.Models.Color; namespace ArchipelagoFFX; [FhLoad(FhGameId.FFX)] public unsafe partial class ArchipelagoFFXModule : FhModule { - public static FhModContext mod_context; private static FileStream global_state_file; @@ -41,9 +39,9 @@ public unsafe partial class ArchipelagoFFXModule : FhModule { private static ushort last_room_id = 0; private static ushort last_entrance_id = 0; - public static ArchipelagoData.RegionEnum current_region = ArchipelagoData.RegionEnum.None; - public static Dictionary region_is_unlocked = []; - public static Dictionary region_states = []; + public static RegionEnum current_region = RegionEnum.None; + public static Dictionary region_is_unlocked = []; + public static Dictionary region_states = []; public static SortedDictionary excess_inventory = []; public static SortedDictionary other_inventory = []; @@ -63,16 +61,55 @@ public unsafe partial class ArchipelagoFFXModule : FhModule { public static nint prev_length = 0; public static nint prev_bank = 0; - public static FhLogger logger; + private FhModuleHandle _client_handle; + private ArchipelagoClientModule? _client; + + private FhModuleHandle _gui_handle; + private ArchipelagoGuiModule? _gui; + + private FhModuleHandle _overdrives_handle; + private OverdriveModule? _overdrives; + + private FhModuleHandle _deathlink_handle; + private DeathLinkModule? _deathlink; + + private FhModuleHandle _hardcore_dreams_end_handle; + private HardcoreDreamsEndModule? _hardcore_dreams_end; public ArchipelagoFFXModule() { init_hooks(); + + _client_handle = new(this); + _gui_handle = new(this); + _hardcore_dreams_end_handle = new(this); + _deathlink_handle = new(this); + } + + public override bool init(FhModContext mod_context, FileStream global_state_file) { + ArchipelagoFFXModule.mod_context = mod_context; + ArchipelagoFFXModule.global_state_file = global_state_file; + + FhApi.Events.Common.GameLoop.PreUpdate.subscribe(pre_update); + + // Initialize Archipelago Client + initalize_states(); + //loadSeed(); + loadSeedList(); + load_global_state(); + + return hook() + && _client_handle.try_get_module(out _client) + && _gui_handle.try_get_module(out _gui) + && _hardcore_dreams_end_handle.try_get_module(out _hardcore_dreams_end) + && _deathlink_handle.try_get_module(out _deathlink);; } public static FhLangId? VoiceLanguage; public static FhLangId? TextLanguage; public static string LastSeed = ""; public static Dictionary SeedToServer = new(); + + //TODO: Transfer this to another file private class ArchipelagoGlobalState { public string LastVersion { get; set; } public FhLangId? VoiceLanguage { get; set; } @@ -82,52 +119,61 @@ private class ArchipelagoGlobalState { public Dictionary SeedToServer { get; set; } public bool ShowRecentItems { get; set; } - public ArchipelagoGlobalState() { - this.LastVersion = ArchipelagoFFXModule.Version.ToString(); - this.VoiceLanguage = ArchipelagoFFXModule.VoiceLanguage; - this.TextLanguage = ArchipelagoFFXModule.TextLanguage; - this.FontSize = ArchipelagoGUI.font_size; - this.LastSeed = ArchipelagoFFXModule.LastSeed; - this.SeedToServer = ArchipelagoFFXModule.SeedToServer; - this.ShowRecentItems = RecentItemsModule.show_recent_items; + public ArchipelagoGlobalState(ArchipelagoFFXModule module) { + LastVersion = ArchipelagoFFXModule.Version.ToString(); + VoiceLanguage = ArchipelagoFFXModule.VoiceLanguage; + TextLanguage = ArchipelagoFFXModule.TextLanguage; + FontSize = module._gui!.font_size; + LastSeed = ArchipelagoFFXModule.LastSeed; + SeedToServer = ArchipelagoFFXModule.SeedToServer; + ShowRecentItems = RecentItemsModule.show_recent_items; } } + //TODO: Transfer this to another file private class ArchipelagoState { - public string SeedId { get; set; } - public Dictionary region_states { get; set; } - public Dictionary region_is_unlocked { get; set; } - public Dictionary unlocked_characters { get; set; } - public SortedDictionary excess_inventory { get; set; } - public SortedDictionary other_inventory { get; set; } - public int[] celestial_level { get; set; } - public HashSet local_checked_locations { get; set; } - public int received_items { get; set; } - public bool enable_hardcore_dreams_end { get; set; } - public bool enable_deathlink { get; set; } - public string deathlink_send_type { get; set; } - public string deathlink_receive_type { get; set; } + public string SeedId { get; set; } + + public Dictionary region_states { get; set; } + public Dictionary region_is_unlocked { get; set; } + + public Dictionary unlocked_characters { get; set; } + + public SortedDictionary excess_inventory { get; set; } + public SortedDictionary other_inventory { get; set; } + + public int[] celestial_level { get; set; } + + public HashSet local_checked_locations { get; set; } + public int received_items { get; set; } + + public bool enable_hardcore_dreams_end { get; set; } + + public bool enable_deathlink { get; set; } + public string deathlink_send_type { get; set; } + public string deathlink_receive_type { get; set; } public bool skip_state_updates { get; set; } - public ArchipelagoState() { - this.SeedId = ArchipelagoFFXModule.seed.Options.SeedId; - this.region_states = ArchipelagoFFXModule.region_states; - this.region_is_unlocked = ArchipelagoFFXModule.region_is_unlocked; - this.unlocked_characters = ArchipelagoFFXModule.unlocked_characters; - this.excess_inventory = ArchipelagoFFXModule.excess_inventory; - this.other_inventory = ArchipelagoFFXModule.other_inventory; - this.celestial_level = ArchipelagoFFXModule.celestial_level; - this.skip_state_updates = ArchipelagoFFXModule.skip_state_updates; - this.local_checked_locations = FFXArchipelagoClient.local_checked_locations; - this.received_items = FFXArchipelagoClient.received_items; - this.enable_hardcore_dreams_end = HardcoreDreamsEndModule.get_enabled(); - this.enable_deathlink = DeathLinkModule.get_enabled(); - this.deathlink_send_type = DeathLinkModule.get_send_type(); - this.deathlink_receive_type = DeathLinkModule.get_receive_type(); + public ArchipelagoState(ArchipelagoFFXModule module) { + SeedId = ArchipelagoFFXModule.seed.Options.SeedId; + region_states = ArchipelagoFFXModule.region_states; + region_is_unlocked = ArchipelagoFFXModule.region_is_unlocked; + unlocked_characters = ArchipelagoFFXModule.unlocked_characters; + excess_inventory = ArchipelagoFFXModule.excess_inventory; + other_inventory = ArchipelagoFFXModule.other_inventory; + celestial_level = ArchipelagoFFXModule.celestial_level; + skip_state_updates = ArchipelagoFFXModule.skip_state_updates; + local_checked_locations = module._client!.local_checked_locations; + received_items = module._client!.received_items; + enable_hardcore_dreams_end = module._hardcore_dreams_end!.get_enabled(); + enable_deathlink = module._deathlink!.get_enabled(); + deathlink_send_type = module._deathlink!.get_send_type(); + deathlink_receive_type = module._deathlink!.get_receive_type(); } } + //TODO: Transfer this to another file public record Location(string location_name, int location_id, uint item_id, string item_name, string player_name); public struct ArchipelagoSeedOptions { [JsonInclude] public string PlayerName; @@ -155,15 +201,15 @@ public ArchipelagoSeedOptions() { PlayerName = ""; SeedId = ""; - Goal = ArchipelagoData.Goal.YuYevon; - GoalRequirement = ArchipelagoData.GoalRequirement.None; + Goal = Goal.YuYevon; + GoalRequirement = GoalRequirement.None; RequiredPartyMembers = 1; RequiredPrimers = 0; APMultiplier = 1; AlwaysSensor = 0; - CaptureRequirement = ArchipelagoData.CaptureRequirement.None; + CaptureRequirement = CaptureRequirement.None; AlwaysCapture = 0; CaptureDamage = 0; EncounterWeighting = 0; @@ -206,16 +252,17 @@ public struct ArchipelagoSeed { public Dictionary Gear { get; set; } public ArchipelagoSeed() { - this.Name = ArchipelagoFFXModule.seed.Name; - this.Options = ArchipelagoFFXModule.seed.Options; - this.Locations = ArchipelagoFFXModule.seed.Locations; - this.Gear = ArchipelagoFFXModule.seed.Gear; + Name = ArchipelagoFFXModule.seed.Name; + Options = ArchipelagoFFXModule.seed.Options; + Locations = ArchipelagoFFXModule.seed.Locations; + Gear = ArchipelagoFFXModule.seed.Gear; } } public record ArchipelagoItem(uint id, string name, string player) { //public GCHandle name_handle = GCHandle.Alloc(FhEncoding.Us.to_bytes(name), GCHandleType.Pinned); } + //TODO: Transfer this to another file public static List cached_strings = []; public record ArchipelagoLocations(ArchipelagoSeedLocations seed) { public Dictionary treasure = seed.Treasure.ToDictionary( x => x.location_id, x => new ArchipelagoItem(x.item_id, x.item_name, x.player_name)); @@ -230,15 +277,15 @@ public record ArchipelagoLocations(ArchipelagoSeedLocations seed) { public bool location_to_item(int location, [MaybeNullWhen(false)] out ArchipelagoItem item) { var dict = (location & 0xF000) switch { - (int)FFXArchipelagoClient.ArchipelagoLocationType.Treasure => treasure, - (int)FFXArchipelagoClient.ArchipelagoLocationType.Boss => boss, - (int)FFXArchipelagoClient.ArchipelagoLocationType.PartyMember => party_member, - (int)FFXArchipelagoClient.ArchipelagoLocationType.Overdrive => overdrive, - (int)FFXArchipelagoClient.ArchipelagoLocationType.OverdriveMode => overdrive_mode, - (int)FFXArchipelagoClient.ArchipelagoLocationType.Other => other, - (int)FFXArchipelagoClient.ArchipelagoLocationType.Recruit => recruit, - (int)FFXArchipelagoClient.ArchipelagoLocationType.SphereGrid => sphere_grid, - (int)FFXArchipelagoClient.ArchipelagoLocationType.Capture => capture, + (int)ArchipelagoClientModule.ArchipelagoLocationType.Treasure => treasure, + (int)ArchipelagoClientModule.ArchipelagoLocationType.Boss => boss, + (int)ArchipelagoClientModule.ArchipelagoLocationType.PartyMember => party_member, + (int)ArchipelagoClientModule.ArchipelagoLocationType.Overdrive => overdrive, + (int)ArchipelagoClientModule.ArchipelagoLocationType.OverdriveMode => overdrive_mode, + (int)ArchipelagoClientModule.ArchipelagoLocationType.Other => other, + (int)ArchipelagoClientModule.ArchipelagoLocationType.Recruit => recruit, + (int)ArchipelagoClientModule.ArchipelagoLocationType.SphereGrid => sphere_grid, + (int)ArchipelagoClientModule.ArchipelagoLocationType.Capture => capture, _ => null, }; item = dict?.GetValueOrDefault(location & 0xFFF); @@ -253,21 +300,21 @@ public record ArchipelagoGear(int id, byte flags, byte owner, byte type, byte dm public static ArchipelagoLocations item_locations = new(new()); public static List loaded_seeds = []; - public static void loadSeedList() { + public void loadSeedList() { var seeds = mod_context.Paths.ResourcesDir.GetDirectories("seeds").FirstOrDefault()?.GetFiles("*.apffx"); if (seeds is null || seeds.Length == 0) { - logger.Warning("No seeds found"); + _logger.Warning("No seeds found"); return; } foreach (FileInfo file in seeds) { try { using ZipArchive apffx = ZipFile.OpenRead(file.FullName); - ZipArchiveEntry zippedOptions = apffx.GetEntry("options.json")!; - ZipArchiveEntry zippedLocations = apffx.GetEntry("locations.json")!; - ZipArchiveEntry zippedGear = apffx.GetEntry("gear.json")!; + ZipArchiveEntry? zippedOptions = apffx.GetEntry("options.json")!; + ZipArchiveEntry? zippedLocations = apffx.GetEntry("locations.json")!; + ZipArchiveEntry? zippedGear = apffx.GetEntry("gear.json")!; - if (zippedOptions != null && zippedLocations != null) { + if (zippedOptions is not null && zippedLocations is not null) { using Stream optionsStream = zippedOptions.Open(); using StreamReader optionsReader = new StreamReader(optionsStream); string optionsContents = optionsReader.ReadToEnd(); @@ -289,81 +336,65 @@ public static void loadSeedList() { Locations = loaded_locations, Gear = loaded_gear.ToDictionary(gear => gear.id), }); - } - else { + } else { throw new ArgumentNullException("apffx file is null"); } - } - catch (Exception e) { - logger.Warning($"Failed to load {file.Name} - {e.Message}"); + } catch (Exception e) { + _logger.Warning($"Failed to load {file.Name} - {e.Message}"); } } } - public static bool loadSeed() { + public bool loadSeed() { string message; - if (FFXArchipelagoClient.SeedId is not null) { - ArchipelagoSeed seed = loaded_seeds.FirstOrDefault(seed => seed.Options.SeedId == FFXArchipelagoClient.SeedId)!; + if (_client!.SeedId is not null) { + ArchipelagoSeed seed = loaded_seeds.FirstOrDefault(seed => seed.Options.SeedId == _client!.SeedId)!; if (seed.Options.SeedId is not null) return loadSeed(seed); message = "Seed for connected slot not found"; - ArchipelagoGUI.add_log_message([(message, Color.Red)]); - logger.Error($"Seed for connected slot not found"); + _gui!.add_log_message([(message, Color.Red)]); + _logger.Error(message); return false; - } else if (ArchipelagoGUI.selected_seed < loaded_seeds.Count) { - return loadSeed(loaded_seeds[ArchipelagoGUI.selected_seed]); } + + if (_gui!.selected_seed < loaded_seeds.Count) { + return loadSeed(loaded_seeds[_gui!.selected_seed]); + } + message = "No seeds found"; - ArchipelagoGUI.add_log_message([(message, Color.Red)]); - logger.Error(message); + _gui!.add_log_message([(message, Color.Red)]); + _logger.Error(message); return false; } - public static bool loadSeed(ArchipelagoSeed loaded_seed) { - lock (client_lock) { - if (FFXArchipelagoClient.is_connected) { - if (FFXArchipelagoClient.SeedId != loaded_seed.Options.SeedId) { + public bool loadSeed(ArchipelagoSeed loaded_seed) { + lock (_client!.client_lock) { + if (_client!.is_connected) { + if (_client!.SeedId != loaded_seed.Options.SeedId) { string message = "Seed doesn't match connected slot"; - ArchipelagoGUI.add_log_message([(message, Color.Red)]); - logger.Error(message); + _gui!.add_log_message([(message, Color.Red)]); + _logger.Error(message); return false; - } else { - if (FFXArchipelagoClient.current_server != null) { - SeedToServer[SeedId] = FFXArchipelagoClient.current_server; - } + } + + if (_client!.current_server != null) { + SeedToServer[_client!.SeedId] = _client!.current_server; } } } + initalize_states(); seed = loaded_seed; ap_multiplier = seed.Options.APMultiplier; - HardcoreDreamsEndModule.set_enabled(seed.Options.HardcoreDreamsEnd != 0); + _hardcore_dreams_end!.set_enabled(seed.Options.HardcoreDreamsEnd != 0); item_locations = new ArchipelagoLocations(seed.Locations); - ArchipelagoGUI.selected_seed = loaded_seeds.FindIndex(x => x.Options.SeedId == seed.Options.SeedId); + _gui!.selected_seed = loaded_seeds.FindIndex(x => x.Options.SeedId == seed.Options.SeedId); LastSeed = seed.Options.SeedId; save_global_state(); return true; } - public override bool init(FhModContext mod_context, FileStream global_state_file) { - ArchipelagoFFXModule.mod_context = mod_context; - ArchipelagoFFXModule.global_state_file = global_state_file; - - FhApi.Events.Common.GameLoop.PreUpdate.subscribe(pre_update); - - // Initialize Archipelago Client - - ArchipelagoGUI.shiori_file = ArchipelagoFFXModule.mod_context.Paths.ResourcesDir.GetFiles("shiori.png").FirstOrDefault(); - logger = _logger; - initalize_states(); - //loadSeed(); - loadSeedList(); - load_global_state(); - - return hook(); - } - public static void initalize_states() { region_is_unlocked.Clear(); foreach (var region in region_to_ids) { @@ -387,19 +418,22 @@ public static void initalize_states() { } + //TODO: Transfer to another file [GeneratedRegex("^(?0|[1-9]\\d*)\\.(?0|[1-9]\\d*)\\.(?0|[1-9]\\d*)(?:-(?(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+(?[0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$")] private static partial Regex RegexSemVer(); - private static readonly string VersionString = Assembly.GetExecutingAssembly().GetCustomAttribute().InformationalVersion; + private static readonly string VersionString = Assembly.GetExecutingAssembly().GetCustomAttribute()!.InformationalVersion; private static readonly SemVer FullVersion = new(VersionString); private static readonly SemVer Version = FullVersion.WithoutMetadata(); - private record SemVer(int major, - int minor, - int patch, - string prerelease = "", - string buildmetadata = "") : IComparable, IEquatable { - public SemVer(string versionString) : this(0, 0, 0, "", "") { + private record SemVer( + int major, + int minor, + int patch, + string prerelease = "", + string buildmetadata = "" + ) : IComparable, IEquatable { + public SemVer(string versionString) : this(0, 0, 0) { try { var version_match = RegexSemVer().Match(versionString); major = int.Parse(version_match.Groups["major"].Value); @@ -414,7 +448,9 @@ public SemVer(string versionString) : this(0, 0, 0, "", "") { } public SemVer WithoutMetadata() { - return new SemVer(major, minor, patch, prerelease, ""); + return this with { + buildmetadata = "", + }; } public override string ToString() { @@ -484,24 +520,27 @@ public int CompareTo(SemVer? other) { } public override void save_local_state(FileStream local_state_file) { - ArchipelagoState state = new(); + ArchipelagoState state = new(this); JsonSerializer.Serialize(local_state_file, state); local_state_file.SetLength(local_state_file.Position); } + public override void load_local_state(FileStream local_state_file, FhLocalStateInfo local_state_info) { SemVer save_version = new(local_state_info.Version); if (save_version != Version) { - logger.Warning($"Saved with different AP version: current:{Version} save:{save_version}"); + _logger.Warning($"Saved with different AP version! Current is {Version} but save is {save_version}"); if (save_version == new SemVer(0, 0, 0)) { string message = "Invalid save version. Returning to main menu"; - ArchipelagoGUI.add_log_message([(message, Color.Red)]); - logger.Error(message); + _gui!.add_log_message([(message, Color.Red)]); + _logger.Error(message); return; - } else if (save_version < new SemVer(0, 8, 0, "alpha")) { + } + + if (save_version < new SemVer(0, 8, 0, "alpha")) { string message = "Incompatible version. Returning to main menu"; - ArchipelagoGUI.add_log_message([(message, Color.Red)]); - logger.Info(message); + _gui!.add_log_message([(message, Color.Red)]); + _logger.Info(message); return; } } @@ -509,19 +548,19 @@ public override void load_local_state(FileStream local_state_file, FhLocalStateI var loaded_state = JsonSerializer.Deserialize(local_state_file); if (loaded_state != null) { // Don't let client sync remote locations until seed is fully loaded - lock (FFXArchipelagoClient.client_lock) { + lock (_client!.client_lock) { ArchipelagoSeed seed = loaded_seeds.FirstOrDefault(s => s.Options.SeedId == loaded_state.SeedId)!; if (seed.Options.SeedId is not null) { if (!loadSeed(seed)) { - FFXArchipelagoClient.disconnect(); + _client!.disconnect(); return; } } else { string message = "Seed for loaded state not found"; - ArchipelagoGUI.add_log_message([(message, Color.Red)]); - logger.Error(message); - FFXArchipelagoClient.disconnect(); + _gui!.add_log_message([(message, Color.Red)]); + _logger.Error(message); + _client!.disconnect(); return; } foreach (var region in loaded_state.region_states) { @@ -546,35 +585,35 @@ public override void load_local_state(FileStream local_state_file, FhLocalStateI other_inventory[item_id] = amount; } - if (FFXArchipelagoClient.is_connected) + if (_client!.is_connected) { for (int i = 0; i <= 103; i++) { int qty = save_data->monsters_captured[i]; if (qty > 0) - FFXArchipelagoClient.current_session!.DataStorage[Scope.Slot, "FFX_CAPTURE_" + i] = qty; + _client!.current_session!.DataStorage[Scope.Slot, "FFX_CAPTURE_" + i] = qty; else - FFXArchipelagoClient.current_session!.DataStorage[Scope.Slot, "FFX_CAPTURE_" + i] = 0; + _client!.current_session!.DataStorage[Scope.Slot, "FFX_CAPTURE_" + i] = 0; } - FFXArchipelagoClient.current_session!.DataStorage[Scope.Slot, "FFX_TIDUS_OVERDRIVE"] = save_data->tidus_limit_uses; + _client!.current_session!.DataStorage[Scope.Slot, "FFX_TIDUS_OVERDRIVE"] = save_data->tidus_limit_uses; } loaded_state.celestial_level.CopyTo(celestial_level, 0); - FFXArchipelagoClient.local_checked_locations.Clear(); - FFXArchipelagoClient.local_checked_locations.UnionWith(loaded_state.local_checked_locations); - FFXArchipelagoClient.local_locations_updated = true; - FFXArchipelagoClient.remote_locations_updated = true; - FFXArchipelagoClient.received_items = loaded_state.received_items; + _client!.local_checked_locations.Clear(); + _client!.local_checked_locations.UnionWith(loaded_state.local_checked_locations); + _client!.local_locations_updated = true; + _client!.remote_locations_updated = true; + _client!.received_items = loaded_state.received_items; skip_state_updates = loaded_state.skip_state_updates; } - HardcoreDreamsEndModule.set_enabled(loaded_state.enable_hardcore_dreams_end); + _hardcore_dreams_end!.set_enabled(loaded_state.enable_hardcore_dreams_end); - DeathLinkModule.set_enabled(loaded_state.enable_deathlink); - DeathLinkModule.set_send_type(loaded_state.deathlink_send_type); - DeathLinkModule.set_receive_type(loaded_state.deathlink_receive_type); + _deathlink!.set_enabled(loaded_state.enable_deathlink); + _deathlink!.set_send_type(loaded_state.deathlink_send_type); + _deathlink!.set_receive_type(loaded_state.deathlink_receive_type); } } - public static bool load_global_state() { + public bool load_global_state() { try { global_state_file.Position = 0; var loaded_state = JsonSerializer.Deserialize(global_state_file); @@ -582,9 +621,9 @@ public static bool load_global_state() { VoiceLanguage = loaded_state.VoiceLanguage; TextLanguage = loaded_state.TextLanguage; - ArchipelagoGUI.voice_lang = VoiceLanguage.HasValue ? (byte)VoiceLanguage.Value : (byte)0xFF; - ArchipelagoGUI.text_lang = TextLanguage.HasValue ? (byte)TextLanguage.Value : (byte)0xFF; - ArchipelagoGUI.font_size = loaded_state.FontSize; + _gui!.voice_lang = VoiceLanguage.HasValue ? (byte)VoiceLanguage.Value : (byte)0xFF; + _gui!.text_lang = TextLanguage.HasValue ? (byte)TextLanguage.Value : (byte)0xFF; + _gui!.font_size = loaded_state.FontSize; LastSeed = loaded_state.LastSeed; RecentItemsModule.show_recent_items = loaded_state.ShowRecentItems; @@ -596,23 +635,23 @@ public static bool load_global_state() { if (loaded_seeds.Count > 0) { int selected_seed = loaded_seeds.FindIndex(x => x.Options.SeedId == LastSeed); if (selected_seed == -1) selected_seed = 0; - ArchipelagoGUI.selected_seed = selected_seed; - ArchipelagoGUI.client_input_name = loaded_seeds[selected_seed].Options.PlayerName; + _gui!.selected_seed = selected_seed; + _gui!.client_input_name = loaded_seeds[selected_seed].Options.PlayerName; if (SeedToServer.TryGetValue(LastSeed, out string? server)) { - ArchipelagoGUI.client_input_address = server; + _gui!.client_input_address = server; } else { - ArchipelagoGUI.client_input_address = ArchipelagoGUI.DEFAULT_CLIENT_ADDRESS; + _gui!.client_input_address = ArchipelagoGuiModule.DEFAULT_CLIENT_ADDRESS; } } return true; - } - catch (Exception) { + } catch (Exception e) { + _logger.Error($"Could not load global state: {e.Message}"); return false; } } - public static bool save_global_state() { - ArchipelagoGlobalState state = new(); + public bool save_global_state() { + ArchipelagoGlobalState state = new(this); global_state_file.Position = 0; JsonSerializer.Serialize(global_state_file, state); global_state_file.SetLength(global_state_file.Position); @@ -622,15 +661,15 @@ public static bool save_global_state() { public void pre_update(UpdateLoopEventArgs args) { // Update Archipelago Client - FFXArchipelagoClient.update(); - if (last_story_progress != Globals.save_data->story_progress) { - ushort story_progress = Globals.save_data->story_progress; + _client!.update(); + if (last_story_progress != save_data->story_progress) { + ushort story_progress = save_data->story_progress; _logger.Info($"story_progress changed: {last_story_progress} -> {story_progress}"); - if (current_region != ArchipelagoData.RegionEnum.None) { - ArchipelagoData.ArchipelagoRegion region = region_states[current_region]; + if (current_region != RegionEnum.None) { + ArchipelagoRegion region = region_states[current_region]; if (region.story_checks.TryGetValue(story_progress, out var storyCheck)) { - storyCheck.check_delegate?.Invoke(region); + storyCheck.check_delegate?.Invoke(region, _client!, this); if (storyCheck.return_to_airship) { call_warp_to_map(382, 0); } @@ -649,23 +688,22 @@ public void pre_update(UpdateLoopEventArgs args) { if (completedPilgrimages >= pilgrimageStoryChecks.Length) { color = Color.Green; } - ArchipelagoGUI.add_log_message([(message, color)]); + _gui!.add_log_message([(message, color)]); } } } last_story_progress = story_progress; } - if (last_room_id != Globals.save_data->current_room_id && Globals.save_data->current_room_id != 0xFFFF) { - _logger.Info($"Room changed: Entered {Globals.save_data->current_room_id} at entrance {Globals.save_data->current_spawnpoint}"); + if (last_room_id != save_data->current_room_id && save_data->current_room_id != 0xFFFF) { + _logger.Info($"Room changed: Entered {save_data->current_room_id} at entrance {save_data->current_spawnpoint}"); on_map_change(); - last_room_id = Globals.save_data->current_room_id; - last_entrance_id = Globals.save_data->current_spawnpoint; + last_room_id = save_data->current_room_id; + last_entrance_id = save_data->current_spawnpoint; - lock (client_lock) { - if (FFXArchipelagoClient.is_connected) - { - FFXArchipelagoClient.current_session!.DataStorage[Scope.Slot, "FFX_ROOM"] = last_room_id; + lock (_client!.client_lock) { + if (_client!.is_connected) { + _client!.current_session!.DataStorage[Scope.Slot, "FFX_ROOM"] = last_room_id; } } } @@ -685,34 +723,35 @@ public override void handle_input() { } } */ - if (Globals.Input.l1.held && Globals.Input.r1.held && Globals.Input.start.just_pressed) { + if (Input.l1.held && Input.r1.held && Input.start.just_pressed) { _logger.Debug("Soft Reset"); //Globals.save_data->current_room_id = 23; - if (Globals.Battle.btl->battle_state != 0) { - Globals.Battle.btl->battle_end_type = 1; + if (Battle.btl->battle_state != 0) { + Battle.btl->battle_end_type = 1; } else { call_warp_to_map(23, 0); } } + if (Input.select.held && Input.l1.just_pressed) { #if DEBUG - AtelBasicWorker* worker0 = Globals.Atel.controllers[0].worker(0); + AtelBasicWorker* worker0 = Atel.controllers[0].worker(0); float minDistance = -1; int closestEntranceIndex = -1; for (int i = 0; i < worker0->script_chunk->map_entrances.Length; i++) { MapEntrance entrance = worker0->script_chunk->map_entrances[i]; Vector4 pos = new(entrance.x, entrance.y, entrance.z, 0); - float distance = (Globals.actors->chr_pos_vec - pos).Length(); - logger.Debug($"Entrance: pos:({entrance.x}, {entrance.y}, {entrance.z}) distance:{distance}"); + float distance = (actors->chr_pos_vec - pos).Length(); + _logger.Debug($"Entrance: pos:({entrance.x}, {entrance.y}, {entrance.z}) distance:{distance}"); if (closestEntranceIndex == -1 || distance < minDistance) { minDistance = distance; closestEntranceIndex = i; } } MapEntrance closestEntrance = worker0->script_chunk->map_entrances[closestEntranceIndex]; - logger.Debug($"Closest Entrance: pos:({closestEntrance.x}, {closestEntrance.y}, {closestEntrance.z}) distance:{minDistance}"); + _logger.Debug($"Closest Entrance: pos:({closestEntrance.x}, {closestEntrance.y}, {closestEntrance.z}) distance:{minDistance}"); #endif @@ -782,12 +821,14 @@ public override void handle_input() { //_ChN_ReadSystemMGRP(2, 2); // Load Swimming motion group } - if (Globals.Input.select.held && Globals.Input.r1.just_pressed) { - _logger.Info($"Resetting party"); + + if (Input.select.held && Input.r1.just_pressed) { + _logger.Info("Resetting party"); save_party(); reset_party(); } - if (Globals.Input.select.held && Globals.Input.l2.just_pressed) { + + if (Input.select.held && Input.l2.just_pressed) { //foreach (var state in region_states) { // _logger.Debug($"{state.Key}: story_progress={state.Value.Story_progress}, room_id={state.Value.room_id}, entrance={state.Value.entrance}"); //} @@ -801,15 +842,15 @@ public override void handle_input() { _logger.Debug($"bank: {bank[0]} {bank[1]} {bank[2]} {bank[3]}"); */ //get_party_frontline(); - } - if (Globals.Input.select.held && Globals.Input.r2.just_pressed) { + + if (Input.select.held && Input.r2.just_pressed) { //_logger.Debug("Warp to Airship"); //call_warp_to_map(382, 0); } } - public static void call_warp_to_map(int map_id, int entrance_id) { + public void call_warp_to_map(int map_id, int entrance_id) { AtelStack stack = new AtelStack(); stack.push_int(map_id); stack.push_int(entrance_id); @@ -819,7 +860,8 @@ public static void call_warp_to_map(int map_id, int entrance_id) { h_Common_warpToMap((AtelBasicWorker*)&work, &storage, &stack); } - public static void call_remove_party_member(int character_id, bool long_term = false) { + + public void call_remove_party_member(int character_id, bool long_term = false) { AtelStack stack = new AtelStack(); stack.push_int(character_id); @@ -830,7 +872,7 @@ public static void call_remove_party_member(int character_id, bool long_term = f else h_Common_removePartyMemberLongTerm((AtelBasicWorker*)&work, &storage, &stack); } - public static void call_add_party_member(int character_id) { + public void call_add_party_member(int character_id) { AtelStack stack = new AtelStack(); stack.push_int(character_id); @@ -840,7 +882,7 @@ public static void call_add_party_member(int character_id) { h_Common_addPartyMember((AtelBasicWorker*)&work, &storage, &stack); } - public static void call_put_party_member_in_slot(int slot, int character_id) { + public void call_put_party_member_in_slot(int slot, int character_id) { AtelStack stack = new AtelStack(); stack.push_int(slot); stack.push_int(character_id); @@ -851,7 +893,7 @@ public static void call_put_party_member_in_slot(int slot, int character_id) { h_Common_putPartyMemberInSlot((AtelBasicWorker*)&work, &storage, &stack); } - public static uint[] get_party_frontline() { + public uint[] get_party_frontline() { uint slot1 = 0; uint slot2 = 0; uint slot3 = 0; @@ -861,24 +903,24 @@ public static uint[] get_party_frontline() { return [slot1, slot2, slot3]; } - public static void save_party() { + public void save_party() { //Globals.save_data->atel_is_push_member = 1; for (int character = 0; character < NUM_CHARACTERS; character++) { if (is_character_unlocked(character)) { - Globals.save_data->atel_push_party |= (byte)(1 << (byte)character); + save_data->atel_push_party |= (byte)(1 << (byte)character); } else { - Globals.save_data->atel_push_party &= (byte)(0xff ^ (1 << (byte)character)); + save_data->atel_push_party &= (byte)(0xff ^ (1 << (byte)character)); } } var party_formation = get_party_frontline(); for (int i = 0; i < 3; i++) { - Globals.save_data->atel_push_frontline[i] = (byte)party_formation[i]; + save_data->atel_push_frontline[i] = (byte)party_formation[i]; } } - public static void reset_party() { + public void reset_party() { //call_put_party_member_in_slot(0, (PlySaveId)0xff); //call_put_party_member_in_slot(1, (PlySaveId)0xff); //call_put_party_member_in_slot(2, (PlySaveId)0xff); @@ -899,10 +941,11 @@ public static void reset_party() { call_remove_party_member(character, !locked_characters[character]); } } + slot = 0; List frontline = []; for (int i = 0; i < 3; i++) { - byte character = Globals.save_data->atel_push_frontline[i]; + byte character = save_data->atel_push_frontline[i]; if (character == 0xff || !is_character_unlocked(character) || frontline.Contains(character)) { while (slot < 3 && (frontline.Contains(unlocked[slot]) || unlocked[slot] > 7)) slot++; if (slot < 3) character = unlocked[slot++]; @@ -914,8 +957,8 @@ public static void reset_party() { //Globals.save_data->atel_is_push_member = 0; } - public static void set_party(List characters, bool saveParty = true, bool onlyUnlocked = true) { - logger.Debug($"Setting party to: {String.Join(", ", characters.Select(i => id_to_character[i]))}"); + public void set_party(List characters, bool saveParty = true, bool onlyUnlocked = true) { + _logger.Debug($"Setting party to: {String.Join(", ", characters.Select(i => id_to_character[i]))}"); party_overridden = true; if (saveParty) { save_party(); @@ -943,28 +986,28 @@ public static void set_party(List characters, bool saveParty = true, bool o } } - public static void set_underwater_party(bool saveParty = true, bool onlyUnlocked = true) { + public void set_underwater_party(bool saveParty = true, bool onlyUnlocked = true) { set_party([PlySaveId.PC_TIDUS, PlySaveId.PC_WAKKA, PlySaveId.PC_RIKKU], saveParty, onlyUnlocked); } - public static void set_summon_party(bool saveParty = true, bool onlyUnlocked = true) { + public void set_summon_party(bool saveParty = true, bool onlyUnlocked = true) { set_party([ PlySaveId.PC_YUNA, PlySaveId.PC_VALEFOR, PlySaveId.PC_IFRIT, PlySaveId.PC_IXION, PlySaveId.PC_SHIVA, PlySaveId.PC_BAHAMUT, PlySaveId.PC_ANIMA, PlySaveId.PC_YOJIMBO, PlySaveId.PC_MAGUS1, PlySaveId.PC_MAGUS2, PlySaveId.PC_MAGUS3 ], saveParty, onlyUnlocked); } - public static void set_character_model(int chr_id) { + public void set_character_model(int chr_id) { AtelStack stack = new AtelStack(); stack.push_int(chr_id + 1); - AtelBasicWorker* worker0 = Globals.Atel.controllers[0].worker(0); + AtelBasicWorker* worker0 = Atel.controllers[0].worker(0); int storage = 0; _Common_loadModel(worker0, &storage, &stack); stack.push_int(0); _Common_linkFieldToBattleActor(worker0, &storage, &stack); } - public static uint allocate_file(string filename, out nint file_ptr) { + public uint allocate_file(string filename, out nint file_ptr) { int[] fileStream = [0,0]; uint readBytes = 0; file_ptr = 0; @@ -973,21 +1016,17 @@ public static uint allocate_file(string filename, out nint file_ptr) { nint pFilename = Marshal.StringToHGlobalAnsi(filename); h_openFile((nint)fs, pFilename, true, 0, 0, 1); Marshal.FreeHGlobal(pFilename); - logger.Debug($"file_handle={fileStream[0]}, file_length={*(long*)(*(int*)(fileStream[1] + 0xc) + 8)}"); + _logger.Debug($"file_handle={fileStream[0]}, file_length={*(long*)(*(int*)(fileStream[1] + 0xc) + 8)}"); if (fileStream[1] == 0) return 0; var file_length = *(long*)(*(int*)(fileStream[1] + 0xc) + 8); file_ptr = Marshal.AllocHGlobal((int)file_length); uint max_len = (uint)file_length; readBytes = _readFile((nint)fs, file_ptr, max_len); } - logger.Debug($"read {readBytes}, beginning={((byte*)file_ptr)[0]} {((byte*)file_ptr)[1]} {((byte*)file_ptr)[2]} {((byte*)file_ptr)[3]}"); + _logger.Debug($"read {readBytes}, beginning={((byte*)file_ptr)[0]} {((byte*)file_ptr)[1]} {((byte*)file_ptr)[2]} {((byte*)file_ptr)[3]}"); return readBytes; } - public override void render_imgui() { - ArchipelagoGUI.render(); - } - public struct CustomStringDrawInfo(ManagedCustomString customString, Vector2 pos, float scale = 0.65f, byte color = 0, bool persistent = false) { public ManagedCustomString customString = customString; public Vector2 pos = pos; @@ -996,7 +1035,7 @@ public struct CustomStringDrawInfo(ManagedCustomString customString, Vector2 pos public bool persistent = persistent; } - public static Dictionary customStringDrawInfos = []; + public Dictionary customStringDrawInfos = []; public override void render_game() { foreach ((string key, CustomStringDrawInfo drawInfo) in customStringDrawInfos) { diff --git a/src/client/client.cs b/src/client/client.cs index 859c6f7..feb589a 100644 --- a/src/client/client.cs +++ b/src/client/client.cs @@ -8,6 +8,7 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Threading.Tasks; @@ -15,25 +16,55 @@ using ArchipelagoFFX.GUI; +using Fahrenheit; + namespace ArchipelagoFFX.Client; -public static class FFXArchipelagoClient { - public static readonly System.Threading.Lock client_lock = new(); - public static ArchipelagoSession? current_session; - public static string? current_server; - public static int received_items = 0; - public static readonly HashSet local_checked_locations = []; - public static bool local_locations_updated = false; - public static bool remote_locations_updated = false; - public static string? SeedId = null; - - public static DeathLinkService? current_death_link; - - public static PlayerInfo? active_player => current_session?.Players.ActivePlayer; - private static bool is_disconnecting = false; - public static bool is_connected => current_session is not null && !is_disconnecting; - - public static async Task Connect(string server, string user, string password) { - ArchipelagoFFXModule.logger.Debug("Connect"); + +[FhLoad(FhGameId.FFX)] +public class ArchipelagoClientModule : FhModule { + public readonly System.Threading.Lock client_lock = new(); + public ArchipelagoSession? current_session; + public string? current_server; + public int received_items = 0; + public readonly HashSet local_checked_locations = []; + public bool local_locations_updated = false; + public bool remote_locations_updated = false; + public string? SeedId = null; + + public DeathLinkService? current_death_link_service; + + public PlayerInfo? active_player => current_session?.Players.ActivePlayer; + private bool is_disconnecting = false; + public bool is_connected => current_session is not null && !is_disconnecting; + + private FhModuleHandle _ffx_interop_handle; + private ArchipelagoFFXModule? _ffx_interop; + + private FhModuleHandle _gui_handle; + private ArchipelagoGuiModule? _gui; + + private FhModuleHandle _recent_items_handle; + private RecentItemsModule? _recent_items; + + private FhModuleHandle _death_link_handle; + private DeathLinkModule? _death_link; + + public ArchipelagoClientModule() { + _ffx_interop_handle = new(this); + _gui_handle = new(this); + _recent_items_handle = new(this); + _death_link_handle = new(this); + } + + public override bool init(FhModContext mod_context, FileStream global_state_file) { + return _ffx_interop_handle.try_get_module(out _ffx_interop) + && _gui_handle.try_get_module(out _gui) + && _recent_items_handle.try_get_module(out _recent_items) + && _death_link_handle.try_get_module(out _death_link); + } + + public async Task Connect(string server, string user, string password) { + _logger.Debug("Connect"); LoginResult? login_result = new LoginFailure(""); ArchipelagoSession? session = null; DeathLinkService? death_link = null; @@ -62,7 +93,7 @@ public static async Task Connect(string server, string user, string password) { errorMessage += $"\n {error}"; } current_session = null; - ArchipelagoFFXModule.logger.Error(errorMessage); + _logger.Error(errorMessage); return; // Did not connect, show the user the contents of `errorMessage` } var loginSuccess = (LoginSuccessful)login_result; @@ -70,39 +101,41 @@ public static async Task Connect(string server, string user, string password) { if (ArchipelagoFFXModule.seed.Options.SeedId is not null) { if (ArchipelagoFFXModule.seed.Options.SeedId != (string)loginSuccess.SlotData["SeedId"]) { string message = "Loaded seed doesn't match connected slot"; - ArchipelagoGUI.add_log_message([(message, Color.Red)]); - ArchipelagoFFXModule.logger.Error(message); + _gui!.add_log_message([(message, Color.Red)]); + _logger.Error(message); disconnect(session); return; } ArchipelagoFFXModule.SeedToServer[ArchipelagoFFXModule.seed.Options.SeedId] = server; - ArchipelagoFFXModule.save_global_state(); + _ffx_interop!.save_global_state(); } else { SeedId = (string)loginSuccess.SlotData["SeedId"]; int selected_seed = ArchipelagoFFXModule.loaded_seeds.FindIndex(x => x.Options.SeedId == SeedId); if (selected_seed != -1) { - ArchipelagoGUI.selected_seed = selected_seed; + _gui!.selected_seed = selected_seed; ArchipelagoFFXModule.SeedToServer[SeedId] = server; - ArchipelagoFFXModule.save_global_state(); + _ffx_interop!.save_global_state(); } } current_server = server; current_session = session; - current_death_link = death_link; + current_death_link_service = death_link; } - public static void disconnect(ArchipelagoSession? session = null) { - ArchipelagoFFXModule.logger.Debug("disconnect"); + public void disconnect(ArchipelagoSession? session = null) { + _logger.Debug("disconnect"); lock (client_lock) { session ??= current_session; if (session is null || is_disconnecting) return; is_disconnecting = true; + disconnectHandlers(session, current_death_link_service); session.Socket.DisconnectAsync(); } } - private static void connectHandlers(ArchipelagoSession session, DeathLinkService death_link) { - ArchipelagoFFXModule.logger.Debug("connectHandlers"); + private void connectHandlers(ArchipelagoSession session, DeathLinkService death_link) { + _logger.Debug("connectHandlers"); + session.MessageLog.OnMessageReceived += MessageLog_OnMessageReceived; session.Socket.ErrorReceived += Socket_ErrorReceived; session.Socket.SocketOpened += Socket_SocketOpened; @@ -111,49 +144,57 @@ private static void connectHandlers(ArchipelagoSession session, DeathLinkService session.MessageLog.OnMessageReceived += RecentItemsModule.post_item_message; - death_link.OnDeathLinkReceived += DeathLinkModule.post_deathlink; + death_link.OnDeathLinkReceived += _death_link!.post_deathlink; } - private static void Locations_CheckedLocationsUpdated(System.Collections.ObjectModel.ReadOnlyCollection newCheckedLocations) { + private void disconnectHandlers(ArchipelagoSession? session, DeathLinkService? death_link) { + _logger.Debug("disconnectHandlers"); + + session?.MessageLog.OnMessageReceived -= MessageLog_OnMessageReceived; + session?.Socket.ErrorReceived -= Socket_ErrorReceived; + session?.Socket.SocketOpened -= Socket_SocketOpened; + session?.Socket.SocketClosed -= Socket_SocketClosed; + session?.Locations.CheckedLocationsUpdated -= Locations_CheckedLocationsUpdated; + + session?.MessageLog.OnMessageReceived -= RecentItemsModule.post_item_message; + + death_link?.OnDeathLinkReceived -= _death_link!.post_deathlink; + } + + private void Locations_CheckedLocationsUpdated(System.Collections.ObjectModel.ReadOnlyCollection newCheckedLocations) { lock (client_lock) { remote_locations_updated = true; } } - private static void Socket_ErrorReceived(Exception e, string message) { - ArchipelagoFFXModule.logger.Debug($"Socket Error: {message}"); - ArchipelagoFFXModule.logger.Debug($"Socket Exception: {e.Message}"); + private void Socket_ErrorReceived(Exception e, string message) { + _logger.Debug($"Socket Error: {message}"); + _logger.Debug($"Socket Exception: {e.Message}"); if (e.StackTrace != null) foreach (var line in e.StackTrace.Split('\n')) - ArchipelagoFFXModule.logger.Debug($" {line}"); + _logger.Debug($" {line}"); else - ArchipelagoFFXModule.logger.Debug($" No stacktrace provided"); + _logger.Debug(" No stacktrace provided"); } - private static void Socket_SocketOpened() { - ArchipelagoFFXModule.logger.Debug($"Socket Opened: \"{current_session?.Socket.Uri}\""); + private void Socket_SocketOpened() { + _logger.Debug($"Socket Opened: \"{current_session?.Socket.Uri}\""); } - private static void Socket_SocketClosed(string reason) { - ArchipelagoFFXModule.logger.Debug($"Socket Closed: \"{reason}\""); - ArchipelagoGUI.add_log_message([($"Disconnected from server ({reason})", Color.Red)]); + private void Socket_SocketClosed(string reason) { + _logger.Debug($"Socket Closed: \"{reason}\""); + _gui!.add_log_message([($"Disconnected from server ({reason})", Color.Red)]); lock (client_lock) { current_session = null; - current_death_link = null; + current_death_link_service = null; SeedId = null; current_server = null; is_disconnecting = false; } } - public unsafe static void update() { - /* - foreach (ItemInfo item in session.Items.AllItemsReceived) { - ArchipelagoFFXModule.logger.Debug($"received_item: {item.ItemName}"); - } - */ - + public unsafe void update() { lock (client_lock) { // TODO: Check for post-battle/other menu? if ( !is_connected @@ -166,10 +207,10 @@ public unsafe static void update() { } if (current_session!.Items.AllItemsReceived.Count > received_items) { - ArchipelagoFFXModule.logger.Debug("New items received"); + _logger.Debug("New items received"); foreach (ItemInfo item in current_session.Items.AllItemsReceived.Skip(received_items)) { - ArchipelagoFFXModule.logger.Debug($"received_item: {item.ItemName}"); - ArchipelagoFFXModule.obtain_item((uint)item.ItemId); + _logger.Debug($"received_item: {item.ItemName}"); + _ffx_interop!.obtain_item((uint)item.ItemId); received_items++; } } @@ -178,7 +219,7 @@ public unsafe static void update() { var local_only = local_checked_locations.Except(current_session.Locations.AllLocationsChecked); if (local_only.Any()) { current_session.Locations.CompleteLocationChecksAsync(local_only.ToArray()); - ArchipelagoFFXModule.logger.Debug($"Sent: {string.Join(",", local_only)}"); + _logger.Debug($"Sent: {string.Join(",", local_only)}"); } local_locations_updated = false; @@ -202,35 +243,19 @@ public unsafe static void update() { var remote_only = current_session.Locations.AllLocationsChecked.Except(local_checked_locations); foreach (long location in remote_only) { if (ArchipelagoFFXModule.item_locations.location_to_item((int)location, out var item)) { - ArchipelagoFFXModule.logger.Debug($"Synced remote location: location:{location}, item:{item.name}, player:{item.player}"); - ArchipelagoFFXModule.obtain_item(item.id); + _logger.Debug($"Synced remote location: location:{location}, item:{item.name}, player:{item.player}"); + _ffx_interop!.obtain_item(item.id); } } local_checked_locations.UnionWith(remote_only); remote_locations_updated = false; } } - - /* - var remote_only = session.Locations.AllLocationsChecked.Except(local_checked_locations); - if (remote_only.Any()) { - ArchipelagoFFXModule.logger.Debug($"Received Remote Locations: {string.Join(",", remote_only)}"); - foreach (var location in remote_only) { - // TODO: Distinguish between location types - var treasure_id = (location - 0x14)/4; - ArchipelagoFFXModule.logger.Debug($"Location id: {Convert.ToInt32(treasure_id)}"); - ArchipelagoModule.receive_treasure(Convert.ToInt32(treasure_id)); - local_checked_locations.Add(location); - } - } - */ - - } - private static void MessageLog_OnMessageReceived(LogMessage message) { + private void MessageLog_OnMessageReceived(LogMessage message) { var parts = message.Parts; - List<(string, Color)> messageParts = parts.Select((part) => { + List<(string, Color)> messageParts = parts.Select(part => { Color color = part.Color; if (part.IsBackgroundColor) { color = Color.White; @@ -240,38 +265,19 @@ private static void MessageLog_OnMessageReceived(LogMessage message) { } return (part.Text, color); }).ToList(); - ArchipelagoGUI.add_log_message(messageParts); + _gui!.add_log_message(messageParts); } - /* -public unsafe static void connectHandlers() { - session.Locations.CheckedLocationsUpdated += (newCheckedLocations) => { - if (Globals.save_data->current_room_id == 23) return; - - var remote_only = newCheckedLocations.Except(local_checked_locations); - if (remote_only.Any()) { - ArchipelagoFFXModule.logger.Debug($"Received Remote Locations: {string.Join(",", remote_only)}"); - foreach (var location in remote_only) { - ArchipelagoFFXModule.logger.Debug($"Location id: {Convert.ToInt32(location)}"); - ArchipelagoModule.receive_treasure(Convert.ToInt32(location)); - local_checked_locations.Add(location); - } - } - }; -} -*/ - - public static void SayAsync(string message) + public void SayAsync(string message) { lock (client_lock) { - if (is_connected) - { + if (is_connected) { current_session!.Socket.SendPacketAsync(new SayPacket { Text = message }); } } } - public enum ArchipelagoLocationType: int { + public enum ArchipelagoLocationType { Treasure = 0x1000, Boss = 0x2000, Overdrive = 0x3000, @@ -283,19 +289,19 @@ public enum ArchipelagoLocationType: int { PartyMember = 0xF000, } - public static bool sendLocation(long locationId, ArchipelagoLocationType locationType) { + public bool sendLocation(long locationId, ArchipelagoLocationType locationType) { var absoluteId = locationId | (long)locationType; return sendLocation(absoluteId); } - private static bool sendLocation(long locationId) { + + private bool sendLocation(long locationId) { if (!local_checked_locations.Add(locationId)) return false; local_locations_updated = true; lock (client_lock) { if (is_connected) { - ArchipelagoFFXModule.logger.Debug(current_session!.Locations.GetLocationNameFromId(locationId) ?? $"Location: {locationId}"); + _logger.Debug(current_session!.Locations.GetLocationNameFromId(locationId) ?? $"Location: {locationId}"); } } return true; } - } diff --git a/src/customization.cs b/src/customization.cs index 6875ee4..c4a2e7b 100644 --- a/src/customization.cs +++ b/src/customization.cs @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT using Fahrenheit.FFX; + using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -12,59 +13,58 @@ namespace ArchipelagoFFX; public unsafe partial class ArchipelagoFFXModule { - // Customization - public static FhMethodHandle _PrepareMenuList; - public static FhMethodHandle _UpdateGearCustomizationMenuState; - public static FhMethodHandle _UpdateAeonCustomizationMenuState; - public static FhMethodHandle _DrawGearCustomizationMenu; - public static FhMethodHandle _DrawAeonCustomizationMenu; - public static delegates.MsGetRomKaizou _MsGetRomKaizou; - public static delegates.MsGetRomAbility _MsGetRomAbility; - public static delegates.MsGetRomSummonGrow _MsGetRomSummonGrow; - public static delegates.TkMn2GetSummonGrowMax _TkMn2GetSummonGrowMax; - public static delegates.TkMenuGetCurrentSummon _TkMenuGetCurrentSummon; - public static delegates.MsGetSaveCommand _MsGetSaveCommand; - - public static delegates.FUN_008c1c70 _FUN_008c1c70; - public static delegates.TODrawMenuPlateXYWHType _TODrawMenuPlateXYWHType; - public static delegates.FUN_008f8bb0 _FUN_008f8bb0; - public static delegates.TODrawScissorXYWH _TODrawScissorXYWH; - public static delegates.FUN_008d5d20 _FUN_008d5d20; - public static delegates.FUN_008c0f40 _FUN_008c0f40; - public static delegates.FUN_008c1350_DrawScissor512x416 _FUN_008c1350_DrawScissor512x416; - public static delegates.FUN_008d5dc0 _FUN_008d5dc0; - public static delegates.DrawCrossMenuScrollParts _DrawCrossMenuScrollParts; - public static delegates.FUN_008d6630 _FUN_008d6630; - - public static delegates.TkVU1SyncPath _TkVU1SyncPath; - public static delegates.FUN_008e71d0 _FUN_008e71d0; - public static delegates.FUN_008ff490 _FUN_008ff490; - public static delegates.FUN_008cd960 _FUN_008cd960; - public static delegates.FUN_008cd9f0 _FUN_008cd9f0; - public static delegates.ToGetCrossExtMesFontWidth _ToGetCrossExtMesFontWidth; - public static delegates.FUN_008bee80 _FUN_008bee80; - - public static delegates.TOMkpShapeXYWHUV _TOMkpShapeXYWHUV; - public static delegates.TOMkpCrossExtMesFontLClut _TOMkpCrossExtMesFontLClut; - public static delegates.FUN_008d48e0 _FUN_008d48e0; - public static delegates.FUN_008d4140 _FUN_008d4140; - public static delegates.TkMn2DrawKickSyncPacket _TkMn2DrawKickSyncPacket; - - - public static delegates.TkMenuMainAllocWindow _TkMenuMainAllocWindow; - public static delegates.TkMenuMainRegistWindow _TkMenuMainRegistWindow; - - - public static delegates.FUN_008e33a0 _FUN_008e33a0; - public static delegates.FUN_008b4460 _FUN_008b4460; - public static delegates.FUN_008e2de0 _FUN_008e2de0; - public static delegates.MsSetSaveParamAll _MsSetSaveParamAll; - public static delegates.MsSetWeaponName _MsSetWeaponName; - public static delegates.FUN_008c2c40 _FUN_008c2c40; - public static delegates.TkMn2DrawCrossCursor _TkMn2DrawCrossCursor; - - public static FhMethodHandle _FUN_008d5720; + public static FhMethodHandle _PrepareMenuList; + public static FhMethodHandle _UpdateGearCustomizationMenuState; + public static FhMethodHandle _UpdateAeonCustomizationMenuState; + public static FhMethodHandle _DrawGearCustomizationMenu; + public static FhMethodHandle _DrawAeonCustomizationMenu; + public static MsGetRomKaizou _MsGetRomKaizou; + public static MsGetRomAbility _MsGetRomAbility; + public static MsGetRomSummonGrow _MsGetRomSummonGrow; + public static TkMn2GetSummonGrowMax _TkMn2GetSummonGrowMax; + public static TkMenuGetCurrentSummon _TkMenuGetCurrentSummon; + public static MsGetSaveCommand _MsGetSaveCommand; + + public static FUN_008c1c70 _FUN_008c1c70; + public static TODrawMenuPlateXYWHType _TODrawMenuPlateXYWHType; + public static FUN_008f8bb0 _FUN_008f8bb0; + public static TODrawScissorXYWH _TODrawScissorXYWH; + public static FUN_008d5d20 _FUN_008d5d20; + public static FUN_008c0f40 _FUN_008c0f40; + public static FUN_008c1350_DrawScissor512x416 _FUN_008c1350_DrawScissor512x416; + public static FUN_008d5dc0 _FUN_008d5dc0; + public static DrawCrossMenuScrollParts _DrawCrossMenuScrollParts; + public static FUN_008d6630 _FUN_008d6630; + + public static TkVU1SyncPath _TkVU1SyncPath; + public static FUN_008e71d0 _FUN_008e71d0; + public static FUN_008ff490 _FUN_008ff490; + public static FUN_008cd960 _FUN_008cd960; + public static FUN_008cd9f0 _FUN_008cd9f0; + public static ToGetCrossExtMesFontWidth _ToGetCrossExtMesFontWidth; + public static FUN_008bee80 _FUN_008bee80; + + public static TOMkpShapeXYWHUV _TOMkpShapeXYWHUV; + public static TOMkpCrossExtMesFontLClut _TOMkpCrossExtMesFontLClut; + public static FUN_008d48e0 _FUN_008d48e0; + public static FUN_008d4140 _FUN_008d4140; + public static TkMn2DrawKickSyncPacket _TkMn2DrawKickSyncPacket; + + + public static TkMenuMainAllocWindow _TkMenuMainAllocWindow; + public static TkMenuMainRegistWindow _TkMenuMainRegistWindow; + + + public static FUN_008e33a0 _FUN_008e33a0; + public static FUN_008b4460 _FUN_008b4460; + public static FUN_008e2de0 _FUN_008e2de0; + public static MsSetSaveParamAll _MsSetSaveParamAll; + public static MsSetWeaponName _MsSetWeaponName; + public static FUN_008c2c40 _FUN_008c2c40; + public static TkMn2DrawCrossCursor _TkMn2DrawCrossCursor; + + public static FhMethodHandle _FUN_008d5720; // Customization-related private static int selected_gear_slot = 0; @@ -74,7 +74,7 @@ public unsafe partial class ArchipelagoFFXModule { public void PrepareMenuList_InitList() { // Init list ushort* _DAT_01597330 = FhUtil.ptr_at(0x1197330); - delegates.CustomizationMenuList* menu_list_iter = FhUtil.ptr_at(0x1197730); + CustomizationMenuList* menu_list_iter = FhUtil.ptr_at(0x1197730); for (int i = 0; i < 0x200; i++) { menu_list_iter[i].a_ability_id = 0; @@ -82,6 +82,7 @@ public void PrepareMenuList_InitList() { menu_list_iter[i].customization_id = 0; _DAT_01597330[i] = 0; } + uint* _DAT_0186a20c = FhUtil.ptr_at(0x146A20C); *_DAT_0186a20c = 0; } @@ -97,15 +98,14 @@ public void PrepareMenuList_SetLength(uint added, uint skipped) { } } - public void h_PrepareMenuList(delegates.MenuListEnum menu_list_id, Equipment* gear) - { - logger.Info($"{menu_list_id}"); + public void h_PrepareMenuList(MenuListEnum menu_list_id, Equipment* gear) { + _logger.Info($"{menu_list_id}"); uint[] ability_international_bonuses = new uint[4]; uint[] ability_group_idxs = new uint[4]; uint[] ability_group_levels = new uint[4]; - if (menu_list_id == delegates.MenuListEnum.GEAR_CUSTOMIZATION) { + if (menu_list_id == MenuListEnum.GEAR_CUSTOMIZATION) { // Modify kaizou.bin int num_customizations; CustomizationRecipe* customizations = _MsGetRomKaizou(&num_customizations); @@ -115,11 +115,12 @@ public void h_PrepareMenuList(delegates.MenuListEnum menu_list_id, Equipment* ge original_kaizou_costs[i] = customizations[i].item_cost; } } + uint item_id = 0xC000; for (int i = 0; i < num_customizations; i++, item_id++) { if (other_inventory.TryGetValue(item_id, out int count)) { if (count > 0) { - logger.Debug($"Free customization: {get_other_item_name(item_id)}"); + _logger.Debug($"Free customization: {get_other_item_name(item_id)}"); customizations[i].item_cost = 0; } } @@ -127,7 +128,7 @@ public void h_PrepareMenuList(delegates.MenuListEnum menu_list_id, Equipment* ge // Init list PrepareMenuList_InitList(); - delegates.CustomizationMenuList* menu_list_iter = FhUtil.ptr_at(0x1197730); + CustomizationMenuList* menu_list_iter = FhUtil.ptr_at(0x1197730); uint* _DAT_0186a20c = FhUtil.ptr_at(0x146A20C); @@ -158,6 +159,7 @@ public void h_PrepareMenuList(delegates.MenuListEnum menu_list_id, Equipment* ge if (a_ability->international_bonus_idx == 0xff) { has_ribbon = true; } + num_abilities++; } } @@ -177,43 +179,42 @@ public void h_PrepareMenuList(delegates.MenuListEnum menu_list_id, Equipment* ge if (item_count == 0 && customization.item_cost != 0) { skipped++; continue; - } - else { - delegates.CustomizationStatusEnum status = delegates.CustomizationStatusEnum.GEAR_AVAILABLE; + } else { + CustomizationStatusEnum status = CustomizationStatusEnum.GEAR_AVAILABLE; if (num_abilities == 0) { if (item_count < customization.item_cost) { - status = delegates.CustomizationStatusEnum.GEAR_NOT_ENOUGH_ITEMS; + status = CustomizationStatusEnum.GEAR_NOT_ENOUGH_ITEMS; } - } - else { + } else { for (int i = 0; i < num_abilities; i++) { if (ability_group_idxs[i] == a_ability->group_idx) { if (a_ability->group_level < ability_group_levels[i]) { // Same group, lower level - status = delegates.CustomizationStatusEnum.GEAR_CONFLICTING; + status = CustomizationStatusEnum.GEAR_CONFLICTING; } + //if (a_ability->group_level == ability_group_levels[i]) { // status = a_ability->international_bonus_idx != ability_international_bonuses[i] ? CustomizationStatusEnum.GEAR_CONFLICTING : CustomizationStatusEnum.GEAR_ALREADY_APPLIED; //} - if (a_ability->group_level == ability_group_levels[i]) - { - if (a_ability->international_bonus_idx == ability_international_bonuses[i]) - { - status = delegates.CustomizationStatusEnum.GEAR_ALREADY_APPLIED; - } else if (selected_gear_slot != i) - { - status = delegates.CustomizationStatusEnum.GEAR_CONFLICTING; + if (a_ability->group_level == ability_group_levels[i]) { + if (a_ability->international_bonus_idx == ability_international_bonuses[i]) { + status = CustomizationStatusEnum.GEAR_ALREADY_APPLIED; + } else if (selected_gear_slot != i) { + status = CustomizationStatusEnum.GEAR_CONFLICTING; } } } + if (has_ribbon && a_ability->international_bonus_idx == 0xFE) { - status = delegates.CustomizationStatusEnum.GEAR_CONFLICTING; + status = CustomizationStatusEnum.GEAR_CONFLICTING; } } - if (status == delegates.CustomizationStatusEnum.GEAR_AVAILABLE && item_count < customization.item_cost) { - status = delegates.CustomizationStatusEnum.GEAR_NOT_ENOUGH_ITEMS; + + if (status == CustomizationStatusEnum.GEAR_AVAILABLE && item_count < customization.item_cost) { + status = CustomizationStatusEnum.GEAR_NOT_ENOUGH_ITEMS; } } + //if (gear->abilities[gear->slot_count - 1] != 0xff && gear->abilities[gear->slot_count - 1] != 0) { // status = CustomizationStatusEnum.GEAR_NO_SLOTS; //} @@ -225,9 +226,10 @@ public void h_PrepareMenuList(delegates.MenuListEnum menu_list_id, Equipment* ge } } } + for (int i = 0; i < skipped; i++) { // ???? - menu_list_iter->status = (delegates.CustomizationStatusEnum)0x11; + menu_list_iter->status = (CustomizationStatusEnum)0x11; menu_list_iter->a_ability_id = 0; menu_list_iter->customization_id = 0xFF; menu_list_iter++; @@ -237,8 +239,7 @@ public void h_PrepareMenuList(delegates.MenuListEnum menu_list_id, Equipment* ge // Set length PrepareMenuList_SetLength(added, skipped); - } - else if (menu_list_id == delegates.MenuListEnum.AEON_ABILITIES) { + } else if (menu_list_id == MenuListEnum.AEON_ABILITIES) { // TODO: Modify sum_grow.bin int num_customizations; CustomizationRecipe* customizations = _MsGetRomSummonGrow(&num_customizations); @@ -249,11 +250,12 @@ public void h_PrepareMenuList(delegates.MenuListEnum menu_list_id, Equipment* ge original_sum_grow_costs[i] = customizations[i].item_cost; } } + uint item_id = 0xC07D; for (int i = 0; i < num_customizations; i++, item_id++) { if (other_inventory.TryGetValue(item_id, out int count)) { if (count > 0) { - logger.Debug($"Free customization: {get_other_item_name(item_id)}"); + _logger.Debug($"Free customization: {get_other_item_name(item_id)}"); customizations[i].item_cost = 0; } } @@ -261,7 +263,7 @@ public void h_PrepareMenuList(delegates.MenuListEnum menu_list_id, Equipment* ge // Init list PrepareMenuList_InitList(); - delegates.CustomizationMenuList* menu_list_iter = FhUtil.ptr_at(0x1197730); + CustomizationMenuList* menu_list_iter = FhUtil.ptr_at(0x1197730); uint* _DAT_0186a20c = FhUtil.ptr_at(0x146A20C); byte current_summon = _TkMenuGetCurrentSummon(); @@ -283,19 +285,20 @@ public void h_PrepareMenuList(delegates.MenuListEnum menu_list_id, Equipment* ge menu_list_iter->a_ability_id = auto_ability_id; menu_list_iter->customization_id = customization_id; if (item_count < customization.item_cost) { - menu_list_iter->status = delegates.CustomizationStatusEnum.AEON_NOT_ENOUGH_ITEMS; + menu_list_iter->status = CustomizationStatusEnum.AEON_NOT_ENOUGH_ITEMS; } else if (((int)customization.target_gear_type & (1 << (current_summon - 8))) == 0 && !has_key_item) { // Never reached because both conditions are always false: Bit is set for all Aeons (always 0x7F) and key item is unused. - menu_list_iter->status = delegates.CustomizationStatusEnum.AEON_CANNOT_LEARN_WITHOUT_KEY; + menu_list_iter->status = CustomizationStatusEnum.AEON_CANNOT_LEARN_WITHOUT_KEY; } else { - menu_list_iter->status = delegates.CustomizationStatusEnum.AEON_AVAILABLE; + menu_list_iter->status = CustomizationStatusEnum.AEON_AVAILABLE; } } } else { menu_list_iter->a_ability_id = auto_ability_id; menu_list_iter->customization_id = customization_id; - menu_list_iter->status = delegates.CustomizationStatusEnum.AEON_ALREADY_LEARNED; + menu_list_iter->status = CustomizationStatusEnum.AEON_ALREADY_LEARNED; } + menu_list_iter++; added++; } @@ -303,7 +306,6 @@ public void h_PrepareMenuList(delegates.MenuListEnum menu_list_id, Equipment* ge // Set length PrepareMenuList_SetLength(added, 0); - } else { _PrepareMenuList.orig_fptr(menu_list_id, gear); } @@ -337,136 +339,130 @@ public void h_UpdateGearCustomizationMenuState(TkWindow* window) { byte* p_DAT_0186a9f8 = (byte*)FhUtil.get_at(0x146A9F8); bool break_loop = false; - while (!break_loop) - { + while (!break_loop) { switch (*state) { case 2: _FUN_008b4460(window); - if (window->exit_value < 1) - { + if (window->exit_value < 1) { return; } + ushort weapon_index = *(ushort*)(p_DAT_0186a9f8 + window->selected_index * 2); gear = _MsGetSaveWeapon(weapon_index, 0); bool can_customize = false; - if (gear->exists && !gear->is_hidden && gear->slot_count > 0) - { - if (!gear->is_celestial && !gear->is_brotherhood) - { + if (gear->exists && !gear->is_hidden && gear->slot_count > 0) { + if (!gear->is_celestial && !gear->is_brotherhood) { //if (gear->abilities[gear->slot_count-1] == 0xff || gear->abilities[gear->slot_count - 1] == 0) can_customize = true; } } - if (!can_customize) - { + + if (!can_customize) { goto default; - } - else - { + } else { _SndSepPlaySimple(0x80000001); { int slot = 0; - for (; slot < gear->slot_count; slot++) - { - if (gear->abilities[slot] is 0 or 0xff) - { + for (; slot < gear->slot_count; slot++) { + if (gear->abilities[slot] is 0 or 0xff) { break; } } - if (slot < 4 && slot < gear->slot_count) - { + + if (slot < 4 && slot < gear->slot_count) { selected_gear_slot = slot; *state = 0x5; - } else - { + } else { CreateMyWindow(gear); *state = 0xe; } } } + break; - case 6: - { - TkWindow* _GearSelectionWindow = (TkWindow*)FhUtil.get_at(0x146A9F0); // DAT_0186a9f0 - gear = _MsGetSaveWeapon(*(ushort*)(p_DAT_0186a9f8 + _GearSelectionWindow->selected_index * 2), - (nint)(&gear_name)); - int slot = 0; - for (; slot < gear->slot_count; slot++) - { - if (gear->abilities[slot] is 0 or 0xff) - { - break; - } - } - if (slot < 4 && slot < gear->slot_count) - { - selected_gear_slot = slot; - goto default; - } - else - { - *state = 8; + + case 6: { + TkWindow* _GearSelectionWindow = (TkWindow*)FhUtil.get_at(0x146A9F0); // DAT_0186a9f0 + gear = _MsGetSaveWeapon( + *(ushort*)(p_DAT_0186a9f8 + _GearSelectionWindow->selected_index * 2), + (nint)(&gear_name) + ); + int slot = 0; + for (; slot < gear->slot_count; slot++) { + if (gear->abilities[slot] is 0 or 0xff) { + break; } } + + if (slot < 4 && slot < gear->slot_count) { + selected_gear_slot = slot; + goto default; + } else { + *state = 8; + } + } break; + case 8: - if (MyWindow != null) - { + if (MyWindow != null) { MyWindow->should_destroy = true; MyWindow = null; } + goto default; - case 0xc: - { - TkWindow* DAT_023cc120 = (TkWindow*)FhUtil.get_at(0x1FCC120); - if (DAT_023cc120->exit_value < 0) - { - _FUN_008e2de0(); - *state = 6; - break_loop = true; - break; - } - if (DAT_023cc120->exit_value == 0) - { - break_loop = true; - break; - } + + case 0xc: { + TkWindow* DAT_023cc120 = (TkWindow*)FhUtil.get_at(0x1FCC120); + if (DAT_023cc120->exit_value < 0) { _FUN_008e2de0(); - if (DAT_023cc120->selected_index != 0) - { - _SndSepPlaySimple(0x80000001); - *state = 6; - break_loop = true; - break; - } + *state = 6; + break_loop = true; + break; + } + + if (DAT_023cc120->exit_value == 0) { + break_loop = true; + break; } + + _FUN_008e2de0(); + if (DAT_023cc120->selected_index != 0) { + _SndSepPlaySimple(0x80000001); + *state = 6; + break_loop = true; + break; + } + } *state = 0xd; break; + case 0xd: TkWindow* AbilitySelectionWindow = (TkWindow*)FhUtil.get_at(0x146A9F4); // PTR_0186a9f4 TkWindow* GearSelectionWindow = (TkWindow*)FhUtil.get_at(0x146A9F0); // DAT_0186a9f0 - delegates.CustomizationMenuList* menu_list = FhUtil.ptr_at(0x1197730); + CustomizationMenuList* menu_list = FhUtil.ptr_at(0x1197730); short selected_ability = AbilitySelectionWindow->selected_index; int num_customizations; CustomizationRecipe* customizations = _MsGetRomKaizou(&num_customizations); byte customization_id = menu_list[selected_ability].customization_id; - gear = _MsGetSaveWeapon(*(ushort*)(p_DAT_0186a9f8 + GearSelectionWindow->selected_index * 2), - (nint)(&gear_name)); + gear = _MsGetSaveWeapon( + *(ushort*)(p_DAT_0186a9f8 + GearSelectionWindow->selected_index * 2), + (nint)(&gear_name) + ); byte* p_DAT_0186aa30 = FhUtil.ptr_at(0x146AA30); int i = -1; - do - { + do { i++; p_DAT_0186aa30[i] = gear_name[i]; } while (gear_name[i] != 0); + //_FUN_008d5650((int)gear, menu_list[selected_ability].a_ability_id); - if (gear->slot_count != 0) - { + if (gear->slot_count != 0) { gear->abilities[selected_gear_slot] = menu_list[selected_ability].a_ability_id; } + _MsSetSaveParamAll(); _MsSetWeaponName(gear); @@ -476,8 +472,7 @@ public void h_UpdateGearCustomizationMenuState(TkWindow* window) { byte* p_DAT_0186aa70 = FhUtil.ptr_at(0x146AA70); i = -1; - do - { + do { i++; p_DAT_0186aa70[i] = gear_name[i]; } while (gear_name[i] != 0); @@ -486,58 +481,56 @@ public void h_UpdateGearCustomizationMenuState(TkWindow* window) { byte prev; byte curr; i = -1; - do - { + do { i++; prev = p_DAT_0186aa30[i]; curr = p_DAT_0186aa70[i]; int is_lower = curr < prev ? 1 : 0; - if (curr != prev) - { + if (curr != prev) { uVar9 = (byte)(-is_lower | 1); break; } } while (curr != 0); - if (uVar9 == 0) - { + + if (uVar9 == 0) { uVar9 = 0x1e; - } - else - { + } else { uVar9 = 0x1f; } + byte* pbVar8 = _FUN_008bee80(uVar9); _FUN_008c2c40(0, 0, p_DAT_0186aa30); _FUN_008c2c40(2, 0, p_DAT_0186aa70); _FUN_008e33a0(pbVar8, (byte*)0, (byte*)0); - { - TkWindow* DAT_023cc120 = (TkWindow*)FhUtil.get_at(0x1FCC120); ; - DAT_023cc120->render_priority = 4; - } + { + TkWindow* DAT_023cc120 = (TkWindow*)FhUtil.get_at(0x1FCC120); + ; + DAT_023cc120->render_priority = 4; + } *state = 10; break_loop = true; break; + case 0xe: // Custom state for selecting slot to overwrite - if (MyWindow->exit_value == 0) - { + if (MyWindow->exit_value == 0) { break_loop = true; - } else - { - logger.Info($"exit_value={MyWindow->exit_value}"); - if (MyWindow->exit_value > 0) - { + } else { + _logger.Info($"exit_value={MyWindow->exit_value}"); + if (MyWindow->exit_value > 0) { selected_gear_slot = MyWindow->selected_index; - logger.Info($"selected_gear_slot={selected_gear_slot}"); + _logger.Info($"selected_gear_slot={selected_gear_slot}"); *state = 5; - } else - { + } else { *state = 8; } + break_loop = true; } + break; + default: _UpdateGearCustomizationMenuState.orig_fptr(window); break_loop = true; @@ -546,16 +539,15 @@ public void h_UpdateGearCustomizationMenuState(TkWindow* window) { } - if (*state != pre_state) { - logger.Info($"{pre_state} -> {*state}"); + _logger.Info($"{pre_state} -> {*state}"); if (pre_state == 0xc && *state == 0xa) { // Applied customization TkWindow* DAT_0186a9f4 = (TkWindow*)FhUtil.get_at(0x0146A9F4); short selected_idx = DAT_0186a9f4->selected_index; - delegates.CustomizationMenuList* menu_list = FhUtil.ptr_at(0x1197730); + CustomizationMenuList* menu_list = FhUtil.ptr_at(0x1197730); int num_customizations; CustomizationRecipe* customizations = _MsGetRomKaizou(&num_customizations); byte customization_id = menu_list[selected_idx].customization_id; @@ -565,8 +557,7 @@ public void h_UpdateGearCustomizationMenuState(TkWindow* window) { if (--count <= 0) { other_inventory.Remove(item_id); customizations[customization_id].item_cost = original_kaizou_costs[customization_id]; - } - else other_inventory[item_id] = count; + } else other_inventory[item_id] = count; } } } @@ -585,32 +576,30 @@ public void h_UpdateGearCustomizationMenuState(TkWindow* window) { // param_1 is TkMenu* public void h_UpdateAeonCustomizationMenuState(uint param_1, uint param_2) { - uint* state = (uint *)(param_1 + 0x1c); + uint* state = (uint*)(param_1 + 0x1c); uint pre_state = *state; _UpdateAeonCustomizationMenuState.orig_fptr(param_1, param_2); if (*state != pre_state) { - logger.Debug($"{pre_state} -> {*state}"); + _logger.Debug($"{pre_state} -> {*state}"); if (pre_state == 0x15) { TkWindow* DAT_0186a568 = (TkWindow*)FhUtil.get_at(0x0146a568); short selected_idx = DAT_0186a568->selected_index; - delegates.CustomizationMenuList* menu_list = FhUtil.ptr_at(0x1197730); + CustomizationMenuList* menu_list = FhUtil.ptr_at(0x1197730); byte customization_id = menu_list[selected_idx].customization_id; int num_customizations; CustomizationRecipe* customizations = _MsGetRomSummonGrow(&num_customizations); - logger.Debug($"Applied customization {get_other_item_name((uint)(0xC07D + customization_id))}"); + _logger.Debug($"Applied customization {get_other_item_name((uint)(0xC07D + customization_id))}"); if (customizations[customization_id].item_cost != original_sum_grow_costs[customization_id]) { uint item_id = (uint)(0xC07D + customization_id); other_inventory.TryGetValue(item_id, out int count); if (--count <= 0) { other_inventory.Remove(item_id); customizations[customization_id].item_cost = original_sum_grow_costs[customization_id]; - } - else other_inventory[item_id] = count; - + } else other_inventory[item_id] = count; } } @@ -618,7 +607,8 @@ public void h_UpdateAeonCustomizationMenuState(uint param_1, uint param_2) { } } - public static ManagedCustomString customization_string = new ManagedCustomString($"Free!"); + public static ManagedCustomString customization_string = new("Free!"); + public void h_DrawGearCustomizationMenu(TkWindow* window) { //_DrawGearCustomizationMenu.orig_fptr(param_1); DrawGearCustomizationMenu_reimplement(window); @@ -636,7 +626,7 @@ public void DrawAeonCustomizationMenu_reimplement(TkWindow* window) { uint current_summon = _TkMenuGetCurrentSummon(); - delegates.CustomizationMenuList* menu_list = FhUtil.ptr_at(0x1197730); + CustomizationMenuList* menu_list = FhUtil.ptr_at(0x1197730); short selected_idx = window->selected_index; Vector2 pos_1; Vector2 pos_2; @@ -658,12 +648,10 @@ public void DrawAeonCustomizationMenu_reimplement(TkWindow* window) { Vector2 pos = new Vector2(1260f, 381f).game_remap_1080p(); _ToMakeBtlEasyFont(text, pos.X, pos.Y, 0, 2f); } - } - else { + } else { pos_1 = new Vector2(970f, 380f).game_remap_1080p(); _FUN_008c1c70((int)pos_1.X, (int)pos_1.Y, item_id, item_cost); } - } pos_1 = new Vector2(210f, 226f).game_remap_1080p(); @@ -685,31 +673,51 @@ public void DrawAeonCustomizationMenu_reimplement(TkWindow* window) { // Header text ("Item cost")? pos_1 = new Vector2(1125f, 318f).game_remap_1080p(); - pos_2 = new Vector2( 430f, 36f).game_remap_1080p(); + pos_2 = new Vector2(430f, 36f).game_remap_1080p(); _FUN_008f8bb0(0x10, pos_1.X, pos_1.Y, pos_2.X, pos_2.Y); } - int iVar2 = (int)new Vector2(0, 365f).game_remap_1080p().Y; + int iVar2 = (int)new Vector2(0, 365f).game_remap_1080p() + .Y; int iVar6, sVar1; float fVar10; if (window->visible_item_offset == window->scroll_offset) { // Draw ability list - _FUN_008c0f40(iVar2, (int)(new Vector2(0, 70f).game_remap_1080p().Y * 9.0), 0, window->scroll_delta); + _FUN_008c0f40( + iVar2, + (int)(new Vector2(0, 70f).game_remap_1080p() + .Y * 9.0), + 0, + window->scroll_delta + ); sVar1 = window->visible_item_offset; fVar10 = 0.0f; iVar6 = 0; - } - else { + } else { // Draw ability list when quick scrolling (L2/R2) - _FUN_008c0f40(iVar2, (int)(new Vector2(0, 70f).game_remap_1080p().Y * 9.0), 1, window->scroll_delta); + _FUN_008c0f40( + iVar2, + (int)(new Vector2(0, 70f).game_remap_1080p() + .Y * 9.0), + 1, + window->scroll_delta + ); FUN_008cd960_Extra(window, 1, window->visible_item_offset, 0.0f, 0.0f); - _FUN_008c0f40(iVar2, (int)(new Vector2(0, 70f).game_remap_1080p().Y * 9.0), 2, window->scroll_delta); + _FUN_008c0f40( + iVar2, + (int)(new Vector2(0, 70f).game_remap_1080p() + .Y * 9.0), + 2, + window->scroll_delta + ); - fVar10 = (int)(new Vector2(0, 70f).game_remap_1080p().Y * 9.0 * window->scroll_delta * -0.00024414063); + fVar10 = (int)(new Vector2(0, 70f).game_remap_1080p() + .Y * 9.0 * window->scroll_delta * -0.00024414063); sVar1 = window->scroll_offset; iVar6 = 2; } + FUN_008cd960_Extra(window, iVar6, sVar1, 0.0f, fVar10); _FUN_008c1350_DrawScissor512x416(); @@ -720,34 +728,45 @@ public void DrawAeonCustomizationMenu_reimplement(TkWindow* window) { float local_8; _ToGetCrossExtMesFontWidth(0, _FUN_008bee80(5), &local_8, 0.78f, 1.0f); - fVar10 = (float)(double)(new Vector2(80f, 0).game_remap_1080p().X + local_8); + fVar10 = (float)(double)(new Vector2(80f, 0).game_remap_1080p() + .X + local_8); local_8 = fVar10; - - float fVar11 = new Vector2(660f, 0).game_remap_1080p().X; + float fVar11 = new Vector2(660f, 0).game_remap_1080p() + .X; if (fVar11 < (float)fVar10 == (float.IsNaN(fVar11) || float.IsNaN(fVar10))) { - fVar10 = new Vector2(740f, 0).game_remap_1080p().X; - } - else { - fVar10 = (float)(new Vector2(80f, 0).game_remap_1080p().X + local_8); + fVar10 = new Vector2(740f, 0).game_remap_1080p() + .X; + } else { + fVar10 = (float)(new Vector2(80f, 0).game_remap_1080p() + .X + local_8); } // graphicUiRemapX2(1806.0); - fVar11 = new Vector2(1806f, 0).game_remap_1080p().X - fVar10; + fVar11 = new Vector2(1806f, 0).game_remap_1080p() + .X - fVar10; float fVar12 = (float)((fVar10 - local_8) * 0.5 + fVar11); pos_1 = new Vector2(955f, 370f).game_remap_1080p(); pos_2 = new Vector2( 8f, 630f).game_remap_1080p(); _DrawCrossMenuScrollParts(pos_1.X, pos_1.Y, pos_2.X, pos_2.Y, window->visible_item_offset, window->max_visible_items, window->num_items); - _TODrawMenuPlateXYWHType(fVar11, new Vector2(0, 925f).game_remap_1080p().Y, fVar10, new Vector2(0, 48f).game_remap_1080p().Y, 2); + _TODrawMenuPlateXYWHType( + fVar11, + new Vector2(0, 925f).game_remap_1080p() + .Y, + fVar10, + new Vector2(0, 48f).game_remap_1080p() + .Y, + 2 + ); float uv_y2 = 0.3017578f; float uv_x2 = 0.99902344f; float uv_y1 = 0.22851563f; float uv_x1 = 0.9267578f; - pos_1 = new Vector2( 0f, 920f).game_remap_1080p(); + pos_1 = new Vector2(0f, 920f).game_remap_1080p(); pos_2 = new Vector2(64f, 64f).game_remap_1080p(); _TOMkpShapeXYWHUV(0xf3, fVar12, pos_1.Y, pos_2.X, pos_2.Y, uv_x1, uv_y1, uv_x2, uv_y2); @@ -766,10 +785,11 @@ private void FUN_008cd960_Extra(TkWindow* window, int param_2, int menu_offset, pos += new Vector2(209f + 50f, 306f).game_remap_1080p(); if (param_2 == 0) { - pos.Y -= (float)(new Vector2(0, 70f).game_remap_1080p().Y * window->scroll_delta * 0.00024414063); // Scroll offset + pos.Y -= (float)(new Vector2(0, 70f).game_remap_1080p() + .Y * window->scroll_delta * 0.00024414063); // Scroll offset } - delegates.CustomizationMenuList* menu_list = FhUtil.ptr_at(0x1197730); + CustomizationMenuList* menu_list = FhUtil.ptr_at(0x1197730); short menu_length = window->num_items; for (int i = -1; i < 10; i++) { int curr_index = menu_offset + i; @@ -787,12 +807,13 @@ private void FUN_008cd960_Extra(TkWindow* window, int param_2, int menu_offset, } } } + pos += new Vector2(0, 70f).game_remap_1080p(); } } public void DrawGearCustomizationMenu_reimplement(TkWindow* window) { - delegates.CustomizationMenuList* menu_list = FhUtil.ptr_at(0x1197730); + CustomizationMenuList* menu_list = FhUtil.ptr_at(0x1197730); short selected_idx = window->selected_index; Vector2 pos_1; Vector2 pos_2; @@ -837,23 +858,44 @@ public void DrawGearCustomizationMenu_reimplement(TkWindow* window) { _FUN_008f8bb0(7, pos_1.X, pos_1.Y, pos_2.X, pos_2.Y); if (window->visible_item_offset == window->scroll_offset) { - // Draw ability list - _TODrawScissorXYWH(0, (int)(new Vector2(0, 315f).game_remap_1080p().Y), 0x200, (int)(new Vector2(0, 680f).game_remap_1080p().Y)); + _TODrawScissorXYWH( + 0, + (int)(new Vector2(0, 315f).game_remap_1080p() + .Y), + 0x200, + (int)(new Vector2(0, 680f).game_remap_1080p() + .Y) + ); FUN_008d5d20_Extra(window, 0, window->visible_item_offset, 0, 0); - } else { // Draw ability list when quick scrolling (L2/R2) short uVar5 = window->scroll_delta; // Scroll offset - _FUN_008c0f40((int)(new Vector2(0, 315f).game_remap_1080p().Y), (int)(new Vector2(0, 680f).game_remap_1080p().Y), 1, uVar5); + _FUN_008c0f40( + (int)(new Vector2(0, 315f).game_remap_1080p() + .Y), + (int)(new Vector2(0, 680f).game_remap_1080p() + .Y), + 1, + uVar5 + ); FUN_008d5d20_Extra(window, 1, window->visible_item_offset, 0, 0); - _FUN_008c0f40((int)(new Vector2(0, 315f).game_remap_1080p().Y), (int)(new Vector2(0, 680f).game_remap_1080p().Y), 2, uVar5); - - int iVar2 = (int)(new Vector2(0, 675f).game_remap_1080p().Y * uVar5 * -0.00024414063); + _FUN_008c0f40( + (int)(new Vector2(0, 315f).game_remap_1080p() + .Y), + (int)(new Vector2(0, 680f).game_remap_1080p() + .Y), + 2, + uVar5 + ); + + int iVar2 = (int)(new Vector2(0, 675f).game_remap_1080p() + .Y * uVar5 * -0.00024414063); FUN_008d5d20_Extra(window, 2, window->scroll_offset, 0, iVar2); } + _FUN_008c1350_DrawScissor512x416(); pos_1 = new Vector2(389f, 325f).game_remap_1080p(); @@ -875,7 +917,6 @@ public void DrawGearCustomizationMenu_reimplement(TkWindow* window) { pos_1 = new Vector2(970f, 659f).game_remap_1080p(); _FUN_008d6630((int)pos_1.X, (int)pos_1.Y, iVar2); } - return; } private void FUN_008d5d20_Extra(TkWindow* window, int param_2, int menu_offset, int x, int y) { @@ -885,10 +926,11 @@ private void FUN_008d5d20_Extra(TkWindow* window, int param_2, int menu_offset, pos += new Vector2(209f + 50f, 255f).game_remap_1080p(); if (param_2 == 0) { - pos.Y -= (float)(new Vector2(0, 75f).game_remap_1080p().Y * window->scroll_delta * 0.00024414063); // Scroll offset + pos.Y -= (float)(new Vector2(0, 75f).game_remap_1080p() + .Y * window->scroll_delta * 0.00024414063); // Scroll offset } - delegates.CustomizationMenuList* menu_list = FhUtil.ptr_at(0x1197730); + CustomizationMenuList* menu_list = FhUtil.ptr_at(0x1197730); short menu_length = window->num_items; for (int i = -1; i < 10; i++) { int curr_index = menu_offset + i; @@ -906,13 +948,14 @@ private void FUN_008d5d20_Extra(TkWindow* window, int param_2, int menu_offset, } } } + pos += new Vector2(0, 75f).game_remap_1080p(); } } public static TkWindow* MyWindow; - public static void CreateMyWindow(Equipment* gear) - { + + public static void CreateMyWindow(Equipment* gear) { MyWindow = _TkMenuMainAllocWindow(); MyWindow->num_items = gear->slot_count; MyWindow->max_visible_items = 4; @@ -928,69 +971,67 @@ public static void CreateMyWindow(Equipment* gear) public static void MyWindow_Init(TkWindow* window) { window->current_state = 0; } + [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] public static void MyWindow_State(TkWindow* window) { - while (true) - { - switch (window->current_state) - { + while (true) { + switch (window->current_state) { case 0: window->exit_value = 0; window->selected_index = 0; window->current_state = 1; return; + case 1: - if (Globals.Input.up.just_pressed && 0 < window->selected_index) - { + if (Globals.Input.up.just_pressed && 0 < window->selected_index) { _SndSepPlaySimple(0x80000001); window->selected_index--; - } else if (Globals.Input.down.just_pressed && window->selected_index < window->num_items - 1) - { + } else if (Globals.Input.down.just_pressed && window->selected_index < window->num_items - 1) { _SndSepPlaySimple(0x80000001); window->selected_index++; - } else if (Globals.Input.confirm.just_pressed) - { + } else if (Globals.Input.confirm.just_pressed) { _SndSepPlaySimple(0x80000001); window->current_state = 2; - - } else if (Globals.Input.cancel.just_pressed) - { + } else if (Globals.Input.cancel.just_pressed) { _SndSepPlaySimple(0x80000004); window->current_state = 3; } + return; + case 2: window->exit_value = 1; window->current_state = 5; break; + case 3: window->exit_value = -1; window->current_state = 7; break; + default: return; } } } + [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] public static void MyWindow_Render(TkWindow* window) { Vector2 pos = new Vector2(970 + 150, 735 + 12 + 68 * window->selected_index).game_remap_1080p(); _TkMn2DrawCrossCursor(pos.X, pos.Y, 0); } - public static bool h_FUN_008d5720(uint gear_id, int param_2) - { + public static bool h_FUN_008d5720(uint gear_id, int param_2) { Equipment* gear = _MsGetSaveWeapon(gear_id, 0); bool can_customize = false; - if (gear->exists && !gear->is_hidden && gear->slot_count > 0) - { - if (param_2 != 0 || (!gear->is_celestial && !gear->is_brotherhood)) - { + if (gear->exists && !gear->is_hidden && gear->slot_count > 0) { + if (param_2 != 0 || (!gear->is_celestial && !gear->is_brotherhood)) { //if (gear->abilities[gear->slot_count-1] == 0xff || gear->abilities[gear->slot_count - 1] == 0) can_customize = true; } } + return can_customize; } } diff --git a/src/data/ArchipelagoData.cs b/src/data/ArchipelagoData.cs index 5d4b9f5..0619851 100644 --- a/src/data/ArchipelagoData.cs +++ b/src/data/ArchipelagoData.cs @@ -1,7 +1,10 @@ using Archipelago.MultiClient.Net.Enums; + using ArchipelagoFFX.Client; + using Fahrenheit.FFX; using Fahrenheit.FFX.Ids; + using System; using System.Collections.Generic; using System.Linq; @@ -59,10 +62,8 @@ public enum RegionEnum { MonsterArena, } - public static RegionEnum stringToRegion(string region) - { - return region.ToLowerInvariant() switch - { + public static RegionEnum stringToRegion(string region) { + return region.ToLowerInvariant() switch { "dreamzanarkand" or "intro" or "dz" or "drzn" or "drzk" or "open" or "znkd" or "dream" => RegionEnum.DreamZanarkand, "baajtemple" or "baj" or "baaj" or "bt" or "bjyt" or "cdsp" => RegionEnum.BaajTemple, "besaid" or "besaidisland" or "bsil" or "bsa" or "bsvr" or "bsyt" or "bsmm" => RegionEnum.Besaid, @@ -91,6 +92,7 @@ public static RegionEnum stringToRegion(string region) _ => RegionEnum.None }; } + public enum Goal { YuYevon = 0, Nemesis, @@ -129,459 +131,484 @@ public enum CaptureRequirement { 2850 // Yunalesca ]; - public static Dictionary> region_to_ids = new(){ - { RegionEnum.DreamZanarkand, [ - 132, - 368, - 376, - 371, - 370, - 366, - 389, - 367, - 384, - 385, - 355, //Blitzball Tutorial - 347, //Blitzball Menu - 62, //Blitzball Arena - 212, //Results Screen - ] }, - { RegionEnum.BaajTemple, [ - 48, - 49, - 50, - 63, - 52, - 74, - 295, - 196, - 298, - 51, - 71, - 288, - 64, - 380, - 355, //Blitzball Tutorial - 347, //Blitzball Menu - 62, //Blitzball Arena - 212, //Results Screen - ] }, - { RegionEnum.Besaid, [ - 70, - 20, - 41, - 67, - 69, - 133, - 17, - 142, - 144, - 145, - 60, - 143, - 84, - 42, - 147, - 146, - 122, - 103, - 83, - 100, - 252, - 68, - 21, - 22, - 19, - 117, - 301, - 148, - 149, - 150, - 154, - 61, - 282, - 220, - 139, - 191, // - 336, // Jecht Sphere - 337, // Jecht Sphere - 347, //Blitzball Menu - 62, //Blitzball Arena - 212, //Results Screen - ] }, - { RegionEnum.Kilika, [ - 43, - 53, - 152, - 46, - 16, - 151, - 293, - 18, - 65, - 78, - 155, - 156, - 96, - 44, - 108, - 45, - 98, - 47, - 118, - 167, - 237, - 168, - 94, - 169, - 191, - 297, - 185, - 294, // Maybe - 302, // Maybe - 355, //Blitzball Tutorial - 347, //Blitzball Menu - 62, //Blitzball Arena - 212, //Results Screen - ] }, - { RegionEnum.Luca, [ - 267, - 377, - 268, - 355, - 72, - 123, - 73, - 85, - 86, - 87, - 88, - 89, - 77, - 157, - 170, - 158, - 184, - 104, - 107, - 159, - 57, - 121, - 299, - 113, - 124, - 62, - 212, - 347, - 250, - 125, - 55, - 335, // Jecht Sphere - ] }, - { RegionEnum.MiihenHighroad, [ - 95, - 120, - 127, - 58, - 171, - 112, - 115, - 116, - 59, - 334, // Jecht Sphere - 355, //Blitzball Tutorial - 347, //Blitzball Menu - 62, //Blitzball Arena - 212, //Results Screen - ] }, - { RegionEnum.MushroomRockRoad, [ - 79, - 92, - 128, - 119, - 247, - 254, - 218, - 341, - 134, - 131, - 253, // Jecht Sphere? - 289, // Maybe - 355, //Blitzball Tutorial - 347, //Blitzball Menu - 62, //Blitzball Arena - 212, //Results Screen - ] }, - { RegionEnum.Djose, [ - 93, - 76, - 82, - 210, - 81, - 161, - 160, - 214, - 90, - 91, - 245, - 355, //Blitzball Tutorial - 347, //Blitzball Menu - 62, //Blitzball Arena - 212, //Results Screen - ] }, - { RegionEnum.Moonflow, [ - 75, - 105, - 187, - 188, - 235, - 99, - 291, - 236, - 190, - 189, - 109, - 97, - 234, // Maybe - 333, // Jecht Sphere - 355, //Blitzball Tutorial - 347, //Blitzball Menu - 62, //Blitzball Arena - 212, //Results Screen - ] }, - { RegionEnum.Guadosalam, [ - 135, - 243, - 174, - 173, - 172, - 163, - 141, - 197, - 217, - 175, - 257, - 193, - 364, - 134, - 213, // Maybe? - 355, //Blitzball Tutorial - 347, //Blitzball Menu - 62, //Blitzball Arena - 212, //Results Screen - ] }, - { RegionEnum.ThunderPlains, [ - 140, - 256, - 264, - 263, - 262, - 162, - 332, // Jecht Sphere - 355, //Blitzball Tutorial - 347, //Blitzball Menu - 62, //Blitzball Arena - 212, //Results Screen - ] }, - { RegionEnum.Macalania, [ - 110, - 241, - 242, - 221, - 248, - 164, - 215, - 102, - 192, - 153, - 106, - 178, - 179, - 239, - 80, - 54, - 284, - 330, - 331, - 332, - 191, - 260, // Maybe - 365, // Maybe - 391, // Luca flashback - 338, // Jecht Sphere - 355, //Blitzball Tutorial - 347, //Blitzball Menu - 62, //Blitzball Arena - 212, //Results Screen - ] }, - { RegionEnum.Bikanel, [ - 129, - 136, - 137, - 138, - 130, - 276, - 280, - 286, - 275, - 219, - 303, - 261, - 391, // Luca flashback - 355, //Blitzball Tutorial - 347, //Blitzball Menu - 62, //Blitzball Arena - 212, //Results Screen - ] }, - { RegionEnum.Airship, [ - 194, - 265, - 351, - 211, - 277, - 255, - 392, - 205, - 199, - 200, - 201, - 374, // Unsure - 375, // Unsure - 202, // Unsure - 355, //Blitzball Tutorial - 347, //Blitzball Menu - 62, //Blitzball Arena - 212, //Results Screen - ] }, - { RegionEnum.Bevelle, [ - 205, - 180, - 181, - 182, - 306, - 226, - 198, - 209, - 208, - 183, - 274, - 206, - 177, - 176, - 329, - 227, - 305, - 238, // Maybe - 269, // Maybe - 273, // Maybe - 287, // Maybe - 339, // Jecht Sphere - 195, - 207, - 355, //Blitzball Tutorial - 347, //Blitzball Menu - 62, //Blitzball Arena - 212, //Results Screen - ] }, - { RegionEnum.CalmLands, [ - 223, - 290, - 308, - 279, - 372, - 355, //Blitzball Tutorial - 347, //Blitzball Menu - 62, //Blitzball Arena - 212, //Results Screen - ] }, - { RegionEnum.CavernOfTheStolenFayth, [ - 266, - 56, - 283, - 355, //Blitzball Tutorial - 347, //Blitzball Menu - 62, //Blitzball Arena - 212, //Results Screen - ] }, - { RegionEnum.MtGagazet, [ - 259, - 244, - 285, - 309, - 134, - 165, - 249, - 272, - 310, - 311, - 312, - 361, - 381, - 383, // Braska Sphere - 362, - 355, //Blitzball Tutorial - 347, //Blitzball Menu - 62, //Blitzball Arena - 212, //Results Screen - ] }, - { RegionEnum.ZanarkandRuins, [ - 132, - 363, - 225, - 314, - 222, - 316, - 320, - 317, - 318, - 224, - 270, - 319, - 315, - 313, - 355, //Blitzball Tutorial - 347, //Blitzball Menu - 62, //Blitzball Arena - 212, //Results Screen - ] }, - { RegionEnum.Sin, [ - 322, - 203, - 296, - 204, - 327, - 324, // Point of no return : 3250 - 325, - 326, - 386, // Ending - 387, // Ending - 388, // Ending - 390, // Ending - 355, //Blitzball Tutorial - 347, //Blitzball Menu - 62, //Blitzball Arena - 212, //Results Screen - ] }, - { RegionEnum.OmegaRuins, [ - 258, - 271, - 355, //Blitzball Tutorial - 347, //Blitzball Menu - 62, //Blitzball Arena - 212, //Results Screen - ] }, - { RegionEnum.MonsterArena, [ - 307, - 355, //Blitzball Tutorial - 347, //Blitzball Menu - 62, //Blitzball Arena - 212, //Results Screen - ] }, + public static Dictionary> region_to_ids = new() { + { + RegionEnum.DreamZanarkand, [ + 132, + 368, + 376, + 371, + 370, + 366, + 389, + 367, + 384, + 385, + 355, //Blitzball Tutorial + 347, //Blitzball Menu + 62, //Blitzball Arena + 212, //Results Screen + ] + }, { + RegionEnum.BaajTemple, [ + 48, + 49, + 50, + 63, + 52, + 74, + 295, + 196, + 298, + 51, + 71, + 288, + 64, + 380, + 355, //Blitzball Tutorial + 347, //Blitzball Menu + 62, //Blitzball Arena + 212, //Results Screen + ] + }, { + RegionEnum.Besaid, [ + 70, + 20, + 41, + 67, + 69, + 133, + 17, + 142, + 144, + 145, + 60, + 143, + 84, + 42, + 147, + 146, + 122, + 103, + 83, + 100, + 252, + 68, + 21, + 22, + 19, + 117, + 301, + 148, + 149, + 150, + 154, + 61, + 282, + 220, + 139, + 191, // + 336, // Jecht Sphere + 337, // Jecht Sphere + 347, //Blitzball Menu + 62, //Blitzball Arena + 212, //Results Screen + ] + }, { + RegionEnum.Kilika, [ + 43, + 53, + 152, + 46, + 16, + 151, + 293, + 18, + 65, + 78, + 155, + 156, + 96, + 44, + 108, + 45, + 98, + 47, + 118, + 167, + 237, + 168, + 94, + 169, + 191, + 297, + 185, + 294, // Maybe + 302, // Maybe + 355, //Blitzball Tutorial + 347, //Blitzball Menu + 62, //Blitzball Arena + 212, //Results Screen + ] + }, { + RegionEnum.Luca, [ + 267, + 377, + 268, + 355, + 72, + 123, + 73, + 85, + 86, + 87, + 88, + 89, + 77, + 157, + 170, + 158, + 184, + 104, + 107, + 159, + 57, + 121, + 299, + 113, + 124, + 62, + 212, + 347, + 250, + 125, + 55, + 335, // Jecht Sphere + ] + }, { + RegionEnum.MiihenHighroad, [ + 95, + 120, + 127, + 58, + 171, + 112, + 115, + 116, + 59, + 334, // Jecht Sphere + 355, //Blitzball Tutorial + 347, //Blitzball Menu + 62, //Blitzball Arena + 212, //Results Screen + ] + }, { + RegionEnum.MushroomRockRoad, [ + 79, + 92, + 128, + 119, + 247, + 254, + 218, + 341, + 134, + 131, + 253, // Jecht Sphere? + 289, // Maybe + 355, //Blitzball Tutorial + 347, //Blitzball Menu + 62, //Blitzball Arena + 212, //Results Screen + ] + }, { + RegionEnum.Djose, [ + 93, + 76, + 82, + 210, + 81, + 161, + 160, + 214, + 90, + 91, + 245, + 355, //Blitzball Tutorial + 347, //Blitzball Menu + 62, //Blitzball Arena + 212, //Results Screen + ] + }, { + RegionEnum.Moonflow, [ + 75, + 105, + 187, + 188, + 235, + 99, + 291, + 236, + 190, + 189, + 109, + 97, + 234, // Maybe + 333, // Jecht Sphere + 355, //Blitzball Tutorial + 347, //Blitzball Menu + 62, //Blitzball Arena + 212, //Results Screen + ] + }, { + RegionEnum.Guadosalam, [ + 135, + 243, + 174, + 173, + 172, + 163, + 141, + 197, + 217, + 175, + 257, + 193, + 364, + 134, + 213, // Maybe? + 355, //Blitzball Tutorial + 347, //Blitzball Menu + 62, //Blitzball Arena + 212, //Results Screen + ] + }, { + RegionEnum.ThunderPlains, [ + 140, + 256, + 264, + 263, + 262, + 162, + 332, // Jecht Sphere + 355, //Blitzball Tutorial + 347, //Blitzball Menu + 62, //Blitzball Arena + 212, //Results Screen + ] + }, { + RegionEnum.Macalania, [ + 110, + 241, + 242, + 221, + 248, + 164, + 215, + 102, + 192, + 153, + 106, + 178, + 179, + 239, + 80, + 54, + 284, + 330, + 331, + 332, + 191, + 260, // Maybe + 365, // Maybe + 391, // Luca flashback + 338, // Jecht Sphere + 355, //Blitzball Tutorial + 347, //Blitzball Menu + 62, //Blitzball Arena + 212, //Results Screen + ] + }, { + RegionEnum.Bikanel, [ + 129, + 136, + 137, + 138, + 130, + 276, + 280, + 286, + 275, + 219, + 303, + 261, + 391, // Luca flashback + 355, //Blitzball Tutorial + 347, //Blitzball Menu + 62, //Blitzball Arena + 212, //Results Screen + ] + }, { + RegionEnum.Airship, [ + 194, + 265, + 351, + 211, + 277, + 255, + 392, + 205, + 199, + 200, + 201, + 374, // Unsure + 375, // Unsure + 202, // Unsure + 355, //Blitzball Tutorial + 347, //Blitzball Menu + 62, //Blitzball Arena + 212, //Results Screen + ] + }, { + RegionEnum.Bevelle, [ + 205, + 180, + 181, + 182, + 306, + 226, + 198, + 209, + 208, + 183, + 274, + 206, + 177, + 176, + 329, + 227, + 305, + 238, // Maybe + 269, // Maybe + 273, // Maybe + 287, // Maybe + 339, // Jecht Sphere + 195, + 207, + 355, //Blitzball Tutorial + 347, //Blitzball Menu + 62, //Blitzball Arena + 212, //Results Screen + ] + }, { + RegionEnum.CalmLands, [ + 223, + 290, + 308, + 279, + 372, + 355, //Blitzball Tutorial + 347, //Blitzball Menu + 62, //Blitzball Arena + 212, //Results Screen + ] + }, { + RegionEnum.CavernOfTheStolenFayth, [ + 266, + 56, + 283, + 355, //Blitzball Tutorial + 347, //Blitzball Menu + 62, //Blitzball Arena + 212, //Results Screen + ] + }, { + RegionEnum.MtGagazet, [ + 259, + 244, + 285, + 309, + 134, + 165, + 249, + 272, + 310, + 311, + 312, + 361, + 381, + 383, // Braska Sphere + 362, + 355, //Blitzball Tutorial + 347, //Blitzball Menu + 62, //Blitzball Arena + 212, //Results Screen + ] + }, { + RegionEnum.ZanarkandRuins, [ + 132, + 363, + 225, + 314, + 222, + 316, + 320, + 317, + 318, + 224, + 270, + 319, + 315, + 313, + 355, //Blitzball Tutorial + 347, //Blitzball Menu + 62, //Blitzball Arena + 212, //Results Screen + ] + }, { + RegionEnum.Sin, [ + 322, + 203, + 296, + 204, + 327, + 324, // Point of no return : 3250 + 325, + 326, + 386, // Ending + 387, // Ending + 388, // Ending + 390, // Ending + 355, //Blitzball Tutorial + 347, //Blitzball Menu + 62, //Blitzball Arena + 212, //Results Screen + ] + }, { + RegionEnum.OmegaRuins, [ + 258, + 271, + 355, //Blitzball Tutorial + 347, //Blitzball Menu + 62, //Blitzball Arena + 212, //Results Screen + ] + }, { + RegionEnum.MonsterArena, [ + 307, + 355, //Blitzball Tutorial + 347, //Blitzball Menu + 62, //Blitzball Arena + 212, //Results Screen + ] + }, }; - public static readonly Lookup id_to_regions = (Lookup)region_to_ids.SelectMany(region => region.Value, (region, id) => new{region.Key, id}).ToLookup(pair => pair.id, pair => pair.Key); + public static readonly Lookup id_to_regions = (Lookup)region_to_ids + .SelectMany(region => region.Value, (region, id) => new { region.Key, id }) + .ToLookup(pair => pair.id, pair => pair.Key); - public delegate void ArchipelagoStoryCheckDelegate(ArchipelagoRegion region); + public delegate void ArchipelagoStoryCheckDelegate(ArchipelagoRegion region, ArchipelagoClientModule client, ArchipelagoFFXModule ffx_interop); public class ArchipelagoStoryCheck { public ushort? next_story_progress; @@ -592,355 +619,653 @@ public class ArchipelagoStoryCheck { public bool return_to_airship = false; public ArchipelagoStoryCheckDelegate? check_delegate; } + public enum SaveDataType { Byte, Short, Int, } + public struct ArchipelagoRegionSaveData(uint offset, int size) { - [JsonInclude] - public uint offset = offset; - [JsonInclude] - public int size = size; - [JsonInclude] - public byte[] bytes = new byte[size]; + [JsonInclude] public uint offset = offset; + [JsonInclude] public int size = size; + [JsonInclude] public byte[] bytes = new byte[size]; + public ArchipelagoRegionSaveData(uint offset, int size, byte[] value) : this(offset, size) { this.bytes = value; } } + public unsafe class ArchipelagoRegion { - public Dictionary story_checks = []; + public Dictionary story_checks = [ ]; - [JsonInclude] - public int completed_visits; - [JsonInclude] - public ushort story_progress; - [JsonInclude] - public ushort room_id; - [JsonInclude] - public ushort entrance; + [JsonInclude] public int completed_visits; + [JsonInclude] public ushort story_progress; + [JsonInclude] public ushort room_id; + [JsonInclude] public ushort entrance; public bool pilgrimage_completed { get; set; } public uint airship_destination_index; - [JsonInclude] - public ArchipelagoRegionSaveData[] savedata = []; - + [JsonInclude] public ArchipelagoRegionSaveData[] savedata = [ ]; } - public static unsafe Dictionary region_starting_state => new(){ - {RegionEnum.DreamZanarkand, new(){ story_progress = 0, room_id = 132, entrance = 0, airship_destination_index = 99, - story_checks = { - // Dream Zanarkand region does not exist in Apworld, so no place to put Tidus location. Revisit when starting party member rando is added. - //{ 4, new() {check_delegate = (r) => { - // // Tidus - // int partyMember_id = 0; - // if (!FFXArchipelagoClient.local_checked_locations.Contains(partyMember_id | (long)FFXArchipelagoClient.ArchipelagoLocationType.PartyMember)) { - // if (ArchipelagoFFXModule.item_locations.party_member.TryGetValue(partyMember_id, out var item)) { - // if (FFXArchipelagoClient.sendLocation(partyMember_id, FFXArchipelagoClient.ArchipelagoLocationType.PartyMember)) { - // ArchipelagoFFXModule.obtain_item(item.id); - // } - // } - // } - //} } }, - { 5, new() {check_delegate = (r) => { - ArchipelagoFFXModule.logger.Info("Dream Zanarkand complete"); - ArchipelagoFFXModule.save_party(); - ArchipelagoFFXModule.reset_party(); - ArchipelagoFFXModule.call_warp_to_map(382, 0); - }} } - } } }, - {RegionEnum.BaajTemple, new(){ story_progress = 30, room_id = 48, entrance = 0, airship_destination_index = 1, - story_checks = { - { 60, new() {check_delegate = (r) => {ArchipelagoFFXModule.logger.Info("Baaj Temple visit 1 complete"); } } }, - { 110, new() {visit_complete = true, next_story_progress = 3210, next_room_id = 49, next_entrance = 2, return_to_airship = true, check_delegate = (r) => {ArchipelagoFFXModule.logger.Info("Al Bhed Ship complete"); } } }, - } } }, - {RegionEnum.Besaid, new(){ story_progress = 111, room_id = 70, entrance = 0, airship_destination_index = 2, - story_checks = { - { 119, new() {check_delegate = (r) => { - // Wakka - int partyMember_id = 4; - if (!FFXArchipelagoClient.local_checked_locations.Contains(partyMember_id | (long)FFXArchipelagoClient.ArchipelagoLocationType.PartyMember)) { - if (ArchipelagoFFXModule.item_locations.party_member.TryGetValue(partyMember_id, out var item)) { - if (FFXArchipelagoClient.sendLocation(partyMember_id, FFXArchipelagoClient.ArchipelagoLocationType.PartyMember)) { - ArchipelagoFFXModule.obtain_item(item.id); + public unsafe static Dictionary region_starting_state => new() { + { + RegionEnum.DreamZanarkand, new() { + story_progress = 0, room_id = 132, entrance = 0, airship_destination_index = 99, + story_checks = { + // Dream Zanarkand region does not exist in Apworld, so no place to put Tidus location. Revisit when starting party member rando is added. + //{ 4, new() {check_delegate = (r, client, ffx_interop) => { + // // Tidus + // int partyMember_id = 0; + // if (!FFXArchipelagoClient.local_checked_locations.Contains(partyMember_id | (long)FFXArchipelagoClient.ArchipelagoLocationType.PartyMember)) { + // if (ArchipelagoFFXModule.item_locations.party_member.TryGetValue(partyMember_id, out var item)) { + // if (FFXArchipelagoClient.sendLocation(partyMember_id, FFXArchipelagoClient.ArchipelagoLocationType.PartyMember)) { + // ffx_interop.obtain_item(item.id); + // } + // } + // } + //} } }, + { + 5, new() { + check_delegate = (r, client, ffx_interop) => { + //ffx_interop.logger.Info("Dream Zanarkand complete"); + ffx_interop.save_party(); + ffx_interop.reset_party(); + ffx_interop.call_warp_to_map(382, 0); } } } - } } }, - { 182, new() {pilgrimage = true, check_delegate = (r) => { - // Valefor - int partyMember_id = 8; - if (!FFXArchipelagoClient.local_checked_locations.Contains(partyMember_id | (long)FFXArchipelagoClient.ArchipelagoLocationType.PartyMember)) { - if (ArchipelagoFFXModule.item_locations.party_member.TryGetValue(partyMember_id, out var item)) { - if (FFXArchipelagoClient.sendLocation(partyMember_id, FFXArchipelagoClient.ArchipelagoLocationType.PartyMember)) { - ArchipelagoFFXModule.obtain_item(item.id); + } + } + }, { + RegionEnum.BaajTemple, new() { + story_progress = 30, room_id = 48, entrance = 0, airship_destination_index = 1, + story_checks = { + { + 60, + new() { + check_delegate = (r, client, ffx_interop) => { + //ArchipelagoFFXModule.logger.Info("Baaj Temple visit 1 complete"); } } - } - } } }, - { 210, new() {check_delegate = (r) => { - // Send and obtain Map and Brotherhood locations if skipped by CSR - int treasure_id = 459; - if (!FFXArchipelagoClient.local_checked_locations.Contains(treasure_id | (long)FFXArchipelagoClient.ArchipelagoLocationType.Treasure)) { - if (ArchipelagoFFXModule.item_locations.treasure.TryGetValue(treasure_id, out var item)) { - if (FFXArchipelagoClient.sendLocation(treasure_id, FFXArchipelagoClient.ArchipelagoLocationType.Treasure)) { - ArchipelagoFFXModule.obtain_item(item.id); + }, + { + 110, + new() { + visit_complete = true, + next_story_progress = 3210, + next_room_id = 49, + next_entrance = 2, + return_to_airship = true, + check_delegate = (r, client, ffx_interop) => { + //ArchipelagoFFXModule.logger.Info("Al Bhed Ship complete"); } } - } - int other_id = 0; - if (!FFXArchipelagoClient.local_checked_locations.Contains(other_id | (long)FFXArchipelagoClient.ArchipelagoLocationType.Other)) { - if (ArchipelagoFFXModule.item_locations.other.TryGetValue(other_id, out var item)) { - if (FFXArchipelagoClient.sendLocation(other_id, FFXArchipelagoClient.ArchipelagoLocationType.Other)) { - ArchipelagoFFXModule.obtain_item(item.id); + }, + } + } + }, { + RegionEnum.Besaid, new() { + story_progress = 111, room_id = 70, entrance = 0, airship_destination_index = 2, + story_checks = { + { + 119, new() { + check_delegate = (r, client, ffx_interop) => { + // Wakka + int partyMember_id = 4; + if (!client.local_checked_locations.Contains(partyMember_id | (long)ArchipelagoClientModule.ArchipelagoLocationType.PartyMember)) { + if (ArchipelagoFFXModule.item_locations.party_member.TryGetValue(partyMember_id, out var item)) { + if (client.sendLocation(partyMember_id, ArchipelagoClientModule.ArchipelagoLocationType.PartyMember)) { + ffx_interop.obtain_item(item.id); + } + } + } } } - } - } } }, - { 228, new() {check_delegate = (r) => {ArchipelagoFFXModule.logger.Info("Besaid visit 1 complete"); } } }, - { 248, new() {check_delegate = (r) => { - int partyMember_id = 3; // Kimahri - if (!FFXArchipelagoClient.local_checked_locations.Contains(partyMember_id | (long)FFXArchipelagoClient.ArchipelagoLocationType.PartyMember)) { - if (ArchipelagoFFXModule.item_locations.party_member.TryGetValue(partyMember_id, out var item)) { - if (FFXArchipelagoClient.sendLocation(partyMember_id, FFXArchipelagoClient.ArchipelagoLocationType.PartyMember)) { - ArchipelagoFFXModule.obtain_item(item.id); + }, { + 182, new() { + pilgrimage = true, + check_delegate = (r, client, ffx_interop) => { + // Valefor + int partyMember_id = 8; + if (!client.local_checked_locations.Contains(partyMember_id | (long)ArchipelagoClientModule.ArchipelagoLocationType.PartyMember)) { + if (ArchipelagoFFXModule.item_locations.party_member.TryGetValue(partyMember_id, out var item)) { + if (client.sendLocation(partyMember_id, ArchipelagoClientModule.ArchipelagoLocationType.PartyMember)) { + ffx_interop.obtain_item(item.id); + } + } + } } } - } - } } }, - { 290, new() {visit_complete = true, next_story_progress = 3210, next_room_id = 19, next_entrance = 1, return_to_airship = true, check_delegate = (r) => {ArchipelagoFFXModule.logger.Info("S.S Liki visit complete"); } } }, - } } }, - {RegionEnum.Kilika, new(){ story_progress = 304, room_id = 16, entrance = 0, airship_destination_index = 3, - savedata = [ - new ArchipelagoRegionSaveData(0x03AC, 1, [0]), - ], - story_checks = { - { 348, new() {pilgrimage = true, check_delegate = (r) => { - // Ifrit - int partyMember_id = 9; - if (!FFXArchipelagoClient.local_checked_locations.Contains(partyMember_id | (long)FFXArchipelagoClient.ArchipelagoLocationType.PartyMember)) { - if (ArchipelagoFFXModule.item_locations.party_member.TryGetValue(partyMember_id, out var item)) { - if (FFXArchipelagoClient.sendLocation(partyMember_id, FFXArchipelagoClient.ArchipelagoLocationType.PartyMember)) { - ArchipelagoFFXModule.obtain_item(item.id); + }, { + 210, new() { + check_delegate = (r, client, ffx_interop) => { + // Send and obtain Map and Brotherhood locations if skipped by CSR + int treasure_id = 459; + if (!client.local_checked_locations.Contains(treasure_id | (long)ArchipelagoClientModule.ArchipelagoLocationType.Treasure)) { + if (ArchipelagoFFXModule.item_locations.treasure.TryGetValue(treasure_id, out var item)) { + if (client.sendLocation(treasure_id, ArchipelagoClientModule.ArchipelagoLocationType.Treasure)) { + ffx_interop.obtain_item(item.id); + } + } + } + + int other_id = 0; + if (!client.local_checked_locations.Contains(other_id | (long)ArchipelagoClientModule.ArchipelagoLocationType.Other)) { + if (ArchipelagoFFXModule.item_locations.other.TryGetValue(other_id, out var item)) { + if (client.sendLocation(other_id, ArchipelagoClientModule.ArchipelagoLocationType.Other)) { + ffx_interop.obtain_item(item.id); + } + } + } } } - } - } } }, - { 372, new() {check_delegate = (r) => {ArchipelagoFFXModule.logger.Info("Kilika visit 1 complete"); } } }, - { 400, new() {visit_complete = true, next_story_progress = 3210, next_room_id = 98, next_entrance = 3, return_to_airship = true, check_delegate = (r) => {ArchipelagoFFXModule.logger.Info("S.S Winno visit complete"); } } }, - { 402, new() {visit_complete = true, next_story_progress = 3210, next_room_id = 98, next_entrance = 3, return_to_airship = true, check_delegate = (r) => {ArchipelagoFFXModule.logger.Info("S.S Winno visit complete"); } } }, - } } }, - {RegionEnum.Luca, new(){ story_progress = 402, room_id = 267, entrance = 0, airship_destination_index = 4, - story_checks = { - { 600, new() {check_delegate = (r) => { - // Auron - int partyMember_id = 2; - if (!FFXArchipelagoClient.local_checked_locations.Contains(partyMember_id | (long)FFXArchipelagoClient.ArchipelagoLocationType.PartyMember)) { - if (ArchipelagoFFXModule.item_locations.party_member.TryGetValue(partyMember_id, out var item)) { - if (FFXArchipelagoClient.sendLocation(partyMember_id, FFXArchipelagoClient.ArchipelagoLocationType.PartyMember)) { - ArchipelagoFFXModule.obtain_item(item.id); + }, + { 228, + new() { + check_delegate = (r, client, ffx_interop) => { + //ArchipelagoFFXModule.logger.Info("Besaid visit 1 complete"); } } - } - } } }, - { 730, new() {visit_complete = true, next_story_progress = 3210, next_room_id = 123, next_entrance = 6, return_to_airship = true, - check_delegate = (r) => { - ArchipelagoFFXModule.logger.Info("Luca visit complete"); - // CSR workaround - Globals.save_data->current_room_id = 123; - Globals.save_data->current_spawnpoint = 6; - } } }, - } } }, - {RegionEnum.MiihenHighroad, new(){ story_progress = 730, room_id = 95, entrance = 0, airship_destination_index = 5, - savedata = [ - new ArchipelagoRegionSaveData(0x0285, 1), - new ArchipelagoRegionSaveData(0x0C3C, 4), - new ArchipelagoRegionSaveData(0x0C40, 4), - new ArchipelagoRegionSaveData(0x0C44, 4), - new ArchipelagoRegionSaveData(0x0C48, 4), + + }, { + 248, new() { + check_delegate = (r, client, ffx_interop) => { + int partyMember_id = 3; // Kimahri + if (!client.local_checked_locations.Contains(partyMember_id | (long)ArchipelagoClientModule.ArchipelagoLocationType.PartyMember)) { + if (ArchipelagoFFXModule.item_locations.party_member.TryGetValue(partyMember_id, out var item)) { + if (client.sendLocation(partyMember_id, ArchipelagoClientModule.ArchipelagoLocationType.PartyMember)) { + ffx_interop.obtain_item(item.id); + } + } + } + } + } + }, + { + 290, + new() { + visit_complete = true, + next_story_progress = 3210, + next_room_id = 19, + next_entrance = 1, + return_to_airship = true, + check_delegate = (r, client, ffx_interop) => { + //ArchipelagoFFXModule.logger.Info("S.S Liki visit complete"); + } + } + }, + } + } + }, { + RegionEnum.Kilika, new() { + story_progress = 304, room_id = 16, entrance = 0, airship_destination_index = 3, + savedata = [ + new ArchipelagoRegionSaveData(0x03AC, 1, [ 0 ]), ], - story_checks = { - { 787, new() {visit_complete = true, next_story_progress = 3210, next_room_id = 171, next_entrance = 1, return_to_airship = true, check_delegate = (r) => {ArchipelagoFFXModule.logger.Info("Mi'ihen Highroad visit complete"); } } }, - } } }, - {RegionEnum.MushroomRockRoad, new(){ story_progress = 787, room_id = 79, entrance = 0, airship_destination_index = 6, - story_checks = { - { 960, new() {visit_complete = true, next_story_progress = 3210, next_room_id = 131, next_entrance = 3, return_to_airship = true, check_delegate = (r) => {ArchipelagoFFXModule.logger.Info("Mushroom Rock Road visit complete"); } } }, - } } }, - {RegionEnum.Djose, new(){ story_progress = 960, room_id = 93, entrance = 0, airship_destination_index = 7, - story_checks = { - { 1010, new() {pilgrimage = true, check_delegate = (r) => { - // Ixion - int partyMember_id = 10; - if (!FFXArchipelagoClient.local_checked_locations.Contains(partyMember_id | (long)FFXArchipelagoClient.ArchipelagoLocationType.PartyMember)) { - if (ArchipelagoFFXModule.item_locations.party_member.TryGetValue(partyMember_id, out var item)) { - if (FFXArchipelagoClient.sendLocation(partyMember_id, FFXArchipelagoClient.ArchipelagoLocationType.PartyMember)) { - ArchipelagoFFXModule.obtain_item(item.id); + story_checks = { + { + 348, new() { + pilgrimage = true, check_delegate = (r, client, ffx_interop) => { + // Ifrit + int partyMember_id = 9; + if (!client.local_checked_locations.Contains(partyMember_id | (long)ArchipelagoClientModule.ArchipelagoLocationType.PartyMember)) { + if (ArchipelagoFFXModule.item_locations.party_member.TryGetValue(partyMember_id, out var item)) { + if (client.sendLocation(partyMember_id, ArchipelagoClientModule.ArchipelagoLocationType.PartyMember)) { + ffx_interop.obtain_item(item.id); + } + } + } } } - } - } } }, - { 1030, new() {visit_complete = true, next_story_progress = 3210, next_room_id = 82, next_entrance = 0, return_to_airship = true, check_delegate = (r) => {ArchipelagoFFXModule.logger.Info("Djose visit 1 complete"); } } }, - } } }, - {RegionEnum.Moonflow, new(){ story_progress = 1030, room_id = 75, entrance = 0, airship_destination_index = 8, - story_checks = { - { 1085, new() {visit_complete = true, next_story_progress = 3210, next_room_id = 235, next_entrance = 1, return_to_airship = true, - check_delegate = (r) => { - // Rikku - int partyMember_id = 6; - if (!FFXArchipelagoClient.local_checked_locations.Contains(partyMember_id | (long)FFXArchipelagoClient.ArchipelagoLocationType.PartyMember)) { - if (ArchipelagoFFXModule.item_locations.party_member.TryGetValue(partyMember_id, out var item)) { - if (FFXArchipelagoClient.sendLocation(partyMember_id, FFXArchipelagoClient.ArchipelagoLocationType.PartyMember)) { - ArchipelagoFFXModule.obtain_item(item.id); + }, + { + 372, + new() { + check_delegate = (r, client, ffx_interop) => { + //ArchipelagoFFXModule.logger.Info("Kilika visit 1 complete"); } } - } - ArchipelagoFFXModule.logger.Info("Moonflow visit complete"); - } } }, - } } }, - {RegionEnum.Guadosalam, new(){ story_progress = 1085, room_id = 135, entrance = 0, airship_destination_index = 9, - story_checks = { - { 1170, new() {check_delegate = (r) => { - // Send and obtain Brotherhood upgrade location if skipped by CSR - int other_id = 37; - if (!FFXArchipelagoClient.local_checked_locations.Contains(other_id | (long)FFXArchipelagoClient.ArchipelagoLocationType.Other)) { - if (ArchipelagoFFXModule.item_locations.other.TryGetValue(other_id, out var item)) { - if (FFXArchipelagoClient.sendLocation(other_id, FFXArchipelagoClient.ArchipelagoLocationType.Other)) { - ArchipelagoFFXModule.obtain_item(item.id); + }, + { + 400, + new() { + visit_complete = true, + next_story_progress = 3210, + next_room_id = 98, + next_entrance = 3, + return_to_airship = true, + check_delegate = (r, client, ffx_interop) => { + //ArchipelagoFFXModule.logger.Info("S.S Winno visit complete"); } } - } - } } }, - { 1210, new() {visit_complete = true, next_story_progress = 1310, next_room_id = 243, next_entrance = 1, return_to_airship = true, check_delegate = (r) => {ArchipelagoFFXModule.logger.Info("Guadosalam visit complete"); } } }, - } } }, - {RegionEnum.ThunderPlains, new(){ story_progress = 1210, room_id = 140, entrance = 0, airship_destination_index = 10, - savedata = [ - new ArchipelagoRegionSaveData(0x03F8, 1, [0]), - new ArchipelagoRegionSaveData(0x03F1, 3, [0, 0, 0]) //save_data->progression_flags_thunder_plains - ], - story_checks = { - { 1375, new() {visit_complete = true, next_story_progress = 3210, next_room_id = 263, next_entrance = 2, return_to_airship = true, check_delegate = (r) => {ArchipelagoFFXModule.logger.Info("Thunder Plains visit complete"); } } }, - } } }, - {RegionEnum.Macalania, new(){ story_progress = 1400, room_id = 110, entrance = 0, airship_destination_index = 11, - story_checks = { - { 1470, new() {check_delegate = (r) => { - ArchipelagoFFXModule.logger.Info("Macalania Woods visit complete"); - int treasure_id = 177; - if (!FFXArchipelagoClient.local_checked_locations.Contains(treasure_id | (long)FFXArchipelagoClient.ArchipelagoLocationType.Treasure)) { - if (ArchipelagoFFXModule.item_locations.treasure.TryGetValue(treasure_id, out var item)) { - if (FFXArchipelagoClient.sendLocation(treasure_id, FFXArchipelagoClient.ArchipelagoLocationType.Treasure)) { - ArchipelagoFFXModule.obtain_item(item.id); + }, + { + 402, + new() { + visit_complete = true, + next_story_progress = 3210, + next_room_id = 98, + next_entrance = 3, + return_to_airship = true, + check_delegate = (r, client, ffx_interop) => { + //ArchipelagoFFXModule.logger.Info("S.S Winno visit complete"); } } - } - } } }, - { 1530, new() {check_delegate = (r) => { - int treasure_id = 85; - if (!FFXArchipelagoClient.local_checked_locations.Contains(treasure_id | (long)FFXArchipelagoClient.ArchipelagoLocationType.Treasure)) { - if (ArchipelagoFFXModule.item_locations.treasure.TryGetValue(treasure_id, out var item)) { - if (FFXArchipelagoClient.sendLocation(treasure_id, FFXArchipelagoClient.ArchipelagoLocationType.Treasure)) { - ArchipelagoFFXModule.obtain_item(item.id); + }, + } + } + }, { + RegionEnum.Luca, new() { + story_progress = 402, room_id = 267, entrance = 0, airship_destination_index = 4, + story_checks = { + { + 600, new() { + check_delegate = (r, client, ffx_interop) => { + // Auron + int partyMember_id = 2; + if (!client.local_checked_locations.Contains(partyMember_id | (long)ArchipelagoClientModule.ArchipelagoLocationType.PartyMember)) { + if (ArchipelagoFFXModule.item_locations.party_member.TryGetValue(partyMember_id, out var item)) { + if (client.sendLocation(partyMember_id, ArchipelagoClientModule.ArchipelagoLocationType.PartyMember)) { + ffx_interop.obtain_item(item.id); + } + } + } } } - } } } }, - { 1545, new() {pilgrimage = true, check_delegate = (r) => { - // Shiva - int partyMember_id = 11; - if (!FFXArchipelagoClient.local_checked_locations.Contains(partyMember_id | (long)FFXArchipelagoClient.ArchipelagoLocationType.PartyMember)) { - if (ArchipelagoFFXModule.item_locations.party_member.TryGetValue(partyMember_id, out var item)) { - if (FFXArchipelagoClient.sendLocation(partyMember_id, FFXArchipelagoClient.ArchipelagoLocationType.PartyMember)) { - ArchipelagoFFXModule.obtain_item(item.id); + }, { + 730, new() { + visit_complete = true, next_story_progress = 3210, next_room_id = 123, next_entrance = 6, return_to_airship = true, + check_delegate = (r, client, ffx_interop) => { + //ArchipelagoFFXModule.logger.Info("Luca visit complete"); + // CSR workaround + Globals.save_data->current_room_id = 123; + Globals.save_data->current_spawnpoint = 6; } } - } - } } }, - { 1704, new() {visit_complete = true, next_story_progress = 3210, next_room_id = 215, next_entrance = 1, return_to_airship = true, check_delegate = (r) => {ArchipelagoFFXModule.logger.Info("Lake Macalania visit 1 complete"); } } }, - } } }, - {RegionEnum.Bikanel, new(){ story_progress = 1704, room_id = 129, entrance = 0, airship_destination_index = 12, - story_checks = { - { 1940, new() {visit_complete = true, next_story_progress = 3210, next_room_id = 129, next_entrance = 2, return_to_airship = true, check_delegate = (r) => { - ArchipelagoFFXModule.logger.Info("Bikanel visit complete"); - int[] treasure_ids = [362, 363, 364]; - foreach (int treasure_id in treasure_ids) { - if (!FFXArchipelagoClient.local_checked_locations.Contains(treasure_id | (long)FFXArchipelagoClient.ArchipelagoLocationType.Treasure)) { - if (ArchipelagoFFXModule.item_locations.treasure.TryGetValue(treasure_id, out var item)) { - if (FFXArchipelagoClient.sendLocation(treasure_id, FFXArchipelagoClient.ArchipelagoLocationType.Treasure)) { - ArchipelagoFFXModule.obtain_item(item.id); + }, + } + } + }, { + RegionEnum.MiihenHighroad, new() { + story_progress = 730, room_id = 95, entrance = 0, airship_destination_index = 5, + savedata = [ + new ArchipelagoRegionSaveData(0x0285, 1), + new ArchipelagoRegionSaveData(0x0C3C, 4), + new ArchipelagoRegionSaveData(0x0C40, 4), + new ArchipelagoRegionSaveData(0x0C44, 4), + new ArchipelagoRegionSaveData(0x0C48, 4), + ], + story_checks = { + { + 787, + new() { + visit_complete = true, + next_story_progress = 3210, + next_room_id = 171, + next_entrance = 1, + return_to_airship = true, + check_delegate = (r, client, ffx_interop) => { + //ArchipelagoFFXModule.logger.Info("Mi'ihen Highroad visit complete"); + } + } + }, + } + } + }, { + RegionEnum.MushroomRockRoad, new() { + story_progress = 787, room_id = 79, entrance = 0, airship_destination_index = 6, + story_checks = { + { + 960, + new() { + visit_complete = true, + next_story_progress = 3210, + next_room_id = 131, + next_entrance = 3, + return_to_airship = true, + check_delegate = (r, client, ffx_interop) => { + //ArchipelagoFFXModule.logger.Info("Mushroom Rock Road visit complete"); + } + } + }, + } + } + }, { + RegionEnum.Djose, new() { + story_progress = 960, room_id = 93, entrance = 0, airship_destination_index = 7, + story_checks = { + { + 1010, new() { + pilgrimage = true, check_delegate = (r, client, ffx_interop) => { + // Ixion + int partyMember_id = 10; + if (!client.local_checked_locations.Contains(partyMember_id | (long)ArchipelagoClientModule.ArchipelagoLocationType.PartyMember)) { + if (ArchipelagoFFXModule.item_locations.party_member.TryGetValue(partyMember_id, out var item)) { + if (client.sendLocation(partyMember_id, ArchipelagoClientModule.ArchipelagoLocationType.PartyMember)) { + ffx_interop.obtain_item(item.id); + } + } } } } - } - } } }, - { 1950, new() {visit_complete = true, next_story_progress = 3210, next_room_id = 129, next_entrance = 2, return_to_airship = true, check_delegate = (r) => { - ArchipelagoFFXModule.logger.Info("Bikanel visit complete"); - int[] treasure_ids = [362, 363, 364]; - foreach (int treasure_id in treasure_ids) { - if (!FFXArchipelagoClient.local_checked_locations.Contains(treasure_id | (long)FFXArchipelagoClient.ArchipelagoLocationType.Treasure)) { - if (ArchipelagoFFXModule.item_locations.treasure.TryGetValue(treasure_id, out var item)) { - if (FFXArchipelagoClient.sendLocation(treasure_id, FFXArchipelagoClient.ArchipelagoLocationType.Treasure)) { - ArchipelagoFFXModule.obtain_item(item.id); + }, + { + 1030, + new() { + visit_complete = true, + next_story_progress = 3210, + next_room_id = 82, + next_entrance = 0, + return_to_airship = true, + check_delegate = (r, client, ffx_interop) => { + //ArchipelagoFFXModule.logger.Info("Djose visit 1 complete"); + } + } + }, + } + } + }, { + RegionEnum.Moonflow, new() { + story_progress = 1030, room_id = 75, entrance = 0, airship_destination_index = 8, + story_checks = { + { + 1085, new() { + visit_complete = true, next_story_progress = 3210, next_room_id = 235, next_entrance = 1, return_to_airship = true, + check_delegate = (r, client, ffx_interop) => { + // Rikku + int partyMember_id = 6; + if (!client.local_checked_locations.Contains(partyMember_id | (long)ArchipelagoClientModule.ArchipelagoLocationType.PartyMember)) { + if (ArchipelagoFFXModule.item_locations.party_member.TryGetValue(partyMember_id, out var item)) { + if (client.sendLocation(partyMember_id, ArchipelagoClientModule.ArchipelagoLocationType.PartyMember)) { + ffx_interop.obtain_item(item.id); + } + } } + + //ArchipelagoFFXModule.logger.Info("Moonflow visit complete"); } } - } - } } }, - } } }, - {RegionEnum.Airship, new(){ story_progress = 1950, room_id = 194, entrance = 1, airship_destination_index = 13, - story_checks = { - { 2075, new() {visit_complete = true, next_story_progress = 2970, next_room_id = 255, next_entrance = 0, return_to_airship = true, check_delegate = (r) => {ArchipelagoFFXModule.logger.Info("Airship visit 1 complete"); } } }, - //{ 3135, new() {next_story_progress = 3210, next_room_id = 255, next_entrance = 0, return_if_locked = RegionEnum.Sin, check_delegate = (r) => {ArchipelagoFFXModule.logger.Info("Airship visit 2 complete"); } } }, - } } }, - {RegionEnum.Bevelle, new(){ story_progress = 2040, room_id = 205, entrance = 0, airship_destination_index = 14, - story_checks = { - { 2220, new() {pilgrimage = true, check_delegate = (r) => { - // Bahamut - int partyMember_id = 12; - if (!FFXArchipelagoClient.local_checked_locations.Contains(partyMember_id | (long)FFXArchipelagoClient.ArchipelagoLocationType.PartyMember)) { - if (ArchipelagoFFXModule.item_locations.party_member.TryGetValue(partyMember_id, out var item)) { - if (FFXArchipelagoClient.sendLocation(partyMember_id, FFXArchipelagoClient.ArchipelagoLocationType.PartyMember)) { - ArchipelagoFFXModule.obtain_item(item.id); + }, + } + } + }, { + RegionEnum.Guadosalam, new() { + story_progress = 1085, room_id = 135, entrance = 0, airship_destination_index = 9, + story_checks = { + { + 1170, new() { + check_delegate = (r, client, ffx_interop) => { + // Send and obtain Brotherhood upgrade location if skipped by CSR + int other_id = 37; + if (!client.local_checked_locations.Contains(other_id | (long)ArchipelagoClientModule.ArchipelagoLocationType.Other)) { + if (ArchipelagoFFXModule.item_locations.other.TryGetValue(other_id, out var item)) { + if (client.sendLocation(other_id, ArchipelagoClientModule.ArchipelagoLocationType.Other)) { + ffx_interop.obtain_item(item.id); + } + } + } } } - } - } } }, - { 2385, new() {visit_complete = true, next_story_progress = 3210, next_room_id = 208, next_entrance = 1, return_to_airship = true, check_delegate = (r) => {ArchipelagoFFXModule.logger.Info("Bevelle complete"); } } }, - } } }, - {RegionEnum.CalmLands, new(){ story_progress = 2385, room_id = 223, entrance = 0, airship_destination_index = 15, - savedata = [ - new ArchipelagoRegionSaveData(0x0285, 1), - new ArchipelagoRegionSaveData(0x0C3C, 4), - new ArchipelagoRegionSaveData(0x0C40, 4), - new ArchipelagoRegionSaveData(0x0C44, 4), - new ArchipelagoRegionSaveData(0x0C48, 4), + }, + { + 1210, + new() { + visit_complete = true, + next_story_progress = 1310, + next_room_id = 243, + next_entrance = 1, + return_to_airship = true, + check_delegate = (r, client, ffx_interop) => { + //ArchipelagoFFXModule.logger.Info("Guadosalam visit complete"); + } + } + }, + } + } + }, { + RegionEnum.ThunderPlains, new() { + story_progress = 1210, room_id = 140, entrance = 0, airship_destination_index = 10, + savedata = [ + new ArchipelagoRegionSaveData(0x03F8, 1, [ 0 ]), + new ArchipelagoRegionSaveData(0x03F1, 3, [ 0, 0, 0 ]) //save_data->progression_flags_thunder_plains ], - story_checks = { - { 2440, new() {visit_complete = true, next_story_progress = 3210, next_room_id = 223, next_entrance = 4, return_to_airship = true, check_delegate = (r) => {ArchipelagoFFXModule.logger.Info("Calm Lands complete"); } } }, // Normally ends at 2440, but CSR skips from 2420 to 2510 - { 2510, new() {visit_complete = true, next_story_progress = 3210, next_room_id = 223, next_entrance = 4, return_to_airship = true, check_delegate = (r) => {ArchipelagoFFXModule.logger.Info("Calm Lands complete"); } } }, // Normally ends at 2440, but CSR skips from 2420 to 2510 - } } }, - {RegionEnum.CavernOfTheStolenFayth, new(){ story_progress = 2420, room_id = 266, entrance = 0, airship_destination_index = 16 } }, - {RegionEnum.MtGagazet, new(){ story_progress = 2440, room_id = 259, entrance = 0, airship_destination_index = 18, - story_checks = { - { 2680, new() {visit_complete = true, next_story_progress = 3210, next_room_id = 259, next_entrance = 2, return_to_airship = true, check_delegate = (r) => {ArchipelagoFFXModule.logger.Info("Mt. Gagazet complete"); } } }, - } } }, - {RegionEnum.ZanarkandRuins, new(){ story_progress = 2680, room_id = 132, entrance = 0, airship_destination_index = 19, - story_checks = { - { 2850, new() {pilgrimage = true } }, - { 2875, new() {visit_complete = true, next_story_progress = 3210, next_room_id = 313, next_entrance = 3, return_to_airship = true, check_delegate = (r) => {ArchipelagoFFXModule.logger.Info("Zanarkand Ruins complete"); } } }, - { 2900, new() {visit_complete = true, next_story_progress = 3210, next_room_id = 313, next_entrance = 3, return_to_airship = true, check_delegate = (r) => {ArchipelagoFFXModule.logger.Info("Zanarkand Ruins complete"); } } }, - } } }, - {RegionEnum.Sin, new(){ story_progress = 3125, room_id = 322, entrance = 2, airship_destination_index = 20, - story_checks = { - { 3400, new() {visit_complete = true, next_room_id = 322, next_entrance = 2, check_delegate = (r) => { - ArchipelagoFFXModule.logger.Info("Game Complete"); - foreach (var character in ArchipelagoFFXModule.locked_characters) { - ArchipelagoFFXModule.locked_characters[character.Key] = false; - } - } } }, - { 11000, new() {next_story_progress = 3210, next_room_id = 327, next_entrance = 0, check_delegate = (r) => { - ArchipelagoFFXModule.call_warp_to_map(382, 0); - } } }, - } } }, - {RegionEnum.OmegaRuins, new(){ story_progress = 3210, room_id = 258, entrance = 2, airship_destination_index = 21 } }, // Story_progress? - {RegionEnum.MonsterArena, new(){ story_progress = 3210, room_id = 307, entrance = 0, airship_destination_index = 17 } }, + story_checks = { + { + 1375, + new() { + visit_complete = true, + next_story_progress = 3210, + next_room_id = 263, + next_entrance = 2, + return_to_airship = true, + check_delegate = (r, client, ffx_interop) => { + //ArchipelagoFFXModule.logger.Info("Thunder Plains visit complete"); + } + } + }, + } + } + }, { + RegionEnum.Macalania, new() { + story_progress = 1400, room_id = 110, entrance = 0, airship_destination_index = 11, + story_checks = { + { + 1470, new() { + check_delegate = (r, client, ffx_interop) => { + //ArchipelagoFFXModule.logger.Info("Macalania Woods visit complete"); + int treasure_id = 177; + if (!client.local_checked_locations.Contains(treasure_id | (long)ArchipelagoClientModule.ArchipelagoLocationType.Treasure)) { + if (ArchipelagoFFXModule.item_locations.treasure.TryGetValue(treasure_id, out var item)) { + if (client.sendLocation(treasure_id, ArchipelagoClientModule.ArchipelagoLocationType.Treasure)) { + ffx_interop.obtain_item(item.id); + } + } + } + } + } + }, { + 1530, new() { + check_delegate = (r, client, ffx_interop) => { + int treasure_id = 85; + if (!client.local_checked_locations.Contains(treasure_id | (long)ArchipelagoClientModule.ArchipelagoLocationType.Treasure)) { + if (ArchipelagoFFXModule.item_locations.treasure.TryGetValue(treasure_id, out var item)) { + if (client.sendLocation(treasure_id, ArchipelagoClientModule.ArchipelagoLocationType.Treasure)) { + ffx_interop.obtain_item(item.id); + } + } + } + } + } + }, { + 1545, new() { + pilgrimage = true, check_delegate = (r, client, ffx_interop) => { + // Shiva + int partyMember_id = 11; + if (!client.local_checked_locations.Contains(partyMember_id | (long)ArchipelagoClientModule.ArchipelagoLocationType.PartyMember)) { + if (ArchipelagoFFXModule.item_locations.party_member.TryGetValue(partyMember_id, out var item)) { + if (client.sendLocation(partyMember_id, ArchipelagoClientModule.ArchipelagoLocationType.PartyMember)) { + ffx_interop.obtain_item(item.id); + } + } + } + } + } + }, + { + 1704, + new() { + visit_complete = true, + next_story_progress = 3210, + next_room_id = 215, + next_entrance = 1, + return_to_airship = true, + check_delegate = (r, client, ffx_interop) => { + //ArchipelagoFFXModule.logger.Info("Lake Macalania visit 1 complete"); + } + } + }, + } + } + }, { + RegionEnum.Bikanel, new() { + story_progress = 1704, room_id = 129, entrance = 0, airship_destination_index = 12, + story_checks = { + { + 1940, new() { + visit_complete = true, next_story_progress = 3210, next_room_id = 129, next_entrance = 2, return_to_airship = true, check_delegate = (r, client, ffx_interop) => { + //ArchipelagoFFXModule.logger.Info("Bikanel visit complete"); + int[] treasure_ids = [ 362, 363, 364 ]; + foreach (int treasure_id in treasure_ids) { + if (!client.local_checked_locations.Contains(treasure_id | (long)ArchipelagoClientModule.ArchipelagoLocationType.Treasure)) { + if (ArchipelagoFFXModule.item_locations.treasure.TryGetValue(treasure_id, out var item)) { + if (client.sendLocation(treasure_id, ArchipelagoClientModule.ArchipelagoLocationType.Treasure)) { + ffx_interop.obtain_item(item.id); + } + } + } + } + } + } + }, { + 1950, new() { + visit_complete = true, next_story_progress = 3210, next_room_id = 129, next_entrance = 2, return_to_airship = true, check_delegate = (r, client, ffx_interop) => { + //ArchipelagoFFXModule.logger.Info("Bikanel visit complete"); + int[] treasure_ids = [ 362, 363, 364 ]; + foreach (int treasure_id in treasure_ids) { + if (!client.local_checked_locations.Contains(treasure_id | (long)ArchipelagoClientModule.ArchipelagoLocationType.Treasure)) { + if (ArchipelagoFFXModule.item_locations.treasure.TryGetValue(treasure_id, out var item)) { + if (client.sendLocation(treasure_id, ArchipelagoClientModule.ArchipelagoLocationType.Treasure)) { + ffx_interop.obtain_item(item.id); + } + } + } + } + } + } + }, + } + } + }, { + RegionEnum.Airship, new() { + story_progress = 1950, room_id = 194, entrance = 1, airship_destination_index = 13, + story_checks = { + { 2075, new() { visit_complete = true, next_story_progress = 2970, next_room_id = 255, next_entrance = 0, return_to_airship = true, check_delegate = (r, client, ffx_interop) => { /* ArchipelagoFFXModule.logger.Info(Airship visit 1 complete); */ } } }, + //{ 3135, new() {next_story_progress = 3210, next_room_id = 255, next_entrance = 0, return_if_locked = RegionEnum.Sin, check_delegate = (r, client, ffx_interop) => {ArchipelagoFFXModule.logger.Info("Airship visit 2 complete"); } } }, + } + } + }, { + RegionEnum.Bevelle, new() { + story_progress = 2040, room_id = 205, entrance = 0, airship_destination_index = 14, + story_checks = { + { + 2220, new() { + pilgrimage = true, check_delegate = (r, client, ffx_interop) => { + // Bahamut + int partyMember_id = 12; + if (!client.local_checked_locations.Contains(partyMember_id | (long)ArchipelagoClientModule.ArchipelagoLocationType.PartyMember)) { + if (ArchipelagoFFXModule.item_locations.party_member.TryGetValue(partyMember_id, out var item)) { + if (client.sendLocation(partyMember_id, ArchipelagoClientModule.ArchipelagoLocationType.PartyMember)) { + ffx_interop.obtain_item(item.id); + } + } + } + } + } + }, + { + 2385, + new() { + visit_complete = true, + next_story_progress = 3210, + next_room_id = 208, + next_entrance = 1, + return_to_airship = true, + check_delegate = (r, client, ffx_interop) => { + //ArchipelagoFFXModule.logger.Info("Bevelle complete"); + } + } + }, + } + } + }, { + RegionEnum.CalmLands, new() { + story_progress = 2385, room_id = 223, entrance = 0, airship_destination_index = 15, + savedata = [ + new ArchipelagoRegionSaveData(0x0285, 1), + new ArchipelagoRegionSaveData(0x0C3C, 4), + new ArchipelagoRegionSaveData(0x0C40, 4), + new ArchipelagoRegionSaveData(0x0C44, 4), + new ArchipelagoRegionSaveData(0x0C48, 4), + ], + story_checks = { + { + 2440, + new() { + visit_complete = true, + next_story_progress = 3210, + next_room_id = 223, + next_entrance = 4, + return_to_airship = true, + check_delegate = (r, client, ffx_interop) => { + //ArchipelagoFFXModule.logger.Info("Calm Lands complete"); + } + } + }, // Normally ends at 2440, but CSR skips from 2420 to 2510 + + { + 2510, + new() { + visit_complete = true, + next_story_progress = 3210, + next_room_id = 223, + next_entrance = 4, + return_to_airship = true, + check_delegate = (r, client, ffx_interop) => { + //ArchipelagoFFXModule.logger.Info("Calm Lands complete"); + } + } + }, // Normally ends at 2440, but CSR skips from 2420 to 2510 + } + } + }, + { RegionEnum.CavernOfTheStolenFayth, new() { story_progress = 2420, room_id = 266, entrance = 0, airship_destination_index = 16 } }, { + RegionEnum.MtGagazet, new() { + story_progress = 2440, room_id = 259, entrance = 0, airship_destination_index = 18, + story_checks = { + { 2680, new() { visit_complete = true, next_story_progress = 3210, next_room_id = 259, next_entrance = 2, return_to_airship = true, check_delegate = (r, client, ffx_interop) => { /* ArchipelagoFFXModule.logger.Info(Mt. Gagazet complete); */ } } }, + } + } + }, { + RegionEnum.ZanarkandRuins, new() { + story_progress = 2680, room_id = 132, entrance = 0, airship_destination_index = 19, + story_checks = { + { 2850, new() { pilgrimage = true } }, + { 2875, new() { visit_complete = true, next_story_progress = 3210, next_room_id = 313, next_entrance = 3, return_to_airship = true, check_delegate = (r, client, ffx_interop) => { /* ArchipelagoFFXModule.logger.Info(Zanarkand Ruins complete); */ } } }, + { 2900, new() { visit_complete = true, next_story_progress = 3210, next_room_id = 313, next_entrance = 3, return_to_airship = true, check_delegate = (r, client, ffx_interop) => { /* ArchipelagoFFXModule.logger.Info(Zanarkand Ruins complete); */ } } }, + } + } + }, { + RegionEnum.Sin, new() { + story_progress = 3125, room_id = 322, entrance = 2, airship_destination_index = 20, + story_checks = { + { + 3400, new() { + visit_complete = true, next_room_id = 322, next_entrance = 2, check_delegate = (r, client, ffx_interop) => { + //ArchipelagoFFXModule.logger.Info("Game Complete"); + foreach (var character in ArchipelagoFFXModule.locked_characters) { + ArchipelagoFFXModule.locked_characters[character.Key] = false; + } + } + } + }, + { 11000, new() { next_story_progress = 3210, next_room_id = 327, next_entrance = 0, check_delegate = (r, client, ffx_interop) => { ffx_interop.call_warp_to_map(382, 0); } } }, + } + } + }, + { RegionEnum.OmegaRuins, new() { story_progress = 3210, room_id = 258, entrance = 2, airship_destination_index = 21 } }, // Story_progress? + { RegionEnum.MonsterArena, new() { story_progress = 3210, room_id = 307, entrance = 0, airship_destination_index = 17 } }, }; public static uint[] airship_destination_addresses = [ @@ -998,25 +1323,32 @@ public unsafe class ArchipelagoRegion { ]; // For battles that don't push/pop but should - public static Dictionary> encounterToPartyDict => new(){ - {"bjyt02_00", [PlySaveId.PC_TIDUS, - PlySaveId.PC_WAKKA, - PlySaveId.PC_RIKKU, - ]}, - {"bjyt02_01", [PlySaveId.PC_TIDUS, - PlySaveId.PC_WAKKA, - PlySaveId.PC_RIKKU, - ]}, - {"lchb07_00", [ // Auron solo - ]}, - {"lchb08_00", [ // Luca post-blitzball sahagins - ]}, + public static Dictionary> encounterToPartyDict => new() { + { + "bjyt02_00", [ + PlySaveId.PC_TIDUS, + PlySaveId.PC_WAKKA, + PlySaveId.PC_RIKKU, + ] + }, { + "bjyt02_01", [ + PlySaveId.PC_TIDUS, + PlySaveId.PC_WAKKA, + PlySaveId.PC_RIKKU, + ] + }, { + "lchb07_00", [ // Auron solo + ] + }, { + "lchb08_00", [ // Luca post-blitzball sahagins + ] + }, }; - public static Dictionary encounterVictoryActions => new() { + public static Dictionary> encounterVictoryActions => new() { // Evrae airship battle //{"hiku15_00", () => { - // ArchipelagoFFXModule.logger.Info("Defeated Evrae. Airship visit 1 complete"); + // /* ArchipelagoFFXModule.logger.Info(Defeated Evrae. Airship visit 1 complete); */ // ArchipelagoFFXModule.region_states[RegionEnum.Airship].story_progress = 2970; // ArchipelagoFFXModule.region_states[RegionEnum.Airship].room_id = 255; // ArchipelagoFFXModule.region_states[RegionEnum.Airship].entrance = 0; @@ -1025,17 +1357,17 @@ public unsafe class ArchipelagoRegion { //}, // Overdrive Sin { - "ssbt03_00", () => { - ArchipelagoFFXModule.logger.Info("Defeated Overdrive Sin. Airship visit 2 complete"); - ArchipelagoFFXModule.region_states[RegionEnum.Airship].story_progress = 3210; - ArchipelagoFFXModule.region_states[RegionEnum.Airship].room_id = 374; - ArchipelagoFFXModule.region_states[RegionEnum.Airship].entrance = 1; - ArchipelagoFFXModule.skip_state_updates = true; + "ssbt03_00", (client, ffx_interop) => { + //ArchipelagoFFXModule.logger.Info("Defeated Overdrive Sin. Airship visit 2 complete"); + ArchipelagoFFXModule.region_states[RegionEnum.Airship].story_progress = 3210; + ArchipelagoFFXModule.region_states[RegionEnum.Airship].room_id = 374; + ArchipelagoFFXModule.region_states[RegionEnum.Airship].entrance = 1; + ArchipelagoFFXModule.skip_state_updates = true; } }, // Yojimbo (Maybe on recruiting Yojimbo instead?) //{"nagi05_10", () => { - // ArchipelagoFFXModule.logger.Info("Defeated Yojimbo. Cavern of the Stolen Fayth visit 1 complete"); + // /* ArchipelagoFFXModule.logger.Info(Defeated Yojimbo. Cavern of the Stolen Fayth visit 1 complete); */ // ArchipelagoFFXModule.region_states[RegionEnum.CavernOfTheStolenFayth].story_progress = 3210; // ArchipelagoFFXModule.region_states[RegionEnum.CavernOfTheStolenFayth].room_id = 56; // ArchipelagoFFXModule.region_states[RegionEnum.CavernOfTheStolenFayth].entrance = 0; @@ -1050,251 +1382,264 @@ public unsafe class ArchipelagoRegion { //} // Bikanel forced Zu fight - {"bika00_10", () => { - lock (FFXArchipelagoClient.client_lock) { - if (FFXArchipelagoClient.is_connected) FFXArchipelagoClient.current_session!.DataStorage[Scope.Slot, "FFX_LOGIC_ZU"] = true; + { + "bika00_10", (client, ffx_interop) => { + lock (client.client_lock) { + if (client.is_connected) client.current_session!.DataStorage[Scope.Slot, "FFX_LOGIC_ZU"] = true; + } } - } }, + }, }; - public static Dictionary encounterEscapeActions => new() { + public static Dictionary> encounterEscapeActions => new() { // Bikanel forced Zu fight - {"bika00_10", () => { - lock (FFXArchipelagoClient.client_lock) { - if (FFXArchipelagoClient.is_connected) FFXArchipelagoClient.current_session!.DataStorage[Scope.Slot, "FFX_LOGIC_ZU"] = true; + { + "bika00_10", (client, ffx_interop) => { + lock (client.client_lock) { + if (client.is_connected) client.current_session!.DataStorage[Scope.Slot, "FFX_LOGIC_ZU"] = true; + } } - } }, - {"mihn02_00", () => { - int boss_id = 8; // Chocobo Eater - if (!FFXArchipelagoClient.local_checked_locations.Contains(boss_id | (long)FFXArchipelagoClient.ArchipelagoLocationType.Boss)) { - if (ArchipelagoFFXModule.item_locations.party_member.TryGetValue(boss_id, out var item)) { - if (FFXArchipelagoClient.sendLocation(boss_id, FFXArchipelagoClient.ArchipelagoLocationType.Boss)) { - ArchipelagoFFXModule.obtain_item(item.id); + }, { + "mihn02_00", (client, ffx_interop) => { + int boss_id = 8; // Chocobo Eater + if (!client.local_checked_locations.Contains(boss_id | (long)ArchipelagoClientModule.ArchipelagoLocationType.Boss)) { + if (ArchipelagoFFXModule.item_locations.party_member.TryGetValue(boss_id, out var item)) { + if (client.sendLocation(boss_id, ArchipelagoClientModule.ArchipelagoLocationType.Boss)) { + ffx_interop.obtain_item(item.id); + } } } } - } }, + }, }; - public static Dictionary encounterToActionDict => new(){ + public static Dictionary> encounterToActionDict => new() { //{"bjyt04_00", ArchipelagoFFXModule.reset_party }, // Klikk (solo Tidus) //{"bjyt04_01", ArchipelagoFFXModule.reset_party }, // Klikk (Tidus + Rikku) // Auron solo - {"lchb07_00", () => ArchipelagoFFXModule.set_party([PlySaveId.PC_AURON], true, false) }, + { "lchb07_00", (client, ffx_interop) => ffx_interop.set_party([ PlySaveId.PC_AURON ], true, false) }, // Yenke and Biran. Can only target Kimahri and scale on his stats. - {"mtgz01_10", () => ArchipelagoFFXModule.set_party([PlySaveId.PC_KIMAHRI], true, true) }, + { "mtgz01_10", (client, ffx_interop) => ffx_interop.set_party([ PlySaveId.PC_KIMAHRI ], true, true) }, // Tutorials // Will softlock without Lulu - {"bsil07_51", () => { - int partyMember_id = 5; // Lulu - if (!FFXArchipelagoClient.local_checked_locations.Contains(partyMember_id | (long)FFXArchipelagoClient.ArchipelagoLocationType.PartyMember)) { - if (ArchipelagoFFXModule.item_locations.party_member.TryGetValue(partyMember_id, out var item)) { - if (FFXArchipelagoClient.sendLocation(partyMember_id, FFXArchipelagoClient.ArchipelagoLocationType.PartyMember)) { - ArchipelagoFFXModule.obtain_item(item.id); + { + "bsil07_51", (client, ffx_interop) => { + int partyMember_id = 5; // Lulu + if (!client.local_checked_locations.Contains(partyMember_id | (long)ArchipelagoClientModule.ArchipelagoLocationType.PartyMember)) { + if (ArchipelagoFFXModule.item_locations.party_member.TryGetValue(partyMember_id, out var item)) { + if (client.sendLocation(partyMember_id, ArchipelagoClientModule.ArchipelagoLocationType.PartyMember)) { + ffx_interop.obtain_item(item.id); + } } } + + ffx_interop.set_party([ PlySaveId.PC_TIDUS, PlySaveId.PC_WAKKA, PlySaveId.PC_LULU ], true, false); } - ArchipelagoFFXModule.set_party([PlySaveId.PC_TIDUS, PlySaveId.PC_WAKKA, PlySaveId.PC_LULU], true, false); - } }, + }, // Yuna is unable to act without an aeon, causing a softlock. - {"bsil05_50", () => { - int partyMember_id = 1; // Yuna - if (!FFXArchipelagoClient.local_checked_locations.Contains(partyMember_id | (long)FFXArchipelagoClient.ArchipelagoLocationType.PartyMember)) { - if (ArchipelagoFFXModule.item_locations.party_member.TryGetValue(partyMember_id, out var item)) { - if (FFXArchipelagoClient.sendLocation(partyMember_id, FFXArchipelagoClient.ArchipelagoLocationType.PartyMember)) { - ArchipelagoFFXModule.obtain_item(item.id); + { + "bsil05_50", (client, ffx_interop) => { + int partyMember_id = 1; // Yuna + if (!client.local_checked_locations.Contains(partyMember_id | (long)ArchipelagoClientModule.ArchipelagoLocationType.PartyMember)) { + if (ArchipelagoFFXModule.item_locations.party_member.TryGetValue(partyMember_id, out var item)) { + if (client.sendLocation(partyMember_id, ArchipelagoClientModule.ArchipelagoLocationType.PartyMember)) { + ffx_interop.obtain_item(item.id); + } } } + + ffx_interop.set_party([ PlySaveId.PC_LULU, PlySaveId.PC_TIDUS, PlySaveId.PC_WAKKA, PlySaveId.PC_YUNA, PlySaveId.PC_VALEFOR ], true, false); } - ArchipelagoFFXModule.set_party([PlySaveId.PC_LULU, PlySaveId.PC_TIDUS, PlySaveId.PC_WAKKA, PlySaveId.PC_YUNA, PlySaveId.PC_VALEFOR], true, false); - } }, + }, // Gui 2 - {"kino03_10", () => { - int partyMember_id = 7; // Seymour - if (!FFXArchipelagoClient.local_checked_locations.Contains(partyMember_id | (long)FFXArchipelagoClient.ArchipelagoLocationType.PartyMember)) { - if (ArchipelagoFFXModule.item_locations.party_member.TryGetValue(partyMember_id, out var item)) { - if (FFXArchipelagoClient.sendLocation(partyMember_id, FFXArchipelagoClient.ArchipelagoLocationType.PartyMember)) { - ArchipelagoFFXModule.obtain_item(item.id); + { + "kino03_10", (client, ffx_interop) => { + int partyMember_id = 7; // Seymour + if (!client.local_checked_locations.Contains(partyMember_id | (long)ArchipelagoClientModule.ArchipelagoLocationType.PartyMember)) { + if (ArchipelagoFFXModule.item_locations.party_member.TryGetValue(partyMember_id, out var item)) { + if (client.sendLocation(partyMember_id, ArchipelagoClientModule.ArchipelagoLocationType.PartyMember)) { + ffx_interop.obtain_item(item.id); + } } } } - } }, + }, // Tidus only gets 1 turn? - {"klyt00_50", () => ArchipelagoFFXModule.set_party([PlySaveId.PC_TIDUS, PlySaveId.PC_KIMAHRI, PlySaveId.PC_LULU], true, false) }, + { "klyt00_50", (client, ffx_interop) => ffx_interop.set_party([ PlySaveId.PC_TIDUS, PlySaveId.PC_KIMAHRI, PlySaveId.PC_LULU ], true, false) }, // Piercing tutorial. Tidus only gets 1 turn. Enemy only attacks 3rd character? - {"mihn00_50", () => ArchipelagoFFXModule.set_party([PlySaveId.PC_TIDUS, PlySaveId.PC_AURON, PlySaveId.PC_WAKKA], true, false) }, + { "mihn00_50", (client, ffx_interop) => ffx_interop.set_party([ PlySaveId.PC_TIDUS, PlySaveId.PC_AURON, PlySaveId.PC_WAKKA ], true, false) }, // Rikku tutorial - {"genk16_50", () => ArchipelagoFFXModule.set_party([PlySaveId.PC_RIKKU], true, false) }, + { "genk16_50", (client, ffx_interop) => ffx_interop.set_party([ PlySaveId.PC_RIKKU ], true, false) }, // Summon fights // Belgemine - {"genk00_40", () => ArchipelagoFFXModule.set_summon_party()}, - {"kino04_40", () => ArchipelagoFFXModule.set_summon_party()}, - {"lmyt01_00", () => ArchipelagoFFXModule.set_summon_party()}, - {"lmyt01_01", () => ArchipelagoFFXModule.set_summon_party()}, - {"lmyt01_02", () => ArchipelagoFFXModule.set_summon_party()}, - {"lmyt01_03", () => ArchipelagoFFXModule.set_summon_party()}, - {"lmyt01_04", () => ArchipelagoFFXModule.set_summon_party()}, - {"lmyt01_05", () => ArchipelagoFFXModule.set_summon_party()}, - {"lmyt01_06", () => ArchipelagoFFXModule.set_summon_party()}, - {"lmyt01_07", () => ArchipelagoFFXModule.set_summon_party()}, - {"mihn00_60", () => ArchipelagoFFXModule.set_summon_party()}, - {"nagi00_40", () => ArchipelagoFFXModule.set_summon_party()}, - {"zzzz00_250", () => ArchipelagoFFXModule.set_summon_party()}, - {"zzzz02_85", () => ArchipelagoFFXModule.set_summon_party()}, + { "genk00_40", (client, ffx_interop) => ffx_interop.set_summon_party() }, + { "kino04_40", (client, ffx_interop) => ffx_interop.set_summon_party() }, + { "lmyt01_00", (client, ffx_interop) => ffx_interop.set_summon_party() }, + { "lmyt01_01", (client, ffx_interop) => ffx_interop.set_summon_party() }, + { "lmyt01_02", (client, ffx_interop) => ffx_interop.set_summon_party() }, + { "lmyt01_03", (client, ffx_interop) => ffx_interop.set_summon_party() }, + { "lmyt01_04", (client, ffx_interop) => ffx_interop.set_summon_party() }, + { "lmyt01_05", (client, ffx_interop) => ffx_interop.set_summon_party() }, + { "lmyt01_06", (client, ffx_interop) => ffx_interop.set_summon_party() }, + { "lmyt01_07", (client, ffx_interop) => ffx_interop.set_summon_party() }, + { "mihn00_60", (client, ffx_interop) => ffx_interop.set_summon_party() }, + { "nagi00_40", (client, ffx_interop) => ffx_interop.set_summon_party() }, + { "zzzz00_250", (client, ffx_interop) => ffx_interop.set_summon_party() }, + { "zzzz02_85", (client, ffx_interop) => ffx_interop.set_summon_party() }, // Isaaru - {"bvyt09_10", () => ArchipelagoFFXModule.set_summon_party()}, - {"bvyt09_11", () => ArchipelagoFFXModule.set_summon_party()}, - {"bvyt09_12", () => ArchipelagoFFXModule.set_summon_party()}, - {"zzzz00_248", () => ArchipelagoFFXModule.set_summon_party()}, + { "bvyt09_10", (client, ffx_interop) => ffx_interop.set_summon_party() }, + { "bvyt09_11", (client, ffx_interop) => ffx_interop.set_summon_party() }, + { "bvyt09_12", (client, ffx_interop) => ffx_interop.set_summon_party() }, + { "zzzz00_248", (client, ffx_interop) => ffx_interop.set_summon_party() }, // Underwater fights // Luca post-blitzball underwater fight - {"lchb08_00", () => { - ArchipelagoFFXModule.set_party([PlySaveId.PC_TIDUS, PlySaveId.PC_WAKKA]); // Only 2. Third character stays in original spot when battle moves forward - } }, + { + "lchb08_00", (client, ffx_interop) => { + ffx_interop.set_party([ PlySaveId.PC_TIDUS, PlySaveId.PC_WAKKA ]); // Only 2. Third character stays in original spot when battle moves forward + } + }, // Extractor. May not work correctly without Yuna? - {"genk09_00", () => { - ArchipelagoFFXModule.set_party([PlySaveId.PC_TIDUS, PlySaveId.PC_WAKKA, PlySaveId.PC_YUNA, PlySaveId.PC_RIKKU]); - } }, + { "genk09_00", (client, ffx_interop) => { ffx_interop.set_party([ PlySaveId.PC_TIDUS, PlySaveId.PC_WAKKA, PlySaveId.PC_YUNA, PlySaveId.PC_RIKKU ]); } }, // Baaj. Should work with 3 - {"bjyt02_00", () => ArchipelagoFFXModule.set_underwater_party()}, - {"bjyt02_01", () => ArchipelagoFFXModule.set_underwater_party()}, - {"bjyt02_02", () => ArchipelagoFFXModule.set_underwater_party()}, + { "bjyt02_00", (client, ffx_interop) => ffx_interop.set_underwater_party() }, + { "bjyt02_01", (client, ffx_interop) => ffx_interop.set_underwater_party() }, + { "bjyt02_02", (client, ffx_interop) => ffx_interop.set_underwater_party() }, // Al Bhed Ship. May only work with 2 - {"cdsp00_00", () => ArchipelagoFFXModule.set_underwater_party()}, - {"cdsp00_01", () => ArchipelagoFFXModule.set_underwater_party()}, - {"cdsp00_02", () => ArchipelagoFFXModule.set_underwater_party()}, - {"cdsp01_00", () => ArchipelagoFFXModule.set_underwater_party()}, - {"cdsp01_01", () => ArchipelagoFFXModule.set_underwater_party()}, - {"cdsp01_02", () => ArchipelagoFFXModule.set_underwater_party()}, // Not confirmed to exist but cdsp01_XX are probably copies of cdsp00_XX - {"cdsp07_00", () => ArchipelagoFFXModule.set_underwater_party()}, - {"cdsp07_01", () => ArchipelagoFFXModule.set_underwater_party()}, + { "cdsp00_00", (client, ffx_interop) => ffx_interop.set_underwater_party() }, + { "cdsp00_01", (client, ffx_interop) => ffx_interop.set_underwater_party() }, + { "cdsp00_02", (client, ffx_interop) => ffx_interop.set_underwater_party() }, + { "cdsp01_00", (client, ffx_interop) => ffx_interop.set_underwater_party() }, + { "cdsp01_01", (client, ffx_interop) => ffx_interop.set_underwater_party() }, + { "cdsp01_02", (client, ffx_interop) => ffx_interop.set_underwater_party() }, // Not confirmed to exist but cdsp01_XX are probably copies of cdsp00_XX + { "cdsp07_00", (client, ffx_interop) => ffx_interop.set_underwater_party() }, + { "cdsp07_01", (client, ffx_interop) => ffx_interop.set_underwater_party() }, // Gagazet. Probably the underwater fights - {"mtgz07_00", () => ArchipelagoFFXModule.set_underwater_party()}, - {"mtgz07_01", () => ArchipelagoFFXModule.set_underwater_party()}, - {"mtgz07_02", () => ArchipelagoFFXModule.set_underwater_party()}, - {"mtgz07_03", () => ArchipelagoFFXModule.set_underwater_party()}, + { "mtgz07_00", (client, ffx_interop) => ffx_interop.set_underwater_party() }, + { "mtgz07_01", (client, ffx_interop) => ffx_interop.set_underwater_party() }, + { "mtgz07_02", (client, ffx_interop) => ffx_interop.set_underwater_party() }, + { "mtgz07_03", (client, ffx_interop) => ffx_interop.set_underwater_party() }, // Via Purifico - {"stbv00_00", () => ArchipelagoFFXModule.set_underwater_party()}, - {"stbv00_01", () => ArchipelagoFFXModule.set_underwater_party()}, - {"stbv00_02", () => ArchipelagoFFXModule.set_underwater_party()}, - {"stbv00_03", () => ArchipelagoFFXModule.set_underwater_party()}, - {"stbv00_04", () => ArchipelagoFFXModule.set_underwater_party()}, - {"stbv00_10", () => ArchipelagoFFXModule.set_underwater_party()}, - {"stbv00_11", () => ArchipelagoFFXModule.set_underwater_party()}, - {"stbv00_12", () => ArchipelagoFFXModule.set_underwater_party()}, + { "stbv00_00", (client, ffx_interop) => ffx_interop.set_underwater_party() }, + { "stbv00_01", (client, ffx_interop) => ffx_interop.set_underwater_party() }, + { "stbv00_02", (client, ffx_interop) => ffx_interop.set_underwater_party() }, + { "stbv00_03", (client, ffx_interop) => ffx_interop.set_underwater_party() }, + { "stbv00_04", (client, ffx_interop) => ffx_interop.set_underwater_party() }, + { "stbv00_10", (client, ffx_interop) => ffx_interop.set_underwater_party() }, + { "stbv00_11", (client, ffx_interop) => ffx_interop.set_underwater_party() }, + { "stbv00_12", (client, ffx_interop) => ffx_interop.set_underwater_party() }, // Besaid with Wakka - {"bsil03_00", () => ArchipelagoFFXModule.set_underwater_party()}, - {"bsil03_01", () => ArchipelagoFFXModule.set_underwater_party()}, - {"bsil03_02", () => ArchipelagoFFXModule.set_underwater_party()}, - {"bsil03_03", () => ArchipelagoFFXModule.set_underwater_party()}, + { "bsil03_00", (client, ffx_interop) => ffx_interop.set_underwater_party() }, + { "bsil03_01", (client, ffx_interop) => ffx_interop.set_underwater_party() }, + { "bsil03_02", (client, ffx_interop) => ffx_interop.set_underwater_party() }, + { "bsil03_03", (client, ffx_interop) => ffx_interop.set_underwater_party() }, // S.S Liki - {"slik02_01", () => ArchipelagoFFXModule.set_underwater_party()}, + { "slik02_01", (client, ffx_interop) => ffx_interop.set_underwater_party() }, // Monster Arena - {"zzzz00_52", () => ArchipelagoFFXModule.set_underwater_party()}, - {"zzzz00_54", () => ArchipelagoFFXModule.set_underwater_party()}, - {"zzzz00_73", () => ArchipelagoFFXModule.set_underwater_party()}, - {"zzzz02_83", () => ArchipelagoFFXModule.set_underwater_party()}, + { "zzzz00_52", (client, ffx_interop) => ffx_interop.set_underwater_party() }, + { "zzzz00_54", (client, ffx_interop) => ffx_interop.set_underwater_party() }, + { "zzzz00_73", (client, ffx_interop) => ffx_interop.set_underwater_party() }, + { "zzzz02_83", (client, ffx_interop) => ffx_interop.set_underwater_party() }, }; - public static Dictionary encounterToLocationDict = new(){ - {"bjyt04_01", [0]}, // Baaj Temple: Klikk Defeated - {"cdsp07_00", [1]}, // Al Bhed Ship: Tros Defeated - {"bsil07_70", [2]}, // Besaid: Dark Valefor - {"slik02_00", [3]}, // S.S. Liki: Sin Fin - {"slik02_01", [4]}, // S.S. Liki: Sinspawn Echuilles - {"klyt00_00", [5]}, // Kilika: Lord Ochu - {"klyt01_00", [6]}, // Kilika: Sinspawn Geneaux - {"cdsp02_00", [7]}, // Luca: Oblitzerator defeated - {"mihn02_00", [8]}, // Mi'Hen Highroad: Chocobo Eater - {"kino02_00", [9]}, // Mushroom Rock Road: Sinspawn Gui 2 - {"kino03_10", [10]}, // Mushroom Rock Road: Sinspawn Gui - {"genk09_00", [12]}, // Moonflow: Extractor - {"kami03_71", [13]}, // Thunder Plains: Dark Ixion - {"mcfr03_00", [14]}, // Macalania Woods: Spherimorph - {"maca02_00", [15]}, // Lake Macalania: Crawler - {"mcyt06_00", [16]}, // Lake Macalania: Seymour/Anima - {"maca02_01", [17]}, // Lake Macalania: Wendigo - {"mcyt00_70", [18]}, // Lake Macalania: Dark Shiva - {"bika03_70", [19]}, // Bikanel: Dark Ifrit - {"hiku15_00", [20]}, // Airship: Evrae - {"ssbt00_00", [21]}, // Airship: Sin Left Fin - {"ssbt01_00", [22]}, // Airship: Sin Right Fin - {"ssbt02_00", [23]}, // Airship: Sinspawn Genais and Core - {"ssbt03_00", [24]}, // Airship: Overdrive Sin - {"hiku15_70", [25]}, // Airship: Penance - {"bvyt09_12", [26]}, // Bevelle: Isaaru (probably?) - {"stbv00_10", [27]}, // Bevelle: Evrae Altana - {"stbv00_11", [27]}, // Bevelle: Evrae Altana - {"stbv00_12", [27]}, // Bevelle: Evrae Altana - {"stbv01_10", [28]}, // Bevelle: Seymour Natus - {"nagi01_00", [29]}, // Calm Lands: Defender X - {"nagi05_74", [31]}, // Cavern of the Stolen Fayth: Dark Yojimbo - {"mtgz01_10", [32]}, // Gagazet (Outside): Biran and Yenke - {"mtgz02_00", [33]}, // Gagazet (Outside): Seymour Flux - {"mtgz01_70", [34]}, // Gagazet (Outside): Dark Anima - {"mtgz08_00", [35]}, // Gagazet: Sanctuary Keeper - {"dome02_00", [36]}, // Zanarkand: Spectral Keeper - {"dome06_00", [37]}, // Zanarkand: Yunalesca - {"dome06_70", [38]}, // Zanarkand: Dark Bahamut - {"sins03_00", [39]}, // Sin: Seymour Omnis - {"sins06_00", [40]}, // Sin: Braska's Final Aeon - {"sins07_0x", [41]}, // Sin: Contest of Aeons - {"sins07_10", [42]}, // Sin: Yu Yevon - {"omeg00_10", [43]}, // Omega Ruins: Ultima Weapon - {"omeg01_10", [44]}, // Omega Ruins: Omega Weapon - {"kino00_70", [45, 46, 47]}, // Dark Mindy, Dark Sandy, Dark Cindy - {"kino01_70", [45, 46, 47]}, // Dark Mindy, Dark Sandy, Dark Cindy - {"kino01_72", [45, 46]}, // Dark Mindy, Dark Sandy - {"kino05_71", [45]}, // Dark Mindy - {"kino05_70", [46]}, // Dark Sandy - {"kino01_71", [47]}, // Dark Cindy - {"bjyt02_02", [48]}, // Geosgaeno - {"zzzz03_00", [49]}, // Stratoavis - {"zzzz03_04", [50]}, // Malboro Menace - {"zzzz03_05", [51]}, // Kottos - {"zzzz03_09", [52]}, // Coeurlregina - {"zzzz03_11", [53]}, // Jormungand - {"zzzz03_14", [54]}, // Cactuar King - {"zzzz03_18", [55]}, // Espada - {"zzzz03_01", [56]}, // Abyss Worm - {"zzzz03_08", [57]}, // Chimerageist - {"zzzz03_17", [58]}, // Don Tonberry - {"zzzz03_07", [59]}, // Catoblepas - {"zzzz03_12", [60]}, // Abaddon - {"zzzz03_15", [61]}, // Vorban - {"zzzz02_94", [62]}, // Fenrir - {"zzzz02_96", [63]}, // Ornitholestes - {"zzzz02_97", [64]}, // Pteryx - {"zzzz02_98", [65]}, // Hornet - {"zzzz02_93", [66]}, // Vidatu - {"zzzz02_99", [67]}, // One-Eye - {"zzzz02_95", [68]}, // Jumbo Flan - {"zzzz03_06", [69]}, // Nega Elemental - {"zzzz02_92", [70]}, // Tanket - {"zzzz03_03", [71]}, // Fafnir - {"zzzz03_16", [72]}, // Sleep Sprout - {"zzzz03_13", [73]}, // Bomb King - {"zzzz03_02", [74]}, // Juggernaut - {"zzzz03_10", [75]}, // Ironclad - {"zzzz02_79", [76]}, // Earth Eater - {"zzzz02_81", [77]}, // Greater Sphere - {"zzzz02_77", [78]}, // Catastrophe - {"zzzz02_82", [79]}, // Th'uban - {"zzzz00_105", [80]}, // Neslug - {"zzzz02_80", [81]}, // Ultima Buster - {"zzzz02_83", [82]}, // Shinryu - {"zzzz02_76", [83]}, // Monster Arena: Nemesis + public static Dictionary encounterToLocationDict = new() { + { "bjyt04_01", [ 0 ] }, // Baaj Temple: Klikk Defeated + { "cdsp07_00", [ 1 ] }, // Al Bhed Ship: Tros Defeated + { "bsil07_70", [ 2 ] }, // Besaid: Dark Valefor + { "slik02_00", [ 3 ] }, // S.S. Liki: Sin Fin + { "slik02_01", [ 4 ] }, // S.S. Liki: Sinspawn Echuilles + { "klyt00_00", [ 5 ] }, // Kilika: Lord Ochu + { "klyt01_00", [ 6 ] }, // Kilika: Sinspawn Geneaux + { "cdsp02_00", [ 7 ] }, // Luca: Oblitzerator defeated + { "mihn02_00", [ 8 ] }, // Mi'Hen Highroad: Chocobo Eater + { "kino02_00", [ 9 ] }, // Mushroom Rock Road: Sinspawn Gui 2 + { "kino03_10", [ 10 ] }, // Mushroom Rock Road: Sinspawn Gui + { "genk09_00", [ 12 ] }, // Moonflow: Extractor + { "kami03_71", [ 13 ] }, // Thunder Plains: Dark Ixion + { "mcfr03_00", [ 14 ] }, // Macalania Woods: Spherimorph + { "maca02_00", [ 15 ] }, // Lake Macalania: Crawler + { "mcyt06_00", [ 16 ] }, // Lake Macalania: Seymour/Anima + { "maca02_01", [ 17 ] }, // Lake Macalania: Wendigo + { "mcyt00_70", [ 18 ] }, // Lake Macalania: Dark Shiva + { "bika03_70", [ 19 ] }, // Bikanel: Dark Ifrit + { "hiku15_00", [ 20 ] }, // Airship: Evrae + { "ssbt00_00", [ 21 ] }, // Airship: Sin Left Fin + { "ssbt01_00", [ 22 ] }, // Airship: Sin Right Fin + { "ssbt02_00", [ 23 ] }, // Airship: Sinspawn Genais and Core + { "ssbt03_00", [ 24 ] }, // Airship: Overdrive Sin + { "hiku15_70", [ 25 ] }, // Airship: Penance + { "bvyt09_12", [ 26 ] }, // Bevelle: Isaaru (probably?) + { "stbv00_10", [ 27 ] }, // Bevelle: Evrae Altana + { "stbv00_11", [ 27 ] }, // Bevelle: Evrae Altana + { "stbv00_12", [ 27 ] }, // Bevelle: Evrae Altana + { "stbv01_10", [ 28 ] }, // Bevelle: Seymour Natus + { "nagi01_00", [ 29 ] }, // Calm Lands: Defender X + { "nagi05_74", [ 31 ] }, // Cavern of the Stolen Fayth: Dark Yojimbo + { "mtgz01_10", [ 32 ] }, // Gagazet (Outside): Biran and Yenke + { "mtgz02_00", [ 33 ] }, // Gagazet (Outside): Seymour Flux + { "mtgz01_70", [ 34 ] }, // Gagazet (Outside): Dark Anima + { "mtgz08_00", [ 35 ] }, // Gagazet: Sanctuary Keeper + { "dome02_00", [ 36 ] }, // Zanarkand: Spectral Keeper + { "dome06_00", [ 37 ] }, // Zanarkand: Yunalesca + { "dome06_70", [ 38 ] }, // Zanarkand: Dark Bahamut + { "sins03_00", [ 39 ] }, // Sin: Seymour Omnis + { "sins06_00", [ 40 ] }, // Sin: Braska's Final Aeon + { "sins07_0x", [ 41 ] }, // Sin: Contest of Aeons + { "sins07_10", [ 42 ] }, // Sin: Yu Yevon + { "omeg00_10", [ 43 ] }, // Omega Ruins: Ultima Weapon + { "omeg01_10", [ 44 ] }, // Omega Ruins: Omega Weapon + { "kino00_70", [ 45, 46, 47 ] }, // Dark Mindy, Dark Sandy, Dark Cindy + { "kino01_70", [ 45, 46, 47 ] }, // Dark Mindy, Dark Sandy, Dark Cindy + { "kino01_72", [ 45, 46 ] }, // Dark Mindy, Dark Sandy + { "kino05_71", [ 45 ] }, // Dark Mindy + { "kino05_70", [ 46 ] }, // Dark Sandy + { "kino01_71", [ 47 ] }, // Dark Cindy + { "bjyt02_02", [ 48 ] }, // Geosgaeno + { "zzzz03_00", [ 49 ] }, // Stratoavis + { "zzzz03_04", [ 50 ] }, // Malboro Menace + { "zzzz03_05", [ 51 ] }, // Kottos + { "zzzz03_09", [ 52 ] }, // Coeurlregina + { "zzzz03_11", [ 53 ] }, // Jormungand + { "zzzz03_14", [ 54 ] }, // Cactuar King + { "zzzz03_18", [ 55 ] }, // Espada + { "zzzz03_01", [ 56 ] }, // Abyss Worm + { "zzzz03_08", [ 57 ] }, // Chimerageist + { "zzzz03_17", [ 58 ] }, // Don Tonberry + { "zzzz03_07", [ 59 ] }, // Catoblepas + { "zzzz03_12", [ 60 ] }, // Abaddon + { "zzzz03_15", [ 61 ] }, // Vorban + { "zzzz02_94", [ 62 ] }, // Fenrir + { "zzzz02_96", [ 63 ] }, // Ornitholestes + { "zzzz02_97", [ 64 ] }, // Pteryx + { "zzzz02_98", [ 65 ] }, // Hornet + { "zzzz02_93", [ 66 ] }, // Vidatu + { "zzzz02_99", [ 67 ] }, // One-Eye + { "zzzz02_95", [ 68 ] }, // Jumbo Flan + { "zzzz03_06", [ 69 ] }, // Nega Elemental + { "zzzz02_92", [ 70 ] }, // Tanket + { "zzzz03_03", [ 71 ] }, // Fafnir + { "zzzz03_16", [ 72 ] }, // Sleep Sprout + { "zzzz03_13", [ 73 ] }, // Bomb King + { "zzzz03_02", [ 74 ] }, // Juggernaut + { "zzzz03_10", [ 75 ] }, // Ironclad + { "zzzz02_79", [ 76 ] }, // Earth Eater + { "zzzz02_81", [ 77 ] }, // Greater Sphere + { "zzzz02_77", [ 78 ] }, // Catastrophe + { "zzzz02_82", [ 79 ] }, // Th'uban + { "zzzz00_105", [ 80 ] }, // Neslug + { "zzzz02_80", [ 81 ] }, // Ultima Buster + { "zzzz02_83", [ 82 ] }, // Shinryu + { "zzzz02_76", [ 83 ] }, // Monster Arena: Nemesis //{"kino00_70", 45}, {"kino01_70", 45}, {"kino01_72", 45}, {"kino05_71", 45}, // Dark Mindy @@ -1315,7 +1660,7 @@ public unsafe class ArchipelagoRegion { 0x3172248B, // ffx_us_voice20: "Sometimes, when I got a lot on my mind" 0x4BC8C5CB, // ffx_us_voice_btl: "Who did that!?" 0x57EA548B, // ffx_us_voice_btl: "Guardians should fight, not think." + Rikku response - ]; + ]; public static string[] other_item_names = [ // Gear Customizations (0 - 7C) @@ -1522,35 +1867,34 @@ public unsafe class ArchipelagoRegion { "Aeon Customization: LCK +1: 1x Fortune Sphere", "Aeon Customization: EVA +1: 1x Speed Sphere", "Aeon Customization: ACC +1: 1x Speed Sphere", - ]; + ]; - public static Dictionary overdrive_names = new Dictionary() - { - {PlayerCommandId.PCOM_SPIRAL_CUT, "Swordplay: Spiral Cut" }, - {PlayerCommandId.PCOM_SLICE_AND_DICE, "Swordplay: Slice & Dice" }, - {PlayerCommandId.PCOM_ENERGY_RAIN, "Swordplay: Energy Rain" }, - {PlayerCommandId.PCOM_BLITZ_ACE, "Swordplay: Blitz Ace" }, - {PlayerCommandId.PCOM_SHOOTING_STAR, "Bushido: Shooting Star" }, - {PlayerCommandId.PCOM_DRAGON_FANG, "Bushido: Dragon Fang" }, - {PlayerCommandId.PCOM_BANISHING_BLADE, "Bushido: Banishing Blade" }, - {PlayerCommandId.PCOM_TORNADO, "Bushido: Tornado" }, - {PlayerCommandId.PCOM_JUMP, "Ronso Rage: Jump" }, - {PlayerCommandId.PCOM_FIRE_BREATH, "Ronso Rage: Fire Breath" }, - {PlayerCommandId.PCOM_SEED_CANNON, "Ronso Rage: Seed Cannon" }, - {PlayerCommandId.PCOM_SELF_DESTRUCT, "Ronso Rage: Self-Destruct" }, - {PlayerCommandId.PCOM_THRUST_KICK, "Ronso Rage: Thrust Kick" }, - {PlayerCommandId.PCOM_STONE_BREATH, "Ronso Rage: Stone Breath" }, - {PlayerCommandId.PCOM_AQUA_BREATH, "Ronso Rage: Aqua Breath" }, - {PlayerCommandId.PCOM_DOOM, "Ronso Rage: Doom" }, - {PlayerCommandId.PCOM_WHITE_WIND, "Ronso Rage: White Wind" }, - {PlayerCommandId.PCOM_BAD_BREATH, "Ronso Rage: Bad Breath" }, - {PlayerCommandId.PCOM_MIGHTY_GUARD, "Ronso Rage: Might Guard" }, - {PlayerCommandId.PCOM_NOVA, "Ronso Rage: Nova" }, - {PlayerCommandId.PCOM_ELEMENT_REELS, "Slots: Element Reels" }, - {PlayerCommandId.PCOM_ATTACK_REELS, "Slots: Attack Reels" }, - {PlayerCommandId.PCOM_STATUS_REELS, "Slots: Status Reels" }, - {PlayerCommandId.PCOM_AUROCHS_REELS, "Slots: Aurochs Reels" }, - {PlayerCommandId.PCOM_REQUIEM, "Overdrive: Requiem" }, - {PlayerCommandId.PCOM_ENERGY_BLAST, "Overdrive: Energy Blast" }, + public static Dictionary overdrive_names = new Dictionary() { + { PlayerCommandId.PCOM_SPIRAL_CUT, "Swordplay: Spiral Cut" }, + { PlayerCommandId.PCOM_SLICE_AND_DICE, "Swordplay: Slice & Dice" }, + { PlayerCommandId.PCOM_ENERGY_RAIN, "Swordplay: Energy Rain" }, + { PlayerCommandId.PCOM_BLITZ_ACE, "Swordplay: Blitz Ace" }, + { PlayerCommandId.PCOM_SHOOTING_STAR, "Bushido: Shooting Star" }, + { PlayerCommandId.PCOM_DRAGON_FANG, "Bushido: Dragon Fang" }, + { PlayerCommandId.PCOM_BANISHING_BLADE, "Bushido: Banishing Blade" }, + { PlayerCommandId.PCOM_TORNADO, "Bushido: Tornado" }, + { PlayerCommandId.PCOM_JUMP, "Ronso Rage: Jump" }, + { PlayerCommandId.PCOM_FIRE_BREATH, "Ronso Rage: Fire Breath" }, + { PlayerCommandId.PCOM_SEED_CANNON, "Ronso Rage: Seed Cannon" }, + { PlayerCommandId.PCOM_SELF_DESTRUCT, "Ronso Rage: Self-Destruct" }, + { PlayerCommandId.PCOM_THRUST_KICK, "Ronso Rage: Thrust Kick" }, + { PlayerCommandId.PCOM_STONE_BREATH, "Ronso Rage: Stone Breath" }, + { PlayerCommandId.PCOM_AQUA_BREATH, "Ronso Rage: Aqua Breath" }, + { PlayerCommandId.PCOM_DOOM, "Ronso Rage: Doom" }, + { PlayerCommandId.PCOM_WHITE_WIND, "Ronso Rage: White Wind" }, + { PlayerCommandId.PCOM_BAD_BREATH, "Ronso Rage: Bad Breath" }, + { PlayerCommandId.PCOM_MIGHTY_GUARD, "Ronso Rage: Might Guard" }, + { PlayerCommandId.PCOM_NOVA, "Ronso Rage: Nova" }, + { PlayerCommandId.PCOM_ELEMENT_REELS, "Slots: Element Reels" }, + { PlayerCommandId.PCOM_ATTACK_REELS, "Slots: Attack Reels" }, + { PlayerCommandId.PCOM_STATUS_REELS, "Slots: Status Reels" }, + { PlayerCommandId.PCOM_AUROCHS_REELS, "Slots: Aurochs Reels" }, + { PlayerCommandId.PCOM_REQUIEM, "Overdrive: Requiem" }, + { PlayerCommandId.PCOM_ENERGY_BLAST, "Overdrive: Energy Blast" }, }; } diff --git a/src/delegates/capture_delegates.cs b/src/delegates/capture_delegates.cs index 71cab5a..5efa11c 100644 --- a/src/delegates/capture_delegates.cs +++ b/src/delegates/capture_delegates.cs @@ -8,7 +8,7 @@ namespace ArchipelagoFFX; -public unsafe partial class CaptureModule : FhModule { +public unsafe partial class CaptureModule { [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate bool MsMonsterCapture(int target_id, int arena_idx); private const nint __addr_MsMonsterCapture = 0x390B80; diff --git a/src/gui/debugWindow.cs b/src/gui/debugWindow.cs index 749dbb8..009bafe 100644 --- a/src/gui/debugWindow.cs +++ b/src/gui/debugWindow.cs @@ -22,57 +22,55 @@ namespace ArchipelagoFFX.GUI; -public unsafe static class ArchipelagoGUI { - public delegate void OnRenderDelegate(); - +public unsafe class ArchipelagoGuiModule : FhModule { public const ImGuiKey archipelago_gui_key = ImGuiKey.F8; public const ImGuiKey experimental_gui_key = ImGuiKey.F9; - public static bool enabled = false; - public static bool experiments_enabled = false; - private static bool show = true; + public bool enabled = false; + public bool experiments_enabled = false; + private bool show = true; public const string DEFAULT_CLIENT_ADDRESS = "archipelago.gg:"; - public static string client_input_address = DEFAULT_CLIENT_ADDRESS; - public static string client_input_name = ""; - private static string client_input_password = ""; + public string client_input_address = DEFAULT_CLIENT_ADDRESS; + public string client_input_name = ""; + private string client_input_password = ""; private static string client_input_command = ""; - public static readonly System.Threading.Lock client_log_lock = new(); - private static List> client_log = []; - public static bool client_log_updated = false; - private static float previous_scroll = 1; - private static float previous_scroll_max = 1; + public readonly System.Threading.Lock client_log_lock = new(); + private List> client_log = []; + public bool client_log_updated = false; + private float previous_scroll = 1; + private float previous_scroll_max = 1; private static readonly Vector2 PANE_BUTTON_SIZE = new Vector2(16f); - private static int grav_mode = 1; - private static int field_mode = 0; - private static int motion_type = 0; + private int grav_mode = 1; + private int field_mode = 0; + private int motion_type = 0; - private static int character_model = 0; + private int character_model = 0; - private static int[] MsBtlGetPosParams = [0, 0, 0]; - private static Vector4 MsBtlGetPosResult = new(0, 0, 0, 0); - private static uint LaunchBattleInput = 0; + private int[] MsBtlGetPosParams = [0, 0, 0]; + private Vector4 MsBtlGetPosResult = new(0, 0, 0, 0); + private uint LaunchBattleInput = 0; - private static int auto_ability_id = 0; - private static AutoAbility* ability = null; - private static int chr_id = 0; - private static Equipment* weapon = null; - private static Equipment* armor = null; + private int auto_ability_id = 0; + private AutoAbility* ability = null; + private int chr_id = 0; + private Equipment* weapon = null; + private Equipment* armor = null; - private static int clickedNodeIndex = -1; + private int clickedNodeIndex = -1; - public static int selected_seed; + public int selected_seed; - public static int font_size = -1; + public int font_size = -1; - private static bool show_popup; - public static string popup_content { + private bool show_popup; + public string popup_content { get; set { field = value; @@ -80,7 +78,35 @@ public static string popup_content { } } - public static void render() { + private FhModuleHandle _client_handle; + private ArchipelagoClientModule? _client; + + private FhModuleHandle _ffx_interop_handle; + private ArchipelagoFFXModule? _ffx_interop; + + private FhModuleHandle _deathlink_handle; + private DeathLinkModule? _deathlink; + + private FhModuleHandle _hardcore_dreams_end_handle; + private HardcoreDreamsEndModule? _hardcore_dreams_end; + + public ArchipelagoGuiModule() { + _client_handle = new(this); + _ffx_interop_handle = new(this); + _hardcore_dreams_end_handle = new(this); + _deathlink_handle = new(this); + } + + public override bool init(FhModContext mod_context, FileStream global_state_file) { + shiori_file = mod_context.Paths.ResourcesDir.GetFiles("shiori.png").FirstOrDefault(); + + return _client_handle.try_get_module(out _client) + && _ffx_interop_handle.try_get_module(out _ffx_interop) + && _hardcore_dreams_end_handle.try_get_module(out _hardcore_dreams_end) + && _deathlink_handle.try_get_module(out _deathlink); + } + + public override void render_imgui() { //ImGui.ShowDebugLogWindow(); //ImGui.ShowStyleEditor(); @@ -90,6 +116,7 @@ public static void render() { //ImGui.PushStyleColor(ImGuiCol.WindowBg, new Vector4 { X = 0.5f, Y = 0.5f, Z = 0.5f }); //ImGui.PushStyleVar(ImGuiStyleVar.WindowRounding, 0f); //ImGui.PushStyleVar(ImGuiStyleVar.WindowBorderSize, 0f); + if (font_size == -1) font_size = (int)ImGui.GetFontSize(); ImGui.PushFont(null, font_size); @@ -104,6 +131,7 @@ public static void render() { } render_client(); + #if DEBUG render_experiments(); //render_clusters(); @@ -116,14 +144,14 @@ public static void render() { //ImGui.PopStyleColor(); } - public static FileInfo? shiori_file; - private static FhTexture? shiori_image; + public FileInfo? shiori_file; + private FhTexture? shiori_image; - private static int voiceline_id; - public static byte voice_lang = 0xFF; - public static byte text_lang = 0xFF; + private int voiceline_id; + public byte voice_lang = 0xFF; + public byte text_lang = 0xFF; - private static void render_experiments() { + private void render_experiments() { experiments_enabled ^= ImGui.IsKeyPressed(experimental_gui_key); if (!experiments_enabled) return; @@ -133,38 +161,22 @@ private static void render_experiments() { float frameHeight = ImGui.GetFrameHeight(); Vector2 windowPos = ImGui.GetWindowPos(); float windowBorderSize = ImGui.GetStyle().WindowBorderSize; - //if (shiori_image != null) ImGui.GetForegroundDrawList().AddImage(shiori_image.TextureRef, windowPos + new Vector2(windowBorderSize), new(windowPos.X + frameHeight - windowBorderSize, windowPos.Y + frameHeight - windowBorderSize)); + if (shiori_image?.try_use(out ImTextureRef texture_ref, out _) ?? false) { - ImGui.GetForegroundDrawList() - .AddImage( - texture_ref, - windowPos + new Vector2(windowBorderSize), - new( - windowPos.X + frameHeight - windowBorderSize, - windowPos.Y + frameHeight - windowBorderSize - ) - ); + Vector2 image_tl = windowPos + new Vector2(windowBorderSize); + Vector2 image_br = windowPos + new Vector2(frameHeight) - new Vector2(windowBorderSize); + + ImGui.GetForegroundDrawList().AddImage(texture_ref, image_tl, image_br); } - //Span tidus_name = new Span(Globals.save_data->character_names[0].raw, 20); - //byte[] tidus_decoded = new byte[FhEncoding.compute_decode_buffer_size(tidus_name)]; - // - //int decoded_length = FhEncoding.decode(tidus_name, tidus_decoded); - //string tidus_string = Encoding.UTF8.GetString(tidus_decoded, 0, decoded_length); - //fixed (byte* name_string = tidus_decoded) { - // if (ImGui.InputText("Tidus Name", ref tidus_string, 19, ImGuiInputTextFlags.EnterReturnsTrue)) { - // string final_string = tidus_string + "{END}"; - // FhEncoding.encode(Encoding.UTF8.GetBytes(final_string), tidus_name); - // } - //} - if (ImGui.Checkbox($"Original soundtrack?", &save_data->soundtrack_type)) { - var soundtrack_callback = FhUtil.get_fptr(__addr_FUN_008cc120); + if (ImGui.Checkbox("Original soundtrack?", &save_data->soundtrack_type)) { + var soundtrack_callback = FhUtil.get_fptr(__addr_FUN_008cc120); soundtrack_callback(save_data->soundtrack_type ? 1 : 0); } - ImGui.InputScalarN("frontline? (0x1FC5)", ImGuiDataType.U8, Globals.Battle.btl->__0x1FC5, 7); - ImGui.InputScalarN("frontline? (0x1FCC)", ImGuiDataType.U8, Globals.Battle.btl->__0x1FCC, 7); - ImGui.InputScalarN("backline? (0x1FD3)", ImGuiDataType.U8, Globals.Battle.btl->__0x1FD3, 17); + ImGui.InputScalarN("frontline? (0x1FC5)", ImGuiDataType.U8, Battle.btl->__0x1FC5, 7); + ImGui.InputScalarN("frontline? (0x1FCC)", ImGuiDataType.U8, Battle.btl->__0x1FCC, 7); + ImGui.InputScalarN("backline? (0x1FD3)", ImGuiDataType.U8, Battle.btl->__0x1FD3, 17); @@ -203,7 +215,7 @@ private static void render_experiments() { // ImGui.Image(shiori_image.TextureRef, new(shiori_image.Metadata.width, shiori_image.Metadata.height)); //} - ImGui.Text($"Tidus overdrive uses: {Globals.save_data->tidus_limit_uses}"); + ImGui.Text($"Tidus overdrive uses: {save_data->tidus_limit_uses}"); //for (int i = 0; i < 18; i++) { // string name = Globals.save_data->character_names[i].name; @@ -214,16 +226,15 @@ private static void render_experiments() { ImGui.InputInt("Voiceline id", ref voiceline_id); if (ImGui.Button("Play voiceline")) { - queued_voice_lines.Enqueue(voiceline_id); + _ffx_interop!.queued_voice_lines.Enqueue(voiceline_id); } int inMenu = FhUtil.get_at(0x01efb4d4); ImGui.Text($"Is in menu?: {inMenu}"); + BtlArea* pos_def_ptr = Battle.btl->ptr_pos_def; - BtlArea* pos_def_ptr = Globals.Battle.btl->ptr_pos_def; - - if (pos_def_ptr != null && Globals.Battle.btl->battle_state != 0) { + if (pos_def_ptr != null && Battle.btl->battle_state != 0) { BtlAreasHelper areas = new(pos_def_ptr); //BtlAreas areas = *pos_def_ptr; @@ -375,142 +386,17 @@ private static void render_experiments() { //if (ImGui.InputText("Name Test", ref tidusName, 20)) { // Globals.save_data->character_names[0].name = tidusName; //} - } - ImGui.End(); - - return; - - if (Globals.SphereGrid.lpamng == null) return; - - if (!ImGui.Begin("Archipelago###Archipelago.Experiments.GUI")) { - ImGui.End(); - return; - } - - if (ImGui.Button("Activate all nodes for all characters")) { - for (int i = 0; i < Globals.SphereGrid.lpamng->node_count; i++) { - Globals.SphereGrid.lpamng->nodes[i].activated_by = 0x7f; - } - } - - //if (ImGui.InputScalar("Selected node:", ImGuiDataType.U32, (nint)(&Globals.SphereGrid.lpamng->selected_node_idx))) { - // Globals.SphereGrid.lpamng->cam_desired_pos.X = Globals.SphereGrid.lpamng->nodes[Globals.SphereGrid.lpamng->selected_node_idx].x; - // Globals.SphereGrid.lpamng->cam_desired_pos.Y = Globals.SphereGrid.lpamng->nodes[Globals.SphereGrid.lpamng->selected_node_idx].y; - //} - var camDesiredPos = Globals.SphereGrid.lpamng->cam_desired_pos; - //ImGui.Text($"desired pos: {camDesiredPos.X}, {camDesiredPos.Y}, {camDesiredPos.Z}, {camDesiredPos.W}"); - - - int selectedNodeIndex = Globals.SphereGrid.lpamng->selected_node_idx; - SphereGridNode selectedNode = Globals.SphereGrid.lpamng->nodes[selectedNodeIndex]; - - //ImGui.Text($"Selected node: {selectedNodeIndex}, pos: ({selectedNode.x}, {selectedNode.y}), type: {(NodeType)selectedNode.node_type}"); - - Matrix4x4* world_matrix = (Matrix4x4*)(*FhUtil.ptr_at(0x8cb9d8) + 0xd34); - //if (ImGui.CollapsingHeader("World Matrix")) { - // ImGui.InputScalarN($"x", ImGuiDataType.Float, (nint)(&world_matrix->M11), 4); - // ImGui.InputScalarN($"y", ImGuiDataType.Float, (nint)(&world_matrix->M21), 4); - // ImGui.InputScalarN($"z", ImGuiDataType.Float, (nint)(&world_matrix->M31), 4); - // ImGui.InputScalarN($"w", ImGuiDataType.Float, (nint)(&world_matrix->M41), 4); - //} - Vector4* temp = (Vector4*)(&world_matrix->M11); - - var mousePos = ImGui.GetMousePos(); - //ImGui.Text($"Mouse pos: {mousePos.X}, {mousePos.Y}"); - var centeredPos = mousePos - (ImGui.GetWindowViewport().Size * 0.5f); - //ImGui.Text($"Centered mouse pos: {centeredPos.X}, {centeredPos.Y}"); - - // Doesn't work - //float tiltRatio = Globals.SphereGrid.lpamng->tilt_level switch { - // SphereGridTilt.FarTilt => 1.40625f, - // SphereGridTilt.SlightTilt => 1.125f, - // _ => 1, - //}; - - float main_x = 2560; - float main_y = 1440; - float x_ratio = main_x / ImGui.GetWindowViewport().Size.X; - float y_ratio = x_ratio * (3.0f/4.0f); - var gridPos = new Vector2(centeredPos.X * x_ratio, centeredPos.Y * y_ratio); - //ImGui.Text($"Grid mouse pos: {gridPos.X}, {gridPos.Y}"); - float zoom_mult = Globals.SphereGrid.lpamng->zoom_level.get_zoom(); - var absPos = new Vector2(-gridPos.X / zoom_mult + world_matrix->M31, -gridPos.Y / zoom_mult + world_matrix->M32); - //ImGui.Text($"Absolute mouse pos: {absPos.X}, {absPos.Y}"); - - // Adjusts the center offset - //float tiltAdjustment = Globals.SphereGrid.lpamng->tilt_level switch { - // SphereGridTilt.FarTilt => 855.801f, - // SphereGridTilt.SlightTilt => 455.475f, - // _ => 0, - //}; - var truePos = new Vector2((absPos.X ) / -3.75f, (absPos.Y ) / -2.8125f); - //ImGui.Text($"True mouse pos: {truePos.X}, {truePos.Y}"); - - // Only bother if flat - int closestNodeIndex = -1; - if (Globals.SphereGrid.lpamng->tilt_level == SphereGridTilt.FLAT) { - float shortestDistance = 20; - for (int i = 0; i < 1024; i++) { - float distance = (new Vector2(Globals.SphereGrid.lpamng->nodes[i].x, Globals.SphereGrid.lpamng->nodes[i].y) - truePos).Length(); - if (distance < shortestDistance) { - closestNodeIndex = i; - shortestDistance = distance; - } - } - if (closestNodeIndex != -1) { - SphereGridNode closestNode = Globals.SphereGrid.lpamng->nodes[closestNodeIndex]; - //ImGui.Text($"Hovered node: {closestNodeIndex}, pos: ({closestNode.x}, {closestNode.y}), type: {(NodeType)closestNode.node_type}"); - - } - if (!ImGui.GetIO().WantCaptureMouse && ImGui.IsMouseReleased(ImGuiMouseButton.Left)) { - clickedNodeIndex = closestNodeIndex; - } - } - - if (clickedNodeIndex != -1) { - SphereGridNode* clickedNode = &Globals.SphereGrid.lpamng->nodes[clickedNodeIndex]; - ImGui.Text($"Clicked node: {clickedNodeIndex}, pos: ({clickedNode->x}, {clickedNode->y}), type: {(NodeType)clickedNode->node_type}"); - NodeType[] typeArray = Enum.GetValues(); - //ImGui.ListBox("Node type", clickedNode->node_type, typeArray, typeArray.Length); - if (ImGui.BeginListBox("Node type")) { - for (int i = 0; i < typeArray.Length; i++) { - bool is_selected = (typeArray[i] == clickedNode->node_type); - if (ImGui.Selectable($"{typeArray[i]}")) { - clickedNode->node_type = typeArray[i]; - Globals.SphereGrid.lpamng->should_update = 1; - Globals.SphereGrid.lpamng->should_update_node = clickedNodeIndex; - } - if (is_selected) { - ImGui.SetItemDefaultFocus(); - } - } - ImGui.EndListBox(); - } - - for (int i = 0; i < 7; i++) { - if (ImGui.Button($"{id_to_character[i]}: {(clickedNode->activated_by & (1 << i)) != 0}")) { - clickedNode->activated_by ^= (byte)(1 << i); - ArchipelagoFFXModule.h_eiAbmParaGet(); - Globals.SphereGrid.lpamng->should_update = 1; - // Setting to clickedNodeIndex only turns off light if no character has it activated. Setting to -1 correctly turns on/off node itself, but not surrounding lights (per character). - Globals.SphereGrid.lpamng->should_update_node = -1; - } - } - } - - - ImGui.End(); } - private static void render_sphere_grid_editor() { + private void render_sphere_grid_editor() { ImGuiStylePtr style = ImGui.GetStyle(); if (ImGui.Button("Activate all nodes for all characters")) { - for (int i = 0; i < Globals.SphereGrid.lpamng->node_count; i++) { - Globals.SphereGrid.lpamng->nodes[i].activated_by = 0x7f; + for (int i = 0; i < SphereGrid.lpamng->node_count; i++) { + SphereGrid.lpamng->nodes[i].activated_by = 0x7f; } } @@ -523,23 +409,23 @@ private static void render_sphere_grid_editor() { float x_ratio = main_x / ImGui.GetWindowViewport().Size.X; float y_ratio = x_ratio * (3.0f/4.0f); var gridPos = new Vector2(centeredPos.X * x_ratio, centeredPos.Y * y_ratio); - float zoom_mult = Globals.SphereGrid.lpamng->zoom_level.get_zoom(); + float zoom_mult = SphereGrid.lpamng->zoom_level.get_zoom(); var absPos = new Vector2(-gridPos.X / zoom_mult + world_matrix->M31, -gridPos.Y / zoom_mult + world_matrix->M32); var truePos = new Vector2((absPos.X ) / -3.75f, (absPos.Y ) / -2.8125f); // Only bother if flat int closestNodeIndex = -1; - if (Globals.SphereGrid.lpamng->tilt_level == SphereGridTilt.FLAT) { + if (SphereGrid.lpamng->tilt_level == SphereGridTilt.FLAT) { float shortestDistance = 20; for (int i = 0; i < 1024; i++) { - float distance = (new Vector2(Globals.SphereGrid.lpamng->nodes[i].x, Globals.SphereGrid.lpamng->nodes[i].y) - truePos).Length(); + float distance = (new Vector2(SphereGrid.lpamng->nodes[i].x, SphereGrid.lpamng->nodes[i].y) - truePos).Length(); if (distance < shortestDistance) { closestNodeIndex = i; shortestDistance = distance; } } if (closestNodeIndex != -1) { - SphereGridNode closestNode = Globals.SphereGrid.lpamng->nodes[closestNodeIndex]; + SphereGridNode closestNode = SphereGrid.lpamng->nodes[closestNodeIndex]; } if (!ImGui.GetIO().WantCaptureMouse && ImGui.IsMouseReleased(ImGuiMouseButton.Left)) { @@ -548,16 +434,16 @@ private static void render_sphere_grid_editor() { } if (clickedNodeIndex != -1) { - SphereGridNode* clickedNode = &Globals.SphereGrid.lpamng->nodes[clickedNodeIndex]; - ImGui.Text($"Clicked node: {clickedNodeIndex}, pos: ({clickedNode->x}, {clickedNode->y}), type: {(NodeType)clickedNode->node_type}"); + SphereGridNode* clickedNode = &SphereGrid.lpamng->nodes[clickedNodeIndex]; + ImGui.Text($"Clicked node: {clickedNodeIndex}, pos: ({clickedNode->x}, {clickedNode->y}), type: {clickedNode->node_type}"); NodeType[] typeArray = Enum.GetValues(); if (ImGui.BeginListBox("Node type")) { for (int i = 0; i < typeArray.Length - 1; i++) { bool is_selected = (typeArray[i] == clickedNode->node_type); if (ImGui.Selectable($"{typeArray[i]}")) { clickedNode->node_type = typeArray[i]; - Globals.SphereGrid.lpamng->should_update = 1; - Globals.SphereGrid.lpamng->should_update_node = clickedNodeIndex; + SphereGrid.lpamng->should_update = 1; + SphereGrid.lpamng->should_update_node = clickedNodeIndex; } if (is_selected) { ImGui.SetItemDefaultFocus(); @@ -569,59 +455,58 @@ private static void render_sphere_grid_editor() { for (int i = 0; i < 7; i++) { if (ImGui.Button($"{id_to_character[i]}: {(clickedNode->activated_by & (1 << i)) != 0}")) { clickedNode->activated_by ^= (byte)(1 << i); - ArchipelagoFFXModule.h_eiAbmParaGet(); - Globals.SphereGrid.lpamng->should_update = 1; + FhUtil.get_fptr(Fahrenheit.FFX.FhCall.__addr_eiAbmParaGet)(); + SphereGrid.lpamng->should_update = 1; // Setting to clickedNodeIndex only turns off light if no character has it activated. Setting to -1 correctly turns on/off node itself, but not surrounding lights (per character). - Globals.SphereGrid.lpamng->should_update_node = -1; + SphereGrid.lpamng->should_update_node = -1; } } } } - private static void render_connection() { - if (seed.Options.SeedId is null && !FFXArchipelagoClient.is_connected) { - string[] seedNames = [.. ArchipelagoFFXModule.loaded_seeds.Select(x => x.Name)]; + private void render_connection() { + if (seed.Options.SeedId is null && !(_client!.is_connected)) { + string[] seedNames = [.. loaded_seeds.Select(x => x.Name)]; if (ImGui.Combo("Selected seed", ref selected_seed, seedNames, seedNames.Length)) { - ArchipelagoFFXModule.ArchipelagoSeed seed = ArchipelagoFFXModule.loaded_seeds[selected_seed]; + ArchipelagoSeed seed = loaded_seeds[selected_seed]; client_input_name = seed.Options.PlayerName; - if (ArchipelagoFFXModule.SeedToServer.TryGetValue(seed.Options.SeedId, out string? server)) { + if (SeedToServer.TryGetValue(seed.Options.SeedId, out string? server)) { client_input_address = server; } else { - ArchipelagoGUI.client_input_address = ArchipelagoGUI.DEFAULT_CLIENT_ADDRESS; + client_input_address = DEFAULT_CLIENT_ADDRESS; } } } else { ImGui.Text($"Loaded seed: {seed.Name}"); } - if (!FFXArchipelagoClient.is_connected) { + if (!(_client!.is_connected)) { ImGui.InputText("Address", ref client_input_address, 50); ImGui.InputText("Name", ref client_input_name, 50); ImGui.InputText("Password", ref client_input_password, 50); if (ImGui.Button("Connect")) { //Task.Run(() => FFXArchipelagoClient.Connect(client_input_address, client_input_name, client_input_password)); - _ = FFXArchipelagoClient.Connect(client_input_address, client_input_name, client_input_password); + _ = _client!.Connect(client_input_address, client_input_name, client_input_password); //FFXArchipelagoClient.Connect(client_input_address, client_input_name, client_input_password); } } else { - ImGui.Text($"Connected as {FFXArchipelagoClient.active_player?.Name}"); + ImGui.Text($"Connected as {_client!.active_player?.Name}"); if (ImGui.Button("Disconnect")) { - FFXArchipelagoClient.disconnect(); + _client!.disconnect(); } } } - public static void add_log_message(List<(string, Color)> message) { + public void add_log_message(List<(string, Color)> message) { lock (client_log_lock) { client_log.Add(message); client_log_updated = true; } } - private static LinkedList client_input_history = new(); - private static LinkedListNode? client_input_history_current = null; - private static ImGuiInputTextCallback _client_input_ImGuiInputTextCallback = client_input_ImGuiInputTextCallback; - private static bool focus_client_input = false; - private static int client_input_ImGuiInputTextCallback(ImGuiInputTextCallbackData* data) { + private LinkedList client_input_history = new(); + private LinkedListNode? client_input_history_current; + private bool focus_client_input; + private int client_input_ImGuiInputTextCallback(ImGuiInputTextCallbackData* data) { if (data->EventFlag == ImGuiInputTextFlags.CallbackHistory) { if (data->EventKey == ImGuiKey.UpArrow) { if (client_input_history_current is null && client_input_history.First is not null) { @@ -634,7 +519,6 @@ private static int client_input_ImGuiInputTextCallback(ImGuiInputTextCallbackDat data->InsertChars(0, client_input_history_current.Value); } } else if (data->EventKey == ImGuiKey.DownArrow) { - client_input_history_current = client_input_history_current?.Previous; data->DeleteChars(0, data->BufTextLen); if (client_input_history_current is not null) { @@ -642,9 +526,11 @@ private static int client_input_ImGuiInputTextCallback(ImGuiInputTextCallbackDat } } } + return 0; } - private static void render_console() { + + private void render_console() { ImGuiStylePtr style = ImGui.GetStyle(); if (ImGui.BeginChild("Archipelago.GUI.Log", new(0, ImGui.GetContentRegionAvail().Y - ImGui.GetTextLineHeight() - 3 * style.ItemSpacing.Y), ImGuiChildFlags.Borders, ImGuiWindowFlags.NoMove)) { //var curr_scroll = ImGui.GetScrollY() / previous_scroll_max; @@ -693,11 +579,14 @@ private static void render_console() { ImGui.SetKeyboardFocusHere(); focus_client_input = false; } - bool process_input = ImGui.InputText("Input", - ref client_input_command, - 150, - ImGuiInputTextFlags.EnterReturnsTrue | ImGuiInputTextFlags.CallbackHistory, - _client_input_ImGuiInputTextCallback); + + bool process_input = ImGui.InputText( + "Input", + ref client_input_command, + 150, + ImGuiInputTextFlags.EnterReturnsTrue | ImGuiInputTextFlags.CallbackHistory, + client_input_ImGuiInputTextCallback + ); if (process_input && client_input_command.Length > 0) { client_input_history.AddFirst(client_input_command); @@ -710,199 +599,197 @@ private static void render_console() { if (!client_input_command.StartsWith("/")) { // Say - FFXArchipelagoClient.SayAsync(client_input_command); + _client!.SayAsync(client_input_command); } else { // Client-side command string[] cmd = client_input_command.Split(" "); + Action cmd_fn = parse_command(cmd); - Action fn = cmd switch { - ["/resetregion", string regionString] => () => { - ArchipelagoData.RegionEnum region = stringToRegion(regionString); - if (region != ArchipelagoData.RegionEnum.None) { - ArchipelagoFFXModule.region_states[region].story_progress = region_starting_state[region].story_progress; - ArchipelagoFFXModule.region_states[region].room_id = region_starting_state[region].room_id; - ArchipelagoFFXModule.region_states[region].entrance = region_starting_state[region].entrance; - region_starting_state[region].savedata.CopyTo(ArchipelagoFFXModule.region_states[region].savedata); + cmd_fn(); + client_log_updated = true; + } + client_input_command = ""; + } + } - List<(string, Color)> message = [(region.ToString(), Color.Blue), (" has been reset", Color.White)]; - add_log_message(message); - } - else { - List<(string, Color)> message = [("invalid region: ", Color.Red), (regionString, Color.Blue)]; - add_log_message(message); - } - } - , - ["/resetregion", ..] => () => { - List<(string, Color)> message = [("Wrong arguments for '/resetregion': Should be ", Color.Red), ($"/resetregion regionName", Color.Blue)]; - add_log_message(message); - } - , -#if DEBUG - ["/setdatastorage", string key, string value] => () => { - lock (FFXArchipelagoClient.client_lock) { - if (FFXArchipelagoClient.is_connected) { - FFXArchipelagoClient.current_session!.DataStorage[Scope.Slot, "FFX_ROOM"] = value; - } + private Action parse_command(string[] command) { + return command switch { + ["/resetregion", { } region_name] => () => { + RegionEnum region = stringToRegion(region_name); + if (region != RegionEnum.None) { + ArchipelagoRegion region_state = region_states[region]; + region_state.story_progress = region_starting_state[region].story_progress; + region_state.room_id = region_starting_state[region].room_id; + region_state.entrance = region_starting_state[region].entrance; + region_starting_state[region].savedata.CopyTo(region_state.savedata); + + List<(string, Color)> message = [(region.ToString(), Color.Blue), (" has been reset", Color.White)]; + add_log_message(message); + } + else { + List<(string, Color)> message = [("invalid region: ", Color.Red), (region_name, Color.Blue)]; + add_log_message(message); + } + }, - } - } - , - ["/getdatastorage", string key] => () => { - lock (FFXArchipelagoClient.client_lock) { - if (FFXArchipelagoClient.is_connected) { - string? message_text = FFXArchipelagoClient.current_session!.DataStorage[Scope.Slot, key]; - if (message_text != null) { - List<(string, Color)> message = [(key, Color.Blue), (message_text, Color.White)]; - add_log_message(message); - } - } - } - } - , - ["/setregion", string regionString, string progressString, string mapString, string entranceString] => () => { - ArchipelagoData.RegionEnum region = stringToRegion(regionString); - if (region != ArchipelagoData.RegionEnum.None) { - if (ushort.TryParse(progressString, out ushort progress)) { - if (ushort.TryParse(mapString, out ushort map)) { - if (ushort.TryParse(entranceString, out ushort entrance)) { - ArchipelagoData.ArchipelagoRegion r = ArchipelagoFFXModule.region_states[region]; - r.story_progress = progress; - r.room_id = map; - r.entrance = entrance; - - List<(string, Color)> message = [(region.ToString(), Color.Blue), ($"'s state has been set to (story_progress: {progress}, room_id: {map}, entrance: {entrance})", Color.White)]; - add_log_message(message); - } - else { - List<(string, Color)> message = [("invalid entrance_id: ", Color.Red), (entranceString, Color.Blue)]; - add_log_message(message); - } - } - else{ - List<(string, Color)> message = [("invalid map_id: ", Color.Red), (mapString, Color.Blue)]; - add_log_message(message); - } + ["/resetregion", ..] => () => { + List<(string, Color)> message = [("Wrong arguments for '/resetregion': Should be ", Color.Red), ("/resetregion regionName", Color.Blue)]; + add_log_message(message); + }, - } - else { - List<(string, Color)> message = [("invalid story_progress: ", Color.Red), (progressString, Color.Blue)]; - add_log_message(message); - } +#if DEBUG + ["/setdatastorage", { } key, { } value] => () => { + lock (_client!.client_lock) { + if (_client!.is_connected) { + _client!.current_session!.DataStorage[Scope.Slot, key] = value; + } - } - else { - List<(string, Color)> message = [("invalid region: ", Color.Red), (regionString, Color.Blue)]; + } + }, + + ["/getdatastorage", { } key] => () => { + lock (_client!.client_lock) { + if (_client!.is_connected) { + string? message_text = _client!.current_session!.DataStorage[Scope.Slot, key]; + if (message_text != null) { + List<(string, Color)> message = [(key, Color.Blue), (message_text, Color.White)]; add_log_message(message); } } - , - ["/setregion", ..] => () => { - List<(string, Color)> message = [("Wrong arguments for '/setregion': Should be ", Color.Red), ($"/setregion regionName story_progress map_id entrance_id", Color.Blue)]; - add_log_message(message); - } - , - ["/warp", string map, string entrance] => () => { - if (int.TryParse(map, out int map_id)) { - if (int.TryParse(entrance, out int entrance_id)) { - List<(string, Color)> message = [("Warping to ", Color.White), ($"{map_id} (entrance {entrance_id})", Color.Blue)]; + } + }, + + ["/setregion", { } regionString, { } progressString, { } mapString, { } entranceString] => () => { + RegionEnum region = stringToRegion(regionString); + if (region != RegionEnum.None) { + if (ushort.TryParse(progressString, out ushort progress)) { + if (ushort.TryParse(mapString, out ushort map)) { + if (ushort.TryParse(entranceString, out ushort entrance)) { + ArchipelagoRegion region_state = region_states[region]; + region_state.story_progress = progress; + region_state.room_id = map; + region_state.entrance = entrance; + + List<(string, Color)> message = [(region.ToString(), Color.Blue), ($"'s state has been set to (story_progress: {progress}, room_id: {map}, entrance: {entrance})", Color.White)]; add_log_message(message); - ArchipelagoFFXModule.call_warp_to_map(map_id, entrance_id); - } - else { - List<(string, Color)> message = [("invalid entrance_id: ", Color.Red), (entrance, Color.Blue)]; + } else { + List<(string, Color)> message = [("invalid entrance_id: ", Color.Red), (entranceString, Color.Blue)]; add_log_message(message); } - } - else { - List<(string, Color)> message = [("invalid map_id: ", Color.Red), (map, Color.Blue)]; + } else { + List<(string, Color)> message = [("invalid map_id: ", Color.Red), (mapString, Color.Blue)]; add_log_message(message); } - } - , - ["/warp", ..] => () => { - List<(string, Color)> message = [("Wrong arguments for /warp: Should be ", Color.Red), ($"/warp map_id entrance_id", Color.Blue)]; + } else { + List<(string, Color)> message = [("invalid story_progress: ", Color.Red), (progressString, Color.Blue)]; add_log_message(message); } - , -#endif - ["/send_checks"] => () => { - FFXArchipelagoClient.local_locations_updated = true; + } else { + List<(string, Color)> message = [("invalid region: ", Color.Red), (regionString, Color.Blue)]; + add_log_message(message); + } + }, - List<(string, Color)> message = [("Resending local checks", Color.White)]; + ["/setregion", ..] => () => { + List<(string, Color)> message = [("Wrong arguments for '/setregion': Should be ", Color.Red), ("/setregion regionName story_progress map_id entrance_id", Color.Blue)]; + add_log_message(message); + }, + + ["/warp", { } map, { } entrance] => () => { + if (int.TryParse(map, out int map_id)) { + if (int.TryParse(entrance, out int entrance_id)) { + List<(string, Color)> message = [("Warping to ", Color.White), ($"{map_id} (entrance {entrance_id})", Color.Blue)]; + add_log_message(message); + _ffx_interop!.call_warp_to_map(map_id, entrance_id); + } else { + List<(string, Color)> message = [("invalid entrance_id: ", Color.Red), (entrance, Color.Blue)]; add_log_message(message); } - , - ["/clear"] => () => { - lock (client_log_lock) { - client_log.Clear(); - } - } - , - ["/help"] => () => { - add_log_message([("Available commands:", Color.White)]); + } else { + List<(string, Color)> message = [("invalid map_id: ", Color.Red), (map, Color.Blue)]; + add_log_message(message); + } + }, + + ["/warp", ..] => () => { + List<(string, Color)> message = [("Wrong arguments for /warp: Should be ", Color.Red), ($"/warp map_id entrance_id", Color.Blue)]; + add_log_message(message); + }, +#endif + + ["/send_checks"] => () => { + _client!.local_locations_updated = true; + + List<(string, Color)> message = [("Resending local checks", Color.White)]; + add_log_message(message); + }, + + ["/clear"] => () => { + lock (client_log_lock) { + client_log.Clear(); + } + }, + + ["/help"] => () => { + add_log_message([("Available commands:", Color.White)]); #if DEBUG - add_log_message([("/setregion regionName progress map entrance", Color.White)]); + add_log_message([("/setdatastorage key value", Color.White)]); + add_log_message([("/getdatastorage key", Color.White)]); + add_log_message([("/warp map entrance", Color.White)]); + add_log_message([("/setregion regionName progress map entrance", Color.White)]); #endif - add_log_message([("/resetregion regionName", Color.White)]); - add_log_message([("/send_checks", Color.White)]); - add_log_message([("/clear", Color.White)]); - } - , - _ => () => { - List<(string, Color)> message = [("unknown command: ", Color.Red), (client_input_command, Color.Blue)]; - add_log_message(message); - } - }; - fn(); - client_log_updated = true; + add_log_message([("/resetregion regionName", Color.White)]); + add_log_message([("/send_checks", Color.White)]); + add_log_message([("/clear", Color.White)]); + }, + + _ => () => { + List<(string, Color)> message = [("unknown command: ", Color.Red), (client_input_command, Color.Blue)]; + add_log_message(message); } - client_input_command = ""; - } + }; } - private static void render_debug_tab() { + private void render_debug_tab() { #if DEBUG - fixed (int* ap_mult = &ArchipelagoFFXModule.ap_multiplier) { + fixed (int* ap_mult = &ap_multiplier) { uint step = 1; uint step_fast = 10; ImGui.InputScalar("AP multiplier", ImGuiDataType.U32, ap_mult, &step, &step_fast); } #endif - ImGui.Text($"Current room: {Globals.save_data->current_room_id} ({Marshal.PtrToStringAnsi((nint)ArchipelagoFFXModule.get_event_name(*(uint*)Globals.event_id))!})"); - ImGui.Text($"Current region: {ArchipelagoFFXModule.current_region}"); - ImGui.Text($"Current story progress: {Globals.save_data->story_progress}"); - if (ArchipelagoFFXModule.current_region != ArchipelagoData.RegionEnum.None) { - foreach (var data in ArchipelagoFFXModule.region_states[current_region].savedata) { + ImGui.Text($"Current room: {save_data->current_room_id} ({Marshal.PtrToStringAnsi((nint)get_event_name(*(uint*)event_id))!})"); + ImGui.Text($"Current region: {current_region}"); + ImGui.Text($"Current story progress: {save_data->story_progress}"); + if (current_region != RegionEnum.None) { + foreach (var data in region_states[current_region].savedata) { ImGui.Text($"{data.offset}: {string.Join(" ", data.bytes.Select(b => b.ToString()).ToArray())}"); } } ImGui.SeparatorText("Region states"); if (ImGui.BeginTable("Region states", 5)) { + ImGui.TableSetupColumn("Region"); ImGui.TableSetupColumn("story_progress"); ImGui.TableSetupColumn("room"); ImGui.TableSetupColumn("entrance"); ImGui.TableSetupColumn("completed_visits"); ImGui.TableHeadersRow(); - foreach (var region in ArchipelagoFFXModule.region_states) { - ImGui.TableNextColumn(); - ImGui.Text($"{region.Key}"); - ImGui.TableNextColumn(); - ImGui.Text($"{region.Value.story_progress}"); - ImGui.TableNextColumn(); - ImGui.Text($"{region.Value.room_id}"); - ImGui.TableNextColumn(); - ImGui.Text($"{region.Value.entrance}"); - ImGui.TableNextColumn(); - ImGui.Text($"{region.Value.completed_visits}"); + + foreach (var region in region_states) { + ImGui.TableNextColumn(); ImGui.Text($"{region.Key}"); + ImGui.TableNextColumn(); ImGui.Text($"{region.Value.story_progress}"); + ImGui.TableNextColumn(); ImGui.Text($"{region.Value.room_id}"); + ImGui.TableNextColumn(); ImGui.Text($"{region.Value.entrance}"); + ImGui.TableNextColumn(); ImGui.Text($"{region.Value.completed_visits}"); } + ImGui.EndTable(); } - if (Globals.Battle.btl->battle_state != 0) { + if (Battle.btl->battle_state != 0) { ImGui.Text($"Battle Name: {Marshal.PtrToStringAnsi((nint)FhUtil.ptr_at(0xD2C25A))}"); } else { #if DEBUG @@ -912,7 +799,7 @@ private static void render_debug_tab() { ImGui.InputScalar("launchBattleInput", ImGuiDataType.U32, battle_input, &p_step, &p_step_fast, "%x"); } if (ImGui.Button("launchBattleButton")) { - ArchipelagoFFXModule._MsBattleLabelExe(LaunchBattleInput, 1, 1); + _MsBattleLabelExe(LaunchBattleInput, 1, 1); } #endif } @@ -944,16 +831,16 @@ private static void render_unlocks() { ImGui.SetCursorPosX((ImGui.GetWindowWidth() - ImGui.CalcTextSize(s).X) * 0.5f); ImGui.Text(s); if (ImGui.BeginTable("Region Unlocks", 3)) { - foreach (var (region, i) in ArchipelagoFFXModule.region_is_unlocked.Select((value, i) => (value, i))) { + foreach (var (region, i) in region_is_unlocked.Select((value, i) => (value, i))) { ImGui.TableNextColumn(); Color color = region.Value ? Color.Green : Color.Red; ImGui.PushStyleColor(ImGuiCol.Text, new Vector4(color.R / 255f, color.G / 255f, color.B / 255f, 1.0f)); #if !DEBUG ImGui.BeginDisabled(); #endif - bool unlocked = ArchipelagoFFXModule.region_is_unlocked[region.Key]; + bool unlocked = region_is_unlocked[region.Key]; if (ImGui.Checkbox($"###Archipelago.GUI.Unlocks.{region.Key}", &unlocked)) { - ArchipelagoFFXModule.region_is_unlocked[region.Key] = unlocked; + region_is_unlocked[region.Key] = unlocked; } #if !DEBUG ImGui.EndDisabled(); @@ -969,16 +856,16 @@ private static void render_unlocks() { ImGui.SetCursorPosX((ImGui.GetWindowWidth() - ImGui.CalcTextSize(s).X) * 0.5f); ImGui.Text(s); if (ImGui.BeginTable("Character Unlocks", 3)) { - foreach (var (character, i) in ArchipelagoFFXModule.unlocked_characters.Select((value, i) => (value, i))) { + foreach (var (character, i) in unlocked_characters.Select((value, i) => (value, i))) { ImGui.TableNextColumn(); Color color = character.Value ? Color.Green : Color.Red; ImGui.PushStyleColor(ImGuiCol.Text, new Vector4(color.R / 255f, color.G / 255f, color.B / 255f, 1.0f)); #if !DEBUG ImGui.BeginDisabled(); #endif - bool unlocked = ArchipelagoFFXModule.unlocked_characters[character.Key]; + bool unlocked = unlocked_characters[character.Key]; if (ImGui.Checkbox($"###Archipelago.GUI.Unlocks.{id_to_character[character.Key]}", &unlocked)) { - ArchipelagoFFXModule.unlocked_characters[character.Key] = unlocked; + unlocked_characters[character.Key] = unlocked; } #if !DEBUG ImGui.EndDisabled(); @@ -995,7 +882,7 @@ private static void render_unlocks() { } } - private static void render_settings() { + private void render_settings() { ImGui.SliderInt("Font size", ref font_size, 10, 60); if (ImGui.BeginCombo("Voice", voice_lang == 0xFF ? "Default" : ((FhLangId)voice_lang).ToString())) { @@ -1026,34 +913,34 @@ private static void render_settings() { ImGui.Checkbox("Show Recent Items", ref RecentItemsModule.show_recent_items); if (ImGui.Button("Save settings")) { - ArchipelagoFFXModule.VoiceLanguage = voice_lang != 0xFF ? (FhLangId)voice_lang : null; - ArchipelagoFFXModule.TextLanguage = text_lang != 0xFF ? (FhLangId)text_lang : null; - ArchipelagoFFXModule.save_global_state(); + VoiceLanguage = voice_lang != 0xFF ? (FhLangId)voice_lang : null; + TextLanguage = text_lang != 0xFF ? (FhLangId)text_lang : null; + _ffx_interop!.save_global_state(); } ImGui.SeparatorText("Save-Local Settings"); ImGui.Indent(); - if (ArchipelagoFFXModule.seed.Options.SeedId is null) { + if (seed.Options.SeedId is null) { ImGui.Text("Please load a save to display these settings."); ImGui.Unindent(); return; } - bool hardcore_contest = HardcoreDreamsEndModule.get_enabled(); + bool hardcore_contest = _hardcore_dreams_end!.get_enabled(); ImGui.Checkbox("Enable Hardcore Dream's End", ref hardcore_contest); - HardcoreDreamsEndModule.set_enabled(hardcore_contest); + _hardcore_dreams_end!.set_enabled(hardcore_contest); - bool deathlink = DeathLinkModule.get_enabled(); + bool deathlink = _deathlink!.get_enabled(); ImGui.Checkbox("Enable Deathlink", ref deathlink); - DeathLinkModule.set_enabled(deathlink); + _deathlink!.set_enabled(deathlink); - ImGui.Text($"Deathlinks Queued: {DeathLinkModule.get_deathlinks_queued()}"); + ImGui.Text($"Deathlinks Queued: {_deathlink!.get_deathlinks_queued()}"); - string deathlink_send_type = DeathLinkModule.get_send_type(); + string deathlink_send_type = _deathlink!.get_send_type(); if (ImGui.BeginCombo("Deathlink Send Type", deathlink_send_type)) { foreach (DeathLinkModule.DeathLinkSendType type in Enum.GetValues()) { - string type_name = DeathLinkModule.get_send_type_name(type); + string type_name = _deathlink!.get_send_type_name(type); if (ImGui.Selectable(type_name, type_name == deathlink_send_type)) { deathlink_send_type = type_name; } @@ -1061,12 +948,12 @@ private static void render_settings() { ImGui.EndCombo(); } - DeathLinkModule.set_send_type(deathlink_send_type); + _deathlink!.set_send_type(deathlink_send_type); - string deathlink_receive_type = DeathLinkModule.get_receive_type(); + string deathlink_receive_type = _deathlink!.get_receive_type(); if (ImGui.BeginCombo("Deathlink Receive Type", deathlink_receive_type)) { foreach (DeathLinkModule.DeathLinkReceiveType type in Enum.GetValues()) { - string type_name = DeathLinkModule.get_receive_type_name(type); + string type_name = _deathlink!.get_receive_type_name(type); if (ImGui.Selectable(type_name, type_name == deathlink_receive_type)) { deathlink_receive_type = type_name; } @@ -1074,22 +961,22 @@ private static void render_settings() { ImGui.EndCombo(); } - DeathLinkModule.set_receive_type(deathlink_receive_type); + _deathlink!.set_receive_type(deathlink_receive_type); #if DEBUG if (ImGui.Button("Receive Debug Deathlink")) { - DeathLinkModule.debug_add_queued(); + _deathlink!.debug_add_queued(); } if (ImGui.Button("Apply Deathlink")) { - DeathLinkModule.debug_apply_deathlink(); + _deathlink!.debug_apply_deathlink(); } #endif ImGui.Unindent(); } - private static void render_client() { + private void render_client() { enabled ^= ImGui.IsKeyPressed(archipelago_gui_key); if (!enabled) return; ImGuiStylePtr style = ImGui.GetStyle(); @@ -1120,7 +1007,7 @@ private static void render_client() { } else { foreach ((uint item_id, int amount) in excess_inventory) { if (amount == 0) continue; - string item_name = get_item_name(item_id); + string item_name = _ffx_interop!.get_item_name(item_id); ImGui.Text($"{item_name}: {amount}"); } } @@ -1129,7 +1016,7 @@ private static void render_client() { ImGui.Text("Empty"); } else { foreach ((uint item_id, int amount) in other_inventory) { - string item_name = get_other_item_name(item_id); + string item_name = _ffx_interop!.get_other_item_name(item_id); ImGui.Text($"{item_name}: {amount}"); } } @@ -1146,7 +1033,7 @@ private static void render_client() { } #if DEBUG - if (Globals.SphereGrid.lpamng != null && *Globals.SphereGrid.is_open && ImGui.BeginTabItem("Sphere Grid###Archipelago.GUI.TabBar.SphereGrid")) { + if (SphereGrid.lpamng != null && *SphereGrid.is_open && ImGui.BeginTabItem("Sphere Grid###Archipelago.GUI.TabBar.SphereGrid")) { render_sphere_grid_editor(); ImGui.EndTabItem(); } @@ -1162,5 +1049,4 @@ private static void render_client() { ImGui.End(); } - } diff --git a/src/gui/recent_items.cs b/src/gui/recent_items.cs index c5cbcb5..56b0cff 100644 --- a/src/gui/recent_items.cs +++ b/src/gui/recent_items.cs @@ -290,7 +290,8 @@ public override void render_imgui() { } // Set up Archipelago's font size - int font_size = ArchipelagoGUI.font_size; + //TODO: Access Archipelago's font size instead of always defaulting + int font_size = -1; if (font_size == -1) font_size = (int)ImGui.GetFontSize(); ImGui.PushFont(null, font_size); diff --git a/src/gui/toast.cs b/src/gui/toast.cs index 0fdbf32..8d3273d 100644 --- a/src/gui/toast.cs +++ b/src/gui/toast.cs @@ -275,7 +275,8 @@ public override void render_imgui() { #endif // Set up Archipelago's font size - int font_size = ArchipelagoGUI.font_size; + //TODO: Access Archipelago's font size instead of always defaulting + int font_size = -1; if (font_size == -1) font_size = (int)ImGui.GetFontSize(); ImGui.PushFont(null, font_size); diff --git a/src/hooks.cs b/src/hooks.cs index d90a75a..4108ae5 100644 --- a/src/hooks.cs +++ b/src/hooks.cs @@ -18,7 +18,6 @@ using static Fahrenheit.FFX.Globals; using static ArchipelagoFFX.ArchipelagoData; -using static ArchipelagoFFX.Client.FFXArchipelagoClient; using static ArchipelagoFFX.delegates; using Color = Archipelago.MultiClient.Net.Models.Color; using FhCall = Fahrenheit.FFX.FhCall; @@ -31,24 +30,24 @@ public unsafe partial class ArchipelagoFFXModule { // AtelEventSetUp - private static FhMethodHandle _AtelEventSetUp; + private static FhMethodHandle _AtelEventSetUp; - public static char* get_event_name(uint event_id) => FhUtil.get_fptr(0x4796e0)(event_id); - public static int atel_stack_pop(int* param_1, AtelStack* atelStack) => FhUtil.get_fptr(0x0046de90)(param_1, atelStack); + public static char* get_event_name(uint event_id) => FhUtil.get_fptr(0x4796e0)(event_id); + public static int atel_stack_pop(int* param_1, AtelStack* atelStack) => FhUtil.get_fptr(0x0046de90)(param_1, atelStack); - private static FhMethodHandle _Common_obtainTreasureInit; - private static FhMethodHandle _Common_obtainTreasureSilentlyInit; - private static FhMethodHandle _Common_isBrotherhoodUnpoweredRetInt; - private static FhMethodHandle _Common_upgradeBrotherhoodRetInt; - private static FhMethodHandle _Common_obtainBrotherhoodRetInt; + private static FhMethodHandle _Common_obtainTreasureInit; + private static FhMethodHandle _Common_obtainTreasureSilentlyInit; + private static FhMethodHandle _Common_isBrotherhoodUnpoweredRetInt; + private static FhMethodHandle _Common_upgradeBrotherhoodRetInt; + private static FhMethodHandle _Common_obtainBrotherhoodRetInt; //private static FhMethodHandle _Common_grantCelestialUpgrade; - private static FhMethodHandle _Common_setPrimerCollected; - private static FhMethodHandle _Common_transitionToMap; - private static FhMethodHandle _Common_warpToMap; + private static FhMethodHandle _Common_setPrimerCollected; + private static FhMethodHandle _Common_transitionToMap; + private static FhMethodHandle _Common_warpToMap; - private static FhMethodHandle _TkSetLegendAbility; + private static FhMethodHandle _TkSetLegendAbility; - private static FhMethodHandle _SgEvent_showModularMenuInit; + private static FhMethodHandle _SgEvent_showModularMenuInit; //private static FhMethodHandle _Common_playFieldVoiceLineInit; //private static FhMethodHandle _Common_playFieldVoiceLineExec; @@ -56,61 +55,61 @@ public unsafe partial class ArchipelagoFFXModule { - private static delegates.Common_playFieldVoiceLineInit _Common_playFieldVoiceLineInit; - private static delegates.Common_playFieldVoiceLineExec _Common_playFieldVoiceLineExec; - private static delegates.Common_playFieldVoiceLineResultInt _Common_playFieldVoiceLineResultInt; + private static Common_playFieldVoiceLineInit _Common_playFieldVoiceLineInit; + private static Common_playFieldVoiceLineExec _Common_playFieldVoiceLineExec; + private static Common_playFieldVoiceLineResultInt _Common_playFieldVoiceLineResultInt; - private static delegates.Common_00D6Init _Common_00D6Init; - private static delegates.Common_00D6Exec _Common_00D6Exec; - private static delegates.Common_00D6ResultInt _Common_00D6ResultInt; + private static Common_00D6Init _Common_00D6Init; + private static Common_00D6Exec _Common_00D6Exec; + private static Common_00D6ResultInt _Common_00D6ResultInt; // Common.01D1Init - private static delegates.Common_01D1Init _Common_01D1Init; + private static Common_01D1Init _Common_01D1Init; // Common.01D1Exec - private static delegates.Common_01D1Exec _Common_01D1Exec; + private static Common_01D1Exec _Common_01D1Exec; - private static FhMethodHandle _Common_addPartyMember; - private static FhMethodHandle _Common_removePartyMember; - private static FhMethodHandle _Common_removePartyMemberLongTerm; - private static FhMethodHandle _Common_setWeaponVisibilty; - private static FhMethodHandle _Common_putPartyMemberInSlot; + private static FhMethodHandle _Common_addPartyMember; + private static FhMethodHandle _Common_removePartyMember; + private static FhMethodHandle _Common_removePartyMemberLongTerm; + private static FhMethodHandle _Common_setWeaponVisibilty; + private static FhMethodHandle _Common_putPartyMemberInSlot; - private static FhMethodHandle _Common_pushParty; - private static FhMethodHandle _Common_popParty; + private static FhMethodHandle _Common_pushParty; + private static FhMethodHandle _Common_popParty; // getCurrentPartySlots - private static FhMethodHandle _MsGetSavePartyMember; + private static FhMethodHandle _MsGetSavePartyMember; // Battle releated - private static delegates.MsBtlListGroup _MsBtlListGroup; - private static FhMethodHandle _MsBattleExe; + private static MsBtlListGroup _MsBtlListGroup; + private static FhMethodHandle _MsBattleExe; - public static delegates.MsBattleLabelExe _MsBattleLabelExe; - private static FhMethodHandle _FUN_00791820; + public static MsBattleLabelExe _MsBattleLabelExe; + private static FhMethodHandle _FUN_00791820; - private static FhMethodHandle _MsBtlGetPos; + private static FhMethodHandle _MsBtlGetPos; - private static FhMethodHandle _MsBtlReadSetScene; + private static FhMethodHandle _MsBtlReadSetScene; // giveItem - private static FhMethodHandle _FUN_007905a0; + private static FhMethodHandle _FUN_007905a0; // giveKeyItem // takeGil // readFromBin - private static FhMethodHandle _FUN_007ab890; + private static FhMethodHandle _FUN_007ab890; // getWeaponName - private static FhMethodHandle _FUN_007a0d10; + private static FhMethodHandle _FUN_007a0d10; // getWeaponModel - private static FhMethodHandle _FUN_007a0c70; + private static FhMethodHandle _FUN_007a0c70; // obtainTreasureCleanup - private static FhMethodHandle _FUN_007993f0; + private static FhMethodHandle _FUN_007993f0; - private static delegates.MsGetChr _MsGetChr; + private static MsGetChr _MsGetChr; private static FhCall.MsGetComData _MsGetComData; private static FhCall.MsGetCommandUse _MsGetCommandUse; private static FhCall.MsGetCommandMP _MsGetCommandMP; @@ -118,126 +117,126 @@ public unsafe partial class ArchipelagoFFXModule { private static FhCall.TODrawCrossBoxXYWHC2 _TODrawCrossBoxXYWHC2; - private static FhMethodHandle _TkMenuAppearMainCmdWindow; + private static FhMethodHandle _TkMenuAppearMainCmdWindow; // Sphere Grid Experiment - private static FhMethodHandle _eiAbmParaGet; - private static FhMethodHandle _MsSetSaveParam; - private static FhMethodHandle _MsSetRamChrParam; - private static FhMethodHandle _FUN_00a48910; + private static FhMethodHandle _eiAbmParaGet; + private static FhMethodHandle _MsSetSaveParam; + private static FhMethodHandle _MsSetRamChrParam; + private static FhMethodHandle _FUN_00a48910; - private static FhMethodHandle _MsApUp; + private static FhMethodHandle _MsApUp; - private static FhMethodHandle _openFile; - private static delegates.readFile _readFile; - private static FhMethodHandle _FUN_0070aec0; + private static FhMethodHandle _openFile; + private static readFile _readFile; + private static FhMethodHandle _FUN_0070aec0; private static FhCall.ChN_ReadSystemMGRP _ChN_ReadSystemMGRP; - private static delegates.Common_loadModel _Common_loadModel; - private static delegates.Common_0043 _Common_0043; - private static delegates.Common_linkFieldToBattleActor _Common_linkFieldToBattleActor; + private static Common_loadModel _Common_loadModel; + private static Common_0043 _Common_0043; + private static Common_linkFieldToBattleActor _Common_linkFieldToBattleActor; private static FhCall.SndSepPlay _SndSepPlay; - public static delegates.MsGetExcelData _MsGetExcelData; + public static MsGetExcelData _MsGetExcelData; - private static FhMethodHandle _Map_800F; + private static FhMethodHandle _Map_800F; - private static FhMethodHandle _FUN_0086bec0; - private static FhMethodHandle _FUN_0086bea0; + private static FhMethodHandle _FUN_0086bec0; + private static FhMethodHandle _FUN_0086bea0; - private static FhMethodHandle _graphicInitFMVPlayer; + private static FhMethodHandle _graphicInitFMVPlayer; - private static FhMethodHandle _FUN_00656c90; - private static delegates.FUN_0065ee30 _FUN_0065ee30; - private static delegates.ClusterManager_loadPCluster _ClusterManager_loadPCluster; - private static delegates.Phyre_PFramework_PApplication_FixupClusters _Phyre_PFramework_PApplication_FixupClusters; - private static delegates.ClusterManager_releasePCluster _ClusterManager_releasePCluster; - private static delegates.ClusterManager_getPClusterByName _ClusterManager_getPClusterByName; - private static delegates.fiosUnifyFilename _fiosUnifyFilename; + private static FhMethodHandle _FUN_00656c90; + private static FUN_0065ee30 _FUN_0065ee30; + private static ClusterManager_loadPCluster _ClusterManager_loadPCluster; + private static Phyre_PFramework_PApplication_FixupClusters _Phyre_PFramework_PApplication_FixupClusters; + private static ClusterManager_releasePCluster _ClusterManager_releasePCluster; + private static ClusterManager_getPClusterByName _ClusterManager_getPClusterByName; + private static fiosUnifyFilename _fiosUnifyFilename; // ObtainTreasure related - private static FhMethodHandle _TkMsImportantSet; - private static delegates.MsPayGIL _MsPayGIL; - private static delegates.SndSepPlaySimple _SndSepPlaySimple; - private static delegates.MsGetSaveWeapon _MsGetSaveWeapon; - private static delegates.FUN_007ab930 _FUN_007ab930; // giveWeapon? - private static delegates.AtelGetCurCtrlWork _AtelGetCurCtrlWork; - private static delegates.MsFieldItemGet _MsFieldItemGet; - private static delegates.TkMsGetRomItem _TkMsGetRomItem; - private static delegates.MsSaveItemUse _MsSaveItemUse; - private static delegates.MsImportantName _MsImportantName; - private static delegates.CT_RetInt_0065 _CT_RetInt_0065; - private static delegates.CT_RetInt_006A _CT_RetInt_006A; + private static FhMethodHandle _TkMsImportantSet; + private static MsPayGIL _MsPayGIL; + private static SndSepPlaySimple _SndSepPlaySimple; + private static MsGetSaveWeapon _MsGetSaveWeapon; + private static FUN_007ab930 _FUN_007ab930; // giveWeapon? + private static AtelGetCurCtrlWork _AtelGetCurCtrlWork; + private static MsFieldItemGet _MsFieldItemGet; + private static TkMsGetRomItem _TkMsGetRomItem; + private static MsSaveItemUse _MsSaveItemUse; + private static MsImportantName _MsImportantName; + private static CT_RetInt_0065 _CT_RetInt_0065; + private static CT_RetInt_006A _CT_RetInt_006A; private static FhCall.MsBtlGetInit _MsBtlGetInit; - private static delegates.AtelGetMesWinWork _AtelGetMesWinWork; - private static delegates.FUN_008b8910 _FUN_008b8910; // setMessageWindowVariableType? (0: text*, 1: int) - private static delegates.FUN_008bda20 _FUN_008bda20; // getMenuText - private static delegates.FUN_008b8930 _FUN_008b8930; // setMessageWindowVariable - private static delegates.FUN_0086a0c0 _FUN_0086a0c0; + private static AtelGetMesWinWork _AtelGetMesWinWork; + private static FUN_008b8910 _FUN_008b8910; // setMessageWindowVariableType? (0: text*, 1: int) + private static FUN_008bda20 _FUN_008bda20; // getMenuText + private static FUN_008b8930 _FUN_008b8930; // setMessageWindowVariable + private static FUN_0086a0c0 _FUN_0086a0c0; // Voice related - private static FhMethodHandle _FmodVoice_dataChange; - private static delegates.FMOD_EventSystem_load _FMOD_EventSystem_load; + private static FhMethodHandle _FmodVoice_dataChange; + private static FMOD_EventSystem_load _FMOD_EventSystem_load; - private static FhMethodHandle _FfxFmod_soundInit_setLang; - private static FhMethodHandle _LocalizationManager_Initialize; - public static delegates.LocalizationManager_GetInstance _LocalizationManager_GetInstance; - public static delegates.FfxFmod_soundInit _FfxFmod_soundInit; - public static delegates.FmodVoice_initList _FmodVoice_initList; + private static FhMethodHandle _FfxFmod_soundInit_setLang; + private static FhMethodHandle _LocalizationManager_Initialize; + public static LocalizationManager_GetInstance _LocalizationManager_GetInstance; + public static FfxFmod_soundInit _FfxFmod_soundInit; + public static FmodVoice_initList _FmodVoice_initList; // Custom namespace - private static FhMethodHandle _AtelInitTotal; - public static void AtelSetUpCallFunc(int id, nint nameSpacePtr) => FhUtil.get_fptr(__addr_AtelSetUpCallFunc)(id, nameSpacePtr); + private static FhMethodHandle _AtelInitTotal; + public static void AtelSetUpCallFunc(int id, nint nameSpacePtr) => FhUtil.get_fptr(__addr_AtelSetUpCallFunc)(id, nameSpacePtr); // Airship menu related - public static delegates.FUN_00867370 _FUN_00867370; - public static delegates.FUN_008671d0 _FUN_008671d0; - public static delegates.Map_show2DLayerResultInt _Map_show2DLayerResultInt; - public static delegates.Map_hide2DLayerResultInt _Map_hide2DLayerResultInt; + public static FUN_00867370 _FUN_00867370; + public static FUN_008671d0 _FUN_008671d0; + public static Map_show2DLayerResultInt _Map_show2DLayerResultInt; + public static Map_hide2DLayerResultInt _Map_hide2DLayerResultInt; // Drawing - public static delegates.TOMkpCrossExtMesFontLClutTypeRGBA _TOMkpCrossExtMesFontLClutTypeRGBA; - public static delegates.ToMakeBtlEasyFont _ToMakeBtlEasyFont; + public static TOMkpCrossExtMesFontLClutTypeRGBA _TOMkpCrossExtMesFontLClutTypeRGBA; + public static ToMakeBtlEasyFont _ToMakeBtlEasyFont; public void init_hooks() { const string game = "FFX.exe"; - _AtelEventSetUp = new FhMethodHandle(this, game, __addr_AtelEventSetUp, h_AtelEventSetUp); + _AtelEventSetUp = new FhMethodHandle(this, game, __addr_AtelEventSetUp, h_AtelEventSetUp); - _Common_obtainTreasureInit = new FhMethodHandle(this, game, __addr_Common_obtainTreasureInit, h_Common_obtainTreasureInit); + _Common_obtainTreasureInit = new FhMethodHandle(this, game, __addr_Common_obtainTreasureInit, h_Common_obtainTreasureInit); - _Common_obtainTreasureSilentlyInit = new FhMethodHandle(this, game, __addr_Common_obtainTreasureSilentlyInit, h_Common_obtainTreasureSilentlyInit); + _Common_obtainTreasureSilentlyInit = new FhMethodHandle(this, game, __addr_Common_obtainTreasureSilentlyInit, h_Common_obtainTreasureSilentlyInit); - _Common_isBrotherhoodUnpoweredRetInt = new FhMethodHandle(this, game, __addr_CT_RetInt_01B6, h_Common_isBrotherhoodUnpoweredRetInt); - _Common_upgradeBrotherhoodRetInt = new FhMethodHandle(this, game, __addr_CT_RetInt_01B7, h_Common_upgradeBrotherhoodRetInt); - _Common_obtainBrotherhoodRetInt = new FhMethodHandle(this, game, __addr_Common_obtainBrotherhoodRetInt, h_Common_obtainBrotherhoodRetInt); + _Common_isBrotherhoodUnpoweredRetInt = new FhMethodHandle(this, game, __addr_CT_RetInt_01B6, h_Common_isBrotherhoodUnpoweredRetInt); + _Common_upgradeBrotherhoodRetInt = new FhMethodHandle(this, game, __addr_CT_RetInt_01B7, h_Common_upgradeBrotherhoodRetInt); + _Common_obtainBrotherhoodRetInt = new FhMethodHandle(this, game, __addr_Common_obtainBrotherhoodRetInt, h_Common_obtainBrotherhoodRetInt); - _TkSetLegendAbility = new FhMethodHandle(this, game, __addr_TkSetLegendAbility, h_TkSetLegendAbility); + _TkSetLegendAbility = new FhMethodHandle(this, game, __addr_TkSetLegendAbility, h_TkSetLegendAbility); - _Common_setPrimerCollected = new FhMethodHandle(this, game, __addr_Common_setPrimerCollected, h_Common_setPrimerCollected); + _Common_setPrimerCollected = new FhMethodHandle(this, game, __addr_Common_setPrimerCollected, h_Common_setPrimerCollected); - _Common_transitionToMap = new FhMethodHandle(this, game, __addr_Common_transitionToMap, h_Common_transitionToMap); - _Common_warpToMap = new FhMethodHandle(this, game, __addr_Common_warpToMap, h_Common_warpToMap); + _Common_transitionToMap = new FhMethodHandle(this, game, __addr_Common_transitionToMap, h_Common_transitionToMap); + _Common_warpToMap = new FhMethodHandle(this, game, __addr_Common_warpToMap, h_Common_warpToMap); - _SgEvent_showModularMenuInit = new FhMethodHandle(this, game, __addr_SgEvent_showModularMenuInit, h_SgEvent_showModularMenuInit); + _SgEvent_showModularMenuInit = new FhMethodHandle(this, game, __addr_SgEvent_showModularMenuInit, h_SgEvent_showModularMenuInit); //_Common_playFieldVoiceLineInit = new FhMethodHandle(this, game, h_Common_playFieldVoiceLineInit, offset: 0x0045cb70); //_Common_playFieldVoiceLineExec = new FhMethodHandle(this, game, h_Common_playFieldVoiceLineExec, offset: 0x0045cd30); //_Common_playFieldVoiceLineResultInt = new FhMethodHandle(this, game, h_Common_playFieldVoiceLineResultInt, offset: 0x0045d150); - _Common_playFieldVoiceLineInit = FhUtil.get_fptr (__addr_Common_playFieldVoiceLineInit ); - _Common_playFieldVoiceLineExec = FhUtil.get_fptr (__addr_Common_playFieldVoiceLineExec ); - _Common_playFieldVoiceLineResultInt = FhUtil.get_fptr(__addr_Common_playFieldVoiceLineResultInt); + _Common_playFieldVoiceLineInit = FhUtil.get_fptr (__addr_Common_playFieldVoiceLineInit ); + _Common_playFieldVoiceLineExec = FhUtil.get_fptr (__addr_Common_playFieldVoiceLineExec ); + _Common_playFieldVoiceLineResultInt = FhUtil.get_fptr(__addr_Common_playFieldVoiceLineResultInt); - _Common_00D6Init = FhUtil.get_fptr (__addr_Common_00D6Init ); - _Common_00D6Exec = FhUtil.get_fptr (__addr_Common_00D6Exec ); - _Common_00D6ResultInt = FhUtil.get_fptr(__addr_Common_00D6ResultInt); + _Common_00D6Init = FhUtil.get_fptr (__addr_Common_00D6Init ); + _Common_00D6Exec = FhUtil.get_fptr (__addr_Common_00D6Exec ); + _Common_00D6ResultInt = FhUtil.get_fptr(__addr_Common_00D6ResultInt); @@ -247,129 +246,129 @@ public void init_hooks() { //_FUN_0085fdb0 = new FhMethodHandle(this, game, h_after_voiceline_exec, offset: 0x0045fdb0); // Common.01D1Init - _Common_01D1Init = FhUtil.get_fptr(__addr_Common_01D1Init); + _Common_01D1Init = FhUtil.get_fptr(__addr_Common_01D1Init); // Common.01D1Exec - _Common_01D1Exec = FhUtil.get_fptr(__addr_Common_01D1Exec); + _Common_01D1Exec = FhUtil.get_fptr(__addr_Common_01D1Exec); - _Common_addPartyMember = new FhMethodHandle(this, game, 0x0045b5a0, h_Common_addPartyMember); - _Common_removePartyMember = new FhMethodHandle(this, game, 0x0045b6c0, h_Common_removePartyMember); - _Common_removePartyMemberLongTerm = new FhMethodHandle(this, game, 0x0045aaf0, h_Common_removePartyMemberLongTerm); - _Common_setWeaponVisibilty = new FhMethodHandle(this, game, 0x00456770, h_Common_setWeaponInvisible); - _Common_putPartyMemberInSlot = new FhMethodHandle(this, game, 0x0045bc90, h_Common_putPartyMemberInSlot); + _Common_addPartyMember = new FhMethodHandle(this, game, 0x0045b5a0, h_Common_addPartyMember); + _Common_removePartyMember = new FhMethodHandle(this, game, 0x0045b6c0, h_Common_removePartyMember); + _Common_removePartyMemberLongTerm = new FhMethodHandle(this, game, 0x0045aaf0, h_Common_removePartyMemberLongTerm); + _Common_setWeaponVisibilty = new FhMethodHandle(this, game, 0x00456770, h_Common_setWeaponInvisible); + _Common_putPartyMemberInSlot = new FhMethodHandle(this, game, 0x0045bc90, h_Common_putPartyMemberInSlot); - _Common_pushParty = new FhMethodHandle(this, game, 0x0045b350, h_Common_pushParty); - _Common_popParty = new FhMethodHandle(this, game, 0x0045b3c0, h_Common_popParty); + _Common_pushParty = new FhMethodHandle(this, game, 0x0045b350, h_Common_pushParty); + _Common_popParty = new FhMethodHandle(this, game, 0x0045b3c0, h_Common_popParty); // getCurrentPartySlots - _MsGetSavePartyMember = new FhMethodHandle(this, game, __addr_MsGetSavePartyMember, h_MsGetSavePartyMember); + _MsGetSavePartyMember = new FhMethodHandle(this, game, __addr_MsGetSavePartyMember, h_MsGetSavePartyMember); - _MsBtlListGroup = FhUtil.get_fptr(__addr_MsBtlListGroup); - _MsBattleExe = new FhMethodHandle(this, game, __addr_MsBattleExe, h_MsBattleExe); - _MsBattleLabelExe = FhUtil.get_fptr(__addr_MsBattleLabelExe); - _FUN_00791820 = new FhMethodHandle(this, game, 0x00391820, h_FUN_00791820); + _MsBtlListGroup = FhUtil.get_fptr(__addr_MsBtlListGroup); + _MsBattleExe = new FhMethodHandle(this, game, __addr_MsBattleExe, h_MsBattleExe); + _MsBattleLabelExe = FhUtil.get_fptr(__addr_MsBattleLabelExe); + _FUN_00791820 = new FhMethodHandle(this, game, 0x00391820, h_FUN_00791820); - _MsBtlGetPos = new FhMethodHandle(this, game, 0x003ac000, h_MsBtlGetPos); + _MsBtlGetPos = new FhMethodHandle(this, game, 0x003ac000, h_MsBtlGetPos); - _MsBtlReadSetScene = new FhMethodHandle(this, game, 0x00383ed0, h_MsBtlReadSetScene); + _MsBtlReadSetScene = new FhMethodHandle(this, game, 0x00383ed0, h_MsBtlReadSetScene); // giveItem - _FUN_007905a0 = new FhMethodHandle(this, game, 0x003905a0, h_give_item); + _FUN_007905a0 = new FhMethodHandle(this, game, 0x003905a0, h_give_item); // readFromBin - _FUN_007ab890 = new FhMethodHandle(this, game, 0x003ab890, h_read_from_bin); + _FUN_007ab890 = new FhMethodHandle(this, game, 0x003ab890, h_read_from_bin); // getWeaponName - _FUN_007a0d10 = new FhMethodHandle(this, game, 0x003a0d10, h_get_weapon_name); + _FUN_007a0d10 = new FhMethodHandle(this, game, 0x003a0d10, h_get_weapon_name); // getWeaponModel - _FUN_007a0c70 = new FhMethodHandle(this, game, 0x003a0c70, h_get_weapon_model); + _FUN_007a0c70 = new FhMethodHandle(this, game, 0x003a0c70, h_get_weapon_model); // obtainTreasureCleanup - _FUN_007993f0 = new FhMethodHandle(this, game, 0x003993f0, h_obtain_treasure_cleanup); + _FUN_007993f0 = new FhMethodHandle(this, game, 0x003993f0, h_obtain_treasure_cleanup); - _MsGetChr = FhUtil.get_fptr(__addr_MsGetChr); + _MsGetChr = FhUtil.get_fptr(__addr_MsGetChr); _MsGetComData = FhUtil.get_fptr(FhCall.__addr_MsGetComData); _MsGetCommandUse = FhUtil.get_fptr(FhCall.__addr_MsGetCommandUse); _MsGetCommandMP = FhUtil.get_fptr(FhCall.__addr_MsGetCommandMP); _MsGetRamChrMonster = FhUtil.get_fptr(FhCall.__addr_MsGetRamChrMonster); _TODrawCrossBoxXYWHC2 = FhUtil.get_fptr(FhCall.__addr_TODrawCrossBoxXYWHC2); - _eiAbmParaGet = new FhMethodHandle(this, game, __addr_eiAbmParaGet, h_eiAbmParaGet); - _MsSetSaveParam = new FhMethodHandle(this, game, __addr_MsSetSaveParam, h_MsSetSaveParam); - _MsSetRamChrParam = new FhMethodHandle(this, game, __addr_MsSetRamChrParam, h_MsSetRamChrParam); - _FUN_00a48910 = new FhMethodHandle(this, game, 0x00648910, h_FUN_00a48910); + _eiAbmParaGet = new FhMethodHandle(this, game, __addr_eiAbmParaGet, h_eiAbmParaGet); + _MsSetSaveParam = new FhMethodHandle(this, game, __addr_MsSetSaveParam, h_MsSetSaveParam); + _MsSetRamChrParam = new FhMethodHandle(this, game, __addr_MsSetRamChrParam, h_MsSetRamChrParam); + _FUN_00a48910 = new FhMethodHandle(this, game, 0x00648910, h_FUN_00a48910); - _MsApUp = new FhMethodHandle(this, game, 0x00398a10, h_MsApUp); + _MsApUp = new FhMethodHandle(this, game, 0x00398a10, h_MsApUp); //delegate* unmanaged[Thiscall] ph_openFile = &h_openFile; //openFile p_openFile = (x, y, z) => d_openFile(ph_openFile, x, y, z); //openFile temp = Marshal.GetDelegateForFunctionPointer((nint)ph_openFile); - _openFile = new FhMethodHandle(this, game, 0x00208100, h_openFile); - _readFile = FhUtil.get_fptr(0x00208250); + _openFile = new FhMethodHandle(this, game, 0x00208100, h_openFile); + _readFile = FhUtil.get_fptr(0x00208250); - _FUN_0070aec0 = new FhMethodHandle(this, game, 0x0030aec0, h_FUN_0070aec0); + _FUN_0070aec0 = new FhMethodHandle(this, game, 0x0030aec0, h_FUN_0070aec0); _ChN_ReadSystemMGRP = FhUtil.get_fptr(FhCall.__addr_ChN_ReadSystemMGRP); - _Common_loadModel = FhUtil.get_fptr(0x0045ce70); - _Common_0043 = FhUtil.get_fptr(0x0045c810); - _Common_linkFieldToBattleActor = FhUtil.get_fptr(0x0045ca00); + _Common_loadModel = FhUtil.get_fptr(0x0045ce70); + _Common_0043 = FhUtil.get_fptr(0x0045c810); + _Common_linkFieldToBattleActor = FhUtil.get_fptr(0x0045ca00); _SndSepPlay = FhUtil.get_fptr(FhCall.__addr_SndSepPlay); - _Map_800F = new FhMethodHandle(this, game, 0x0051b1a0, h_Map_800F); + _Map_800F = new FhMethodHandle(this, game, 0x0051b1a0, h_Map_800F); - _MsGetExcelData = FhUtil.get_fptr(__addr_MsGetExcelData); + _MsGetExcelData = FhUtil.get_fptr(__addr_MsGetExcelData); // obtainTreasure related - _TkMsImportantSet = new FhMethodHandle(this, game, __addr_TkMsImportantSet, h_TkMsImportantSet); - _MsPayGIL = FhUtil.get_fptr(__addr_MsPayGIL); // takeGil - _SndSepPlaySimple = FhUtil.get_fptr(__addr_SndSepPlaySimple); - _MsGetSaveWeapon = FhUtil.get_fptr(__addr_MsGetSaveWeapon); - _FUN_007ab930 = FhUtil.get_fptr(0x003ab930); // giveWeapon - _AtelGetCurCtrlWork = FhUtil.get_fptr(__addr_AtelGetCurCtrlWork); - _MsFieldItemGet = FhUtil.get_fptr(__addr_MsFieldItemGet); - _TkMsGetRomItem = FhUtil.get_fptr(__addr_TkMsGetRomItem); - _MsSaveItemUse = FhUtil.get_fptr(__addr_MsSaveItemUse); - _MsImportantName = FhUtil.get_fptr(__addr_MsImportantName); - _CT_RetInt_0065 = FhUtil.get_fptr(__addr_CT_RetInt_0065); - _CT_RetInt_006A = FhUtil.get_fptr(__addr_CT_RetInt_006A); + _TkMsImportantSet = new FhMethodHandle(this, game, __addr_TkMsImportantSet, h_TkMsImportantSet); + _MsPayGIL = FhUtil.get_fptr(__addr_MsPayGIL); // takeGil + _SndSepPlaySimple = FhUtil.get_fptr(__addr_SndSepPlaySimple); + _MsGetSaveWeapon = FhUtil.get_fptr(__addr_MsGetSaveWeapon); + _FUN_007ab930 = FhUtil.get_fptr(0x003ab930); // giveWeapon + _AtelGetCurCtrlWork = FhUtil.get_fptr(__addr_AtelGetCurCtrlWork); + _MsFieldItemGet = FhUtil.get_fptr(__addr_MsFieldItemGet); + _TkMsGetRomItem = FhUtil.get_fptr(__addr_TkMsGetRomItem); + _MsSaveItemUse = FhUtil.get_fptr(__addr_MsSaveItemUse); + _MsImportantName = FhUtil.get_fptr(__addr_MsImportantName); + _CT_RetInt_0065 = FhUtil.get_fptr(__addr_CT_RetInt_0065); + _CT_RetInt_006A = FhUtil.get_fptr(__addr_CT_RetInt_006A); _MsBtlGetInit = FhUtil.get_fptr(FhCall.__addr_MsBtlGetInit); - _AtelGetMesWinWork = FhUtil.get_fptr(__addr_AtelGetMesWinWork); - _FUN_008b8910 = FhUtil.get_fptr(__addr_FUN_008b8910); - _FUN_008bda20 = FhUtil.get_fptr(__addr_FUN_008bda20); - _FUN_008b8930 = FhUtil.get_fptr(__addr_FUN_008b8930); - _FUN_0086a0c0 = FhUtil.get_fptr(__addr_FUN_0086a0c0); + _AtelGetMesWinWork = FhUtil.get_fptr(__addr_AtelGetMesWinWork); + _FUN_008b8910 = FhUtil.get_fptr(__addr_FUN_008b8910); + _FUN_008bda20 = FhUtil.get_fptr(__addr_FUN_008bda20); + _FUN_008b8930 = FhUtil.get_fptr(__addr_FUN_008b8930); + _FUN_0086a0c0 = FhUtil.get_fptr(__addr_FUN_0086a0c0); - _FUN_0086bec0 = new FhMethodHandle(this, game, 0x0046bec0, h_FUN_0086bec0); - _FUN_0086bea0 = new FhMethodHandle(this, game, 0x0046bea0, h_FUN_0086bea0); + _FUN_0086bec0 = new FhMethodHandle(this, game, 0x0046bec0, h_FUN_0086bec0); + _FUN_0086bea0 = new FhMethodHandle(this, game, 0x0046bea0, h_FUN_0086bea0); - _FUN_00656c90 = new FhMethodHandle(this, game, 0x00256c90, h_FUN_00656c90); + _FUN_00656c90 = new FhMethodHandle(this, game, 0x00256c90, h_FUN_00656c90); - _TkMenuAppearMainCmdWindow = new FhMethodHandle(this, game, __addr_TkMenuAppearMainCmdWindow, h_TkMenuAppearMainCmdWindow); + _TkMenuAppearMainCmdWindow = new FhMethodHandle(this, game, __addr_TkMenuAppearMainCmdWindow, h_TkMenuAppearMainCmdWindow); // For loading texture from game - _FUN_0065ee30 = FhUtil.get_fptr(__addr_ClusterManager_FUN_0065ee30); - _ClusterManager_loadPCluster = FhUtil.get_fptr(__addr_ClusterManager_loadPCluster); - _Phyre_PFramework_PApplication_FixupClusters = FhUtil.get_fptr(__addr_Phyre_PFramework_PApplication_FixupClusters); - _ClusterManager_releasePCluster = FhUtil.get_fptr(__addr_ClusterManager_releasePCluster); - _ClusterManager_getPClusterByName = FhUtil.get_fptr(__addr_ClusterManager_getPClusterByName); - _fiosUnifyFilename = FhUtil.get_fptr(__addr_fiosUnifyFilename); + _FUN_0065ee30 = FhUtil.get_fptr(__addr_ClusterManager_FUN_0065ee30); + _ClusterManager_loadPCluster = FhUtil.get_fptr(__addr_ClusterManager_loadPCluster); + _Phyre_PFramework_PApplication_FixupClusters = FhUtil.get_fptr(__addr_Phyre_PFramework_PApplication_FixupClusters); + _ClusterManager_releasePCluster = FhUtil.get_fptr(__addr_ClusterManager_releasePCluster); + _ClusterManager_getPClusterByName = FhUtil.get_fptr(__addr_ClusterManager_getPClusterByName); + _fiosUnifyFilename = FhUtil.get_fptr(__addr_fiosUnifyFilename); // Non-loading FMV - _graphicInitFMVPlayer = new FhMethodHandle(this, game, __addr_graphicInitFMVPlayer, h_graphicInitFMVPlayer); + _graphicInitFMVPlayer = new FhMethodHandle(this, game, __addr_graphicInitFMVPlayer, h_graphicInitFMVPlayer); foreach (byte[] script in customScripts) { customScriptHandles.Add(GCHandle.Alloc(script, GCHandleType.Pinned)); @@ -380,84 +379,84 @@ public void init_hooks() { // customStrings[i] = new CustomString(text); //} - _FmodVoice_dataChange = new FhMethodHandle(this, game, __addr_FmodVoice_dataChange, h_FmodVoice_dataChange); + _FmodVoice_dataChange = new FhMethodHandle(this, game, __addr_FmodVoice_dataChange, h_FmodVoice_dataChange); var _FMOD_EventSystem_load_pointer = FhUtil.get_at(__addr_FMOD_EventSystem_load); - _FMOD_EventSystem_load = Marshal.GetDelegateForFunctionPointer(_FMOD_EventSystem_load_pointer); + _FMOD_EventSystem_load = Marshal.GetDelegateForFunctionPointer(_FMOD_EventSystem_load_pointer); //_FMOD_EventSystem_load = new FhMethodHandle(this, _FMOD_EventSystem_load_pointer, h_FMOD_EventSystem_load); //_FfxFmod_soundInit_setLang = new FhMethodHandle(this, game, __addr_FfxFmod_soundInit_setLang, h_FfxFmod_soundInit_setLang); - _LocalizationManager_Initialize = new FhMethodHandle(this, game, __addr_LocalizationManager_Initialize, h_LocalizationManager_Initialize); - _LocalizationManager_GetInstance = FhUtil.get_fptr(__addr_LocalizationManager_GetInstance); - _FfxFmod_soundInit = FhUtil.get_fptr(__addr_FfxFmod_soundInit); - _FmodVoice_initList = FhUtil.get_fptr(__addr_FmodVoice_initList); + _LocalizationManager_Initialize = new FhMethodHandle(this, game, __addr_LocalizationManager_Initialize, h_LocalizationManager_Initialize); + _LocalizationManager_GetInstance = FhUtil.get_fptr(__addr_LocalizationManager_GetInstance); + _FfxFmod_soundInit = FhUtil.get_fptr(__addr_FfxFmod_soundInit); + _FmodVoice_initList = FhUtil.get_fptr(__addr_FmodVoice_initList); // Custom namespace - _AtelInitTotal = new FhMethodHandle(this, game, __addr_AtelInitTotal, h_AtelInitTotal); + _AtelInitTotal = new FhMethodHandle(this, game, __addr_AtelInitTotal, h_AtelInitTotal); // Airship - _FUN_00867370 = FhUtil.get_fptr(__addr_FUN_00867370); - _FUN_008671d0 = FhUtil.get_fptr(__addr_FUN_008671d0); - _Map_show2DLayerResultInt = FhUtil.get_fptr(__addr_Map_show2DLayerResultInt); - _Map_hide2DLayerResultInt = FhUtil.get_fptr(__addr_Map_hide2DLayerResultInt); + _FUN_00867370 = FhUtil.get_fptr(__addr_FUN_00867370); + _FUN_008671d0 = FhUtil.get_fptr(__addr_FUN_008671d0); + _Map_show2DLayerResultInt = FhUtil.get_fptr(__addr_Map_show2DLayerResultInt); + _Map_hide2DLayerResultInt = FhUtil.get_fptr(__addr_Map_hide2DLayerResultInt); // Drawing - _TOMkpCrossExtMesFontLClutTypeRGBA = FhUtil.get_fptr(__addr_TOMkpCrossExtMesFontLClutTypeRGBA); - _ToMakeBtlEasyFont = FhUtil.get_fptr(__addr_ToMakeBtlEasyFont); - - _PrepareMenuList = new FhMethodHandle(this, game, __addr_PrepareMenuList, h_PrepareMenuList); - _UpdateGearCustomizationMenuState = new FhMethodHandle(this, game, __addr_UpdateGearCustomizationMenuState, h_UpdateGearCustomizationMenuState); - _UpdateAeonCustomizationMenuState = new FhMethodHandle(this, game, __addr_UpdateAeonCustomizationMenuState, h_UpdateAeonCustomizationMenuState); - _DrawGearCustomizationMenu = new FhMethodHandle(this, game, __addr_DrawGearCustomizationMenu, h_DrawGearCustomizationMenu); - _DrawAeonCustomizationMenu = new FhMethodHandle(this, game, __addr_DrawAeonCustomizationMenu, h_DrawAeonCustomizationMenu); - _MsGetRomKaizou = FhUtil.get_fptr(__addr_MsGetRomKaizou); - _MsGetRomAbility = FhUtil.get_fptr(__addr_MsGetRomAbility); - _MsGetRomSummonGrow = FhUtil.get_fptr(__addr_MsGetRomSummonGrow); - _TkMn2GetSummonGrowMax = FhUtil.get_fptr(__addr_TkMn2GetSummonGrowMax); - _TkMenuGetCurrentSummon = FhUtil.get_fptr(__addr_TkMenuGetCurrentSummon); - _MsGetSaveCommand = FhUtil.get_fptr(__addr_MsGetSaveCommand); - - _FUN_008c1c70 = FhUtil.get_fptr(__addr_FUN_008c1c70); - _TODrawMenuPlateXYWHType = FhUtil.get_fptr(__addr_TODrawMenuPlateXYWHType); - _FUN_008f8bb0 = FhUtil.get_fptr(__addr_FUN_008f8bb0); - _TODrawScissorXYWH = FhUtil.get_fptr(__addr_TODrawScissorXYWH); - _FUN_008d5d20 = FhUtil.get_fptr(__addr_FUN_008d5d20); - _FUN_008c0f40 = FhUtil.get_fptr(__addr_FUN_008c0f40); - _FUN_008c1350_DrawScissor512x416 = FhUtil.get_fptr(__addr_FUN_008c1350_DrawScissor512x416); - _FUN_008d5dc0 = FhUtil.get_fptr(__addr_FUN_008d5dc0); - _DrawCrossMenuScrollParts = FhUtil.get_fptr(__addr_DrawCrossMenuScrollParts); - _FUN_008d6630 = FhUtil.get_fptr(__addr_FUN_008d6630); - - _TkVU1SyncPath = FhUtil.get_fptr(__addr_TkVU1SyncPath); - _FUN_008e71d0 = FhUtil.get_fptr(__addr_FUN_008e71d0); - _FUN_008ff490 = FhUtil.get_fptr(__addr_FUN_008ff490); - _FUN_008cd960 = FhUtil.get_fptr(__addr_FUN_008cd960); - _FUN_008cd9f0 = FhUtil.get_fptr(__addr_FUN_008cd9f0); - _ToGetCrossExtMesFontWidth = FhUtil.get_fptr(__addr_ToGetCrossExtMesFontWidth); - _FUN_008bee80 = FhUtil.get_fptr(__addr_FUN_008bee80); - _TOMkpShapeXYWHUV = FhUtil.get_fptr(__addr_TOMkpShapeXYWHUV); - _TOMkpCrossExtMesFontLClut = FhUtil.get_fptr(__addr_TOMkpCrossExtMesFontLClut); - _FUN_008d48e0 = FhUtil.get_fptr(__addr_FUN_008d48e0); - _FUN_008d4140 = FhUtil.get_fptr(__addr_FUN_008d4140); - _TkMn2DrawKickSyncPacket = FhUtil.get_fptr(__addr_TkMn2DrawKickSyncPacket); - - _TkMenuMainAllocWindow = FhUtil.get_fptr(__addr_TkMenuMainAllocWindow); - _TkMenuMainRegistWindow = FhUtil.get_fptr(__addr_TkMenuMainRegistWindow); - - _FUN_008e33a0 = FhUtil.get_fptr(__addr_FUN_008e33a0); - _FUN_008b4460 = FhUtil.get_fptr(__addr_FUN_008b4460); - _FUN_008e2de0 = FhUtil.get_fptr(__addr_FUN_008e2de0); - _MsSetSaveParamAll = FhUtil.get_fptr(__addr_MsSetSaveParamAll); - _MsSetWeaponName = FhUtil.get_fptr(__addr_MsSetWeaponName); - _FUN_008c2c40 = FhUtil.get_fptr(__addr_FUN_008c2c40); - _TkMn2DrawCrossCursor = FhUtil.get_fptr(__addr_TkMn2DrawCrossCursor); - - _FUN_008d5720 = new FhMethodHandle(this, game, __addr_FUN_008d5720, h_FUN_008d5720); + _TOMkpCrossExtMesFontLClutTypeRGBA = FhUtil.get_fptr(__addr_TOMkpCrossExtMesFontLClutTypeRGBA); + _ToMakeBtlEasyFont = FhUtil.get_fptr(__addr_ToMakeBtlEasyFont); + + _PrepareMenuList = new FhMethodHandle(this, game, __addr_PrepareMenuList, h_PrepareMenuList); + _UpdateGearCustomizationMenuState = new FhMethodHandle(this, game, __addr_UpdateGearCustomizationMenuState, h_UpdateGearCustomizationMenuState); + _UpdateAeonCustomizationMenuState = new FhMethodHandle(this, game, __addr_UpdateAeonCustomizationMenuState, h_UpdateAeonCustomizationMenuState); + _DrawGearCustomizationMenu = new FhMethodHandle(this, game, __addr_DrawGearCustomizationMenu, h_DrawGearCustomizationMenu); + _DrawAeonCustomizationMenu = new FhMethodHandle(this, game, __addr_DrawAeonCustomizationMenu, h_DrawAeonCustomizationMenu); + _MsGetRomKaizou = FhUtil.get_fptr(__addr_MsGetRomKaizou); + _MsGetRomAbility = FhUtil.get_fptr(__addr_MsGetRomAbility); + _MsGetRomSummonGrow = FhUtil.get_fptr(__addr_MsGetRomSummonGrow); + _TkMn2GetSummonGrowMax = FhUtil.get_fptr(__addr_TkMn2GetSummonGrowMax); + _TkMenuGetCurrentSummon = FhUtil.get_fptr(__addr_TkMenuGetCurrentSummon); + _MsGetSaveCommand = FhUtil.get_fptr(__addr_MsGetSaveCommand); + + _FUN_008c1c70 = FhUtil.get_fptr(__addr_FUN_008c1c70); + _TODrawMenuPlateXYWHType = FhUtil.get_fptr(__addr_TODrawMenuPlateXYWHType); + _FUN_008f8bb0 = FhUtil.get_fptr(__addr_FUN_008f8bb0); + _TODrawScissorXYWH = FhUtil.get_fptr(__addr_TODrawScissorXYWH); + _FUN_008d5d20 = FhUtil.get_fptr(__addr_FUN_008d5d20); + _FUN_008c0f40 = FhUtil.get_fptr(__addr_FUN_008c0f40); + _FUN_008c1350_DrawScissor512x416 = FhUtil.get_fptr(__addr_FUN_008c1350_DrawScissor512x416); + _FUN_008d5dc0 = FhUtil.get_fptr(__addr_FUN_008d5dc0); + _DrawCrossMenuScrollParts = FhUtil.get_fptr(__addr_DrawCrossMenuScrollParts); + _FUN_008d6630 = FhUtil.get_fptr(__addr_FUN_008d6630); + + _TkVU1SyncPath = FhUtil.get_fptr(__addr_TkVU1SyncPath); + _FUN_008e71d0 = FhUtil.get_fptr(__addr_FUN_008e71d0); + _FUN_008ff490 = FhUtil.get_fptr(__addr_FUN_008ff490); + _FUN_008cd960 = FhUtil.get_fptr(__addr_FUN_008cd960); + _FUN_008cd9f0 = FhUtil.get_fptr(__addr_FUN_008cd9f0); + _ToGetCrossExtMesFontWidth = FhUtil.get_fptr(__addr_ToGetCrossExtMesFontWidth); + _FUN_008bee80 = FhUtil.get_fptr(__addr_FUN_008bee80); + _TOMkpShapeXYWHUV = FhUtil.get_fptr(__addr_TOMkpShapeXYWHUV); + _TOMkpCrossExtMesFontLClut = FhUtil.get_fptr(__addr_TOMkpCrossExtMesFontLClut); + _FUN_008d48e0 = FhUtil.get_fptr(__addr_FUN_008d48e0); + _FUN_008d4140 = FhUtil.get_fptr(__addr_FUN_008d4140); + _TkMn2DrawKickSyncPacket = FhUtil.get_fptr(__addr_TkMn2DrawKickSyncPacket); + + _TkMenuMainAllocWindow = FhUtil.get_fptr(__addr_TkMenuMainAllocWindow); + _TkMenuMainRegistWindow = FhUtil.get_fptr(__addr_TkMenuMainRegistWindow); + + _FUN_008e33a0 = FhUtil.get_fptr(__addr_FUN_008e33a0); + _FUN_008b4460 = FhUtil.get_fptr(__addr_FUN_008b4460); + _FUN_008e2de0 = FhUtil.get_fptr(__addr_FUN_008e2de0); + _MsSetSaveParamAll = FhUtil.get_fptr(__addr_MsSetSaveParamAll); + _MsSetWeaponName = FhUtil.get_fptr(__addr_MsSetWeaponName); + _FUN_008c2c40 = FhUtil.get_fptr(__addr_FUN_008c2c40); + _TkMn2DrawCrossCursor = FhUtil.get_fptr(__addr_TkMn2DrawCrossCursor); + + _FUN_008d5720 = new FhMethodHandle(this, game, __addr_FUN_008d5720, h_FUN_008d5720); } public static int ignore_this = 11; - public static int h_Map_800F(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + public int h_Map_800F(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int param_1 = atelStack->values.as_int()[0]; if (param_1 == ignore_this) { atelStack->pop_int(); @@ -466,20 +465,73 @@ public static int h_Map_800F(AtelBasicWorker* work, int* storage, AtelStack* ate return _Map_800F.orig_fptr(work, storage, atelStack); } - public static bool h_openFile(nint _this, nint filename, bool readOnly, nint unknown_1, nint unknown_2, nint unknown_3) { + public bool h_openFile(nint _this, nint filename, bool readOnly, nint unknown_1, nint unknown_2, nint unknown_3) { string x = Marshal.PtrToStringAnsi(filename); - logger.Debug($"{_this}, {x}, {readOnly}, {unknown_1}, {unknown_2}, {unknown_3}"); + _logger.Debug($"{_this}, {x}, {readOnly}, {unknown_1}, {unknown_2}, {unknown_3}"); var result = _openFile.orig_fptr(_this, filename, readOnly, unknown_1, unknown_2, unknown_3); - logger.Debug($"{result}, {*(int*)_this}, {*(int*)((int)_this + 4)}"); + _logger.Debug($"{result}, {*(int*)_this}, {*(int*)((int)_this + 4)}"); return result; } - public static uint h_FUN_0070aec0(nint _this, uint voice_id, uint param_2) { - + public uint h_FUN_0070aec0(nint _this, uint voice_id, uint param_2) { return _FUN_0070aec0.orig_fptr(_this, voice_id, param_2); } - public bool hook() { + private CT_RetInt[] custom_ct_retints; + private int turnAroundScriptLength; + private byte* turnAroundScript; + private void init_custom_atel() { + custom_ct_retints = [ + CT_RetInt_PushInt, + CT_RetInt_PushFloat, + CT_RetInt_IsCharacterUnlocked, + CT_RetInt_HasCelestialWeapon, + CT_RetInt_IsOtherLocationChecked, + CT_RetInt_CollectedPrimers, + CT_RetInt_SendOtherLocation, + CT_RetInt_SendPartyMemberLocation, + CT_RetInt_SendRecruitLocation, + CT_RetInt_BlockWarp, + CT_RetInt_BlockKilikaBoatChoice, + CT_RetInt_RestoreInteraction, + CT_RetInt_SetAirshipDestinations, + CT_RetInt_ShowAirshipDestinations, + CT_RetInt_HideAirshipDestinations, + CT_RetInt_ShowCurrentAirshipLocation, + CT_RetInt_HideCurrentAirshipLocation, + CT_RetInt_TransitionToRegion, + CT_RetInt_Jump, + CT_RetInt_JumpIfFalse, + CT_RetInt_JumpIfTrue, + CT_RetInt_Offset, + CT_RetInt_OffsetIfFalse, + CT_RetInt_OffsetIfTrue, + CT_RetInt_UpdateRegionState, + CT_RetInt_LockPartyMember, + CT_RetInt_LockAllAeons, + CT_RetInt_IsGoalUnlocked, + CT_RetInt_ReplaceEntryPoint, + CT_RetInt_RestoreEntryPoint, + CT_RetInt_LightningDodging, + CT_RetInt_JechtSphere, + CT_RetInt_KickedBlitzballAway, + CT_RetInt_CheckUnlockedAeons, + ]; + + customNameSpace = new AtelCallTarget[custom_ct_retints.Length]; + + for (int i = 0; i < custom_ct_retints.Length; i++) { + customNameSpace[i].ret_int_func = Marshal.GetFunctionPointerForDelegate(custom_ct_retints[i]); + } + + customNameSpaceHandle = GCHandle.Alloc(customNameSpace, GCHandleType.Pinned); + + turnAroundScriptLength = atelTurnAround(Span.Empty, 0, 0, 0, 0, 0, 0); + turnAroundScript = (byte*)NativeMemory.AllocZeroed((uint)turnAroundScriptLength); + + } + + private bool hook() { return _Common_obtainTreasureInit.hook() && _Common_obtainTreasureSilentlyInit.hook() && _Common_obtainBrotherhoodRetInt.hook() && _TkSetLegendAbility.hook() && _Common_setPrimerCollected.hook() && _AtelEventSetUp.hook() && _Common_transitionToMap.hook() && _Common_warpToMap.hook() @@ -501,20 +553,20 @@ public bool hook() { } - private static void set(byte* code_ptr, uint offset, AtelInst opcode) { + private void set(byte* code_ptr, uint offset, AtelInst opcode) { byte* ptr = code_ptr + offset; foreach (byte b in opcode.to_bytes()) { *ptr = b; ptr++; } } - private static void set(byte* code_ptr, uint[] offsets, AtelInst opcode) { + private void set(byte* code_ptr, uint[] offsets, AtelInst opcode) { foreach (uint offset in offsets) { set(code_ptr, offset, opcode); } } - private static void set(byte* code_ptr, uint offset, AtelInst[] opcodes) { + private void set(byte* code_ptr, uint offset, AtelInst[] opcodes) { byte* ptr = code_ptr + offset; foreach (AtelInst op in opcodes) { foreach (byte b in op.to_bytes()) { @@ -523,13 +575,13 @@ private static void set(byte* code_ptr, uint offset, AtelInst[] opcodes) { } } } - private static void set(byte* code_ptr, uint[] offsets, AtelInst[] opcodes) { + private void set(byte* code_ptr, uint[] offsets, AtelInst[] opcodes) { foreach (uint offset in offsets) { set(code_ptr, offset, opcodes); } } - private static void move(byte* code_ptr, uint sourceOffset, int moveBy, int size) { + private void move(byte* code_ptr, uint sourceOffset, int moveBy, int size) { Span source = new(code_ptr + sourceOffset , size); Span destination = new(code_ptr + sourceOffset + moveBy, size); @@ -551,9 +603,7 @@ private static void move(byte* code_ptr, uint sourceOffset, int moveBy, int size temp.CopyTo(destinationDestination); } - - - private static byte* h_FUN_0086bec0(int param_1) { + private byte* h_FUN_0086bec0(int param_1) { byte* result; if ((param_1 & 0x8000) != 0) { int custom_index = param_1 & 0x7FFF; @@ -561,7 +611,7 @@ private static void move(byte* code_ptr, uint sourceOffset, int moveBy, int size //result = (byte*)customStringHandles[custom_index].AddrOfPinnedObject(); //FhEncoding.compute_decode_buffer_size(result); //string decoded = FhEncoding.Us.to_string(result); - logger.Debug(customStrings[custom_index].decoded); + _logger.Debug(customStrings[custom_index].decoded); } else { // May crash if called with invalid index result = _FUN_0086bec0.orig_fptr(param_1); @@ -569,7 +619,8 @@ private static void move(byte* code_ptr, uint sourceOffset, int moveBy, int size return result; } - private static short h_FUN_0086bea0(int param_1) { + + private short h_FUN_0086bea0(int param_1) { short result; if ((param_1 & 0x8000) != 0) { int custom_index = param_1 & 0x7FFF; @@ -730,6 +781,7 @@ AtelOp.PUSHII .build((ushort)(value >> 16)), AtelOp.CALLPOPA.build((ushort)CustomCallTarget.PUSH_INT), ]; } + private static AtelInst[] atelPushFloat(float value) { int as_int = BitConverter.SingleToInt32Bits(value); return [ @@ -738,6 +790,7 @@ AtelOp.PUSHII .build((ushort)(as_int >> 16)), AtelOp.CALLPOPA.build((ushort)CustomCallTarget.PUSH_FLOAT), ]; } + private static AtelInst[] atelPushIntAsFloat(uint value) { return [ AtelOp.PUSHII .build((ushort)(value & 0xffff)), @@ -755,8 +808,8 @@ private static AtelInst[] atelNOPArray(uint n) { return temp; } - private static readonly List customScriptHandles = []; - private static readonly byte[][] customScripts = { + private readonly List customScriptHandles = []; + private readonly byte[][] customScripts = { // Cid talk hook ((AtelInst[])[ // 0 // If GameMoment < 2970 or GameMoment >= 3120: Jump to j01 (return) @@ -1173,7 +1226,7 @@ AtelOp.RET .build( ), // Check Nemesis requirements ((AtelInst[])[ // C - + // !!!(MonsterArenaOriginalCreationUnlockFlags[0] & 128 [80h]) AtelOp.PUSHII .build(0x0000), AtelOp.PUSHAR .build(0x000C), @@ -1424,7 +1477,7 @@ AtelOp.PUSHII .build(0x50AB), private static Dictionary<(int, int), uint> originalEntryPoints = new(); private static string current_event_name = ""; - private static void h_AtelEventSetUp(int event_id) { + private void h_AtelEventSetUp(int event_id) { _AtelEventSetUp.orig_fptr(event_id); foreach (NativeCustomString customString in cached_strings) { @@ -1439,7 +1492,7 @@ private static void h_AtelEventSetUp(int event_id) { } string event_name = Marshal.PtrToStringAnsi((nint)get_event_name((uint)event_id))!; - logger.Debug($"atel_event_setup: {event_name}"); + _logger.Debug($"atel_event_setup: {event_name}"); byte* code_ptr = Globals.Atel.controllers[0].worker(0)->code_ptr; switch (event_name) { case "bjyt1200": @@ -1464,7 +1517,7 @@ .. atelNOPArray(1), ]); break; case "hiku2100": - logger.Debug($"atel_event_setup: Inject set_airship_destinations call"); + _logger.Debug($"atel_event_setup: Inject set_airship_destinations call"); set(code_ptr, 0x26D1, [ .. atelNOPArray(3), AtelOp.CALLPOPA.build((ushort)CustomCallTarget.SET_AIRSHIP_DESTINATIONS), @@ -1559,7 +1612,7 @@ AtelOp.PUSHII .build((ushort)region), break; case "hiku0801": - logger.Debug($"atel_event_setup: Inject Cid talk hook"); + _logger.Debug($"atel_event_setup: Inject Cid talk hook"); set(code_ptr, 0x4DC5, [ AtelOp.PUSHII .build(0x0000), AtelOp.CALLPOPA.build((ushort)CustomCallTarget.JUMP), // Common.Jump(0000) = jump to customScripts[0] @@ -1570,11 +1623,11 @@ AtelOp.PUSHII .build(0x0000), set(code_ptr, 0x5869, AtelOp.CALL.build((ushort)CustomCallTarget.COLLECTED_PRIMERS)); break; case "ssbt0300": - logger.Debug($"atel_event_setup: Redirect Overdrive Sin post-battle warp"); + _logger.Debug($"atel_event_setup: Redirect Overdrive Sin post-battle warp"); set(code_ptr, 0x500E, AtelOp.PUSHII.build(382)); break; case "sins0700": - logger.Debug($"atel_event_setup: Handle removing Aeons"); + _logger.Debug($"atel_event_setup: Handle removing Aeons"); // Lock all Aeons and skip Contest of Aeons if (seed.Options.SkipContestOfAeons == 1) { @@ -1600,7 +1653,7 @@ AtelOp.PUSHII .build(0x000A), ]); break; case "luca0400": - logger.Debug($"atel_event_setup: Wait longer"); + _logger.Debug($"atel_event_setup: Wait longer"); set(code_ptr, 0x68F9, [ AtelOp.PUSHII .build(10), AtelOp.CALLPOPA.build( 0), @@ -2120,7 +2173,7 @@ AtelOp.NOP .build(), // Inject save sphere hook if (event_name == "nagi0000") { uint save_sphere_offset = 0x1BB69; - logger.Info($"Save sphere init at {save_sphere_offset}"); + _logger.Info($"Save sphere init at {save_sphere_offset}"); set(code_ptr, save_sphere_offset + 0x48, AtelOp.JMP.build(0x0007)); // Always all options // Update region state. Also skips save sphere tutorial @@ -2146,7 +2199,7 @@ AtelOp.PUSHII .build( 0), } else if (event_name == "cdsp0700") { uint save_sphere_offset = 0x2AA3; - logger.Info($"Underwater save sphere init at {save_sphere_offset}"); + _logger.Info($"Underwater save sphere init at {save_sphere_offset}"); set(code_ptr, save_sphere_offset + 0x5A, AtelOp.JMP.build(0x0002)); // Always all options // Update region state. Also skips save sphere tutorial @@ -2172,7 +2225,7 @@ AtelOp.PUSHII .build( 0), } else if (event_name == "stbv0000") { uint save_sphere_offset = 0x2982; - logger.Info($"Underwater save sphere init at {save_sphere_offset}"); + _logger.Info($"Underwater save sphere init at {save_sphere_offset}"); set(code_ptr, save_sphere_offset + 0x5A, AtelOp.JMP.build(0x0002)); // Always all options // Update region state. Also skips save sphere tutorial @@ -2197,7 +2250,7 @@ AtelOp.PUSHII .build( 0), save_sphere_offset = 0x3168; - logger.Info($"Underwater save sphere init at {save_sphere_offset}"); + _logger.Info($"Underwater save sphere init at {save_sphere_offset}"); set(code_ptr, save_sphere_offset + 0x5A, AtelOp.JMP.build(0x0002)); // Always all options // Update region state. Also skips save sphere tutorial @@ -2222,7 +2275,7 @@ AtelOp.PUSHII .build( 0), } else if (false && event_name == "stbv0100") { uint save_sphere_offset = 0xF07F; - logger.Info($"Save sphere init at {save_sphere_offset}"); + _logger.Info($"Save sphere init at {save_sphere_offset}"); set(code_ptr, save_sphere_offset + 0x48, AtelOp.JMP.build(0x0007)); // Always all options // Update region state. Also skips save sphere tutorial @@ -2247,7 +2300,7 @@ AtelOp.PUSHII .build( 0), save_sphere_offset = 0xFCF1; - logger.Info($"Save sphere init at {save_sphere_offset}"); + _logger.Info($"Save sphere init at {save_sphere_offset}"); set(code_ptr, save_sphere_offset + 0x48, AtelOp.JMP.build(0x0007)); // Always all options // Update region state. Also skips save sphere tutorial @@ -2288,7 +2341,7 @@ AtelOp.JMP .build(0x0000), AtelBasicWorker* save_sphere_worker_1 = Globals.Atel.current_controller->worker(0x13); // Custom switch save_sphere_worker_1->table_jump[1] = (uint)(customScriptHandles[6].AddrOfPinnedObject() - (nint)save_sphere_worker_1->code_ptr); - logger.Debug($"{save_sphere_worker_1->table_var[1].raw}"); + _logger.Debug($"{save_sphere_worker_1->table_var[1].raw}"); save_sphere_worker_1->table_var[1].raw = 0x0000000100000A98; AtelBasicWorker* save_sphere_worker_2 = Globals.Atel.current_controller->worker(0x14); @@ -2328,15 +2381,15 @@ AtelOp.JMP .build(0x0000), } else if (save_spheres_detected > 1) { // Potentially incorrect offsets - logger.Info("Potentially incorrect Save Sphere offsets"); + _logger.Info("Potentially incorrect Save Sphere offsets"); } save_spheres_detected++; - logger.Info($"Detected save sphere init at {i - 6}"); + _logger.Info($"Detected save sphere init at {i - 6}"); uint save_sphere_offset = i - 6; AtelOp someInst = (AtelOp)code_ptr[save_sphere_offset + sphere_level_offset]; if (!someInst.has_operand() || someInst.build(*(ushort*)(code_ptr + save_sphere_offset + sphere_level_offset + 1)) != AtelOp.PUSHV.build(0x0000)) { - logger.Warning($"Unexpected instruction at {save_sphere_offset + sphere_level_offset}"); + _logger.Warning($"Unexpected instruction at {save_sphere_offset + sphere_level_offset}"); } set(code_ptr, save_sphere_offset + sphere_level_offset, AtelOp.JMP.build(0x0007)); // Always all options @@ -2344,7 +2397,7 @@ AtelOp.JMP .build(0x0000), someInst = (AtelOp)code_ptr[save_sphere_offset + tutorial_offset + 13]; if (!someInst.has_operand() || someInst.build(*(ushort*)(code_ptr + save_sphere_offset + tutorial_offset + 13 + 1)) != AtelOp.POPXNCJMP.build(tutorial_jump)) { - logger.Warning($"Unexpected instruction at {save_sphere_offset + tutorial_offset + 13}"); + _logger.Warning($"Unexpected instruction at {save_sphere_offset + tutorial_offset + 13}"); } // Update region state. Also skips save sphere tutorial set(code_ptr, save_sphere_offset + tutorial_offset, [ @@ -2355,7 +2408,7 @@ AtelOp.JMP .build(tutorial_jump), someInst = (AtelOp)code_ptr[save_sphere_offset + airship_warp_offset]; if (!someInst.has_operand() || someInst.build(*(ushort*)(code_ptr + save_sphere_offset + airship_warp_offset + 1)) != AtelOp.PUSHV.build(0x0000)) { - logger.Warning($"Unexpected instruction at {save_sphere_offset + airship_warp_offset}"); + _logger.Warning($"Unexpected instruction at {save_sphere_offset + airship_warp_offset}"); } // Board Airship option set(code_ptr, save_sphere_offset + airship_warp_offset, [ @@ -2379,20 +2432,20 @@ AtelOp.PUSHII .build( 0), current_event_name = event_name; } - private static void h_Common_obtainTreasureInit(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + private void h_Common_obtainTreasureInit(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int treasure_id = atelStack->values.as_int()[1]; - logger.Info($"obtain_treasure: {treasure_id}"); + _logger.Info($"obtain_treasure: {treasure_id}"); //_Common_obtainTreasureInit.orig_fptr(work, storage, atelStack); obtainTreasureInitReimplement(work, storage, atelStack); } - private static void obtainTreasureInitReimplement(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + private void obtainTreasureInitReimplement(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { byte* item_name = (byte*)0; int treasure_id = atelStack->pop_int(); int window_id = atelStack->pop_int(); - logger.Debug($"window_id:{window_id}, treasure_id:{treasure_id}"); + _logger.Debug($"window_id:{window_id}, treasure_id:{treasure_id}"); _SndSepPlaySimple(0x80000026); AtelWorkerController* pAVar2 = (AtelWorkerController*)_AtelGetCurCtrlWork(); @@ -2404,14 +2457,13 @@ private static void obtainTreasureInitReimplement(AtelBasicWorker* work, int* st uint weapon_id = 0; byte* message_text = _FUN_008bda20(0x401d); // "Nothing" - if (item_locations.treasure.TryGetValue(treasure_id, out var item)) { - if (FFXArchipelagoClient.sendLocation(treasure_id, FFXArchipelagoClient.ArchipelagoLocationType.Treasure)) { + if (_client!.sendLocation(treasure_id, ArchipelagoClientModule.ArchipelagoLocationType.Treasure)) { obtain_item(item.id); NativeCustomString name = new NativeCustomString(item.id != 0 ? item.name : $"{item.name} to {item.player}", encodingFlags: FhEncodingFlags.IGNORE_EXPRESSIONS); //CustomString name = new CustomString(item.name, encodingFlags: FhEncodingFlags.IGNORE_EXPRESSIONS); - logger.Info(item.name); + _logger.Info(item.name); cached_strings.Add(name); item_name = name.encoded; @@ -2448,7 +2500,7 @@ private static void obtainTreasureInitReimplement(AtelBasicWorker* work, int* st int decoded_length = FhEncoding.decode(new ReadOnlySpan(item_name, 1000), decoded, flags:FhEncodingFlags.IMPLICIT_END); //string decoded = FhEncoding.Us.to_string(item_name); - logger.Info(Encoding.UTF8.GetString(decoded, 0, decoded_length)); + _logger.Info(Encoding.UTF8.GetString(decoded, 0, decoded_length)); _MsSaveItemUse(Battle.reward_data->items[0], Battle.reward_data->items_amounts[0]); } @@ -2478,7 +2530,7 @@ private static void obtainTreasureInitReimplement(AtelBasicWorker* work, int* st atelStack->push_int(4); _CT_RetInt_0065((nint)work, storage, (nint)atelStack); - delegates.TOMesWinWork* mesageWindowWorker = _AtelGetMesWinWork(window_id); + TOMesWinWork* mesageWindowWorker = _AtelGetMesWinWork(window_id); mesageWindowWorker->_0x20 = 0; mesageWindowWorker->text = message_text; mesageWindowWorker->_0xc = message_text; @@ -2501,14 +2553,14 @@ private static void obtainTreasureInitReimplement(AtelBasicWorker* work, int* st mesageWindowWorker->_0x1d |= 0x10; } - private static void h_Common_obtainTreasureSilentlyInit(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + private void h_Common_obtainTreasureSilentlyInit(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int treasure_id = atelStack->values.as_int()[0]; - logger.Info($"obtain_treasure_silently: {treasure_id}"); + _logger.Info($"obtain_treasure_silently: {treasure_id}"); //_Common_obtainTreasureSilentlyInit.orig_fptr(work, storage, atelStack); obtainTreasureSilentlyInitReimplement(work, storage, atelStack); } - private static void obtainTreasureSilentlyInitReimplement(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + private void obtainTreasureSilentlyInitReimplement(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int treasure_id = atelStack->pop_int(); _MsFieldItemGet(treasure_id); @@ -2516,7 +2568,7 @@ private static void obtainTreasureSilentlyInitReimplement(AtelBasicWorker* work, uint weapon_id = 0; if (item_locations.treasure.TryGetValue(treasure_id, out var item)) { - if (FFXArchipelagoClient.sendLocation(treasure_id, FFXArchipelagoClient.ArchipelagoLocationType.Treasure)) { + if (_client!.sendLocation(treasure_id, ArchipelagoClientModule.ArchipelagoLocationType.Treasure)) { obtain_item(item.id); } } @@ -2545,8 +2597,8 @@ private static void obtainTreasureSilentlyInitReimplement(AtelBasicWorker* work, } } - private static int h_Common_obtainBrotherhoodRetInt(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { - logger.Debug($"obtain_brotherhoodRetInt"); + private int h_Common_obtainBrotherhoodRetInt(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + _logger.Debug("obtain_brotherhoodRetInt"); if (atelStack->size > 0) { throw new Exception($"Too many parameters ({atelStack->size}) passed to obtainBrotherhood!"); } @@ -2556,8 +2608,8 @@ private static int h_Common_obtainBrotherhoodRetInt(AtelBasicWorker* work, int* } return _Common_obtainBrotherhoodRetInt.orig_fptr(work, storage, atelStack); } - private static int h_Common_upgradeBrotherhoodRetInt(nint work, int* storage, nint atelStack) { - logger.Debug($"upgrade_brotherhoodRetInt"); + private int h_Common_upgradeBrotherhoodRetInt(nint work, int* storage, nint atelStack) { + _logger.Debug("upgrade_brotherhoodRetInt"); if (item_locations.other.TryGetValue(37, out var item)) { obtain_item(item.id); return 1; @@ -2565,15 +2617,15 @@ private static int h_Common_upgradeBrotherhoodRetInt(nint work, int* storage, ni return _Common_upgradeBrotherhoodRetInt.orig_fptr(work, storage, atelStack); } - private static int h_Common_isBrotherhoodUnpoweredRetInt(nint work, int* storage, nint atelStack) { - logger.Debug($"isBrotherhoodUnpoweredRetInt"); + private int h_Common_isBrotherhoodUnpoweredRetInt(nint work, int* storage, nint atelStack) { + _logger.Debug("isBrotherhoodUnpoweredRetInt"); return _Common_isBrotherhoodUnpoweredRetInt.orig_fptr(work, storage, atelStack); } //private static int h_Common_grantCelestialUpgrade(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { // int character = atelStack->values.as_int()[0]; // int level = atelStack->values.as_int()[1]; - // logger.Debug($"grant_celestial_upgrade: character={id_to_character[character]}, level={level}"); + // _logger.Debug($"grant_celestial_upgrade: character={id_to_character[character]}, level={level}"); // // // if (0 <= character && character <= 6 && item_locations.other.TryGetValue(36 + level + character*2, out var item)) { @@ -2586,12 +2638,12 @@ private static int h_Common_isBrotherhoodUnpoweredRetInt(nint work, int* storage // return _Common_grantCelestialUpgrade.orig_fptr(work, storage, atelStack); //} - private static int h_TkSetLegendAbility(int chr_id, int level) { - logger.Debug($"grant_celestial_upgrade: character={id_to_character[chr_id]}, level={level}"); + private int h_TkSetLegendAbility(int chr_id, int level) { + _logger.Debug($"grant_celestial_upgrade: character={id_to_character[chr_id]}, level={level}"); int other_id = 37 + level + chr_id * 2; if (0 <= chr_id && chr_id <= 6 && item_locations.other.TryGetValue(other_id, out var item)) { - if (FFXArchipelagoClient.sendLocation(other_id, FFXArchipelagoClient.ArchipelagoLocationType.Other)) { + if (_client!.sendLocation(other_id, ArchipelagoClientModule.ArchipelagoLocationType.Other)) { obtain_item(item.id); } return level; @@ -2601,12 +2653,12 @@ private static int h_TkSetLegendAbility(int chr_id, int level) { } - private static int h_Common_setPrimerCollected(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + private int h_Common_setPrimerCollected(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int primer = atelStack->values.as_int()[0]; - logger.Debug($"set_primer_collected: Al Bhed Primer {primer + 1}"); + _logger.Debug($"set_primer_collected: Al Bhed Primer {primer + 1}"); if (item_locations.other.TryGetValue(primer + 1, out var item)) { - if (FFXArchipelagoClient.sendLocation(primer + 1, FFXArchipelagoClient.ArchipelagoLocationType.Other)) { + if (_client!.sendLocation(primer + 1, ArchipelagoClientModule.ArchipelagoLocationType.Other)) { obtain_item(item.id); } atelStack->pop_int(); @@ -2616,18 +2668,18 @@ private static int h_Common_setPrimerCollected(AtelBasicWorker* work, int* stora return _Common_setPrimerCollected.orig_fptr(work, storage, atelStack); } - private static void update_region_state() { + private void update_region_state() { update_region_state(save_data->current_room_id, save_data->current_spawnpoint); } - private static void update_region_state(int map, int entrance) { - logger.Info($"Update region state"); + private void update_region_state(int map, int entrance) { + _logger.Info("Update region state"); // Update region state - if (current_region != ArchipelagoData.RegionEnum.None && region_states.TryGetValue(current_region, out ArchipelagoData.ArchipelagoRegion? current_state)) { + if (current_region != RegionEnum.None && region_states.TryGetValue(current_region, out ArchipelagoRegion? current_state)) { current_state = region_states[current_region]; for (int i = 0; i < current_state.savedata.Length; i++) { - ref ArchipelagoData.ArchipelagoRegionSaveData data = ref current_state.savedata[i]; + ref ArchipelagoRegionSaveData data = ref current_state.savedata[i]; new Span((byte*)((int)save_data + data.offset), data.size).CopyTo(data.bytes); } @@ -2640,8 +2692,8 @@ private static void update_region_state(int map, int entrance) { } } - private static void restore_region_state(ref int map, ref int entrance) { - ArchipelagoData.ArchipelagoRegion current_state = region_states[current_region]; + private void restore_region_state(ref int map, ref int entrance) { + ArchipelagoRegion current_state = region_states[current_region]; save_data->story_progress = current_state.story_progress; map = current_state.room_id; entrance = (byte)current_state.entrance; @@ -2651,7 +2703,7 @@ private static void restore_region_state(ref int map, ref int entrance) { } } - private static void on_map_change() { + private void on_map_change() { int map = save_data->current_room_id; int entrance = save_data->current_spawnpoint; handle_warp_transition(save_data->last_room_id, save_data->last_spawnpoint, ref map, ref entrance); // We can ignore return value? @@ -2661,7 +2713,7 @@ private static void on_map_change() { save_data->current_spawnpoint = (byte)entrance; } } - private static bool handle_warp_transition(int current_map, int current_entrance, ref int next_map, ref int next_entrance) { + private bool handle_warp_transition(int current_map, int current_entrance, ref int next_map, ref int next_entrance) { if (next_map == -1) { // Loading a save next_map = save_data->saved_current_room_id; @@ -2671,20 +2723,20 @@ private static bool handle_warp_transition(int current_map, int current_entrance save_data->saved_current_spawnpoint = 0; if (id_to_regions.Contains(next_map)) { var regions = id_to_regions[next_map]; - ArchipelagoData.RegionEnum region = regions.Any(r => current_region == r) ? current_region : regions.Last(); + RegionEnum region = regions.Any(r => current_region == r) ? current_region : regions.Last(); current_region = region; restore_region_state(ref next_map, ref next_entrance); } } - if (id_to_regions.Contains(next_map)) { + if (id_to_regions.Contains(next_map)) { // New Game if (save_data->current_room_id == 0 && next_map == 132) { - current_region = ArchipelagoData.RegionEnum.DreamZanarkand; - FFXArchipelagoClient.local_checked_locations.Clear(); - FFXArchipelagoClient.received_items = 0; - FFXArchipelagoClient.remote_locations_updated = true; + current_region = RegionEnum.DreamZanarkand; + _client!.local_checked_locations.Clear(); + _client!.received_items = 0; + _client!.remote_locations_updated = true; // Load seed here? if (!loadSeed()) { next_map = 23; @@ -2695,6 +2747,7 @@ private static bool handle_warp_transition(int current_map, int current_entrance foreach (uint item in seed.Locations.StartingItems) obtain_item(item); OverdriveModule.OverdriveProvider.set_overdrive_modes(); } + if (seed.Options.SeedId is null) { // In-game with no seed next_map = 23; @@ -2704,40 +2757,39 @@ private static bool handle_warp_transition(int current_map, int current_entrance } var regions = id_to_regions[next_map]; - ArchipelagoData.RegionEnum region = regions.Any(r => current_region == r) ? current_region : regions.Last(); + RegionEnum region = regions.Any(r => current_region == r) ? current_region : regions.Last(); if (current_region != region) { next_map = 382; next_entrance = 0; return false; } - else { - // Skip crystal collecting - if (next_map == 324 && save_data->story_progress == 3250) { - logger.Info($"Skipping crystal collecting"); - next_map = 325; - next_entrance = 0; - save_data->story_progress = 3260; - return handle_warp_transition(current_map, current_entrance, ref next_map, ref next_entrance); - } + + // Skip crystal collecting + if (next_map == 324 && save_data->story_progress == 3250) { + _logger.Info("Skipping crystal collecting"); + next_map = 325; + next_entrance = 0; + save_data->story_progress = 3260; + return handle_warp_transition(current_map, current_entrance, ref next_map, ref next_entrance); } - } - else { + } else { if (next_map == 23) { - logger.Debug("Enter main menu"); + _logger.Debug("Enter main menu"); // Main Menu initalize_states(); seed = default; } + if (next_map == 382) update_region_state(current_map, current_entrance); // Airship Menu - current_region = ArchipelagoData.RegionEnum.None; + current_region = RegionEnum.None; skip_state_updates = false; } return true; } - private static void refill_inventory() { - logger.Debug($"Refill inventory"); + private void refill_inventory() { + _logger.Debug("Refill inventory"); foreach ((var item_id, var amount) in excess_inventory.ToList()) { if (amount > 0 && save_data->get_item_count((int)item_id) < 99) { @@ -2747,37 +2799,36 @@ private static void refill_inventory() { } } - private static int h_Common_transitionToMap(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + private int h_Common_transitionToMap(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { ref int map = ref atelStack->values.as_int()[0]; ref int entrance = ref atelStack->values.as_int()[1]; - logger.Debug($"transition_to_map: map={map}, entrance={entrance}"); + _logger.Debug($"transition_to_map: map={map}, entrance={entrance}"); if (handle_warp_transition(save_data->current_room_id, save_data->current_spawnpoint, ref map, ref entrance)) { return _Common_transitionToMap.orig_fptr(work, storage, atelStack); } - else { - return blockWarp(work, storage, atelStack); - } + + return blockWarp(work, storage, atelStack); } - private static int h_Common_warpToMap(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + private int h_Common_warpToMap(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { ref int map = ref atelStack->values.as_int()[0]; ref int entrance = ref atelStack->values.as_int()[1]; - logger.Debug($"warp_to_map: map={map}, entrance={entrance}"); + _logger.Debug($"warp_to_map: map={map}, entrance={entrance}"); // Skip intro if (map == 348) { - logger.Debug("Skip intro"); + _logger.Debug("Skip intro"); map = 23; } if (handle_warp_transition(save_data->current_room_id, save_data->current_spawnpoint, ref map, ref entrance)) { return _Common_warpToMap.orig_fptr(work, storage, atelStack); - } else { - return blockWarp(work, storage, atelStack); } + + return blockWarp(work, storage, atelStack); } - private static void h_SgEvent_showModularMenuInit(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + private void h_SgEvent_showModularMenuInit(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int menu = atelStack->values.as_int()[0]; int unknown1 = menu >> 24 & 0xFF; int menuType = menu >> 16 & 0xFF; @@ -2799,7 +2850,7 @@ private static void h_SgEvent_showModularMenuInit(AtelBasicWorker* work, int* st // TODO: Investigate why Magus Sisters naming menus (0x4008000F, 0x40080010, 0x40080011) need to be skipped if (menu == 0x40800001 || menu == 0x40800002 || menu == 0x40800003 || menu == 0x40800004 || menu == 0x40800005 || menu == 0x4008000F || menu == 0x40080010 || menu == 0x40080011) { - logger.Debug($"Skipping menu: type={menuTypeString}, index={index} {(unknown1 == 0x40 ? "" : $", Unknown1={unknown1}")} {(unknown2 == 0x00 ? "" : $", Unknown2={unknown2}")}"); + _logger.Debug($"Skipping menu: type={menuTypeString}, index={index} {(unknown1 == 0x40 ? "" : $", Unknown1={unknown1}")} {(unknown2 == 0x00 ? "" : $", Unknown2={unknown2}")}"); //FhUtil.set_at(0x00efbbf0, 0x40080000); //FhUtil.set_at(0x00efbbf4, 0xffffffff); atelStack->pop_int(); @@ -2808,15 +2859,15 @@ private static void h_SgEvent_showModularMenuInit(AtelBasicWorker* work, int* st } if (menuType == 0x80) { - logger.Info($"Unknown tutorial?"); + _logger.Info($"Unknown tutorial?"); } - logger.Info($"Opening menu: type={menuTypeString}, index={index} {(unknown1 == 0x40 ? "" : $", Unknown1={unknown1}")} {(unknown2 == 0x00 ? "" : $", Unknown2={unknown2}")}"); + _logger.Info($"Opening menu: type={menuTypeString}, index={index} {(unknown1 == 0x40 ? "" : $", Unknown1={unknown1}")} {(unknown2 == 0x00 ? "" : $", Unknown2={unknown2}")}"); _SgEvent_showModularMenuInit.orig_fptr(work, storage, atelStack); } - public static int h_Common_addPartyMember(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + public int h_Common_addPartyMember(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int character = atelStack->values.as_int()[0]; //if (!party_overridden && !(save_data->atel_is_push_member == 1)) { @@ -2830,7 +2881,8 @@ public static int h_Common_addPartyMember(AtelBasicWorker* work, int* storage, A return _Common_addPartyMember.orig_fptr(work, storage, atelStack); } - public static int h_Common_removePartyMember(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + + public int h_Common_removePartyMember(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int character = atelStack->values.as_int()[0]; //if (!party_overridden && !(save_data->atel_is_push_member == 1)) { @@ -2844,7 +2896,8 @@ public static int h_Common_removePartyMember(AtelBasicWorker* work, int* storage return _Common_removePartyMember.orig_fptr(work, storage, atelStack); } - public static int h_Common_removePartyMemberLongTerm(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + + public int h_Common_removePartyMemberLongTerm(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int character = atelStack->values.as_int()[0]; //if (!party_overridden && !(save_data->atel_is_push_member == 1)) { @@ -2858,10 +2911,11 @@ public static int h_Common_removePartyMemberLongTerm(AtelBasicWorker* work, int* return _Common_removePartyMemberLongTerm.orig_fptr(work, storage, atelStack); } - public static int h_Common_setWeaponInvisible(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + + public int h_Common_setWeaponInvisible(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int character = (byte)atelStack->values.as_int()[0]; int state = atelStack->values.as_int()[1]; - logger.Debug($"character={id_to_character[character]}, state={state}"); + _logger.Debug($"character={id_to_character[character]}, state={state}"); if (state != 0 && is_character_unlocked(character)) { atelStack->pop_int(); atelStack->pop_int(); @@ -2869,7 +2923,8 @@ public static int h_Common_setWeaponInvisible(AtelBasicWorker* work, int* storag } return _Common_setWeaponVisibilty.orig_fptr(work, storage, atelStack); } - public static int h_Common_putPartyMemberInSlot(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + + public int h_Common_putPartyMemberInSlot(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int slot = atelStack->values.as_int()[0]; int character = (byte)atelStack->values.as_int()[1]; //if (!party_overridden && !(save_data->atel_is_push_member == 1)) { @@ -2885,14 +2940,16 @@ public static int h_Common_putPartyMemberInSlot(AtelBasicWorker* work, int* stor return _Common_putPartyMemberInSlot.orig_fptr(work, storage, atelStack); } - public static int h_Common_pushParty(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + + public int h_Common_pushParty(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { //logger.Debug($"push_party"); //if (party_overridden) return _Common_pushParty.orig_fptr(work, storage, atelStack); //save_party(); return 0; } - public static int h_Common_popParty(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + + public int h_Common_popParty(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { //logger.Debug($"pop_party"); //if (party_overridden) return _Common_popParty.orig_fptr(work, storage, atelStack); @@ -2901,7 +2958,7 @@ public static int h_Common_popParty(AtelBasicWorker* work, int* storage, AtelSta } // TODO: Get function pointer instead of hook for most of these - public static void h_MsGetSavePartyMember(uint* param_1, uint* param_2, uint* param_3) { + public void h_MsGetSavePartyMember(uint* param_1, uint* param_2, uint* param_3) { //logger.Debug($"get_current_party_slots"); _MsGetSavePartyMember.orig_fptr(param_1, param_2, param_3); @@ -2909,23 +2966,23 @@ public static void h_MsGetSavePartyMember(uint* param_1, uint* param_2, uint* pa } // Pre-battle - public static void h_MsBattleExe(uint param_1, int field_idx, int group_idx, int formation_idx) { + public void h_MsBattleExe(uint param_1, int field_idx, int group_idx, int formation_idx) { // Evrae is 52, 0, 0 // Penance is 52, 1, 0 if (field_idx == 52 && group_idx == 1 && formation_idx == 0) { // Try to avoid getting Penance'd by setting the group to Evrae manually group_idx = 0; - logger.Info("Tried to avoid getting Penance'd!"); + _logger.Info("Tried to avoid getting Penance'd!"); } var field_ptr = Battle.btl->ptr_btl_bin_fields + field_idx * 0xe; - string field_name = Marshal.PtrToStringAnsi((nint)(field_ptr+6)); + string field_name = Marshal.PtrToStringAnsi((nint)(field_ptr+6))!; var group_ptr = _MsBtlListGroup(field_idx, group_idx); byte group_name = *(byte*)(group_ptr+5 + formation_idx * 2); string encounter_name = $"{field_name}_{group_name:00}"; - logger.Debug($"{encounter_name}: param_1={param_1}, ({field_idx}, {group_idx}, {formation_idx})"); + _logger.Debug($"{encounter_name}: param_1={param_1}, ({field_idx}, {group_idx}, {formation_idx})"); /* if (encounterToPartyDict.TryGetValue(encounter_name, out List characters)) { if (characters.Count > 0) { @@ -2937,10 +2994,9 @@ public static void h_MsBattleExe(uint param_1, int field_idx, int group_idx, int } } */ - if (encounterToActionDict.TryGetValue(encounter_name, out Action? action)) { - action(); - } - else { + if (encounterToActionDict.TryGetValue(encounter_name, out Action? action)) { + action(_client!, this); + } else { save_party(); // Probably? reset_party(); } @@ -2948,9 +3004,9 @@ public static void h_MsBattleExe(uint param_1, int field_idx, int group_idx, int } // Battle loop? - public static void h_FUN_00791820() { + public void h_FUN_00791820() { _FUN_00791820.orig_fptr(); - string encounter_name = Marshal.PtrToStringAnsi((nint)(&Battle.btl->field_name)); + string encounter_name = Marshal.PtrToStringAnsi((nint)(&Battle.btl->field_name))!; byte battle_end_type = Battle.btl->battle_end_type; byte battle_state = Battle.btl->battle_state; @@ -2968,36 +3024,36 @@ public static void h_FUN_00791820() { } switch (battle_end_type) { case 2: // Battle Victory - logger.Info($"Victory: type={battle_end_type}, encounter={encounter_name}"); - if (encounterVictoryActions.TryGetValue(encounter_name!, out Action? victoryAction)) { - victoryAction(); + _logger.Info($"Victory: type={battle_end_type}, encounter={encounter_name}"); + if (encounterVictoryActions.TryGetValue(encounter_name!, out Action? victoryAction)) { + victoryAction(_client!, this); } if (encounterToLocationDict.TryGetValue(encounter_name!, out int[]? boss_locations)) { foreach (int location_id in boss_locations) { // Sending all locations even if they don't exist - if (sendLocation(location_id, FFXArchipelagoClient.ArchipelagoLocationType.Boss) && item_locations.boss.TryGetValue(location_id, out var item)) { - ArchipelagoFFXModule.obtain_item(item.id); + if (_client!.sendLocation(location_id, ArchipelagoClientModule.ArchipelagoLocationType.Boss) && item_locations.boss.TryGetValue(location_id, out var item)) { + obtain_item(item.id); } } } break; case 3: // Battle Escape - logger.Info($"Escape: type={battle_end_type}, encounter={encounter_name}"); - if (encounterEscapeActions.TryGetValue(encounter_name!, out Action? escapeAction)) { - escapeAction(); + _logger.Info($"Escape: type={battle_end_type}, encounter={encounter_name}"); + if (encounterEscapeActions.TryGetValue(encounter_name!, out Action? escapeAction)) { + escapeAction(_client!, this); } break; default: - logger.Info($"Battle End: type={battle_end_type}, encounter={encounter_name}"); + _logger.Info($"Battle End: type={battle_end_type}, encounter={encounter_name}"); break; } } } - private static void* curr_pos_area_ptr = null; - public static byte h_MsBtlReadSetScene() { + private void* curr_pos_area_ptr = null; + public byte h_MsBtlReadSetScene() { byte result = _MsBtlReadSetScene.orig_fptr(); - logger.Info($"Battle Name: {Marshal.PtrToStringAnsi((nint)FhUtil.ptr_at(0xD2C25A))}"); + _logger.Info($"Battle Name: {Marshal.PtrToStringAnsi((nint)FhUtil.ptr_at(0xD2C25A))}"); //ref BtlAreas original_pos_struct = ref *Battle.btl->ptr_pos_def; BtlAreasHelper original_pos_struct = new BtlAreasHelper(Battle.btl->ptr_pos_def); if (original_pos_struct.areas.Length == 0) return result; @@ -3173,7 +3229,7 @@ public static byte h_MsBtlReadSetScene() { return result; } - public static int h_MsBtlGetPos(int param_1, Chr* chr, int btl_pos_a, int btl_pos_b, int btl_pos_c, Vector4* out_pos) { + public int h_MsBtlGetPos(int param_1, Chr* chr, int btl_pos_a, int btl_pos_b, int btl_pos_c, Vector4* out_pos) { // btl_pos_a: position group/set/area // btl_pos_b = 3: party_pos[btl_pos_c] // btl_pos_b = 4: aeon_pos[btl_pos_c] @@ -3186,8 +3242,8 @@ public static int h_MsBtlGetPos(int param_1, Chr* chr, int btl_pos_a, int btl_po return _MsBtlGetPos.orig_fptr(param_1, chr, btl_pos_a, btl_pos_b, btl_pos_c, out_pos); } - private static uint h_give_item(uint item_id, int amount) { - logger.Debug($"give_item: {amount} x {item_id}"); + private uint h_give_item(uint item_id, int amount) { + _logger.Debug($"give_item: {amount} x {item_id}"); int new_amount = (int)(save_data->get_item_count((int)item_id) + amount); if (new_amount > 99) { @@ -3199,41 +3255,46 @@ private static uint h_give_item(uint item_id, int amount) { return _FUN_007905a0.orig_fptr(item_id, amount); } - private static void h_TkMsImportantSet(uint param_1) { - logger.Debug($"give_key_item: {param_1}"); + + private void h_TkMsImportantSet(uint param_1) { + _logger.Debug($"give_key_item: {param_1}"); _TkMsImportantSet.orig_fptr(param_1); } - private static byte* h_read_from_bin(int param_1, short* param_2, int param_3) { - logger.Debug($"get_from_bin: {param_1}, {(int)param_2}, {param_3}"); - logger.Debug($"bin_pointers: {(uint)param_2}, {(uint)(*takara_pointer)}, {(uint)(*buki_get_pointer)}"); + + private byte* h_read_from_bin(int param_1, short* param_2, int param_3) { + _logger.Debug($"get_from_bin: {param_1}, {(int)param_2}, {param_3}"); + _logger.Debug($"bin_pointers: {(uint)param_2}, {(uint)(*takara_pointer)}, {(uint)(*buki_get_pointer)}"); if (param_2 == (short*)*takara_pointer) { - logger.Debug($"get_from_bin: takara.bin"); + _logger.Debug("get_from_bin: takara.bin"); } else if (param_2 == (short*)*buki_get_pointer) { - logger.Debug($"get_from_bin: buki_get.bin"); + _logger.Debug("get_from_bin: buki_get.bin"); } var result = _FUN_007ab890.orig_fptr(param_1, param_2, param_3); - logger.Debug($"get_from_bin: result = {((uint)result).ToString("X")}"); + _logger.Debug($"get_from_bin: result = {((uint)result).ToString("X")}"); return result; } - private static ushort h_get_weapon_name(Equipment* param_1) { - logger.Debug($"get_weapon_name: {(int)param_1}"); + + private ushort h_get_weapon_name(Equipment* param_1) { + _logger.Debug($"get_weapon_name: {(int)param_1}"); return _FUN_007a0d10.orig_fptr(param_1); } - private static void h_get_weapon_model(ushort name_id, byte owner, int unknown, ushort* model_id_pointer) { - logger.Debug($"get_weapon_model: {name_id}, {owner}, {unknown}, {*model_id_pointer}, "); + + private void h_get_weapon_model(ushort name_id, byte owner, int unknown, ushort* model_id_pointer) { + _logger.Debug($"get_weapon_model: {name_id}, {owner}, {unknown}, {*model_id_pointer}, "); _FUN_007a0c70.orig_fptr(name_id, owner, unknown, model_id_pointer); } - private static void h_obtain_treasure_cleanup(BtlRewardData* param_1, int param_2) { - logger.Debug($"obtain_treasure_cleanup"); + + private void h_obtain_treasure_cleanup(BtlRewardData* param_1, int param_2) { + _logger.Debug("obtain_treasure_cleanup"); _FUN_007993f0.orig_fptr(param_1, param_2); } - public static void obtain_item(uint item_id, int amount=-1) { + public void obtain_item(uint item_id, int amount=-1) { if (item_id == 0) return; var item_type = (item_id & 0xF000) >> 12; if (amount == -1) amount = (int)((item_id & 0xFF0000) >> 16); @@ -3244,16 +3305,16 @@ public static void obtain_item(uint item_id, int amount=-1) { // Key Item // Progressive Mirror - if (item_id == 0xA002 && Globals.save_data->key_items.get((int)item_id)) { + if (item_id == 0xA002 && save_data->key_items.get((int)item_id)) { //Globals.save_data->key_items.set((int)item_id, false); item_id = 0xA003; } // Al Bhed Primers - if (item_id == 0xA004 && Globals.save_data->key_items.get((int)item_id)) { + if (item_id == 0xA004 && save_data->key_items.get((int)item_id)) { for (byte i = 0; i < 26; i++) { - if (!Globals.save_data->unlocked_primers.get_bit(i)) + if (!save_data->unlocked_primers.get_bit(i)) { item_id += i; break; @@ -3266,13 +3327,13 @@ public static void obtain_item(uint item_id, int amount=-1) { save_data->jecht_spheres.collected_amount++; if (save_data->jecht_spheres.collected_amount >= 1) - OverdriveModule.send_overdrive(PlayerCommandId.PCOM_SHOOTING_STAR); + _overdrives!.send_overdrive(PlayerCommandId.PCOM_SHOOTING_STAR); if (save_data->jecht_spheres.collected_amount >= 3) - OverdriveModule.send_overdrive(PlayerCommandId.PCOM_BANISHING_BLADE); + _overdrives!.send_overdrive(PlayerCommandId.PCOM_BANISHING_BLADE); if (save_data->jecht_spheres.collected_amount >= 10) - OverdriveModule.send_overdrive(PlayerCommandId.PCOM_TORNADO); + _overdrives!.send_overdrive(PlayerCommandId.PCOM_TORNADO); } h_TkMsImportantSet(item_id); @@ -3287,7 +3348,7 @@ public static void obtain_item(uint item_id, int amount=-1) { //UnownedEquipment* weapon_data = (UnownedEquipment*)h_read_from_bin((int)item_id, (short*)(*buki_get_pointer), 0); if (!seed.Gear.TryGetValue((int)item_id, out ArchipelagoGear? gear)) { - logger.Error($"Gear {item_id} doesn't exist"); + _logger.Error($"Gear {item_id} doesn't exist"); break; } @@ -3306,7 +3367,7 @@ public static void obtain_item(uint item_id, int amount=-1) { //var data = get_from_bin((int)item_id, (short*)0x12000C00, 0); if (weapon_data.is_celestial) { - foreach (var equip in Globals.save_data->equipment) { + foreach (var equip in save_data->equipment) { if (equip.exists && equip.owner == weapon_data.owner && equip.is_celestial) { // Upgrade celestial if (celestial_level[equip.owner] < 2) { @@ -3317,7 +3378,7 @@ public static void obtain_item(uint item_id, int amount=-1) { } } } else if (weapon_data.is_brotherhood) { - foreach (ref var equip in Globals.save_data->equipment) { + foreach (ref var equip in save_data->equipment) { if (equip.exists && equip.is_brotherhood) { if (equip.is_hidden) { // Obtain @@ -3378,13 +3439,13 @@ public static void obtain_item(uint item_id, int amount=-1) { case 0xE: // Region Unlock item_id &= 0xff; - logger.Debug($"Region: {(ArchipelagoData.RegionEnum)item_id}"); - region_is_unlocked[(ArchipelagoData.RegionEnum)item_id] = true; + _logger.Debug($"Region: {(RegionEnum)item_id}"); + region_is_unlocked[(RegionEnum)item_id] = true; break; case 0xF: // Party Member int char_id = (int)(item_id & 0xFF); - logger.Debug($"Character: {id_to_character[char_id]}"); + _logger.Debug($"Character: {id_to_character[char_id]}"); unlocked_characters[char_id] = true; if (char_id == 0xF) { // Magus sisters @@ -3393,10 +3454,10 @@ public static void obtain_item(uint item_id, int amount=-1) { } save_party(); reset_party(); - if (seed.Options.GoalRequirement == ArchipelagoData.GoalRequirement.PartyMembers || seed.Options.GoalRequirement == ArchipelagoData.GoalRequirement.PartyMembersAndAeons) { + if (seed.Options.GoalRequirement == GoalRequirement.PartyMembers || seed.Options.GoalRequirement == GoalRequirement.PartyMembersAndAeons) { int num_unlocked; int num_required; - if (seed.Options.GoalRequirement == ArchipelagoData.GoalRequirement.PartyMembers) { + if (seed.Options.GoalRequirement == GoalRequirement.PartyMembers) { num_unlocked = unlocked_characters.Where(x => x.Key < 8 && x.Value).Count(); num_required = Math.Min(seed.Options.RequiredPartyMembers, 8); } else { @@ -3408,20 +3469,20 @@ public static void obtain_item(uint item_id, int amount=-1) { if (unlocked_characters.Count(x => x.Value) >= seed.Options.RequiredPartyMembers) { color = Color.Green; } - ArchipelagoGUI.add_log_message([(message, color)]); + _gui!.add_log_message([(message, color)]); } break; case 0x9: // Trap item_id &= 0xfff; - logger.Debug($"Trap: {item_id}"); + _logger.Debug($"Trap: {item_id}"); if (item_id == 0) { queued_voice_lines.Enqueue(voicelines[rng.Next(voicelines.Length)]); } break; case 0x3: // Overdrive - logger.Debug($"Overdrive: {item_id}"); + _logger.Debug($"Overdrive: {item_id}"); other_inventory.TryGetValue(item_id, out count); other_inventory[item_id] = count + 1; @@ -3450,15 +3511,16 @@ public static void obtain_item(uint item_id, int amount=-1) { break; case 0xC: // Other - logger.Debug($"Other: {item_id}"); + _logger.Debug($"Other: {item_id}"); other_inventory.TryGetValue(item_id, out count); other_inventory[item_id] = count+1; break; } } - private static Random rng = new Random(); - public static void call_obtain_brotherhood() { + private Random rng = new Random(); + + public void call_obtain_brotherhood() { AtelStack stack = new AtelStack(); int param_1 = 0; @@ -3467,7 +3529,7 @@ public static void call_obtain_brotherhood() { h_Common_obtainBrotherhoodRetInt((AtelBasicWorker*)¶m_1, ¶m_2, &stack); } - public static void receive_treasure(int id) { + public void receive_treasure(int id) { AtelStack stack = new AtelStack(); stack.push_int(id); @@ -3477,9 +3539,9 @@ public static void receive_treasure(int id) { _Common_obtainTreasureSilentlyInit.orig_fptr((AtelBasicWorker*)¶m_1, ¶m_2, &stack); } - public static void set_airship_destinations() { - logger.Debug("set_airship_destinations"); - AtelBasicWorker* worker = Globals.Atel.controllers[0].worker(0); + public void set_airship_destinations() { + _logger.Debug("set_airship_destinations"); + AtelBasicWorker* worker = Atel.controllers[0].worker(0); var var_table = worker->table_event_data; uint* airshipDestinationCount = &var_table[11]; uint* airshipDestinationLength = &var_table[12]; @@ -3505,9 +3567,9 @@ public static void set_airship_destinations() { // Sphere Grid Experiment - public static void h_eiAbmParaGet() { + public void h_eiAbmParaGet() { // TODO: Replace normal calculation with custom Archipelago-based calculation (if option enabled) - logger.Debug("Calculating stats"); + _logger.Debug("Calculating stats"); _eiAbmParaGet.orig_fptr(); //foreach (ref PlySave ply in save_data->ply_saves) { @@ -3518,8 +3580,8 @@ public static void h_eiAbmParaGet() { //} } - private static void h_MsSetRamChrParam(uint chr_id) { - logger.Debug($"MsSetRamChrParam: {chr_id}"); + private void h_MsSetRamChrParam(uint chr_id) { + _logger.Debug($"MsSetRamChrParam: {chr_id}"); _MsSetRamChrParam.orig_fptr(chr_id); Chr* chr = _MsGetChr(chr_id); @@ -3529,8 +3591,8 @@ private static void h_MsSetRamChrParam(uint chr_id) { } } - private static void h_MsSetSaveParam(uint chr_id) { - logger.Debug("Calculating base stats and equipment"); + private void h_MsSetSaveParam(uint chr_id) { + _logger.Debug("Calculating base stats and equipment"); _MsSetSaveParam.orig_fptr(chr_id); // Does nothing?? @@ -3593,14 +3655,14 @@ private static void h_MsSetSaveParam(uint chr_id) { //ply.mp = (uint)Math.Clamp(ply.mp * mp_mult / 100, 0, ply.auto_ability_effects.has_break_mp_limit ? 9999 : 999); } - public static void h_FUN_00a48910(uint chr_id, int node_idx) { + public void h_FUN_00a48910(uint chr_id, int node_idx) { // TODO: Send Archipelago location when node is unlocked (if option enabled) - logger.Debug($"Unlock node {node_idx} for {id_to_character[chr_id]}"); + _logger.Debug($"Unlock node {node_idx} for {id_to_character[chr_id]}"); _FUN_00a48910.orig_fptr(chr_id, node_idx); } - private static uint h_MsApUp(int chr_id, Chr* chr, int base_ap_add, uint param_4) { - logger.Debug($"AP gain: character={id_to_character[chr_id]}, ap={base_ap_add}"); + private uint h_MsApUp(int chr_id, Chr* chr, int base_ap_add, uint param_4) { + _logger.Debug($"AP gain: character={id_to_character[chr_id]}, ap={base_ap_add}"); int new_ap = (int)Math.Min(Math.BigMul(base_ap_add, ap_multiplier), 999_999_999); return _MsApUp.orig_fptr(chr_id, chr, new_ap, param_4); } @@ -3608,13 +3670,13 @@ private static uint h_MsApUp(int chr_id, Chr* chr, int base_ap_add, uint param_4 // Non-loading FMV - private static bool h_graphicInitFMVPlayer(int movie_id, int param_2) { + private bool h_graphicInitFMVPlayer(int movie_id, int param_2) { bool result = _graphicInitFMVPlayer.orig_fptr(movie_id, param_2); return !result; } // Texture experiments - private static void h_FUN_00656c90(int param_1, int param_2, char* fileName) { + private void h_FUN_00656c90(int param_1, int param_2, char* fileName) { //logger.Debug($"{param_1}, {param_2}, {(nint)fileName}"); // //string nameString = Marshal.PtrToStringAnsi((nint)fileName); @@ -3625,7 +3687,7 @@ private static void h_FUN_00656c90(int param_1, int param_2, char* fileName) { _FUN_00656c90.orig_fptr(param_1, param_2, fileName); } - private static void h_TkMenuAppearMainCmdWindow(int param_1, int param_2) { + private void h_TkMenuAppearMainCmdWindow(int param_1, int param_2) { // All menu options are enabled at progress 0 ushort progress = save_data->story_progress; save_data->story_progress = 0; @@ -3634,35 +3696,35 @@ private static void h_TkMenuAppearMainCmdWindow(int param_1, int param_2) { } // Voice related - //public static nint h_FMOD_EventSystem_load(nint param_1, nint file_path, nint param_3, nint param_4) { + //public nint h_FMOD_EventSystem_load(nint param_1, nint file_path, nint param_3, nint param_4) { // string path = Marshal.PtrToStringAnsi(file_path); // nint result = _FMOD_EventSystem_load.orig_fptr(param_1, file_path, param_3, param_4); - // logger.Debug($"{path}, {param_1}, {param_3} -> {result}"); + // _logger.Debug($"{path}, {param_1}, {param_3} -> {result}"); // return result; //} - public static void h_FfxFmod_soundInit_setLang(nint ffxFmod, int lang) { + public void h_FfxFmod_soundInit_setLang(nint ffxFmod, int lang) { _FfxFmod_soundInit_setLang.orig_fptr(ffxFmod, lang); *(byte*)(ffxFmod + 4) = 0; } // Unsure if there are side effects - public static void h_LocalizationManager_Initialize(delegates.FFXLocalizationManager* localizationManager) { + public void h_LocalizationManager_Initialize(FFXLocalizationManager* localizationManager) { _LocalizationManager_Initialize.orig_fptr(localizationManager); if (TextLanguage.HasValue) { - logger.Debug($"Text: {TextLanguage.Value}"); + _logger.Debug($"Text: {TextLanguage.Value}"); localizationManager->text = (int)TextLanguage; } if (VoiceLanguage.HasValue) { - logger.Debug($"Voice: {VoiceLanguage.Value}"); + _logger.Debug($"Voice: {VoiceLanguage.Value}"); localizationManager->video = (int)VoiceLanguage; localizationManager->voice = (int)VoiceLanguage; } } - public static int h_FmodVoice_dataChange(nint FmodVoice, int event_id, nint param_2) { - logger.Debug($"{FmodVoice}, {event_id}, {param_2}"); + public int h_FmodVoice_dataChange(nint FmodVoice, int event_id, nint param_2) { + _logger.Debug($"{FmodVoice}, {event_id}, {param_2}"); int result = _FmodVoice_dataChange.orig_fptr(FmodVoice, event_id, param_2); //string bank_name = "ffx_us_voice03"; // Contains "Stay away from the summoner!" (136815042) foreach (string bank_name in (string[])["ffx_us_voice03", "ffx_us_voice07", "ffx_us_voice11", "ffx_us_voice12", "ffx_us_voice20"]) { @@ -3678,12 +3740,12 @@ public static int h_FmodVoice_dataChange(nint FmodVoice, int event_id, nint para if (load_result == 0) { int* piVar5 = *(int**)bank; if (piVar5 != null) { - delegates.FMOD_Bank_Post_Load _FMOD_Bank_Post_Load = Marshal.GetDelegateForFunctionPointer(*(nint*)(*piVar5 + 8)); + FMOD_Bank_Post_Load _FMOD_Bank_Post_Load = Marshal.GetDelegateForFunctionPointer(*(nint*)(*piVar5 + 8)); nint s_voice = Marshal.StringToHGlobalAnsi("voice"); load_result = _FMOD_Bank_Post_Load((nint)piVar5, s_voice, 0, *(int*)(FmodVoice + 0xc) + bank_index*4); Marshal.FreeHGlobal(s_voice); - logger.Debug($"{bank_name}: {load_result}"); + _logger.Debug($"{bank_name}: {load_result}"); } } @@ -3692,11 +3754,11 @@ public static int h_FmodVoice_dataChange(nint FmodVoice, int event_id, nint para return result; } - public static Queue queued_voice_lines = []; - public static void play_voice_line(int voice_line) { + public Queue queued_voice_lines = []; + public void play_voice_line(int voice_line) { AtelStack stack = new AtelStack(); stack.push_int(voice_line); - logger.Debug($"stack_size = {stack.size}, voice_line = {stack.values.as_int()[0]}"); + _logger.Debug($"stack_size = {stack.size}, voice_line = {stack.values.as_int()[0]}"); int work = 0; int[] storage_array = [0,0,0,0]; @@ -3714,8 +3776,8 @@ public static void play_voice_line(int voice_line) { } - private static Dictionary item_name_cache = []; - public static string get_item_name(uint item_id) { + private Dictionary item_name_cache = []; + public string get_item_name(uint item_id) { if (item_name_cache.TryGetValue(item_id, out var name)) return name; byte* item_name; _TkMsGetRomItem(item_id, (int*)&item_name); @@ -3726,7 +3788,7 @@ public static string get_item_name(uint item_id) { return decoded_string; } - public static string get_other_item_name(uint item_id) { + public string get_other_item_name(uint item_id) { var item_type = (item_id & 0xF000) >> 0xC; var id = item_id & 0xFFF; @@ -3739,44 +3801,46 @@ public static string get_other_item_name(uint item_id) { return $"Unnamed item ({item_id})"; } - private static Dictionary cached_CT_Execs = new(); - private static Dictionary cached_CT_RetInts = new(); - private static Dictionary cached_CT_RetFloats = new(); - public static delegates.CT_Exec get_CT_Exec(int id) { + private Dictionary cached_CT_Execs = new(); + private Dictionary cached_CT_RetInts = new(); + private Dictionary cached_CT_RetFloats = new(); + + public CT_Exec get_CT_Exec(int id) { if (cached_CT_Execs.TryGetValue(id, out var result)) { return result; } AtelCallTargetNamespace nmsp = (AtelCallTargetNamespace)(id >> 0xC); AtelCallTarget* internal_ct = nmsp.get_internal() + (id & 0xFFF); - delegates.CT_Exec ct = Marshal.GetDelegateForFunctionPointer(internal_ct->ret_float_func); + CT_Exec ct = Marshal.GetDelegateForFunctionPointer(internal_ct->ret_float_func); cached_CT_Execs[id] = ct; return ct; } - public static delegates.CT_RetInt get_CT_RetInt(int id) { + + public CT_RetInt get_CT_RetInt(int id) { if (cached_CT_RetInts.TryGetValue(id, out var result)) { return result; } AtelCallTargetNamespace nmsp = (AtelCallTargetNamespace)(id >> 0xC); AtelCallTarget* internal_ct = nmsp.get_internal() + (id & 0xFFF); - delegates.CT_RetInt ct = Marshal.GetDelegateForFunctionPointer(internal_ct->ret_float_func); + CT_RetInt ct = Marshal.GetDelegateForFunctionPointer(internal_ct->ret_float_func); cached_CT_RetInts[id] = ct; return ct; } - public static delegates.CT_RetFloat get_CT_RetFloat(int id) { + + public CT_RetFloat get_CT_RetFloat(int id) { if (cached_CT_RetFloats.TryGetValue(id, out var result)) { return result; } AtelCallTargetNamespace nmsp = (AtelCallTargetNamespace)(id >> 0xC); AtelCallTarget* internal_ct = nmsp.get_internal() + (id & 0xFFF); - delegates.CT_RetFloat ct = Marshal.GetDelegateForFunctionPointer(internal_ct->ret_float_func); + CT_RetFloat ct = Marshal.GetDelegateForFunctionPointer(internal_ct->ret_float_func); cached_CT_RetFloats[id] = ct; return ct; } - // Custom namespace public void h_AtelInitTotal() { _logger.Debug("Initializing Atel namespaces"); @@ -3823,155 +3887,110 @@ enum CustomCallTarget : ushort { CHECK_UNLOCKED_AEONS, } - static AtelCallTarget[] customNameSpace = { - new() { ret_int_func = (nint)(delegate* unmanaged[Cdecl])(&CT_RetInt_PushInt)}, - new() { ret_int_func = (nint)(delegate* unmanaged[Cdecl])(&CT_RetInt_PushFloat)}, - new() { ret_int_func = (nint)(delegate* unmanaged[Cdecl])(&CT_RetInt_IsCharacterUnlocked)}, - new() { ret_int_func = (nint)(delegate* unmanaged[Cdecl])(&CT_RetInt_HasCelestialWeapon)}, - new() { ret_int_func = (nint)(delegate* unmanaged[Cdecl])(&CT_RetInt_IsOtherLocationChecked)}, - new() { ret_int_func = (nint)(delegate* unmanaged[Cdecl])(&CT_RetInt_IsTreasureLocationChecked)}, - new() { ret_int_func = (nint)(delegate* unmanaged[Cdecl])(&CT_RetInt_CollectedPrimers)}, - new() { ret_int_func = (nint)(delegate* unmanaged[Cdecl])(&CT_RetInt_SendOtherLocation)}, - new() { ret_int_func = (nint)(delegate* unmanaged[Cdecl])(&CT_RetInt_SendPartyMemberLocation)}, - new() { ret_int_func = (nint)(delegate* unmanaged[Cdecl])(&CT_RetInt_SendRecruitLocation)}, - new() { ret_int_func = (nint)(delegate* unmanaged[Cdecl])(&CT_RetInt_BlockWarp)}, - new() { ret_int_func = (nint)(delegate* unmanaged[Cdecl])(&CT_RetInt_blockKilikaBoatChoice)}, - new() { ret_int_func = (nint)(delegate* unmanaged[Cdecl])(&CT_RetInt_RestoreInteraction)}, - new() { ret_int_func = (nint)(delegate* unmanaged[Cdecl])(&CT_RetInt_SetAirshipDestinations)}, - new() { ret_int_func = (nint)(delegate* unmanaged[Cdecl])(&CT_RetInt_ShowAirshipDestinations)}, - new() { ret_int_func = (nint)(delegate* unmanaged[Cdecl])(&CT_RetInt_HideAirshipDestinations)}, - new() { ret_int_func = (nint)(delegate* unmanaged[Cdecl])(&CT_RetInt_ShowCurrentAirshipLocation)}, - new() { ret_int_func = (nint)(delegate* unmanaged[Cdecl])(&CT_RetInt_HideCurrentAirshipLocation)}, - new() { ret_int_func = (nint)(delegate* unmanaged[Cdecl])(&CT_RetInt_TransitionToRegion)}, - new() { ret_int_func = (nint)(delegate* unmanaged[Cdecl])(&CT_RetInt_Jump)}, - new() { ret_int_func = (nint)(delegate* unmanaged[Cdecl])(&CT_RetInt_JumpIfFalse)}, - new() { ret_int_func = (nint)(delegate* unmanaged[Cdecl])(&CT_RetInt_JumpIfTrue)}, - new() { ret_int_func = (nint)(delegate* unmanaged[Cdecl])(&CT_RetInt_Offset)}, - new() { ret_int_func = (nint)(delegate* unmanaged[Cdecl])(&CT_RetInt_OffsetIfFalse)}, - new() { ret_int_func = (nint)(delegate* unmanaged[Cdecl])(&CT_RetInt_OffsetIfTrue)}, - new() { ret_int_func = (nint)(delegate* unmanaged[Cdecl])(&CT_RetInt_UpdateRegionState)}, - new() { ret_int_func = (nint)(delegate* unmanaged[Cdecl])(&CT_RetInt_LockPartyMember)}, - new() { ret_int_func = (nint)(delegate* unmanaged[Cdecl])(&CT_RetInt_LockAllAeons)}, - new() { ret_int_func = (nint)(delegate* unmanaged[Cdecl])(&CT_RetInt_IsGoalUnlocked)}, - new() { ret_int_func = (nint)(delegate* unmanaged[Cdecl])(&CT_RetInt_ReplaceEntryPoint)}, - new() { ret_int_func = (nint)(delegate* unmanaged[Cdecl])(&CT_RetInt_RestoreEntryPoint)}, - new() { ret_int_func = (nint)(delegate* unmanaged[Cdecl])(&CT_RetInt_LightningDodging)}, - new() { ret_int_func = (nint)(delegate* unmanaged[Cdecl])(&CT_RetInt_JechtSphere)}, - new() { ret_int_func = (nint)(delegate* unmanaged[Cdecl])(&CT_RetInt_KickedBlitzballAway)}, - new() { ret_int_func = (nint)(delegate* unmanaged[Cdecl])(&CT_RetInt_CheckUnlockedAeons)}, - }; - static GCHandle customNameSpaceHandle = GCHandle.Alloc(customNameSpace, GCHandleType.Pinned); + private GCHandle customNameSpaceHandle; + private AtelCallTarget[] customNameSpace; + - [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] - public static int CT_RetInt_PushInt(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + public int CT_RetInt_PushInt(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int high = atelStack->pop_int(); int low = atelStack->pop_int(); int result = (high << 16) | low; - logger.Debug($"PushInt: ({high}, {low}) => {result}"); + _logger.Debug($"PushInt: ({high}, {low}) => {result}"); atelStack->push_int(result); return 1; } - [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] - public static int CT_RetInt_PushFloat(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + public int CT_RetInt_PushFloat(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { uint high = (uint)atelStack->pop_int() & 0xFFFF; uint low = (uint)atelStack->pop_int() & 0xFFFF; float result = BitConverter.Int32BitsToSingle((int)((high << 16) | low)); - logger.Debug($"PushFloat: ({high}, {low}) => {result}"); + _logger.Debug($"PushFloat: ({high}, {low}) => {result}"); atelStack->push_float(result); return 1; } - [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] - public static int CT_RetInt_IsCharacterUnlocked(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + public int CT_RetInt_IsCharacterUnlocked(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int character_id = atelStack->pop_int(); - logger.Debug($"IsCharacterUnlocked: {id_to_character[character_id]}"); + _logger.Debug($"IsCharacterUnlocked: {id_to_character[character_id]}"); return is_character_unlocked(character_id) ? 1 : 0; } - [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] - public static int CT_RetInt_HasCelestialWeapon(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + public int CT_RetInt_HasCelestialWeapon(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int character_id = atelStack->pop_int(); - logger.Debug($"HasCelestialWeapon: {id_to_character[character_id]}"); + _logger.Debug($"HasCelestialWeapon: {id_to_character[character_id]}"); - foreach (var equip in Globals.save_data->equipment) { + foreach (var equip in save_data->equipment) { if (equip.exists && equip.owner == character_id && equip.is_celestial) return 1; } return 0; } - [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] - public static int CT_RetInt_IsOtherLocationChecked(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + public int CT_RetInt_IsOtherLocationChecked(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int other_id = atelStack->pop_int(); - logger.Debug($"IsOtherLocationChecked: {other_id | (long)FFXArchipelagoClient.ArchipelagoLocationType.Other}"); + _logger.Debug($"IsOtherLocationChecked: {other_id | (long)ArchipelagoClientModule.ArchipelagoLocationType.Other}"); - return local_checked_locations.Contains(other_id | (long)FFXArchipelagoClient.ArchipelagoLocationType.Other) ? 1 : 0; + return _client!.local_checked_locations.Contains(other_id | (long)ArchipelagoClientModule.ArchipelagoLocationType.Other) ? 1 : 0; } - [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] - public static int CT_RetInt_IsTreasureLocationChecked(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + public int CT_RetInt_IsTreasureLocationChecked(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int other_id = atelStack->pop_int(); - logger.Debug($"IsTreasureLocationChecked: {other_id | (long)FFXArchipelagoClient.ArchipelagoLocationType.Treasure}"); + _logger.Debug($"IsTreasureLocationChecked: {other_id | (long)ArchipelagoClientModule.ArchipelagoLocationType.Treasure}"); - return local_checked_locations.Contains(other_id | (long)FFXArchipelagoClient.ArchipelagoLocationType.Treasure) ? 1 : 0; + return _client!.local_checked_locations.Contains(other_id | (long)ArchipelagoClientModule.ArchipelagoLocationType.Treasure) ? 1 : 0; } - [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] - public static int CT_RetInt_CollectedPrimers(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + public int CT_RetInt_CollectedPrimers(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int collected_primers = 0; for (int i = 0; i < 26; i++) { - collected_primers += Globals.save_data->unlocked_primers.get_bit(i) ? 1 : 0; + collected_primers += save_data->unlocked_primers.get_bit(i) ? 1 : 0; } - logger.Debug($"CollectedPrimers: {collected_primers}"); + _logger.Debug($"CollectedPrimers: {collected_primers}"); return collected_primers; } - [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] - public static int CT_RetInt_SendOtherLocation(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + public int CT_RetInt_SendOtherLocation(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int other_id = atelStack->pop_int(); - if (!FFXArchipelagoClient.local_checked_locations.Contains(other_id | (long)FFXArchipelagoClient.ArchipelagoLocationType.Other)) { + if (!(_client!.local_checked_locations.Contains(other_id | (long)ArchipelagoClientModule.ArchipelagoLocationType.Other))) { if (ArchipelagoFFXModule.item_locations.other.TryGetValue(other_id, out var item)) { - if (FFXArchipelagoClient.sendLocation(other_id, FFXArchipelagoClient.ArchipelagoLocationType.Other)) { - ArchipelagoFFXModule.obtain_item(item.id); + if (_client!.sendLocation(other_id, ArchipelagoClientModule.ArchipelagoLocationType.Other)) { + obtain_item(item.id); } } } return 1; } - [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] - public static int CT_RetInt_SendPartyMemberLocation(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + public int CT_RetInt_SendPartyMemberLocation(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int partyMember_id = atelStack->pop_int(); - if (!FFXArchipelagoClient.local_checked_locations.Contains(partyMember_id | (long)FFXArchipelagoClient.ArchipelagoLocationType.PartyMember)) { + if (!(_client!.local_checked_locations.Contains(partyMember_id | (long)ArchipelagoClientModule.ArchipelagoLocationType.PartyMember))) { if (ArchipelagoFFXModule.item_locations.party_member.TryGetValue(partyMember_id, out var item)) { - if (FFXArchipelagoClient.sendLocation(partyMember_id, FFXArchipelagoClient.ArchipelagoLocationType.PartyMember)) { - ArchipelagoFFXModule.obtain_item(item.id); + if (_client!.sendLocation(partyMember_id, ArchipelagoClientModule.ArchipelagoLocationType.PartyMember)) { + obtain_item(item.id); } } } return 1; } - [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] - public static int CT_RetInt_SendRecruitLocation(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + public int CT_RetInt_SendRecruitLocation(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int recruit_id = atelStack->pop_int(); - if (!FFXArchipelagoClient.local_checked_locations.Contains(recruit_id | (long)FFXArchipelagoClient.ArchipelagoLocationType.Recruit)) { + if (!(_client!.local_checked_locations.Contains(recruit_id | (long)ArchipelagoClientModule.ArchipelagoLocationType.Recruit))) { if (ArchipelagoFFXModule.item_locations.recruit.TryGetValue(recruit_id, out var item)) { - if (FFXArchipelagoClient.sendLocation(recruit_id, FFXArchipelagoClient.ArchipelagoLocationType.Recruit)) { - ArchipelagoFFXModule.obtain_item(item.id); + if (_client!.sendLocation(recruit_id, ArchipelagoClientModule.ArchipelagoLocationType.Recruit)) { + obtain_item(item.id); } } } return 1; } - public static int atelTurnAround(Span dest, float x, float y, float z, ushort current_worker, ushort target_worker, ushort entry_point, float movementSpeed = 34.0f, float rotationSpeed1 = 0.10471976f, float rotationSpeed2 = 0.17453294f) { - logger?.Debug($"x={x}, y={y}, z={z}"); + public int atelTurnAround(Span dest, float x, float y, float z, ushort current_worker, ushort target_worker, ushort entry_point, float movementSpeed = 34.0f, float rotationSpeed1 = 0.10471976f, float rotationSpeed2 = 0.17453294f) { + _logger.Debug($"x={x}, y={y}, z={z}"); uint rotationFlags = 0x0000D002; uint motionFlags = 0x0000C001; byte[] script = ((AtelInst[])[ // 5 @@ -4049,46 +4068,42 @@ AtelOp.RET .build( ), } return script.Length; } - private static int turnAroundScriptLength = atelTurnAround(Span.Empty, 0, 0, 0, 0, 0, 0); - private static byte* turnAroundScript = (byte*)NativeMemory.AllocZeroed((uint)turnAroundScriptLength); - private static bool savedCrossInteractionStatus; - private static byte savedInteractionFlags; + private bool savedCrossInteractionStatus; + private byte savedInteractionFlags; - [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] - public static int CT_RetInt_BlockWarp(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + public int CT_RetInt_BlockWarp(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { return blockWarp(work, storage, atelStack); } - [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] - public static int CT_RetInt_blockKilikaBoatChoice(AtelBasicWorker* worker, int* storage, AtelStack* stack) { + public int CT_RetInt_BlockKilikaBoatChoice(AtelBasicWorker* worker, int* storage, AtelStack* stack) { return blockKilikaBoatChoice(worker, storage, stack); } - public static int blockWarp(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + public int blockWarp(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int entrance = atelStack->pop_int(); int map = atelStack->pop_int(); - logger.Info($"Exit leads to other Region!"); + _logger.Info("Exit leads to other Region!"); - Chr* tidus = (Chr*)((int)Globals.Atel.controllers[0].worker(0) + 0x9c); + Chr* tidus = (Chr*)((int)Atel.controllers[0].worker(0) + 0x9c); if (tidus != null && tidus->actor != null) { Vector3 playerPos = tidus->actor->chr_pos_vec.AsVector3(); - var entrances = Globals.Atel.controllers[0].worker(0)->script_chunk->map_entrances.ToArray(); - var closestEntrance = Globals.Atel.controllers[0].worker(0)->script_chunk->map_entrances.ToArray() + var entrances = Atel.controllers[0].worker(0)->script_chunk->map_entrances.ToArray(); + var closestEntrance = Atel.controllers[0].worker(0)->script_chunk->map_entrances.ToArray() .Select((e, i) => new {Index=i, Entrance=e, Distance=(playerPos - e.pos).Length()}) .MinBy(tuple => tuple.Distance); if (closestEntrance?.Distance < 200) { - logger.Debug($"Entrance within 200: pos:({closestEntrance.Entrance.x}, {closestEntrance.Entrance.y}, {closestEntrance.Entrance.z}) distance:{closestEntrance.Distance}"); + _logger.Debug($"Entrance within 200: pos:({closestEntrance.Entrance.x}, {closestEntrance.Entrance.y}, {closestEntrance.Entrance.z}) distance:{closestEntrance.Distance}"); Vector3 target_pos = closestEntrance.Entrance.pos; - ushort entry_point = (ushort)(Globals.Atel.controllers[0].worker(0)->script_header->entry_point_count - 1); + ushort entry_point = (ushort)(Atel.controllers[0].worker(0)->script_header->entry_point_count - 1); if (turnAroundScript == null) turnAroundScript = (byte*)NativeMemory.AllocZeroed((uint)turnAroundScriptLength); atelTurnAround(new Span(turnAroundScript, turnAroundScriptLength), target_pos.X, target_pos.Y, target_pos.Z, work->worker_idx, 0, entry_point, 17, 1f, 1f); - AtelBasicWorker* targetWorker = Globals.Atel.controllers[0].worker(0); + AtelBasicWorker* targetWorker = Atel.controllers[0].worker(0); if (!originalEntryPoints.ContainsKey((0, entry_point))) { originalEntryPoints[(0, entry_point)] = targetWorker->table_entry_points[entry_point]; } @@ -4112,17 +4127,17 @@ public static int blockWarp(AtelBasicWorker* work, int* storage, AtelStack* atel //_FUN_008671d0((byte)AtelOp.REQ & 0x7F, &work->threads[work->current_thread_priority], work, atelStack); return 1; } - logger.Debug($"Closest entrance: pos:({closestEntrance?.Entrance.x}, {closestEntrance?.Entrance.y}, {closestEntrance?.Entrance.z}) distance:{closestEntrance?.Distance}"); + _logger.Debug($"Closest entrance: pos:({closestEntrance?.Entrance.x}, {closestEntrance?.Entrance.y}, {closestEntrance?.Entrance.z}) distance:{closestEntrance?.Distance}"); } + // Warp atelStack->push_int(382); atelStack->push_int(0); h_Common_warpToMap(work, storage, atelStack); return 1; - } - public static int blockKilikaBoatChoice(AtelBasicWorker* worker, int* storage, AtelStack* stack) { + public int blockKilikaBoatChoice(AtelBasicWorker* worker, int* storage, AtelStack* stack) { uint choice = (uint)worker->current_thread.reg_a; if (choice == 0) { @@ -4135,22 +4150,20 @@ public static int blockKilikaBoatChoice(AtelBasicWorker* worker, int* storage, A return 1; } - [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] - public static int CT_RetInt_RestoreInteraction(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + public int CT_RetInt_RestoreInteraction(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int target_worker_index = atelStack->pop_int(); - AtelBasicWorker* target_worker = Globals.Atel.controllers[0].worker(target_worker_index); + AtelBasicWorker* target_worker = Atel.controllers[0].worker(target_worker_index); //if (savedCrossInteractionStatus) target_worker->field_interaction_flags |= 1 << 2; // Enable cross interaction target_worker->field_interaction_flags = savedInteractionFlags; return 1; } - [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] - public static int CT_RetInt_SetAirshipDestinations(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + public int CT_RetInt_SetAirshipDestinations(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { set_airship_destinations(); return 1; } - [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] - public static int CT_RetInt_ShowAirshipDestinations(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + + public int CT_RetInt_ShowAirshipDestinations(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { var var_table = work->table_event_data; uint* airshipDestinations = &var_table[13]; uint airshipDestinationsOffset = var_table[50]; @@ -4171,17 +4184,15 @@ public static int CT_RetInt_ShowAirshipDestinations(AtelBasicWorker* work, int* return 1; } - [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] - public static int CT_RetInt_HideAirshipDestinations(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + public int CT_RetInt_HideAirshipDestinations(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { for (uint i = 0; i < 15; i++) { customStringDrawInfos.Remove($"destination {i}"); } return 1; } - [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] - public static int CT_RetInt_ShowCurrentAirshipLocation(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { - logger.Debug("ShowCurrentAirshipLocation"); + public int CT_RetInt_ShowCurrentAirshipLocation(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + _logger.Debug("ShowCurrentAirshipLocation"); customStringDrawInfos[$"current destination"] = new CustomStringDrawInfo(airship_destination_names[save_data->current_airship_location], new(52f, 73f), 1f); // AE0300 D80F80 call Map.?show2DLayer [800Fh](layerIndex=3 [03h]); @@ -4190,9 +4201,8 @@ public static int CT_RetInt_ShowCurrentAirshipLocation(AtelBasicWorker* work, in return 1; } - [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] - public static int CT_RetInt_HideCurrentAirshipLocation(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { - logger.Debug("HideCurrentAirshipLocation"); + public int CT_RetInt_HideCurrentAirshipLocation(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + _logger.Debug("HideCurrentAirshipLocation"); customStringDrawInfos.Remove($"current destination"); // AE0300 D81080 call Map.?hide2DLayer [8010h](layerIndex=3 [03h]); @@ -4201,24 +4211,23 @@ public static int CT_RetInt_HideCurrentAirshipLocation(AtelBasicWorker* work, in return 1; } - [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] - public static int CT_RetInt_TransitionToRegion(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { - ArchipelagoData.RegionEnum region = (ArchipelagoData.RegionEnum)atelStack->pop_int(); + public int CT_RetInt_TransitionToRegion(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + RegionEnum region = (RegionEnum)atelStack->pop_int(); - if (current_region != ArchipelagoData.RegionEnum.None) { + if (current_region != RegionEnum.None) { update_region_state(); - current_region = ArchipelagoData.RegionEnum.None; + current_region = RegionEnum.None; skip_state_updates = false; } current_region = region; int map = 0, entrance = 0; restore_region_state(ref map, ref entrance); - logger.Debug($"Entering {region}: map={map}, entrance={entrance}"); + _logger.Debug($"Entering {region}: map={map}, entrance={entrance}"); // Unlock locked characters. May not be necessary - foreach (var character in ArchipelagoFFXModule.locked_characters) { - ArchipelagoFFXModule.locked_characters[character.Key] = false; + foreach (var character in locked_characters) { + locked_characters[character.Key] = false; } save_party(); reset_party(); @@ -4230,14 +4239,13 @@ public static int CT_RetInt_TransitionToRegion(AtelBasicWorker* work, int* stora return 1; } - [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] - public static int CT_RetInt_Jump(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + public int CT_RetInt_Jump(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int jump_index = atelStack->pop_int(); work->current_thread.pc = (byte*)customScriptHandles[jump_index].AddrOfPinnedObject() - 3; return 1; } - [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] - public static int CT_RetInt_JumpIfFalse(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + + public int CT_RetInt_JumpIfFalse(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int jump_index = atelStack->pop_int(); int val = atelStack->pop_int(); if (val == 0) { @@ -4245,8 +4253,8 @@ public static int CT_RetInt_JumpIfFalse(AtelBasicWorker* work, int* storage, Ate } return 1; } - [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] - public static int CT_RetInt_JumpIfTrue(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + + public int CT_RetInt_JumpIfTrue(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int jump_index = atelStack->pop_int(); int val = atelStack->pop_int(); if (val == 1) { @@ -4254,14 +4262,14 @@ public static int CT_RetInt_JumpIfTrue(AtelBasicWorker* work, int* storage, Atel } return 1; } - [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] - public static int CT_RetInt_Offset(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + + public int CT_RetInt_Offset(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int offset = atelStack->pop_int(); work->current_thread.pc += offset - 3; return 1; } - [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] - public static int CT_RetInt_OffsetIfFalse(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + + public int CT_RetInt_OffsetIfFalse(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int offset = atelStack->pop_int(); int val = atelStack->pop_int(); if (val == 0) { @@ -4269,8 +4277,8 @@ public static int CT_RetInt_OffsetIfFalse(AtelBasicWorker* work, int* storage, A } return 1; } - [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] - public static int CT_RetInt_OffsetIfTrue(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + + public int CT_RetInt_OffsetIfTrue(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int offset = atelStack->pop_int(); int val = atelStack->pop_int(); if (val == 1) { @@ -4278,23 +4286,23 @@ public static int CT_RetInt_OffsetIfTrue(AtelBasicWorker* work, int* storage, At } return 1; } - [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] - public static int CT_RetInt_UpdateRegionState(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { - Vector3 playerPos = Globals.actors->chr_pos_vec.AsVector3(); - var closestEntrance = Globals.Atel.controllers[0].worker(0)->script_chunk->map_entrances.ToArray() + + public int CT_RetInt_UpdateRegionState(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + Vector3 playerPos = actors->chr_pos_vec.AsVector3(); + var closestEntrance = Atel.controllers[0].worker(0)->script_chunk->map_entrances.ToArray() .Select((entrance, index) => new {Index=index, Entrance=entrance, Distance=(playerPos - entrance.pos).Length()}) .MinBy(tuple => tuple.Distance); if (closestEntrance?.Distance < 100) { save_data->current_spawnpoint = (byte)closestEntrance.Index; - logger.Debug($"Entrance within 100: pos:({closestEntrance.Entrance.x}, {closestEntrance.Entrance.y}, {closestEntrance.Entrance.z}) distance:{closestEntrance.Distance}"); + _logger.Debug($"Entrance within 100: pos:({closestEntrance.Entrance.x}, {closestEntrance.Entrance.y}, {closestEntrance.Entrance.z}) distance:{closestEntrance.Distance}"); } update_region_state(save_data->current_room_id, save_data->current_spawnpoint); refill_inventory(); return 1; } - [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] - public static int CT_RetInt_LockPartyMember(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + + public int CT_RetInt_LockPartyMember(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int party_member = atelStack->pop_int(); locked_characters[party_member] = true; if (party_member == PlySaveId.PC_MAGUS1) { @@ -4303,45 +4311,48 @@ public static int CT_RetInt_LockPartyMember(AtelBasicWorker* work, int* storage, } return 1; } - [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] - public static int CT_RetInt_LockAllAeons(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + + public int CT_RetInt_LockAllAeons(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { for (int chr_id = PlySaveId.PC_VALEFOR; chr_id <= PlySaveId.PC_MAGUS3; chr_id++) { locked_characters[chr_id] = true; } + return 1; } - [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] - public static int CT_RetInt_IsGoalUnlocked(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + + public int CT_RetInt_IsGoalUnlocked(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { bool goal_requirement = false; bool primer_requirement = false; switch (seed.Options.GoalRequirement) { - case ArchipelagoData.GoalRequirement.None: + case GoalRequirement.None: goal_requirement = true; break; - case ArchipelagoData.GoalRequirement.PartyMembers: - if (unlocked_characters.Where(x => x.Key < 8 && x.Value).Count() >= Math.Min(seed.Options.RequiredPartyMembers, 8)) + case GoalRequirement.PartyMembers: + if (unlocked_characters.Count(x => x.Key < 8 && x.Value) >= Math.Min(seed.Options.RequiredPartyMembers, 8)) goal_requirement = true; //if (unlocked_characters.All(c => c.Value)) { // return 1; //} break; - case ArchipelagoData.GoalRequirement.PartyMembersAndAeons: - if (unlocked_characters.Where(x => x.Key < 16 && x.Value).Count() >= seed.Options.RequiredPartyMembers) + case GoalRequirement.PartyMembersAndAeons: + if (unlocked_characters.Count(x => x.Key < 16 && x.Value) >= seed.Options.RequiredPartyMembers) goal_requirement = true; break; - case ArchipelagoData.GoalRequirement.Pilgrimage: - if (local_checked_locations.Contains(8 | (long)FFXArchipelagoClient.ArchipelagoLocationType.PartyMember) && - local_checked_locations.Contains(9 | (long)FFXArchipelagoClient.ArchipelagoLocationType.PartyMember) && - local_checked_locations.Contains(10 | (long)FFXArchipelagoClient.ArchipelagoLocationType.PartyMember) && - local_checked_locations.Contains(11 | (long)FFXArchipelagoClient.ArchipelagoLocationType.PartyMember) && - local_checked_locations.Contains(12 | (long)FFXArchipelagoClient.ArchipelagoLocationType.PartyMember) && - local_checked_locations.Contains(37 | (long)FFXArchipelagoClient.ArchipelagoLocationType.Boss)) { + case GoalRequirement.Pilgrimage: + if ( + _client!.local_checked_locations.Contains(8 | (long)ArchipelagoClientModule.ArchipelagoLocationType.PartyMember) + && _client!.local_checked_locations.Contains(9 | (long)ArchipelagoClientModule.ArchipelagoLocationType.PartyMember) + && _client!.local_checked_locations.Contains(10 | (long)ArchipelagoClientModule.ArchipelagoLocationType.PartyMember) + && _client!.local_checked_locations.Contains(11 | (long)ArchipelagoClientModule.ArchipelagoLocationType.PartyMember) + && _client!.local_checked_locations.Contains(12 | (long)ArchipelagoClientModule.ArchipelagoLocationType.PartyMember) + && _client!.local_checked_locations.Contains(37 | (long)ArchipelagoClientModule.ArchipelagoLocationType.Boss) + ) { goal_requirement = true; } break; - case ArchipelagoData.GoalRequirement.Nemesis: - if (local_checked_locations.Contains(83 | (long)FFXArchipelagoClient.ArchipelagoLocationType.Boss)) { + case GoalRequirement.Nemesis: + if (_client!.local_checked_locations.Contains(83 | (long)ArchipelagoClientModule.ArchipelagoLocationType.Boss)) { goal_requirement = true; } break; @@ -4350,7 +4361,7 @@ public static int CT_RetInt_IsGoalUnlocked(AtelBasicWorker* work, int* storage, if (seed.Options.RequiredPrimers > 0) { int collected_primers = 0; for (int i = 0; i < 26; i++) { - collected_primers += Globals.save_data->unlocked_primers.get_bit(i) ? 1 : 0; + collected_primers += save_data->unlocked_primers.get_bit(i) ? 1 : 0; } if (collected_primers >= seed.Options.RequiredPrimers) @@ -4362,13 +4373,13 @@ public static int CT_RetInt_IsGoalUnlocked(AtelBasicWorker* work, int* storage, return goal_requirement && primer_requirement ? 1 : 0; } - [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] - public static int CT_RetInt_ReplaceEntryPoint(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + + public int CT_RetInt_ReplaceEntryPoint(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int script_index = atelStack->pop_int(); int entryPoint = atelStack->pop_int(); int workerIndex = atelStack->pop_int(); - AtelBasicWorker* targetWorker = Globals.Atel.controllers[0].worker(workerIndex); + AtelBasicWorker* targetWorker = Atel.controllers[0].worker(workerIndex); if (!originalEntryPoints.ContainsKey((workerIndex, entryPoint))) { originalEntryPoints[(workerIndex, entryPoint)] = targetWorker->table_entry_points[entryPoint]; @@ -4381,18 +4392,17 @@ public static int CT_RetInt_ReplaceEntryPoint(AtelBasicWorker* work, int* storag targetWorker->table_entry_points[entryPoint] = (uint)addressOffset; return 1; } - [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] - public static int CT_RetInt_RestoreEntryPoint(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + + public int CT_RetInt_RestoreEntryPoint(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int entryPoint = atelStack->pop_int(); int workerIndex = atelStack->pop_int(); if (originalEntryPoints.TryGetValue((workerIndex, entryPoint), out uint value)) { - Globals.Atel.controllers[0].worker(workerIndex)->table_entry_points[entryPoint] = value; + Atel.controllers[0].worker(workerIndex)->table_entry_points[entryPoint] = value; } return 1; } - [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] - public static int CT_RetInt_LightningDodging(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + public int CT_RetInt_LightningDodging(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int southNorth = atelStack->pop_int(); ushort highestDodged = save_data->lightning_dodging_highest_consecutive_dodges; byte* table = (byte*)work->table_event_data; @@ -4419,27 +4429,26 @@ public static int CT_RetInt_LightningDodging(AtelBasicWorker* work, int* storage string currentString = $"Dodged: {current}"; customStringDrawInfos["Lightning Streak"] = new CustomStringDrawInfo(new ManagedCustomString(currentString), new(40f, 140f), 0.5f); - logger.Info($"Lightning Dodged: {current}"); + _logger.Info($"Lightning Dodged: {current}"); if (current > save_data->lightning_dodging_highest_consecutive_dodges) highestDodged = (ushort)current; string highestString = $"Highest: {highestDodged}"; customStringDrawInfos["Lightning Highest Streak"] = new CustomStringDrawInfo(new ManagedCustomString(highestString), new(40f, 150f), 0.5f); - logger.Info($"Highest Consecutive Dodged: {highestDodged}"); + _logger.Info($"Highest Consecutive Dodged: {highestDodged}"); return *dodged == 1 ? 1 : 0; } - [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] - public static int CT_RetInt_JechtSphere(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + public int CT_RetInt_JechtSphere(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int jecht_sphere = atelStack->pop_int(); int other_id = atelStack->pop_int(); - if (!FFXArchipelagoClient.local_checked_locations.Contains(other_id | (long)FFXArchipelagoClient.ArchipelagoLocationType.Other)) { + if (!(_client!.local_checked_locations.Contains(other_id | (long)ArchipelagoClientModule.ArchipelagoLocationType.Other))) { if (ArchipelagoFFXModule.item_locations.other.TryGetValue(other_id, out var item)) { - if (FFXArchipelagoClient.sendLocation(other_id, FFXArchipelagoClient.ArchipelagoLocationType.Other)) { - ArchipelagoFFXModule.obtain_item(item.id); + if (_client!.sendLocation(other_id, ArchipelagoClientModule.ArchipelagoLocationType.Other)) { + obtain_item(item.id); } } } @@ -4448,39 +4457,33 @@ public static int CT_RetInt_JechtSphere(AtelBasicWorker* work, int* storage, Ate return 1; } - [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] - public static int CT_RetInt_KickedBlitzballAway(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + public int CT_RetInt_KickedBlitzballAway(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { byte* table = (byte*)work->table_event_data; table[0x0008] = 1; int treasure_id = 312; - if (!FFXArchipelagoClient.local_checked_locations.Contains(treasure_id | (long)FFXArchipelagoClient.ArchipelagoLocationType.Treasure)) - { - if (ArchipelagoFFXModule.item_locations.treasure.TryGetValue(treasure_id, out var item)) - { - lock (client_lock) - { - if (FFXArchipelagoClient.is_connected) - { - FFXArchipelagoClient.current_session!.Locations.ScoutLocationsAsync(Archipelago.MultiClient.Net.Enums.HintCreationPolicy.CreateAndAnnounceOnce, - treasure_id | (long)FFXArchipelagoClient.ArchipelagoLocationType.Treasure); + if (!(_client!.local_checked_locations.Contains(treasure_id | (long)ArchipelagoClientModule.ArchipelagoLocationType.Treasure))) { + if (ArchipelagoFFXModule.item_locations.treasure.TryGetValue(treasure_id, out var item)) { + lock (_client!.client_lock) { + if (_client!.is_connected) { + _client!.current_session!.Locations.ScoutLocationsAsync(Archipelago.MultiClient.Net.Enums.HintCreationPolicy.CreateAndAnnounceOnce, + treasure_id | (long)ArchipelagoClientModule.ArchipelagoLocationType.Treasure); } } - FFXArchipelagoClient.SayAsync($"kicked away {item.player}'s {item.name}!"); + _client!.SayAsync($"kicked away {item.player}'s {item.name}!"); } } return 1; } - [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] - public static int CT_RetInt_CheckUnlockedAeons(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + public int CT_RetInt_CheckUnlockedAeons(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { uint aeon_bitfield = work->table_priv_data[0]; - logger.Info($"aeon_bitfield: {aeon_bitfield}"); + _logger.Info($"aeon_bitfield: {aeon_bitfield}"); uint temp = aeon_bitfield; for (int i = 0; i < PlySaveId.PC_DUMMY; i++) { - logger.Info($"{id_to_character[i]}: {(temp & 1) == 1}"); + _logger.Info($"{id_to_character[i]}: {(temp & 1) == 1}"); temp >>= 1; } @@ -4488,10 +4491,10 @@ public static int CT_RetInt_CheckUnlockedAeons(AtelBasicWorker* work, int* stora return 1; } - if (!FFXArchipelagoClient.local_checked_locations.Contains(41 | (long)FFXArchipelagoClient.ArchipelagoLocationType.Boss)) { + if (!(_client!.local_checked_locations.Contains(41 | (long)ArchipelagoClientModule.ArchipelagoLocationType.Boss))) { if (ArchipelagoFFXModule.item_locations.boss.TryGetValue(41, out var item)) { - if (FFXArchipelagoClient.sendLocation(41, FFXArchipelagoClient.ArchipelagoLocationType.Boss)) { - ArchipelagoFFXModule.obtain_item(item.id); + if (_client!.sendLocation(41, ArchipelagoClientModule.ArchipelagoLocationType.Boss)) { + obtain_item(item.id); } } } diff --git a/src/modules/captures.cs b/src/modules/captures.cs index 063e666..28aeaf4 100644 --- a/src/modules/captures.cs +++ b/src/modules/captures.cs @@ -17,7 +17,7 @@ using Fahrenheit; using static Fahrenheit.FFX.Globals; -using static ArchipelagoFFX.Client.FFXArchipelagoClient; +using static ArchipelagoFFX.Client.ArchipelagoClientModule; using static ArchipelagoFFX.delegates; namespace ArchipelagoFFX; @@ -68,16 +68,22 @@ private struct BtlBinFormation { public byte weight; } - private FhModContext? _mod_context; - private FileStream? _global_state; + private FhModuleHandle _client_handle; + private ArchipelagoClientModule? _client; + + private FhModuleHandle _ffx_interop_handle; + private ArchipelagoFFXModule? _ffx_interop; public CaptureModule() { const string GAME = "FFX.exe"; + _client_handle = new(this); + _ffx_interop_handle = new(this); + _MsMonsterCapture = new FhMethodHandle(this, GAME, __addr_MsMonsterCapture, h_MsMonsterCapture); _FUN_00783bb0 = new FhMethodHandle(this, GAME, __addr_FUN_00783bb0, h_FUN_00783bb0); _AtelEventSetUp = new FhMethodHandle(this, GAME, __addr_AtelEventSetUp, h_AtelEventSetUp); - _ret_hasKeyItem = new FhMethodHandle(this, GAME, __addr_ret_hasKeyItem, h_ret_hasKeyItem); + _ret_hasKeyItem = new FhMethodHandle(this, GAME, __addr_ret_hasKeyItem, h_ret_hasKeyItem); _MsDamageCheckDeath = new FhMethodHandle(this, GAME, __addr_MsDamageCheckDeath, h_MsDamageCheckDeath); _MsSetRamChrParam = new FhMethodHandle(this, GAME, __addr_MsSetRamChrParam, h_MsSetRamChrParam); _MsSetSaveParam = new FhMethodHandle(this, GAME, __addr_MsSetSaveParam, h_MsSetSaveParam); @@ -86,10 +92,9 @@ public CaptureModule() { } public override bool init(FhModContext mod_context, FileStream global_state_file) { - _mod_context = mod_context; - _global_state = global_state_file; - - return _MsMonsterCapture.hook() + return _client_handle.try_get_module(out _client) + && _ffx_interop_handle.try_get_module(out _ffx_interop) + && _MsMonsterCapture.hook() && _FUN_00783bb0.hook() && _AtelEventSetUp.hook() && _ret_hasKeyItem.hook() @@ -123,24 +128,24 @@ private bool h_MsMonsterCapture(int target_id, int arena_idx) { // Send AP Location if successfully captured if (captured) { - if (sendLocation(arena_idx, FFXArchipelagoClient.ArchipelagoLocationType.Capture) && ArchipelagoFFXModule.item_locations.capture.TryGetValue(arena_idx, out var item)) { - ArchipelagoFFXModule.obtain_item(item.id); - } + lock (_client!.client_lock) { + if (_client!.sendLocation(arena_idx, ArchipelagoLocationType.Capture) && ArchipelagoFFXModule.item_locations.capture.TryGetValue(arena_idx, out var item)) { + _ffx_interop!.obtain_item(item.id); + } - int amount = save_data->monsters_captured[arena_idx]; - lock (FFXArchipelagoClient.client_lock) { - if (FFXArchipelagoClient.is_connected) { + int amount = save_data->monsters_captured[arena_idx]; + if (_client!.is_connected) { if (amount > 0) - FFXArchipelagoClient.current_session!.DataStorage[Scope.Slot, "FFX_CAPTURE_" + arena_idx] = amount; + _client!.current_session!.DataStorage[Scope.Slot, "FFX_CAPTURE_" + arena_idx] = amount; else - FFXArchipelagoClient.current_session!.DataStorage[Scope.Slot, "FFX_CAPTURE_" + arena_idx] = 0; + _client!.current_session!.DataStorage[Scope.Slot, "FFX_CAPTURE_" + arena_idx] = 0; } } } return captured; } - private HashSet initialized_monsters = []; + private readonly HashSet initialized_monsters = []; private static readonly HashSet _incorrect_arena_idx = [ 041, // Sahagin 042, // Sahagin @@ -166,7 +171,7 @@ private void h_FUN_00783bb0(byte mon_idx) { Chr* mon = _MsGetMon(mon_idx); if (initialized_monsters.Add(mon->chr_id)) { - MonStats* stats = (MonStats*)mon->ptr_base_stats; + MonStats* stats = mon->ptr_base_stats; // Corrects incorrect monster arena indexes to be uncapturable if (_incorrect_arena_idx.Contains((short)(mon->chr_id & 0xFFF))) { @@ -184,7 +189,7 @@ private void h_AtelEventSetUp(int event_id) { _event_name = Marshal.PtrToStringAnsi((nint)get_event_name((uint)event_id))!; _logger.Debug($"atel_event_setup: {_event_name}"); - byte* code_ptr = Globals.Atel.controllers[0].worker(0)->code_ptr; + byte* code_ptr = Atel.controllers[0].worker(0)->code_ptr; switch (_event_name) { case "nagi0700": @@ -211,7 +216,9 @@ private int h_ret_hasKeyItem(AtelBasicWorker* work, int* storage, AtelStack* ate int item_id = atelStack->pop_int(); if (item_id == 0xA028) { - return local_checked_locations.Contains(276 | (long)FFXArchipelagoClient.ArchipelagoLocationType.Treasure) ? 1 : 0; + lock (_client!.client_lock) { + return _client!.local_checked_locations.Contains(276 | (long)ArchipelagoLocationType.Treasure) ? 1 : 0; + } } else { atelStack->push_int(item_id); @@ -223,7 +230,7 @@ private int h_ret_hasKeyItem(AtelBasicWorker* work, int* storage, AtelStack* ate private int h_MsDamageCheckDeath(int attacker_id, int target_id, int param_3, uint param_4) { Chr* target = _MsGetChr((uint)target_id); - MonStats* mon_stats = (MonStats*)target->ptr_base_stats; + MonStats* mon_stats = target->ptr_base_stats; ushort capture_index = mon_stats is not null ? mon_stats->monster_arena_idx : (ushort)0xFF; diff --git a/src/modules/deathlink.cs b/src/modules/deathlink.cs index 7a22fce..d748eaa 100644 --- a/src/modules/deathlink.cs +++ b/src/modules/deathlink.cs @@ -32,11 +32,10 @@ public enum DeathLinkReceiveType { public static readonly Vector4 DEATHLINK_COLOR = new(1.0f, 0.18f, 0.21f, 1.0f); - // This is annoying but necessary for now because `FFXArchipelagoClient` wants everything to be static - //TODO: Remove this once it's no longer necessary - private static DeathLinkModule _this; + private ArchipelagoFFXModule.NativeCustomString _deathlink_announcement; - private static ArchipelagoFFXModule.NativeCustomString _deathlink_announcement; + private FhModuleHandle _client_handle; + private ArchipelagoClientModule? _client; private readonly FhModuleHandle _toasts_handle; private ToastModule? _toasts; @@ -52,10 +51,9 @@ public enum DeathLinkReceiveType { private bool deathlink_grace = false; public DeathLinkModule() { - _this = this; - _deathlink_announcement = new("Deathlink!"); + _client_handle = new(this); _toasts_handle = new(this); const string GAME = "FFX.exe"; @@ -65,62 +63,62 @@ public DeathLinkModule() { _MsGetBattleEndStatus = new(this, GAME, __addr_MsGetBattleEndStatus, _h_MsGetBattleEndStatus); } - public static bool get_enabled() { - return _this._deathlink_enabled; + public bool get_enabled() { + return _deathlink_enabled; } - public static void set_enabled(bool value) { - _this._deathlink_enabled = value; + public void set_enabled(bool value) { + _deathlink_enabled = value; - if (!_this._deathlink_enabled) { + if (!_deathlink_enabled) { // Clear remaining deathlinks - _this._deathlinks_queued = 0; + _deathlinks_queued = 0; } - if (_this._deathlink_enabled) { - FFXArchipelagoClient.current_death_link?.EnableDeathLink(); + if (_deathlink_enabled) { + _client!.current_death_link_service?.EnableDeathLink(); } else { - FFXArchipelagoClient.current_death_link?.DisableDeathLink(); + _client!.current_death_link_service?.DisableDeathLink(); } } - public static string get_send_type() { - return get_send_type_name(_this.deathlink_send_type); + public string get_send_type() { + return get_send_type_name(deathlink_send_type); } - public static string get_send_type_name(DeathLinkSendType send_type) { + public string get_send_type_name(DeathLinkSendType send_type) { return send_type switch { DeathLinkSendType.GameOver => "Game Over", DeathLinkSendType.KO => "KO", - _ => throw new NotImplementedException($"Unknown deathlink type: {(int)_this.deathlink_receive_type}"), + _ => throw new NotImplementedException($"Unknown deathlink type: {(int)deathlink_receive_type}"), }; } - public static void set_send_type(string type) { - _this.deathlink_send_type = type switch { + public void set_send_type(string type) { + deathlink_send_type = type switch { "Game Over" => DeathLinkSendType.GameOver, "KO" => DeathLinkSendType.KO, _ => throw new NotImplementedException($"Unknown deathlink type: {type}"), }; } - public static string get_receive_type() { - return get_receive_type_name(_this.deathlink_receive_type); + public string get_receive_type() { + return get_receive_type_name(deathlink_receive_type); } - public static string get_receive_type_name(DeathLinkReceiveType receive_type) { + public string get_receive_type_name(DeathLinkReceiveType receive_type) { return receive_type switch { DeathLinkReceiveType.DOOM_STRICT => "Doom (1 turn)", DeathLinkReceiveType.DOOM_LENIENT => "Doom (3 turns)", DeathLinkReceiveType.GRAVE_HP => "Grave HP", DeathLinkReceiveType.BAD_BREATH => "Bad Breath", DeathLinkReceiveType.RANDOM => "Random", - _ => throw new NotImplementedException($"Unknown deathlink type: {(int)_this.deathlink_receive_type}"), + _ => throw new NotImplementedException($"Unknown deathlink type: {(int)deathlink_receive_type}"), }; } - public static void set_receive_type(string type) { - _this.deathlink_receive_type = type switch { + public void set_receive_type(string type) { + deathlink_receive_type = type switch { "Doom (1 turn)" => DeathLinkReceiveType.DOOM_STRICT, "Doom (3 turns)" => DeathLinkReceiveType.DOOM_LENIENT, "Grave HP" => DeathLinkReceiveType.GRAVE_HP, @@ -130,20 +128,21 @@ public static void set_receive_type(string type) { }; } - public static uint get_deathlinks_queued() { - return _this._deathlinks_queued; + public uint get_deathlinks_queued() { + return _deathlinks_queued; } - public static void debug_add_queued() { - _this._deathlinks_queued += 1; + public void debug_add_queued() { + _deathlinks_queued += 1; } - public static void debug_apply_deathlink() { - _this.apply_death_link(); + public void debug_apply_deathlink() { + apply_death_link(); } public override bool init(FhModContext mod_context, FileStream global_state_file) { - return _toasts_handle.try_get_module(out _toasts) + return _client_handle.try_get_module(out _client) + && _toasts_handle.try_get_module(out _toasts) && _MsBtlReadManage.hook() && _MsDamageCheckDeath.hook() && _MsGetBattleEndStatus.hook(); @@ -259,7 +258,7 @@ private int _h_MsDamageCheckDeath(int attacker_id, int target_id, int p3, int ta _logger.Info(" Sending deathlink..."); - string player = FFXArchipelagoClient.active_player?.Alias ?? "Someone"; + string player = _client!.active_player?.Alias ?? "Someone"; Chr* target = _MsGetChr(target_id); byte[] decoded = new byte[FhEncoding.compute_decode_buffer_size(target->ram.name, null, null, FhEncodingFlags.IMPLICIT_END)]; @@ -268,7 +267,7 @@ private int _h_MsDamageCheckDeath(int attacker_id, int target_id, int p3, int ta string message = _get_deathlink_send_text($"{player}'s {target_name}"); - FFXArchipelagoClient.current_death_link?.SendDeathLink(new(player, message)); + _client!.current_death_link_service?.SendDeathLink(new(player, message)); ToastModule.Toast deathlink_toast = new( [ @@ -299,10 +298,10 @@ private uint _h_MsGetBattleEndStatus() { _logger.Info(" Sending deathlink..."); - string player = FFXArchipelagoClient.active_player?.Alias ?? "Someone"; + string player = _client!.active_player?.Alias ?? "Someone"; string message = _get_deathlink_send_text(player); - FFXArchipelagoClient.current_death_link?.SendDeathLink(new(player, message)); + _client!.current_death_link_service?.SendDeathLink(new(player, message)); ToastModule.Toast deathlink_toast = new( [ @@ -444,9 +443,9 @@ private string _get_backup_deathlink_received_text(string source_player) { return String.Format(FhApi.Localization.localize(message_id), source_player); } - public static void post_deathlink(DeathLink death_msg) { - if (!_this._deathlink_enabled) return; - _this._deathlinks_queued += 1; + public void post_deathlink(DeathLink death_msg) { + if (!_deathlink_enabled) return; + _deathlinks_queued += 1; // Display a toast ToastModule.Toast deathlink_toast = new( @@ -454,10 +453,10 @@ public static void post_deathlink(DeathLink death_msg) { new(DEATHLINK_COLOR, "Deathlink received!"), ], [ - new(new(1f), death_msg.Cause ?? _this._get_backup_deathlink_received_text(death_msg.Source)), + new(new(1f), death_msg.Cause ?? _get_backup_deathlink_received_text(death_msg.Source)), ] ); - _this._toasts!.queue_toast(deathlink_toast); + _toasts?.queue_toast(deathlink_toast); } } diff --git a/src/modules/hardcore_contest.cs b/src/modules/hardcore_contest.cs index db943a0..83f4c83 100644 --- a/src/modules/hardcore_contest.cs +++ b/src/modules/hardcore_contest.cs @@ -13,22 +13,20 @@ public unsafe partial class HardcoreDreamsEndModule : FhModule { public delegate void MsBtlReadManage(); public const nint __addr_MsBtlReadManage = 0x3830d0; - private static HardcoreDreamsEndModule _this; private bool _hardcore_dreams_end_enabled; private FhMethodHandle _MsBtlReadManage; public HardcoreDreamsEndModule() { - _this = this; _MsBtlReadManage = new(this, "FFX.exe", __addr_MsBtlReadManage, _h_MsBtlReadManage); } - public static bool get_enabled() { - return _this._hardcore_dreams_end_enabled; + public bool get_enabled() { + return _hardcore_dreams_end_enabled; } - public static void set_enabled(bool enabled) { - _this._hardcore_dreams_end_enabled = enabled; + public void set_enabled(bool enabled) { + _hardcore_dreams_end_enabled = enabled; } public override bool init(FhModContext mod_context, FileStream global_state_file) { diff --git a/src/modules/overdrives.cs b/src/modules/overdrives.cs index 6524a48..3e3cdca 100644 --- a/src/modules/overdrives.cs +++ b/src/modules/overdrives.cs @@ -13,18 +13,22 @@ using static Fahrenheit.FFX.Globals; using static ArchipelagoFFX.ArchipelagoFFXModule; -using static ArchipelagoFFX.Client.FFXArchipelagoClient; using static ArchipelagoFFX.delegates; namespace ArchipelagoFFX; [FhLoad(FhGameId.FFX)] -public unsafe partial class OverdriveModule : FhModule -{ +public unsafe partial class OverdriveModule : FhModule { // Fahrenheit-related private FhModContext? _mod_context; private FileStream? _global_state; + private FhModuleHandle _client_handle; + private ArchipelagoClientModule? _client; + + private FhModuleHandle _ffx_interop_handle; + private ArchipelagoFFXModule? _ffx_interop; + // Damage Calc [StructLayout(LayoutKind.Explicit, Size = 0x2C)] private struct DamageInfo @@ -66,28 +70,40 @@ private struct Chr__0x774 [FieldOffset(0x18)] public DamageInfo field24_0x18; }; - public OverdriveModule() - { + public OverdriveModule() { const string GAME = "FFX.exe"; - + + _client_handle = new(this); + _ffx_interop_handle = new(this); + _MsGetSaveCommand = new FhMethodHandle(this, GAME, __addr_MsGetSaveCommand, h_MsGetSaveCommand); _MsSetRamChrAbility = new FhMethodHandle(this, GAME, __addr_MsSetRamChrAbility, h_MsSetRamChrAbility); _MsLimitTidusLearn = new FhMethodHandle(this, GAME, __addr_MsLimitTidusLearn, h_MsLimitTidusLearn); _MsAfterDamageProcess = new FhMethodHandle(this, GAME, __addr_MsAfterDamageProcess, h_MsAfterDamageProcess); - _ret_doesChrKnowCommand = new FhMethodHandle(this, GAME, __addr_ret_doesChrKnowCommand, h_ret_doesChrKnowCommand); + _ret_doesChrKnowCommand = new FhMethodHandle(this, GAME, __addr_ret_doesChrKnowCommand, h_ret_doesChrKnowCommand); _MsSetSaveCommandWithPrefix = new FhMethodHandle(this, GAME, __addr_MsSetSaveCommandWithPrefix, h_MsSetSaveCommandWithPrefix); _TOBtlDrawLearningMessageWindow = new FhMethodHandle(this, GAME, __addr_TOBtlDrawLearningMessageWindow, h_TOBtlDrawLearningMessageWindow); } + public override bool init(FhModContext mod_context, FileStream global_state_file) { + _mod_context = mod_context; + _global_state = global_state_file; + + return _client_handle.try_get_module(out _client) + && _ffx_interop_handle.try_get_module(out _ffx_interop) + && _MsGetSaveCommand.hook() + && _MsSetRamChrAbility.hook() + && _MsLimitTidusLearn.hook() + && _MsAfterDamageProcess.hook() + && _ret_doesChrKnowCommand.hook() + && _MsSetSaveCommandWithPrefix.hook() + && _TOBtlDrawLearningMessageWindow.hook(); + } + // Helper class for overdrive provider functions - public static class OverdriveProvider - { - private const int overdriveOffset = 0x3000; - - public static void provide_overdrive(int chr_id) - { - switch (chr_id) - { + public static class OverdriveProvider { + public static void provide_overdrive(int chr_id) { + switch (chr_id) { case PlySaveId.PC_TIDUS: tidus_overdrive(); break; @@ -109,8 +125,7 @@ public static void provide_overdrive(int chr_id) } } - private static void tidus_overdrive() - { + private static void tidus_overdrive() { bool hasSpiralCut = other_inventory.ContainsKey(PlayerCommandId.PCOM_SPIRAL_CUT); bool hasSliceAndDice = other_inventory.ContainsKey(PlayerCommandId.PCOM_SLICE_AND_DICE); bool hasEnergyRain = other_inventory.ContainsKey(PlayerCommandId.PCOM_ENERGY_RAIN); @@ -124,8 +139,7 @@ private static void tidus_overdrive() save_data->ability_map_limit.has_blitz_ace = hasBlitzAce; } - private static void auron_overdrive() - { + private static void auron_overdrive() { bool hasDragonFang = other_inventory.ContainsKey(PlayerCommandId.PCOM_DRAGON_FANG); bool hasShootingStar = other_inventory.ContainsKey(PlayerCommandId.PCOM_SHOOTING_STAR); bool hasBanishingBlade = other_inventory.ContainsKey(PlayerCommandId.PCOM_BANISHING_BLADE); @@ -139,8 +153,7 @@ private static void auron_overdrive() save_data->ability_map_limit.has_tornado = hasTornado; } - private static void kimahri_overdrive() - { + private static void kimahri_overdrive() { bool hasJump = other_inventory.ContainsKey(PlayerCommandId.PCOM_JUMP); bool hasFireBreath = other_inventory.ContainsKey(PlayerCommandId.PCOM_FIRE_BREATH); bool hasSeedCannon = other_inventory.ContainsKey(PlayerCommandId.PCOM_SEED_CANNON); @@ -172,8 +185,7 @@ private static void kimahri_overdrive() save_data->ability_map_limit.has_nova = hasNova; } - private static void wakka_overdrive() - { + private static void wakka_overdrive() { bool hasElementReels = other_inventory.ContainsKey(PlayerCommandId.PCOM_ELEMENT_REELS); bool hasAttackReels = other_inventory.ContainsKey(PlayerCommandId.PCOM_ATTACK_REELS); bool hasStatusReels = other_inventory.ContainsKey(PlayerCommandId.PCOM_STATUS_REELS); @@ -187,15 +199,13 @@ private static void wakka_overdrive() save_data->ability_map_limit.has_aurochs_reels = hasAurochsReels; } - private static void seymour_overdrive() - { + private static void seymour_overdrive() { bool hasRequiem = other_inventory.ContainsKey(PlayerCommandId.PCOM_REQUIEM); save_data->ability_map_limit.has_requiem = hasRequiem; } - private static void valefor_overdrive() - { + private static void valefor_overdrive() { bool hasEnergyBlast = other_inventory.ContainsKey(PlayerCommandId.PCOM_ENERGY_BLAST); save_data->ability_map_limit.has_energy_blast = hasEnergyBlast; @@ -212,28 +222,13 @@ public static void set_overdrive_modes() { } } - public override bool init(FhModContext mod_context, FileStream global_state_file) - { - _mod_context = mod_context; - _global_state = global_state_file; - - return _MsGetSaveCommand.hook() - && _MsSetRamChrAbility.hook() - && _MsLimitTidusLearn.hook() - && _MsAfterDamageProcess.hook() - && _ret_doesChrKnowCommand.hook() - && _MsSetSaveCommandWithPrefix.hook() - && _TOBtlDrawLearningMessageWindow.hook(); - } - - private static T* ptr_at(nint address) where T : unmanaged { return (T*)(address); } + private static T* ptr_at(nint address) where T : unmanaged { return (T*)address; } private static T get_at(nint address) where T : unmanaged { return *ptr_at(address); } - private static T set_at(nint address, T value) where T : unmanaged { return *ptr_at(address) = value; } + private static void set_at(nint address, T value) where T : unmanaged { *ptr_at(address) = value; } // When game is attempting to give a character an overdrive, instead call the relevant overdrive provider function - private int h_MsGetSaveCommand(int chr_id, uint com_id) - { - if (com_id is >= PlayerCommandId.PCOM_SPIRAL_CUT and <= PlayerCommandId.PCOM_AUROCHS_REELS + private int h_MsGetSaveCommand(int chr_id, uint com_id) { + if (com_id is >= PlayerCommandId.PCOM_SPIRAL_CUT and <= PlayerCommandId.PCOM_AUROCHS_REELS || com_id == PlayerCommandId.PCOM_REQUIEM || com_id == PlayerCommandId.PCOM_ENERGY_BLAST) { @@ -244,24 +239,21 @@ private int h_MsGetSaveCommand(int chr_id, uint com_id) } // When game is attempting to set character abilities, ensure the correct overdrive provider is called first - private void h_MsSetRamChrAbility(int chr_id, Chr* chr) - { + private void h_MsSetRamChrAbility(int chr_id, Chr* chr) { OverdriveProvider.provide_overdrive(chr_id); - + _MsSetRamChrAbility.orig_fptr(chr_id, chr); - return; } // Runs on every Tidus Limit. Override the normal requirements, and send locations based on 10 / 20 / 40 - private int h_MsLimitTidusLearn(int chr_id) - { + private int h_MsLimitTidusLearn(int chr_id) { if (chr_id != PlySaveId.PC_TIDUS) return 0; uint tidusLimitUses = ++save_data->tidus_limit_uses; - lock (FFXArchipelagoClient.client_lock) { - if (FFXArchipelagoClient.is_connected) { - FFXArchipelagoClient.current_session!.DataStorage[Scope.Slot, "FFX_TIDUS_OVERDRIVE"] = tidusLimitUses; + lock (_client!.client_lock) { + if (_client!.is_connected) { + _client!.current_session!.DataStorage[Scope.Slot, "FFX_TIDUS_OVERDRIVE"] = tidusLimitUses; } } @@ -282,36 +274,30 @@ private int h_MsLimitTidusLearn(int chr_id) _MsMessageCueRegist(6, PlySaveId.PC_TIDUS, PlayerCommandId.PCOM_BLITZ_ACE, 0x1e, 0x32); } } - + return 0; } // Called multiple times on every instance damage. Complete reimplementation in order to interject on Kimahri's overdrive learning - private uint h_MsAfterDamageProcess(int attacker_id, uint param_2, int target_id, uint* param_4, uint param_5) - { + private uint h_MsAfterDamageProcess(int attacker_id, uint param_2, int target_id, uint* param_4, uint param_5) { uint uVar12 = 0; DamageInfo* local_30 = (DamageInfo*)0x0; Chr* attacker = _MsGetChr(attacker_id); Chr* target = _MsGetChr(target_id); Chr__0x774* target_0x774 = (Chr__0x774*)((int)target + 0x774); - for (int n = 2; n > 0; n--) - { - if (target_0x774->field2_0x2 == attacker_id && target_0x774->field3_0x3 == param_2) - { + for (int n = 2; n > 0; n--) { + if (target_0x774->field2_0x2 == attacker_id && target_0x774->field3_0x3 == param_2) { //set_at((int)target + 0xF5E, param_5 & 0x7f); set_at((int)target + 0xF5E, (byte)param_5.get_bits(0, 7)); set_at((int)target + 0xDED, (byte)attacker_id); - if (!param_5.get_bit(3)) - { - if (target_0x774->field7_0x7 != 0) - { + if (!param_5.get_bit(3)) { + if (target_0x774->field7_0x7 != 0) { _MsMenuCloseTitleWindow(0); target_0x774->field7_0x7 = 0; //_MsMessageCueRegist(0x4, target_0x774->field7_0x7 + 3, target_0x774->field7_0x7 + 1, 0x1b, 0x23); _MsMessageCueRegist(0x4, target_0x774->field10_0xA, target_0x774->field8_0x8, 0x1b, 0x23); - if (0 < target_0x774->field8_0x8) - { + if (0 < target_0x774->field8_0x8) { _MsSetStealEffect(target_id, target_0x774->field1_0x1); _MsRegSEplay2(target_id, 0x41); } @@ -319,13 +305,11 @@ private uint h_MsAfterDamageProcess(int attacker_id, uint param_2, int target_id target_0x774->field5_0x5 |= 1; } - if (target_0x774->field12_0xC != 0) - { + if (target_0x774->field12_0xC != 0) { _MsMenuCloseTitleWindow(0); target_0x774->field12_0xC = 0; _MsMessageCueRegist(0x8, target_0x774->field16_0x10, 0, 0x1b, 0x23); - if (0 < target_0x774->field16_0x10) - { + if (0 < target_0x774->field16_0x10) { _MsPayGIL(-*(int*)(target_0x774 + 9)); _MsSetStealGillEffect(target_id, target_0x774->field1_0x1); _MsRegSEplay2(target_id, 0x41); @@ -335,35 +319,31 @@ private uint h_MsAfterDamageProcess(int attacker_id, uint param_2, int target_id } } - if (target_0x774->field4_0x4 != 0) - { - if (target_0x774->field4_0x4.get_bit(0)) - { + if (target_0x774->field4_0x4 != 0) { + if (target_0x774->field4_0x4.get_bit(0)) { byte bVar1 = attacker->ram.limit_charge; attacker->ram.limit_charge = 0; target->ram.limit_charge = (byte)_MsCheckRange(target->ram.limit_charge + bVar1, 0, target->ram.limit_charge_max); } - if (target_0x774->field4_0x4.get_bit(1)) - { + if (target_0x774->field4_0x4.get_bit(1)) { Chr* pCVar8 = _MsGetChr(target_0x774->chr_id__0x17); - if (target_id == PlySaveId.PC_KIMAHRI && pCVar8->loot != (ChrLoot*)0x0) - { + if (target_id == PlySaveId.PC_KIMAHRI && pCVar8->loot != (ChrLoot*)0x0) { ushort rage_to_learn = pCVar8->loot->ronso_rage; - if (rage_to_learn != 0) - { + if (rage_to_learn != 0) { if(send_overdrive(rage_to_learn)) { _MsMessageCueRegist(6, PlySaveId.PC_KIMAHRI, rage_to_learn, 0x1e, 0x32); target->ram.limit_charge = target->ram.limit_charge_max; } - if (save_data->ability_map_limit.has_jump && save_data->ability_map_limit.has_fire_breath && + if ( + save_data->ability_map_limit.has_jump && save_data->ability_map_limit.has_fire_breath && save_data->ability_map_limit.has_seed_cannon && save_data->ability_map_limit.has_self_destruct && save_data->ability_map_limit.has_thrust_kick && save_data->ability_map_limit.has_stone_breath && save_data->ability_map_limit.has_aqua_breath && save_data->ability_map_limit.has_doom && save_data->ability_map_limit.has_white_wind && save_data->ability_map_limit.has_bad_breath && - save_data->ability_map_limit.has_mighty_guard && save_data->ability_map_limit.has_nova) - { + save_data->ability_map_limit.has_mighty_guard && save_data->ability_map_limit.has_nova + ) { _achievementUnlockAchievement(0x19); } } @@ -373,29 +353,23 @@ private uint h_MsAfterDamageProcess(int attacker_id, uint param_2, int target_id target_0x774->field4_0x4 = 0; } - if (target_0x774->field0_0x0 < target_0x774->field1_0x1) - { + if (target_0x774->field0_0x0 < target_0x774->field1_0x1) { DamageInfo* target_0x774_damage_info = &target_0x774->field24_0x18 + target_0x774->field0_0x0; int local_20 = 0; - if (!param_5.get_bit(3)) - { + if (!param_5.get_bit(3)) { int iVar7 = target_0x774_damage_info->field1_0x1; uint uVar9 = target_0x774_damage_info->field2_0x2; - if (iVar7 == 1) - { + if (iVar7 == 1) { _MsNumberRegist(target_id, 3, 0, 0, 1, uVar9, 0x81); - } - else if (iVar7 == 2) - { + } else if (iVar7 == 2) { _MsNumberRegist(target_id, 4, 0, 0, 2, uVar9, 0x81); } _MsLimitTypeDamageCheck(attacker_id, attacker, target_id, target, target_0x774_damage_info->out_damage_hp, target_0x774_damage_info->out_damage_expected, target_0x774->field6_0x6); - if (target_0x774_damage_info->dmg_calc_flags1.get_bit(0)) - { + if (target_0x774_damage_info->dmg_calc_flags1.get_bit(0)) { _MsSubHP(target_id, target, target_0x774_damage_info->out_damage_hp, target_0x774_damage_info->out_damage_mp, iVar7, uVar9, 0x81); set_at((int)target + 0xF60, get_at((int)target + 0xF60) - target_0x774_damage_info->out_damage_hp); @@ -403,13 +377,11 @@ private uint h_MsAfterDamageProcess(int attacker_id, uint param_2, int target_id local_20 += target_0x774_damage_info->out_damage_hp; } - if (target_0x774_damage_info->dmg_calc_flags1.get_bit(1)) - { + if (target_0x774_damage_info->dmg_calc_flags1.get_bit(1)) { _MsSubMP(target_id, target, target_0x774_damage_info->out_damage_mp, target_0x774_damage_info->out_damage_hp, iVar7, uVar9, 0x81); } - if (target_0x774_damage_info->dmg_calc_flags1.get_bit(2)) - { + if (target_0x774_damage_info->dmg_calc_flags1.get_bit(2)) { _MsSubCTB(target_id, target, target_0x774_damage_info->out_damage_ctb, iVar7, uVar9, 0x81); //dbgPrintf("CTB DAMAGE %d %d : %d\n", target_id, iVar10, (target->ram).ctb); } @@ -422,8 +394,7 @@ private uint h_MsAfterDamageProcess(int attacker_id, uint param_2, int target_id StatusExtraFlags bVar4 = target->ram.status_suffer_extra; target->ram.status_suffer = target_0x774_damage_info->target_status_suffer; - for (int i = 0; i < 0xD; i++) - { + for (int i = 0; i < 0xD; i++) { // TODO: Improvements pending the availability of indexers from Fahrenheit, as per https://github.com/fahrenheit-crew/fahrenheit/issues/114 (&target->ram.status_suffer_turns_left.sleep)[i] = (&target_0x774_damage_info->target_status_suffer_turns_left.sleep)[i]; } @@ -431,89 +402,71 @@ private uint h_MsAfterDamageProcess(int attacker_id, uint param_2, int target_id target->ram.status_suffer_extra = target_0x774_damage_info->target_status_suffer_extra; _MsLimitStatusProcess(target_id, target, target_0x774_damage_info->flags_buffs_mix); - if ((target->ram.status_suffer_turns_left.regen != 0) && (bVar3 == 0)) - { + if (target->ram.status_suffer_turns_left.regen != 0 && bVar3 == 0) { target->ram.regen_strength = 0; } StatusPermanentFlags SVar6 = target->ram.status_suffer; set_at((int)target + 0xDCE, SVar6.petrification()); - if (target->ram.status_suffer.death() != SVar5.death()) - { + if (target->ram.status_suffer.death() != SVar5.death()) { _MsAliveProcess(target_id, target); } - if (target->ram.status_suffer.petrification() != SVar5.petrification()) - { + if (target->ram.status_suffer.petrification() != SVar5.petrification()) { _MsStoneProcess(target_id, target); } - if (target->ram.status_suffer_extra.eject() != bVar4.eject()) - { + if (target->ram.status_suffer_extra.eject() != bVar4.eject()) { _MsBlowProcess(target_id, target); } - if (target->ram.status_suffer.threaten() != SVar5.threaten()) - { + if (target->ram.status_suffer.threaten() != SVar5.threaten()) { _MsThreatProcess(target_id, target); } target_0x774->field5_0x5 |= 1; - if (target->ram.auto_ability_effects.has_auto_med) - { + if (target->ram.auto_ability_effects.has_auto_med) { _MsAutoCureProcess(target_id, target, attacker_id, (int)SVar5 >> 3 & 1, (int)SVar5 >> 1 & 1, bVar1, bVar2); } - if (0 < local_20 && target->ram.auto_ability_effects.has_auto_potion) - { + if (0 < local_20 && target->ram.auto_ability_effects.has_auto_potion) { _MsAutoPotionProcess(target_id, target, attacker_id); } _MsSetChrWeak(target_id, -1); - uVar12 = uVar12 | 2; + uVar12 |= 2; target_0x774->field0_0x0 += 1; } - if (get_at((int)&target->ram + 0x19C)) - { + if (get_at((int)&target->ram + 0x19C)) { _MsAutoRelifeProcess(attacker_id, attacker, target_id, target); } - if (!param_5.get_bit(1) && (target_0x774_damage_info->field0_0x0 != 1 || !target_0x774->field5_0x5.get_bit(2))) - { + if (!param_5.get_bit(1) && (target_0x774_damage_info->field0_0x0 != 1 || !target_0x774->field5_0x5.get_bit(2))) { target_0x774->field5_0x5 |= 4; local_30 = target_0x774_damage_info; } - if (!param_5.get_bit(4)) - { + if (!param_5.get_bit(4)) { _MsStatusEffectCheck(target_id); - if (_MsStatusDefenseEffect(attacker_id, target_id, target_0x774_damage_info->dmg_calc_flags1) != 0) - { + if (_MsStatusDefenseEffect(attacker_id, target_id, target_0x774_damage_info->dmg_calc_flags1) != 0) { *param_4 = (uint)target_id; } } } - if (target_0x774->field0_0x0 < target_0x774->field1_0x1) - { - uVar12 = uVar12 | 1; - } - else - { - if (target_0x774->field5_0x5.get_bit(0) && !target_0x774->field5_0x5.get_bit(1)) - { + if (target_0x774->field0_0x0 < target_0x774->field1_0x1) { + uVar12 |= 1; + } else { + if (target_0x774->field5_0x5.get_bit(0) && !target_0x774->field5_0x5.get_bit(1)) { set_at((int)&target->ram + 0x19D, false); target_0x774->field5_0x5 |= 2; _MsActionRequest(target_id, attacker_id, 3, 0, 1, null); } - if (!param_5.get_bit(10)) - { + if (!param_5.get_bit(10)) { _MsPopBtlPos(target); - } - else - { + } else { target_0x774->field2_0x2 = 0xff; } } @@ -522,51 +475,47 @@ private uint h_MsAfterDamageProcess(int attacker_id, uint param_2, int target_id target_0x774 += 1; } - if (!uVar12.get_bit(0) && _MsDamageCheckDeath(attacker_id, target_id, 0, (attacker_id != target_id) ? 1 : 0) != 0) - { + int not_attacking_self = attacker_id != target_id ? 1 : 0; + + if (!uVar12.get_bit(0) && _MsDamageCheckDeath(attacker_id, target_id, 0, not_attacking_self) != 0) { return uVar12; } - if (local_30 == (DamageInfo*)0x0) - { + if (local_30 == (DamageInfo*)0x0) { return uVar12; } - if (!param_5.get_bit(5)) - { - _MsDamageSetMotion(target_id, local_30->field0_0x0, (attacker_id != target_id) ? 1 : 0); + if (!param_5.get_bit(5)) { + _MsDamageSetMotion(target_id, local_30->field0_0x0, not_attacking_self); return uVar12; } - if (local_30->field0_0x0 != 5) - { - if (local_30->field0_0x0 == 6) - { - _MsDamageSetMotion(target_id, _brnd(9).get_bit(0) ? (byte)0x10 : (byte)0xF, (attacker_id != target_id) ? 1 : 0); + if (local_30->field0_0x0 != 5) { + if (local_30->field0_0x0 == 6) { + _MsDamageSetMotion(target_id, _brnd(9).get_bit(0) ? 0x10 : 0xF, not_attacking_self); return uVar12; } - if (local_30->field0_0x0 != 8) - { - _MsDamageSetMotion(target_id, local_30->field0_0x0, (attacker_id != target_id) ? 1 : 0); + if (local_30->field0_0x0 != 8) { + _MsDamageSetMotion(target_id, local_30->field0_0x0, not_attacking_self); return uVar12; } } - _MsDamageSetMotion(target_id, _brnd(9).get_bits(0, 2) + 0xD, (attacker_id != target_id) ? 1 : 0); + _MsDamageSetMotion(target_id, _brnd(9).get_bits(0, 2) + 0xD, not_attacking_self); return uVar12; } // Required in order to allow Biran & Yenke's ChrLoot to progress to the next Ronso Rage based on location sent, rather than command known - private int h_ret_doesChrKnowCommand(AtelBasicWorker* work, int* storage, AtelStack* atelStack) - { + private int h_ret_doesChrKnowCommand(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int com_id = atelStack->pop_int(); int chr_id = atelStack->pop_int(); - if (chr_id == PlySaveId.PC_KIMAHRI && - com_id is >= PlayerCommandId.PCOM_JUMP and <= PlayerCommandId.PCOM_NOVA) - { - return local_checked_locations.Contains(((com_id - PlayerCommandId.PCOM_SPIRAL_CUT) & 0xFF) | (long)FFXArchipelagoClient.ArchipelagoLocationType.Overdrive) ? 1 : 0; + if ( + chr_id == PlySaveId.PC_KIMAHRI && + com_id is >= PlayerCommandId.PCOM_JUMP and <= PlayerCommandId.PCOM_NOVA + ) { + return _client!.local_checked_locations.Contains(((com_id - PlayerCommandId.PCOM_SPIRAL_CUT) & 0xFF) | (long)ArchipelagoClientModule.ArchipelagoLocationType.Overdrive) ? 1 : 0; } atelStack->push_int(chr_id); @@ -583,7 +532,6 @@ private void h_MsSetSaveCommandWithPrefix(int chr_id, int com_id, int param_3) { } _MsSetSaveCommandWithPrefix.orig_fptr(chr_id, com_id, param_3); - return; } private int h_TOBtlDrawLearningMessageWindow(int chr_id, int com_id) { @@ -599,7 +547,7 @@ private int h_TOBtlDrawLearningMessageWindow(int chr_id, int com_id) { _TOBtlSetMacroCommandType(7, 1, 0); if (item_locations.overdrive.TryGetValue(com_id - PlayerCommandId.PCOM_SPIRAL_CUT, out var item)) { - ArchipelagoFFXModule.NativeCustomString custom_text; + NativeCustomString custom_text; if (item.id != 0) { custom_text = new($"{item.name}"); @@ -618,19 +566,15 @@ private int h_TOBtlDrawLearningMessageWindow(int chr_id, int com_id) { return 7; } - public static bool send_overdrive(int com_id) - { + public bool send_overdrive(int com_id) { // Apworld defines Spiral Cut as overdrive location 0, and all other overdrives are treated as an offset from that value. int overdrive_id = com_id - PlayerCommandId.PCOM_SPIRAL_CUT; bool sent_overdrive = false; - if (!FFXArchipelagoClient.local_checked_locations.Contains(overdrive_id | (long)FFXArchipelagoClient.ArchipelagoLocationType.Overdrive)) - { - if (ArchipelagoFFXModule.item_locations.overdrive.TryGetValue(overdrive_id, out var item)) - { - if (FFXArchipelagoClient.sendLocation(overdrive_id, FFXArchipelagoClient.ArchipelagoLocationType.Overdrive)) - { - ArchipelagoFFXModule.obtain_item(item.id); + if (!_client!.local_checked_locations.Contains(overdrive_id | (long)ArchipelagoClientModule.ArchipelagoLocationType.Overdrive)) { + if (item_locations.overdrive.TryGetValue(overdrive_id, out var item)) { + if (_client!.sendLocation(overdrive_id, ArchipelagoClientModule.ArchipelagoLocationType.Overdrive)) { + _ffx_interop!.obtain_item(item.id); sent_overdrive = true; } } From 059ea984978c561a3905285d02d92633249a73f9 Mon Sep 17 00:00:00 2001 From: evelyntsmg Date: Sun, 31 May 2026 04:16:51 +0200 Subject: [PATCH 02/20] Actually load the Gui Module --- src/gui/debugWindow.cs | 1 + src/hooks.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/gui/debugWindow.cs b/src/gui/debugWindow.cs index 009bafe..aba2f93 100644 --- a/src/gui/debugWindow.cs +++ b/src/gui/debugWindow.cs @@ -22,6 +22,7 @@ namespace ArchipelagoFFX.GUI; +[FhLoad(FhGameId.FFX)] public unsafe class ArchipelagoGuiModule : FhModule { public const ImGuiKey archipelago_gui_key = ImGuiKey.F8; public const ImGuiKey experimental_gui_key = ImGuiKey.F9; diff --git a/src/hooks.cs b/src/hooks.cs index 4108ae5..b692ad8 100644 --- a/src/hooks.cs +++ b/src/hooks.cs @@ -23,6 +23,7 @@ using FhCall = Fahrenheit.FFX.FhCall; namespace ArchipelagoFFX; + public unsafe partial class ArchipelagoFFXModule { public static int* takara_pointer => FhUtil.ptr_at(0xD35FEC); From 2a916d1835ca24faab873ead9ca3f48e7168f333 Mon Sep 17 00:00:00 2001 From: evelyntsmg Date: Sun, 31 May 2026 04:31:02 +0200 Subject: [PATCH 03/20] Fix potential `_gui` field access before it is initialized --- src/archipelago.cs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/archipelago.cs b/src/archipelago.cs index e38c784..7c81ed6 100644 --- a/src/archipelago.cs +++ b/src/archipelago.cs @@ -91,17 +91,23 @@ public override bool init(FhModContext mod_context, FileStream global_state_file FhApi.Events.Common.GameLoop.PreUpdate.subscribe(pre_update); + return hook() + && _client_handle.try_get_module(out _client) + && _gui_handle.try_get_module(out _gui) + && _hardcore_dreams_end_handle.try_get_module(out _hardcore_dreams_end) + && _deathlink_handle.try_get_module(out _deathlink) + && post_init(); + } + + private bool post_init() { // Initialize Archipelago Client initalize_states(); + //loadSeed(); loadSeedList(); load_global_state(); - return hook() - && _client_handle.try_get_module(out _client) - && _gui_handle.try_get_module(out _gui) - && _hardcore_dreams_end_handle.try_get_module(out _hardcore_dreams_end) - && _deathlink_handle.try_get_module(out _deathlink);; + return true; } public static FhLangId? VoiceLanguage; @@ -613,6 +619,7 @@ public override void load_local_state(FileStream local_state_file, FhLocalStateI _deathlink!.set_receive_type(loaded_state.deathlink_receive_type); } } + public bool load_global_state() { try { global_state_file.Position = 0; @@ -650,6 +657,7 @@ public bool load_global_state() { return false; } } + public bool save_global_state() { ArchipelagoGlobalState state = new(this); global_state_file.Position = 0; From 599ab13b088a5b5fa2c41bdfe96159bca0354c64 Mon Sep 17 00:00:00 2001 From: evelyntsmg Date: Sun, 31 May 2026 04:47:21 +0200 Subject: [PATCH 04/20] Actually initialize custom atel at initialization time --- src/archipelago.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/archipelago.cs b/src/archipelago.cs index 7c81ed6..0d45bb0 100644 --- a/src/archipelago.cs +++ b/src/archipelago.cs @@ -78,6 +78,7 @@ public unsafe partial class ArchipelagoFFXModule : FhModule { public ArchipelagoFFXModule() { init_hooks(); + init_custom_atel(); _client_handle = new(this); _gui_handle = new(this); From d6052f5e5cfdb24ab5967fcc8e7609e6b00e8823 Mon Sep 17 00:00:00 2001 From: Andrewki44 Date: Tue, 9 Jun 2026 18:36:29 +1000 Subject: [PATCH 05/20] Overdrive Delegates --- Fahrenheit.Modules.ArchipelagoFFX.csproj | 3 + src/delegates/overdrive_delegates.cs | 372 +++++++++++------------ src/modules/overdrives.cs | 177 +++++------ 3 files changed, 269 insertions(+), 283 deletions(-) diff --git a/Fahrenheit.Modules.ArchipelagoFFX.csproj b/Fahrenheit.Modules.ArchipelagoFFX.csproj index 96157ba..6caf590 100644 --- a/Fahrenheit.Modules.ArchipelagoFFX.csproj +++ b/Fahrenheit.Modules.ArchipelagoFFX.csproj @@ -37,6 +37,9 @@ + + + fhcsr diff --git a/src/delegates/overdrive_delegates.cs b/src/delegates/overdrive_delegates.cs index 79bbe7b..1221a8c 100644 --- a/src/delegates/overdrive_delegates.cs +++ b/src/delegates/overdrive_delegates.cs @@ -1,241 +1,233 @@ -using Fahrenheit.FFX; -using Fahrenheit.FFX.Battle; -using System.Runtime.InteropServices; - -using Fahrenheit; - -using static ArchipelagoFFX.delegates; - namespace ArchipelagoFFX; public unsafe partial class OverdriveModule { //TODO: Remove these once FhCall is more up-to-date - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate int MsGetSaveCommand(int char_id, uint com_id); - private const int __addr_MsGetSaveCommand = 0x3850E0; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate int MsGetSaveCommand(int char_id, uint com_id); + //private const int __addr_MsGetSaveCommand = 0x3850E0; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate void MsSetRamChrAbility(int chr_id, Chr* chr); - private const nint __addr_MsSetRamChrAbility = 0x39BB70; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate void MsSetRamChrAbility(int chr_id, Chr* chr); + //private const nint __addr_MsSetRamChrAbility = 0x39BB70; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate int MsLimitTidusLearn(int chr_id); - private const nint __addr_MsLimitTidusLearn = 0x3B0CE0; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate int MsLimitTidusLearn(int chr_id); + //private const nint __addr_MsLimitTidusLearn = 0x3B0CE0; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate uint MsAfterDamageProcess(int attacker_id, uint param_2, int target_id, uint* param_4, uint param_5); - private const nint __addr_MsAfterDamageProcess = 0x38F0B0; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate uint MsAfterDamageProcess(int attacker_id, uint param_2, int target_id, uint* param_4, uint param_5); + //private const nint __addr_MsAfterDamageProcess = 0x38F0B0; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate Chr* MsGetChr(int chr_id); - private const nint __addr_MsGetChr = 0x394030; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate Chr* MsGetChr(int chr_id); + //private const nint __addr_MsGetChr = 0x394030; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate void MsMenuCloseTitleWindow(int param_1); - private const nint __addr_MsMenuCloseTitleWindow = 0x38FA80; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate void MsMenuCloseTitleWindow(int param_1); + //private const nint __addr_MsMenuCloseTitleWindow = 0x38FA80; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate int MsMessageCueRegist(uint type, int param_2, int param_3, byte param_4, byte param_5); - private const nint __addr_MsMessageCueRegist = 0x39CFF0; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate int MsMessageCueRegist(uint type, int param_2, int param_3, byte param_4, byte param_5); + //private const nint __addr_MsMessageCueRegist = 0x39CFF0; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate void MsSetStealEffect(int param_1, int param_2); - private const nint __addr_MsSetStealEffect = 0x39ED20; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate void MsSetStealEffect(int param_1, int param_2); + //private const nint __addr_MsSetStealEffect = 0x39ED20; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate uint MsRegSEplay2(int param_1, uint param_2); - private const nint __addr_MsRegSEplay2 = 0x3A0160; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate uint MsRegSEplay2(int param_1, uint param_2); + //private const nint __addr_MsRegSEplay2 = 0x3A0160; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate int MsPayGIL(int param_1); - private const nint __addr_MsPayGIL = 0x385A60; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate int MsPayGIL(int param_1); + //private const nint __addr_MsPayGIL = 0x385A60; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate void MsSetStealGillEffect(int param_1, int param_2); - private const nint __addr_MsSetStealGillEffect = 0x39ED40; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate void MsSetStealGillEffect(int param_1, int param_2); + //private const nint __addr_MsSetStealGillEffect = 0x39ED40; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate int MsCheckRange(int param_1, int param_2, int param_3); - private const nint __addr_MsCheckRange = 0x39A0D0; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate int MsCheckRange(int param_1, int param_2, int param_3); + //private const nint __addr_MsCheckRange = 0x39A0D0; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate int MsSetSaveCommand(int chr_id, uint param_2, int param_3); - private const nint __addr_MsSetSaveCommand = 0x385D10; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate int MsSetSaveCommand(int chr_id, uint param_2, int param_3); + //private const nint __addr_MsSetSaveCommand = 0x385D10; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate void achievementUnlockAchievement(int ach_id); - private const nint __addr_achievementUnlockAchievement = 0x422410; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate void achievementUnlockAchievement(int ach_id); + //private const nint __addr_achievementUnlockAchievement = 0x422410; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate int MsNumberRegist(int param_1, int param_2, int param_3, int param_4, int param_5, uint param_6, uint param_7); - private const nint __addr_MsNumberRegist = 0x39FA20; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate int MsNumberRegist(int param_1, int param_2, int param_3, int param_4, int param_5, uint param_6, uint param_7); + //private const nint __addr_MsNumberRegist = 0x39FA20; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate int MsLimitTypeDamageCheck(int attacker_id, Chr* attacker, int target_id, Chr* target, int param_5, int param_6, int param_7); - private const nint __addr_MsLimitTypeDamageCheck = 0x3B0D60; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate int MsLimitTypeDamageCheck(int attacker_id, Chr* attacker, int target_id, Chr* target, int param_5, int param_6, int param_7); + //private const nint __addr_MsLimitTypeDamageCheck = 0x3B0D60; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate void MsSubHP(int chr_id, Chr* chr, int param_3, int param_4, int param_5, uint param_6, uint param_7); - private const nint __addr_MsSubHP = 0x38E2F0; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate void MsSubHP(int chr_id, Chr* chr, int param_3, int param_4, int param_5, uint param_6, uint param_7); + //private const nint __addr_MsSubHP = 0x38E2F0; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate void MsSubMP(int chr_id, Chr* chr, int param_3, int param_4, int param_5, uint param_6, uint param_7); - private const nint __addr_MsSubMP = 0x38E400; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate void MsSubMP(int chr_id, Chr* chr, int param_3, int param_4, int param_5, uint param_6, uint param_7); + //private const nint __addr_MsSubMP = 0x38E400; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate void MsSubCTB(int chr_id, Chr* chr, int param_3, int param_4, uint param_5, uint param_6); - private const nint __addr_MsSubCTB = 0x38E2A0; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate void MsSubCTB(int chr_id, Chr* chr, int param_3, int param_4, uint param_5, uint param_6); + //private const nint __addr_MsSubCTB = 0x38E2A0; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate int MsLimitTypeStatusCheck(int attacker_id, Chr* attacker, int target_id, Chr* target, int param_5, uint param_6); - private const nint __addr_MsLimitTypeStatusCheck = 0x3B12D0; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate int MsLimitTypeStatusCheck(int attacker_id, Chr* attacker, int target_id, Chr* target, int param_5, uint param_6); + //private const nint __addr_MsLimitTypeStatusCheck = 0x3B12D0; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate int MsLimitStatusProcess(int chr_id, Chr* chr, uint param_3); - private const nint __addr_MsLimitStatusProcess = 0x38D330; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate int MsLimitStatusProcess(int chr_id, Chr* chr, uint param_3); + //private const nint __addr_MsLimitStatusProcess = 0x38D330; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate int MsAliveProcess(int chr_id, Chr* chr); - private const nint __addr_MsAliveProcess = 0x389220; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate int MsAliveProcess(int chr_id, Chr* chr); + //private const nint __addr_MsAliveProcess = 0x389220; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate int MsStoneProcess(int chr_id, Chr* chr); - private const nint __addr_MsStoneProcess = 0x38E210; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate int MsStoneProcess(int chr_id, Chr* chr); + //private const nint __addr_MsStoneProcess = 0x38E210; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate int MsBlowProcess(int chr_id, Chr* chr); - private const nint __addr_MsBlowProcess = 0x389270; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate int MsBlowProcess(int chr_id, Chr* chr); + //private const nint __addr_MsBlowProcess = 0x389270; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate int MsThreatProcess(int chr_id, Chr* chr); - private const nint __addr_MsThreatProcess = 0x38E4B0; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate int MsThreatProcess(int chr_id, Chr* chr); + //private const nint __addr_MsThreatProcess = 0x38E4B0; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate int MsAutoCureProcess(int target_id, Chr* target, int attacker_id, int poison, int zombie, int darkness, int silence); - private const nint __addr_MsAutoCureProcess = 0x3B2520; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate int MsAutoCureProcess(int target_id, Chr* target, int attacker_id, int poison, int zombie, int darkness, int silence); + //private const nint __addr_MsAutoCureProcess = 0x3B2520; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate int MsAutoPotionProcess(int target_id, Chr* target, int attacker_id); - private const nint __addr_MsAutoPotionProcess = 0x3B2860; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate int MsAutoPotionProcess(int target_id, Chr* target, int attacker_id); + //private const nint __addr_MsAutoPotionProcess = 0x3B2860; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate int MsSetChrWeak(int chr_id, int new_weak_level); - private const nint __addr_MsSetChrWeak = 0x38D8B0; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate int MsSetChrWeak(int chr_id, int new_weak_level); + //private const nint __addr_MsSetChrWeak = 0x38D8B0; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate bool MsAutoRelifeProcess(int attacker_id, Chr* attacker, int target_id, Chr* target); - private const nint __addr_MsAutoRelifeProcess = 0x38D990; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate bool MsAutoRelifeProcess(int attacker_id, Chr* attacker, int target_id, Chr* target); + //private const nint __addr_MsAutoRelifeProcess = 0x38D990; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate void MsStatusEffectCheck(int chr_id); - private const nint __addr_MsStatusEffectCheck = 0x39F010; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate void MsStatusEffectCheck(int chr_id); + //private const nint __addr_MsStatusEffectCheck = 0x39F010; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate int MsStatusDefenseEffect(int attacker_id, int target_id, int dmg_calc_flags); - private const nint __addr_MsStatusDefenseEffect = 0x39EE40; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate int MsStatusDefenseEffect(int attacker_id, int target_id, int dmg_calc_flags); + //private const nint __addr_MsStatusDefenseEffect = 0x39EE40; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate int MsActionRequest(int target_id, int attacker_id, int param_3, int param_4, int param_5, void* param_6); - private const nint __addr_MsActionRequest = 0x3ACEC0; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate int MsActionRequest(int target_id, int attacker_id, int param_3, int param_4, int param_5, void* param_6); + //private const nint __addr_MsActionRequest = 0x3ACEC0; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate void MsPopBtlPos(Chr* chr); - private const nint __addr_MsPopBtlPos = 0x3AC620; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate void MsPopBtlPos(Chr* chr); + //private const nint __addr_MsPopBtlPos = 0x3AC620; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate int MsDamageCheckDeath(int attacker_id, int target_id, int param_3, int targeting_self); - private const nint __addr_MsDamageCheckDeath = 0x38C800; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate int MsDamageCheckDeath(int attacker_id, int target_id, int param_3, int targeting_self); + //private const nint __addr_MsDamageCheckDeath = 0x38C800; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate void MsDamageSetMotion(int chr_id, int param_2, int targeting_self); - private const nint __addr_MsDamageSetMotion = 0x38CAE0; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate void MsDamageSetMotion(int chr_id, int param_2, int targeting_self); + //private const nint __addr_MsDamageSetMotion = 0x38CAE0; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate int brnd(int rng_idx); - private const nint __addr_brnd = 0x398900; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate int brnd(int rng_idx); + //private const nint __addr_brnd = 0x398900; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate void MsSetSaveCommandWithPrefix(int chr_id, int com_id, int param_3); - private const nint __addr_MsSetSaveCommandWithPrefix = 0x474190; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate void MsSetSaveCommandWithPrefix(int chr_id, int com_id, int param_3); + //private const nint __addr_MsSetSaveCommandWithPrefix = 0x474190; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate int TOBtlDrawLearningMessageWindow(int chr_id, int com_id); - private const nint __addr_TOBtlDrawLearningMessageWindow = 0x495290; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate int TOBtlDrawLearningMessageWindow(int chr_id, int com_id); + //private const nint __addr_TOBtlDrawLearningMessageWindow = 0x495290; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate void TOBtlSetMacroCommandType(int param_1, int param_2, byte param_3); - private const nint __addr_TOBtlSetMacroCommandType = 0x4B5770; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate void TOBtlSetMacroCommandType(int param_1, int param_2, byte param_3); + //private const nint __addr_TOBtlSetMacroCommandType = 0x4B5770; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate void TOBtlSetMacroCommandValue(int param_1, int param_2, byte* param_3); - private const nint __addr_TOBtlSetMacroCommandValue = 0x4B57A0; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate void TOBtlSetMacroCommandValue(int param_1, int param_2, byte* param_3); + //private const nint __addr_TOBtlSetMacroCommandValue = 0x4B57A0; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate byte* TOGetSaveChrName(int chr_id); - private const nint __addr_TOGetSaveChrName = 0x4AC800; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate byte* TOGetSaveChrName(int chr_id); + //private const nint __addr_TOGetSaveChrName = 0x4AC800; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate Command* MsGetComData(int com_id, byte** param_2); - private const nint __addr_MsGetComData = 0x39A4C0; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate Command* MsGetComData(int com_id, byte** param_2); + //private const nint __addr_MsGetComData = 0x39A4C0; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate byte* MsGetRomBtlText(int param_1, int param_2); - private const nint __addr_MsGetRomBtlText = 0x38F940; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate byte* MsGetRomBtlText(int param_1, int param_2); + //private const nint __addr_MsGetRomBtlText = 0x38F940; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate int FUN_0089db10(int param_1, byte* param_2); - private const nint __addr_FUN_0089db10 = 0x49DB10; + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //private delegate int FUN_0089db10(int param_1, byte* param_2); + //private const nint __addr_FUN_0089db10 = 0x49DB10; - private const nint __addr_ret_doesChrKnowCommand = 0x3A30C0; + //private const nint __addr_ret_doesChrKnowCommand = 0x3A30C0; // Method Handles - private readonly FhMethodHandle _MsGetSaveCommand; - private readonly FhMethodHandle _MsSetRamChrAbility; - private readonly FhMethodHandle _MsLimitTidusLearn; - private readonly FhMethodHandle _MsAfterDamageProcess; - private readonly FhMethodHandle _ret_doesChrKnowCommand; - private readonly FhMethodHandle _MsSetSaveCommandWithPrefix; - private readonly FhMethodHandle _TOBtlDrawLearningMessageWindow; - - private readonly MsGetChr _MsGetChr = FhUtil.get_fptr(__addr_MsGetChr); - private readonly MsMenuCloseTitleWindow _MsMenuCloseTitleWindow = FhUtil.get_fptr(__addr_MsMenuCloseTitleWindow); - private readonly MsMessageCueRegist _MsMessageCueRegist = FhUtil.get_fptr(__addr_MsMessageCueRegist); - private readonly MsSetStealEffect _MsSetStealEffect = FhUtil.get_fptr(__addr_MsSetStealEffect); - private readonly MsRegSEplay2 _MsRegSEplay2 = FhUtil.get_fptr(__addr_MsRegSEplay2); - private readonly MsPayGIL _MsPayGIL = FhUtil.get_fptr(__addr_MsPayGIL); - private readonly MsSetStealGillEffect _MsSetStealGillEffect = FhUtil.get_fptr(__addr_MsSetStealGillEffect); - private readonly MsCheckRange _MsCheckRange = FhUtil.get_fptr(__addr_MsCheckRange); - private readonly MsSetSaveCommand _MsSetSaveCommand = FhUtil.get_fptr(__addr_MsSetSaveCommand); - private readonly achievementUnlockAchievement _achievementUnlockAchievement = FhUtil.get_fptr(__addr_achievementUnlockAchievement); - private readonly MsNumberRegist _MsNumberRegist = FhUtil.get_fptr(__addr_MsNumberRegist); - private readonly MsLimitTypeDamageCheck _MsLimitTypeDamageCheck = FhUtil.get_fptr(__addr_MsLimitTypeDamageCheck); - private readonly MsSubHP _MsSubHP = FhUtil.get_fptr(__addr_MsSubHP); - private readonly MsSubMP _MsSubMP = FhUtil.get_fptr(__addr_MsSubMP); - private readonly MsSubCTB _MsSubCTB = FhUtil.get_fptr(__addr_MsSubCTB); - private readonly MsLimitTypeStatusCheck _MsLimitTypeStatusCheck = FhUtil.get_fptr(__addr_MsLimitTypeStatusCheck); - private readonly MsLimitStatusProcess _MsLimitStatusProcess = FhUtil.get_fptr(__addr_MsLimitStatusProcess); - private readonly MsAliveProcess _MsAliveProcess = FhUtil.get_fptr(__addr_MsAliveProcess); - private readonly MsStoneProcess _MsStoneProcess = FhUtil.get_fptr(__addr_MsStoneProcess); - private readonly MsBlowProcess _MsBlowProcess = FhUtil.get_fptr(__addr_MsBlowProcess); - private readonly MsThreatProcess _MsThreatProcess = FhUtil.get_fptr(__addr_MsThreatProcess); - private readonly MsAutoCureProcess _MsAutoCureProcess = FhUtil.get_fptr(__addr_MsAutoCureProcess); - private readonly MsAutoPotionProcess _MsAutoPotionProcess = FhUtil.get_fptr(__addr_MsAutoPotionProcess); - private readonly MsSetChrWeak _MsSetChrWeak = FhUtil.get_fptr(__addr_MsSetChrWeak); - private readonly MsAutoRelifeProcess _MsAutoRelifeProcess = FhUtil.get_fptr(__addr_MsAutoRelifeProcess); - private readonly MsStatusEffectCheck _MsStatusEffectCheck = FhUtil.get_fptr(__addr_MsStatusEffectCheck); - private readonly MsStatusDefenseEffect _MsStatusDefenseEffect = FhUtil.get_fptr(__addr_MsStatusDefenseEffect); - private readonly MsActionRequest _MsActionRequest = FhUtil.get_fptr(__addr_MsActionRequest); - private readonly MsPopBtlPos _MsPopBtlPos = FhUtil.get_fptr(__addr_MsPopBtlPos); - private readonly MsDamageCheckDeath _MsDamageCheckDeath = FhUtil.get_fptr(__addr_MsDamageCheckDeath); - private readonly MsDamageSetMotion _MsDamageSetMotion = FhUtil.get_fptr(__addr_MsDamageSetMotion); - private readonly brnd _brnd = FhUtil.get_fptr(__addr_brnd); - private readonly TOBtlSetMacroCommandType _TOBtlSetMacroCommandType = FhUtil.get_fptr(__addr_TOBtlSetMacroCommandType); - private readonly TOBtlSetMacroCommandValue _TOBtlSetMacroCommandValue = FhUtil.get_fptr(__addr_TOBtlSetMacroCommandValue); - private readonly TOGetSaveChrName _TOGetSaveChrName = FhUtil.get_fptr(__addr_TOGetSaveChrName); - private readonly MsGetComData _MsGetComData = FhUtil.get_fptr(__addr_MsGetComData); - private readonly MsGetRomBtlText _MsGetRomBtlText = FhUtil.get_fptr(__addr_MsGetRomBtlText); - private readonly FUN_0089db10 _FUN_0089db10 = FhUtil.get_fptr(__addr_FUN_0089db10); - - private readonly MsGetSaveCommand _fn_MsGetSaveCommand = FhUtil.get_fptr(__addr_MsGetSaveCommand); - private readonly TOBtlDrawLearningMessageWindow _fn_TOBtlDrawLearningMessageWindow = FhUtil.get_fptr(__addr_TOBtlDrawLearningMessageWindow); + //private readonly FhMethodHandle _MsGetSaveCommand; + //private readonly FhMethodHandle _MsSetRamChrAbility; + //private readonly FhMethodHandle _MsLimitTidusLearn; + //private readonly FhMethodHandle _MsAfterDamageProcess; + //private readonly FhMethodHandle _ret_doesChrKnowCommand; + //private readonly FhMethodHandle _MsSetSaveCommandWithPrefix; + //private readonly FhMethodHandle _TOBtlDrawLearningMessageWindow; + + //private readonly MsGetChr _MsGetChr = FhUtil.get_fptr(__addr_MsGetChr); + //private readonly MsMenuCloseTitleWindow _MsMenuCloseTitleWindow = FhUtil.get_fptr(__addr_MsMenuCloseTitleWindow); + //private readonly MsMessageCueRegist _MsMessageCueRegist = FhUtil.get_fptr(__addr_MsMessageCueRegist); + //private readonly MsSetStealEffect _MsSetStealEffect = FhUtil.get_fptr(__addr_MsSetStealEffect); + //private readonly MsRegSEplay2 _MsRegSEplay2 = FhUtil.get_fptr(__addr_MsRegSEplay2); + //private readonly MsPayGIL _MsPayGIL = FhUtil.get_fptr(__addr_MsPayGIL); + //private readonly MsSetStealGillEffect _MsSetStealGillEffect = FhUtil.get_fptr(__addr_MsSetStealGillEffect); + //private readonly MsCheckRange _MsCheckRange = FhUtil.get_fptr(__addr_MsCheckRange); + //private readonly MsSetSaveCommand _MsSetSaveCommand = FhUtil.get_fptr(__addr_MsSetSaveCommand); + //private readonly achievementUnlockAchievement _achievementUnlockAchievement = FhUtil.get_fptr(__addr_achievementUnlockAchievement); + //private readonly MsNumberRegist _MsNumberRegist = FhUtil.get_fptr(__addr_MsNumberRegist); + //private readonly MsLimitTypeDamageCheck _MsLimitTypeDamageCheck = FhUtil.get_fptr(__addr_MsLimitTypeDamageCheck); + //private readonly MsSubHP _MsSubHP = FhUtil.get_fptr(__addr_MsSubHP); + //private readonly MsSubMP _MsSubMP = FhUtil.get_fptr(__addr_MsSubMP); + //private readonly MsSubCTB _MsSubCTB = FhUtil.get_fptr(__addr_MsSubCTB); + //private readonly MsLimitTypeStatusCheck _MsLimitTypeStatusCheck = FhUtil.get_fptr(__addr_MsLimitTypeStatusCheck); + //private readonly MsLimitStatusProcess _MsLimitStatusProcess = FhUtil.get_fptr(__addr_MsLimitStatusProcess); + //private readonly MsAliveProcess _MsAliveProcess = FhUtil.get_fptr(__addr_MsAliveProcess); + //private readonly MsStoneProcess _MsStoneProcess = FhUtil.get_fptr(__addr_MsStoneProcess); + //private readonly MsBlowProcess _MsBlowProcess = FhUtil.get_fptr(__addr_MsBlowProcess); + //private readonly MsThreatProcess _MsThreatProcess = FhUtil.get_fptr(__addr_MsThreatProcess); + //private readonly MsAutoCureProcess _MsAutoCureProcess = FhUtil.get_fptr(__addr_MsAutoCureProcess); + //private readonly MsAutoPotionProcess _MsAutoPotionProcess = FhUtil.get_fptr(__addr_MsAutoPotionProcess); + //private readonly MsSetChrWeak _MsSetChrWeak = FhUtil.get_fptr(__addr_MsSetChrWeak); + //private readonly MsAutoRelifeProcess _MsAutoRelifeProcess = FhUtil.get_fptr(__addr_MsAutoRelifeProcess); + //private readonly MsStatusEffectCheck _MsStatusEffectCheck = FhUtil.get_fptr(__addr_MsStatusEffectCheck); + //private readonly MsStatusDefenseEffect _MsStatusDefenseEffect = FhUtil.get_fptr(__addr_MsStatusDefenseEffect); + //private readonly MsActionRequest _MsActionRequest = FhUtil.get_fptr(__addr_MsActionRequest); + //private readonly MsPopBtlPos _MsPopBtlPos = FhUtil.get_fptr(__addr_MsPopBtlPos); + //private readonly MsDamageCheckDeath _MsDamageCheckDeath = FhUtil.get_fptr(__addr_MsDamageCheckDeath); + //private readonly MsDamageSetMotion _MsDamageSetMotion = FhUtil.get_fptr(__addr_MsDamageSetMotion); + //private readonly brnd _brnd = FhUtil.get_fptr(__addr_brnd); + //private readonly TOBtlSetMacroCommandType _TOBtlSetMacroCommandType = FhUtil.get_fptr(__addr_TOBtlSetMacroCommandType); + //private readonly TOBtlSetMacroCommandValue _TOBtlSetMacroCommandValue = FhUtil.get_fptr(__addr_TOBtlSetMacroCommandValue); + //private readonly TOGetSaveChrName _TOGetSaveChrName = FhUtil.get_fptr(__addr_TOGetSaveChrName); + //private readonly MsGetComData _MsGetComData = FhUtil.get_fptr(__addr_MsGetComData); + //private readonly MsGetRomBtlText _MsGetRomBtlText = FhUtil.get_fptr(__addr_MsGetRomBtlText); + //private readonly FUN_0089db10 _FUN_0089db10 = FhUtil.get_fptr(__addr_FUN_0089db10); + + //private readonly MsGetSaveCommand _fn_MsGetSaveCommand = FhUtil.get_fptr(__addr_MsGetSaveCommand); + //private readonly TOBtlDrawLearningMessageWindow _fn_TOBtlDrawLearningMessageWindow = FhUtil.get_fptr(__addr_TOBtlDrawLearningMessageWindow); } diff --git a/src/modules/overdrives.cs b/src/modules/overdrives.cs index 3e3cdca..f09b60a 100644 --- a/src/modules/overdrives.cs +++ b/src/modules/overdrives.cs @@ -1,19 +1,16 @@ -using Archipelago.MultiClient.Net.Enums; +using Archipelago.MultiClient.Net.Enums; +using ArchipelagoFFX.Client; +using Fahrenheit; using Fahrenheit.Atel; using Fahrenheit.FFX; using Fahrenheit.FFX.Battle; using Fahrenheit.FFX.Ids; - using System.IO; using System.Runtime.InteropServices; - -using ArchipelagoFFX.Client; - -using Fahrenheit; - -using static Fahrenheit.FFX.Globals; using static ArchipelagoFFX.ArchipelagoFFXModule; -using static ArchipelagoFFX.delegates; +using static Fahrenheit.FFX.Globals; +using FhGCall = Fahrenheit.FhCall; +using FhXCall = Fahrenheit.FFX.FhCall; namespace ArchipelagoFFX; @@ -29,6 +26,8 @@ public unsafe partial class OverdriveModule : FhModule { private FhModuleHandle _ffx_interop_handle; private ArchipelagoFFXModule? _ffx_interop; + private FhMethodHandle h_ret_doesChrKnowCommand => new(new FhMethodLocation("FFX.exe", 0x3A30C0)); + // Damage Calc [StructLayout(LayoutKind.Explicit, Size = 0x2C)] private struct DamageInfo @@ -71,33 +70,8 @@ private struct Chr__0x774 }; public OverdriveModule() { - const string GAME = "FFX.exe"; - - _client_handle = new(this); + _client_handle = new(this); _ffx_interop_handle = new(this); - - _MsGetSaveCommand = new FhMethodHandle(this, GAME, __addr_MsGetSaveCommand, h_MsGetSaveCommand); - _MsSetRamChrAbility = new FhMethodHandle(this, GAME, __addr_MsSetRamChrAbility, h_MsSetRamChrAbility); - _MsLimitTidusLearn = new FhMethodHandle(this, GAME, __addr_MsLimitTidusLearn, h_MsLimitTidusLearn); - _MsAfterDamageProcess = new FhMethodHandle(this, GAME, __addr_MsAfterDamageProcess, h_MsAfterDamageProcess); - _ret_doesChrKnowCommand = new FhMethodHandle(this, GAME, __addr_ret_doesChrKnowCommand, h_ret_doesChrKnowCommand); - _MsSetSaveCommandWithPrefix = new FhMethodHandle(this, GAME, __addr_MsSetSaveCommandWithPrefix, h_MsSetSaveCommandWithPrefix); - _TOBtlDrawLearningMessageWindow = new FhMethodHandle(this, GAME, __addr_TOBtlDrawLearningMessageWindow, h_TOBtlDrawLearningMessageWindow); - } - - public override bool init(FhModContext mod_context, FileStream global_state_file) { - _mod_context = mod_context; - _global_state = global_state_file; - - return _client_handle.try_get_module(out _client) - && _ffx_interop_handle.try_get_module(out _ffx_interop) - && _MsGetSaveCommand.hook() - && _MsSetRamChrAbility.hook() - && _MsLimitTidusLearn.hook() - && _MsAfterDamageProcess.hook() - && _ret_doesChrKnowCommand.hook() - && _MsSetSaveCommandWithPrefix.hook() - && _TOBtlDrawLearningMessageWindow.hook(); } // Helper class for overdrive provider functions @@ -222,7 +196,23 @@ public static void set_overdrive_modes() { } } - private static T* ptr_at(nint address) where T : unmanaged { return (T*)address; } + public override bool init(FhModContext mod_context, FileStream global_state_file) + { + _mod_context = mod_context; + _global_state = global_state_file; + + return _client_handle.try_get_module(out _client) + && _ffx_interop_handle.try_get_module(out _ffx_interop) + && FhXCall.h_MsGetSaveCommand.hook(this, h_MsGetSaveCommand) + && FhXCall.h_MsSetRamChrAbility.hook(this, h_MsSetRamChrAbility) + && FhXCall.h_MsLimitTidusLearn.hook(this, h_MsLimitTidusLearn) + && FhXCall.h_MsAfterDamageProcess.hook(this, h_MsAfterDamageProcess) + && h_ret_doesChrKnowCommand.hook(this, h_ret_doesChrKnowCommand_reimpl) + && FhXCall.h_MsSetSaveCommandWithPrefix.hook(this, h_MsSetSaveCommandWithPrefix) + && FhXCall.h_TOBtlDrawLearningMessageWindow.hook(this, h_TOBtlDrawLearningMessageWindow); + } + + private static T* ptr_at(nint address) where T : unmanaged { return (T*)(address); } private static T get_at(nint address) where T : unmanaged { return *ptr_at(address); } private static void set_at(nint address, T value) where T : unmanaged { *ptr_at(address) = value; } @@ -235,14 +225,15 @@ private int h_MsGetSaveCommand(int chr_id, uint com_id) { OverdriveProvider.provide_overdrive(chr_id); } - return _MsGetSaveCommand.orig_fptr(chr_id, com_id); + return FhXCall.h_MsGetSaveCommand.chain_from(h_MsGetSaveCommand).fnptr!(chr_id, com_id); } // When game is attempting to set character abilities, ensure the correct overdrive provider is called first private void h_MsSetRamChrAbility(int chr_id, Chr* chr) { OverdriveProvider.provide_overdrive(chr_id); - _MsSetRamChrAbility.orig_fptr(chr_id, chr); + FhXCall.h_MsSetRamChrAbility.chain_from(h_MsSetRamChrAbility).fnptr!(chr_id, chr); + return; } // Runs on every Tidus Limit. Override the normal requirements, and send locations based on 10 / 20 / 40 @@ -259,19 +250,19 @@ private int h_MsLimitTidusLearn(int chr_id) { if (tidusLimitUses >= 10) { if (send_overdrive(PlayerCommandId.PCOM_SLICE_AND_DICE)) { - _MsMessageCueRegist(6, PlySaveId.PC_TIDUS, PlayerCommandId.PCOM_SLICE_AND_DICE, 0x1e, 0x32); + FhXCall.h_MsMessageCueRegist.fnptr!(6, PlySaveId.PC_TIDUS, PlayerCommandId.PCOM_SLICE_AND_DICE, 0x1e, 0x32); } } if (tidusLimitUses >= 20) { if(send_overdrive(PlayerCommandId.PCOM_ENERGY_RAIN)) { - _MsMessageCueRegist(6, PlySaveId.PC_TIDUS, PlayerCommandId.PCOM_ENERGY_RAIN, 0x1e, 0x32); + FhXCall.h_MsMessageCueRegist.fnptr!(6, PlySaveId.PC_TIDUS, PlayerCommandId.PCOM_ENERGY_RAIN, 0x1e, 0x32); } } if (tidusLimitUses >= 40) { if(send_overdrive(PlayerCommandId.PCOM_BLITZ_ACE)) { - _MsMessageCueRegist(6, PlySaveId.PC_TIDUS, PlayerCommandId.PCOM_BLITZ_ACE, 0x1e, 0x32); + FhXCall.h_MsMessageCueRegist.fnptr!(6, PlySaveId.PC_TIDUS, PlayerCommandId.PCOM_BLITZ_ACE, 0x1e, 0x32); } } @@ -282,8 +273,8 @@ private int h_MsLimitTidusLearn(int chr_id) { private uint h_MsAfterDamageProcess(int attacker_id, uint param_2, int target_id, uint* param_4, uint param_5) { uint uVar12 = 0; DamageInfo* local_30 = (DamageInfo*)0x0; - Chr* attacker = _MsGetChr(attacker_id); - Chr* target = _MsGetChr(target_id); + Chr* attacker = FhXCall.h_MsGetChr.fnptr!(attacker_id); + Chr* target = FhXCall.h_MsGetChr.fnptr!(target_id); Chr__0x774* target_0x774 = (Chr__0x774*)((int)target + 0x774); for (int n = 2; n > 0; n--) { @@ -293,26 +284,26 @@ private uint h_MsAfterDamageProcess(int attacker_id, uint param_2, int target_id set_at((int)target + 0xDED, (byte)attacker_id); if (!param_5.get_bit(3)) { if (target_0x774->field7_0x7 != 0) { - _MsMenuCloseTitleWindow(0); + FhXCall.h_MsMenuCloseTitleWindow.fnptr!(0); target_0x774->field7_0x7 = 0; //_MsMessageCueRegist(0x4, target_0x774->field7_0x7 + 3, target_0x774->field7_0x7 + 1, 0x1b, 0x23); - _MsMessageCueRegist(0x4, target_0x774->field10_0xA, target_0x774->field8_0x8, 0x1b, 0x23); + FhXCall.h_MsMessageCueRegist.fnptr!(0x4, target_0x774->field10_0xA, target_0x774->field8_0x8, 0x1b, 0x23); if (0 < target_0x774->field8_0x8) { - _MsSetStealEffect(target_id, target_0x774->field1_0x1); - _MsRegSEplay2(target_id, 0x41); + FhXCall.h_MsSetStealEffect.fnptr!(target_id, target_0x774->field1_0x1); + FhXCall.h_MsRegSEplay2.fnptr!(target_id, 0x41); } target_0x774->field5_0x5 |= 1; } if (target_0x774->field12_0xC != 0) { - _MsMenuCloseTitleWindow(0); + FhXCall.h_MsMenuCloseTitleWindow.fnptr!(0); target_0x774->field12_0xC = 0; - _MsMessageCueRegist(0x8, target_0x774->field16_0x10, 0, 0x1b, 0x23); + FhXCall.h_MsMessageCueRegist.fnptr!(0x8, target_0x774->field16_0x10, 0, 0x1b, 0x23); if (0 < target_0x774->field16_0x10) { - _MsPayGIL(-*(int*)(target_0x774 + 9)); - _MsSetStealGillEffect(target_id, target_0x774->field1_0x1); - _MsRegSEplay2(target_id, 0x41); + FhXCall.h_MsPayGIL.fnptr!(-*(int*)(target_0x774 + 9)); + FhXCall.h_MsSetStealGillEffect.fnptr!(target_id, target_0x774->field1_0x1); + FhXCall.h_MsRegSEplay2.fnptr!(target_id, 0x41); } target_0x774->field5_0x5 |= 1; @@ -323,16 +314,16 @@ private uint h_MsAfterDamageProcess(int attacker_id, uint param_2, int target_id if (target_0x774->field4_0x4.get_bit(0)) { byte bVar1 = attacker->ram.limit_charge; attacker->ram.limit_charge = 0; - target->ram.limit_charge = (byte)_MsCheckRange(target->ram.limit_charge + bVar1, 0, target->ram.limit_charge_max); + target->ram.limit_charge = (byte)FhXCall.h_MsCheckRange.fnptr!(target->ram.limit_charge + bVar1, 0, target->ram.limit_charge_max); } if (target_0x774->field4_0x4.get_bit(1)) { - Chr* pCVar8 = _MsGetChr(target_0x774->chr_id__0x17); + Chr* pCVar8 = FhXCall.h_MsGetChr.fnptr!(target_0x774->chr_id__0x17); if (target_id == PlySaveId.PC_KIMAHRI && pCVar8->loot != (ChrLoot*)0x0) { ushort rage_to_learn = pCVar8->loot->ronso_rage; if (rage_to_learn != 0) { if(send_overdrive(rage_to_learn)) { - _MsMessageCueRegist(6, PlySaveId.PC_KIMAHRI, rage_to_learn, 0x1e, 0x32); + FhXCall.h_MsMessageCueRegist.fnptr!(6, PlySaveId.PC_KIMAHRI, rage_to_learn, 0x1e, 0x32); target->ram.limit_charge = target->ram.limit_charge_max; } @@ -344,7 +335,7 @@ private uint h_MsAfterDamageProcess(int attacker_id, uint param_2, int target_id save_data->ability_map_limit.has_white_wind && save_data->ability_map_limit.has_bad_breath && save_data->ability_map_limit.has_mighty_guard && save_data->ability_map_limit.has_nova ) { - _achievementUnlockAchievement(0x19); + FhXCall.h_achievementUnlockAchievement.fnptr!(0x19); } } } @@ -362,15 +353,15 @@ private uint h_MsAfterDamageProcess(int attacker_id, uint param_2, int target_id uint uVar9 = target_0x774_damage_info->field2_0x2; if (iVar7 == 1) { - _MsNumberRegist(target_id, 3, 0, 0, 1, uVar9, 0x81); + FhXCall.h_MsNumberRegist.fnptr!(target_id, 3, 0, 0, 1, uVar9, 0x81); } else if (iVar7 == 2) { - _MsNumberRegist(target_id, 4, 0, 0, 2, uVar9, 0x81); + FhXCall.h_MsNumberRegist.fnptr!(target_id, 4, 0, 0, 2, uVar9, 0x81); } - _MsLimitTypeDamageCheck(attacker_id, attacker, target_id, target, target_0x774_damage_info->out_damage_hp, target_0x774_damage_info->out_damage_expected, target_0x774->field6_0x6); + FhXCall.h_MsLimitTypeDamageCheck.fnptr!(attacker_id, attacker, target_id, target, target_0x774_damage_info->out_damage_hp, target_0x774_damage_info->out_damage_expected, target_0x774->field6_0x6); if (target_0x774_damage_info->dmg_calc_flags1.get_bit(0)) { - _MsSubHP(target_id, target, target_0x774_damage_info->out_damage_hp, target_0x774_damage_info->out_damage_mp, iVar7, uVar9, 0x81); + FhXCall.h_MsSubHP.fnptr!(target_id, target, target_0x774_damage_info->out_damage_hp, target_0x774_damage_info->out_damage_mp, iVar7, uVar9, 0x81); set_at((int)target + 0xF60, get_at((int)target + 0xF60) - target_0x774_damage_info->out_damage_hp); @@ -378,15 +369,15 @@ private uint h_MsAfterDamageProcess(int attacker_id, uint param_2, int target_id } if (target_0x774_damage_info->dmg_calc_flags1.get_bit(1)) { - _MsSubMP(target_id, target, target_0x774_damage_info->out_damage_mp, target_0x774_damage_info->out_damage_hp, iVar7, uVar9, 0x81); + FhXCall.h_MsSubMP.fnptr!(target_id, target, target_0x774_damage_info->out_damage_mp, target_0x774_damage_info->out_damage_hp, iVar7, uVar9, 0x81); } if (target_0x774_damage_info->dmg_calc_flags1.get_bit(2)) { - _MsSubCTB(target_id, target, target_0x774_damage_info->out_damage_ctb, iVar7, uVar9, 0x81); + FhXCall.h_MsSubCTB.fnptr!(target_id, target, target_0x774_damage_info->out_damage_ctb, iVar7, uVar9, 0x81); //dbgPrintf("CTB DAMAGE %d %d : %d\n", target_id, iVar10, (target->ram).ctb); } - _MsLimitTypeStatusCheck(attacker_id, attacker, target_id, target, target_0x774_damage_info->field4_0x4, target_0x774_damage_info->field3_0x3); + FhXCall.h_MsLimitTypeStatusCheck.fnptr!(attacker_id, attacker, target_id, target, target_0x774_damage_info->field4_0x4, target_0x774_damage_info->field3_0x3); StatusPermanentFlags SVar5 = target->ram.status_suffer; byte bVar1 = target->ram.status_suffer_turns_left.darkness; byte bVar2 = target->ram.status_suffer_turns_left.silence; @@ -400,7 +391,7 @@ private uint h_MsAfterDamageProcess(int attacker_id, uint param_2, int target_id } target->ram.status_suffer_extra = target_0x774_damage_info->target_status_suffer_extra; - _MsLimitStatusProcess(target_id, target, target_0x774_damage_info->flags_buffs_mix); + FhXCall.h_MsLimitStatusProcess.fnptr!(target_id, target, target_0x774_damage_info->flags_buffs_mix); if (target->ram.status_suffer_turns_left.regen != 0 && bVar3 == 0) { target->ram.regen_strength = 0; @@ -409,37 +400,37 @@ private uint h_MsAfterDamageProcess(int attacker_id, uint param_2, int target_id StatusPermanentFlags SVar6 = target->ram.status_suffer; set_at((int)target + 0xDCE, SVar6.petrification()); if (target->ram.status_suffer.death() != SVar5.death()) { - _MsAliveProcess(target_id, target); + FhXCall.h_MsAliveProcess.fnptr!(target_id, target); } if (target->ram.status_suffer.petrification() != SVar5.petrification()) { - _MsStoneProcess(target_id, target); + FhXCall.h_MsStoneProcess.fnptr!(target_id, target); } if (target->ram.status_suffer_extra.eject() != bVar4.eject()) { - _MsBlowProcess(target_id, target); + FhXCall.h_MsBlowProcess.fnptr!(target_id, target); } if (target->ram.status_suffer.threaten() != SVar5.threaten()) { - _MsThreatProcess(target_id, target); + FhXCall.h_MsThreatProcess.fnptr!(target_id, target); } target_0x774->field5_0x5 |= 1; if (target->ram.auto_ability_effects.has_auto_med) { - _MsAutoCureProcess(target_id, target, attacker_id, (int)SVar5 >> 3 & 1, (int)SVar5 >> 1 & 1, bVar1, bVar2); + FhXCall.h_MsAutoCureProcess.fnptr!(target_id, target, attacker_id, (int)SVar5 >> 3 & 1, (int)SVar5 >> 1 & 1, bVar1, bVar2); } if (0 < local_20 && target->ram.auto_ability_effects.has_auto_potion) { - _MsAutoPotionProcess(target_id, target, attacker_id); + FhXCall.h_MsAutoPotionProcess.fnptr!(target_id, target, attacker_id); } - _MsSetChrWeak(target_id, -1); + FhXCall.h_MsSetChrWeak.fnptr!(target_id, -1); uVar12 |= 2; target_0x774->field0_0x0 += 1; } if (get_at((int)&target->ram + 0x19C)) { - _MsAutoRelifeProcess(attacker_id, attacker, target_id, target); + FhXCall.h_MsAutoRelifeProcess.fnptr!(attacker_id, attacker, target_id, target); } if (!param_5.get_bit(1) && (target_0x774_damage_info->field0_0x0 != 1 || !target_0x774->field5_0x5.get_bit(2))) { @@ -448,8 +439,8 @@ private uint h_MsAfterDamageProcess(int attacker_id, uint param_2, int target_id } if (!param_5.get_bit(4)) { - _MsStatusEffectCheck(target_id); - if (_MsStatusDefenseEffect(attacker_id, target_id, target_0x774_damage_info->dmg_calc_flags1) != 0) { + FhXCall.h_MsStatusEffectCheck.fnptr!(target_id); + if (FhXCall.h_MsStatusDefenseEffect.fnptr!(attacker_id, target_id, target_0x774_damage_info->dmg_calc_flags1) != 0) { *param_4 = (uint)target_id; } } @@ -461,11 +452,11 @@ private uint h_MsAfterDamageProcess(int attacker_id, uint param_2, int target_id if (target_0x774->field5_0x5.get_bit(0) && !target_0x774->field5_0x5.get_bit(1)) { set_at((int)&target->ram + 0x19D, false); target_0x774->field5_0x5 |= 2; - _MsActionRequest(target_id, attacker_id, 3, 0, 1, null); + FhXCall.h_MsActionRequest.fnptr!(target_id, attacker_id, 3, 0, 1, null); } if (!param_5.get_bit(10)) { - _MsPopBtlPos(target); + FhXCall.h_MsPopBtlPos.fnptr!(target); } else { target_0x774->field2_0x2 = 0xff; } @@ -477,7 +468,7 @@ private uint h_MsAfterDamageProcess(int attacker_id, uint param_2, int target_id int not_attacking_self = attacker_id != target_id ? 1 : 0; - if (!uVar12.get_bit(0) && _MsDamageCheckDeath(attacker_id, target_id, 0, not_attacking_self) != 0) { + if (!uVar12.get_bit(0) && FhXCall.h_MsDamageCheckDeath.fnptr!(attacker_id, target_id, 0, not_attacking_self) != 0) { return uVar12; } @@ -486,28 +477,28 @@ private uint h_MsAfterDamageProcess(int attacker_id, uint param_2, int target_id } if (!param_5.get_bit(5)) { - _MsDamageSetMotion(target_id, local_30->field0_0x0, not_attacking_self); + FhXCall.h_MsDamageSetMotion.fnptr!(target_id, local_30->field0_0x0, not_attacking_self); return uVar12; } if (local_30->field0_0x0 != 5) { if (local_30->field0_0x0 == 6) { - _MsDamageSetMotion(target_id, _brnd(9).get_bit(0) ? 0x10 : 0xF, not_attacking_self); + FhXCall.h_MsDamageSetMotion.fnptr!(target_id, FhXCall.h_brnd.fnptr!(9).get_bit(0) ? 0x10 : 0xF, not_attacking_self); return uVar12; } if (local_30->field0_0x0 != 8) { - _MsDamageSetMotion(target_id, local_30->field0_0x0, not_attacking_self); + FhXCall.h_MsDamageSetMotion.fnptr!(target_id, local_30->field0_0x0, not_attacking_self); return uVar12; } } - _MsDamageSetMotion(target_id, _brnd(9).get_bits(0, 2) + 0xD, not_attacking_self); + FhXCall.h_MsDamageSetMotion.fnptr!(target_id, FhXCall.h_brnd.fnptr!(9).get_bits(0, 2) + 0xD, not_attacking_self); return uVar12; } // Required in order to allow Biran & Yenke's ChrLoot to progress to the next Ronso Rage based on location sent, rather than command known - private int h_ret_doesChrKnowCommand(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + private int h_ret_doesChrKnowCommand_reimpl(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int com_id = atelStack->pop_int(); int chr_id = atelStack->pop_int(); @@ -520,7 +511,7 @@ private int h_ret_doesChrKnowCommand(AtelBasicWorker* work, int* storage, AtelSt atelStack->push_int(chr_id); atelStack->push_int(com_id); - return _ret_doesChrKnowCommand.orig_fptr(work, storage, atelStack); + return h_ret_doesChrKnowCommand.fnptr!(work, storage, atelStack); } // Called from teachAbilityToPartyMemberSilently & teachAbilityToPartyMemberWithMsg @@ -531,20 +522,20 @@ private void h_MsSetSaveCommandWithPrefix(int chr_id, int com_id, int param_3) { return; } - _MsSetSaveCommandWithPrefix.orig_fptr(chr_id, com_id, param_3); + FhXCall.h_MsSetSaveCommandWithPrefix.chain_from(h_MsSetSaveCommandWithPrefix).fnptr!(chr_id, com_id, param_3); } private int h_TOBtlDrawLearningMessageWindow(int chr_id, int com_id) { byte* data_end; - byte* chr_name = _TOGetSaveChrName(chr_id); - _TOBtlSetMacroCommandType(7, 0, 0); - _TOBtlSetMacroCommandValue(7, 0, chr_name); + byte* chr_name = FhXCall.h_TOGetSaveChrName.fnptr!(chr_id); + FhXCall.h_TOBtlSetMacroCommandType.fnptr!(7, 0, 0); + FhXCall.h_TOBtlSetMacroCommandValue.fnptr!(7, 0, chr_name); - Command* com = _MsGetComData(com_id, &data_end); + Command* com = FhXCall.h_MsGetComData.fnptr!(com_id, &data_end); ushort com_name_offset = com->name_offset; - _TOBtlSetMacroCommandType(7, 1, 0); + FhXCall.h_TOBtlSetMacroCommandType.fnptr!(7, 1, 0); if (item_locations.overdrive.TryGetValue(com_id - PlayerCommandId.PCOM_SPIRAL_CUT, out var item)) { NativeCustomString custom_text; @@ -555,13 +546,13 @@ private int h_TOBtlDrawLearningMessageWindow(int chr_id, int com_id) { custom_text = new($"{item.player}'s {item.name}"); } - _TOBtlSetMacroCommandValue(7, 1, custom_text.encoded); + FhXCall.h_TOBtlSetMacroCommandValue.fnptr!(7, 1, custom_text.encoded); } else { - _TOBtlSetMacroCommandValue(7, 1, data_end + com_name_offset); + FhXCall.h_TOBtlSetMacroCommandValue.fnptr!(7, 1, data_end + com_name_offset); } - byte* btl_text = _MsGetRomBtlText(0x300d, 0); - _FUN_0089db10(0, btl_text); + byte* btl_text = FhXCall.h_MsGetRomBtlText.fnptr!(0x300d, 0); + FhXCall.h_FUN_0089db10.fnptr!(0, btl_text); return 7; } From c0f3f7f41d9cfd46de985815c535ffd932efa5df Mon Sep 17 00:00:00 2001 From: Andrew K Date: Wed, 10 Jun 2026 12:35:09 +1000 Subject: [PATCH 06/20] Delegate Migration --- Fahrenheit.Modules.ArchipelagoFFX.csproj | 2 +- src/archipelago.cs | 27 +- src/customization.cs | 262 ++++---- src/delegates/capture_delegates.cs | 142 ----- src/delegates/deathlink_delegates.cs | 44 -- src/delegates/delegates.cs | 721 ----------------------- src/delegates/overdrive_delegates.cs | 233 -------- src/gui/debugWindow.cs | 25 +- src/hooks.cs | 705 +++++----------------- src/modules/captures.cs | 176 ++---- src/modules/deathlink.cs | 28 +- src/modules/hardcore_contest.cs | 18 +- src/modules/sphere_grid.cs | 70 +-- 13 files changed, 374 insertions(+), 2079 deletions(-) delete mode 100644 src/delegates/capture_delegates.cs delete mode 100644 src/delegates/deathlink_delegates.cs delete mode 100644 src/delegates/delegates.cs delete mode 100644 src/delegates/overdrive_delegates.cs diff --git a/Fahrenheit.Modules.ArchipelagoFFX.csproj b/Fahrenheit.Modules.ArchipelagoFFX.csproj index 6caf590..efe5faf 100644 --- a/Fahrenheit.Modules.ArchipelagoFFX.csproj +++ b/Fahrenheit.Modules.ArchipelagoFFX.csproj @@ -38,7 +38,7 @@ - + diff --git a/src/archipelago.cs b/src/archipelago.cs index 7c81ed6..ca16e0e 100644 --- a/src/archipelago.cs +++ b/src/archipelago.cs @@ -1,7 +1,9 @@ using Archipelago.MultiClient.Net.Enums; +using ArchipelagoFFX.Client; +using ArchipelagoFFX.GUI; +using Fahrenheit; using Fahrenheit.Atel; using Fahrenheit.Events; -using Fahrenheit.FFX; using Fahrenheit.FFX.Ids; //using Fahrenheit.ImGuiNET; using System; @@ -16,16 +18,11 @@ using System.Text.Json; using System.Text.Json.Serialization; using System.Text.RegularExpressions; - -using ArchipelagoFFX.Client; -using ArchipelagoFFX.GUI; - -using Fahrenheit; - -using static Fahrenheit.FFX.Globals; //using Fahrenheit.Modules.ArchipelagoFFX.GUI; using static ArchipelagoFFX.ArchipelagoData; +using static Fahrenheit.FFX.Globals; using Color = Archipelago.MultiClient.Net.Models.Color; +using FhXCall = Fahrenheit.FFX.FhCall; namespace ArchipelagoFFX; @@ -185,15 +182,15 @@ public struct ArchipelagoSeedOptions { [JsonInclude] public string PlayerName; [JsonInclude] public string SeedId; - [JsonInclude] public ArchipelagoData.Goal Goal; - [JsonInclude] public ArchipelagoData.GoalRequirement GoalRequirement; + [JsonInclude] public Goal Goal; + [JsonInclude] public GoalRequirement GoalRequirement; [JsonInclude] public int RequiredPartyMembers; [JsonInclude] public int RequiredPrimers; [JsonInclude] public int APMultiplier; [JsonInclude] public int AlwaysSensor; - [JsonInclude] public ArchipelagoData.CaptureRequirement CaptureRequirement; + [JsonInclude] public CaptureRequirement CaptureRequirement; [JsonInclude] public int AlwaysCapture; [JsonInclude] public int CaptureDamage; [JsonInclude] public int EncounterWeighting; @@ -1010,9 +1007,9 @@ public void set_character_model(int chr_id) { stack.push_int(chr_id + 1); AtelBasicWorker* worker0 = Atel.controllers[0].worker(0); int storage = 0; - _Common_loadModel(worker0, &storage, &stack); + FhXCall.h_Common_loadModel.fnptr!(worker0, &storage, &stack); stack.push_int(0); - _Common_linkFieldToBattleActor(worker0, &storage, &stack); + FhXCall.h_Common_linkFieldToBattleActor.fnptr!(worker0, &storage, &stack); } public uint allocate_file(string filename, out nint file_ptr) { @@ -1029,7 +1026,7 @@ public uint allocate_file(string filename, out nint file_ptr) { var file_length = *(long*)(*(int*)(fileStream[1] + 0xc) + 8); file_ptr = Marshal.AllocHGlobal((int)file_length); uint max_len = (uint)file_length; - readBytes = _readFile((nint)fs, file_ptr, max_len); + readBytes = FhXCall.h_readFile.fnptr!((nint)fs, file_ptr, max_len); } _logger.Debug($"read {readBytes}, beginning={((byte*)file_ptr)[0]} {((byte*)file_ptr)[1]} {((byte*)file_ptr)[2]} {((byte*)file_ptr)[3]}"); return readBytes; @@ -1048,7 +1045,7 @@ public struct CustomStringDrawInfo(ManagedCustomString customString, Vector2 pos public override void render_game() { foreach ((string key, CustomStringDrawInfo drawInfo) in customStringDrawInfos) { fixed (byte* text = drawInfo.customString.encoded) { - _TOMkpCrossExtMesFontLClutTypeRGBA(0, text, drawInfo.pos.X, drawInfo.pos.Y, drawInfo.color, 0, 0x80, 0x80, 0x80, 0x80, drawInfo.scale, 0); + FhXCall.h_TOMkpCrossExtMesFontLClutTypeRGBA.fnptr!(0, text, drawInfo.pos.X, drawInfo.pos.Y, drawInfo.color, 0, 0x80, 0x80, 0x80, 0x80, drawInfo.scale, 0); } } } diff --git a/src/customization.cs b/src/customization.cs index c4a2e7b..8f7511a 100644 --- a/src/customization.cs +++ b/src/customization.cs @@ -1,70 +1,37 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: MIT +using Fahrenheit; using Fahrenheit.FFX; - +using Fahrenheit.FFX.Ids; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; - -using Fahrenheit; - -using static ArchipelagoFFX.delegates; +using FhXCall = Fahrenheit.FFX.FhCall; namespace ArchipelagoFFX; public unsafe partial class ArchipelagoFFXModule { - // Customization - public static FhMethodHandle _PrepareMenuList; - public static FhMethodHandle _UpdateGearCustomizationMenuState; - public static FhMethodHandle _UpdateAeonCustomizationMenuState; - public static FhMethodHandle _DrawGearCustomizationMenu; - public static FhMethodHandle _DrawAeonCustomizationMenu; - public static MsGetRomKaizou _MsGetRomKaizou; - public static MsGetRomAbility _MsGetRomAbility; - public static MsGetRomSummonGrow _MsGetRomSummonGrow; - public static TkMn2GetSummonGrowMax _TkMn2GetSummonGrowMax; - public static TkMenuGetCurrentSummon _TkMenuGetCurrentSummon; - public static MsGetSaveCommand _MsGetSaveCommand; - - public static FUN_008c1c70 _FUN_008c1c70; - public static TODrawMenuPlateXYWHType _TODrawMenuPlateXYWHType; - public static FUN_008f8bb0 _FUN_008f8bb0; - public static TODrawScissorXYWH _TODrawScissorXYWH; - public static FUN_008d5d20 _FUN_008d5d20; - public static FUN_008c0f40 _FUN_008c0f40; - public static FUN_008c1350_DrawScissor512x416 _FUN_008c1350_DrawScissor512x416; - public static FUN_008d5dc0 _FUN_008d5dc0; - public static DrawCrossMenuScrollParts _DrawCrossMenuScrollParts; - public static FUN_008d6630 _FUN_008d6630; - - public static TkVU1SyncPath _TkVU1SyncPath; - public static FUN_008e71d0 _FUN_008e71d0; - public static FUN_008ff490 _FUN_008ff490; - public static FUN_008cd960 _FUN_008cd960; - public static FUN_008cd9f0 _FUN_008cd9f0; - public static ToGetCrossExtMesFontWidth _ToGetCrossExtMesFontWidth; - public static FUN_008bee80 _FUN_008bee80; - - public static TOMkpShapeXYWHUV _TOMkpShapeXYWHUV; - public static TOMkpCrossExtMesFontLClut _TOMkpCrossExtMesFontLClut; - public static FUN_008d48e0 _FUN_008d48e0; - public static FUN_008d4140 _FUN_008d4140; - public static TkMn2DrawKickSyncPacket _TkMn2DrawKickSyncPacket; - - - public static TkMenuMainAllocWindow _TkMenuMainAllocWindow; - public static TkMenuMainRegistWindow _TkMenuMainRegistWindow; - - - public static FUN_008e33a0 _FUN_008e33a0; - public static FUN_008b4460 _FUN_008b4460; - public static FUN_008e2de0 _FUN_008e2de0; - public static MsSetSaveParamAll _MsSetSaveParamAll; - public static MsSetWeaponName _MsSetWeaponName; - public static FUN_008c2c40 _FUN_008c2c40; - public static TkMn2DrawCrossCursor _TkMn2DrawCrossCursor; - - public static FhMethodHandle _FUN_008d5720; + public enum CustomizationStatusEnum : byte { + NONE = 0x0, + AEON_AVAILABLE = 0x4, + AEON_ALREADY_LEARNED = 0x5, + AEON_CANNOT_LEARN_WITHOUT_KEY = 0x6, + AEON_NOT_ENOUGH_ITEMS = 0x7, + + GEAR_AVAILABLE = 0xb, + GEAR_ALREADY_APPLIED = 0xc, + GEAR_NOT_ENOUGH_ITEMS = 0xe, + GEAR_CONFLICTING = 0xf, // (same group but lower level) or (same group, same level, different international bonus) or (international bonus is 0xfe AND gear has any ability with 0xff international bonus) + GEAR_NO_SLOTS = 0x10, + //NONE = 0x11 + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct CustomizationMenuList { + public ushort a_ability_id; + public CustomizationStatusEnum status; + public byte customization_id; + } // Customization-related private static int selected_gear_slot = 0; @@ -98,17 +65,18 @@ public void PrepareMenuList_SetLength(uint added, uint skipped) { } } - public void h_PrepareMenuList(MenuListEnum menu_list_id, Equipment* gear) { + public void h_PrepareMenuList(MenuList menu_list_id, Equipment* gear) { + //MenuList menu_list_id = (MenuList)menu_list_id_raw; _logger.Info($"{menu_list_id}"); uint[] ability_international_bonuses = new uint[4]; uint[] ability_group_idxs = new uint[4]; uint[] ability_group_levels = new uint[4]; - if (menu_list_id == MenuListEnum.GEAR_CUSTOMIZATION) { + if (menu_list_id == MenuList.GEAR_CUSTOMIZATION) { // Modify kaizou.bin int num_customizations; - CustomizationRecipe* customizations = _MsGetRomKaizou(&num_customizations); + CustomizationRecipe* customizations = FhXCall.h_MsGetRomKaizou.fnptr!(&num_customizations); if (original_kaizou_costs == null) { original_kaizou_costs = new ushort[num_customizations]; for (int i = 0; i < num_customizations; i++) { @@ -151,7 +119,7 @@ public void h_PrepareMenuList(MenuListEnum menu_list_id, Equipment* gear) { ushort ability_id = gear->abilities[i]; if (ability_id != 0 && ability_id != 0xFF) { int a_ability_id; - AutoAbility* a_ability = _MsGetRomAbility(ability_id, &a_ability_id); + AutoAbility* a_ability = FhXCall.h_MsGetRomAbility.fnptr!(ability_id, &a_ability_id); ability_group_idxs[num_abilities] = (uint)a_ability->group_idx; ability_group_levels[num_abilities] = (uint)a_ability->group_level; @@ -173,7 +141,7 @@ public void h_PrepareMenuList(MenuListEnum menu_list_id, Equipment* gear) { if (customization.target_gear_type.HasFlag(gear_type)) { ushort a_ability_id = customization.auto_ability; int local_68; - AutoAbility* a_ability = _MsGetRomAbility(a_ability_id, &local_68); + AutoAbility* a_ability = FhXCall.h_MsGetRomAbility.fnptr!(a_ability_id, &local_68); uint item_count = Globals.save_data->get_item_count(customization.item); if (item_count == 0 && customization.item_cost != 0) { @@ -239,11 +207,11 @@ public void h_PrepareMenuList(MenuListEnum menu_list_id, Equipment* gear) { // Set length PrepareMenuList_SetLength(added, skipped); - } else if (menu_list_id == MenuListEnum.AEON_ABILITIES) { + } else if (menu_list_id == MenuList.AEON_ABILITIES) { // TODO: Modify sum_grow.bin int num_customizations; - CustomizationRecipe* customizations = _MsGetRomSummonGrow(&num_customizations); - num_customizations = _TkMn2GetSummonGrowMax(); + CustomizationRecipe* customizations = FhXCall.h_MsGetRomSummonGrow.fnptr!(&num_customizations); + num_customizations = FhXCall.h_TkMn2GetSummonGrowMax.fnptr!(); if (original_sum_grow_costs == null) { original_sum_grow_costs = new ushort[num_customizations]; for (int i = 0; i < num_customizations; i++) { @@ -266,7 +234,7 @@ public void h_PrepareMenuList(MenuListEnum menu_list_id, Equipment* gear) { CustomizationMenuList* menu_list_iter = FhUtil.ptr_at(0x1197730); uint* _DAT_0186a20c = FhUtil.ptr_at(0x146A20C); - byte current_summon = _TkMenuGetCurrentSummon(); + byte current_summon = FhXCall.h_TkMenuGetCurrentSummon.fnptr!(); bool has_key_item = Globals.save_data->key_items.get(0xa022); uint added = 0; @@ -275,7 +243,7 @@ public void h_PrepareMenuList(MenuListEnum menu_list_id, Equipment* gear) { CustomizationRecipe customization = customizations[customization_id]; ushort auto_ability_id = customization.auto_ability; menu_list_iter->customization_id = 0xff; - bool has_command = _MsGetSaveCommand(current_summon, auto_ability_id); + bool has_command = FhXCall.h_MsGetSaveCommand.fnptr!(current_summon, auto_ability_id) != 0; if (!has_command) { uint item_count = Globals.save_data->get_item_count(customization.item); @@ -307,11 +275,11 @@ public void h_PrepareMenuList(MenuListEnum menu_list_id, Equipment* gear) { // Set length PrepareMenuList_SetLength(added, 0); } else { - _PrepareMenuList.orig_fptr(menu_list_id, gear); + FhXCall.h_PrepareMenuList.chain_from(h_PrepareMenuList).fnptr!(menu_list_id, gear); } - //if (menu_list_id == MenuListEnum.GEAR_CUSTOMIZATION) { + //if (menu_list_id == MenuList.GEAR_CUSTOMIZATION) { // CustomizationMenuList* menu_list = FhUtil.ptr_at(0x1197730); // int i = 0; // while (menu_list->status != CustomizationStatusEnum.NONE) { @@ -342,13 +310,13 @@ public void h_UpdateGearCustomizationMenuState(TkWindow* window) { while (!break_loop) { switch (*state) { case 2: - _FUN_008b4460(window); + FhXCall.h_FUN_008b4460.fnptr!(window); if (window->exit_value < 1) { return; } ushort weapon_index = *(ushort*)(p_DAT_0186a9f8 + window->selected_index * 2); - gear = _MsGetSaveWeapon(weapon_index, 0); + gear = FhXCall.h_MsGetSaveWeapon.fnptr!(weapon_index, 0); bool can_customize = false; if (gear->exists && !gear->is_hidden && gear->slot_count > 0) { if (!gear->is_celestial && !gear->is_brotherhood) { @@ -360,7 +328,7 @@ public void h_UpdateGearCustomizationMenuState(TkWindow* window) { if (!can_customize) { goto default; } else { - _SndSepPlaySimple(0x80000001); + FhXCall.h_SndSepPlaySimple.fnptr!(0x80000001); { int slot = 0; for (; slot < gear->slot_count; slot++) { @@ -383,7 +351,7 @@ public void h_UpdateGearCustomizationMenuState(TkWindow* window) { case 6: { TkWindow* _GearSelectionWindow = (TkWindow*)FhUtil.get_at(0x146A9F0); // DAT_0186a9f0 - gear = _MsGetSaveWeapon( + gear = FhXCall.h_MsGetSaveWeapon.fnptr!( *(ushort*)(p_DAT_0186a9f8 + _GearSelectionWindow->selected_index * 2), (nint)(&gear_name) ); @@ -414,7 +382,7 @@ public void h_UpdateGearCustomizationMenuState(TkWindow* window) { case 0xc: { TkWindow* DAT_023cc120 = (TkWindow*)FhUtil.get_at(0x1FCC120); if (DAT_023cc120->exit_value < 0) { - _FUN_008e2de0(); + FhXCall.h_FUN_008e2de0.fnptr!(); *state = 6; break_loop = true; break; @@ -425,9 +393,9 @@ public void h_UpdateGearCustomizationMenuState(TkWindow* window) { break; } - _FUN_008e2de0(); + FhXCall.h_FUN_008e2de0.fnptr!(); if (DAT_023cc120->selected_index != 0) { - _SndSepPlaySimple(0x80000001); + FhXCall.h_SndSepPlaySimple.fnptr!(0x80000001); *state = 6; break_loop = true; break; @@ -444,9 +412,9 @@ public void h_UpdateGearCustomizationMenuState(TkWindow* window) { short selected_ability = AbilitySelectionWindow->selected_index; int num_customizations; - CustomizationRecipe* customizations = _MsGetRomKaizou(&num_customizations); + CustomizationRecipe* customizations = FhXCall.h_MsGetRomKaizou.fnptr!(&num_customizations); byte customization_id = menu_list[selected_ability].customization_id; - gear = _MsGetSaveWeapon( + gear = FhXCall.h_MsGetSaveWeapon.fnptr!( *(ushort*)(p_DAT_0186a9f8 + GearSelectionWindow->selected_index * 2), (nint)(&gear_name) ); @@ -463,12 +431,12 @@ public void h_UpdateGearCustomizationMenuState(TkWindow* window) { gear->abilities[selected_gear_slot] = menu_list[selected_ability].a_ability_id; } - _MsSetSaveParamAll(); + FhXCall.h_MsSetSaveParamAll.fnptr!(); - _MsSetWeaponName(gear); - _MsSaveItemUse(customizations[customization_id].item, -customizations[customization_id].item_cost); - _SndSepPlaySimple(0x80000063); - _MsGetSaveWeapon((uint)*(ushort*)(p_DAT_0186a9f8 + GearSelectionWindow->selected_index * 2), (nint)(&gear_name)); + FhXCall.h_MsSetWeaponName.fnptr!(gear); + FhXCall.h_MsSaveItemUse.fnptr!(customizations[customization_id].item, -customizations[customization_id].item_cost); + FhXCall.h_SndSepPlaySimple.fnptr!(0x80000063); + FhXCall.h_MsGetSaveWeapon.fnptr!((uint)*(ushort*)(p_DAT_0186a9f8 + GearSelectionWindow->selected_index * 2), (nint)(&gear_name)); byte* p_DAT_0186aa70 = FhUtil.ptr_at(0x146AA70); i = -1; @@ -499,10 +467,10 @@ public void h_UpdateGearCustomizationMenuState(TkWindow* window) { uVar9 = 0x1f; } - byte* pbVar8 = _FUN_008bee80(uVar9); - _FUN_008c2c40(0, 0, p_DAT_0186aa30); - _FUN_008c2c40(2, 0, p_DAT_0186aa70); - _FUN_008e33a0(pbVar8, (byte*)0, (byte*)0); + byte* pbVar8 = FhXCall.h_FUN_008bee80.fnptr!(uVar9); + FhXCall.h_FUN_008c2c40.fnptr!(0, 0, p_DAT_0186aa30); + FhXCall.h_FUN_008c2c40.fnptr!(2, 0, p_DAT_0186aa70); + FhXCall.h_FUN_008e33a0.fnptr!(pbVar8, (byte*)0, (byte*)0); { TkWindow* DAT_023cc120 = (TkWindow*)FhUtil.get_at(0x1FCC120); ; @@ -532,7 +500,7 @@ public void h_UpdateGearCustomizationMenuState(TkWindow* window) { break; default: - _UpdateGearCustomizationMenuState.orig_fptr(window); + FhXCall.h_UpdateGearCustomizationMenuState.chain_from(h_UpdateGearCustomizationMenuState).fnptr!(window); break_loop = true; break; } @@ -549,7 +517,7 @@ public void h_UpdateGearCustomizationMenuState(TkWindow* window) { short selected_idx = DAT_0186a9f4->selected_index; CustomizationMenuList* menu_list = FhUtil.ptr_at(0x1197730); int num_customizations; - CustomizationRecipe* customizations = _MsGetRomKaizou(&num_customizations); + CustomizationRecipe* customizations = FhXCall.h_MsGetRomKaizou.fnptr!(&num_customizations); byte customization_id = menu_list[selected_idx].customization_id; if (customizations[customization_id].item_cost != original_kaizou_costs[customization_id]) { uint item_id = (uint)(0xC000 | customization_id); @@ -566,7 +534,7 @@ public void h_UpdateGearCustomizationMenuState(TkWindow* window) { // Reset kaizou.bin if (original_kaizou_costs != null) { int num_customizations; - CustomizationRecipe* customizations = _MsGetRomKaizou(&num_customizations); + CustomizationRecipe* customizations = FhXCall.h_MsGetRomKaizou.fnptr!(&num_customizations); for (int i = 0; i < num_customizations; i++) { customizations[i].item_cost = original_kaizou_costs[i]; } @@ -580,7 +548,7 @@ public void h_UpdateAeonCustomizationMenuState(uint param_1, uint param_2) { uint pre_state = *state; - _UpdateAeonCustomizationMenuState.orig_fptr(param_1, param_2); + FhXCall.h_UpdateAeonCustomizationMenuState.chain_from(h_UpdateAeonCustomizationMenuState).fnptr!(param_1, param_2); if (*state != pre_state) { _logger.Debug($"{pre_state} -> {*state}"); @@ -591,7 +559,7 @@ public void h_UpdateAeonCustomizationMenuState(uint param_1, uint param_2) { CustomizationMenuList* menu_list = FhUtil.ptr_at(0x1197730); byte customization_id = menu_list[selected_idx].customization_id; int num_customizations; - CustomizationRecipe* customizations = _MsGetRomSummonGrow(&num_customizations); + CustomizationRecipe* customizations = FhXCall.h_MsGetRomSummonGrow.fnptr!(&num_customizations); _logger.Debug($"Applied customization {get_other_item_name((uint)(0xC07D + customization_id))}"); if (customizations[customization_id].item_cost != original_sum_grow_costs[customization_id]) { uint item_id = (uint)(0xC07D + customization_id); @@ -610,20 +578,20 @@ public void h_UpdateAeonCustomizationMenuState(uint param_1, uint param_2) { public static ManagedCustomString customization_string = new("Free!"); public void h_DrawGearCustomizationMenu(TkWindow* window) { - //_DrawGearCustomizationMenu.orig_fptr(param_1); + //FhXCall.h_DrawGearCustomizationMenu.chain_from(h_DrawGearCustomizationMenu).fnptr!(param_1); DrawGearCustomizationMenu_reimplement(window); return; } public void h_DrawAeonCustomizationMenu(TkWindow* window) { - //_DrawAeonCustomizationMenu.orig_fptr(param_1); + //FhXCall.h_DrawAeonCustomizationMenu.chain_from(h_DrawAeonCustomizationMenu).fnptr!(param_1); DrawAeonCustomizationMenu_reimplement(window); } public void DrawAeonCustomizationMenu_reimplement(TkWindow* window) { - _TkVU1SyncPath(); - _FUN_008e71d0(7); - uint current_summon = _TkMenuGetCurrentSummon(); + FhXCall.h_TkVU1SyncPath.fnptr!(); + FhXCall.h_FUN_008e71d0.fnptr!(7); + uint current_summon = FhXCall.h_TkMenuGetCurrentSummon.fnptr!(); CustomizationMenuList* menu_list = FhUtil.ptr_at(0x1197730); @@ -637,7 +605,7 @@ public void DrawAeonCustomizationMenu_reimplement(TkWindow* window) { } else { byte customization_id = menu_list[selected_idx].customization_id; int num_customizations; - CustomizationRecipe* customizations = _MsGetRomSummonGrow(&num_customizations); + CustomizationRecipe* customizations = FhXCall.h_MsGetRomSummonGrow.fnptr!(&num_customizations); item_id = customizations[customization_id].item; int item_cost = customizations[customization_id].item_cost; @@ -646,35 +614,35 @@ public void DrawAeonCustomizationMenu_reimplement(TkWindow* window) { if (item_cost == 0) { fixed (byte* text = customization_string.encoded) { Vector2 pos = new Vector2(1260f, 381f).game_remap_1080p(); - _ToMakeBtlEasyFont(text, pos.X, pos.Y, 0, 2f); + FhXCall.h_ToMakeBtlEasyFont.fnptr!(text, pos.X, pos.Y, 0, 2f); } } else { pos_1 = new Vector2(970f, 380f).game_remap_1080p(); - _FUN_008c1c70((int)pos_1.X, (int)pos_1.Y, item_id, item_cost); + FhXCall.h_FUN_008c1c70.fnptr!((int)pos_1.X, (int)pos_1.Y, item_id, item_cost); } } pos_1 = new Vector2(210f, 226f).game_remap_1080p(); - _FUN_008ff490(current_summon, pos_1.X, pos_1.Y); + FhXCall.h_FUN_008ff490.fnptr!(current_summon, pos_1.X, pos_1.Y); pos_1 = new Vector2(210f, 312f).game_remap_1080p(); pos_2 = new Vector2(740f, 48f).game_remap_1080p(); - _TODrawMenuPlateXYWHType(pos_1.X, pos_1.Y, pos_2.X, pos_2.Y, 2); + FhXCall.h_TODrawMenuPlateXYWHType.fnptr!(pos_1.X, pos_1.Y, pos_2.X, pos_2.Y, 2); // Header text pos_1 = new Vector2(365f, 320f).game_remap_1080p(); pos_2 = new Vector2(430f, 36f).game_remap_1080p(); - _FUN_008f8bb0(0xf, pos_1.X, pos_1.Y, pos_2.X, pos_2.Y); + FhXCall.h_FUN_008f8bb0.fnptr!(0xf, pos_1.X, pos_1.Y, pos_2.X, pos_2.Y); if (-1 < (int)item_id) { pos_1 = new Vector2(970f, 312f).game_remap_1080p(); pos_2 = new Vector2(740f, 48f).game_remap_1080p(); - _TODrawMenuPlateXYWHType(pos_1.X, pos_1.Y, pos_2.X, pos_2.Y, 2); + FhXCall.h_TODrawMenuPlateXYWHType.fnptr!(pos_1.X, pos_1.Y, pos_2.X, pos_2.Y, 2); // Header text ("Item cost")? pos_1 = new Vector2(1125f, 318f).game_remap_1080p(); pos_2 = new Vector2(430f, 36f).game_remap_1080p(); - _FUN_008f8bb0(0x10, pos_1.X, pos_1.Y, pos_2.X, pos_2.Y); + FhXCall.h_FUN_008f8bb0.fnptr!(0x10, pos_1.X, pos_1.Y, pos_2.X, pos_2.Y); } int iVar2 = (int)new Vector2(0, 365f).game_remap_1080p() @@ -683,7 +651,7 @@ public void DrawAeonCustomizationMenu_reimplement(TkWindow* window) { float fVar10; if (window->visible_item_offset == window->scroll_offset) { // Draw ability list - _FUN_008c0f40( + FhXCall.h_FUN_008c0f40.fnptr!( iVar2, (int)(new Vector2(0, 70f).game_remap_1080p() .Y * 9.0), @@ -695,7 +663,7 @@ public void DrawAeonCustomizationMenu_reimplement(TkWindow* window) { iVar6 = 0; } else { // Draw ability list when quick scrolling (L2/R2) - _FUN_008c0f40( + FhXCall.h_FUN_008c0f40.fnptr!( iVar2, (int)(new Vector2(0, 70f).game_remap_1080p() .Y * 9.0), @@ -704,7 +672,7 @@ public void DrawAeonCustomizationMenu_reimplement(TkWindow* window) { ); FUN_008cd960_Extra(window, 1, window->visible_item_offset, 0.0f, 0.0f); - _FUN_008c0f40( + FhXCall.h_FUN_008c0f40.fnptr!( iVar2, (int)(new Vector2(0, 70f).game_remap_1080p() .Y * 9.0), @@ -719,14 +687,14 @@ public void DrawAeonCustomizationMenu_reimplement(TkWindow* window) { } FUN_008cd960_Extra(window, iVar6, sVar1, 0.0f, fVar10); - _FUN_008c1350_DrawScissor512x416(); + FhXCall.h_FUN_008c1350_DrawScissor512x416.fnptr!(); ushort _DAT_0186a5a4 = FhUtil.get_at(0x0146a5a4); ushort _DAT_0186a5a6 = FhUtil.get_at(0x0146a5a6); - _FUN_008cd9f0(window, _DAT_0186a5a4 + 0xc, _DAT_0186a5a6 + 1); + FhXCall.h_FUN_008cd9f0.fnptr!(window, _DAT_0186a5a4 + 0xc, _DAT_0186a5a6 + 1); float local_8; - _ToGetCrossExtMesFontWidth(0, _FUN_008bee80(5), &local_8, 0.78f, 1.0f); + FhXCall.h_ToGetCrossExtMesFontWidth.fnptr!(0, FhXCall.h_FUN_008bee80.fnptr!(5), &local_8, 0.78f, 1.0f); fVar10 = (float)(double)(new Vector2(80f, 0).game_remap_1080p() .X + local_8); @@ -750,9 +718,9 @@ public void DrawAeonCustomizationMenu_reimplement(TkWindow* window) { pos_1 = new Vector2(955f, 370f).game_remap_1080p(); pos_2 = new Vector2( 8f, 630f).game_remap_1080p(); - _DrawCrossMenuScrollParts(pos_1.X, pos_1.Y, pos_2.X, pos_2.Y, window->visible_item_offset, window->max_visible_items, window->num_items); + FhXCall.h_DrawCrossMenuScrollParts.fnptr!(pos_1.X, pos_1.Y, pos_2.X, pos_2.Y, window->visible_item_offset, window->max_visible_items, window->num_items); - _TODrawMenuPlateXYWHType( + FhXCall.h_TODrawMenuPlateXYWHType.fnptr!( fVar11, new Vector2(0, 925f).game_remap_1080p() .Y, @@ -768,18 +736,18 @@ public void DrawAeonCustomizationMenu_reimplement(TkWindow* window) { float uv_x1 = 0.9267578f; pos_1 = new Vector2(0f, 920f).game_remap_1080p(); pos_2 = new Vector2(64f, 64f).game_remap_1080p(); - _TOMkpShapeXYWHUV(0xf3, fVar12, pos_1.Y, pos_2.X, pos_2.Y, uv_x1, uv_y1, uv_x2, uv_y2); + FhXCall.h_TOMkpShapeXYWHUV.fnptr!(0xf3, fVar12, pos_1.Y, pos_2.X, pos_2.Y, uv_x1, uv_y1, uv_x2, uv_y2); pos_1 = new Vector2(80f, 928f).game_remap_1080p(); - _TOMkpCrossExtMesFontLClut(0, _FUN_008bee80(5), pos_1.X + fVar12, pos_1.Y, 0, 0.78f, 1.0f); + FhXCall.h_TOMkpCrossExtMesFontLClut.fnptr!(0, FhXCall.h_FUN_008bee80.fnptr!(5), pos_1.X + fVar12, pos_1.Y, 0, 0.78f, 1.0f); - item_id = _FUN_008d48e0(); - _FUN_008d4140(item_id, 1); - _TkMn2DrawKickSyncPacket(); + item_id = FhXCall.h_FUN_008d48e0.fnptr!(); + FhXCall.h_FUN_008d4140.fnptr!(item_id, 1); + FhXCall.h_TkMn2DrawKickSyncPacket.fnptr!(); } private void FUN_008cd960_Extra(TkWindow* window, int param_2, int menu_offset, float x, float y) { - _FUN_008cd960(window, param_2, menu_offset, x, y); + FhXCall.h_FUN_008cd960.fnptr!(window, param_2, menu_offset, x, y); Vector2 pos = new(x, y); pos += new Vector2(209f + 50f, 306f).game_remap_1080p(); @@ -796,13 +764,13 @@ private void FUN_008cd960_Extra(TkWindow* window, int param_2, int menu_offset, if (0 <= curr_index && curr_index < menu_length) { if (menu_list[curr_index].customization_id != 0xFF) { int num_customizations; - CustomizationRecipe* customizations = _MsGetRomSummonGrow(&num_customizations); + CustomizationRecipe* customizations = FhXCall.h_MsGetRomSummonGrow.fnptr!(&num_customizations); uint item_id = customizations[menu_list[curr_index].customization_id].item; int item_cost = customizations[menu_list[curr_index].customization_id].item_cost; if (item_cost == 0) { fixed (byte* text = customization_string.encoded) { - _ToMakeBtlEasyFont(text, pos.X, pos.Y, 0, 0.78f); + FhXCall.h_ToMakeBtlEasyFont.fnptr!(text, pos.X, pos.Y, 0, 0.78f); } } } @@ -819,7 +787,7 @@ public void DrawGearCustomizationMenu_reimplement(TkWindow* window) { Vector2 pos_2; if (menu_list[selected_idx].customization_id != 0xFF) { int num_customizations; - CustomizationRecipe* customizations = _MsGetRomKaizou(&num_customizations); + CustomizationRecipe* customizations = FhXCall.h_MsGetRomKaizou.fnptr!(&num_customizations); uint item_id = customizations[menu_list[selected_idx].customization_id].item; int item_cost = customizations[menu_list[selected_idx].customization_id].item_cost; @@ -828,38 +796,38 @@ public void DrawGearCustomizationMenu_reimplement(TkWindow* window) { if (item_cost == 0) { fixed (byte* text = customization_string.encoded) { Vector2 pos = new Vector2(1260f, 320f).game_remap_1080p(); - _ToMakeBtlEasyFont(text, pos.X, pos.Y, 0, 2f); + FhXCall.h_ToMakeBtlEasyFont.fnptr!(text, pos.X, pos.Y, 0, 2f); } } else { pos_1 = new Vector2(970f, 319f).game_remap_1080p(); - _FUN_008c1c70((int)pos_1.X, (int)pos_1.Y, item_id, item_cost); + FhXCall.h_FUN_008c1c70.fnptr!((int)pos_1.X, (int)pos_1.Y, item_id, item_cost); } // Header background pos_1 = new Vector2(970f, 252f).game_remap_1080p(); pos_2 = new Vector2(740f, 60f).game_remap_1080p(); - _TODrawMenuPlateXYWHType(pos_1.X, pos_1.Y, pos_2.X, pos_2.Y, 2); + FhXCall.h_TODrawMenuPlateXYWHType.fnptr!(pos_1.X, pos_1.Y, pos_2.X, pos_2.Y, 2); // Header ("Item cost") pos_1 = new Vector2(1125f, 264f).game_remap_1080p(); pos_2 = new Vector2(430f, 36f).game_remap_1080p(); - _FUN_008f8bb0(0x10, pos_1.X, pos_1.Y, pos_2.X, pos_2.Y); + FhXCall.h_FUN_008f8bb0.fnptr!(0x10, pos_1.X, pos_1.Y, pos_2.X, pos_2.Y); } //_TkMenuGetCurrentPlayer(); // Result is unused? // Abilities Header background pos_1 = new Vector2(211f, 252f).game_remap_1080p(); pos_2 = new Vector2(740f, 60f).game_remap_1080p(); - _TODrawMenuPlateXYWHType(pos_1.X, pos_1.Y, pos_2.X, pos_2.Y, 2); + FhXCall.h_TODrawMenuPlateXYWHType.fnptr!(pos_1.X, pos_1.Y, pos_2.X, pos_2.Y, 2); // Header ("Abilities") pos_1 = new Vector2(366f, 264f).game_remap_1080p(); pos_2 = new Vector2(430f, 36f).game_remap_1080p(); - _FUN_008f8bb0(7, pos_1.X, pos_1.Y, pos_2.X, pos_2.Y); + FhXCall.h_FUN_008f8bb0.fnptr!(7, pos_1.X, pos_1.Y, pos_2.X, pos_2.Y); if (window->visible_item_offset == window->scroll_offset) { // Draw ability list - _TODrawScissorXYWH( + FhXCall.h_TODrawScissorXYWH.fnptr!( 0, (int)(new Vector2(0, 315f).game_remap_1080p() .Y), @@ -872,7 +840,7 @@ public void DrawGearCustomizationMenu_reimplement(TkWindow* window) { // Draw ability list when quick scrolling (L2/R2) short uVar5 = window->scroll_delta; // Scroll offset - _FUN_008c0f40( + FhXCall.h_FUN_008c0f40.fnptr!( (int)(new Vector2(0, 315f).game_remap_1080p() .Y), (int)(new Vector2(0, 680f).game_remap_1080p() @@ -882,7 +850,7 @@ public void DrawGearCustomizationMenu_reimplement(TkWindow* window) { ); FUN_008d5d20_Extra(window, 1, window->visible_item_offset, 0, 0); - _FUN_008c0f40( + FhXCall.h_FUN_008c0f40.fnptr!( (int)(new Vector2(0, 315f).game_remap_1080p() .Y), (int)(new Vector2(0, 680f).game_remap_1080p() @@ -896,10 +864,10 @@ public void DrawGearCustomizationMenu_reimplement(TkWindow* window) { FUN_008d5d20_Extra(window, 2, window->scroll_offset, 0, iVar2); } - _FUN_008c1350_DrawScissor512x416(); + FhXCall.h_FUN_008c1350_DrawScissor512x416.fnptr!(); pos_1 = new Vector2(389f, 325f).game_remap_1080p(); - _FUN_008d5dc0(window, (int)pos_1.X, (int)pos_1.Y); + FhXCall.h_FUN_008d5dc0.fnptr!(window, (int)pos_1.X, (int)pos_1.Y); { int uVar5 = window->num_items; @@ -907,7 +875,7 @@ public void DrawGearCustomizationMenu_reimplement(TkWindow* window) { int iVar2 = window->visible_item_offset; pos_1 = new Vector2(955f, 319f).game_remap_1080p(); pos_2 = new Vector2(8f, 675f).game_remap_1080p(); - _DrawCrossMenuScrollParts(pos_1.X, pos_1.Y, pos_2.X, pos_2.Y, iVar2, uVar1, uVar5); + FhXCall.h_DrawCrossMenuScrollParts.fnptr!(pos_1.X, pos_1.Y, pos_2.X, pos_2.Y, iVar2, uVar1, uVar5); } { @@ -915,12 +883,12 @@ public void DrawGearCustomizationMenu_reimplement(TkWindow* window) { uint _DAT_0186a9f0 = FhUtil.get_at(0x146A9F0); int iVar2 = *(short*)(_DAT_0186a9f0 + 0x48); pos_1 = new Vector2(970f, 659f).game_remap_1080p(); - _FUN_008d6630((int)pos_1.X, (int)pos_1.Y, iVar2); + FhXCall.h_FUN_008d6630.fnptr!((int)pos_1.X, (int)pos_1.Y, iVar2); } } private void FUN_008d5d20_Extra(TkWindow* window, int param_2, int menu_offset, int x, int y) { - _FUN_008d5d20(window, param_2, menu_offset, x, y); + FhXCall.h_FUN_008d5d20.fnptr!(window, param_2, menu_offset, x, y); Vector2 pos = new(x, y); pos += new Vector2(209f + 50f, 255f).game_remap_1080p(); @@ -937,13 +905,13 @@ private void FUN_008d5d20_Extra(TkWindow* window, int param_2, int menu_offset, if (0 <= curr_index && curr_index < menu_length) { if (menu_list[curr_index].customization_id != 0xFF) { int num_customizations; - CustomizationRecipe* customizations = _MsGetRomKaizou(&num_customizations); + CustomizationRecipe* customizations = FhXCall.h_MsGetRomKaizou.fnptr!(&num_customizations); uint item_id = customizations[menu_list[curr_index].customization_id].item; int item_cost = customizations[menu_list[curr_index].customization_id].item_cost; if (item_cost == 0) { fixed (byte* text = customization_string.encoded) { - _ToMakeBtlEasyFont(text, pos.X, pos.Y, 0, 0.78f); + FhXCall.h_ToMakeBtlEasyFont.fnptr!(text, pos.X, pos.Y, 0, 0.78f); } } } @@ -956,7 +924,7 @@ private void FUN_008d5d20_Extra(TkWindow* window, int param_2, int menu_offset, public static TkWindow* MyWindow; public static void CreateMyWindow(Equipment* gear) { - MyWindow = _TkMenuMainAllocWindow(); + MyWindow = FhXCall.h_TkMenuMainAllocWindow.fnptr!(); MyWindow->num_items = gear->slot_count; MyWindow->max_visible_items = 4; MyWindow->selected_index = 0; @@ -964,7 +932,7 @@ public static void CreateMyWindow(Equipment* gear) { MyWindow->fn_init = &MyWindow_Init; MyWindow->fn_state = &MyWindow_State; MyWindow->fn_render = &MyWindow_Render; - _TkMenuMainRegistWindow(MyWindow); + FhXCall.h_TkMenuMainRegistWindow.fnptr!(MyWindow); } [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] @@ -984,16 +952,16 @@ public static void MyWindow_State(TkWindow* window) { case 1: if (Globals.Input.up.just_pressed && 0 < window->selected_index) { - _SndSepPlaySimple(0x80000001); + FhXCall.h_SndSepPlaySimple.fnptr!(0x80000001); window->selected_index--; } else if (Globals.Input.down.just_pressed && window->selected_index < window->num_items - 1) { - _SndSepPlaySimple(0x80000001); + FhXCall.h_SndSepPlaySimple.fnptr!(0x80000001); window->selected_index++; } else if (Globals.Input.confirm.just_pressed) { - _SndSepPlaySimple(0x80000001); + FhXCall.h_SndSepPlaySimple.fnptr!(0x80000001); window->current_state = 2; } else if (Globals.Input.cancel.just_pressed) { - _SndSepPlaySimple(0x80000004); + FhXCall.h_SndSepPlaySimple.fnptr!(0x80000004); window->current_state = 3; } @@ -1018,11 +986,11 @@ public static void MyWindow_State(TkWindow* window) { [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] public static void MyWindow_Render(TkWindow* window) { Vector2 pos = new Vector2(970 + 150, 735 + 12 + 68 * window->selected_index).game_remap_1080p(); - _TkMn2DrawCrossCursor(pos.X, pos.Y, 0); + FhXCall.h_TkMn2DrawCrossCursor.fnptr!(pos.X, pos.Y, 0); } public static bool h_FUN_008d5720(uint gear_id, int param_2) { - Equipment* gear = _MsGetSaveWeapon(gear_id, 0); + Equipment* gear = FhXCall.h_MsGetSaveWeapon.fnptr!(gear_id, 0); bool can_customize = false; if (gear->exists && !gear->is_hidden && gear->slot_count > 0) { diff --git a/src/delegates/capture_delegates.cs b/src/delegates/capture_delegates.cs deleted file mode 100644 index 5efa11c..0000000 --- a/src/delegates/capture_delegates.cs +++ /dev/null @@ -1,142 +0,0 @@ -using Fahrenheit.FFX; -using Fahrenheit.FFX.Battle; -using System.Runtime.InteropServices; - -using Fahrenheit; - -using static ArchipelagoFFX.delegates; - -namespace ArchipelagoFFX; - -public unsafe partial class CaptureModule { - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate bool MsMonsterCapture(int target_id, int arena_idx); - private const nint __addr_MsMonsterCapture = 0x390B80; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate void FUN_00783bb0(byte mon_idx); - private const int __addr_FUN_00783bb0 = 0x383BB0; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate Chr* MsGetMon(byte mon_idx); - private const int __addr_MsGetMon = 0x00395AB0; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate void AtelEventSetUp(int event_id); - private const nint __addr_AtelEventSetUp = 0x472E90; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate char* AtelGetEventName(uint event_id); - private const nint __addr_AtelGetEventName = 0x4796E0; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate int MsDamageCheckDeath(int attacker_id, int target_id, int param_3, uint param_4); - private const nint __addr_MsDamageCheckDeath = 0x38C800; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate Chr* MsGetChr(uint chr_id); - private const nint __addr_MsGetChr = 0x394030; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public unsafe delegate void MsSetSaveParam(uint chr_id); - public const nint __addr_MsSetSaveParam = 0x3861B0; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public unsafe delegate void MsSetRamChrParam(uint chr_id); - public const nint __addr_MsSetRamChrParam = 0x39C610; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public unsafe delegate void MsCalcCommand(AttackCue* param_1, int param_2); - public const nint __addr_MsCalcCommand = 0x3893A0; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public unsafe delegate Command* MsGetCommand(int chr_id, int unused, int quit_on_idx, AttackCommandInfo* param_4, uint* param_5); - public const nint __addr_MsGetCommand = 0x38CF10; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public unsafe delegate uint FUN_0078d100(Chr* chr); - public const nint __addr_FUN_0078d100 = 0x38D100; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public unsafe delegate uint FUN_0078bb30(int param_1, byte* param_2, byte* param_3, Command* param_4, uint param_5, uint* param_6, int* param_7); - public const nint __addr_FUN_0078bb30 = 0x38BB30; - - private const nint __addr_ret_hasKeyItem = 0x45B7A0; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int MsBattleEncountExe(int field_id, int group_idx, float walked_delta); - public const nint __addr_MsBattleEncountExe = 0x380de0; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int MsBtlListFieldNum(int field_id); - public const nint __addr_MsBtlListFieldNum = 0x39d1e0; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void ResetEncountExe(int p1); - public const nint __addr_ResetEncountExe = 0x3810c0; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int brnd(int rng_slot); - public const nint __addr_brnd = 0x398900; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate BtlBinField* MsBtlListField(int field_idx); - private const nint __addr_MsBtlListField = 0x39d1b0; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate BtlBinEncounter* MsBtlListEncount(int field_idx); - private const nint __addr_MsBtlListEncount = 0x39d190; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate BtlBinGroup* MsBtlListGroup(int field_idx, int group_idx); - private const nint __addr_MsBtlListGroup = 0x39d230; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void Sg_FadeInW(int p1); - public const nint __addr_Sg_FadeInW = 0x42cc20; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void* sceOpen(byte* p1, int p2); - public const nint __addr_sceOpen = 0x22fbe0; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int sceLseek(void* p1, int p2, int p3); - public const nint __addr_sceLseek = 0x22fa90; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int sceRead(void* p1, void* dst, int amount); - public const nint __addr_sceRead = 0x22fdb0; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int sceClose(void* p1); - public const nint __addr_sceClose = 0x22f7c0; - - // Method Handles - private readonly FhMethodHandle _MsMonsterCapture; - private readonly FhMethodHandle _FUN_00783bb0; - private readonly FhMethodHandle _AtelEventSetUp; - private readonly FhMethodHandle _ret_hasKeyItem; - private readonly FhMethodHandle _MsDamageCheckDeath; - private readonly FhMethodHandle _MsSetSaveParam; - private readonly FhMethodHandle _MsSetRamChrParam; - private readonly FhMethodHandle _MsCalcCommand; - private readonly FhMethodHandle _MsBattleEncountExe; - - private static char* get_event_name(uint event_id) => FhUtil.get_fptr(__addr_AtelGetEventName)(event_id); - private readonly MsGetMon _MsGetMon = FhUtil.get_fptr(__addr_MsGetMon); - private readonly MsGetChr _MsGetChr = FhUtil.get_fptr(__addr_MsGetChr); - private readonly MsGetCommand _MsGetCommand = FhUtil.get_fptr(__addr_MsGetCommand); - private readonly FUN_0078d100 _FUN_0078d100 = FhUtil.get_fptr(__addr_FUN_0078d100); - private readonly FUN_0078bb30 _FUN_0078bb30 = FhUtil.get_fptr(__addr_FUN_0078bb30); - private readonly MsBtlListFieldNum _MsBtlListFieldNum = FhUtil.get_fptr(__addr_MsBtlListFieldNum); - private readonly ResetEncountExe _ResetEncountExe = FhUtil.get_fptr(__addr_ResetEncountExe); - private readonly brnd _brnd = FhUtil.get_fptr(__addr_brnd); - private readonly MsBtlListField _MsBtlListField = FhUtil.get_fptr(__addr_MsBtlListField); - private readonly MsBtlListEncount _MsBtlListEncount = FhUtil.get_fptr(__addr_MsBtlListEncount); - private readonly MsBtlListGroup _MsBtlListGroup = FhUtil.get_fptr(__addr_MsBtlListGroup); - private readonly Sg_FadeInW _Sg_FadeInW = FhUtil.get_fptr(__addr_Sg_FadeInW); - private readonly sceOpen _sceOpen = FhUtil.get_fptr(__addr_sceOpen); - private readonly sceLseek _sceLseek = FhUtil.get_fptr(__addr_sceLseek); - private readonly sceRead _sceRead = FhUtil.get_fptr(__addr_sceRead); - private readonly sceClose _sceClose = FhUtil.get_fptr(__addr_sceClose); -} diff --git a/src/delegates/deathlink_delegates.cs b/src/delegates/deathlink_delegates.cs deleted file mode 100644 index d8c6164..0000000 --- a/src/delegates/deathlink_delegates.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System.Runtime.InteropServices; - -using Fahrenheit; -using Fahrenheit.FFX.Battle; - -using static ArchipelagoFFX.delegates; - -namespace ArchipelagoFFX; - -public unsafe partial class DeathLinkModule { - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void FUN_0079b480(int chr_id, int com_id, int is_disabled); - public const nint __addr_FUN_0079b480 = 0x39b480; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate Chr* MsGetChr(int chr_id); - public const nint __addr_MsGetChr = 0x394030; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate uint MsGetBattleEndStatus(); - public const nint __addr_MsGetBattleEndStatus = 0x3928f0; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void MsBtlReadManage(); - public const nint __addr_MsBtlReadManage = 0x3830d0; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int MsDamageCheckDeath(int attacker_id, int target_id, int p3, int targetting_self); - public const nint __addr_MsDamageCheckDeath = 0x38c800; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int MsMessageCueRegist(MessageCueType type, int arg1, int arg2, byte p4, byte p5); - public const nint __addr_MsMessageCueRegist = 0x39cff0; - - // Method Handles - private FhMethodHandle _MsGetBattleEndStatus; - private FhMethodHandle _MsBtlReadManage; - private FhMethodHandle _MsDamageCheckDeath; - - // Function library - private FUN_0079b480 _set_command_disabled = FhUtil.get_fptr(__addr_FUN_0079b480); - private MsGetChr _MsGetChr = FhUtil.get_fptr(__addr_MsGetChr); - private MsMessageCueRegist _MsMessageCueRegist = FhUtil.get_fptr(__addr_MsMessageCueRegist); -} diff --git a/src/delegates/delegates.cs b/src/delegates/delegates.cs deleted file mode 100644 index 0e7f09d..0000000 --- a/src/delegates/delegates.cs +++ /dev/null @@ -1,721 +0,0 @@ -using Fahrenheit.Atel; -using Fahrenheit.FFX; -using Fahrenheit.FFX.Battle; -using System.Numerics; -using System.Runtime.InteropServices; - -namespace ArchipelagoFFX; -public static unsafe class delegates { - - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void AtelInitTotal(); - public const nint __addr_AtelInitTotal = 0x0046d660; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void AtelSetUpCallFunc(int nameSpaceId, nint nameSpacePtr); - public const nint __addr_AtelSetUpCallFunc = 0x00477800; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int CT_Exec (AtelBasicWorker* work, AtelStack* atelStack); - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int CT_RetInt (AtelBasicWorker* work, int* storage, AtelStack* atelStack); - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate float CT_RetFloat(AtelBasicWorker* work, int* storage, AtelStack* atelStack); - - - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate char* AtelGetEventName(uint event_id); - - // AtelStackPop - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int AtelStackPop(int* param_1, AtelStack* atelStack); - - // Common.obtainTreasureInit - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void Common_obtainTreasureInit(AtelBasicWorker* work, int* storage, AtelStack* atelStack); - public const nint __addr_Common_obtainTreasureInit = 0x0045a740; - - // Common.obtainTreasureSilentlyInit - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void Common_obtainTreasureSilentlyInit(AtelBasicWorker* work, int* storage, AtelStack* atelStack); - public const nint __addr_Common_obtainTreasureSilentlyInit = 0x004579e0; - - // Common.obtainBrotherhood - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int Common_obtainBrotherhoodRetInt(AtelBasicWorker* work, int* storage, AtelStack* atelStack); - public const nint __addr_Common_obtainBrotherhoodRetInt = 0x00459a40; - - // Common.grantCelestialUpgrade - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //public delegate int Common_grantCelestialUpgrade(AtelBasicWorker* work, int* storage, AtelStack* atelStack); - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int TkSetLegendAbility(int chr_id, int level); - public const nint __addr_TkSetLegendAbility = 0x004c3150; - - // Common.setPrimerCollected - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int Common_setPrimerCollected(AtelBasicWorker* work, int* storage, AtelStack* atelStack); - public const nint __addr_Common_setPrimerCollected = 0x0045ab30; - - // Common.transitionToMap - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int Common_transitionToMap(AtelBasicWorker* work, int* storage, AtelStack* atelStack); - public const nint __addr_Common_transitionToMap = 0x004580c0; - - // Common.warpToMap - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int Common_warpToMap(AtelBasicWorker* work, int* storage, AtelStack* atelStack); - public const nint __addr_Common_warpToMap = 0x00458370; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void SgEvent_showModularMenuInit(AtelBasicWorker* work, int* storage, AtelStack* atelStack); - public const nint __addr_SgEvent_showModularMenuInit = 0x00678210; - - - // Common.playFieldVoiceLineInit - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int Common_playFieldVoiceLineInit(AtelBasicWorker* work, int* storage, AtelStack* atelStack); - public const nint __addr_Common_playFieldVoiceLineInit = 0x0045cb70; - // Common.playFieldVoiceLineExec - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int Common_playFieldVoiceLineExec(AtelBasicWorker* param_1, AtelStack* param_2); - public const nint __addr_Common_playFieldVoiceLineExec = 0x0045cd30; - // Common.playFieldVoiceLineResultInt - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int Common_playFieldVoiceLineResultInt(AtelBasicWorker* work, int* storage, AtelStack* atelStack); - public const nint __addr_Common_playFieldVoiceLineResultInt = 0x0045d150; - - - // Common.00D6Init - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int Common_00D6Init(AtelBasicWorker* work, int* storage, AtelStack* atelStack); - public const nint __addr_Common_00D6Init = 0x0045d520; - // Common.00D6eExec - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int Common_00D6Exec(AtelBasicWorker* param_1, AtelStack* param_2); - public const nint __addr_Common_00D6Exec = 0x0045d820; - // Common.00D6ResultInt - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int Common_00D6ResultInt(AtelBasicWorker* work, int* storage, AtelStack* atelStack); - public const nint __addr_Common_00D6ResultInt = 0x0045dcf0; - - // Map.show2DLayer - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int Map_show2DLayerResultInt(AtelBasicWorker* work, int* storage, AtelStack* atelStack); - public const nint __addr_Map_show2DLayerResultInt = 0x0051b1a0; - - // Map.hide2DLayer - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int Map_hide2DLayerResultInt(AtelBasicWorker* work, int* storage, AtelStack* atelStack); - public const nint __addr_Map_hide2DLayerResultInt = 0x0051b1e0; - - // Common.01D1Init - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int Common_01D1Init(AtelBasicWorker* work, int* storage, AtelStack* atelStack); - public const nint __addr_Common_01D1Init = 0x0045fb60; - // Common.01D1Exec - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate bool Common_01D1Exec(AtelBasicWorker* param_1, AtelStack* param_2); - public const nint __addr_Common_01D1Exec = 0x0045fdb0; - - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int Common_addPartyMember(AtelBasicWorker* work, int* storage, AtelStack* atelStack); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int Common_removePartyMember(AtelBasicWorker* work, int* storage, AtelStack* atelStack); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int Common_removePartyMemberLongTerm(AtelBasicWorker* work, int* storage, AtelStack* atelStack); - // Common.setWeaponVisibilty (Common.0240) - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int Common_setWeaponInvisible(AtelBasicWorker* work, int* storage, AtelStack* atelStack); - - // Common.putPartyMemberInSlot - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int Common_putPartyMemberInSlot(AtelBasicWorker* work, int* storage, AtelStack* atelStack); - - - // Common.pushParty - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int Common_pushParty(AtelBasicWorker* work, int* storage, AtelStack* atelStack); - - // Common.popParty - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int Common_popParty(AtelBasicWorker* work, int* storage, AtelStack* atelStack); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int MsBattleLabelExe(uint encounter_id, byte param_2, byte screen_transition); - public const nint __addr_MsBattleLabelExe = 0x00381d60; - - // EndOfBattle? - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - public delegate void FUN_00791820(); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int MsBtlGetPos(int param_1, Chr* chr, int btl_pos_a, int btl_pos_b, int btl_pos_c, Vector4* out_pos); - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - public delegate byte MsBtlReadSetScene(); - - - // giveItem - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate uint FUN_007905a0(uint param_1, int param_2); - - - // readFromBin - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate byte* FUN_007ab890(int param_1, short* param_2, int param_3); - - // getWeaponName - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate ushort FUN_007a0d10(Equipment* param_1); - // getWeaponModel - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void FUN_007a0c70(ushort name_id, byte owner, int unknown, ushort* model_id_pointer); - // giveWeapon - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int FUN_007ab930(Equipment* param_1); - // obtainTreasureCleanup - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void FUN_007993f0(BtlRewardData* param_1, int param_2); - - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void FUN_00a48910(uint chr_id, int node_idx); - - - - [UnmanagedFunctionPointer(CallingConvention.ThisCall)] - public delegate bool openFile(nint _this, nint filename, bool readOnly, nint unknown_1, nint unknown_2, nint unknown_3); - - [UnmanagedFunctionPointer(CallingConvention.ThisCall)] - public delegate uint readFile(nint _this, nint buffer, uint max_len); - - [UnmanagedFunctionPointer(CallingConvention.ThisCall)] - public delegate uint FUN_0070aec0(nint _this, uint voice_id, uint param_2); - - - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int Common_loadModel(AtelBasicWorker* work, int* storage, AtelStack* atelStack); - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int Common_linkFieldToBattleActor(AtelBasicWorker* work, int* storage, AtelStack* atelStack); - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int Common_0043(AtelBasicWorker* work, int* storage, AtelStack* atelStack); - - - - - - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int Map_800F(AtelBasicWorker* work, int* storage, AtelStack* atelStack); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate byte* FUN_0086bec0(int param_1); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate short FUN_0086bea0(int param_1); - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - public delegate void FUN_00656c90(int param_1, int param_2, char* fileName); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate bool graphicInitFMVPlayer(int movie_id, int param_2); - public const nint __addr_graphicInitFMVPlayer = 0x00241840; - - - [UnmanagedFunctionPointer(CallingConvention.ThisCall)] - public delegate int PhyreScene_loadVFXTexture(nint phyreScene, int param_1, byte* param_2, char param_3); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void PhyreScene_onVFXTextureLoaded(nint param_1, int* param_2); - - public struct returnedTexData { - public short unknown1; - public short type; - public nint dataName; - public short offset; - public short size; - public nint unknown2; - } - [UnmanagedFunctionPointer(CallingConvention.ThisCall)] - public delegate returnedTexData* FUN_0056cd50(nint _this, nint dataName); - - public struct FixedClusterData { - public nint _0x00; // Texture data offsets? - public nint _0x04; // Texture data? - public nint _0x08; - public nint _0x0c; - public nint _0x10; - public nint _0x14; - public nint _0x18; - public nint _0x1c; - } - - [UnmanagedFunctionPointer(CallingConvention.ThisCall)] - public delegate void FUN_0065ee30(FixedClusterData* param_1); - public const nint __addr_ClusterManager_FUN_0065ee30 = 0x0025ee30; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int Phyre_PFramework_PApplication_FixupClusters(PCluster* cluster, int param_1); - public const nint __addr_Phyre_PFramework_PApplication_FixupClusters = 0x00223740; - - [UnmanagedFunctionPointer(CallingConvention.ThisCall)] - public delegate PCluster* ClusterManager_loadPCluster(nint _this, nint filePath); - public const nint __addr_ClusterManager_loadPCluster = 0x0029ba80; - - [UnmanagedFunctionPointer(CallingConvention.ThisCall)] - public delegate void ClusterManager_releasePCluster(nint _this, PCluster* cluster); - public const nint __addr_ClusterManager_releasePCluster = 0x0029bef0; - - [UnmanagedFunctionPointer(CallingConvention.ThisCall)] - public delegate PCluster* ClusterManager_getPClusterByName(nint _this, nint filePath); - public const nint __addr_ClusterManager_getPClusterByName = 0x0029b5f0; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void fiosUnifyFilename(nint in_string, nint out_buffer, int buffer_size); - public const nint __addr_fiosUnifyFilename = 0x002799d0; - - - [StructLayout(LayoutKind.Explicit, Pack = 1, Size = 0x20)] - public struct PCluster { - } - - - - - - - - - - [StructLayout(LayoutKind.Explicit, Pack = 1, Size = 0x2c)] - public struct TOMesWinWork { - [FieldOffset(0x08)] public byte* text; - [FieldOffset(0x0c)] public byte* _0xc; - [FieldOffset(0x14)] public short status; - - [FieldOffset(0x16)] public short _0x16; - - [FieldOffset(0x18)] public int _0x18; - [FieldOffset(0x1d)] public byte _0x1d; - [FieldOffset(0x20)] public byte _0x20; - - } - - // obbtainTreasure related - public delegate void FUN_008b8910(int window_idx, int variable_idx, int type); // setMessageWindowVariableType (0: text*, 1: int) - public const nint __addr_FUN_008b8910 = 0x004b8910; - - public delegate byte* FUN_008bda20(uint window_idx); // getMenuText - public const nint __addr_FUN_008bda20 = 0x004bda20; - - public delegate void FUN_008b8930(int window_idx, int variable_idx, int value); // setMessageWindowVariable - public const nint __addr_FUN_008b8930 = 0x004b8930; - - public delegate void FUN_0086a0c0(); - public const nint __addr_FUN_0086a0c0 = 0x0046a0c0; - - public delegate TOMesWinWork* AtelGetMesWinWork(int idx); - public const nint __addr_AtelGetMesWinWork = 0x0046be20; - - - // Voice related - [UnmanagedFunctionPointer(CallingConvention.ThisCall)] - public unsafe delegate int FmodVoice_dataChange(nint FmodVoice, int event_id, nint param_2); - public const nint __addr_FmodVoice_dataChange = 0x0030a720; - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - public unsafe delegate nint FMOD_EventSystem_load(nint param_1, nint file_path, nint param_3, nint bank); - public const nint __addr_FMOD_EventSystem_load = 0x70C75C; - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - public unsafe delegate nint FMOD_Bank_Post_Load(nint param_1, nint param_2, nint param_3, nint param_4); - - - [UnmanagedFunctionPointer(CallingConvention.ThisCall)] - public unsafe delegate void FfxFmod_soundInit_setLang(nint ffxFmod, int lang); - public const nint __addr_FfxFmod_soundInit_setLang = 0x0030b4e0; - - - [StructLayout(LayoutKind.Explicit, Pack = 4, Size = 0x1C)] - public struct FFXLocalizationManager { - [FieldOffset(0x00)] public int video; // Also voice? - [FieldOffset(0x04)] public int text; // Probably - [FieldOffset(0x08)] public int voice; // Unused? - } - - [UnmanagedFunctionPointer(CallingConvention.ThisCall)] - public unsafe delegate void LocalizationManager_Initialize(FFXLocalizationManager* localizationManager); - public const nint __addr_LocalizationManager_Initialize = 0x002db1c0; - - public unsafe delegate FFXLocalizationManager* LocalizationManager_GetInstance(); - public const nint __addr_LocalizationManager_GetInstance = 0x002db1a0; - - - [UnmanagedFunctionPointer(CallingConvention.ThisCall)] - public unsafe delegate void FfxFmod_soundInit(nint ffxFmod); - public const nint __addr_FfxFmod_soundInit = 0x00307170; - - [UnmanagedFunctionPointer(CallingConvention.ThisCall)] - public unsafe delegate void FmodVoice_initList(nint fmodVoice); - public const nint __addr_FmodVoice_initList = 0x0030ac80; - - // Set soundtrack type (0 = arranged, 1 = original) - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public unsafe delegate void FUN_008cc120(int param_1); - public const nint __addr_FUN_008cc120 = 0x004cc120; - - - - - // Temporary - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public unsafe delegate void AtelEventSetUp(int event_id); - public const nint __addr_AtelEventSetUp = 0x472E90; - - // getCurrentPartySlots - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void MsGetSavePartyMember(uint* param_1, uint* param_2, uint* param_3); - public const nint __addr_MsGetSavePartyMember = 0x3853B0; - - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int CT_RetInt_01B6(nint work, int* storage, nint atelStack); - public static int __addr_CT_RetInt_01B6 = 0x004594d0; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int Common_upgradeBrotherhoodRetInt(nint work, int* storage, nint atelStack); - public static int __addr_CT_RetInt_01B7 = 0x004596a0; - - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - public delegate void eiAbmParaGet(); - public static int __addr_eiAbmParaGet = 0x00654860; - - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate uint MsApUp(int chr_id, Chr* chr, int base_ap_add, uint param_4); - public const nint __addr_MsApUp = 0x00398A10; - - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void TkMsImportantSet(uint param_1); - public const nint __addr_TkMsImportantSet = 0x0048e700; - - - public delegate void MsFieldItemGet(int treasure_id); - public const nint __addr_MsFieldItemGet = 0x00398fe0; - - public delegate void CT_RetInt_0065(nint work, int* storage, nint atelStack); - public const nint __addr_CT_RetInt_0065 = 0x00457f60; - - public delegate void CT_RetInt_006A(nint work, int* storage, nint atelStack); - public const nint __addr_CT_RetInt_006A = 0x004589f0; - - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public unsafe delegate nint AtelGetCurCtrlWork(); - public const nint __addr_AtelGetCurCtrlWork = 0x46AF80; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public unsafe delegate int MsPayGIL(int change); - public const nint __addr_MsPayGIL = 0x385A60; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public unsafe delegate void SndSepPlaySimple(uint param_1); - public const nint __addr_SndSepPlaySimple = 0x486DE0; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public unsafe delegate Equipment* MsGetSaveWeapon(uint gear_inv_idx, nint ref_name); - public const nint __addr_MsGetSaveWeapon = 0x3ABBF0; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public unsafe delegate void MsSetSaveParam(uint chr_id); - public const nint __addr_MsSetSaveParam = 0x3861B0; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public unsafe delegate void MsSetRamChrParam(uint chr_id); - public const nint __addr_MsSetRamChrParam = 0x39c610; - - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public unsafe delegate void MsBattleExe(uint param_1, int field_idx, int group_idx, int formation_idx); - public const nint __addr_MsBattleExe = 0x3810F0; - - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public unsafe delegate void TkMsGetRomItem(uint param_1, int* param_2); - public const nint __addr_TkMsGetRomItem = 0x4AB230; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public unsafe delegate void MsSaveItemUse(uint item_id, int amount); - public const nint __addr_MsSaveItemUse = 0x3905A0; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public unsafe delegate byte* MsImportantName(uint key_item_idx); - public const nint __addr_MsImportantName = 0x3908B0; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public unsafe delegate nint MsBtlListGroup(int field_idx, int group_idx); - public const nint __addr_MsBtlListGroup = 0x39D230; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public unsafe delegate nint MsGetExcelData(int req_elem_idx, nint excel_data_ptr, int* ref_data_end); - public const nint __addr_MsGetExcelData = 0x3AB890; - - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public unsafe delegate void TkMenuAppearMainCmdWindow(int param_1, int param_2); - public static int __addr_TkMenuAppearMainCmdWindow = 0x004e1c60; - - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int UpgradeBrotherhood(int level); - public static int __addr_UpgradeBrotherhood = 0x004596a0; - - // Initializes monster data pointers - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate Chr* MsGetChr(uint chr_id); - public const nint __addr_MsGetChr = 0x394030; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int FUN_00867370(byte opcode, AtelBasicWorker* work, AtelWorkThread* thread, AtelStack* stack, uint param_5); - public static int __addr_FUN_00867370 = 0x00467370; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void FUN_008671d0(byte opcode, AtelWorkThread* thread, AtelBasicWorker* work, AtelStack* stack); - public static int __addr_FUN_008671d0 = 0x004671d0; - - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void TOMkpCrossExtMesFontLClutTypeRGBA( - uint p1, - byte* text, - float x, - float y, - byte color, - byte p6, - byte tint_r, byte tint_g, byte tint_b, byte tint_a, - float scale, - float _); - public static int __addr_TOMkpCrossExtMesFontLClutTypeRGBA = 0x501700; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void ToMakeBtlEasyFont(byte* text, float x, float y, byte alpha, float scale); - public static int __addr_ToMakeBtlEasyFont = 0x505AB0; - - // Customization-related - public enum MenuListEnum : uint { - OVERDRIVES = 0, - OVERDRIVE_MODES = 1, - AEON_ABILITIES = 3, - GEAR_CUSTOMIZATION = 5, - EQUIPMENT = 21 - } - public enum CustomizationStatusEnum : byte { - NONE = 0x0, - AEON_AVAILABLE = 0x4, - AEON_ALREADY_LEARNED = 0x5, - AEON_CANNOT_LEARN_WITHOUT_KEY = 0x6, - AEON_NOT_ENOUGH_ITEMS = 0x7, - - GEAR_AVAILABLE = 0xb, - GEAR_ALREADY_APPLIED = 0xc, - GEAR_NOT_ENOUGH_ITEMS = 0xe, - GEAR_CONFLICTING = 0xf, // (same group but lower level) or (same group, same level, different international bonus) or (international bonus is 0xfe AND gear has any ability with 0xff international bonus) - GEAR_NO_SLOTS = 0x10, - //NONE = 0x11 - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct CustomizationMenuList { - public ushort a_ability_id; - public CustomizationStatusEnum status; - public byte customization_id; - } - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void PrepareMenuList(MenuListEnum menu_list_id, Equipment* gear); - public static int __addr_PrepareMenuList = 0x004c2370; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void UpdateGearCustomizationMenuState(TkWindow* window); - public static int __addr_UpdateGearCustomizationMenuState = 0x004d5800; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void UpdateAeonCustomizationMenuState(uint param_1, uint param_2); - public static int __addr_UpdateAeonCustomizationMenuState = 0x004cc300; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate CustomizationRecipe* MsGetRomKaizou(int *size); - public static int __addr_MsGetRomKaizou = 0x390A60; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate AutoAbility* MsGetRomAbility(uint a_ability_id, int* ref_data_end); - public static int __addr_MsGetRomAbility = 0x3909C0; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate CustomizationRecipe* MsGetRomSummonGrow(int* size); - public static int __addr_MsGetRomSummonGrow = 0x390B00; - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - public delegate int TkMn2GetSummonGrowMax(); - public static int __addr_TkMn2GetSummonGrowMax = 0x4C1C20; - - - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate byte TkMenuGetCurrentSummon(); - public static int __addr_TkMenuGetCurrentSummon = 0x4A9830; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate bool MsGetSaveCommand(int char_id, uint com_id); - public static int __addr_MsGetSaveCommand = 0x3850E0; - - - - - - // Draw customization menu - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void DrawGearCustomizationMenu(TkWindow* window); - public static int __addr_DrawGearCustomizationMenu = 0x004d5f30; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void DrawAeonCustomizationMenu(TkWindow* window); - public static int __addr_DrawAeonCustomizationMenu = 0x004cdb70; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void FUN_008c1c70(int param_1, int param_2, uint param_3, int param_4); - public static int __addr_FUN_008c1c70 = 0x004c1c70; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void TODrawMenuPlateXYWHType(float x, float y, float w, float h, int type); - public static int __addr_TODrawMenuPlateXYWHType = 0x004f5f70; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void FUN_008f8bb0(int param_1, float param_2, float param_3, float param_4, float param_5); - public static int __addr_FUN_008f8bb0 = 0x004f8bb0; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void TODrawScissorXYWH(int x, int y, int w, int h); - public static int __addr_TODrawScissorXYWH = 0x004f9230; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void FUN_008d5d20(TkWindow* window, int param_2, int param_3, int param_4, int param_5); - public static int __addr_FUN_008d5d20 = 0x004d5d20; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void FUN_008c0f40(int param_1, int param_2, int param_3, int param_4); - public static int __addr_FUN_008c0f40 = 0x004c0f40; - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - public delegate void FUN_008c1350_DrawScissor512x416(); - public static int __addr_FUN_008c1350_DrawScissor512x416 = 0x004c1350; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void FUN_008d5dc0(TkWindow* window, int param_2, int param_3); - public static int __addr_FUN_008d5dc0 = 0x004d5dc0; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void DrawCrossMenuScrollParts(float param_1, float param_2, float param_3, float param_4, int param_5, int param_6, int param_7); - public static int __addr_DrawCrossMenuScrollParts = 0x004e6cc0; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void FUN_008d6630(int param_1, int param_2, int param_3); - public static int __addr_FUN_008d6630 = 0x004d6630; - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - public delegate void TkVU1SyncPath(); - public static int __addr_TkVU1SyncPath = 0x0048ebd0; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void FUN_008e71d0(int param_1); - public static int __addr_FUN_008e71d0 = 0x004e71d0; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void FUN_008ff490(uint param_1, float param_2, float param_3); - public static int __addr_FUN_008ff490 = 0x004ff490; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void FUN_008cd960(TkWindow* window, int param_2, int param_3, float param_4, float param_5); - public static int __addr_FUN_008cd960 = 0x004cd960; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void FUN_008cd9f0(TkWindow* window, int param_2, int param_3); - public static int __addr_FUN_008cd9f0 = 0x004cd9f0; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void ToGetCrossExtMesFontWidth(int param_1, byte* param_2, float* param_3, float param_4, float param_5); - public static int __addr_ToGetCrossExtMesFontWidth = 0x00505320; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate byte* FUN_008bee80(uint param_1); - public static int __addr_FUN_008bee80 = 0x004bee80; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void TOMkpShapeXYWHUV(int param_1, float x, float y, float w, float h, float uv_x1, float uv_y1, float uv_x2, float uv_y2); - public static int __addr_TOMkpShapeXYWHUV = 0x00503bb0; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void TOMkpCrossExtMesFontLClut(int param_1, byte* text, float x, float y, byte color, float scale, float p7_unused); - public static int __addr_TOMkpCrossExtMesFontLClut = 0x005016b0; - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - public delegate uint FUN_008d48e0(); - public static int __addr_FUN_008d48e0 = 0x004d48e0; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void FUN_008d4140(uint param_1, int param_2); - public static int __addr_FUN_008d4140 = 0x004d4140; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void TkMn2DrawKickSyncPacket(); - public static int __addr_TkMn2DrawKickSyncPacket = 0x004c0c90; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int FUN_008e33a0(byte* text, byte* param_2, byte* param_3); - public static int __addr_FUN_008e33a0 = 0x004e33a0; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate TkWindow* TkMenuMainAllocWindow(); - public static int __addr_TkMenuMainAllocWindow = 0x004aa150; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate TkWindow* TkMenuMainRegistWindow(TkWindow* window); - public static int __addr_TkMenuMainRegistWindow = 0x004aaab0; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void FUN_008b4460(TkWindow* window); - public static int __addr_FUN_008b4460 = 0x004b4460; - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - public delegate void FUN_008e2de0(); - public static int __addr_FUN_008e2de0 = 0x004e2de0; - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - public delegate void MsSetSaveParamAll(); - public static int __addr_MsSetSaveParamAll = 0x003869c0; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void MsSetWeaponName(Equipment* gear); - public static int __addr_MsSetWeaponName = 0x003993c0; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void FUN_008c2c40(int param_1, int param_2, byte* param_3); - public static int __addr_FUN_008c2c40 = 0x004c2c40; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void TkMn2DrawCrossCursor(float x, float y, int param_3); - public static int __addr_TkMn2DrawCrossCursor = 0x004c0640; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate bool FUN_008d5720(uint gear_id, int param_2); - public static int __addr_FUN_008d5720 = 0x004d5720; -} diff --git a/src/delegates/overdrive_delegates.cs b/src/delegates/overdrive_delegates.cs deleted file mode 100644 index 1221a8c..0000000 --- a/src/delegates/overdrive_delegates.cs +++ /dev/null @@ -1,233 +0,0 @@ -namespace ArchipelagoFFX; - -public unsafe partial class OverdriveModule { - //TODO: Remove these once FhCall is more up-to-date - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate int MsGetSaveCommand(int char_id, uint com_id); - //private const int __addr_MsGetSaveCommand = 0x3850E0; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate void MsSetRamChrAbility(int chr_id, Chr* chr); - //private const nint __addr_MsSetRamChrAbility = 0x39BB70; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate int MsLimitTidusLearn(int chr_id); - //private const nint __addr_MsLimitTidusLearn = 0x3B0CE0; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate uint MsAfterDamageProcess(int attacker_id, uint param_2, int target_id, uint* param_4, uint param_5); - //private const nint __addr_MsAfterDamageProcess = 0x38F0B0; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate Chr* MsGetChr(int chr_id); - //private const nint __addr_MsGetChr = 0x394030; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate void MsMenuCloseTitleWindow(int param_1); - //private const nint __addr_MsMenuCloseTitleWindow = 0x38FA80; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate int MsMessageCueRegist(uint type, int param_2, int param_3, byte param_4, byte param_5); - //private const nint __addr_MsMessageCueRegist = 0x39CFF0; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate void MsSetStealEffect(int param_1, int param_2); - //private const nint __addr_MsSetStealEffect = 0x39ED20; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate uint MsRegSEplay2(int param_1, uint param_2); - //private const nint __addr_MsRegSEplay2 = 0x3A0160; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate int MsPayGIL(int param_1); - //private const nint __addr_MsPayGIL = 0x385A60; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate void MsSetStealGillEffect(int param_1, int param_2); - //private const nint __addr_MsSetStealGillEffect = 0x39ED40; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate int MsCheckRange(int param_1, int param_2, int param_3); - //private const nint __addr_MsCheckRange = 0x39A0D0; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate int MsSetSaveCommand(int chr_id, uint param_2, int param_3); - //private const nint __addr_MsSetSaveCommand = 0x385D10; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate void achievementUnlockAchievement(int ach_id); - //private const nint __addr_achievementUnlockAchievement = 0x422410; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate int MsNumberRegist(int param_1, int param_2, int param_3, int param_4, int param_5, uint param_6, uint param_7); - //private const nint __addr_MsNumberRegist = 0x39FA20; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate int MsLimitTypeDamageCheck(int attacker_id, Chr* attacker, int target_id, Chr* target, int param_5, int param_6, int param_7); - //private const nint __addr_MsLimitTypeDamageCheck = 0x3B0D60; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate void MsSubHP(int chr_id, Chr* chr, int param_3, int param_4, int param_5, uint param_6, uint param_7); - //private const nint __addr_MsSubHP = 0x38E2F0; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate void MsSubMP(int chr_id, Chr* chr, int param_3, int param_4, int param_5, uint param_6, uint param_7); - //private const nint __addr_MsSubMP = 0x38E400; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate void MsSubCTB(int chr_id, Chr* chr, int param_3, int param_4, uint param_5, uint param_6); - //private const nint __addr_MsSubCTB = 0x38E2A0; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate int MsLimitTypeStatusCheck(int attacker_id, Chr* attacker, int target_id, Chr* target, int param_5, uint param_6); - //private const nint __addr_MsLimitTypeStatusCheck = 0x3B12D0; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate int MsLimitStatusProcess(int chr_id, Chr* chr, uint param_3); - //private const nint __addr_MsLimitStatusProcess = 0x38D330; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate int MsAliveProcess(int chr_id, Chr* chr); - //private const nint __addr_MsAliveProcess = 0x389220; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate int MsStoneProcess(int chr_id, Chr* chr); - //private const nint __addr_MsStoneProcess = 0x38E210; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate int MsBlowProcess(int chr_id, Chr* chr); - //private const nint __addr_MsBlowProcess = 0x389270; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate int MsThreatProcess(int chr_id, Chr* chr); - //private const nint __addr_MsThreatProcess = 0x38E4B0; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate int MsAutoCureProcess(int target_id, Chr* target, int attacker_id, int poison, int zombie, int darkness, int silence); - //private const nint __addr_MsAutoCureProcess = 0x3B2520; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate int MsAutoPotionProcess(int target_id, Chr* target, int attacker_id); - //private const nint __addr_MsAutoPotionProcess = 0x3B2860; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate int MsSetChrWeak(int chr_id, int new_weak_level); - //private const nint __addr_MsSetChrWeak = 0x38D8B0; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate bool MsAutoRelifeProcess(int attacker_id, Chr* attacker, int target_id, Chr* target); - //private const nint __addr_MsAutoRelifeProcess = 0x38D990; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate void MsStatusEffectCheck(int chr_id); - //private const nint __addr_MsStatusEffectCheck = 0x39F010; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate int MsStatusDefenseEffect(int attacker_id, int target_id, int dmg_calc_flags); - //private const nint __addr_MsStatusDefenseEffect = 0x39EE40; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate int MsActionRequest(int target_id, int attacker_id, int param_3, int param_4, int param_5, void* param_6); - //private const nint __addr_MsActionRequest = 0x3ACEC0; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate void MsPopBtlPos(Chr* chr); - //private const nint __addr_MsPopBtlPos = 0x3AC620; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate int MsDamageCheckDeath(int attacker_id, int target_id, int param_3, int targeting_self); - //private const nint __addr_MsDamageCheckDeath = 0x38C800; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate void MsDamageSetMotion(int chr_id, int param_2, int targeting_self); - //private const nint __addr_MsDamageSetMotion = 0x38CAE0; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate int brnd(int rng_idx); - //private const nint __addr_brnd = 0x398900; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate void MsSetSaveCommandWithPrefix(int chr_id, int com_id, int param_3); - //private const nint __addr_MsSetSaveCommandWithPrefix = 0x474190; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate int TOBtlDrawLearningMessageWindow(int chr_id, int com_id); - //private const nint __addr_TOBtlDrawLearningMessageWindow = 0x495290; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate void TOBtlSetMacroCommandType(int param_1, int param_2, byte param_3); - //private const nint __addr_TOBtlSetMacroCommandType = 0x4B5770; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate void TOBtlSetMacroCommandValue(int param_1, int param_2, byte* param_3); - //private const nint __addr_TOBtlSetMacroCommandValue = 0x4B57A0; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate byte* TOGetSaveChrName(int chr_id); - //private const nint __addr_TOGetSaveChrName = 0x4AC800; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate Command* MsGetComData(int com_id, byte** param_2); - //private const nint __addr_MsGetComData = 0x39A4C0; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate byte* MsGetRomBtlText(int param_1, int param_2); - //private const nint __addr_MsGetRomBtlText = 0x38F940; - - //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] - //private delegate int FUN_0089db10(int param_1, byte* param_2); - //private const nint __addr_FUN_0089db10 = 0x49DB10; - - //private const nint __addr_ret_doesChrKnowCommand = 0x3A30C0; - - // Method Handles - //private readonly FhMethodHandle _MsGetSaveCommand; - //private readonly FhMethodHandle _MsSetRamChrAbility; - //private readonly FhMethodHandle _MsLimitTidusLearn; - //private readonly FhMethodHandle _MsAfterDamageProcess; - //private readonly FhMethodHandle _ret_doesChrKnowCommand; - //private readonly FhMethodHandle _MsSetSaveCommandWithPrefix; - //private readonly FhMethodHandle _TOBtlDrawLearningMessageWindow; - - //private readonly MsGetChr _MsGetChr = FhUtil.get_fptr(__addr_MsGetChr); - //private readonly MsMenuCloseTitleWindow _MsMenuCloseTitleWindow = FhUtil.get_fptr(__addr_MsMenuCloseTitleWindow); - //private readonly MsMessageCueRegist _MsMessageCueRegist = FhUtil.get_fptr(__addr_MsMessageCueRegist); - //private readonly MsSetStealEffect _MsSetStealEffect = FhUtil.get_fptr(__addr_MsSetStealEffect); - //private readonly MsRegSEplay2 _MsRegSEplay2 = FhUtil.get_fptr(__addr_MsRegSEplay2); - //private readonly MsPayGIL _MsPayGIL = FhUtil.get_fptr(__addr_MsPayGIL); - //private readonly MsSetStealGillEffect _MsSetStealGillEffect = FhUtil.get_fptr(__addr_MsSetStealGillEffect); - //private readonly MsCheckRange _MsCheckRange = FhUtil.get_fptr(__addr_MsCheckRange); - //private readonly MsSetSaveCommand _MsSetSaveCommand = FhUtil.get_fptr(__addr_MsSetSaveCommand); - //private readonly achievementUnlockAchievement _achievementUnlockAchievement = FhUtil.get_fptr(__addr_achievementUnlockAchievement); - //private readonly MsNumberRegist _MsNumberRegist = FhUtil.get_fptr(__addr_MsNumberRegist); - //private readonly MsLimitTypeDamageCheck _MsLimitTypeDamageCheck = FhUtil.get_fptr(__addr_MsLimitTypeDamageCheck); - //private readonly MsSubHP _MsSubHP = FhUtil.get_fptr(__addr_MsSubHP); - //private readonly MsSubMP _MsSubMP = FhUtil.get_fptr(__addr_MsSubMP); - //private readonly MsSubCTB _MsSubCTB = FhUtil.get_fptr(__addr_MsSubCTB); - //private readonly MsLimitTypeStatusCheck _MsLimitTypeStatusCheck = FhUtil.get_fptr(__addr_MsLimitTypeStatusCheck); - //private readonly MsLimitStatusProcess _MsLimitStatusProcess = FhUtil.get_fptr(__addr_MsLimitStatusProcess); - //private readonly MsAliveProcess _MsAliveProcess = FhUtil.get_fptr(__addr_MsAliveProcess); - //private readonly MsStoneProcess _MsStoneProcess = FhUtil.get_fptr(__addr_MsStoneProcess); - //private readonly MsBlowProcess _MsBlowProcess = FhUtil.get_fptr(__addr_MsBlowProcess); - //private readonly MsThreatProcess _MsThreatProcess = FhUtil.get_fptr(__addr_MsThreatProcess); - //private readonly MsAutoCureProcess _MsAutoCureProcess = FhUtil.get_fptr(__addr_MsAutoCureProcess); - //private readonly MsAutoPotionProcess _MsAutoPotionProcess = FhUtil.get_fptr(__addr_MsAutoPotionProcess); - //private readonly MsSetChrWeak _MsSetChrWeak = FhUtil.get_fptr(__addr_MsSetChrWeak); - //private readonly MsAutoRelifeProcess _MsAutoRelifeProcess = FhUtil.get_fptr(__addr_MsAutoRelifeProcess); - //private readonly MsStatusEffectCheck _MsStatusEffectCheck = FhUtil.get_fptr(__addr_MsStatusEffectCheck); - //private readonly MsStatusDefenseEffect _MsStatusDefenseEffect = FhUtil.get_fptr(__addr_MsStatusDefenseEffect); - //private readonly MsActionRequest _MsActionRequest = FhUtil.get_fptr(__addr_MsActionRequest); - //private readonly MsPopBtlPos _MsPopBtlPos = FhUtil.get_fptr(__addr_MsPopBtlPos); - //private readonly MsDamageCheckDeath _MsDamageCheckDeath = FhUtil.get_fptr(__addr_MsDamageCheckDeath); - //private readonly MsDamageSetMotion _MsDamageSetMotion = FhUtil.get_fptr(__addr_MsDamageSetMotion); - //private readonly brnd _brnd = FhUtil.get_fptr(__addr_brnd); - //private readonly TOBtlSetMacroCommandType _TOBtlSetMacroCommandType = FhUtil.get_fptr(__addr_TOBtlSetMacroCommandType); - //private readonly TOBtlSetMacroCommandValue _TOBtlSetMacroCommandValue = FhUtil.get_fptr(__addr_TOBtlSetMacroCommandValue); - //private readonly TOGetSaveChrName _TOGetSaveChrName = FhUtil.get_fptr(__addr_TOGetSaveChrName); - //private readonly MsGetComData _MsGetComData = FhUtil.get_fptr(__addr_MsGetComData); - //private readonly MsGetRomBtlText _MsGetRomBtlText = FhUtil.get_fptr(__addr_MsGetRomBtlText); - //private readonly FUN_0089db10 _FUN_0089db10 = FhUtil.get_fptr(__addr_FUN_0089db10); - - //private readonly MsGetSaveCommand _fn_MsGetSaveCommand = FhUtil.get_fptr(__addr_MsGetSaveCommand); - //private readonly TOBtlDrawLearningMessageWindow _fn_TOBtlDrawLearningMessageWindow = FhUtil.get_fptr(__addr_TOBtlDrawLearningMessageWindow); -} diff --git a/src/gui/debugWindow.cs b/src/gui/debugWindow.cs index aba2f93..0bc584a 100644 --- a/src/gui/debugWindow.cs +++ b/src/gui/debugWindow.cs @@ -1,7 +1,8 @@ -using Archipelago.MultiClient.Net.Enums; +using Archipelago.MultiClient.Net.Enums; +using ArchipelagoFFX.Client; +using Fahrenheit; using Fahrenheit.FFX; using Fahrenheit.FFX.Battle; - using Hexa.NET.ImGui; using System; using System.Collections.Generic; @@ -9,16 +10,11 @@ using System.Linq; using System.Numerics; using System.Runtime.InteropServices; - -using ArchipelagoFFX.Client; - -using Fahrenheit; - -using static Fahrenheit.FFX.Globals; using static ArchipelagoFFX.ArchipelagoData; using static ArchipelagoFFX.ArchipelagoFFXModule; -using static ArchipelagoFFX.delegates; +using static Fahrenheit.FFX.Globals; using Color = Archipelago.MultiClient.Net.Models.Color; +using FhXCall = Fahrenheit.FFX.FhCall; namespace ArchipelagoFFX.GUI; @@ -171,8 +167,7 @@ private void render_experiments() { } if (ImGui.Checkbox("Original soundtrack?", &save_data->soundtrack_type)) { - var soundtrack_callback = FhUtil.get_fptr(__addr_FUN_008cc120); - soundtrack_callback(save_data->soundtrack_type ? 1 : 0); + FhXCall.h_FUN_008cc120.fnptr!(save_data->soundtrack_type ? 1 : 0); } ImGui.InputScalarN("frontline? (0x1FC5)", ImGuiDataType.U8, Battle.btl->__0x1FC5, 7); @@ -366,7 +361,7 @@ private void render_experiments() { // localizationManager->voice = voice_language; // // nint _FmodManager = FhUtil.get_at(0x008E9000); - // //_FfxFmod_soundInit(*(nint*)(_FmodManager+8)); + // //FhXCall.h_FfxFmod_soundInit.fnptr!(*(nint*)(_FmodManager+8)); // // nint ffxFmod = *(nint*)(_FmodManager + 8); // @@ -374,7 +369,7 @@ private void render_experiments() { // // *(byte*)(fmodVoice + 4) = (byte)voice_language; // - // _FmodVoice_initList(fmodVoice); + // FhXCall.h_FmodVoice_initList.fnptr!(fmodVoice); // // int dataChange_result = h_FmodVoice_dataChange(fmodVoice, Globals.save_data->current_room_id, *(nint*)(ffxFmod + 4)); // if (dataChange_result != 0) { @@ -456,7 +451,7 @@ private void render_sphere_grid_editor() { for (int i = 0; i < 7; i++) { if (ImGui.Button($"{id_to_character[i]}: {(clickedNode->activated_by & (1 << i)) != 0}")) { clickedNode->activated_by ^= (byte)(1 << i); - FhUtil.get_fptr(Fahrenheit.FFX.FhCall.__addr_eiAbmParaGet)(); + FhXCall.h_eiAbmParaGet.fnptr!(); SphereGrid.lpamng->should_update = 1; // Setting to clickedNodeIndex only turns off light if no character has it activated. Setting to -1 correctly turns on/off node itself, but not surrounding lights (per character). SphereGrid.lpamng->should_update_node = -1; @@ -800,7 +795,7 @@ private void render_debug_tab() { ImGui.InputScalar("launchBattleInput", ImGuiDataType.U32, battle_input, &p_step, &p_step_fast, "%x"); } if (ImGui.Button("launchBattleButton")) { - _MsBattleLabelExe(LaunchBattleInput, 1, 1); + FhXCall.h_MsBattleLabelExe.fnptr!(LaunchBattleInput, 1, 1); } #endif } diff --git a/src/hooks.cs b/src/hooks.cs index b692ad8..47db251 100644 --- a/src/hooks.cs +++ b/src/hooks.cs @@ -1,26 +1,20 @@ -using Fahrenheit.Atel; +using ArchipelagoFFX.Client; +using Fahrenheit; +using Fahrenheit.Atel; using Fahrenheit.FFX; using Fahrenheit.FFX.Battle; using Fahrenheit.FFX.Ids; - using System; using System.Collections.Generic; using System.Linq; using System.Numerics; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; - -using ArchipelagoFFX.Client; -using ArchipelagoFFX.GUI; - -using Fahrenheit; - -using static Fahrenheit.FFX.Globals; using static ArchipelagoFFX.ArchipelagoData; -using static ArchipelagoFFX.delegates; +using static Fahrenheit.FFX.Globals; using Color = Archipelago.MultiClient.Net.Models.Color; -using FhCall = Fahrenheit.FFX.FhCall; +using FhGCall = Fahrenheit.FhCall; +using FhXCall = Fahrenheit.FFX.FhCall; namespace ArchipelagoFFX; @@ -29,431 +23,15 @@ public unsafe partial class ArchipelagoFFXModule { public static int* takara_pointer => FhUtil.ptr_at(0xD35FEC); public static int* buki_get_pointer => FhUtil.ptr_at(0xD35FF4); + public static char* get_event_name(uint event_id) => FhXCall.h_AtelGetEventName.fnptr!(event_id); + public static int atel_stack_pop(int* param_1, AtelStack* atelStack) => FhXCall.h_AtelStackPop.fnptr!(param_1, atelStack); - // AtelEventSetUp - private static FhMethodHandle _AtelEventSetUp; - - public static char* get_event_name(uint event_id) => FhUtil.get_fptr(0x4796e0)(event_id); - public static int atel_stack_pop(int* param_1, AtelStack* atelStack) => FhUtil.get_fptr(0x0046de90)(param_1, atelStack); - - private static FhMethodHandle _Common_obtainTreasureInit; - private static FhMethodHandle _Common_obtainTreasureSilentlyInit; - private static FhMethodHandle _Common_isBrotherhoodUnpoweredRetInt; - private static FhMethodHandle _Common_upgradeBrotherhoodRetInt; - private static FhMethodHandle _Common_obtainBrotherhoodRetInt; - //private static FhMethodHandle _Common_grantCelestialUpgrade; - private static FhMethodHandle _Common_setPrimerCollected; - private static FhMethodHandle _Common_transitionToMap; - private static FhMethodHandle _Common_warpToMap; - - private static FhMethodHandle _TkSetLegendAbility; - - private static FhMethodHandle _SgEvent_showModularMenuInit; - - //private static FhMethodHandle _Common_playFieldVoiceLineInit; - //private static FhMethodHandle _Common_playFieldVoiceLineExec; - //private static FhMethodHandle _Common_playFieldVoiceLineResultInt; - - - - private static Common_playFieldVoiceLineInit _Common_playFieldVoiceLineInit; - private static Common_playFieldVoiceLineExec _Common_playFieldVoiceLineExec; - private static Common_playFieldVoiceLineResultInt _Common_playFieldVoiceLineResultInt; - - private static Common_00D6Init _Common_00D6Init; - private static Common_00D6Exec _Common_00D6Exec; - private static Common_00D6ResultInt _Common_00D6ResultInt; - - - // Common.01D1Init - private static Common_01D1Init _Common_01D1Init; - // Common.01D1Exec - private static Common_01D1Exec _Common_01D1Exec; - - private static FhMethodHandle _Common_addPartyMember; - private static FhMethodHandle _Common_removePartyMember; - private static FhMethodHandle _Common_removePartyMemberLongTerm; - private static FhMethodHandle _Common_setWeaponVisibilty; - private static FhMethodHandle _Common_putPartyMemberInSlot; - - private static FhMethodHandle _Common_pushParty; - private static FhMethodHandle _Common_popParty; - - // getCurrentPartySlots - private static FhMethodHandle _MsGetSavePartyMember; - - // Battle releated - private static MsBtlListGroup _MsBtlListGroup; - private static FhMethodHandle _MsBattleExe; - - - public static MsBattleLabelExe _MsBattleLabelExe; - private static FhMethodHandle _FUN_00791820; - - private static FhMethodHandle _MsBtlGetPos; - - private static FhMethodHandle _MsBtlReadSetScene; - - // giveItem - private static FhMethodHandle _FUN_007905a0; - // giveKeyItem - // takeGil - - - // readFromBin - private static FhMethodHandle _FUN_007ab890; - - // getWeaponName - private static FhMethodHandle _FUN_007a0d10; - // getWeaponModel - private static FhMethodHandle _FUN_007a0c70; - // obtainTreasureCleanup - private static FhMethodHandle _FUN_007993f0; - - private static MsGetChr _MsGetChr; - private static FhCall.MsGetComData _MsGetComData; - private static FhCall.MsGetCommandUse _MsGetCommandUse; - private static FhCall.MsGetCommandMP _MsGetCommandMP; - private static FhCall.MsGetRamChrMonster _MsGetRamChrMonster; - private static FhCall.TODrawCrossBoxXYWHC2 _TODrawCrossBoxXYWHC2; - - - private static FhMethodHandle _TkMenuAppearMainCmdWindow; - - // Sphere Grid Experiment - private static FhMethodHandle _eiAbmParaGet; - private static FhMethodHandle _MsSetSaveParam; - private static FhMethodHandle _MsSetRamChrParam; - private static FhMethodHandle _FUN_00a48910; - - private static FhMethodHandle _MsApUp; - - - private static FhMethodHandle _openFile; - private static readFile _readFile; - private static FhMethodHandle _FUN_0070aec0; - - private static FhCall.ChN_ReadSystemMGRP _ChN_ReadSystemMGRP; - private static Common_loadModel _Common_loadModel; - private static Common_0043 _Common_0043; - private static Common_linkFieldToBattleActor _Common_linkFieldToBattleActor; - private static FhCall.SndSepPlay _SndSepPlay; - - - public static MsGetExcelData _MsGetExcelData; - - private static FhMethodHandle _Map_800F; - - private static FhMethodHandle _FUN_0086bec0; - private static FhMethodHandle _FUN_0086bea0; - - private static FhMethodHandle _graphicInitFMVPlayer; - - private static FhMethodHandle _FUN_00656c90; - private static FUN_0065ee30 _FUN_0065ee30; - private static ClusterManager_loadPCluster _ClusterManager_loadPCluster; - private static Phyre_PFramework_PApplication_FixupClusters _Phyre_PFramework_PApplication_FixupClusters; - private static ClusterManager_releasePCluster _ClusterManager_releasePCluster; - private static ClusterManager_getPClusterByName _ClusterManager_getPClusterByName; - private static fiosUnifyFilename _fiosUnifyFilename; - - - // ObtainTreasure related - private static FhMethodHandle _TkMsImportantSet; - private static MsPayGIL _MsPayGIL; - private static SndSepPlaySimple _SndSepPlaySimple; - private static MsGetSaveWeapon _MsGetSaveWeapon; - private static FUN_007ab930 _FUN_007ab930; // giveWeapon? - private static AtelGetCurCtrlWork _AtelGetCurCtrlWork; - private static MsFieldItemGet _MsFieldItemGet; - private static TkMsGetRomItem _TkMsGetRomItem; - private static MsSaveItemUse _MsSaveItemUse; - private static MsImportantName _MsImportantName; - private static CT_RetInt_0065 _CT_RetInt_0065; - private static CT_RetInt_006A _CT_RetInt_006A; - private static FhCall.MsBtlGetInit _MsBtlGetInit; - private static AtelGetMesWinWork _AtelGetMesWinWork; - private static FUN_008b8910 _FUN_008b8910; // setMessageWindowVariableType? (0: text*, 1: int) - private static FUN_008bda20 _FUN_008bda20; // getMenuText - private static FUN_008b8930 _FUN_008b8930; // setMessageWindowVariable - private static FUN_0086a0c0 _FUN_0086a0c0; - - - // Voice related - private static FhMethodHandle _FmodVoice_dataChange; - private static FMOD_EventSystem_load _FMOD_EventSystem_load; - - private static FhMethodHandle _FfxFmod_soundInit_setLang; - private static FhMethodHandle _LocalizationManager_Initialize; - public static LocalizationManager_GetInstance _LocalizationManager_GetInstance; - public static FfxFmod_soundInit _FfxFmod_soundInit; - public static FmodVoice_initList _FmodVoice_initList; - - - // Custom namespace - private static FhMethodHandle _AtelInitTotal; - public static void AtelSetUpCallFunc(int id, nint nameSpacePtr) => FhUtil.get_fptr(__addr_AtelSetUpCallFunc)(id, nameSpacePtr); - - // Airship menu related - public static FUN_00867370 _FUN_00867370; - public static FUN_008671d0 _FUN_008671d0; - public static Map_show2DLayerResultInt _Map_show2DLayerResultInt; - public static Map_hide2DLayerResultInt _Map_hide2DLayerResultInt; - - // Drawing - public static TOMkpCrossExtMesFontLClutTypeRGBA _TOMkpCrossExtMesFontLClutTypeRGBA; - public static ToMakeBtlEasyFont _ToMakeBtlEasyFont; + public static void AtelSetUpCallFunc(int id, nint nameSpacePtr) => FhXCall.h_AtelSetUpCallFunc.fnptr!(id, nameSpacePtr); public void init_hooks() { - const string game = "FFX.exe"; - - _AtelEventSetUp = new FhMethodHandle(this, game, __addr_AtelEventSetUp, h_AtelEventSetUp); - - _Common_obtainTreasureInit = new FhMethodHandle(this, game, __addr_Common_obtainTreasureInit, h_Common_obtainTreasureInit); - - _Common_obtainTreasureSilentlyInit = new FhMethodHandle(this, game, __addr_Common_obtainTreasureSilentlyInit, h_Common_obtainTreasureSilentlyInit); - - _Common_isBrotherhoodUnpoweredRetInt = new FhMethodHandle(this, game, __addr_CT_RetInt_01B6, h_Common_isBrotherhoodUnpoweredRetInt); - _Common_upgradeBrotherhoodRetInt = new FhMethodHandle(this, game, __addr_CT_RetInt_01B7, h_Common_upgradeBrotherhoodRetInt); - _Common_obtainBrotherhoodRetInt = new FhMethodHandle(this, game, __addr_Common_obtainBrotherhoodRetInt, h_Common_obtainBrotherhoodRetInt); - - _TkSetLegendAbility = new FhMethodHandle(this, game, __addr_TkSetLegendAbility, h_TkSetLegendAbility); - - _Common_setPrimerCollected = new FhMethodHandle(this, game, __addr_Common_setPrimerCollected, h_Common_setPrimerCollected); - - _Common_transitionToMap = new FhMethodHandle(this, game, __addr_Common_transitionToMap, h_Common_transitionToMap); - _Common_warpToMap = new FhMethodHandle(this, game, __addr_Common_warpToMap, h_Common_warpToMap); - - _SgEvent_showModularMenuInit = new FhMethodHandle(this, game, __addr_SgEvent_showModularMenuInit, h_SgEvent_showModularMenuInit); - - - //_Common_playFieldVoiceLineInit = new FhMethodHandle(this, game, h_Common_playFieldVoiceLineInit, offset: 0x0045cb70); - //_Common_playFieldVoiceLineExec = new FhMethodHandle(this, game, h_Common_playFieldVoiceLineExec, offset: 0x0045cd30); - //_Common_playFieldVoiceLineResultInt = new FhMethodHandle(this, game, h_Common_playFieldVoiceLineResultInt, offset: 0x0045d150); - - _Common_playFieldVoiceLineInit = FhUtil.get_fptr (__addr_Common_playFieldVoiceLineInit ); - _Common_playFieldVoiceLineExec = FhUtil.get_fptr (__addr_Common_playFieldVoiceLineExec ); - _Common_playFieldVoiceLineResultInt = FhUtil.get_fptr(__addr_Common_playFieldVoiceLineResultInt); - - _Common_00D6Init = FhUtil.get_fptr (__addr_Common_00D6Init ); - _Common_00D6Exec = FhUtil.get_fptr (__addr_Common_00D6Exec ); - _Common_00D6ResultInt = FhUtil.get_fptr(__addr_Common_00D6ResultInt); - - - - // Common.01D1Init - //_FUN_0085fb60 = new FhMethodHandle(this, game, h_after_voiceline_init, offset: 0x0045fb60); - // Common.01D1Exec - //_FUN_0085fdb0 = new FhMethodHandle(this, game, h_after_voiceline_exec, offset: 0x0045fdb0); - - // Common.01D1Init - _Common_01D1Init = FhUtil.get_fptr(__addr_Common_01D1Init); - // Common.01D1Exec - _Common_01D1Exec = FhUtil.get_fptr(__addr_Common_01D1Exec); - - - - - _Common_addPartyMember = new FhMethodHandle(this, game, 0x0045b5a0, h_Common_addPartyMember); - _Common_removePartyMember = new FhMethodHandle(this, game, 0x0045b6c0, h_Common_removePartyMember); - _Common_removePartyMemberLongTerm = new FhMethodHandle(this, game, 0x0045aaf0, h_Common_removePartyMemberLongTerm); - _Common_setWeaponVisibilty = new FhMethodHandle(this, game, 0x00456770, h_Common_setWeaponInvisible); - _Common_putPartyMemberInSlot = new FhMethodHandle(this, game, 0x0045bc90, h_Common_putPartyMemberInSlot); - - - _Common_pushParty = new FhMethodHandle(this, game, 0x0045b350, h_Common_pushParty); - _Common_popParty = new FhMethodHandle(this, game, 0x0045b3c0, h_Common_popParty); - - // getCurrentPartySlots - _MsGetSavePartyMember = new FhMethodHandle(this, game, __addr_MsGetSavePartyMember, h_MsGetSavePartyMember); - - - _MsBtlListGroup = FhUtil.get_fptr(__addr_MsBtlListGroup); - _MsBattleExe = new FhMethodHandle(this, game, __addr_MsBattleExe, h_MsBattleExe); - _MsBattleLabelExe = FhUtil.get_fptr(__addr_MsBattleLabelExe); - _FUN_00791820 = new FhMethodHandle(this, game, 0x00391820, h_FUN_00791820); - - _MsBtlGetPos = new FhMethodHandle(this, game, 0x003ac000, h_MsBtlGetPos); - - _MsBtlReadSetScene = new FhMethodHandle(this, game, 0x00383ed0, h_MsBtlReadSetScene); - - // giveItem - _FUN_007905a0 = new FhMethodHandle(this, game, 0x003905a0, h_give_item); - - - - // readFromBin - _FUN_007ab890 = new FhMethodHandle(this, game, 0x003ab890, h_read_from_bin); - - // getWeaponName - _FUN_007a0d10 = new FhMethodHandle(this, game, 0x003a0d10, h_get_weapon_name); - // getWeaponModel - _FUN_007a0c70 = new FhMethodHandle(this, game, 0x003a0c70, h_get_weapon_model); - // obtainTreasureCleanup - _FUN_007993f0 = new FhMethodHandle(this, game, 0x003993f0, h_obtain_treasure_cleanup); - - - _MsGetChr = FhUtil.get_fptr(__addr_MsGetChr); - _MsGetComData = FhUtil.get_fptr(FhCall.__addr_MsGetComData); - _MsGetCommandUse = FhUtil.get_fptr(FhCall.__addr_MsGetCommandUse); - _MsGetCommandMP = FhUtil.get_fptr(FhCall.__addr_MsGetCommandMP); - _MsGetRamChrMonster = FhUtil.get_fptr(FhCall.__addr_MsGetRamChrMonster); - _TODrawCrossBoxXYWHC2 = FhUtil.get_fptr(FhCall.__addr_TODrawCrossBoxXYWHC2); - - _eiAbmParaGet = new FhMethodHandle(this, game, __addr_eiAbmParaGet, h_eiAbmParaGet); - _MsSetSaveParam = new FhMethodHandle(this, game, __addr_MsSetSaveParam, h_MsSetSaveParam); - _MsSetRamChrParam = new FhMethodHandle(this, game, __addr_MsSetRamChrParam, h_MsSetRamChrParam); - _FUN_00a48910 = new FhMethodHandle(this, game, 0x00648910, h_FUN_00a48910); - - _MsApUp = new FhMethodHandle(this, game, 0x00398a10, h_MsApUp); - - //delegate* unmanaged[Thiscall] ph_openFile = &h_openFile; - //openFile p_openFile = (x, y, z) => d_openFile(ph_openFile, x, y, z); - //openFile temp = Marshal.GetDelegateForFunctionPointer((nint)ph_openFile); - _openFile = new FhMethodHandle(this, game, 0x00208100, h_openFile); - _readFile = FhUtil.get_fptr(0x00208250); - - _FUN_0070aec0 = new FhMethodHandle(this, game, 0x0030aec0, h_FUN_0070aec0); - - - _ChN_ReadSystemMGRP = FhUtil.get_fptr(FhCall.__addr_ChN_ReadSystemMGRP); - - _Common_loadModel = FhUtil.get_fptr(0x0045ce70); - _Common_0043 = FhUtil.get_fptr(0x0045c810); - _Common_linkFieldToBattleActor = FhUtil.get_fptr(0x0045ca00); - - _SndSepPlay = FhUtil.get_fptr(FhCall.__addr_SndSepPlay); - - - _Map_800F = new FhMethodHandle(this, game, 0x0051b1a0, h_Map_800F); - - - _MsGetExcelData = FhUtil.get_fptr(__addr_MsGetExcelData); - - - // obtainTreasure related - _TkMsImportantSet = new FhMethodHandle(this, game, __addr_TkMsImportantSet, h_TkMsImportantSet); - _MsPayGIL = FhUtil.get_fptr(__addr_MsPayGIL); // takeGil - _SndSepPlaySimple = FhUtil.get_fptr(__addr_SndSepPlaySimple); - _MsGetSaveWeapon = FhUtil.get_fptr(__addr_MsGetSaveWeapon); - _FUN_007ab930 = FhUtil.get_fptr(0x003ab930); // giveWeapon - _AtelGetCurCtrlWork = FhUtil.get_fptr(__addr_AtelGetCurCtrlWork); - _MsFieldItemGet = FhUtil.get_fptr(__addr_MsFieldItemGet); - _TkMsGetRomItem = FhUtil.get_fptr(__addr_TkMsGetRomItem); - _MsSaveItemUse = FhUtil.get_fptr(__addr_MsSaveItemUse); - _MsImportantName = FhUtil.get_fptr(__addr_MsImportantName); - _CT_RetInt_0065 = FhUtil.get_fptr(__addr_CT_RetInt_0065); - _CT_RetInt_006A = FhUtil.get_fptr(__addr_CT_RetInt_006A); - _MsBtlGetInit = FhUtil.get_fptr(FhCall.__addr_MsBtlGetInit); - _AtelGetMesWinWork = FhUtil.get_fptr(__addr_AtelGetMesWinWork); - _FUN_008b8910 = FhUtil.get_fptr(__addr_FUN_008b8910); - _FUN_008bda20 = FhUtil.get_fptr(__addr_FUN_008bda20); - _FUN_008b8930 = FhUtil.get_fptr(__addr_FUN_008b8930); - _FUN_0086a0c0 = FhUtil.get_fptr(__addr_FUN_0086a0c0); - - - _FUN_0086bec0 = new FhMethodHandle(this, game, 0x0046bec0, h_FUN_0086bec0); - _FUN_0086bea0 = new FhMethodHandle(this, game, 0x0046bea0, h_FUN_0086bea0); - - - _FUN_00656c90 = new FhMethodHandle(this, game, 0x00256c90, h_FUN_00656c90); - - _TkMenuAppearMainCmdWindow = new FhMethodHandle(this, game, __addr_TkMenuAppearMainCmdWindow, h_TkMenuAppearMainCmdWindow); - - // For loading texture from game - _FUN_0065ee30 = FhUtil.get_fptr(__addr_ClusterManager_FUN_0065ee30); - _ClusterManager_loadPCluster = FhUtil.get_fptr(__addr_ClusterManager_loadPCluster); - _Phyre_PFramework_PApplication_FixupClusters = FhUtil.get_fptr(__addr_Phyre_PFramework_PApplication_FixupClusters); - _ClusterManager_releasePCluster = FhUtil.get_fptr(__addr_ClusterManager_releasePCluster); - _ClusterManager_getPClusterByName = FhUtil.get_fptr(__addr_ClusterManager_getPClusterByName); - _fiosUnifyFilename = FhUtil.get_fptr(__addr_fiosUnifyFilename); - - // Non-loading FMV - _graphicInitFMVPlayer = new FhMethodHandle(this, game, __addr_graphicInitFMVPlayer, h_graphicInitFMVPlayer); - foreach (byte[] script in customScripts) { customScriptHandles.Add(GCHandle.Alloc(script, GCHandleType.Pinned)); } - - //for (int i = 0; i < rawCustomStrings.Length; i++) { - // byte[] text = rawCustomStrings[i]; - // customStrings[i] = new CustomString(text); - //} - - _FmodVoice_dataChange = new FhMethodHandle(this, game, __addr_FmodVoice_dataChange, h_FmodVoice_dataChange); - var _FMOD_EventSystem_load_pointer = FhUtil.get_at(__addr_FMOD_EventSystem_load); - _FMOD_EventSystem_load = Marshal.GetDelegateForFunctionPointer(_FMOD_EventSystem_load_pointer); - //_FMOD_EventSystem_load = new FhMethodHandle(this, _FMOD_EventSystem_load_pointer, h_FMOD_EventSystem_load); - - //_FfxFmod_soundInit_setLang = new FhMethodHandle(this, game, __addr_FfxFmod_soundInit_setLang, h_FfxFmod_soundInit_setLang); - - _LocalizationManager_Initialize = new FhMethodHandle(this, game, __addr_LocalizationManager_Initialize, h_LocalizationManager_Initialize); - _LocalizationManager_GetInstance = FhUtil.get_fptr(__addr_LocalizationManager_GetInstance); - _FfxFmod_soundInit = FhUtil.get_fptr(__addr_FfxFmod_soundInit); - _FmodVoice_initList = FhUtil.get_fptr(__addr_FmodVoice_initList); - - - // Custom namespace - _AtelInitTotal = new FhMethodHandle(this, game, __addr_AtelInitTotal, h_AtelInitTotal); - - // Airship - _FUN_00867370 = FhUtil.get_fptr(__addr_FUN_00867370); - _FUN_008671d0 = FhUtil.get_fptr(__addr_FUN_008671d0); - _Map_show2DLayerResultInt = FhUtil.get_fptr(__addr_Map_show2DLayerResultInt); - _Map_hide2DLayerResultInt = FhUtil.get_fptr(__addr_Map_hide2DLayerResultInt); - - // Drawing - _TOMkpCrossExtMesFontLClutTypeRGBA = FhUtil.get_fptr(__addr_TOMkpCrossExtMesFontLClutTypeRGBA); - _ToMakeBtlEasyFont = FhUtil.get_fptr(__addr_ToMakeBtlEasyFont); - - _PrepareMenuList = new FhMethodHandle(this, game, __addr_PrepareMenuList, h_PrepareMenuList); - _UpdateGearCustomizationMenuState = new FhMethodHandle(this, game, __addr_UpdateGearCustomizationMenuState, h_UpdateGearCustomizationMenuState); - _UpdateAeonCustomizationMenuState = new FhMethodHandle(this, game, __addr_UpdateAeonCustomizationMenuState, h_UpdateAeonCustomizationMenuState); - _DrawGearCustomizationMenu = new FhMethodHandle(this, game, __addr_DrawGearCustomizationMenu, h_DrawGearCustomizationMenu); - _DrawAeonCustomizationMenu = new FhMethodHandle(this, game, __addr_DrawAeonCustomizationMenu, h_DrawAeonCustomizationMenu); - _MsGetRomKaizou = FhUtil.get_fptr(__addr_MsGetRomKaizou); - _MsGetRomAbility = FhUtil.get_fptr(__addr_MsGetRomAbility); - _MsGetRomSummonGrow = FhUtil.get_fptr(__addr_MsGetRomSummonGrow); - _TkMn2GetSummonGrowMax = FhUtil.get_fptr(__addr_TkMn2GetSummonGrowMax); - _TkMenuGetCurrentSummon = FhUtil.get_fptr(__addr_TkMenuGetCurrentSummon); - _MsGetSaveCommand = FhUtil.get_fptr(__addr_MsGetSaveCommand); - - _FUN_008c1c70 = FhUtil.get_fptr(__addr_FUN_008c1c70); - _TODrawMenuPlateXYWHType = FhUtil.get_fptr(__addr_TODrawMenuPlateXYWHType); - _FUN_008f8bb0 = FhUtil.get_fptr(__addr_FUN_008f8bb0); - _TODrawScissorXYWH = FhUtil.get_fptr(__addr_TODrawScissorXYWH); - _FUN_008d5d20 = FhUtil.get_fptr(__addr_FUN_008d5d20); - _FUN_008c0f40 = FhUtil.get_fptr(__addr_FUN_008c0f40); - _FUN_008c1350_DrawScissor512x416 = FhUtil.get_fptr(__addr_FUN_008c1350_DrawScissor512x416); - _FUN_008d5dc0 = FhUtil.get_fptr(__addr_FUN_008d5dc0); - _DrawCrossMenuScrollParts = FhUtil.get_fptr(__addr_DrawCrossMenuScrollParts); - _FUN_008d6630 = FhUtil.get_fptr(__addr_FUN_008d6630); - - _TkVU1SyncPath = FhUtil.get_fptr(__addr_TkVU1SyncPath); - _FUN_008e71d0 = FhUtil.get_fptr(__addr_FUN_008e71d0); - _FUN_008ff490 = FhUtil.get_fptr(__addr_FUN_008ff490); - _FUN_008cd960 = FhUtil.get_fptr(__addr_FUN_008cd960); - _FUN_008cd9f0 = FhUtil.get_fptr(__addr_FUN_008cd9f0); - _ToGetCrossExtMesFontWidth = FhUtil.get_fptr(__addr_ToGetCrossExtMesFontWidth); - _FUN_008bee80 = FhUtil.get_fptr(__addr_FUN_008bee80); - _TOMkpShapeXYWHUV = FhUtil.get_fptr(__addr_TOMkpShapeXYWHUV); - _TOMkpCrossExtMesFontLClut = FhUtil.get_fptr(__addr_TOMkpCrossExtMesFontLClut); - _FUN_008d48e0 = FhUtil.get_fptr(__addr_FUN_008d48e0); - _FUN_008d4140 = FhUtil.get_fptr(__addr_FUN_008d4140); - _TkMn2DrawKickSyncPacket = FhUtil.get_fptr(__addr_TkMn2DrawKickSyncPacket); - - _TkMenuMainAllocWindow = FhUtil.get_fptr(__addr_TkMenuMainAllocWindow); - _TkMenuMainRegistWindow = FhUtil.get_fptr(__addr_TkMenuMainRegistWindow); - - _FUN_008e33a0 = FhUtil.get_fptr(__addr_FUN_008e33a0); - _FUN_008b4460 = FhUtil.get_fptr(__addr_FUN_008b4460); - _FUN_008e2de0 = FhUtil.get_fptr(__addr_FUN_008e2de0); - _MsSetSaveParamAll = FhUtil.get_fptr(__addr_MsSetSaveParamAll); - _MsSetWeaponName = FhUtil.get_fptr(__addr_MsSetWeaponName); - _FUN_008c2c40 = FhUtil.get_fptr(__addr_FUN_008c2c40); - _TkMn2DrawCrossCursor = FhUtil.get_fptr(__addr_TkMn2DrawCrossCursor); - - _FUN_008d5720 = new FhMethodHandle(this, game, __addr_FUN_008d5720, h_FUN_008d5720); } public static int ignore_this = 11; @@ -463,22 +41,22 @@ public int h_Map_800F(AtelBasicWorker* work, int* storage, AtelStack* atelStack) atelStack->pop_int(); return 1; } - return _Map_800F.orig_fptr(work, storage, atelStack); + return FhXCall.h_Map_800F.chain_from(h_Map_800F).fnptr!(work, storage, atelStack); } public bool h_openFile(nint _this, nint filename, bool readOnly, nint unknown_1, nint unknown_2, nint unknown_3) { - string x = Marshal.PtrToStringAnsi(filename); + string x = Marshal.PtrToStringAnsi(filename)!; _logger.Debug($"{_this}, {x}, {readOnly}, {unknown_1}, {unknown_2}, {unknown_3}"); - var result = _openFile.orig_fptr(_this, filename, readOnly, unknown_1, unknown_2, unknown_3); + var result = FhXCall.h_openFile.chain_from(h_openFile).fnptr!(_this, filename, readOnly, unknown_1, unknown_2, unknown_3); _logger.Debug($"{result}, {*(int*)_this}, {*(int*)((int)_this + 4)}"); return result; } public uint h_FUN_0070aec0(nint _this, uint voice_id, uint param_2) { - return _FUN_0070aec0.orig_fptr(_this, voice_id, param_2); + return FhXCall.h_FUN_0070aec0.chain_from(h_FUN_0070aec0).fnptr!(_this, voice_id, param_2); } - private CT_RetInt[] custom_ct_retints; + private FhGCall.CT_RetInt[] custom_ct_retints; private int turnAroundScriptLength; private byte* turnAroundScript; private void init_custom_atel() { @@ -533,21 +111,21 @@ private void init_custom_atel() { } private bool hook() { - return _Common_obtainTreasureInit.hook() && _Common_obtainTreasureSilentlyInit.hook() && _Common_obtainBrotherhoodRetInt.hook() - && _TkSetLegendAbility.hook() && _Common_setPrimerCollected.hook() - && _AtelEventSetUp.hook() && _Common_transitionToMap.hook() && _Common_warpToMap.hook() - && _SgEvent_showModularMenuInit.hook() - && _Common_addPartyMember.hook() && _Common_removePartyMember.hook() && _Common_removePartyMemberLongTerm.hook() && _Common_setWeaponVisibilty.hook() - && _Common_putPartyMemberInSlot.hook() && _Common_pushParty.hook() && _Common_popParty.hook() && _MsBattleExe.hook() && _FUN_00791820.hook() - && _MsApUp.hook() && _MsBtlReadSetScene.hook() // && _Map_800F.hook() //_MsBtlGetPos.hook() - && _eiAbmParaGet.hook() && _MsSetSaveParam.hook() && _MsSetRamChrParam.hook() // && _FUN_00a48910.hook() - && _FUN_0086bec0.hook() && _FUN_0086bea0.hook() // Custom strings - && _graphicInitFMVPlayer.hook() && _FmodVoice_dataChange.hook() - && _AtelInitTotal.hook() - && _LocalizationManager_Initialize.hook() - && _TkMenuAppearMainCmdWindow.hook() - && _PrepareMenuList.hook() && _UpdateGearCustomizationMenuState.hook() && _DrawGearCustomizationMenu.hook() - && _UpdateAeonCustomizationMenuState.hook() && _DrawAeonCustomizationMenu.hook() && _FUN_008d5720.hook(); + return FhXCall.h_Common_obtainTreasureInit.hook(this, h_Common_obtainTreasureInit) && FhXCall.h_Common_obtainTreasureSilentlyInit.hook(this, h_Common_obtainTreasureSilentlyInit) && FhXCall.h_Common_obtainBrotherhoodRetInt.hook(this, h_Common_obtainBrotherhoodRetInt) + && FhXCall.h_TkSetLegendAbility.hook(this, h_TkSetLegendAbility) && FhXCall.h_Common_setPrimerCollected.hook(this, h_Common_setPrimerCollected) + && FhXCall.h_AtelEventSetUp.hook(this, h_AtelEventSetUp) && FhXCall.h_Common_transitionToMap.hook(this, h_Common_transitionToMap) && FhXCall.h_Common_warpToMap.hook(this, h_Common_warpToMap) + && FhXCall.h_SgEvent_showModularMenuInit.hook(this, h_SgEvent_showModularMenuInit) + && FhXCall.h_Common_addPartyMember.hook(this, h_Common_addPartyMember) && FhXCall.h_Common_removePartyMember.hook(this, h_Common_removePartyMember) && FhXCall.h_Common_removePartyMemberLongTerm.hook(this, h_Common_removePartyMemberLongTerm) && FhXCall.h_Common_setWeaponInvisible.hook(this, h_Common_setWeaponInvisible) + && FhXCall.h_Common_putPartyMemberInSlot.hook(this, h_Common_putPartyMemberInSlot) && FhXCall.h_Common_pushParty.hook(this, h_Common_pushParty) && FhXCall.h_Common_popParty.hook(this, h_Common_popParty) && FhXCall.h_MsBattleExe.hook(this, h_MsBattleExe) && FhXCall.h_FUN_00791820.hook(this, h_FUN_00791820) + && FhXCall.h_MsApUp.hook(this, h_MsApUp) && FhXCall.h_MsBtlReadSetScene.hook(this, h_MsBtlReadSetScene) // && Map_800F //MsBtlGetPos + && FhXCall.h_eiAbmParaGet.hook(this, h_eiAbmParaGet) && FhXCall.h_MsSetSaveParam.hook(this, h_MsSetSaveParam) && FhXCall.h_MsSetRamChrParam.hook(this, h_MsSetRamChrParam) // && FUN_00a48910 + && FhXCall.h_FUN_0086bec0.hook(this, h_FUN_0086bec0) && FhXCall.h_FUN_0086bea0.hook(this, h_FUN_0086bea0) // Custom strings + && FhXCall.h_graphicInitFMVPlayer.hook(this, h_graphicInitFMVPlayer) && FhXCall.h_FmodVoice_dataChange.hook(this, h_FmodVoice_dataChange) + && FhXCall.h_AtelInitTotal.hook(this, h_AtelInitTotal) + && FhXCall.h_LocalizationManager_Initialize.hook(this, h_LocalizationManager_Initialize) + && FhXCall.h_TkMenuAppearMainCmdWindow.hook(this, h_TkMenuAppearMainCmdWindow) + && FhXCall.h_PrepareMenuList.hook(this, h_PrepareMenuList) && FhXCall.h_UpdateGearCustomizationMenuState.hook(this, h_UpdateGearCustomizationMenuState) && FhXCall.h_DrawGearCustomizationMenu.hook(this, h_DrawGearCustomizationMenu) + && FhXCall.h_UpdateAeonCustomizationMenuState.hook(this, h_UpdateAeonCustomizationMenuState) && FhXCall.h_DrawAeonCustomizationMenu.hook(this, h_DrawAeonCustomizationMenu) && FhXCall.h_FUN_008d5720.hook(this, h_FUN_008d5720); //&& _FUN_00656c90.hook() && _FUN_0065ee30.hook(); //&& _openFile.hook() && _FUN_0070aec0.hook(); //&& _MsCheckLeftWindow.hook() && _MsCheckUseCommand.hook() && _TOBtlDrawStatusLimitGauge.hook(); @@ -615,7 +193,7 @@ private void move(byte* code_ptr, uint sourceOffset, int moveBy, int size) { _logger.Debug(customStrings[custom_index].decoded); } else { // May crash if called with invalid index - result = _FUN_0086bec0.orig_fptr(param_1); + result = FhXCall.h_FUN_0086bec0.chain_from(h_FUN_0086bec0).fnptr!(param_1); } return result; @@ -628,7 +206,7 @@ private short h_FUN_0086bea0(int param_1) { result = customStrings[custom_index].metadata; } else { - result = _FUN_0086bea0.orig_fptr(param_1); + result = FhXCall.h_FUN_0086bea0.chain_from(h_FUN_0086bea0).fnptr!(param_1); } return result; @@ -1479,7 +1057,7 @@ AtelOp.PUSHII .build(0x50AB), private static Dictionary<(int, int), uint> originalEntryPoints = new(); private static string current_event_name = ""; private void h_AtelEventSetUp(int event_id) { - _AtelEventSetUp.orig_fptr(event_id); + FhXCall.h_AtelEventSetUp.chain_from(h_AtelEventSetUp).fnptr!(event_id); foreach (NativeCustomString customString in cached_strings) { customString.Free(); @@ -2436,7 +2014,7 @@ AtelOp.PUSHII .build( 0), private void h_Common_obtainTreasureInit(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int treasure_id = atelStack->values.as_int()[1]; _logger.Info($"obtain_treasure: {treasure_id}"); - //_Common_obtainTreasureInit.orig_fptr(work, storage, atelStack); + //FhXCall.h_Common_obtainTreasureInit.chain_from(h_Common_obtainTreasureInit).fnptr!(work, storage, atelStack); obtainTreasureInitReimplement(work, storage, atelStack); } @@ -2448,15 +2026,15 @@ private void obtainTreasureInitReimplement(AtelBasicWorker* work, int* storage, int window_id = atelStack->pop_int(); _logger.Debug($"window_id:{window_id}, treasure_id:{treasure_id}"); - _SndSepPlaySimple(0x80000026); - AtelWorkerController* pAVar2 = (AtelWorkerController*)_AtelGetCurCtrlWork(); + FhXCall.h_SndSepPlaySimple.fnptr!(0x80000026); + AtelWorkerController* pAVar2 = (AtelWorkerController*)FhXCall.h_AtelGetCurCtrlWork.fnptr!(); ((byte*)pAVar2)[3] |= 4; - _MsFieldItemGet(treasure_id); - _FUN_008b8910(window_id, 0, 0); - _FUN_008b8910(window_id, 1, 1); + FhXCall.h_MsFieldItemGet.fnptr!(treasure_id); + FhXCall.h_FUN_008b8910.fnptr!(window_id, 0, 0); + FhXCall.h_FUN_008b8910.fnptr!(window_id, 1, 1); bool gear_inv_is_full = false; uint weapon_id = 0; - byte* message_text = _FUN_008bda20(0x401d); // "Nothing" + byte* message_text = FhXCall.h_FUN_008bda20.fnptr!(0x401d); // "Nothing" if (item_locations.treasure.TryGetValue(treasure_id, out var item)) { if (_client!.sendLocation(treasure_id, ArchipelagoClientModule.ArchipelagoLocationType.Treasure)) { @@ -2469,7 +2047,7 @@ private void obtainTreasureInitReimplement(AtelBasicWorker* work, int* storage, cached_strings.Add(name); item_name = name.encoded; if (item.id != 0) { - message_text = _FUN_008bda20(0x4018); // "Obtained %0!" + message_text = FhXCall.h_FUN_008bda20.fnptr!(0x4018); // "Obtained %0!" } else { NativeCustomString sent_text = new NativeCustomString("Sent {VAR:00}!"); //CustomString sent_text = new CustomString("Sent {VAR:00} to {VAR:01}!"); @@ -2488,13 +2066,13 @@ private void obtainTreasureInitReimplement(AtelBasicWorker* work, int* storage, } else if (Battle.reward_data->item_count != 0) { - _TkMsGetRomItem(Battle.reward_data->items[0], (int*)&item_name); - _FUN_008b8930(window_id, 1, Battle.reward_data->items_amounts[0]); + FhXCall.h_TkMsGetRomItem.fnptr!(Battle.reward_data->items[0], (int*)&item_name); + FhXCall.h_FUN_008b8930.fnptr!(window_id, 1, Battle.reward_data->items_amounts[0]); if (Battle.reward_data->items_amounts[0] == 1) { - message_text = _FUN_008bda20(0x4018); // "Obtained %0!" + message_text = FhXCall.h_FUN_008bda20.fnptr!(0x4018); // "Obtained %0!" } else { - message_text = _FUN_008bda20(0x4019); // "Obtained %0 x%1!" + message_text = FhXCall.h_FUN_008bda20.fnptr!(0x4019); // "Obtained %0 x%1!" } byte[] decoded = new byte[FhEncoding.compute_decode_buffer_size(new ReadOnlySpan(item_name, 1000))]; @@ -2503,35 +2081,35 @@ private void obtainTreasureInitReimplement(AtelBasicWorker* work, int* storage, //string decoded = FhEncoding.Us.to_string(item_name); _logger.Info(Encoding.UTF8.GetString(decoded, 0, decoded_length)); - _MsSaveItemUse(Battle.reward_data->items[0], Battle.reward_data->items_amounts[0]); + FhXCall.h_MsSaveItemUse.fnptr!(Battle.reward_data->items[0], Battle.reward_data->items_amounts[0]); } else if (Battle.reward_data->key_item_count != 0) { - item_name = _MsImportantName(Battle.reward_data->key_item); - message_text = _FUN_008bda20(0x4017); // "Obtained %0!" - _TkMsImportantSet.hook_fptr(Battle.reward_data->key_item); + item_name = FhXCall.h_MsImportantName.fnptr!(Battle.reward_data->key_item); + message_text = FhXCall.h_FUN_008bda20.fnptr!(0x4017); // "Obtained %0!" + FhXCall.h_TkMsImportantSet.fnptr!(Battle.reward_data->key_item); } else if (Battle.reward_data->gear_count != 0) { weapon_id = Battle.reward_data->gear_inv_idx; - message_text = _FUN_008bda20(0x4016); // "Obtained %0!" - Equipment* weapon = (Equipment*)_MsGetSaveWeapon(weapon_id, (nint)(&item_name)); - int inv_id = _FUN_007ab930(weapon); // giveWeapon? + message_text = FhXCall.h_FUN_008bda20.fnptr!(0x4016); // "Obtained %0!" + Equipment* weapon = (Equipment*)FhXCall.h_MsGetSaveWeapon.fnptr!(weapon_id, (nint)(&item_name)); + int inv_id = FhXCall.h_FUN_007ab930.fnptr!(weapon); // giveWeapon? gear_inv_is_full = inv_id == 0; } else if (Battle.reward_data->gil != 0) { - _FUN_008b8930(window_id, 1, (int)Battle.reward_data->gil); - message_text = _FUN_008bda20(0x401a); // "Obtained %1 Gil!" - _MsPayGIL(-(int)Battle.reward_data->gil); + FhXCall.h_FUN_008b8930.fnptr!(window_id, 1, (int)Battle.reward_data->gil); + message_text = FhXCall.h_FUN_008bda20.fnptr!(0x401a); // "Obtained %1 Gil!" + FhXCall.h_MsPayGIL.fnptr!(-(int)Battle.reward_data->gil); } - _FUN_008b8930(window_id, 0, (int)item_name); + FhXCall.h_FUN_008b8930.fnptr!(window_id, 0, (int)item_name); atelStack->push_int(window_id); atelStack->push_int(0x100); atelStack->push_int(0xd0); atelStack->push_int(4); - _CT_RetInt_0065((nint)work, storage, (nint)atelStack); + FhXCall.h_CT_RetInt_0065.fnptr!((nint)work, storage, (nint)atelStack); - TOMesWinWork* mesageWindowWorker = _AtelGetMesWinWork(window_id); + TOMesWinWork* mesageWindowWorker = FhXCall.h_AtelGetMesWinWork.fnptr!(window_id); mesageWindowWorker->_0x20 = 0; mesageWindowWorker->text = message_text; mesageWindowWorker->_0xc = message_text; @@ -2540,7 +2118,7 @@ private void obtainTreasureInitReimplement(AtelBasicWorker* work, int* storage, atelStack->push_int(window_id); atelStack->push_int(0); - _CT_RetInt_006A((nint)work, storage, (nint)atelStack); + FhXCall.h_CT_RetInt_006A.fnptr!((nint)work, storage, (nint)atelStack); *storage = window_id; storage[1] = 1; @@ -2548,23 +2126,23 @@ private void obtainTreasureInitReimplement(AtelBasicWorker* work, int* storage, storage[3] = (int)weapon_id; if (!gear_inv_is_full) { - _MsBtlGetInit(); + FhXCall.h_MsBtlGetInit.fnptr!(); } - _FUN_0086a0c0(); + FhXCall.h_FUN_0086a0c0.fnptr!(); mesageWindowWorker->_0x1d |= 0x10; } private void h_Common_obtainTreasureSilentlyInit(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int treasure_id = atelStack->values.as_int()[0]; _logger.Info($"obtain_treasure_silently: {treasure_id}"); - //_Common_obtainTreasureSilentlyInit.orig_fptr(work, storage, atelStack); + //FhXCall.h_Common_obtainTreasureSilentlyInit.chain_from(h_Common_obtainTreasureSilentlyInit).fnptr!(work, storage, atelStack); obtainTreasureSilentlyInitReimplement(work, storage, atelStack); } private void obtainTreasureSilentlyInitReimplement(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int treasure_id = atelStack->pop_int(); - _MsFieldItemGet(treasure_id); + FhXCall.h_MsFieldItemGet.fnptr!(treasure_id); bool gear_inv_is_full = false; uint weapon_id = 0; @@ -2575,26 +2153,26 @@ private void obtainTreasureSilentlyInitReimplement(AtelBasicWorker* work, int* s } else if (Battle.reward_data->item_count != 0) { - _MsSaveItemUse(Battle.reward_data->items[0], Battle.reward_data->items_amounts[0]); + FhXCall.h_MsSaveItemUse.fnptr!(Battle.reward_data->items[0], Battle.reward_data->items_amounts[0]); } else if (Battle.reward_data->key_item_count != 0) { - _TkMsImportantSet.hook_fptr(Battle.reward_data->key_item); + FhXCall.h_TkMsImportantSet.fnptr!(Battle.reward_data->key_item); } else if (Battle.reward_data->gear_count != 0) { weapon_id = Battle.reward_data->gear_inv_idx; - Equipment* weapon = (Equipment*)_MsGetSaveWeapon(weapon_id, 0); - int inv_id = _FUN_007ab930(weapon); // giveWeapon? + Equipment* weapon = FhXCall.h_MsGetSaveWeapon.fnptr!(weapon_id, 0); + int inv_id = FhXCall.h_FUN_007ab930.fnptr!(weapon); // giveWeapon? gear_inv_is_full = inv_id == 0; } else if (Battle.reward_data->gil != 0) { - _MsPayGIL(-(int)Battle.reward_data->gil); + FhXCall.h_MsPayGIL.fnptr!(-(int)Battle.reward_data->gil); } storage[2] = gear_inv_is_full ? 1 : 0; storage[3] = (int)weapon_id; if (!gear_inv_is_full) { - _MsBtlGetInit(); + FhXCall.h_MsBtlGetInit.fnptr!(); } } @@ -2607,7 +2185,7 @@ private int h_Common_obtainBrotherhoodRetInt(AtelBasicWorker* work, int* storage obtain_item(item.id); return 1; } - return _Common_obtainBrotherhoodRetInt.orig_fptr(work, storage, atelStack); + return FhXCall.h_Common_obtainBrotherhoodRetInt.chain_from(h_Common_obtainBrotherhoodRetInt).fnptr!(work, storage, atelStack); } private int h_Common_upgradeBrotherhoodRetInt(nint work, int* storage, nint atelStack) { _logger.Debug("upgrade_brotherhoodRetInt"); @@ -2616,12 +2194,12 @@ private int h_Common_upgradeBrotherhoodRetInt(nint work, int* storage, nint atel return 1; } - return _Common_upgradeBrotherhoodRetInt.orig_fptr(work, storage, atelStack); + return FhXCall.h_Common_upgradeBrotherhoodRetInt.chain_from(h_Common_upgradeBrotherhoodRetInt).fnptr!(work, storage, atelStack); } private int h_Common_isBrotherhoodUnpoweredRetInt(nint work, int* storage, nint atelStack) { _logger.Debug("isBrotherhoodUnpoweredRetInt"); - return _Common_isBrotherhoodUnpoweredRetInt.orig_fptr(work, storage, atelStack); + return FhXCall.h_CT_RetInt_01B6.chain_from(h_Common_isBrotherhoodUnpoweredRetInt).fnptr!(work, storage, atelStack); } //private static int h_Common_grantCelestialUpgrade(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { // int character = atelStack->values.as_int()[0]; @@ -2650,7 +2228,7 @@ private int h_TkSetLegendAbility(int chr_id, int level) { return level; } - return _TkSetLegendAbility.orig_fptr(chr_id, level); + return FhXCall.h_TkSetLegendAbility.chain_from(h_TkSetLegendAbility).fnptr!(chr_id, level); } @@ -2666,7 +2244,7 @@ private int h_Common_setPrimerCollected(AtelBasicWorker* work, int* storage, Ate return 1; } - return _Common_setPrimerCollected.orig_fptr(work, storage, atelStack); + return FhXCall.h_Common_setPrimerCollected.chain_from(h_Common_setPrimerCollected).fnptr!(work, storage, atelStack); } private void update_region_state() { @@ -2806,7 +2384,7 @@ private int h_Common_transitionToMap(AtelBasicWorker* work, int* storage, AtelSt _logger.Debug($"transition_to_map: map={map}, entrance={entrance}"); if (handle_warp_transition(save_data->current_room_id, save_data->current_spawnpoint, ref map, ref entrance)) { - return _Common_transitionToMap.orig_fptr(work, storage, atelStack); + return FhXCall.h_Common_transitionToMap.chain_from(h_Common_transitionToMap).fnptr!(work, storage, atelStack); } return blockWarp(work, storage, atelStack); @@ -2823,7 +2401,7 @@ private int h_Common_warpToMap(AtelBasicWorker* work, int* storage, AtelStack* a } if (handle_warp_transition(save_data->current_room_id, save_data->current_spawnpoint, ref map, ref entrance)) { - return _Common_warpToMap.orig_fptr(work, storage, atelStack); + return FhXCall.h_Common_warpToMap.chain_from(h_Common_warpToMap).fnptr!(work, storage, atelStack); } return blockWarp(work, storage, atelStack); @@ -2864,7 +2442,7 @@ private void h_SgEvent_showModularMenuInit(AtelBasicWorker* work, int* storage, } _logger.Info($"Opening menu: type={menuTypeString}, index={index} {(unknown1 == 0x40 ? "" : $", Unknown1={unknown1}")} {(unknown2 == 0x00 ? "" : $", Unknown2={unknown2}")}"); - _SgEvent_showModularMenuInit.orig_fptr(work, storage, atelStack); + FhXCall.h_SgEvent_showModularMenuInit.chain_from(h_SgEvent_showModularMenuInit).fnptr!(work, storage, atelStack); } @@ -2880,7 +2458,7 @@ public int h_Common_addPartyMember(AtelBasicWorker* work, int* storage, AtelStac } //logger.Debug($"add_party_member: character={id_to_character[character]}"); - return _Common_addPartyMember.orig_fptr(work, storage, atelStack); + return FhXCall.h_Common_addPartyMember.chain_from(h_Common_addPartyMember).fnptr!(work, storage, atelStack); } public int h_Common_removePartyMember(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { @@ -2895,7 +2473,7 @@ public int h_Common_removePartyMember(AtelBasicWorker* work, int* storage, AtelS } //logger.Debug($"remove_party_member: character={id_to_character[character]}"); - return _Common_removePartyMember.orig_fptr(work, storage, atelStack); + return FhXCall.h_Common_removePartyMember.chain_from(h_Common_removePartyMember).fnptr!(work, storage, atelStack); } public int h_Common_removePartyMemberLongTerm(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { @@ -2910,7 +2488,7 @@ public int h_Common_removePartyMemberLongTerm(AtelBasicWorker* work, int* storag } //logger.Debug($"remove_party_member_long_term: character={id_to_character[character]}"); - return _Common_removePartyMemberLongTerm.orig_fptr(work, storage, atelStack); + return FhXCall.h_Common_removePartyMemberLongTerm.chain_from(h_Common_removePartyMemberLongTerm).fnptr!(work, storage, atelStack); } public int h_Common_setWeaponInvisible(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { @@ -2922,7 +2500,7 @@ public int h_Common_setWeaponInvisible(AtelBasicWorker* work, int* storage, Atel atelStack->pop_int(); return 0; } - return _Common_setWeaponVisibilty.orig_fptr(work, storage, atelStack); + return FhXCall.h_Common_setWeaponInvisible.chain_from(h_Common_setWeaponInvisible).fnptr!(work, storage, atelStack); } public int h_Common_putPartyMemberInSlot(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { @@ -2939,13 +2517,13 @@ public int h_Common_putPartyMemberInSlot(AtelBasicWorker* work, int* storage, At } //logger.Debug($"put_party_member_in_slot: slot={slot}, character={(character != 0xff ? id_to_character[character] : "Empty")}"); - return _Common_putPartyMemberInSlot.orig_fptr(work, storage, atelStack); + return FhXCall.h_Common_putPartyMemberInSlot.chain_from(h_Common_putPartyMemberInSlot).fnptr!(work, storage, atelStack); } public int h_Common_pushParty(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { //logger.Debug($"push_party"); - //if (party_overridden) return _Common_pushParty.orig_fptr(work, storage, atelStack); + //if (party_overridden) return FhXCall.h_Common_pushParty.chain_from(h_Common_pushParty).fnptr!(work, storage, atelStack); //save_party(); return 0; } @@ -2953,7 +2531,7 @@ public int h_Common_pushParty(AtelBasicWorker* work, int* storage, AtelStack* at public int h_Common_popParty(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { //logger.Debug($"pop_party"); - //if (party_overridden) return _Common_popParty.orig_fptr(work, storage, atelStack); + //if (party_overridden) return FhXCall.h_Common_popParty.chain_from(h_Common_popParty).fnptr!(work, storage, atelStack); //reset_party(); return 1; } @@ -2961,7 +2539,7 @@ public int h_Common_popParty(AtelBasicWorker* work, int* storage, AtelStack* ate // TODO: Get function pointer instead of hook for most of these public void h_MsGetSavePartyMember(uint* param_1, uint* param_2, uint* param_3) { //logger.Debug($"get_current_party_slots"); - _MsGetSavePartyMember.orig_fptr(param_1, param_2, param_3); + FhXCall.h_MsGetSavePartyMember.chain_from(h_MsGetSavePartyMember).fnptr!(param_1, param_2, param_3); //logger.Debug($"get_current_party_slots: slot_0={*param_1}, slot_1={*param_2}, slot_2={*param_3}"); } @@ -2979,7 +2557,7 @@ public void h_MsBattleExe(uint param_1, int field_idx, int group_idx, int format var field_ptr = Battle.btl->ptr_btl_bin_fields + field_idx * 0xe; string field_name = Marshal.PtrToStringAnsi((nint)(field_ptr+6))!; - var group_ptr = _MsBtlListGroup(field_idx, group_idx); + var group_ptr = FhXCall.h_MsBtlListGroup.fnptr!(field_idx, group_idx); byte group_name = *(byte*)(group_ptr+5 + formation_idx * 2); string encounter_name = $"{field_name}_{group_name:00}"; @@ -3001,12 +2579,12 @@ public void h_MsBattleExe(uint param_1, int field_idx, int group_idx, int format save_party(); // Probably? reset_party(); } - _MsBattleExe.orig_fptr(param_1, field_idx, group_idx, formation_idx); + FhXCall.h_MsBattleExe.chain_from(h_MsBattleExe).fnptr!(param_1, field_idx, group_idx, formation_idx); } // Battle loop? public void h_FUN_00791820() { - _FUN_00791820.orig_fptr(); + FhXCall.h_FUN_00791820.chain_from(h_FUN_00791820).fnptr!(); string encounter_name = Marshal.PtrToStringAnsi((nint)(&Battle.btl->field_name))!; byte battle_end_type = Battle.btl->battle_end_type; byte battle_state = Battle.btl->battle_state; @@ -3053,7 +2631,7 @@ public void h_FUN_00791820() { private void* curr_pos_area_ptr = null; public byte h_MsBtlReadSetScene() { - byte result = _MsBtlReadSetScene.orig_fptr(); + byte result = FhXCall.h_MsBtlReadSetScene.chain_from(h_MsBtlReadSetScene).fnptr!(); _logger.Info($"Battle Name: {Marshal.PtrToStringAnsi((nint)FhUtil.ptr_at(0xD2C25A))}"); //ref BtlAreas original_pos_struct = ref *Battle.btl->ptr_pos_def; BtlAreasHelper original_pos_struct = new BtlAreasHelper(Battle.btl->ptr_pos_def); @@ -3240,7 +2818,7 @@ public int h_MsBtlGetPos(int param_1, Chr* chr, int btl_pos_a, int btl_pos_b, in // btl_pos_b = 8: enemy_run_pos[btl_pos_c]? // btl_pos_b = 9: b? // btl_pos_b = 10: c? - return _MsBtlGetPos.orig_fptr(param_1, chr, btl_pos_a, btl_pos_b, btl_pos_c, out_pos); + return FhXCall.h_MsBtlGetPos.chain_from(h_MsBtlGetPos).fnptr!(param_1, chr, btl_pos_a, btl_pos_b, btl_pos_c, out_pos); } private uint h_give_item(uint item_id, int amount) { @@ -3254,13 +2832,13 @@ private uint h_give_item(uint item_id, int amount) { amount -= excess; } - return _FUN_007905a0.orig_fptr(item_id, amount); + return FhXCall.h_FUN_007905a0.chain_from(h_give_item).fnptr!(item_id, amount); } private void h_TkMsImportantSet(uint param_1) { _logger.Debug($"give_key_item: {param_1}"); - _TkMsImportantSet.orig_fptr(param_1); + FhXCall.h_TkMsImportantSet.chain_from(h_TkMsImportantSet).fnptr!(param_1); } private byte* h_read_from_bin(int param_1, short* param_2, int param_3) { @@ -3272,7 +2850,7 @@ private void h_TkMsImportantSet(uint param_1) { else if (param_2 == (short*)*buki_get_pointer) { _logger.Debug("get_from_bin: buki_get.bin"); } - var result = _FUN_007ab890.orig_fptr(param_1, param_2, param_3); + var result = FhXCall.h_FUN_007ab890.chain_from(h_read_from_bin).fnptr!(param_1, param_2, param_3); _logger.Debug($"get_from_bin: result = {((uint)result).ToString("X")}"); return result; } @@ -3280,19 +2858,19 @@ private void h_TkMsImportantSet(uint param_1) { private ushort h_get_weapon_name(Equipment* param_1) { _logger.Debug($"get_weapon_name: {(int)param_1}"); - return _FUN_007a0d10.orig_fptr(param_1); + return FhXCall.h_FUN_007a0d10.chain_from(h_get_weapon_name).fnptr!(param_1); } private void h_get_weapon_model(ushort name_id, byte owner, int unknown, ushort* model_id_pointer) { _logger.Debug($"get_weapon_model: {name_id}, {owner}, {unknown}, {*model_id_pointer}, "); - _FUN_007a0c70.orig_fptr(name_id, owner, unknown, model_id_pointer); + FhXCall.h_FUN_007a0c70.chain_from(h_get_weapon_model).fnptr!(name_id, owner, unknown, model_id_pointer); } private void h_obtain_treasure_cleanup(BtlRewardData* param_1, int param_2) { _logger.Debug("obtain_treasure_cleanup"); - _FUN_007993f0.orig_fptr(param_1, param_2); + FhXCall.h_FUN_007993f0.chain_from(h_obtain_treasure_cleanup).fnptr!(param_1, param_2); } public void obtain_item(uint item_id, int amount=-1) { @@ -3373,7 +2951,7 @@ public void obtain_item(uint item_id, int amount=-1) { // Upgrade celestial if (celestial_level[equip.owner] < 2) { celestial_level[equip.owner] += 1; - _TkSetLegendAbility.orig_fptr(equip.owner, celestial_level[equip.owner]); + FhXCall.h_TkSetLegendAbility.chain_from(h_TkSetLegendAbility).fnptr!(equip.owner, celestial_level[equip.owner]); } return; } @@ -3427,7 +3005,7 @@ public void obtain_item(uint item_id, int amount=-1) { new_weapon.slot_count = (byte)Math.Max(weapon_data.slot_count, count); new_weapon.name_id = h_get_weapon_name(&new_weapon); h_get_weapon_model(new_weapon.name_id, new_weapon.owner, 0, &new_weapon.model_id); - var result = _FUN_007ab930(&new_weapon); // giveWeapon? + var result = FhXCall.h_FUN_007ab930.fnptr!(&new_weapon); // giveWeapon? if (result != 0) { h_obtain_treasure_cleanup(&rewardData, 7); } @@ -3435,7 +3013,7 @@ public void obtain_item(uint item_id, int amount=-1) { case 0x1: // Gil if (amount == -1) amount = (int)((item_id & 0xFF0000) >> 16) * 1000; - _MsPayGIL(-amount); + FhXCall.h_MsPayGIL.fnptr!(-amount); break; case 0xE: // Region Unlock @@ -3537,7 +3115,7 @@ public void receive_treasure(int id) { int param_1 = 0; int param_2 = 0; - _Common_obtainTreasureSilentlyInit.orig_fptr((AtelBasicWorker*)¶m_1, ¶m_2, &stack); + FhXCall.h_Common_obtainTreasureSilentlyInit.chain_from(h_Common_obtainTreasureSilentlyInit).fnptr!((AtelBasicWorker*)¶m_1, ¶m_2, &stack); } public void set_airship_destinations() { @@ -3571,7 +3149,7 @@ public void set_airship_destinations() { public void h_eiAbmParaGet() { // TODO: Replace normal calculation with custom Archipelago-based calculation (if option enabled) _logger.Debug("Calculating stats"); - _eiAbmParaGet.orig_fptr(); + FhXCall.h_eiAbmParaGet.chain_from(h_eiAbmParaGet).fnptr!(); //foreach (ref PlySave ply in save_data->ply_saves) { // ply.abi_map.has_extract_power = true; @@ -3583,9 +3161,9 @@ public void h_eiAbmParaGet() { private void h_MsSetRamChrParam(uint chr_id) { _logger.Debug($"MsSetRamChrParam: {chr_id}"); - _MsSetRamChrParam.orig_fptr(chr_id); + FhXCall.h_MsSetRamChrParam.chain_from(h_MsSetRamChrParam).fnptr!(chr_id); - Chr* chr = _MsGetChr(chr_id); + Chr* chr = FhXCall.h_MsGetChr.fnptr!((int)chr_id); if (seed.Options.AlwaysSensor == 1) { chr->ram.auto_ability_effects.has_sensor = true; @@ -3594,7 +3172,7 @@ private void h_MsSetRamChrParam(uint chr_id) { private void h_MsSetSaveParam(uint chr_id) { _logger.Debug("Calculating base stats and equipment"); - _MsSetSaveParam.orig_fptr(chr_id); + FhXCall.h_MsSetSaveParam.chain_from(h_MsSetSaveParam).fnptr!(chr_id); // Does nothing?? if (seed.Options.AlwaysSensor == 1) { @@ -3605,8 +3183,8 @@ private void h_MsSetSaveParam(uint chr_id) { //PlySave ply = save_data->ply_saves[(int)chr_id]; //Equipment*[] equips = //[ - // (Equipment*)_MsGetSaveWeapon(ply.wpn_inv_idx, 0x0), - // (Equipment*)_MsGetSaveWeapon(ply.arm_inv_idx, 0x0), + // (Equipment*)FhXCall.h_MsGetSaveWeapon.fnptr!(ply.wpn_inv_idx, 0x0), + // (Equipment*)FhXCall.h_MsGetSaveWeapon.fnptr!(ply.arm_inv_idx, 0x0), //]; //int strength_mult = 0; //int defense_mult = 0; @@ -3626,7 +3204,7 @@ private void h_MsSetSaveParam(uint chr_id) { //foreach (Equipment* equip in equips) { // for (int i = 0; i < 4; i++) { // if (equip->abilities[i] == 0 || equip->abilities[i] == 0xFF) continue; - // AutoAbility* a_ability = (AutoAbility*)_MsGetExcelData(equip->abilities[i] & 0xFFF, Battle.btl->ptr_a_ability_bin, (int*)0x0); + // AutoAbility* a_ability = (AutoAbility*)FhXCall.h_MsGetExcelData.fnptr!(equip->abilities[i] & 0xFFF, Battle.btl->ptr_a_ability_bin, (int*)0x0); // strength_mult += a_ability->stat_inc_flags.strength() ? a_ability->stat_inc_amount : 0; // defense_mult += a_ability->stat_inc_flags.defense() ? a_ability->stat_inc_amount : 0; // magic_mult += a_ability->stat_inc_flags.magic() ? a_ability->stat_inc_amount : 0; @@ -3659,20 +3237,20 @@ private void h_MsSetSaveParam(uint chr_id) { public void h_FUN_00a48910(uint chr_id, int node_idx) { // TODO: Send Archipelago location when node is unlocked (if option enabled) _logger.Debug($"Unlock node {node_idx} for {id_to_character[chr_id]}"); - _FUN_00a48910.orig_fptr(chr_id, node_idx); + FhXCall.h_FUN_00a48910.chain_from(h_FUN_00a48910).fnptr!(chr_id, node_idx); } private uint h_MsApUp(int chr_id, Chr* chr, int base_ap_add, uint param_4) { _logger.Debug($"AP gain: character={id_to_character[chr_id]}, ap={base_ap_add}"); int new_ap = (int)Math.Min(Math.BigMul(base_ap_add, ap_multiplier), 999_999_999); - return _MsApUp.orig_fptr(chr_id, chr, new_ap, param_4); + return FhXCall.h_MsApUp.chain_from(h_MsApUp).fnptr!(chr_id, chr, new_ap, param_4); } // Non-loading FMV private bool h_graphicInitFMVPlayer(int movie_id, int param_2) { - bool result = _graphicInitFMVPlayer.orig_fptr(movie_id, param_2); + bool result = FhXCall.h_graphicInitFMVPlayer.chain_from(h_graphicInitFMVPlayer).fnptr!(movie_id, param_2); return !result; } @@ -3685,14 +3263,14 @@ private void h_FUN_00656c90(int param_1, int param_2, char* fileName) { //logger.Debug(nameString); - _FUN_00656c90.orig_fptr(param_1, param_2, fileName); + FhXCall.h_FUN_00656c90.chain_from(h_FUN_00656c90).fnptr!(param_1, param_2, fileName); } private void h_TkMenuAppearMainCmdWindow(int param_1, int param_2) { // All menu options are enabled at progress 0 ushort progress = save_data->story_progress; save_data->story_progress = 0; - _TkMenuAppearMainCmdWindow.orig_fptr(param_1, param_2); + FhXCall.h_TkMenuAppearMainCmdWindow.chain_from(h_TkMenuAppearMainCmdWindow).fnptr!(param_1, param_2); save_data->story_progress = progress; } @@ -3706,27 +3284,30 @@ private void h_TkMenuAppearMainCmdWindow(int param_1, int param_2) { //} public void h_FfxFmod_soundInit_setLang(nint ffxFmod, int lang) { - _FfxFmod_soundInit_setLang.orig_fptr(ffxFmod, lang); + FhXCall.h_FfxFmod_soundInit_setLang.chain_from(h_FfxFmod_soundInit_setLang).fnptr!(ffxFmod, lang); *(byte*)(ffxFmod + 4) = 0; } // Unsure if there are side effects - public void h_LocalizationManager_Initialize(FFXLocalizationManager* localizationManager) { - _LocalizationManager_Initialize.orig_fptr(localizationManager); + public void h_LocalizationManager_Initialize(LocalizationManager* localizationManager) { + FhXCall.h_LocalizationManager_Initialize.chain_from(h_LocalizationManager_Initialize).fnptr!(localizationManager); if (TextLanguage.HasValue) { _logger.Debug($"Text: {TextLanguage.Value}"); - localizationManager->text = (int)TextLanguage; + localizationManager->current_language = TextLanguage.Value; } if (VoiceLanguage.HasValue) { _logger.Debug($"Voice: {VoiceLanguage.Value}"); - localizationManager->video = (int)VoiceLanguage; - localizationManager->voice = (int)VoiceLanguage; + localizationManager->video = VoiceLanguage.Value; + localizationManager->voice = VoiceLanguage.Value; } } + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public unsafe delegate nint FMOD_Bank_Post_Load(nint param_1, nint param_2, nint param_3, nint param_4); public int h_FmodVoice_dataChange(nint FmodVoice, int event_id, nint param_2) { _logger.Debug($"{FmodVoice}, {event_id}, {param_2}"); - int result = _FmodVoice_dataChange.orig_fptr(FmodVoice, event_id, param_2); + int result = FhXCall.h_FmodVoice_dataChange.chain_from(h_FmodVoice_dataChange).fnptr!(FmodVoice, event_id, param_2); //string bank_name = "ffx_us_voice03"; // Contains "Stay away from the summoner!" (136815042) foreach (string bank_name in (string[])["ffx_us_voice03", "ffx_us_voice07", "ffx_us_voice11", "ffx_us_voice12", "ffx_us_voice20"]) { string path = $"../../../FFX_Data/GameData/PS3Data/Sound_PC/Voice/US/{bank_name}.fev"; @@ -3735,7 +3316,7 @@ public int h_FmodVoice_dataChange(nint FmodVoice, int event_id, nint param_2) { int bank_index = bank_name[^1] + (bank_name[^2] * 5 - 0x108)*2; nint bank = *(int*)(FmodVoice+0x18) + bank_index*4; - nint load_result = _FMOD_EventSystem_load(param_2, file_path, 0, bank); + nint load_result = FhXCall.h_FMOD_EventSystem_load.fnptr!(param_2, file_path, 0, bank); Marshal.FreeHGlobal(file_path); if (load_result == 0) { @@ -3765,13 +3346,13 @@ public void play_voice_line(int voice_line) { int[] storage_array = [0,0,0,0]; fixed (int* storage = storage_array) { - _Common_playFieldVoiceLineInit((AtelBasicWorker*)&work, storage, &stack); - _Common_playFieldVoiceLineExec((AtelBasicWorker*)&work, &stack); - _Common_playFieldVoiceLineResultInt((AtelBasicWorker*)&work, storage, &stack); + FhXCall.h_Common_playFieldVoiceLineInit.fnptr!((AtelBasicWorker*)&work, storage, &stack); + FhXCall.h_Common_playFieldVoiceLineExec.fnptr!((AtelBasicWorker*)&work, &stack); + FhXCall.h_Common_playFieldVoiceLineResultInt.fnptr!((AtelBasicWorker*)&work, storage, &stack); - _Common_00D6Init((AtelBasicWorker*)&work, storage, &stack); - _Common_00D6Exec((AtelBasicWorker*)&work, &stack); - _Common_00D6ResultInt((AtelBasicWorker*)&work, storage, &stack); + FhXCall.h_Common_00D6Init.fnptr!((AtelBasicWorker*)&work, storage, &stack); + FhXCall.h_Common_00D6Exec.fnptr!((AtelBasicWorker*)&work, &stack); + FhXCall.h_Common_00D6ResultInt.fnptr!((AtelBasicWorker*)&work, storage, &stack); } @@ -3781,7 +3362,7 @@ public void play_voice_line(int voice_line) { public string get_item_name(uint item_id) { if (item_name_cache.TryGetValue(item_id, out var name)) return name; byte* item_name; - _TkMsGetRomItem(item_id, (int*)&item_name); + FhXCall.h_TkMsGetRomItem.fnptr!(item_id, (int*)&item_name); byte[] decoded = new byte[FhEncoding.compute_decode_buffer_size(new ReadOnlySpan(item_name, 1000))]; int decoded_length = FhEncoding.decode(new ReadOnlySpan(item_name, 1000), decoded, flags:FhEncodingFlags.IMPLICIT_END); string decoded_string = Encoding.UTF8.GetString(decoded, 0, decoded_length); @@ -3802,42 +3383,42 @@ public string get_other_item_name(uint item_id) { return $"Unnamed item ({item_id})"; } - private Dictionary cached_CT_Execs = new(); - private Dictionary cached_CT_RetInts = new(); - private Dictionary cached_CT_RetFloats = new(); + private Dictionary cached_CT_Execs = new(); + private Dictionary cached_CT_RetInts = new(); + private Dictionary cached_CT_RetFloats = new(); - public CT_Exec get_CT_Exec(int id) { + public FhGCall.CT_Exec get_CT_Exec(int id) { if (cached_CT_Execs.TryGetValue(id, out var result)) { return result; } AtelCallTargetNamespace nmsp = (AtelCallTargetNamespace)(id >> 0xC); AtelCallTarget* internal_ct = nmsp.get_internal() + (id & 0xFFF); - CT_Exec ct = Marshal.GetDelegateForFunctionPointer(internal_ct->ret_float_func); + FhGCall.CT_Exec ct = Marshal.GetDelegateForFunctionPointer(internal_ct->ret_float_func); cached_CT_Execs[id] = ct; return ct; } - public CT_RetInt get_CT_RetInt(int id) { + public FhGCall.CT_RetInt get_CT_RetInt(int id) { if (cached_CT_RetInts.TryGetValue(id, out var result)) { return result; } AtelCallTargetNamespace nmsp = (AtelCallTargetNamespace)(id >> 0xC); AtelCallTarget* internal_ct = nmsp.get_internal() + (id & 0xFFF); - CT_RetInt ct = Marshal.GetDelegateForFunctionPointer(internal_ct->ret_float_func); + FhGCall.CT_RetInt ct = Marshal.GetDelegateForFunctionPointer(internal_ct->ret_float_func); cached_CT_RetInts[id] = ct; return ct; } - public CT_RetFloat get_CT_RetFloat(int id) { + public FhGCall.CT_RetFloat get_CT_RetFloat(int id) { if (cached_CT_RetFloats.TryGetValue(id, out var result)) { return result; } AtelCallTargetNamespace nmsp = (AtelCallTargetNamespace)(id >> 0xC); AtelCallTarget* internal_ct = nmsp.get_internal() + (id & 0xFFF); - CT_RetFloat ct = Marshal.GetDelegateForFunctionPointer(internal_ct->ret_float_func); + FhGCall.CT_RetFloat ct = Marshal.GetDelegateForFunctionPointer(internal_ct->ret_float_func); cached_CT_RetFloats[id] = ct; return ct; } @@ -3845,7 +3426,7 @@ public CT_RetFloat get_CT_RetFloat(int id) { // Custom namespace public void h_AtelInitTotal() { _logger.Debug("Initializing Atel namespaces"); - _AtelInitTotal.orig_fptr(); + FhXCall.h_AtelInitTotal.chain_from(h_AtelInitTotal).fnptr!(); AtelSetUpCallFunc(0xF, customNameSpaceHandle.AddrOfPinnedObject()); } @@ -4121,11 +3702,11 @@ public int blockWarp(AtelBasicWorker* work, int* storage, AtelStack* atelStack) atelStack->push_int(2); // signal priority? atelStack->push_int(0); // worker atelStack->push_int(entry_point); // entrypoint - _FUN_00867370((byte)AtelOp.REQEW & 0x7F, work, &work->threads[work->current_thread_priority], atelStack, 0); + FhXCall.h_FUN_00867370.fnptr!((byte)AtelOp.REQEW & 0x7F, work, &work->threads[work->current_thread_priority], atelStack, 0); work->__0x34 = (ushort)(work->__0x34 & 0xEBFF | 0x800); //work->__0x34 = (ushort)(work->__0x34 | 0x800); atelStack->pop_int(); - //_FUN_008671d0((byte)AtelOp.REQ & 0x7F, &work->threads[work->current_thread_priority], work, atelStack); + //FhXCall.h_FUN_008671d0.fnptr!((byte)AtelOp.REQ & 0x7F, &work->threads[work->current_thread_priority], work, atelStack); return 1; } _logger.Debug($"Closest entrance: pos:({closestEntrance?.Entrance.x}, {closestEntrance?.Entrance.y}, {closestEntrance?.Entrance.z}) distance:{closestEntrance?.Distance}"); @@ -4198,7 +3779,7 @@ public int CT_RetInt_ShowCurrentAirshipLocation(AtelBasicWorker* work, int* stor // AE0300 D80F80 call Map.?show2DLayer [800Fh](layerIndex=3 [03h]); atelStack->push_int(3); - _Map_show2DLayerResultInt(work, storage, atelStack); + FhXCall.h_Map_show2DLayerResultInt.fnptr!(work, storage, atelStack); return 1; } @@ -4208,7 +3789,7 @@ public int CT_RetInt_HideCurrentAirshipLocation(AtelBasicWorker* work, int* stor // AE0300 D81080 call Map.?hide2DLayer [8010h](layerIndex=3 [03h]); atelStack->push_int(3); - _Map_hide2DLayerResultInt(work, storage, atelStack); + FhXCall.h_Map_hide2DLayerResultInt.fnptr!(work, storage, atelStack); return 1; } diff --git a/src/modules/captures.cs b/src/modules/captures.cs index 28aeaf4..b203971 100644 --- a/src/modules/captures.cs +++ b/src/modules/captures.cs @@ -1,73 +1,23 @@ -using System; - -using Archipelago.MultiClient.Net.Enums; +using Archipelago.MultiClient.Net.Enums; +using ArchipelagoFFX.Client; +using Fahrenheit; using Fahrenheit.Atel; using Fahrenheit.FFX; using Fahrenheit.FFX.Battle; - +using System; using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; using System.IO; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; - -using ArchipelagoFFX.Client; - -using Fahrenheit; - -using static Fahrenheit.FFX.Globals; using static ArchipelagoFFX.Client.ArchipelagoClientModule; -using static ArchipelagoFFX.delegates; +using static Fahrenheit.FFX.Globals; +using FhGCall = Fahrenheit.FhCall; +using FhXCall = Fahrenheit.FFX.FhCall; namespace ArchipelagoFFX; [FhLoad(FhGameId.FFX)] public unsafe partial class CaptureModule : FhModule { - // Some structs that Fahrenheit is currently missing - [StructLayout(LayoutKind.Sequential)] - private struct BtlBinField { - [InlineArray(8)] - public struct FieldName { - private byte _data; - } - - public short id; - public short data_offset; - public short __0x4; - public FieldName name; - } - - [StructLayout(LayoutKind.Explicit, Size = 0x2)] - private struct BtlBinEncounter { - [FieldOffset(0x0)] public byte total_formation_count; - [FieldOffset(0x1)] public byte group_count; - - [FieldOffset(0x2)] private BtlBinGroup _first_group; - - [UnscopedRef] - public Span groups => MemoryMarshal.CreateSpan(ref _first_group, group_count); - } - - [StructLayout(LayoutKind.Explicit, Size = 0x5)] - private struct BtlBinGroup { - [FieldOffset(0x0)] public byte formation_count; - [FieldOffset(0x1)] public short battlefield; - [FieldOffset(0x3)] public byte grace; - [FieldOffset(0x4)] public byte total_weight; - - [FieldOffset(0x5)] private BtlBinFormation _first_formation; - - [UnscopedRef] - public Span formations => MemoryMarshal.CreateSpan(ref _first_formation, formation_count); - } - - [StructLayout(LayoutKind.Sequential)] - private struct BtlBinFormation { - public byte index; - public byte weight; - } - private FhModuleHandle _client_handle; private ArchipelagoClientModule? _client; @@ -75,34 +25,26 @@ private struct BtlBinFormation { private ArchipelagoFFXModule? _ffx_interop; public CaptureModule() { - const string GAME = "FFX.exe"; - _client_handle = new(this); _ffx_interop_handle = new(this); - - _MsMonsterCapture = new FhMethodHandle(this, GAME, __addr_MsMonsterCapture, h_MsMonsterCapture); - _FUN_00783bb0 = new FhMethodHandle(this, GAME, __addr_FUN_00783bb0, h_FUN_00783bb0); - _AtelEventSetUp = new FhMethodHandle(this, GAME, __addr_AtelEventSetUp, h_AtelEventSetUp); - _ret_hasKeyItem = new FhMethodHandle(this, GAME, __addr_ret_hasKeyItem, h_ret_hasKeyItem); - _MsDamageCheckDeath = new FhMethodHandle(this, GAME, __addr_MsDamageCheckDeath, h_MsDamageCheckDeath); - _MsSetRamChrParam = new FhMethodHandle(this, GAME, __addr_MsSetRamChrParam, h_MsSetRamChrParam); - _MsSetSaveParam = new FhMethodHandle(this, GAME, __addr_MsSetSaveParam, h_MsSetSaveParam); - _MsCalcCommand = new FhMethodHandle(this, GAME, __addr_MsCalcCommand, h_MsCalcCommand); - _MsBattleEncountExe = new FhMethodHandle(this, GAME, __addr_MsBattleEncountExe, h_MsBattleEncountExe); } + // Mars Sigil location check (Atel CT_RetInt hook); not yet a curated FhCall entry, so kept as a local handle. + private FhMethodHandle h_ret_hasKeyItem_handle + => new( new FhMethodLocation("FFX.exe", 0x45B7A0) ); + public override bool init(FhModContext mod_context, FileStream global_state_file) { return _client_handle.try_get_module(out _client) && _ffx_interop_handle.try_get_module(out _ffx_interop) - && _MsMonsterCapture.hook() - && _FUN_00783bb0.hook() - && _AtelEventSetUp.hook() - && _ret_hasKeyItem.hook() - && _MsDamageCheckDeath.hook() - && _MsSetRamChrParam.hook() - && _MsSetSaveParam.hook() - && _MsCalcCommand.hook() - && _MsBattleEncountExe.hook(); + && FhXCall.h_MsMonsterCapture.hook(this, h_MsMonsterCapture) + && FhXCall.h_FUN_00783bb0.hook(this, h_FUN_00783bb0) + && FhXCall.h_AtelEventSetUp.hook(this, h_AtelEventSetUp) + && h_ret_hasKeyItem_handle.hook(this, h_ret_hasKeyItem) + && FhXCall.h_MsDamageCheckDeath.hook(this, h_MsDamageCheckDeath) + && FhXCall.h_MsSetRamChrParam.hook(this, h_MsSetRamChrParam) + && FhXCall.h_MsSetSaveParam.hook(this, h_MsSetSaveParam) + && FhXCall.h_MsCalcCommand.hook(this, h_MsCalcCommand) + && FhXCall.h_MsBattleEncountExe.hook(this, h_MsBattleEncountExe); } private static void set(byte* code_ptr, uint offset, AtelInst[] opcodes) { @@ -122,7 +64,7 @@ private static void set(byte* code_ptr, uint[] offsets, AtelInst[] opcodes) { } private bool h_MsMonsterCapture(int target_id, int arena_idx) { - bool captured = _MsMonsterCapture.orig_fptr(target_id, arena_idx); + bool captured = FhXCall.h_MsMonsterCapture.chain_from(h_MsMonsterCapture).fnptr!(target_id, arena_idx); _logger.Info($"Fiend Capture: Target={target_id}, Arena Index={arena_idx}, Captured={captured}"); @@ -167,9 +109,9 @@ private void h_FUN_00783bb0(byte mon_idx) { byte num_initialized = FhUtil.get_at(0xD2CA80); if (num_initialized == 0) initialized_monsters.Clear(); - _FUN_00783bb0.orig_fptr(mon_idx); + FhXCall.h_FUN_00783bb0.chain_from(h_FUN_00783bb0).fnptr!(mon_idx); - Chr* mon = _MsGetMon(mon_idx); + Chr* mon = FhXCall.h_MsGetMon.fnptr!(mon_idx); if (initialized_monsters.Add(mon->chr_id)) { MonStats* stats = mon->ptr_base_stats; @@ -185,9 +127,9 @@ private void h_FUN_00783bb0(byte mon_idx) { private string? _event_name; private void h_AtelEventSetUp(int event_id) { - _AtelEventSetUp.orig_fptr(event_id); + FhXCall.h_AtelEventSetUp.chain_from(h_AtelEventSetUp).fnptr!(event_id); - _event_name = Marshal.PtrToStringAnsi((nint)get_event_name((uint)event_id))!; + _event_name = Marshal.PtrToStringAnsi((nint)FhXCall.h_AtelGetEventName.fnptr!((uint)event_id))!; _logger.Debug($"atel_event_setup: {_event_name}"); byte* code_ptr = Atel.controllers[0].worker(0)->code_ptr; @@ -225,11 +167,11 @@ private int h_ret_hasKeyItem(AtelBasicWorker* work, int* storage, AtelStack* ate } } - return _ret_hasKeyItem.orig_fptr(work, storage, atelStack); + return h_ret_hasKeyItem_handle.fnptr!(work, storage, atelStack); } - private int h_MsDamageCheckDeath(int attacker_id, int target_id, int param_3, uint param_4) { - Chr* target = _MsGetChr((uint)target_id); + private int h_MsDamageCheckDeath(int attacker_id, int target_id, int param_3, int param_4) { + Chr* target = FhXCall.h_MsGetChr.fnptr!(target_id); MonStats* mon_stats = target->ptr_base_stats; ushort capture_index = mon_stats is not null ? mon_stats->monster_arena_idx : (ushort)0xFF; @@ -243,13 +185,13 @@ private int h_MsDamageCheckDeath(int attacker_id, int target_id, int param_3, ui target->should_try_capture = true; } - return _MsDamageCheckDeath.orig_fptr(attacker_id, target_id, param_3, param_4); + return FhXCall.h_MsDamageCheckDeath.chain_from(h_MsDamageCheckDeath).fnptr!(attacker_id, target_id, param_3, param_4); } private void h_MsSetRamChrParam(uint chr_id) { - _MsSetRamChrParam.orig_fptr(chr_id); + FhXCall.h_MsSetRamChrParam.chain_from(h_MsSetRamChrParam).fnptr!(chr_id); - Chr* chr = _MsGetChr(chr_id); + Chr* chr = FhXCall.h_MsGetChr.fnptr!((int)chr_id); if (ArchipelagoFFXModule.seed.Options.AlwaysCapture == 1) { chr->ram.auto_ability_effects.has_capture = true; @@ -257,7 +199,7 @@ private void h_MsSetRamChrParam(uint chr_id) { } private void h_MsSetSaveParam(uint chr_id) { - _MsSetSaveParam.orig_fptr(chr_id); + FhXCall.h_MsSetSaveParam.chain_from(h_MsSetSaveParam).fnptr!(chr_id); // Does nothing?? if (ArchipelagoFFXModule.seed.Options.AlwaysCapture == 1) { @@ -266,19 +208,19 @@ private void h_MsSetSaveParam(uint chr_id) { } private void h_MsCalcCommand(AttackCue* param_1, int param_2) { - _MsCalcCommand.orig_fptr(param_1, param_2); + FhXCall.h_MsCalcCommand.chain_from(h_MsCalcCommand).fnptr!(param_1, param_2); if (param_1 == null) return; uint local_6c; - Command* command = _MsGetCommand(param_1->attacker_id, 0, -1, ¶m_1->command_list[param_2], &local_6c); + Command* command = FhXCall.h_MsGetCommand.fnptr!(param_1->attacker_id, 0, -1, ¶m_1->command_list[param_2], &local_6c); if (param_1->command_count <= param_2 || command == null) return; - Chr* attacker = _MsGetChr(param_1->attacker_id); + Chr* attacker = FhXCall.h_MsGetChr.fnptr!(param_1->attacker_id); int[] local_7c = [0, 0, 0, param_2]; if (command->absorbs_dmg) { - local_7c[2] = (int)_FUN_0078d100(attacker); + local_7c[2] = (int)FhXCall.h_FUN_0078d100.fnptr!(attacker); } //TODO: Figure out a way not to duplicate affection in _FUN_0078bb30 @@ -287,7 +229,7 @@ private void h_MsCalcCommand(AttackCue* param_1, int param_2) { fixed (byte* p_targets = targets) { fixed (byte* p_local_48 = local_48) { fixed (int* p_local_7c = local_7c) { - _FUN_0078bb30(param_1->attacker_id, p_targets, p_local_48, command, local_6c, ¶m_1->command_list[param_2].targets, p_local_7c + 1); + FhXCall.h_FUN_0078bb30.fnptr!(param_1->attacker_id, p_targets, p_local_48, command, local_6c, ¶m_1->command_list[param_2].targets, p_local_7c + 1); } } } @@ -295,8 +237,8 @@ private void h_MsCalcCommand(AttackCue* param_1, int param_2) { for (uint target_id = 0; target_id < 32; target_id++) { if (targets[target_id] != 0) { if (local_7c[2] == 0 || target_id != param_1->attacker_id) { - Chr* target = _MsGetChr(target_id); - uint iVar6 = _FUN_0078d100(target); + Chr* target = FhXCall.h_MsGetChr.fnptr!((int)target_id); + uint iVar6 = FhXCall.h_FUN_0078d100.fnptr!(target); if (iVar6 != 0) { if (attacker->ram.auto_ability_effects.has_capture && Battle.btl->battle_type == 0 && (ArchipelagoFFXModule.seed.Options.CaptureDamage > 0 || command->uses_weapon_properties)) { target->should_try_capture = true; @@ -314,19 +256,19 @@ private int get_monster_arena_idx(int monster_id) { byte[] filename = Encoding.UTF8.GetBytes($"host0:/ffx/master/jppc/battle/mon/_m{monster_id:D3}/m{monster_id:D3}.bin"); fixed (byte* filename_ptr = &filename[0]) { - void* filestream = _sceOpen(filename_ptr, 1); + void* filestream = FhXCall.h_sceOpen.fnptr!(filename_ptr, 1); if (filestream is null) { _logger.Info("Failed to open monster file"); return -1; } - int filesize = _sceLseek(filestream, 0, 2); - _sceLseek(filestream, 0, 0); + int filesize = FhXCall.h_sceLseek.fnptr!(filestream, 0, 2); + FhXCall.h_sceLseek.fnptr!(filestream, 0, 0); void* file = NativeMemory.Alloc((nuint)filesize); - _sceRead(filestream, file, filesize); - _sceClose(filestream); + FhXCall.h_sceRead.fnptr!(filestream, file, filesize); + FhXCall.h_sceClose.fnptr!(filestream); int stats_offset = *(int*)((int)file + 0xC); MonStats* mon_stats = (MonStats*)((int)file + stats_offset); @@ -524,16 +466,16 @@ private int get_extra_weight_for_formation(BtlBinField* field, BtlBinFormation f float extra_weight = 0.0f; fixed (byte* filepath_ptr = &filepath[0]) { - void* open_result = _sceOpen(filepath_ptr, 1); + void* open_result = FhXCall.h_sceOpen.fnptr!(filepath_ptr, 1); if (open_result is null) return 0; - int file_size = _sceLseek(open_result, 0, 2); - _sceLseek(open_result, 0, 0); + int file_size = FhXCall.h_sceLseek.fnptr!(open_result, 0, 2); + FhXCall.h_sceLseek.fnptr!(open_result, 0, 0); void* file = NativeMemory.Alloc((nuint)file_size); - _sceRead(open_result, file, file_size); - _sceClose(open_result); + FhXCall.h_sceRead.fnptr!(open_result, file, file_size); + FhXCall.h_sceClose.fnptr!(open_result); int chunk_ptr = *(int*)((nint)file + 0xC); if (chunk_ptr != 0) { @@ -582,7 +524,7 @@ private int get_extra_weight_for_formation(BtlBinField* field, BtlBinFormation f private int h_MsBattleEncountExe(int field_id, int group_idx, float walked_delta) { if (ArchipelagoFFXModule.seed.Options.CaptureRequirement == 0 || ArchipelagoFFXModule.seed.Options.EncounterWeighting == 0) { - return _MsBattleEncountExe.orig_fptr(field_id, group_idx, walked_delta); + return FhXCall.h_MsBattleEncountExe.chain_from(h_MsBattleEncountExe).fnptr!(field_id, group_idx, walked_delta); } // Globals @@ -598,14 +540,14 @@ private int h_MsBattleEncountExe(int field_id, int group_idx, float walked_delta // _logger.Info($" g_encounter_level = {*g_encounter_level}"); // _logger.Info($" EnableBattle = {*EnableBattle}"); - int field_idx = _MsBtlListFieldNum(field_id); + int field_idx = FhXCall.h_MsBtlListFieldNum.fnptr!(field_id); if (*g_keybattle != 0 && *g_keydown_R != 0) { Battle.btl->group_idx = (byte)group_idx; Battle.btl->formation_idx = (byte)*DAT_0112ca28; *(byte*)((nint)Battle.btl + 0x12) = 1; Battle.btl->field_idx = (ushort)field_idx; - _ResetEncountExe(1); + FhXCall.h_ResetEncountExe.fnptr!(1); return -1; } @@ -627,15 +569,15 @@ private int h_MsBattleEncountExe(int field_id, int group_idx, float walked_delta if (field_idx < 0) return 0; if (walked_delta <= 0.0f || !can_encounter) return 0; - BtlBinField* field = _MsBtlListField(field_idx); - BtlBinEncounter* encounter = _MsBtlListEncount(field_idx); + BtlBinField* field = FhXCall.h_MsBtlListField.fnptr!(field_idx); + BtlBinEncounter* encounter = FhXCall.h_MsBtlListEncount.fnptr!(field_idx); // _logger.Info($" encounter->group_count: {encounter->group_count}"); if (group_idx < 0 || group_idx >= encounter->group_count) return 0; if (*EnableBattle == 0) return 0; - BtlBinGroup* group = _MsBtlListGroup(field_idx, group_idx); + BtlBinGroup* group = FhXCall.h_MsBtlListGroup.fnptr!(field_idx, group_idx); if (group->grace == 0 || group->total_weight == 0 || group->formation_count == 0) return 0; @@ -656,7 +598,7 @@ private int h_MsBattleEncountExe(int field_id, int group_idx, float walked_delta *(float*)((nint)Battle.btl + 0x110) *= 256.0f - encounter_chance; *(float*)((nint)Battle.btl + 0x114) *= 256.0f; - if ((_brnd(0) & 0xFF) >= encounter_chance) continue; + if ((FhXCall.h_brnd.fnptr!(0) & 0xFF) >= encounter_chance) continue; // We have to prepare weights first int total_weight = group->total_weight; @@ -700,7 +642,7 @@ private int h_MsBattleEncountExe(int field_id, int group_idx, float walked_delta } // Let's figure out which formation we should encounter! - int formation_rng = _brnd(1) % total_weight; + int formation_rng = FhXCall.h_brnd.fnptr!(1) % total_weight; int iVar7 = 0; _logger.Debug( "Encounter!"); @@ -716,14 +658,14 @@ private int h_MsBattleEncountExe(int field_id, int group_idx, float walked_delta if (*(byte*)((nint)Battle.btl + 0x27) == 0) { *(byte*)((nint)Battle.btl + 0x12) = 1; } else { - _Sg_FadeInW(3); + FhXCall.h_Sg_FadeInW.fnptr!(3); save_data->battle_count += 1; } Battle.btl->field_idx = (ushort)field_idx; Battle.btl->group_idx = (byte)group_idx; Battle.btl->formation_idx = (byte)formation_idx; - _ResetEncountExe(1); + FhXCall.h_ResetEncountExe.fnptr!(1); return -1; } diff --git a/src/modules/deathlink.cs b/src/modules/deathlink.cs index d748eaa..d27bea0 100644 --- a/src/modules/deathlink.cs +++ b/src/modules/deathlink.cs @@ -13,6 +13,8 @@ using Fahrenheit.FFX.Battle; using Fahrenheit.FFX.Ids; +using FhXCall = Fahrenheit.FFX.FhCall; + namespace ArchipelagoFFX; [FhLoad(FhGameId.FFX)] @@ -55,12 +57,6 @@ public DeathLinkModule() { _client_handle = new(this); _toasts_handle = new(this); - - const string GAME = "FFX.exe"; - - _MsBtlReadManage = new(this, GAME, __addr_MsBtlReadManage, _h_MsBtlReadManage); - _MsDamageCheckDeath = new(this, GAME, __addr_MsDamageCheckDeath, _h_MsDamageCheckDeath); - _MsGetBattleEndStatus = new(this, GAME, __addr_MsGetBattleEndStatus, _h_MsGetBattleEndStatus); } public bool get_enabled() { @@ -143,9 +139,9 @@ public void debug_apply_deathlink() { public override bool init(FhModContext mod_context, FileStream global_state_file) { return _client_handle.try_get_module(out _client) && _toasts_handle.try_get_module(out _toasts) - && _MsBtlReadManage.hook() - && _MsDamageCheckDeath.hook() - && _MsGetBattleEndStatus.hook(); + && FhXCall.h_MsBtlReadManage.hook(this, _h_MsBtlReadManage) + && FhXCall.h_MsDamageCheckDeath.hook(this, _h_MsDamageCheckDeath) + && FhXCall.h_MsGetBattleEndStatus.hook(this, _h_MsGetBattleEndStatus); } private void apply_death_link() { @@ -210,7 +206,7 @@ private void apply_death_link() { private void _h_MsBtlReadManage() { int old_state = Globals.Battle.btl->battle_state; - _MsBtlReadManage.orig_fptr(); + FhXCall.h_MsBtlReadManage.chain_from(_h_MsBtlReadManage).fnptr!(); if (Globals.Battle.btl->battle_state != 13 || old_state == Globals.Battle.btl->battle_state) return; @@ -229,13 +225,13 @@ private void _h_MsBtlReadManage() { apply_death_link(); - _MsMessageCueRegist(MessageCueType.FH_CUSTOM, (int)_deathlink_announcement.encoded, 0, 27, 35); + FhXCall.h_MsMessageCueRegist.fnptr!((uint)MessageCueType.FH_CUSTOM, (int)_deathlink_announcement.encoded, 0, 27, 35); _logger.Info(" Disabling Escape and Flee..."); for (int chr_id = 0; chr_id <= PlySaveId.PC_SEYMOUR; chr_id++) { - _set_command_disabled(chr_id, PlayerCommandId.PCOM_ESCAPE, 1); - _set_command_disabled(chr_id, PlayerCommandId.PCOM_FLEE, 1); + FhXCall.h_FUN_0079b480.fnptr!(chr_id, PlayerCommandId.PCOM_ESCAPE, 1); + FhXCall.h_FUN_0079b480.fnptr!(chr_id, PlayerCommandId.PCOM_FLEE, 1); } _deathlinks_queued -= 1; @@ -244,7 +240,7 @@ private void _h_MsBtlReadManage() { } private int _h_MsDamageCheckDeath(int attacker_id, int target_id, int p3, int targetting_self) { - int result = _MsDamageCheckDeath.orig_fptr(attacker_id, target_id, p3, targetting_self); + int result = FhXCall.h_MsDamageCheckDeath.chain_from(_h_MsDamageCheckDeath).fnptr!(attacker_id, target_id, p3, targetting_self); if (result == 0 || target_id > PlySaveId.PC_MAGUS3) { return result; @@ -260,7 +256,7 @@ private int _h_MsDamageCheckDeath(int attacker_id, int target_id, int p3, int ta string player = _client!.active_player?.Alias ?? "Someone"; - Chr* target = _MsGetChr(target_id); + Chr* target = FhXCall.h_MsGetChr.fnptr!(target_id); byte[] decoded = new byte[FhEncoding.compute_decode_buffer_size(target->ram.name, null, null, FhEncodingFlags.IMPLICIT_END)]; FhEncoding.decode(target->ram.name, decoded, null, null, FhEncodingFlags.IMPLICIT_END); string target_name = Encoding.UTF8.GetString(decoded); @@ -284,7 +280,7 @@ private int _h_MsDamageCheckDeath(int attacker_id, int target_id, int p3, int ta } private uint _h_MsGetBattleEndStatus() { - uint battle_end_type = _MsGetBattleEndStatus.orig_fptr(); + uint battle_end_type = FhXCall.h_MsGetBattleEndStatus.chain_from(_h_MsGetBattleEndStatus).fnptr!(); if (!_deathlink_enabled || battle_end_type != 1 || Globals.Battle.btl->battle_state != 0x17) { return battle_end_type; diff --git a/src/modules/hardcore_contest.cs b/src/modules/hardcore_contest.cs index 83f4c83..b84c9ee 100644 --- a/src/modules/hardcore_contest.cs +++ b/src/modules/hardcore_contest.cs @@ -1,26 +1,18 @@ using System.IO; -using System.Runtime.InteropServices; using Fahrenheit; using Fahrenheit.FFX; using Fahrenheit.FFX.Ids; +using FhGCall = Fahrenheit.FhCall; +using FhXCall = Fahrenheit.FFX.FhCall; + namespace ArchipelagoFFX; [FhLoad(FhGameId.FFX)] public unsafe partial class HardcoreDreamsEndModule : FhModule { - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void MsBtlReadManage(); - public const nint __addr_MsBtlReadManage = 0x3830d0; - private bool _hardcore_dreams_end_enabled; - private FhMethodHandle _MsBtlReadManage; - - public HardcoreDreamsEndModule() { - _MsBtlReadManage = new(this, "FFX.exe", __addr_MsBtlReadManage, _h_MsBtlReadManage); - } - public bool get_enabled() { return _hardcore_dreams_end_enabled; } @@ -30,13 +22,13 @@ public void set_enabled(bool enabled) { } public override bool init(FhModContext mod_context, FileStream global_state_file) { - return _MsBtlReadManage.hook(); + return FhXCall.h_MsBtlReadManage.hook(this, _h_MsBtlReadManage); } private void _h_MsBtlReadManage() { int old_state = Globals.Battle.btl->battle_state; - _MsBtlReadManage.orig_fptr(); + FhXCall.h_MsBtlReadManage.chain_from(_h_MsBtlReadManage).fnptr!(); if (Globals.Battle.btl->battle_state != 13 || old_state == Globals.Battle.btl->battle_state) return; diff --git a/src/modules/sphere_grid.cs b/src/modules/sphere_grid.cs index a2ce483..c15e242 100644 --- a/src/modules/sphere_grid.cs +++ b/src/modules/sphere_grid.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.IO; -using System.Runtime.InteropServices; using System.Text; using Fahrenheit; @@ -11,43 +10,18 @@ using static Fahrenheit.FFX.Globals; +using FhGCall = Fahrenheit.FhCall; +using FhXCall = Fahrenheit.FFX.FhCall; + namespace ArchipelagoFFX; [FhLoad(FhGameId.FFX)] public unsafe class SphereGridQolModule : FhModule { - // Delegates for handles - //TODO: Remove these once FhCall is more up-to-date - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void abmap_get_panel(int ply_id, int node_idx); - public const nint __addr_abmap_get_panel = 0x6458a0; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void abmap_ctrl(); - public const nint __addr_AbmapState_MovingToTarget = 0x659990; - public const nint __addr_AbmapState_ChangingNode = 0x647d50; - public const nint __addr_AbmapState_Warping = 0x647f00; - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void abmap_confirm_move(int p1, int p2, int p3); - public const nint __addr_FUN_00a56160 = 0x656160; - // Sound IDs private const uint SND_PREFIX = 0x80000000; public const uint SND_ACTIVATE_NODE = 0x50 | SND_PREFIX; public const uint SND_DEACTIVATE_NODE = 0x6e | SND_PREFIX; - // Method handles - private readonly FhMethodHandle _sphere_grid_move_speed; - private readonly FhMethodHandle _sphere_grid_confirm_move; - private readonly FhMethodHandle _sphere_grid_state_moving; - private readonly FhMethodHandle _sphere_grid_state_warping; - private readonly FhMethodHandle _sphere_grid_change_node; - - // Function pointers - //TODO: Move this into a library common between modules - private static delegates.SndSepPlaySimple _SndSepPlaySimple = FhUtil.get_fptr(delegates.__addr_SndSepPlaySimple); - private readonly abmap_get_panel _abmap_get_panel = FhUtil.get_fptr(__addr_abmap_get_panel); - // Fahrenheit-related private FhModContext? _mod_context; private FileStream? _global_state; @@ -60,25 +34,15 @@ public unsafe class SphereGridQolModule : FhModule { private static readonly HashSet temporarily_activated_nodes = []; - public SphereGridQolModule() { - const string GAME = "FFX.exe"; - - _sphere_grid_move_speed = new(this, GAME, __addr_AbmapState_MovingToTarget, h_move_speed); - _sphere_grid_confirm_move = new(this, GAME, __addr_FUN_00a56160, h_move_confirm); - _sphere_grid_state_moving = new(this, GAME, __addr_AbmapState_MovingToTarget, h_state_moving); - _sphere_grid_state_warping = new(this, GAME, __addr_AbmapState_Warping, h_state_warping); - _sphere_grid_change_node = new(this, GAME, __addr_AbmapState_ChangingNode, h_change_node); - } - public override bool init(FhModContext mod_context, FileStream global_state_file) { _mod_context = mod_context; _global_state = global_state_file; - return _sphere_grid_move_speed.hook() - && _sphere_grid_confirm_move.hook() - && _sphere_grid_state_moving.hook() - && _sphere_grid_state_warping.hook() - && _sphere_grid_change_node.hook(); + return FhXCall.h_AbmapState_MovingToTarget.hook(this, h_move_speed) + && FhXCall.h_abmap_confirm_move.hook(this, h_move_confirm) + && FhXCall.h_AbmapState_MovingToTarget.hook(this, h_state_moving) + && FhXCall.h_AbmapState_Warping.hook(this, h_state_warping) + && FhXCall.h_AbmapState_ChangingNode.hook(this, h_change_node); } private string get_state_name() { @@ -233,12 +197,12 @@ private void render_node_info() { if (ImGui.Button(activated ? $"Deactivate##{i}" : $"Activate##{i}")) { if (activated) { selected_node->activated_by.set_bit(i, false); - _SndSepPlaySimple(SND_DEACTIVATE_NODE); + FhXCall.h_SndSepPlaySimple.fnptr!(SND_DEACTIVATE_NODE); lpamng->should_update = 1; lpamng->should_update_node = lpamng->selected_node_idx; } else { - _abmap_get_panel(i, lpamng->selected_node_idx); + FhXCall.h_abmap_get_panel.fnptr!(i, lpamng->selected_node_idx); } } } @@ -256,7 +220,7 @@ public void h_move_speed() { float prev_t = lpamng->moving_progress; - _sphere_grid_move_speed.orig_fptr(); + FhXCall.h_AbmapState_MovingToTarget.chain_from(h_move_speed).fnptr!(); if (freeze_move) { lpamng->moving_progress = prev_t; @@ -310,7 +274,7 @@ private bool try_activate(short node_idx, int ply_id, bool temporary) { } node->activated_by.set_bit(ply_id, true); - _SndSepPlaySimple(SND_ACTIVATE_NODE); + FhXCall.h_SndSepPlaySimple.fnptr!(SND_ACTIVATE_NODE); if (temporary) { temporarily_activated_nodes.Add(node_idx); @@ -344,7 +308,7 @@ public void h_move_confirm(int p1, int p2, int p3) { knots_counted = 0; - _sphere_grid_confirm_move.orig_fptr(p1, p2, p3); + FhXCall.h_abmap_confirm_move.chain_from(h_move_confirm).fnptr!(p1, p2, p3); // If we cancelled it, also deactivate all activated nodes if (p3 == 1 && temporarily_activated_nodes.Count > 0) { @@ -354,7 +318,7 @@ public void h_move_confirm(int p1, int p2, int p3) { lpamng->nodes[node_idx].activated_by.set_bit(chr_id, false); } - _SndSepPlaySimple(SND_DEACTIVATE_NODE); + FhXCall.h_SndSepPlaySimple.fnptr!(SND_DEACTIVATE_NODE); lpamng->should_update = 1; lpamng->should_update_node = -1; @@ -369,7 +333,7 @@ public void h_state_moving() { float prev_t = lpamng->moving_progress; short last_knot = lpamng->move_next_target_node_idx; - _sphere_grid_state_moving.orig_fptr(); + FhXCall.h_AbmapState_MovingToTarget.chain_from(h_state_moving).fnptr!(); float current_t = lpamng->moving_progress; @@ -396,7 +360,7 @@ public void h_state_warping() { byte last_warp_state = *(byte*)((int)lpamng + 0x1164c); - _sphere_grid_state_warping.orig_fptr(); + FhXCall.h_AbmapState_Warping.chain_from(h_state_warping).fnptr!(); // Warp states: // 0 == Disappearing @@ -432,7 +396,7 @@ public void h_change_node() { short node_idx = *(short*)((int)lpamng + 0x1164e); byte ply_id = lpamng->current_chr_id; - _sphere_grid_change_node.orig_fptr(); + FhXCall.h_AbmapState_ChangingNode.chain_from(h_change_node).fnptr!(); byte timing = *(byte*)((int)lpamng + 0x11650); From e29ac1ffa0566e722e5ecaede9c6245bd10fcf75 Mon Sep 17 00:00:00 2001 From: Andrew K Date: Wed, 10 Jun 2026 13:54:45 +1000 Subject: [PATCH 07/20] h_MsSaveItemUse --- src/hooks.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hooks.cs b/src/hooks.cs index 47db251..7e2cff9 100644 --- a/src/hooks.cs +++ b/src/hooks.cs @@ -2832,7 +2832,7 @@ private uint h_give_item(uint item_id, int amount) { amount -= excess; } - return FhXCall.h_FUN_007905a0.chain_from(h_give_item).fnptr!(item_id, amount); + return FhXCall.h_MsSaveItemUse.chain_from(h_give_item).fnptr!(item_id, amount); } private void h_TkMsImportantSet(uint param_1) { From 8243384295a694ea198c0521b6786d742902b3e0 Mon Sep 17 00:00:00 2001 From: Andrew K Date: Wed, 10 Jun 2026 14:15:19 +1000 Subject: [PATCH 08/20] h_give_item return type --- src/hooks.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/hooks.cs b/src/hooks.cs index 7e2cff9..067b126 100644 --- a/src/hooks.cs +++ b/src/hooks.cs @@ -2821,7 +2821,7 @@ public int h_MsBtlGetPos(int param_1, Chr* chr, int btl_pos_a, int btl_pos_b, in return FhXCall.h_MsBtlGetPos.chain_from(h_MsBtlGetPos).fnptr!(param_1, chr, btl_pos_a, btl_pos_b, btl_pos_c, out_pos); } - private uint h_give_item(uint item_id, int amount) { + private void h_give_item(uint item_id, int amount) { _logger.Debug($"give_item: {amount} x {item_id}"); int new_amount = (int)(save_data->get_item_count((int)item_id) + amount); @@ -2832,7 +2832,8 @@ private uint h_give_item(uint item_id, int amount) { amount -= excess; } - return FhXCall.h_MsSaveItemUse.chain_from(h_give_item).fnptr!(item_id, amount); + FhXCall.h_MsSaveItemUse.chain_from(h_give_item).fnptr!(item_id, amount); + return; } private void h_TkMsImportantSet(uint param_1) { From 2d955595fdd1b7b549c495a23bf3f991afa1809a Mon Sep 17 00:00:00 2001 From: evelyntsmg Date: Wed, 10 Jun 2026 12:02:18 +0200 Subject: [PATCH 09/20] Add missing custom call target --- src/hooks.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hooks.cs b/src/hooks.cs index b692ad8..0c225a6 100644 --- a/src/hooks.cs +++ b/src/hooks.cs @@ -488,6 +488,7 @@ private void init_custom_atel() { CT_RetInt_IsCharacterUnlocked, CT_RetInt_HasCelestialWeapon, CT_RetInt_IsOtherLocationChecked, + CT_RetInt_IsTreasureLocationChecked, CT_RetInt_CollectedPrimers, CT_RetInt_SendOtherLocation, CT_RetInt_SendPartyMemberLocation, From efd9380495c024a623f0c0b66c56df31d59e4d14 Mon Sep 17 00:00:00 2001 From: evelyntsmg Date: Wed, 10 Jun 2026 12:26:11 +0200 Subject: [PATCH 10/20] Fix being able to connect twice by quickly doubleclicking the button --- src/client/client.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/client/client.cs b/src/client/client.cs index feb589a..2837a2a 100644 --- a/src/client/client.cs +++ b/src/client/client.cs @@ -63,6 +63,7 @@ public override bool init(FhModContext mod_context, FileStream global_state_file && _death_link_handle.try_get_module(out _death_link); } + private bool _connecting = false; public async Task Connect(string server, string user, string password) { _logger.Debug("Connect"); LoginResult? login_result = new LoginFailure(""); @@ -71,6 +72,9 @@ public async Task Connect(string server, string user, string password) { if (is_disconnecting) return; + if (_connecting) return; // Already connecting, so don't attempt to connect twice at the same time + _connecting = true; + try { session = ArchipelagoSessionFactory.CreateSession(server); death_link = session.CreateDeathLinkService(); @@ -78,8 +82,7 @@ public async Task Connect(string server, string user, string password) { var roomInfoPacket = await session.ConnectAsync(); login_result = await session.LoginAsync("Final Fantasy X", user, ItemsHandlingFlags.RemoteItems, Version.Parse("0.6.0"), password: password, requestSlotData: true); - } - catch (Exception e) { + } catch (Exception e) { login_result = new LoginFailure(e.GetBaseException().Message); } @@ -92,6 +95,7 @@ public async Task Connect(string server, string user, string password) { foreach (ConnectionRefusedError error in failure.ErrorCodes) { errorMessage += $"\n {error}"; } + _connecting = false; current_session = null; _logger.Error(errorMessage); return; // Did not connect, show the user the contents of `errorMessage` @@ -104,6 +108,7 @@ public async Task Connect(string server, string user, string password) { _gui!.add_log_message([(message, Color.Red)]); _logger.Error(message); disconnect(session); + _connecting = false; return; } ArchipelagoFFXModule.SeedToServer[ArchipelagoFFXModule.seed.Options.SeedId] = server; @@ -120,6 +125,7 @@ public async Task Connect(string server, string user, string password) { current_server = server; current_session = session; current_death_link_service = death_link; + _connecting = false; } public void disconnect(ArchipelagoSession? session = null) { From 3be95acd3b1058b78050c762b95b0f568ae3e21d Mon Sep 17 00:00:00 2001 From: Andrew K Date: Wed, 17 Jun 2026 15:25:48 +1000 Subject: [PATCH 11/20] Updated to latest from Fh PR + Error Resolutions --- src/archipelago.cs | 16 +-- src/customization.cs | 50 +++---- src/gui/debugWindow.cs | 2 +- src/hooks.cs | 297 ++++++++++++++++++++++++++-------------- src/modules/captures.cs | 6 +- 5 files changed, 230 insertions(+), 141 deletions(-) diff --git a/src/archipelago.cs b/src/archipelago.cs index ca16e0e..26614bd 100644 --- a/src/archipelago.cs +++ b/src/archipelago.cs @@ -863,7 +863,7 @@ public void call_warp_to_map(int map_id, int entrance_id) { int work = 0; int storage = 0; - h_Common_warpToMap((AtelBasicWorker*)&work, &storage, &stack); + Common_warpToMap((AtelBasicWorker*)&work, &storage, &stack); } public void call_remove_party_member(int character_id, bool long_term = false) { @@ -873,8 +873,8 @@ public void call_remove_party_member(int character_id, bool long_term = false) { int work = 0; int storage = 0; - if (!long_term) h_Common_removePartyMember((AtelBasicWorker*)&work, &storage, &stack); - else h_Common_removePartyMemberLongTerm((AtelBasicWorker*)&work, &storage, &stack); + if (!long_term) Common_removePartyMember((AtelBasicWorker*)&work, &storage, &stack); + else Common_removePartyMemberLongTerm((AtelBasicWorker*)&work, &storage, &stack); } public void call_add_party_member(int character_id) { @@ -884,7 +884,7 @@ public void call_add_party_member(int character_id) { int work = 0; int storage = 0; - h_Common_addPartyMember((AtelBasicWorker*)&work, &storage, &stack); + Common_addPartyMember((AtelBasicWorker*)&work, &storage, &stack); } public void call_put_party_member_in_slot(int slot, int character_id) { @@ -895,7 +895,7 @@ public void call_put_party_member_in_slot(int slot, int character_id) { int work = 0; int storage = 0; - h_Common_putPartyMemberInSlot((AtelBasicWorker*)&work, &storage, &stack); + Common_putPartyMemberInSlot((AtelBasicWorker*)&work, &storage, &stack); } public uint[] get_party_frontline() { @@ -1007,9 +1007,9 @@ public void set_character_model(int chr_id) { stack.push_int(chr_id + 1); AtelBasicWorker* worker0 = Atel.controllers[0].worker(0); int storage = 0; - FhXCall.h_Common_loadModel.fnptr!(worker0, &storage, &stack); + h_Common_loadModel.fnptr!(worker0, &storage, &stack); stack.push_int(0); - FhXCall.h_Common_linkFieldToBattleActor.fnptr!(worker0, &storage, &stack); + h_Common_linkFieldToBattleActor.fnptr!(worker0, &storage, &stack); } public uint allocate_file(string filename, out nint file_ptr) { @@ -1026,7 +1026,7 @@ public uint allocate_file(string filename, out nint file_ptr) { var file_length = *(long*)(*(int*)(fileStream[1] + 0xc) + 8); file_ptr = Marshal.AllocHGlobal((int)file_length); uint max_len = (uint)file_length; - readBytes = FhXCall.h_readFile.fnptr!((nint)fs, file_ptr, max_len); + readBytes = FhXCall.h_Phyre_PSerialization_PStreamFileWin32_readFile.fnptr!((nint)fs, file_ptr, max_len); } _logger.Debug($"read {readBytes}, beginning={((byte*)file_ptr)[0]} {((byte*)file_ptr)[1]} {((byte*)file_ptr)[2]} {((byte*)file_ptr)[3]}"); return readBytes; diff --git a/src/customization.cs b/src/customization.cs index 8f7511a..d6df3c1 100644 --- a/src/customization.cs +++ b/src/customization.cs @@ -65,7 +65,7 @@ public void PrepareMenuList_SetLength(uint added, uint skipped) { } } - public void h_PrepareMenuList(MenuList menu_list_id, Equipment* gear) { + public void PrepareMenuList(TkMenuItemListId menu_list_id, Equipment* gear) { //MenuList menu_list_id = (MenuList)menu_list_id_raw; _logger.Info($"{menu_list_id}"); @@ -73,7 +73,7 @@ public void h_PrepareMenuList(MenuList menu_list_id, Equipment* gear) { uint[] ability_group_idxs = new uint[4]; uint[] ability_group_levels = new uint[4]; - if (menu_list_id == MenuList.GEAR_CUSTOMIZATION) { + if (menu_list_id == TkMenuItemListId.GEAR_CUSTOMIZATION) { // Modify kaizou.bin int num_customizations; CustomizationRecipe* customizations = FhXCall.h_MsGetRomKaizou.fnptr!(&num_customizations); @@ -207,10 +207,10 @@ public void h_PrepareMenuList(MenuList menu_list_id, Equipment* gear) { // Set length PrepareMenuList_SetLength(added, skipped); - } else if (menu_list_id == MenuList.AEON_ABILITIES) { + } else if (menu_list_id == TkMenuItemListId.AEON_ABILITIES) { // TODO: Modify sum_grow.bin int num_customizations; - CustomizationRecipe* customizations = FhXCall.h_MsGetRomSummonGrow.fnptr!(&num_customizations); + AeonAbilityRecipe* customizations = FhXCall.h_MsGetRomSummonGrow.fnptr!(&num_customizations); num_customizations = FhXCall.h_TkMn2GetSummonGrowMax.fnptr!(); if (original_sum_grow_costs == null) { original_sum_grow_costs = new ushort[num_customizations]; @@ -240,21 +240,21 @@ public void h_PrepareMenuList(MenuList menu_list_id, Equipment* gear) { uint added = 0; if (0 < num_customizations) { for (byte customization_id = 0; customization_id < num_customizations; customization_id++) { - CustomizationRecipe customization = customizations[customization_id]; - ushort auto_ability_id = customization.auto_ability; + AeonAbilityRecipe customization = customizations[customization_id]; + short auto_ability_id = customization.command; menu_list_iter->customization_id = 0xff; - bool has_command = FhXCall.h_MsGetSaveCommand.fnptr!(current_summon, auto_ability_id) != 0; + bool has_command = FhXCall.h_MsGetSaveCommand.fnptr!(current_summon, (uint)auto_ability_id) != 0; if (!has_command) { uint item_count = Globals.save_data->get_item_count(customization.item); if (item_count == 0 && customization.item_cost != 0) { continue; } else { - menu_list_iter->a_ability_id = auto_ability_id; + menu_list_iter->a_ability_id = (ushort)auto_ability_id; menu_list_iter->customization_id = customization_id; if (item_count < customization.item_cost) { menu_list_iter->status = CustomizationStatusEnum.AEON_NOT_ENOUGH_ITEMS; - } else if (((int)customization.target_gear_type & (1 << (current_summon - 8))) == 0 && !has_key_item) { + } else if ((0x7F & (1 << (current_summon - 8))) == 0 && !has_key_item) { // Never reached because both conditions are always false: Bit is set for all Aeons (always 0x7F) and key item is unused. menu_list_iter->status = CustomizationStatusEnum.AEON_CANNOT_LEARN_WITHOUT_KEY; } else { @@ -262,7 +262,7 @@ public void h_PrepareMenuList(MenuList menu_list_id, Equipment* gear) { } } } else { - menu_list_iter->a_ability_id = auto_ability_id; + menu_list_iter->a_ability_id = (ushort)auto_ability_id; menu_list_iter->customization_id = customization_id; menu_list_iter->status = CustomizationStatusEnum.AEON_ALREADY_LEARNED; } @@ -275,7 +275,7 @@ public void h_PrepareMenuList(MenuList menu_list_id, Equipment* gear) { // Set length PrepareMenuList_SetLength(added, 0); } else { - FhXCall.h_PrepareMenuList.chain_from(h_PrepareMenuList).fnptr!(menu_list_id, gear); + FhXCall.h_FUN_008c2370.chain_from(PrepareMenuList).fnptr!(menu_list_id, gear); } @@ -298,7 +298,7 @@ public void h_PrepareMenuList(MenuList menu_list_id, Equipment* gear) { /// 6: Calls TkMenuRestartSelFileWindow, then ??? and goes to 7 /// /// - public void h_UpdateGearCustomizationMenuState(TkWindow* window) { + public void UpdateGearCustomizationMenuState(TkWindow* window) { uint* state = FhUtil.ptr_at(0x146AA28); uint pre_state = *state; @@ -500,7 +500,7 @@ public void h_UpdateGearCustomizationMenuState(TkWindow* window) { break; default: - FhXCall.h_UpdateGearCustomizationMenuState.chain_from(h_UpdateGearCustomizationMenuState).fnptr!(window); + FhXCall.h_UpdateGearCustomizationMenuState.chain_from(UpdateGearCustomizationMenuState).fnptr!(window); break_loop = true; break; } @@ -543,12 +543,12 @@ public void h_UpdateGearCustomizationMenuState(TkWindow* window) { } // param_1 is TkMenu* - public void h_UpdateAeonCustomizationMenuState(uint param_1, uint param_2) { - uint* state = (uint*)(param_1 + 0x1c); + public void TkMenuCtrlSummon(TkMenu* menu, int param_2) { + uint* state = (uint*)(menu->state); uint pre_state = *state; - FhXCall.h_UpdateAeonCustomizationMenuState.chain_from(h_UpdateAeonCustomizationMenuState).fnptr!(param_1, param_2); + FhXCall.h_TkMenuCtrlSummon.chain_from(TkMenuCtrlSummon).fnptr!(menu, param_2); if (*state != pre_state) { _logger.Debug($"{pre_state} -> {*state}"); @@ -559,14 +559,14 @@ public void h_UpdateAeonCustomizationMenuState(uint param_1, uint param_2) { CustomizationMenuList* menu_list = FhUtil.ptr_at(0x1197730); byte customization_id = menu_list[selected_idx].customization_id; int num_customizations; - CustomizationRecipe* customizations = FhXCall.h_MsGetRomSummonGrow.fnptr!(&num_customizations); + AeonAbilityRecipe* customizations = FhXCall.h_MsGetRomSummonGrow.fnptr!(&num_customizations); _logger.Debug($"Applied customization {get_other_item_name((uint)(0xC07D + customization_id))}"); if (customizations[customization_id].item_cost != original_sum_grow_costs[customization_id]) { uint item_id = (uint)(0xC07D + customization_id); other_inventory.TryGetValue(item_id, out int count); if (--count <= 0) { other_inventory.Remove(item_id); - customizations[customization_id].item_cost = original_sum_grow_costs[customization_id]; + customizations[customization_id].item_cost = (byte)original_sum_grow_costs[customization_id]; } else other_inventory[item_id] = count; } } @@ -577,14 +577,14 @@ public void h_UpdateAeonCustomizationMenuState(uint param_1, uint param_2) { public static ManagedCustomString customization_string = new("Free!"); - public void h_DrawGearCustomizationMenu(TkWindow* window) { - //FhXCall.h_DrawGearCustomizationMenu.chain_from(h_DrawGearCustomizationMenu).fnptr!(param_1); + public void DrawGearCustomizationMenu(TkWindow* window) { + //FhXCall.DrawGearCustomizationMenu.chain_from(DrawGearCustomizationMenu).fnptr!(param_1); DrawGearCustomizationMenu_reimplement(window); return; } - public void h_DrawAeonCustomizationMenu(TkWindow* window) { - //FhXCall.h_DrawAeonCustomizationMenu.chain_from(h_DrawAeonCustomizationMenu).fnptr!(param_1); + public void DrawAeonCustomizationMenu(TkWindow* window) { + //FhXCall.DrawAeonCustomizationMenu.chain_from(DrawAeonCustomizationMenu).fnptr!(param_1); DrawAeonCustomizationMenu_reimplement(window); } @@ -605,7 +605,7 @@ public void DrawAeonCustomizationMenu_reimplement(TkWindow* window) { } else { byte customization_id = menu_list[selected_idx].customization_id; int num_customizations; - CustomizationRecipe* customizations = FhXCall.h_MsGetRomSummonGrow.fnptr!(&num_customizations); + AeonAbilityRecipe* customizations = FhXCall.h_MsGetRomSummonGrow.fnptr!(&num_customizations); item_id = customizations[customization_id].item; int item_cost = customizations[customization_id].item_cost; @@ -764,7 +764,7 @@ private void FUN_008cd960_Extra(TkWindow* window, int param_2, int menu_offset, if (0 <= curr_index && curr_index < menu_length) { if (menu_list[curr_index].customization_id != 0xFF) { int num_customizations; - CustomizationRecipe* customizations = FhXCall.h_MsGetRomSummonGrow.fnptr!(&num_customizations); + AeonAbilityRecipe* customizations = FhXCall.h_MsGetRomSummonGrow.fnptr!(&num_customizations); uint item_id = customizations[menu_list[curr_index].customization_id].item; int item_cost = customizations[menu_list[curr_index].customization_id].item_cost; @@ -989,7 +989,7 @@ public static void MyWindow_Render(TkWindow* window) { FhXCall.h_TkMn2DrawCrossCursor.fnptr!(pos.X, pos.Y, 0); } - public static bool h_FUN_008d5720(uint gear_id, int param_2) { + public static bool FUN_008d5720(uint gear_id, int param_2) { Equipment* gear = FhXCall.h_MsGetSaveWeapon.fnptr!(gear_id, 0); bool can_customize = false; diff --git a/src/gui/debugWindow.cs b/src/gui/debugWindow.cs index 0bc584a..e402d60 100644 --- a/src/gui/debugWindow.cs +++ b/src/gui/debugWindow.cs @@ -371,7 +371,7 @@ private void render_experiments() { // // FhXCall.h_FmodVoice_initList.fnptr!(fmodVoice); // - // int dataChange_result = h_FmodVoice_dataChange(fmodVoice, Globals.save_data->current_room_id, *(nint*)(ffxFmod + 4)); + // int dataChange_result = FmodVoice_dataChange(fmodVoice, Globals.save_data->current_room_id, *(nint*)(ffxFmod + 4)); // if (dataChange_result != 0) { // *(nint*)(*(int*)((int)ffxFmod + 0xc) + 0x28) = **(nint**)((int)ffxFmod + 0x10); // } diff --git a/src/hooks.cs b/src/hooks.cs index 067b126..11ce9ab 100644 --- a/src/hooks.cs +++ b/src/hooks.cs @@ -20,11 +20,76 @@ namespace ArchipelagoFFX; public unsafe partial class ArchipelagoFFXModule { + private FhMethodHandle h_Map_800F + => new(new FhMethodLocation("FFX.exe", 0x51B1A0)); + private FhMethodHandle h_Map_show2DLayerResultInt + => new(new FhMethodLocation("FFX.exe", 0x51B1A0)); + private FhMethodHandle h_Map_hide2DLayerResultInt + => new(new FhMethodLocation("FFX.exe", 0x51B1E0)); + private FhMethodHandle h_Common_obtainBrotherhoodRetInt + => new(new FhMethodLocation("FFX.exe", 0x459A40)); + private FhMethodHandle h_Common_obtainTreasureInit + => new(new FhMethodLocation("FFX.exe", 0x45A740)); + private FhMethodHandle h_Common_removePartyMemberLongTerm + => new(new FhMethodLocation("FFX.exe", 0x45AAF0)); + private FhMethodHandle h_Common_setPrimerCollected + => new(new FhMethodLocation("FFX.exe", 0x45AB30)); + private FhMethodHandle h_Common_pushParty + => new(new FhMethodLocation("FFX.exe", 0x45B350)); + private FhMethodHandle h_Common_popParty + => new(new FhMethodLocation("FFX.exe", 0x45B3C0)); + private FhMethodHandle h_Common_addPartyMember + => new(new FhMethodLocation("FFX.exe", 0x45B5A0)); + private FhMethodHandle h_Common_removePartyMember + => new(new FhMethodLocation("FFX.exe", 0x45B6C0)); + private FhMethodHandle h_Common_putPartyMemberInSlot + => new(new FhMethodLocation("FFX.exe", 0x45BC90)); + private FhMethodHandle h_Common_0043 + => new(new FhMethodLocation("FFX.exe", 0x45C810)); + private FhMethodHandle h_Common_linkFieldToBattleActor + => new(new FhMethodLocation("FFX.exe", 0x45CA00)); + private FhMethodHandle h_Common_playFieldVoiceLineInit + => new(new FhMethodLocation("FFX.exe", 0x45CB70)); + private FhMethodHandle h_Common_playFieldVoiceLineExec + => new(new FhMethodLocation("FFX.exe", 0x45CD30)); + private FhMethodHandle h_Common_loadModel + => new(new FhMethodLocation("FFX.exe", 0x45CE70)); + private FhMethodHandle h_Common_playFieldVoiceLineResultInt + => new(new FhMethodLocation("FFX.exe", 0x45D150)); + private FhMethodHandle h_Common_00D6Init + => new(new FhMethodLocation("FFX.exe", 0x45D520)); + private FhMethodHandle h_Common_00D6Exec + => new(new FhMethodLocation("FFX.exe", 0x45D820)); + private FhMethodHandle h_Common_00D6ResultInt + => new(new FhMethodLocation("FFX.exe", 0x45DCF0)); + private FhMethodHandle h_Common_01D1Init + => new(new FhMethodLocation("FFX.exe", 0x45FB60)); + private FhMethodHandle h_Common_01D1Exec + => new(new FhMethodLocation("FFX.exe", 0x45FDB0)); + private FhMethodHandle h_Common_setWeaponInvisible + => new(new FhMethodLocation("FFX.exe", 0x456770)); + private FhMethodHandle h_Common_obtainTreasureSilentlyInit + => new(new FhMethodLocation("FFX.exe", 0x4579E0)); + private FhMethodHandle h_CT_RetInt_0065 + => new(new FhMethodLocation("FFX.exe", 0x457F60)); + private FhMethodHandle h_Common_transitionToMap + => new(new FhMethodLocation("FFX.exe", 0x4580C0)); + private FhMethodHandle h_Common_warpToMap + => new(new FhMethodLocation("FFX.exe", 0x458370)); + private FhMethodHandle h_CT_RetInt_006A + => new(new FhMethodLocation("FFX.exe", 0x4589F0)); + private FhMethodHandle h_CT_RetInt_01B6 + => new(new FhMethodLocation("FFX.exe", 0x4594D0)); + private FhMethodHandle h_Common_upgradeBrotherhoodRetInt + => new(new FhMethodLocation("FFX.exe", 0x4596A0)); + private FhMethodHandle h_SgEvent_showModularMenuInit + => new(new FhMethodLocation("FFX.exe", 0x678210)); + public static int* takara_pointer => FhUtil.ptr_at(0xD35FEC); public static int* buki_get_pointer => FhUtil.ptr_at(0xD35FF4); public static char* get_event_name(uint event_id) => FhXCall.h_AtelGetEventName.fnptr!(event_id); - public static int atel_stack_pop(int* param_1, AtelStack* atelStack) => FhXCall.h_AtelStackPop.fnptr!(param_1, atelStack); + public static int atel_stack_pop(int* arg1, AtelStack* atelStack) => FhXCall.h_AtelPopStackInteger.fnptr!(arg1, atelStack); public static void AtelSetUpCallFunc(int id, nint nameSpacePtr) => FhXCall.h_AtelSetUpCallFunc.fnptr!(id, nameSpacePtr); @@ -35,19 +100,19 @@ public void init_hooks() { } public static int ignore_this = 11; - public int h_Map_800F(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + public int h_Map_800F_reimpl(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int param_1 = atelStack->values.as_int()[0]; if (param_1 == ignore_this) { atelStack->pop_int(); return 1; } - return FhXCall.h_Map_800F.chain_from(h_Map_800F).fnptr!(work, storage, atelStack); + return h_Map_800F.chain_from(h_Map_800F_reimpl).fnptr!(work, storage, atelStack); } public bool h_openFile(nint _this, nint filename, bool readOnly, nint unknown_1, nint unknown_2, nint unknown_3) { string x = Marshal.PtrToStringAnsi(filename)!; _logger.Debug($"{_this}, {x}, {readOnly}, {unknown_1}, {unknown_2}, {unknown_3}"); - var result = FhXCall.h_openFile.chain_from(h_openFile).fnptr!(_this, filename, readOnly, unknown_1, unknown_2, unknown_3); + var result = FhXCall.h_Phyre_PSerialization_PStreamFileWin32_openFile.chain_from(h_openFile).fnptr!(_this, filename, readOnly, unknown_1, unknown_2, unknown_3); _logger.Debug($"{result}, {*(int*)_this}, {*(int*)((int)_this + 4)}"); return result; } @@ -111,24 +176,47 @@ private void init_custom_atel() { } private bool hook() { - return FhXCall.h_Common_obtainTreasureInit.hook(this, h_Common_obtainTreasureInit) && FhXCall.h_Common_obtainTreasureSilentlyInit.hook(this, h_Common_obtainTreasureSilentlyInit) && FhXCall.h_Common_obtainBrotherhoodRetInt.hook(this, h_Common_obtainBrotherhoodRetInt) - && FhXCall.h_TkSetLegendAbility.hook(this, h_TkSetLegendAbility) && FhXCall.h_Common_setPrimerCollected.hook(this, h_Common_setPrimerCollected) - && FhXCall.h_AtelEventSetUp.hook(this, h_AtelEventSetUp) && FhXCall.h_Common_transitionToMap.hook(this, h_Common_transitionToMap) && FhXCall.h_Common_warpToMap.hook(this, h_Common_warpToMap) - && FhXCall.h_SgEvent_showModularMenuInit.hook(this, h_SgEvent_showModularMenuInit) - && FhXCall.h_Common_addPartyMember.hook(this, h_Common_addPartyMember) && FhXCall.h_Common_removePartyMember.hook(this, h_Common_removePartyMember) && FhXCall.h_Common_removePartyMemberLongTerm.hook(this, h_Common_removePartyMemberLongTerm) && FhXCall.h_Common_setWeaponInvisible.hook(this, h_Common_setWeaponInvisible) - && FhXCall.h_Common_putPartyMemberInSlot.hook(this, h_Common_putPartyMemberInSlot) && FhXCall.h_Common_pushParty.hook(this, h_Common_pushParty) && FhXCall.h_Common_popParty.hook(this, h_Common_popParty) && FhXCall.h_MsBattleExe.hook(this, h_MsBattleExe) && FhXCall.h_FUN_00791820.hook(this, h_FUN_00791820) - && FhXCall.h_MsApUp.hook(this, h_MsApUp) && FhXCall.h_MsBtlReadSetScene.hook(this, h_MsBtlReadSetScene) // && Map_800F //MsBtlGetPos - && FhXCall.h_eiAbmParaGet.hook(this, h_eiAbmParaGet) && FhXCall.h_MsSetSaveParam.hook(this, h_MsSetSaveParam) && FhXCall.h_MsSetRamChrParam.hook(this, h_MsSetRamChrParam) // && FUN_00a48910 - && FhXCall.h_FUN_0086bec0.hook(this, h_FUN_0086bec0) && FhXCall.h_FUN_0086bea0.hook(this, h_FUN_0086bea0) // Custom strings - && FhXCall.h_graphicInitFMVPlayer.hook(this, h_graphicInitFMVPlayer) && FhXCall.h_FmodVoice_dataChange.hook(this, h_FmodVoice_dataChange) - && FhXCall.h_AtelInitTotal.hook(this, h_AtelInitTotal) - && FhXCall.h_LocalizationManager_Initialize.hook(this, h_LocalizationManager_Initialize) - && FhXCall.h_TkMenuAppearMainCmdWindow.hook(this, h_TkMenuAppearMainCmdWindow) - && FhXCall.h_PrepareMenuList.hook(this, h_PrepareMenuList) && FhXCall.h_UpdateGearCustomizationMenuState.hook(this, h_UpdateGearCustomizationMenuState) && FhXCall.h_DrawGearCustomizationMenu.hook(this, h_DrawGearCustomizationMenu) - && FhXCall.h_UpdateAeonCustomizationMenuState.hook(this, h_UpdateAeonCustomizationMenuState) && FhXCall.h_DrawAeonCustomizationMenu.hook(this, h_DrawAeonCustomizationMenu) && FhXCall.h_FUN_008d5720.hook(this, h_FUN_008d5720); - //&& _FUN_00656c90.hook() && _FUN_0065ee30.hook(); - //&& _openFile.hook() && _FUN_0070aec0.hook(); - //&& _MsCheckLeftWindow.hook() && _MsCheckUseCommand.hook() && _TOBtlDrawStatusLimitGauge.hook(); + return h_Common_obtainTreasureInit.hook(this, Common_obtainTreasureInit) + && h_Common_obtainTreasureSilentlyInit.hook(this, Common_obtainTreasureSilentlyInit) + && h_Common_obtainBrotherhoodRetInt.hook(this, Common_obtainBrotherhoodRetInt) + && h_Common_setPrimerCollected.hook(this, Common_setPrimerCollected) + && h_Common_transitionToMap.hook(this, Common_transitionToMap) + && h_Common_warpToMap.hook(this, Common_warpToMap) + && h_SgEvent_showModularMenuInit.hook(this, SgEvent_showModularMenuInit) + && h_Common_addPartyMember.hook(this, Common_addPartyMember) + && h_Common_removePartyMember.hook(this, Common_removePartyMember) + && h_Common_removePartyMemberLongTerm.hook(this, Common_removePartyMemberLongTerm) + && h_Common_setWeaponInvisible.hook(this, Common_setWeaponInvisible) + && h_Common_putPartyMemberInSlot.hook(this, Common_putPartyMemberInSlot) + && h_Common_pushParty.hook(this, Common_pushParty) + && h_Common_popParty.hook(this, Common_popParty) + && FhXCall.h_TkSetLegendAbility.hook(this, TkSetLegendAbility) + && FhXCall.h_AtelEventSetUp.hook(this, AtelEventSetUp) + && FhXCall.h_MsBattleExe.hook(this, MsBattleExe) + && FhXCall.h_FUN_00791820.hook(this, FUN_00791820) + && FhXCall.h_MsApUp.hook(this, MsApUp) + && FhXCall.h_MsBtlReadSetScene.hook(this, MsBtlReadSetScene) + && FhXCall.h_eiAbmParaGet.hook(this, eiAbmParaGet) + && FhXCall.h_MsSetSaveParam.hook(this, MsSetSaveParam) + && FhXCall.h_MsSetRamChrParam.hook(this, MsSetRamChrParam) + && FhXCall.h_FUN_0086bec0.hook(this, FUN_0086bec0) + && FhXCall.h_FUN_0086bea0.hook(this, FUN_0086bea0) // Custom strings + && FhXCall.h_graphicInitFMVPlayer.hook(this, graphicInitFMVPlayer) + && FhXCall.h_FmodVoice_dataChange.hook(this, FmodVoice_dataChange) + && FhXCall.h_AtelInitTotal.hook(this, AtelInitTotal) + && FhXCall.h_LocalizationManager_Initialize.hook(this, LocalizationManager_Initialize) + && FhXCall.h_TkMenuAppearMainCmdWindow.hook(this, TkMenuAppearMainCmdWindow) + && FhXCall.h_FUN_008c2370.hook(this, PrepareMenuList) + && FhXCall.h_UpdateGearCustomizationMenuState.hook(this, UpdateGearCustomizationMenuState) + && FhXCall.h_DrawGearCustomizationMenu.hook(this, DrawGearCustomizationMenu) + && FhXCall.h_TkMenuCtrlSummon.hook(this, TkMenuCtrlSummon) + && FhXCall.h_FUN_008cdb70.hook(this, DrawAeonCustomizationMenu) + && FhXCall.h_FUN_008d5720.hook(this, FUN_008d5720); + // && _FUN_00656c90.hook() && _FUN_0065ee30.hook(); + // && _openFile.hook() && _FUN_0070aec0.hook(); + // && _MsCheckLeftWindow.hook() && _MsCheckUseCommand.hook() && _TOBtlDrawStatusLimitGauge.hook(); + // && Map_800F //MsBtlGetPos + // && FUN_00a48910 } @@ -182,7 +270,7 @@ private void move(byte* code_ptr, uint sourceOffset, int moveBy, int size) { temp.CopyTo(destinationDestination); } - private byte* h_FUN_0086bec0(int param_1) { + private byte* FUN_0086bec0(int param_1) { byte* result; if ((param_1 & 0x8000) != 0) { int custom_index = param_1 & 0x7FFF; @@ -193,20 +281,20 @@ private void move(byte* code_ptr, uint sourceOffset, int moveBy, int size) { _logger.Debug(customStrings[custom_index].decoded); } else { // May crash if called with invalid index - result = FhXCall.h_FUN_0086bec0.chain_from(h_FUN_0086bec0).fnptr!(param_1); + result = FhXCall.h_FUN_0086bec0.chain_from(FUN_0086bec0).fnptr!(param_1); } return result; } - private short h_FUN_0086bea0(int param_1) { + private short FUN_0086bea0(int param_1) { short result; if ((param_1 & 0x8000) != 0) { int custom_index = param_1 & 0x7FFF; result = customStrings[custom_index].metadata; } else { - result = FhXCall.h_FUN_0086bea0.chain_from(h_FUN_0086bea0).fnptr!(param_1); + result = FhXCall.h_FUN_0086bea0.chain_from(FUN_0086bea0).fnptr!(param_1); } return result; @@ -1056,8 +1144,8 @@ AtelOp.PUSHII .build(0x50AB), private static Dictionary<(int, int), uint> originalEntryPoints = new(); private static string current_event_name = ""; - private void h_AtelEventSetUp(int event_id) { - FhXCall.h_AtelEventSetUp.chain_from(h_AtelEventSetUp).fnptr!(event_id); + private void AtelEventSetUp(int event_id) { + FhXCall.h_AtelEventSetUp.chain_from(AtelEventSetUp).fnptr!(event_id); foreach (NativeCustomString customString in cached_strings) { customString.Free(); @@ -2011,7 +2099,7 @@ AtelOp.PUSHII .build( 0), current_event_name = event_name; } - private void h_Common_obtainTreasureInit(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + private void Common_obtainTreasureInit(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int treasure_id = atelStack->values.as_int()[1]; _logger.Info($"obtain_treasure: {treasure_id}"); //FhXCall.h_Common_obtainTreasureInit.chain_from(h_Common_obtainTreasureInit).fnptr!(work, storage, atelStack); @@ -2107,7 +2195,7 @@ private void obtainTreasureInitReimplement(AtelBasicWorker* work, int* storage, atelStack->push_int(0x100); atelStack->push_int(0xd0); atelStack->push_int(4); - FhXCall.h_CT_RetInt_0065.fnptr!((nint)work, storage, (nint)atelStack); + h_CT_RetInt_0065.fnptr!(work, storage, atelStack); TOMesWinWork* mesageWindowWorker = FhXCall.h_AtelGetMesWinWork.fnptr!(window_id); mesageWindowWorker->_0x20 = 0; @@ -2118,7 +2206,7 @@ private void obtainTreasureInitReimplement(AtelBasicWorker* work, int* storage, atelStack->push_int(window_id); atelStack->push_int(0); - FhXCall.h_CT_RetInt_006A.fnptr!((nint)work, storage, (nint)atelStack); + h_CT_RetInt_006A.fnptr!(work, storage, atelStack); *storage = window_id; storage[1] = 1; @@ -2132,7 +2220,7 @@ private void obtainTreasureInitReimplement(AtelBasicWorker* work, int* storage, mesageWindowWorker->_0x1d |= 0x10; } - private void h_Common_obtainTreasureSilentlyInit(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + private void Common_obtainTreasureSilentlyInit(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int treasure_id = atelStack->values.as_int()[0]; _logger.Info($"obtain_treasure_silently: {treasure_id}"); //FhXCall.h_Common_obtainTreasureSilentlyInit.chain_from(h_Common_obtainTreasureSilentlyInit).fnptr!(work, storage, atelStack); @@ -2176,7 +2264,7 @@ private void obtainTreasureSilentlyInitReimplement(AtelBasicWorker* work, int* s } } - private int h_Common_obtainBrotherhoodRetInt(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + private int Common_obtainBrotherhoodRetInt(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { _logger.Debug("obtain_brotherhoodRetInt"); if (atelStack->size > 0) { throw new Exception($"Too many parameters ({atelStack->size}) passed to obtainBrotherhood!"); @@ -2185,21 +2273,21 @@ private int h_Common_obtainBrotherhoodRetInt(AtelBasicWorker* work, int* storage obtain_item(item.id); return 1; } - return FhXCall.h_Common_obtainBrotherhoodRetInt.chain_from(h_Common_obtainBrotherhoodRetInt).fnptr!(work, storage, atelStack); + return h_Common_obtainBrotherhoodRetInt.chain_from(Common_obtainBrotherhoodRetInt).fnptr!(work, storage, atelStack); } - private int h_Common_upgradeBrotherhoodRetInt(nint work, int* storage, nint atelStack) { + private int Common_upgradeBrotherhoodRetInt(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { _logger.Debug("upgrade_brotherhoodRetInt"); if (item_locations.other.TryGetValue(37, out var item)) { obtain_item(item.id); return 1; } - return FhXCall.h_Common_upgradeBrotherhoodRetInt.chain_from(h_Common_upgradeBrotherhoodRetInt).fnptr!(work, storage, atelStack); + return h_Common_upgradeBrotherhoodRetInt.chain_from(Common_upgradeBrotherhoodRetInt).fnptr!(work, storage, atelStack); } - private int h_Common_isBrotherhoodUnpoweredRetInt(nint work, int* storage, nint atelStack) { + private int Common_isBrotherhoodUnpoweredRetInt(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { _logger.Debug("isBrotherhoodUnpoweredRetInt"); - return FhXCall.h_CT_RetInt_01B6.chain_from(h_Common_isBrotherhoodUnpoweredRetInt).fnptr!(work, storage, atelStack); + return h_CT_RetInt_01B6.chain_from(Common_isBrotherhoodUnpoweredRetInt).fnptr!(work, storage, atelStack); } //private static int h_Common_grantCelestialUpgrade(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { // int character = atelStack->values.as_int()[0]; @@ -2217,7 +2305,7 @@ private int h_Common_isBrotherhoodUnpoweredRetInt(nint work, int* storage, nint // return _Common_grantCelestialUpgrade.orig_fptr(work, storage, atelStack); //} - private int h_TkSetLegendAbility(int chr_id, int level) { + private int TkSetLegendAbility(int chr_id, int level) { _logger.Debug($"grant_celestial_upgrade: character={id_to_character[chr_id]}, level={level}"); int other_id = 37 + level + chr_id * 2; @@ -2228,11 +2316,11 @@ private int h_TkSetLegendAbility(int chr_id, int level) { return level; } - return FhXCall.h_TkSetLegendAbility.chain_from(h_TkSetLegendAbility).fnptr!(chr_id, level); + return FhXCall.h_TkSetLegendAbility.chain_from(TkSetLegendAbility).fnptr!(chr_id, level); } - private int h_Common_setPrimerCollected(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + private int Common_setPrimerCollected(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int primer = atelStack->values.as_int()[0]; _logger.Debug($"set_primer_collected: Al Bhed Primer {primer + 1}"); @@ -2244,7 +2332,7 @@ private int h_Common_setPrimerCollected(AtelBasicWorker* work, int* storage, Ate return 1; } - return FhXCall.h_Common_setPrimerCollected.chain_from(h_Common_setPrimerCollected).fnptr!(work, storage, atelStack); + return h_Common_setPrimerCollected.chain_from(Common_setPrimerCollected).fnptr!(work, storage, atelStack); } private void update_region_state() { @@ -2373,23 +2461,23 @@ private void refill_inventory() { foreach ((var item_id, var amount) in excess_inventory.ToList()) { if (amount > 0 && save_data->get_item_count((int)item_id) < 99) { excess_inventory[item_id] = 0; - h_give_item(item_id, amount); + give_item(item_id, amount); } } } - private int h_Common_transitionToMap(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + private int Common_transitionToMap(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { ref int map = ref atelStack->values.as_int()[0]; ref int entrance = ref atelStack->values.as_int()[1]; _logger.Debug($"transition_to_map: map={map}, entrance={entrance}"); if (handle_warp_transition(save_data->current_room_id, save_data->current_spawnpoint, ref map, ref entrance)) { - return FhXCall.h_Common_transitionToMap.chain_from(h_Common_transitionToMap).fnptr!(work, storage, atelStack); + return h_Common_transitionToMap.chain_from(Common_transitionToMap).fnptr!(work, storage, atelStack); } return blockWarp(work, storage, atelStack); } - private int h_Common_warpToMap(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + private int Common_warpToMap(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { ref int map = ref atelStack->values.as_int()[0]; ref int entrance = ref atelStack->values.as_int()[1]; _logger.Debug($"warp_to_map: map={map}, entrance={entrance}"); @@ -2401,13 +2489,13 @@ private int h_Common_warpToMap(AtelBasicWorker* work, int* storage, AtelStack* a } if (handle_warp_transition(save_data->current_room_id, save_data->current_spawnpoint, ref map, ref entrance)) { - return FhXCall.h_Common_warpToMap.chain_from(h_Common_warpToMap).fnptr!(work, storage, atelStack); + return h_Common_warpToMap.chain_from(Common_warpToMap).fnptr!(work, storage, atelStack); } return blockWarp(work, storage, atelStack); } - private void h_SgEvent_showModularMenuInit(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + private void SgEvent_showModularMenuInit(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int menu = atelStack->values.as_int()[0]; int unknown1 = menu >> 24 & 0xFF; int menuType = menu >> 16 & 0xFF; @@ -2442,11 +2530,11 @@ private void h_SgEvent_showModularMenuInit(AtelBasicWorker* work, int* storage, } _logger.Info($"Opening menu: type={menuTypeString}, index={index} {(unknown1 == 0x40 ? "" : $", Unknown1={unknown1}")} {(unknown2 == 0x00 ? "" : $", Unknown2={unknown2}")}"); - FhXCall.h_SgEvent_showModularMenuInit.chain_from(h_SgEvent_showModularMenuInit).fnptr!(work, storage, atelStack); + h_SgEvent_showModularMenuInit.chain_from(SgEvent_showModularMenuInit).fnptr!(work, storage, atelStack); } - public int h_Common_addPartyMember(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + public int Common_addPartyMember(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int character = atelStack->values.as_int()[0]; //if (!party_overridden && !(save_data->atel_is_push_member == 1)) { @@ -2458,10 +2546,10 @@ public int h_Common_addPartyMember(AtelBasicWorker* work, int* storage, AtelStac } //logger.Debug($"add_party_member: character={id_to_character[character]}"); - return FhXCall.h_Common_addPartyMember.chain_from(h_Common_addPartyMember).fnptr!(work, storage, atelStack); + return h_Common_addPartyMember.chain_from(Common_addPartyMember).fnptr!(work, storage, atelStack); } - public int h_Common_removePartyMember(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + public int Common_removePartyMember(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int character = atelStack->values.as_int()[0]; //if (!party_overridden && !(save_data->atel_is_push_member == 1)) { @@ -2473,10 +2561,10 @@ public int h_Common_removePartyMember(AtelBasicWorker* work, int* storage, AtelS } //logger.Debug($"remove_party_member: character={id_to_character[character]}"); - return FhXCall.h_Common_removePartyMember.chain_from(h_Common_removePartyMember).fnptr!(work, storage, atelStack); + return h_Common_removePartyMember.chain_from(Common_removePartyMember).fnptr!(work, storage, atelStack); } - public int h_Common_removePartyMemberLongTerm(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + public int Common_removePartyMemberLongTerm(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int character = atelStack->values.as_int()[0]; //if (!party_overridden && !(save_data->atel_is_push_member == 1)) { @@ -2488,10 +2576,10 @@ public int h_Common_removePartyMemberLongTerm(AtelBasicWorker* work, int* storag } //logger.Debug($"remove_party_member_long_term: character={id_to_character[character]}"); - return FhXCall.h_Common_removePartyMemberLongTerm.chain_from(h_Common_removePartyMemberLongTerm).fnptr!(work, storage, atelStack); + return h_Common_removePartyMemberLongTerm.chain_from(Common_removePartyMemberLongTerm).fnptr!(work, storage, atelStack); } - public int h_Common_setWeaponInvisible(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + public int Common_setWeaponInvisible(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int character = (byte)atelStack->values.as_int()[0]; int state = atelStack->values.as_int()[1]; _logger.Debug($"character={id_to_character[character]}, state={state}"); @@ -2500,10 +2588,10 @@ public int h_Common_setWeaponInvisible(AtelBasicWorker* work, int* storage, Atel atelStack->pop_int(); return 0; } - return FhXCall.h_Common_setWeaponInvisible.chain_from(h_Common_setWeaponInvisible).fnptr!(work, storage, atelStack); + return h_Common_setWeaponInvisible.chain_from(Common_setWeaponInvisible).fnptr!(work, storage, atelStack); } - public int h_Common_putPartyMemberInSlot(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + public int Common_putPartyMemberInSlot(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int slot = atelStack->values.as_int()[0]; int character = (byte)atelStack->values.as_int()[1]; //if (!party_overridden && !(save_data->atel_is_push_member == 1)) { @@ -2517,10 +2605,10 @@ public int h_Common_putPartyMemberInSlot(AtelBasicWorker* work, int* storage, At } //logger.Debug($"put_party_member_in_slot: slot={slot}, character={(character != 0xff ? id_to_character[character] : "Empty")}"); - return FhXCall.h_Common_putPartyMemberInSlot.chain_from(h_Common_putPartyMemberInSlot).fnptr!(work, storage, atelStack); + return h_Common_putPartyMemberInSlot.chain_from(Common_putPartyMemberInSlot).fnptr!(work, storage, atelStack); } - public int h_Common_pushParty(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + public int Common_pushParty(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { //logger.Debug($"push_party"); //if (party_overridden) return FhXCall.h_Common_pushParty.chain_from(h_Common_pushParty).fnptr!(work, storage, atelStack); @@ -2528,7 +2616,7 @@ public int h_Common_pushParty(AtelBasicWorker* work, int* storage, AtelStack* at return 0; } - public int h_Common_popParty(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + public int Common_popParty(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { //logger.Debug($"pop_party"); //if (party_overridden) return FhXCall.h_Common_popParty.chain_from(h_Common_popParty).fnptr!(work, storage, atelStack); @@ -2545,7 +2633,7 @@ public void h_MsGetSavePartyMember(uint* param_1, uint* param_2, uint* param_3) } // Pre-battle - public void h_MsBattleExe(uint param_1, int field_idx, int group_idx, int formation_idx) { + public void MsBattleExe(uint param_1, int field_idx, int group_idx, int formation_idx) { // Evrae is 52, 0, 0 // Penance is 52, 1, 0 if (field_idx == 52 && group_idx == 1 && formation_idx == 0) { @@ -2579,12 +2667,12 @@ public void h_MsBattleExe(uint param_1, int field_idx, int group_idx, int format save_party(); // Probably? reset_party(); } - FhXCall.h_MsBattleExe.chain_from(h_MsBattleExe).fnptr!(param_1, field_idx, group_idx, formation_idx); + FhXCall.h_MsBattleExe.chain_from(MsBattleExe).fnptr!(param_1, field_idx, group_idx, formation_idx); } // Battle loop? - public void h_FUN_00791820() { - FhXCall.h_FUN_00791820.chain_from(h_FUN_00791820).fnptr!(); + public void FUN_00791820() { + FhXCall.h_FUN_00791820.chain_from(FUN_00791820).fnptr!(); string encounter_name = Marshal.PtrToStringAnsi((nint)(&Battle.btl->field_name))!; byte battle_end_type = Battle.btl->battle_end_type; byte battle_state = Battle.btl->battle_state; @@ -2630,8 +2718,8 @@ public void h_FUN_00791820() { } private void* curr_pos_area_ptr = null; - public byte h_MsBtlReadSetScene() { - byte result = FhXCall.h_MsBtlReadSetScene.chain_from(h_MsBtlReadSetScene).fnptr!(); + public byte MsBtlReadSetScene() { + byte result = FhXCall.h_MsBtlReadSetScene.chain_from(MsBtlReadSetScene).fnptr!(); _logger.Info($"Battle Name: {Marshal.PtrToStringAnsi((nint)FhUtil.ptr_at(0xD2C25A))}"); //ref BtlAreas original_pos_struct = ref *Battle.btl->ptr_pos_def; BtlAreasHelper original_pos_struct = new BtlAreasHelper(Battle.btl->ptr_pos_def); @@ -2821,7 +2909,7 @@ public int h_MsBtlGetPos(int param_1, Chr* chr, int btl_pos_a, int btl_pos_b, in return FhXCall.h_MsBtlGetPos.chain_from(h_MsBtlGetPos).fnptr!(param_1, chr, btl_pos_a, btl_pos_b, btl_pos_c, out_pos); } - private void h_give_item(uint item_id, int amount) { + private int give_item(uint item_id, int amount) { _logger.Debug($"give_item: {amount} x {item_id}"); int new_amount = (int)(save_data->get_item_count((int)item_id) + amount); @@ -2832,8 +2920,7 @@ private void h_give_item(uint item_id, int amount) { amount -= excess; } - FhXCall.h_MsSaveItemUse.chain_from(h_give_item).fnptr!(item_id, amount); - return; + return FhXCall.h_MsSaveItemUse.chain_from(give_item).fnptr!(item_id, amount); } private void h_TkMsImportantSet(uint param_1) { @@ -2920,7 +3007,7 @@ public void obtain_item(uint item_id, int amount=-1) { break; case 0x2: // Item - h_give_item(item_id, amount); + give_item(item_id, amount); break; case 0x5: // Equipment @@ -2952,7 +3039,7 @@ public void obtain_item(uint item_id, int amount=-1) { // Upgrade celestial if (celestial_level[equip.owner] < 2) { celestial_level[equip.owner] += 1; - FhXCall.h_TkSetLegendAbility.chain_from(h_TkSetLegendAbility).fnptr!(equip.owner, celestial_level[equip.owner]); + FhXCall.h_TkSetLegendAbility.chain_from(TkSetLegendAbility).fnptr!(equip.owner, celestial_level[equip.owner]); } return; } @@ -3106,7 +3193,7 @@ public void call_obtain_brotherhood() { int param_1 = 0; int param_2 = 0; - h_Common_obtainBrotherhoodRetInt((AtelBasicWorker*)¶m_1, ¶m_2, &stack); + h_Common_obtainBrotherhoodRetInt.fnptr!((AtelBasicWorker*)¶m_1, ¶m_2, &stack); } public void receive_treasure(int id) { @@ -3116,7 +3203,7 @@ public void receive_treasure(int id) { int param_1 = 0; int param_2 = 0; - FhXCall.h_Common_obtainTreasureSilentlyInit.chain_from(h_Common_obtainTreasureSilentlyInit).fnptr!((AtelBasicWorker*)¶m_1, ¶m_2, &stack); + h_Common_obtainTreasureSilentlyInit.chain_from(Common_obtainTreasureSilentlyInit).fnptr!((AtelBasicWorker*)¶m_1, ¶m_2, &stack); } public void set_airship_destinations() { @@ -3147,10 +3234,10 @@ public void set_airship_destinations() { // Sphere Grid Experiment - public void h_eiAbmParaGet() { + public void eiAbmParaGet() { // TODO: Replace normal calculation with custom Archipelago-based calculation (if option enabled) _logger.Debug("Calculating stats"); - FhXCall.h_eiAbmParaGet.chain_from(h_eiAbmParaGet).fnptr!(); + FhXCall.h_eiAbmParaGet.chain_from(eiAbmParaGet).fnptr!(); //foreach (ref PlySave ply in save_data->ply_saves) { // ply.abi_map.has_extract_power = true; @@ -3160,9 +3247,9 @@ public void h_eiAbmParaGet() { //} } - private void h_MsSetRamChrParam(uint chr_id) { + private void MsSetRamChrParam(uint chr_id) { _logger.Debug($"MsSetRamChrParam: {chr_id}"); - FhXCall.h_MsSetRamChrParam.chain_from(h_MsSetRamChrParam).fnptr!(chr_id); + FhXCall.h_MsSetRamChrParam.chain_from(MsSetRamChrParam).fnptr!(chr_id); Chr* chr = FhXCall.h_MsGetChr.fnptr!((int)chr_id); @@ -3171,9 +3258,9 @@ private void h_MsSetRamChrParam(uint chr_id) { } } - private void h_MsSetSaveParam(uint chr_id) { + private void MsSetSaveParam(uint chr_id) { _logger.Debug("Calculating base stats and equipment"); - FhXCall.h_MsSetSaveParam.chain_from(h_MsSetSaveParam).fnptr!(chr_id); + FhXCall.h_MsSetSaveParam.chain_from(MsSetSaveParam).fnptr!(chr_id); // Does nothing?? if (seed.Options.AlwaysSensor == 1) { @@ -3241,17 +3328,17 @@ public void h_FUN_00a48910(uint chr_id, int node_idx) { FhXCall.h_FUN_00a48910.chain_from(h_FUN_00a48910).fnptr!(chr_id, node_idx); } - private uint h_MsApUp(int chr_id, Chr* chr, int base_ap_add, uint param_4) { + private uint MsApUp(int chr_id, Chr* chr, int base_ap_add, uint param_4) { _logger.Debug($"AP gain: character={id_to_character[chr_id]}, ap={base_ap_add}"); int new_ap = (int)Math.Min(Math.BigMul(base_ap_add, ap_multiplier), 999_999_999); - return FhXCall.h_MsApUp.chain_from(h_MsApUp).fnptr!(chr_id, chr, new_ap, param_4); + return FhXCall.h_MsApUp.chain_from(MsApUp).fnptr!(chr_id, chr, new_ap, param_4); } // Non-loading FMV - private bool h_graphicInitFMVPlayer(int movie_id, int param_2) { - bool result = FhXCall.h_graphicInitFMVPlayer.chain_from(h_graphicInitFMVPlayer).fnptr!(movie_id, param_2); + private bool graphicInitFMVPlayer(int movie_id, int param_2) { + bool result = FhXCall.h_graphicInitFMVPlayer.chain_from(graphicInitFMVPlayer).fnptr!(movie_id, param_2); return !result; } @@ -3267,11 +3354,11 @@ private void h_FUN_00656c90(int param_1, int param_2, char* fileName) { FhXCall.h_FUN_00656c90.chain_from(h_FUN_00656c90).fnptr!(param_1, param_2, fileName); } - private void h_TkMenuAppearMainCmdWindow(int param_1, int param_2) { + private void TkMenuAppearMainCmdWindow(int param_1, int param_2) { // All menu options are enabled at progress 0 ushort progress = save_data->story_progress; save_data->story_progress = 0; - FhXCall.h_TkMenuAppearMainCmdWindow.chain_from(h_TkMenuAppearMainCmdWindow).fnptr!(param_1, param_2); + FhXCall.h_TkMenuAppearMainCmdWindow.chain_from(TkMenuAppearMainCmdWindow).fnptr!(param_1, param_2); save_data->story_progress = progress; } @@ -3290,25 +3377,25 @@ public void h_FfxFmod_soundInit_setLang(nint ffxFmod, int lang) { } // Unsure if there are side effects - public void h_LocalizationManager_Initialize(LocalizationManager* localizationManager) { - FhXCall.h_LocalizationManager_Initialize.chain_from(h_LocalizationManager_Initialize).fnptr!(localizationManager); + public void LocalizationManager_Initialize(LocalizationManager* localizationManager) { + FhXCall.h_LocalizationManager_Initialize.chain_from(LocalizationManager_Initialize).fnptr!(localizationManager); if (TextLanguage.HasValue) { _logger.Debug($"Text: {TextLanguage.Value}"); - localizationManager->current_language = TextLanguage.Value; + localizationManager->lang_text = TextLanguage.Value; } if (VoiceLanguage.HasValue) { _logger.Debug($"Voice: {VoiceLanguage.Value}"); - localizationManager->video = VoiceLanguage.Value; - localizationManager->voice = VoiceLanguage.Value; + localizationManager->lang_video = VoiceLanguage.Value; + localizationManager->lang_voice = VoiceLanguage.Value; } } [UnmanagedFunctionPointer(CallingConvention.StdCall)] public unsafe delegate nint FMOD_Bank_Post_Load(nint param_1, nint param_2, nint param_3, nint param_4); - public int h_FmodVoice_dataChange(nint FmodVoice, int event_id, nint param_2) { + public int FmodVoice_dataChange(nint FmodVoice, int event_id, nint param_2) { _logger.Debug($"{FmodVoice}, {event_id}, {param_2}"); - int result = FhXCall.h_FmodVoice_dataChange.chain_from(h_FmodVoice_dataChange).fnptr!(FmodVoice, event_id, param_2); + int result = FhXCall.h_FmodVoice_dataChange.chain_from(FmodVoice_dataChange).fnptr!(FmodVoice, event_id, param_2); //string bank_name = "ffx_us_voice03"; // Contains "Stay away from the summoner!" (136815042) foreach (string bank_name in (string[])["ffx_us_voice03", "ffx_us_voice07", "ffx_us_voice11", "ffx_us_voice12", "ffx_us_voice20"]) { string path = $"../../../FFX_Data/GameData/PS3Data/Sound_PC/Voice/US/{bank_name}.fev"; @@ -3347,13 +3434,13 @@ public void play_voice_line(int voice_line) { int[] storage_array = [0,0,0,0]; fixed (int* storage = storage_array) { - FhXCall.h_Common_playFieldVoiceLineInit.fnptr!((AtelBasicWorker*)&work, storage, &stack); - FhXCall.h_Common_playFieldVoiceLineExec.fnptr!((AtelBasicWorker*)&work, &stack); - FhXCall.h_Common_playFieldVoiceLineResultInt.fnptr!((AtelBasicWorker*)&work, storage, &stack); + h_Common_playFieldVoiceLineInit.fnptr!((AtelBasicWorker*)&work, storage, &stack); + h_Common_playFieldVoiceLineExec.fnptr!((AtelBasicWorker*)&work, &stack); + h_Common_playFieldVoiceLineResultInt.fnptr!((AtelBasicWorker*)&work, storage, &stack); - FhXCall.h_Common_00D6Init.fnptr!((AtelBasicWorker*)&work, storage, &stack); - FhXCall.h_Common_00D6Exec.fnptr!((AtelBasicWorker*)&work, &stack); - FhXCall.h_Common_00D6ResultInt.fnptr!((AtelBasicWorker*)&work, storage, &stack); + h_Common_00D6Init.fnptr!((AtelBasicWorker*)&work, storage, &stack); + h_Common_00D6Exec.fnptr!((AtelBasicWorker*)&work, &stack); + h_Common_00D6ResultInt.fnptr!((AtelBasicWorker*)&work, storage, &stack); } @@ -3425,9 +3512,9 @@ public FhGCall.CT_RetFloat get_CT_RetFloat(int id) { } // Custom namespace - public void h_AtelInitTotal() { + public void AtelInitTotal() { _logger.Debug("Initializing Atel namespaces"); - FhXCall.h_AtelInitTotal.chain_from(h_AtelInitTotal).fnptr!(); + FhXCall.h_AtelInitTotal.chain_from(AtelInitTotal).fnptr!(); AtelSetUpCallFunc(0xF, customNameSpaceHandle.AddrOfPinnedObject()); } @@ -3716,7 +3803,7 @@ public int blockWarp(AtelBasicWorker* work, int* storage, AtelStack* atelStack) // Warp atelStack->push_int(382); atelStack->push_int(0); - h_Common_warpToMap(work, storage, atelStack); + Common_warpToMap(work, storage, atelStack); return 1; } @@ -3780,7 +3867,7 @@ public int CT_RetInt_ShowCurrentAirshipLocation(AtelBasicWorker* work, int* stor // AE0300 D80F80 call Map.?show2DLayer [800Fh](layerIndex=3 [03h]); atelStack->push_int(3); - FhXCall.h_Map_show2DLayerResultInt.fnptr!(work, storage, atelStack); + h_Map_show2DLayerResultInt.fnptr!(work, storage, atelStack); return 1; } @@ -3790,7 +3877,7 @@ public int CT_RetInt_HideCurrentAirshipLocation(AtelBasicWorker* work, int* stor // AE0300 D81080 call Map.?hide2DLayer [8010h](layerIndex=3 [03h]); atelStack->push_int(3); - FhXCall.h_Map_hide2DLayerResultInt.fnptr!(work, storage, atelStack); + h_Map_hide2DLayerResultInt.fnptr!(work, storage, atelStack); return 1; } @@ -3817,7 +3904,7 @@ public int CT_RetInt_TransitionToRegion(AtelBasicWorker* work, int* storage, Ate atelStack->push_int(map); atelStack->push_int(entrance); - h_Common_transitionToMap(work, storage, atelStack); + Common_transitionToMap(work, storage, atelStack); return 1; } diff --git a/src/modules/captures.cs b/src/modules/captures.cs index b203971..8afba0e 100644 --- a/src/modules/captures.cs +++ b/src/modules/captures.cs @@ -606,7 +606,8 @@ private int h_MsBattleEncountExe(int field_id, int group_idx, float walked_delta bool all_complete = true; for (int formation_idx = 0; formation_idx < group->formation_count; formation_idx++) { - BtlBinFormation formation = group->formations[formation_idx]; + //BtlBinFormation formation = group->formations[formation_idx]; + BtlBinFormation formation = MemoryMarshal.CreateSpan(ref group->_first_formation, group->formation_count); if (formation.weight == 0) { weights[formation_idx] = 0; @@ -636,7 +637,8 @@ private int h_MsBattleEncountExe(int field_id, int group_idx, float walked_delta total_weight = group->total_weight; for (int formation_idx = 0; formation_idx < group->formation_count; formation_idx++) { - BtlBinFormation formation = group->formations[formation_idx]; + //BtlBinFormation formation = group->formations[formation_idx]; + BtlBinFormation formation = MemoryMarshal.CreateSpan(ref group->_first_formation, group->formation_count); weights[formation_idx] = formation.weight / 17; } } From c14f49727969713767dec85624aa065391f2ca6e Mon Sep 17 00:00:00 2001 From: Andrew K Date: Wed, 17 Jun 2026 15:31:45 +1000 Subject: [PATCH 12/20] Review Comments (WIP) --- src/modules/captures.cs | 7 ++++--- src/modules/deathlink.cs | 15 ++++++--------- src/modules/overdrives.cs | 12 ++++++------ 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/modules/captures.cs b/src/modules/captures.cs index 8afba0e..f2986f2 100644 --- a/src/modules/captures.cs +++ b/src/modules/captures.cs @@ -29,6 +29,7 @@ public CaptureModule() { _ffx_interop_handle = new(this); } + // TODO: Remove once Fahrenheit adds Atel call targets to FhCall // Mars Sigil location check (Atel CT_RetInt hook); not yet a curated FhCall entry, so kept as a local handle. private FhMethodHandle h_ret_hasKeyItem_handle => new( new FhMethodLocation("FFX.exe", 0x45B7A0) ); @@ -39,7 +40,7 @@ public override bool init(FhModContext mod_context, FileStream global_state_file && FhXCall.h_MsMonsterCapture.hook(this, h_MsMonsterCapture) && FhXCall.h_FUN_00783bb0.hook(this, h_FUN_00783bb0) && FhXCall.h_AtelEventSetUp.hook(this, h_AtelEventSetUp) - && h_ret_hasKeyItem_handle.hook(this, h_ret_hasKeyItem) + && h_ret_hasKeyItem_handle.hook(this, ret_hasKeyItem) && FhXCall.h_MsDamageCheckDeath.hook(this, h_MsDamageCheckDeath) && FhXCall.h_MsSetRamChrParam.hook(this, h_MsSetRamChrParam) && FhXCall.h_MsSetSaveParam.hook(this, h_MsSetSaveParam) @@ -153,7 +154,7 @@ private void h_AtelEventSetUp(int event_id) { } //Check Mars Sigil location instead of inventory - private int h_ret_hasKeyItem(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + private int ret_hasKeyItem(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { if (_event_name == "nagi0700") { int item_id = atelStack->pop_int(); @@ -167,7 +168,7 @@ private int h_ret_hasKeyItem(AtelBasicWorker* work, int* storage, AtelStack* ate } } - return h_ret_hasKeyItem_handle.fnptr!(work, storage, atelStack); + return h_ret_hasKeyItem_handle.chain_from(ret_hasKeyItem).fnptr!(work, storage, atelStack); } private int h_MsDamageCheckDeath(int attacker_id, int target_id, int param_3, int param_4) { diff --git a/src/modules/deathlink.cs b/src/modules/deathlink.cs index d27bea0..e2083e3 100644 --- a/src/modules/deathlink.cs +++ b/src/modules/deathlink.cs @@ -1,18 +1,14 @@ -using System; -using System.IO; -using System.Numerics; -using System.Runtime.InteropServices; -using System.Text; - using Archipelago.MultiClient.Net.BounceFeatures.DeathLink; - using ArchipelagoFFX.Client; - using Fahrenheit; using Fahrenheit.FFX; using Fahrenheit.FFX.Battle; using Fahrenheit.FFX.Ids; - +using System; +using System.IO; +using System.Numerics; +using System.Runtime.InteropServices; +using System.Text; using FhXCall = Fahrenheit.FFX.FhCall; namespace ArchipelagoFFX; @@ -230,6 +226,7 @@ private void _h_MsBtlReadManage() { _logger.Info(" Disabling Escape and Flee..."); for (int chr_id = 0; chr_id <= PlySaveId.PC_SEYMOUR; chr_id++) { + // Disable Escape & Flee commands FhXCall.h_FUN_0079b480.fnptr!(chr_id, PlayerCommandId.PCOM_ESCAPE, 1); FhXCall.h_FUN_0079b480.fnptr!(chr_id, PlayerCommandId.PCOM_FLEE, 1); } diff --git a/src/modules/overdrives.cs b/src/modules/overdrives.cs index f09b60a..881b1ea 100644 --- a/src/modules/overdrives.cs +++ b/src/modules/overdrives.cs @@ -26,7 +26,8 @@ public unsafe partial class OverdriveModule : FhModule { private FhModuleHandle _ffx_interop_handle; private ArchipelagoFFXModule? _ffx_interop; - private FhMethodHandle h_ret_doesChrKnowCommand => new(new FhMethodLocation("FFX.exe", 0x3A30C0)); + private FhMethodHandle h_ret_doesChrKnowCommand + => new(new FhMethodLocation("FFX.exe", 0x3A30C0)); // Damage Calc [StructLayout(LayoutKind.Explicit, Size = 0x2C)] @@ -206,8 +207,8 @@ public override bool init(FhModContext mod_context, FileStream global_state_file && FhXCall.h_MsGetSaveCommand.hook(this, h_MsGetSaveCommand) && FhXCall.h_MsSetRamChrAbility.hook(this, h_MsSetRamChrAbility) && FhXCall.h_MsLimitTidusLearn.hook(this, h_MsLimitTidusLearn) - && FhXCall.h_MsAfterDamageProcess.hook(this, h_MsAfterDamageProcess) - && h_ret_doesChrKnowCommand.hook(this, h_ret_doesChrKnowCommand_reimpl) + && FhXCall.h_AfterDamageProcess.hook(this, h_MsAfterDamageProcess) + && h_ret_doesChrKnowCommand.hook(this, ret_doesChrKnowCommand) && FhXCall.h_MsSetSaveCommandWithPrefix.hook(this, h_MsSetSaveCommandWithPrefix) && FhXCall.h_TOBtlDrawLearningMessageWindow.hook(this, h_TOBtlDrawLearningMessageWindow); } @@ -233,7 +234,6 @@ private void h_MsSetRamChrAbility(int chr_id, Chr* chr) { OverdriveProvider.provide_overdrive(chr_id); FhXCall.h_MsSetRamChrAbility.chain_from(h_MsSetRamChrAbility).fnptr!(chr_id, chr); - return; } // Runs on every Tidus Limit. Override the normal requirements, and send locations based on 10 / 20 / 40 @@ -498,7 +498,7 @@ private uint h_MsAfterDamageProcess(int attacker_id, uint param_2, int target_id } // Required in order to allow Biran & Yenke's ChrLoot to progress to the next Ronso Rage based on location sent, rather than command known - private int h_ret_doesChrKnowCommand_reimpl(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { + private int ret_doesChrKnowCommand(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int com_id = atelStack->pop_int(); int chr_id = atelStack->pop_int(); @@ -511,7 +511,7 @@ private int h_ret_doesChrKnowCommand_reimpl(AtelBasicWorker* work, int* storage, atelStack->push_int(chr_id); atelStack->push_int(com_id); - return h_ret_doesChrKnowCommand.fnptr!(work, storage, atelStack); + return h_ret_doesChrKnowCommand.chain_from(ret_doesChrKnowCommand).fnptr!(work, storage, atelStack); } // Called from teachAbilityToPartyMemberSilently & teachAbilityToPartyMemberWithMsg From 85ecf1a7a88584776eb3bfb4041665de69a2dbd4 Mon Sep 17 00:00:00 2001 From: Andrew K Date: Wed, 17 Jun 2026 15:37:42 +1000 Subject: [PATCH 13/20] Update private -> public member name --- src/modules/captures.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/captures.cs b/src/modules/captures.cs index f2986f2..df3646b 100644 --- a/src/modules/captures.cs +++ b/src/modules/captures.cs @@ -608,7 +608,7 @@ private int h_MsBattleEncountExe(int field_id, int group_idx, float walked_delta for (int formation_idx = 0; formation_idx < group->formation_count; formation_idx++) { //BtlBinFormation formation = group->formations[formation_idx]; - BtlBinFormation formation = MemoryMarshal.CreateSpan(ref group->_first_formation, group->formation_count); + BtlBinFormation formation = MemoryMarshal.CreateSpan(ref group->first_formation, group->formation_count); if (formation.weight == 0) { weights[formation_idx] = 0; @@ -639,7 +639,7 @@ private int h_MsBattleEncountExe(int field_id, int group_idx, float walked_delta for (int formation_idx = 0; formation_idx < group->formation_count; formation_idx++) { //BtlBinFormation formation = group->formations[formation_idx]; - BtlBinFormation formation = MemoryMarshal.CreateSpan(ref group->_first_formation, group->formation_count); + BtlBinFormation formation = MemoryMarshal.CreateSpan(ref group->first_formation, group->formation_count); weights[formation_idx] = formation.weight / 17; } } From b5ba4dc400370a53059fa61f6f0423f19993d744 Mon Sep 17 00:00:00 2001 From: Andrewki44 Date: Mon, 22 Jun 2026 22:17:03 +1000 Subject: [PATCH 14/20] Latest FhCall PR Updates --- src/archipelago.cs | 39 +++++++++++++++++------------------ src/hooks.cs | 42 +++++++++++++++++++------------------- src/modules/captures.cs | 4 ++-- src/modules/sphere_grid.cs | 16 +++++---------- 4 files changed, 47 insertions(+), 54 deletions(-) diff --git a/src/archipelago.cs b/src/archipelago.cs index 26614bd..e7aee62 100644 --- a/src/archipelago.cs +++ b/src/archipelago.cs @@ -14,7 +14,6 @@ using System.Linq; using System.Numerics; using System.Reflection; -using System.Runtime.InteropServices; using System.Text.Json; using System.Text.Json.Serialization; using System.Text.RegularExpressions; @@ -1012,25 +1011,25 @@ public void set_character_model(int chr_id) { h_Common_linkFieldToBattleActor.fnptr!(worker0, &storage, &stack); } - public uint allocate_file(string filename, out nint file_ptr) { - int[] fileStream = [0,0]; - uint readBytes = 0; - file_ptr = 0; - - fixed (int* fs = fileStream) { - nint pFilename = Marshal.StringToHGlobalAnsi(filename); - h_openFile((nint)fs, pFilename, true, 0, 0, 1); - Marshal.FreeHGlobal(pFilename); - _logger.Debug($"file_handle={fileStream[0]}, file_length={*(long*)(*(int*)(fileStream[1] + 0xc) + 8)}"); - if (fileStream[1] == 0) return 0; - var file_length = *(long*)(*(int*)(fileStream[1] + 0xc) + 8); - file_ptr = Marshal.AllocHGlobal((int)file_length); - uint max_len = (uint)file_length; - readBytes = FhXCall.h_Phyre_PSerialization_PStreamFileWin32_readFile.fnptr!((nint)fs, file_ptr, max_len); - } - _logger.Debug($"read {readBytes}, beginning={((byte*)file_ptr)[0]} {((byte*)file_ptr)[1]} {((byte*)file_ptr)[2]} {((byte*)file_ptr)[3]}"); - return readBytes; - } + //public uint allocate_file(string filename, out nint file_ptr) { + // int[] fileStream = [0,0]; + // uint readBytes = 0; + // file_ptr = 0; + + // fixed (int* fs = fileStream) { + // nint pFilename = Marshal.StringToHGlobalAnsi(filename); + // h_openFile((nint)fs, pFilename, true, 0, 0, 1); + // Marshal.FreeHGlobal(pFilename); + // _logger.Debug($"file_handle={fileStream[0]}, file_length={*(long*)(*(int*)(fileStream[1] + 0xc) + 8)}"); + // if (fileStream[1] == 0) return 0; + // var file_length = *(long*)(*(int*)(fileStream[1] + 0xc) + 8); + // file_ptr = Marshal.AllocHGlobal((int)file_length); + // uint max_len = (uint)file_length; + // readBytes = FhXCall.h_Phyre_PSerialization_PStreamFileWin32_Read.fnptr!((nint)fs, file_ptr, max_len); + // } + // _logger.Debug($"read {readBytes}, beginning={((byte*)file_ptr)[0]} {((byte*)file_ptr)[1]} {((byte*)file_ptr)[2]} {((byte*)file_ptr)[3]}"); + // return readBytes; + //} public struct CustomStringDrawInfo(ManagedCustomString customString, Vector2 pos, float scale = 0.65f, byte color = 0, bool persistent = false) { public ManagedCustomString customString = customString; diff --git a/src/hooks.cs b/src/hooks.cs index 11ce9ab..7e3057f 100644 --- a/src/hooks.cs +++ b/src/hooks.cs @@ -109,13 +109,13 @@ public int h_Map_800F_reimpl(AtelBasicWorker* work, int* storage, AtelStack* ate return h_Map_800F.chain_from(h_Map_800F_reimpl).fnptr!(work, storage, atelStack); } - public bool h_openFile(nint _this, nint filename, bool readOnly, nint unknown_1, nint unknown_2, nint unknown_3) { - string x = Marshal.PtrToStringAnsi(filename)!; - _logger.Debug($"{_this}, {x}, {readOnly}, {unknown_1}, {unknown_2}, {unknown_3}"); - var result = FhXCall.h_Phyre_PSerialization_PStreamFileWin32_openFile.chain_from(h_openFile).fnptr!(_this, filename, readOnly, unknown_1, unknown_2, unknown_3); - _logger.Debug($"{result}, {*(int*)_this}, {*(int*)((int)_this + 4)}"); - return result; - } + //public bool h_openFile(nint _this, nint filename, bool readOnly, nint unknown_1, nint unknown_2, nint unknown_3) { + // string x = Marshal.PtrToStringAnsi(filename)!; + // _logger.Debug($"{_this}, {x}, {readOnly}, {unknown_1}, {unknown_2}, {unknown_3}"); + // var result = FhXCall.h_Phyre_PSerialization_PStreamFileWin32_Open.chain_from(h_openFile).fnptr!(_this, filename, readOnly, unknown_1, unknown_2, unknown_3); + // _logger.Debug($"{result}, {*(int*)_this}, {*(int*)((int)_this + 4)}"); + // return result; + //} public uint h_FUN_0070aec0(nint _this, uint voice_id, uint param_2) { return FhXCall.h_FUN_0070aec0.chain_from(h_FUN_0070aec0).fnptr!(_this, voice_id, param_2); @@ -2122,7 +2122,7 @@ private void obtainTreasureInitReimplement(AtelBasicWorker* work, int* storage, FhXCall.h_FUN_008b8910.fnptr!(window_id, 1, 1); bool gear_inv_is_full = false; uint weapon_id = 0; - byte* message_text = FhXCall.h_FUN_008bda20.fnptr!(0x401d); // "Nothing" + byte* message_text = FhXCall.h_TkBtlEndGetText.fnptr!(0x401d); // "Nothing" if (item_locations.treasure.TryGetValue(treasure_id, out var item)) { if (_client!.sendLocation(treasure_id, ArchipelagoClientModule.ArchipelagoLocationType.Treasure)) { @@ -2135,7 +2135,7 @@ private void obtainTreasureInitReimplement(AtelBasicWorker* work, int* storage, cached_strings.Add(name); item_name = name.encoded; if (item.id != 0) { - message_text = FhXCall.h_FUN_008bda20.fnptr!(0x4018); // "Obtained %0!" + message_text = FhXCall.h_TkBtlEndGetText.fnptr!(0x4018); // "Obtained %0!" } else { NativeCustomString sent_text = new NativeCustomString("Sent {VAR:00}!"); //CustomString sent_text = new CustomString("Sent {VAR:00} to {VAR:01}!"); @@ -2157,10 +2157,10 @@ private void obtainTreasureInitReimplement(AtelBasicWorker* work, int* storage, FhXCall.h_TkMsGetRomItem.fnptr!(Battle.reward_data->items[0], (int*)&item_name); FhXCall.h_FUN_008b8930.fnptr!(window_id, 1, Battle.reward_data->items_amounts[0]); if (Battle.reward_data->items_amounts[0] == 1) { - message_text = FhXCall.h_FUN_008bda20.fnptr!(0x4018); // "Obtained %0!" + message_text = FhXCall.h_TkBtlEndGetText.fnptr!(0x4018); // "Obtained %0!" } else { - message_text = FhXCall.h_FUN_008bda20.fnptr!(0x4019); // "Obtained %0 x%1!" + message_text = FhXCall.h_TkBtlEndGetText.fnptr!(0x4019); // "Obtained %0 x%1!" } byte[] decoded = new byte[FhEncoding.compute_decode_buffer_size(new ReadOnlySpan(item_name, 1000))]; @@ -2173,19 +2173,19 @@ private void obtainTreasureInitReimplement(AtelBasicWorker* work, int* storage, } else if (Battle.reward_data->key_item_count != 0) { item_name = FhXCall.h_MsImportantName.fnptr!(Battle.reward_data->key_item); - message_text = FhXCall.h_FUN_008bda20.fnptr!(0x4017); // "Obtained %0!" + message_text = FhXCall.h_TkBtlEndGetText.fnptr!(0x4017); // "Obtained %0!" FhXCall.h_TkMsImportantSet.fnptr!(Battle.reward_data->key_item); } else if (Battle.reward_data->gear_count != 0) { weapon_id = Battle.reward_data->gear_inv_idx; - message_text = FhXCall.h_FUN_008bda20.fnptr!(0x4016); // "Obtained %0!" + message_text = FhXCall.h_TkBtlEndGetText.fnptr!(0x4016); // "Obtained %0!" Equipment* weapon = (Equipment*)FhXCall.h_MsGetSaveWeapon.fnptr!(weapon_id, (nint)(&item_name)); int inv_id = FhXCall.h_FUN_007ab930.fnptr!(weapon); // giveWeapon? gear_inv_is_full = inv_id == 0; } else if (Battle.reward_data->gil != 0) { FhXCall.h_FUN_008b8930.fnptr!(window_id, 1, (int)Battle.reward_data->gil); - message_text = FhXCall.h_FUN_008bda20.fnptr!(0x401a); // "Obtained %1 Gil!" + message_text = FhXCall.h_TkBtlEndGetText.fnptr!(0x401a); // "Obtained %1 Gil!" FhXCall.h_MsPayGIL.fnptr!(-(int)Battle.reward_data->gil); } @@ -2929,16 +2929,16 @@ private void h_TkMsImportantSet(uint param_1) { FhXCall.h_TkMsImportantSet.chain_from(h_TkMsImportantSet).fnptr!(param_1); } - private byte* h_read_from_bin(int param_1, short* param_2, int param_3) { - _logger.Debug($"get_from_bin: {param_1}, {(int)param_2}, {param_3}"); + private nint h_read_from_bin(int param_1, nint param_2, int* param_3) { + _logger.Debug($"get_from_bin: {param_1}, {(int)param_2}, {*param_3}"); _logger.Debug($"bin_pointers: {(uint)param_2}, {(uint)(*takara_pointer)}, {(uint)(*buki_get_pointer)}"); - if (param_2 == (short*)*takara_pointer) { + if (param_2 == *takara_pointer) { _logger.Debug("get_from_bin: takara.bin"); } - else if (param_2 == (short*)*buki_get_pointer) { + else if (param_2 == *buki_get_pointer) { _logger.Debug("get_from_bin: buki_get.bin"); } - var result = FhXCall.h_FUN_007ab890.chain_from(h_read_from_bin).fnptr!(param_1, param_2, param_3); + var result = FhXCall.h_MsGetExcelData.chain_from(h_read_from_bin).fnptr!(param_1, param_2, param_3); _logger.Debug($"get_from_bin: result = {((uint)result).ToString("X")}"); return result; } @@ -2946,13 +2946,13 @@ private void h_TkMsImportantSet(uint param_1) { private ushort h_get_weapon_name(Equipment* param_1) { _logger.Debug($"get_weapon_name: {(int)param_1}"); - return FhXCall.h_FUN_007a0d10.chain_from(h_get_weapon_name).fnptr!(param_1); + return FhXCall.h_MsWeaponNameNum.chain_from(h_get_weapon_name).fnptr!(param_1); } private void h_get_weapon_model(ushort name_id, byte owner, int unknown, ushort* model_id_pointer) { _logger.Debug($"get_weapon_model: {name_id}, {owner}, {unknown}, {*model_id_pointer}, "); - FhXCall.h_FUN_007a0c70.chain_from(h_get_weapon_model).fnptr!(name_id, owner, unknown, model_id_pointer); + FhXCall.h_MsWeaponName.chain_from(h_get_weapon_model).fnptr!(name_id, owner, unknown, model_id_pointer); } private void h_obtain_treasure_cleanup(BtlRewardData* param_1, int param_2) { diff --git a/src/modules/captures.cs b/src/modules/captures.cs index df3646b..77edd23 100644 --- a/src/modules/captures.cs +++ b/src/modules/captures.cs @@ -608,7 +608,7 @@ private int h_MsBattleEncountExe(int field_id, int group_idx, float walked_delta for (int formation_idx = 0; formation_idx < group->formation_count; formation_idx++) { //BtlBinFormation formation = group->formations[formation_idx]; - BtlBinFormation formation = MemoryMarshal.CreateSpan(ref group->first_formation, group->formation_count); + BtlBinFormation formation = MemoryMarshal.CreateSpan(ref group->first_formation, group->formation_count)[formation_idx]; if (formation.weight == 0) { weights[formation_idx] = 0; @@ -639,7 +639,7 @@ private int h_MsBattleEncountExe(int field_id, int group_idx, float walked_delta for (int formation_idx = 0; formation_idx < group->formation_count; formation_idx++) { //BtlBinFormation formation = group->formations[formation_idx]; - BtlBinFormation formation = MemoryMarshal.CreateSpan(ref group->first_formation, group->formation_count); + BtlBinFormation formation = MemoryMarshal.CreateSpan(ref group->first_formation, group->formation_count)[formation_idx]; weights[formation_idx] = formation.weight / 17; } } diff --git a/src/modules/sphere_grid.cs b/src/modules/sphere_grid.cs index c15e242..668b825 100644 --- a/src/modules/sphere_grid.cs +++ b/src/modules/sphere_grid.cs @@ -1,16 +1,10 @@ +using Fahrenheit; +using Fahrenheit.FFX; +using Hexa.NET.ImGui; using System.Collections.Generic; using System.IO; using System.Text; - -using Fahrenheit; - -using Hexa.NET.ImGui; - -using Fahrenheit.FFX; - using static Fahrenheit.FFX.Globals; - -using FhGCall = Fahrenheit.FhCall; using FhXCall = Fahrenheit.FFX.FhCall; namespace ArchipelagoFFX; @@ -39,7 +33,7 @@ public override bool init(FhModContext mod_context, FileStream global_state_file _global_state = global_state_file; return FhXCall.h_AbmapState_MovingToTarget.hook(this, h_move_speed) - && FhXCall.h_abmap_confirm_move.hook(this, h_move_confirm) + && FhXCall.h_FUN_00a56160.hook(this, h_move_confirm) && FhXCall.h_AbmapState_MovingToTarget.hook(this, h_state_moving) && FhXCall.h_AbmapState_Warping.hook(this, h_state_warping) && FhXCall.h_AbmapState_ChangingNode.hook(this, h_change_node); @@ -308,7 +302,7 @@ public void h_move_confirm(int p1, int p2, int p3) { knots_counted = 0; - FhXCall.h_abmap_confirm_move.chain_from(h_move_confirm).fnptr!(p1, p2, p3); + FhXCall.h_FUN_00a56160.chain_from(h_move_confirm).fnptr!(p1, p2, p3); // If we cancelled it, also deactivate all activated nodes if (p3 == 1 && temporarily_activated_nodes.Count > 0) { From b2403fede2cf26f56c82a40f039eecb75ac466eb Mon Sep 17 00:00:00 2001 From: evelyntsmg Date: Thu, 23 Jul 2026 17:55:58 +0200 Subject: [PATCH 15/20] Fix potential race condition in `Connect()` --- src/client/client.cs | 104 +++++++++++++++++++++++-------------------- 1 file changed, 55 insertions(+), 49 deletions(-) diff --git a/src/client/client.cs b/src/client/client.cs index 2837a2a..6b98de7 100644 --- a/src/client/client.cs +++ b/src/client/client.cs @@ -63,7 +63,6 @@ public override bool init(FhModContext mod_context, FileStream global_state_file && _death_link_handle.try_get_module(out _death_link); } - private bool _connecting = false; public async Task Connect(string server, string user, string password) { _logger.Debug("Connect"); LoginResult? login_result = new LoginFailure(""); @@ -72,60 +71,67 @@ public async Task Connect(string server, string user, string password) { if (is_disconnecting) return; - if (_connecting) return; // Already connecting, so don't attempt to connect twice at the same time - _connecting = true; - - try { - session = ArchipelagoSessionFactory.CreateSession(server); - death_link = session.CreateDeathLinkService(); - connectHandlers(session, death_link); - var roomInfoPacket = await session.ConnectAsync(); - - login_result = await session.LoginAsync("Final Fantasy X", user, ItemsHandlingFlags.RemoteItems, Version.Parse("0.6.0"), password: password, requestSlotData: true); - } catch (Exception e) { - login_result = new LoginFailure(e.GetBaseException().Message); - } + lock (client_lock) { - if (!login_result.Successful) { - LoginFailure failure = (LoginFailure)login_result; - string errorMessage = $"Failed to Connect to {server} as {user}:"; - foreach (string error in failure.Errors) { - errorMessage += $"\n {error}"; + // Already connecting, so don't attempt to connect twice at the same time + if (current_session is not null) return; + + try { + session = ArchipelagoSessionFactory.CreateSession(server); + death_link = session.CreateDeathLinkService(); + connectHandlers(session, death_link); + var roomInfoPacket = session.ConnectAsync(); + + login_result = session.TryConnectAndLogin( + "Final Fantasy X", + user, + ItemsHandlingFlags.RemoteItems, + Version.Parse("0.6.0"), + password: password, + requestSlotData: true + ); + } catch (Exception e) { + login_result = new LoginFailure(e.GetBaseException().Message); } - foreach (ConnectionRefusedError error in failure.ErrorCodes) { - errorMessage += $"\n {error}"; - } - _connecting = false; - current_session = null; - _logger.Error(errorMessage); - return; // Did not connect, show the user the contents of `errorMessage` - } - var loginSuccess = (LoginSuccessful)login_result; - - if (ArchipelagoFFXModule.seed.Options.SeedId is not null) { - if (ArchipelagoFFXModule.seed.Options.SeedId != (string)loginSuccess.SlotData["SeedId"]) { - string message = "Loaded seed doesn't match connected slot"; - _gui!.add_log_message([(message, Color.Red)]); - _logger.Error(message); - disconnect(session); - _connecting = false; - return; + + if (!login_result.Successful) { + LoginFailure failure = (LoginFailure)login_result; + string errorMessage = $"Failed to Connect to {server} as {user}:"; + foreach (string error in failure.Errors) { + errorMessage += $"\n {error}"; + } + foreach (ConnectionRefusedError error in failure.ErrorCodes) { + errorMessage += $"\n {error}"; + } + current_session = null; + _logger.Error(errorMessage); + return; // Did not connect, show the user the contents of `errorMessage` } - ArchipelagoFFXModule.SeedToServer[ArchipelagoFFXModule.seed.Options.SeedId] = server; - _ffx_interop!.save_global_state(); - } else { - SeedId = (string)loginSuccess.SlotData["SeedId"]; - int selected_seed = ArchipelagoFFXModule.loaded_seeds.FindIndex(x => x.Options.SeedId == SeedId); - if (selected_seed != -1) { - _gui!.selected_seed = selected_seed; - ArchipelagoFFXModule.SeedToServer[SeedId] = server; + var loginSuccess = (LoginSuccessful)login_result; + + if (ArchipelagoFFXModule.seed.Options.SeedId is not null) { + if (ArchipelagoFFXModule.seed.Options.SeedId != (string)loginSuccess.SlotData["SeedId"]) { + string message = "Loaded seed doesn't match connected slot"; + _gui!.add_log_message([(message, Color.Red)]); + _logger.Error(message); + disconnect(session); + return; + } + ArchipelagoFFXModule.SeedToServer[ArchipelagoFFXModule.seed.Options.SeedId] = server; _ffx_interop!.save_global_state(); + } else { + SeedId = (string)loginSuccess.SlotData["SeedId"]; + int selected_seed = ArchipelagoFFXModule.loaded_seeds.FindIndex(x => x.Options.SeedId == SeedId); + if (selected_seed != -1) { + _gui!.selected_seed = selected_seed; + ArchipelagoFFXModule.SeedToServer[SeedId] = server; + _ffx_interop!.save_global_state(); + } } + current_server = server; + current_session = session; + current_death_link_service = death_link; } - current_server = server; - current_session = session; - current_death_link_service = death_link; - _connecting = false; } public void disconnect(ArchipelagoSession? session = null) { From 95d28438ff8a3cf31c1047760ed8dcb96454dc38 Mon Sep 17 00:00:00 2001 From: evelyntsmg Date: Tue, 28 Jul 2026 04:03:18 +0200 Subject: [PATCH 16/20] Update to Fahrenheit 1.0.0-alpha11 --- Fahrenheit.Modules.ArchipelagoFFX.csproj | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/Fahrenheit.Modules.ArchipelagoFFX.csproj b/Fahrenheit.Modules.ArchipelagoFFX.csproj index f79080f..9578b5c 100644 --- a/Fahrenheit.Modules.ArchipelagoFFX.csproj +++ b/Fahrenheit.Modules.ArchipelagoFFX.csproj @@ -1,9 +1,9 @@ - + 0.8.1-alpha - v1.0.0-alpha10 + v1.0.0-alpha11 @@ -18,11 +18,11 @@ - + - + @@ -37,9 +37,6 @@ - - - fhcsr @@ -132,5 +129,5 @@ - + From 2f1890a9c3522d1184c6751168c2fae899460513 Mon Sep 17 00:00:00 2001 From: evelyntsmg Date: Tue, 28 Jul 2026 23:07:57 +0200 Subject: [PATCH 17/20] Use the new FhCall syntax --- src/archipelago.cs | 19 +- src/customization.cs | 174 +++++++++--------- src/gui/debugWindow.cs | 16 +- src/gui/recent_items.cs | 26 +-- src/hooks.cs | 306 ++++++++++++++++---------------- src/modules/captures.cs | 94 +++++----- src/modules/deathlink.cs | 22 +-- src/modules/hardcore_contest.cs | 6 +- src/modules/overdrives.cs | 136 +++++++------- src/modules/sphere_grid.cs | 42 +++-- 10 files changed, 424 insertions(+), 417 deletions(-) diff --git a/src/archipelago.cs b/src/archipelago.cs index 4b1bd6c..e6d9801 100644 --- a/src/archipelago.cs +++ b/src/archipelago.cs @@ -719,7 +719,7 @@ public void pre_update(UpdateLoopEventArgs args) { } } - public override void handle_input() { + public void handle_input() { /* if (Globals.Input.select.held) { if (Globals.Input.l1.just_pressed) { @@ -728,7 +728,7 @@ public override void handle_input() { } } */ - if (Input.l1.held && Input.r1.held && Input.start.just_pressed) { + if (Input.l1.is_pressed && Input.r1.is_pressed && Input.start.is_pressed) { _logger.Debug("Soft Reset"); //Globals.save_data->current_room_id = 23; if (Battle.btl->battle_state != 0) { @@ -739,7 +739,7 @@ public override void handle_input() { } - if (Input.select.held && Input.l1.just_pressed) { + if (Input.select.is_pressed && Input.l1.is_pressed) { #if DEBUG AtelBasicWorker* worker0 = Atel.controllers[0].worker(0); @@ -827,13 +827,13 @@ public override void handle_input() { } - if (Input.select.held && Input.r1.just_pressed) { + if (Input.select.is_pressed && Input.r1.is_pressed) { _logger.Info("Resetting party"); save_party(); reset_party(); } - if (Input.select.held && Input.l2.just_pressed) { + if (Input.select.is_pressed && Input.l2.is_pressed) { //foreach (var state in region_states) { // _logger.Debug($"{state.Key}: story_progress={state.Value.Story_progress}, room_id={state.Value.room_id}, entrance={state.Value.entrance}"); //} @@ -849,7 +849,7 @@ public override void handle_input() { //get_party_frontline(); } - if (Input.select.held && Input.r2.just_pressed) { + if (Input.select.is_pressed && Input.r2.is_pressed) { //_logger.Debug("Warp to Airship"); //call_warp_to_map(382, 0); } @@ -1026,7 +1026,7 @@ public void set_character_model(int chr_id) { // var file_length = *(long*)(*(int*)(fileStream[1] + 0xc) + 8); // file_ptr = Marshal.AllocHGlobal((int)file_length); // uint max_len = (uint)file_length; - // readBytes = FhXCall.h_Phyre_PSerialization_PStreamFileWin32_Read.fnptr!((nint)fs, file_ptr, max_len); + // readBytes = FhXCall.Phyre_PSerialization_PStreamFileWin32_Read.fnptr!((nint)fs, file_ptr, max_len); // } // _logger.Debug($"read {readBytes}, beginning={((byte*)file_ptr)[0]} {((byte*)file_ptr)[1]} {((byte*)file_ptr)[2]} {((byte*)file_ptr)[3]}"); // return readBytes; @@ -1042,10 +1042,11 @@ public struct CustomStringDrawInfo(ManagedCustomString customString, Vector2 pos public Dictionary customStringDrawInfos = []; - public override void render_game() { + //TODO: Figure out where to hook to make this work again + public void render_game() { foreach ((string key, CustomStringDrawInfo drawInfo) in customStringDrawInfos) { fixed (byte* text = drawInfo.customString.encoded) { - FhXCall.h_TOMkpCrossExtMesFontLClutTypeRGBA.fnptr!(0, text, drawInfo.pos.X, drawInfo.pos.Y, drawInfo.color, 0, 0x80, 0x80, 0x80, 0x80, drawInfo.scale, 0); + FhXCall.TOMkpCrossExtMesFontLClutTypeRGBA.fnptr!(0, text, drawInfo.pos.X, drawInfo.pos.Y, drawInfo.color, 0, 0x80, 0x80, 0x80, 0x80, drawInfo.scale, 0); } } } diff --git a/src/customization.cs b/src/customization.cs index d6df3c1..b214e95 100644 --- a/src/customization.cs +++ b/src/customization.cs @@ -76,7 +76,7 @@ public void PrepareMenuList(TkMenuItemListId menu_list_id, Equipment* gear) { if (menu_list_id == TkMenuItemListId.GEAR_CUSTOMIZATION) { // Modify kaizou.bin int num_customizations; - CustomizationRecipe* customizations = FhXCall.h_MsGetRomKaizou.fnptr!(&num_customizations); + CustomizationRecipe* customizations = FhXCall.MsGetRomKaizou.fnptr!(&num_customizations); if (original_kaizou_costs == null) { original_kaizou_costs = new ushort[num_customizations]; for (int i = 0; i < num_customizations; i++) { @@ -119,7 +119,7 @@ public void PrepareMenuList(TkMenuItemListId menu_list_id, Equipment* gear) { ushort ability_id = gear->abilities[i]; if (ability_id != 0 && ability_id != 0xFF) { int a_ability_id; - AutoAbility* a_ability = FhXCall.h_MsGetRomAbility.fnptr!(ability_id, &a_ability_id); + AutoAbility* a_ability = FhXCall.MsGetRomAbility.fnptr!(ability_id, &a_ability_id); ability_group_idxs[num_abilities] = (uint)a_ability->group_idx; ability_group_levels[num_abilities] = (uint)a_ability->group_level; @@ -141,7 +141,7 @@ public void PrepareMenuList(TkMenuItemListId menu_list_id, Equipment* gear) { if (customization.target_gear_type.HasFlag(gear_type)) { ushort a_ability_id = customization.auto_ability; int local_68; - AutoAbility* a_ability = FhXCall.h_MsGetRomAbility.fnptr!(a_ability_id, &local_68); + AutoAbility* a_ability = FhXCall.MsGetRomAbility.fnptr!(a_ability_id, &local_68); uint item_count = Globals.save_data->get_item_count(customization.item); if (item_count == 0 && customization.item_cost != 0) { @@ -210,8 +210,8 @@ public void PrepareMenuList(TkMenuItemListId menu_list_id, Equipment* gear) { } else if (menu_list_id == TkMenuItemListId.AEON_ABILITIES) { // TODO: Modify sum_grow.bin int num_customizations; - AeonAbilityRecipe* customizations = FhXCall.h_MsGetRomSummonGrow.fnptr!(&num_customizations); - num_customizations = FhXCall.h_TkMn2GetSummonGrowMax.fnptr!(); + AeonAbilityRecipe* customizations = FhXCall.MsGetRomSummonGrow.fnptr!(&num_customizations); + num_customizations = FhXCall.TkMn2GetSummonGrowMax.fnptr!(); if (original_sum_grow_costs == null) { original_sum_grow_costs = new ushort[num_customizations]; for (int i = 0; i < num_customizations; i++) { @@ -234,7 +234,7 @@ public void PrepareMenuList(TkMenuItemListId menu_list_id, Equipment* gear) { CustomizationMenuList* menu_list_iter = FhUtil.ptr_at(0x1197730); uint* _DAT_0186a20c = FhUtil.ptr_at(0x146A20C); - byte current_summon = FhXCall.h_TkMenuGetCurrentSummon.fnptr!(); + byte current_summon = FhXCall.TkMenuGetCurrentSummon.fnptr!(); bool has_key_item = Globals.save_data->key_items.get(0xa022); uint added = 0; @@ -243,7 +243,7 @@ public void PrepareMenuList(TkMenuItemListId menu_list_id, Equipment* gear) { AeonAbilityRecipe customization = customizations[customization_id]; short auto_ability_id = customization.command; menu_list_iter->customization_id = 0xff; - bool has_command = FhXCall.h_MsGetSaveCommand.fnptr!(current_summon, (uint)auto_ability_id) != 0; + bool has_command = FhXCall.MsGetSaveCommand.fnptr!(current_summon, (uint)auto_ability_id) != 0; if (!has_command) { uint item_count = Globals.save_data->get_item_count(customization.item); @@ -275,7 +275,7 @@ public void PrepareMenuList(TkMenuItemListId menu_list_id, Equipment* gear) { // Set length PrepareMenuList_SetLength(added, 0); } else { - FhXCall.h_FUN_008c2370.chain_from(PrepareMenuList).fnptr!(menu_list_id, gear); + FhXCall.FUN_008c2370.chain_from(PrepareMenuList).fnptr!(menu_list_id, gear); } @@ -310,13 +310,13 @@ public void UpdateGearCustomizationMenuState(TkWindow* window) { while (!break_loop) { switch (*state) { case 2: - FhXCall.h_FUN_008b4460.fnptr!(window); + FhXCall.FUN_008b4460.fnptr!(window); if (window->exit_value < 1) { return; } ushort weapon_index = *(ushort*)(p_DAT_0186a9f8 + window->selected_index * 2); - gear = FhXCall.h_MsGetSaveWeapon.fnptr!(weapon_index, 0); + gear = FhXCall.MsGetSaveWeapon.fnptr!(weapon_index, 0); bool can_customize = false; if (gear->exists && !gear->is_hidden && gear->slot_count > 0) { if (!gear->is_celestial && !gear->is_brotherhood) { @@ -328,7 +328,7 @@ public void UpdateGearCustomizationMenuState(TkWindow* window) { if (!can_customize) { goto default; } else { - FhXCall.h_SndSepPlaySimple.fnptr!(0x80000001); + FhXCall.SndSepPlaySimple.fnptr!(0x80000001); { int slot = 0; for (; slot < gear->slot_count; slot++) { @@ -351,7 +351,7 @@ public void UpdateGearCustomizationMenuState(TkWindow* window) { case 6: { TkWindow* _GearSelectionWindow = (TkWindow*)FhUtil.get_at(0x146A9F0); // DAT_0186a9f0 - gear = FhXCall.h_MsGetSaveWeapon.fnptr!( + gear = FhXCall.MsGetSaveWeapon.fnptr!( *(ushort*)(p_DAT_0186a9f8 + _GearSelectionWindow->selected_index * 2), (nint)(&gear_name) ); @@ -382,7 +382,7 @@ public void UpdateGearCustomizationMenuState(TkWindow* window) { case 0xc: { TkWindow* DAT_023cc120 = (TkWindow*)FhUtil.get_at(0x1FCC120); if (DAT_023cc120->exit_value < 0) { - FhXCall.h_FUN_008e2de0.fnptr!(); + FhXCall.FUN_008e2de0.fnptr!(); *state = 6; break_loop = true; break; @@ -393,9 +393,9 @@ public void UpdateGearCustomizationMenuState(TkWindow* window) { break; } - FhXCall.h_FUN_008e2de0.fnptr!(); + FhXCall.FUN_008e2de0.fnptr!(); if (DAT_023cc120->selected_index != 0) { - FhXCall.h_SndSepPlaySimple.fnptr!(0x80000001); + FhXCall.SndSepPlaySimple.fnptr!(0x80000001); *state = 6; break_loop = true; break; @@ -412,9 +412,9 @@ public void UpdateGearCustomizationMenuState(TkWindow* window) { short selected_ability = AbilitySelectionWindow->selected_index; int num_customizations; - CustomizationRecipe* customizations = FhXCall.h_MsGetRomKaizou.fnptr!(&num_customizations); + CustomizationRecipe* customizations = FhXCall.MsGetRomKaizou.fnptr!(&num_customizations); byte customization_id = menu_list[selected_ability].customization_id; - gear = FhXCall.h_MsGetSaveWeapon.fnptr!( + gear = FhXCall.MsGetSaveWeapon.fnptr!( *(ushort*)(p_DAT_0186a9f8 + GearSelectionWindow->selected_index * 2), (nint)(&gear_name) ); @@ -431,12 +431,12 @@ public void UpdateGearCustomizationMenuState(TkWindow* window) { gear->abilities[selected_gear_slot] = menu_list[selected_ability].a_ability_id; } - FhXCall.h_MsSetSaveParamAll.fnptr!(); + FhXCall.MsSetSaveParamAll.fnptr!(); - FhXCall.h_MsSetWeaponName.fnptr!(gear); - FhXCall.h_MsSaveItemUse.fnptr!(customizations[customization_id].item, -customizations[customization_id].item_cost); - FhXCall.h_SndSepPlaySimple.fnptr!(0x80000063); - FhXCall.h_MsGetSaveWeapon.fnptr!((uint)*(ushort*)(p_DAT_0186a9f8 + GearSelectionWindow->selected_index * 2), (nint)(&gear_name)); + FhXCall.MsSetWeaponName.fnptr!(gear); + FhXCall.MsSaveItemUse.fnptr!(customizations[customization_id].item, -customizations[customization_id].item_cost); + FhXCall.SndSepPlaySimple.fnptr!(0x80000063); + FhXCall.MsGetSaveWeapon.fnptr!((uint)*(ushort*)(p_DAT_0186a9f8 + GearSelectionWindow->selected_index * 2), (nint)(&gear_name)); byte* p_DAT_0186aa70 = FhUtil.ptr_at(0x146AA70); i = -1; @@ -467,10 +467,10 @@ public void UpdateGearCustomizationMenuState(TkWindow* window) { uVar9 = 0x1f; } - byte* pbVar8 = FhXCall.h_FUN_008bee80.fnptr!(uVar9); - FhXCall.h_FUN_008c2c40.fnptr!(0, 0, p_DAT_0186aa30); - FhXCall.h_FUN_008c2c40.fnptr!(2, 0, p_DAT_0186aa70); - FhXCall.h_FUN_008e33a0.fnptr!(pbVar8, (byte*)0, (byte*)0); + byte* pbVar8 = FhXCall.FUN_008bee80.fnptr!(uVar9); + FhXCall.FUN_008c2c40.fnptr!(0, 0, p_DAT_0186aa30); + FhXCall.FUN_008c2c40.fnptr!(2, 0, p_DAT_0186aa70); + FhXCall.FUN_008e33a0.fnptr!(pbVar8, (byte*)0, (byte*)0); { TkWindow* DAT_023cc120 = (TkWindow*)FhUtil.get_at(0x1FCC120); ; @@ -500,7 +500,7 @@ public void UpdateGearCustomizationMenuState(TkWindow* window) { break; default: - FhXCall.h_UpdateGearCustomizationMenuState.chain_from(UpdateGearCustomizationMenuState).fnptr!(window); + FhXCall.UpdateGearCustomizationMenuState.chain_from(UpdateGearCustomizationMenuState).fnptr!(window); break_loop = true; break; } @@ -517,7 +517,7 @@ public void UpdateGearCustomizationMenuState(TkWindow* window) { short selected_idx = DAT_0186a9f4->selected_index; CustomizationMenuList* menu_list = FhUtil.ptr_at(0x1197730); int num_customizations; - CustomizationRecipe* customizations = FhXCall.h_MsGetRomKaizou.fnptr!(&num_customizations); + CustomizationRecipe* customizations = FhXCall.MsGetRomKaizou.fnptr!(&num_customizations); byte customization_id = menu_list[selected_idx].customization_id; if (customizations[customization_id].item_cost != original_kaizou_costs[customization_id]) { uint item_id = (uint)(0xC000 | customization_id); @@ -534,7 +534,7 @@ public void UpdateGearCustomizationMenuState(TkWindow* window) { // Reset kaizou.bin if (original_kaizou_costs != null) { int num_customizations; - CustomizationRecipe* customizations = FhXCall.h_MsGetRomKaizou.fnptr!(&num_customizations); + CustomizationRecipe* customizations = FhXCall.MsGetRomKaizou.fnptr!(&num_customizations); for (int i = 0; i < num_customizations; i++) { customizations[i].item_cost = original_kaizou_costs[i]; } @@ -548,7 +548,7 @@ public void TkMenuCtrlSummon(TkMenu* menu, int param_2) { uint pre_state = *state; - FhXCall.h_TkMenuCtrlSummon.chain_from(TkMenuCtrlSummon).fnptr!(menu, param_2); + FhXCall.TkMenuCtrlSummon.chain_from(TkMenuCtrlSummon).fnptr!(menu, param_2); if (*state != pre_state) { _logger.Debug($"{pre_state} -> {*state}"); @@ -559,7 +559,7 @@ public void TkMenuCtrlSummon(TkMenu* menu, int param_2) { CustomizationMenuList* menu_list = FhUtil.ptr_at(0x1197730); byte customization_id = menu_list[selected_idx].customization_id; int num_customizations; - AeonAbilityRecipe* customizations = FhXCall.h_MsGetRomSummonGrow.fnptr!(&num_customizations); + AeonAbilityRecipe* customizations = FhXCall.MsGetRomSummonGrow.fnptr!(&num_customizations); _logger.Debug($"Applied customization {get_other_item_name((uint)(0xC07D + customization_id))}"); if (customizations[customization_id].item_cost != original_sum_grow_costs[customization_id]) { uint item_id = (uint)(0xC07D + customization_id); @@ -589,9 +589,9 @@ public void DrawAeonCustomizationMenu(TkWindow* window) { } public void DrawAeonCustomizationMenu_reimplement(TkWindow* window) { - FhXCall.h_TkVU1SyncPath.fnptr!(); - FhXCall.h_FUN_008e71d0.fnptr!(7); - uint current_summon = FhXCall.h_TkMenuGetCurrentSummon.fnptr!(); + FhXCall.TkVU1SyncPath.fnptr!(); + FhXCall.FUN_008e71d0.fnptr!(7); + uint current_summon = FhXCall.TkMenuGetCurrentSummon.fnptr!(); CustomizationMenuList* menu_list = FhUtil.ptr_at(0x1197730); @@ -605,7 +605,7 @@ public void DrawAeonCustomizationMenu_reimplement(TkWindow* window) { } else { byte customization_id = menu_list[selected_idx].customization_id; int num_customizations; - AeonAbilityRecipe* customizations = FhXCall.h_MsGetRomSummonGrow.fnptr!(&num_customizations); + AeonAbilityRecipe* customizations = FhXCall.MsGetRomSummonGrow.fnptr!(&num_customizations); item_id = customizations[customization_id].item; int item_cost = customizations[customization_id].item_cost; @@ -614,35 +614,35 @@ public void DrawAeonCustomizationMenu_reimplement(TkWindow* window) { if (item_cost == 0) { fixed (byte* text = customization_string.encoded) { Vector2 pos = new Vector2(1260f, 381f).game_remap_1080p(); - FhXCall.h_ToMakeBtlEasyFont.fnptr!(text, pos.X, pos.Y, 0, 2f); + FhXCall.ToMakeBtlEasyFont.fnptr!(text, pos.X, pos.Y, 0, 2f); } } else { pos_1 = new Vector2(970f, 380f).game_remap_1080p(); - FhXCall.h_FUN_008c1c70.fnptr!((int)pos_1.X, (int)pos_1.Y, item_id, item_cost); + FhXCall.FUN_008c1c70.fnptr!((int)pos_1.X, (int)pos_1.Y, item_id, item_cost); } } pos_1 = new Vector2(210f, 226f).game_remap_1080p(); - FhXCall.h_FUN_008ff490.fnptr!(current_summon, pos_1.X, pos_1.Y); + FhXCall.FUN_008ff490.fnptr!(current_summon, pos_1.X, pos_1.Y); pos_1 = new Vector2(210f, 312f).game_remap_1080p(); pos_2 = new Vector2(740f, 48f).game_remap_1080p(); - FhXCall.h_TODrawMenuPlateXYWHType.fnptr!(pos_1.X, pos_1.Y, pos_2.X, pos_2.Y, 2); + FhXCall.TODrawMenuPlateXYWHType.fnptr!(pos_1.X, pos_1.Y, pos_2.X, pos_2.Y, 2); // Header text pos_1 = new Vector2(365f, 320f).game_remap_1080p(); pos_2 = new Vector2(430f, 36f).game_remap_1080p(); - FhXCall.h_FUN_008f8bb0.fnptr!(0xf, pos_1.X, pos_1.Y, pos_2.X, pos_2.Y); + FhXCall.FUN_008f8bb0.fnptr!(0xf, pos_1.X, pos_1.Y, pos_2.X, pos_2.Y); if (-1 < (int)item_id) { pos_1 = new Vector2(970f, 312f).game_remap_1080p(); pos_2 = new Vector2(740f, 48f).game_remap_1080p(); - FhXCall.h_TODrawMenuPlateXYWHType.fnptr!(pos_1.X, pos_1.Y, pos_2.X, pos_2.Y, 2); + FhXCall.TODrawMenuPlateXYWHType.fnptr!(pos_1.X, pos_1.Y, pos_2.X, pos_2.Y, 2); // Header text ("Item cost")? pos_1 = new Vector2(1125f, 318f).game_remap_1080p(); pos_2 = new Vector2(430f, 36f).game_remap_1080p(); - FhXCall.h_FUN_008f8bb0.fnptr!(0x10, pos_1.X, pos_1.Y, pos_2.X, pos_2.Y); + FhXCall.FUN_008f8bb0.fnptr!(0x10, pos_1.X, pos_1.Y, pos_2.X, pos_2.Y); } int iVar2 = (int)new Vector2(0, 365f).game_remap_1080p() @@ -651,7 +651,7 @@ public void DrawAeonCustomizationMenu_reimplement(TkWindow* window) { float fVar10; if (window->visible_item_offset == window->scroll_offset) { // Draw ability list - FhXCall.h_FUN_008c0f40.fnptr!( + FhXCall.FUN_008c0f40.fnptr!( iVar2, (int)(new Vector2(0, 70f).game_remap_1080p() .Y * 9.0), @@ -663,7 +663,7 @@ public void DrawAeonCustomizationMenu_reimplement(TkWindow* window) { iVar6 = 0; } else { // Draw ability list when quick scrolling (L2/R2) - FhXCall.h_FUN_008c0f40.fnptr!( + FhXCall.FUN_008c0f40.fnptr!( iVar2, (int)(new Vector2(0, 70f).game_remap_1080p() .Y * 9.0), @@ -672,7 +672,7 @@ public void DrawAeonCustomizationMenu_reimplement(TkWindow* window) { ); FUN_008cd960_Extra(window, 1, window->visible_item_offset, 0.0f, 0.0f); - FhXCall.h_FUN_008c0f40.fnptr!( + FhXCall.FUN_008c0f40.fnptr!( iVar2, (int)(new Vector2(0, 70f).game_remap_1080p() .Y * 9.0), @@ -687,14 +687,14 @@ public void DrawAeonCustomizationMenu_reimplement(TkWindow* window) { } FUN_008cd960_Extra(window, iVar6, sVar1, 0.0f, fVar10); - FhXCall.h_FUN_008c1350_DrawScissor512x416.fnptr!(); + FhXCall.FUN_008c1350_DrawScissor512x416.fnptr!(); ushort _DAT_0186a5a4 = FhUtil.get_at(0x0146a5a4); ushort _DAT_0186a5a6 = FhUtil.get_at(0x0146a5a6); - FhXCall.h_FUN_008cd9f0.fnptr!(window, _DAT_0186a5a4 + 0xc, _DAT_0186a5a6 + 1); + FhXCall.FUN_008cd9f0.fnptr!(window, _DAT_0186a5a4 + 0xc, _DAT_0186a5a6 + 1); float local_8; - FhXCall.h_ToGetCrossExtMesFontWidth.fnptr!(0, FhXCall.h_FUN_008bee80.fnptr!(5), &local_8, 0.78f, 1.0f); + FhXCall.ToGetCrossExtMesFontWidth.fnptr!(0, FhXCall.FUN_008bee80.fnptr!(5), &local_8, 0.78f, 1.0f); fVar10 = (float)(double)(new Vector2(80f, 0).game_remap_1080p() .X + local_8); @@ -718,9 +718,9 @@ public void DrawAeonCustomizationMenu_reimplement(TkWindow* window) { pos_1 = new Vector2(955f, 370f).game_remap_1080p(); pos_2 = new Vector2( 8f, 630f).game_remap_1080p(); - FhXCall.h_DrawCrossMenuScrollParts.fnptr!(pos_1.X, pos_1.Y, pos_2.X, pos_2.Y, window->visible_item_offset, window->max_visible_items, window->num_items); + FhXCall.DrawCrossMenuScrollParts.fnptr!(pos_1.X, pos_1.Y, pos_2.X, pos_2.Y, window->visible_item_offset, window->max_visible_items, window->num_items); - FhXCall.h_TODrawMenuPlateXYWHType.fnptr!( + FhXCall.TODrawMenuPlateXYWHType.fnptr!( fVar11, new Vector2(0, 925f).game_remap_1080p() .Y, @@ -736,18 +736,18 @@ public void DrawAeonCustomizationMenu_reimplement(TkWindow* window) { float uv_x1 = 0.9267578f; pos_1 = new Vector2(0f, 920f).game_remap_1080p(); pos_2 = new Vector2(64f, 64f).game_remap_1080p(); - FhXCall.h_TOMkpShapeXYWHUV.fnptr!(0xf3, fVar12, pos_1.Y, pos_2.X, pos_2.Y, uv_x1, uv_y1, uv_x2, uv_y2); + FhXCall.TOMkpShapeXYWHUV.fnptr!(0xf3, fVar12, pos_1.Y, pos_2.X, pos_2.Y, uv_x1, uv_y1, uv_x2, uv_y2); pos_1 = new Vector2(80f, 928f).game_remap_1080p(); - FhXCall.h_TOMkpCrossExtMesFontLClut.fnptr!(0, FhXCall.h_FUN_008bee80.fnptr!(5), pos_1.X + fVar12, pos_1.Y, 0, 0.78f, 1.0f); + FhXCall.TOMkpCrossExtMesFontLClut.fnptr!(0, FhXCall.FUN_008bee80.fnptr!(5), pos_1.X + fVar12, pos_1.Y, 0, 0.78f, 1.0f); - item_id = FhXCall.h_FUN_008d48e0.fnptr!(); - FhXCall.h_FUN_008d4140.fnptr!(item_id, 1); - FhXCall.h_TkMn2DrawKickSyncPacket.fnptr!(); + item_id = FhXCall.FUN_008d48e0.fnptr!(); + FhXCall.FUN_008d4140.fnptr!(item_id, 1); + FhXCall.TkMn2DrawKickSyncPacket.fnptr!(); } private void FUN_008cd960_Extra(TkWindow* window, int param_2, int menu_offset, float x, float y) { - FhXCall.h_FUN_008cd960.fnptr!(window, param_2, menu_offset, x, y); + FhXCall.FUN_008cd960.fnptr!(window, param_2, menu_offset, x, y); Vector2 pos = new(x, y); pos += new Vector2(209f + 50f, 306f).game_remap_1080p(); @@ -764,13 +764,13 @@ private void FUN_008cd960_Extra(TkWindow* window, int param_2, int menu_offset, if (0 <= curr_index && curr_index < menu_length) { if (menu_list[curr_index].customization_id != 0xFF) { int num_customizations; - AeonAbilityRecipe* customizations = FhXCall.h_MsGetRomSummonGrow.fnptr!(&num_customizations); + AeonAbilityRecipe* customizations = FhXCall.MsGetRomSummonGrow.fnptr!(&num_customizations); uint item_id = customizations[menu_list[curr_index].customization_id].item; int item_cost = customizations[menu_list[curr_index].customization_id].item_cost; if (item_cost == 0) { fixed (byte* text = customization_string.encoded) { - FhXCall.h_ToMakeBtlEasyFont.fnptr!(text, pos.X, pos.Y, 0, 0.78f); + FhXCall.ToMakeBtlEasyFont.fnptr!(text, pos.X, pos.Y, 0, 0.78f); } } } @@ -787,7 +787,7 @@ public void DrawGearCustomizationMenu_reimplement(TkWindow* window) { Vector2 pos_2; if (menu_list[selected_idx].customization_id != 0xFF) { int num_customizations; - CustomizationRecipe* customizations = FhXCall.h_MsGetRomKaizou.fnptr!(&num_customizations); + CustomizationRecipe* customizations = FhXCall.MsGetRomKaizou.fnptr!(&num_customizations); uint item_id = customizations[menu_list[selected_idx].customization_id].item; int item_cost = customizations[menu_list[selected_idx].customization_id].item_cost; @@ -796,38 +796,38 @@ public void DrawGearCustomizationMenu_reimplement(TkWindow* window) { if (item_cost == 0) { fixed (byte* text = customization_string.encoded) { Vector2 pos = new Vector2(1260f, 320f).game_remap_1080p(); - FhXCall.h_ToMakeBtlEasyFont.fnptr!(text, pos.X, pos.Y, 0, 2f); + FhXCall.ToMakeBtlEasyFont.fnptr!(text, pos.X, pos.Y, 0, 2f); } } else { pos_1 = new Vector2(970f, 319f).game_remap_1080p(); - FhXCall.h_FUN_008c1c70.fnptr!((int)pos_1.X, (int)pos_1.Y, item_id, item_cost); + FhXCall.FUN_008c1c70.fnptr!((int)pos_1.X, (int)pos_1.Y, item_id, item_cost); } // Header background pos_1 = new Vector2(970f, 252f).game_remap_1080p(); pos_2 = new Vector2(740f, 60f).game_remap_1080p(); - FhXCall.h_TODrawMenuPlateXYWHType.fnptr!(pos_1.X, pos_1.Y, pos_2.X, pos_2.Y, 2); + FhXCall.TODrawMenuPlateXYWHType.fnptr!(pos_1.X, pos_1.Y, pos_2.X, pos_2.Y, 2); // Header ("Item cost") pos_1 = new Vector2(1125f, 264f).game_remap_1080p(); pos_2 = new Vector2(430f, 36f).game_remap_1080p(); - FhXCall.h_FUN_008f8bb0.fnptr!(0x10, pos_1.X, pos_1.Y, pos_2.X, pos_2.Y); + FhXCall.FUN_008f8bb0.fnptr!(0x10, pos_1.X, pos_1.Y, pos_2.X, pos_2.Y); } //_TkMenuGetCurrentPlayer(); // Result is unused? // Abilities Header background pos_1 = new Vector2(211f, 252f).game_remap_1080p(); pos_2 = new Vector2(740f, 60f).game_remap_1080p(); - FhXCall.h_TODrawMenuPlateXYWHType.fnptr!(pos_1.X, pos_1.Y, pos_2.X, pos_2.Y, 2); + FhXCall.TODrawMenuPlateXYWHType.fnptr!(pos_1.X, pos_1.Y, pos_2.X, pos_2.Y, 2); // Header ("Abilities") pos_1 = new Vector2(366f, 264f).game_remap_1080p(); pos_2 = new Vector2(430f, 36f).game_remap_1080p(); - FhXCall.h_FUN_008f8bb0.fnptr!(7, pos_1.X, pos_1.Y, pos_2.X, pos_2.Y); + FhXCall.FUN_008f8bb0.fnptr!(7, pos_1.X, pos_1.Y, pos_2.X, pos_2.Y); if (window->visible_item_offset == window->scroll_offset) { // Draw ability list - FhXCall.h_TODrawScissorXYWH.fnptr!( + FhXCall.TODrawScissorXYWH.fnptr!( 0, (int)(new Vector2(0, 315f).game_remap_1080p() .Y), @@ -840,7 +840,7 @@ public void DrawGearCustomizationMenu_reimplement(TkWindow* window) { // Draw ability list when quick scrolling (L2/R2) short uVar5 = window->scroll_delta; // Scroll offset - FhXCall.h_FUN_008c0f40.fnptr!( + FhXCall.FUN_008c0f40.fnptr!( (int)(new Vector2(0, 315f).game_remap_1080p() .Y), (int)(new Vector2(0, 680f).game_remap_1080p() @@ -850,7 +850,7 @@ public void DrawGearCustomizationMenu_reimplement(TkWindow* window) { ); FUN_008d5d20_Extra(window, 1, window->visible_item_offset, 0, 0); - FhXCall.h_FUN_008c0f40.fnptr!( + FhXCall.FUN_008c0f40.fnptr!( (int)(new Vector2(0, 315f).game_remap_1080p() .Y), (int)(new Vector2(0, 680f).game_remap_1080p() @@ -864,10 +864,10 @@ public void DrawGearCustomizationMenu_reimplement(TkWindow* window) { FUN_008d5d20_Extra(window, 2, window->scroll_offset, 0, iVar2); } - FhXCall.h_FUN_008c1350_DrawScissor512x416.fnptr!(); + FhXCall.FUN_008c1350_DrawScissor512x416.fnptr!(); pos_1 = new Vector2(389f, 325f).game_remap_1080p(); - FhXCall.h_FUN_008d5dc0.fnptr!(window, (int)pos_1.X, (int)pos_1.Y); + FhXCall.FUN_008d5dc0.fnptr!(window, (int)pos_1.X, (int)pos_1.Y); { int uVar5 = window->num_items; @@ -875,7 +875,7 @@ public void DrawGearCustomizationMenu_reimplement(TkWindow* window) { int iVar2 = window->visible_item_offset; pos_1 = new Vector2(955f, 319f).game_remap_1080p(); pos_2 = new Vector2(8f, 675f).game_remap_1080p(); - FhXCall.h_DrawCrossMenuScrollParts.fnptr!(pos_1.X, pos_1.Y, pos_2.X, pos_2.Y, iVar2, uVar1, uVar5); + FhXCall.DrawCrossMenuScrollParts.fnptr!(pos_1.X, pos_1.Y, pos_2.X, pos_2.Y, iVar2, uVar1, uVar5); } { @@ -883,12 +883,12 @@ public void DrawGearCustomizationMenu_reimplement(TkWindow* window) { uint _DAT_0186a9f0 = FhUtil.get_at(0x146A9F0); int iVar2 = *(short*)(_DAT_0186a9f0 + 0x48); pos_1 = new Vector2(970f, 659f).game_remap_1080p(); - FhXCall.h_FUN_008d6630.fnptr!((int)pos_1.X, (int)pos_1.Y, iVar2); + FhXCall.FUN_008d6630.fnptr!((int)pos_1.X, (int)pos_1.Y, iVar2); } } private void FUN_008d5d20_Extra(TkWindow* window, int param_2, int menu_offset, int x, int y) { - FhXCall.h_FUN_008d5d20.fnptr!(window, param_2, menu_offset, x, y); + FhXCall.FUN_008d5d20.fnptr!(window, param_2, menu_offset, x, y); Vector2 pos = new(x, y); pos += new Vector2(209f + 50f, 255f).game_remap_1080p(); @@ -905,13 +905,13 @@ private void FUN_008d5d20_Extra(TkWindow* window, int param_2, int menu_offset, if (0 <= curr_index && curr_index < menu_length) { if (menu_list[curr_index].customization_id != 0xFF) { int num_customizations; - CustomizationRecipe* customizations = FhXCall.h_MsGetRomKaizou.fnptr!(&num_customizations); + CustomizationRecipe* customizations = FhXCall.MsGetRomKaizou.fnptr!(&num_customizations); uint item_id = customizations[menu_list[curr_index].customization_id].item; int item_cost = customizations[menu_list[curr_index].customization_id].item_cost; if (item_cost == 0) { fixed (byte* text = customization_string.encoded) { - FhXCall.h_ToMakeBtlEasyFont.fnptr!(text, pos.X, pos.Y, 0, 0.78f); + FhXCall.ToMakeBtlEasyFont.fnptr!(text, pos.X, pos.Y, 0, 0.78f); } } } @@ -924,7 +924,7 @@ private void FUN_008d5d20_Extra(TkWindow* window, int param_2, int menu_offset, public static TkWindow* MyWindow; public static void CreateMyWindow(Equipment* gear) { - MyWindow = FhXCall.h_TkMenuMainAllocWindow.fnptr!(); + MyWindow = FhXCall.TkMenuMainAllocWindow.fnptr!(); MyWindow->num_items = gear->slot_count; MyWindow->max_visible_items = 4; MyWindow->selected_index = 0; @@ -932,7 +932,7 @@ public static void CreateMyWindow(Equipment* gear) { MyWindow->fn_init = &MyWindow_Init; MyWindow->fn_state = &MyWindow_State; MyWindow->fn_render = &MyWindow_Render; - FhXCall.h_TkMenuMainRegistWindow.fnptr!(MyWindow); + FhXCall.TkMenuMainRegistWindow.fnptr!(MyWindow); } [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] @@ -951,17 +951,17 @@ public static void MyWindow_State(TkWindow* window) { return; case 1: - if (Globals.Input.up.just_pressed && 0 < window->selected_index) { - FhXCall.h_SndSepPlaySimple.fnptr!(0x80000001); + if (Globals.Input.up.is_pressed && 0 < window->selected_index) { + FhXCall.SndSepPlaySimple.fnptr!(0x80000001); window->selected_index--; - } else if (Globals.Input.down.just_pressed && window->selected_index < window->num_items - 1) { - FhXCall.h_SndSepPlaySimple.fnptr!(0x80000001); + } else if (Globals.Input.down.is_pressed && window->selected_index < window->num_items - 1) { + FhXCall.SndSepPlaySimple.fnptr!(0x80000001); window->selected_index++; - } else if (Globals.Input.confirm.just_pressed) { - FhXCall.h_SndSepPlaySimple.fnptr!(0x80000001); + } else if (Globals.Input.confirm.is_pressed) { + FhXCall.SndSepPlaySimple.fnptr!(0x80000001); window->current_state = 2; - } else if (Globals.Input.cancel.just_pressed) { - FhXCall.h_SndSepPlaySimple.fnptr!(0x80000004); + } else if (Globals.Input.cancel.is_pressed) { + FhXCall.SndSepPlaySimple.fnptr!(0x80000004); window->current_state = 3; } @@ -986,11 +986,11 @@ public static void MyWindow_State(TkWindow* window) { [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] public static void MyWindow_Render(TkWindow* window) { Vector2 pos = new Vector2(970 + 150, 735 + 12 + 68 * window->selected_index).game_remap_1080p(); - FhXCall.h_TkMn2DrawCrossCursor.fnptr!(pos.X, pos.Y, 0); + FhXCall.TkMn2DrawCrossCursor.fnptr!(pos.X, pos.Y, 0); } public static bool FUN_008d5720(uint gear_id, int param_2) { - Equipment* gear = FhXCall.h_MsGetSaveWeapon.fnptr!(gear_id, 0); + Equipment* gear = FhXCall.MsGetSaveWeapon.fnptr!(gear_id, 0); bool can_customize = false; if (gear->exists && !gear->is_hidden && gear->slot_count > 0) { diff --git a/src/gui/debugWindow.cs b/src/gui/debugWindow.cs index e402d60..3de4bd6 100644 --- a/src/gui/debugWindow.cs +++ b/src/gui/debugWindow.cs @@ -167,12 +167,12 @@ private void render_experiments() { } if (ImGui.Checkbox("Original soundtrack?", &save_data->soundtrack_type)) { - FhXCall.h_FUN_008cc120.fnptr!(save_data->soundtrack_type ? 1 : 0); + FhXCall.FUN_008cc120.fnptr!(save_data->soundtrack_type ? 1 : 0); } - ImGui.InputScalarN("frontline? (0x1FC5)", ImGuiDataType.U8, Battle.btl->__0x1FC5, 7); - ImGui.InputScalarN("frontline? (0x1FCC)", ImGuiDataType.U8, Battle.btl->__0x1FCC, 7); - ImGui.InputScalarN("backline? (0x1FD3)", ImGuiDataType.U8, Battle.btl->__0x1FD3, 17); + ImGui.InputScalarN("frontline? (0x1FC5)", ImGuiDataType.U8, &Battle.btl->__0x1FC5, 7); + ImGui.InputScalarN("frontline? (0x1FCC)", ImGuiDataType.U8, &Battle.btl->__0x1FCC, 7); + ImGui.InputScalarN("backline? (0x1FD3)", ImGuiDataType.U8, &Battle.btl->__0x1FD3, 17); @@ -361,7 +361,7 @@ private void render_experiments() { // localizationManager->voice = voice_language; // // nint _FmodManager = FhUtil.get_at(0x008E9000); - // //FhXCall.h_FfxFmod_soundInit.fnptr!(*(nint*)(_FmodManager+8)); + // //FhXCall.FfxFmod_soundInit.fnptr!(*(nint*)(_FmodManager+8)); // // nint ffxFmod = *(nint*)(_FmodManager + 8); // @@ -369,7 +369,7 @@ private void render_experiments() { // // *(byte*)(fmodVoice + 4) = (byte)voice_language; // - // FhXCall.h_FmodVoice_initList.fnptr!(fmodVoice); + // FhXCall.FmodVoice_initList.fnptr!(fmodVoice); // // int dataChange_result = FmodVoice_dataChange(fmodVoice, Globals.save_data->current_room_id, *(nint*)(ffxFmod + 4)); // if (dataChange_result != 0) { @@ -451,7 +451,7 @@ private void render_sphere_grid_editor() { for (int i = 0; i < 7; i++) { if (ImGui.Button($"{id_to_character[i]}: {(clickedNode->activated_by & (1 << i)) != 0}")) { clickedNode->activated_by ^= (byte)(1 << i); - FhXCall.h_eiAbmParaGet.fnptr!(); + FhXCall.eiAbmParaGet.fnptr!(); SphereGrid.lpamng->should_update = 1; // Setting to clickedNodeIndex only turns off light if no character has it activated. Setting to -1 correctly turns on/off node itself, but not surrounding lights (per character). SphereGrid.lpamng->should_update_node = -1; @@ -795,7 +795,7 @@ private void render_debug_tab() { ImGui.InputScalar("launchBattleInput", ImGuiDataType.U32, battle_input, &p_step, &p_step_fast, "%x"); } if (ImGui.Button("launchBattleButton")) { - FhXCall.h_MsBattleLabelExe.fnptr!(LaunchBattleInput, 1, 1); + FhXCall.MsBattleLabelExe.fnptr!(LaunchBattleInput, 1, 1); } #endif } diff --git a/src/gui/recent_items.cs b/src/gui/recent_items.cs index 56b0cff..a30d276 100644 --- a/src/gui/recent_items.cs +++ b/src/gui/recent_items.cs @@ -81,25 +81,27 @@ public enum RecentItemsTextAlignment { // Accessing settings through `FhModule.settings` goes through an array, which is rather unpleasant // So `RecentItemsSettings` exists to provide flat access to all settings public class RecentItemsSettings { + //TODO: Uncomment these when the relevant FhSetting types are implemented + public readonly FhSettingToggle display_items = new("display_items", true); public readonly FhSettingToggle display_only_personal = new("display_only_personal", false); public readonly FhSettingToggle display_locations = new("display_locations", true); public readonly FhSettingNumber item_count = new("item_count", 4, 0, 10, 1); - - //TODO: Implement smooth scrolling - public readonly FhSettingDropdown animation = new("interpolation", RecentItemsInterpolation.SMOOTH); - - //TODO: Implement old items fading away + // + // //TODO: Implement smooth scrolling + // public readonly FhSettingDropdown animation = new("interpolation", RecentItemsInterpolation.SMOOTH); + // + // //TODO: Implement old items fading away public readonly FhSettingNumber fade_after = new("fade_after", 10.0f, 0.0f, 60.0f, 1.0f); - public readonly FhSettingDropdown fade_method = new("fade_method", RecentItemsFadeMethod.SLIDE); - - //TODO: Implement different background behavior - public readonly FhSettingDropdown background = new("background", RecentItemsBackground.NONE); - - //TODO: Implement configurable positioning + // public readonly FhSettingDropdown fade_method = new("fade_method", RecentItemsFadeMethod.SLIDE); + // + // //TODO: Implement different background behavior + // public readonly FhSettingDropdown background = new("background", RecentItemsBackground.NONE); + // + // //TODO: Implement configurable positioning public readonly FhSettingNumber pos_x = new("x", 0.05f, 0.0f, 1.0f, 0.1f); public readonly FhSettingNumber pos_y = new("y", 0.34f, 0.0f, 1.0f, 0.1f); - public readonly FhSettingDropdown alignment = new("alignment", RecentItemsTextAlignment.LEFT); + // public readonly FhSettingDropdown alignment = new("alignment", RecentItemsTextAlignment.LEFT); } public RecentItemsSettings module_settings = new(); diff --git a/src/hooks.cs b/src/hooks.cs index 7c94c6c..3511d7f 100644 --- a/src/hooks.cs +++ b/src/hooks.cs @@ -20,78 +20,78 @@ namespace ArchipelagoFFX; public unsafe partial class ArchipelagoFFXModule { - private FhMethodHandle h_Map_800F + private FhMethodHandle h_Map_800F => new(new FhMethodLocation("FFX.exe", 0x51B1A0)); - private FhMethodHandle h_Map_show2DLayerResultInt + private FhMethodHandle h_Map_show2DLayerResultInt => new(new FhMethodLocation("FFX.exe", 0x51B1A0)); - private FhMethodHandle h_Map_hide2DLayerResultInt + private FhMethodHandle h_Map_hide2DLayerResultInt => new(new FhMethodLocation("FFX.exe", 0x51B1E0)); - private FhMethodHandle h_Common_obtainBrotherhoodRetInt + private FhMethodHandle h_Common_obtainBrotherhoodRetInt => new(new FhMethodLocation("FFX.exe", 0x459A40)); - private FhMethodHandle h_Common_obtainTreasureInit + private FhMethodHandle h_Common_obtainTreasureInit => new(new FhMethodLocation("FFX.exe", 0x45A740)); - private FhMethodHandle h_Common_removePartyMemberLongTerm + private FhMethodHandle h_Common_removePartyMemberLongTerm => new(new FhMethodLocation("FFX.exe", 0x45AAF0)); - private FhMethodHandle h_Common_setPrimerCollected + private FhMethodHandle h_Common_setPrimerCollected => new(new FhMethodLocation("FFX.exe", 0x45AB30)); - private FhMethodHandle h_Common_pushParty + private FhMethodHandle h_Common_pushParty => new(new FhMethodLocation("FFX.exe", 0x45B350)); - private FhMethodHandle h_Common_popParty + private FhMethodHandle h_Common_popParty => new(new FhMethodLocation("FFX.exe", 0x45B3C0)); - private FhMethodHandle h_Common_addPartyMember + private FhMethodHandle h_Common_addPartyMember => new(new FhMethodLocation("FFX.exe", 0x45B5A0)); - private FhMethodHandle h_Common_removePartyMember + private FhMethodHandle h_Common_removePartyMember => new(new FhMethodLocation("FFX.exe", 0x45B6C0)); - private FhMethodHandle h_Common_putPartyMemberInSlot + private FhMethodHandle h_Common_putPartyMemberInSlot => new(new FhMethodLocation("FFX.exe", 0x45BC90)); - private FhMethodHandle h_Common_0043 + private FhMethodHandle h_Common_0043 => new(new FhMethodLocation("FFX.exe", 0x45C810)); - private FhMethodHandle h_Common_linkFieldToBattleActor + private FhMethodHandle h_Common_linkFieldToBattleActor => new(new FhMethodLocation("FFX.exe", 0x45CA00)); - private FhMethodHandle h_Common_playFieldVoiceLineInit + private FhMethodHandle h_Common_playFieldVoiceLineInit => new(new FhMethodLocation("FFX.exe", 0x45CB70)); - private FhMethodHandle h_Common_playFieldVoiceLineExec + private FhMethodHandle h_Common_playFieldVoiceLineExec => new(new FhMethodLocation("FFX.exe", 0x45CD30)); - private FhMethodHandle h_Common_loadModel + private FhMethodHandle h_Common_loadModel => new(new FhMethodLocation("FFX.exe", 0x45CE70)); - private FhMethodHandle h_Common_playFieldVoiceLineResultInt + private FhMethodHandle h_Common_playFieldVoiceLineResultInt => new(new FhMethodLocation("FFX.exe", 0x45D150)); - private FhMethodHandle h_Common_00D6Init + private FhMethodHandle h_Common_00D6Init => new(new FhMethodLocation("FFX.exe", 0x45D520)); - private FhMethodHandle h_Common_00D6Exec + private FhMethodHandle h_Common_00D6Exec => new(new FhMethodLocation("FFX.exe", 0x45D820)); - private FhMethodHandle h_Common_00D6ResultInt + private FhMethodHandle h_Common_00D6ResultInt => new(new FhMethodLocation("FFX.exe", 0x45DCF0)); - private FhMethodHandle h_Common_01D1Init + private FhMethodHandle h_Common_01D1Init => new(new FhMethodLocation("FFX.exe", 0x45FB60)); - private FhMethodHandle h_Common_01D1Exec + private FhMethodHandle h_Common_01D1Exec => new(new FhMethodLocation("FFX.exe", 0x45FDB0)); - private FhMethodHandle h_Common_setWeaponInvisible + private FhMethodHandle h_Common_setWeaponInvisible => new(new FhMethodLocation("FFX.exe", 0x456770)); - private FhMethodHandle h_Common_obtainTreasureSilentlyInit + private FhMethodHandle h_Common_obtainTreasureSilentlyInit => new(new FhMethodLocation("FFX.exe", 0x4579E0)); - private FhMethodHandle h_CT_RetInt_0065 + private FhMethodHandle h_CT_RetInt_0065 => new(new FhMethodLocation("FFX.exe", 0x457F60)); - private FhMethodHandle h_Common_transitionToMap + private FhMethodHandle h_Common_transitionToMap => new(new FhMethodLocation("FFX.exe", 0x4580C0)); - private FhMethodHandle h_Common_warpToMap + private FhMethodHandle h_Common_warpToMap => new(new FhMethodLocation("FFX.exe", 0x458370)); - private FhMethodHandle h_CT_RetInt_006A + private FhMethodHandle h_CT_RetInt_006A => new(new FhMethodLocation("FFX.exe", 0x4589F0)); - private FhMethodHandle h_CT_RetInt_01B6 + private FhMethodHandle h_CT_RetInt_01B6 => new(new FhMethodLocation("FFX.exe", 0x4594D0)); - private FhMethodHandle h_Common_upgradeBrotherhoodRetInt + private FhMethodHandle h_Common_upgradeBrotherhoodRetInt => new(new FhMethodLocation("FFX.exe", 0x4596A0)); - private FhMethodHandle h_SgEvent_showModularMenuInit + private FhMethodHandle h_SgEvent_showModularMenuInit => new(new FhMethodLocation("FFX.exe", 0x678210)); public static int* takara_pointer => FhUtil.ptr_at(0xD35FEC); public static int* buki_get_pointer => FhUtil.ptr_at(0xD35FF4); - public static char* get_event_name(uint event_id) => FhXCall.h_AtelGetEventName.fnptr!(event_id); - public static int atel_stack_pop(int* arg1, AtelStack* atelStack) => FhXCall.h_AtelPopStackInteger.fnptr!(arg1, atelStack); + public static char* get_event_name(uint event_id) => FhXCall.AtelGetEventName.fnptr!(event_id); + public static int atel_stack_pop(int* arg1, AtelStack* atelStack) => FhXCall.AtelPopStackInteger.fnptr!(arg1, atelStack); - public static void AtelSetUpCallFunc(int id, nint nameSpacePtr) => FhXCall.h_AtelSetUpCallFunc.fnptr!(id, nameSpacePtr); + public static void AtelSetUpCallFunc(int id, nint nameSpacePtr) => FhXCall.AtelSetUpCallFunc.fnptr!(id, nameSpacePtr); public void init_hooks() { foreach (byte[] script in customScripts) { @@ -112,16 +112,16 @@ public int h_Map_800F_reimpl(AtelBasicWorker* work, int* storage, AtelStack* ate //public bool h_openFile(nint _this, nint filename, bool readOnly, nint unknown_1, nint unknown_2, nint unknown_3) { // string x = Marshal.PtrToStringAnsi(filename)!; // _logger.Debug($"{_this}, {x}, {readOnly}, {unknown_1}, {unknown_2}, {unknown_3}"); - // var result = FhXCall.h_Phyre_PSerialization_PStreamFileWin32_Open.chain_from(h_openFile).fnptr!(_this, filename, readOnly, unknown_1, unknown_2, unknown_3); + // var result = FhXCall.Phyre_PSerialization_PStreamFileWin32_Open.chain_from(h_openFile).fnptr!(_this, filename, readOnly, unknown_1, unknown_2, unknown_3); // _logger.Debug($"{result}, {*(int*)_this}, {*(int*)((int)_this + 4)}"); // return result; //} public uint h_FUN_0070aec0(nint _this, uint voice_id, uint param_2) { - return FhXCall.h_FUN_0070aec0.chain_from(h_FUN_0070aec0).fnptr!(_this, voice_id, param_2); + return FhXCall.FUN_0070aec0.chain_from(h_FUN_0070aec0).fnptr!(_this, voice_id, param_2); } - private FhGCall.CT_RetInt[] custom_ct_retints; + private FhGCall.d_CT_RetInt[] custom_ct_retints; private int turnAroundScriptLength; private byte* turnAroundScript; private void init_custom_atel() { @@ -177,42 +177,42 @@ private void init_custom_atel() { } private bool hook() { - return h_Common_obtainTreasureInit.hook(this, Common_obtainTreasureInit) - && h_Common_obtainTreasureSilentlyInit.hook(this, Common_obtainTreasureSilentlyInit) + return h_Common_obtainTreasureInit.hook(this, Common_obtainTreasureInit) + && h_Common_obtainTreasureSilentlyInit.hook(this, Common_obtainTreasureSilentlyInit) && h_Common_obtainBrotherhoodRetInt.hook(this, Common_obtainBrotherhoodRetInt) && h_Common_setPrimerCollected.hook(this, Common_setPrimerCollected) - && h_Common_transitionToMap.hook(this, Common_transitionToMap) + && h_Common_transitionToMap.hook(this, Common_transitionToMap) && h_Common_warpToMap.hook(this, Common_warpToMap) && h_SgEvent_showModularMenuInit.hook(this, SgEvent_showModularMenuInit) - && h_Common_addPartyMember.hook(this, Common_addPartyMember) - && h_Common_removePartyMember.hook(this, Common_removePartyMember) - && h_Common_removePartyMemberLongTerm.hook(this, Common_removePartyMemberLongTerm) + && h_Common_addPartyMember.hook(this, Common_addPartyMember) + && h_Common_removePartyMember.hook(this, Common_removePartyMember) + && h_Common_removePartyMemberLongTerm.hook(this, Common_removePartyMemberLongTerm) && h_Common_setWeaponInvisible.hook(this, Common_setWeaponInvisible) - && h_Common_putPartyMemberInSlot.hook(this, Common_putPartyMemberInSlot) - && h_Common_pushParty.hook(this, Common_pushParty) + && h_Common_putPartyMemberInSlot.hook(this, Common_putPartyMemberInSlot) + && h_Common_pushParty.hook(this, Common_pushParty) && h_Common_popParty.hook(this, Common_popParty) - && FhXCall.h_TkSetLegendAbility.hook(this, TkSetLegendAbility) - && FhXCall.h_AtelEventSetUp.hook(this, AtelEventSetUp) - && FhXCall.h_MsBattleExe.hook(this, MsBattleExe) - && FhXCall.h_FUN_00791820.hook(this, FUN_00791820) - && FhXCall.h_MsApUp.hook(this, MsApUp) - && FhXCall.h_MsBtlReadSetScene.hook(this, MsBtlReadSetScene) - && FhXCall.h_eiAbmParaGet.hook(this, eiAbmParaGet) - && FhXCall.h_MsSetSaveParam.hook(this, MsSetSaveParam) - && FhXCall.h_MsSetRamChrParam.hook(this, MsSetRamChrParam) - && FhXCall.h_FUN_0086bec0.hook(this, FUN_0086bec0) - && FhXCall.h_FUN_0086bea0.hook(this, FUN_0086bea0) // Custom strings - && FhXCall.h_graphicInitFMVPlayer.hook(this, graphicInitFMVPlayer) - && FhXCall.h_FmodVoice_dataChange.hook(this, FmodVoice_dataChange) - && FhXCall.h_AtelInitTotal.hook(this, AtelInitTotal) - && FhXCall.h_LocalizationManager_Initialize.hook(this, LocalizationManager_Initialize) - && FhXCall.h_TkMenuAppearMainCmdWindow.hook(this, TkMenuAppearMainCmdWindow) - && FhXCall.h_FUN_008c2370.hook(this, PrepareMenuList) - && FhXCall.h_UpdateGearCustomizationMenuState.hook(this, UpdateGearCustomizationMenuState) - && FhXCall.h_DrawGearCustomizationMenu.hook(this, DrawGearCustomizationMenu) - && FhXCall.h_TkMenuCtrlSummon.hook(this, TkMenuCtrlSummon) - && FhXCall.h_FUN_008cdb70.hook(this, DrawAeonCustomizationMenu) - && FhXCall.h_FUN_008d5720.hook(this, FUN_008d5720); + && FhXCall.TkSetLegendAbility.hook(this, TkSetLegendAbility) + && FhXCall.AtelEventSetUp.hook(this, AtelEventSetUp) + && FhXCall.MsBattleExe.hook(this, MsBattleExe) + && FhXCall.FUN_00791820.hook(this, FUN_00791820) + && FhXCall.MsApUp.hook(this, MsApUp) + && FhXCall.MsBtlReadSetScene.hook(this, MsBtlReadSetScene) + && FhXCall.eiAbmParaGet.hook(this, eiAbmParaGet) + && FhXCall.MsSetSaveParam.hook(this, MsSetSaveParam) + && FhXCall.MsSetRamChrParam.hook(this, MsSetRamChrParam) + && FhXCall.FUN_0086bec0.hook(this, FUN_0086bec0) + && FhXCall.FUN_0086bea0.hook(this, FUN_0086bea0) // Custom strings + && FhXCall.graphicInitFMVPlayer.hook(this, graphicInitFMVPlayer) + && FhXCall.FmodVoice_dataChange.hook(this, FmodVoice_dataChange) + && FhXCall.AtelInitTotal.hook(this, AtelInitTotal) + && FhXCall.LocalizationManager_Initialize.hook(this, LocalizationManager_Initialize) + && FhXCall.TkMenuAppearMainCmdWindow.hook(this, TkMenuAppearMainCmdWindow) + && FhXCall.FUN_008c2370.hook(this, PrepareMenuList) + && FhXCall.UpdateGearCustomizationMenuState.hook(this, UpdateGearCustomizationMenuState) + && FhXCall.DrawGearCustomizationMenu.hook(this, DrawGearCustomizationMenu) + && FhXCall.TkMenuCtrlSummon.hook(this, TkMenuCtrlSummon) + && FhXCall.FUN_008cdb70.hook(this, DrawAeonCustomizationMenu) + && FhXCall.FUN_008d5720.hook(this, FUN_008d5720); // && _FUN_00656c90.hook() && _FUN_0065ee30.hook(); // && _openFile.hook() && _FUN_0070aec0.hook(); // && _MsCheckLeftWindow.hook() && _MsCheckUseCommand.hook() && _TOBtlDrawStatusLimitGauge.hook(); @@ -282,7 +282,7 @@ private void move(byte* code_ptr, uint sourceOffset, int moveBy, int size) { _logger.Debug(customStrings[custom_index].decoded); } else { // May crash if called with invalid index - result = FhXCall.h_FUN_0086bec0.chain_from(FUN_0086bec0).fnptr!(param_1); + result = FhXCall.FUN_0086bec0.chain_from(FUN_0086bec0).fnptr!(param_1); } return result; @@ -295,7 +295,7 @@ private short FUN_0086bea0(int param_1) { result = customStrings[custom_index].metadata; } else { - result = FhXCall.h_FUN_0086bea0.chain_from(FUN_0086bea0).fnptr!(param_1); + result = FhXCall.FUN_0086bea0.chain_from(FUN_0086bea0).fnptr!(param_1); } return result; @@ -1157,7 +1157,7 @@ AtelOp.PUSHII .build(0x50AB), private static Dictionary<(int, int), uint> originalEntryPoints = new(); private static string current_event_name = ""; private void AtelEventSetUp(int event_id) { - FhXCall.h_AtelEventSetUp.chain_from(AtelEventSetUp).fnptr!(event_id); + FhXCall.AtelEventSetUp.chain_from(AtelEventSetUp).fnptr!(event_id); foreach (NativeCustomString customString in cached_strings) { customString.Free(); @@ -2117,7 +2117,7 @@ AtelOp.PUSHII .build( 0), private void Common_obtainTreasureInit(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int treasure_id = atelStack->values.as_int()[1]; _logger.Info($"obtain_treasure: {treasure_id}"); - //FhXCall.h_Common_obtainTreasureInit.chain_from(h_Common_obtainTreasureInit).fnptr!(work, storage, atelStack); + //FhXCall.Common_obtainTreasureInit.chain_from(h_Common_obtainTreasureInit).fnptr!(work, storage, atelStack); obtainTreasureInitReimplement(work, storage, atelStack); } @@ -2129,15 +2129,15 @@ private void obtainTreasureInitReimplement(AtelBasicWorker* work, int* storage, int window_id = atelStack->pop_int(); _logger.Debug($"window_id:{window_id}, treasure_id:{treasure_id}"); - FhXCall.h_SndSepPlaySimple.fnptr!(0x80000026); - AtelWorkerController* pAVar2 = (AtelWorkerController*)FhXCall.h_AtelGetCurCtrlWork.fnptr!(); + FhXCall.SndSepPlaySimple.fnptr!(0x80000026); + AtelWorkerController* pAVar2 = (AtelWorkerController*)FhXCall.AtelGetCurCtrlWork.fnptr!(); ((byte*)pAVar2)[3] |= 4; - FhXCall.h_MsFieldItemGet.fnptr!(treasure_id); - FhXCall.h_FUN_008b8910.fnptr!(window_id, 0, 0); - FhXCall.h_FUN_008b8910.fnptr!(window_id, 1, 1); + FhXCall.MsFieldItemGet.fnptr!(treasure_id); + FhXCall.FUN_008b8910.fnptr!(window_id, 0, 0); + FhXCall.FUN_008b8910.fnptr!(window_id, 1, 1); bool gear_inv_is_full = false; uint weapon_id = 0; - byte* message_text = FhXCall.h_TkBtlEndGetText.fnptr!(0x401d); // "Nothing" + byte* message_text = FhXCall.TkBtlEndGetText.fnptr!(0x401d); // "Nothing" if (item_locations.treasure.TryGetValue(treasure_id, out var item)) { if (_client!.sendLocation(treasure_id, ArchipelagoClientModule.ArchipelagoLocationType.Treasure)) { @@ -2150,7 +2150,7 @@ private void obtainTreasureInitReimplement(AtelBasicWorker* work, int* storage, cached_strings.Add(name); item_name = name.encoded; if (item.id != 0) { - message_text = FhXCall.h_TkBtlEndGetText.fnptr!(0x4018); // "Obtained %0!" + message_text = FhXCall.TkBtlEndGetText.fnptr!(0x4018); // "Obtained %0!" } else { NativeCustomString sent_text = new NativeCustomString("Sent {VAR:00}!"); //CustomString sent_text = new CustomString("Sent {VAR:00} to {VAR:01}!"); @@ -2169,13 +2169,13 @@ private void obtainTreasureInitReimplement(AtelBasicWorker* work, int* storage, } else if (Battle.reward_data->item_count != 0) { - FhXCall.h_TkMsGetRomItem.fnptr!(Battle.reward_data->items[0], (int*)&item_name); - FhXCall.h_FUN_008b8930.fnptr!(window_id, 1, Battle.reward_data->items_amounts[0]); + FhXCall.TkMsGetRomItem.fnptr!(Battle.reward_data->items[0], (int*)&item_name); + FhXCall.FUN_008b8930.fnptr!(window_id, 1, Battle.reward_data->items_amounts[0]); if (Battle.reward_data->items_amounts[0] == 1) { - message_text = FhXCall.h_TkBtlEndGetText.fnptr!(0x4018); // "Obtained %0!" + message_text = FhXCall.TkBtlEndGetText.fnptr!(0x4018); // "Obtained %0!" } else { - message_text = FhXCall.h_TkBtlEndGetText.fnptr!(0x4019); // "Obtained %0 x%1!" + message_text = FhXCall.TkBtlEndGetText.fnptr!(0x4019); // "Obtained %0 x%1!" } byte[] decoded = new byte[FhEncoding.compute_decode_buffer_size(new ReadOnlySpan(item_name, 1000))]; @@ -2184,27 +2184,27 @@ private void obtainTreasureInitReimplement(AtelBasicWorker* work, int* storage, //string decoded = FhEncoding.Us.to_string(item_name); _logger.Info(Encoding.UTF8.GetString(decoded, 0, decoded_length)); - FhXCall.h_MsSaveItemUse.fnptr!(Battle.reward_data->items[0], Battle.reward_data->items_amounts[0]); + FhXCall.MsSaveItemUse.fnptr!(Battle.reward_data->items[0], Battle.reward_data->items_amounts[0]); } else if (Battle.reward_data->key_item_count != 0) { - item_name = FhXCall.h_MsImportantName.fnptr!(Battle.reward_data->key_item); - message_text = FhXCall.h_TkBtlEndGetText.fnptr!(0x4017); // "Obtained %0!" - FhXCall.h_TkMsImportantSet.fnptr!(Battle.reward_data->key_item); + item_name = FhXCall.MsImportantName.fnptr!(Battle.reward_data->key_item); + message_text = FhXCall.TkBtlEndGetText.fnptr!(0x4017); // "Obtained %0!" + FhXCall.TkMsImportantSet.fnptr!(Battle.reward_data->key_item); } else if (Battle.reward_data->gear_count != 0) { weapon_id = Battle.reward_data->gear_inv_idx; - message_text = FhXCall.h_TkBtlEndGetText.fnptr!(0x4016); // "Obtained %0!" - Equipment* weapon = (Equipment*)FhXCall.h_MsGetSaveWeapon.fnptr!(weapon_id, (nint)(&item_name)); - int inv_id = FhXCall.h_FUN_007ab930.fnptr!(weapon); // giveWeapon? + message_text = FhXCall.TkBtlEndGetText.fnptr!(0x4016); // "Obtained %0!" + Equipment* weapon = (Equipment*)FhXCall.MsGetSaveWeapon.fnptr!(weapon_id, (nint)(&item_name)); + int inv_id = FhXCall.FUN_007ab930.fnptr!(weapon); // giveWeapon? gear_inv_is_full = inv_id == 0; } else if (Battle.reward_data->gil != 0) { - FhXCall.h_FUN_008b8930.fnptr!(window_id, 1, (int)Battle.reward_data->gil); - message_text = FhXCall.h_TkBtlEndGetText.fnptr!(0x401a); // "Obtained %1 Gil!" - FhXCall.h_MsPayGIL.fnptr!(-(int)Battle.reward_data->gil); + FhXCall.FUN_008b8930.fnptr!(window_id, 1, (int)Battle.reward_data->gil); + message_text = FhXCall.TkBtlEndGetText.fnptr!(0x401a); // "Obtained %1 Gil!" + FhXCall.MsPayGIL.fnptr!(-(int)Battle.reward_data->gil); } - FhXCall.h_FUN_008b8930.fnptr!(window_id, 0, (int)item_name); + FhXCall.FUN_008b8930.fnptr!(window_id, 0, (int)item_name); atelStack->push_int(window_id); atelStack->push_int(0x100); @@ -2212,7 +2212,7 @@ private void obtainTreasureInitReimplement(AtelBasicWorker* work, int* storage, atelStack->push_int(4); h_CT_RetInt_0065.fnptr!(work, storage, atelStack); - TOMesWinWork* mesageWindowWorker = FhXCall.h_AtelGetMesWinWork.fnptr!(window_id); + TOMesWinWork* mesageWindowWorker = FhXCall.AtelGetMesWinWork.fnptr!(window_id); mesageWindowWorker->_0x20 = 0; mesageWindowWorker->text = message_text; mesageWindowWorker->_0xc = message_text; @@ -2229,23 +2229,23 @@ private void obtainTreasureInitReimplement(AtelBasicWorker* work, int* storage, storage[3] = (int)weapon_id; if (!gear_inv_is_full) { - FhXCall.h_MsBtlGetInit.fnptr!(); + FhXCall.MsBtlGetInit.fnptr!(); } - FhXCall.h_FUN_0086a0c0.fnptr!(); + FhXCall.FUN_0086a0c0.fnptr!(); mesageWindowWorker->_0x1d |= 0x10; } private void Common_obtainTreasureSilentlyInit(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int treasure_id = atelStack->values.as_int()[0]; _logger.Info($"obtain_treasure_silently: {treasure_id}"); - //FhXCall.h_Common_obtainTreasureSilentlyInit.chain_from(h_Common_obtainTreasureSilentlyInit).fnptr!(work, storage, atelStack); + //FhXCall.Common_obtainTreasureSilentlyInit.chain_from(h_Common_obtainTreasureSilentlyInit).fnptr!(work, storage, atelStack); obtainTreasureSilentlyInitReimplement(work, storage, atelStack); } private void obtainTreasureSilentlyInitReimplement(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { int treasure_id = atelStack->pop_int(); - FhXCall.h_MsFieldItemGet.fnptr!(treasure_id); + FhXCall.MsFieldItemGet.fnptr!(treasure_id); bool gear_inv_is_full = false; uint weapon_id = 0; @@ -2256,26 +2256,26 @@ private void obtainTreasureSilentlyInitReimplement(AtelBasicWorker* work, int* s } else if (Battle.reward_data->item_count != 0) { - FhXCall.h_MsSaveItemUse.fnptr!(Battle.reward_data->items[0], Battle.reward_data->items_amounts[0]); + FhXCall.MsSaveItemUse.fnptr!(Battle.reward_data->items[0], Battle.reward_data->items_amounts[0]); } else if (Battle.reward_data->key_item_count != 0) { - FhXCall.h_TkMsImportantSet.fnptr!(Battle.reward_data->key_item); + FhXCall.TkMsImportantSet.fnptr!(Battle.reward_data->key_item); } else if (Battle.reward_data->gear_count != 0) { weapon_id = Battle.reward_data->gear_inv_idx; - Equipment* weapon = FhXCall.h_MsGetSaveWeapon.fnptr!(weapon_id, 0); - int inv_id = FhXCall.h_FUN_007ab930.fnptr!(weapon); // giveWeapon? + Equipment* weapon = FhXCall.MsGetSaveWeapon.fnptr!(weapon_id, 0); + int inv_id = FhXCall.FUN_007ab930.fnptr!(weapon); // giveWeapon? gear_inv_is_full = inv_id == 0; } else if (Battle.reward_data->gil != 0) { - FhXCall.h_MsPayGIL.fnptr!(-(int)Battle.reward_data->gil); + FhXCall.MsPayGIL.fnptr!(-(int)Battle.reward_data->gil); } storage[2] = gear_inv_is_full ? 1 : 0; storage[3] = (int)weapon_id; if (!gear_inv_is_full) { - FhXCall.h_MsBtlGetInit.fnptr!(); + FhXCall.MsBtlGetInit.fnptr!(); } } @@ -2331,7 +2331,7 @@ private int TkSetLegendAbility(int chr_id, int level) { return level; } - return FhXCall.h_TkSetLegendAbility.chain_from(TkSetLegendAbility).fnptr!(chr_id, level); + return FhXCall.TkSetLegendAbility.chain_from(TkSetLegendAbility).fnptr!(chr_id, level); } @@ -2626,7 +2626,7 @@ public int Common_putPartyMemberInSlot(AtelBasicWorker* work, int* storage, Atel public int Common_pushParty(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { //logger.Debug($"push_party"); - //if (party_overridden) return FhXCall.h_Common_pushParty.chain_from(h_Common_pushParty).fnptr!(work, storage, atelStack); + //if (party_overridden) return FhXCall.Common_pushParty.chain_from(h_Common_pushParty).fnptr!(work, storage, atelStack); //save_party(); return 0; } @@ -2634,7 +2634,7 @@ public int Common_pushParty(AtelBasicWorker* work, int* storage, AtelStack* atel public int Common_popParty(AtelBasicWorker* work, int* storage, AtelStack* atelStack) { //logger.Debug($"pop_party"); - //if (party_overridden) return FhXCall.h_Common_popParty.chain_from(h_Common_popParty).fnptr!(work, storage, atelStack); + //if (party_overridden) return FhXCall.Common_popParty.chain_from(h_Common_popParty).fnptr!(work, storage, atelStack); //reset_party(); return 1; } @@ -2642,7 +2642,7 @@ public int Common_popParty(AtelBasicWorker* work, int* storage, AtelStack* atelS // TODO: Get function pointer instead of hook for most of these public void h_MsGetSavePartyMember(uint* param_1, uint* param_2, uint* param_3) { //logger.Debug($"get_current_party_slots"); - FhXCall.h_MsGetSavePartyMember.chain_from(h_MsGetSavePartyMember).fnptr!(param_1, param_2, param_3); + FhXCall.MsGetSavePartyMember.chain_from(h_MsGetSavePartyMember).fnptr!(param_1, param_2, param_3); //logger.Debug($"get_current_party_slots: slot_0={*param_1}, slot_1={*param_2}, slot_2={*param_3}"); } @@ -2660,7 +2660,7 @@ public void MsBattleExe(uint param_1, int field_idx, int group_idx, int formatio var field_ptr = Battle.btl->ptr_btl_bin_fields + field_idx * 0xe; string field_name = Marshal.PtrToStringAnsi((nint)(field_ptr+6))!; - var group_ptr = FhXCall.h_MsBtlListGroup.fnptr!(field_idx, group_idx); + var group_ptr = FhXCall.MsBtlListGroup.fnptr!(field_idx, group_idx); byte group_name = *(byte*)(group_ptr+5 + formation_idx * 2); string encounter_name = $"{field_name}_{group_name:00}"; @@ -2682,12 +2682,12 @@ public void MsBattleExe(uint param_1, int field_idx, int group_idx, int formatio save_party(); // Probably? reset_party(); } - FhXCall.h_MsBattleExe.chain_from(MsBattleExe).fnptr!(param_1, field_idx, group_idx, formation_idx); + FhXCall.MsBattleExe.chain_from(MsBattleExe).fnptr!(param_1, field_idx, group_idx, formation_idx); } // Battle loop? public void FUN_00791820() { - FhXCall.h_FUN_00791820.chain_from(FUN_00791820).fnptr!(); + FhXCall.FUN_00791820.chain_from(FUN_00791820).fnptr!(); string encounter_name = Marshal.PtrToStringAnsi((nint)(&Battle.btl->field_name))!; byte battle_end_type = Battle.btl->battle_end_type; byte battle_state = Battle.btl->battle_state; @@ -2734,7 +2734,7 @@ public void FUN_00791820() { private void* curr_pos_area_ptr = null; public byte MsBtlReadSetScene() { - byte result = FhXCall.h_MsBtlReadSetScene.chain_from(MsBtlReadSetScene).fnptr!(); + byte result = FhXCall.MsBtlReadSetScene.chain_from(MsBtlReadSetScene).fnptr!(); _logger.Info($"Battle Name: {Marshal.PtrToStringAnsi((nint)FhUtil.ptr_at(0xD2C25A))}"); //ref BtlAreas original_pos_struct = ref *Battle.btl->ptr_pos_def; BtlAreasHelper original_pos_struct = new BtlAreasHelper(Battle.btl->ptr_pos_def); @@ -2921,7 +2921,7 @@ public int h_MsBtlGetPos(int param_1, Chr* chr, int btl_pos_a, int btl_pos_b, in // btl_pos_b = 8: enemy_run_pos[btl_pos_c]? // btl_pos_b = 9: b? // btl_pos_b = 10: c? - return FhXCall.h_MsBtlGetPos.chain_from(h_MsBtlGetPos).fnptr!(param_1, chr, btl_pos_a, btl_pos_b, btl_pos_c, out_pos); + return FhXCall.MsBtlGetPos.chain_from(h_MsBtlGetPos).fnptr!(param_1, chr, btl_pos_a, btl_pos_b, btl_pos_c, out_pos); } private int give_item(uint item_id, int amount) { @@ -2935,13 +2935,13 @@ private int give_item(uint item_id, int amount) { amount -= excess; } - return FhXCall.h_MsSaveItemUse.chain_from(give_item).fnptr!(item_id, amount); + return FhXCall.MsSaveItemUse.chain_from(give_item).fnptr!(item_id, amount); } private void h_TkMsImportantSet(uint param_1) { _logger.Debug($"give_key_item: {param_1}"); - FhXCall.h_TkMsImportantSet.chain_from(h_TkMsImportantSet).fnptr!(param_1); + FhXCall.TkMsImportantSet.chain_from(h_TkMsImportantSet).fnptr!(param_1); } private nint h_read_from_bin(int param_1, nint param_2, int* param_3) { @@ -2953,7 +2953,7 @@ private nint h_read_from_bin(int param_1, nint param_2, int* param_3) { else if (param_2 == *buki_get_pointer) { _logger.Debug("get_from_bin: buki_get.bin"); } - var result = FhXCall.h_MsGetExcelData.chain_from(h_read_from_bin).fnptr!(param_1, param_2, param_3); + var result = FhXCall.MsGetExcelData.chain_from(h_read_from_bin).fnptr!(param_1, param_2, param_3); _logger.Debug($"get_from_bin: result = {((uint)result).ToString("X")}"); return result; } @@ -2961,19 +2961,19 @@ private nint h_read_from_bin(int param_1, nint param_2, int* param_3) { private ushort h_get_weapon_name(Equipment* param_1) { _logger.Debug($"get_weapon_name: {(int)param_1}"); - return FhXCall.h_MsWeaponNameNum.chain_from(h_get_weapon_name).fnptr!(param_1); + return FhXCall.MsWeaponNameNum.chain_from(h_get_weapon_name).fnptr!(param_1); } private void h_get_weapon_model(ushort name_id, byte owner, int unknown, ushort* model_id_pointer) { _logger.Debug($"get_weapon_model: {name_id}, {owner}, {unknown}, {*model_id_pointer}, "); - FhXCall.h_MsWeaponName.chain_from(h_get_weapon_model).fnptr!(name_id, owner, unknown, model_id_pointer); + FhXCall.MsWeaponName.chain_from(h_get_weapon_model).fnptr!(name_id, owner, unknown, model_id_pointer); } private void h_obtain_treasure_cleanup(BtlRewardData* param_1, int param_2) { _logger.Debug("obtain_treasure_cleanup"); - FhXCall.h_FUN_007993f0.chain_from(h_obtain_treasure_cleanup).fnptr!(param_1, param_2); + FhXCall.FUN_007993f0.chain_from(h_obtain_treasure_cleanup).fnptr!(param_1, param_2); } public void obtain_item(uint item_id, int amount=-1) { @@ -3054,7 +3054,7 @@ public void obtain_item(uint item_id, int amount=-1) { // Upgrade celestial if (celestial_level[equip.owner] < 2) { celestial_level[equip.owner] += 1; - FhXCall.h_TkSetLegendAbility.chain_from(TkSetLegendAbility).fnptr!(equip.owner, celestial_level[equip.owner]); + FhXCall.TkSetLegendAbility.chain_from(TkSetLegendAbility).fnptr!(equip.owner, celestial_level[equip.owner]); } return; } @@ -3108,7 +3108,7 @@ public void obtain_item(uint item_id, int amount=-1) { new_weapon.slot_count = (byte)Math.Max(weapon_data.slot_count, count); new_weapon.name_id = h_get_weapon_name(&new_weapon); h_get_weapon_model(new_weapon.name_id, new_weapon.owner, 0, &new_weapon.model_id); - var result = FhXCall.h_FUN_007ab930.fnptr!(&new_weapon); // giveWeapon? + var result = FhXCall.FUN_007ab930.fnptr!(&new_weapon); // giveWeapon? if (result != 0) { h_obtain_treasure_cleanup(&rewardData, 7); } @@ -3116,7 +3116,7 @@ public void obtain_item(uint item_id, int amount=-1) { case 0x1: // Gil if (amount == -1) amount = (int)((item_id & 0xFF0000) >> 16) * 1000; - FhXCall.h_MsPayGIL.fnptr!(-amount); + FhXCall.MsPayGIL.fnptr!(-amount); break; case 0xE: // Region Unlock @@ -3252,7 +3252,7 @@ public void set_airship_destinations() { public void eiAbmParaGet() { // TODO: Replace normal calculation with custom Archipelago-based calculation (if option enabled) _logger.Debug("Calculating stats"); - FhXCall.h_eiAbmParaGet.chain_from(eiAbmParaGet).fnptr!(); + FhXCall.eiAbmParaGet.chain_from(eiAbmParaGet).fnptr!(); //foreach (ref PlySave ply in save_data->ply_saves) { // ply.abi_map.has_extract_power = true; @@ -3264,9 +3264,9 @@ public void eiAbmParaGet() { private void MsSetRamChrParam(uint chr_id) { _logger.Debug($"MsSetRamChrParam: {chr_id}"); - FhXCall.h_MsSetRamChrParam.chain_from(MsSetRamChrParam).fnptr!(chr_id); + FhXCall.MsSetRamChrParam.chain_from(MsSetRamChrParam).fnptr!(chr_id); - Chr* chr = FhXCall.h_MsGetChr.fnptr!((int)chr_id); + Chr* chr = FhXCall.MsGetChr.fnptr!((int)chr_id); if (seed.Options.AlwaysSensor == 1) { chr->ram.auto_ability_effects.has_sensor = true; @@ -3275,7 +3275,7 @@ private void MsSetRamChrParam(uint chr_id) { private void MsSetSaveParam(uint chr_id) { _logger.Debug("Calculating base stats and equipment"); - FhXCall.h_MsSetSaveParam.chain_from(MsSetSaveParam).fnptr!(chr_id); + FhXCall.MsSetSaveParam.chain_from(MsSetSaveParam).fnptr!(chr_id); // Does nothing?? if (seed.Options.AlwaysSensor == 1) { @@ -3286,8 +3286,8 @@ private void MsSetSaveParam(uint chr_id) { //PlySave ply = save_data->ply_saves[(int)chr_id]; //Equipment*[] equips = //[ - // (Equipment*)FhXCall.h_MsGetSaveWeapon.fnptr!(ply.wpn_inv_idx, 0x0), - // (Equipment*)FhXCall.h_MsGetSaveWeapon.fnptr!(ply.arm_inv_idx, 0x0), + // (Equipment*)FhXCall.MsGetSaveWeapon.fnptr!(ply.wpn_inv_idx, 0x0), + // (Equipment*)FhXCall.MsGetSaveWeapon.fnptr!(ply.arm_inv_idx, 0x0), //]; //int strength_mult = 0; //int defense_mult = 0; @@ -3307,7 +3307,7 @@ private void MsSetSaveParam(uint chr_id) { //foreach (Equipment* equip in equips) { // for (int i = 0; i < 4; i++) { // if (equip->abilities[i] == 0 || equip->abilities[i] == 0xFF) continue; - // AutoAbility* a_ability = (AutoAbility*)FhXCall.h_MsGetExcelData.fnptr!(equip->abilities[i] & 0xFFF, Battle.btl->ptr_a_ability_bin, (int*)0x0); + // AutoAbility* a_ability = (AutoAbility*)FhXCall.MsGetExcelData.fnptr!(equip->abilities[i] & 0xFFF, Battle.btl->ptr_a_ability_bin, (int*)0x0); // strength_mult += a_ability->stat_inc_flags.strength() ? a_ability->stat_inc_amount : 0; // defense_mult += a_ability->stat_inc_flags.defense() ? a_ability->stat_inc_amount : 0; // magic_mult += a_ability->stat_inc_flags.magic() ? a_ability->stat_inc_amount : 0; @@ -3340,20 +3340,20 @@ private void MsSetSaveParam(uint chr_id) { public void h_FUN_00a48910(uint chr_id, int node_idx) { // TODO: Send Archipelago location when node is unlocked (if option enabled) _logger.Debug($"Unlock node {node_idx} for {id_to_character[chr_id]}"); - FhXCall.h_FUN_00a48910.chain_from(h_FUN_00a48910).fnptr!(chr_id, node_idx); + FhXCall.FUN_00a48910.chain_from(h_FUN_00a48910).fnptr!(chr_id, node_idx); } private uint MsApUp(int chr_id, Chr* chr, int base_ap_add, uint param_4) { _logger.Debug($"AP gain: character={id_to_character[chr_id]}, ap={base_ap_add}"); int new_ap = (int)Math.Min(Math.BigMul(base_ap_add, ap_multiplier), 999_999_999); - return FhXCall.h_MsApUp.chain_from(MsApUp).fnptr!(chr_id, chr, new_ap, param_4); + return FhXCall.MsApUp.chain_from(MsApUp).fnptr!(chr_id, chr, new_ap, param_4); } // Non-loading FMV private bool graphicInitFMVPlayer(int movie_id, int param_2) { - bool result = FhXCall.h_graphicInitFMVPlayer.chain_from(graphicInitFMVPlayer).fnptr!(movie_id, param_2); + bool result = FhXCall.graphicInitFMVPlayer.chain_from(graphicInitFMVPlayer).fnptr!(movie_id, param_2); return !result; } @@ -3366,14 +3366,14 @@ private void h_FUN_00656c90(int param_1, int param_2, char* fileName) { //logger.Debug(nameString); - FhXCall.h_FUN_00656c90.chain_from(h_FUN_00656c90).fnptr!(param_1, param_2, fileName); + FhXCall.FUN_00656c90.chain_from(h_FUN_00656c90).fnptr!(param_1, param_2, fileName); } private void TkMenuAppearMainCmdWindow(int param_1, int param_2) { // All menu options are enabled at progress 0 ushort progress = save_data->story_progress; save_data->story_progress = 0; - FhXCall.h_TkMenuAppearMainCmdWindow.chain_from(TkMenuAppearMainCmdWindow).fnptr!(param_1, param_2); + FhXCall.TkMenuAppearMainCmdWindow.chain_from(TkMenuAppearMainCmdWindow).fnptr!(param_1, param_2); save_data->story_progress = progress; } @@ -3387,13 +3387,13 @@ private void TkMenuAppearMainCmdWindow(int param_1, int param_2) { //} public void h_FfxFmod_soundInit_setLang(nint ffxFmod, int lang) { - FhXCall.h_FfxFmod_soundInit_setLang.chain_from(h_FfxFmod_soundInit_setLang).fnptr!(ffxFmod, lang); + FhXCall.FfxFmod_soundInit_setLang.chain_from(h_FfxFmod_soundInit_setLang).fnptr!(ffxFmod, lang); *(byte*)(ffxFmod + 4) = 0; } // Unsure if there are side effects public void LocalizationManager_Initialize(LocalizationManager* localizationManager) { - FhXCall.h_LocalizationManager_Initialize.chain_from(LocalizationManager_Initialize).fnptr!(localizationManager); + FhXCall.LocalizationManager_Initialize.chain_from(LocalizationManager_Initialize).fnptr!(localizationManager); if (TextLanguage.HasValue) { _logger.Debug($"Text: {TextLanguage.Value}"); localizationManager->lang_text = TextLanguage.Value; @@ -3404,13 +3404,13 @@ public void LocalizationManager_Initialize(LocalizationManager* localizationMana localizationManager->lang_voice = VoiceLanguage.Value; } } - + [UnmanagedFunctionPointer(CallingConvention.StdCall)] public unsafe delegate nint FMOD_Bank_Post_Load(nint param_1, nint param_2, nint param_3, nint param_4); public int FmodVoice_dataChange(nint FmodVoice, int event_id, nint param_2) { _logger.Debug($"{FmodVoice}, {event_id}, {param_2}"); - int result = FhXCall.h_FmodVoice_dataChange.chain_from(FmodVoice_dataChange).fnptr!(FmodVoice, event_id, param_2); + int result = FhXCall.FmodVoice_dataChange.chain_from(FmodVoice_dataChange).fnptr!(FmodVoice, event_id, param_2); //string bank_name = "ffx_us_voice03"; // Contains "Stay away from the summoner!" (136815042) foreach (string bank_name in (string[])["ffx_us_voice03", "ffx_us_voice07", "ffx_us_voice11", "ffx_us_voice12", "ffx_us_voice20"]) { string path = $"../../../FFX_Data/GameData/PS3Data/Sound_PC/Voice/US/{bank_name}.fev"; @@ -3419,7 +3419,7 @@ public int FmodVoice_dataChange(nint FmodVoice, int event_id, nint param_2) { int bank_index = bank_name[^1] + (bank_name[^2] * 5 - 0x108)*2; nint bank = *(int*)(FmodVoice+0x18) + bank_index*4; - nint load_result = FhXCall.h_FMOD_EventSystem_load.fnptr!(param_2, file_path, 0, bank); + nint load_result = FhXCall.FMOD_EventSystem_load.fnptr!(param_2, file_path, 0, bank); Marshal.FreeHGlobal(file_path); if (load_result == 0) { @@ -3465,7 +3465,7 @@ public void play_voice_line(int voice_line) { public string get_item_name(uint item_id) { if (item_name_cache.TryGetValue(item_id, out var name)) return name; byte* item_name; - FhXCall.h_TkMsGetRomItem.fnptr!(item_id, (int*)&item_name); + FhXCall.TkMsGetRomItem.fnptr!(item_id, (int*)&item_name); byte[] decoded = new byte[FhEncoding.compute_decode_buffer_size(new ReadOnlySpan(item_name, 1000))]; int decoded_length = FhEncoding.decode(new ReadOnlySpan(item_name, 1000), decoded, flags:FhEncodingFlags.IMPLICIT_END); string decoded_string = Encoding.UTF8.GetString(decoded, 0, decoded_length); @@ -3486,42 +3486,42 @@ public string get_other_item_name(uint item_id) { return $"Unnamed item ({item_id})"; } - private Dictionary cached_CT_Execs = new(); - private Dictionary cached_CT_RetInts = new(); - private Dictionary cached_CT_RetFloats = new(); + private Dictionary cached_CT_Execs = new(); + private Dictionary cached_CT_RetInts = new(); + private Dictionary cached_CT_RetFloats = new(); - public FhGCall.CT_Exec get_CT_Exec(int id) { + public FhGCall.d_CT_Exec get_CT_Exec(int id) { if (cached_CT_Execs.TryGetValue(id, out var result)) { return result; } AtelCallTargetNamespace nmsp = (AtelCallTargetNamespace)(id >> 0xC); AtelCallTarget* internal_ct = nmsp.get_internal() + (id & 0xFFF); - FhGCall.CT_Exec ct = Marshal.GetDelegateForFunctionPointer(internal_ct->ret_float_func); + FhGCall.d_CT_Exec ct = Marshal.GetDelegateForFunctionPointer(internal_ct->ret_float_func); cached_CT_Execs[id] = ct; return ct; } - public FhGCall.CT_RetInt get_CT_RetInt(int id) { + public FhGCall.d_CT_RetInt get_CT_RetInt(int id) { if (cached_CT_RetInts.TryGetValue(id, out var result)) { return result; } AtelCallTargetNamespace nmsp = (AtelCallTargetNamespace)(id >> 0xC); AtelCallTarget* internal_ct = nmsp.get_internal() + (id & 0xFFF); - FhGCall.CT_RetInt ct = Marshal.GetDelegateForFunctionPointer(internal_ct->ret_float_func); + FhGCall.d_CT_RetInt ct = Marshal.GetDelegateForFunctionPointer(internal_ct->ret_float_func); cached_CT_RetInts[id] = ct; return ct; } - public FhGCall.CT_RetFloat get_CT_RetFloat(int id) { + public FhGCall.d_CT_RetFloat get_CT_RetFloat(int id) { if (cached_CT_RetFloats.TryGetValue(id, out var result)) { return result; } AtelCallTargetNamespace nmsp = (AtelCallTargetNamespace)(id >> 0xC); AtelCallTarget* internal_ct = nmsp.get_internal() + (id & 0xFFF); - FhGCall.CT_RetFloat ct = Marshal.GetDelegateForFunctionPointer(internal_ct->ret_float_func); + FhGCall.d_CT_RetFloat ct = Marshal.GetDelegateForFunctionPointer(internal_ct->ret_float_func); cached_CT_RetFloats[id] = ct; return ct; } @@ -3529,7 +3529,7 @@ public FhGCall.CT_RetFloat get_CT_RetFloat(int id) { // Custom namespace public void AtelInitTotal() { _logger.Debug("Initializing Atel namespaces"); - FhXCall.h_AtelInitTotal.chain_from(AtelInitTotal).fnptr!(); + FhXCall.AtelInitTotal.chain_from(AtelInitTotal).fnptr!(); AtelSetUpCallFunc(0xF, customNameSpaceHandle.AddrOfPinnedObject()); } @@ -3805,11 +3805,11 @@ public int blockWarp(AtelBasicWorker* work, int* storage, AtelStack* atelStack) atelStack->push_int(2); // signal priority? atelStack->push_int(0); // worker atelStack->push_int(entry_point); // entrypoint - FhXCall.h_FUN_00867370.fnptr!((byte)AtelOp.REQEW & 0x7F, work, &work->threads[work->current_thread_priority], atelStack, 0); + FhXCall.FUN_00867370.fnptr!((byte)AtelOp.REQEW & 0x7F, work, &work->threads[work->current_thread_priority], atelStack, 0); work->__0x34 = (ushort)(work->__0x34 & 0xEBFF | 0x800); //work->__0x34 = (ushort)(work->__0x34 | 0x800); atelStack->pop_int(); - //FhXCall.h_FUN_008671d0.fnptr!((byte)AtelOp.REQ & 0x7F, &work->threads[work->current_thread_priority], work, atelStack); + //FhXCall.FUN_008671d0.fnptr!((byte)AtelOp.REQ & 0x7F, &work->threads[work->current_thread_priority], work, atelStack); return 1; } _logger.Debug($"Closest entrance: pos:({closestEntrance?.Entrance.x}, {closestEntrance?.Entrance.y}, {closestEntrance?.Entrance.z}) distance:{closestEntrance?.Distance}"); diff --git a/src/modules/captures.cs b/src/modules/captures.cs index 77edd23..17be65d 100644 --- a/src/modules/captures.cs +++ b/src/modules/captures.cs @@ -17,7 +17,7 @@ namespace ArchipelagoFFX; [FhLoad(FhGameId.FFX)] -public unsafe partial class CaptureModule : FhModule { +public unsafe class CaptureModule : FhModule { private FhModuleHandle _client_handle; private ArchipelagoClientModule? _client; @@ -31,21 +31,21 @@ public CaptureModule() { // TODO: Remove once Fahrenheit adds Atel call targets to FhCall // Mars Sigil location check (Atel CT_RetInt hook); not yet a curated FhCall entry, so kept as a local handle. - private FhMethodHandle h_ret_hasKeyItem_handle + private FhMethodHandle h_ret_hasKeyItem_handle => new( new FhMethodLocation("FFX.exe", 0x45B7A0) ); public override bool init(FhModContext mod_context, FileStream global_state_file) { return _client_handle.try_get_module(out _client) && _ffx_interop_handle.try_get_module(out _ffx_interop) - && FhXCall.h_MsMonsterCapture.hook(this, h_MsMonsterCapture) - && FhXCall.h_FUN_00783bb0.hook(this, h_FUN_00783bb0) - && FhXCall.h_AtelEventSetUp.hook(this, h_AtelEventSetUp) + && FhXCall.MsMonsterCapture.hook(this, h_MsMonsterCapture) + && FhXCall.FUN_00783bb0.hook(this, h_FUN_00783bb0) + && FhXCall.AtelEventSetUp.hook(this, h_AtelEventSetUp) && h_ret_hasKeyItem_handle.hook(this, ret_hasKeyItem) - && FhXCall.h_MsDamageCheckDeath.hook(this, h_MsDamageCheckDeath) - && FhXCall.h_MsSetRamChrParam.hook(this, h_MsSetRamChrParam) - && FhXCall.h_MsSetSaveParam.hook(this, h_MsSetSaveParam) - && FhXCall.h_MsCalcCommand.hook(this, h_MsCalcCommand) - && FhXCall.h_MsBattleEncountExe.hook(this, h_MsBattleEncountExe); + && FhXCall.MsDamageCheckDeath.hook(this, h_MsDamageCheckDeath) + && FhXCall.MsSetRamChrParam.hook(this, h_MsSetRamChrParam) + && FhXCall.MsSetSaveParam.hook(this, h_MsSetSaveParam) + && FhXCall.MsCalcCommand.hook(this, h_MsCalcCommand) + && FhXCall.MsBattleEncountExe.hook(this, h_MsBattleEncountExe); } private static void set(byte* code_ptr, uint offset, AtelInst[] opcodes) { @@ -65,7 +65,7 @@ private static void set(byte* code_ptr, uint[] offsets, AtelInst[] opcodes) { } private bool h_MsMonsterCapture(int target_id, int arena_idx) { - bool captured = FhXCall.h_MsMonsterCapture.chain_from(h_MsMonsterCapture).fnptr!(target_id, arena_idx); + bool captured = FhXCall.MsMonsterCapture.chain_from(h_MsMonsterCapture).fnptr!(target_id, arena_idx); _logger.Info($"Fiend Capture: Target={target_id}, Arena Index={arena_idx}, Captured={captured}"); @@ -110,9 +110,9 @@ private void h_FUN_00783bb0(byte mon_idx) { byte num_initialized = FhUtil.get_at(0xD2CA80); if (num_initialized == 0) initialized_monsters.Clear(); - FhXCall.h_FUN_00783bb0.chain_from(h_FUN_00783bb0).fnptr!(mon_idx); + FhXCall.FUN_00783bb0.chain_from(h_FUN_00783bb0).fnptr!(mon_idx); - Chr* mon = FhXCall.h_MsGetMon.fnptr!(mon_idx); + Chr* mon = FhXCall.MsGetMon.fnptr!(mon_idx); if (initialized_monsters.Add(mon->chr_id)) { MonStats* stats = mon->ptr_base_stats; @@ -128,9 +128,9 @@ private void h_FUN_00783bb0(byte mon_idx) { private string? _event_name; private void h_AtelEventSetUp(int event_id) { - FhXCall.h_AtelEventSetUp.chain_from(h_AtelEventSetUp).fnptr!(event_id); + FhXCall.AtelEventSetUp.chain_from(h_AtelEventSetUp).fnptr!(event_id); - _event_name = Marshal.PtrToStringAnsi((nint)FhXCall.h_AtelGetEventName.fnptr!((uint)event_id))!; + _event_name = Marshal.PtrToStringAnsi((nint)FhXCall.AtelGetEventName.fnptr!((uint)event_id))!; _logger.Debug($"atel_event_setup: {_event_name}"); byte* code_ptr = Atel.controllers[0].worker(0)->code_ptr; @@ -172,7 +172,7 @@ private int ret_hasKeyItem(AtelBasicWorker* work, int* storage, AtelStack* atelS } private int h_MsDamageCheckDeath(int attacker_id, int target_id, int param_3, int param_4) { - Chr* target = FhXCall.h_MsGetChr.fnptr!(target_id); + Chr* target = FhXCall.MsGetChr.fnptr!(target_id); MonStats* mon_stats = target->ptr_base_stats; ushort capture_index = mon_stats is not null ? mon_stats->monster_arena_idx : (ushort)0xFF; @@ -186,13 +186,13 @@ private int h_MsDamageCheckDeath(int attacker_id, int target_id, int param_3, in target->should_try_capture = true; } - return FhXCall.h_MsDamageCheckDeath.chain_from(h_MsDamageCheckDeath).fnptr!(attacker_id, target_id, param_3, param_4); + return FhXCall.MsDamageCheckDeath.chain_from(h_MsDamageCheckDeath).fnptr!(attacker_id, target_id, param_3, param_4); } private void h_MsSetRamChrParam(uint chr_id) { - FhXCall.h_MsSetRamChrParam.chain_from(h_MsSetRamChrParam).fnptr!(chr_id); + FhXCall.MsSetRamChrParam.chain_from(h_MsSetRamChrParam).fnptr!(chr_id); - Chr* chr = FhXCall.h_MsGetChr.fnptr!((int)chr_id); + Chr* chr = FhXCall.MsGetChr.fnptr!((int)chr_id); if (ArchipelagoFFXModule.seed.Options.AlwaysCapture == 1) { chr->ram.auto_ability_effects.has_capture = true; @@ -200,7 +200,7 @@ private void h_MsSetRamChrParam(uint chr_id) { } private void h_MsSetSaveParam(uint chr_id) { - FhXCall.h_MsSetSaveParam.chain_from(h_MsSetSaveParam).fnptr!(chr_id); + FhXCall.MsSetSaveParam.chain_from(h_MsSetSaveParam).fnptr!(chr_id); // Does nothing?? if (ArchipelagoFFXModule.seed.Options.AlwaysCapture == 1) { @@ -209,19 +209,19 @@ private void h_MsSetSaveParam(uint chr_id) { } private void h_MsCalcCommand(AttackCue* param_1, int param_2) { - FhXCall.h_MsCalcCommand.chain_from(h_MsCalcCommand).fnptr!(param_1, param_2); + FhXCall.MsCalcCommand.chain_from(h_MsCalcCommand).fnptr!(param_1, param_2); if (param_1 == null) return; uint local_6c; - Command* command = FhXCall.h_MsGetCommand.fnptr!(param_1->attacker_id, 0, -1, ¶m_1->command_list[param_2], &local_6c); + Command* command = FhXCall.MsGetCommand.fnptr!(param_1->attacker_id, 0, -1, ¶m_1->command_list[param_2], &local_6c); if (param_1->command_count <= param_2 || command == null) return; - Chr* attacker = FhXCall.h_MsGetChr.fnptr!(param_1->attacker_id); + Chr* attacker = FhXCall.MsGetChr.fnptr!(param_1->attacker_id); int[] local_7c = [0, 0, 0, param_2]; if (command->absorbs_dmg) { - local_7c[2] = (int)FhXCall.h_FUN_0078d100.fnptr!(attacker); + local_7c[2] = (int)FhXCall.FUN_0078d100.fnptr!(attacker); } //TODO: Figure out a way not to duplicate affection in _FUN_0078bb30 @@ -230,7 +230,7 @@ private void h_MsCalcCommand(AttackCue* param_1, int param_2) { fixed (byte* p_targets = targets) { fixed (byte* p_local_48 = local_48) { fixed (int* p_local_7c = local_7c) { - FhXCall.h_FUN_0078bb30.fnptr!(param_1->attacker_id, p_targets, p_local_48, command, local_6c, ¶m_1->command_list[param_2].targets, p_local_7c + 1); + FhXCall.FUN_0078bb30.fnptr!(param_1->attacker_id, p_targets, p_local_48, command, local_6c, ¶m_1->command_list[param_2].targets, p_local_7c + 1); } } } @@ -238,8 +238,8 @@ private void h_MsCalcCommand(AttackCue* param_1, int param_2) { for (uint target_id = 0; target_id < 32; target_id++) { if (targets[target_id] != 0) { if (local_7c[2] == 0 || target_id != param_1->attacker_id) { - Chr* target = FhXCall.h_MsGetChr.fnptr!((int)target_id); - uint iVar6 = FhXCall.h_FUN_0078d100.fnptr!(target); + Chr* target = FhXCall.MsGetChr.fnptr!((int)target_id); + uint iVar6 = FhXCall.FUN_0078d100.fnptr!(target); if (iVar6 != 0) { if (attacker->ram.auto_ability_effects.has_capture && Battle.btl->battle_type == 0 && (ArchipelagoFFXModule.seed.Options.CaptureDamage > 0 || command->uses_weapon_properties)) { target->should_try_capture = true; @@ -257,19 +257,19 @@ private int get_monster_arena_idx(int monster_id) { byte[] filename = Encoding.UTF8.GetBytes($"host0:/ffx/master/jppc/battle/mon/_m{monster_id:D3}/m{monster_id:D3}.bin"); fixed (byte* filename_ptr = &filename[0]) { - void* filestream = FhXCall.h_sceOpen.fnptr!(filename_ptr, 1); + void* filestream = FhXCall.sceOpen.fnptr!(filename_ptr, 1); if (filestream is null) { _logger.Info("Failed to open monster file"); return -1; } - int filesize = FhXCall.h_sceLseek.fnptr!(filestream, 0, 2); - FhXCall.h_sceLseek.fnptr!(filestream, 0, 0); + int filesize = FhXCall.sceLseek.fnptr!(filestream, 0, 2); + FhXCall.sceLseek.fnptr!(filestream, 0, 0); void* file = NativeMemory.Alloc((nuint)filesize); - FhXCall.h_sceRead.fnptr!(filestream, file, filesize); - FhXCall.h_sceClose.fnptr!(filestream); + FhXCall.sceRead.fnptr!(filestream, file, filesize); + FhXCall.sceClose.fnptr!(filestream); int stats_offset = *(int*)((int)file + 0xC); MonStats* mon_stats = (MonStats*)((int)file + stats_offset); @@ -467,16 +467,16 @@ private int get_extra_weight_for_formation(BtlBinField* field, BtlBinFormation f float extra_weight = 0.0f; fixed (byte* filepath_ptr = &filepath[0]) { - void* open_result = FhXCall.h_sceOpen.fnptr!(filepath_ptr, 1); + void* open_result = FhXCall.sceOpen.fnptr!(filepath_ptr, 1); if (open_result is null) return 0; - int file_size = FhXCall.h_sceLseek.fnptr!(open_result, 0, 2); - FhXCall.h_sceLseek.fnptr!(open_result, 0, 0); + int file_size = FhXCall.sceLseek.fnptr!(open_result, 0, 2); + FhXCall.sceLseek.fnptr!(open_result, 0, 0); void* file = NativeMemory.Alloc((nuint)file_size); - FhXCall.h_sceRead.fnptr!(open_result, file, file_size); - FhXCall.h_sceClose.fnptr!(open_result); + FhXCall.sceRead.fnptr!(open_result, file, file_size); + FhXCall.sceClose.fnptr!(open_result); int chunk_ptr = *(int*)((nint)file + 0xC); if (chunk_ptr != 0) { @@ -525,7 +525,7 @@ private int get_extra_weight_for_formation(BtlBinField* field, BtlBinFormation f private int h_MsBattleEncountExe(int field_id, int group_idx, float walked_delta) { if (ArchipelagoFFXModule.seed.Options.CaptureRequirement == 0 || ArchipelagoFFXModule.seed.Options.EncounterWeighting == 0) { - return FhXCall.h_MsBattleEncountExe.chain_from(h_MsBattleEncountExe).fnptr!(field_id, group_idx, walked_delta); + return FhXCall.MsBattleEncountExe.chain_from(h_MsBattleEncountExe).fnptr!(field_id, group_idx, walked_delta); } // Globals @@ -541,14 +541,14 @@ private int h_MsBattleEncountExe(int field_id, int group_idx, float walked_delta // _logger.Info($" g_encounter_level = {*g_encounter_level}"); // _logger.Info($" EnableBattle = {*EnableBattle}"); - int field_idx = FhXCall.h_MsBtlListFieldNum.fnptr!(field_id); + int field_idx = FhXCall.MsBtlListFieldNum.fnptr!(field_id); if (*g_keybattle != 0 && *g_keydown_R != 0) { Battle.btl->group_idx = (byte)group_idx; Battle.btl->formation_idx = (byte)*DAT_0112ca28; *(byte*)((nint)Battle.btl + 0x12) = 1; Battle.btl->field_idx = (ushort)field_idx; - FhXCall.h_ResetEncountExe.fnptr!(1); + FhXCall.ResetEncountExe.fnptr!(1); return -1; } @@ -570,15 +570,15 @@ private int h_MsBattleEncountExe(int field_id, int group_idx, float walked_delta if (field_idx < 0) return 0; if (walked_delta <= 0.0f || !can_encounter) return 0; - BtlBinField* field = FhXCall.h_MsBtlListField.fnptr!(field_idx); - BtlBinEncounter* encounter = FhXCall.h_MsBtlListEncount.fnptr!(field_idx); + BtlBinField* field = FhXCall.MsBtlListField.fnptr!(field_idx); + BtlBinEncounter* encounter = FhXCall.MsBtlListEncount.fnptr!(field_idx); // _logger.Info($" encounter->group_count: {encounter->group_count}"); if (group_idx < 0 || group_idx >= encounter->group_count) return 0; if (*EnableBattle == 0) return 0; - BtlBinGroup* group = FhXCall.h_MsBtlListGroup.fnptr!(field_idx, group_idx); + BtlBinGroup* group = FhXCall.MsBtlListGroup.fnptr!(field_idx, group_idx); if (group->grace == 0 || group->total_weight == 0 || group->formation_count == 0) return 0; @@ -599,7 +599,7 @@ private int h_MsBattleEncountExe(int field_id, int group_idx, float walked_delta *(float*)((nint)Battle.btl + 0x110) *= 256.0f - encounter_chance; *(float*)((nint)Battle.btl + 0x114) *= 256.0f; - if ((FhXCall.h_brnd.fnptr!(0) & 0xFF) >= encounter_chance) continue; + if ((FhXCall.brnd.fnptr!(0) & 0xFF) >= encounter_chance) continue; // We have to prepare weights first int total_weight = group->total_weight; @@ -645,7 +645,7 @@ private int h_MsBattleEncountExe(int field_id, int group_idx, float walked_delta } // Let's figure out which formation we should encounter! - int formation_rng = FhXCall.h_brnd.fnptr!(1) % total_weight; + int formation_rng = FhXCall.brnd.fnptr!(1) % total_weight; int iVar7 = 0; _logger.Debug( "Encounter!"); @@ -661,14 +661,14 @@ private int h_MsBattleEncountExe(int field_id, int group_idx, float walked_delta if (*(byte*)((nint)Battle.btl + 0x27) == 0) { *(byte*)((nint)Battle.btl + 0x12) = 1; } else { - FhXCall.h_Sg_FadeInW.fnptr!(3); + FhXCall.Sg_FadeInW.fnptr!(3); save_data->battle_count += 1; } Battle.btl->field_idx = (ushort)field_idx; Battle.btl->group_idx = (byte)group_idx; Battle.btl->formation_idx = (byte)formation_idx; - FhXCall.h_ResetEncountExe.fnptr!(1); + FhXCall.ResetEncountExe.fnptr!(1); return -1; } diff --git a/src/modules/deathlink.cs b/src/modules/deathlink.cs index e2083e3..c761119 100644 --- a/src/modules/deathlink.cs +++ b/src/modules/deathlink.cs @@ -14,7 +14,7 @@ namespace ArchipelagoFFX; [FhLoad(FhGameId.FFX)] -public unsafe partial class DeathLinkModule : FhModule { +public unsafe class DeathLinkModule : FhModule { public enum DeathLinkSendType { GameOver, KO, @@ -135,9 +135,9 @@ public void debug_apply_deathlink() { public override bool init(FhModContext mod_context, FileStream global_state_file) { return _client_handle.try_get_module(out _client) && _toasts_handle.try_get_module(out _toasts) - && FhXCall.h_MsBtlReadManage.hook(this, _h_MsBtlReadManage) - && FhXCall.h_MsDamageCheckDeath.hook(this, _h_MsDamageCheckDeath) - && FhXCall.h_MsGetBattleEndStatus.hook(this, _h_MsGetBattleEndStatus); + && FhXCall.MsBtlReadManage.hook(this, _h_MsBtlReadManage) + && FhXCall.MsDamageCheckDeath.hook(this, _h_MsDamageCheckDeath) + && FhXCall.MsGetBattleEndStatus.hook(this, _h_MsGetBattleEndStatus); } private void apply_death_link() { @@ -202,7 +202,7 @@ private void apply_death_link() { private void _h_MsBtlReadManage() { int old_state = Globals.Battle.btl->battle_state; - FhXCall.h_MsBtlReadManage.chain_from(_h_MsBtlReadManage).fnptr!(); + FhXCall.MsBtlReadManage.chain_from(_h_MsBtlReadManage).fnptr!(); if (Globals.Battle.btl->battle_state != 13 || old_state == Globals.Battle.btl->battle_state) return; @@ -221,14 +221,14 @@ private void _h_MsBtlReadManage() { apply_death_link(); - FhXCall.h_MsMessageCueRegist.fnptr!((uint)MessageCueType.FH_CUSTOM, (int)_deathlink_announcement.encoded, 0, 27, 35); + FhXCall.MsMessageCueRegist.fnptr!((uint)MessageCueType.FH_CUSTOM, (int)_deathlink_announcement.encoded, 0, 27, 35); _logger.Info(" Disabling Escape and Flee..."); for (int chr_id = 0; chr_id <= PlySaveId.PC_SEYMOUR; chr_id++) { // Disable Escape & Flee commands - FhXCall.h_FUN_0079b480.fnptr!(chr_id, PlayerCommandId.PCOM_ESCAPE, 1); - FhXCall.h_FUN_0079b480.fnptr!(chr_id, PlayerCommandId.PCOM_FLEE, 1); + FhXCall.FUN_0079b480.fnptr!(chr_id, PlayerCommandId.PCOM_ESCAPE, 1); + FhXCall.FUN_0079b480.fnptr!(chr_id, PlayerCommandId.PCOM_FLEE, 1); } _deathlinks_queued -= 1; @@ -237,7 +237,7 @@ private void _h_MsBtlReadManage() { } private int _h_MsDamageCheckDeath(int attacker_id, int target_id, int p3, int targetting_self) { - int result = FhXCall.h_MsDamageCheckDeath.chain_from(_h_MsDamageCheckDeath).fnptr!(attacker_id, target_id, p3, targetting_self); + int result = FhXCall.MsDamageCheckDeath.chain_from(_h_MsDamageCheckDeath).fnptr!(attacker_id, target_id, p3, targetting_self); if (result == 0 || target_id > PlySaveId.PC_MAGUS3) { return result; @@ -253,7 +253,7 @@ private int _h_MsDamageCheckDeath(int attacker_id, int target_id, int p3, int ta string player = _client!.active_player?.Alias ?? "Someone"; - Chr* target = FhXCall.h_MsGetChr.fnptr!(target_id); + Chr* target = FhXCall.MsGetChr.fnptr!(target_id); byte[] decoded = new byte[FhEncoding.compute_decode_buffer_size(target->ram.name, null, null, FhEncodingFlags.IMPLICIT_END)]; FhEncoding.decode(target->ram.name, decoded, null, null, FhEncodingFlags.IMPLICIT_END); string target_name = Encoding.UTF8.GetString(decoded); @@ -277,7 +277,7 @@ private int _h_MsDamageCheckDeath(int attacker_id, int target_id, int p3, int ta } private uint _h_MsGetBattleEndStatus() { - uint battle_end_type = FhXCall.h_MsGetBattleEndStatus.chain_from(_h_MsGetBattleEndStatus).fnptr!(); + uint battle_end_type = FhXCall.MsGetBattleEndStatus.chain_from(_h_MsGetBattleEndStatus).fnptr!(); if (!_deathlink_enabled || battle_end_type != 1 || Globals.Battle.btl->battle_state != 0x17) { return battle_end_type; diff --git a/src/modules/hardcore_contest.cs b/src/modules/hardcore_contest.cs index b84c9ee..9f0abe7 100644 --- a/src/modules/hardcore_contest.cs +++ b/src/modules/hardcore_contest.cs @@ -10,7 +10,7 @@ namespace ArchipelagoFFX; [FhLoad(FhGameId.FFX)] -public unsafe partial class HardcoreDreamsEndModule : FhModule { +public unsafe class HardcoreDreamsEndModule : FhModule { private bool _hardcore_dreams_end_enabled; public bool get_enabled() { @@ -22,13 +22,13 @@ public void set_enabled(bool enabled) { } public override bool init(FhModContext mod_context, FileStream global_state_file) { - return FhXCall.h_MsBtlReadManage.hook(this, _h_MsBtlReadManage); + return FhXCall.MsBtlReadManage.hook(this, _h_MsBtlReadManage); } private void _h_MsBtlReadManage() { int old_state = Globals.Battle.btl->battle_state; - FhXCall.h_MsBtlReadManage.chain_from(_h_MsBtlReadManage).fnptr!(); + FhXCall.MsBtlReadManage.chain_from(_h_MsBtlReadManage).fnptr!(); if (Globals.Battle.btl->battle_state != 13 || old_state == Globals.Battle.btl->battle_state) return; diff --git a/src/modules/overdrives.cs b/src/modules/overdrives.cs index 881b1ea..e32e7cc 100644 --- a/src/modules/overdrives.cs +++ b/src/modules/overdrives.cs @@ -15,7 +15,7 @@ namespace ArchipelagoFFX; [FhLoad(FhGameId.FFX)] -public unsafe partial class OverdriveModule : FhModule { +public unsafe class OverdriveModule : FhModule { // Fahrenheit-related private FhModContext? _mod_context; private FileStream? _global_state; @@ -26,7 +26,7 @@ public unsafe partial class OverdriveModule : FhModule { private FhModuleHandle _ffx_interop_handle; private ArchipelagoFFXModule? _ffx_interop; - private FhMethodHandle h_ret_doesChrKnowCommand + private FhMethodHandle h_ret_doesChrKnowCommand => new(new FhMethodLocation("FFX.exe", 0x3A30C0)); // Damage Calc @@ -204,13 +204,13 @@ public override bool init(FhModContext mod_context, FileStream global_state_file return _client_handle.try_get_module(out _client) && _ffx_interop_handle.try_get_module(out _ffx_interop) - && FhXCall.h_MsGetSaveCommand.hook(this, h_MsGetSaveCommand) - && FhXCall.h_MsSetRamChrAbility.hook(this, h_MsSetRamChrAbility) - && FhXCall.h_MsLimitTidusLearn.hook(this, h_MsLimitTidusLearn) - && FhXCall.h_AfterDamageProcess.hook(this, h_MsAfterDamageProcess) + && FhXCall.MsGetSaveCommand.hook(this, h_MsGetSaveCommand) + && FhXCall.MsSetRamChrAbility.hook(this, h_MsSetRamChrAbility) + && FhXCall.MsLimitTidusLearn.hook(this, h_MsLimitTidusLearn) + && FhXCall.AfterDamageProcess.hook(this, h_MsAfterDamageProcess) && h_ret_doesChrKnowCommand.hook(this, ret_doesChrKnowCommand) - && FhXCall.h_MsSetSaveCommandWithPrefix.hook(this, h_MsSetSaveCommandWithPrefix) - && FhXCall.h_TOBtlDrawLearningMessageWindow.hook(this, h_TOBtlDrawLearningMessageWindow); + && FhXCall.MsSetSaveCommandWithPrefix.hook(this, h_MsSetSaveCommandWithPrefix) + && FhXCall.TOBtlDrawLearningMessageWindow.hook(this, h_TOBtlDrawLearningMessageWindow); } private static T* ptr_at(nint address) where T : unmanaged { return (T*)(address); } @@ -226,14 +226,14 @@ private int h_MsGetSaveCommand(int chr_id, uint com_id) { OverdriveProvider.provide_overdrive(chr_id); } - return FhXCall.h_MsGetSaveCommand.chain_from(h_MsGetSaveCommand).fnptr!(chr_id, com_id); + return FhXCall.MsGetSaveCommand.chain_from(h_MsGetSaveCommand).fnptr!(chr_id, com_id); } // When game is attempting to set character abilities, ensure the correct overdrive provider is called first private void h_MsSetRamChrAbility(int chr_id, Chr* chr) { OverdriveProvider.provide_overdrive(chr_id); - FhXCall.h_MsSetRamChrAbility.chain_from(h_MsSetRamChrAbility).fnptr!(chr_id, chr); + FhXCall.MsSetRamChrAbility.chain_from(h_MsSetRamChrAbility).fnptr!(chr_id, chr); } // Runs on every Tidus Limit. Override the normal requirements, and send locations based on 10 / 20 / 40 @@ -250,19 +250,19 @@ private int h_MsLimitTidusLearn(int chr_id) { if (tidusLimitUses >= 10) { if (send_overdrive(PlayerCommandId.PCOM_SLICE_AND_DICE)) { - FhXCall.h_MsMessageCueRegist.fnptr!(6, PlySaveId.PC_TIDUS, PlayerCommandId.PCOM_SLICE_AND_DICE, 0x1e, 0x32); + FhXCall.MsMessageCueRegist.fnptr!(6, PlySaveId.PC_TIDUS, PlayerCommandId.PCOM_SLICE_AND_DICE, 0x1e, 0x32); } } if (tidusLimitUses >= 20) { if(send_overdrive(PlayerCommandId.PCOM_ENERGY_RAIN)) { - FhXCall.h_MsMessageCueRegist.fnptr!(6, PlySaveId.PC_TIDUS, PlayerCommandId.PCOM_ENERGY_RAIN, 0x1e, 0x32); + FhXCall.MsMessageCueRegist.fnptr!(6, PlySaveId.PC_TIDUS, PlayerCommandId.PCOM_ENERGY_RAIN, 0x1e, 0x32); } } if (tidusLimitUses >= 40) { if(send_overdrive(PlayerCommandId.PCOM_BLITZ_ACE)) { - FhXCall.h_MsMessageCueRegist.fnptr!(6, PlySaveId.PC_TIDUS, PlayerCommandId.PCOM_BLITZ_ACE, 0x1e, 0x32); + FhXCall.MsMessageCueRegist.fnptr!(6, PlySaveId.PC_TIDUS, PlayerCommandId.PCOM_BLITZ_ACE, 0x1e, 0x32); } } @@ -273,8 +273,8 @@ private int h_MsLimitTidusLearn(int chr_id) { private uint h_MsAfterDamageProcess(int attacker_id, uint param_2, int target_id, uint* param_4, uint param_5) { uint uVar12 = 0; DamageInfo* local_30 = (DamageInfo*)0x0; - Chr* attacker = FhXCall.h_MsGetChr.fnptr!(attacker_id); - Chr* target = FhXCall.h_MsGetChr.fnptr!(target_id); + Chr* attacker = FhXCall.MsGetChr.fnptr!(attacker_id); + Chr* target = FhXCall.MsGetChr.fnptr!(target_id); Chr__0x774* target_0x774 = (Chr__0x774*)((int)target + 0x774); for (int n = 2; n > 0; n--) { @@ -284,26 +284,26 @@ private uint h_MsAfterDamageProcess(int attacker_id, uint param_2, int target_id set_at((int)target + 0xDED, (byte)attacker_id); if (!param_5.get_bit(3)) { if (target_0x774->field7_0x7 != 0) { - FhXCall.h_MsMenuCloseTitleWindow.fnptr!(0); + FhXCall.MsMenuCloseTitleWindow.fnptr!(0); target_0x774->field7_0x7 = 0; //_MsMessageCueRegist(0x4, target_0x774->field7_0x7 + 3, target_0x774->field7_0x7 + 1, 0x1b, 0x23); - FhXCall.h_MsMessageCueRegist.fnptr!(0x4, target_0x774->field10_0xA, target_0x774->field8_0x8, 0x1b, 0x23); + FhXCall.MsMessageCueRegist.fnptr!(0x4, target_0x774->field10_0xA, target_0x774->field8_0x8, 0x1b, 0x23); if (0 < target_0x774->field8_0x8) { - FhXCall.h_MsSetStealEffect.fnptr!(target_id, target_0x774->field1_0x1); - FhXCall.h_MsRegSEplay2.fnptr!(target_id, 0x41); + FhXCall.MsSetStealEffect.fnptr!(target_id, target_0x774->field1_0x1); + FhXCall.MsRegSEplay2.fnptr!(target_id, 0x41); } target_0x774->field5_0x5 |= 1; } if (target_0x774->field12_0xC != 0) { - FhXCall.h_MsMenuCloseTitleWindow.fnptr!(0); + FhXCall.MsMenuCloseTitleWindow.fnptr!(0); target_0x774->field12_0xC = 0; - FhXCall.h_MsMessageCueRegist.fnptr!(0x8, target_0x774->field16_0x10, 0, 0x1b, 0x23); + FhXCall.MsMessageCueRegist.fnptr!(0x8, target_0x774->field16_0x10, 0, 0x1b, 0x23); if (0 < target_0x774->field16_0x10) { - FhXCall.h_MsPayGIL.fnptr!(-*(int*)(target_0x774 + 9)); - FhXCall.h_MsSetStealGillEffect.fnptr!(target_id, target_0x774->field1_0x1); - FhXCall.h_MsRegSEplay2.fnptr!(target_id, 0x41); + FhXCall.MsPayGIL.fnptr!(-*(int*)(target_0x774 + 9)); + FhXCall.MsSetStealGillEffect.fnptr!(target_id, target_0x774->field1_0x1); + FhXCall.MsRegSEplay2.fnptr!(target_id, 0x41); } target_0x774->field5_0x5 |= 1; @@ -314,16 +314,16 @@ private uint h_MsAfterDamageProcess(int attacker_id, uint param_2, int target_id if (target_0x774->field4_0x4.get_bit(0)) { byte bVar1 = attacker->ram.limit_charge; attacker->ram.limit_charge = 0; - target->ram.limit_charge = (byte)FhXCall.h_MsCheckRange.fnptr!(target->ram.limit_charge + bVar1, 0, target->ram.limit_charge_max); + target->ram.limit_charge = (byte)FhXCall.MsCheckRange.fnptr!(target->ram.limit_charge + bVar1, 0, target->ram.limit_charge_max); } if (target_0x774->field4_0x4.get_bit(1)) { - Chr* pCVar8 = FhXCall.h_MsGetChr.fnptr!(target_0x774->chr_id__0x17); + Chr* pCVar8 = FhXCall.MsGetChr.fnptr!(target_0x774->chr_id__0x17); if (target_id == PlySaveId.PC_KIMAHRI && pCVar8->loot != (ChrLoot*)0x0) { ushort rage_to_learn = pCVar8->loot->ronso_rage; if (rage_to_learn != 0) { if(send_overdrive(rage_to_learn)) { - FhXCall.h_MsMessageCueRegist.fnptr!(6, PlySaveId.PC_KIMAHRI, rage_to_learn, 0x1e, 0x32); + FhXCall.MsMessageCueRegist.fnptr!(6, PlySaveId.PC_KIMAHRI, rage_to_learn, 0x1e, 0x32); target->ram.limit_charge = target->ram.limit_charge_max; } @@ -335,7 +335,7 @@ private uint h_MsAfterDamageProcess(int attacker_id, uint param_2, int target_id save_data->ability_map_limit.has_white_wind && save_data->ability_map_limit.has_bad_breath && save_data->ability_map_limit.has_mighty_guard && save_data->ability_map_limit.has_nova ) { - FhXCall.h_achievementUnlockAchievement.fnptr!(0x19); + FhXCall.achievementUnlockAchievement.fnptr!(0x19); } } } @@ -353,15 +353,15 @@ private uint h_MsAfterDamageProcess(int attacker_id, uint param_2, int target_id uint uVar9 = target_0x774_damage_info->field2_0x2; if (iVar7 == 1) { - FhXCall.h_MsNumberRegist.fnptr!(target_id, 3, 0, 0, 1, uVar9, 0x81); + FhXCall.MsNumberRegist.fnptr!(target_id, 3, 0, 0, 1, uVar9, 0x81); } else if (iVar7 == 2) { - FhXCall.h_MsNumberRegist.fnptr!(target_id, 4, 0, 0, 2, uVar9, 0x81); + FhXCall.MsNumberRegist.fnptr!(target_id, 4, 0, 0, 2, uVar9, 0x81); } - FhXCall.h_MsLimitTypeDamageCheck.fnptr!(attacker_id, attacker, target_id, target, target_0x774_damage_info->out_damage_hp, target_0x774_damage_info->out_damage_expected, target_0x774->field6_0x6); + FhXCall.MsLimitTypeDamageCheck.fnptr!(attacker_id, attacker, target_id, target, target_0x774_damage_info->out_damage_hp, target_0x774_damage_info->out_damage_expected, target_0x774->field6_0x6); if (target_0x774_damage_info->dmg_calc_flags1.get_bit(0)) { - FhXCall.h_MsSubHP.fnptr!(target_id, target, target_0x774_damage_info->out_damage_hp, target_0x774_damage_info->out_damage_mp, iVar7, uVar9, 0x81); + FhXCall.MsSubHP.fnptr!(target_id, target, target_0x774_damage_info->out_damage_hp, target_0x774_damage_info->out_damage_mp, iVar7, uVar9, 0x81); set_at((int)target + 0xF60, get_at((int)target + 0xF60) - target_0x774_damage_info->out_damage_hp); @@ -369,15 +369,15 @@ private uint h_MsAfterDamageProcess(int attacker_id, uint param_2, int target_id } if (target_0x774_damage_info->dmg_calc_flags1.get_bit(1)) { - FhXCall.h_MsSubMP.fnptr!(target_id, target, target_0x774_damage_info->out_damage_mp, target_0x774_damage_info->out_damage_hp, iVar7, uVar9, 0x81); + FhXCall.MsSubMP.fnptr!(target_id, target, target_0x774_damage_info->out_damage_mp, target_0x774_damage_info->out_damage_hp, iVar7, uVar9, 0x81); } if (target_0x774_damage_info->dmg_calc_flags1.get_bit(2)) { - FhXCall.h_MsSubCTB.fnptr!(target_id, target, target_0x774_damage_info->out_damage_ctb, iVar7, uVar9, 0x81); + FhXCall.MsSubCTB.fnptr!(target_id, target, target_0x774_damage_info->out_damage_ctb, iVar7, uVar9, 0x81); //dbgPrintf("CTB DAMAGE %d %d : %d\n", target_id, iVar10, (target->ram).ctb); } - FhXCall.h_MsLimitTypeStatusCheck.fnptr!(attacker_id, attacker, target_id, target, target_0x774_damage_info->field4_0x4, target_0x774_damage_info->field3_0x3); + FhXCall.MsLimitTypeStatusCheck.fnptr!(attacker_id, attacker, target_id, target, target_0x774_damage_info->field4_0x4, target_0x774_damage_info->field3_0x3); StatusPermanentFlags SVar5 = target->ram.status_suffer; byte bVar1 = target->ram.status_suffer_turns_left.darkness; byte bVar2 = target->ram.status_suffer_turns_left.silence; @@ -391,46 +391,46 @@ private uint h_MsAfterDamageProcess(int attacker_id, uint param_2, int target_id } target->ram.status_suffer_extra = target_0x774_damage_info->target_status_suffer_extra; - FhXCall.h_MsLimitStatusProcess.fnptr!(target_id, target, target_0x774_damage_info->flags_buffs_mix); + FhXCall.MsLimitStatusProcess.fnptr!(target_id, target, target_0x774_damage_info->flags_buffs_mix); if (target->ram.status_suffer_turns_left.regen != 0 && bVar3 == 0) { target->ram.regen_strength = 0; } StatusPermanentFlags SVar6 = target->ram.status_suffer; - set_at((int)target + 0xDCE, SVar6.petrification()); - if (target->ram.status_suffer.death() != SVar5.death()) { - FhXCall.h_MsAliveProcess.fnptr!(target_id, target); + set_at((int)target + 0xDCE, SVar6.petrification); + if (target->ram.status_suffer.death != SVar5.death) { + FhXCall.MsAliveProcess.fnptr!(target_id, target); } - if (target->ram.status_suffer.petrification() != SVar5.petrification()) { - FhXCall.h_MsStoneProcess.fnptr!(target_id, target); + if (target->ram.status_suffer.petrification != SVar5.petrification) { + FhXCall.MsStoneProcess.fnptr!(target_id, target); } - if (target->ram.status_suffer_extra.eject() != bVar4.eject()) { - FhXCall.h_MsBlowProcess.fnptr!(target_id, target); + if (target->ram.status_suffer_extra.eject != bVar4.eject) { + FhXCall.MsBlowProcess.fnptr!(target_id, target); } - if (target->ram.status_suffer.threaten() != SVar5.threaten()) { - FhXCall.h_MsThreatProcess.fnptr!(target_id, target); + if (target->ram.status_suffer.threaten != SVar5.threaten) { + FhXCall.MsThreatProcess.fnptr!(target_id, target); } target_0x774->field5_0x5 |= 1; if (target->ram.auto_ability_effects.has_auto_med) { - FhXCall.h_MsAutoCureProcess.fnptr!(target_id, target, attacker_id, (int)SVar5 >> 3 & 1, (int)SVar5 >> 1 & 1, bVar1, bVar2); + FhXCall.MsAutoCureProcess.fnptr!(target_id, target, attacker_id, (int)SVar5 >> 3 & 1, (int)SVar5 >> 1 & 1, bVar1, bVar2); } if (0 < local_20 && target->ram.auto_ability_effects.has_auto_potion) { - FhXCall.h_MsAutoPotionProcess.fnptr!(target_id, target, attacker_id); + FhXCall.MsAutoPotionProcess.fnptr!(target_id, target, attacker_id); } - FhXCall.h_MsSetChrWeak.fnptr!(target_id, -1); + FhXCall.MsSetChrWeak.fnptr!(target_id, -1); uVar12 |= 2; target_0x774->field0_0x0 += 1; } if (get_at((int)&target->ram + 0x19C)) { - FhXCall.h_MsAutoRelifeProcess.fnptr!(attacker_id, attacker, target_id, target); + FhXCall.MsAutoRelifeProcess.fnptr!(attacker_id, attacker, target_id, target); } if (!param_5.get_bit(1) && (target_0x774_damage_info->field0_0x0 != 1 || !target_0x774->field5_0x5.get_bit(2))) { @@ -439,8 +439,8 @@ private uint h_MsAfterDamageProcess(int attacker_id, uint param_2, int target_id } if (!param_5.get_bit(4)) { - FhXCall.h_MsStatusEffectCheck.fnptr!(target_id); - if (FhXCall.h_MsStatusDefenseEffect.fnptr!(attacker_id, target_id, target_0x774_damage_info->dmg_calc_flags1) != 0) { + FhXCall.MsStatusEffectCheck.fnptr!(target_id); + if (FhXCall.MsStatusDefenseEffect.fnptr!(attacker_id, target_id, target_0x774_damage_info->dmg_calc_flags1) != 0) { *param_4 = (uint)target_id; } } @@ -452,11 +452,11 @@ private uint h_MsAfterDamageProcess(int attacker_id, uint param_2, int target_id if (target_0x774->field5_0x5.get_bit(0) && !target_0x774->field5_0x5.get_bit(1)) { set_at((int)&target->ram + 0x19D, false); target_0x774->field5_0x5 |= 2; - FhXCall.h_MsActionRequest.fnptr!(target_id, attacker_id, 3, 0, 1, null); + FhXCall.MsActionRequest.fnptr!(target_id, attacker_id, 3, 0, 1, null); } if (!param_5.get_bit(10)) { - FhXCall.h_MsPopBtlPos.fnptr!(target); + FhXCall.MsPopBtlPos.fnptr!(target); } else { target_0x774->field2_0x2 = 0xff; } @@ -468,7 +468,7 @@ private uint h_MsAfterDamageProcess(int attacker_id, uint param_2, int target_id int not_attacking_self = attacker_id != target_id ? 1 : 0; - if (!uVar12.get_bit(0) && FhXCall.h_MsDamageCheckDeath.fnptr!(attacker_id, target_id, 0, not_attacking_self) != 0) { + if (!uVar12.get_bit(0) && FhXCall.MsDamageCheckDeath.fnptr!(attacker_id, target_id, 0, not_attacking_self) != 0) { return uVar12; } @@ -477,23 +477,23 @@ private uint h_MsAfterDamageProcess(int attacker_id, uint param_2, int target_id } if (!param_5.get_bit(5)) { - FhXCall.h_MsDamageSetMotion.fnptr!(target_id, local_30->field0_0x0, not_attacking_self); + FhXCall.MsDamageSetMotion.fnptr!(target_id, local_30->field0_0x0, not_attacking_self); return uVar12; } if (local_30->field0_0x0 != 5) { if (local_30->field0_0x0 == 6) { - FhXCall.h_MsDamageSetMotion.fnptr!(target_id, FhXCall.h_brnd.fnptr!(9).get_bit(0) ? 0x10 : 0xF, not_attacking_self); + FhXCall.MsDamageSetMotion.fnptr!(target_id, FhXCall.brnd.fnptr!(9).get_bit(0) ? 0x10 : 0xF, not_attacking_self); return uVar12; } if (local_30->field0_0x0 != 8) { - FhXCall.h_MsDamageSetMotion.fnptr!(target_id, local_30->field0_0x0, not_attacking_self); + FhXCall.MsDamageSetMotion.fnptr!(target_id, local_30->field0_0x0, not_attacking_self); return uVar12; } } - FhXCall.h_MsDamageSetMotion.fnptr!(target_id, FhXCall.h_brnd.fnptr!(9).get_bits(0, 2) + 0xD, not_attacking_self); + FhXCall.MsDamageSetMotion.fnptr!(target_id, FhXCall.brnd.fnptr!(9).get_bits(0, 2) + 0xD, not_attacking_self); return uVar12; } @@ -522,20 +522,20 @@ private void h_MsSetSaveCommandWithPrefix(int chr_id, int com_id, int param_3) { return; } - FhXCall.h_MsSetSaveCommandWithPrefix.chain_from(h_MsSetSaveCommandWithPrefix).fnptr!(chr_id, com_id, param_3); + FhXCall.MsSetSaveCommandWithPrefix.chain_from(h_MsSetSaveCommandWithPrefix).fnptr!(chr_id, com_id, param_3); } private int h_TOBtlDrawLearningMessageWindow(int chr_id, int com_id) { byte* data_end; - byte* chr_name = FhXCall.h_TOGetSaveChrName.fnptr!(chr_id); - FhXCall.h_TOBtlSetMacroCommandType.fnptr!(7, 0, 0); - FhXCall.h_TOBtlSetMacroCommandValue.fnptr!(7, 0, chr_name); + byte* chr_name = FhXCall.TOGetSaveChrName.fnptr!(chr_id); + FhXCall.TOBtlSetMacroCommandType.fnptr!(7, 0, 0); + FhXCall.TOBtlSetMacroCommandValue.fnptr!(7, 0, chr_name); - Command* com = FhXCall.h_MsGetComData.fnptr!(com_id, &data_end); + Command* com = FhXCall.MsGetComData.fnptr!(com_id, &data_end); ushort com_name_offset = com->name_offset; - FhXCall.h_TOBtlSetMacroCommandType.fnptr!(7, 1, 0); + FhXCall.TOBtlSetMacroCommandType.fnptr!(7, 1, 0); if (item_locations.overdrive.TryGetValue(com_id - PlayerCommandId.PCOM_SPIRAL_CUT, out var item)) { NativeCustomString custom_text; @@ -546,13 +546,13 @@ private int h_TOBtlDrawLearningMessageWindow(int chr_id, int com_id) { custom_text = new($"{item.player}'s {item.name}"); } - FhXCall.h_TOBtlSetMacroCommandValue.fnptr!(7, 1, custom_text.encoded); + FhXCall.TOBtlSetMacroCommandValue.fnptr!(7, 1, custom_text.encoded); } else { - FhXCall.h_TOBtlSetMacroCommandValue.fnptr!(7, 1, data_end + com_name_offset); + FhXCall.TOBtlSetMacroCommandValue.fnptr!(7, 1, data_end + com_name_offset); } - byte* btl_text = FhXCall.h_MsGetRomBtlText.fnptr!(0x300d, 0); - FhXCall.h_FUN_0089db10.fnptr!(0, btl_text); + byte* btl_text = FhXCall.MsGetRomBtlText.fnptr!(0x300d, 0); + FhXCall.FUN_0089db10.fnptr!(0, btl_text); return 7; } diff --git a/src/modules/sphere_grid.cs b/src/modules/sphere_grid.cs index 668b825..8d35ff3 100644 --- a/src/modules/sphere_grid.cs +++ b/src/modules/sphere_grid.cs @@ -1,10 +1,14 @@ -using Fahrenheit; -using Fahrenheit.FFX; -using Hexa.NET.ImGui; using System.Collections.Generic; using System.IO; using System.Text; + +using Hexa.NET.ImGui; + +using Fahrenheit; +using Fahrenheit.FFX; + using static Fahrenheit.FFX.Globals; + using FhXCall = Fahrenheit.FFX.FhCall; namespace ArchipelagoFFX; @@ -32,11 +36,11 @@ public override bool init(FhModContext mod_context, FileStream global_state_file _mod_context = mod_context; _global_state = global_state_file; - return FhXCall.h_AbmapState_MovingToTarget.hook(this, h_move_speed) - && FhXCall.h_FUN_00a56160.hook(this, h_move_confirm) - && FhXCall.h_AbmapState_MovingToTarget.hook(this, h_state_moving) - && FhXCall.h_AbmapState_Warping.hook(this, h_state_warping) - && FhXCall.h_AbmapState_ChangingNode.hook(this, h_change_node); + return FhXCall.AbmapState_MovingToTarget.hook(this, h_move_speed) + && FhXCall.FUN_00a56160.hook(this, h_move_confirm) + && FhXCall.AbmapState_MovingToTarget.hook(this, h_state_moving) + && FhXCall.AbmapState_Warping.hook(this, h_state_warping) + && FhXCall.AbmapState_ChangingNode.hook(this, h_change_node); } private string get_state_name() { @@ -191,20 +195,20 @@ private void render_node_info() { if (ImGui.Button(activated ? $"Deactivate##{i}" : $"Activate##{i}")) { if (activated) { selected_node->activated_by.set_bit(i, false); - FhXCall.h_SndSepPlaySimple.fnptr!(SND_DEACTIVATE_NODE); + FhXCall.SndSepPlaySimple.fnptr!(SND_DEACTIVATE_NODE); lpamng->should_update = 1; lpamng->should_update_node = lpamng->selected_node_idx; } else { - FhXCall.h_abmap_get_panel.fnptr!(i, lpamng->selected_node_idx); + FhXCall.abmap_get_panel.fnptr!(i, lpamng->selected_node_idx); } } } ImGui.Unindent(); - ImGui.Text($"Can target? {selected_node->properties.can_target()}"); - ImGui.Text($"Is highlighted? {selected_node->properties.is_highlighted()}"); + ImGui.Text($"Can target? {selected_node->properties.can_target}"); + ImGui.Text($"Is highlighted? {selected_node->properties.is_highlighted}"); ImGui.Text($"Move cost: {selected_node->move_cost}"); } @@ -214,7 +218,7 @@ public void h_move_speed() { float prev_t = lpamng->moving_progress; - FhXCall.h_AbmapState_MovingToTarget.chain_from(h_move_speed).fnptr!(); + FhXCall.AbmapState_MovingToTarget.chain_from(h_move_speed).fnptr!(); if (freeze_move) { lpamng->moving_progress = prev_t; @@ -268,7 +272,7 @@ private bool try_activate(short node_idx, int ply_id, bool temporary) { } node->activated_by.set_bit(ply_id, true); - FhXCall.h_SndSepPlaySimple.fnptr!(SND_ACTIVATE_NODE); + FhXCall.SndSepPlaySimple.fnptr!(SND_ACTIVATE_NODE); if (temporary) { temporarily_activated_nodes.Add(node_idx); @@ -302,7 +306,7 @@ public void h_move_confirm(int p1, int p2, int p3) { knots_counted = 0; - FhXCall.h_FUN_00a56160.chain_from(h_move_confirm).fnptr!(p1, p2, p3); + FhXCall.FUN_00a56160.chain_from(h_move_confirm).fnptr!(p1, p2, p3); // If we cancelled it, also deactivate all activated nodes if (p3 == 1 && temporarily_activated_nodes.Count > 0) { @@ -312,7 +316,7 @@ public void h_move_confirm(int p1, int p2, int p3) { lpamng->nodes[node_idx].activated_by.set_bit(chr_id, false); } - FhXCall.h_SndSepPlaySimple.fnptr!(SND_DEACTIVATE_NODE); + FhXCall.SndSepPlaySimple.fnptr!(SND_DEACTIVATE_NODE); lpamng->should_update = 1; lpamng->should_update_node = -1; @@ -327,7 +331,7 @@ public void h_state_moving() { float prev_t = lpamng->moving_progress; short last_knot = lpamng->move_next_target_node_idx; - FhXCall.h_AbmapState_MovingToTarget.chain_from(h_state_moving).fnptr!(); + FhXCall.AbmapState_MovingToTarget.chain_from(h_state_moving).fnptr!(); float current_t = lpamng->moving_progress; @@ -354,7 +358,7 @@ public void h_state_warping() { byte last_warp_state = *(byte*)((int)lpamng + 0x1164c); - FhXCall.h_AbmapState_Warping.chain_from(h_state_warping).fnptr!(); + FhXCall.AbmapState_Warping.chain_from(h_state_warping).fnptr!(); // Warp states: // 0 == Disappearing @@ -390,7 +394,7 @@ public void h_change_node() { short node_idx = *(short*)((int)lpamng + 0x1164e); byte ply_id = lpamng->current_chr_id; - FhXCall.h_AbmapState_ChangingNode.chain_from(h_change_node).fnptr!(); + FhXCall.AbmapState_ChangingNode.chain_from(h_change_node).fnptr!(); byte timing = *(byte*)((int)lpamng + 0x11650); From 291d9e175f349321901f6477b3894d96ccbea221 Mon Sep 17 00:00:00 2001 From: evelyntsmg Date: Tue, 28 Jul 2026 23:14:10 +0200 Subject: [PATCH 18/20] Hook up 'render_game' properly --- src/archipelago.cs | 19 ------------------- src/hooks.cs | 24 +++++++++++++++++++++++- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/src/archipelago.cs b/src/archipelago.cs index e6d9801..37962a6 100644 --- a/src/archipelago.cs +++ b/src/archipelago.cs @@ -1031,23 +1031,4 @@ public void set_character_model(int chr_id) { // _logger.Debug($"read {readBytes}, beginning={((byte*)file_ptr)[0]} {((byte*)file_ptr)[1]} {((byte*)file_ptr)[2]} {((byte*)file_ptr)[3]}"); // return readBytes; //} - - public struct CustomStringDrawInfo(ManagedCustomString customString, Vector2 pos, float scale = 0.65f, byte color = 0, bool persistent = false) { - public ManagedCustomString customString = customString; - public Vector2 pos = pos; - public float scale = scale; - public byte color = color; - public bool persistent = persistent; - } - - public Dictionary customStringDrawInfos = []; - - //TODO: Figure out where to hook to make this work again - public void render_game() { - foreach ((string key, CustomStringDrawInfo drawInfo) in customStringDrawInfos) { - fixed (byte* text = drawInfo.customString.encoded) { - FhXCall.TOMkpCrossExtMesFontLClutTypeRGBA.fnptr!(0, text, drawInfo.pos.X, drawInfo.pos.Y, drawInfo.color, 0, 0x80, 0x80, 0x80, 0x80, drawInfo.scale, 0); - } - } - } } diff --git a/src/hooks.cs b/src/hooks.cs index 3511d7f..a8fe9c0 100644 --- a/src/hooks.cs +++ b/src/hooks.cs @@ -212,7 +212,8 @@ private bool hook() { && FhXCall.DrawGearCustomizationMenu.hook(this, DrawGearCustomizationMenu) && FhXCall.TkMenuCtrlSummon.hook(this, TkMenuCtrlSummon) && FhXCall.FUN_008cdb70.hook(this, DrawAeonCustomizationMenu) - && FhXCall.FUN_008d5720.hook(this, FUN_008d5720); + && FhXCall.FUN_008d5720.hook(this, FUN_008d5720) + && FhXCall.TODrawWindow.hook(this, render_game); // && _FUN_00656c90.hook() && _FUN_0065ee30.hook(); // && _openFile.hook() && _FUN_0070aec0.hook(); // && _MsCheckLeftWindow.hook() && _MsCheckUseCommand.hook() && _TOBtlDrawStatusLimitGauge.hook(); @@ -4185,4 +4186,25 @@ public int CT_RetInt_CheckUnlockedAeons(AtelBasicWorker* work, int* storage, Ate } return 0; } + + public struct CustomStringDrawInfo(ManagedCustomString customString, Vector2 pos, float scale = 0.65f, byte color = 0, bool persistent = false) { + public ManagedCustomString customString = customString; + public Vector2 pos = pos; + public float scale = scale; + public byte color = color; + public bool persistent = persistent; + } + + public Dictionary customStringDrawInfos = []; + + //TODO: Figure out where to hook to make this work again + public void render_game() { + FhXCall.TODrawWindow.chain_from(render_game).fnptr!(); + + foreach ((string key, CustomStringDrawInfo drawInfo) in customStringDrawInfos) { + fixed (byte* text = drawInfo.customString.encoded) { + FhXCall.TOMkpCrossExtMesFontLClutTypeRGBA.fnptr!(0, text, drawInfo.pos.X, drawInfo.pos.Y, drawInfo.color, 0, 0x80, 0x80, 0x80, 0x80, drawInfo.scale, 0); + } + } + } } From 99da8be4203678c9543a9b7161c7ecf11097ffa6 Mon Sep 17 00:00:00 2001 From: evelyntsmg Date: Tue, 28 Jul 2026 23:16:44 +0200 Subject: [PATCH 19/20] Remove residual TODO --- src/hooks.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/hooks.cs b/src/hooks.cs index a8fe9c0..6e60a98 100644 --- a/src/hooks.cs +++ b/src/hooks.cs @@ -4197,7 +4197,6 @@ public struct CustomStringDrawInfo(ManagedCustomString customString, Vector2 pos public Dictionary customStringDrawInfos = []; - //TODO: Figure out where to hook to make this work again public void render_game() { FhXCall.TODrawWindow.chain_from(render_game).fnptr!(); From decfd97f001e827f7014f3bb580221023b61dad4 Mon Sep 17 00:00:00 2001 From: evelyntsmg Date: Tue, 28 Jul 2026 23:21:40 +0200 Subject: [PATCH 20/20] Hook up 'handle_input' through the GameLoop.PreUpdate event --- src/archipelago.cs | 2 +- src/hooks.cs | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/archipelago.cs b/src/archipelago.cs index 37962a6..a083c6f 100644 --- a/src/archipelago.cs +++ b/src/archipelago.cs @@ -719,7 +719,7 @@ public void pre_update(UpdateLoopEventArgs args) { } } - public void handle_input() { + public void handle_input(UpdateLoopEventArgs e) { /* if (Globals.Input.select.held) { if (Globals.Input.l1.just_pressed) { diff --git a/src/hooks.cs b/src/hooks.cs index 6e60a98..0435c7a 100644 --- a/src/hooks.cs +++ b/src/hooks.cs @@ -177,6 +177,8 @@ private void init_custom_atel() { } private bool hook() { + FhApi.Events.Common.GameLoop.PreUpdate.subscribe(handle_input); + return h_Common_obtainTreasureInit.hook(this, Common_obtainTreasureInit) && h_Common_obtainTreasureSilentlyInit.hook(this, Common_obtainTreasureSilentlyInit) && h_Common_obtainBrotherhoodRetInt.hook(this, Common_obtainBrotherhoodRetInt)