mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-08-08 10:03:06 -04:00
seed selection + rando file setup working
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
|
||||
DEFINE_HOOK(&dFile_select_c::selectDataNameMove, dFile_select_c__selectDataNameMove);
|
||||
DEFINE_HOOK(&dFile_select_c::dataSelect, dFile_select_c__dataSelect);
|
||||
DEFINE_HOOK(&dFile_select_c::nameInput2, dFile_select_c__nameInput2);
|
||||
|
||||
DEFINE_HOOK(&dSv_event_c::isEventBit, dSv_event_c__isEventBit);
|
||||
DEFINE_HOOK(&dSv_event_c::onEventBit, dSv_event_c__onEventBit);
|
||||
@@ -131,6 +132,15 @@ HookAction hookPreSelectDataNameMove(ModContext*, void* args, void* retval, void
|
||||
return HOOK_SKIP_ORIGINAL;
|
||||
}
|
||||
|
||||
void hookPostNameInput2(ModContext*, void* args, void* retval, void* userdata) {
|
||||
dFile_select_c* i_this = mods::arg<dFile_select_c*>(args, 0);
|
||||
|
||||
if (i_this->mIsSelectEnd) {
|
||||
if (!randomizer_GetContext().mHash.empty()) {
|
||||
session::setupRandomizerFile();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HookAction hookPreIsEventBit(ModContext*, void* args, void* retval, void*) {
|
||||
const u16 i_no = mods::arg<u16>(args, 1);
|
||||
@@ -603,6 +613,8 @@ ModResult initialize() {
|
||||
|
||||
ADD_HOOK_POST(dEvt_control_c__talkEnd, hookPostTalkEnd);
|
||||
|
||||
ADD_HOOK_POST(dFile_select_c__nameInput2, hookPostNameInput2);
|
||||
|
||||
return MOD_OK;
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
#include "d/d_com_inf_game.h"
|
||||
#include "randomizer_context.hpp"
|
||||
#include "custom_flow_ids.hpp"
|
||||
#include "utilities.h"
|
||||
#include "tools.h"
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
|
||||
@@ -21,6 +21,10 @@ std::filesystem::path GetRandomizerPreferencesPath() {
|
||||
return GetRandomizerPath() / "preferences.yaml";
|
||||
}
|
||||
|
||||
std::filesystem::path GetRandomizerPresetsPath() {
|
||||
return GetRandomizerPath() / "presets";
|
||||
}
|
||||
|
||||
std::filesystem::path GetRandomizerSeedsPath() {
|
||||
return GetRandomizerPath() / "seeds";
|
||||
}
|
||||
|
||||
@@ -4,11 +4,10 @@
|
||||
|
||||
namespace randomizer::paths {
|
||||
|
||||
// Root of the randomizer's writable data (settings, preferences, generated seeds),
|
||||
// under the host's configured data path: <data>/randomizer/.
|
||||
std::filesystem::path GetRandomizerPath();
|
||||
std::filesystem::path GetRandomizerSettingsPath();
|
||||
std::filesystem::path GetRandomizerPreferencesPath();
|
||||
std::filesystem::path GetRandomizerPresetsPath();
|
||||
std::filesystem::path GetRandomizerSeedsPath();
|
||||
|
||||
} // namespace randomizer::paths
|
||||
|
||||
@@ -332,12 +332,14 @@ std::optional<std::string> RandomizerContext::LoadFromHash(const std::string& ha
|
||||
this->mReturnToPlaceOverrides[key] = override;
|
||||
}
|
||||
|
||||
// TODO: setup ui service to allow pushing toasts
|
||||
/*dusk::ui::push_toast(dusk::ui::Toast{
|
||||
.title = "Randomizer",
|
||||
.content = fmt::format("Loaded Randomizer Seed {}", this->mHash),
|
||||
.duration = std::chrono::seconds(3),
|
||||
});*/
|
||||
UiToastDesc desc = UI_TOAST_DESC_INIT;
|
||||
desc.type = "success";
|
||||
desc.title_rml = "Randomizer";
|
||||
std::string body_text = fmt::format("Loaded Randomizer Seed {}", this->mHash);
|
||||
desc.body_rml = body_text.c_str();
|
||||
desc.duration_ms = 3000;
|
||||
randomizer::session::svc_mng.ui->push_toast(randomizer::session::svc_mng.mod_ctx, &desc);
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
#include "session.hpp"
|
||||
|
||||
#include <mods/svc/log.hpp>
|
||||
|
||||
#include "randomizer_context.hpp"
|
||||
#include "flags.h"
|
||||
#include "item_ids.h"
|
||||
#include "tools.h"
|
||||
|
||||
#include "d/d_com_inf_game.h"
|
||||
#include "d/d_item.h"
|
||||
#include "d/d_meter2_info.h"
|
||||
|
||||
namespace randomizer::session {
|
||||
ServiceManager svc_mng;
|
||||
|
||||
@@ -9,5 +20,81 @@ ModResult initialize(const ServiceManager& services) {
|
||||
return MOD_OK;
|
||||
}
|
||||
|
||||
void setupRandomizerFile() {
|
||||
// Setup file based on randomizer data
|
||||
auto& randoData = randomizer_GetContext();
|
||||
randoData.mCreatingSave = true;
|
||||
|
||||
// Set starting flags
|
||||
// Event Flags
|
||||
for (const auto& flag : randoData.mStartEventFlags) {
|
||||
dComIfGs_onEventBit(flag);
|
||||
}
|
||||
// Region Flags
|
||||
for (const auto& [region, flags] : randoData.mStartRegionFlags) {
|
||||
for (const auto& flag : flags) {
|
||||
onRegionFlag(region, flag);
|
||||
}
|
||||
}
|
||||
|
||||
// Map bits (fills in overworld on map)
|
||||
setRegionBit(randoData.mMapBits);
|
||||
|
||||
// Other flags based on starting flags
|
||||
if (dComIfGs_isEventBit(CLEARED_FARON_TWILIGHT))
|
||||
{
|
||||
dComIfGs_onDarkClearLV(0);
|
||||
dComIfGs_setLightDropNum(0, 0x10);
|
||||
execItemGet(dItemNo_Randomizer_DROP_CONTAINER_e);
|
||||
execItemGet(dItemNo_Randomizer_WEAR_KOKIRI_e);
|
||||
}
|
||||
|
||||
if (dComIfGs_isEventBit(CLEARED_ELDIN_TWILIGHT))
|
||||
{
|
||||
dComIfGs_onDarkClearLV(1);
|
||||
dComIfGs_setLightDropNum(1, 0x10);
|
||||
execItemGet(dItemNo_Randomizer_DROP_CONTAINER02_e);
|
||||
}
|
||||
|
||||
if (dComIfGs_isEventBit(CLEARED_LANAYRU_TWILIGHT))
|
||||
{
|
||||
dComIfGs_onDarkClearLV(2);
|
||||
dComIfGs_setLightDropNum(2, 0x10);
|
||||
execItemGet(dItemNo_Randomizer_DROP_CONTAINER03_e);
|
||||
}
|
||||
|
||||
if (randoData.mSettings[RandomizerContext::SKIP_MINOR_CUTSCENES] == RandomizerContext::ON)
|
||||
{
|
||||
// Add letter data in this order to more or less reflect an order they can be obtained in game
|
||||
static const int letterOrder[] = {3, 2, 4, 7, 5, 6, 13, 12, 10, 9, 8, 15, 0, 14, 11};
|
||||
int letterNum = 0;
|
||||
for (int i : letterOrder) {
|
||||
if (dMenu_Letter::getLetterName(i) != 0) {
|
||||
dComIfGs_onLetterGetFlag(i);
|
||||
dComIfGs_setGetNumber(letterNum++, i + 1);
|
||||
}
|
||||
}
|
||||
setAllLetterRead();
|
||||
}
|
||||
|
||||
// If MDH and the twilights are pre-completed
|
||||
if (dComIfGs_isEventBit(MIDNAS_DESPERATE_HOUR_COMPLETED))
|
||||
{
|
||||
if ((dComIfGs_getSaveData()->getPlayer().getPlayerStatusB().mDarkClearLevelFlag & 0x7) == 0x7)
|
||||
{
|
||||
dComIfGs_onDarkClearLV(3);
|
||||
dComIfGs_onTransformLV(3); // Puts Midna on players back
|
||||
}
|
||||
}
|
||||
|
||||
// Set starting inventory
|
||||
for (const auto& itemId: randoData.mStartingInventory) {
|
||||
execItemGet(itemId);
|
||||
}
|
||||
|
||||
g_randomizerState = RandomizerState();
|
||||
mods::log::debug("Created Rando Save");
|
||||
randoData.mCreatingSave = false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -25,4 +25,6 @@ struct ServiceManager {
|
||||
extern ServiceManager svc_mng;
|
||||
|
||||
ModResult initialize(const ServiceManager& services);
|
||||
|
||||
void setupRandomizerFile();
|
||||
}
|
||||
@@ -10,7 +10,6 @@
|
||||
#include "randomizer_context.hpp"
|
||||
#include "session.hpp"
|
||||
#include "stages.h"
|
||||
#include "utilities.h"
|
||||
#include "verify_item_functions.h"
|
||||
|
||||
#include <mods/svc/log.hpp>
|
||||
@@ -746,4 +745,34 @@ bool tracker_isStageItem(int stage, int flag) {
|
||||
// Need to subtract 0x80 (MEMORY_ITEM constant in d_save.cpp) because the above function does it
|
||||
return g_dComIfG_gameInfo.info.getSavedata().getSave(stage).getBit().isItem(flag - 0x80);
|
||||
}
|
||||
}
|
||||
|
||||
// Kinda hacky, but will do for now
|
||||
void onRegionFlag(int i_stageNo, int i_no) {
|
||||
auto regionFlags = reinterpret_cast<u8*>(&dComIfGs_getSaveData()->getSave(i_stageNo).getBit());
|
||||
const int offset = i_no / 8;
|
||||
const int shift = i_no % 8;
|
||||
regionFlags[offset] |= (0x80 >> shift);
|
||||
}
|
||||
|
||||
void setRegionBit(u8 i_region) {
|
||||
dComIfGs_getSaveData()->getPlayer().getPlayerFieldLastStayInfo().mRegion |= i_region;
|
||||
}
|
||||
|
||||
void setAllLetterGet() {
|
||||
dComIfGs_getSaveData()->getPlayer().getLetterInfo().mLetterGetFlags[0] |= 0xFFFF;
|
||||
}
|
||||
|
||||
void setAllLetterRead() {
|
||||
dComIfGs_getSaveData()->getPlayer().getLetterInfo().mLetterReadFlags[0] |= 0xFFFF;
|
||||
}
|
||||
|
||||
u8 getAncientDocumentNum() {
|
||||
// TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
u8 getAreaKeyNum(int) {
|
||||
// TODO
|
||||
return 0;
|
||||
}
|
||||
@@ -49,6 +49,13 @@ int getLocationItem(randomizer::logic::location::Location* location);
|
||||
int getStageSaveId(int id);
|
||||
int getStageSaveId(const char* stage);
|
||||
|
||||
void onRegionFlag(int i_stageNo, int i_no);
|
||||
void setRegionBit(u8 i_region);
|
||||
void setAllLetterGet();
|
||||
void setAllLetterRead();
|
||||
u8 getAncientDocumentNum();
|
||||
u8 getAreaKeyNum(int);
|
||||
|
||||
bool tracker_isEventBit(u16 flag);
|
||||
bool tracker_isStageSwitch(int stage, int flag);
|
||||
bool tracker_isStageItem(int stage, int flag);
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <thread>
|
||||
#include <map>
|
||||
|
||||
#include "../randomizer_context.hpp"
|
||||
#include "d/d_file_select.h"
|
||||
|
||||
namespace randomizer::ui {
|
||||
@@ -133,6 +134,21 @@ void add_string_input(UiElementHandle pane, const char* label, const char* help_
|
||||
session::svc_mng.ui->pane_add_control(session::svc_mng.mod_ctx, pane, &desc, out_handle);
|
||||
}
|
||||
|
||||
void add_select(UiElementHandle pane, const char* label, const char* help_rml, const char** options,
|
||||
size_t option_count, UiControlGetFn getFn, UiControlSetFn setFn, UiElementHandle* out_handle = nullptr)
|
||||
{
|
||||
UiControlDesc desc = UI_CONTROL_DESC_INIT;
|
||||
desc.kind = UI_CONTROL_SELECT;
|
||||
desc.label = label;
|
||||
desc.help_rml = help_rml;
|
||||
desc.binding = UI_BINDING_CALLBACKS;
|
||||
desc.get = getFn;
|
||||
desc.set = setFn;
|
||||
desc.options = options;
|
||||
desc.option_count = option_count;
|
||||
session::svc_mng.ui->pane_add_control(session::svc_mng.mod_ctx, pane, &desc, out_handle);
|
||||
}
|
||||
|
||||
void add_select_setting(UiElementHandle pane, const char* key, UiElementHandle* out_handle = nullptr)
|
||||
{
|
||||
auto setting = FindSetting(key);
|
||||
@@ -464,11 +480,59 @@ void OnMenuTabSelected(ModContext* ctx, void*) {
|
||||
ModResult buildPlayTab(ModContext* ctx, UiWindowHandle, UiElementHandle leftPane,
|
||||
UiElementHandle rightPane, void*, ModError*)
|
||||
{
|
||||
add_button(leftPane,
|
||||
std::filesystem::path seed_dir = paths::GetRandomizerSeedsPath();
|
||||
|
||||
std::string help_rml = "";
|
||||
if (std::filesystem::is_empty(seed_dir)) {
|
||||
help_rml = "No seeds generated! You can generate a seed from the Seed Management Tab.";
|
||||
} else {
|
||||
help_rml = "Choose which seed you want to play.";
|
||||
}
|
||||
|
||||
std::vector<std::string> seedHashes;
|
||||
for (const auto& entry : std::filesystem::directory_iterator(seed_dir)) {
|
||||
if (entry.is_directory()) {
|
||||
seedHashes.push_back(entry.path().filename().string());
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<const char*> availableSeeds;
|
||||
for (const auto& hash : seedHashes) {
|
||||
availableSeeds.push_back(hash.c_str());
|
||||
}
|
||||
|
||||
add_select(leftPane,
|
||||
"Selected Seed",
|
||||
"",
|
||||
[](ModContext*, void*) {
|
||||
// TODO
|
||||
help_rml.c_str(),
|
||||
availableSeeds.data(),
|
||||
availableSeeds.size(),
|
||||
[](ModContext*, void*, UiControlValue* out_value) {
|
||||
int idx = 0;
|
||||
for (const auto& entry : std::filesystem::directory_iterator(paths::GetRandomizerSeedsPath())) {
|
||||
if (entry.is_directory()) {
|
||||
std::string hash = entry.path().filename().string();
|
||||
if (randomizer_GetContext().mHash == hash) {
|
||||
break;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
out_value->int_value = idx;
|
||||
},
|
||||
[](ModContext*, void*, const UiControlValue* value) {
|
||||
int idx = 0;
|
||||
for (const auto& entry : std::filesystem::directory_iterator(paths::GetRandomizerSeedsPath())) {
|
||||
if (entry.is_directory()) {
|
||||
if (idx == value->int_value) {
|
||||
std::string hash = entry.path().filename().string();
|
||||
randomizer_GetContext() = RandomizerContext();
|
||||
randomizer_GetContext().LoadFromHash(hash);
|
||||
break;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
add_button(leftPane,
|
||||
@@ -543,24 +607,4 @@ ModResult buildFileSelectGateMenu(dFile_select_c* fileSelect) {
|
||||
session::svc_mng.ui->window_push(session::svc_mng.mod_ctx, &desc, &g_file_select_window_ctx.window_handle);
|
||||
}
|
||||
|
||||
std::filesystem::path GetRandomizerPath() {
|
||||
return paths::GetRandomizerPath() / "randomizer";
|
||||
}
|
||||
|
||||
std::filesystem::path GetRandomizerSettingsPath() {
|
||||
return GetRandomizerPath() / "settings.yaml";
|
||||
}
|
||||
|
||||
std::filesystem::path GetRandomizerPreferencesPath() {
|
||||
return GetRandomizerPath() / "preferences.yaml";
|
||||
}
|
||||
|
||||
std::filesystem::path GetRandomizerPresetsPath() {
|
||||
return GetRandomizerPath() / "presets";
|
||||
}
|
||||
|
||||
std::filesystem::path GetRandomizerSeedsPath() {
|
||||
return GetRandomizerPath() / "seeds";
|
||||
}
|
||||
|
||||
} // namespace dusk::ui
|
||||
|
||||
@@ -34,11 +34,4 @@ void PastePermalinkFromClipboard();
|
||||
|
||||
ModResult buildMenuTab();
|
||||
ModResult buildFileSelectGateMenu(dFile_select_c*);
|
||||
|
||||
std::filesystem::path GetRandomizerPath();
|
||||
std::filesystem::path GetRandomizerSettingsPath();
|
||||
std::filesystem::path GetRandomizerPreferencesPath();
|
||||
std::filesystem::path GetRandomizerSeedsPath();
|
||||
std::filesystem::path GetRandomizerPresetsPath();
|
||||
|
||||
}
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <dolphin/types.h>
|
||||
|
||||
inline u8 getAncientDocumentNum() {
|
||||
// TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline u8 getAreaKeyNum(int) {
|
||||
// TODO
|
||||
return 0;
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
#include "d/d_item.h"
|
||||
#include "d/d_item_data.h"
|
||||
#include "item_ids.h"
|
||||
#include "utilities.h"
|
||||
#include "tools.h"
|
||||
|
||||
bool haveItem(u32 item) {
|
||||
return checkItemGet((u8)item, 1);
|
||||
|
||||
Reference in New Issue
Block a user