From 3c4a9069ae08e09fcfbd26ef1d84103212d1ad1f Mon Sep 17 00:00:00 2001 From: elsid Date: Tue, 13 Apr 2021 23:10:43 +0200 Subject: [PATCH] Do not use infinite area cost Division by zero causes float value to be infinite. When infinite cost is multiplied by zero distance the result is NaN. After this pathfinding algorithm state is broken. --- apps/openmw/mwmechanics/aipackage.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index 8dcf37355..e7ba9e227 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -25,6 +25,14 @@ #include +namespace +{ + float divOrMax(float dividend, float divisor) + { + return divisor == 0 ? std::numeric_limits::max() * std::numeric_limits::epsilon() : dividend / divisor; + } +} + MWMechanics::AiPackage::AiPackage(AiPackageTypeId typeId, const Options& options) : mTypeId(typeId), mOptions(options), @@ -439,15 +447,15 @@ DetourNavigator::AreaCosts MWMechanics::AiPackage::getAreaCosts(const MWWorld::P const MWWorld::Class& actorClass = actor.getClass(); if (flags & DetourNavigator::Flag_swim) - costs.mWater = costs.mWater / actorClass.getSwimSpeed(actor); + costs.mWater = divOrMax(costs.mWater, actorClass.getSwimSpeed(actor)); if (flags & DetourNavigator::Flag_walk) { float walkCost; if (getTypeId() == AiPackageTypeId::Wander) - walkCost = 1.0 / actorClass.getWalkSpeed(actor); + walkCost = divOrMax(1.0, actorClass.getWalkSpeed(actor)); else - walkCost = 1.0 / actorClass.getRunSpeed(actor); + walkCost = divOrMax(1.0, actorClass.getRunSpeed(actor)); costs.mDoor = costs.mDoor * walkCost; costs.mPathgrid = costs.mPathgrid * walkCost; costs.mGround = costs.mGround * walkCost;