diff --git a/resources/dialogue/sample_dialogues.json b/resources/dialogue/sample_dialogues.json index a08bdf1..5a5a28b 100644 --- a/resources/dialogue/sample_dialogues.json +++ b/resources/dialogue/sample_dialogues.json @@ -129,39 +129,39 @@ ] }, { - "id": "driving_dialogue2", + "id": "driving_dialogue_gas1", "start": "line_1", "nodes": [ - { + { "id": "line_1", "type": "Line", - "speaker": "Ghost", - "portrait": "resources/ghost_avatar.png", - "text": "Наконец-то ты пришел.", + "speaker": "Hero", + "portrait": "resources/w/gg/gg2_s_podsvetkoy5.png", + "text": "У нас бензин кончается.", "next": "line_2" }, - { + { "id": "line_2", "type": "Line", "speaker": "Hero", "portrait": "resources/w/gg/gg2_s_podsvetkoy5.png", - "text": "Ты сделан из дыма?", + "text": "Надо заправиться.", "next": "line_3" }, - { + { "id": "line_3", "type": "Line", "speaker": "Ghost", "portrait": "resources/ghost_avatar.png", - "text": "Ты думаешь, это смешно?", + "text": "Хорошо, только давай быстро.", "next": "line_4" }, { "id": "line_4", "type": "Line", - "speaker": "Hero", - "portrait": "resources/w/gg/gg2_s_podsvetkoy5.png", - "text": "Я думаю что ты пахнешь как выхлоп от Камаза.", + "speaker": "Ghost", + "portrait": "resources/ghost_avatar.png", + "text": "Мне как-то не по себе.", "next": "end_1" }, { diff --git a/src/Location.cpp b/src/Location.cpp index d549219..a9d6801 100644 --- a/src/Location.cpp +++ b/src/Location.cpp @@ -34,8 +34,7 @@ namespace ZL void Location::setup() { - carPosition = { 5.4005, 0, -3.811283 }; - + tileMesh.data = LoadFromTextFile02("resources/e/land/land003.txt", CONST_ZIP_FILE); tileMesh.RefreshVBO(); @@ -64,8 +63,8 @@ void Location::setup() player->modelCorrectionRotation = Eigen::Quaternionf(Eigen::AngleAxisf(M_PI, Eigen::Vector3f::UnitY())); player->canAttack = true; player->isPlayer = true; - player->position = { 9.43527, 0, 0.952688 }; - player->setTarget(player->position); + //player->position = { 9.43527, 0, 0.952688 }; + //player->setTarget(player->position); @@ -88,8 +87,8 @@ void Location::setup() girlfriend->rotationSpeed = 8.0f; girlfriend->modelScale = 0.01f; girlfriend->modelCorrectionRotation = Eigen::Quaternionf(Eigen::AngleAxisf(M_PI, Eigen::Vector3f::UnitY())); - girlfriend->position = Vector3f{ -10, -0, -10 }; - girlfriend->setTarget(girlfriend->position); + //girlfriend->position = Vector3f{ -10, -0, -10 }; + //girlfriend->setTarget(girlfriend->position); auto salesPersonTexture0 = std::make_shared(CreateTextureDataFromPng("resources/e/Salesperson_packed0_diffuse.png", CONST_ZIP_FILE)); auto salesPersonTexture1 = std::make_shared(CreateTextureDataFromPng("resources/e/Salesperson_packed1_diffuse.png", CONST_ZIP_FILE)); @@ -166,6 +165,16 @@ void Location::setup() { std::cout << "[LOCATION] Setting up FOREST location (custom models only)" << std::endl; + carPosition = { 7, 0, -7 + 200 }; + + girlfriend->position = Vector3f{ 5, 0, 0.9 + 200 }; + girlfriend->setTarget(girlfriend->position); + + player->position = { 9.5, 0, 0.95 + 200 }; + player->setTarget(player->position); + + + /* gameObjects.clear(); interactiveObjects.clear(); npcs.clear(); @@ -225,6 +234,16 @@ void Location::setup() } else // default { + carPosition = { 5.4005, 0, -3.811283 }; + + player->position = { 9.43527, 0, 0.952688 }; + player->setTarget(player->position); + + girlfriend->position = Vector3f{ -10, -0, -10 }; + girlfriend->setTarget(girlfriend->position); + + + std::vector models = { {"resources/out/main/birch-1.txt", "resources/ghost_avatar.png", {0.0f, 0.0f, 0.0f}, 2.0f}, {"resources/out/main/birch-11.txt", "resources/ghost_avatar.png", {0.0f, 0.0f, 0.0f}, 2.0f}, @@ -630,7 +649,7 @@ void Location::setup() if (player && !inCar) player->draw(renderer); - if (girlfriend) + if (girlfriend && !girlfriendInCar) { girlfriend->draw(renderer); } @@ -731,7 +750,7 @@ void Location::setup() // Draw characters (they handle their own skinning shader switch internally) if (player) player->drawShadowDepth(renderer); - if (girlfriend) + if (girlfriend && !girlfriendInCar) { girlfriend->drawShadowDepth(renderer); } @@ -1021,8 +1040,11 @@ void Location::setup() if (girlfriend) { + updateGirlfriendFollow(); girlfriend->update(delta); - pushOutOfNpcCarFootprint(girlfriend->position); + if (!girlfriendInCar) { + pushOutOfNpcCarFootprint(girlfriend->position); + } } if (salesperson) pushOutOfNpcCarFootprint(salesperson->position); @@ -1121,6 +1143,18 @@ void Location::setup() if (player) { player->position = carPosition; } + + + if (girlfriendInCar) + { + if (!dialoguePlayedDrivingGas1 && !dialogueSystem.isActive()) { + if (dialogueSystem.startDialogue("driving_dialogue_gas1")) { + dialoguePlayedDrivingGas1 = true; + } + } + } + + } if (player && !inCar) { @@ -1307,6 +1341,78 @@ void Location::setup() } } + void Location::updateGirlfriendFollow() + { + if (!girlfriend || !player) return; + + constexpr float retargetThreshold = 0.1f; + constexpr float stopDistance = 1.0f; + constexpr float carEnterRadius = 3.0f; + + // Player just exited the car while girlfriend was inside — she steps out + // right next to him, as if coming out of the rear door (same lateral side, + // offset back along the car's length). + if (girlfriendInCar && !inCar) { + const Eigen::Vector3f forward(-std::sin(carRotation), 0.f, -std::cos(carRotation)); + Eigen::Vector3f exitPos = player->position - forward * 1.5f; + exitPos.y() = 0.f; + girlfriend->position = exitPos; + girlfriend->clearPath(); + girlfriendInCar = false; + girlfriendLastFollowTargetValid = false; + } + + // While she is riding, her position is glued to the car and no pathing needed. + if (girlfriendInCar) { + girlfriend->position = carPosition; + girlfriend->position.y() = 0.f; + girlfriend->clearPath(); + return; + } + + // Player is in car and girlfriend has caught up — she jumps in. + if (inCar) { + Eigen::Vector3f diff = girlfriend->position - carPosition; + diff.y() = 0.f; + if (diff.norm() <= carEnterRadius) { + girlfriendInCar = true; + girlfriend->position = carPosition; + girlfriend->position.y() = 0.f; + girlfriend->clearPath(); + girlfriendLastFollowTargetValid = false; + return; + } + } + + // Follow anchor: the car when player is driving, otherwise a point stopDistance + // away from the player along the line to the girlfriend (so she stops near him). + Eigen::Vector3f anchor; + if (inCar) { + anchor = carPosition; + } else { + Eigen::Vector3f toPlayer = player->position - girlfriend->position; + toPlayer.y() = 0.f; + const float distToPlayer = toPlayer.norm(); + if (distToPlayer <= stopDistance) { + girlfriend->clearPath(); + girlfriendLastFollowTargetValid = false; + return; + } + const Eigen::Vector3f fromPlayer = -toPlayer / distToPlayer; + anchor = player->position + fromPlayer * stopDistance; + } + anchor.y() = 0.f; + + const bool shouldRetarget = !girlfriendLastFollowTargetValid || + (anchor - girlfriendLastFollowTarget).norm() > retargetThreshold; + + if (shouldRetarget) { + girlfriend->setTarget(anchor); + girlfriendLastFollowTarget = anchor; + girlfriendLastFollowTargetValid = true; + } + } + void Location::drawNpcCar() { if (!npcCar.texture) return; diff --git a/src/Location.h b/src/Location.h index 1592e20..97a7b01 100644 --- a/src/Location.h +++ b/src/Location.h @@ -103,8 +103,13 @@ namespace ZL bool inCar = false; + bool girlfriendInCar = false; + Eigen::Vector3f girlfriendLastFollowTarget = Eigen::Vector3f::Zero(); + bool girlfriendLastFollowTargetValid = false; + bool dialoguePlayedOffroad = false; bool dialoguePlayedCrash = false; + bool dialoguePlayedDrivingGas1 = false; ScriptEngine scriptEngine; @@ -140,6 +145,7 @@ namespace ZL void update(int64_t deltaMs); void updateNpcCar(int64_t deltaMs); + void updateGirlfriendFollow(); void drawNpcCar(); void handleDown(int64_t fingerId, int eventX, int eventY, int mx, int my);