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:
parent
68c75f66eb
commit
d658065fe7
10 changed files with 97 additions and 50 deletions
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -36,7 +36,8 @@ public:
|
|||
VM_Normal,
|
||||
VM_FirstPerson,
|
||||
VM_HeadOnly,
|
||||
VM_VRHeadless,
|
||||
VM_VRNormal,
|
||||
VM_VRFirstPerson,
|
||||
};
|
||||
|
||||
protected:
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue