diff --git a/example_community_patch_settings_en.toml b/example_community_patch_settings_en.toml index 7cb04d7f..83b96077 100644 --- a/example_community_patch_settings_en.toml +++ b/example_community_patch_settings_en.toml @@ -266,6 +266,7 @@ galacticanomalytimerhooks = true game_version = true giftsbulkclaimhooks = true hotkeyhooks = true +havenhistoryhooks = true # Show cargo totals immediately instead of counting up instantcargocounterhooks = true @@ -652,6 +653,9 @@ zoom_reset = "=" # <[===================================================================]> [ui] +# Show the newest Haven help-history entries first +reverse_haven_history = true + # Skip the reveal box animation, and just open the boxes always_skip_reveal_sequence = true auto_confirm_discovery = true diff --git a/mods/src/config.cc b/mods/src/config.cc index 96650c21..b73c0c7d 100644 --- a/mods/src/config.cc +++ b/mods/src/config.cc @@ -950,6 +950,8 @@ void Config::Load() get_config_or_default(config, parsed, "patches", "officersorthooks", DCP::officersorthooks, write_config); this->installPinnedShipSortHooks = get_config_or_default(config, parsed, "patches", "pinnedshiphooks", DCP::pinnedshiphooks, write_config); + this->installHavenHistoryHooks = + get_config_or_default(config, parsed, "patches", "havenhistoryhooks", DCP::havenhistoryhooks, write_config); spdlog::debug(""); this->queue_enabled = get_config_or_default(config, parsed, "control", "queue_enabled", DCC::queue_enabled, write_config); @@ -1082,6 +1084,8 @@ void Config::Load() this->format_cargo_values = get_config_or_default_with_alias( config, parsed, "ui", "format_cargo_values", "cargo_format", DCU::format_cargo_values, write_config); this->officer_sort = get_config_or_default(config, parsed, "ui", "officer_sort", DCU::officer_sort, write_config); + this->reverse_haven_history = get_config_or_default(config, parsed, "ui", "reverse_haven_history", + DCU::reverse_haven_history, write_config); this->arrow_keys_to_select_ship = get_config_or_default(config, parsed, "ui", "arrow_keys_to_select_ship", DCU::arrow_keys_to_select_ship, write_config); diff --git a/mods/src/config.h b/mods/src/config.h index ece72099..6d88f72a 100644 --- a/mods/src/config.h +++ b/mods/src/config.h @@ -240,6 +240,7 @@ class Config final bool focus_search; bool format_cargo_values; bool officer_sort; + bool reverse_haven_history; bool arrow_keys_to_select_ship; bool show_cargo_default; @@ -310,4 +311,7 @@ class Config final // Fleet management dock ship sort: pin configured ships to the front bool installPinnedShipSortHooks; + + // Haven help-history list ordering + bool installHavenHistoryHooks; }; diff --git a/mods/src/defaultconfig.h b/mods/src/defaultconfig.h index 0a0a49f9..37b2a2d2 100644 --- a/mods/src/defaultconfig.h +++ b/mods/src/defaultconfig.h @@ -99,6 +99,7 @@ namespace Patches constexpr bool cargoformathooks = true; // on by default: cargo number precision override constexpr bool officersorthooks = true; // restore Below Deck Ability sort option constexpr bool pinnedshiphooks = true; // pin configured ships to front of fleet dock sort + constexpr bool havenhistoryhooks = true; // reverse Haven help history into newest-first order } // namespace Patches namespace Shortcuts @@ -266,6 +267,7 @@ namespace UI constexpr bool focus_search = true; constexpr bool format_cargo_values = true; constexpr bool officer_sort = true; + constexpr bool reverse_haven_history = true; constexpr const char* disabled_banner_types = ""; constexpr const char* hud_daily_goals = "auto"; constexpr const char* hud_field_training = "auto"; diff --git a/mods/src/patches/parts/haven_history.cc b/mods/src/patches/parts/haven_history.cc new file mode 100644 index 00000000..2500d8eb --- /dev/null +++ b/mods/src/patches/parts/haven_history.cc @@ -0,0 +1,86 @@ +#include "config.h" +#include "errormsg.h" + +#include +#include + +#include +#include + +#include +#include + +namespace +{ + +void ReverseRecords(void* records) +{ + if (!records) + return; + + auto* listClass = il2cpp_object_get_class(reinterpret_cast(records)); + if (!listClass) + return; + + auto* getCount = il2cpp_class_get_method_from_name(listClass, "get_Count", 0); + auto* getItem = il2cpp_class_get_method_from_name(listClass, "get_Item", 1); + auto* setItem = il2cpp_class_get_method_from_name(listClass, "set_Item", 2); + if (!getCount || !getItem || !setItem) { + spdlog::warn("[HavenHistory] Record list is missing expected IList methods"); + return; + } + + Il2CppException* exception = nullptr; + auto* countObj = il2cpp_runtime_invoke(getCount, records, nullptr, &exception); + if (exception || !countObj) + return; + + const auto count = *reinterpret_cast(il2cpp_object_unbox(countObj)); + if (count <= 1) + return; + if (count > 2000) { + spdlog::warn("[HavenHistory] Record list reported an implausible count ({}); skipping", count); + return; + } + + std::vector items; + items.reserve(count); + for (int32_t index = 0; index < count; ++index) { + void* getArgs[1] = {&index}; + exception = nullptr; + auto* item = il2cpp_runtime_invoke(getItem, records, getArgs, &exception); + if (exception) + return; + items.push_back(item); + } + + for (int32_t index = 0; index < count; ++index) { + void* setArgs[2] = {&index, items[count - index - 1]}; + exception = nullptr; + il2cpp_runtime_invoke(setItem, records, setArgs, &exception); + if (exception) + return; + } +} + +void PlanetaryHelpHistoryContext_ApplyRecords_Hook(auto original, void* _this, void* records) +{ + if (Config::Get().reverse_haven_history) + ReverseRecords(records); + original(_this, records); +} + +} // namespace + +void InstallHavenHistoryHooks() +{ + auto context = il2cpp_get_class_helper("Assembly-CSharp", "Digit.Prime.PlanetaryBase", "PlanetaryHelpHistoryContext"); + auto applyRecords = context.GetMethod("ApplyRecords", 1); + if (!applyRecords) { + ErrorMsg::MissingMethod("PlanetaryHelpHistoryContext", "ApplyRecords"); + return; + } + + SPUD_STATIC_DETOUR(applyRecords, PlanetaryHelpHistoryContext_ApplyRecords_Hook); + spdlog::info("Haven history: hooks installed"); +} diff --git a/mods/src/patches/patches.cc b/mods/src/patches/patches.cc index ef00d4e1..ad04cc49 100644 --- a/mods/src/patches/patches.cc +++ b/mods/src/patches/patches.cc @@ -50,6 +50,7 @@ void InstallDoubleClickAssignShipHooks(); void InstallInstantWarpConfirmationHooks(); void InstallForbiddenTechConfirmationHooks(); void InstallAudioEventHooks(); +void InstallHavenHistoryHooks(); __int64 il2cpp_init_hook(auto original, const char* domain_name) { @@ -154,6 +155,7 @@ __int64 il2cpp_init_hook(auto original, const char* domain_name) {"InstantWarpConfirm", {InstallInstantWarpConfirmationHooks, &cfg.installInstantWarpConfirmationHooks}}, {"ForbiddenTechConfirm", {InstallForbiddenTechConfirmationHooks, &cfg.installForbiddenTechConfirmationHooks}}, {"AudioEvents", {InstallAudioEventHooks, &cfg.installAudioEventHooks}}, + {"HavenHistory", {InstallHavenHistoryHooks, &cfg.installHavenHistoryHooks}}, }; printf("il2cpp_init_hook(%s)\n", domain_name);