diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 9db5ce451a..6e52190d33 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -104,7 +104,7 @@ static const struct { { WeapType_TwoHand, "2c", "2c", "weapontwohand" }, { WeapType_TwoWide, "2w", "2w", "weapontwowide" }, { WeapType_BowAndArrow, "1h", "1h", "bowandarrow" }, - { WeapType_Crossbow, "crossbow", "2c", "crossbow" }, + { WeapType_Crossbow, "crossbow", "1h", "crossbow" }, { WeapType_ThowWeapon, "1h", "1h", "throwweapon" }, { WeapType_Spell, "spell", "", "spellcast" }, }; @@ -147,6 +147,19 @@ void CharacterController::getCurrentGroup(std::string &group, Priority &priority } +void CharacterController::getWeaponGroup(WeaponType weaptype, std::string &group) +{ + for(size_t i = 0;i < sWeaponTypeListSize;i++) + { + if(sWeaponTypeList[i].type == weaptype) + { + group = sWeaponTypeList[i].actiongroup; + break; + } + } +} + + CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim, CharacterState state) : mPtr(ptr) , mAnimation(anim) @@ -229,68 +242,6 @@ void CharacterController::update(float duration, Movement &movement) } } - if(mPtr.getTypeName() == typeid(ESM::NPC).name()) - { - NpcStats &stats = cls.getNpcStats(mPtr); - WeaponType weaptype = WeapType_None; - - if(stats.getDrawState() == DrawState_Spell) - weaptype = WeapType_Spell; - else if(stats.getDrawState() == MWMechanics::DrawState_Weapon) - { - MWWorld::InventoryStore &inv = cls.getInventoryStore(mPtr); - MWWorld::ContainerStoreIterator weapon = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); - if(weapon == inv.end()) - weaptype = WeapType_HandToHand; - else - { - const std::string &type = weapon->getTypeName(); - if(type == typeid(ESM::Lockpick).name() || type == typeid(ESM::Probe).name()) - weaptype = WeapType_OneHand; - else if(type == typeid(ESM::Weapon).name()) - { - MWWorld::LiveCellRef *ref = weapon->get(); - ESM::Weapon::Type type = (ESM::Weapon::Type)ref->mBase->mData.mType; - switch(type) - { - case ESM::Weapon::ShortBladeOneHand: - case ESM::Weapon::LongBladeOneHand: - case ESM::Weapon::BluntOneHand: - case ESM::Weapon::AxeOneHand: - case ESM::Weapon::Arrow: - case ESM::Weapon::Bolt: - weaptype = WeapType_OneHand; - break; - case ESM::Weapon::LongBladeTwoHand: - case ESM::Weapon::BluntTwoClose: - case ESM::Weapon::AxeTwoHand: - weaptype = WeapType_TwoHand; - break; - case ESM::Weapon::BluntTwoWide: - case ESM::Weapon::SpearTwoWide: - weaptype = WeapType_TwoWide; - break; - case ESM::Weapon::MarksmanBow: - weaptype = WeapType_BowAndArrow; - break; - case ESM::Weapon::MarksmanCrossbow: - weaptype = WeapType_Crossbow; - break; - case ESM::Weapon::MarksmanThrown: - weaptype = WeapType_ThowWeapon; - break; - } - } - } - } - - if(weaptype != mWeaponType) - { - mWeaponType = weaptype; - forceStateUpdate(); - } - } - /* FIXME: The state should be set to Jump, and X/Y movement should be disallowed except * for the initial thrust (which would be carried by "physics" until landing). */ if(onground && vec.z > 0.0f) @@ -359,6 +310,85 @@ void CharacterController::update(float duration, Movement &movement) movement.mRotation[0] += rot.x * duration; movement.mRotation[1] += rot.y * duration; movement.mRotation[2] += rot.z * duration; + + if(mPtr.getTypeName() == typeid(ESM::NPC).name()) + { + NpcStats &stats = cls.getNpcStats(mPtr); + WeaponType weaptype = WeapType_None; + + if(stats.getDrawState() == DrawState_Spell) + weaptype = WeapType_Spell; + else if(stats.getDrawState() == MWMechanics::DrawState_Weapon) + { + MWWorld::InventoryStore &inv = cls.getInventoryStore(mPtr); + MWWorld::ContainerStoreIterator weapon = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); + if(weapon == inv.end()) + weaptype = WeapType_HandToHand; + else + { + const std::string &type = weapon->getTypeName(); + if(type == typeid(ESM::Lockpick).name() || type == typeid(ESM::Probe).name()) + weaptype = WeapType_OneHand; + else if(type == typeid(ESM::Weapon).name()) + { + MWWorld::LiveCellRef *ref = weapon->get(); + ESM::Weapon::Type type = (ESM::Weapon::Type)ref->mBase->mData.mType; + switch(type) + { + case ESM::Weapon::ShortBladeOneHand: + case ESM::Weapon::LongBladeOneHand: + case ESM::Weapon::BluntOneHand: + case ESM::Weapon::AxeOneHand: + case ESM::Weapon::Arrow: + case ESM::Weapon::Bolt: + weaptype = WeapType_OneHand; + break; + case ESM::Weapon::LongBladeTwoHand: + case ESM::Weapon::BluntTwoClose: + case ESM::Weapon::AxeTwoHand: + weaptype = WeapType_TwoHand; + break; + case ESM::Weapon::BluntTwoWide: + case ESM::Weapon::SpearTwoWide: + weaptype = WeapType_TwoWide; + break; + case ESM::Weapon::MarksmanBow: + weaptype = WeapType_BowAndArrow; + break; + case ESM::Weapon::MarksmanCrossbow: + weaptype = WeapType_Crossbow; + break; + case ESM::Weapon::MarksmanThrown: + weaptype = WeapType_ThowWeapon; + break; + } + } + } + } + + if(weaptype != mWeaponType) + { + std::string weapgroup; + if(weaptype == WeapType_None) + { + getWeaponGroup(mWeaponType, weapgroup); + mAnimation->play(weapgroup, Priority_Weapon, + MWRender::Animation::Group_UpperBody, true, + "unequip start", "unequip stop", 0.0f, 0); + } + else + { + getWeaponGroup(weaptype, weapgroup); + mAnimation->showWeapons(false); + mAnimation->play(weapgroup, Priority_Weapon, + MWRender::Animation::Group_UpperBody, true, + "equip start", "equip stop", 0.0f, 0); + } + + mWeaponType = weaptype; + forceStateUpdate(); + } + } } if(mAnimation && !mSkipAnim) @@ -437,9 +467,6 @@ void CharacterController::forceStateUpdate() getCurrentGroup(group, prio, loops); mAnimation->play(group, prio, MWRender::Animation::Group_All, false, "start", "stop", 0.0f, loops ? (~(size_t)0) : 0); - - mAnimation->showWeapons(mWeaponType != WeapType_None && mWeaponType != WeapType_HandToHand && - mWeaponType != WeapType_Spell); } } diff --git a/apps/openmw/mwmechanics/character.hpp b/apps/openmw/mwmechanics/character.hpp index a961b97910..4c5ad03f5e 100644 --- a/apps/openmw/mwmechanics/character.hpp +++ b/apps/openmw/mwmechanics/character.hpp @@ -17,6 +17,7 @@ class Movement; enum Priority { Priority_Default, + Priority_Weapon, Priority_Death, @@ -108,6 +109,8 @@ class CharacterController // Gets an animation group name from the current character state, and whether it should loop. void getCurrentGroup(std::string &group, Priority &prio, bool &loops) const; + static void getWeaponGroup(WeaponType weaptype, std::string &group); + public: CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim, CharacterState state); virtual ~CharacterController(); diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index cf118c9443..7dc6cfc132 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -475,6 +475,17 @@ bool Animation::handleTextKey(AnimState &state, const std::string &groupname, co return true; } + if(evt.compare(off, len, "equip attach") == 0) + { + showWeapons(true); + return true; + } + if(evt.compare(off, len, "unequip detach") == 0) + { + showWeapons(false); + return true; + } + /* Nothing to do for these */ if(evt.compare(off, len, "equip start") == 0 || evt.compare(off, len, "equip stop") == 0 || evt.compare(off, len, "unequip start") == 0 || evt.compare(off, len, "unequip stop") == 0)