Skip to content

Commit 5104f8d

Browse files
committed
Logic Rework
1 parent a64e2e3 commit 5104f8d

12 files changed

Lines changed: 272 additions & 68 deletions

File tree

src/port/Rando/CheckTracker/CheckTracker.cpp

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "CheckTracker.h"
2+
#include "port/Rando/Logic/Logic.h"
23
#include "port/ShipUtils.h"
34
#include "port/ui/UIWidgets.hpp"
45
#include <cstring>
@@ -91,6 +92,26 @@ namespace Rando {
9192

9293
namespace CheckTracker {
9394

95+
void SetCheckTrackerList() {
96+
for (auto& [id, name] : levelIdList) {
97+
CheckTrackerObject entry;
98+
entry.levelId = id;
99+
entry.levelName = name;
100+
101+
for (auto& [randoCheckId, randoStaticCheck] : Rando::StaticData::Checks) {
102+
if (entry.levelId == randoStaticCheck.levelId) {
103+
if (!Rando::Logic::IsCheckShuffled(randoCheckId)) {
104+
continue;
105+
}
106+
107+
entry.randoCheckNameList.push_back(
108+
{ randoCheckId, convertEnumToReadableName(randoStaticCheck.name), false });
109+
}
110+
}
111+
checkTrackerList.push_back(entry);
112+
}
113+
}
114+
94115
void CheckTrackerWindow::Draw() {
95116
if (!CVAR_SHOW_CHECK_TRACKER) {
96117
return;
@@ -107,10 +128,8 @@ void CheckTrackerWindow::Draw() {
107128
if (ImGui::Begin("Check Tracker", nullptr, ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoFocusOnAppearing)) {
108129
trackerBG.w = ImGui::IsWindowDocked() ? 1.0f : CVAR_TRACKER_OPACITY;
109130
ImGui::SetWindowFontScale(trackerScale);
110-
if (!IS_RANDO(selectedFileNum)) {
111-
ImGui::SetCursorPosX((ImGui::GetWindowWidth() - ImGui::CalcTextSize("No Rando Save Loaded").x) / 2);
112-
ImGui::SetCursorPosY(ImGui::GetWindowHeight() / 2 - 10.0f);
113-
ImGui::TextColored(UIWidgets::ColorValues.at(UIWidgets::Colors::Gray), "No Rando Save Loaded");
131+
if (checkTrackerList.empty()) {
132+
ImGui::TextColored(UIWidgets::ColorValues.at(UIWidgets::Colors::Orange), "No Rando Save Loaded");
114133
ImGui::End();
115134
ImGui::PopStyleColor(4);
116135
ImGui::PopStyleVar(1);
@@ -187,23 +206,6 @@ void SettingsWindow::DrawElement() {
187206

188207
bool isInitialized = false;
189208
void Init() {
190-
if (!isInitialized) {
191-
for (auto& [id, name] : levelIdList) {
192-
CheckTrackerObject entry;
193-
entry.levelId = id;
194-
entry.levelName = name;
195-
196-
for (auto& [randoCheckId, randoStaticCheck] : Rando::StaticData::Checks) {
197-
if (entry.levelId == randoStaticCheck.levelId) {
198-
entry.randoCheckNameList.push_back(
199-
{ randoCheckId, convertEnumToReadableName(randoStaticCheck.name), false });
200-
}
201-
}
202-
checkTrackerList.push_back(entry);
203-
}
204-
isInitialized = true;
205-
}
206-
207209
trackerBG = { 0, 0, 0, CVAR_TRACKER_OPACITY };
208210
trackerScale = CVAR_TRACKER_SCALE;
209211
}

src/port/Rando/CheckTracker/CheckTracker.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ namespace Rando {
1717
namespace CheckTracker {
1818

1919
void Init();
20-
void OnFileLoad();
20+
//void OnFileLoad();
21+
void SetCheckTrackerList();
2122

2223
class CheckTrackerWindow : public Ship::GuiWindow {
2324
public:

src/port/Rando/Logic/GeneratePools.cpp

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
#include "Logic.h"
2+
#include "port/Rando/Spoiler/Spoiler.h"
3+
#include "port/ui/Notification.h"
24
#include <libultraship/bridge/consolevariablebridge.h>
35
#include <sstream>
46
#include <random>
@@ -10,25 +12,30 @@ extern "C" {
1012
namespace Rando {
1113

1214
namespace Logic {
13-
15+
// Initial Shuffling containers
1416
std::vector<std::vector<LevelShuffleEntry>> shuffledList;
1517
std::vector<LevelShuffleEntry> shuffledLevelList;
1618
std::vector<RandoCheckId> shuffledChecks;
1719
std::vector<std::pair<RandoItemId, RandoAct>> shuffledItems;
1820

19-
void shuffleRandoItems(std::vector<std::pair<RandoItemId, RandoAct>>& shuffledItems) {
21+
// Final Shuffle List
22+
std::vector<LevelShuffleEntry> shuffledPool;
23+
24+
void ShuffleRandoItems(std::vector<std::pair<RandoItemId, RandoAct>>& shuffledItems) {
2025
std::random_device rd;
2126
std::mt19937 g(rd());
2227

2328
std::shuffle(shuffledItems.begin(), shuffledItems.end(), g);
2429
}
2530

2631
void GenerateShuffleList() {
27-
shuffledList.clear();
32+
shuffledPool.clear();
33+
2834
for (int i = LEVEL_UNKNOWN_1; i < LEVEL_UNKNOWN_38; i++) {
2935
shuffledLevelList.clear();
3036
shuffledChecks.clear();
3137
shuffledItems.clear();
38+
3239
for (auto& [randoCheckId, randoCheckData] : Rando::StaticData::Checks) {
3340
if (randoCheckId == RC_UNKNOWN) {
3441
continue;
@@ -64,15 +71,33 @@ void GenerateShuffleList() {
6471
shuffledChecks.push_back(randoCheckId);
6572
shuffledItems.push_back({ randoCheckData.randoItemId, randoCheckData.actData });
6673
}
67-
6874
if (!shuffledItems.empty()) {
69-
shuffleRandoItems(shuffledItems);
7075
for (int v = 0; v < shuffledChecks.size(); v++) {
7176
shuffledLevelList.push_back({ shuffledChecks[v], shuffledItems[v].first, shuffledItems[v].second });
7277
}
78+
shuffledList.push_back(shuffledLevelList);
7379
}
80+
}
81+
82+
switch (CVarGetInteger(Rando::StaticData::Options[RO_LOGIC].cvar, 0)) {
83+
case RO_LOGIC_GLITCHLESS:
84+
break;
85+
case RO_LOGIC_NO_LOGIC:
86+
ApplyNoLogicToSaveContext(shuffledList);
87+
break;
88+
default:
89+
break;
90+
}
7491

75-
shuffledList.push_back(shuffledLevelList);
92+
nlohmann::json spoilerLog = Rando::Spoiler::GenerateFromPoolGeneration(shuffledPool);
93+
if (spoilerLog.empty()) {
94+
Notification::Emit(
95+
{ .message = "Error: No Spoiler Log was created.", .messageColor = ImVec4(0.85f, 0.3f, 0, 1) });
96+
} else {
97+
std::string fileName = spoilerLog["fileNum"].get<std::string>() + ".json";
98+
Rando::Spoiler::SaveToFile(fileName, spoilerLog);
99+
Notification::Emit(
100+
{ .prefix = fileName + " ", .message = "Spoiler Log created.", .messageColor = ImVec4(0, 0.3f, 0.85f, 1) });
76101
}
77102
}
78103

src/port/Rando/Logic/Logic.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,16 @@ namespace Logic {
1616

1717
extern std::vector<std::vector<LevelShuffleEntry>> shuffledList;
1818
extern std::vector<LevelShuffleEntry> shuffledLevelList;
19+
20+
extern std::vector<LevelShuffleEntry> shuffledPool;
1921
extern std::vector<RandoCheckId> shuffledChecks;
2022
extern std::vector<std::pair<RandoItemId, RandoAct>> shuffledItems;
2123

22-
void shuffleRandoItems(std::vector<std::pair<RandoItemId, RandoAct>>& shuffledItems);
24+
void ShuffleRandoItems(std::vector<std::pair<RandoItemId, RandoAct>>& shuffledItems);
2325
void GenerateShuffleList();
2426

27+
void ApplyNoLogicToSaveContext(std::vector<std::vector<LevelShuffleEntry>>& initialPool);
28+
2529
// Logic Operators
2630
inline bool IsBlueSwitchActivated(RandoCheckId randoCheckId) {
2731
if (Rando::StaticData::Checks[randoCheckId].randoItemId == RI_COIN_BLUE) {
@@ -30,12 +34,8 @@ inline bool IsBlueSwitchActivated(RandoCheckId randoCheckId) {
3034
return false;
3135
};
3236

33-
inline bool IsCheckShuffled(int16_t levelId, RandoCheckId randoCheckId) {
34-
if (levelId < 0 || levelId >= shuffledList.size()) {
35-
return false;
36-
}
37-
38-
for (auto& entry : shuffledList[levelId]) {
37+
inline bool IsCheckShuffled(RandoCheckId randoCheckId) {
38+
for (auto& entry : shuffledPool) {
3939
if (entry.randoCheckId == randoCheckId) {
4040
return true;
4141
}

src/port/Rando/Logic/NoLogic.cpp

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,29 @@ namespace Rando {
88

99
namespace Logic {
1010

11-
void ApplyNoLogicToSaveContext(std::vector<RandoCheckId>& checkPool, std::vector<RandoItemId>& itemPool) {
12-
// for (size_t i = 0; i < itemPool.size(); i++) {
13-
// std::swap(itemPool[i], itemPool[Ship_Random(0, itemPool.size() - 1)]);
14-
// }
15-
//
16-
// for (auto& randoCheckId : checkPool) {
17-
// if (randoCheckId == RC_UNKNOWN) {
18-
// continue;
19-
// }
20-
//
21-
// RANDO_SAVE_CHECKS[randoCheckId].shuffled = true;
22-
// RANDO_SAVE_CHECKS[randoCheckId].randoItemId = itemPool.back();
23-
// itemPool.pop_back();
24-
// }
11+
void ApplyNoLogicToSaveContext(std::vector<std::vector<LevelShuffleEntry>>& initialPool) {
12+
std::vector<LevelShuffleEntry> pool;
13+
std::vector<RandoCheckId> checkPool;
14+
std::vector<std::pair<RandoItemId, RandoAct>> itemPool;
15+
16+
for (auto& level : initialPool) {
17+
checkPool.clear();
18+
itemPool.clear();
19+
20+
for (auto& entry : level) {
21+
checkPool.push_back(entry.randoCheckId);
22+
itemPool.push_back({ entry.randoItemId, entry.randoAct });
23+
}
24+
25+
if (!itemPool.empty()) {
26+
ShuffleRandoItems(itemPool);
27+
for (int v = 0; v < checkPool.size(); v++) {
28+
pool.push_back({ checkPool[v], itemPool[v].first, itemPool[v].second });
29+
}
30+
}
31+
}
32+
shuffledPool = pool;
33+
initialPool.clear();
2534
}
2635

2736
} // namespace Logic

src/port/Rando/MiscBehavior/OnFileLoad.cpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,23 @@
11
#include "MiscBehavior.h"
22
#include "port/Rando/Logic/Logic.h"
3+
#include "port/Rando/Spoiler/Spoiler.h"
4+
#include "port/Rando/CheckTracker/CheckTracker.h"
5+
#include "port/ui/Notification.h"
36

47
extern "C" {
58
extern struct SaveBuffer gSaveBuffer;
69
}
710

11+
bool SpoilerExistsForFileNum(std::string fileName) {
12+
nlohmann::json spoilerCheck = Rando::Spoiler::LoadFromFile(fileName);
13+
if (spoilerCheck.empty()) {
14+
Notification::Emit({ .message = "Error: No Spoiler Log found.", .messageColor = ImVec4(0.85f, 0.3f, 0, 1) });
15+
return false;
16+
} else {
17+
return true;
18+
}
19+
}
20+
821
void Rando::MiscBehavior::OnFileLoad() {
922
REGISTER_LISTENER(OnGameFileLoad, EVENT_PRIORITY_NORMAL, [](IEvent* event) {
1023
OnGameFileLoad* ev = (OnGameFileLoad*)event;
@@ -14,12 +27,19 @@ void Rando::MiscBehavior::OnFileLoad() {
1427
}
1528

1629
selectedFileNum = ev->fileNum - 1;
30+
std::string fileName = std::to_string(selectedFileNum) + ".json";
31+
bool logExists = SpoilerExistsForFileNum(fileName);
1732

1833
if (!IS_RANDO(selectedFileNum)) {
1934
gSaveBuffer.files[selectedFileNum]->shipSaveData.saveType = SAVETYPE_RANDO;
20-
// Rando::Logic::GenerateShuffleList();
35+
if (!logExists) {
36+
Rando::Logic::GenerateShuffleList();
37+
} else {
38+
nlohmann::json loadedSpoiler = Rando::Spoiler::LoadFromFile(fileName);
39+
Rando::Logic::shuffledPool = Rando::Spoiler::GenerateFromSpoilerLog(loadedSpoiler);
40+
}
41+
Rando::CheckTracker::SetCheckTrackerList();
2142
}
22-
Rando::Logic::GenerateShuffleList();
2343

2444
// TODO: Inject Save File with spoiler data
2545
// gSaveBuffer.files[ev->fileNum]->shipSaveData.randoSaveData.isRando = true;

src/port/Rando/ObjectBehavior/ObjectBehavior.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,8 @@ void LogOutSpawns(std::string type, int16_t model, int16_t posX, int16_t posY, i
2424

2525
void ModifySpawnedObject(bool* shouldCancel, s16 x, s16 y, s16 z, s32 param) {
2626
Rando::StaticData::RandoStaticCheck randoStaticCheck = Rando::StaticData::GetShuffledRandoStaticCheck(x, y, z);
27-
if (!Rando::Logic::IsCheckShuffled(Rando::StaticData::Checks[randoStaticCheck.randoCheckId].levelId - 1,
28-
randoStaticCheck.randoCheckId) ||
29-
randoStaticCheck.randoCheckId == RC_UNKNOWN || randoStaticCheck.randoItemId == RI_UNKNOWN) {
27+
if (!Rando::Logic::IsCheckShuffled(randoStaticCheck.randoCheckId) || randoStaticCheck.randoCheckId == RC_UNKNOWN ||
28+
randoStaticCheck.randoItemId == RI_UNKNOWN) {
3029
return;
3130
}
3231

@@ -40,9 +39,8 @@ void ModifySpawnedObject(bool* shouldCancel, s16 x, s16 y, s16 z, s32 param) {
4039

4140
void ModifyCoinStarObject(bool* shouldCancel, s16 x, s16 y, s16 z) {
4241
Rando::StaticData::RandoStaticCheck randoStaticCheck = Rando::StaticData::GetShuffledRandoStaticCheck(0, 0, 0);
43-
if (!Rando::Logic::IsCheckShuffled(Rando::StaticData::Checks[randoStaticCheck.randoCheckId].levelId - 1,
44-
randoStaticCheck.randoCheckId) ||
45-
randoStaticCheck.randoCheckId == RC_UNKNOWN || randoStaticCheck.randoItemId == RI_UNKNOWN) {
42+
if (!Rando::Logic::IsCheckShuffled(randoStaticCheck.randoCheckId) || randoStaticCheck.randoCheckId == RC_UNKNOWN ||
43+
randoStaticCheck.randoItemId == RI_UNKNOWN) {
4644
return;
4745
}
4846

src/port/Rando/Spoiler/File.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#include "Spoiler.h"
2+
#include <fstream>
3+
4+
const std::string appShortName = "sm64";
5+
6+
namespace Rando {
7+
8+
namespace Spoiler {
9+
10+
void SaveToFile(const std::string& fileName, nlohmann::json spoiler) {
11+
std::string filePath = Ship::Context::GetPathRelativeToAppDirectory("randomizer/" + fileName, appShortName);
12+
std::ofstream fileStream(filePath);
13+
if (!fileStream.is_open()) {
14+
throw std::runtime_error("Failed to open spoiler file");
15+
}
16+
17+
fileStream << spoiler.dump(4);
18+
}
19+
20+
nlohmann::json LoadFromFile(const std::string& fileName) {
21+
std::string spoilerFilePath = Ship::Context::GetPathRelativeToAppDirectory("randomizer/" + fileName, appShortName);
22+
std::ifstream fileStream(spoilerFilePath);
23+
if (!fileStream.is_open()) {
24+
throw std::runtime_error("Failed to open spoiler file");
25+
}
26+
27+
nlohmann::json spoiler;
28+
try {
29+
fileStream >> spoiler;
30+
} catch (nlohmann::json::exception& e) {
31+
throw std::runtime_error("Failed to parse spoiler file: " + std::string(e.what()));
32+
}
33+
34+
if (!spoiler.contains("type") || spoiler["type"] != "GHOSTSHIP_RANDO_SPOILER") {
35+
throw std::runtime_error("Spoiler file is not a valid spoiler file");
36+
}
37+
38+
return spoiler;
39+
}
40+
41+
} // namespace Spoiler
42+
43+
} // namespace Rando

0 commit comments

Comments
 (0)