From 06e631f2133ac028c847b670407ad3e1459e8a94 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 15 Jul 2013 23:43:33 -0700 Subject: [PATCH] Track death separately in the character controller --- apps/openmw/mwmechanics/actors.cpp | 15 +++--- apps/openmw/mwmechanics/character.cpp | 71 +++++++++++++++++++-------- apps/openmw/mwmechanics/character.hpp | 13 +++-- apps/openmw/mwmechanics/objects.cpp | 3 +- 4 files changed, 66 insertions(+), 36 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 082100b27..7af7e063c 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -168,13 +168,10 @@ namespace MWMechanics void Actors::addActor (const MWWorld::Ptr& ptr) { // erase previous death events since we are currently only tracking them while in an active cell - MWWorld::Class::get (ptr).getCreatureStats (ptr).clearHasDied(); + MWWorld::Class::get(ptr).getCreatureStats(ptr).clearHasDied(); MWRender::Animation *anim = MWBase::Environment::get().getWorld()->getAnimation(ptr); - if(!MWWorld::Class::get(ptr).getCreatureStats(ptr).isDead()) - mActors.insert(std::make_pair(ptr, new CharacterController(ptr, anim, CharState_Idle))); - else - mActors.insert(std::make_pair(ptr, new CharacterController(ptr, anim, CharState_Death1))); + mActors.insert(std::make_pair(ptr, new CharacterController(ptr, anim))); } void Actors::removeActor (const MWWorld::Ptr& ptr) @@ -228,8 +225,8 @@ namespace MWMechanics { if(!MWWorld::Class::get(iter->first).getCreatureStats(iter->first).isDead()) { - if(iter->second->getState() >= CharState_Death1) - iter->second->setState(CharState_Idle); + if(iter->second->isDead()) + iter->second->resurrect(); updateActor(iter->first, totalDuration); if(iter->first.getTypeName() == typeid(ESM::NPC).name()) @@ -256,10 +253,10 @@ namespace MWMechanics continue; } - if(iter->second->getState() >= CharState_Death1) + if(iter->second->isDead()) continue; - iter->second->setState(CharState_Death1); + iter->second->kill(); ++mDeathCount[MWWorld::Class::get(iter->first).getId(iter->first)]; diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 0e15652cc..8c231107e 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -221,12 +221,12 @@ void CharacterController::getWeaponGroup(WeaponType weaptype, std::string &group } -CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim, CharacterState state) +CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim) : mPtr(ptr) , mAnimation(anim) , mIdleState(CharState_Idle) , mMovementState(CharState_None) - , mCharState(state) + , mDeathState(CharState_None) , mWeaponType(WeapType_None) , mSkipAnim(false) , mSecondsOfRunning(0) @@ -241,6 +241,12 @@ CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Anim /* Accumulate along X/Y only for now, until we can figure out how we should * handle knockout and death which moves the character down. */ mAnimation->setAccumulation(Ogre::Vector3(1.0f, 1.0f, 0.0f)); + + if(MWWorld::Class::get(mPtr).getCreatureStats(mPtr).isDead()) + { + /* FIXME: Get the actual death state used. */ + mDeathState = CharState_Death1; + } } else { @@ -249,13 +255,14 @@ CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Anim } refreshCurrentAnims(mIdleState, mMovementState, true); - if(mCharState >= CharState_Death1) + if(mDeathState != CharState_None) { - const StateInfo *state = std::find_if(sStateList, sStateListEnd, FindCharState(mCharState)); + const StateInfo *state = std::find_if(sStateList, sStateListEnd, FindCharState(mDeathState)); if(state == sStateListEnd) - throw std::runtime_error("Failed to find character state "+Ogre::StringConverter::toString(mCharState)); + throw std::runtime_error("Failed to find character state "+Ogre::StringConverter::toString(mDeathState)); - mAnimation->play(state->groupname, Priority_Death, MWRender::Animation::Group_All, + mCurrentDeath = state->groupname; + mAnimation->play(mCurrentDeath, Priority_Death, MWRender::Animation::Group_All, false, "start", "stop", 1.0f, 0); } } @@ -608,15 +615,6 @@ void CharacterController::clearAnimQueue() } -void CharacterController::setState(CharacterState state) -{ - if(mCharState == state) - return; - mCharState = state; - - forceStateUpdate(); -} - void CharacterController::forceStateUpdate() { if(!mAnimation) @@ -624,16 +622,49 @@ void CharacterController::forceStateUpdate() clearAnimQueue(); refreshCurrentAnims(mIdleState, mMovementState, true); - if(mCharState >= CharState_Death1) + if(mDeathState != CharState_None) { - const StateInfo *state = std::find_if(sStateList, sStateListEnd, FindCharState(mCharState)); + const StateInfo *state = std::find_if(sStateList, sStateListEnd, FindCharState(mDeathState)); if(state == sStateListEnd) - throw std::runtime_error("Failed to find character state "+Ogre::StringConverter::toString(mCharState)); + throw std::runtime_error("Failed to find character state "+Ogre::StringConverter::toString(mDeathState)); - if(!mAnimation->getInfo(state->groupname)) - mAnimation->play(state->groupname, Priority_Death, MWRender::Animation::Group_All, + mCurrentDeath = state->groupname; + if(!mAnimation->getInfo(mCurrentDeath)) + mAnimation->play(mCurrentDeath, Priority_Death, MWRender::Animation::Group_All, false, "start", "stop", 0.0f, 0); } } +void CharacterController::kill() +{ + static const CharacterState deathstates[] = { + CharState_Death1, CharState_Death2, CharState_Death3, CharState_Death4, CharState_Death5 + }; + + if(mDeathState != CharState_None) + return; + + mDeathState = deathstates[(int)(rand()/((double)RAND_MAX+1.0)*5.0)]; + const StateInfo *state = std::find_if(sStateList, sStateListEnd, FindCharState(mDeathState)); + if(state == sStateListEnd) + throw std::runtime_error("Failed to find character state "+Ogre::StringConverter::toString(mDeathState)); + + mCurrentDeath = state->groupname; + if(mAnimation && !mAnimation->getInfo(mCurrentDeath)) + mAnimation->play(mCurrentDeath, Priority_Death, MWRender::Animation::Group_All, + false, "start", "stop", 0.0f, 0); +} + +void CharacterController::resurrect() +{ + if(mDeathState == CharState_None) + return; + + if(mAnimation) + mAnimation->disable(mCurrentDeath); + mCurrentDeath.empty(); + mDeathState = CharState_None; +} + + } diff --git a/apps/openmw/mwmechanics/character.hpp b/apps/openmw/mwmechanics/character.hpp index 4f23101bb..84f324fad 100644 --- a/apps/openmw/mwmechanics/character.hpp +++ b/apps/openmw/mwmechanics/character.hpp @@ -108,7 +108,9 @@ class CharacterController CharacterState mMovementState; std::string mCurrentMovement; - CharacterState mCharState; + CharacterState mDeathState; + std::string mCurrentDeath; + WeaponType mWeaponType; bool mSkipAnim; @@ -126,7 +128,7 @@ class CharacterController void clearAnimQueue(); public: - CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim, CharacterState state); + CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim); virtual ~CharacterController(); void updatePtr(const MWWorld::Ptr &ptr); @@ -137,9 +139,10 @@ public: void skipAnim(); bool isAnimPlaying(const std::string &groupName); - void setState(CharacterState state); - CharacterState getState() const - { return mCharState; } + void kill(); + void resurrect(); + bool isDead() const + { return mDeathState != CharState_None; } void forceStateUpdate(); }; diff --git a/apps/openmw/mwmechanics/objects.cpp b/apps/openmw/mwmechanics/objects.cpp index 24d8a8bf7..45760b68b 100644 --- a/apps/openmw/mwmechanics/objects.cpp +++ b/apps/openmw/mwmechanics/objects.cpp @@ -17,8 +17,7 @@ Objects::Objects() void Objects::addObject(const MWWorld::Ptr& ptr) { MWRender::Animation *anim = MWBase::Environment::get().getWorld()->getAnimation(ptr); - if(anim != NULL) - mObjects.insert(std::make_pair(ptr, CharacterController(ptr, anim, CharState_Idle))); + if(anim) mObjects.insert(std::make_pair(ptr, CharacterController(ptr, anim))); } void Objects::removeObject(const MWWorld::Ptr& ptr)