1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-02-03 18:45:34 +00:00

Merge remote-tracking branch 'scrawl/master'

This commit is contained in:
Marc Zinnschlag 2014-05-27 08:34:54 +02:00
commit 9e21da9636
10 changed files with 87 additions and 36 deletions

View file

@ -407,29 +407,25 @@ MWWorld::ContainerStoreIterator getActiveWeapon(CreatureStats &stats, MWWorld::I
return inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); return inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
} }
void CharacterController::playRandomDeath(float startpoint) void CharacterController::playDeath(float startpoint, CharacterState death)
{ {
if(MWBase::Environment::get().getWorld()->isSwimming(mPtr) && mAnimation->hasAnimation("swimdeath")) switch (death)
{ {
mDeathState = CharState_SwimDeath; case CharState_SwimDeath:
mCurrentDeath = "swimdeath"; mCurrentDeath = "swimdeath";
} break;
else if (mHitState == CharState_KnockDown) case CharState_DeathKnockDown:
{
mDeathState = CharState_DeathKnockDown;
mCurrentDeath = "deathknockdown"; mCurrentDeath = "deathknockdown";
} break;
else if (mHitState == CharState_KnockOut) case CharState_DeathKnockOut:
{
mDeathState = CharState_DeathKnockOut;
mCurrentDeath = "deathknockout"; mCurrentDeath = "deathknockout";
break;
default:
mCurrentDeath = "death" + Ogre::StringConverter::toString(death - CharState_Death1 + 1);
} }
else mDeathState = death;
{
int selected=0; mPtr.getClass().getCreatureStats(mPtr).setDeathAnimation(mDeathState - CharState_Death1);
mCurrentDeath = chooseRandomGroup("death", &selected);
mDeathState = static_cast<CharacterState>(CharState_Death1 + (selected-1));
}
// For dead actors, refreshCurrentAnims is no longer called, so we need to disable the movement state manually. // For dead actors, refreshCurrentAnims is no longer called, so we need to disable the movement state manually.
mMovementState = CharState_None; mMovementState = CharState_None;
@ -440,6 +436,29 @@ void CharacterController::playRandomDeath(float startpoint)
false, 1.0f, "start", "stop", startpoint, 0); false, 1.0f, "start", "stop", startpoint, 0);
} }
void CharacterController::playRandomDeath(float startpoint)
{
if(MWBase::Environment::get().getWorld()->isSwimming(mPtr) && mAnimation->hasAnimation("swimdeath"))
{
mDeathState = CharState_SwimDeath;
}
else if (mHitState == CharState_KnockDown)
{
mDeathState = CharState_DeathKnockDown;
}
else if (mHitState == CharState_KnockOut)
{
mDeathState = CharState_DeathKnockOut;
}
else
{
int selected=0;
chooseRandomGroup("death", &selected);
mDeathState = static_cast<CharacterState>(CharState_Death1 + (selected-1));
}
playDeath(startpoint, mDeathState);
}
CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim) CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim)
: mPtr(ptr) : mPtr(ptr)
, mAnimation(anim) , mAnimation(anim)
@ -497,7 +516,8 @@ CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Anim
if(mDeathState != CharState_None) if(mDeathState != CharState_None)
{ {
playRandomDeath(1.0f); int deathindex = mPtr.getClass().getCreatureStats(mPtr).getDeathAnimation();
playDeath(1.0f, CharacterState(CharState_Death1 + deathindex));
} }
else else
refreshCurrentAnims(mIdleState, mMovementState, true); refreshCurrentAnims(mIdleState, mMovementState, true);

View file

@ -181,6 +181,7 @@ class CharacterController
void updateVisibility(); void updateVisibility();
void playDeath(float startpoint, CharacterState death);
void playRandomDeath(float startpoint = 0.0f); void playRandomDeath(float startpoint = 0.0f);
/// choose a random animation group with \a prefix and numeric suffix /// choose a random animation group with \a prefix and numeric suffix

