From 61d806a7a1c3c7a969182af009b35292da4719cd Mon Sep 17 00:00:00 2001 From: Vladislav Khorev Date: Sun, 19 Apr 2026 20:00:15 +0300 Subject: [PATCH 1/2] Added more dialogs, some minor tweaks --- resources/dialogue/sample_dialogues.json | 351 ++++++++++++++++++++++- resources/e/menu/about.png | 4 +- resources/loading.png | 4 +- src/Environment.h | 2 +- src/Game.cpp | 6 +- src/Location.cpp | 45 +-- src/Location.h | 2 +- src/dialogue/DialogueSystem.h | 2 +- 8 files changed, 376 insertions(+), 40 deletions(-) diff --git a/resources/dialogue/sample_dialogues.json b/resources/dialogue/sample_dialogues.json index 00f9b0b..82df86a 100644 --- a/resources/dialogue/sample_dialogues.json +++ b/resources/dialogue/sample_dialogues.json @@ -9,7 +9,7 @@ "type": "Line", "speaker": "Милиция", "portrait": "resources/ghost_avatar.png", - "text": "Автомобиль 256 остановитесь немедленно!", + "text": "Белый седан 256 остановитесь немедленно!", "next": "end_1" }, { @@ -551,14 +551,108 @@ "text": "Старший лейтенант Каримов, отдел милиции Чуйской области.", "next": "line_2" }, - { + { "id": "line_2", "type": "Line", "speaker": "Hero", "portrait": "resources/hero.png", - "text": "Я задержан?", - "next": "end_1" + "text": "Предъявите ваши права.", + "next": "line_3" }, + { + "id": "line_3", + "type": "Line", + "speaker": "Hero", + "portrait": "resources/hero.png", + "text": "Вот, пожалуйста.", + "next": "line_4" + }, + { + "id": "line_4", + "type": "Line", + "speaker": "Hero", + "portrait": "resources/hero.png", + "text": "Алексей Смирнов, да?", + "next": "line_5" + }, + { + "id": "line_5", + "type": "Line", + "speaker": "Hero", + "portrait": "resources/hero.png", + "text": "Когда в последний раз проходили техосмотр?", + "next": "line_6" + }, + { + "id": "line_6", + "type": "Line", + "speaker": "Hero", + "portrait": "resources/hero.png", + "text": "В прошлом году.", + "next": "line_7" + }, + { + "id": "line_7", + "type": "Line", + "speaker": "Hero", + "portrait": "resources/hero.png", + "text": "Страховка у вас есть?", + "next": "line_8" + }, + { + "id": "line_8", + "type": "Line", + "speaker": "Hero", + "portrait": "resources/hero.png", + "text": "Да, вот, до ноября.", + "next": "line_9" + }, + { + "id": "line_9", + "type": "Line", + "speaker": "Hero", + "portrait": "resources/hero.png", + "text": "А огнетушитель в машине есть?", + "next": "line_10" + }, + { + "id": "line_10", + "type": "Line", + "speaker": "Hero", + "portrait": "resources/hero.png", + "text": "*Да он просто тянет время!*", + "next": "line_11" + }, + { + "id": "line_11", + "type": "Line", + "speaker": "Hero", + "portrait": "resources/hero.png", + "text": "Давайте напрямую, я задержан или нет?", + "next": "line_12" + }, + { + "id": "line_12", + "type": "Line", + "speaker": "Hero", + "portrait": "resources/hero.png", + "text": "Нет...", + "next": "line_13" + },{ + "id": "line_13", + "type": "Line", + "speaker": "Hero", + "portrait": "resources/hero.png", + "text": "Если не отпустите меня сейчас, я позвоню в прокуратуру.", + "next": "line_14" + },{ + "id": "line_14", + "type": "Line", + "speaker": "Hero", + "portrait": "resources/hero.png", + "text": ".. Счастливого пути!", + "next": "end_1" + } { "id": "end_1", "type": "End" @@ -646,7 +740,55 @@ "type": "Line", "speaker": "Игрок", "portrait": "resources/hero.png", - "text": "Быстро прыгай в окно, я открою.", + "text": "Алтынай ты тут?", + "next": "line_2" + }, + { + "id": "line_2", + "type": "Line", + "speaker": "Игрок", + "portrait": "resources/hero.png", + "text": "Да, я тут!", + "next": "line_3" + }, + { + "id": "line_3", + "type": "Line", + "speaker": "Игрок", + "portrait": "resources/hero.png", + "text": "Где твоя машина припаркована?", + "next": "line_4" + }, + { + "id": "line_4", + "type": "Line", + "speaker": "Игрок", + "portrait": "resources/hero.png", + "text": "Прямо тут, недалеко.", + "next": "line_5" + }, + { + "id": "line_5", + "type": "Line", + "speaker": "Игрок", + "portrait": "resources/hero.png", + "text": "Давай отведи меня в машину, только тихо!", + "next": "line_6" + }, + { + "id": "line_6", + "type": "Line", + "speaker": "Игрок", + "portrait": "resources/hero.png", + "text": "Постарайся не попадаться на глаза бандитам!", + "next": "line_7" + }, + { + "id": "line_7", + "type": "Line", + "speaker": "Игрок", + "portrait": "resources/hero.png", + "text": "Я прыгаю!", "next": "end_1" }, { @@ -664,7 +806,87 @@ "type": "Line", "speaker": "Игрок", "portrait": "resources/hero.png", - "text": "Мне лучше поехать туда на авто.", + "text": "*Моя подруга Алтынай пропала сегодня.*", + "next": "line_2" + }, + { + "id": "line_2", + "type": "Line", + "speaker": "Игрок", + "portrait": "resources/hero.png", + "text": "*А потом я получил голосовое сообщение от нее.*", + "next": "line_3" + }, + { + "id": "line_3", + "type": "Line", + "speaker": "Игрок", + "portrait": "resources/hero.png", + "text": "Если ты это слушаешь, то случилась беда.", + "next": "line_4" + }, + { + "id": "line_4", + "type": "Line", + "speaker": "Игрок", + "portrait": "resources/hero.png", + "text": "Ко мне сватался Нурланбай, местный бизнесмен и авторитет.", + "next": "line_5" + }, + { + "id": "line_5", + "type": "Line", + "speaker": "Игрок", + "portrait": "resources/hero.png", + "text": "Он мне обещал, что похитит меня, и сегодня он сделал это.", + "next": "line_6" + }, + { + "id": "line_6", + "type": "Line", + "speaker": "Игрок", + "portrait": "resources/hero.png", + "text": "Я отправила тебе координаты дома, куда могут меня спрятать.", + "next": "line_7" + }, + { + "id": "line_7", + "type": "Line", + "speaker": "Игрок", + "portrait": "resources/hero.png", + "text": "Не обращайся в милицию, у него есть связи в МВД Чуйской области.", + "next": "line_8" + }, + { + "id": "line_8", + "type": "Line", + "speaker": "Игрок", + "portrait": "resources/hero.png", + "text": "Приезжай на своей машине и помоги мне сбежать оттуда!", + "next": "line_9" + }, + { + "id": "line_9", + "type": "Line", + "speaker": "Игрок", + "portrait": "resources/hero.png", + "text": "Мне больше не к кому обращаться. Я жду тебя!", + "next": "line_10" + }, + { + "id": "line_10", + "type": "Line", + "speaker": "Игрок", + "portrait": "resources/hero.png", + "text": "*Село где держат Алтынай, находится впереди по трассе.*", + "next": "line_11" + }, + { + "id": "line_11", + "type": "Line", + "speaker": "Игрок", + "portrait": "resources/hero.png", + "text": "*Пора садится в машину и отправляться в путь!*", "next": "end_1" }, { @@ -682,7 +904,31 @@ "type": "Line", "speaker": "Игрок", "portrait": "resources/hero.png", - "text": "Да, похоже это как раз тот дом.", + "text": "*Вот этот дом, с охраной!*", + "next": "line_2" + }, + { + "id": "line_2", + "type": "Line", + "speaker": "Игрок", + "portrait": "resources/hero.png", + "text": "*Нужно держаться от этого бандита подальше!*", + "next": "line_3" + }, + { + "id": "line_3", + "type": "Line", + "speaker": "Игрок", + "portrait": "resources/hero.png", + "text": "*Если этот бандит меня заметит, он меня убьет!*", + "next": "line_4" + }, + { + "id": "line_4", + "type": "Line", + "speaker": "Игрок", + "portrait": "resources/hero.png", + "text": "*Может стоит прократься мимо него и осмотреть дом сзади?*", "next": "end_1" }, { @@ -700,7 +946,62 @@ "type": "Line", "speaker": "Игрок", "portrait": "resources/hero.png", - "text": "Финал 1", + "text": "Что сидишь, поехали!", + "next": "line_2" + }, + { + "id": "line_2", + "type": "Line", + "speaker": "Игрок", + "portrait": "resources/hero.png", + "text": "Дави по газам быстрее пока они нас не заметили!", + "next": "line_3" + }, + { + "id": "line_3", + "type": "Line", + "speaker": "Игрок", + "portrait": "resources/hero.png", + "text": "Конечно, сейчас...", + "next": "line_4" + }, + { + "id": "line_4", + "type": "Line", + "speaker": "Игрок", + "portrait": "resources/hero.png", + "text": "Спасибо что помог мне!", + "next": "line_5" + }, + { + "id": "line_5", + "type": "Line", + "speaker": "Игрок", + "portrait": "resources/hero.png", + "text": "Этот Нурланбай сумасшедший!", + "next": "line_6" + }, + { + "id": "line_6", + "type": "Line", + "speaker": "Игрок", + "portrait": "resources/hero.png", + "text": "Он владелец сети заправок, а еще свою банду собрал.", + "next": "line_7" + },{ + "id": "line_7", + "type": "Line", + "speaker": "Игрок", + "portrait": "resources/hero.png", + "text": "У него друг начальник милиции Чуйской области.", + "next": "line_8" + }, + { + "id": "line_8", + "type": "Line", + "speaker": "Игрок", + "portrait": "resources/hero.png", + "text": "Но я не выйду за него, пусть он сдохнет!", "next": "end_1" }, { @@ -718,7 +1019,39 @@ "type": "Line", "speaker": "Игрок", "portrait": "resources/hero.png", - "text": "Финал 2", + "text": "А куда мы поедем?", + "next": "line_2" + }, + { + "id": "line_2", + "type": "Line", + "speaker": "Игрок", + "portrait": "resources/hero.png", + "text": "Давай в Талас.", + "next": "line_3" + }, + { + "id": "line_3", + "type": "Line", + "speaker": "Игрок", + "portrait": "resources/hero.png", + "text": "Там у меня есть дядя в администрации области.", + "next": "line_4" + }, + { + "id": "line_4", + "type": "Line", + "speaker": "Игрок", + "portrait": "resources/hero.png", + "text": "Я у него спрячусь, и никакой Нурланбай нас там не достанет.", + "next": "line_5" + }, + { + "id": "line_5", + "type": "Line", + "speaker": "Игрок", + "portrait": "resources/hero.png", + "text": "Надо только доехать хотя бы до границы области.", "next": "end_1" }, { diff --git a/resources/e/menu/about.png b/resources/e/menu/about.png index 9db38fd..468c4f5 100644 --- a/resources/e/menu/about.png +++ b/resources/e/menu/about.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ca305c611f142e22487fd99cb3c4791dbc07c09b0191e1904cd27d9c93dd0f96 -size 42502 +oid sha256:0227bec93b6f05d913d385a600810e919b1fadc00dfdd3a328885527d9a7fe0e +size 42630 diff --git a/resources/loading.png b/resources/loading.png index 72f06b9..3ce1a98 100644 --- a/resources/loading.png +++ b/resources/loading.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:09efb1e5ca09a8ee95dbd5a42a73de6e02dce738457a13491f2c156881b6f4ff -size 45290 +oid sha256:61036ed35e803aa301c605f226189ab86a9d2af65168535197a0b4b700effa3a +size 45484 diff --git a/src/Environment.h b/src/Environment.h index d564f20..d79bb48 100644 --- a/src/Environment.h +++ b/src/Environment.h @@ -15,7 +15,7 @@ namespace ZL { using std::max; #endif - constexpr float DEFAULT_ZOOM = 4.f; + constexpr float DEFAULT_ZOOM = 5.f; class Environment { public: diff --git a/src/Game.cpp b/src/Game.cpp index f98a625..0eac095 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -127,7 +127,7 @@ namespace ZL #ifdef EMSCRIPTEN renderer.shaderManager.AddShaderFromFiles("env_sky", "resources/shaders/env_sky.vertex", "resources/shaders/env_sky_web.fragment", CONST_ZIP_FILE); - renderer.shaderManager.AddShaderFromFiles("defaultAtmosphere", "resources/shaders/defaultAtmosphere.vertex", "resources/shaders/defaultAtmosphere_web.fragment", CONST_ZIP_FILE); + renderer.shcuaderManager.AddShaderFromFiles("defaultAtmosphere", "resources/shaders/defaultAtmosphere.vertex", "resources/shaders/defaultAtmosphere_web.fragment", CONST_ZIP_FILE); renderer.shaderManager.AddShaderFromFiles("planetBake", "resources/shaders/planet_bake.vertex", "resources/shaders/planet_bake_web.fragment", CONST_ZIP_FILE); renderer.shaderManager.AddShaderFromFiles("planetStone", "resources/shaders/planet_stone.vertex", "resources/shaders/planet_stone_web.fragment", CONST_ZIP_FILE); renderer.shaderManager.AddShaderFromFiles("planetLand", "resources/shaders/planet_land.vertex", "resources/shaders/planet_land_web.fragment", CONST_ZIP_FILE); @@ -578,13 +578,13 @@ namespace ZL break;*/ case SDLK_c: { - if (menuManager.getState() == GameState::Gameplay) { + /*if (menuManager.getState() == GameState::Gameplay) { std::cout << "[GAME] Location change triggered by key press" << std::endl; static size_t locIndex = 0; static std::vector locations = {"forest", "barn", "default"}; locIndex = (locIndex + 1) % locations.size(); changeLocation(locations[locIndex]); - } + }*/ break; } case SDLK_f: diff --git a/src/Location.cpp b/src/Location.cpp index d099145..fd18f20 100644 --- a/src/Location.cpp +++ b/src/Location.cpp @@ -78,6 +78,7 @@ void Location::setup() player->isPlayer = true; player->modelCorrectionRotation = Eigen::Quaternionf(Eigen::AngleAxisf(M_PI, Eigen::Vector3f::UnitY())); + //player->position = { 9.43527, 0, 0.952688 }; //player->setTarget(player->position); @@ -320,11 +321,11 @@ void Location::setup() bandit->position = Vector3f{ 12.1782, 0, 62.4014 }; bandit->setTarget(bandit->position); - carPosition = { -6.61929, 0, -30.7197 }; + carPosition = { -6.61929, 0, -30.7197-300 }; carRotation = M_PI; npcCar.position = Vector3f{ 7.1782, 0, 68.4014 }; - player->position = { -6.61929, 0, -40 }; + player->position = { -6.61929, 0, -40-300 }; player->setTarget(player->position); cameraAzimuth = M_PI; @@ -386,11 +387,13 @@ void Location::setup() carTexture = std::make_unique(CreateTextureDataFromPng("resources/e/car002.png", CONST_ZIP_FILE)); carMesh.data = LoadFromTextFile02("resources/e/car001.txt", CONST_ZIP_FILE); + carMesh.data.Scale(0.8f); carMesh.data.RotateByMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(M_PI * 0.5, Eigen::Vector3f::UnitY())).toRotationMatrix()); carMesh.RefreshVBO(); carWheelTexture = std::make_unique(CreateTextureDataFromPng("resources/e/Wheel_base002.png", CONST_ZIP_FILE)); carWheelMesh.data = LoadFromTextFile02("resources/e/car_wheel001.txt", CONST_ZIP_FILE); + carWheelMesh.data.Scale(0.8f); carWheelMesh.data.RotateByMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(M_PI * 0.5, Eigen::Vector3f::UnitY())).toRotationMatrix()); carWheelMesh.RefreshVBO(); @@ -698,14 +701,14 @@ void Location::setup() renderer.DrawVertexRenderStruct(carMesh); if (carWheelTexture) { - constexpr float track_width = 1.28f; - constexpr float wheel_base = 2.25f; - constexpr float shift = 0.6f; + constexpr float track_width = 1.28f * 0.8f; + constexpr float wheel_base = 2.25f * 0.8f; + constexpr float shift = 0.6f * 0.8f; const Eigen::Vector3f wheelPositions[4] = { - Eigen::Vector3f( track_width, 0.f - 0.21, -(wheel_base + shift)+1.25), // front right - Eigen::Vector3f(-track_width, 0.f - 0.21, -(wheel_base + shift)+1.25), // front left - Eigen::Vector3f( track_width, 0.f - 0.21, (wheel_base - shift)+1.1), // rear right - Eigen::Vector3f(-track_width, 0.f - 0.21, (wheel_base - shift)+1.1) // rear left + Eigen::Vector3f( track_width, 0.f - 0.21, -(wheel_base + shift)+1.25*0.8), // front right + Eigen::Vector3f(-track_width, 0.f - 0.21, -(wheel_base + shift)+1.25*0.8), // front left + Eigen::Vector3f( track_width, 0.f - 0.21, (wheel_base - shift)+1.1*0.8), // rear right + Eigen::Vector3f(-track_width, 0.f - 0.21, (wheel_base - shift)+1.1*0.8) // rear left }; const bool isFront[4] = { true, true, false, false }; @@ -1398,17 +1401,17 @@ void Location::setup() if (player) { distanceRemaining += player->position.z() - playerPosBefore.z(); } - if (!dialoguePlayedDistance7000 && distanceRemaining < 7000.f / 5.f && !dialogueSystem.isActive()) { + if (!dialoguePlayedDistance7000 && distanceRemaining < 7000.f / 2.5f && !dialogueSystem.isActive()) { if (dialogueSystem.startDialogue("driving_dialogue_distance7000")) { dialoguePlayedDistance7000 = true; } } - if (!dialoguePlayedDistance5000 && distanceRemaining < 5000.f / 5.f && !dialogueSystem.isActive()) { + if (!dialoguePlayedDistance5000 && distanceRemaining < 5000.f / 2.5f && !dialogueSystem.isActive()) { if (dialogueSystem.startDialogue("driving_dialogue_distance5000")) { dialoguePlayedDistance5000 = true; } } - if (!dialoguePlayedDistance2000 && distanceRemaining < 2000.f / 5.f && !dialogueSystem.isActive()) { + if (!dialoguePlayedDistance2000 && distanceRemaining < 2000.f / 2.5f && !dialogueSystem.isActive()) { if (dialogueSystem.startDialogue("driving_dialogue_distance2000")) { dialoguePlayedDistance2000 = true; } @@ -1550,7 +1553,7 @@ void Location::setup() if (locationId == "default") { if (player && !dialoguePlayedVillageIntro1 && !dialogueSystem.isActive()) { - if (player->position.z() > -36.f) { + if (player->position.z() > -36.f - 300) { if (dialogueSystem.startDialogue("dialogue_village_intro1")) { dialoguePlayedVillageIntro1 = true; } @@ -1614,7 +1617,7 @@ void Location::setup() } } - if (player && !dialoguePlayedVillageFinal2 && !dialogueSystem.isActive()) { + if (player && !dialoguePlayedVillageFinal2 && !dialogueSystem.isActive() && dialoguePlayedVillageFinal1) { if (std::abs(player->position.z()) > 250.f) { if (dialogueSystem.startDialogue("dialogue_village_final2", [this]() { if (onLocationChangeRequest) onLocationChangeRequest("forest"); @@ -1870,14 +1873,14 @@ void Location::setup() renderer.DrawVertexRenderStruct(carMesh); if (carWheelTexture) { - constexpr float track_width = 1.28f; - constexpr float wheel_base = 2.25f; - constexpr float shift = 0.6f; + constexpr float track_width = 1.28f*0.8f; + constexpr float wheel_base = 2.25f * 0.8f; + constexpr float shift = 0.6f * 0.8f; const Eigen::Vector3f wheelPositions[4] = { - Eigen::Vector3f( track_width, 0.f - 0.21f, -(wheel_base + shift) + 1.25f), - Eigen::Vector3f(-track_width, 0.f - 0.21f, -(wheel_base + shift) + 1.25f), - Eigen::Vector3f( track_width, 0.f - 0.21f, (wheel_base - shift) + 1.1f), - Eigen::Vector3f(-track_width, 0.f - 0.21f, (wheel_base - shift) + 1.1f) + Eigen::Vector3f( track_width, 0.f - 0.21f, -(wheel_base + shift) + 1.25f * 0.8f), + Eigen::Vector3f(-track_width, 0.f - 0.21f, -(wheel_base + shift) + 1.25f * 0.8f), + Eigen::Vector3f( track_width, 0.f - 0.21f, (wheel_base - shift) + 1.1f * 0.8f), + Eigen::Vector3f(-track_width, 0.f - 0.21f, (wheel_base - shift) + 1.1f * 0.8f) }; const bool isFront[4] = { true, true, false, false }; diff --git a/src/Location.h b/src/Location.h index 1813319..f8e6d41 100644 --- a/src/Location.h +++ b/src/Location.h @@ -121,7 +121,7 @@ namespace ZL bool carOutOfGas = false; bool dialoguePlayedDrivingGasOut = false; - float distanceRemaining = 2000.f;//10000.0f; + float distanceRemaining = 4000.f;//10000.0f; bool dialoguePlayedDistance7000 = false; bool dialoguePlayedDistance5000 = false; bool dialoguePlayedDistance2000 = false; diff --git a/src/dialogue/DialogueSystem.h b/src/dialogue/DialogueSystem.h index 1d47db0..1f93aa9 100644 --- a/src/dialogue/DialogueSystem.h +++ b/src/dialogue/DialogueSystem.h @@ -21,7 +21,7 @@ struct TriggerZone { struct AutoSkipConfig { float baseDurationMs = 1200.0f; - float msPerCharacter = 45.0f; + float msPerCharacter = 25.0f; float minDurationMs = 1500.0f; }; From 28a3ace187bf6b10851c6ce2026569dccfbf0ad3 Mon Sep 17 00:00:00 2001 From: Vladislav Khorev Date: Sun, 19 Apr 2026 20:28:22 +0300 Subject: [PATCH 2/2] Add more dialogs logic --- resources/dialogue/sample_dialogues.json | 4 +- resources/hero.png | 4 +- resources/phone.png | 3 + src/Location.cpp | 78 +++++++++++++++++++++--- src/Location.h | 2 + 5 files changed, 80 insertions(+), 11 deletions(-) create mode 100644 resources/phone.png diff --git a/resources/dialogue/sample_dialogues.json b/resources/dialogue/sample_dialogues.json index 82df86a..5f512a3 100644 --- a/resources/dialogue/sample_dialogues.json +++ b/resources/dialogue/sample_dialogues.json @@ -369,7 +369,7 @@ "text": "У нас бензин кончается.", "next": "line_2" }, - { + { "id": "line_2", "type": "Line", "speaker": "Hero", @@ -652,7 +652,7 @@ "portrait": "resources/hero.png", "text": ".. Счастливого пути!", "next": "end_1" - } + }, { "id": "end_1", "type": "End" diff --git a/resources/hero.png b/resources/hero.png index 963e132..78e6b92 100644 --- a/resources/hero.png +++ b/resources/hero.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3e6fcd692f1217cbab79f0dfbbfa67b9c88fd03ae5875c74eebee8428e1428cf -size 74667 +oid sha256:50e72de3a8a096c82897cf23f302f8b8b9c6c135ae066c9022238d4ad59ff519 +size 56920 diff --git a/resources/phone.png b/resources/phone.png new file mode 100644 index 0000000..527d142 --- /dev/null +++ b/resources/phone.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:023000b7f6c4aff4106305692ddf0a6a6b6621cbe24b4ee0f0c2f3e338c5eee5 +size 2562 diff --git a/src/Location.cpp b/src/Location.cpp index fd18f20..ba7bb55 100644 --- a/src/Location.cpp +++ b/src/Location.cpp @@ -165,15 +165,16 @@ void Location::setup() police->position = Vector3f{ 1000, -0, 10 }; police->setTarget(police->position); + std::cout << "[LOCATION] Setting up FOREST location (custom models only)" << std::endl; - carPosition ={ 7, 0, -7 + 200 }; + carPosition ={ 7, 0, -7 + 300 }; npcCar.position = Vector3f(9, 0, -335) + Vector3f(1000,0,0); - girlfriend->position = Vector3f{ 5, 0, 0.9 + 200 }; + girlfriend->position = Vector3f{ 5, 0, 0.9 + 300 }; girlfriend->setTarget(girlfriend->position); - player->position = { 9.5, 0, 0.95 + 200 }; + player->position = { 9.5, 0, 0.95 + 300 }; player->setTarget(player->position); Vector3f azsShift = { -17,0,0 }; @@ -1327,7 +1328,9 @@ void Location::setup() if (girlfriendInCar) { if (!dialoguePlayedDrivingGas1 && !dialogueSystem.isActive()) { - if (dialogueSystem.startDialogue("driving_dialogue_gas1")) { + if (dialogueSystem.startDialogue("driving_dialogue_gas1", [this]() { + dialogueDrivingGas1Finished = true; + })) { dialoguePlayedDrivingGas1 = true; } } @@ -1456,6 +1459,35 @@ void Location::setup() if (locationId == "forest") { + // Loop the player back in Z until the driving-gas dialogue has been + // completed. Mirrors the village-intro loop in the "default" location, + // but inverted: spawn is at positive Z and the player drives toward Z-. + if (!dialogueDrivingGas1Finished) { + constexpr float tileSize = 100.0f; + constexpr float loopStartZ = -7.0f + 300.0f; + constexpr float loopForwardThreshold = loopStartZ - tileSize; + + const Eigen::Vector3f anchor = inCar + ? carPosition + : (player ? player->position : Eigen::Vector3f::Zero()); + + if (anchor.z() < loopForwardThreshold) { + const Eigen::Vector3f shift(0.f, 0.f, tileSize); + if (inCar) { + carPosition += shift; + if (player) player->position = carPosition; + } + else if (player) { + player->position += shift; + player->setTarget(player->position); + player->clearPath(); + } + if (npcCar.mode == NpcCar::Mode::FOLLOW_PLAYER || npcCar.mode == NpcCar::Mode::NONE_STAY) { + npcCar.position += shift; + } + } + } + // After the gas-station sale, once the player has walked away from the // salesperson, the girlfriend chimes in — fires once. if (!dialoguePlayedGirlfriend1 && dialoguePlayedGas1 && salesperson && player && !dialogueSystem.isActive()) { @@ -1552,9 +1584,41 @@ void Location::setup() if (locationId == "default") { + // Loop the player back in Z until the village-intro dialogue has been + // completed. Mirrors the generic tile-wrap teleport above, but constrained + // to the stretch near the car's spawn point so the player can't reach the + // village center prematurely. + if (!dialogueVillageIntro1Finished) { + constexpr float tileSize = 100.0f; + constexpr float loopStartZ = -30.7197f - 300.0f; + constexpr float loopForwardThreshold = loopStartZ + tileSize; + + const Eigen::Vector3f anchor = inCar + ? carPosition + : (player ? player->position : Eigen::Vector3f::Zero()); + + if (anchor.z() > loopForwardThreshold) { + const Eigen::Vector3f shift(0.f, 0.f, -tileSize); + if (inCar) { + carPosition += shift; + if (player) player->position = carPosition; + } + else if (player) { + player->position += shift; + player->setTarget(player->position); + player->clearPath(); + } + if (npcCar.mode == NpcCar::Mode::FOLLOW_PLAYER || npcCar.mode == NpcCar::Mode::NONE_STAY) { + npcCar.position += shift; + } + } + } + if (player && !dialoguePlayedVillageIntro1 && !dialogueSystem.isActive()) { if (player->position.z() > -36.f - 300) { - if (dialogueSystem.startDialogue("dialogue_village_intro1")) { + if (dialogueSystem.startDialogue("dialogue_village_intro1", [this]() { + dialogueVillageIntro1Finished = true; + })) { dialoguePlayedVillageIntro1 = true; } } @@ -1586,7 +1650,7 @@ void Location::setup() if (bandit && player && !dialoguePlayedBanditCaught1) { Eigen::Vector3f toBandit = bandit->position - player->position; toBandit.y() = 0.f; - if (toBandit.norm() < 12.0f && !dialogueSystem.isActive()) { + if (toBandit.norm() < 10.0f && !dialogueSystem.isActive()) { if (dialogueSystem.startDialogue("dialogue_village_caught1_car")) { dialoguePlayedBanditCaught1 = true; banditFollowingPlayer = true; @@ -1834,7 +1898,7 @@ void Location::setup() if (!bandit || !player || !banditFollowingPlayer) return; constexpr float retargetThreshold = 0.1f; - constexpr float stopDistance = 4.0f; + constexpr float stopDistance = 2.0f; const Eigen::Vector3f targetPos = inCar ? carPosition : player->position; diff --git a/src/Location.h b/src/Location.h index f8e6d41..bf297b5 100644 --- a/src/Location.h +++ b/src/Location.h @@ -113,6 +113,7 @@ namespace ZL bool dialoguePlayedOffroad = false; bool dialoguePlayedCrash = false; bool dialoguePlayedDrivingGas1 = false; + bool dialogueDrivingGas1Finished = false; bool dialoguePlayedGas1 = false; bool dialoguePlayedGirlfriend1 = false; bool dialoguePlayedPhone1 = false; @@ -145,6 +146,7 @@ namespace ZL bool dialoguePlayedVillageRescue1 = false; bool dialoguePlayedVillageIntro1 = false; + bool dialogueVillageIntro1Finished = false; bool dialoguePlayedVillageIntro2 = false; bool dialoguePlayedVillageFinal1 = false; bool dialoguePlayedVillageFinal2 = false;