Some quests

This commit is contained in:
Vladislav Khorev 2026-04-19 07:56:42 +03:00
parent 542939207f
commit 8e0936836e
3 changed files with 226 additions and 10 deletions

View File

@ -83,6 +83,74 @@
"type": "End" "type": "End"
} }
] ]
},
{
"id": "dialogue_gas2",
"start": "line_2",
"nodes": [
{
"id": "line_2",
"type": "Line",
"speaker": "Кассир",
"portrait": "resources/ghost_avatar.png",
"text": "[Смотрит подозрительно]",
"next": "line_3"
},
{
"id": "line_3",
"type": "Line",
"speaker": "Игрок",
"portrait": "resources/w/gg/gg2_s_podsvetkoy5.png",
"text": "Что-то случилось?",
"next": "line_4"
},
{
"id": "line_4",
"type": "Line",
"speaker": "Кассир",
"portrait": "resources/ghost_avatar.png",
"text": "Поставьте машину чуть ближе к колонке пожалуйста.",
"next": "end_1"
},
{
"id": "end_1",
"type": "End"
}
]
},
{
"id": "dialogue_gas3",
"start": "line_2",
"nodes": [
{
"id": "line_2",
"type": "Line",
"speaker": "Кассир",
"portrait": "resources/ghost_avatar.png",
"text": "[Смотрит подозрительно]",
"next": "line_3"
},
{
"id": "line_3",
"type": "Line",
"speaker": "Игрок",
"portrait": "resources/w/gg/gg2_s_podsvetkoy5.png",
"text": "Что-то случилось?",
"next": "line_4"
},
{
"id": "line_4",
"type": "Line",
"speaker": "Кассир",
"portrait": "resources/ghost_avatar.png",
"text": "У вас уже заправлен полный бак.",
"next": "end_1"
},
{
"id": "end_1",
"type": "End"
}
]
}, },
{ {
"id": "driving_dialogue_offroad", "id": "driving_dialogue_offroad",
@ -169,6 +237,74 @@
"type": "End" "type": "End"
} }
] ]
},
{
"id": "dialogue_girlfriend1",
"start": "line_1",
"nodes": [
{
"id": "line_1",
"type": "Line",
"speaker": "Ghost",
"portrait": "resources/ghost_avatar.png",
"text": "Ты видел? Он так на меня смотрел, как будто узнал меня.",
"next": "line_2"
},
{
"id": "line_2",
"type": "Line",
"speaker": "Hero",
"portrait": "resources/w/gg/gg2_s_podsvetkoy5.png",
"text": "Что-то мне стремно, давай поедем отсюда быстрее",
"next": "end_1"
},
{
"id": "end_1",
"type": "End"
}
]
},
{
"id": "dialogue_phone1",
"start": "line_1",
"nodes": [
{
"id": "line_1",
"type": "Line",
"speaker": "Hero",
"portrait": "resources/w/gg/gg2_s_podsvetkoy5.png",
"text": "Phone 1 У нас бензин кончается.",
"next": "line_2"
},
{
"id": "line_2",
"type": "Line",
"speaker": "Hero",
"portrait": "resources/w/gg/gg2_s_podsvetkoy5.png",
"text": "Надо заправиться.",
"next": "line_3"
},
{
"id": "line_3",
"type": "Line",
"speaker": "Ghost",
"portrait": "resources/ghost_avatar.png",
"text": "Хорошо, только давай быстро.",
"next": "line_4"
},
{
"id": "line_4",
"type": "Line",
"speaker": "Ghost",
"portrait": "resources/ghost_avatar.png",
"text": "Мне как-то не по себе.",
"next": "end_1"
},
{
"id": "end_1",
"type": "End"
}
]
}, },
{ {
"id": "test_line_dialogue", "id": "test_line_dialogue",

View File

@ -166,6 +166,7 @@ void Location::setup()
std::cout << "[LOCATION] Setting up FOREST location (custom models only)" << std::endl; std::cout << "[LOCATION] Setting up FOREST location (custom models only)" << std::endl;
carPosition ={ 7, 0, -7 + 200 }; carPosition ={ 7, 0, -7 + 200 };
npcCar.position = Vector3f(9, 0, -235);
girlfriend->position = Vector3f{ 5, 0, 0.9 + 200 }; girlfriend->position = Vector3f{ 5, 0, 0.9 + 200 };
girlfriend->setTarget(girlfriend->position); girlfriend->setTarget(girlfriend->position);
@ -235,6 +236,7 @@ void Location::setup()
else // default else // default
{ {
carPosition = { 5.4005, 0, -3.811283 }; carPosition = { 5.4005, 0, -3.811283 };
npcCar.position = Vector3f(9, 0, -100);
player->position = { 9.43527, 0, 0.952688 }; player->position = { 9.43527, 0, 0.952688 };
player->setTarget(player->position); player->setTarget(player->position);
@ -361,9 +363,9 @@ void Location::setup()
carWheelMesh.RefreshVBO(); carWheelMesh.RefreshVBO();
npcCar.texture = std::make_shared<Texture>(CreateTextureDataFromPng("resources/e/car_black001.png", CONST_ZIP_FILE)); npcCar.texture = std::make_shared<Texture>(CreateTextureDataFromPng("resources/e/car_black001.png", CONST_ZIP_FILE));
npcCar.position = carPosition + Eigen::Vector3f(0, 0.f, 14.f);//Eigen::Vector3f(-12.f, 0.f, 8.f); //npcCar.position = carPosition + Eigen::Vector3f(0, 0.f, 14.f);//Eigen::Vector3f(-12.f, 0.f, 8.f);
npcCar.rotation = 0.f; npcCar.rotation = 0.f;
npcCar.mode = NpcCar::Mode::FOLLOW_PLAYER; npcCar.mode = NpcCar::Mode::NONE;
/*npcCar.mode = NpcCar::Mode::FOLLOW_WAYPOINTS; /*npcCar.mode = NpcCar::Mode::FOLLOW_WAYPOINTS;
npcCar.waypoints = { npcCar.waypoints = {
Eigen::Vector3f(-12.f, 0.f, 8.f), Eigen::Vector3f(-12.f, 0.f, 8.f),
@ -1144,7 +1146,6 @@ void Location::setup()
player->position = carPosition; player->position = carPosition;
} }
if (girlfriendInCar) if (girlfriendInCar)
{ {
if (!dialoguePlayedDrivingGas1 && !dialogueSystem.isActive()) { if (!dialoguePlayedDrivingGas1 && !dialogueSystem.isActive()) {
@ -1154,6 +1155,12 @@ void Location::setup()
} }
} }
if (!policeFollow && player->position.z() < -240)
{
policeFollow = true;
npcCar.mode = NpcCar::Mode::FOLLOW_PLAYER;
}
} }
@ -1216,6 +1223,33 @@ void Location::setup()
if (targetInteractiveObject && player) { if (targetInteractiveObject && player) {
}*/ }*/
// 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()) {
constexpr float minDistance = 8.0f;
const float dx = player->position.x() - salesperson->position.x();
const float dz = player->position.z() - salesperson->position.z();
if (std::hypot(dx, dz) > minDistance) {
if (dialogueSystem.startDialogue("dialogue_girlfriend1")) {
dialoguePlayedGirlfriend1 = true;
}
}
}
// Phone rings once the player drives far from the gas station — fires once,
// and only after the gas-station sale.
if (inCar && dialoguePlayedGas1 && !dialoguePlayedPhone1 && !dialogueSystem.isActive()) {
constexpr float minDistance = 50.0f;
const Eigen::Vector3f gasStationPos(-3.f, 0.f, -11.f);
const float dx = carPosition.x() - gasStationPos.x();
const float dz = carPosition.z() - gasStationPos.z();
if (std::hypot(dx, dz) > minDistance) {
if (dialogueSystem.startDialogue("dialogue_phone1")) {
dialoguePlayedPhone1 = true;
}
}
}
} }
void Location::updateNpcCar(int64_t deltaMs) void Location::updateNpcCar(int64_t deltaMs)
@ -1241,7 +1275,7 @@ void Location::setup()
hasTarget = true; hasTarget = true;
} }
} }
else { else if (npcCar.mode == NpcCar::Mode::FOLLOW_PLAYER) {
//if (x > 0.5) //if (x > 0.5)
{ {
@ -1269,10 +1303,10 @@ void Location::setup()
} }
hasTarget = dist > 0.5f; hasTarget = dist > 0.5f;
} }
/*else }
else
{ {
throttle = 0.f; throttle = 0.f;
}*/
} }
float targetHeading = npcCar.rotation; float targetHeading = npcCar.rotation;
@ -1463,7 +1497,49 @@ void Location::setup()
return; return;
} }
if (salesperson && player && !dialogueSystem.isActive()) {
constexpr float maxTalkDistance = 4.0f;
// cos(45°) — salesperson must lie within the ±45° half-cone in front
// of the player (90° total field of view).
constexpr float coneCosThreshold = 0.7071067f;
Eigen::Vector3f toSales = salesperson->position - player->position;
toSales.y() = 0.f;
const float dist = toSales.norm();
if (dist > 1e-4f && dist <= maxTalkDistance) {
const Eigen::Vector3f playerForward(std::sin(cameraAzimuth), 0.f, -std::cos(cameraAzimuth));
const Eigen::Vector3f toSalesDir = toSales / dist;
if (playerForward.dot(toSalesDir) >= coneCosThreshold) {
const Eigen::Vector3f gasStationPos(-3.f, 0.f, -11.f);
const float carDistToStation = std::hypot(
carPosition.x() - gasStationPos.x(),
carPosition.z() - gasStationPos.z());
std::string dialogueId;
if (dialoguePlayedGas1) {
dialogueId = "dialogue_gas3";
} else if (carDistToStation <= 10.f) {
dialogueId = "dialogue_gas1";
} else {
dialogueId = "dialogue_gas2";
}
if (dialogueSystem.startDialogue(dialogueId)) {
// Face each other. cameraAzimuth also drives the player's
// targetFacingAngle, so updating it rotates the player toward
// the salesperson.
cameraAzimuth = std::atan2(toSales.x(), -toSales.z());
salesperson->targetFacingAngle = std::atan2(-toSales.x(), toSales.z());
if (dialogueId == "dialogue_gas1") {
dialoguePlayedGas1 = true;
}
}
}
}
}
} }
void Location::handleUp(int64_t fingerId, int mx, int my) void Location::handleUp(int64_t fingerId, int mx, int my)
{ {

View File

@ -15,7 +15,7 @@ namespace ZL
struct NpcCar struct NpcCar
{ {
enum class Mode { FOLLOW_WAYPOINTS, FOLLOW_PLAYER }; enum class Mode { FOLLOW_WAYPOINTS, FOLLOW_PLAYER, NONE };
Eigen::Vector3f position = Eigen::Vector3f::Zero(); Eigen::Vector3f position = Eigen::Vector3f::Zero();
float rotation = 0.f; float rotation = 0.f;
@ -110,7 +110,11 @@ namespace ZL
bool dialoguePlayedOffroad = false; bool dialoguePlayedOffroad = false;
bool dialoguePlayedCrash = false; bool dialoguePlayedCrash = false;
bool dialoguePlayedDrivingGas1 = false; bool dialoguePlayedDrivingGas1 = false;
bool dialoguePlayedGas1 = false;
bool dialoguePlayedGirlfriend1 = false;
bool dialoguePlayedPhone1 = false;
bool policeFollow = false;
ScriptEngine scriptEngine; ScriptEngine scriptEngine;
Dialogue::DialogueSystem dialogueSystem; Dialogue::DialogueSystem dialogueSystem;