View file

@ -22,7 +22,8 @@ namespace MWMechanics
mFallHeight(0), mRecalcDynamicStats(false), mKnockdown(false), mKnockdownOneFrame(false), mFallHeight(0), mRecalcDynamicStats(false), mKnockdown(false), mKnockdownOneFrame(false),
mKnockdownOverOneFrame(false), mHitRecovery(false), mBlock(false), mKnockdownOverOneFrame(false), mHitRecovery(false), mBlock(false),
mMovementFlags(0), mDrawState (DrawState_Nothing), mAttackStrength(0.f), mMovementFlags(0), mDrawState (DrawState_Nothing), mAttackStrength(0.f),
mLastRestock(0,0), mGoldPool(0), mActorId(-1) mLastRestock(0,0), mGoldPool(0), mActorId(-1),
mDeathAnimation(0)
{ {
for (int i=0; i<4; ++i) for (int i=0; i<4; ++i)
mAiSettings[i] = 0; mAiSettings[i] = 0;
@ -498,6 +499,7 @@ namespace MWMechanics
state.mDrawState = mDrawState; state.mDrawState = mDrawState;
state.mLevel = mLevel; state.mLevel = mLevel;
state.mActorId = mActorId; state.mActorId = mActorId;
state.mDeathAnimation = mDeathAnimation;
mSpells.writeState(state.mSpells); mSpells.writeState(state.mSpells);
mActiveSpells.writeState(state.mActiveSpells); mActiveSpells.writeState(state.mActiveSpells);
@ -537,6 +539,7 @@ namespace MWMechanics
mDrawState = DrawState_(state.mDrawState); mDrawState = DrawState_(state.mDrawState);
mLevel = state.mLevel; mLevel = state.mLevel;
mActorId = state.mActorId; mActorId = state.mActorId;
mDeathAnimation = state.mDeathAnimation;
mSpells.readState(state.mSpells); mSpells.readState(state.mSpells);
mActiveSpells.readState(state.mActiveSpells); mActiveSpells.readState(state.mActiveSpells);
@ -590,4 +593,14 @@ namespace MWMechanics
{ {
esm.getHNT(sActorId, "COUN"); esm.getHNT(sActorId, "COUN");
} }
unsigned char CreatureStats::getDeathAnimation() const
{
return mDeathAnimation;
}
void CreatureStats::setDeathAnimation(unsigned char index)
{
mDeathAnimation = index;
}
} }

View file

@ -64,6 +64,9 @@ namespace MWMechanics
int mActorId; int mActorId;
// The index of the death animation that was played
unsigned char mDeathAnimation;
protected: protected:
// These two are only set by NpcStats, but they are declared in CreatureStats to prevent using virtual methods. // These two are only set by NpcStats, but they are declared in CreatureStats to prevent using virtual methods.
bool mIsWerewolf; bool mIsWerewolf;
@ -250,6 +253,9 @@ namespace MWMechanics
void setGoldPool(int pool); void setGoldPool(int pool);
int getGoldPool() const; int getGoldPool() const;
unsigned char getDeathAnimation() const;
void setDeathAnimation(unsigned char index);
int getActorId(); int getActorId();
///< Will generate an actor ID, if the actor does not have one yet. ///< Will generate an actor ID, if the actor does not have one yet.

View file

@ -54,17 +54,12 @@ void Actors::insertBegin(const MWWorld::Ptr &ptr)
// Convert MW rotation to a quaternion: // Convert MW rotation to a quaternion:
f = ptr.getCellRef().getPosition().rot; f = ptr.getCellRef().getPosition().rot;
// Rotate around X axis // For rendering purposes, actors should only rotate around the Z axis.
Ogre::Quaternion xr(Ogre::Radian(-f[0]), Ogre::Vector3::UNIT_X); // X rotation is used for camera rotation (for the player) and for
// ranged magic / ranged weapon aiming.
// Rotate around Y axis
Ogre::Quaternion yr(Ogre::Radian(-f[1]), Ogre::Vector3::UNIT_Y);
// Rotate around Z axis
Ogre::Quaternion zr(Ogre::Radian(-f[2]), Ogre::Vector3::UNIT_Z); Ogre::Quaternion zr(Ogre::Radian(-f[2]), Ogre::Vector3::UNIT_Z);
// Rotates first around z, then y, then x insert->setOrientation(zr);
insert->setOrientation(xr*yr*zr);
ptr.getRefData().setBaseNode(insert); ptr.getRefData().setBaseNode(insert);
} }

