Working on reset state and the end game

This commit is contained in:
Vladislav Khorev committed 2026-07-08 16:24:06 +03:00
1 parent 124208f2a4
commit 1c2c80f0ea
5 files changed
+1653 -43

No files matched your search

+98 -41
View File
@@ -289,33 +289,6 @@ namespace ZL
std::cout << "Load resurces step 13" << std::endl;
menuManager.onResetGame = [this]() {
gameState.currentLocationName.clear();
gameState.isDarklands = false;
gameState.isNight = false;
gameState.isDawn = false;
gameState.playerHp = 200.f;
gameState.playerMaxHp = 200.f;
gameState.money = 5500;
gameState.globalInts.clear();
gameState.globalFloats.clear();
gameState.tutorialStep = TutorialStep::Step0;
gameState.uniIntTutorialState = UniIntTutorialState::Step10;
gameState.tutorialPhonePickedUp = false;
gameState.tutorialJournalPickedUp = false;
gameState.tutorialPhoneChatScreenOpened = false;
gameState.tutorialJournalScreenOpened = false;
gameState.tutorialNeedOpenTaxiScreen = false;
for (int i = 0; i < 3; ++i) {
gameState.chatUnread[i] = true;
gameState.chatPreviewMsg[i].clear();
gameState.chatHistory[i].clear();
}
gameState.inventory.clear();
gameState.questJournal.loadFromFile(localizedConfigPath("resources/config/quests.json", g_currentLanguage), CONST_ZIP_FILE);
createLocations();
};
try {
menuManager.setup(gameState.inventory, CONST_ZIP_FILE);
std::cout << "UI loaded successfully" << std::endl;
@@ -326,9 +299,12 @@ namespace ZL
}
menuManager.startGameFunc = [this]() {
gameState.currentLocationName = "location_dorm";
currentLocation()->scriptEngine.callLocationEnterCallback();
this->audioPlayer->crossFadeMusicAsync("audio/obshaga.ogg");
mainThreadHandler.EnqueueMainThreadTask([this]() {
performResetToInitialState();
gameState.currentLocationName = "location_dorm";
currentLocation()->scriptEngine.callLocationEnterCallback();
this->audioPlayer->crossFadeMusicAsync("audio/obshaga.ogg");
});
};
menuManager.onSaveGame = [this](int slot) { saveGame(slot); };
@@ -353,6 +329,97 @@ namespace ZL
}
void Game::rearmDormOneShotCallbacks() {
auto it = gameState.locations.find("location_dorm");
if (it == gameState.locations.end() || !it->second) return;
it->second->onPlayerTaxiRequired = [this]() {
menuManager.tutorialShowTaxiHint();
};
menuManager.tutorialUnlockInteractiveObjectsFunc = [this]()
{
if (gameState.locations["location_dorm"])
{
gameState.locations["location_dorm"]->state.tutorialInteractiveObjectsLocked = false;
}
};
}
void Game::performFullReset() {
gameState.currentLocationName.clear();
gameState.isDarklands = false;
gameState.isNight = false;
gameState.isDawn = false;
gameState.playerHp = 200.f;
gameState.playerMaxHp = 200.f;
gameState.money = 5500;
gameState.globalInts.clear();
gameState.globalFloats.clear();
gameState.tutorialStep = TutorialStep::Step0;
gameState.uniIntTutorialState = UniIntTutorialState::Step10;
gameState.tutorialPhonePickedUp = false;
gameState.tutorialJournalPickedUp = false;
gameState.tutorialPhoneChatScreenOpened = false;
gameState.tutorialJournalScreenOpened = false;
gameState.tutorialNeedOpenTaxiScreen = false;
for (int i = 0; i < 3; ++i) {
gameState.chatUnread[i] = true;
gameState.chatPreviewMsg[i].clear();
gameState.chatHistory[i].clear();
}
gameState.inventory.clear();
gameState.questJournal.loadFromFile(localizedConfigPath("resources/config/quests.json", g_currentLanguage), CONST_ZIP_FILE);
createLocations();
// Developer workflow: uncomment to (re)generate resources/config/start_state.json
// from this freshly-rebuilt state after changing gameplay/content JSON or Lua.
// Re-comment before shipping.
//saveInitialState();
}
void Game::performResetToInitialState() {
const std::string path = "resources/config/start_state.json";
const std::string content = ZL::readTextFile(path);
if (!content.empty()) {
try {
nlohmann::json root = nlohmann::json::parse(content);
// GameState::load() merges into existing maps rather than replacing them,
// so any Lua globals set during play that aren't in the pristine snapshot
// must be cleared explicitly before loading it.
gameState.globalInts.clear();
gameState.globalFloats.clear();
gameState.load(root); // updates existing Location objects in place -- no
// destruction, no re-parsing JSON/nav files, no new
// sol2 state (GameState::load only touches map entries
// that already exist).
// Locations survive this reset, so any one-shot callbacks they consumed
// during the previous playthrough (tutorial unlock, taxi request) must be
// re-armed here -- createLocations() normally does this, but doesn't run
// on this fast path.
rearmDormOneShotCallbacks();
return;
} catch (const std::exception& e) {
std::cerr << "[reset] Failed to parse " << path << ": " << e.what()
<< " -- falling back to full rebuild" << std::endl;
}
}
performFullReset();
}
void Game::saveInitialState() {
nlohmann::json root;
gameState.save(root);
const std::string path = "resources/config/start_state.json";
std::ofstream file(path);
if (file.is_open()) {
file << root.dump(2);
std::cout << "[reset] Saved initial state snapshot to " << path << std::endl;
} else {
std::cerr << "[reset] Could not open " << path << " for writing" << std::endl;
}
}
void Game::createLocations()
{
gameState.locations.clear();
@@ -561,19 +628,9 @@ namespace ZL
if (gameState.locations["location_dorm"]->player)
gameState.locations["location_dorm"]->player->state.onDeathAnimComplete = [this]() { startDarklandsTransition(); };
gameState.locations["location_dorm"]->onPlayerTaxiRequired = [this]() {
menuManager.tutorialShowTaxiHint();
};
gameState.locations["location_dorm"]->state.tutorialInteractiveObjectsLocked = true;
menuManager.tutorialUnlockInteractiveObjectsFunc = [this]()
{
if (gameState.locations["location_dorm"])
{
gameState.locations["location_dorm"]->state.tutorialInteractiveObjectsLocked = false;
}
};
rearmDormOneShotCallbacks();
menuManager.callTaxiFunc = [this]()
{