Merge branch 'reststates' into 'master'

Inform the player about both resting hindrances (#8408)

Closes #8408

See merge request OpenMW/openmw!4598
This commit is contained in:
psi29a 2025-07-04 11:03:28 +00:00
commit 9013ed16f0
4 changed files with 37 additions and 37 deletions

View File

@ -406,17 +406,16 @@ namespace MWBase
virtual void enableActorCollision(const MWWorld::Ptr& actor, bool enable) = 0; virtual void enableActorCollision(const MWWorld::Ptr& actor, bool enable) = 0;
enum RestPermitted enum RestFlags
{ {
Rest_Allowed = 0, Rest_PlayerIsUnderwater = 1,
Rest_OnlyWaiting = 1,
Rest_PlayerIsInAir = 2, Rest_PlayerIsInAir = 2,
Rest_PlayerIsUnderwater = 3, Rest_EnemiesAreNearby = 4,
Rest_EnemiesAreNearby = 4 Rest_CanSleep = 8,
}; };
/// check if the player is allowed to rest /// check if the player is allowed to rest
virtual RestPermitted canRest() const = 0; virtual int canRest() const = 0;
/// \todo Probably shouldn't be here /// \todo Probably shouldn't be here
virtual MWRender::Animation* getAnimation(const MWWorld::Ptr& ptr) = 0; virtual MWRender::Animation* getAnimation(const MWWorld::Ptr& ptr) = 0;

View File

@ -84,15 +84,29 @@ namespace MWGui
void WaitDialog::setPtr(const MWWorld::Ptr& ptr) void WaitDialog::setPtr(const MWWorld::Ptr& ptr)
{ {
setCanRest(!ptr.isEmpty() || MWBase::Environment::get().getWorld()->canRest() == MWBase::World::Rest_Allowed); const int restFlags = MWBase::Environment::get().getWorld()->canRest();
if (ptr.isEmpty() && MWBase::Environment::get().getWorld()->canRest() == MWBase::World::Rest_PlayerIsInAir) const bool underwater = (restFlags & MWBase::World::Rest_PlayerIsUnderwater) != 0;
// Resting in air is allowed if you're using a bed
const bool inAir = ptr.isEmpty() && (restFlags & MWBase::World::Rest_PlayerIsInAir) != 0;
const bool enemiesNearby = (restFlags & MWBase::World::Rest_EnemiesAreNearby) != 0;
const bool solidGround = !underwater && !inAir;
if (!solidGround || enemiesNearby)
{ {
// Resting in air is not allowed unless you're using a bed if (!solidGround)
MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage1}"); MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage1}");
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Rest);
if (enemiesNearby)
MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage2}");
MWBase::Environment::get().getWindowManager()->popGuiMode();
return;
} }
const bool canSleep = !ptr.isEmpty() || (restFlags & MWBase::World::Rest_CanSleep) != 0;
setCanRest(canSleep);
if (mUntilHealedButton->getVisible()) if (mUntilHealedButton->getVisible())
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mUntilHealedButton); MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mUntilHealedButton);
else else
@ -138,20 +152,6 @@ namespace MWGui
MWBase::Environment::get().getWindowManager()->popGuiMode(); MWBase::Environment::get().getWindowManager()->popGuiMode();
} }
MWBase::World::RestPermitted canRest = MWBase::Environment::get().getWorld()->canRest();
if (canRest == MWBase::World::Rest_EnemiesAreNearby)
{
MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage2}");
MWBase::Environment::get().getWindowManager()->popGuiMode();
}
else if (canRest == MWBase::World::Rest_PlayerIsUnderwater)
{
// resting underwater not allowed
MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage1}");
MWBase::Environment::get().getWindowManager()->popGuiMode();
}
onHourSliderChangedPosition(mHourSlider, 0); onHourSliderChangedPosition(mHourSlider, 0);
mHourSlider->setScrollPosition(0); mHourSlider->setScrollPosition(0);

View File

@ -2333,34 +2333,35 @@ namespace MWWorld
Log(Debug::Warning) << "Player agent bounds are not supported by navigator: " << agentBounds; Log(Debug::Warning) << "Player agent bounds are not supported by navigator: " << agentBounds;
} }
World::RestPermitted World::canRest() const int World::canRest() const
{ {
int result = 0;
CellStore* currentCell = mWorldScene->getCurrentCell(); CellStore* currentCell = mWorldScene->getCurrentCell();
Ptr player = mPlayer->getPlayer(); Ptr player = mPlayer->getPlayer();
RefData& refdata = player.getRefData();
osg::Vec3f playerPos(refdata.getPosition().asVec3());
const MWPhysics::Actor* actor = mPhysics->getActor(player); const MWPhysics::Actor* actor = mPhysics->getActor(player);
if (!actor) if (!actor)
throw std::runtime_error("can't find player"); throw std::runtime_error("can't find player");
if (mPlayer->enemiesNearby()) const osg::Vec3f playerPos(player.getRefData().getPosition().asVec3());
return Rest_EnemiesAreNearby;
if (isUnderwater(currentCell, playerPos) || isWalkingOnWater(player)) if (isUnderwater(currentCell, playerPos) || isWalkingOnWater(player))
return Rest_PlayerIsUnderwater; result |= Rest_PlayerIsUnderwater;
float fallHeight = player.getClass().getCreatureStats(player).getFallHeight(); float fallHeight = player.getClass().getCreatureStats(player).getFallHeight();
float epsilon = 1e-4; float epsilon = 1e-4;
if ((actor->getCollisionMode() && (!mPhysics->isOnSolidGround(player) || fallHeight >= epsilon)) if ((actor->getCollisionMode() && (!mPhysics->isOnSolidGround(player) || fallHeight >= epsilon))
|| isFlying(player)) || isFlying(player))
return Rest_PlayerIsInAir; result |= Rest_PlayerIsInAir;
if (currentCell->getCell()->noSleep() || player.getClass().getNpcStats(player).isWerewolf()) if (mPlayer->enemiesNearby())
return Rest_OnlyWaiting; result |= Rest_EnemiesAreNearby;
return Rest_Allowed; if (!currentCell->getCell()->noSleep() && !player.getClass().getNpcStats(player).isWerewolf())
result |= Rest_CanSleep;
return result;
} }
MWRender::Animation* World::getAnimation(const MWWorld::Ptr& ptr) MWRender::Animation* World::getAnimation(const MWWorld::Ptr& ptr)

View File

@ -505,7 +505,7 @@ namespace MWWorld
void enableActorCollision(const MWWorld::Ptr& actor, bool enable) override; void enableActorCollision(const MWWorld::Ptr& actor, bool enable) override;
RestPermitted canRest() const override; int canRest() const override;
///< check if the player is allowed to rest ///< check if the player is allowed to rest
void rest(double hours) override; void rest(double hours) override;