diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f44e83b3..cee5137d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ Bug #4715: "Cannot get class of an empty object" exception after pressing ESC in the dialogue mode Bug #4720: Inventory avatar has shield with two-handed weapon during [un]equipping animation Bug #4723: ResetActors command works incorrectly + Bug #4746: Non-solid player can't run or sneak Feature #2229: Improve pathfinding AI Feature #3442: Default values for fallbacks from ini file Feature #4673: Weapon sheathing diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index c2e5c9afb..4646875fd 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -413,5 +413,5 @@ DetourNavigator::Flags MWMechanics::AiPackage::getNavigatorFlags(const MWWorld:: bool MWMechanics::AiPackage::canActorMoveByZAxis(const MWWorld::Ptr& actor) const { MWBase::World* world = MWBase::Environment::get().getWorld(); - return (actor.getClass().canSwim(actor) && world->isSwimming(actor)) || world->isFlying(actor); + return (actor.getClass().canSwim(actor) && world->isSwimming(actor)) || world->isFlying(actor) || !world->isActorCollisionEnabled(actor); } diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 129d1347b..837d49f38 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -209,7 +209,8 @@ namespace MWMechanics } bool actorCanMoveByZ = (actor.getClass().canSwim(actor) && MWBase::Environment::get().getWorld()->isSwimming(actor)) - || MWBase::Environment::get().getWorld()->isFlying(actor); + || MWBase::Environment::get().getWorld()->isFlying(actor) + || !MWBase::Environment::get().getWorld()->isActorCollisionEnabled(actor); if(actorCanMoveByZ && mDistance > 0) { // Typically want to idle for a short time before the next wander diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index b0bd7d01d..07a6aa3b1 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -1886,6 +1886,7 @@ void CharacterController::update(float duration, bool animationOnly) bool incapacitated = (cls.getCreatureStats(mPtr).isParalyzed() || cls.getCreatureStats(mPtr).getKnockedDown()); bool inwater = world->isSwimming(mPtr); bool flying = world->isFlying(mPtr); + bool solid = world->isActorCollisionEnabled(mPtr); // Can't run and sneak while flying (see speed formula in Npc/Creature::getSpeed) bool sneak = cls.getCreatureStats(mPtr).getStance(MWMechanics::CreatureStats::Stance_Sneak) && !flying; bool isrunning = cls.getCreatureStats(mPtr).getStance(MWMechanics::CreatureStats::Stance_Run) && !flying; @@ -1894,7 +1895,7 @@ void CharacterController::update(float duration, bool animationOnly) //Force Jump Logic bool isMoving = (std::abs(cls.getMovementSettings(mPtr).mPosition[0]) > .5 || std::abs(cls.getMovementSettings(mPtr).mPosition[1]) > .5); - if(!inwater && !flying) + if(!inwater && !flying && solid) { //Force Jump if(stats.getMovementFlag(MWMechanics::CreatureStats::Flag_ForceJump)) @@ -2002,12 +2003,12 @@ void CharacterController::update(float duration, bool animationOnly) cls.getCreatureStats(mPtr).setFatigue(fatigue); } - if(sneak || inwater || flying || incapacitated) + if(sneak || inwater || flying || incapacitated || !solid) vec.z() = 0.0f; bool inJump = true; bool playLandingSound = false; - if(!onground && !flying && !inwater) + if(!onground && !flying && !inwater && solid) { // In the air (either getting up —ascending part of jump— or falling). @@ -2060,7 +2061,7 @@ void CharacterController::update(float duration, bool animationOnly) } } } - else if(mJumpState == JumpState_InAir && !inwater && !flying) + else if(mJumpState == JumpState_InAir && !inwater && !flying && solid) { forcestateupdate = true; jumpstate = JumpState_Landing; @@ -2099,7 +2100,7 @@ void CharacterController::update(float duration, bool animationOnly) } else { - if(mPtr.getClass().isNpc() && mJumpState == JumpState_InAir && !flying) + if(mPtr.getClass().isNpc() && mJumpState == JumpState_InAir && !flying && solid) playLandingSound = true; jumpstate = mAnimation->isPlaying(mCurrentJump) ? JumpState_Landing : JumpState_None; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 6fd11c2af..8a5e23ed9 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1385,7 +1385,7 @@ namespace MWWorld pos.z() += 20; // place slightly above. will snap down to ground with code below - if (force || !isFlying(ptr)) + if (force || !ptr.getClass().isActor() || (!isFlying(ptr) && isActorCollisionEnabled(ptr))) { osg::Vec3f traced = mPhysics->traceDown(ptr, pos, Constants::CellSizeInUnits); if (traced.z() < pos.z()) @@ -2229,11 +2229,11 @@ namespace MWWorld bool World::isFlying(const MWWorld::Ptr &ptr) const { - const MWMechanics::CreatureStats &stats = ptr.getClass().getCreatureStats(ptr); - if(!ptr.getClass().isActor()) return false; + const MWMechanics::CreatureStats &stats = ptr.getClass().getCreatureStats(ptr); + if (stats.isDead()) return false; @@ -2245,7 +2245,7 @@ namespace MWWorld return true; const MWPhysics::Actor* actor = mPhysics->getActor(ptr); - if(!actor || !actor->getCollisionMode()) + if(!actor) return true; return false;