Restore back old navigation system

This commit is contained in:
Vladislav Khorev committed 2026-10-22 23:02:25 +06:00
1 parent c9c6b7e7fb
commit ea8f64c940
7 files changed
+44 -275

No files matched your search

+36 -77
View File
@@ -450,16 +450,7 @@ namespace FRG
const auto addCharacter = [&](const Character* other) {
if (!other || other == self) return;
if (other->getHp() <= 0.f || !other->state.enabled) return;
// Проверяем, находятся ли персонажи в состоянии фактического столкновения
const float dist = (other->state.position - self->state.position).norm();
const float collisionDist = self->state.collisionRadius + other->state.collisionRadius;
// Добавляем epsilon (0.1f) для учета погрешностей при входе в зону коллизии
const bool isColliding = dist <= (collisionDist + 0.1f);
// Игнорируем движущегося персонажа, только если мы с ним НЕ сталкиваемся в данный момент
if (other->isMoving() && !isColliding) return;
if (other->isMoving()) return;
if (distancePointToSegmentXZ(other->state.position, start, end) > kDynamicObstacleInfluenceDist) {
return;
@@ -469,7 +460,7 @@ namespace FRG
obs.position = Eigen::Vector3f(other->state.position.x(), navigation->getFloorY(), other->state.position.z());
obs.radius = (std::max)(0.0f, other->state.collisionRadius * 0.6f);
dynamicObstacles.push_back(obs);
};
};
addCharacter(player.get());
for (const auto& npc : npcs) {
@@ -477,8 +468,8 @@ namespace FRG
}
return navigation->findPathToNearest(start, end, dynamicObstacles);
};
};
};
if (player) {
player->setPathPlanner(makePlanner(player.get()));
@@ -600,9 +591,6 @@ namespace FRG
}
Character* Location::raycastNpcs(const Eigen::Vector3f& rayOrigin, const Eigen::Vector3f& rayDir, float maxDistance) {
//return nullptr;
// Every NPC is treated as a vertical cylinder: radius 1.0m, height 1.85m,
// base at npc->position (the model's foot). Intersection = circle hit in the
// XZ plane, then clip the entry/exit t against the [yFoot, yFoot+height] slab.
@@ -666,6 +654,7 @@ namespace FRG
else {
//logger() << "[RAYCAST_NPC] No NPC hit" << std::endl;
}
return closestNpc;
}
@@ -1424,83 +1413,53 @@ namespace FRG
continue;
}
// 1. ПЕРЕСТРОЕНИЕ ПУТИ (выполняется при пересечении обычного радиуса коллизии)
Eigen::Vector2f normal(1.f, 0.f);
if (dist > kMinSeparationEps) {
normal = delta / dist;
}
const float penetration = (minDist - dist);
const float push = penetration * 0.5f;
Eigen::Vector3f newA = a->state.position;
Eigen::Vector3f newB = b->state.position;
newA.x() -= normal.x() * push;
newA.z() -= normal.y() * push;
newA.y() = 0.f;
newB.x() += normal.x() * push;
newB.z() += normal.y() * push;
newB.y() = 0.f;
const bool aWasMoving = a->isMoving();
const bool bWasMoving = b->isMoving();
auto tryReplan = [&](Character* c) {
if (replanCooldownRemainingMs.find(c) != replanCooldownRemainingMs.end()) {
return; // Уже находится в откате
}
if (c->forceReplan()) {
replanCooldownRemainingMs[c] = 500; // таймаут на спам
}
};
if (navigation && navigation->isReady()) {
const bool aOk = navigation->isWalkable(newA);
const bool bOk = navigation->isWalkable(newB);
if (aWasMoving || bWasMoving) {
if (aWasMoving && bWasMoving) {
tryReplan(a);
tryReplan(b);
}
else if (aWasMoving) {
tryReplan(a);
}
else if (bWasMoving) {
tryReplan(b);
}
}
// 2. ФИЗИЧЕСКОЕ ВЫТАЛКИВАНИЕ (только если дистанция меньше 0.5 * minDist)
const float hardMinDist = minDist * 0.5f;
if (dist < hardMinDist) {
Eigen::Vector2f normal(1.f, 0.f);
if (dist > kMinSeparationEps) {
normal = delta / dist;
}
// Вычисляем выталкивание относительно hardMinDist, а не minDist
const float penetration = (hardMinDist - dist);
const float push = penetration * 0.5f;
Eigen::Vector3f newA = a->state.position;
Eigen::Vector3f newB = b->state.position;
newA.x() -= normal.x() * push;
newA.z() -= normal.y() * push;
newA.y() = 0.f;
newB.x() += normal.x() * push;
newB.z() += normal.y() * push;
newB.y() = 0.f;
if (navigation && navigation->isReady()) {
const bool aOk = navigation->isWalkable(newA);
const bool bOk = navigation->isWalkable(newB);
if (aOk && bOk) {
a->state.position = newA;
b->state.position = newB;
}
else if (aOk && !bOk) {
a->state.position = newA;
}
else if (!aOk && bOk) {
b->state.position = newB;
}
}
else {
if (aOk && bOk) {
a->state.position = newA;
b->state.position = newB;
}
else if (aOk && !bOk) {
a->state.position = newA;
}
else if (!aOk && bOk) {
b->state.position = newB;
}
}
else {
a->state.position = newA;
b->state.position = newB;
}
// 3. ОСТАНОВКА И КОЛЛБЭКИ
if (a->state.isPlayer && !aWasMoving) a->stopInPlace();
if (b->state.isPlayer && !bWasMoving) b->stopInPlace();
if (aWasMoving && !bWasMoving) {
nudgeCharacterAside(b, a->state.position);
fireBumpCallbacks(a, b);
}
else if (bWasMoving && !aWasMoving) {
} else if (bWasMoving && !aWasMoving) {
nudgeCharacterAside(a, b->state.position);
fireBumpCallbacks(b, a);
}