1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-29 02:15:33 +00:00

Show full player body when knocked out or dead

This commit is contained in:
Mads Buvik Sandvei 2020-03-28 16:30:56 +01:00
parent 68c75f66eb
commit d658065fe7
10 changed files with 97 additions and 50 deletions

View file

@ -39,6 +39,7 @@
#include "../mwworld/inventorystore.hpp"
#include "../mwworld/esmstore.hpp"
#include "../mwworld/player.hpp"
#include "../mwrender/npcanimation.hpp"
#include "aicombataction.hpp"
#include "movement.hpp"
@ -2377,6 +2378,18 @@ void CharacterController::update(float duration, bool animationOnly)
mSkipAnim = false;
mAnimation->enableHeadAnimation(cls.isActor() && !cls.getCreatureStats(mPtr).isDead());
#ifdef USE_OPENXR
if (isPlayer)
{
auto disabled = MWBase::Environment::get().getWorld()->getPlayer().isDisabled();
auto animation = static_cast<MWRender::NpcAnimation*>(mAnimation);
if (disabled)
animation->setViewMode(MWRender::NpcAnimation::VM_VRNormal);
else
animation->setViewMode(MWRender::NpcAnimation::VM_VRFirstPerson);
}
#endif
}
void CharacterController::persistAnimationState()

View file

@ -286,6 +286,7 @@ namespace MWPhysics
return position;
const bool isPlayer = (ptr == MWMechanics::getPlayer());
auto* world = MWBase::Environment::get().getWorld();
// In VR, player should move according to current direction of
// a selected limb, rather than current orientation of camera.
@ -320,7 +321,7 @@ namespace MWPhysics
// While this is strictly speaking wrong, it's needed for MW compatibility.
position.z() += halfExtents.z();
static const float fSwimHeightScale = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
static const float fSwimHeightScale = world->getStore().get<ESM::GameSetting>()
.find("fSwimHeightScale")->mValue.getFloat();
float swimlevel = waterlevel + halfExtents.z() - (physicActor->getRenderingHalfExtents().z() * 2 * fSwimHeightScale);
@ -355,13 +356,13 @@ namespace MWPhysics
if (isPlayer)
{
ptr.getClass().skillUsageSucceeded(ptr, ESM::Skill::Acrobatics, 0);
MWBase::Environment::get().getWorld()->getPlayer().setJumping(true);
world->getPlayer().setJumping(true);
}
// Decrease fatigue
if (!isPlayer || !MWBase::Environment::get().getWorld()->getGodModeState())
if (!isPlayer || !world->getGodModeState())
{
const MWWorld::Store<ESM::GameSetting> &gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
const MWWorld::Store<ESM::GameSetting> &gmst = world->getStore().get<ESM::GameSetting>();
const float fFatigueJumpBase = gmst.find("fFatigueJumpBase")->mValue.getFloat();
const float fFatigueJumpMult = gmst.find("fFatigueJumpMult")->mValue.getFloat();
const float normalizedEncumbrance = std::min(1.f, ptr.getClass().getNormalizedEncumbrance(ptr));
@ -374,11 +375,11 @@ namespace MWPhysics
}
// Now that we have the effective movement vector, apply wind forces to it
if (MWBase::Environment::get().getWorld()->isInStorm())
if (world->isInStorm())
{
osg::Vec3f stormDirection = MWBase::Environment::get().getWorld()->getStormDirection();
osg::Vec3f stormDirection = world->getStormDirection();
float angleDegrees = osg::RadiansToDegrees(std::acos(stormDirection * velocity / (stormDirection.length() * velocity.length())));
static const float fStromWalkMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
static const float fStromWalkMult = world->getStore().get<ESM::GameSetting>()
.find("fStromWalkMult")->mValue.getFloat();
velocity *= 1.f-(fStromWalkMult * (angleDegrees/180.f));
}
@ -388,8 +389,9 @@ namespace MWPhysics
osg::Vec3f newPosition = position;
#ifdef USE_OPENXR
if (isPlayer)
if (isPlayer && !world->getPlayer().isDisabled())
{
auto* inputManager = MWVR::Environment::get().getInputManager();
osg::Vec3 trackingOffset = inputManager->mHeadOffset;

View file

@ -417,11 +417,8 @@ namespace MWRender
void Camera::processViewChange()
{
#ifdef USE_OPENXR
mAnimation->setViewMode(NpcAnimation::VM_VRHeadless);
//mAnimation->setViewMode(NpcAnimation::VM_VRFirstPerson);
// For comfort, in VR mode the camera should only track nodes that don't animate.
// As-is, only the first person mode adds any unanimated nodes, but we want the third-person mode body.
// So we look up the root node of the player to track that.
SceneUtil::FindByNameVisitor findRootVisitor("Player Root", osg::NodeVisitor::TRAVERSE_PARENTS);
mAnimation->getObjectRoot()->accept(findRootVisitor);
mTrackingNode = findRootVisitor.mFoundNode;

View file

@ -949,7 +949,7 @@ void NpcAnimation::addControllers()
mActiveControllers.emplace(node, mFirstPersonNeckController);
}
}
else if (mViewMode == VM_Normal || mViewMode == VM_VRHeadless)
else if (mViewMode != VM_HeadOnly)
{
WeaponAnimation::addControllers(mNodeMap, mActiveControllers, mObjectRoot.get());
}

