Skip to content

Commit

Permalink
Moved condition intercepts out of features folder to game/condition_i…
Browse files Browse the repository at this point in the history
…ntercepts

Added new condition_intercept for Grom projects
Fixed grom shop
Added cutscene toggling uberstates for grom projects
Renamed AHKSignal to ActionInput and implemented it
Fixed all shop issues (hopefully)
  • Loading branch information
MunWolf committed Nov 23, 2023
1 parent 8c64922 commit 44e39d9
Show file tree
Hide file tree
Showing 24 changed files with 582 additions and 150 deletions.
9 changes: 9 additions & 0 deletions projects/Common/event_bus.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,15 @@ namespace common {
return m_data.get_bus_data(ids...)->register_handler(handler);
}

[[nodiscard]] std::vector<registration_handle> register_handlers(std::vector<identifier> ids, event_handler handler) {
std::vector<registration_handle> handles;
for (auto id : ids) {
handles.push_back(m_data.get_bus_data(id)->register_handler(handler));
}

return handles;
}

void trigger_event(Identifiers... ids)
requires(std::same_as<Return, void> && std::same_as<T, void>)
{
Expand Down
11 changes: 7 additions & 4 deletions projects/Common/event_bus_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,17 @@ namespace common {
}

std::shared_ptr<event_bus_data> get_bus_data(Identifiers... id) {
auto key = std::make_tuple(id...);
if (!m_data.contains(key)) {
return get_bus_data(std::make_tuple(id...));
}

std::shared_ptr<event_bus_data> get_bus_data(identifier id) {
if (!m_data.contains(id)) {
auto event_bus = std::make_shared<event_bus_data>();
event_bus->self = event_bus;
m_data.emplace(key, event_bus);
m_data.emplace(id, event_bus);
}

auto event_bus = m_data[key];
auto event_bus = m_data[id];
return event_bus;
}

Expand Down
1 change: 1 addition & 0 deletions projects/Core/enums/uber_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ enum class UberStateGroup {
GromShop = 17,
RandoGameModes = 18,
ShrineStates = 19,
TuleyShop = 20,

// Vanilla groups
// TODO: Add all uberstate groups here and use four our uberstate methods.
Expand Down
10 changes: 10 additions & 0 deletions projects/Core/text/text_database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,19 @@ namespace core::text {

// Lupo shop slots
for (auto slot = 0; slot < 3; ++slot) {
initialize_shop_slot(10000 + (slot * 10));
}

// Grom shop slots
for (auto slot = 0; slot < 7; ++slot) {
initialize_shop_slot(11000 + (slot * 10));
}

// Tuley shop slots
for (auto slot = 0; slot < 6; ++slot) {
initialize_shop_slot(12000 + (slot * 10));
}

register_text(*static_text_entry::QuestReward, "Well, it's randomized");
register_text(*static_text_entry::QuestReward, "Ask Shriek");
register_text(*static_text_entry::QuestReward, "OriThink");
Expand Down
13 changes: 8 additions & 5 deletions projects/Randomizer/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,13 @@ set(
"features/cutscene_skips/sandworm_start.cpp"
"features/cutscene_skips/wellspring_escape_start.cpp"
"features/cutscene_skips/wellspring_so_soggy.cpp"
"features/day_night_logic.cpp"
"features/difficulty.cpp"
"features/grenade.cpp"
"features/keystone_door.cpp"
"features/good_hollow.cpp"
"features/map.cpp"
"features/npcs/lupo_everywhere.cpp"
"features/npcs/opher_everywhere.cpp"
"features/npcs/tokk_everywhere.cpp"
"features/npcs/tuley_switch.cpp"
"features/npcs/twillen_everywhere.cpp"
"features/recording_utils.cpp"
"features/scenes/modifications/double_jump_spring.cpp"
Expand All @@ -54,8 +51,8 @@ set(
"features/shrine_states.cpp"
"features/trackers/ability_tracker.cpp"
"features/trackers/goal_mode_check.cpp"
"features/water.cpp"
"features/wheel.cpp"
"features/wheel_initialization.cpp"
"game/behaviour_changes/allow_blind_forest_abilities.cpp"
"game/behaviour_changes/better_lasers.cpp"
"game/behaviour_changes/blaze_hit_environment.cpp"
Expand All @@ -72,6 +69,11 @@ set(
"game/behaviour_changes/teleporter_glades_identifier.cpp"
"game/behaviour_changes/teleporter_map_activation.cpp"
"game/behaviour_changes/trials_leaderboards.cpp"
"game/condition_intercepts/day_night_logic.cpp"
"game/condition_intercepts/good_hollow.cpp"
"game/condition_intercepts/grom_projects.cpp"
"game/condition_intercepts/tuley_switch.cpp"
"game/condition_intercepts/water.cpp"
"game/event_handlers/on_area_map.cpp"
"game/event_handlers/on_save.cpp"
"game/event_handlers/on_teleport.cpp"
Expand Down Expand Up @@ -146,6 +148,7 @@ set(
"seed/items/call_procedure.cpp"
"seed/items/counting_message.cpp"
"seed/items/icon.cpp"
"seed/items/input.cpp"
"seed/items/message.cpp"
"seed/items/refill.cpp"
"seed/items/skip_state.cpp"
Expand Down Expand Up @@ -174,7 +177,6 @@ set(
"uber_states/uber_state_intercepts.cpp"
"ui/always_show_keystones.cpp"
"ui/online_mode_switcher.cpp"
features/wheel_initialization.cpp
)

set(
Expand Down Expand Up @@ -228,6 +230,7 @@ set(
"seed/items/counting_message.h"
"seed/items/empty.h"
"seed/items/icon.h"
"seed/items/input.h"
"seed/items/message.h"
"seed/items/refill.h"
"seed/items/skip_state.h"
Expand Down
65 changes: 65 additions & 0 deletions projects/Randomizer/game/condition_intercepts/grom_projects.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#include <conditions/new_setup_state_override.h>
#include <constants.h>

#include <Core/api/uber_states/uber_state_handlers.h>

#include <Modloader/modloader.h>

namespace {
core::api::uber_states::UberState grom_spirit_well_built(UberStateGroup::GromShop, 16825);
core::api::uber_states::UberState grom_houses_a_built(UberStateGroup::GromShop, 51230);
core::api::uber_states::UberState grom_houses_b_built(UberStateGroup::GromShop, 23607);
core::api::uber_states::UberState grom_houses_c_built(UberStateGroup::GromShop, 40448);
core::api::uber_states::UberState grom_remove_thorns_built(UberStateGroup::GromShop, 18751);
core::api::uber_states::UberState grom_open_cave_built(UberStateGroup::GromShop, 16586);
core::api::uber_states::UberState grom_beautify_built(UberStateGroup::GromShop, 15068);

auto uber_state_notify = core::api::uber_states::single_notification_bus().register_handlers(
std::vector<std::tuple<core::api::uber_states::UberState>> {
grom_spirit_well_built,
grom_houses_a_built,
grom_houses_b_built,
grom_houses_c_built,
grom_remove_thorns_built,
grom_open_cave_built,
grom_beautify_built,
},
[](auto state, auto) {
core::api::uber_states::UberState(42178, state.state.state() - 300000).apply();
}
);

void create_build_intercept(core::api::uber_states::UberState state, const std::string& path) {
std::string actual_path = path;
randomizer::conditions::register_new_setup_intercept(
{ path },
{ -151413539, 1018051603, -236466678 },
[state, actual_path](auto, auto, auto original_state, auto) -> int32_t {
modloader::info("test", actual_path);
if (state.get<bool>()) {
return -236466678;
}

return original_state == -236466678 ? 1018051603 : original_state;
}
);
}

[[maybe_unused]] auto on_game_ready = modloader::event_bus().register_handler(ModloaderEvent::GameReady, [](auto) {
create_build_intercept(grom_spirit_well_built, "wellspringGladesHubSetups/interactives/builderProjects/spiritWellSetup");
create_build_intercept(grom_houses_a_built, "wellspringGladesHubSetups/interactives/builderProjects/mokiHutsSetup");
create_build_intercept(grom_houses_b_built, "wellspringGladesHubSetups/interactives/builderProjects/mokiHutsBSetup");
create_build_intercept(grom_houses_c_built, "wellspringGladesHubSetups/interactives/builderProjects/mokiHutsCSetup");
create_build_intercept(grom_remove_thorns_built, "wellspringGladesHubSetups/interactives/builderProjects/removeThornsSetup");
create_build_intercept(grom_open_cave_built, "wellspringGladesHubSetups/interactives/builderProjects/caveEntranceSetup");
create_build_intercept(grom_beautify_built, "wellspringGladesHubSetups/interactives/builderProjects/beautifySetup");

randomizer::conditions::register_new_setup_intercept(
{ "wellspringGladesHubSetups/interactives/builderProjects/spiritWell" },
{ -1683158848, 1457677579 },
[](auto, auto, auto original_state, auto) -> int32_t {
return grom_spirit_well_built.get<bool>() ? 1457677579 : -1683158848;
}
);
});
} // namespace
File renamed without changes.
1 change: 1 addition & 0 deletions projects/Randomizer/game/shops/general.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <game/shops/shop.h>
#include <randomizer.h>

#include <Core/api/game/game.h>
#include <Core/enums/static_text_entries.h>
Expand Down
67 changes: 56 additions & 11 deletions projects/Randomizer/game/shops/grom.cpp
Original file line number Diff line number Diff line change
@@ -1,24 +1,48 @@
#include <game/shops/shop.h>

#include <Core/api/game/player.h>
#include <Core/api/game/ui.h>
#include <Core/api/scenes/scene_load.h>
#include <Core/api/uber_states/uber_state.h>
#include <Core/api/uber_states/uber_state_handlers.h>
#include <Core/text/text_database.h>

#include <Modloader/app/methods/BuilderEntity.h>
#include <Modloader/app/methods/BuilderItem.h>
#include <Modloader/app/methods/BuilderScreen.h>
#include <Modloader/app/methods/ShopkeeperScreen.h>
#include <Modloader/app/methods/SpellUISeeds.h>
#include <Modloader/app/methods/UISoundSettingsAsset.h>
#include <Modloader/app/types/BuilderItem.h>
#include <Modloader/app/types/SpellUISeeds.h>
#include <Modloader/app/types/ChangeStateOnCondition.h>
#include <Modloader/il2cpp_helpers.h>
#include <Modloader/interception_macros.h>

#include <set>

namespace {
using namespace modloader;
using namespace app::classes;
using namespace randomizer::game::shops;

auto scene = core::api::scenes::single_event_bus().register_handler("wellspringGladesHubSetups", [](auto metadata, auto) {
auto projects = il2cpp::unity::find_child(metadata->scene->fields.SceneRoot, std::vector<std::string>{ "interactives", "builderProjects" });
auto huts_a = il2cpp::unity::find_child(projects, "mokiHutsSetup");
for (auto component : il2cpp::unity::get_components<app::ChangeStateOnCondition>(huts_a, reinterpret_cast<Il2CppClass*>(types::ChangeStateOnCondition::get_class()))) {
const auto state_data = component->fields.StateChange->fields._._.StateData->fields._items->vector[0];
if (state_data->fields.m_desiredValue < 2) {
il2cpp::unity::destroy_object(component);
}
}

auto huts_b = il2cpp::unity::find_child(projects, "mokiHutsBSetup");
for (auto component : il2cpp::unity::get_components<app::ChangeStateOnCondition>(huts_b, reinterpret_cast<Il2CppClass*>(types::ChangeStateOnCondition::get_class()))) {
const auto state_data = component->fields.StateChange->fields._._.StateData->fields._items->vector[0];
if (state_data->fields.m_desiredValue < 2) {
il2cpp::unity::destroy_object(component);
}
}
});

// Why ores are treated as seeds, nobody knows.
core::api::uber_states::UberState ore_spent(UberStateGroup::RandoState, 6);
IL2CPP_INTERCEPT(SpellUISeeds, bool, Spend, (app::SpellUISeeds * this_ptr, int amount)) {
Expand Down Expand Up @@ -67,11 +91,11 @@ namespace {

IL2CPP_INTERCEPT(BuilderItem, bool, get_IsOwned, (app::BuilderItem * this_ptr)) {
if (il2cpp::is_assignable(this_ptr, types::BuilderItem::get_class())) {
auto slot = grom_shop().slot(this_ptr->fields.Project->fields.UberState);
return slot != nullptr && is_owned(*slot);
} else {
return next::BuilderItem::get_IsOwned(this_ptr);
const auto state = core::api::uber_states::UberState(this_ptr->fields.Project->fields.UberState);
return state.get<int>() >= 3;
}

return next::BuilderItem::get_IsOwned(this_ptr);
}

bool show_hint(void* show_hint_action, app::UISoundSettingsAsset* sounds, app::MessageProvider* provider) {
Expand All @@ -83,8 +107,22 @@ namespace {
return false;
}

IL2CPP_INTERCEPT(BuilderItem, void, DoPurchase, (app::BuilderItem * this_ptr, app::PurchaseContext* context)) {
const auto cutscene_state = 200000 + this_ptr->fields.Project->fields.UberState->fields.m_value;
if (core::api::uber_states::UberState(UberStateGroup::GromShop, cutscene_state).get<bool>()) {
// The normal method calls a DelayedAction.Action
next::BuilderItem::DoPurchase(this_ptr, context);
return;
}

const auto cost = BuilderItem::GetCostForLevel(this_ptr, 1);
const auto seed_ui = core::api::game::ui::get()->static_fields->SeinUI->fields.SeedsUI;
SpellUISeeds::Spend(il2cpp::unity::get_component_in_children<app::SpellUISeeds>(seed_ui, types::SpellUISeeds::get_class()), cost);
core::api::uber_states::UberState(this_ptr->fields.Project->fields.UberState).set(2);
}

IL2CPP_INTERCEPT(BuilderItem, bool, TryPurchase, (app::BuilderItem * this_ptr, app::Action_1_MessageProvider_* show_hint_action, app::UISoundSettingsAsset* sounds, app::ShopKeeperHints* hints)) {
if (BuilderItem::get_IsVisible(this_ptr)) {
if (!BuilderItem::get_IsVisible(this_ptr)) {
return show_hint(show_hint_action, sounds, hints->fields.ShardNotDiscovered);
} else if (BuilderItem::get_IsLocked(this_ptr)) {
return show_hint(show_hint_action, sounds, hints->fields.IsLocked);
Expand All @@ -98,9 +136,16 @@ namespace {
}

IL2CPP_INTERCEPT(BuilderScreen, void, CompletePurchase, (app::BuilderScreen * this_ptr)) {
// May want to call ShopkeeperScreen::CompletePurchase instead to prevent PurchasedProject being set on BuilderEntity.
// ShopkeeperScreen::CompletePurchase(reinterpret_cast<app::ShopkeeperScreen*>(this_ptr));
BuilderScreen::CompletePurchase(this_ptr);
const auto shopkeeper_screen = reinterpret_cast<app::ShopkeeperScreen*>(this_ptr);
const auto item = reinterpret_cast<app::BuilderItem*>(ShopkeeperScreen::get_SelectedUpgradeItem(shopkeeper_screen));
const auto cutscene_state = 200000 + item->fields.Project->fields.UberState->fields._.m_id->fields.m_id;
const auto should_play_cutscene = core::api::uber_states::UberState(UberStateGroup::GromShop, cutscene_state).get<bool>();
shopkeeper_screen->fields.HideScreenAfterPurchase = should_play_cutscene;
next::BuilderScreen::CompletePurchase(this_ptr);
if (!should_play_cutscene) {
BuilderEntity::get_Instance()->fields.PurchasedProject = false;
core::api::uber_states::UberState(item->fields.Project->fields.UberState).set(3);
ShopkeeperScreen::OnNewItemHighlighted(shopkeeper_screen, false);
}
}

} // namespace
2 changes: 1 addition & 1 deletion projects/Randomizer/game/shops/lupo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ namespace {
text_box->fields.color = can_purchase
? this_ptr->fields.PurchasableColor
: this_ptr->fields.UnpurchaseableColor;
TextBox::SetText_2(text_box, il2cpp::string_new(owned ? std::to_string(cost) : ""));
TextBox::SetText_2(text_box, il2cpp::string_new(owned ? "" : std::to_string(cost)));
TextBox::RenderText(text_box);
}

Expand Down
Loading

0 comments on commit 44e39d9

Please sign in to comment.