Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/macro_presets.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ struct MacroPreset {
/*0x06*/ s16 param;
};

extern struct MacroPreset MacroObjectPresets[] = {
struct MacroPreset MacroObjectPresets[] = {
{bhvYellowCoin, MODEL_YELLOW_COIN, 0},
{bhvOneCoin, MODEL_YELLOW_COIN, 0},
{bhvMovingBlueCoin, MODEL_BLUE_COIN, 0},
Expand Down
10 changes: 6 additions & 4 deletions src/game/save_file.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,11 @@ struct RandoSaveCheck {
struct RandoSaveEntrance {
RandoEntranceId randoEntranceId;
int16_t destinationId;
RandoEntranceType randoEntranceType;
WarpNodes deathWarpId;
int16_t deathArea;
};

struct RandoSaveOption {
const char* randoOptionName;
int32_t randoOptionValue;
};

typedef enum {
Expand All @@ -42,8 +44,8 @@ typedef enum {
struct RandoSaveData {
struct RandoSaveCheck randoSaveChecks[RC_MAX];
struct RandoSaveEntrance randoSaveEntrances[RE_MAX];
u32 randoSaveOptions[RO_MAX];
u32 finalSeed;
// u32 randoSaveOptions[RO_MAX];
};

struct ShipSaveData {
Expand Down
23 changes: 21 additions & 2 deletions src/port/Rando/GhostshipMenuRando.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,20 @@ void GhostshipMenu::AddMenuRando() {
.PreFunc([](WidgetInfo& info) {
info.options->Disabled(CVarGetInteger(CVAR_RANDOMIZER_SETTING("ManualSeedEntry"), 0));
});
AddWidget(path, "Available Spoiler Logs", WIDGET_CUSTOM).CustomFunction([](WidgetInfo& info) {
ImGui::BeginDisabled(!CVarGetInteger(CVAR_RANDOMIZER_SETTING("UseExistingLog"), 0));
if (UIWidgets::CVarCombobox("Seed", CVAR_RANDOMIZER_SETTING("SpoilerFileIndex"), Rando::Spoiler::spoilerLogs)) {
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("SpoilerFileIndex"), 0) == 0) {
CVarSetString(CVAR_RANDOMIZER_SETTING("SpoilerFile"), "");
} else {
CVarSetString(
"gRandoSettings.SpoilerFile",
Rando::Spoiler::spoilerLogs[CVarGetInteger(CVAR_RANDOMIZER_SETTING("SpoilerFileIndex"), 0)]
.c_str());
}
}
ImGui::EndDisabled();
});
AddWidget(path, "Manual Seed Entry", WIDGET_CVAR_CHECKBOX)
.CVar(CVAR_RANDOMIZER_SETTING("ManualSeedEntry"))
.RaceDisable(false)
Expand Down Expand Up @@ -76,7 +90,8 @@ void GhostshipMenu::AddMenuRando() {
});
AddWidget(path, "Create Spoiler Log", WIDGET_BUTTON)
.Callback([](WidgetInfo& info) {
nlohmann::json spoiler = Rando::Spoiler::GenerateFromPoolGeneration(Rando::Logic::shuffledPool);
nlohmann::json spoiler =
Rando::Spoiler::GenerateFromPoolGeneration(Rando::Logic::shuffledPool, Rando::Logic::shuffledEntrances);
std::string fileName = std::to_string(spoiler["finalSeed"].get<u32>()).c_str();
fileName += ".json";
Rando::Spoiler::SaveToFile(fileName, spoiler);
Expand Down Expand Up @@ -128,7 +143,11 @@ void GhostshipMenu::AddMenuRando() {
AddWidget(path, "Shuffle Bowser Levels", WIDGET_CVAR_CHECKBOX)
.CVar(Rando::StaticData::Options[RO_SHUFFLE_ENTRANCES_BOWSER].cvar)
.RaceDisable(false)
.Options(CheckboxOptions().Tooltip("Shuffles Bowser Entrances."));
.Options(CheckboxOptions().Tooltip("Shuffles Bowser in the Dark World and Fire Sea Entrances."));
AddWidget(path, "Shuffle Bowser in the Sky Level", WIDGET_CVAR_CHECKBOX)
.CVar(Rando::StaticData::Options[RO_SHUFFLE_ENTRANCES_BOWSER_FINAL].cvar)
.RaceDisable(false)
.Options(CheckboxOptions().Tooltip("Shuffles Bowser in the Sky Entrance."));
AddWidget(path, "Shuffle Cap Unlock Levels", WIDGET_CVAR_CHECKBOX)
.CVar(Rando::StaticData::Options[RO_SHUFFLE_ENTRANCES_CAP].cvar)
.RaceDisable(false)
Expand Down
18 changes: 13 additions & 5 deletions src/port/Rando/Logic/GeneratePools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,17 @@ void InitializeSaveChecks() {
void InitializeSaveEntrances() {
for (auto& [randoEntranceId, randoStaticEntrance] : Rando::StaticData::Entrances) {
RandoSaveEntrance randoSaveEntrance = { .randoEntranceId = randoEntranceId,
.destinationId = randoStaticEntrance.destinationId,
.randoEntranceType = randoStaticEntrance.randoEntranceType,
.deathWarpId = randoStaticEntrance.deathWarpId,
.deathArea = randoStaticEntrance.deathArea };
.destinationId = randoStaticEntrance.destinationId };
RANDO_SAVE_ENTRANCES(selectedFileNum)[randoEntranceId] = randoSaveEntrance;
}
}

void InitializeSaveOptions() {
for (auto& [randoOptionId, optionData] : Rando::StaticData::Options) {
RANDO_SAVE_OPTIONS(selectedFileNum)[randoOptionId] = optionData.defaultValue;
}
}

void GenerateShuffleList() {
shuffledPool.clear();
shuffledEntrances.clear();
Expand Down Expand Up @@ -146,6 +149,11 @@ void GenerateShuffleList() {
continue;
}

if (randoStaticEntrance.randoEntranceType == RETYPE_BOWSER_FINAL &&
CVarGetInteger(Rando::StaticData::Options[RO_SHUFFLE_ENTRANCES_BOWSER_FINAL].cvar, 0) == RO_GENERIC_OFF) {
continue;
}

if (randoStaticEntrance.randoEntranceType == RETYPE_CAP &&
CVarGetInteger(Rando::StaticData::Options[RO_SHUFFLE_ENTRANCES_CAP].cvar, 0) == RO_GENERIC_OFF) {
continue;
Expand Down Expand Up @@ -176,7 +184,7 @@ void GenerateShuffleList() {
gSaveBuffer.files[selectedFileNum][0].shipSaveData.randoSaveData.finalSeed = finalSeed;

if (CVarGetInteger("gRandoSettings.GenerateLog", 0)) {
nlohmann::json spoilerLog = Rando::Spoiler::GenerateFromPoolGeneration(shuffledPool);
nlohmann::json spoilerLog = Rando::Spoiler::GenerateFromPoolGeneration(shuffledPool, shuffledEntrances);
if (spoilerLog.empty()) {
Notification::Emit(
{ .message = "Error: No Spoiler Log was created.", .messageColor = ImVec4(0.85f, 0.3f, 0, 1) });
Expand Down
1 change: 1 addition & 0 deletions src/port/Rando/Logic/Logic.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ void ShuffleRandoItems(std::vector<std::pair<RandoItemId, RandoAct>>& shuffledIt
void ShuffleRandoEntrances(std::vector<int16_t>& shuffledLevels, const std::string& input);
void InitializeSaveChecks();
void InitializeSaveEntrances();
void InitializeSaveOptions();
void GenerateShuffleList();

void ApplyNoLogicToSaveContext(std::vector<std::vector<LevelShuffleEntry>>& initialPool,
Expand Down
3 changes: 0 additions & 3 deletions src/port/Rando/Logic/NoLogic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,6 @@ void ApplyNoLogicToSaveContext(std::vector<std::vector<LevelShuffleEntry>>& init
RandoSaveEntrance randoSaveEntrance;
randoSaveEntrance.randoEntranceId = entranceIds[e];
randoSaveEntrance.destinationId = initialLevelPool[e];
randoSaveEntrance.randoEntranceType =
Rando::StaticData::Entrances[randoSaveEntrance.randoEntranceId].randoEntranceType;
randoSaveEntrance.deathWarpId = Rando::StaticData::Entrances[randoSaveEntrance.randoEntranceId].deathWarpId;
entrancePool.push_back(randoSaveEntrance);
}
}
Expand Down
23 changes: 16 additions & 7 deletions src/port/Rando/MiscBehavior/OnFileLoad.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ extern "C" {
extern struct SaveBuffer gSaveBuffer;
}

bool SpoilerExistsForFileNum(std::string fileName) {
bool SpoilerExistsForFileName(std::string fileName) {
nlohmann::json spoilerCheck = Rando::Spoiler::LoadFromFile(fileName);
if (spoilerCheck.empty()) {
Notification::Emit({ .message = "Error: No Spoiler Log found.", .messageColor = ImVec4(0.85f, 0.3f, 0, 1) });
Expand All @@ -22,6 +22,8 @@ void Rando::MiscBehavior::OnFileLoad() {
OnGameFileLoad* ev = (OnGameFileLoad*)event;
selectedFileNum = ev->fileNum - 1;

bool loadedFromSpoiler = false;

if (!CVarGetInteger("gRandoSettings.Enabled", 0)) {
gSaveBuffer.files[selectedFileNum]->shipSaveData.saveType = SAVETYPE_VANILLA;
Rando::Logic::shuffledPool.clear();
Expand All @@ -32,17 +34,20 @@ void Rando::MiscBehavior::OnFileLoad() {
gSaveBuffer.files[selectedFileNum]->shipSaveData.saveType = SAVETYPE_RANDO;
Rando::Logic::InitializeSaveChecks();
Rando::Logic::InitializeSaveEntrances();
Rando::Logic::InitializeSaveOptions();

if (CVarGetInteger("gRandoSettings.ManualSeedEntry", 0)) {
Rando::Logic::GenerateShuffleList();
} else if (CVarGetInteger("gRandoSettings.UseExistingLog", 0)) {
std::string fileName = std::to_string(selectedFileNum) + ".json";
bool logExists = SpoilerExistsForFileNum(fileName);
std::string fileName =
Rando::Spoiler::spoilerLogs.at(CVarGetInteger("gRandoSettings.SpoilerFileIndex", 0));
bool logExists = SpoilerExistsForFileName(fileName);
if (!logExists) {
Rando::Logic::GenerateShuffleList();
} else {
nlohmann::json loadedSpoiler = Rando::Spoiler::LoadFromFile(fileName);
Rando::Logic::shuffledPool = Rando::Spoiler::GenerateFromSpoilerLog(loadedSpoiler);
Rando::Spoiler::GenerateFromSpoiler(loadedSpoiler);
loadedFromSpoiler = true;
}
} else {
Rando::Logic::GenerateShuffleList();
Expand All @@ -63,14 +68,18 @@ void Rando::MiscBehavior::OnFileLoad() {
RandoSaveEntrance randoSaveEntrance;
randoSaveEntrance.randoEntranceId = entrance.randoEntranceId;
randoSaveEntrance.destinationId = entrance.destinationId;
randoSaveEntrance.randoEntranceType = entrance.randoEntranceType;
randoSaveEntrance.deathWarpId = entrance.deathWarpId;
randoSaveEntrance.deathArea = entrance.deathArea;

RANDO_SAVE_ENTRANCES(selectedFileNum)[entrance.randoEntranceId] = randoSaveEntrance;
}
}

if (!loadedFromSpoiler) {
for (auto& [randoOptionId, optionData] : Rando::StaticData::Options) {
RANDO_SAVE_OPTIONS(selectedFileNum)
[randoOptionId] = CVarGetInteger(optionData.cvar, optionData.defaultValue);
}
}

Notification::Emit(
{ .message = "Spoiler written to Save File.", .messageColor = ImVec4(0, 0.85f, 0.3f, 1) });
save_file_do_save(selectedFileNum);
Expand Down
3 changes: 2 additions & 1 deletion src/port/Rando/Rando.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "ObjectBehavior/ObjectBehavior.h"
#include "MiscBehavior/MiscBehavior.h"
#include "port/Rando/CheckTracker/CheckTracker.h"
#include "port/Rando/Spoiler/Spoiler.h"
#include "port/ShipInit.hpp"

#include <fstream>
Expand All @@ -18,7 +19,7 @@ void Rando::Init() {
fs::create_directory(dir);
}

// Rando::Spoiler::RefreshOptions();
Rando::Spoiler::RefreshSpoilerLogs();
Rando::MiscBehavior::Init();
Rando::ObjectBehavior::Init();
Rando::CheckTracker::Init();
Expand Down
2 changes: 0 additions & 2 deletions src/port/Rando/Spoiler/File.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
#include "Spoiler.h"
#include "port/ui/Notification.h"
#include <fstream>
#include <filesystem>

const std::string appShortName = "sm64";
namespace fs = std::filesystem;

namespace Rando {
Expand Down
74 changes: 54 additions & 20 deletions src/port/Rando/Spoiler/Generate.cpp
Original file line number Diff line number Diff line change
@@ -1,28 +1,25 @@
#include "Spoiler.h"
#include "port/Rando/Logic/Logic.h"
#include "port/Rando/Rando.h"
#include "port/ui/Notification.h"

namespace Rando {

namespace Spoiler {

nlohmann::json GenerateFromPoolGeneration(std::vector<LevelShuffleEntry>& shuffledPool) {
nlohmann::json GenerateFromPoolGeneration(std::vector<LevelShuffleEntry>& shuffledPool,
std::vector<RandoSaveEntrance>& shuffledEntrances) {
nlohmann::json spoiler;
spoiler["type"] = "GHOSTSHIP_RANDO_SPOILER";
spoiler["fileNum"] = std::to_string(selectedFileNum);
if (CVarGetInteger("gRandoSettings.ManualSeedEntry", 0)) {
spoiler["seed"] = seedString;
} else {
spoiler["seed"] = "";
}
spoiler["finalSeed"] = gSaveBuffer.files[selectedFileNum][0].shipSaveData.randoSaveData.finalSeed;

// TODO: Add once JSON Saves are in.
// spoiler["options"] = nlohmann::json::object();
// for (auto& [randoOptionId, randoStaticOption] : Rando::StaticData::Options) {
// spoiler["options"][randoStaticOption.name] = RANDO_SAVE_OPTIONS[randoOptionId];
// }
spoiler["options"] = nlohmann::json::object();
for (auto& [randoOptionId, randoStaticOption] : Rando::StaticData::Options) {
spoiler["options"][randoStaticOption.name] = RANDO_SAVE_OPTIONS(selectedFileNum)[randoOptionId];
}

spoiler["checks"] = nlohmann::json::object();
for (auto& entry : shuffledPool) {
Expand All @@ -37,46 +34,83 @@ nlohmann::json GenerateFromPoolGeneration(std::vector<LevelShuffleEntry>& shuffl
}
}

if (!shuffledEntrances.empty()) {
spoiler["entrances"] = nlohmann::json::object();
for (auto& entrance : shuffledEntrances) {
spoiler["entrances"][Rando::StaticData::Entrances[entrance.randoEntranceId].name] =
Rando::StaticData::Entrances[Rando::StaticData::GetEntranceIdFromDestination(entrance.destinationId)]
.name;
}
}

return spoiler;
}
std::vector<LevelShuffleEntry> GenerateFromSpoilerLog(nlohmann::json spoiler) {
std::vector<LevelShuffleEntry> spoilerChecks;

void GenerateFromSpoiler(nlohmann::json spoiler) {
Rando::Logic::shuffledPool.clear();
Rando::Logic::shuffledEntrances.clear();

if (!spoiler.contains("type") || spoiler["type"] != "GHOSTSHIP_RANDO_SPOILER") {
Notification::Emit({ .message = "Error: Invalid Spoiler Log.", .messageColor = ImVec4(0.85f, 0.3f, 0, 1) });
return spoilerChecks;
}

if (spoiler.contains("checks") && !spoiler["checks"].empty()) {
for (auto& data : spoiler["checks"].items()) {
struct LevelShuffleEntry levelEntry;
struct LevelShuffleEntry checkEntry;
for (auto& [checkId, staticCheck] : Rando::StaticData::Checks) {
if (staticCheck.name == data.key()) {
levelEntry.randoCheckId = checkId;
checkEntry.randoCheckId = checkId;
break;
}
}

std::string randoItemStr = "";
if (data.value().contains("randoAct")) {
levelEntry.randoAct = data.value()["randoAct"];
checkEntry.randoAct = data.value()["randoAct"];
randoItemStr = data.value()["randoItemId"];
} else {
levelEntry.randoAct = RA_ACT_NONE;
checkEntry.randoAct = RA_ACT_NONE;
randoItemStr = data.value();
}

for (auto& [itemId, staticItem] : Rando::StaticData::Items) {
if (staticItem.spoilerName == randoItemStr) {
levelEntry.randoItemId = itemId;
checkEntry.randoItemId = itemId;
}
}
checkEntry.obtained = false;
checkEntry.skipped = false;
Rando::Logic::shuffledPool.push_back(checkEntry);
}
}

if (spoiler.contains("entrances") && !spoiler["entrances"].empty()) {
for (auto& data : spoiler["entrances"].items()) {
RandoSaveEntrance randoSaveEntrance;
for (auto& [entranceId, staticEntrance] : Rando::StaticData::Entrances) {
if (staticEntrance.name == data.key()) {
randoSaveEntrance.randoEntranceId = entranceId;
}
if (staticEntrance.name == data.value()) {
randoSaveEntrance.destinationId = staticEntrance.destinationId;
}
}
levelEntry.obtained = false;
spoilerChecks.push_back(levelEntry);

Rando::Logic::shuffledEntrances.push_back(randoSaveEntrance);
}
}

return spoilerChecks;
if (spoiler.contains("options") && !spoiler["options"].empty()) {
for (auto& data : spoiler["options"].items()) {
for (auto& [optionId, staticOption] : Rando::StaticData::Options) {
RandoSaveOption randoSaveOption;
if (staticOption.name == data.key()) {
RANDO_SAVE_OPTIONS(selectedFileNum)[optionId] = data.value().get<int32_t>();
break;
}
}
}
}
}

} // namespace Spoiler
Expand Down
Loading
Loading