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",
"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"
},
{

View File

@ -34,7 +34,6 @@ namespace ZL
void Location::setup()
{
carPosition = { 5.4005, 0, -3.811283 };
tileMesh.data = LoadFromTextFile02("resources/e/land/land003.txt", CONST_ZIP_FILE);
@ -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<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));
@ -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<ModelAsset> 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;

View File

@ -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);