Change girlfriend behavior, set some dialogs

This commit is contained in:
Vladislav Khorev 2026-04-19 06:37:35 +03:00
parent 2195542974
commit 542939207f
3 changed files with 133 additions and 21 deletions

View File

@ -129,39 +129,39 @@
] ]
}, },
{ {
"id": "driving_dialogue2", "id": "driving_dialogue_gas1",
"start": "line_1", "start": "line_1",
"nodes": [ "nodes": [
{ {
"id": "line_1", "id": "line_1",
"type": "Line", "type": "Line",
"speaker": "Ghost", "speaker": "Hero",
"portrait": "resources/ghost_avatar.png", "portrait": "resources/w/gg/gg2_s_podsvetkoy5.png",
"text": "Наконец-то ты пришел.", "text": "У нас бензин кончается.",
"next": "line_2" "next": "line_2"
}, },
{ {
"id": "line_2", "id": "line_2",
"type": "Line", "type": "Line",
"speaker": "Hero", "speaker": "Hero",
"portrait": "resources/w/gg/gg2_s_podsvetkoy5.png", "portrait": "resources/w/gg/gg2_s_podsvetkoy5.png",
"text": "Ты сделан из дыма?", "text": "Надо заправиться.",
"next": "line_3" "next": "line_3"
}, },
{ {
"id": "line_3", "id": "line_3",
"type": "Line", "type": "Line",
"speaker": "Ghost", "speaker": "Ghost",
"portrait": "resources/ghost_avatar.png", "portrait": "resources/ghost_avatar.png",
"text": "Ты думаешь, это смешно?", "text": "Хорошо, только давай быстро.",
"next": "line_4" "next": "line_4"
}, },
{ {
"id": "line_4", "id": "line_4",
"type": "Line", "type": "Line",
"speaker": "Hero", "speaker": "Ghost",
"portrait": "resources/w/gg/gg2_s_podsvetkoy5.png", "portrait": "resources/ghost_avatar.png",
"text": "Я думаю что ты пахнешь как выхлоп от Камаза.", "text": "Мне как-то не по себе.",
"next": "end_1" "next": "end_1"
}, },
{ {

View File

@ -34,8 +34,7 @@ namespace ZL
void Location::setup() void Location::setup()
{ {
carPosition = { 5.4005, 0, -3.811283 };
tileMesh.data = LoadFromTextFile02("resources/e/land/land003.txt", CONST_ZIP_FILE); tileMesh.data = LoadFromTextFile02("resources/e/land/land003.txt", CONST_ZIP_FILE);
tileMesh.RefreshVBO(); tileMesh.RefreshVBO();
@ -64,8 +63,8 @@ void Location::setup()
player->modelCorrectionRotation = Eigen::Quaternionf(Eigen::AngleAxisf(M_PI, Eigen::Vector3f::UnitY())); player->modelCorrectionRotation = Eigen::Quaternionf(Eigen::AngleAxisf(M_PI, Eigen::Vector3f::UnitY()));
player->canAttack = true; player->canAttack = true;
player->isPlayer = true; player->isPlayer = true;
player->position = { 9.43527, 0, 0.952688 }; //player->position = { 9.43527, 0, 0.952688 };
player->setTarget(player->position); //player->setTarget(player->position);
@ -88,8 +87,8 @@ void Location::setup()
girlfriend->rotationSpeed = 8.0f; girlfriend->rotationSpeed = 8.0f;
girlfriend->modelScale = 0.01f; girlfriend->modelScale = 0.01f;
girlfriend->modelCorrectionRotation = Eigen::Quaternionf(Eigen::AngleAxisf(M_PI, Eigen::Vector3f::UnitY())); girlfriend->modelCorrectionRotation = Eigen::Quaternionf(Eigen::AngleAxisf(M_PI, Eigen::Vector3f::UnitY()));
girlfriend->position = Vector3f{ -10, -0, -10 }; //girlfriend->position = Vector3f{ -10, -0, -10 };
girlfriend->setTarget(girlfriend->position); //girlfriend->setTarget(girlfriend->position);
auto salesPersonTexture0 = std::make_shared<Texture>(CreateTextureDataFromPng("resources/e/Salesperson_packed0_diffuse.png", CONST_ZIP_FILE)); auto salesPersonTexture0 = std::make_shared<Texture>(CreateTextureDataFromPng("resources/e/Salesperson_packed0_diffuse.png", CONST_ZIP_FILE));
auto salesPersonTexture1 = std::make_shared<Texture>(CreateTextureDataFromPng("resources/e/Salesperson_packed1_diffuse.png", CONST_ZIP_FILE)); auto salesPersonTexture1 = std::make_shared<Texture>(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; 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(); /* gameObjects.clear();
interactiveObjects.clear(); interactiveObjects.clear();
npcs.clear(); npcs.clear();
@ -225,6 +234,16 @@ void Location::setup()
} }
else // default 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<ModelAsset> models = { std::vector<ModelAsset> models = {
{"resources/out/main/birch-1.txt", "resources/ghost_avatar.png", {0.0f, 0.0f, 0.0f}, 2.0f}, {"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}, {"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 (player && !inCar) player->draw(renderer);
if (girlfriend) if (girlfriend && !girlfriendInCar)
{ {
girlfriend->draw(renderer); girlfriend->draw(renderer);
} }
@ -731,7 +750,7 @@ void Location::setup()
// Draw characters (they handle their own skinning shader switch internally) // Draw characters (they handle their own skinning shader switch internally)
if (player) player->drawShadowDepth(renderer); if (player) player->drawShadowDepth(renderer);
if (girlfriend) if (girlfriend && !girlfriendInCar)
{ {
girlfriend->drawShadowDepth(renderer); girlfriend->drawShadowDepth(renderer);
} }
@ -1021,8 +1040,11 @@ void Location::setup()
if (girlfriend) if (girlfriend)
{ {
updateGirlfriendFollow();
girlfriend->update(delta); girlfriend->update(delta);
pushOutOfNpcCarFootprint(girlfriend->position); if (!girlfriendInCar) {
pushOutOfNpcCarFootprint(girlfriend->position);
}
} }
if (salesperson) pushOutOfNpcCarFootprint(salesperson->position); if (salesperson) pushOutOfNpcCarFootprint(salesperson->position);
@ -1121,6 +1143,18 @@ void Location::setup()
if (player) { if (player) {
player->position = carPosition; player->position = carPosition;
} }
if (girlfriendInCar)
{
if (!dialoguePlayedDrivingGas1 && !dialogueSystem.isActive()) {
if (dialogueSystem.startDialogue("driving_dialogue_gas1")) {
dialoguePlayedDrivingGas1 = true;
}
}
}
} }
if (player && !inCar) { 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() void Location::drawNpcCar()
{ {
if (!npcCar.texture) return; if (!npcCar.texture) return;

View File

@ -103,8 +103,13 @@ namespace ZL
bool inCar = false; bool inCar = false;
bool girlfriendInCar = false;
Eigen::Vector3f girlfriendLastFollowTarget = Eigen::Vector3f::Zero();
bool girlfriendLastFollowTargetValid = false;
bool dialoguePlayedOffroad = false; bool dialoguePlayedOffroad = false;
bool dialoguePlayedCrash = false; bool dialoguePlayedCrash = false;
bool dialoguePlayedDrivingGas1 = false;
ScriptEngine scriptEngine; ScriptEngine scriptEngine;
@ -140,6 +145,7 @@ namespace ZL
void update(int64_t deltaMs); void update(int64_t deltaMs);
void updateNpcCar(int64_t deltaMs); void updateNpcCar(int64_t deltaMs);
void updateGirlfriendFollow();
void drawNpcCar(); void drawNpcCar();
void handleDown(int64_t fingerId, int eventX, int eventY, int mx, int my); void handleDown(int64_t fingerId, int eventX, int eventY, int mx, int my);