diff --git a/src/archipelago.cs b/src/archipelago.cs index bd2d6f2..86aff37 100644 --- a/src/archipelago.cs +++ b/src/archipelago.cs @@ -135,19 +135,19 @@ public struct ArchipelagoSeedOptions { [JsonInclude] public int CaptureDamage; [JsonInclude] - public int SkipContestOfAeons; + public int ContestOfAeonsDifficulty; public ArchipelagoSeedOptions() { - PlayerName = ""; - SeedId = ""; - GoalRequirement = GoalRequirement.None; - RequiredPartyMembers = 1; - RequiredPrimers = 0; - APMultiplier = 1; - AlwaysSensor = 0; - AlwaysCapture = 0; - CaptureDamage = 0; - SkipContestOfAeons = 0; + PlayerName = ""; + SeedId = ""; + GoalRequirement = GoalRequirement.None; + RequiredPartyMembers = 1; + RequiredPrimers = 0; + APMultiplier = 1; + AlwaysSensor = 0; + AlwaysCapture = 0; + CaptureDamage = 0; + ContestOfAeonsDifficulty = 2; } } public struct ArchipelagoSeedLocations { @@ -938,6 +938,16 @@ public static uint allocate_file(string filename, out nint file_ptr) { return readBytes; } + public static void try_remove_autolife() { + // In every Contest of Aeons battle, autolife is applied at 004E through 005A, so just remove those + if (seed.Options.ContestOfAeonsDifficulty == 2) { + AtelScriptChunk* script_chunk = Globals.Atel.controllers[0].script_chunk; + nint code_ptr = (nint)((int)script_chunk + script_chunk->offset_code); + NativeMemory.Fill((void*)(code_ptr + 0x4E), 0xC, 0); + set(code_ptr, 0x4E, atelNOPArray(0xC)); + } + } + public override void render_imgui() { ArchipelagoGUI.render(); } diff --git a/src/data/ArchipelagoData.cs b/src/data/ArchipelagoData.cs index 66dcffc..d5b17ab 100644 --- a/src/data/ArchipelagoData.cs +++ b/src/data/ArchipelagoData.cs @@ -159,7 +159,7 @@ public enum GoalRequirement { 282, 220, 139, - 191, // + 191, // 336, // Jecht Sphere 337, // Jecht Sphere 347, //Blitzball Menu @@ -606,7 +606,7 @@ public unsafe class ArchipelagoRegion { ArchipelagoFFXModule.call_warp_to_map(382, 0); }} } } } }, - {RegionEnum.BaajTemple, new(){ story_progress = 30, room_id = 48, entrance = 0, airship_destination_index = 1, + {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"); } } }, @@ -700,9 +700,9 @@ public unsafe class ArchipelagoRegion { } } } } }, - { 730, new() {visit_complete = true, next_story_progress = 3210, next_room_id = 123, next_entrance = 6, return_to_airship = true, + { 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"); + ArchipelagoFFXModule.logger.Info("Luca visit complete"); // CSR workaround Globals.save_data->current_room_id = 123; Globals.save_data->current_spawnpoint = 6; @@ -740,7 +740,7 @@ public unsafe class ArchipelagoRegion { } } }, {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, + { 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; @@ -842,7 +842,7 @@ public unsafe class ArchipelagoRegion { { 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, // Destination 12 doesn't work (12 = Bevelle but doesn't have destination, 18 = Highbridge) + {RegionEnum.Bevelle, new(){ story_progress = 2040, room_id = 205, entrance = 0, airship_destination_index = 14, // Destination 12 doesn't work (12 = Bevelle but doesn't have destination, 18 = Highbridge) story_checks = { { 2220, new() {pilgrimage = true, check_delegate = (r) => { // Bahamut @@ -857,7 +857,7 @@ public unsafe class ArchipelagoRegion { } } }, { 2385, new() {visit_complete = true, next_story_progress = 2920, next_room_id = 208, next_entrance = 1, return_to_airship = true, check_delegate = (r) => {ArchipelagoFFXModule.logger.Info("Bevelle visit 1 complete"); } } }, { 2945, new() {visit_complete = true, next_story_progress = 3210, next_room_id = 208, next_entrance = 1, check_delegate = (r) => {ArchipelagoFFXModule.logger.Info("Bevelle visit 2 complete"); } } }, - } } }, + } } }, {RegionEnum.CalmLands, new(){ story_progress = 2385, room_id = 223, entrance = 0, airship_destination_index = 15, savedata = [ new ArchipelagoRegionSaveData(0x0285, 1), @@ -1025,7 +1025,7 @@ public unsafe class ArchipelagoRegion { 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) }, // Yenke and Biran. Can only target Kimahri and scale on his stats. @@ -1144,12 +1144,23 @@ public unsafe class ArchipelagoRegion { {"bsil03_03", () => ArchipelagoFFXModule.set_underwater_party()}, // S.S Liki {"slik02_01", () => ArchipelagoFFXModule.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()}, + + // Hardcore Contest of Aeons + { "sins07_00", () => ArchipelagoFFXModule.try_remove_autolife() }, // Valefor + { "sins07_01", () => ArchipelagoFFXModule.try_remove_autolife() }, // Ifrit + { "sins07_02", () => ArchipelagoFFXModule.try_remove_autolife() }, // Ixion + { "sins07_03", () => ArchipelagoFFXModule.try_remove_autolife() }, // Shiva + { "sins07_04", () => ArchipelagoFFXModule.try_remove_autolife() }, // Bahamut + { "sins07_05", () => ArchipelagoFFXModule.try_remove_autolife() }, // Anima + { "sins07_06", () => ArchipelagoFFXModule.try_remove_autolife() }, // Yojimbo + { "sins07_07", () => ArchipelagoFFXModule.try_remove_autolife() }, // Magus Sisters + { "sins07_10", () => ArchipelagoFFXModule.try_remove_autolife() }, // Yu Yevon }; diff --git a/src/hooks.cs b/src/hooks.cs index 78081d3..455e10f 100644 --- a/src/hooks.cs +++ b/src/hooks.cs @@ -1528,7 +1528,7 @@ AtelOp.PUSHII .build(0x0000), logger.Debug($"atel_event_setup: Handle removing Aeons"); // Lock all Aeons and skip Contest of Aeons - if (seed.Options.SkipContestOfAeons == 1) { + if (seed.Options.ContestOfAeonsDifficulty == 1) { set(code_ptr, 0x58FA, [ AtelOp.CALLPOPA.build((ushort)CustomCallTarget.LOCK_ALL_AEONS), AtelOp.JMP.build(0x0003),