View file

@ -36,7 +36,8 @@ public:
VM_Normal,
VM_FirstPerson,
VM_HeadOnly,
VM_VRHeadless,
VM_VRNormal,
VM_VRFirstPerson,
};
protected:

View file

@ -943,7 +943,7 @@ private:
auto player = mPlayer->getPlayer();
if (!mRealisticCombat || mRealisticCombat->ptr != player)
mRealisticCombat.reset(new RealisticCombat::StateMachine(player));
bool enabled = !guiMode && mPlayer->getDrawState() == MWMechanics::DrawState_Weapon;
bool enabled = !guiMode && mPlayer->getDrawState() == MWMechanics::DrawState_Weapon && !mPlayer->isDisabled();
mRealisticCombat->update(dt, enabled);
}
@ -1126,13 +1126,6 @@ private:
osg::Vec3 vrMovement = currentHeadPose.position - mPreviousHeadPose.position;
mPreviousHeadPose = currentHeadPose;
float yaw = 0.f;
float pitch = 0.f;
float roll = 0.f;
getEulerAngles(currentHeadPose.orientation, yaw, pitch, roll);
yaw += mYaw;
if (mRecenter)
{
mHeadOffset = osg::Vec3(0, 0, 0);
@ -1145,10 +1138,25 @@ private:
osg::Quat gameworldYaw = osg::Quat(mYaw, osg::Vec3(0, 0, -1));
mHeadOffset += gameworldYaw * vrMovement;
float yaw = 0.f;
float pitch = 0.f;
float roll = 0.f;
getEulerAngles(currentHeadPose.orientation, yaw, pitch, roll);
yaw += mYaw;
mVrAngles[0] = pitch;
mVrAngles[1] = roll;
mVrAngles[2] = yaw;
world->rotateObject(player, mVrAngles[0], mVrAngles[1], mVrAngles[2], MWBase::RotationFlag_none);
if (!mPlayer->isDisabled())
{
world->rotateObject(player, mVrAngles[0], mVrAngles[1], mVrAngles[2], MWBase::RotationFlag_none);
}
else {
// Update the camera directly to avoid rotating the disabled player
world->getRenderingManager().getCamera()->rotateCamera(-pitch, -roll, -yaw, false);
}
}
}

View file