View file

@ -775,11 +775,11 @@ void Animation::play(const std::string &groupname, int priority, int groups, boo
} }
/* Look in reverse; last-inserted source has priority. */ /* Look in reverse; last-inserted source has priority. */
AnimState state;
AnimSourceList::reverse_iterator iter(mAnimSources.rbegin()); AnimSourceList::reverse_iterator iter(mAnimSources.rbegin());
for(;iter != mAnimSources.rend();++iter) for(;iter != mAnimSources.rend();++iter)
{ {
const NifOgre::TextKeyMap &textkeys = (*iter)->mTextKeys; const NifOgre::TextKeyMap &textkeys = (*iter)->mTextKeys;
AnimState state;
if(reset(state, textkeys, groupname, start, stop, startpoint)) if(reset(state, textkeys, groupname, start, stop, startpoint))
{ {
state.mSource = *iter; state.mSource = *iter;
@ -821,6 +821,13 @@ void Animation::play(const std::string &groupname, int priority, int groups, boo
std::cerr<< "Failed to find animation "<<groupname<<" for "<<mPtr.getCellRef().getRefId() <<std::endl; std::cerr<< "Failed to find animation "<<groupname<<" for "<<mPtr.getCellRef().getRefId() <<std::endl;
resetActiveGroups(); resetActiveGroups();
if (!state.mPlaying && mNonAccumCtrl)
{
// If the animation state is not playing, we need to manually apply the accumulation
// (see updatePosition, which would be called if the animation was playing)
mAccumRoot->setPosition(-mNonAccumCtrl->getTranslation(state.mTime)*mAccumulate);
}
} }
bool Animation::isPlaying(const std::string &groupname) const bool Animation::isPlaying(const std::string &groupname) const

View file

@ -33,12 +33,12 @@ void ESMStore::load(ESM::ESMReader &esm, Loading::Listener* listener)
// Cache parent esX files by tracking their indices in the global list of // Cache parent esX files by tracking their indices in the global list of
// all files/readers used by the engine. This will greaty accelerate // all files/readers used by the engine. This will greaty accelerate
// refnumber mangling, as required for handling moved references. // refnumber mangling, as required for handling moved references.
int index = ~0;
const std::vector<ESM::Header::MasterData> &masters = esm.getGameFiles(); const std::vector<ESM::Header::MasterData> &masters = esm.getGameFiles();
std::vector<ESM::ESMReader> *allPlugins = esm.getGlobalReaderList(); std::vector<ESM::ESMReader> *allPlugins = esm.getGlobalReaderList();
for (size_t j = 0; j < masters.size(); j++) { for (size_t j = 0; j < masters.size(); j++) {
ESM::Header::MasterData &mast = const_cast<ESM::Header::MasterData&>(masters[j]); ESM::Header::MasterData &mast = const_cast<ESM::Header::MasterData&>(masters[j]);
std::string fname = mast.name; std::string fname = mast.name;
int index = ~0;
for (int i = 0; i < esm.getIndex(); i++) { for (int i = 0; i < esm.getIndex(); i++) {
const std::string &candidate = allPlugins->at(i).getContext().filename; const std::string &candidate = allPlugins->at(i).getContext().filename;
std::string fnamecandidate = boost::filesystem::path(candidate).filename().string(); std::string fnamecandidate = boost::filesystem::path(candidate).filename().string();

View file

@ -1116,13 +1116,15 @@ namespace MWWorld
while(ptr.getRefData().getLocalRotation().rot[2]<=-fullRotateRad) while(ptr.getRefData().getLocalRotation().rot[2]<=-fullRotateRad)
ptr.getRefData().getLocalRotation().rot[2]+=fullRotateRad; ptr.getRefData().getLocalRotation().rot[2]+=fullRotateRad;
Ogre::Quaternion worldRotQuat(Ogre::Quaternion(Ogre::Radian(ptr.getRefData().getPosition().rot[0]), Ogre::Vector3::NEGATIVE_UNIT_X)* Ogre::Quaternion worldRotQuat(Ogre::Radian(ptr.getRefData().getPosition().rot[2]), Ogre::Vector3::NEGATIVE_UNIT_Z);
Ogre::Quaternion(Ogre::Radian(ptr.getRefData().getPosition().rot[1]), Ogre::Vector3::NEGATIVE_UNIT_Y)* if (!ptr.getClass().isActor())
Ogre::Quaternion(Ogre::Radian(ptr.getRefData().getPosition().rot[2]), Ogre::Vector3::NEGATIVE_UNIT_Z)); worldRotQuat = Ogre::Quaternion(Ogre::Radian(ptr.getRefData().getPosition().rot[0]), Ogre::Vector3::NEGATIVE_UNIT_X)*
Ogre::Quaternion(Ogre::Radian(ptr.getRefData().getPosition().rot[1]), Ogre::Vector3::NEGATIVE_UNIT_Y)* worldRotQuat;
Ogre::Quaternion rot(Ogre::Quaternion(Ogre::Degree(x), Ogre::Vector3::NEGATIVE_UNIT_X)* Ogre::Quaternion rot(Ogre::Degree(z), Ogre::Vector3::NEGATIVE_UNIT_Z);
Ogre::Quaternion(Ogre::Degree(y), Ogre::Vector3::NEGATIVE_UNIT_Y)* if (!ptr.getClass().isActor())
Ogre::Quaternion(Ogre::Degree(z), Ogre::Vector3::NEGATIVE_UNIT_Z)); rot = Ogre::Quaternion(Ogre::Degree(x), Ogre::Vector3::NEGATIVE_UNIT_X)*
Ogre::Quaternion(Ogre::Degree(y), Ogre::Vector3::NEGATIVE_UNIT_Y)*rot;
ptr.getRefData().getBaseNode()->setOrientation(worldRotQuat*rot); ptr.getRefData().getBaseNode()->setOrientation(worldRotQuat*rot);
mPhysics->rotateObject(ptr); mPhysics->rotateObject(ptr);

View file

@ -74,6 +74,9 @@ void ESM::CreatureStats::load (ESMReader &esm)
mActorId = -1; mActorId = -1;
esm.getHNOT (mActorId, "ACID"); esm.getHNOT (mActorId, "ACID");
mDeathAnimation = 0;
esm.getHNOT (mDeathAnimation, "DANM");
mSpells.load(esm); mSpells.load(esm);
mActiveSpells.load(esm); mActiveSpells.load(esm);
} }
@ -152,6 +155,9 @@ void ESM::CreatureStats::save (ESMWriter &esm) const
if (mActorId != -1) if (mActorId != -1)
esm.writeHNT ("ACID", mActorId); esm.writeHNT ("ACID", mActorId);
if (mDeathAnimation)
esm.writeHNT ("DANM", mDeathAnimation);
mSpells.save(esm); mSpells.save(esm);
mActiveSpells.save(esm); mActiveSpells.save(esm);
} }

View file

@ -46,6 +46,7 @@ namespace ESM
std::string mLastHitObject; std::string mLastHitObject;
bool mRecalcDynamicStats; bool mRecalcDynamicStats;
int mDrawState; int mDrawState;
unsigned char mDeathAnimation;
int mLevel; int mLevel;