From 7d304fd38d62b8fff4084bc6ece7de1381a2e52f Mon Sep 17 00:00:00 2001 From: Guffawaffle Date: Thu, 10 Sep 2026 00:55:16 -0500 Subject: [PATCH 1/2] Add option to hide artifact Exchange All button --- example_community_patch_settings_da.toml | 2 + example_community_patch_settings_de.toml | 2 + ...munity_patch_settings_en-GB-x-cockney.toml | 2 + ...mmunity_patch_settings_en-x-minionese.toml | 2 + example_community_patch_settings_en.toml | 2 + example_community_patch_settings_es.toml | 2 + example_community_patch_settings_fr.toml | 2 + example_community_patch_settings_nl.toml | 2 + example_community_patch_settings_ru.toml | 2 + example_community_patch_settings_tlh.toml | 2 + mods/src/config.cc | 2 + mods/src/config.h | 1 + mods/src/defaultconfig.h | 1 + mods/src/patches/parts/artifact_exchange.cc | 47 +++++++++++++++++++ mods/src/patches/patches.cc | 2 + 15 files changed, 73 insertions(+) create mode 100644 mods/src/patches/parts/artifact_exchange.cc diff --git a/example_community_patch_settings_da.toml b/example_community_patch_settings_da.toml index c60c5c39f..e31ebf99d 100644 --- a/example_community_patch_settings_da.toml +++ b/example_community_patch_settings_da.toml @@ -630,6 +630,8 @@ zoom_reset = "=" # <[=================================================================================]> [ui] +# Hide artifact shards "Exchange All"; individual exchanges remain available. Requires restart. +hide_artifact_exchange_all = false # Spring animationen ved åbning af kasser over, og åbn blot kasserne always_skip_reveal_sequence = true auto_confirm_discovery = true diff --git a/example_community_patch_settings_de.toml b/example_community_patch_settings_de.toml index 6756ed409..b0848be81 100644 --- a/example_community_patch_settings_de.toml +++ b/example_community_patch_settings_de.toml @@ -629,6 +629,8 @@ zoom_reset = "=" # <[==================================================================================================================================]> [ui] +# Blendet "Alle umtauschen" bei Artefaktfragmenten aus; einzelne Tauschvorgänge bleiben verfügbar. Neustart erforderlich. +hide_artifact_exchange_all = false # Überspringt die Animation und öffnet die Boxen direkt always_skip_reveal_sequence = true auto_confirm_discovery = true diff --git a/example_community_patch_settings_en-GB-x-cockney.toml b/example_community_patch_settings_en-GB-x-cockney.toml index ded80a9ef..3d5723a52 100644 --- a/example_community_patch_settings_en-GB-x-cockney.toml +++ b/example_community_patch_settings_en-GB-x-cockney.toml @@ -629,6 +629,8 @@ zoom_reset = "=" # <[===================================================================]> [ui] +# Hide artifact shards "Exchange All"; individual exchanges remain available. Requires restart. +hide_artifact_exchange_all = false # Skip the reveal box animation, and just open the boxes always_skip_reveal_sequence = true auto_confirm_discovery = true diff --git a/example_community_patch_settings_en-x-minionese.toml b/example_community_patch_settings_en-x-minionese.toml index 78b129750..e938ba07a 100644 --- a/example_community_patch_settings_en-x-minionese.toml +++ b/example_community_patch_settings_en-x-minionese.toml @@ -629,6 +629,8 @@ zoom_reset = "=" # <[==================]> [ui] +# Hide artifact shards "Exchange All"; individual exchanges remain available. Requires restart. +hide_artifact_exchange_all = false # Skip the reveal box animation, and just open the boxes always_skip_reveal_sequence = true auto_confirm_discovery = true diff --git a/example_community_patch_settings_en.toml b/example_community_patch_settings_en.toml index 7706e7c95..bd999d662 100644 --- a/example_community_patch_settings_en.toml +++ b/example_community_patch_settings_en.toml @@ -629,6 +629,8 @@ zoom_reset = "=" # <[===================================================================]> [ui] +# Hide artifact shards "Exchange All"; individual exchanges remain available. Requires restart. +hide_artifact_exchange_all = false # Skip the reveal box animation, and just open the boxes always_skip_reveal_sequence = true auto_confirm_discovery = true diff --git a/example_community_patch_settings_es.toml b/example_community_patch_settings_es.toml index 68b2bb4f7..2ef2260a0 100644 --- a/example_community_patch_settings_es.toml +++ b/example_community_patch_settings_es.toml @@ -629,6 +629,8 @@ zoom_reset = "=" # <[============================================================]> [ui] +# Hide artifact shards "Exchange All"; individual exchanges remain available. Requires restart. +hide_artifact_exchange_all = false # Omite la animación de revelado de cajas y simplemente ábrelas always_skip_reveal_sequence = true auto_confirm_discovery = true diff --git a/example_community_patch_settings_fr.toml b/example_community_patch_settings_fr.toml index dd8e462ac..204e3f82a 100644 --- a/example_community_patch_settings_fr.toml +++ b/example_community_patch_settings_fr.toml @@ -629,6 +629,8 @@ zoom_reset = "=" # <[===================================================================]> [ui] +# Masque "Tout échanger" pour les fragments d’artefacts ; les échanges individuels restent disponibles. Redémarrage requis. +hide_artifact_exchange_all = false # Ignorer l'animation d'ouverture des coffres et les ouvrir directement always_skip_reveal_sequence = true auto_confirm_discovery = true diff --git a/example_community_patch_settings_nl.toml b/example_community_patch_settings_nl.toml index b0726f8a9..181646e26 100644 --- a/example_community_patch_settings_nl.toml +++ b/example_community_patch_settings_nl.toml @@ -629,6 +629,8 @@ zoom_reset = "=" # <[===================================================================]> [ui] +# Verberg "Alles inwisselen" voor artefactfragmenten; afzonderlijk inwisselen blijft beschikbaar. Herstart vereist. +hide_artifact_exchange_all = false # Slaat de onthullig animatie van een kist altijd over en opent gewoon de kist always_skip_reveal_sequence = true auto_confirm_discovery = true diff --git a/example_community_patch_settings_ru.toml b/example_community_patch_settings_ru.toml index 1238fb805..3497155b8 100644 --- a/example_community_patch_settings_ru.toml +++ b/example_community_patch_settings_ru.toml @@ -629,6 +629,8 @@ zoom_reset = "=" # <[===================================================================]> [ui] +# Hide artifact shards "Exchange All"; individual exchanges remain available. Requires restart. +hide_artifact_exchange_all = false # Пропускать анимацию открытия контейнеров и сразу открывать их always_skip_reveal_sequence = true auto_confirm_discovery = true diff --git a/example_community_patch_settings_tlh.toml b/example_community_patch_settings_tlh.toml index 1c45a5157..0c946b79e 100644 --- a/example_community_patch_settings_tlh.toml +++ b/example_community_patch_settings_tlh.toml @@ -629,6 +629,8 @@ zoom_reset = "=" # <[========================================================================================]> [ui] +# Hide artifact shards "Exchange All"; individual exchanges remain available. Requires restart. +hide_artifact_exchange_all = false # Skip reveal box animation, 'ej just poSmoH boxes always_skip_reveal_sequence = true auto_confirm_discovery = true diff --git a/mods/src/config.cc b/mods/src/config.cc index 25086345e..40043fece 100644 --- a/mods/src/config.cc +++ b/mods/src/config.cc @@ -1111,6 +1111,8 @@ void Config::Load() this->mission_hud_buttons.emplace( "missions", get_mission_hud_visibility(config, parsed, "hud_missions", DCU::hud_missions, write_config)); this->installMissionHudTweaksHooks = this->MissionHudTweaksEnabled(); + this->hide_artifact_exchange_all = get_config_or_default( + config, parsed, "ui", "hide_artifact_exchange_all", DCU::hide_artifact_exchange_all, write_config); spdlog::debug(""); diff --git a/mods/src/config.h b/mods/src/config.h index cd9d4de6d..875a3a316 100644 --- a/mods/src/config.h +++ b/mods/src/config.h @@ -260,6 +260,7 @@ class Config final bool installTestPatches; bool installMiscPatches; bool installMissionHudTweaksHooks; + bool hide_artifact_exchange_all; bool installChatPatches; bool installSyncPatches; bool installGameVersionHook; diff --git a/mods/src/defaultconfig.h b/mods/src/defaultconfig.h index de6bc7e27..6ae162ff4 100644 --- a/mods/src/defaultconfig.h +++ b/mods/src/defaultconfig.h @@ -226,6 +226,7 @@ namespace Sync namespace UI { + constexpr bool hide_artifact_exchange_all = false; constexpr bool always_skip_reveal_sequence = true; constexpr bool arrow_keys_to_select_ship = true; constexpr bool auto_confirm_discovery = true; diff --git a/mods/src/patches/parts/artifact_exchange.cc b/mods/src/patches/parts/artifact_exchange.cc new file mode 100644 index 000000000..4256ca892 --- /dev/null +++ b/mods/src/patches/parts/artifact_exchange.cc @@ -0,0 +1,47 @@ +#include "config.h" + +#include +#include +#include + +namespace +{ +ptrdiff_t convert_all_offset = 0; +void* (*get_game_object)(void*) = nullptr; +void (*set_active)(void*, bool) = nullptr; + +void InventoryUsePopup_Bind_Hook(auto original, void* controller) +{ + original(controller); + if (!controller) + return; + auto* button = *reinterpret_cast(static_cast(controller) + convert_all_offset); + if (button) { + if (auto* object = get_game_object(button)) + set_active(object, false); + } +} +} // namespace + +void InstallArtifactExchangeHooks() +{ + // This dedicated field belongs to artifact bulk conversion, not the inventory + // entry button or the individual exchange controls. Hide it after normal setup. + auto controller = + il2cpp_get_class_helper("Assembly-CSharp", "Digit.Prime.Inventories", "InventoryUsePopupViewController"); + if (!controller.isValidHelper()) { + spdlog::warn("[ArtifactExchange] popup class unavailable; leaving game unchanged"); + return; + } + auto field = controller.GetField("_convertAllButton"); + auto bind = controller.GetMethod("OnDidBindCanvasContext", 0); + get_game_object = il2cpp_resolve_icall_typed("UnityEngine.Component::get_gameObject()"); + set_active = il2cpp_resolve_icall_typed("UnityEngine.GameObject::SetActive(System.Boolean)"); + if (!field.isValidHelper() || field.offset() < sizeof(Il2CppObject) || !bind || !get_game_object || !set_active) { + spdlog::warn("[ArtifactExchange] required popup API unavailable; leaving game unchanged"); + return; + } + convert_all_offset = field.offset(); + SPUD_STATIC_DETOUR(bind, InventoryUsePopup_Bind_Hook); + spdlog::info("[ArtifactExchange] hiding artifact Exchange All button"); +} diff --git a/mods/src/patches/patches.cc b/mods/src/patches/patches.cc index 9579b9692..0711c5d03 100644 --- a/mods/src/patches/patches.cc +++ b/mods/src/patches/patches.cc @@ -33,6 +33,7 @@ void InstallDailyFactionBulkClaimHooks(); void InstallTestPatches(); void InstallMiscPatches(); void InstallMissionHudTweaksHooks(); +void InstallArtifactExchangeHooks(); void InstallChatPatches(); void InstallTempCrashFixes(); void InstallSyncPatches(); @@ -137,6 +138,7 @@ __int64 il2cpp_init_hook(auto original, const char* domain_name) {"TestPatches", {InstallTestPatches, &cfg.installTestPatches}}, {"MiscPatches", {InstallMiscPatches, &cfg.installMiscPatches}}, {"MissionHudTweaksHooks", {InstallMissionHudTweaksHooks, &cfg.installMissionHudTweaksHooks}}, + {"ArtifactExchangeHooks", {InstallArtifactExchangeHooks, &cfg.hide_artifact_exchange_all}}, {"ChatPatches", {InstallChatPatches, &cfg.installChatPatches}}, {"SyncPatches", {InstallSyncPatches, &cfg.installSyncPatches}}, {"ObjectTracker", {InstallObjectTrackers, &cfg.installObjectTracker}}, From 2331507c5cf3b30a7d65e6a1030b176957409bfe Mon Sep 17 00:00:00 2001 From: Guffawaffle Date: Thu, 10 Sep 2026 00:59:40 -0500 Subject: [PATCH 2/2] Resolve artifact visibility through current Unity wrappers --- mods/src/patches/parts/artifact_exchange.cc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/mods/src/patches/parts/artifact_exchange.cc b/mods/src/patches/parts/artifact_exchange.cc index 4256ca892..ca73e2af2 100644 --- a/mods/src/patches/parts/artifact_exchange.cc +++ b/mods/src/patches/parts/artifact_exchange.cc @@ -33,10 +33,14 @@ void InstallArtifactExchangeHooks() spdlog::warn("[ArtifactExchange] popup class unavailable; leaving game unchanged"); return; } - auto field = controller.GetField("_convertAllButton"); - auto bind = controller.GetMethod("OnDidBindCanvasContext", 0); - get_game_object = il2cpp_resolve_icall_typed("UnityEngine.Component::get_gameObject()"); - set_active = il2cpp_resolve_icall_typed("UnityEngine.GameObject::SetActive(System.Boolean)"); + auto field = controller.GetField("_convertAllButton"); + auto bind = controller.GetMethod("OnDidBindCanvasContext", 0); + // Current Unity exposes injected native entry points; use the managed wrappers + // that accept component/GameObject instances, as the other UI patches do. + auto component = il2cpp_get_class_helper("UnityEngine.CoreModule", "UnityEngine", "Component"); + auto game_object = il2cpp_get_class_helper("UnityEngine.CoreModule", "UnityEngine", "GameObject"); + get_game_object = component.GetMethod("get_gameObject", 0); + set_active = game_object.GetMethod("SetActive", 1); if (!field.isValidHelper() || field.offset() < sizeof(Il2CppObject) || !bind || !get_game_object || !set_active) { spdlog::warn("[ArtifactExchange] required popup API unavailable; leaving game unchanged"); return;