@ -179,8 +179,6 @@ void ForearmController::operator()(osg::Node* node, osg::NodeVisitor* nv)
// Finally, set transform
transform->setMatrix(worldReference * osg::Matrix::inverse(worldToLimb) * transform->getMatrix());
Log(Debug::Verbose) << "Updating hand: " << node->getName();
// Omit nested callbacks to override animations of this node
osg::ref_ptr<osg::Callback> ncb = getNestedCallback();
setNestedCallback(nullptr);
@ -431,7 +429,7 @@ VRAnimation::VRAnimation(
const MWWorld::Ptr& ptr, osg::ref_ptr<osg::Group> parentNode, Resource::ResourceSystem* resourceSystem,
bool disableSounds, std::shared_ptr<OpenXRSession> xrSession)
// Note that i let it construct as 3rd person and then later update it to VM_VRHeadless
// when OpenMW sets the view mode of the camera object.
// when the character controller updates
: MWRender::NpcAnimation(ptr, parentNode, resourceSystem, disableSounds, VM_Normal, 55.f)
, mSession(xrSession)
, mIndexFingerControllers{nullptr, nullptr}
@ -474,9 +472,12 @@ VRAnimation::~VRAnimation() {};
void VRAnimation::setViewMode(NpcAnimation::ViewMode viewMode)
{
if (viewMode != VM_VRHeadless)
Log(Debug::Warning) << "View mode of VRAnimation may only be VM_VRHeadless";
NpcAnimation::setViewMode(VM_VRHeadless);
if (viewMode != VM_VRFirstPerson && viewMode != VM_VRNormal)
{
Log(Debug::Warning) << "Attempted to set view mode of VRAnimation to non-vr mode. Defaulted to VM_VRFirstPerson.";
viewMode = VM_VRFirstPerson;
}
NpcAnimation::setViewMode(viewMode);
return;
}
@ -484,25 +485,36 @@ void VRAnimation::updateParts()
{
NpcAnimation::updateParts();
// Hide head and hair to avoid getting them in the player's face
// TODO: Hair might be acceptable ?
removeIndividualPart(ESM::PartReferenceType::PRT_Hair);
removeIndividualPart(ESM::PartReferenceType::PRT_Head);
removeIndividualPart(ESM::PartReferenceType::PRT_LForearm);
removeIndividualPart(ESM::PartReferenceType::PRT_LUpperarm);
removeIndividualPart(ESM::PartReferenceType::PRT_LWrist);
removeIndividualPart(ESM::PartReferenceType::PRT_RForearm);
removeIndividualPart(ESM::PartReferenceType::PRT_RUpperarm);
removeIndividualPart(ESM::PartReferenceType::PRT_RWrist);
removeIndividualPart(ESM::PartReferenceType::PRT_Cuirass);
removeIndividualPart(ESM::PartReferenceType::PRT_Groin);
removeIndividualPart(ESM::PartReferenceType::PRT_Neck);
removeIndividualPart(ESM::PartReferenceType::PRT_Skirt);
removeIndividualPart(ESM::PartReferenceType::PRT_Tail);
removeIndividualPart(ESM::PartReferenceType::PRT_LLeg);
removeIndividualPart(ESM::PartReferenceType::PRT_RLeg);
removeIndividualPart(ESM::PartReferenceType::PRT_LAnkle);
removeIndividualPart(ESM::PartReferenceType::PRT_RAnkle);
if (mViewMode == VM_VRFirstPerson)
{
// Hide everything other than the hands and feet.
removeIndividualPart(ESM::PartReferenceType::PRT_Hair);
removeIndividualPart(ESM::PartReferenceType::PRT_Head);
removeIndividualPart(ESM::PartReferenceType::PRT_LForearm);
removeIndividualPart(ESM::PartReferenceType::PRT_LUpperarm);
removeIndividualPart(ESM::PartReferenceType::PRT_LWrist);
removeIndividualPart(ESM::PartReferenceType::PRT_RForearm);
removeIndividualPart(ESM::PartReferenceType::PRT_RUpperarm);
removeIndividualPart(ESM::PartReferenceType::PRT_RWrist);
removeIndividualPart(ESM::PartReferenceType::PRT_Cuirass);
removeIndividualPart(ESM::PartReferenceType::PRT_Groin);
removeIndividualPart(ESM::PartReferenceType::PRT_Neck);
removeIndividualPart(ESM::PartReferenceType::PRT_Skirt);
removeIndividualPart(ESM::PartReferenceType::PRT_Tail);
removeIndividualPart(ESM::PartReferenceType::PRT_LLeg);
removeIndividualPart(ESM::PartReferenceType::PRT_RLeg);
removeIndividualPart(ESM::PartReferenceType::PRT_LAnkle);
removeIndividualPart(ESM::PartReferenceType::PRT_RAnkle);
removeIndividualPart(ESM::PartReferenceType::PRT_LKnee);
removeIndividualPart(ESM::PartReferenceType::PRT_RKnee);
}
else
{
removeIndividualPart(ESM::PartReferenceType::PRT_LForearm);
removeIndividualPart(ESM::PartReferenceType::PRT_LWrist);
removeIndividualPart(ESM::PartReferenceType::PRT_RForearm);
removeIndividualPart(ESM::PartReferenceType::PRT_RWrist);
}
}
void VRAnimation::setPointForward(bool enabled)

View file

@ -46,14 +46,13 @@ public:
/// to indicate the facing orientation of the character.
virtual void setPitchFactor(float factor) { mPitchFactor = factor; }
/// Overriden to always be VM_VRHeadless
/// Overriden to always be a variant of VM_VR*
virtual void setViewMode(ViewMode viewMode);
/// Overriden to include VR modifications
virtual void updateParts();
/// Overrides finger animations to point forward
/// (Used to visualize direction of activation action)
void setPointForward(bool enabled);
bool canPlaceObject();

View file

@ -293,6 +293,18 @@ namespace MWWorld
return MWBase::Environment::get().getMechanicsManager()->getActorsFighting(getPlayer()).size() != 0;
}
bool Player::isDisabled()
{
bool disabled = false;
auto ptr = getPlayer();
const MWWorld::Class& cls = ptr.getClass();
auto& stats = cls.getCreatureStats(ptr);
disabled |= stats.getKnockedDown();
disabled |= stats.getMagicEffects().get(ESM::MagicEffect::Paralyze).getMagnitude() > 0.f;
disabled |= stats.isDead();
return disabled;
}
bool Player::enemiesNearby()
{
return MWBase::Environment::get().getMechanicsManager()->getEnemiesNearby(getPlayer()).size() != 0;

View file

@ -127,6 +127,9 @@ namespace MWWorld
///Checks all nearby actors to see if anyone has an aipackage against you
bool isInCombat();
///Checks if the player is currently in a state where he cannot act
bool isDisabled();
bool enemiesNearby();
void clear();