mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-08-17 12:39:27 -04:00
add imgui menu for generating and selecting seeds
This commit is contained in:
@@ -1362,6 +1362,8 @@ set(DUSK_FILES
|
||||
src/dusk/imgui/ImGuiMenuTools.hpp
|
||||
src/dusk/imgui/ImGuiMenuEnhancements.cpp
|
||||
src/dusk/imgui/ImGuiMenuEnhancements.hpp
|
||||
src/dusk/imgui/ImGuiMenuRandomizer.cpp
|
||||
src/dusk/imgui/ImGuiMenuRandomizer.hpp
|
||||
src/dusk/imgui/ImGuiPreLaunchWindow.cpp
|
||||
src/dusk/imgui/ImGuiPreLaunchWindow.hpp
|
||||
src/dusk/imgui/ImGuiFirstRunPreset.hpp
|
||||
@@ -1389,6 +1391,8 @@ set(DUSK_FILES
|
||||
src/dusk/randomizer/game/tools.h
|
||||
src/dusk/randomizer/game/verify_item_functions.cpp
|
||||
src/dusk/randomizer/game/verify_item_functions.h
|
||||
src/dusk/randomizer/game/randomizer_context.cpp
|
||||
src/dusk/randomizer/game/randomizer_context.hpp
|
||||
src/dusk/randomizer/generator/logic/area.cpp
|
||||
src/dusk/randomizer/generator/logic/area.hpp
|
||||
src/dusk/randomizer/generator/logic/dungeon.cpp
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
#ifndef D_COM_D_COM_INF_GAME_H
|
||||
#define D_COM_D_COM_INF_GAME_H
|
||||
|
||||
#if TARGET_PC
|
||||
#include "dusk/randomizer/game/randomizer_context.hpp"
|
||||
#endif
|
||||
|
||||
#include "d/d_attention.h"
|
||||
#include "d/d_cc_s.h"
|
||||
#include "d/d_event.h"
|
||||
@@ -1269,14 +1273,6 @@ int dComIfGd_setShadow(u32 param_0, s8 param_1, J3DModel* param_2, cXyz* param_3
|
||||
dKy_tevstr_c* param_9, s16 param_10, f32 param_11, TGXTexObj* param_12);
|
||||
|
||||
#if TARGET_PC
|
||||
inline dSv_randomizer_c& dComIfG_getRandomizer() {
|
||||
return g_dComIfG_gameInfo.info.mRandomizer;
|
||||
}
|
||||
|
||||
inline BOOL dComIfG_isRandomizer() {
|
||||
return g_dComIfG_gameInfo.info.mRandomizer.mActive;
|
||||
}
|
||||
|
||||
void dComIfGs_setupRandomizerSave();
|
||||
#endif
|
||||
|
||||
|
||||
@@ -964,18 +964,6 @@ public:
|
||||
/* 0x8 */ s8 m_no;
|
||||
};
|
||||
|
||||
#if TARGET_PC
|
||||
class dSv_randomizer_c {
|
||||
public:
|
||||
BOOL mActive{false};
|
||||
std::unordered_map<std::string, std::unordered_map<u8, u8>> mTreasureChestOverrides{};
|
||||
std::unordered_map<std::string, std::unordered_map<u8, u8>> mPoeOverrides{};
|
||||
|
||||
u8 mStartHour{0};
|
||||
|
||||
void clear();
|
||||
};
|
||||
#endif
|
||||
|
||||
class dSv_info_c {
|
||||
public:
|
||||
@@ -1059,9 +1047,6 @@ public:
|
||||
#if DEBUG
|
||||
/* 0xF80 */ flagFile_c mFlagFile;
|
||||
#endif
|
||||
#if TARGET_PC
|
||||
/* 0xF38 */ dSv_randomizer_c mRandomizer;
|
||||
#endif
|
||||
}; // Size: 0xF38
|
||||
|
||||
class dSv_event_flag_c {
|
||||
|
||||
@@ -1023,12 +1023,12 @@ void daAlink_c::setGetItemFace(u16 i_itemNo) {
|
||||
|| i_itemNo == dItemNo_DROP_CONTAINER02_e
|
||||
#if TARGET_PC
|
||||
// Rando items for facial expressions
|
||||
|| (dComIfG_isRandomizer() && i_itemNo == dItemNo_Randomizer_WOOD_STICK_e)
|
||||
|| (dComIfG_isRandomizer() && i_itemNo == dItemNo_Randomizer_SWORD_e)
|
||||
|| (dComIfG_isRandomizer() && i_itemNo == dItemNo_Randomizer_SHIELD_e)
|
||||
|| (dComIfG_isRandomizer() && i_itemNo == dItemNo_Randomizer_MASTER_SWORD_e)
|
||||
|| (dComIfG_isRandomizer() && i_itemNo == dItemNo_Randomizer_LIGHT_SWORD_e)
|
||||
|| (dComIfG_isRandomizer() && i_itemNo == dItemNo_Randomizer_MAGIC_LV1_e)
|
||||
|| (randomizer_IsActive() && i_itemNo == dItemNo_Randomizer_WOOD_STICK_e)
|
||||
|| (randomizer_IsActive() && i_itemNo == dItemNo_Randomizer_SWORD_e)
|
||||
|| (randomizer_IsActive() && i_itemNo == dItemNo_Randomizer_SHIELD_e)
|
||||
|| (randomizer_IsActive() && i_itemNo == dItemNo_Randomizer_MASTER_SWORD_e)
|
||||
|| (randomizer_IsActive() && i_itemNo == dItemNo_Randomizer_LIGHT_SWORD_e)
|
||||
|| (randomizer_IsActive() && i_itemNo == dItemNo_Randomizer_MAGIC_LV1_e)
|
||||
#endif
|
||||
|| i_itemNo == dItemNo_DROP_CONTAINER03_e)
|
||||
{
|
||||
@@ -1037,7 +1037,7 @@ void daAlink_c::setGetItemFace(u16 i_itemNo) {
|
||||
setFaceBasicTexture(FTANM_K_A);
|
||||
setFaceBasicBck(dRes_ID_ALANM_BCK_FK_e);
|
||||
#if TARGET_PC
|
||||
} else if (i_itemNo == dItemNo_TOMATO_PUREE_e || i_itemNo == dItemNo_TASTE_e || (dComIfG_isRandomizer() && i_itemNo == dItemNo_Randomizer_FOOLISH_ITEM_e)) {
|
||||
} else if (i_itemNo == dItemNo_TOMATO_PUREE_e || i_itemNo == dItemNo_TASTE_e || (randomizer_IsActive() && i_itemNo == dItemNo_Randomizer_FOOLISH_ITEM_e)) {
|
||||
#else
|
||||
} else if (i_itemNo == dItemNo_TOMATO_PUREE_e || i_itemNo == dItemNo_TASTE_e) {
|
||||
#endif
|
||||
@@ -2494,7 +2494,7 @@ void daAlink_c::setGetSubBgm(int i_itemNo) {
|
||||
};
|
||||
|
||||
#if TARGET_PC
|
||||
u32 se_type = dComIfG_isRandomizer() ? getSeTypeRandomizer[i_itemNo] : getSeType[i_itemNo];
|
||||
u32 se_type = randomizer_IsActive() ? getSeTypeRandomizer[i_itemNo] : getSeType[i_itemNo];
|
||||
#else
|
||||
u32 se_type = getSeType[i_itemNo];
|
||||
#endif
|
||||
|
||||
@@ -533,7 +533,7 @@ int daDitem_c::execute() {
|
||||
|
||||
#if TARGET_PC
|
||||
// Certain items use field models that are too big to fit in link's hands so we want to scale them down to fit.
|
||||
if (dComIfG_isRandomizer()) {
|
||||
if (randomizer_IsActive()) {
|
||||
switch (m_itemNo)
|
||||
{
|
||||
case dItemNo_Randomizer_MIRROR_PIECE_1_e:
|
||||
|
||||
@@ -1270,7 +1270,7 @@ void daNpc_Fairy_c::AppearDemoCall() {
|
||||
mEvtNo = EVT_APPEAR_50F_02;
|
||||
}
|
||||
#if TARGET_PC
|
||||
} else if (dComIfGs_checkEmptyBottle() || dComIfG_isRandomizer()) {
|
||||
} else if (dComIfGs_checkEmptyBottle() || randomizer_IsActive()) {
|
||||
#else
|
||||
} else if (dComIfGs_checkEmptyBottle()) {
|
||||
#endif
|
||||
|
||||
@@ -153,7 +153,7 @@ void daItem_c::CreateInit() {
|
||||
show();
|
||||
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer()) {
|
||||
if (randomizer_IsActive()) {
|
||||
// Adjust item scale based on item ID
|
||||
switch(m_itemNo)
|
||||
{
|
||||
@@ -230,7 +230,7 @@ void daItem_c::CreateInit() {
|
||||
animPlay(1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
#if TARGET_PC
|
||||
if (m_itemNo == dItemNo_BOOMERANG_e && !dComIfG_isRandomizer()) {
|
||||
if (m_itemNo == dItemNo_BOOMERANG_e && !randomizer_IsActive()) {
|
||||
#else
|
||||
if (m_itemNo == dItemNo_BOOMERANG_e) {
|
||||
#endif
|
||||
|
||||
@@ -1787,11 +1787,11 @@ cPhs_Step daTbox_c::create1st() {
|
||||
field_0x980 = home.angle.x;
|
||||
#if TARGET_PC
|
||||
// The upper 8 bits of home.angle.z hold the itemId
|
||||
if (dComIfG_isRandomizer()) {
|
||||
if (randomizer_IsActive()) {
|
||||
home.angle.z &= ~0xFF00;
|
||||
auto stage = dComIfGp_getStartStageName();
|
||||
auto tboxId = static_cast<u8>(getTboxNo());
|
||||
home.angle.z |= dComIfG_getRandomizer().mTreasureChestOverrides[stage][tboxId] << 8;
|
||||
home.angle.z |= randomizer_GetContext().mTreasureChestOverrides[stage][tboxId] << 8;
|
||||
}
|
||||
#endif
|
||||
field_0x982 = home.angle.z;
|
||||
|
||||
@@ -62,7 +62,7 @@ int CheckFieldItemCreateHeap(fopAc_ac_c* i_this) {
|
||||
|
||||
u8 item_no = a_this->getItemNo();
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer()) {
|
||||
if (randomizer_IsActive()) {
|
||||
switch (item_no)
|
||||
{
|
||||
case dItemNo_Randomizer_EMPTY_BOTTLE_e:
|
||||
|
||||
+18
-79
@@ -29,11 +29,10 @@
|
||||
|
||||
#if TARGET_PC
|
||||
#include "dusk/randomizer/generator/randomizer.hpp"
|
||||
#include "dusk/randomizer/generator/utility/yaml.hpp"
|
||||
#include "dusk/randomizer/game/tools.h"
|
||||
#include "dusk/randomizer/game/stages.h"
|
||||
#include "dusk/randomizer/game/flags.h"
|
||||
#include "dusk/randomizer//game/verify_item_functions.h"
|
||||
#include "dusk/randomizer/game/randomizer_context.hpp"
|
||||
#endif
|
||||
|
||||
|
||||
@@ -173,7 +172,7 @@ int dComIfG_play_c::getLayerNo_common_common(const char* i_stageName, int i_room
|
||||
|
||||
#if TARGET_PC
|
||||
// Special layer checks for randomizer
|
||||
if (dComIfG_isRandomizer()) {
|
||||
if (randomizer_IsActive()) {
|
||||
int stageID = getStageID(i_stageName);
|
||||
bool condition = false;
|
||||
bool darkIsClear = false;
|
||||
@@ -2866,65 +2865,26 @@ int dComIfGd_setShadow(u32 param_0, s8 param_1, J3DModel* param_2, cXyz* param_3
|
||||
|
||||
#if TARGET_PC
|
||||
void dComIfGs_setupRandomizerSave() {
|
||||
randomizer::Randomizer randomizer;
|
||||
if (randomizer.Generate())
|
||||
throw std::runtime_error("Randomizer Generation Faild");
|
||||
auto world = randomizer.GetWorlds()[0].get();
|
||||
|
||||
// Setup randomizer data
|
||||
auto& randoData = g_dComIfG_gameInfo.info.mRandomizer;
|
||||
randoData.mActive = TRUE;
|
||||
for (const auto& location : world->GetAllLocations()) {
|
||||
const auto& metaData = location->GetMetadata();
|
||||
if (location->HasCategories("Chest")) {
|
||||
const auto& stage = metaData[0]["Stage"].as<std::string>();
|
||||
const auto& tboxId = metaData[0]["Tbox ID"].as<u8>();
|
||||
const auto& itemId = location->GetCurrentItem()->GetID();
|
||||
randoData.mTreasureChestOverrides[stage][tboxId] = itemId;
|
||||
}
|
||||
}
|
||||
// Setup file based on randomizer data
|
||||
auto& randoData = randomizer_GetContext();
|
||||
randoData.mActive = true;
|
||||
randoData.mCreatingSave = true;
|
||||
|
||||
// Set starting flags
|
||||
auto startFlags = LoadYAML(RANDO_DATA_PATH "startflags.yaml");
|
||||
// Event Flags
|
||||
for (const auto& flagNode : startFlags["EventFlags"]) {
|
||||
if (flagNode.IsScalar()) {
|
||||
const auto& flag = flagNode.as<u16>();
|
||||
dComIfGs_onEventBit(flag);
|
||||
} else if (flagNode.IsMap()) {
|
||||
const auto& condition = flagNode.begin()->first.as<std::string>();
|
||||
if (world->EvaluateSettingCondition(condition)) {
|
||||
DuskLog.debug("Setting flags for {}", condition);
|
||||
for (const auto& conditionalFlag : flagNode.begin()->second) {
|
||||
const auto& flag = conditionalFlag.as<u16>();
|
||||
dComIfGs_onEventBit(flag);
|
||||
}
|
||||
}
|
||||
for (const auto& flag : randoData.mStartEventFlags) {
|
||||
dComIfGs_onEventBit(flag);
|
||||
}
|
||||
// Region Flags
|
||||
for (const auto& [region, flags] : randoData.mStartRegionFlags) {
|
||||
for (const auto& flag : flags) {
|
||||
dComIfGs_onRegionFlag(region, flag);
|
||||
}
|
||||
}
|
||||
|
||||
// Region Flags
|
||||
for (const auto& regionNode : startFlags["RegionFlags"]) {
|
||||
const auto& region = regionNode.first.as<std::string>();
|
||||
const auto& index = regionNode.second["Index"].as<int>();
|
||||
const auto& flags = regionNode.second["Flags"];
|
||||
DuskLog.debug("Setting region flags for {}", region);
|
||||
// This seems kinda scuffed so maybe we change it later
|
||||
for (const auto& flagNode : flags) {
|
||||
if (flagNode.IsScalar()) {
|
||||
const auto& flag = flagNode.as<int>();
|
||||
dComIfGs_onRegionFlag(index, flag);
|
||||
} else if (flagNode.IsMap()) {
|
||||
const auto& condition = flagNode.begin()->first.as<std::string>();
|
||||
if (world->EvaluateSettingCondition(condition)) {
|
||||
for (const auto& conditionalFlag : flagNode.begin()->second) {
|
||||
const auto& flag = conditionalFlag.as<int>();
|
||||
dComIfGs_onRegionFlag(index, flag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Map bits (fills in overworld on map)
|
||||
dComIfGs_setRegionBit(randoData.mMapBits);
|
||||
|
||||
// Other flags based on starting flags
|
||||
if (dComIfGs_isEventBit(CLEARED_FARON_TWILIGHT))
|
||||
@@ -2963,35 +2923,14 @@ void dComIfGs_setupRandomizerSave() {
|
||||
dComIfGs_onTransformLV(3);
|
||||
}
|
||||
}
|
||||
|
||||
if (world->Setting("Unlock Map Regions") == "On")
|
||||
{
|
||||
int mapBits = 0x20;
|
||||
if (world->Setting("Snowpeak Does Not Require Reekfish Scent") == "On") {mapBits |= 0x40;}
|
||||
if (dComIfGs_isEventBit(CLEARED_LANAYRU_TWILIGHT)) {mapBits |= 0x10;}
|
||||
if (dComIfGs_isEventBit(CLEARED_ELDIN_TWILIGHT)) {mapBits |= 0x08;}
|
||||
if (dComIfGs_isEventBit(CLEARED_FARON_TWILIGHT)) {mapBits |= 0x04;}
|
||||
if (world->Setting("Skip Prologue") == "On") {mapBits |= 0x02;}
|
||||
dComIfGs_setRegionBit(mapBits);
|
||||
}
|
||||
|
||||
// Set starting inventory
|
||||
for (const auto& item: world->GetStartingItemPool()) {
|
||||
execItemGet(static_cast<u8>(item->GetID()));
|
||||
for (const auto& itemId: randoData.mStartingInventory) {
|
||||
execItemGet(itemId);
|
||||
}
|
||||
|
||||
// Set starting time of day
|
||||
const auto startTimeSetting = world->Setting("Starting Time of Day");
|
||||
if (startTimeSetting == "Morning")
|
||||
randoData.mStartHour = 6;
|
||||
else if (startTimeSetting == "Noon")
|
||||
randoData.mStartHour = 12;
|
||||
else if (startTimeSetting == "Evening")
|
||||
randoData.mStartHour = 18;
|
||||
else if (startTimeSetting == "Night")
|
||||
randoData.mStartHour = 24;
|
||||
|
||||
DuskLog.debug("Created Rando Save");
|
||||
randoData.mCreatingSave = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1536,8 +1536,8 @@ void dFile_select_c::nameInput2() {
|
||||
dComIfGs_setHorseName(mpName->getInputStrPtr());
|
||||
mIsSelectEnd = true;
|
||||
#if TARGET_PC
|
||||
// Create a randomizer save if Z is being held
|
||||
if (mDoCPd_c::getHoldZ(PAD_1)) {
|
||||
// Create a randomizer save if one is selected
|
||||
if (!randomizer_GetContext().mHash.empty()) {
|
||||
dComIfGs_setupRandomizerSave();
|
||||
}
|
||||
#endif
|
||||
|
||||
+46
-46
@@ -537,7 +537,7 @@ static void (*item_func_ptr_randomizer[256])() = {
|
||||
inline void getItemFunc(u8 i_itemNo) {
|
||||
dComIfGs_onItemFirstBit(i_itemNo);
|
||||
#if TARGET_PC
|
||||
(dComIfG_isRandomizer() ? item_func_ptr_randomizer : item_func_ptr)[i_itemNo]();
|
||||
(randomizer_IsActive() ? item_func_ptr_randomizer : item_func_ptr)[i_itemNo]();
|
||||
#else
|
||||
item_func_ptr[i_itemNo]();
|
||||
#endif
|
||||
@@ -545,7 +545,7 @@ inline void getItemFunc(u8 i_itemNo) {
|
||||
|
||||
void execItemGet(u8 i_itemNo) {
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer())
|
||||
if (randomizer_IsActive())
|
||||
i_itemNo = verifyProgressiveItem(i_itemNo);
|
||||
#endif
|
||||
getItemFunc(i_itemNo);
|
||||
@@ -1074,7 +1074,7 @@ static int (*item_getcheck_func_ptr_randomizer[256])() = {
|
||||
|
||||
inline int getCheckItemFunc(u8 i_itemNo) {
|
||||
#if TARGET_PC
|
||||
return (dComIfG_isRandomizer() ? item_getcheck_func_ptr_randomizer : item_getcheck_func_ptr)[i_itemNo]();
|
||||
return (randomizer_IsActive() ? item_getcheck_func_ptr_randomizer : item_getcheck_func_ptr)[i_itemNo]();
|
||||
#else
|
||||
return item_getcheck_func_ptr[i_itemNo]();
|
||||
#endif
|
||||
@@ -1233,7 +1233,7 @@ void item_func_SMALL_KEY() {
|
||||
void item_func_KAKERA_HEART() {
|
||||
dComIfGp_setItemMaxLifeCount(1);
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer()) {
|
||||
if (randomizer_IsActive()) {
|
||||
// TODO rando
|
||||
/*
|
||||
Pasting rando code until the framework has been updated
|
||||
@@ -1259,7 +1259,7 @@ void item_func_UTUWA_HEART() {
|
||||
int tmp = dStage_stagInfo_GetSaveTbl(stag_info);
|
||||
dComIfGs_onStageLife();
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer()) {
|
||||
if (randomizer_IsActive()) {
|
||||
// TODO rando
|
||||
/*
|
||||
Pasting rando code until the framework has been updated
|
||||
@@ -1334,7 +1334,7 @@ void item_func_WEAR_ZORA() {}
|
||||
|
||||
void item_func_MAGIC_LV1() {
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer()) {
|
||||
if (randomizer_IsActive()) {
|
||||
dComIfGs_onEventBit(0xD04); // Can transform at will
|
||||
dComIfGs_onEventBit(0x501); // Midna Charge Unlocked
|
||||
return;
|
||||
@@ -1355,7 +1355,7 @@ void item_func_WALLET_LV1() {
|
||||
void item_func_WALLET_LV2() {
|
||||
dComIfGs_setWalletSize(BIG_WALLET);
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer()) {
|
||||
if (randomizer_IsActive()) {
|
||||
// TODO rando
|
||||
// Putting rando code here until the framework gets built:
|
||||
/*
|
||||
@@ -1386,7 +1386,7 @@ void item_func_WALLET_LV3() {
|
||||
dComIfGs_setWalletSize(GIANT_WALLET);
|
||||
#if TARGET_PC
|
||||
// TODO rando
|
||||
if (dComIfG_isRandomizer()) {
|
||||
if (randomizer_IsActive()) {
|
||||
// Putting rando code here until the framework gets built:
|
||||
/*
|
||||
Basically we fill the wallet if desired and then we change the color of the rupee icon to red
|
||||
@@ -1451,7 +1451,7 @@ void item_func_WOOD_STICK() {
|
||||
dComIfGs_setCollectSword(COLLECT_WOODEN_SWORD);
|
||||
dComIfGs_setSelectEquipSword(dItemNo_WOOD_STICK_e);
|
||||
#if TARGET_PC
|
||||
if (!dComIfG_isRandomizer())
|
||||
if (!randomizer_IsActive())
|
||||
#endif
|
||||
dComIfGs_onSwitch(28, dComIfGp_roomControl_getStayNo());
|
||||
}
|
||||
@@ -1514,7 +1514,7 @@ void item_func_PACHINKO() {
|
||||
|
||||
void item_func_COPY_ROD_2() {
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer())
|
||||
if (randomizer_IsActive())
|
||||
dComIfGs_onEventBit(0x2580); // Power up dominion rod
|
||||
else
|
||||
#endif
|
||||
@@ -1729,7 +1729,7 @@ void item_func_LV3_SOUP() {
|
||||
|
||||
void item_func_LETTER() {
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer()) {
|
||||
if (randomizer_IsActive()) {
|
||||
if (dComIfGs_getItem(SLOT_21, true) != dItemNo_Randomizer_HORSE_FLUTE_e)
|
||||
dComIfGs_setItem(SLOT_21, dItemNo_Randomizer_LETTER_e);
|
||||
} else
|
||||
@@ -1739,7 +1739,7 @@ void item_func_LETTER() {
|
||||
|
||||
void item_func_BILL() {
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer()) {
|
||||
if (randomizer_IsActive()) {
|
||||
if (dComIfGs_getItem(SLOT_21, true) != dItemNo_Randomizer_HORSE_FLUTE_e)
|
||||
dComIfGs_setItem(SLOT_21, dItemNo_Randomizer_BILL_e);
|
||||
} else
|
||||
@@ -1751,7 +1751,7 @@ void item_func_WOOD_STATUE() {
|
||||
/* dSv_event_flag_c::F_283 - Hyrule Field - Get wood carving */
|
||||
dComIfGs_onEventBit(dSv_event_flag_c::saveBitLabels[283]);
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer()) {
|
||||
if (randomizer_IsActive()) {
|
||||
if (dComIfGs_getItem(SLOT_21, true) != dItemNo_Randomizer_HORSE_FLUTE_e)
|
||||
dComIfGs_setItem(SLOT_21, dItemNo_Randomizer_WOOD_STATUE_e);
|
||||
} else
|
||||
@@ -1761,7 +1761,7 @@ void item_func_WOOD_STATUE() {
|
||||
|
||||
void item_func_IRIAS_PENDANT() {
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer()) {
|
||||
if (randomizer_IsActive()) {
|
||||
if (dComIfGs_getItem(SLOT_21, true) != dItemNo_Randomizer_HORSE_FLUTE_e)
|
||||
dComIfGs_setItem(SLOT_21, dItemNo_Randomizer_IRIAS_PENDANT_e);
|
||||
} else
|
||||
@@ -1771,7 +1771,7 @@ void item_func_IRIAS_PENDANT() {
|
||||
|
||||
void item_func_HORSE_FLUTE() {
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer()) {
|
||||
if (randomizer_IsActive()) {
|
||||
if (dComIfGs_getItem(SLOT_21, true) != dItemNo_Randomizer_NONE_e)
|
||||
dComIfGs_setItem(SLOT_21, dItemNo_Randomizer_HORSE_FLUTE_e);
|
||||
} else
|
||||
@@ -1837,7 +1837,7 @@ void item_func_LAKE_HYLIA_PORTAL() {
|
||||
|
||||
void item_func_RAFRELS_MEMO() {
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer())
|
||||
if (randomizer_IsActive())
|
||||
dComIfGs_setItem(SLOT_7, dItemNo_Randomizer_RAFRELS_MEMO_e);
|
||||
else
|
||||
#endif
|
||||
@@ -1846,7 +1846,7 @@ void item_func_RAFRELS_MEMO() {
|
||||
|
||||
void item_func_ASHS_SCRIBBLING() {
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer()) {
|
||||
if (randomizer_IsActive()) {
|
||||
if (!dComIfGs_isEventBit(0x3B80)) { // Got earring from Ralis
|
||||
dComIfGs_setItem(SLOT_19, dItemNo_Randomizer_ASHS_SCRIBBLING_e);
|
||||
}
|
||||
@@ -1928,7 +1928,7 @@ void item_func_DROP_CONTAINER02() {
|
||||
void item_func_DROP_CONTAINER03() {
|
||||
dComIfGs_onLightDropGetFlag(LANAYRU_VESSEL);
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer()) {
|
||||
if (randomizer_IsActive()) {
|
||||
dComIfGs_onEventBit(0x1E80); // Malo Mart Fundraising Starts
|
||||
}
|
||||
#endif
|
||||
@@ -1938,7 +1938,7 @@ void item_func_FILLED_CONTAINER() {}
|
||||
|
||||
void item_func_MIRROR_PIECE_2() {
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer()) {
|
||||
if (randomizer_IsActive()) {
|
||||
dComIfGs_onCollectMirror(1);
|
||||
// TODO rando
|
||||
/*
|
||||
@@ -1955,7 +1955,7 @@ void item_func_MIRROR_PIECE_2() {
|
||||
|
||||
void item_func_MIRROR_PIECE_3() {
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer()) {
|
||||
if (randomizer_IsActive()) {
|
||||
dComIfGs_onCollectMirror(2);
|
||||
// TODO rando
|
||||
/*
|
||||
@@ -1972,7 +1972,7 @@ void item_func_MIRROR_PIECE_3() {
|
||||
|
||||
void item_func_MIRROR_PIECE_4() {
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer()) {
|
||||
if (randomizer_IsActive()) {
|
||||
dComIfGs_onCollectMirror(3);
|
||||
// TODO rando
|
||||
/*
|
||||
@@ -2144,7 +2144,7 @@ void item_func_FUSED_SHADOW_1() {
|
||||
}
|
||||
|
||||
void item_func_FUSED_SHADOW_2() {
|
||||
if (dComIfG_isRandomizer()) {
|
||||
if (randomizer_IsActive()) {
|
||||
dComIfGs_onCollectCrystal(1);
|
||||
/*
|
||||
Adding rando code until framework is implemented
|
||||
@@ -2158,7 +2158,7 @@ void item_func_FUSED_SHADOW_2() {
|
||||
}
|
||||
|
||||
void item_func_FUSED_SHADOW_3() {
|
||||
if (dComIfG_isRandomizer()) {
|
||||
if (randomizer_IsActive()) {
|
||||
dComIfGs_onCollectCrystal(2);
|
||||
/*
|
||||
Adding rando code until framework is implemented
|
||||
@@ -2179,7 +2179,7 @@ void item_func_FUSED_SHADOW_3() {
|
||||
|
||||
void item_func_MIRROR_PIECE_1() {
|
||||
|
||||
if (dComIfG_isRandomizer()) {
|
||||
if (randomizer_IsActive()) {
|
||||
dComIfGs_onCollectMirror(0);
|
||||
// TODO rando
|
||||
/*
|
||||
@@ -2197,7 +2197,7 @@ void item_func_MIRROR_PIECE_1() {
|
||||
|
||||
void item_func_POU_SPIRIT() {
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer()) {
|
||||
if (randomizer_IsActive()) {
|
||||
dComIfGs_addPohSpiritNum();
|
||||
// TODO rando
|
||||
/*
|
||||
@@ -2252,7 +2252,7 @@ void item_func_ANCIENT_DOCUMENT() {
|
||||
|
||||
void item_func_AIR_LETTER() {
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer()) {
|
||||
if (randomizer_IsActive()) {
|
||||
u8 letterCount = dComIfGs_getAncientDocumentNum();
|
||||
dComIfGs_setAncientDocumentNum(letterCount + 1);
|
||||
} else
|
||||
@@ -2262,7 +2262,7 @@ void item_func_AIR_LETTER() {
|
||||
|
||||
void item_func_ANCIENT_DOCUMENT2() {
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer()) {
|
||||
if (randomizer_IsActive()) {
|
||||
dComIfGs_onEventBit(0x3B08); // Repaired Cannon at Lake
|
||||
dComIfGs_setAncientDocumentNum(6);
|
||||
}
|
||||
@@ -2280,7 +2280,7 @@ void item_func_LINKS_SAVINGS() {
|
||||
|
||||
void item_func_SMALL_KEY2() {
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer())
|
||||
if (randomizer_IsActive())
|
||||
dComIfGs_onStageSwitch(0x2, 0x14); // Unlock North Faron Gate
|
||||
else
|
||||
#endif
|
||||
@@ -2297,7 +2297,7 @@ void item_func_POU_FIRE4() {}
|
||||
|
||||
void item_func_BOSSRIDER_KEY() {
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer()) {
|
||||
if (randomizer_IsActive()) {
|
||||
dComIfGs_onStageSwitch(0x3, 0x69); // Started Escort
|
||||
dComIfGs_onStageSwitch(0x3, 0x65); // Followed Rutella to Graveyard
|
||||
dComIfGs_onEventBit(0x840); // Started Zora Escort
|
||||
@@ -2308,7 +2308,7 @@ void item_func_BOSSRIDER_KEY() {
|
||||
|
||||
void item_func_TOMATO_PUREE() {
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer()) {
|
||||
if (randomizer_IsActive()) {
|
||||
dComIfGs_onEventBit(0x480); // Told Yeta about Pumpkin
|
||||
dComIfGs_onEventBit(0x2); // Yeto put Pumpkin in Soup
|
||||
dComIfGs_onEventBit(0x1440); // SPR Lobby Door Unlocked
|
||||
@@ -2319,7 +2319,7 @@ void item_func_TOMATO_PUREE() {
|
||||
|
||||
void item_func_TASTE() {
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer()) {
|
||||
if (randomizer_IsActive()) {
|
||||
dComIfGs_onEventBit(0x120); // Told Yeta about Cheese
|
||||
dComIfGs_onEventBit(0x1); // Yeto put Pumpkin in Soup
|
||||
dComIfGs_onEventBit(0x1420); // SPR Lobby west Door Unlocked
|
||||
@@ -2330,7 +2330,7 @@ void item_func_TASTE() {
|
||||
|
||||
void item_func_LV5_BOSS_KEY() {
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer())
|
||||
if (randomizer_IsActive())
|
||||
dComIfGs_onDungeonItemBossKey(0x14);
|
||||
else
|
||||
#endif
|
||||
@@ -2351,7 +2351,7 @@ void item_func_KEY_OF_CARAVAN() {}
|
||||
|
||||
void item_func_LV2_BOSS_KEY() {
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer()) {
|
||||
if (randomizer_IsActive()) {
|
||||
dComIfGs_onDungeonItemBossKey(0x11);
|
||||
execItemGet(dItemNo_Randomizer_L2_KEY_PIECES3_e);
|
||||
} else
|
||||
@@ -2361,7 +2361,7 @@ void item_func_LV2_BOSS_KEY() {
|
||||
|
||||
void item_func_KEY_OF_FILONE() {
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer())
|
||||
if (randomizer_IsActive())
|
||||
dComIfGs_onStageSwitch(0x2, 0xC); // Unlock Coro Gate
|
||||
else
|
||||
#endif
|
||||
@@ -2564,7 +2564,7 @@ int item_getcheck_func_WEAR_ZORA() {
|
||||
|
||||
int item_getcheck_func_MAGIC_LV1() {
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer())
|
||||
if (randomizer_IsActive())
|
||||
return dComIfGs_isItemFirstBit(dItemNo_Randomizer_MAGIC_LV1_e);
|
||||
#endif
|
||||
return -1;
|
||||
@@ -2580,7 +2580,7 @@ int item_getcheck_func_WALLET_LV1() {
|
||||
|
||||
int item_getcheck_func_WALLET_LV2() {
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer())
|
||||
if (randomizer_IsActive())
|
||||
return dComIfGs_isItemFirstBit(dItemNo_Randomizer_WALLET_LV2_e);
|
||||
#endif
|
||||
return -1;
|
||||
@@ -2588,7 +2588,7 @@ int item_getcheck_func_WALLET_LV2() {
|
||||
|
||||
int item_getcheck_func_WALLET_LV3() {
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer())
|
||||
if (randomizer_IsActive())
|
||||
return dComIfGs_isItemFirstBit(dItemNo_Randomizer_WALLET_LV3_e);
|
||||
#endif
|
||||
return -1;
|
||||
@@ -2855,7 +2855,7 @@ int item_getcheck_func_LV3_SOUP() {
|
||||
|
||||
int item_getcheck_func_LETTER() {
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer())
|
||||
if (randomizer_IsActive())
|
||||
return dComIfGs_isItemFirstBit(dItemNo_Randomizer_LETTER_e);
|
||||
#endif
|
||||
return dComIfGs_getItem(SLOT_21, true) == dItemNo_LETTER_e ? TRUE : FALSE;
|
||||
@@ -2863,7 +2863,7 @@ int item_getcheck_func_LETTER() {
|
||||
|
||||
int item_getcheck_func_BILL() {
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer())
|
||||
if (randomizer_IsActive())
|
||||
return dComIfGs_isItemFirstBit(dItemNo_Randomizer_BILL_e);
|
||||
#endif
|
||||
return dComIfGs_getItem(SLOT_21, true) == dItemNo_BILL_e ? TRUE : FALSE;
|
||||
@@ -2871,7 +2871,7 @@ int item_getcheck_func_BILL() {
|
||||
|
||||
int item_getcheck_func_WOOD_STATUE() {
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer())
|
||||
if (randomizer_IsActive())
|
||||
return dComIfGs_isItemFirstBit(dItemNo_Randomizer_WOOD_STATUE_e);
|
||||
#endif
|
||||
return dComIfGs_getItem(SLOT_21, true) == dItemNo_WOOD_STATUE_e ? TRUE : FALSE;
|
||||
@@ -2879,7 +2879,7 @@ int item_getcheck_func_WOOD_STATUE() {
|
||||
|
||||
int item_getcheck_func_IRIAS_PENDANT() {
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer())
|
||||
if (randomizer_IsActive())
|
||||
return dComIfGs_isItemFirstBit(dItemNo_Randomizer_IRIAS_PENDANT_e);
|
||||
#endif
|
||||
return dComIfGs_getItem(SLOT_21, true) == dItemNo_IRIAS_PENDANT_e ? TRUE : FALSE;
|
||||
@@ -2887,7 +2887,7 @@ int item_getcheck_func_IRIAS_PENDANT() {
|
||||
|
||||
int item_getcheck_func_HORSE_FLUTE() {
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer())
|
||||
if (randomizer_IsActive())
|
||||
return dComIfGs_isItemFirstBit(dItemNo_Randomizer_HORSE_FLUTE_e);
|
||||
#endif
|
||||
return dComIfGs_getItem(SLOT_22, true) == dItemNo_HORSE_FLUTE_e ? TRUE : FALSE;
|
||||
@@ -2945,7 +2945,7 @@ int item_getcheck_func_FILLED_CONTAINER() {
|
||||
|
||||
int item_getcheck_func_MIRROR_PIECE_2() {
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer())
|
||||
if (randomizer_IsActive())
|
||||
return dComIfGs_isItemFirstBit(dItemNo_Randomizer_MIRROR_PIECE_2_e);
|
||||
#endif
|
||||
return -1;
|
||||
@@ -2953,7 +2953,7 @@ int item_getcheck_func_MIRROR_PIECE_2() {
|
||||
|
||||
int item_getcheck_func_MIRROR_PIECE_3() {
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer())
|
||||
if (randomizer_IsActive())
|
||||
return dComIfGs_isItemFirstBit(dItemNo_Randomizer_MIRROR_PIECE_3_e);
|
||||
#endif
|
||||
return -1;
|
||||
@@ -2961,7 +2961,7 @@ int item_getcheck_func_MIRROR_PIECE_3() {
|
||||
|
||||
int item_getcheck_func_MIRROR_PIECE_4() {
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer())
|
||||
if (randomizer_IsActive())
|
||||
return dComIfGs_isItemFirstBit(dItemNo_Randomizer_MIRROR_PIECE_4_e);
|
||||
#endif
|
||||
return -1;
|
||||
@@ -3181,7 +3181,7 @@ int item_getcheck_func_POU_FIRE4() {
|
||||
|
||||
int item_getcheck_func_BOSSRIDER_KEY() {
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer())
|
||||
if (randomizer_IsActive())
|
||||
return dComIfGs_isItemFirstBit(dItemNo_Randomizer_BOSSRIDER_KEY_e);
|
||||
#endif
|
||||
return -1;
|
||||
|
||||
@@ -1147,12 +1147,12 @@ dItem_itemInfo dItem_data::item_info_randomizer[] = {
|
||||
};
|
||||
|
||||
dItem_itemResource* dItem_data_getItemResource() {
|
||||
return dComIfG_isRandomizer() ? dItem_data::item_resource_randomizer : dItem_data::item_resource;
|
||||
return randomizer_IsActive() ? dItem_data::item_resource_randomizer : dItem_data::item_resource;
|
||||
}
|
||||
dItem_fieldItemResource* dItem_data_getFieldItemResource() {
|
||||
return dComIfG_isRandomizer() ? dItem_data::field_item_res_randomizer : dItem_data::field_item_res;
|
||||
return randomizer_IsActive() ? dItem_data::field_item_res_randomizer : dItem_data::field_item_res;
|
||||
}
|
||||
dItem_itemInfo* dItem_data_getItemInfo() {
|
||||
return dComIfG_isRandomizer() ? dItem_data::item_info_randomizer : dItem_data::item_info;
|
||||
return randomizer_IsActive() ? dItem_data::item_info_randomizer : dItem_data::item_info;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1620,7 +1620,7 @@ u8 dMenu_Ring_c::getItemNum(u8 i_slotNo) {
|
||||
case dItemNo_Randomizer_ANCIENT_DOCUMENT_e:
|
||||
case dItemNo_Randomizer_AIR_LETTER_e:
|
||||
case dItemNo_Randomizer_ANCIENT_DOCUMENT2_e:
|
||||
if (dComIfG_isRandomizer())
|
||||
if (randomizer_IsActive())
|
||||
ret = dComIfGs_getAncientDocumentNum();
|
||||
break;
|
||||
#endif
|
||||
@@ -1667,7 +1667,7 @@ u8 dMenu_Ring_c::getItemMaxNum(u8 i_slotNo) {
|
||||
case dItemNo_Randomizer_ANCIENT_DOCUMENT_e:
|
||||
case dItemNo_Randomizer_AIR_LETTER_e:
|
||||
case dItemNo_Randomizer_ANCIENT_DOCUMENT2_e:
|
||||
if (dComIfG_isRandomizer())
|
||||
if (randomizer_IsActive())
|
||||
ret = 6;
|
||||
break;
|
||||
#endif
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
|
||||
#if TARGET_PC
|
||||
#include "dusk/memory.h"
|
||||
#include "dusk/randomizer/game/tools.h"
|
||||
#endif
|
||||
|
||||
#if DEBUG
|
||||
|
||||
+4
-9
@@ -449,7 +449,7 @@ void dSv_player_item_c::setLineUpItem() {
|
||||
|
||||
#if TARGET_PC
|
||||
// Allow rando to use all item slots
|
||||
if (dComIfG_isRandomizer()) {
|
||||
if (randomizer_IsActive()) {
|
||||
mItemSlots[23] = 7;
|
||||
}
|
||||
#endif
|
||||
@@ -1205,7 +1205,7 @@ void dSv_memBit_c::onDungeonItem(int i_no) {
|
||||
JUT_ASSERT(2969, 0 <= i_no && i_no < DSV_MEMBIT_ENUM_MAX);
|
||||
#if TARGET_PC
|
||||
// Don't use the stage life collection flag for rando
|
||||
if (dComIfG_isRandomizer()) {
|
||||
if (randomizer_IsActive()) {
|
||||
if (i_no == STAGE_LIFE) {
|
||||
return;
|
||||
}
|
||||
@@ -1251,7 +1251,7 @@ void dSv_memBit_c::offDungeonItem(int i_no) {
|
||||
JUT_ASSERT(2983, 0 <= i_no && i_no < DSV_MEMBIT_ENUM_MAX);
|
||||
#if TARGET_PC
|
||||
// Don't use the stage life collection flag for rando
|
||||
if (dComIfG_isRandomizer() && i_no == STAGE_LIFE) {
|
||||
if (randomizer_IsActive() && i_no == STAGE_LIFE) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -1261,7 +1261,7 @@ void dSv_memBit_c::offDungeonItem(int i_no) {
|
||||
s32 dSv_memBit_c::isDungeonItem(int i_no) const {
|
||||
JUT_ASSERT(2998, 0 <= i_no && i_no < DSV_MEMBIT_ENUM_MAX);
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer()) {
|
||||
if (randomizer_IsActive()) {
|
||||
// Don't use the stage life collection flag for rando
|
||||
if (i_no == STAGE_LIFE) {
|
||||
return FALSE;
|
||||
@@ -1644,11 +1644,6 @@ dSv_memory2_c* dSv_save_c::getSave2(int i_stage2No) {
|
||||
return &mSave2[i_stage2No];
|
||||
}
|
||||
|
||||
void dSv_randomizer_c::clear() {
|
||||
mTreasureChestOverrides.clear();
|
||||
mPoeOverrides.clear();
|
||||
mActive = FALSE;
|
||||
}
|
||||
|
||||
void dSv_info_c::getSave(int i_stageNo) {
|
||||
JUT_ASSERT(4133, 0 <= i_stageNo && i_stageNo < dSv_save_c::STAGE_MAX);
|
||||
|
||||
+2
-2
@@ -2931,9 +2931,9 @@ int dStage_changeScene4Event(int i_exitId, s8 room_no, int i_wipe, bool param_3,
|
||||
if (timeH < 31) {
|
||||
#if TARGET_PC
|
||||
// If randomizer is active and we're loading the first spawn, set our starting time of day
|
||||
if (dComIfG_isRandomizer() && strcmp(scls_info->mStage, "F_SP103") == 0 &&
|
||||
if (randomizer_IsActive() && strcmp(scls_info->mStage, "F_SP103") == 0 &&
|
||||
scls_info->mRoom == 1 && scls_info->mStart == 1)
|
||||
timeH = dComIfG_getRandomizer().mStartHour;
|
||||
timeH = randomizer_GetContext().mStartHour;
|
||||
#endif
|
||||
dKy_set_nexttime(15.0f * timeH);
|
||||
}
|
||||
|
||||
@@ -239,6 +239,7 @@ namespace dusk {
|
||||
if (showMenu && ImGui::BeginMainMenuBar()) {
|
||||
m_menuGame.draw();
|
||||
m_menuEnhancements.draw();
|
||||
m_menuRandomizer.draw();
|
||||
m_menuTools.draw();
|
||||
|
||||
ImGui::SetCursorPosX(ImGui::GetWindowWidth() - 80.0f * ImGuiScale());
|
||||
@@ -276,6 +277,8 @@ namespace dusk {
|
||||
m_menuTools.ShowSaveEditor();
|
||||
}
|
||||
m_menuTools.ShowStateShare();
|
||||
m_menuRandomizer.windowRandoStats();
|
||||
m_menuRandomizer.windowRandoGeneration();
|
||||
DuskDebugPad(); // temporary, remove later
|
||||
|
||||
// Only show cursor when menu or any windows are open
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "ImGuiMenuEnhancements.hpp"
|
||||
#include "ImGuiMenuGame.hpp"
|
||||
#include "ImGuiMenuTools.hpp"
|
||||
#include "ImGuiMenuRandomizer.hpp"
|
||||
#include "ImGuiPreLaunchWindow.hpp"
|
||||
#include "imgui.h"
|
||||
|
||||
@@ -39,6 +40,7 @@ private:
|
||||
ImGuiFirstRunPreset m_firstRunPreset;
|
||||
ImGuiMenuGame m_menuGame;
|
||||
ImGuiMenuEnhancements m_menuEnhancements;
|
||||
ImGuiMenuRandomizer m_menuRandomizer;
|
||||
ImGuiPreLaunchWindow m_preLaunchWindow;
|
||||
|
||||
// Keep always last
|
||||
|
||||
@@ -0,0 +1,304 @@
|
||||
#include "imgui.h"
|
||||
|
||||
#include "ImGuiConsole.hpp"
|
||||
#include "ImGuiMenuRandomizer.hpp"
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include "dusk/app_info.hpp"
|
||||
#include "dusk/logging.h"
|
||||
#include "dusk/randomizer/game/randomizer_context.hpp"
|
||||
#include "dusk/randomizer/game/tools.h"
|
||||
#include "dusk/randomizer/generator/randomizer.hpp"
|
||||
|
||||
#include "SDL3/SDL_filesystem.h"
|
||||
|
||||
#include <thread>
|
||||
#include <filesystem>
|
||||
|
||||
namespace dusk {
|
||||
|
||||
static bool generatingSeed = false;
|
||||
static std::string generationStatusMsg{};
|
||||
static std::mutex generationStatusMsgMutex{};
|
||||
|
||||
void GenerateSeed() {
|
||||
std::lock_guard lock(generationStatusMsgMutex);
|
||||
const auto result = SDL_GetPrefPath(dusk::OrgName, dusk::AppName);
|
||||
if (!result) {
|
||||
DuskLog.fatal("Unable to get PrefPath: {}", SDL_GetError());
|
||||
}
|
||||
randomizer::Randomizer r;
|
||||
r.SetBaseOutputPath(result);
|
||||
auto generationResult = r.Generate();
|
||||
if (generationResult.has_value()) {
|
||||
generationStatusMsg = fmt::format("Generation failed with the following error:\n{}", generationResult.value());
|
||||
return;
|
||||
}
|
||||
|
||||
auto& world = r.GetWorlds()[0];
|
||||
|
||||
RandomizerContext randoData{};
|
||||
// Chest overrides
|
||||
for (const auto& location : world->GetAllLocations()) {
|
||||
const auto& metaData = location->GetMetadata();
|
||||
if (location->HasCategories("Chest")) {
|
||||
const auto& stage = metaData[0]["Stage"].as<std::string>();
|
||||
const auto& tboxId = metaData[0]["Tbox ID"].as<u8>();
|
||||
const auto& itemId = location->GetCurrentItem()->GetID();
|
||||
randoData.mTreasureChestOverrides[stage][tboxId] = itemId;
|
||||
}
|
||||
}
|
||||
|
||||
// Set starting inventory
|
||||
for (const auto& item: world->GetStartingItemPool()) {
|
||||
randoData.mStartingInventory.push_back(item->GetID());
|
||||
}
|
||||
|
||||
// Set starting flags
|
||||
auto startFlags = LoadYAML(RANDO_DATA_PATH "startflags.yaml");
|
||||
// Event Flags
|
||||
for (const auto& flagNode : startFlags["EventFlags"]) {
|
||||
if (flagNode.IsScalar()) {
|
||||
const auto& flag = flagNode.as<u16>();
|
||||
randoData.mStartEventFlags.push_back(flag);
|
||||
} else if (flagNode.IsMap()) {
|
||||
const auto& condition = flagNode.begin()->first.as<std::string>();
|
||||
if (world->EvaluateSettingCondition(condition)) {
|
||||
DuskLog.debug("Setting flags for {}", condition);
|
||||
for (const auto& conditionalFlag : flagNode.begin()->second) {
|
||||
const auto& flag = conditionalFlag.as<u16>();
|
||||
randoData.mStartEventFlags.push_back(flag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Region Flags
|
||||
for (const auto& regionNode : startFlags["RegionFlags"]) {
|
||||
const auto& region = regionNode.first.as<std::string>();
|
||||
const auto& index = regionNode.second["Index"].as<int>();
|
||||
const auto& flags = regionNode.second["Flags"];
|
||||
DuskLog.debug("Setting region flags for {}", region);
|
||||
// This seems kinda scuffed so maybe we change it later
|
||||
for (const auto& flagNode : flags) {
|
||||
if (flagNode.IsScalar()) {
|
||||
const auto& flag = flagNode.as<int>();
|
||||
randoData.mStartRegionFlags[index].push_back(flag);
|
||||
} else if (flagNode.IsMap()) {
|
||||
const auto& condition = flagNode.begin()->first.as<std::string>();
|
||||
if (world->EvaluateSettingCondition(condition)) {
|
||||
for (const auto& conditionalFlag : flagNode.begin()->second) {
|
||||
const auto& flag = conditionalFlag.as<int>();
|
||||
randoData.mStartRegionFlags[index].push_back(flag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (world->Setting("Unlock Map Regions") == "On")
|
||||
{
|
||||
auto& bits = randoData.mMapBits;
|
||||
bits = 0x20;
|
||||
if (world->Setting("Snowpeak Does Not Require Reekfish Scent") == "On") {bits |= 0x40;}
|
||||
if (world->Setting("Lanayru Twilight Cleared") == "On") {bits |= 0x10;}
|
||||
if (world->Setting("Eldin Twilight Cleared") == "On") {bits |= 0x08;}
|
||||
if (world->Setting("Faron Twilight Cleared") == "On") {bits |= 0x04;}
|
||||
if (world->Setting("Skip Prologue") == "On") {bits |= 0x02;}
|
||||
}
|
||||
|
||||
// Set starting time of day
|
||||
const auto startTimeSetting = world->Setting("Starting Time of Day");
|
||||
if (startTimeSetting == "Morning")
|
||||
randoData.mStartHour = 6;
|
||||
else if (startTimeSetting == "Noon")
|
||||
randoData.mStartHour = 12;
|
||||
else if (startTimeSetting == "Evening")
|
||||
randoData.mStartHour = 18;
|
||||
else if (startTimeSetting == "Night")
|
||||
randoData.mStartHour = 24;
|
||||
|
||||
randoData.mHash = r.GetConfig().GetHash();
|
||||
auto writeToFileResult = randoData.WriteToFile();
|
||||
if (writeToFileResult.has_value()) {
|
||||
generationStatusMsg =
|
||||
fmt::format("Failed to write seed data. Reason: {}", writeToFileResult.value());
|
||||
return;
|
||||
}
|
||||
|
||||
generationStatusMsg = fmt::format("Seed generated! Hash: {}", randoData.mHash);
|
||||
}
|
||||
|
||||
static void StartSeedGeneration() {
|
||||
if (generatingSeed) {
|
||||
return;
|
||||
}
|
||||
generatingSeed = true;
|
||||
GenerateSeed();
|
||||
generatingSeed = false;
|
||||
DuskLog.debug("{}", generationStatusMsg);
|
||||
}
|
||||
|
||||
ImGuiMenuRandomizer::ImGuiMenuRandomizer() {}
|
||||
|
||||
void ImGuiMenuRandomizer::draw() {
|
||||
if (ImGui::BeginMenu("Randomizer")) {
|
||||
if (ImGui::BeginMenu("Generate")) {
|
||||
if (ImGui::MenuItem("Generate Seed", nullptr, false, !generatingSeed)) {
|
||||
|
||||
std::thread randoGenerationThread(StartSeedGeneration);
|
||||
randoGenerationThread.detach();
|
||||
m_showRandoGeneration = true;
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
std::string loadSeedText = "Load Seed";
|
||||
if (!playerIsOnTitleScreen()) {
|
||||
loadSeedText += " (Must be on title screen)";
|
||||
}
|
||||
if (ImGui::BeginMenu(loadSeedText.c_str(), playerIsOnTitleScreen())) {
|
||||
|
||||
std::string seedDirectory =
|
||||
std::string(SDL_GetPrefPath(dusk::OrgName, dusk::AppName)) + "randomizer/seeds";
|
||||
|
||||
std::list<std::string> hashes{};
|
||||
|
||||
for (const auto& entry : std::filesystem::directory_iterator(seedDirectory)) {
|
||||
if (entry.is_directory()) {
|
||||
hashes.push_back(entry.path().filename().string());
|
||||
}
|
||||
}
|
||||
|
||||
if (hashes.empty()) {
|
||||
if (ImGui::MenuItem("No seeds generated")) {}
|
||||
}
|
||||
|
||||
for (const auto& hash : hashes) {
|
||||
std::string name = hash;
|
||||
if (randomizer_GetContext().mHash == hash) {
|
||||
name += " (Current Seed)";
|
||||
}
|
||||
if (ImGui::MenuItem(name.c_str())) {
|
||||
if (!randomizer_IsActive()) {
|
||||
randomizer_GetContext() = RandomizerContext();
|
||||
randomizer_GetContext().LoadFromHash(hash);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("Delete Seed")) {
|
||||
|
||||
std::string seedDirectory =
|
||||
std::string(SDL_GetPrefPath(dusk::OrgName, dusk::AppName)) + "randomizer/seeds";
|
||||
|
||||
std::list<std::string> hashes{};
|
||||
|
||||
for (const auto& entry : std::filesystem::directory_iterator(seedDirectory)) {
|
||||
if (entry.is_directory()) {
|
||||
hashes.push_back(entry.path().filename().string());
|
||||
}
|
||||
}
|
||||
|
||||
if (hashes.empty()) {
|
||||
if (ImGui::MenuItem("No seeds generated")) {}
|
||||
}
|
||||
|
||||
for (const auto& hash : hashes) {
|
||||
std::string name = hash;
|
||||
if (randomizer_GetContext().mHash == hash) {
|
||||
name += " (Current Seed)";
|
||||
}
|
||||
if (ImGui::MenuItem(name.c_str(), nullptr, false, playerIsOnTitleScreen() || randomizer_GetContext().mHash != hash)) {
|
||||
const std::string hashDirectory = seedDirectory + "/" + hash;
|
||||
if (randomizer_GetContext().mHash != hash) {
|
||||
std::filesystem::remove_all(hashDirectory);
|
||||
} else if (!randomizer_IsActive()){
|
||||
// If the user selected the currently seed, but it's not active, we'll allow the delete
|
||||
std::filesystem::remove_all(hashDirectory);
|
||||
randomizer_GetContext() = RandomizerContext();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
std::string name = "Deactive Randomizer";
|
||||
if (!playerIsOnTitleScreen()) {
|
||||
name += " (Must be on title screen)";
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem(name.c_str(), nullptr, false, playerIsOnTitleScreen())) {
|
||||
// Reset the main randomizer context only if we're not active
|
||||
if (!randomizer_IsActive()) {
|
||||
randomizer_GetContext() = RandomizerContext();
|
||||
}
|
||||
}
|
||||
ImGui::Checkbox("Show Rando Stats", &m_showRandoStats);
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
void ImGuiMenuRandomizer::windowRandoGeneration() {
|
||||
if (!m_showRandoGeneration) {
|
||||
return;
|
||||
}
|
||||
|
||||
ImGuiWindowFlags windowFlags =
|
||||
ImGuiWindowFlags_NoResize |
|
||||
ImGuiWindowFlags_AlwaysAutoResize;
|
||||
|
||||
ImGui::SetNextWindowBgAlpha(0.65f);
|
||||
|
||||
if (!ImGui::Begin("Randomizer Generation", &m_showRandoGeneration, windowFlags)) {
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
|
||||
// Print "Generating..." until the seed finishes generating (at which point it will release
|
||||
// the lock on the mutex)
|
||||
std::string generationText = "Generating Randomizer Seed...";
|
||||
if (generationStatusMsgMutex.try_lock()) {
|
||||
generationText = generationStatusMsg;
|
||||
generationStatusMsgMutex.unlock();
|
||||
}
|
||||
|
||||
ImGui::Text(generationText.c_str());
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void ImGuiMenuRandomizer::windowRandoStats() {
|
||||
if (!m_showRandoStats) {
|
||||
return;
|
||||
}
|
||||
|
||||
ImGuiWindowFlags windowFlags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize |
|
||||
ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav;
|
||||
|
||||
ImGui::SetNextWindowBgAlpha(0.65f);
|
||||
if (ImGui::Begin("Rando Stats", nullptr, windowFlags)) {
|
||||
|
||||
const char* seed = randomizer_GetContext().mHash.empty() ? "None" : randomizer_GetContext().mHash.c_str();
|
||||
|
||||
ImGui::Text("Current Seed: %s", seed);
|
||||
ImGui::Text("Status: ");
|
||||
ImGui::SameLine();
|
||||
if (randomizer_IsActive()) {
|
||||
ImGui::TextColored(ImVec4(0.f, 1.f, 0.f, 1.f), "ACTIVE");
|
||||
} else {
|
||||
ImGui::TextColored(ImVec4(1.f, 0.f, 0.f, 1.f), "NOT ACTIVE");
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
} // namespace dusk
|
||||
@@ -0,0 +1,21 @@
|
||||
|
||||
|
||||
#ifndef DUSK_IMGUI_MENU_RANDOMIZER_HPP
|
||||
#define DUSK_IMGUI_MENU_RANDOMIZER_HPP
|
||||
|
||||
namespace dusk {
|
||||
class ImGuiMenuRandomizer {
|
||||
public:
|
||||
ImGuiMenuRandomizer();
|
||||
void draw();
|
||||
|
||||
void windowRandoStats();
|
||||
void windowRandoGeneration();
|
||||
|
||||
private:
|
||||
bool m_showRandoStats{false};
|
||||
bool m_showRandoGeneration{false};
|
||||
};
|
||||
}
|
||||
|
||||
#endif //DUSK_IMGUI_MENU_RANDOMIZER_HPP
|
||||
@@ -0,0 +1,109 @@
|
||||
#include "randomizer_context.hpp"
|
||||
|
||||
#include "../generator/utility/yaml.hpp"
|
||||
|
||||
#include "dusk/app_info.hpp"
|
||||
#include "dusk/logging.h"
|
||||
#include "dusk/main.h"
|
||||
#include "dusk/randomizer/game/tools.h"
|
||||
|
||||
#include "SDL3/SDL_filesystem.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
RandomizerContext& randomizer_GetContext() {
|
||||
static RandomizerContext instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
bool randomizer_IsActive() {
|
||||
return dusk::IsGameLaunched && (!playerIsOnTitleScreen() || randomizer_GetContext().mCreatingSave) && randomizer_GetContext().mActive;
|
||||
}
|
||||
|
||||
std::optional<std::string> RandomizerContext::WriteToFile() {
|
||||
|
||||
std::ofstream seedData(this->GetSeedDataPath());
|
||||
if (!seedData.is_open()) {
|
||||
return "Could not open seed data file";
|
||||
}
|
||||
|
||||
YAML::Node out{};
|
||||
|
||||
// NOTE: When dumping u8s, they must be converted to u16s (or higher), otherwise they get dumped
|
||||
// as single characters and not numbers
|
||||
|
||||
out["mStartEventFlags"] = this->mStartEventFlags;
|
||||
for (const auto& [region, flags] : this->mStartRegionFlags) {
|
||||
const std::list<u16> u16Flags(flags.begin(), flags.end());
|
||||
out["mStartRegionFlags"][static_cast<u16>(region)] = u16Flags;
|
||||
}
|
||||
|
||||
const std::list<u16> u16Inventory(this->mStartingInventory.begin(), this->mStartingInventory.end());
|
||||
out["mStartingInventory"] = u16Inventory;
|
||||
|
||||
for (const auto& [stageName, chestOverride] : this->mTreasureChestOverrides) {
|
||||
for (const auto& [tboxId, itemId] : chestOverride) {
|
||||
out["mTreasureChestOverrides"][stageName][static_cast<u16>(tboxId)] = static_cast<u16>(itemId);
|
||||
}
|
||||
}
|
||||
|
||||
out["mStartHour"] = static_cast<u16>(this->mStartHour);
|
||||
out["mMapBits"] = static_cast<u16>(this->mMapBits);
|
||||
|
||||
seedData << YAML::Dump(out);
|
||||
seedData.close();
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::string> RandomizerContext::LoadFromHash(const std::string& hash) {
|
||||
this->mHash = hash;
|
||||
|
||||
auto in = LoadYAML(this->GetSeedDataPath());
|
||||
|
||||
// Event flags
|
||||
for (const auto& flag : in["mStartEventFlags"]) {
|
||||
this->mStartEventFlags.push_back(flag.as<u16>());
|
||||
}
|
||||
// Region Flags
|
||||
for (const auto& regionNode : in["mStartRegionFlags"]) {
|
||||
const auto& regionId = regionNode.first.as<u8>();
|
||||
for (const auto& flag : regionNode.second) {
|
||||
this->mStartRegionFlags[regionId].push_back(flag.as<u8>());
|
||||
}
|
||||
}
|
||||
|
||||
// Starting inventory
|
||||
for (const auto& itemId : in["mStartingInventory"]) {
|
||||
this->mStartingInventory.push_back(itemId.as<u8>());
|
||||
}
|
||||
|
||||
// Chest overrides
|
||||
for (const auto& stageNode : in["mTreasureChestOverrides"]) {
|
||||
const auto& stageName = stageNode.first.as<std::string>();
|
||||
// Single nodes with a zero in their key will get dumped as sequences
|
||||
if (stageNode.second.IsSequence()) {
|
||||
this->mTreasureChestOverrides[stageName][0] = stageNode.second[0].as<u8>();
|
||||
} else {
|
||||
for (const auto& chestItemPair : stageNode.second) {
|
||||
auto tboxId = chestItemPair.first.as<u8>();
|
||||
auto itemId = chestItemPair.second.as<u8>();
|
||||
this->mTreasureChestOverrides[stageName][tboxId] = itemId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Starting hour
|
||||
this->mStartHour = in["mStartHour"].as<u8>();
|
||||
// Starting map bits
|
||||
this->mMapBits = in["mMapBits"].as<u8>();
|
||||
|
||||
DuskLog.debug("Loaded Randomizer Seed {}", this->mHash);
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::string RandomizerContext::GetSeedDataPath() const {
|
||||
return std::string(SDL_GetPrefPath(dusk::OrgName, dusk::AppName)) + "randomizer/seeds/" + this->mHash + "/seed.dat";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
#ifndef DUSK_RANDOMIZER_CONTEXT_HPP
|
||||
#define DUSK_RANDOMIZER_CONTEXT_HPP
|
||||
|
||||
#include <dolphin/types.h>
|
||||
#include <optional>
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
class RandomizerContext {
|
||||
public:
|
||||
RandomizerContext() = default;
|
||||
|
||||
bool mActive{false};
|
||||
bool mCreatingSave{false};
|
||||
u32 mSeedID{0};
|
||||
std::string mHash{""};
|
||||
|
||||
std::list<u16> mStartEventFlags{};
|
||||
std::unordered_map<u8, std::list<u8>> mStartRegionFlags{};
|
||||
std::list<u8> mStartingInventory{};
|
||||
std::unordered_map<std::string, std::unordered_map<u8, u8>> mTreasureChestOverrides{};
|
||||
std::unordered_map<std::string, std::unordered_map<u8, u8>> mPoeOverrides{};
|
||||
u8 mStartHour{0};
|
||||
u8 mMapBits{};
|
||||
|
||||
std::optional<std::string> WriteToFile();
|
||||
std::optional<std::string> LoadFromHash(const std::string& hash);
|
||||
std::string GetSeedDataPath() const;
|
||||
};
|
||||
|
||||
RandomizerContext& randomizer_GetContext();
|
||||
|
||||
bool randomizer_IsActive();
|
||||
|
||||
#endif //DUSK_RANDOMIZER_CONTEXT_HPP
|
||||
@@ -106,4 +106,10 @@ int getStageID(const char* stage)
|
||||
}
|
||||
// Didn't find the current stage for some reason
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool playerIsOnTitleScreen() {
|
||||
// Player is either on title screen movie stage (S_MV000) or on title screen map layer 10
|
||||
return strcmp(dComIfGp_getStartStageName(), "S_MV000") == 0 ||
|
||||
(strcmp(dComIfGp_getStartStageName(), "F_SP102") == 0 && dComIfG_play_c::getLayerNo(0) == 10);
|
||||
}
|
||||
@@ -8,3 +8,4 @@ u8 setNextWarashibeItem();
|
||||
void offWarashibeItem(u8 item);
|
||||
int initCreatePlayerItem(u32 item, u32 flag, const cXyz* pos, int roomNo, const csXyz* angle, const cXyz* scale);
|
||||
int getStageID(const char* stage);
|
||||
bool playerIsOnTitleScreen();
|
||||
|
||||
@@ -45,20 +45,20 @@ namespace randomizer::logic::spoiler_log
|
||||
log << YAML::Dump(randomizer->GetConfig().SettingsToYaml()) << std::endl;
|
||||
}
|
||||
|
||||
void GenerateSpoilerLog(randomizer::Randomizer* randomizer)
|
||||
void GenerateSpoilerLog(Randomizer* randomizer)
|
||||
{
|
||||
randomizer::utility::platform::Log("Generating Spoiler Log");
|
||||
utility::platform::Log("Generating Spoiler Log");
|
||||
|
||||
// Create logs folder if it doesn't exist
|
||||
if (!randomizer::utility::file::dirExists(LOGS_PATH))
|
||||
// Create folders
|
||||
if (!utility::file::dirExists(randomizer->GetSeedOutputPath()))
|
||||
{
|
||||
randomizer::utility::file::create_directories(LOGS_PATH);
|
||||
utility::file::create_directories(randomizer->GetSeedOutputPath());
|
||||
}
|
||||
|
||||
auto& config = randomizer->GetConfig();
|
||||
auto& worlds = randomizer->GetWorlds();
|
||||
|
||||
std::string filepath = std::string(LOGS_PATH) + config.GetHash() + " Spoiler Log.txt";
|
||||
std::string filepath = std::string(randomizer->GetSeedOutputPath()) + config.GetHash() + " Spoiler Log.txt";
|
||||
std::ofstream spoilerLog;
|
||||
spoilerLog.open(filepath);
|
||||
|
||||
@@ -228,18 +228,18 @@ namespace randomizer::logic::spoiler_log
|
||||
|
||||
spoilerLog.close();
|
||||
|
||||
randomizer::utility::platform::Log("Wrote spoiler log to " + filepath);
|
||||
utility::platform::Log("Wrote spoiler log to " + filepath);
|
||||
}
|
||||
|
||||
void GenerateAntiSpoilerLog(randomizer::Randomizer* randomizer)
|
||||
void GenerateAntiSpoilerLog(Randomizer* randomizer)
|
||||
{
|
||||
// Create logs folder if it doesn't exist
|
||||
if (!randomizer::utility::file::dirExists(LOGS_PATH))
|
||||
if (!utility::file::dirExists(randomizer->GetSeedOutputPath()))
|
||||
{
|
||||
randomizer::utility::file::create_directories(LOGS_PATH);
|
||||
utility::file::create_directories(randomizer->GetSeedOutputPath());
|
||||
}
|
||||
|
||||
std::string filepath = std::string(LOGS_PATH) + randomizer->GetConfig().GetHash() + " Anti-Spoiler Log.txt";
|
||||
std::string filepath = std::string(randomizer->GetSeedOutputPath()) + randomizer->GetConfig().GetHash() + " Anti-Spoiler Log.txt";
|
||||
std::ofstream antiSpoilerLog;
|
||||
antiSpoilerLog.open(filepath);
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
namespace randomizer
|
||||
{
|
||||
int Randomizer::Generate()
|
||||
std::optional<std::string> Randomizer::Generate()
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -25,17 +25,17 @@ namespace randomizer
|
||||
{
|
||||
std::cout << "============================================================" << std::endl;
|
||||
std::cout << "The following exception occured: " << e.what() << std::endl;
|
||||
return 1;
|
||||
return e.what();
|
||||
}
|
||||
|
||||
return 0;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void Randomizer::GenerateWorlds()
|
||||
{
|
||||
utility::time::ScopedTimer<"Seed generation took ", std::chrono::milliseconds> timer;
|
||||
this->_worlds.clear();
|
||||
this->_config.LoadFromFile(SETTINGS_PATH, PREFERENCES_PATH);
|
||||
this->_config.LoadFromFile(this->GetBaseOutputPath() + "settings.yaml", this->GetBaseOutputPath() + "preferences.yaml");
|
||||
|
||||
utility::platform::Log(std::string("Seed: ") + this->_config.GetSeed());
|
||||
|
||||
@@ -111,4 +111,9 @@ namespace randomizer
|
||||
}
|
||||
logic::spoiler_log::GenerateAntiSpoilerLog(this);
|
||||
}
|
||||
|
||||
std::string Randomizer::GetSeedOutputPath()
|
||||
{
|
||||
return this->_baseOutputPath + "seeds/" + this->_config.GetHash() + "/";
|
||||
}
|
||||
} // namespace randomizer
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include "logic/world.hpp"
|
||||
|
||||
#include <optional>
|
||||
|
||||
namespace randomizer
|
||||
{
|
||||
class Randomizer
|
||||
@@ -12,9 +14,9 @@ namespace randomizer
|
||||
/**
|
||||
* @brief Generates a complete randomizer seed
|
||||
*
|
||||
* @return 0 if no errors. 1 if there were errors
|
||||
* @return a std::optional<std::string> containing a message if there was an error.
|
||||
*/
|
||||
int Generate();
|
||||
std::optional<std::string> Generate();
|
||||
void GenerateWorlds();
|
||||
|
||||
auto& GetConfig() { return this->_config; }
|
||||
@@ -26,6 +28,10 @@ namespace randomizer
|
||||
|
||||
auto& GetPlaythroughSpheres() { return this->_playthroughSpheres; }
|
||||
auto& GetEntranceSpheres() { return this->_entranceSpheres; }
|
||||
|
||||
std::string GetSeedOutputPath();
|
||||
const std::string& GetBaseOutputPath() const { return this->_baseOutputPath; };
|
||||
void SetBaseOutputPath(const std::string& path) { this->_baseOutputPath = path + "randomizer/"; };
|
||||
private:
|
||||
seedgen::config::Config _config{};
|
||||
logic::world::WorldPool _worlds{};
|
||||
@@ -37,5 +43,7 @@ namespace randomizer
|
||||
// Playthrough data
|
||||
std::list<std::list<logic::location::Location*>> _playthroughSpheres{};
|
||||
std::list<std::list<logic::entrance::Entrance*>> _entranceSpheres{};
|
||||
|
||||
std::string _baseOutputPath{RANDO_SAVE_PATH};
|
||||
};
|
||||
} // namespace randomizer
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace randomizer::seedgen::config
|
||||
// If the option doesn't exist, revert to default and rewrite later if necessary
|
||||
if (settingInfo->GetIndexOfOption(settingOption) == -1)
|
||||
{
|
||||
randomizer::utility::platform::Log(std::string("Setting \"") + settingName + "\" has no option \"" +
|
||||
utility::platform::Log(std::string("Setting \"") + settingName + "\" has no option \"" +
|
||||
settingOption + "\". Reverting to default \"" +
|
||||
settingInfo->GetDefaultOption() + "\"");
|
||||
settingOption = settingInfo->GetDefaultOption();
|
||||
@@ -148,7 +148,7 @@ namespace randomizer::seedgen::config
|
||||
// If the option doesn't exist, revert to default and rewrite later if necessary
|
||||
if (preferenceInfo->GetIndexOfOption(preferenceOption) == -1)
|
||||
{
|
||||
randomizer::utility::platform::Log(std::string("Preference \"") + preferenceName + " has no option \"" +
|
||||
utility::platform::Log(std::string("Preference \"") + preferenceName + " has no option \"" +
|
||||
preferenceOption + "\". Reverting to default \"" +
|
||||
preferenceInfo->GetDefaultOption() + "\"");
|
||||
preferenceOption = preferenceInfo->GetDefaultOption();
|
||||
@@ -182,7 +182,7 @@ namespace randomizer::seedgen::config
|
||||
{
|
||||
settings.InsertSetting(settingName,
|
||||
settings::Setting(settingInfo.get(), settingInfo->GetDefaultOption()));
|
||||
randomizer::utility::platform::Log(std::string("Added missing setting \"") + settingName + "\"");
|
||||
utility::platform::Log(std::string("Added missing setting \"") + settingName + "\"");
|
||||
if (settingInfo->GetType() == settings::Type::STANDARD)
|
||||
{
|
||||
rewriteSettings = true;
|
||||
@@ -196,7 +196,7 @@ namespace randomizer::seedgen::config
|
||||
if (!settingsTree["Seed"])
|
||||
{
|
||||
this->_seed = seed::GenerateSeed();
|
||||
randomizer::utility::platform::Log("Seed is missing. Generated new seed.");
|
||||
utility::platform::Log("Seed is missing. Generated new seed.");
|
||||
rewriteSettings = true;
|
||||
}
|
||||
if (!settingsTree["Plandomizer"] || !settingsTree["Generate Spoiler Log"] || !settingsTree["Starting Inventory"] ||
|
||||
@@ -212,12 +212,12 @@ namespace randomizer::seedgen::config
|
||||
// Rewrite files if deemed necessary
|
||||
if (allowRewrite && rewriteSettings)
|
||||
{
|
||||
randomizer::utility::platform::Log(std::string("Rewriting ") + settingsPath.generic_string());
|
||||
utility::platform::Log(std::string("Rewriting ") + settingsPath.generic_string());
|
||||
this->WriteSettingsToFile(settingsPath);
|
||||
}
|
||||
if (allowRewrite && rewritePreferences)
|
||||
{
|
||||
randomizer::utility::platform::Log(std::string("Rewriting ") + preferencesPath.generic_string());
|
||||
utility::platform::Log(std::string("Rewriting ") + preferencesPath.generic_string());
|
||||
this->WritePreferencesToFile(preferencesPath);
|
||||
}
|
||||
}
|
||||
@@ -335,7 +335,7 @@ namespace randomizer::seedgen::config
|
||||
|
||||
int WriteDefaultSettings(const fspath& settingsPath)
|
||||
{
|
||||
randomizer::utility::platform::Log("Creating Default Settings");
|
||||
utility::platform::Log("Creating Default Settings");
|
||||
std::ofstream settingsFile(settingsPath);
|
||||
if (settingsFile.is_open() == false)
|
||||
{
|
||||
@@ -369,7 +369,7 @@ namespace randomizer::seedgen::config
|
||||
|
||||
int WriteDefaultPreferences(const fspath& preferencesPath)
|
||||
{
|
||||
randomizer::utility::platform::Log("Creating Default Preferences");
|
||||
utility::platform::Log("Creating Default Preferences");
|
||||
std::ofstream preferencesFile(preferencesPath);
|
||||
if (preferencesFile.is_open() == false)
|
||||
{
|
||||
@@ -402,7 +402,7 @@ namespace randomizer::seedgen::config
|
||||
{
|
||||
// Seed with system time incase we have to choose random preferences during seeding
|
||||
auto seed = static_cast<uint32_t>(std::random_device {}());
|
||||
randomizer::utility::random::RandomInit(seed);
|
||||
utility::random::RandomInit(seed);
|
||||
|
||||
// Seed the rng using a combination of the seed and standard settings
|
||||
std::string hashStr = config.GetSeed();
|
||||
@@ -444,7 +444,7 @@ namespace randomizer::seedgen::config
|
||||
if (config.IsUsingPlandomizer())
|
||||
{
|
||||
std::string plandomizerContents;
|
||||
auto retVal = randomizer::utility::file::GetContents(config.GetPlandomizerPath(), plandomizerContents);
|
||||
auto retVal = utility::file::GetContents(config.GetPlandomizerPath(), plandomizerContents);
|
||||
if (!ignoreInvalidPlandomizer && retVal != 0)
|
||||
{
|
||||
LOG_TO_ERROR("Could not read plandomizer file at \"" + config.GetPlandomizerPath().generic_string() + "\"");
|
||||
@@ -460,7 +460,7 @@ namespace randomizer::seedgen::config
|
||||
}
|
||||
|
||||
const size_t integerSeed = zng_crc32(0L, reinterpret_cast<const uint8_t*>(hashStr.data()), hashStr.length());
|
||||
randomizer::utility::random::RandomInit(integerSeed);
|
||||
utility::random::RandomInit(integerSeed);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
set(RANDOMIZER_ONLY "0" CACHE STRING "Runs only the randomizer generator")
|
||||
set(RANDO_SAVE_PATH "${CMAKE_BINARY_DIR}/randomizer")
|
||||
set(RANDO_SAVE_PATH "${CMAKE_BINARY_DIR}/randomizer/")
|
||||
|
||||
set(GAME_COMPILE_DEFS ${GAME_COMPILE_DEFS}
|
||||
RANDOMIZER_ONLY=${RANDOMIZER_ONLY}
|
||||
RANDO_SAVE_PATH="${RANDO_SAVE_PATH}"
|
||||
LOGS_PATH="${RANDO_SAVE_PATH}/logs/"
|
||||
RANDO_SAVE_PATH="${RANDO_SAVE_PATH}"
|
||||
RANDO_DATA_PATH="${CMAKE_SOURCE_DIR}/src/dusk/randomizer/generator/data/")
|
||||
|
||||
if(RANDO_ERROR_LOG)
|
||||
|
||||
@@ -1395,7 +1395,7 @@ fpc_ProcID fopAcM_createItemForPresentDemo(cXyz const* i_pos, int i_itemNo, u8 p
|
||||
int i_itemBitNo, int i_roomNo, csXyz const* i_angle,
|
||||
cXyz const* i_scale) {
|
||||
#if TARGET_PC
|
||||
if (dComIfG_isRandomizer()) {
|
||||
if (randomizer_IsActive()) {
|
||||
i_itemNo = verifyProgressiveItem(i_itemNo);
|
||||
}
|
||||
#endif
|
||||
@@ -1624,7 +1624,7 @@ fpc_ProcID fopAcM_createItemForBoss(const cXyz* i_pos, int i_itemNo, int i_roomN
|
||||
return fpcM_ERROR_PROCESS_ID_e;
|
||||
}
|
||||
|
||||
if (dComIfG_isRandomizer()) {
|
||||
if (randomizer_IsActive()) {
|
||||
i_itemNo = verifyProgressiveItem(i_itemNo);
|
||||
if (i_itemNo == dItemNo_Randomizer_UTAWA_HEART_e)
|
||||
{
|
||||
@@ -1665,7 +1665,7 @@ fpc_ProcID fopAcM_createItemForMidBoss(const cXyz* i_pos, int i_itemNo, int i_ro
|
||||
}
|
||||
|
||||
// If we are fighting Ook in randomizer, we want to handle the boomerang check a different way.
|
||||
if (dComIfG_isRandomizer()) {
|
||||
if (randomizer_IsActive()) {
|
||||
if (daAlink_c::checkStageName("D_MN05B")) {
|
||||
i_itemNo = verifyProgressiveItem(i_itemNo);
|
||||
return initCreatePlayerItem(i_itemNo, 0xFF, i_pos, i_roomNo, i_angle, i_scale);
|
||||
|
||||
Reference in New Issue
Block a user