Merge branch 'reststates' into 'master'
Some checks failed
Build and test / Ubuntu (push) Has been cancelled
Build and test / MacOS (push) Has been cancelled
Build and test / Read .env file and expose it as output (push) Has been cancelled
Build and test / Windows (2019) (push) Has been cancelled
Build and test / Windows (2022) (push) Has been cancelled

Inform the player about both resting hindrances (#8408)

Closes #8408

See merge request OpenMW/openmw!4598
This commit is contained in:
Alexei Kotov 2025-04-24 18:30:28 +03:00
commit 4773022294
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;
enum RestPermitted
enum RestFlags
{
Rest_Allowed = 0,
Rest_OnlyWaiting = 1,
Rest_PlayerIsUnderwater = 1,
Rest_PlayerIsInAir = 2,
Rest_PlayerIsUnderwater = 3,
Rest_EnemiesAreNearby = 4
Rest_EnemiesAreNearby = 4,
Rest_CanSleep = 8,
};
/// check if the player is allowed to rest
virtual RestPermitted canRest() const = 0;
virtual int canRest() const = 0;
/// \todo Probably shouldn't be here
virtual MWRender::Animation* getAnimation(const MWWorld::Ptr& ptr) = 0;

View file

@ -84,15 +84,29 @@ namespace MWGui
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
MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage1}");
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Rest);
if (!solidGround)
MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage1}");
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())
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mUntilHealedButton);
else
@ -138,20 +152,6 @@ namespace MWGui
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);
mHourSlider->setScrollPosition(0);

View file

@ -2333,34 +2333,35 @@ namespace MWWorld
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();
Ptr player = mPlayer->getPlayer();
RefData& refdata = player.getRefData();
osg::Vec3f playerPos(refdata.getPosition().asVec3());
const MWPhysics::Actor* actor = mPhysics->getActor(player);
if (!actor)
throw std::runtime_error("can't find player");
if (mPlayer->enemiesNearby())
return Rest_EnemiesAreNearby;
const osg::Vec3f playerPos(player.getRefData().getPosition().asVec3());
if (isUnderwater(currentCell, playerPos) || isWalkingOnWater(player))
return Rest_PlayerIsUnderwater;
result |= Rest_PlayerIsUnderwater;
float fallHeight = player.getClass().getCreatureStats(player).getFallHeight();
float epsilon = 1e-4;
if ((actor->getCollisionMode() && (!mPhysics->isOnSolidGround(player) || fallHeight >= epsilon))
|| isFlying(player))
return Rest_PlayerIsInAir;
result |= Rest_PlayerIsInAir;
if (currentCell->getCell()->noSleep() || player.getClass().getNpcStats(player).isWerewolf())
return Rest_OnlyWaiting;
if (mPlayer->enemiesNearby())
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)

View file

@ -505,7 +505,7 @@ namespace MWWorld
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
void rest(double hours) override;