Working on game state
This commit is contained in:
1 parent
b01e970554
commit
2807d82d51
12 files changed
+501
-445
No files matched your search
+181
-186
@@ -64,10 +64,16 @@ namespace ZL
|
||||
}
|
||||
#endif
|
||||
|
||||
Location* Game::currentLocation() const {
|
||||
if (gameState.currentLocationName.empty()) return nullptr;
|
||||
auto it = gameState.locations.find(gameState.currentLocationName);
|
||||
return (it != gameState.locations.end()) ? it->second.get() : nullptr;
|
||||
}
|
||||
|
||||
Game::Game()
|
||||
: newTickCount(0)
|
||||
, lastTickCount(0)
|
||||
, menuManager(renderer, globalInts)
|
||||
, menuManager(renderer, gameState)
|
||||
, audioPlayer(std::make_unique<AudioPlayerAsync>())
|
||||
{
|
||||
}
|
||||
@@ -236,7 +242,7 @@ namespace ZL
|
||||
|
||||
ItemRegistry::instance().loadFromJson("resources/config2/items.json", CONST_ZIP_FILE);
|
||||
|
||||
globalFloats["player_hp"] = 200;
|
||||
gameState.globalFloats["player_hp"] = 200;
|
||||
|
||||
LocationSetup uniInteriorParams;
|
||||
uniInteriorParams.gameObjectsJsonPath = "resources/config2/gameobjects_uni_interior_x.json";
|
||||
@@ -311,24 +317,24 @@ namespace ZL
|
||||
uniInteriorParams.interactiveObjectsJsonPath = "resources/config2/interactive_objects_uni_interior_x.json";
|
||||
uniInteriorParams.playerPosition = Eigen::Vector3f(0.942694, 0, -9.63104);
|
||||
|
||||
locations["uni_interior"] = std::make_shared<Location>(renderer, inventory);
|
||||
locations["uni_interior"]->setup(uniInteriorParams, &menuManager.questJournal);
|
||||
locations["uni_interior"]->scriptEngine.setGlobalStore(&globalInts);
|
||||
locations["uni_interior"]->scriptEngine.setGlobalFloatStore(&globalFloats);
|
||||
locations["uni_interior"]->requestNightDayTransition = [this](bool isNight, bool isDawn) { this->menuManager.isNight = isNight; this->menuManager.isDawn = isDawn; };
|
||||
locations["uni_interior"]->requestDarklandsTransition = [this]() { return startDarklandsTransition(); };
|
||||
locations["uni_interior"]->requestAdvanceDarklandsHud = [this]() { menuManager.advanceUniIntDarklandsHud(); };
|
||||
locations["uni_interior"]->requestClosePhone = [this]() { menuManager.closePhoneEntirely(); };
|
||||
locations["uni_interior"]->requestReturnToMainMenu = [this]() {
|
||||
this->currentLocation = nullptr;
|
||||
gameState.locations["uni_interior"] = std::make_shared<Location>(renderer, gameState.inventory);
|
||||
gameState.locations["uni_interior"]->setup(uniInteriorParams, &gameState.questJournal);
|
||||
gameState.locations["uni_interior"]->scriptEngine.setGlobalStore(&gameState.globalInts);
|
||||
gameState.locations["uni_interior"]->scriptEngine.setGlobalFloatStore(&gameState.globalFloats);
|
||||
gameState.locations["uni_interior"]->requestNightDayTransition = [this](bool isNight, bool isDawn) { gameState.isNight = isNight; gameState.isDawn = isDawn; };
|
||||
gameState.locations["uni_interior"]->requestDarklandsTransition = [this]() { return startDarklandsTransition(); };
|
||||
gameState.locations["uni_interior"]->requestAdvanceDarklandsHud = [this]() { menuManager.advanceUniIntDarklandsHud(); };
|
||||
gameState.locations["uni_interior"]->requestClosePhone = [this]() { menuManager.closePhoneEntirely(); };
|
||||
gameState.locations["uni_interior"]->requestReturnToMainMenu = [this]() {
|
||||
gameState.currentLocationName.clear();
|
||||
menuManager.showMainMenu();
|
||||
};
|
||||
locations["uni_interior"]->requestSetChatUnread = [this](int idx, bool unread, const std::string& msg) {
|
||||
gameState.locations["uni_interior"]->requestSetChatUnread = [this](int idx, bool unread, const std::string& msg) {
|
||||
menuManager.setChatUnread(idx, unread, msg);
|
||||
};
|
||||
if (locations["uni_interior"]->player)
|
||||
locations["uni_interior"]->player->state.onDeathAnimComplete = [this]() { startDarklandsTransition(); };
|
||||
for (auto& npc : locations["uni_interior"]->npcs) {
|
||||
if (gameState.locations["uni_interior"]->player)
|
||||
gameState.locations["uni_interior"]->player->state.onDeathAnimComplete = [this]() { startDarklandsTransition(); };
|
||||
for (auto& npc : gameState.locations["uni_interior"]->npcs) {
|
||||
if (npc && npc->state.canAttack) {
|
||||
npc->state.onDeathAnimComplete = [this]() { menuManager.onEnemyKilledInUniInterior(); };
|
||||
}
|
||||
@@ -348,28 +354,22 @@ namespace ZL
|
||||
uniExteriorParams.npcsJsonPath = "resources/config2/npcs_uni_exterior.json";
|
||||
uniExteriorParams.dialoguesJsonPath = "resources/dialogue/uni_exterior_dialogues.json";
|
||||
|
||||
locations["uni_exterior"] = std::make_shared<Location>(renderer, inventory);
|
||||
locations["uni_exterior"]->setup(uniExteriorParams, &menuManager.questJournal);
|
||||
locations["uni_exterior"]->scriptEngine.setGlobalStore(&globalInts);
|
||||
locations["uni_exterior"]->scriptEngine.setGlobalFloatStore(&globalFloats);
|
||||
locations["uni_exterior"]->requestNightDayTransition = [this](bool isNight, bool isDawn) {
|
||||
this->menuManager.isNight = isNight;
|
||||
this->menuManager.isDawn = isDawn;
|
||||
/*for (auto& locPair : locations) {
|
||||
if (locPair.second) {
|
||||
locPair.second->isNight = isNight;
|
||||
locPair.second->isDawn = isDawn;
|
||||
}
|
||||
}*/
|
||||
gameState.locations["uni_exterior"] = std::make_shared<Location>(renderer, gameState.inventory);
|
||||
gameState.locations["uni_exterior"]->setup(uniExteriorParams, &gameState.questJournal);
|
||||
gameState.locations["uni_exterior"]->scriptEngine.setGlobalStore(&gameState.globalInts);
|
||||
gameState.locations["uni_exterior"]->scriptEngine.setGlobalFloatStore(&gameState.globalFloats);
|
||||
gameState.locations["uni_exterior"]->requestNightDayTransition = [this](bool isNight, bool isDawn) {
|
||||
gameState.isNight = isNight;
|
||||
gameState.isDawn = isDawn;
|
||||
};
|
||||
locations["uni_exterior"]->requestDarklandsTransition = [this]() { return startDarklandsTransition(); };
|
||||
locations["uni_exterior"]->requestClosePhone = [this]() { menuManager.closePhoneEntirely(); };
|
||||
locations["uni_exterior"]->requestReturnToMainMenu = [this]() { menuManager.showMainMenu(); };
|
||||
locations["uni_exterior"]->requestSetChatUnread = [this](int idx, bool unread, const std::string& msg) {
|
||||
gameState.locations["uni_exterior"]->requestDarklandsTransition = [this]() { return startDarklandsTransition(); };
|
||||
gameState.locations["uni_exterior"]->requestClosePhone = [this]() { menuManager.closePhoneEntirely(); };
|
||||
gameState.locations["uni_exterior"]->requestReturnToMainMenu = [this]() { menuManager.showMainMenu(); };
|
||||
gameState.locations["uni_exterior"]->requestSetChatUnread = [this](int idx, bool unread, const std::string& msg) {
|
||||
menuManager.setChatUnread(idx, unread, msg);
|
||||
};
|
||||
if (locations["uni_exterior"]->player)
|
||||
locations["uni_exterior"]->player->state.onDeathAnimComplete = [this]() { startDarklandsTransition(); };
|
||||
if (gameState.locations["uni_exterior"]->player)
|
||||
gameState.locations["uni_exterior"]->player->state.onDeathAnimComplete = [this]() { startDarklandsTransition(); };
|
||||
|
||||
LocationSetup params_dorm;
|
||||
//params_dorm.gameObjectsJsonPath = "resources/config2/gameobjects_dorm.json";
|
||||
@@ -404,96 +404,96 @@ namespace ZL
|
||||
params_dorm.playerPosition = Eigen::Vector3f(6.76345, 0, -14.6022);
|
||||
|
||||
|
||||
locations["location_dorm"] = std::make_shared<Location>(renderer, inventory);
|
||||
locations["location_dorm"]->setup(params_dorm, &menuManager.questJournal);
|
||||
locations["location_dorm"]->scriptEngine.setGlobalStore(&globalInts);
|
||||
locations["location_dorm"]->scriptEngine.setGlobalFloatStore(&globalFloats);
|
||||
locations["location_dorm"]->requestNightDayTransition = [this](bool isNight, bool isDawn) { this->menuManager.isNight = isNight; this->menuManager.isDawn = isDawn; };
|
||||
locations["location_dorm"]->requestDarklandsTransition = [this]() { return startDarklandsTransition(); };
|
||||
locations["location_dorm"]->requestClosePhone = [this]() { menuManager.closePhoneEntirely(); };
|
||||
locations["location_dorm"]->requestReturnToMainMenu = [this]() { menuManager.showMainMenu(); };
|
||||
locations["location_dorm"]->requestSetChatUnread = [this](int idx, bool unread, const std::string& msg) {
|
||||
gameState.locations["location_dorm"] = std::make_shared<Location>(renderer, gameState.inventory);
|
||||
gameState.locations["location_dorm"]->setup(params_dorm, &gameState.questJournal);
|
||||
gameState.locations["location_dorm"]->scriptEngine.setGlobalStore(&gameState.globalInts);
|
||||
gameState.locations["location_dorm"]->scriptEngine.setGlobalFloatStore(&gameState.globalFloats);
|
||||
gameState.locations["location_dorm"]->requestNightDayTransition = [this](bool isNight, bool isDawn) { gameState.isNight = isNight; gameState.isDawn = isDawn; };
|
||||
gameState.locations["location_dorm"]->requestDarklandsTransition = [this]() { return startDarklandsTransition(); };
|
||||
gameState.locations["location_dorm"]->requestClosePhone = [this]() { menuManager.closePhoneEntirely(); };
|
||||
gameState.locations["location_dorm"]->requestReturnToMainMenu = [this]() { menuManager.showMainMenu(); };
|
||||
gameState.locations["location_dorm"]->requestSetChatUnread = [this](int idx, bool unread, const std::string& msg) {
|
||||
menuManager.setChatUnread(idx, unread, msg);
|
||||
};
|
||||
if (locations["location_dorm"]->player)
|
||||
locations["location_dorm"]->player->state.onDeathAnimComplete = [this]() { startDarklandsTransition(); };
|
||||
if (gameState.locations["location_dorm"]->player)
|
||||
gameState.locations["location_dorm"]->player->state.onDeathAnimComplete = [this]() { startDarklandsTransition(); };
|
||||
|
||||
locations["location_dorm"]->onPlayerTaxiRequired = [this]() {
|
||||
gameState.locations["location_dorm"]->onPlayerTaxiRequired = [this]() {
|
||||
menuManager.tutorialShowTaxiHint();
|
||||
};
|
||||
|
||||
locations["location_dorm"]->state.tutorialInteractiveObjectsLocked = true;
|
||||
gameState.locations["location_dorm"]->state.tutorialInteractiveObjectsLocked = true;
|
||||
|
||||
menuManager.tutorialUnlockInteractiveObjectsFunc = [this]()
|
||||
{
|
||||
if (locations["location_dorm"])
|
||||
if (gameState.locations["location_dorm"])
|
||||
{
|
||||
locations["location_dorm"]->state.tutorialInteractiveObjectsLocked = false;
|
||||
gameState.locations["location_dorm"]->state.tutorialInteractiveObjectsLocked = false;
|
||||
}
|
||||
};
|
||||
|
||||
menuManager.callTaxiFunc = [this]()
|
||||
{
|
||||
if (locations["location_dorm"])
|
||||
if (gameState.locations["location_dorm"])
|
||||
{
|
||||
locations["location_dorm"]->onPlayerTaxiRequired = nullptr;
|
||||
gameState.locations["location_dorm"]->onPlayerTaxiRequired = nullptr;
|
||||
}
|
||||
|
||||
if (currentLocation)
|
||||
if (currentLocation())
|
||||
{
|
||||
currentLocation->scriptEngine.callCallTaxiCallback();
|
||||
currentLocation()->scriptEngine.callCallTaxiCallback();
|
||||
}
|
||||
};
|
||||
|
||||
// Teleport callbacks: destination name and position come from the teleport zone data.
|
||||
auto teleportCallback = [this](const std::string& destName, const Eigen::Vector3f& destPos, float destRotY) {
|
||||
std::cout << "[TELEPORT] " << " -> " << destName << std::endl;
|
||||
auto it = locations.find(destName);
|
||||
if (it == locations.end()) {
|
||||
auto it = gameState.locations.find(destName);
|
||||
if (it == gameState.locations.end()) {
|
||||
std::cerr << "[TELEPORT] Unknown destination location: " << destName << std::endl;
|
||||
return;
|
||||
}
|
||||
if (currentLocation)
|
||||
if (currentLocation())
|
||||
{
|
||||
currentLocation->scriptEngine.callLocationExitCallback();
|
||||
currentLocation->dialogueSystem.stopDialogue();
|
||||
currentLocation()->scriptEngine.callLocationExitCallback();
|
||||
currentLocation()->dialogueSystem.stopDialogue();
|
||||
}
|
||||
currentLocation = it->second;
|
||||
if (currentLocation->player) {
|
||||
currentLocation->player->state.position = destPos;
|
||||
currentLocation->player->setTarget(destPos);
|
||||
currentLocation->player->stopInPlace();
|
||||
currentLocation->player->state.facingAngle = destRotY;
|
||||
currentLocation->player->state.targetFacingAngle = destRotY;
|
||||
gameState.currentLocationName = destName;
|
||||
Location* loc = currentLocation();
|
||||
if (loc->player) {
|
||||
loc->player->state.position = destPos;
|
||||
loc->player->setTarget(destPos);
|
||||
loc->player->stopInPlace();
|
||||
loc->player->state.facingAngle = destRotY;
|
||||
loc->player->state.targetFacingAngle = destRotY;
|
||||
}
|
||||
currentLocation->state.cameraAzimuth = destRotY;
|
||||
currentLocation->state.isDarklands = isDarklands;
|
||||
currentLocation->state.isNight = menuManager.isNight;
|
||||
currentLocation->state.isDawn = menuManager.isDawn;
|
||||
currentLocation->scriptEngine.callLocationEnterCallback();
|
||||
|
||||
loc->state.cameraAzimuth = destRotY;
|
||||
loc->state.isDarklands = gameState.isDarklands;
|
||||
loc->state.isNight = gameState.isNight;
|
||||
loc->state.isDawn = gameState.isDawn;
|
||||
loc->scriptEngine.callLocationEnterCallback();
|
||||
|
||||
menuManager.onLocationChanged(destName);
|
||||
};
|
||||
|
||||
locations["uni_exterior"]->onTeleport = teleportCallback;
|
||||
locations["uni_interior"]->onTeleport = teleportCallback;
|
||||
locations["location_dorm"]->onTeleport = teleportCallback;
|
||||
gameState.locations["uni_exterior"]->onTeleport = teleportCallback;
|
||||
gameState.locations["uni_interior"]->onTeleport = teleportCallback;
|
||||
gameState.locations["location_dorm"]->onTeleport = teleportCallback;
|
||||
|
||||
// Share the global int store with all dialogue runtimes so flags set via
|
||||
// dialogue JSON and via Lua set_dialogue_flag all see the same state.
|
||||
for (auto& [name, loc] : locations) {
|
||||
loc->dialogueSystem.setGlobalFlagStore(&globalInts);
|
||||
for (auto& [name, loc] : gameState.locations) {
|
||||
loc->dialogueSystem.setGlobalFlagStore(&gameState.globalInts);
|
||||
}
|
||||
|
||||
// Wire tutorial advance callbacks for all locations.
|
||||
// advanceTutorialStep() guards against double-advancing, so sharing is safe.
|
||||
for (auto& [name, loc] : locations) {
|
||||
for (auto& [name, loc] : gameState.locations) {
|
||||
loc->dialogueSystem.setOnDialogueAdvanced([this]() {
|
||||
menuManager.advanceTutorialStep();
|
||||
});
|
||||
loc->onPlayerFloorWalk = [this]() {
|
||||
if (menuManager.tutorialStep == TutorialStep::Step2) {
|
||||
if (gameState.tutorialStep == TutorialStep::Step2) {
|
||||
menuManager.advanceTutorialStep();
|
||||
}
|
||||
menuManager.onPlayerStartedWalking();
|
||||
@@ -509,19 +509,19 @@ namespace ZL
|
||||
|
||||
|
||||
// Wire inventory callbacks: tutorial tracking + toast notifications.
|
||||
inventory.onItemAdded = [this](const std::string& itemId) {
|
||||
gameState.inventory.onItemAdded = [this](const std::string& itemId) {
|
||||
menuManager.onItemPickedUp(itemId);
|
||||
const Item* item = ItemRegistry::instance().findById(itemId);
|
||||
if (item) menuManager.showToast("resources/w/ui/img/toast/item_received001.png", item->name);
|
||||
};
|
||||
inventory.onItemRemoved = [this](const std::string& itemId) {
|
||||
gameState.inventory.onItemRemoved = [this](const std::string& itemId) {
|
||||
const Item* item = ItemRegistry::instance().findById(itemId);
|
||||
if (item) menuManager.showToast("resources/w/ui/img/toast/item_removed001.png", item->name);
|
||||
};
|
||||
|
||||
// Wire phone dialogue start function so MenuManager can trigger dialogues.
|
||||
menuManager.startDialogueFunc = [this](const std::string& id) {
|
||||
if (currentLocation) currentLocation->dialogueSystem.startDialogue(id);
|
||||
if (currentLocation()) currentLocation()->dialogueSystem.startDialogue(id);
|
||||
};
|
||||
|
||||
menuManager.startDarklandsTransitionFunc = [this]() {
|
||||
@@ -533,19 +533,19 @@ namespace ZL
|
||||
};
|
||||
|
||||
menuManager.chatOpenCallback = [this](int chatIndex) {
|
||||
if (currentLocation)
|
||||
currentLocation->scriptEngine.callChatOpenCallback(chatIndex);
|
||||
if (currentLocation())
|
||||
currentLocation()->scriptEngine.callChatOpenCallback(chatIndex);
|
||||
};
|
||||
|
||||
// Wire chat-bubble callback so dynamic bubbles appear as dialogue lines are shown.
|
||||
for (auto& [name, loc] : locations) {
|
||||
for (auto& [name, loc] : gameState.locations) {
|
||||
loc->dialogueSystem.setOnChatBubbleReady([this](const std::string& text, bool incoming) {
|
||||
menuManager.onChatBubbleReady(text, incoming);
|
||||
});
|
||||
}
|
||||
|
||||
// Wire cutscene HUD: show skip button when cutscene starts, restore HUD when it ends.
|
||||
for (auto& [name, loc] : locations) {
|
||||
for (auto& [name, loc] : gameState.locations) {
|
||||
loc->dialogueSystem.setOnCutsceneStarted([this]() {
|
||||
menuManager.onCutsceneStarted();
|
||||
});
|
||||
@@ -554,13 +554,13 @@ namespace ZL
|
||||
});
|
||||
}
|
||||
menuManager.skipCutsceneFunc = [this]() {
|
||||
if (currentLocation) currentLocation->dialogueSystem.skipCutscene();
|
||||
if (currentLocation()) currentLocation()->dialogueSystem.skipCutscene();
|
||||
};
|
||||
|
||||
std::cout << "Load resurces step 13" << std::endl;
|
||||
|
||||
try {
|
||||
menuManager.setup(inventory, CONST_ZIP_FILE);
|
||||
menuManager.setup(gameState.inventory, CONST_ZIP_FILE);
|
||||
std::cout << "UI loaded successfully" << std::endl;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
@@ -569,12 +569,12 @@ namespace ZL
|
||||
}
|
||||
|
||||
menuManager.startGameFunc = [this]() {
|
||||
currentLocation = locations["location_dorm"];
|
||||
currentLocation->scriptEngine.callLocationEnterCallback();
|
||||
gameState.currentLocationName = "location_dorm";
|
||||
currentLocation()->scriptEngine.callLocationEnterCallback();
|
||||
};
|
||||
|
||||
// Wire HP-change callbacks so all player instances update the health bar HUD.
|
||||
for (auto& [name, loc] : locations) {
|
||||
for (auto& [name, loc] : gameState.locations) {
|
||||
if (loc->player) {
|
||||
loc->player->state.onHpChanged = [this](float hp, float maxHp) {
|
||||
menuManager.updateHealthBar(hp, maxHp);
|
||||
@@ -608,9 +608,9 @@ namespace ZL
|
||||
|
||||
if (!menuManager.cutsceneHudActive_)
|
||||
menuManager.uiManager.draw(renderer);
|
||||
if (currentLocation)
|
||||
if (currentLocation())
|
||||
{
|
||||
currentLocation->dialogueSystem.draw(renderer);
|
||||
currentLocation()->dialogueSystem.draw(renderer);
|
||||
}
|
||||
glEnable(GL_BLEND);
|
||||
menuManager.topUiManager.draw(renderer);
|
||||
@@ -635,30 +635,31 @@ namespace ZL
|
||||
}
|
||||
else
|
||||
{
|
||||
if (currentLocation)
|
||||
Location* loc = currentLocation();
|
||||
if (loc)
|
||||
{
|
||||
// Sync global flags so Location's draw functions see them.
|
||||
currentLocation->state.isDarklands = isDarklands;
|
||||
currentLocation->state.isNight = menuManager.isNight;
|
||||
currentLocation->state.isDawn = menuManager.isDawn;
|
||||
loc->state.isDarklands = gameState.isDarklands;
|
||||
loc->state.isNight = gameState.isNight;
|
||||
loc->state.isDawn = gameState.isDawn;
|
||||
|
||||
if (isDarklands) {
|
||||
currentLocation->drawGameDarklands();
|
||||
if (gameState.isDarklands) {
|
||||
loc->drawGameDarklands();
|
||||
CheckGlError(__FILE__, __LINE__);
|
||||
}
|
||||
else if (menuManager.isNight) {
|
||||
currentLocation->drawGameNight();
|
||||
else if (gameState.isNight) {
|
||||
loc->drawGameNight();
|
||||
CheckGlError(__FILE__, __LINE__);
|
||||
}
|
||||
else if (currentLocation->shadowMap) {
|
||||
else if (loc->shadowMap) {
|
||||
CheckGlError(__FILE__, __LINE__);
|
||||
currentLocation->drawShadowDepthPass();
|
||||
loc->drawShadowDepthPass();
|
||||
CheckGlError(__FILE__, __LINE__);
|
||||
currentLocation->drawGameWithShadows();
|
||||
loc->drawGameWithShadows();
|
||||
CheckGlError(__FILE__, __LINE__);
|
||||
}
|
||||
else {
|
||||
currentLocation->drawGame();
|
||||
loc->drawGame();
|
||||
CheckGlError(__FILE__, __LINE__);
|
||||
}
|
||||
}
|
||||
@@ -838,9 +839,9 @@ namespace ZL
|
||||
if (!menuManager.isMainMenuOpen())
|
||||
menuManager.update(static_cast<float>(delta));
|
||||
|
||||
if (currentLocation)
|
||||
if (currentLocation())
|
||||
{
|
||||
currentLocation->update(delta);
|
||||
currentLocation()->update(delta);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -928,8 +929,8 @@ namespace ZL
|
||||
else if (event.button.button == SDL_BUTTON_RIGHT
|
||||
&& event.type == SDL_MOUSEBUTTONUP
|
||||
&& editorMode == EditorMode::Navigation
|
||||
&& currentLocation) {
|
||||
currentLocation->editor.handleRightClick();
|
||||
&& currentLocation()) {
|
||||
currentLocation()->editor.handleRightClick();
|
||||
}
|
||||
}
|
||||
else if (event.type == SDL_MOUSEMOTION) {
|
||||
@@ -956,7 +957,7 @@ namespace ZL
|
||||
}
|
||||
std::cout << "Current zoom: " << Environment::zoom << std::endl;
|
||||
// Tutorial step3 → step4: any mouse-wheel scroll counts as "zoom gesture".
|
||||
if (menuManager.tutorialStep == TutorialStep::Step3) {
|
||||
if (gameState.tutorialStep == TutorialStep::Step3) {
|
||||
menuManager.advanceTutorialStep();
|
||||
}
|
||||
}
|
||||
@@ -964,32 +965,27 @@ namespace ZL
|
||||
if (event.type == SDL_KEYDOWN && event.key.repeat == 0) {
|
||||
switch (event.key.keysym.sym) {
|
||||
case SDLK_8:
|
||||
if (editorMode == EditorMode::InteractiveObjects && currentLocation) {
|
||||
currentLocation->editor.selectInteractiveObject(8);
|
||||
if (editorMode == EditorMode::InteractiveObjects && currentLocation()) {
|
||||
currentLocation()->editor.selectInteractiveObject(8);
|
||||
} else {
|
||||
menuManager.isDawn = !menuManager.isDawn;
|
||||
if (menuManager.isDawn) menuManager.isNight = true;
|
||||
gameState.isDawn = !gameState.isDawn;
|
||||
if (gameState.isDawn) gameState.isNight = true;
|
||||
}
|
||||
break;
|
||||
case SDLK_9:
|
||||
if (editorMode == EditorMode::InteractiveObjects && currentLocation) {
|
||||
currentLocation->editor.selectInteractiveObject(9);
|
||||
if (editorMode == EditorMode::InteractiveObjects && currentLocation()) {
|
||||
currentLocation()->editor.selectInteractiveObject(9);
|
||||
} else {
|
||||
startNightTransition();
|
||||
/*if (menuManager.isDawn) {
|
||||
menuManager.isDawn = false; // step back: dawn → plain night
|
||||
} else {
|
||||
menuManager.isNight = !menuManager.isNight;
|
||||
}*/
|
||||
}
|
||||
break;
|
||||
case SDLK_0:
|
||||
|
||||
if (editorMode == EditorMode::InteractiveObjects && currentLocation) {
|
||||
currentLocation->editor.selectInteractiveObject(event.key.keysym.sym - SDLK_0);
|
||||
|
||||
if (editorMode == EditorMode::InteractiveObjects && currentLocation()) {
|
||||
currentLocation()->editor.selectInteractiveObject(event.key.keysym.sym - SDLK_0);
|
||||
}
|
||||
else {
|
||||
currentLocation->requestDarklandsTransition();
|
||||
currentLocation()->requestDarklandsTransition();
|
||||
}
|
||||
break;
|
||||
case SDLK_1:
|
||||
@@ -999,21 +995,21 @@ namespace ZL
|
||||
case SDLK_5:
|
||||
case SDLK_6:
|
||||
case SDLK_7:
|
||||
|
||||
if (editorMode == EditorMode::InteractiveObjects && currentLocation) {
|
||||
currentLocation->editor.selectInteractiveObject(event.key.keysym.sym - SDLK_0);
|
||||
|
||||
if (editorMode == EditorMode::InteractiveObjects && currentLocation()) {
|
||||
currentLocation()->editor.selectInteractiveObject(event.key.keysym.sym - SDLK_0);
|
||||
} else {
|
||||
currentLocation->switchNavigation(event.key.keysym.sym - SDLK_0);
|
||||
currentLocation()->switchNavigation(event.key.keysym.sym - SDLK_0);
|
||||
std::cout << "Switched to nav mesh " << (event.key.keysym.sym - SDLK_0) << std::endl;
|
||||
}
|
||||
break;
|
||||
case SDLK_f:
|
||||
currentLocation->dialogueSystem.startDialogue("phone_night_aiperi001");
|
||||
currentLocation()->dialogueSystem.startDialogue("phone_night_aiperi001");
|
||||
|
||||
|
||||
break;
|
||||
case SDLK_e:
|
||||
currentLocation->dialogueSystem.startCutscene("computer_cutscene001"); //.startDialogue("test_cutscene_pan_dialogue");
|
||||
currentLocation()->dialogueSystem.startCutscene("computer_cutscene001"); //.startDialogue("test_cutscene_pan_dialogue");
|
||||
break;
|
||||
|
||||
|
||||
@@ -1024,12 +1020,12 @@ namespace ZL
|
||||
editorMode = EditorMode::InteractiveObjects;
|
||||
else
|
||||
editorMode = EditorMode::None;
|
||||
if (currentLocation) {
|
||||
currentLocation->editorMode = editorMode;
|
||||
if (currentLocation()) {
|
||||
currentLocation()->editorMode = editorMode;
|
||||
if (editorMode == EditorMode::Navigation)
|
||||
currentLocation->editor.buildNavMeshes();
|
||||
currentLocation()->editor.buildNavMeshes();
|
||||
else if (editorMode == EditorMode::InteractiveObjects)
|
||||
currentLocation->editor.buildInteractiveObjectBoundsMeshes();
|
||||
currentLocation()->editor.buildInteractiveObjectBoundsMeshes();
|
||||
}
|
||||
{
|
||||
const char* modeName = (editorMode == EditorMode::Navigation) ? "Navigation"
|
||||
@@ -1055,15 +1051,15 @@ namespace ZL
|
||||
//std::cout << "current y: " << y << std::endl;
|
||||
//y = y - 0.002;
|
||||
|
||||
std::cout << "Player pos: " << currentLocation->player->state.position.transpose() << std::endl;
|
||||
std::cout << "Player pos: " << currentLocation()->player->state.position.transpose() << std::endl;
|
||||
//currentLocation->npcs[0]->walkSpeed -= 0.01f;
|
||||
//std::cout << "Walk speed: " << currentLocation->npcs[0]->walkSpeed << std::endl;
|
||||
break;
|
||||
|
||||
case SDLK_p:
|
||||
currentLocation = locations["uni_interior"];
|
||||
currentLocation->player->state.position = Eigen::Vector3f(-0.0189243, 0, -13.4314);
|
||||
currentLocation->player->setTarget(currentLocation->player->state.position);
|
||||
gameState.currentLocationName = "uni_interior";
|
||||
currentLocation()->player->state.position = Eigen::Vector3f(-0.0189243, 0, -13.4314);
|
||||
currentLocation()->player->setTarget(currentLocation()->player->state.position);
|
||||
//std::cout << "Switched to location " << ((currentLocation == locations["location1"]) ? "1" : "2") << std::endl;
|
||||
break;
|
||||
|
||||
@@ -1071,8 +1067,8 @@ namespace ZL
|
||||
//x = x - 1;
|
||||
//std::cout << "current x: " << x << std::endl;
|
||||
|
||||
std::cout << "Azimuth: " << currentLocation->state.cameraAzimuth << std::endl;
|
||||
std::cout << "Inclination: " << currentLocation->state.cameraInclination << std::endl;
|
||||
std::cout << "Azimuth: " << currentLocation()->state.cameraAzimuth << std::endl;
|
||||
std::cout << "Inclination: " << currentLocation()->state.cameraInclination << std::endl;
|
||||
break;
|
||||
|
||||
case SDLK_c:
|
||||
@@ -1086,22 +1082,22 @@ namespace ZL
|
||||
break;
|
||||
|
||||
case SDLK_b:
|
||||
if (editorMode != EditorMode::None && currentLocation) {
|
||||
currentLocation->editor.saveAll();
|
||||
if (editorMode != EditorMode::None && currentLocation()) {
|
||||
currentLocation()->editor.saveAll();
|
||||
}
|
||||
break;
|
||||
|
||||
case SDLK_j:
|
||||
if (editorMode != EditorMode::None && currentLocation) {
|
||||
currentLocation->editor.placeTree();
|
||||
if (editorMode != EditorMode::None && currentLocation()) {
|
||||
currentLocation()->editor.placeTree();
|
||||
} else {
|
||||
menuManager.toggleQuestJournal();
|
||||
}
|
||||
break;
|
||||
|
||||
case SDLK_v:
|
||||
if (editorMode != EditorMode::None && currentLocation) {
|
||||
currentLocation->editor.saveObjects();
|
||||
if (editorMode != EditorMode::None && currentLocation()) {
|
||||
currentLocation()->editor.saveObjects();
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1152,13 +1148,13 @@ namespace ZL
|
||||
}
|
||||
|
||||
void Game::activateSlowMoEffect() {
|
||||
if (!currentLocation) return;
|
||||
if (!currentLocation()) return;
|
||||
|
||||
if (currentLocation->player) {
|
||||
currentLocation->player->state.slowMoTimeRemaining = currentLocation->player->state.slowMoActiveTime;
|
||||
if (currentLocation()->player) {
|
||||
currentLocation()->player->state.slowMoTimeRemaining = currentLocation()->player->state.slowMoActiveTime;
|
||||
}
|
||||
|
||||
for (auto& npc : currentLocation->npcs) {
|
||||
for (auto& npc : currentLocation()->npcs) {
|
||||
if (npc) {
|
||||
npc->state.slowMoTimeRemaining = npc->state.slowMoActiveTime;
|
||||
}
|
||||
@@ -1168,25 +1164,25 @@ namespace ZL
|
||||
void Game::enterCameraDragMode(int eventX, int eventY)
|
||||
{
|
||||
cameraDragging = true;
|
||||
if (currentLocation) {
|
||||
currentLocation->cameraDragging = true;
|
||||
if (currentLocation()) {
|
||||
currentLocation()->cameraDragging = true;
|
||||
// Anchor on the *current* position, not the original press, so the
|
||||
// camera doesn't snap by however far the finger drifted before the
|
||||
// movement threshold was crossed.
|
||||
currentLocation->lastMouseX = eventX;
|
||||
currentLocation->lastMouseY = eventY;
|
||||
currentLocation()->lastMouseX = eventX;
|
||||
currentLocation()->lastMouseY = eventY;
|
||||
|
||||
// Snapshot current angles so we can measure how far the user rotates.
|
||||
dragStartAzimuth = currentLocation->state.cameraAzimuth;
|
||||
dragStartInclination = currentLocation->state.cameraInclination;
|
||||
dragStartAzimuth = currentLocation()->state.cameraAzimuth;
|
||||
dragStartInclination = currentLocation()->state.cameraInclination;
|
||||
}
|
||||
}
|
||||
|
||||
void Game::exitCameraDragMode()
|
||||
{
|
||||
cameraDragging = false;
|
||||
if (currentLocation) {
|
||||
currentLocation->cameraDragging = false;
|
||||
if (currentLocation()) {
|
||||
currentLocation()->cameraDragging = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1237,7 +1233,7 @@ namespace ZL
|
||||
Environment::zoom = newZoom;
|
||||
|
||||
// Tutorial step3 → step4: detect a significant pinch-zoom (≥ 2 zoom units).
|
||||
if (menuManager.tutorialStep == TutorialStep::Step3) {
|
||||
if (gameState.tutorialStep == TutorialStep::Step3) {
|
||||
if (std::abs(Environment::zoom - pinchStartZoom) >= 2.0f) {
|
||||
menuManager.advanceTutorialStep();
|
||||
}
|
||||
@@ -1263,7 +1259,7 @@ namespace ZL
|
||||
const int uiY = Environment::projectionHeight - my;
|
||||
menuManager.topUiManager.onTouchDown(fingerId, uiX, uiY);
|
||||
const bool capturedByTopUi = menuManager.topUiManager.isUiInteractionForFinger(fingerId);
|
||||
const bool dialogueActive = currentLocation && currentLocation->dialogueSystem.isActive();
|
||||
const bool dialogueActive = currentLocation() && currentLocation()->dialogueSystem.isActive();
|
||||
if (!dialogueActive && !capturedByTopUi) {
|
||||
menuManager.uiManager.onTouchDown(fingerId, uiX, uiY);
|
||||
}
|
||||
@@ -1299,7 +1295,7 @@ namespace ZL
|
||||
const int uiX = mx;
|
||||
const int uiY = Environment::projectionHeight - my;
|
||||
menuManager.topUiManager.onTouchUp(fingerId, uiX, uiY);
|
||||
const bool dialogueActive = currentLocation && currentLocation->dialogueSystem.isActive();
|
||||
const bool dialogueActive = currentLocation() && currentLocation()->dialogueSystem.isActive();
|
||||
if (!dialogueActive) {
|
||||
menuManager.uiManager.onTouchUp(fingerId, uiX, uiY);
|
||||
}
|
||||
@@ -1334,8 +1330,8 @@ namespace ZL
|
||||
|
||||
// Tap → walk-to / interact, using the original press coords so the target
|
||||
// isn't shifted by tiny finger drift before release.
|
||||
if (currentLocation) {
|
||||
currentLocation->handleDown(fingerId, st.downEventX, st.downEventY, st.downMx, st.downMy);
|
||||
if (currentLocation()) {
|
||||
currentLocation()->handleDown(fingerId, st.downEventX, st.downEventY, st.downMx, st.downMy);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1344,7 +1340,7 @@ namespace ZL
|
||||
const int uiX = mx;
|
||||
const int uiY = Environment::projectionHeight - my;
|
||||
menuManager.topUiManager.onTouchMove(fingerId, uiX, uiY);
|
||||
const bool dialogueActive = currentLocation && currentLocation->dialogueSystem.isActive();
|
||||
const bool dialogueActive = currentLocation() && currentLocation()->dialogueSystem.isActive();
|
||||
if (!dialogueActive) {
|
||||
menuManager.uiManager.onTouchMove(fingerId, uiX, uiY);
|
||||
}
|
||||
@@ -1373,18 +1369,18 @@ namespace ZL
|
||||
}
|
||||
}
|
||||
|
||||
if (currentLocation) {
|
||||
if (currentLocation()) {
|
||||
// Forwarded for dialogue hover and (when cameraDragging) camera rotation.
|
||||
currentLocation->handleMotion(fingerId, eventX, eventY, mx, my);
|
||||
currentLocation()->handleMotion(fingerId, eventX, eventY, mx, my);
|
||||
|
||||
// Tutorial step1 → step2: detect a significant camera rotation on BOTH axes.
|
||||
// ~0.15 rad (≈8.6°) per axis ensures the user intentionally panned in 2D,
|
||||
// not just nudged a single axis by accident.
|
||||
static constexpr float TUTORIAL_ROTATION_THRESHOLD = 0.15f;
|
||||
if (cameraDragging
|
||||
&& menuManager.tutorialStep == TutorialStep::Step1) {
|
||||
float deltaAz = std::abs(currentLocation->state.cameraAzimuth - dragStartAzimuth);
|
||||
float deltaInc = std::abs(currentLocation->state.cameraInclination - dragStartInclination);
|
||||
&& gameState.tutorialStep == TutorialStep::Step1) {
|
||||
float deltaAz = std::abs(currentLocation()->state.cameraAzimuth - dragStartAzimuth);
|
||||
float deltaInc = std::abs(currentLocation()->state.cameraInclination - dragStartInclination);
|
||||
if (deltaAz >= TUTORIAL_ROTATION_THRESHOLD && deltaInc >= TUTORIAL_ROTATION_THRESHOLD) {
|
||||
menuManager.advanceTutorialStep();
|
||||
}
|
||||
@@ -1394,15 +1390,15 @@ namespace ZL
|
||||
|
||||
bool Game::startDarklandsTransition()
|
||||
{
|
||||
if (!menuManager.isNight)
|
||||
if (!gameState.isNight)
|
||||
{
|
||||
currentLocation->dialogueSystem.startDialogue("darklands_day_dialog001");
|
||||
currentLocation()->dialogueSystem.startDialogue("darklands_day_dialog001");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (menuManager.isDawn)
|
||||
if (gameState.isDawn)
|
||||
{
|
||||
currentLocation->dialogueSystem.startDialogue("darklands_morning_dialog001");
|
||||
currentLocation()->dialogueSystem.startDialogue("darklands_morning_dialog001");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1434,25 +1430,24 @@ namespace ZL
|
||||
darklandsFlashAlpha = min(darklandsFlashAlpha + step, 1.0f);
|
||||
if (darklandsFlashAlpha >= 1.0f) {
|
||||
if (isNightTransition) {
|
||||
menuManager.isNight = !menuManager.isNight;
|
||||
if (currentLocation)
|
||||
gameState.isNight = !gameState.isNight;
|
||||
if (currentLocation())
|
||||
{
|
||||
//currentLocation->dialogueSystem.startDialogue("dialog_video001");
|
||||
currentLocation->state.isNight = menuManager.isNight;
|
||||
currentLocation->scriptEngine.callTriggerNightEnterCallback();
|
||||
currentLocation()->state.isNight = gameState.isNight;
|
||||
currentLocation()->scriptEngine.callTriggerNightEnterCallback();
|
||||
}
|
||||
} else {
|
||||
isDarklands = !isDarklands;
|
||||
gameState.isDarklands = !gameState.isDarklands;
|
||||
|
||||
// Change HUD
|
||||
menuManager.setDarklandsMode(isDarklands);
|
||||
menuManager.setDarklandsMode(gameState.isDarklands);
|
||||
|
||||
if (currentLocation) {
|
||||
currentLocation->state.isDarklands = isDarklands;
|
||||
if (isDarklands)
|
||||
currentLocation->scriptEngine.callDarklandsEnterCallback();
|
||||
if (currentLocation()) {
|
||||
currentLocation()->state.isDarklands = gameState.isDarklands;
|
||||
if (gameState.isDarklands)
|
||||
currentLocation()->scriptEngine.callDarklandsEnterCallback();
|
||||
else
|
||||
currentLocation->scriptEngine.callDarklandsExitCallback();
|
||||
currentLocation()->scriptEngine.callDarklandsExitCallback();
|
||||
}
|
||||
}
|
||||
darklandsFlashFadingIn = false;
|
||||
|
||||
Reference in new issue
Block a user